diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index 1eab62cc9..89be796ad 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -13,12 +13,12 @@ set(SRB2_ASSET_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/installer" CACHE STRING "Path to directory that contains all asset files for the installer.") set(SRB2_ASSET_HASHED -"srb2.srb;\ -patch.kart;\ -gfx.kart;\ -textures.kart;\ -chars.kart;\ -maps.kart" +"main.kart;\ +gfx.pk3;\ +textures.pk3;\ +chars.pk3;\ +maps.wad;\ +patch.pk3" CACHE STRING "Asset filenames to apply MD5 checks. No spaces between entries!" ) diff --git a/src/Makefile b/src/Makefile index 214c2bf7a..f4a77aedd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -83,16 +83,14 @@ # SRB2 data files D_DIR?=../bin/Resources -D_FILES=$(D_DIR)/srb2.srb \ - $(D_DIR)/patch.dta \ - #$(D_DIR)/music.dta \ - $(D_DIR)/gfx.kart \ - $(D_DIR)/textures.kart \ - $(D_DIR)/chars.kart \ - $(D_DIR)/maps.kart \ - $(D_DIR)/sounds.kart \ - $(D_DIR)/patch.kart \ - $(D_DIR)/music.kart \ +D_FILES=$(D_DIR)/main.kart \ + $(D_DIR)/gfx.pk3 \ + $(D_DIR)/textures.pk3 \ + $(D_DIR)/chars.pk3 \ + $(D_DIR)/maps.wad \ + $(D_DIR)/patch.pk3 \ + $(D_DIR)/sounds.wad \ + $(D_DIR)/music.wad \ PKG_CONFIG?=pkg-config diff --git a/src/android/i_sound.c b/src/android/i_sound.c index 2bb304424..b5a1c3646 100644 --- a/src/android/i_sound.c +++ b/src/android/i_sound.c @@ -96,6 +96,37 @@ boolean I_SetSongSpeed(float speed) return false; } +/// ------------------------ +// MUSIC SEEKING +/// ------------------------ + +UINT32 I_GetSongLength(void) +{ + return 0; +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetSongLoopPoint(void) +{ + return 0; +} + +boolean I_SetSongPosition(UINT32 position) +{ + (void)position; + return false; +} + +UINT32 I_GetSongPosition(void) +{ + return 0; +} + /// ------------------------ // MUSIC PLAYBACK /// ------------------------ @@ -140,3 +171,44 @@ void I_SetMusicVolume(INT32 volume) { (void)volume; } + +/// ------------------------ +// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + (void)volume; +} + +void I_StopFadingSong(void) +{ +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); +{ + (void)target_volume; + (void)source_volume; + (void)ms; + return false; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); +{ + (void)target_volume; + (void)ms; + return false; +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + (void)ms; + return false; +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + (void)ms; + (void)looping; + return false; +} diff --git a/src/command.c b/src/command.c index 306508a36..3eebe32d1 100644 --- a/src/command.c +++ b/src/command.c @@ -157,6 +157,20 @@ void COM_BufInsertText(const char *ptext) } } +/** Progress the wait timer and flush waiting console commands when ready. + */ +void +COM_BufTicker(void) +{ + if (com_wait) + { + com_wait--; + return; + } + + COM_BufExecute(); +} + /** Flushes (executes) console commands in the buffer. */ void COM_BufExecute(void) @@ -166,12 +180,6 @@ void COM_BufExecute(void) char line[1024] = ""; INT32 quotes; - if (com_wait) - { - com_wait--; - return; - } - while (com_text.cursize) { // find a '\n' or; line break diff --git a/src/command.h b/src/command.h index 55c8700f1..6b5d513ef 100644 --- a/src/command.h +++ b/src/command.h @@ -45,6 +45,9 @@ void COM_ImmedExecute(const char *ptext); // Execute commands in buffer, flush them void COM_BufExecute(void); +// As above; and progress the wait timer. +void COM_BufTicker(void); + // setup command buffer, at game tartup void COM_Init(void); diff --git a/src/config.h.in b/src/config.h.in index 338647435..92708a46c 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -11,19 +11,13 @@ #ifdef CMAKECONFIG -// Base SRB2 hashes -#define ASSET_HASH_SRB2_SRB "${SRB2_ASSET_srb2.srb_HASH}" -#ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_DTA "${SRB2_ASSET_patch.dta_HASH}" -#endif - -// SRB2Kart-specific hashes -#define ASSET_HASH_GFX_KART "${SRB2_ASSET_gfx.kart_HASH}" -#define ASSET_HASH_TEXTURES_KART "${SRB2_ASSET_textures.kart_HASH}" -#define ASSET_HASH_CHARS_KART "${SRB2_ASSET_chars.kart_HASH}" -#define ASSET_HASH_MAPS_KART "${SRB2_ASSET_maps.kart_HASH}" -#ifdef USE_PATCH_KART -#define ASSET_HASH_PATCH_KART "${SRB2_ASSET_patch.kart_HASH}" +#define ASSET_HASH_MAIN_KART "${SRB2_ASSET_main.kart_HASH}" +#define ASSET_HASH_GFX_PK3 "${SRB2_ASSET_gfx.pk3_HASH}" +#define ASSET_HASH_TEXTURES_PK3 "${SRB2_ASSET_textures.pk3_HASH}" +#define ASSET_HASH_CHARS_PK3 "${SRB2_ASSET_chars.pk3_HASH}" +#define ASSET_HASH_MAPS_WAD "${SRB2_ASSET_maps.wad_HASH}" +#ifdef USE_PATCH_FILE +#define ASSET_HASH_PATCH_PK3 "${SRB2_ASSET_patch.pk3_HASH}" #endif #define SRB2_COMP_REVISION "${SRB2_COMP_REVISION}" @@ -34,25 +28,17 @@ #else /* Manually defined asset hashes for non-CMake builds - * Last updated 2015 / 05 / 03 - SRB2 v2.1.15 - srb2.srb - * Last updated 2018 / 12 / 23 - SRB2 v2.1.22 - patch.dta * Last updated 2019 / 01 / 18 - Kart v1.0.2 - Main assets * Last updated 2019 / 05 / 06 - Kart v1.1.0 - patch.kart */ -// Base SRB2 hashes -#define ASSET_HASH_SRB2_SRB "c1b9577687f8a795104aef4600720ea7" -#ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_DTA "b04fd9624bfd94dc96dcf4f400f7deb4" -#endif - -// SRB2Kart-specific hashes -#define ASSET_HASH_GFX_KART "99c39f223d84ebc78e67ab68f3bead95" -#define ASSET_HASH_TEXTURES_KART "ec8e9b7535cf585afe72ef277b08f490" -#define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964" -#define ASSET_HASH_MAPS_KART "1335cd064656aedca359cfbb5233ac4a" -#ifdef USE_PATCH_KART -#define ASSET_HASH_PATCH_KART "6461b30bb20754a16a1b582120f55842" +#define ASSET_HASH_MAIN_KART "00000000000000000000000000000000" +#define ASSET_HASH_GFX_PK3 "99c39f223d84ebc78e67ab68f3bead95" +#define ASSET_HASH_TEXTURES_PK3 "ec8e9b7535cf585afe72ef277b08f490" +#define ASSET_HASH_CHARS_PK3 "e2c428347dde52858a3dacd29fc5b964" +#define ASSET_HASH_MAPS_WAD "1335cd064656aedca359cfbb5233ac4a" +#ifdef USE_PATCH_FILE +#define ASSET_HASH_PATCH_PK3 "6461b30bb20754a16a1b582120f55842" #endif #endif diff --git a/src/console.c b/src/console.c index 44bb03a3d..1defa7e82 100644 --- a/src/console.c +++ b/src/console.c @@ -96,6 +96,7 @@ static size_t input_len; // length of current line, used to bound cursor and suc // protos. static void CON_InputInit(void); static void CON_RecalcSize(void); +static void CON_ChangeHeight(void); static void CONS_hudlines_Change(void); static void CONS_backcolor_Change(void); @@ -130,12 +131,12 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"} static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"}, - {3, "Brown"}, {4, "Pink"}, {5, "Raspberry"}, - {6, "Red"}, {7, "Creamsicle"}, {8, "Orange"}, - {9, "Gold"}, {10,"Yellow"}, {11,"Emerald"}, - {12,"Green"}, {13,"Cyan"}, {14,"Steel"}, - {15,"Periwinkle"}, {16,"Blue"}, {17,"Purple"}, - {18,"Lavender"}, + {3, "Brown"}, {4, "Pink"}, {5, "Red"}, + {6, "Orange"}, {7, "Gold"}, {8, "Yellow"}, + {9, "Peridot"}, {10,"Green"}, {11,"Aquamarine"}, + {12,"Cyan"}, {13,"Steel"}, {14,"Blue"}, + {15,"Purple"}, {16,"Magenta"}, {17,"Lavender"}, + {18,"Rose"}, {0, NULL}}; consvar_t cons_backcolor = {"con_backcolor", "Black", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL}; @@ -152,11 +153,11 @@ static CV_PossibleValue_t menuhighlight_cons_t[] = {V_SKYMAP, "Always sky-blue"}, {V_GOLDMAP, "Always gold"}, {V_LAVENDERMAP, "Always lavender"}, - {V_TEAMAP, "Always tea-green"}, - {V_STEELMAP, "Always steel-blue"}, + {V_AQUAMAP, "Always aqua-green"}, + {V_MAGENTAMAP, "Always magenta"}, {V_PINKMAP, "Always pink"}, {V_BROWNMAP, "Always brown"}, - {V_PEACHMAP, "Always peach"}, + {V_TANMAP, "Always tan"}, {0, NULL} }; consvar_t cons_menuhighlight = {"menuhighlight", "Game type", CV_SAVE, menuhighlight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -261,27 +262,27 @@ void CON_SetupBackColormap(void) switch (cons_backcolor.value) { - case 0: palindex = 15; break; // White - case 1: palindex = 31; break; // Gray - case 2: palindex = 47; break; // Sepia - case 3: palindex = 63; break; // Brown - case 4: palindex = 150; shift = 7; break; // Pink - case 5: palindex = 127; shift = 7; break; // Raspberry - case 6: palindex = 143; break; // Red - case 7: palindex = 86; shift = 7; break; // Creamsicle - case 8: palindex = 95; break; // Orange - case 9: palindex = 119; shift = 7; break; // Gold - case 10: palindex = 111; break; // Yellow - case 11: palindex = 191; shift = 7; break; // Emerald - case 12: palindex = 175; break; // Green - case 13: palindex = 219; break; // Cyan - case 14: palindex = 207; shift = 7; break; // Steel - case 15: palindex = 230; shift = 7; break; // Periwinkle - case 16: palindex = 239; break; // Blue - case 17: palindex = 199; shift = 7; break; // Purple - case 18: palindex = 255; shift = 7; break; // Lavender - // Default green - default: palindex = 175; break; + case 0: palindex = 15; break; // White + case 1: palindex = 31; break; // Black + case 2: palindex = 251; break; // Sepia + case 3: palindex = 239; break; // Brown + case 4: palindex = 214; shift = 7; break; // Pink + case 5: palindex = 47; break; // Red + case 6: palindex = 63; break; // Orange + case 7: palindex = 71; shift = 7; break; // Gold + case 8: palindex = 79; shift = 7; break; // Yellow + case 9: palindex = 191; shift = 8; break; // Peridot + case 10: palindex = 111; break; // Green + case 11: palindex = 127; shift = 7; break; // Aquamarine + case 12: palindex = 139; break; // Cyan + case 13: palindex = 175; shift = 7; break; // Steel + case 14: palindex = 159; break; // Blue + case 15: palindex = 169; break; // Purple + case 16: palindex = 187; break; // Magenta + case 17: palindex = 199; shift = 7; break; // Lavender + case 18: palindex = 207; shift = 7; break; // Rose + // Default black + default: palindex = 31; break; } @@ -302,7 +303,7 @@ static void CONS_backcolor_Change(void) // TODO: This could probably be improved somehow... // These colormaps are 99% identical, with just a few changed bytes UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap,\ - *skymap, *goldmap, *lavendermap, *teamap, *steelmap, *pinkmap, *brownmap, *peachmap; + *skymap, *goldmap, *lavendermap, *aquamap, *magentamap, *pinkmap, *brownmap, *tanmap; static void CON_SetupColormaps(void) { @@ -319,11 +320,11 @@ static void CON_SetupColormaps(void) skymap = (orangemap+256); lavendermap = (skymap+256); goldmap = (lavendermap+256); - teamap = (goldmap+256); - steelmap = (teamap+256); - pinkmap = (steelmap+256); + aquamap = (goldmap+256); + magentamap = (aquamap+256); + pinkmap = (magentamap+256); brownmap = (pinkmap+256); - peachmap = (brownmap+256); + tanmap = (brownmap+256); // setup the other colormaps, for console text @@ -334,21 +335,21 @@ static void CON_SetupColormaps(void) *memorysrc = (UINT8)(i & 0xFF); // remap each color to itself... // SRB2Kart: Different console font, new colors - purplemap[120] = (UINT8)194; - yellowmap[120] = (UINT8)103; - greenmap[120] = (UINT8)162; - bluemap[120] = (UINT8)228; - redmap[120] = (UINT8)126; // battle - graymap[120] = (UINT8)10; - orangemap[120] = (UINT8)85; // record attack - skymap[120] = (UINT8)214; // race - lavendermap[120] = (UINT8)248; - goldmap[120] = (UINT8)114; - teamap[120] = (UINT8)177; - steelmap[120] = (UINT8)201; - pinkmap[120] = (UINT8)145; - brownmap[120] = (UINT8)48; - peachmap[120] = (UINT8)69; // nice + purplemap[0] = (UINT8)163; + yellowmap[0] = (UINT8)73; + greenmap[0] = (UINT8)98; + bluemap[0] = (UINT8)148; + redmap[0] = (UINT8)34; // battle + graymap[0] = (UINT8)10; + orangemap[0] = (UINT8)52; // record attack + skymap[0] = (UINT8)132; // race + lavendermap[0] = (UINT8)192; + goldmap[0] = (UINT8)65; + aquamap[0] = (UINT8)121; + magentamap[0] = (UINT8)182; + pinkmap[0] = (UINT8)210; + brownmap[0] = (UINT8)224; + tanmap[0] = (UINT8)217; // no longer nice :( // Init back colormap CON_SetupBackColormap(); @@ -467,6 +468,12 @@ static void CON_RecalcSize(void) con_destlines = vid.height; } + if (con_destlines > 0) // Resize console if already open + { + CON_ChangeHeight(); + con_curlines = con_destlines; + } + // check for change of video width if (conw == con_width) return; // didn't change @@ -516,6 +523,20 @@ static void CON_RecalcSize(void) Z_Free(tmp_buffer); } +static void CON_ChangeHeight(void) +{ + INT32 minheight = 20 * con_scalefactor; // 20 = 8+8+4 + + // toggle console in + con_destlines = (cons_height.value*vid.height)/100; + if (con_destlines < minheight) + con_destlines = minheight; + else if (con_destlines > vid.height) + con_destlines = vid.height; + + con_destlines &= ~0x3; // multiple of text row height +} + // Handles Console moves in/out of screen (per frame) // static void CON_MoveConsole(void) @@ -620,16 +641,7 @@ void CON_Ticker(void) CON_ClearHUD(); } else - { - // toggle console in - con_destlines = (cons_height.value*vid.height)/100; - if (con_destlines < minheight) - con_destlines = minheight; - else if (con_destlines > vid.height) - con_destlines = vid.height; - - con_destlines &= ~0x3; // multiple of text row height - } + CON_ChangeHeight(); } // console movement @@ -1149,6 +1161,7 @@ static void CON_Print(char *msg) { size_t l; INT32 controlchars = 0; // for color changing + char color = '\x80'; // keep color across lines if (msg == NULL) return; @@ -1174,7 +1187,7 @@ static void CON_Print(char *msg) { if (*msg & 0x80) { - con_line[con_cx++] = *(msg++); + color = con_line[con_cx++] = *(msg++); controlchars++; continue; } @@ -1182,12 +1195,14 @@ static void CON_Print(char *msg) { con_cy--; CON_Linefeed(); + color = '\x80'; controlchars = 0; } else if (*msg == '\n') // linefeed { CON_Linefeed(); - controlchars = 0; + con_line[con_cx++] = color; + controlchars = 1; } else if (*msg == ' ') // space { @@ -1195,7 +1210,8 @@ static void CON_Print(char *msg) if (con_cx - controlchars >= con_width-11) { CON_Linefeed(); - controlchars = 0; + con_line[con_cx++] = color; + controlchars = 1; } } else if (*msg == '\t') @@ -1210,7 +1226,8 @@ static void CON_Print(char *msg) if (con_cx - controlchars >= con_width-11) { CON_Linefeed(); - controlchars = 0; + con_line[con_cx++] = color; + controlchars = 1; } } msg++; @@ -1227,7 +1244,8 @@ static void CON_Print(char *msg) if ((con_cx - controlchars) + l > con_width-11) { CON_Linefeed(); - controlchars = 0; + con_line[con_cx++] = color; + controlchars = 1; } // a word at a time @@ -1454,7 +1472,7 @@ static void CON_DrawInput(void) { x -= charwidth*3; if (input_sel < c) - V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 107 | V_NOSCALESTART); + V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 77 | V_NOSCALESTART); for (i = 0; i < 3; ++i, x += charwidth) V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); } @@ -1465,7 +1483,7 @@ static void CON_DrawInput(void) { if ((input_sel > c && input_cur <= c) || (input_sel <= c && input_cur > c)) { - V_DrawFill(x, y, charwidth, (10 * con_scalefactor), 107 | V_NOSCALESTART); + V_DrawFill(x, y, charwidth, (10 * con_scalefactor), 77 | V_NOSCALESTART); V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, !cv_allcaps.value); } else @@ -1479,7 +1497,7 @@ static void CON_DrawInput(void) if (rellip) { if (input_sel > cend) - V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 107 | V_NOSCALESTART); + V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 77 | V_NOSCALESTART); for (i = 0; i < 3; ++i, x += charwidth) V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); } @@ -1582,8 +1600,7 @@ static void CON_DrawConsole(void) i = con_cy - con_scrollup; // skip the last empty line due to the cursor being at the start of a new line - if (!con_scrollup && !con_cx) - i--; + i--; i -= (con_curlines - minheight) / charheight; diff --git a/src/console.h b/src/console.h index 11621746c..7ed585177 100644 --- a/src/console.h +++ b/src/console.h @@ -39,7 +39,7 @@ extern UINT32 con_scalefactor; // console text scale factor extern consvar_t cons_backcolor, cons_menuhighlight; extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap,\ - *skymap, *goldmap, *lavendermap, *teamap, *steelmap, *pinkmap, *brownmap, *peachmap; + *skymap, *goldmap, *lavendermap, *aquamap, *magentamap, *pinkmap, *brownmap, *tanmap; // Console bg color (auto updated to match) extern UINT8 *consolebgmap; diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e3d3bbef7..fa228df06 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1175,7 +1175,7 @@ static inline void CL_DrawConnectionStatus(void) if (cl_mode != CL_DOWNLOADFILES) { INT32 i, animtime = ((ccstime / 4) & 15) + 16; - UINT8 palstart = (cl_mode == CL_SEARCHING) ? 128 : 160; + UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96; // 15 pal entries total. const char *cltext; @@ -1259,8 +1259,8 @@ static inline void CL_DrawConnectionStatus(void) dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); if (dldlength > 256) dldlength = 256; - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 160); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 96); memset(tempname, 0, sizeof(tempname)); // offset filename to just the name only part @@ -2309,20 +2309,14 @@ static void CL_ConnectToServer(boolean viams) if (i != -1) { - INT32 j; + UINT8 num = serverlist[i].info.gametype; const char *gametypestr = NULL; strncpy(connectedservername, serverlist[i].info.servername, MAXSERVERNAME); CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); - for (j = 0; gametype_cons_t[j].strvalue; j++) - { - if (gametype_cons_t[j].value == serverlist[i].info.gametype) - { - gametypestr = gametype_cons_t[j].strvalue; - break; - } - } + if (num < NUMGAMETYPES) + gametypestr = Gametype_Names[num]; if (gametypestr) CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, @@ -5235,7 +5229,7 @@ void TryRunTics(tic_t realtics) if (realtics >= 1) { - COM_BufExecute(); + COM_BufTicker(); if (mapchangepending) D_MapChange(-1, 0, encoremode, false, 2, false, fromlevelselect); // finish the map change } diff --git a/src/d_main.c b/src/d_main.c index c2d1d2869..1404a5e61 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -793,7 +793,6 @@ void D_StartTitle(void) paused = false; advancedemo = false; F_StartTitleScreen(); - CON_ToggleOff(); // Reset the palette -- SRB2Kart: actually never mind let's do this in the middle of every fade /*if (rendermode != render_none) @@ -837,11 +836,11 @@ static inline void D_CleanFile(char **filearray) static void IdentifyVersion(void) { - char *srb2wad1, *srb2wad2; + char *mainresource; const char *srb2waddir = NULL; #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - // change to the directory where 'srb2.srb' is found + // change to the directory where 'main.kart' is found srb2waddir = I_LocateWad(); #endif @@ -872,46 +871,34 @@ static void IdentifyVersion(void) srb2waddir = I_GetWadDir(); #endif // Commercial. - srb2wad1 = malloc(strlen(srb2waddir)+1+8+1); - srb2wad2 = malloc(strlen(srb2waddir)+1+8+1); - if (srb2wad1 == NULL && srb2wad2 == NULL) + mainresource = malloc(strlen(srb2waddir)+1+9+1); + if (mainresource == NULL) I_Error("No more free memory to look in %s", srb2waddir); - if (srb2wad1 != NULL) - sprintf(srb2wad1, pandf, srb2waddir, "srb2.srb"); - if (srb2wad2 != NULL) - sprintf(srb2wad2, pandf, srb2waddir, "srb2.wad"); + if (mainresource != NULL) + sprintf(mainresource, pandf, srb2waddir, "main.kart"); // will be overwritten in case of -cdrom or unix/win home snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2waddir); configfile[sizeof configfile - 1] = '\0'; // Load the IWAD - if (srb2wad2 != NULL && FIL_ReadFileOK(srb2wad2)) - D_AddFile(srb2wad2, startupwadfiles); - else if (srb2wad1 != NULL && FIL_ReadFileOK(srb2wad1)) - D_AddFile(srb2wad1, startupwadfiles); + if (mainresource != NULL && FIL_ReadFileOK(mainresource)) + D_AddFile(mainresource, startupwadfiles); else - I_Error("SRB2.SRB/SRB2.WAD not found! Expected in %s, ss files: %s or %s\n", srb2waddir, srb2wad1, srb2wad2); + I_Error("MAIN.KART not found! Expected in %s, ss file: %s \n", srb2waddir, mainresource); - if (srb2wad1) - free(srb2wad1); - if (srb2wad2) - free(srb2wad2); + if (mainresource) + free(mainresource); // if you change the ordering of this or add/remove a file, be sure to update the md5 // checking in D_SRB2Main -#ifdef USE_PATCH_DTA - // Add our crappy patches to fix our bugs - D_AddFile(va(pandf,srb2waddir,"patch.dta")); -#endif - - D_AddFile(va(pandf,srb2waddir,"gfx.kart"), startupwadfiles); - D_AddFile(va(pandf,srb2waddir,"textures.kart"), startupwadfiles); - D_AddFile(va(pandf,srb2waddir,"chars.kart"), startupwadfiles); - D_AddFile(va(pandf,srb2waddir,"maps.kart"), startupwadfiles); -#ifdef USE_PATCH_KART - D_AddFile(va(pandf,srb2waddir,"patch.kart"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"gfx.pk3"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"textures.pk3"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"chars.pk3"), startupwadfiles); + D_AddFile(va(pandf,srb2waddir,"maps.wad"), startupwadfiles); // TODO: make this a pk3 too! +#ifdef USE_PATCH_FILE + D_AddFile(va(pandf,srb2waddir,"patch.pk3"), startupwadfiles); #endif #if !defined (HAVE_SDL) || defined (HAVE_MIXER) @@ -924,8 +911,8 @@ static void IdentifyVersion(void) else if (ms == 0) \ I_Error("File "str" has been modified with non-music/sound lumps"); \ } - MUSICTEST("sounds.kart") - MUSICTEST("music.kart") + MUSICTEST("sounds.wad") + MUSICTEST("music.wad") #undef MUSICTEST #endif } @@ -1190,6 +1177,10 @@ void D_SRB2Main(void) // Setup default unlockable conditions M_SetupDefaultConditionSets(); + // Setup character tables + // Have to be done here before files are loaded + M_InitCharacterTables(); + // load wad, including the main wad file CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); if (!W_InitMultipleFiles(startupwadfiles, false)) @@ -1205,27 +1196,21 @@ void D_SRB2Main(void) #ifndef DEVELOP // Check MD5s of autoloaded files // Note: Do not add any files that ignore MD5! - W_VerifyFileMD5(mainwads, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad -#ifdef USE_PATCH_DTA - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_DTA); // patch.dta -#endif - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.kart - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_KART); // textures.kart - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart -- 4 - If you touch this, make sure to touch up the majormods stuff below. -#ifdef USE_PATCH_KART - mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); // patch.kart + W_VerifyFileMD5(mainwads, ASSET_HASH_MAIN_KART); // main.kart + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_PK3); // gfx.pk3 + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_PK3); // textures.pk3 + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_PK3); // chars.pk3 + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_WAD); // maps.wad -- 4 - If you touch this, make sure to touch up the majormods stuff below. +#ifdef USE_PATCH_FILE + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_PK3); // patch.pk3 #endif #else -#ifdef USE_PATCH_DTA - mainwads++; // patch.dta -#endif - mainwads++; // gfx.kart - mainwads++; // textures.kart - mainwads++; // chars.kart - mainwads++; // maps.kart -#ifdef USE_PATCH_KART - mainwads++; // patch.kart + mainwads++; // gfx.pk3 + mainwads++; // textures.pk3 + mainwads++; // chars.pk3 + mainwads++; // maps.wad +#ifdef USE_PATCH_FILE + mainwads++; // patch.pk3 #endif #endif //ifndef DEVELOP @@ -1520,13 +1505,9 @@ void D_SRB2Main(void) INT16 newgametype = -1; const char *sgametype = M_GetNextParm(); - for (j = 0; gametype_cons_t[j].strvalue; j++) - if (!strcasecmp(gametype_cons_t[j].strvalue, sgametype)) - { - newgametype = (INT16)gametype_cons_t[j].value; - break; - } - if (!gametype_cons_t[j].strvalue) // reached end of the list with no match + newgametype = G_GetGametypeByName(sgametype); + + if (newgametype == -1) // reached end of the list with no match { j = atoi(sgametype); // assume they gave us a gametype number, which is okay too if (j >= 0 && j < NUMGAMETYPES) @@ -1581,13 +1562,13 @@ void D_SRB2Main(void) } else if (M_CheckParm("-skipintro")) { - CON_ToggleOff(); - CON_ClearHUD(); F_StartTitleScreen(); } else F_StartIntro(); // Tails 03-03-2002 + CON_ToggleOff(); + if (dedicated && server) { pagename = "TITLESKY"; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index dda897ed0..c4d99e840 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -516,17 +516,24 @@ const char *netxcmdnames[MAXNETXCMD - 1] = */ void D_RegisterServerCommands(void) { - int i; + INT32 i; Forceskin_cons_t[0].value = -1; Forceskin_cons_t[0].strvalue = "Off"; - // Set the values to 0/NULl, it will be overwritten later when a skin is assigned to the slot. + for (i = 0; i < NUMGAMETYPES; i++) + { + gametype_cons_t[i].value = i; + gametype_cons_t[i].strvalue = Gametype_Names[i]; + } + gametype_cons_t[NUMGAMETYPES].value = 0; + gametype_cons_t[NUMGAMETYPES].strvalue = NULL; + + // Set the values to 0/NULL, it will be overwritten later when a skin is assigned to the slot. for (i = 1; i < MAXSKINS; i++) { Forceskin_cons_t[i].value = 0; Forceskin_cons_t[i].strvalue = NULL; } - RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor); RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref); RegisterNetXCmd(XD_MAP, Got_Mapcmd); @@ -2435,7 +2442,7 @@ static void Command_Map_f(void) { const char *mapname; size_t i; - INT32 j, newmapnum; + INT32 newmapnum; boolean newresetplayers, newencoremode; INT32 newgametype = gametype; @@ -2503,26 +2510,12 @@ static void Command_Map_f(void) return; } - for (j = 0; gametype_cons_t[j].strvalue; j++) - if (!strcasecmp(gametype_cons_t[j].strvalue, COM_Argv(i+1))) - { - // 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; - } - - if (!gametype_cons_t[j].strvalue) // reached end of the list with no match + newgametype = G_GetGametypeByName(COM_Argv(i+1)); + if (newgametype == -1) // reached end of the list with no match { - // assume they gave us a gametype number, which is okay too - for (j = 0; gametype_cons_t[j].strvalue != NULL; j++) - { - if (atoi(COM_Argv(i+1)) == gametype_cons_t[j].value) - { - newgametype = gametype_cons_t[j].value; - break; - } - } + INT32 j = atoi(COM_Argv(i+1)); // assume they gave us a gametype number, which is okay too + if (j >= 0 && j < NUMGAMETYPES) + newgametype = (INT16)j; } } @@ -2549,15 +2542,20 @@ static void Command_Map_f(void) ; // 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 + else if (!mapheaderinfo[newmapnum-1] + || !(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype))) { - if (!mapheaderinfo[newmapnum-1] - || !(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype))) + char gametypestring[32] = "Single Player"; + + if (multiplayer) { - 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; + if (newgametype >= 0 && newgametype < NUMGAMETYPES + && Gametype_Names[newgametype]) + strcpy(gametypestring, Gametype_Names[newgametype]); } + + CONS_Alert(CONS_WARNING, M_GetText("%s doesn't support %s mode!\n(Use -force to override)\n"), mapname, gametypestring); + return; } // Prevent warping to locked levels @@ -2642,9 +2640,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) CON_LogMessage(M_GetText("Speeding off to level...\n")); } - CON_ToggleOff(); - CON_ClearHUD(); - if (demo.playback && !demo.timing) precache = false; @@ -4613,12 +4608,22 @@ static void Command_ModDetails_f(void) // static void Command_ShowGametype_f(void) { + const char *gametypestr = NULL; + if (!(netgame || multiplayer)) // print "Single player" instead of "Race" { CONS_Printf(M_GetText("Current gametype is %s\n"), "Single Player"); return; } - CONS_Printf(M_GetText("Current gametype is %s\n"), gametype_cons_t[gametype].strvalue); + + // get name string for current gametype + if (gametype >= 0 && gametype < NUMGAMETYPES) + gametypestr = Gametype_Names[gametype]; + + 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); } /** Plays the intro. @@ -4762,9 +4767,18 @@ static void TimeLimit_OnChange(void) */ void D_GameTypeChanged(INT32 lastgametype) { - if (multiplayer) - CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), gametype_cons_t[lastgametype].strvalue, gametype_cons_t[gametype].strvalue); + if (netgame) + { + const char *oldgt = NULL, *newgt = NULL; + if (lastgametype >= 0 && lastgametype < NUMGAMETYPES) + oldgt = Gametype_Names[lastgametype]; + if (gametype >= 0 && lastgametype < NUMGAMETYPES) + newgt = Gametype_Names[gametype]; + + if (oldgt && newgt) + CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), oldgt, newgt); + } // 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)) diff --git a/src/d_netfil.c b/src/d_netfil.c index 4dcd3da4a..0b9dc9126 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -358,7 +358,6 @@ INT32 CL_CheckFiles(void) // return 1; // the first is the iwad (the main wad file) - // we don't care if it's called srb2.srb or srb2.wad. // Never download the IWAD, just assume it's there and identical // ...No! Why were we sending the base wads to begin with?? //fileneeded[0].status = FS_OPEN; @@ -774,17 +773,14 @@ void Got_Filetxpak(void) char *filename = file->filename; static INT32 filetime = 0; - if (!(strcmp(filename, "srb2.srb") - && strcmp(filename, "srb2.wad") - && strcmp(filename, "patch.dta") - //&& strcmp(filename, "music.dta") - && strcmp(filename, "gfx.kart") - && strcmp(filename, "textures.kart") - && strcmp(filename, "chars.kart") - && strcmp(filename, "maps.kart") - && strcmp(filename, "sounds.kart") - && strcmp(filename, "music.kart") - && strcmp(filename, "patch.kart") + if (!(strcmp(filename, "main.kart") + && strcmp(filename, "gfx.pk3") + && strcmp(filename, "textures.pk3") + && strcmp(filename, "chars.pk3") + && strcmp(filename, "maps.wad") + && strcmp(filename, "patch.pk3") + && strcmp(filename, "sounds.wad") + && strcmp(filename, "music.wad") )) I_Error("Tried to download \"%s\"", filename); diff --git a/src/d_player.h b/src/d_player.h index 4b08d111a..e794f4903 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -235,6 +235,7 @@ typedef enum //{ SRB2kart - kartstuff typedef enum { + // TODO: Kill this giant array. Add them as actual player_t variables, or condense related timers into their own, smaller arrays. // Basic gameplay things k_position, // Used for Kart positions, mostly for deterministic stuff k_oldposition, // Used for taunting when you pass someone @@ -248,13 +249,7 @@ typedef enum k_dropdash, // Charge up for respawn Drop Dash k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir") - k_lapanimation, // Used to show the lap start wing logo animation - k_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down: - 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_enginesnd, // Engine sound number you're on. 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, 2 = stay still & no flashing tics @@ -284,9 +279,6 @@ typedef enum k_draftpower, // Drafting power (from 0 to FRACUNIT), doubles your top speed & acceleration at max k_draftleeway, // Leniency timer before removing draft power k_lastdraft, // Last player being drafted - k_boostcam, // Camera push forward on boost - k_destboostcam, // Ditto - k_timeovercam, // Camera timer for leaving behind or not k_aizdriftstrat, // Let go of your drift while boosting? Helper for the SICK STRATZ you have just unlocked k_brakedrift, // Helper for brake-drift spark spawning @@ -327,11 +319,8 @@ typedef enum 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 - k_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly // v1.0.2+ vars - k_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator - k_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items) k_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed k_jawztargetdelay, // Delay for Jawz target switching, to make it less twitchy k_spectatewait, // How long have you been waiting as a spectator @@ -340,6 +329,40 @@ typedef enum NUMKARTSTUFF } kartstufftype_t; +typedef enum +{ + // Unsynced, HUD or clientsided effects + // Item box + khud_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator + khud_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items) + + // Rings + khud_ringframe, // Ring spin frame + khud_ringtics, // Tics left until next ring frame + khud_ringdelay, // Next frame's tics + khud_ringspblock, // Which frame of the SPB ring lock animation to use + + // Lap finish + khud_lapanimation, // Used to show the lap start wing logo animation + khud_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down: + + // Camera + khud_boostcam, // Camera push forward on boost + khud_destboostcam, // Ditto + khud_timeovercam, // Camera timer for leaving behind or not + + // Sounds + khud_enginesnd, // Engine sound offset this player is using. + khud_voices, // Used to stop the player saying more voices than it should + khud_tauntvoices, // Used to specifically stop taunt voice spam + + // Battle + khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics + khud_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly + + NUMKARTHUD +} karthudtype_t; + // QUICKLY GET EITHER SNEAKER OR LEVEL BOOSTER SINCE THEY ARE FUNCTIONALLY IDENTICAL #define EITHERSNEAKER(p) (p->kartstuff[k_sneakertimer] || p->kartstuff[k_levelbooster]) @@ -403,6 +426,7 @@ typedef struct player_s // SRB2kart stuff INT32 kartstuff[NUMKARTSTUFF]; + INT32 karthud[NUMKARTHUD]; angle_t frameangle; // for the player add the ability to have the sprite only face other angles INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)? INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right diff --git a/src/dehacked.c b/src/dehacked.c index 3db8962d2..609eec42a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1216,6 +1216,13 @@ static void readlevelheader(MYFILE *f, INT32 num) #endif else if (fastcmp(word, "MUSICTRACK")) mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1); + else if (fastcmp(word, "MUSICPOS")) + mapheaderinfo[num-1]->muspos = (UINT32)get_number(word2); + else if (fastcmp(word, "MUSICINTERFADEOUT")) + mapheaderinfo[num-1]->musinterfadeout = (UINT32)get_number(word2); + else if (fastcmp(word, "MUSICINTER")) + deh_strlcpy(mapheaderinfo[num-1]->musintername, word2, + sizeof(mapheaderinfo[num-1]->musintername), va("Level header %d: intermission music", num)); else if (fastcmp(word, "FORCECHARACTER")) { strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1); @@ -1539,6 +1546,11 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE); cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK; } + else if (fastcmp(word, "MUSICPOS")) + { + DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchposition), UNDO_NONE); + cutscenes[num]->scene[scenenum].musswitchposition = (UINT32)get_number(word2); + } else if (fastcmp(word, "MUSICLOOP")) { DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE); @@ -3737,8 +3749,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) } else if (fastcmp(word, "SRB2")) { - if (mainwads) // srb2.srb triggers this warning otherwise - deh_warning("Patch is only compatible with base SRB2."); + deh_warning("Patch is only compatible with base SRB2."); } // Clear all data in certain locations (mostly for unlocks) // Unless you REALLY want to piss people off, @@ -8180,51 +8191,46 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "GREY", // SKINCOLOR_GREY "NICKEL", // SKINCOLOR_NICKEL "BLACK", // SKINCOLOR_BLACK - "SKUNK", // SKINCOLOR_SKUNK "FAIRY", // SKINCOLOR_FAIRY "POPCORN", // SKINCOLOR_POPCORN "ARTICHOKE", // SKINCOLOR_ARTICHOKE "PIGEON", // SKINCOLOR_PIGEON "SEPIA", // SKINCOLOR_SEPIA "BEIGE", // SKINCOLOR_BEIGE - "WALNUT", // SKINCOLOR_WALNUT + "CARAMEL", // SKINCOLOR_CARAMEL + "PEACH", // SKINCOLOR_PEACH "BROWN", // SKINCOLOR_BROWN "LEATHER", // SKINCOLOR_LEATHER "SALMON", // SKINCOLOR_SALMON "PINK", // SKINCOLOR_PINK "ROSE", // SKINCOLOR_ROSE - "BRICK", // SKINCOLOR_BRICK "CINNAMON", // SKINCOLOR_CINNAMON "RUBY", // SKINCOLOR_RUBY "RASPBERRY", // SKINCOLOR_RASPBERRY - "CHERRY", // SKINCOLOR_CHERRY "RED", // SKINCOLOR_RED "CRIMSON", // SKINCOLOR_CRIMSON "MAROON", // SKINCOLOR_MAROON "LEMONADE", // SKINCOLOR_LEMONADE - "FLAME", // SKINCOLOR_FLAME "SCARLET", // SKINCOLOR_SCARLET "KETCHUP", // SKINCOLOR_KETCHUP "DAWN", // SKINCOLOR_DAWN "SUNSET", // SKINCOLOR_SUNSET "CREAMSICLE", // SKINCOLOR_CREAMSICLE "ORANGE", // SKINCOLOR_ORANGE - "PUMPKIN", // SKINCOLOR_PUMPKIN "ROSEWOOD", // SKINCOLOR_ROSEWOOD - "BURGUNDY", // SKINCOLOR_BURGUNDY "TANGERINE", // SKINCOLOR_TANGERINE - "PEACH", // SKINCOLOR_PEACH - "CARAMEL", // SKINCOLOR_CARAMEL + "TAN", // SKINCOLOR_TAN "CREAM", // SKINCOLOR_CREAM "GOLD", // SKINCOLOR_GOLD "ROYAL", // SKINCOLOR_ROYAL "BRONZE", // SKINCOLOR_BRONZE "COPPER", // SKINCOLOR_COPPER - "QUARRY", // SKINCOLOR_QUARRY "YELLOW", // SKINCOLOR_YELLOW "MUSTARD", // SKINCOLOR_MUSTARD - "CROCODILE", // SKINCOLOR_CROCODILE + "BANANA", // SKINCOLOR_BANANA "OLIVE", // SKINCOLOR_OLIVE + "CROCODILE", // SKINCOLOR_CROCODILE + "PERIDOT", // SKINCOLOR_PERIDOT "VOMIT", // SKINCOLOR_VOMIT "GARDEN", // SKINCOLOR_GARDEN "LIME", // SKINCOLOR_LIME @@ -8237,14 +8243,16 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "MINT", // SKINCOLOR_MINT "GREEN", // SKINCOLOR_GREEN "PINETREE", // SKINCOLOR_PINETREE - "EMERALD", // SKINCOLOR_EMERALD + "TURTLE", // SKINCOLOR_TURTLE "SWAMP", // SKINCOLOR_SWAMP "DREAM", // SKINCOLOR_DREAM "PLAGUE", // SKINCOLOR_PLAGUE + "EMERALD", // SKINCOLOR_EMERALD "ALGAE", // SKINCOLOR_ALGAE "CARIBBEAN", // SKINCOLOR_CARIBBEAN "AZURE", // SKINCOLOR_AZURE - "AQUA", // SKINCOLOR_AQUA + "AQUAMARINE", // SKINCOLOR_AQUAMARINE + "TURQUOISE", // SKINCOLOR_TURQUOISE "TEAL", // SKINCOLOR_TEAL "CYAN", // SKINCOLOR_CYAN "JAWZ", // SKINCOLOR_JAWZ @@ -8254,20 +8262,22 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "SLATE", // SKINCOLOR_SLATE "STEEL", // SKINCOLOR_STEEL "THUNDER", // SKINCOLOR_THUNDER + "NOVA", // SKINCOLOR_NOVA "RUST", // SKINCOLOR_RUST "WRISTWATCH", // SKINCOLOR_WRISTWATCH "JET", // SKINCOLOR_JET "SAPPHIRE", // SKINCOLOR_SAPPHIRE + "ULTRAMARINE", // SKINCOLOR_ULTRAMARINE "PERIWINKLE", // SKINCOLOR_PERIWINKLE "BLUE", // SKINCOLOR_BLUE "BLUEBERRY", // SKINCOLOR_BLUEBERRY - "NOVA", // SKINCOLOR_NOVA + "THISTLE", // SKINCOLOR_THISTLE + "PURPLE", // SKINCOLOR_PURPLE "PASTEL", // SKINCOLOR_PASTEL "MOONSLAM", // SKINCOLOR_MOONSLAM - "ULTRAVIOLET", // SKINCOLOR_ULTRAVIOLET "DUSK", // SKINCOLOR_DUSK "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM - "PURPLE", // SKINCOLOR_PURPLE + "MAGENTA", // SKINCOLOR_MAGENTA "FUCHSIA", // SKINCOLOR_FUCHSIA "TOXIC", // SKINCOLOR_TOXIC "MAUVE", // SKINCOLOR_MAUVE @@ -8275,6 +8285,7 @@ static const char *COLOR_ENUMS[] = { // Rejigged for Kart. "BYZANTIUM", // SKINCOLOR_BYZANTIUM "POMEGRANATE", // SKINCOLOR_POMEGRANATE "LILAC", // SKINCOLOR_LILAC + "TAFFY", // SKINCOLOR_TAFFY // Special super colors // Super Sonic Yellow @@ -8390,13 +8401,7 @@ static const char *const KARTSTUFF_LIST[] = { "DROPDASH", "THROWDIR", - "LAPANIMATION", - "LAPHAND", - "CARDANIMATION", - "VOICES", - "TAUNTVOICES", "INSTASHIELD", - "ENGINESND", "FLOORBOOST", "SPINOUTTYPE", @@ -8426,9 +8431,6 @@ static const char *const KARTSTUFF_LIST[] = { "DRAFTPOWER", "DRAFTLEEWAY", "LASTDRAFT", - "BOOSTCAM", - "DESTBOOSTCAM", - "TIMEOVERCAM", "AIZDRIFTSTRAT", "BRAKEDRIFT", @@ -8465,10 +8467,7 @@ static const char *const KARTSTUFF_LIST[] = { "COMEBACKPOINTS", "COMEBACKMODE", "WANTED", - "YOUGOTEM", - "ITEMBLINK", - "ITEMBLINKMODE", "GETSPARKS", "JAWZTARGETDELAY", "SPECTATEWAIT", @@ -8547,6 +8546,7 @@ struct { // doomdef.h constants {"TICRATE",TICRATE}, + {"MUSICRATE",MUSICRATE}, {"RING_DIST",RING_DIST}, {"PUSHACCEL",PUSHACCEL}, {"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into. @@ -8928,11 +8928,11 @@ struct { {"V_SKYMAP",V_SKYMAP}, {"V_LAVENDERMAP",V_LAVENDERMAP}, {"V_GOLDMAP",V_GOLDMAP}, - {"V_TEAMAP",V_TEAMAP}, - {"V_STEELMAP",V_STEELMAP}, + {"V_AQUAMAP",V_AQUAMAP}, + {"V_MAGENTAMAP",V_MAGENTAMAP}, {"V_PINKMAP",V_PINKMAP}, {"V_BROWNMAP",V_BROWNMAP}, - {"V_PEACHMAP",V_PEACHMAP}, + {"V_TANMAP",V_TANMAP}, {"V_TRANSLUCENT",V_TRANSLUCENT}, {"V_10TRANS",V_10TRANS}, {"V_20TRANS",V_20TRANS}, @@ -9913,6 +9913,9 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"mapmusflags")) { lua_pushinteger(L, mapmusflags); return 1; + } else if (fastcmp(word,"mapmusposition")) { + lua_pushinteger(L, mapmusposition); + return 1; } else if (fastcmp(word,"server")) { if ((!multiplayer || !(netgame || demo.playback)) && !playeringame[serverplayer]) return 0; diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c index 52c90aac2..88b598622 100644 --- a/src/djgppdos/i_sound.c +++ b/src/djgppdos/i_sound.c @@ -438,6 +438,37 @@ boolean I_SetSongSpeed(float speed) return false; } +/// ------------------------ +// MUSIC SEEKING +/// ------------------------ + +UINT32 I_GetSongLength(void) +{ + return 0; +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetSongLoopPoint(void) +{ + return 0; +} + +boolean I_SetSongPosition(UINT32 position) +{ + (void)position; + return false; +} + +UINT32 I_GetSongPosition(void) +{ + return 0; +} + /// ------------------------ // MUSIC PLAYBACK /// ------------------------ @@ -545,3 +576,44 @@ int I_QrySongPlaying(int handle) return (midi_pos==-1); } #endif + +/// ------------------------ +// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + (void)volume; +} + +void I_StopFadingSong(void) +{ +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); +{ + (void)target_volume; + (void)source_volume; + (void)ms; + return false; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); +{ + (void)target_volume; + (void)ms; + return false; +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + (void)ms; + return false; +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + (void)ms; + (void)looping; + return false; +} diff --git a/src/doomdef.h b/src/doomdef.h index acd279776..4d3934773 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -163,10 +163,7 @@ extern FILE *logstream; // Does this version require an added patch file? // Comment or uncomment this as necessary. -//#define USE_PATCH_DTA - -// Kart has it's own, as well. -#define USE_PATCH_KART +//#define USE_PATCH_FILE // Use .kart extension addons #define USE_KART @@ -260,51 +257,46 @@ typedef enum SKINCOLOR_GREY, SKINCOLOR_NICKEL, SKINCOLOR_BLACK, - SKINCOLOR_SKUNK, SKINCOLOR_FAIRY, SKINCOLOR_POPCORN, SKINCOLOR_ARTICHOKE, SKINCOLOR_PIGEON, SKINCOLOR_SEPIA, SKINCOLOR_BEIGE, - SKINCOLOR_WALNUT, + SKINCOLOR_CARAMEL, + SKINCOLOR_PEACH, SKINCOLOR_BROWN, SKINCOLOR_LEATHER, SKINCOLOR_SALMON, SKINCOLOR_PINK, SKINCOLOR_ROSE, - SKINCOLOR_BRICK, SKINCOLOR_CINNAMON, SKINCOLOR_RUBY, SKINCOLOR_RASPBERRY, - SKINCOLOR_CHERRY, SKINCOLOR_RED, SKINCOLOR_CRIMSON, SKINCOLOR_MAROON, SKINCOLOR_LEMONADE, - SKINCOLOR_FLAME, SKINCOLOR_SCARLET, SKINCOLOR_KETCHUP, SKINCOLOR_DAWN, SKINCOLOR_SUNSET, SKINCOLOR_CREAMSICLE, SKINCOLOR_ORANGE, - SKINCOLOR_PUMPKIN, SKINCOLOR_ROSEWOOD, - SKINCOLOR_BURGUNDY, SKINCOLOR_TANGERINE, - SKINCOLOR_PEACH, - SKINCOLOR_CARAMEL, + SKINCOLOR_TAN, SKINCOLOR_CREAM, SKINCOLOR_GOLD, SKINCOLOR_ROYAL, SKINCOLOR_BRONZE, SKINCOLOR_COPPER, - SKINCOLOR_QUARRY, SKINCOLOR_YELLOW, SKINCOLOR_MUSTARD, - SKINCOLOR_CROCODILE, + SKINCOLOR_BANANA, SKINCOLOR_OLIVE, + SKINCOLOR_CROCODILE, + SKINCOLOR_PERIDOT, SKINCOLOR_VOMIT, SKINCOLOR_GARDEN, SKINCOLOR_LIME, @@ -317,14 +309,16 @@ typedef enum SKINCOLOR_MINT, SKINCOLOR_GREEN, SKINCOLOR_PINETREE, - SKINCOLOR_EMERALD, + SKINCOLOR_TURTLE, SKINCOLOR_SWAMP, SKINCOLOR_DREAM, SKINCOLOR_PLAGUE, + SKINCOLOR_EMERALD, SKINCOLOR_ALGAE, SKINCOLOR_CARIBBEAN, SKINCOLOR_AZURE, - SKINCOLOR_AQUA, + SKINCOLOR_AQUAMARINE, + SKINCOLOR_TURQUOISE, SKINCOLOR_TEAL, SKINCOLOR_CYAN, SKINCOLOR_JAWZ, // Oni's torment @@ -334,20 +328,22 @@ typedef enum SKINCOLOR_SLATE, SKINCOLOR_STEEL, SKINCOLOR_THUNDER, + SKINCOLOR_NOVA, SKINCOLOR_RUST, SKINCOLOR_WRISTWATCH, SKINCOLOR_JET, SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave - slender aphrodite has overcome me with longing for a girl + SKINCOLOR_ULTRAMARINE, SKINCOLOR_PERIWINKLE, SKINCOLOR_BLUE, SKINCOLOR_BLUEBERRY, - SKINCOLOR_NOVA, + SKINCOLOR_THISTLE, + SKINCOLOR_PURPLE, SKINCOLOR_PASTEL, SKINCOLOR_MOONSLAM, - SKINCOLOR_ULTRAVIOLET, SKINCOLOR_DUSK, SKINCOLOR_BUBBLEGUM, - SKINCOLOR_PURPLE, + SKINCOLOR_MAGENTA, SKINCOLOR_FUCHSIA, SKINCOLOR_TOXIC, SKINCOLOR_MAUVE, @@ -355,6 +351,7 @@ typedef enum SKINCOLOR_BYZANTIUM, SKINCOLOR_POMEGRANATE, SKINCOLOR_LILAC, + SKINCOLOR_TAFFY, // "Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now." // (This comment is a dirty liar! This is only limited by the integer type, so 255 for UINT8.) @@ -433,6 +430,8 @@ typedef enum #define NEWTICRATERATIO 1 // try 4 for 140 fps :) #define NEWTICRATE (TICRATE*NEWTICRATERATIO) +#define MUSICRATE 1000 // sound timing is calculated by milliseconds + #define RING_DIST 1280*FRACUNIT // how close you need to be to a ring to attract it #define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items. diff --git a/src/doomstat.h b/src/doomstat.h index a9e67d845..1f855da27 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -33,8 +33,10 @@ extern INT16 gamemap; extern char mapmusname[7]; extern UINT16 mapmusflags; +extern UINT32 mapmusposition; #define MUSIC_TRACKMASK 0x0FFF // ----************ #define MUSIC_RELOADRESET 0x8000 // *--------------- +#define MUSIC_FORCERESET 0x4000 // -*-------------- // Use other bits if necessary. extern INT16 maptol; @@ -150,6 +152,7 @@ typedef struct char musswitch[7]; UINT16 musswitchflags; + UINT32 musswitchposition; UINT8 fadecolor; // Color number for fade, 0 means don't do the first fade UINT8 fadeinid; // ID of the first fade, to a color -- ignored if fadecolor is 0 @@ -221,6 +224,7 @@ typedef struct INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. char musname[7]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. + UINT32 muspos; ///< Music position to jump to. char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable. UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave. INT16 skynum; ///< Sky number to use. @@ -254,6 +258,10 @@ typedef struct //boolean automap; ///< Displays a level's white map outline in modified games fixed_t mobj_scale; ///< Replacement for TOL_ERZ3 + // Music stuff. + UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds + char musintername[7]; ///< Intermission screen music. + // Lua stuff. // (This is not ifdeffed so the map header structure can stay identical, just in case.) UINT8 numCustomOptions; ///< Internal. For Lua custom value support. @@ -324,7 +332,10 @@ enum GameType // SRB2Kart GT_HIDEANDSEEK, GT_CTF }; -// If you alter this list, update gametype_cons_t in m_menu.c +// If you alter this list, update dehacked.c, and Gametype_Names in g_game.c + +// String names for gametypes +extern const char *Gametype_Names[NUMGAMETYPES]; extern tic_t totalplaytime; extern UINT32 matchesplayed; diff --git a/src/dummy/i_sound.c b/src/dummy/i_sound.c index 7275bb1ae..f09158e01 100644 --- a/src/dummy/i_sound.c +++ b/src/dummy/i_sound.c @@ -95,6 +95,37 @@ boolean I_SetSongSpeed(float speed) return false; } +/// ------------------------ +// MUSIC SEEKING +/// ------------------------ + +UINT32 I_GetSongLength(void) +{ + return 0; +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetSongLoopPoint(void) +{ + return 0; +} + +boolean I_SetSongPosition(UINT32 position) +{ + (void)position; + return false; +} + +UINT32 I_GetSongPosition(void) +{ + return 0; +} + /// ------------------------ // MUSIC PLAYBACK /// ------------------------ @@ -142,4 +173,45 @@ boolean I_SetSongTrack(int track) { (void)track; return false; -} \ No newline at end of file +} + +/// ------------------------ +// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + (void)volume; +} + +void I_StopFadingSong(void) +{ +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); +{ + (void)target_volume; + (void)source_volume; + (void)ms; + return false; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); +{ + (void)target_volume; + (void)ms; + return false; +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + (void)ms; + return false; +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + (void)ms; + (void)looping; + return false; +} diff --git a/src/f_finale.c b/src/f_finale.c index 4d8d0607f..0932550fd 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -173,7 +173,7 @@ static void F_SkyScroll(INT32 scrollspeed) // SRB2Kart: F_DrawPatchCol is over-engineered; recoded to be less shitty and error-prone if (rendermode != render_none) { - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); x = -((INT32)animtimer); y = 0; @@ -238,7 +238,6 @@ void F_StartIntro(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); F_NewCutscene(introtext[0]); intro_scenenum = 0; @@ -275,7 +274,7 @@ static void F_IntroDrawScene(void) highres = true; } - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); if (background) { @@ -460,9 +459,13 @@ static const char *credits[] = { "\"ZarroTsu\"", "", "\1External Artists", + "\"1-Up Mason\"", + "\"Chengi\"", "\"Chrispy\"", "\"DirkTheHusky\"", + "\"LJSTAR\"", "\"MotorRoach\"", + "\"Mr. McScrewup\"", "\"Nev3r\"", "\"Ritz\"", "\"Rob\"", @@ -471,6 +474,7 @@ static const char *credits[] = { "\"Spherallic\"", "\"VAdaPEGA\"", "\"Virt\"", + "\"Voltrix\"", "\"zxyspku\"", "", "\1Sound Design", @@ -580,7 +584,6 @@ void F_StartCredits(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); S_StopMusic(); S_ChangeMusicInternal("credit", false); @@ -774,7 +777,6 @@ void F_StartGameEvaluation(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); finalecount = 0; } @@ -884,7 +886,6 @@ void F_StartGameEnd(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - CON_ClearHUD(); S_StopMusic(); // In case menus are still up?!! @@ -969,7 +970,7 @@ void F_TitleScreenDrawer(void) } else if (finalecount < 52) { - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); V_DrawSmallScaledPatch(84, 36, 0, ttkflash); } else @@ -985,7 +986,7 @@ void F_TitleScreenDrawer(void) V_DrawSciencePatch(280<scene[scenenum].ycoord[picnum]; if (cutscenes[cutnum]->scene[scenenum].musswitch[0]) - S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musswitch, + S_ChangeMusicEx(cutscenes[cutnum]->scene[scenenum].musswitch, cutscenes[cutnum]->scene[scenenum].musswitchflags, - cutscenes[cutnum]->scene[scenenum].musicloop); + cutscenes[cutnum]->scene[scenenum].musicloop, + cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0); // Fade to the next dofadenow = true; @@ -1370,8 +1371,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset F_NewCutscene(cutscenes[cutscenenum]->scene[0].text); - CON_ClearHUD(); - cutsceneover = false; runningprecutscene = precutscene; precutresetplayer = resetplayer; @@ -1392,9 +1391,10 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset stoptimer = 0; if (cutscenes[cutnum]->scene[0].musswitch[0]) - S_ChangeMusic(cutscenes[cutnum]->scene[0].musswitch, + S_ChangeMusicEx(cutscenes[cutnum]->scene[0].musswitch, cutscenes[cutnum]->scene[0].musswitchflags, - cutscenes[cutnum]->scene[0].musicloop); + cutscenes[cutnum]->scene[0].musicloop, + cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0); else S_StopMusic(); } diff --git a/src/g_game.c b/src/g_game.c index 2f5053d06..6f08eb7c6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -78,6 +78,7 @@ static void G_DoStartVote(void); char mapmusname[7]; // Music name UINT16 mapmusflags; // Track and reset bit +UINT32 mapmusposition; // Position to jump to INT16 gamemap = 1; INT16 maptol; @@ -1248,7 +1249,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (demo.playback) return; - player = &players[displayplayers[ssplayer-1]]; + if (ssplayer == 1) + player = &players[consoleplayer]; + else + player = &players[displayplayers[ssplayer-1]]; + if (ssplayer == 2) thiscam = (player->bot == 2 ? &camera[0] : &camera[ssplayer-1]); else @@ -2736,7 +2741,8 @@ void G_PlayerReborn(INT32 player) { strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); mapmusname[6] = 0; - mapmusflags = mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK; + mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); + mapmusposition = mapheaderinfo[gamemap-1]->muspos; songcredit = true; } } @@ -3268,6 +3274,36 @@ void G_ExitLevel(void) } } +// See also the enum GameType in doomstat.h +const char *Gametype_Names[NUMGAMETYPES] = +{ + "Race", // GT_RACE + "Battle" // GT_MATCH + + /*"Co-op", // GT_COOP + "Competition", // GT_COMPETITION + "Team Match", // GT_TEAMMATCH + "Tag", // GT_TAG + "Hide and Seek", // GT_HIDEANDSEEK + "CTF" // GT_CTF*/ +}; + +// +// G_GetGametypeByName +// +// Returns the number for the given gametype name string, or -1 if not valid. +// +INT32 G_GetGametypeByName(const char *gametypestr) +{ + INT32 i; + + for (i = 0; i < NUMGAMETYPES; i++) + if (!stricmp(gametypestr, Gametype_Names[i])) + return i; + + return -1; // unknown gametype +} + // // G_IsSpecialStage // @@ -3409,12 +3445,12 @@ UINT8 G_GetGametypeColor(INT16 gt) { if (modeattacking // == ATTACKING_RECORD || gamestate == GS_TIMEATTACK) - return orangemap[120]; + return orangemap[0]; if (gt == GT_MATCH) - return redmap[120]; + return redmap[0]; if (gt == GT_RACE) - return skymap[120]; - return 247; // FALLBACK + return skymap[0]; + return 255; // FALLBACK } // @@ -5915,7 +5951,8 @@ void G_StoreRewindInfo(void) void G_PreviewRewind(tic_t previewtime) { - size_t i, j; + SINT8 i; + size_t j; fixed_t tweenvalue = 0; rewindinfo_t *info = rewindhead, *next_info = rewindhead; @@ -5975,13 +6012,14 @@ void G_PreviewRewind(tic_t previewtime) players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j]; } - for (i = splitscreen+1; i > 0; i--) + for (i = splitscreen; i >= 0; i--) P_ResetCamera(&players[displayplayers[i]], &camera[i]); } void G_ConfirmRewind(tic_t rewindtime) { - tic_t i; + SINT8 i; + tic_t j; boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled; INT32 olddp1 = displayplayers[0], olddp2 = displayplayers[1], olddp3 = displayplayers[2], olddp4 = displayplayers[3]; @@ -6001,10 +6039,10 @@ void G_ConfirmRewind(tic_t rewindtime) G_DoPlayDemo(NULL); // Restart the current demo - for (i = 0; i < rewindtime && leveltime < rewindtime; i++) + for (j = 0; j < rewindtime && leveltime < rewindtime; i++) { //TryRunTics(1); - G_Ticker((i % NEWTICRATERATIO) == 0); + G_Ticker((j % NEWTICRATERATIO) == 0); } demo.rewinding = false; @@ -6023,7 +6061,7 @@ void G_ConfirmRewind(tic_t rewindtime) R_ExecuteSetViewSize(); G_ResetViews(); - for (i = splitscreen+1; i > 0; i--) + for (i = splitscreen; i >= 0; i--) P_ResetCamera(&players[displayplayers[i]], &camera[i]); } diff --git a/src/g_game.h b/src/g_game.h index 27cf60d4e..a69f91421 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -278,6 +278,7 @@ boolean G_CheckDemoStatus(void); void G_SaveDemo(void); boolean G_DemoTitleResponder(event_t *ev); +INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); boolean G_GametypeHasTeams(void); diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index b37850bb7..9ecb16a56 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -46,8 +46,8 @@ typedef unsigned char FBOOLEAN; #define HWR_PATCHES_CHROMAKEY_COLORINDEX 0 #define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 1 #else -#define HWR_PATCHES_CHROMAKEY_COLORINDEX 247 -#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 220 +#define HWR_PATCHES_CHROMAKEY_COLORINDEX 255 +#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 130 #endif // the chroma key color shows on border sprites, set it to black diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4d5767535..3fe1e18be 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4263,10 +4263,45 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t } } +// This is expecting a pointer to an array containing 4 wallVerts for a sprite +static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) +{ + if (cv_grspritebillboarding.value + && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) + && wallVerts) + { + float basey = FIXED_TO_FLOAT(spr->mobj->z); + float lowy = wallVerts[0].y; + if (P_MobjFlip(spr->mobj) == -1) + { + basey = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); + } + // Rotate sprites to fully billboard with the camera + // X, Y, AND Z need to be manipulated for the polys to rotate around the + // origin, because of how the origin setting works I believe that should + // be mobj->z or mobj->z + mobj->height + wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gr_viewludsin + basey; + wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gr_viewludsin + basey; + // translate back to be around 0 before translating back + wallVerts[3].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos; + wallVerts[2].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos; + + wallVerts[0].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos; + wallVerts[1].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos; + + wallVerts[3].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin; + wallVerts[2].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin; + + wallVerts[0].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin; + wallVerts[1].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin; + } +} + static void HWR_SplitSprite(gr_vissprite_t *spr) { float this_scale = 1.0f; FOutVector wallVerts[4]; + FOutVector baseWallVerts[4]; // This is what the verts should end up as GLPatch_t *gpatch; FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); @@ -4279,11 +4314,13 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) float realtop, realbot, top, bot; float towtop, towbot, towmult; float bheight; + float realheight, heightmult; const sector_t *sector = spr->mobj->subsector->sector; const lightlist_t *list = sector->lightlist; #ifdef ESLOPE float endrealtop, endrealbot, endtop, endbot; float endbheight; + float endrealheight; fixed_t temp; fixed_t v1x, v1y, v2x, v2y; #endif @@ -4316,16 +4353,16 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) HWR_DrawSpriteShadow(spr, gpatch, this_scale); } - wallVerts[0].x = wallVerts[3].x = spr->x1; - wallVerts[2].x = wallVerts[1].x = spr->x2; - wallVerts[0].z = wallVerts[3].z = spr->z1; - wallVerts[1].z = wallVerts[2].z = spr->z2; + baseWallVerts[0].x = baseWallVerts[3].x = spr->x1; + baseWallVerts[2].x = baseWallVerts[1].x = spr->x2; + baseWallVerts[0].z = baseWallVerts[3].z = spr->z1; + baseWallVerts[1].z = baseWallVerts[2].z = spr->z2; - wallVerts[2].y = wallVerts[3].y = spr->ty; + baseWallVerts[2].y = baseWallVerts[3].y = spr->ty; if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f) - wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale; + baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height * this_scale; else - wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height; + baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height; v1x = FLOAT_TO_FIXED(spr->x1); v1y = FLOAT_TO_FIXED(spr->z1); @@ -4334,44 +4371,56 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (spr->flip) { - wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s; - wallVerts[2].sow = wallVerts[1].sow = 0; - }else{ - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s; + baseWallVerts[2].sow = baseWallVerts[1].sow = 0; + } + else + { + baseWallVerts[0].sow = baseWallVerts[3].sow = 0; + baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t; - wallVerts[0].tow = wallVerts[1].tow = 0; - }else{ - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t; + baseWallVerts[0].tow = baseWallVerts[1].tow = 0; + } + else + { + baseWallVerts[3].tow = baseWallVerts[2].tow = 0; + baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t; } // if it has a dispoffset, push it a little towards the camera if (spr->dispoffset) { float co = -gr_viewcos*(0.05f*spr->dispoffset); float si = -gr_viewsin*(0.05f*spr->dispoffset); - wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si; - wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si; - wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co; - wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co; + baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si; + baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si; + baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co; + baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co; } - realtop = top = wallVerts[3].y; - realbot = bot = wallVerts[0].y; - towtop = wallVerts[3].tow; - towbot = wallVerts[0].tow; + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, baseWallVerts); + + realtop = top = baseWallVerts[3].y; + realbot = bot = baseWallVerts[0].y; + towtop = baseWallVerts[3].tow; + towbot = baseWallVerts[0].tow; towmult = (towbot - towtop) / (top - bot); #ifdef ESLOPE - endrealtop = endtop = wallVerts[2].y; - endrealbot = endbot = wallVerts[1].y; + endrealtop = endtop = baseWallVerts[2].y; + endrealbot = endbot = baseWallVerts[1].y; #endif + // copy the contents of baseWallVerts into the drawn wallVerts array + // baseWallVerts is used to know the final shape to easily get the vertex + // co-ordinates + memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts)); + if (!cv_translucency.value) // translucency disabled { Surf.FlatColor.s.alpha = 0xFF; @@ -4514,12 +4563,55 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; + + // The x and y only need to be adjusted in the case that it's not a papersprite + if (cv_grspritebillboarding.value + && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) + { + // Get the x and z of the vertices so billboarding draws correctly + realheight = realbot - realtop; + endrealheight = endrealbot - endrealtop; + heightmult = (realtop - top) / realheight; + wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + + heightmult = (endrealtop - endtop) / endrealheight; + wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + + heightmult = (realtop - bot) / realheight; + wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + + heightmult = (endrealtop - endbot) / endrealheight; + wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + } #else wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); wallVerts[2].y = wallVerts[3].y = top; wallVerts[0].y = wallVerts[1].y = bot; + + // The x and y only need to be adjusted in the case that it's not a papersprite + if (cv_grspritebillboarding.value + && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) + { + // Get the x and z of the vertices so billboarding draws correctly + realheight = realbot - realtop; + heightmult = (realtop - top) / realheight; + wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + + heightmult = (realtop - bot) / realheight; + wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; + wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; + wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; + wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; + } #endif if (colormap) @@ -4689,6 +4781,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co; } + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, wallVerts); + // This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black. // sprite lighting by modulating the RGB components /// \todo coloured @@ -4774,6 +4869,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) wallVerts[0].z = wallVerts[3].z = spr->z1; wallVerts[1].z = wallVerts[2].z = spr->z2; + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, wallVerts); + wallVerts[0].sow = wallVerts[3].sow = 0; wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index bf61d585e..7bc361d95 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -93,6 +93,7 @@ extern consvar_t cv_granisotropicmode; extern consvar_t cv_grcorrecttricks; extern consvar_t cv_grfovchange; extern consvar_t cv_grsolvetjoin; +extern consvar_t cv_grspritebillboarding; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowx, gr_baseviewwindowy; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index f343f12b7..7a912e010 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -793,13 +793,14 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) case SKINCOLOR_GREY: case SKINCOLOR_NICKEL: case SKINCOLOR_BLACK: - case SKINCOLOR_SKUNK: + case SKINCOLOR_PLATINUM: case SKINCOLOR_JET: cstart = "\x86"; // V_GRAYMAP break; case SKINCOLOR_SEPIA: case SKINCOLOR_BEIGE: - case SKINCOLOR_WALNUT: + case SKINCOLOR_CARAMEL: + case SKINCOLOR_PEACH: case SKINCOLOR_BROWN: case SKINCOLOR_LEATHER: case SKINCOLOR_RUST: @@ -810,20 +811,18 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) case SKINCOLOR_SALMON: case SKINCOLOR_PINK: case SKINCOLOR_ROSE: - case SKINCOLOR_BRICK: case SKINCOLOR_LEMONADE: case SKINCOLOR_BUBBLEGUM: case SKINCOLOR_LILAC: + case SKINCOLOR_TAFFY: cstart = "\x8d"; // V_PINKMAP break; case SKINCOLOR_CINNAMON: case SKINCOLOR_RUBY: case SKINCOLOR_RASPBERRY: - case SKINCOLOR_CHERRY: case SKINCOLOR_RED: case SKINCOLOR_CRIMSON: case SKINCOLOR_MAROON: - case SKINCOLOR_FLAME: case SKINCOLOR_SCARLET: case SKINCOLOR_KETCHUP: cstart = "\x85"; // V_REDMAP @@ -832,16 +831,13 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) case SKINCOLOR_SUNSET: case SKINCOLOR_CREAMSICLE: case SKINCOLOR_ORANGE: - case SKINCOLOR_PUMPKIN: case SKINCOLOR_ROSEWOOD: - case SKINCOLOR_BURGUNDY: case SKINCOLOR_TANGERINE: cstart = "\x87"; // V_ORANGEMAP break; - case SKINCOLOR_PEACH: - case SKINCOLOR_CARAMEL: + case SKINCOLOR_TAN: case SKINCOLOR_CREAM: - cstart = "\x8f"; // V_PEACHMAP + cstart = "\x8f"; // V_TANMAP break; case SKINCOLOR_GOLD: case SKINCOLOR_ROYAL: @@ -851,39 +847,43 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) cstart = "\x8A"; // V_GOLDMAP break; case SKINCOLOR_POPCORN: - case SKINCOLOR_QUARRY: case SKINCOLOR_YELLOW: case SKINCOLOR_MUSTARD: - case SKINCOLOR_CROCODILE: + case SKINCOLOR_BANANA: case SKINCOLOR_OLIVE: + case SKINCOLOR_CROCODILE: cstart = "\x82"; // V_YELLOWMAP break; case SKINCOLOR_ARTICHOKE: + case SKINCOLOR_PERIDOT: case SKINCOLOR_VOMIT: case SKINCOLOR_GARDEN: - case SKINCOLOR_TEA: - case SKINCOLOR_PISTACHIO: - cstart = "\x8b"; // V_TEAMAP - break; case SKINCOLOR_LIME: case SKINCOLOR_HANDHELD: + case SKINCOLOR_TEA: + case SKINCOLOR_PISTACHIO: case SKINCOLOR_MOSS: case SKINCOLOR_CAMOUFLAGE: case SKINCOLOR_ROBOHOOD: case SKINCOLOR_MINT: case SKINCOLOR_GREEN: case SKINCOLOR_PINETREE: - case SKINCOLOR_EMERALD: + case SKINCOLOR_TURTLE: case SKINCOLOR_SWAMP: case SKINCOLOR_DREAM: case SKINCOLOR_PLAGUE: + case SKINCOLOR_EMERALD: case SKINCOLOR_ALGAE: cstart = "\x83"; // V_GREENMAP break; case SKINCOLOR_CARIBBEAN: case SKINCOLOR_AZURE: - case SKINCOLOR_AQUA: + case SKINCOLOR_AQUAMARINE: + case SKINCOLOR_TURQUOISE: case SKINCOLOR_TEAL: + cstart = "\x8b"; // V_AQUAMAP + break; + case SKINCOLOR_PIGEON: case SKINCOLOR_CYAN: case SKINCOLOR_JAWZ: case SKINCOLOR_CERULEAN: @@ -891,24 +891,24 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) case SKINCOLOR_SAPPHIRE: cstart = "\x88"; // V_SKYMAP break; - case SKINCOLOR_PIGEON: - case SKINCOLOR_PLATINUM: case SKINCOLOR_STEEL: - cstart = "\x8c"; // V_STEELMAP - break; + case SKINCOLOR_ULTRAMARINE: case SKINCOLOR_PERIWINKLE: case SKINCOLOR_BLUE: case SKINCOLOR_BLUEBERRY: case SKINCOLOR_NOVA: cstart = "\x84"; // V_BLUEMAP break; - case SKINCOLOR_ULTRAVIOLET: + case SKINCOLOR_THISTLE: case SKINCOLOR_PURPLE: - case SKINCOLOR_FUCHSIA: + case SKINCOLOR_PASTEL: cstart = "\x81"; // V_PURPLEMAP break; - case SKINCOLOR_PASTEL: + case SKINCOLOR_MAGENTA: + case SKINCOLOR_FUCHSIA: case SKINCOLOR_MOONSLAM: + cstart = "\x8c"; // V_MAGENTAMAP + break; case SKINCOLOR_DUSK: case SKINCOLOR_TOXIC: case SKINCOLOR_MAUVE: @@ -1581,7 +1581,7 @@ static void HU_drawMiniChat(void) else { if (cv_chatbacktint.value) // on request of wolfy - V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); + V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 159|V_SNAPTOBOTTOM|V_SNAPTOLEFT); V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, !cv_allcaps.value, colormap); } @@ -1645,7 +1645,7 @@ static void HU_drawChatLog(INT32 offset) chat_topy = y + chat_scroll*charheight; chat_bottomy = chat_topy + boxh*charheight; - V_DrawFillConsoleMap(chatx, chat_topy, boxw, boxh*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box + V_DrawFillConsoleMap(chatx, chat_topy, boxw, boxh*charheight +2, 159|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box for (i=0; ikartstuff[k_roulettetype] == 2) { player->kartstuff[k_eggmanexplode] = 4*TICRATE; - //player->kartstuff[k_itemblink] = TICRATE; - //player->kartstuff[k_itemblinkmode] = 1; + //player->karthud[khud_itemblink] = TICRATE; + //player->karthud[khud_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1124,8 +1125,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { K_KartGetItemResult(player, cv_kartdebugitem.value); player->kartstuff[k_itemamount] = cv_kartdebugamount.value; - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = 2; + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = 2; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1142,7 +1143,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (mashed && (modeattacking || cv_superring.value)) // ANY mashed value? You get rings. { K_KartGetItemResult(player, KITEM_SUPERRING); - player->kartstuff[k_itemblinkmode] = 1; + player->karthud[khud_itemblinkmode] = 1; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolm); } @@ -1152,7 +1153,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) K_KartGetItemResult(player, KITEM_SNEAKER); else // Default to sad if nothing's enabled... K_KartGetItemResult(player, KITEM_SAD); - player->kartstuff[k_itemblinkmode] = 0; + player->karthud[khud_itemblinkmode] = 0; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolf); } @@ -1162,7 +1163,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (mashed && (modeattacking || cv_banana.value)) // ANY mashed value? You get a banana. { K_KartGetItemResult(player, KITEM_BANANA); - player->kartstuff[k_itemblinkmode] = 1; + player->karthud[khud_itemblinkmode] = 1; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolm); } @@ -1172,13 +1173,13 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) K_KartGetItemResult(player, KITEM_ORBINAUT); else // Default to sad if nothing's enabled... K_KartGetItemResult(player, KITEM_SAD); - player->kartstuff[k_itemblinkmode] = 0; + player->karthud[khud_itemblinkmode] = 0; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolf); } } - player->kartstuff[k_itemblink] = TICRATE; + player->karthud[khud_itemblink] = TICRATE; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; return; @@ -1192,8 +1193,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (P_RandomChance((debtamount*FRACUNIT)/20)) { K_KartGetItemResult(player, KITEM_SUPERRING); - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = 1; + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1209,8 +1210,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) && cv_selfpropelledbomb.value) { K_KartGetItemResult(player, KITEM_SPB); - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = (mashed ? 1 : 0); + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = (mashed ? 1 : 0); player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1246,8 +1247,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (P_IsDisplayPlayer(player)) S_StartSound(NULL, ((player->kartstuff[k_roulettetype] == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf))); - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = ((player->kartstuff[k_roulettetype] == 1) ? 2 : (mashed ? 1 : 0)); + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = ((player->kartstuff[k_roulettetype] == 1) ? 2 : (mashed ? 1 : 0)); player->kartstuff[k_itemroulette] = 0; // Since we're done, clear the roulette number player->kartstuff[k_roulettetype] = 0; // This too @@ -1593,11 +1594,11 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur SKINCOLOR_PLATINUM, SKINCOLOR_TEA, SKINCOLOR_GARDEN, - SKINCOLOR_MUSTARD, - SKINCOLOR_YELLOW, + SKINCOLOR_BANANA, + SKINCOLOR_GOLD, SKINCOLOR_ORANGE, SKINCOLOR_SCARLET, - SKINCOLOR_CHERRY + SKINCOLOR_TAFFY }; fixed_t minimumdist = FixedMul(RING_DIST>>1, player->mo->scale); UINT8 c = FixedMul(CHAOTIXBANDCOLORS<> FRACBITS; @@ -2075,8 +2076,8 @@ static void K_TauntVoiceTimers(player_t *player) if (!player) return; - player->kartstuff[k_tauntvoices] = 6*TICRATE; - player->kartstuff[k_voices] = 4*TICRATE; + player->karthud[khud_tauntvoices] = 6*TICRATE; + player->karthud[khud_voices] = 4*TICRATE; } static void K_RegularVoiceTimers(player_t *player) @@ -2084,16 +2085,16 @@ static void K_RegularVoiceTimers(player_t *player) if (!player) return; - player->kartstuff[k_voices] = 4*TICRATE; + player->karthud[khud_voices] = 4*TICRATE; - if (player->kartstuff[k_tauntvoices] < 4*TICRATE) - player->kartstuff[k_tauntvoices] = 4*TICRATE; + if (player->karthud[khud_tauntvoices] < 4*TICRATE) + player->karthud[khud_tauntvoices] = 4*TICRATE; } void K_PlayAttackTaunt(mobj_t *source) { sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons - boolean tasteful = (!source->player || !source->player->kartstuff[k_tauntvoices]); + boolean tasteful = (!source->player || !source->player->karthud[khud_tauntvoices]); if (cv_kartvoices.value && (tasteful || cv_kartvoices.value == 2)) S_StartSound(source, sfx_kattk1+pick); @@ -2107,7 +2108,7 @@ void K_PlayAttackTaunt(mobj_t *source) void K_PlayBoostTaunt(mobj_t *source) { sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons - boolean tasteful = (!source->player || !source->player->kartstuff[k_tauntvoices]); + boolean tasteful = (!source->player || !source->player->karthud[khud_tauntvoices]); if (cv_kartvoices.value && (tasteful || cv_kartvoices.value == 2)) S_StartSound(source, sfx_kbost1+pick); @@ -2120,7 +2121,7 @@ void K_PlayBoostTaunt(mobj_t *source) void K_PlayOvertakeSound(mobj_t *source) { - boolean tasteful = (!source->player || !source->player->kartstuff[k_voices]); + boolean tasteful = (!source->player || !source->player->karthud[khud_voices]); if (!G_RaceGametype()) // Only in race return; @@ -3875,7 +3876,7 @@ static void K_DoHyudoroSteal(player_t *player) && (players[i].kartstuff[k_itemtype] && players[i].kartstuff[k_itemamount] && !players[i].kartstuff[k_itemheld] - && !players[i].kartstuff[k_itemblink])) + && !players[i].karthud[khud_itemblink])) { playerswappable[numplayers] = i; numplayers++; @@ -3938,7 +3939,7 @@ void K_DoSneaker(player_t *player, INT32 type) S_StartSound(player->mo, sfx_cdfm01); K_SpawnDashDustRelease(player); if (intendedboost > player->kartstuff[k_speedboost]) - player->kartstuff[k_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost)); + player->karthud[khud_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost)); } if (!EITHERSNEAKER(player)) @@ -4743,7 +4744,7 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) // Silence the engines if (leveltime < 8 || player->spectator || player->exiting) { - player->kartstuff[k_enginesnd] = 0; // Reset sound number + player->karthud[khud_enginesnd] = 0; // Reset sound number return; } @@ -4764,15 +4765,15 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) if (targetsnd > 12) targetsnd = 12; - if (player->kartstuff[k_enginesnd] < targetsnd) - player->kartstuff[k_enginesnd]++; - if (player->kartstuff[k_enginesnd] > targetsnd) - player->kartstuff[k_enginesnd]--; + if (player->karthud[khud_enginesnd] < targetsnd) + player->karthud[khud_enginesnd]++; + if (player->karthud[khud_enginesnd] > targetsnd) + player->karthud[khud_enginesnd]--; - if (player->kartstuff[k_enginesnd] < 0) - player->kartstuff[k_enginesnd] = 0; - if (player->kartstuff[k_enginesnd] > 12) - player->kartstuff[k_enginesnd] = 12; + if (player->karthud[khud_enginesnd] < 0) + player->karthud[khud_enginesnd] = 0; + if (player->karthud[khud_enginesnd] > 12) + player->karthud[khud_enginesnd] = 12; for (i = 0; i < MAXPLAYERS; i++) { @@ -4812,7 +4813,7 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) if (volume <= 0) // Might as well return; - S_StartSoundAtVolume(player->mo, (sfx_krta00 + player->kartstuff[k_enginesnd]) + (class*numsnds), volume); + S_StartSoundAtVolume(player->mo, (sfx_krta00 + player->karthud[khud_enginesnd]) + (class*numsnds), volume); } static void K_UpdateInvincibilitySounds(player_t *player) @@ -4850,47 +4851,111 @@ static void K_UpdateInvincibilitySounds(player_t *player) #undef STOPTHIS } +#define RINGANIM_NUMFRAMES 10 +#define RINGANIM_DELAYMAX 5 + void K_KartPlayerHUDUpdate(player_t *player) { - if (player->kartstuff[k_lapanimation]) - player->kartstuff[k_lapanimation]--; + if (player->karthud[khud_lapanimation]) + player->karthud[khud_lapanimation]--; - if (player->kartstuff[k_yougotem]) - player->kartstuff[k_yougotem]--; + if (player->karthud[khud_yougotem]) + player->karthud[khud_yougotem]--; + + if (player->karthud[khud_voices]) + player->karthud[khud_voices]--; + + if (player->karthud[khud_tauntvoices]) + player->karthud[khud_tauntvoices]--; + + if (G_RaceGametype()) + { + // 0 is the fast spin animation, set at 30 tics of ring boost or higher! + if (player->kartstuff[k_ringboost] >= 30) + player->karthud[khud_ringdelay] = 0; + else + player->karthud[khud_ringdelay] = ((RINGANIM_DELAYMAX+1) * (30 - player->kartstuff[k_ringboost])) / 30; + + if (player->karthud[khud_ringframe] == 0 && player->karthud[khud_ringdelay] > RINGANIM_DELAYMAX) + { + player->karthud[khud_ringframe] = 0; + player->karthud[khud_ringtics] = 0; + } + else if ((player->karthud[khud_ringtics]--) <= 0) + { + if (player->karthud[khud_ringdelay] == 0) // fast spin animation + { + player->karthud[khud_ringframe] = ((player->karthud[khud_ringframe]+2) % RINGANIM_NUMFRAMES); + player->karthud[khud_ringtics] = 0; + } + else + { + player->karthud[khud_ringframe] = ((player->karthud[khud_ringframe]+1) % RINGANIM_NUMFRAMES); + player->karthud[khud_ringtics] = min(RINGANIM_DELAYMAX, player->karthud[khud_ringdelay])-1; + } + } + + if (player->kartstuff[k_ringlock]) + { + UINT8 normalanim = (leveltime % 14); + UINT8 debtanim = 14 + (leveltime % 2); + + if (player->karthud[khud_ringspblock] >= 14) // debt animation + { + if ((player->kartstuff[k_rings] > 0) // Get out of 0 ring animation + && (normalanim == 3 || normalanim == 10)) // on these transition frames. + player->karthud[khud_ringspblock] = normalanim; + else + player->karthud[khud_ringspblock] = debtanim; + } + else // normal animation + { + if ((player->kartstuff[k_rings] <= 0) // Go into 0 ring animation + && (player->karthud[khud_ringspblock] == 1 || player->karthud[khud_ringspblock] == 8)) // on these transition frames. + player->karthud[khud_ringspblock] = debtanim; + else + player->karthud[khud_ringspblock] = normalanim; + } + } + else + player->karthud[khud_ringspblock] = (leveltime % 14); // reset to normal anim next time + } if (G_BattleGametype() && (player->exiting || player->kartstuff[k_comebacktimer])) { if (player->exiting) { if (player->exiting < 6*TICRATE) - player->kartstuff[k_cardanimation] += ((164-player->kartstuff[k_cardanimation])/8)+1; + player->karthud[khud_cardanimation] += ((164-player->karthud[khud_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]++; + player->karthud[khud_cardanimation] = 0; + else if (player->karthud[khud_cardanimation] < 2*TICRATE) + player->karthud[khud_cardanimation]++; } else { if (player->kartstuff[k_comebacktimer] < 6*TICRATE) - player->kartstuff[k_cardanimation] -= ((164-player->kartstuff[k_cardanimation])/8)+1; + player->karthud[khud_cardanimation] -= ((164-player->karthud[khud_cardanimation])/8)+1; else if (player->kartstuff[k_comebacktimer] < 9*TICRATE) - player->kartstuff[k_cardanimation] += ((164-player->kartstuff[k_cardanimation])/8)+1; + player->karthud[khud_cardanimation] += ((164-player->karthud[khud_cardanimation])/8)+1; } - if (player->kartstuff[k_cardanimation] > 164) - player->kartstuff[k_cardanimation] = 164; - if (player->kartstuff[k_cardanimation] < 0) - player->kartstuff[k_cardanimation] = 0; + if (player->karthud[khud_cardanimation] > 164) + player->karthud[khud_cardanimation] = 164; + if (player->karthud[khud_cardanimation] < 0) + player->karthud[khud_cardanimation] = 0; } else if (G_RaceGametype() && player->exiting) { - if (player->kartstuff[k_cardanimation] < 2*TICRATE) - player->kartstuff[k_cardanimation]++; + if (player->karthud[khud_cardanimation] < 2*TICRATE) + player->karthud[khud_cardanimation]++; } else - player->kartstuff[k_cardanimation] = 0; + player->karthud[khud_cardanimation] = 0; } +#undef RINGANIM_DELAYMAX + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -5041,25 +5106,25 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } // DKR style camera for boosting - if (player->kartstuff[k_boostcam] != 0 || player->kartstuff[k_destboostcam] != 0) + if (player->karthud[khud_boostcam] != 0 || player->karthud[khud_destboostcam] != 0) { - if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam] - && player->kartstuff[k_destboostcam] != 0) + if (player->karthud[khud_boostcam] < player->karthud[khud_destboostcam] + && player->karthud[khud_destboostcam] != 0) { - player->kartstuff[k_boostcam] += FRACUNIT/(TICRATE/4); - if (player->kartstuff[k_boostcam] >= player->kartstuff[k_destboostcam]) - player->kartstuff[k_destboostcam] = 0; + player->karthud[khud_boostcam] += FRACUNIT/(TICRATE/4); + if (player->karthud[khud_boostcam] >= player->karthud[khud_destboostcam]) + player->karthud[khud_destboostcam] = 0; } else { - player->kartstuff[k_boostcam] -= FRACUNIT/TICRATE; - if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam]) - player->kartstuff[k_boostcam] = player->kartstuff[k_destboostcam] = 0; + player->karthud[khud_boostcam] -= FRACUNIT/TICRATE; + if (player->karthud[khud_boostcam] < player->karthud[khud_destboostcam]) + player->karthud[khud_boostcam] = player->karthud[khud_destboostcam] = 0; } - //CONS_Printf("cam: %d, dest: %d\n", player->kartstuff[k_boostcam], player->kartstuff[k_destboostcam]); + //CONS_Printf("cam: %d, dest: %d\n", player->karthud[khud_boostcam], player->karthud[khud_destboostcam]); } - player->kartstuff[k_timeovercam] = 0; + player->karthud[khud_timeovercam] = 0; // Specific hack because it insists on setting flashing tics during this anyway... if (player->kartstuff[k_spinouttype] == 2) @@ -5191,20 +5256,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_justbumped]--; // This doesn't go in HUD update because it has potential gameplay ramifications - if (player->kartstuff[k_itemblink] && player->kartstuff[k_itemblink]-- <= 0) + if (player->karthud[khud_itemblink] && player->karthud[khud_itemblink]-- <= 0) { - player->kartstuff[k_itemblinkmode] = 0; - player->kartstuff[k_itemblink] = 0; + player->karthud[khud_itemblinkmode] = 0; + player->karthud[khud_itemblink] = 0; } K_KartPlayerHUDUpdate(player); - if (player->kartstuff[k_voices]) - player->kartstuff[k_voices]--; - - if (player->kartstuff[k_tauntvoices]) - player->kartstuff[k_tauntvoices]--; - if (G_BattleGametype() && player->kartstuff[k_bumper] > 0) player->kartstuff[k_wanted]++; @@ -6876,9 +6935,13 @@ static patch_t *kp_facenum[MAXPLAYERS+1]; static patch_t *kp_facehighlight[8]; static patch_t *kp_ringsticker[2]; +static patch_t *kp_ringstickersplit[4]; static patch_t *kp_ring[6]; +static patch_t *kp_smallring[6]; static patch_t *kp_ringdebtminus; +static patch_t *kp_ringdebtminussmall; static patch_t *kp_ringspblock[16]; +static patch_t *kp_ringspblocksmall[16]; static patch_t *kp_speedometersticker; static patch_t *kp_speedometerlabel[4]; @@ -7043,6 +7106,26 @@ void K_LoadKartHUDGraphics(void) kp_ringspblock[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } + kp_ringstickersplit[0] = W_CachePatchName("SMRNGBGA", PU_HUDGFX); + kp_ringstickersplit[1] = W_CachePatchName("SMRNGBGB", PU_HUDGFX); + + sprintf(buffer, "K_SRINGx"); + for (i = 0; i < 6; i++) + { + buffer[7] = '0'+(i+1); + kp_smallring[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + kp_ringdebtminussmall = W_CachePatchName("SRDEBTMN", PU_HUDGFX); + + sprintf(buffer, "SPBRGSxx"); + for (i = 0; i < 16; i++) + { + buffer[6] = '0'+((i+1) / 10); + buffer[7] = '0'+((i+1) % 10); + kp_ringspblocksmall[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + // Speedometer kp_speedometersticker = W_CachePatchName("K_SPDMBG", PU_HUDGFX); @@ -7372,20 +7455,20 @@ static void K_initKartHUD(void) ITEM_Y = -8; LAPS_X = 3; - LAPS_Y = (BASEVIDHEIGHT/2)-13; + LAPS_Y = (BASEVIDHEIGHT/2)-12; POSI_X = 24; - POSI_Y = (BASEVIDHEIGHT/2)- 16; + POSI_Y = (BASEVIDHEIGHT/2)-26; // 2P (top right) ITEM2_X = BASEVIDWIDTH-39; ITEM2_Y = -8; - LAPS2_X = BASEVIDWIDTH-40; - LAPS2_Y = (BASEVIDHEIGHT/2)-13; + LAPS2_X = BASEVIDWIDTH-43; + LAPS2_Y = (BASEVIDHEIGHT/2)-12; POSI2_X = BASEVIDWIDTH -4; - POSI2_Y = (BASEVIDHEIGHT/2)- 16; + POSI2_Y = (BASEVIDHEIGHT/2)-26; // Reminder that 3P and 4P are just 1P and 2P splitscreen'd to the bottom. @@ -7676,11 +7759,11 @@ static void K_drawKartItem(void) localpatch = kp_nodraw; } - if (stplyr->kartstuff[k_itemblink] && (leveltime & 1)) + if (stplyr->karthud[khud_itemblink] && (leveltime & 1)) { colormode = TC_BLINK; - switch (stplyr->kartstuff[k_itemblinkmode]) + switch (stplyr->karthud[khud_itemblinkmode]) { case 2: localcolor = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); @@ -7760,7 +7843,7 @@ static void K_drawKartItem(void) V_DrawFill(fx+x+length, fy+y+1, 1, height, 12|fflags); // the right one if (height == 2) V_DrawFill(fx+x+2, fy+y+2, length-2, 1, 8|fflags); // the dulled underside - V_DrawFill(fx+x+2, fy+y+1, length-2, 1, 120|fflags); // the shine + V_DrawFill(fx+x+2, fy+y+1, length-2, 1, 0|fflags); // the shine } } @@ -8291,93 +8374,21 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } } -static void K_drawKartLaps(void) -{ - INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); - INT32 fx = 0, fy = 0, fflags = 0; // stuff for 3p / 4p splitscreen. - boolean flipstring = false; // used for 3p or 4p - INT32 stringw = 0; // used with the above - - if (splitscreen > 1) - { - - // pain and suffering defined below - if (splitscreen < 2) // don't change shit for THIS splitscreen. - { - fx = LAPS_X; - fy = LAPS_Y; - fflags = splitflags; - } - else - { - if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... - { - fx = LAPS_X; - fy = LAPS_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. - } - else // else, that means we're P2 or P4. - { - fx = LAPS2_X; - fy = LAPS2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom - flipstring = true; // make the string right aligned and other shit - } - } - - - - if (stplyr->exiting) // draw stuff as god intended. - { - V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, kp_splitlapflag); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, "FIN"); - } - else // take flipstring into account here since we may have more laps than just 10 - if (flipstring) - { - stringw = V_StringWidth(va("%d/%d", stplyr->laps+1, cv_numlaps.value), 0); - - V_DrawScaledPatch(BASEVIDWIDTH-stringw-16, fy, V_HUDTRANS|fflags, kp_splitlapflag); - V_DrawRightAlignedString(BASEVIDWIDTH-3, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); - } - else // draw stuff NORMALLY. - { - V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, kp_splitlapflag); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); - } - } - else - { - V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapsticker); - - if (stplyr->exiting) - V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, "FIN"); - else - V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); - } -} - -static void K_drawKartRingsAndLives(void) -{ -#define RINGANIM_NUMFRAMES 10 #define RINGANIM_FLIPFRAME (RINGANIM_NUMFRAMES/2) -#define RINGANIM_DELAYMAX 5 - static UINT8 ringanim_frame = 0; - static UINT8 ringanim_tics = 0; - static UINT8 ringanim_delay = RINGANIM_DELAYMAX+1; - static UINT8 ringlockanim = 0; - - SINT8 ringanim_realframe = ringanim_frame; +static void K_drawKartLapsAndRings(void) +{ + SINT8 ringanim_realframe = stplyr->karthud[khud_ringframe]; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); - UINT8 firstnum = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); - UINT8 secondnum = (abs(stplyr->kartstuff[k_rings]) % 10); + UINT8 rn[2]; INT32 ringflip = 0; UINT8 *ringmap = NULL; boolean colorring = false; - INT32 ringx = LAPS_X+7; + INT32 ringx = 0; + + rn[0] = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); + rn[1] = (abs(stplyr->kartstuff[k_rings]) % 10); - // Rings if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) // In debt { ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); @@ -8386,98 +8397,146 @@ static void K_drawKartRingsAndLives(void) else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); - - if (netgame) - V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); - else - V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); - - if (ringanim_frame > RINGANIM_FLIPFRAME) + if (stplyr->karthud[khud_ringframe] > RINGANIM_FLIPFRAME) { ringflip = V_FLIP; - ringanim_realframe = RINGANIM_NUMFRAMES-ringanim_frame; - ringx += SHORT(kp_ring[ringanim_realframe]->width); + ringanim_realframe = RINGANIM_NUMFRAMES-stplyr->karthud[khud_ringframe]; + ringx += SHORT((splitscreen > 1) ? kp_smallring[ringanim_realframe]->width : kp_ring[ringanim_realframe]->width); } - V_DrawMappedPatch(ringx, LAPS_Y-16, V_HUDTRANS|splitflags|ringflip, kp_ring[ringanim_realframe], (colorring ? ringmap : NULL)); // Don't do maxed out gold mapping + if (splitscreen > 1) + { + INT32 fx = 0, fy = 0, fr = 0; + INT32 flipflag = 0; - if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt - { - V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap); - V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap); - V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); - } - else - { - V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap); - V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); - } - - // 0 is the fast spin animation, set at 30 tics of ring boost or higher! - if (stplyr->kartstuff[k_ringboost] >= 30) - ringanim_delay = 0; - else - ringanim_delay = ((RINGANIM_DELAYMAX+1) * (30 - stplyr->kartstuff[k_ringboost])) / 30; - - if (ringanim_frame == 0 && ringanim_delay > RINGANIM_DELAYMAX) - { - ringanim_frame = 0; - ringanim_tics = 0; - } - else if ((ringanim_tics--) <= 0) - { - if (ringanim_delay == 0) // fast spin animation + // pain and suffering defined below + if (splitscreen < 2) // don't change shit for THIS splitscreen. { - ringanim_frame = ((ringanim_frame+2) % RINGANIM_NUMFRAMES); - ringanim_tics = 0; + fx = LAPS_X; + fy = LAPS_Y; } else { - ringanim_frame = ((ringanim_frame+1) % RINGANIM_NUMFRAMES); - ringanim_tics = min(RINGANIM_DELAYMAX, ringanim_delay)-1; + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + { + fx = LAPS_X; + fy = LAPS_Y; + splitflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + } + else // else, that means we're P2 or P4. + { + fx = LAPS2_X; + fy = LAPS2_Y; + splitflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + flipflag = V_FLIP; // make the string right aligned and other shit + } + } + + fr = fx; + + // Laps + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); + + V_DrawScaledPatch(fx, fy, V_HUDTRANS|splitflags, kp_splitlapflag); + V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|splitflags, frameslash); + + if (cv_numlaps.value >= 10) + { + UINT8 ln[2]; + ln[0] = ((abs(stplyr->laps+1) / 10) % 10); + ln[1] = (abs(stplyr->laps+1) % 10); + + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + + ln[0] = ((abs(cv_numlaps.value) / 10) % 10); + ln[1] = (abs(cv_numlaps.value) % 10); + + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + } + else + { + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->laps+1) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_numlaps.value) % 10]); + } + + // Rings + if (netgame) + { + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy-10, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[1]); + if (flipflag) + fr += 15; + } + else + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[0]->width) - 3) : 0), fy-10, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); + + V_DrawMappedPatch(fr+ringx, fy-13, V_HUDTRANS|splitflags|ringflip, kp_smallring[ringanim_realframe], (colorring ? ringmap : NULL)); + + if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt + V_DrawMappedPatch(fr+7, fy-10, V_HUDTRANS|splitflags, kp_ringdebtminussmall, ringmap); + + V_DrawMappedPatch(fr+11, fy-10, V_HUDTRANS|splitflags, pingnum[rn[0]], ringmap); + V_DrawMappedPatch(fr+15, fy-10, V_HUDTRANS|splitflags, pingnum[rn[1]], ringmap); + + // SPB ring lock + if (stplyr->kartstuff[k_ringlock]) + V_DrawScaledPatch(fr-12, fy-23, V_HUDTRANS|splitflags, kp_ringspblocksmall[stplyr->karthud[khud_ringspblock]]); + + // Lives + if (!netgame) + { + UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); + V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|splitflags, facemmapprefix[stplyr->skin], colormap); + V_DrawScaledPatch(fr+34, fy-10, V_HUDTRANS|splitflags, pingnum[(stplyr->lives % 10)]); // make sure this doesn't overflow } } + else + { + // Laps + V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapsticker); + + if (stplyr->exiting) + V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, "FIN"); + else + V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); + + // Rings + if (netgame) + V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); + else + V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); + + V_DrawMappedPatch(LAPS_X+ringx+7, LAPS_Y-16, V_HUDTRANS|splitflags|ringflip, kp_ring[ringanim_realframe], (colorring ? ringmap : NULL)); + + if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt + { + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[0]], ringmap); + V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[1]], ringmap); + } + else + { + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[0]], ringmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[1]], ringmap); + } + + // SPB ring lock + if (stplyr->kartstuff[k_ringlock]) + V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[stplyr->karthud[khud_ringspblock]]); + + // Lives + if (!netgame) + { + UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); + V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap); + V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow + } + } +} #undef RINGANIM_NUMFRAMES #undef RINGANIM_FLIPFRAME -#undef RINGANIM_DELAYMAX - - // SPB ring lock - if (stplyr->kartstuff[k_ringlock]) - { - UINT8 normalanim = (leveltime % 14); - UINT8 debtanim = 14 + (leveltime % 2); - - if (ringlockanim >= 14) // debt animation - { - if ((stplyr->kartstuff[k_rings] > 0) // Get out of 0 ring animation - && (normalanim == 3 || normalanim == 10)) // on these transition frames. - ringlockanim = normalanim; - else - ringlockanim = debtanim; - } - else // normal animation - { - if ((stplyr->kartstuff[k_rings] <= 0) // Go into 0 ring animation - && (ringlockanim == 1 || ringlockanim == 8)) // on these transition frames. - ringlockanim = debtanim; - else - ringlockanim = normalanim; - } - - V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[ringlockanim]); - } - else - ringlockanim = (leveltime % 14); // reset to normal anim next time - - // Lives - if (!netgame) - { - UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); - V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap); - V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow - } -} static void K_drawKartSpeedometer(void) { @@ -8533,47 +8592,67 @@ static void K_drawKartBumpersOrKarma(void) { UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); - INT32 fx = 0, fy = 0, fflags = 0; - boolean flipstring = false; // same as laps, used for splitscreen - INT32 stringw = 0; // used with the above if (splitscreen > 1) { + INT32 fx = 0, fy = 0; + INT32 flipflag = 0; - // we will reuse lap coords here since it's essentially the same shit. - - if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + // pain and suffering defined below + if (splitscreen < 2) // don't change shit for THIS splitscreen. { fx = LAPS_X; fy = LAPS_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. } - else // else, that means we're P2 or P4. + else { - fx = LAPS2_X; - fy = LAPS2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom - flipstring = true; + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + { + fx = LAPS_X; + fy = LAPS_Y; + splitflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + } + else // else, that means we're P2 or P4. + { + fx = LAPS2_X; + fy = LAPS2_Y; + splitflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + flipflag = V_FLIP; // make the string right aligned and other shit + } } + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); + V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|splitflags, frameslash); + if (stplyr->kartstuff[k_bumper] <= 0) { - V_DrawMappedPatch(fx, fy-1, V_HUDTRANS|fflags, kp_splitkarmabomb, colormap); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/2", stplyr->kartstuff[k_comebackpoints])); + V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap); + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_comebackpoints]) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[2]); } - else // the above doesn't need to account for weird stuff since the max amount of karma necessary is always 2 ^^^^ + else { - if (flipstring) // for p2 and p4, assume we can have more than 10 bumpers. It's retarded but who knows. - { - stringw = V_StringWidth(va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value), 0); + V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap); - V_DrawMappedPatch(BASEVIDWIDTH-stringw-16, fy-1, V_HUDTRANS|fflags, kp_rankbumper, colormap); - V_DrawRightAlignedString(BASEVIDWIDTH-3, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); - } - else // draw bumpers normally. + if (stplyr->kartstuff[k_bumper] > 9 || cv_kartbumpers.value > 9) { - V_DrawMappedPatch(fx, fy-1, V_HUDTRANS|fflags, kp_rankbumper, colormap); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); + UINT8 ln[2]; + ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10); + ln[1] = (abs(stplyr->kartstuff[k_bumper]) % 10); + + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + + ln[0] = ((abs(cv_kartbumpers.value) / 10) % 10); + ln[1] = (abs(cv_kartbumpers.value) % 10); + + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + } + else + { + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_kartbumpers.value) % 10]); } } } @@ -8989,10 +9068,10 @@ static void K_drawKartFinish(void) { INT32 pnum = 0, splitflags = K_calcSplitFlags(0); - if (!stplyr->kartstuff[k_cardanimation] || stplyr->kartstuff[k_cardanimation] >= 2*TICRATE) + if (!stplyr->karthud[khud_cardanimation] || stplyr->karthud[khud_cardanimation] >= 2*TICRATE) return; - if ((stplyr->kartstuff[k_cardanimation] % (2*5)) / 5) // blink + if ((stplyr->karthud[khud_cardanimation] % (2*5)) / 5) // blink pnum = 1; if (splitscreen > 1) // 3/4p, stationary FIN @@ -9011,7 +9090,7 @@ static void K_drawKartFinish(void) x = ((vid.width<width)<kartstuff[k_cardanimation])*(xval > x ? xval : x))/TICRATE; + x = ((TICRATE - stplyr->karthud[khud_cardanimation])*(xval > x ? xval : x))/TICRATE; if (splitscreen && stplyr == &players[displayplayers[1]]) x = -x; @@ -9026,7 +9105,7 @@ static void K_drawKartFinish(void) static void K_drawBattleFullscreen(void) { INT32 x = BASEVIDWIDTH/2; - INT32 y = -64+(stplyr->kartstuff[k_cardanimation]); // card animation goes from 0 to 164, 164 is the middle of the screen + INT32 y = -64+(stplyr->karthud[khud_cardanimation]); // card animation goes from 0 to 164, 164 is the middle of the screen INT32 splitflags = V_SNAPTOTOP; // I don't feel like properly supporting non-green resolutions, so you can have a misuse of SNAPTO instead fixed_t scale = FRACUNIT; @@ -9036,11 +9115,11 @@ static void K_drawBattleFullscreen(void) || (splitscreen > 1 && (stplyr == &players[displayplayers[2]] || (stplyr == &players[displayplayers[3]] && splitscreen > 2)))) { - y = 232-(stplyr->kartstuff[k_cardanimation]/2); + y = 232-(stplyr->karthud[khud_cardanimation]/2); splitflags = V_SNAPTOBOTTOM; } else - y = -32+(stplyr->kartstuff[k_cardanimation]/2); + y = -32+(stplyr->karthud[khud_cardanimation]/2); if (splitscreen > 1) { @@ -9404,21 +9483,21 @@ static void K_drawChallengerScreen(void) static void K_drawLapStartAnim(void) { // This is an EVEN MORE insanely complicated animation. - const UINT8 progress = 80-stplyr->kartstuff[k_lapanimation]; + const UINT8 progress = 80-stplyr->karthud[khud_lapanimation]; UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); - V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->kartstuff[k_lapanimation]-76)))*FRACUNIT, + V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->karthud[khud_lapanimation]-76)))*FRACUNIT, (48 - (32*max(0, progress-76)))*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, (modeattacking ? kp_lapanim_emblem[1] : kp_lapanim_emblem[0]), colormap); - if (stplyr->kartstuff[k_laphand] >= 1 && stplyr->kartstuff[k_laphand] <= 3) + if (stplyr->karthud[khud_laphand] >= 1 && stplyr->karthud[khud_laphand] <= 3) { - V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->kartstuff[k_lapanimation]-76)))*FRACUNIT, + V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->karthud[khud_lapanimation]-76)))*FRACUNIT, (48 - (32*max(0, progress-76)) + 4 - abs((signed)((leveltime % 8) - 4)))*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, - kp_lapanim_hand[stplyr->kartstuff[k_laphand]-1], NULL); + kp_lapanim_hand[stplyr->karthud[khud_laphand]-1], NULL); } if (stplyr->laps == (UINT8)(cv_numlaps.value - 1)) @@ -9726,10 +9805,7 @@ void K_drawKartHUD(void) #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_gametypeinfo)) #endif - { - K_drawKartLaps(); - K_drawKartRingsAndLives(); - } + K_drawKartLapsAndRings(); if (isfreeplay) ; @@ -9782,14 +9858,14 @@ void K_drawKartHUD(void) { if (stplyr->exiting) K_drawKartFinish(); - else if (stplyr->kartstuff[k_lapanimation] && !splitscreen) + else if (stplyr->karthud[khud_lapanimation] && !splitscreen) K_drawLapStartAnim(); } if (modeattacking) // everything after here is MP and debug only return; - if (G_BattleGametype() && !splitscreen && (stplyr->kartstuff[k_yougotem] % 2)) // * YOU GOT EM * + if (G_BattleGametype() && !splitscreen && (stplyr->karthud[khud_yougotem] % 2)) // * YOU GOT EM * V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem); // Draw FREE PLAY. diff --git a/src/lua_baselib.c b/src/lua_baselib.c index be740c3f0..38af4d2e9 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -776,7 +776,8 @@ static int lib_pRestoreMusic(lua_State *L) NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - P_RestoreMusic(player); + if (P_IsLocalPlayer(player)) + P_RestoreMusic(player); return 0; } @@ -1778,7 +1779,7 @@ static int lib_sChangeMusic(lua_State *L) { #ifdef MUSICSLOT_COMPATIBILITY const char *music_name; - UINT32 music_num; + UINT32 music_num, position, prefadems, fadeinms; char music_compat_name[7]; boolean looping; @@ -1806,7 +1807,6 @@ static int lib_sChangeMusic(lua_State *L) music_name = luaL_checkstring(L, 1); } - looping = (boolean)lua_opttrueboolean(L, 2); #else @@ -1831,8 +1831,12 @@ static int lib_sChangeMusic(lua_State *L) #endif music_flags = (UINT16)luaL_optinteger(L, 4, 0); + position = (UINT32)luaL_optinteger(L, 5, 0); + prefadems = (UINT32)luaL_optinteger(L, 6, 0); + fadeinms = (UINT32)luaL_optinteger(L, 7, 0); + if (!player || P_IsLocalPlayer(player)) - S_ChangeMusic(music_name, music_flags, looping); + S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms); return 0; } @@ -1849,10 +1853,8 @@ static int lib_sSpeedMusic(lua_State *L) return LUA_ErrInvalid(L, "player_t"); } if (!player || P_IsLocalPlayer(player)) - lua_pushboolean(L, S_SpeedMusic(speed)); - else - lua_pushboolean(L, false); - return 1; + S_SpeedMusic(speed); + return 0; } static int lib_sStopMusic(lua_State *L) @@ -1870,6 +1872,110 @@ static int lib_sStopMusic(lua_State *L) return 0; } +static int lib_sSetInternalMusicVolume(lua_State *L) +{ + UINT32 volume = (UINT32)luaL_checkinteger(L, 1); + player_t *player = NULL; + NOHUD + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + { + player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + { + S_SetInternalMusicVolume(volume); + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; +} + +static int lib_sStopFadingMusic(lua_State *L) +{ + player_t *player = NULL; + NOHUD + if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + { + player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + { + S_StopFadingMusic(); + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; +} + +static int lib_sFadeMusic(lua_State *L) +{ + UINT32 target_volume = (UINT32)luaL_checkinteger(L, 1); + UINT32 ms; + INT32 source_volume; + player_t *player = NULL; + NOHUD + if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) + { + player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + ms = (UINT32)luaL_checkinteger(L, 2); + source_volume = -1; + } + else if (!lua_isnone(L, 4) && lua_isuserdata(L, 4)) + { + player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + source_volume = (INT32)luaL_checkinteger(L, 2); + ms = (UINT32)luaL_checkinteger(L, 3); + } + else if (luaL_optinteger(L, 3, INT32_MAX) == INT32_MAX) + { + ms = (UINT32)luaL_checkinteger(L, 2); + source_volume = -1; + } + else + { + source_volume = (INT32)luaL_checkinteger(L, 2); + ms = (UINT32)luaL_checkinteger(L, 3); + } + + NOHUD + + if (!player || P_IsLocalPlayer(player)) + lua_pushboolean(L, S_FadeMusicFromVolume(target_volume, source_volume, ms)); + else + lua_pushnil(L); + return 1; +} + +static int lib_sFadeOutStopMusic(lua_State *L) +{ + UINT32 ms = (UINT32)luaL_checkinteger(L, 1); + player_t *player = NULL; + NOHUD + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) + { + player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + { + lua_pushboolean(L, S_FadeOutStopMusic(ms)); + } + else + lua_pushnil(L); + return 1; +} + static int lib_sOriginPlaying(lua_State *L) { void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2673,6 +2779,10 @@ static luaL_Reg lib[] = { {"S_ChangeMusic",lib_sChangeMusic}, {"S_SpeedMusic",lib_sSpeedMusic}, {"S_StopMusic",lib_sStopMusic}, + {"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume}, + {"S_StopFadingMusic",lib_sStopFadingMusic}, + {"S_FadeMusic",lib_sFadeMusic}, + {"S_FadeOutStopMusic",lib_sFadeOutStopMusic}, {"S_OriginPlaying",lib_sOriginPlaying}, {"S_IdPlaying",lib_sIdPlaying}, {"S_SoundPlaying",lib_sSoundPlaying}, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 31beecf09..c6f2f782b 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -443,26 +443,26 @@ static int libd_drawFill(lua_State *L) 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); + UINT16 color = luaL_checkinteger(L, 1); + UINT8 strength = luaL_checkinteger(L, 2); + const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10); - HUDONLY + HUDONLY - if (!strength) - return 0; + 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) + 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; - } + 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; + V_DrawFadeScreen(color, strength); + return 0; } static int libd_drawString(lua_State *L) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0bb9a99d6..19292b3d6 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1477,6 +1477,12 @@ static int mapheaderinfo_get(lua_State *L) lua_pushstring(L, header->musname); else if (fastcmp(field,"mustrack")) lua_pushinteger(L, header->mustrack); + else if (fastcmp(field,"muspos")) + lua_pushinteger(L, header->muspos); + else if (fastcmp(field,"musinterfadeout")) + lua_pushinteger(L, header->musinterfadeout); + else if (fastcmp(field,"musintername")) + lua_pushstring(L, header->musintername); else if (fastcmp(field,"forcecharacter")) lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) diff --git a/src/m_menu.c b/src/m_menu.c index 945318b5e..b367fc9a4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -121,41 +121,8 @@ typedef enum const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 -description_t description[32] = -{ - {"\x82Sonic\x80\n\x82Speed:\x80 7\n\x82Weight:\x80 3", "", "sonic"}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""}, - {"???", "", ""} -}; +description_t description[MAXSKINS]; + //static char *char_notes = NULL; //static fixed_t char_scroll = 0; @@ -435,27 +402,9 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; // This gametype list is integral for many different reasons. -// When you add gametypes here, don't forget to update them in CV_AddValue! -CV_PossibleValue_t gametype_cons_t[] = -{ - {GT_RACE, "Race"}, {GT_MATCH, "Battle"}, +// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! +CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; - /* // SRB2kart - {GT_COOP, "Co-op"}, - - {GT_COMPETITION, "Competition"}, - {GT_RACE, "Race"}, - - {GT_MATCH, "Match"}, - {GT_TEAMMATCH, "Team Match"}, - - {GT_TAG, "Tag"}, - {GT_HIDEANDSEEK, "Hide and Seek"}, - - {GT_CTF, "CTF"}, - */ - {0, NULL} -}; consvar_t cv_newgametype = {"newgametype", "Race", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t serversort_cons_t[] = { @@ -3397,6 +3346,55 @@ void M_Init(void) CV_RegisterVar(&cv_allcaps); } +void M_InitCharacterTables(void) +{ + UINT8 i; + + // Setup PlayerMenu table + for (i = 0; i < MAXSKINS; i++) + { + PlayerMenu[i].status = (i < 4 ? IT_CALL : IT_DISABLED); + PlayerMenu[i].patch = PlayerMenu[i].text = NULL; + PlayerMenu[i].itemaction = M_ChoosePlayer; + PlayerMenu[i].alphaKey = 0; + } + + // Setup description table + for (i = 0; i < MAXSKINS; i++) + { + if (i == 0) + { + strcpy(description[i].notes, "\x82Sonic\x80 is the fastest of the three, but also the hardest to control. Beginners beware, but experts will find Sonic very powerful.\n\n\x82""Ability:\x80 Speed Thok\nDouble jump to zoom forward with a huge burst of speed.\n\n\x82Tip:\x80 Simply letting go of forward does not slow down in SRB2. To slow down, hold the opposite direction."); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, "sonic"); + } + else if (i == 1) + { + strcpy(description[i].notes, "\x82Tails\x80 is the most mobile of the three, but has the slowest speed. Because of his mobility, he's well-\nsuited to beginners.\n\n\x82""Ability:\x80 Fly\nDouble jump to start flying for a limited time. Repetitively hit the jump button to ascend.\n\n\x82Tip:\x80 To quickly descend while flying, hit the spin button."); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, "tails"); + } + else if (i == 2) + { + strcpy(description[i].notes, "\x82Knuckles\x80 is well-\nrounded and can destroy breakable walls simply by touching them, but he can't jump as high as the other two.\n\n\x82""Ability:\x80 Glide & Climb\nDouble jump to glide in the air as long as jump is held. Glide into a wall to climb it.\n\n\x82Tip:\x80 Press spin while climbing to jump off the wall; press jump instead to jump off\nand face away from\nthe wall."); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, "knuckles"); + } + else if (i == 3) + { + strcpy(description[i].notes, "\x82Sonic & Tails\x80 team up to take on Dr. Eggman!\nControl Sonic while Tails desperately struggles to keep up.\n\nPlayer 2 can control Tails directly by setting the controls in the options menu.\nTails's directional controls are relative to Player 1's camera.\n\nTails can pick up Sonic while flying and carry him around."); + strcpy(description[i].picname, "CHRS&T"); + strcpy(description[i].skinname, "sonic&tails"); + } + else + { + strcpy(description[i].notes, "???"); + strcpy(description[i].picname, ""); + strcpy(description[i].skinname, ""); + } + } +} + // ========================================================================== // SPECIAL MENU OPTION DRAW ROUTINES GO HERE // ========================================================================== @@ -3515,7 +3513,7 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) { // Solid color textbox. - V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 239); + V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 159); //V_DrawFill(x+8, y+8, width*8, boxlines*8, 31); /* patch_t *p; @@ -4674,10 +4672,10 @@ static void M_DrawTemperature(INT32 x, fixed_t t) t = (FixedMul(h<>FRACBITS); // border - V_DrawFill(x - 1, vpadding, 1, h, 120); - V_DrawFill(x + width, vpadding, 1, h, 120); - V_DrawFill(x - 1, vpadding-1, width+2, 1, 120); - V_DrawFill(x - 1, vpadding+h, width+2, 1, 120); + V_DrawFill(x - 1, vpadding, 1, h, 0); + V_DrawFill(x + width, vpadding, 1, h, 0); + V_DrawFill(x - 1, vpadding-1, width+2, 1, 0); + V_DrawFill(x - 1, vpadding+h, width+2, 1, 0); // bar itself y = h; @@ -4828,14 +4826,14 @@ static void M_DrawAddons(void) x = currentMenu->x; y = currentMenu->y + 1; - hilicol = V_GetStringColormap(highlightflags)[120]; + hilicol = V_GetStringColormap(highlightflags)[0]; V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), highlightflags|V_ALLOWLOWERCASE, M_AddonsHeaderPath()); V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), MAXSTRINGLENGTH*8+6, 1, hilicol); V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 30); m = (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1); - V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 239); + V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 159); // scrollbar! if (sizedirmenu <= (2*numaddonsshown + 1)) @@ -5561,8 +5559,8 @@ static void M_DrawReplayHut(void) y = sizedirmenu*10 + currentMenu->menuitems[replaylistitem].alphaKey + 30; if (y > SCALEDVIEWHEIGHT-80) { - V_DrawFill(BASEVIDWIDTH-4, 75, 4, SCALEDVIEWHEIGHT-80, V_SNAPTOTOP|V_SNAPTORIGHT|239); - V_DrawFill(BASEVIDWIDTH-3, 76 + (SCALEDVIEWHEIGHT-80) * replayhutmenuy / y, 2, (((SCALEDVIEWHEIGHT-80) * (SCALEDVIEWHEIGHT-80))-1) / y - 1, V_SNAPTOTOP|V_SNAPTORIGHT|229); + V_DrawFill(BASEVIDWIDTH-4, 75, 4, SCALEDVIEWHEIGHT-80, V_SNAPTOTOP|V_SNAPTORIGHT|159); + V_DrawFill(BASEVIDWIDTH-3, 76 + (SCALEDVIEWHEIGHT-80) * replayhutmenuy / y, 2, (((SCALEDVIEWHEIGHT-80) * (SCALEDVIEWHEIGHT-80))-1) / y - 1, V_SNAPTOTOP|V_SNAPTORIGHT|149); } // Draw the cursor @@ -5571,7 +5569,7 @@ static void M_DrawReplayHut(void) V_DrawString(currentMenu->x, cursory, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[itemOn].text); // Now draw some replay info! - V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|239); + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); if (itemOn == replaylistitem) { @@ -5653,7 +5651,7 @@ static void M_DrawReplayStartMenu(void) } } - V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|239); + V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); DrawReplayHutReplayInfo(); V_DrawString(10, 72, V_SNAPTOTOP|highlightflags|V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].title); @@ -7582,7 +7580,7 @@ void M_DrawTimeAttackMenu(void) time = mainrecords[cv_nextmap.value-1]->time; } - V_DrawFill((BASEVIDWIDTH - dupadjust)>>1, 78, dupadjust, 36, 239); + V_DrawFill((BASEVIDWIDTH - dupadjust)>>1, 78, dupadjust, 36, 159); V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:"); K_drawKartTimestamp(lap, 19, 86, 0, 2); @@ -8256,7 +8254,7 @@ static void M_DrawRoomMenu(void) static void M_DrawConnectMenu(void) { - UINT16 i, j; + UINT16 i; const char *gt = "Unknown"; const char *spd = ""; INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; @@ -8303,11 +8301,8 @@ static void M_DrawConnectMenu(void) va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time))); gt = "Unknown"; - for (j = 0; gametype_cons_t[j].strvalue; j++) - { - if (gametype_cons_t[j].value == serverlist[slindex].info.gametype) - gt = gametype_cons_t[j].strvalue; - } + if (serverlist[slindex].info.gametype < NUMGAMETYPES) + gt = Gametype_Names[serverlist[slindex].info.gametype]; V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer)); @@ -8632,7 +8627,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) y = currentMenu->y + 130 + 8 - i; if (currentMenu->menuitems[itemOn].itemaction == &cv_nextmap && skullAnimCounter < 4) - trans = 120; + trans = 0; else trans = G_GetGametypeColor(cv_newgametype.value); @@ -8824,7 +8819,7 @@ Update the maxplayers label... #ifndef NONET y += MP_MainMenu[8].alphaKey; - V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 239); + V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); // draw name string V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip); @@ -9298,7 +9293,7 @@ static void M_DrawSetupMultiPlayerMenu(void) flags |= V_FLIP; // This sprite is left/right flipped! // draw box around guy - V_DrawFill(mx + 43 - (charw/2), my+65, charw, 84, 239); + V_DrawFill(mx + 43 - (charw/2), my+65, charw, 84, 159); // draw player sprite if (setupm_fakecolor) // inverse should never happen @@ -9324,6 +9319,9 @@ static void M_HandleSetupMultiPlayer(INT32 choice) size_t l; boolean exitmenu = false; // exit to previous menu and send name change + if ((choice == gamecontrol[gc_fire][0] || choice == gamecontrol[gc_fire][1]) && itemOn == 2) + choice = KEY_BACKSPACE; // Hack to allow resetting prefcolor on controllers + switch (choice) { case KEY_DOWNARROW: diff --git a/src/m_menu.h b/src/m_menu.h index ef0381d11..62c852e4d 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -38,6 +38,9 @@ void M_Drawer(void); // Called by D_SRB2Main, loads the config file. void M_Init(void); +// Called by D_SRB2Main also, sets up the playermenu and description tables. +void M_InitCharacterTables(void); + // Called by intro code to force menu up upon a keypress, // does nothing if menu is already up. void M_StartControlPanel(void); @@ -210,7 +213,7 @@ typedef struct UINT8 netgame; } saveinfo_t; -extern description_t description[32]; +extern description_t description[MAXSKINS]; extern consvar_t cv_showfocuslost; extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort; diff --git a/src/p_inter.c b/src/p_inter.c index 9e6d64030..de14b3db9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -494,7 +494,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->kartstuff[k_comebackpoints] += ptadd; if (ptadd > 1) - special->target->player->kartstuff[k_yougotem] = 2*TICRATE; + special->target->player->karthud[khud_yougotem] = 2*TICRATE; if (special->target->player->kartstuff[k_comebackpoints] >= 2) K_StealBumper(special->target->player, player, true); @@ -557,7 +557,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->kartstuff[k_comebackpoints] += ptadd; if (ptadd > 1) - special->target->player->kartstuff[k_yougotem] = 2*TICRATE; + special->target->player->karthud[khud_yougotem] = 2*TICRATE; if (special->target->player->kartstuff[k_comebackpoints] >= 2) K_StealBumper(special->target->player, player, true); @@ -1856,6 +1856,9 @@ void P_CheckTimeLimit(void) } } + if (playercount > MAXPLAYERS) + playercount = MAXPLAYERS; + //Sort 'em. for (i = 1; i < playercount; i++) { diff --git a/src/p_mobj.c b/src/p_mobj.c index e5f8bc65f..a3a73b7ff 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3624,7 +3624,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.z = thiscam->z; dummy.height = thiscam->height; if (player->pflags & PF_TIMEOVER) - player->kartstuff[k_timeovercam] = (2*TICRATE)+1; + player->karthud[khud_timeovercam] = (2*TICRATE)+1; if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. P_ResetCamera(player, thiscam); else @@ -10001,7 +10001,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; } - mobj->color = SKINCOLOR_AQUA; + mobj->color = SKINCOLOR_CYAN; break; } case MT_MARBLETORCH: @@ -11640,20 +11640,16 @@ void P_SpawnMapThing(mapthing_t *mthing) mobjtype_t macetype = MT_SMALLMACE; boolean firsttime; mobj_t *spawnee; - size_t line; + INT32 line; const size_t mthingi = (size_t)(mthing - mapthings); - // Why does P_FindSpecialLineFromTag not work here?!? - // Monster Iestyn: tag lists haven't been initialised yet for the map, that's why - for (line = 0; line < numlines; line++) - { - if (lines[line].special == 9 && lines[line].tag == mthing->angle) - break; - } + // Find the corresponding linedef special, using angle as tag + // P_FindSpecialLineFromTag works here now =D + line = P_FindSpecialLineFromTag(9, mthing->angle, -1); - if (line == numlines) + if (line == -1) { - CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); return; } /* diff --git a/src/p_setup.c b/src/p_setup.c index c85e95307..d1ef91705 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -197,6 +197,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->musname[6] = 0; DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE); mapheaderinfo[num]->mustrack = 0; + DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->muspos), UNDO_NONE); + mapheaderinfo[num]->muspos = 0; + DEH_WriteUndoline("MUSICINTERFADEOUT", va("%d", mapheaderinfo[num]->musinterfadeout), UNDO_NONE); + mapheaderinfo[num]->musinterfadeout = 0; + DEH_WriteUndoline("MUSICINTER", mapheaderinfo[num]->musintername, UNDO_NONE); + mapheaderinfo[num]->musintername[0] = '\0'; DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE); mapheaderinfo[num]->forcecharacter[0] = '\0'; DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE); @@ -1548,19 +1554,33 @@ static void P_LoadRawSideDefs2(void *data) { M_Memcpy(process,msd->bottomtexture,8); process[8] = '\0'; - sd->bottomtexture = get_number(process)-1; + sd->bottomtexture = get_number(process); } - M_Memcpy(process,msd->toptexture,8); - process[8] = '\0'; - sd->text = Z_Malloc(7, PU_LEVEL, NULL); - // If they type in O_ or D_ and their music name, just shrug, - // then copy the rest instead. - if ((process[0] == 'O' || process[0] == 'D') && process[7]) - M_Memcpy(sd->text, process+2, 6); - else // Assume it's a proper music name. - M_Memcpy(sd->text, process, 6); - sd->text[6] = 0; + if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0') + { + M_Memcpy(process,msd->midtexture,8); + process[8] = '\0'; + sd->midtexture = get_number(process); + } + + // always process if back sidedef, because we need that - symbol + sd->text = Z_Malloc(7, PU_LEVEL, NULL); + if (i == 1 || msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') + { + M_Memcpy(process,msd->toptexture,8); + process[8] = '\0'; + + // If they type in O_ or D_ and their music name, just shrug, + // then copy the rest instead. + if ((process[0] == 'O' || process[0] == 'D') && process[7]) + M_Memcpy(sd->text, process+2, 6); + else // Assume it's a proper music name. + M_Memcpy(sd->text, process, 6); + sd->text[6] = 0; + } + else + sd->text[0] = 0; break; } @@ -2796,8 +2816,7 @@ boolean P_SetupLevel(boolean skipprecip) for (i = 0; i <= splitscreen; i++) postimgtype[i] = postimg_none; - if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0' - && atoi(mapheaderinfo[gamemap-1]->forcecharacter) != 255) + if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0') P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter); // chasecam on in chaos, race, coop @@ -2839,13 +2858,13 @@ boolean P_SetupLevel(boolean skipprecip) S_StartSound(NULL, sfx_ruby1); F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 122); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 209); F_WipeEndScreen(); F_RunWipe(wipedefs[wipe_speclevel_towhite], false); F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); F_WipeEndScreen(); F_RunWipe(wipedefs[wipe_level_final], false); @@ -2878,7 +2897,7 @@ boolean P_SetupLevel(boolean skipprecip) // We should be fine starting it here. S_Start(); - levelfadecol = (encoremode && !ranspecialwipe ? 122 : 120); + levelfadecol = (encoremode && !ranspecialwipe ? 209 : 0); // Let's fade to white here // But only if we didn't do the encore startup wipe @@ -3046,6 +3065,10 @@ boolean P_SetupLevel(boolean skipprecip) P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); } + // init gravity, tag lists, + // anything that P_ResetDynamicSlopes/P_LoadThings needs to know + P_InitSpecials(); + #ifdef ESLOPE P_ResetDynamicSlopes(); #endif @@ -3064,8 +3087,6 @@ boolean P_SetupLevel(boolean skipprecip) if (loadprecip) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame) P_SpawnPrecipitation(); - globalweather = mapheaderinfo[gamemap-1]->weather; - #ifdef HWRENDER // not win32 only 19990829 by Kin if (rendermode != render_soft && rendermode != render_none) { diff --git a/src/p_slopes.c b/src/p_slopes.c index b672be56e..b6c649888 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -264,7 +264,7 @@ void P_SpawnSlope_Line(int linenum) if(!line->frontsector || !line->backsector) { - CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n"); + CONS_Debug(DBG_SETUP, "P_SpawnSlope_Line used on a line without two sides. (line number %i)\n", linenum); return; } diff --git a/src/p_spec.c b/src/p_spec.c index a0f967e4f..e0c1a7465 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2426,18 +2426,71 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // console player only unless NOCLIMB is set if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player))) { - UINT16 tracknum = (UINT16)sides[line->sidenum[0]].bottomtexture; + boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7)); + UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0); + INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0); + UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0); + UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0); + UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0); + INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1); - strncpy(mapmusname, sides[line->sidenum[0]].text, 7); - mapmusname[6] = 0; + // Seek offset from current song position + if (line->flags & ML_EFFECT1) + { + // adjust for loop point if subtracting + if (position < 0 && S_GetMusicLength() && + S_GetMusicPosition() > S_GetMusicLoopPoint() && + S_GetMusicPosition() + position < S_GetMusicLoopPoint()) + position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0); + else + position = max(S_GetMusicPosition() + position, 0); + } - mapmusflags = tracknum & MUSIC_TRACKMASK; - if (!(line->flags & ML_BLOCKMONSTERS)) - mapmusflags |= MUSIC_RELOADRESET; + // Fade current music to target volume (if music won't be changed) + if ((line->flags & ML_EFFECT2) && fadetarget && musicsame) + { + // 0 fadesource means fade from current volume. + // meaning that we can't specify volume 0 as the source volume -- this starts at 1. + if (!fadesource) + fadesource = -1; - S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4)); - if (!(line->flags & ML_EFFECT3)) - S_ShowMusicCredit(); + if (!postfadems) + S_SetInternalMusicVolume(fadetarget); + else + S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); + + if (!(line->flags & ML_EFFECT3)) + S_ShowMusicCredit(); + + if (position) + S_SetMusicPosition(position); + } + // Change the music and apply position/fade operations + else + { + strncpy(mapmusname, sides[line->sidenum[0]].text, 7); + mapmusname[6] = 0; + + mapmusflags = tracknum & MUSIC_TRACKMASK; + if (!(line->flags & ML_BLOCKMONSTERS)) + mapmusflags |= MUSIC_RELOADRESET; + if (line->flags & ML_BOUNCY) + mapmusflags |= MUSIC_FORCERESET; + + mapmusposition = position; + + S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position, + !(line->flags & ML_EFFECT2) ? prefadems : 0, + !(line->flags & ML_EFFECT2) ? postfadems : 0); + + if ((line->flags & ML_EFFECT2) && fadetarget) + { + if (!postfadems) + S_SetInternalMusicVolume(fadetarget); + else + S_FadeMusicFromVolume(fadetarget, fadesource, postfadems); + } + } // Except, you can use the ML_BLOCKMONSTERS flag to change this behavior. // if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn. @@ -4194,19 +4247,19 @@ DoneSection2: if (nump > 1) { if (K_IsPlayerLosing(player)) - player->kartstuff[k_laphand] = 3; + player->karthud[khud_laphand] = 3; else { if (nump > 2 && player->kartstuff[k_position] == 1) // 1st place in 1v1 uses thumbs up - player->kartstuff[k_laphand] = 1; + player->karthud[khud_laphand] = 1; else - player->kartstuff[k_laphand] = 2; + player->karthud[khud_laphand] = 2; } } else - player->kartstuff[k_laphand] = 0; // No hands in FREE PLAY + player->karthud[khud_laphand] = 0; // No hands in FREE PLAY - player->kartstuff[k_lapanimation] = 80; + player->karthud[khud_lapanimation] = 80; if (player->pflags & PF_NIGHTSMODE) player->drillmeter += 48*20; @@ -5606,6 +5659,45 @@ static void P_RunLevelLoadExecutors(void) } } +/** Before things are loaded, initialises certain stuff in case they're needed + * by P_ResetDynamicSlopes or P_LoadThings. This was split off from + * P_SpawnSpecials, in case you couldn't tell. + * + * \sa P_SpawnSpecials, P_InitTagLists + * \author Monster Iestyn + */ +void P_InitSpecials(void) +{ + // Set the default gravity. Custom gravity overrides this setting. + gravity = (FRACUNIT*8)/10; + + // Defaults in case levels don't have them set. + sstimer = 90*TICRATE + 6; + totalrings = 1; + + CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; + + // Set curWeather + switch (mapheaderinfo[gamemap-1]->weather) + { + case PRECIP_SNOW: // snow + case PRECIP_RAIN: // rain + case PRECIP_STORM: // storm + case PRECIP_STORM_NORAIN: // storm w/o rain + case PRECIP_STORM_NOSTRIKES: // storm w/o lightning + curWeather = mapheaderinfo[gamemap-1]->weather; + break; + default: // blank/none + curWeather = PRECIP_NONE; + break; + } + + // Set globalweather + globalweather = mapheaderinfo[gamemap-1]->weather; + + P_InitTagLists(); // Create xref tables for tags +} + /** After the map has loaded, scans for specials that spawn 3Dfloors and * thinkers. * @@ -5627,15 +5719,6 @@ void P_SpawnSpecials(INT32 fromnetsave) // but currently isn't. (void)fromnetsave; - // Set the default gravity. Custom gravity overrides this setting. - gravity = (FRACUNIT*8)/10; - - // Defaults in case levels don't have them set. - sstimer = 90*TICRATE + 6; - totalrings = 1; - - CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; - // Init special SECTORs. sector = sectors; for (i = 0; i < numsectors; i++, sector++) @@ -5684,20 +5767,6 @@ void P_SpawnSpecials(INT32 fromnetsave) } } - if (mapheaderinfo[gamemap-1]->weather == 2) // snow - curWeather = PRECIP_SNOW; - else if (mapheaderinfo[gamemap-1]->weather == 3) // rain - curWeather = PRECIP_RAIN; - else if (mapheaderinfo[gamemap-1]->weather == 1) // storm - curWeather = PRECIP_STORM; - else if (mapheaderinfo[gamemap-1]->weather == 5) // storm w/o rain - curWeather = PRECIP_STORM_NORAIN; - else if (mapheaderinfo[gamemap-1]->weather == 6) // storm w/o lightning - curWeather = PRECIP_STORM_NOSTRIKES; - else - curWeather = PRECIP_NONE; - - P_InitTagLists(); // Create xref tables for tags P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line P_SpawnScrollers(); // Add generalized scrollers diff --git a/src/p_spec.h b/src/p_spec.h index 1231aeda8..b604ac951 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -32,6 +32,7 @@ void P_InitPicAnims(void); void P_SetupLevelFlatAnims(void); // at map load +void P_InitSpecials(void); void P_SpawnSpecials(INT32 fromnetsave); // every tic diff --git a/src/p_user.c b/src/p_user.c index f87a79649..0db76f85a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1256,7 +1256,7 @@ void P_RestoreMusic(player_t *player) if (G_RaceGametype() && player->laps >= (UINT8)(cv_numlaps.value - 1)) S_SpeedMusic(1.2f); #endif - S_ChangeMusic(mapmusname, mapmusflags, true); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } } } @@ -1721,7 +1721,7 @@ 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 + player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation if (player == &players[consoleplayer]) demo.savebutton = leveltime; @@ -7043,7 +7043,7 @@ static void P_DeathThink(player_t *player) if (player->pflags & PF_TIMEOVER) { - player->kartstuff[k_timeovercam]++; + player->karthud[khud_timeovercam]++; if (player->mo) { player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); @@ -7051,7 +7051,7 @@ static void P_DeathThink(player_t *player) } } else - player->kartstuff[k_timeovercam] = 0; + player->karthud[khud_timeovercam] = 0; K_KartPlayerHUDUpdate(player); @@ -7259,7 +7259,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall #endif if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround - timeover = (player->kartstuff[k_timeovercam] > 2*TICRATE ? 2 : 1); + timeover = (player->karthud[khud_timeovercam] > 2*TICRATE ? 2 : 1); else timeover = 0; @@ -7402,7 +7402,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (timeover) { - const INT32 timeovercam = max(0, min(180, (player->kartstuff[k_timeovercam] - 2*TICRATE)*15)); + const INT32 timeovercam = max(0, min(180, (player->karthud[khud_timeovercam] - 2*TICRATE)*15)); camrotate += timeovercam; } else if (leveltime < introtime) // Whoooshy camera! @@ -7476,10 +7476,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall dist += 4*(player->speed - K_GetKartSpeed(player, false)); dist += abs(thiscam->momz)/4; - if (player->kartstuff[k_boostcam]) + if (player->karthud[khud_boostcam]) { - dist -= FixedMul(11*dist/16, player->kartstuff[k_boostcam]); - height -= FixedMul(height, player->kartstuff[k_boostcam]); + dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]); + height -= FixedMul(height, player->karthud[khud_boostcam]); } x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); @@ -8063,8 +8063,11 @@ void P_PlayerThink(player_t *player) if (player->bot) { - if (player->playerstate == PST_LIVE && B_CheckRespawn(player)) - player->playerstate = PST_REBORN; + if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD) + { + if (B_CheckRespawn(player)) + player->playerstate = PST_REBORN; + } if (player->playerstate == PST_REBORN) return; } diff --git a/src/r_draw.c b/src/r_draw.c index 02a912155..1931ce6ee 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -139,75 +139,12 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; #define BLINK_TT_CACHE_INDEX (MAXSKINS + 5) #define TT_CACHE_SIZE (MAXSKINS + 6) #define SKIN_RAMP_LENGTH 16 -#define DEFAULT_STARTTRANSCOLOR 160 +#define DEFAULT_STARTTRANSCOLOR 96 #define NUM_PALETTE_ENTRIES 256 static UINT8** translationtablecache[TT_CACHE_SIZE] = {NULL}; - -// See also the enum skincolors_t -// TODO Callum: Can this be translated? -/* -const char *Color_Names[MAXSKINCOLORS] = -{ - "None", // SKINCOLOR_NONE - "White", // SKINCOLOR_WHITE - "Silver", // SKINCOLOR_SILVER - "Grey", // SKINCOLOR_GREY - "Black", // SKINCOLOR_BLACK - "Cyan", // SKINCOLOR_CYAN - "Teal", // SKINCOLOR_TEAL - "Steel_Blue",// SKINCOLOR_STEEL - "Blue", // SKINCOLOR_BLUE - "Peach", // SKINCOLOR_PEACH - "Tan", // SKINCOLOR_TAN - "Pink", // SKINCOLOR_PINK - "Lavender", // SKINCOLOR_LAVENDER - "Purple", // SKINCOLOR_PURPLE - "Orange", // SKINCOLOR_ORANGE - "Rosewood", // SKINCOLOR_ROSEWOOD - "Beige", // SKINCOLOR_BEIGE - "Brown", // SKINCOLOR_BROWN - "Red", // SKINCOLOR_RED - "Dark_Red", // SKINCOLOR_DARKRED - "Neon_Green",// SKINCOLOR_NEONGREEN - "Green", // SKINCOLOR_GREEN - "Zim", // SKINCOLOR_ZIM - "Olive", // SKINCOLOR_OLIVE - "Yellow", // SKINCOLOR_YELLOW - "Gold" // SKINCOLOR_GOLD -}; - -const UINT8 Color_Opposite[MAXSKINCOLORS*2] = -{ - SKINCOLOR_NONE,8, // SKINCOLOR_NONE - SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE - SKINCOLOR_GREY,4, // SKINCOLOR_SILVER - SKINCOLOR_SILVER,12,// SKINCOLOR_GREY - SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK - SKINCOLOR_NONE,8, // SKINCOLOR_CYAN - SKINCOLOR_NONE,8, // SKINCOLOR_TEAL - SKINCOLOR_NONE,8, // SKINCOLOR_STEEL - SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE - SKINCOLOR_NONE,8, // SKINCOLOR_PEACH - SKINCOLOR_NONE,8, // SKINCOLOR_TAN - SKINCOLOR_NONE,8, // SKINCOLOR_PINK - SKINCOLOR_NONE,8, // SKINCOLOR_LAVENDER - SKINCOLOR_NONE,8, // SKINCOLOR_PURPLE - SKINCOLOR_BLUE,12, // SKINCOLOR_ORANGE - SKINCOLOR_NONE,8, // SKINCOLOR_ROSEWOOD - SKINCOLOR_NONE,8, // SKINCOLOR_BEIGE - SKINCOLOR_NONE,8, // SKINCOLOR_BROWN - SKINCOLOR_GREEN,5, // SKINCOLOR_RED - SKINCOLOR_NONE,8, // SKINCOLOR_DARKRED - SKINCOLOR_NONE,8, // SKINCOLOR_NEONGREEN - SKINCOLOR_RED,11, // SKINCOLOR_GREEN - SKINCOLOR_PURPLE,3, // SKINCOLOR_ZIM - SKINCOLOR_NONE,8, // SKINCOLOR_OLIVE - SKINCOLOR_NONE,8, // SKINCOLOR_YELLOW - SKINCOLOR_NONE,8 // SKINCOLOR_GOLD -}; -*/ +// SKINCOLOR DEFINITIONS HAVE BEEN MOVED TO K_KART.C CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; @@ -239,280 +176,6 @@ void R_InitTranslationTables(void) #endif } - -/** \brief Generates a translation colormap. - - \param dest_colormap colormap to populate - \param skinnum number of skin, TC_DEFAULT or TC_BOSS - \param color translation color - - \return void -*/ -/* -static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color) -{ - // Table of indices into the palette of the first entries of each translated ramp - const UINT8 skinbasecolors[] = { - 0x00, // SKINCOLOR_WHITE - 0x03, // SKINCOLOR_SILVER - 0x08, // SKINCOLOR_GREY - 0x18, // SKINCOLOR_BLACK - 0xd0, // SKINCOLOR_CYAN - 0xdc, // SKINCOLOR_TEAL - 0xc8, // SKINCOLOR_STEEL - 0xe2, // SKINCOLOR_BLUE - 0x40, // SKINCOLOR_PEACH - 0x48, // SKINCOLOR_TAN - 0x90, // SKINCOLOR_PINK - 0xf8, // SKINCOLOR_LAVENDER - 0xc0, // SKINCOLOR_PURPLE - 0x52, // SKINCOLOR_ORANGE - 0x5c, // SKINCOLOR_ROSEWOOD - 0x20, // SKINCOLOR_BEIGE - 0x30, // SKINCOLOR_BROWN - 0x7d, // SKINCOLOR_RED - 0x85, // SKINCOLOR_DARKRED - 0xb8, // SKINCOLOR_NEONGREEN - 0xa0, // SKINCOLOR_GREEN - 0xb0, // SKINCOLOR_ZIM - 0x69, // SKINCOLOR_OLIVE - 0x67, // SKINCOLOR_YELLOW - 0x70, // SKINCOLOR_GOLD - }; - INT32 i; - INT32 starttranscolor; - - // Handle a couple of simple special cases - if (skinnum == TC_BOSS || skinnum == TC_ALLWHITE || skinnum == TC_METALSONIC || color == SKINCOLOR_NONE) - { - for (i = 0; i < NUM_PALETTE_ENTRIES; i++) - { - if (skinnum == TC_ALLWHITE) dest_colormap[i] = 0; - else dest_colormap[i] = (UINT8)i; - } - - // White! - if (skinnum == TC_BOSS) - dest_colormap[31] = 0; - else if (skinnum == TC_METALSONIC) - dest_colormap[239] = 0; - - return; - } - - starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR; - - // Fill in the entries of the palette that are fixed - for (i = 0; i < starttranscolor; i++) - dest_colormap[i] = (UINT8)i; - - for (i = (UINT8)(starttranscolor + 16); i < NUM_PALETTE_ENTRIES; i++) - dest_colormap[i] = (UINT8)i; - - // Build the translated ramp - switch (color) - { - case SKINCOLOR_SILVER: - case SKINCOLOR_GREY: - case SKINCOLOR_PEACH: - case SKINCOLOR_BEIGE: - case SKINCOLOR_BROWN: - case SKINCOLOR_RED: - case SKINCOLOR_GREEN: - case SKINCOLOR_BLUE: - // 16 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); - break; - - case SKINCOLOR_ORANGE: - // 14 colors of orange + brown - for (i = 0; i < SKIN_RAMP_LENGTH-2; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + (i+SKIN_RAMP_LENGTH-2)] = (UINT8)(152 + i); - break; - - case SKINCOLOR_CYAN: - // 12 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (12*i/SKIN_RAMP_LENGTH)); - break; - - case SKINCOLOR_WHITE: - case SKINCOLOR_BLACK: - case SKINCOLOR_STEEL: - case SKINCOLOR_PINK: - case SKINCOLOR_LAVENDER: - case SKINCOLOR_PURPLE: - case SKINCOLOR_DARKRED: - case SKINCOLOR_ZIM: - case SKINCOLOR_YELLOW: - case SKINCOLOR_GOLD: - // 8 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1)); - break; - - case SKINCOLOR_TEAL: - // 5 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (5*i/16 == 0) - dest_colormap[starttranscolor + i] = 0xf7; - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (5*i/SKIN_RAMP_LENGTH) - 1); - } - break; - - case SKINCOLOR_OLIVE: - // 7 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (7*i/SKIN_RAMP_LENGTH)); - break; - - case SKINCOLOR_TAN: - // 16 color ramp, from two color ranges - for (i = 0; i < SKIN_RAMP_LENGTH/2; i++) // Peach half - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); - for (i = 0; i < SKIN_RAMP_LENGTH/2; i++) // Brown half - dest_colormap[starttranscolor + (i+8)] = (UINT8)(48 + i); - break; - - case SKINCOLOR_ROSEWOOD: - // 12 color ramp, from two color ranges! - for (i = 0; i < 6; i++) // Orange ...third? - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (12*i/SKIN_RAMP_LENGTH)); - for (i = 0; i < 10; i++) // Rosewood two-thirds-ish - dest_colormap[starttranscolor + (i+6)] = (UINT8)(152 + (12*i/SKIN_RAMP_LENGTH)); - break; - - case SKINCOLOR_NEONGREEN: - // Multi-color ramp - dest_colormap[starttranscolor] = 0xA0; // Brighter green - for (i = 0; i < SKIN_RAMP_LENGTH-1; i++) // Neon Green - dest_colormap[starttranscolor + (i+1)] = (UINT8)(skinbasecolors[color - 1] + (6*i/(SKIN_RAMP_LENGTH-1))); - break; - - // Super colors, from lightest to darkest! - case SKINCOLOR_SUPER1: - // Super White - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = 120; // True white - for (; i < SKIN_RAMP_LENGTH; i++) // White-yellow fade - dest_colormap[starttranscolor + i] = (UINT8)(96 + (i-10)); - break; - - case SKINCOLOR_SUPER2: - // Super Bright - for (i = 0; i < 5; i++) // White-yellow fade - dest_colormap[starttranscolor + i] = (UINT8)(96 + i); - dest_colormap[starttranscolor + 5] = 112; // Golden shine - for (i = 0; i < 8; i++) // Yellow - dest_colormap[starttranscolor + (i+6)] = (UINT8)(101 + (i>>1)); - for (i = 0; i < 2; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + (i+14)] = (UINT8)(113 + i); - break; - - case SKINCOLOR_SUPER3: - // Super Yellow - for (i = 0; i < 3; i++) // White-yellow fade - dest_colormap[starttranscolor + i] = (UINT8)(98 + i); - dest_colormap[starttranscolor + 3] = 112; // Golden shine - for (i = 0; i < 8; i++) // Yellow - dest_colormap[starttranscolor + (i+4)] = (UINT8)(101 + (i>>1)); - for (i = 0; i < 4; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + (i+12)] = (UINT8)(113 + i); - break; - - case SKINCOLOR_SUPER4: - // "The SSNTails" - dest_colormap[starttranscolor] = 112; // Golden shine - for (i = 0; i < 8; i++) // Yellow - dest_colormap[starttranscolor + (i+1)] = (UINT8)(101 + (i>>1)); - for (i = 0; i < 7; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + (i+9)] = (UINT8)(113 + i); - break; - - case SKINCOLOR_SUPER5: - // Golden Delicious - for (i = 0; i < 8; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)(101 + (i>>1)); - for (i = 0; i < 7; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + (i+8)] = (UINT8)(113 + i); - dest_colormap[starttranscolor + 15] = 155; - break; - - // Super Tails - case SKINCOLOR_TSUPER1: - for (i = 0; i < 10; i++) // white - dest_colormap[starttranscolor + i] = 120; - for (; i < SKIN_RAMP_LENGTH; i++) // orange - dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-10)); - break; - - case SKINCOLOR_TSUPER2: - for (i = 0; i < 4; i++) // white - dest_colormap[starttranscolor + i] = 120; - for (; i < SKIN_RAMP_LENGTH; i++) // orange - dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-4)>>1)); - break; - - case SKINCOLOR_TSUPER3: - dest_colormap[starttranscolor] = 120; // pure white - dest_colormap[starttranscolor+1] = 120; - for (i = 2; i < SKIN_RAMP_LENGTH; i++) // orange - dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-2)>>1)); - break; - - case SKINCOLOR_TSUPER4: - dest_colormap[starttranscolor] = 120; // pure white - for (i = 1; i < 9; i++) // orange - dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-1)); - for (; i < SKIN_RAMP_LENGTH; i++) // gold - dest_colormap[starttranscolor + i] = (UINT8)(115 + (5*(i-9)/7)); - break; - - case SKINCOLOR_TSUPER5: - for (i = 0; i < 8; i++) // orange - dest_colormap[starttranscolor + i] = (UINT8)(80 + i); - for (; i < SKIN_RAMP_LENGTH; i++) // gold - dest_colormap[starttranscolor + i] = (UINT8)(115 + (5*(i-8)/8)); - break; - - // Super Knuckles - case SKINCOLOR_KSUPER1: - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(120 + (i >> 2)); - break; - - case SKINCOLOR_KSUPER2: - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(120 + (6*i/SKIN_RAMP_LENGTH)); - break; - - case SKINCOLOR_KSUPER3: - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(120 + (i >> 1)); - break; - - case SKINCOLOR_KSUPER4: - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(121 + (i >> 1)); - break; - - case SKINCOLOR_KSUPER5: - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(122 + (i >> 1)); - break; - - default: - I_Error("Invalid skin color #%hu.", (UINT16)color); - break; - } -} -*/ - /** \brief Retrieves a translation colormap from the cache. \param skinnum number of skin, TC_DEFAULT or TC_BOSS diff --git a/src/r_draw8.c b/src/r_draw8.c index 634ae7075..ef67dbaf7 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -105,7 +105,7 @@ void R_DrawColumn_8(void) } } -#define TRANSPARENTPIXEL 247 +#define TRANSPARENTPIXEL 255 void R_Draw2sMultiPatchColumn_8(void) { diff --git a/src/r_main.c b/src/r_main.c index 94c18d4ba..0d14bed73 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1331,7 +1331,7 @@ void R_RenderPlayerView(player_t *player) if (cv_homremoval.value == 1) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect! else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted. - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 128+(timeinmap&15)); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 32+(timeinmap&15)); } // Draw over the fourth screen so you don't have to stare at a HOM :V else if (splitscreen == 2 && player == &players[displayplayers[2]]) @@ -1562,6 +1562,7 @@ void R_RegisterEngineStuff(void) #endif CV_RegisterVar(&cv_grmdls); CV_RegisterVar(&cv_grfallbackplayermodel); + CV_RegisterVar(&cv_grspritebillboarding); #endif #ifdef HWRENDER diff --git a/src/r_segs.c b/src/r_segs.c index 1e8f27dda..399f514bc 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -862,8 +862,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights) { lightlist_t *nextlight = &frontsector->lightlist[i+1]; - if (nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height > pfloorleft - && nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height > pfloorright) + if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft + && (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright) continue; } diff --git a/src/r_things.c b/src/r_things.c index c3f30bfe6..1afbb125c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -42,8 +42,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; -static void R_InitSkins(void); - #define MINZ (FRACUNIT*4) #define BASEYCENTER (BASEVIDHEIGHT/2) @@ -585,7 +583,17 @@ void R_InitSprites(void) // // it can be is do before loading config for skin cvar possible value - R_InitSkins(); + // (... what the fuck did you just say to me? "it can be is do"?) +#ifdef SKINVALUES + for (i = 0; i <= MAXSKINS; i++) + { + skin_cons_t[i].value = 0; + skin_cons_t[i].strvalue = NULL; + } +#endif + + numskins = 0; + for (i = 0; i < numwadfiles; i++) R_AddSkins((UINT16)i); @@ -2537,7 +2545,7 @@ static void Sk_SetDefaultValue(skin_t *skin) strncpy(skin->facewant, "PLAYWANT", 9); strncpy(skin->facemmap, "PLAYMMAP", 9); - skin->starttranscolor = 160; + skin->starttranscolor = 96; skin->prefcolor = SKINCOLOR_GREEN; // SRB2kart @@ -2552,61 +2560,6 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->soundsid[S_sfx[i].skinsound] = i; } -// -// Initialize the basic skins -// -void R_InitSkins(void) -{ - skin_t *skin; -#ifdef SKINVALUES - INT32 i; - - for (i = 0; i <= MAXSKINS; i++) - { - skin_cons_t[i].value = 0; - skin_cons_t[i].strvalue = NULL; - } -#endif - - // skin[0] = Sonic skin - skin = &skins[0]; - numskins = 1; - Sk_SetDefaultValue(skin); - - // Hardcoded S_SKIN customizations for Sonic. - strcpy(skin->name, DEFAULTSKIN); -#ifdef SKINVALUES - skin_cons_t[0].strvalue = skins[0].name; -#endif - skin->flags = 0; - strcpy(skin->realname, "Sonic"); - strcpy(skin->hudname, "SONIC"); - - strncpy(skin->facerank, "PLAYRANK", 9); - strncpy(skin->facewant, "PLAYWANT", 9); - strncpy(skin->facemmap, "PLAYMMAP", 9); - skin->prefcolor = SKINCOLOR_BLUE; - - // SRB2kart - skin->kartspeed = 8; - skin->kartweight = 2; - // - - skin->spritedef.numframes = sprites[SPR_PLAY].numframes; - skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes; - ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0); - - // Set values for Sonic skin - Forceskin_cons_t[1].value = 0; - Forceskin_cons_t[1].strvalue = skin->name; - - //MD2 for sonic doesn't want to load in Linux. -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddPlayerMD2(0); -#endif -} - // returns true if the skin name is found (loaded from pwad) // warning return -1 if not found INT32 R_SkinAvailable(const char *name) diff --git a/src/s_sound.c b/src/s_sound.c index 545336e0f..21b668f28 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -38,6 +38,10 @@ extern INT32 msg_id; #include "p_local.h" // camera info #include "m_misc.h" // for tunes command +#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) +#include "lua_hook.h" // MusicChange hook +#endif + #ifdef HW3SOUND // 3D Sound Interface #include "hardware/hw3sound.h" @@ -1547,6 +1551,12 @@ static void *music_data; static UINT16 music_flags; static boolean music_looping; +static char queue_name[7]; +static UINT16 queue_flags; +static boolean queue_looping; +static UINT32 queue_position; +static UINT32 queue_fadeinms; + /// ------------------------ /// Music Definitions /// ------------------------ @@ -1785,6 +1795,11 @@ musictype_t S_MusicType(void) return I_SongType(); } +const char *S_MusicName(void) +{ + return music_name; +} + boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping) { if (!I_SongPlaying()) @@ -1815,6 +1830,35 @@ boolean S_SpeedMusic(float speed) return I_SetSongSpeed(speed); } +/// ------------------------ +/// Music Seeking +/// ------------------------ + +UINT32 S_GetMusicLength(void) +{ + return I_GetSongLength(); +} + +boolean S_SetMusicLoopPoint(UINT32 looppoint) +{ + return I_SetSongLoopPoint(looppoint); +} + +UINT32 S_GetMusicLoopPoint(void) +{ + return I_GetSongLoopPoint(); +} + +boolean S_SetMusicPosition(UINT32 position) +{ + return I_SetSongPosition(position); +} + +UINT32 S_GetMusicPosition(void) +{ + return I_GetSongPosition(); +} + /// ------------------------ /// Music Playback /// ------------------------ @@ -1891,12 +1935,13 @@ static void S_UnloadMusic(void) music_looping = false; } -static boolean S_PlayMusic(boolean looping) +static boolean S_PlayMusic(boolean looping, UINT32 fadeinms) { if (S_MusicDisabled()) return false; - if (!I_PlaySong(looping)) + if ((!fadeinms && !I_PlaySong(looping)) || + (fadeinms && !I_FadeInPlaySong(fadeinms, looping))) { S_UnloadMusic(); return false; @@ -1910,8 +1955,30 @@ static boolean S_PlayMusic(boolean looping) return true; } -void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) +static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 fadeinms) { + strncpy(queue_name, mmusic, 7); + queue_flags = mflags; + queue_looping = looping; + queue_position = position; + queue_fadeinms = fadeinms; +} + +static void S_ClearQueue(void) +{ + queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0; +} + +static void S_ChangeMusicToQueue(void) +{ + S_ChangeMusicEx(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms); + S_ClearQueue(); +} + +void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms) +{ + char newmusic[7]; + #if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X) S_ClearSfx(); #endif @@ -1921,33 +1988,66 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping) || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; - // No Music (empty string) - if (mmusic[0] == 0) - { - S_StopMusic(); + strncpy(newmusic, mmusic, 7); +#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) + if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) + return; +#endif + newmusic[6] = 0; + + // No Music (empty string) + if (newmusic[0] == 0) + { + if (prefadems) + I_FadeSong(0, prefadems, &S_StopMusic); + else + S_StopMusic(); return; } - if (strnicmp(music_name, mmusic, 6)) + if (prefadems && S_MusicPlaying()) // queue music change for after fade // allow even if the music is the same { - S_StopMusic(); // shutdown old music + CONS_Debug(DBG_DETAILED, "Now fading out song %s\n", music_name); + S_QueueMusic(newmusic, mflags, looping, position, fadeinms); + I_FadeSong(0, prefadems, S_ChangeMusicToQueue); + return; + } + else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET)) + { + CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic); - if (!S_LoadMusic(mmusic)) + S_StopMusic(); + + if (!S_LoadMusic(newmusic)) { - CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", mmusic); + CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", newmusic); return; } music_flags = mflags; music_looping = looping; - if (!S_PlayMusic(looping)) - { - CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", mmusic); + if (!S_PlayMusic(looping, fadeinms)) + { + CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", newmusic); return; } + + if (position) + I_SetSongPosition(position); + + I_SetSongTrack(mflags & MUSIC_TRACKMASK); + } + else if (fadeinms) // let fades happen with same music + { + I_SetSongPosition(position); + I_FadeSong(100, fadeinms, NULL); + } + else // reset volume to 100 with same music + { + I_StopFadingSong(); + I_FadeSong(100, 500, NULL); } - I_SetSongTrack(mflags & MUSIC_TRACKMASK); } void S_StopMusic(void) @@ -2054,6 +2154,32 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) } } +/// ------------------------ +/// Music Fading +/// ------------------------ + +void S_SetInternalMusicVolume(INT32 volume) +{ + I_SetInternalMusicVolume(min(max(volume, 0), 100)); +} + +void S_StopFadingMusic(void) +{ + I_StopFadingSong(); +} + +boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms) +{ + if (source_volume < 0) + return I_FadeSong(target_volume, ms, NULL); + else + return I_FadeSongFromVolume(target_volume, source_volume, ms, NULL); +} + +boolean S_FadeOutStopMusic(UINT32 ms) +{ + return I_FadeSong(0, ms, &S_StopMusic); +} /// ------------------------ /// Init & Others @@ -2071,26 +2197,28 @@ void S_Start(void) strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); mapmusname[6] = 0; mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); + mapmusposition = mapheaderinfo[gamemap-1]->muspos; } //if (cv_resetmusic.value) // Starting ambience should always be restarted S_StopMusic(); if (leveltime < (starttime + (TICRATE/2))) // SRB2Kart - S_ChangeMusic((encoremode ? "estart" : "kstart"), 0, false); + S_ChangeMusicEx((encoremode ? "estart" : "kstart"), 0, false, mapmusposition, 0, 0); else - S_ChangeMusic(mapmusname, mapmusflags, true); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } static void Command_Tunes_f(void) { const char *tunearg; UINT16 tunenum, track = 0; + UINT32 position = 0; const size_t argc = COM_Argc(); if (argc < 2) //tunes slot ... { - CONS_Printf("tunes [track] [speed] / <-show> / <-default> / <-none>:\n"); + CONS_Printf("tunes [track] [speed] [position] / <-show> / <-default> / <-none>:\n"); CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n")); CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n")); CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n")); @@ -2137,10 +2265,15 @@ static void Command_Tunes_f(void) snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum)); else strncpy(mapmusname, tunearg, 7); + + if (argc > 4) + position = (UINT32)atoi(COM_Argv(4)); + mapmusname[6] = 0; mapmusflags = (track & MUSIC_TRACKMASK); + mapmusposition = position; - S_ChangeMusic(mapmusname, mapmusflags, true); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); if (argc > 3) { diff --git a/src/s_sound.h b/src/s_sound.h index 1c9386816..2a904faff 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -117,14 +117,14 @@ boolean S_MusicDisabled(void); boolean S_MusicPlaying(void); boolean S_MusicPaused(void); musictype_t S_MusicType(void); +const char *S_MusicName(void); boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping); boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); #define S_DigExists(a) S_MusicExists(a, false, true) #define S_MIDIExists(a) S_MusicExists(a, true, false) - // -// Music Properties +// Music Effects // // Set Speed of Music @@ -154,15 +154,35 @@ void S_InitMusicDefs(void); void S_ShowMusicCredit(void); // -// Music Routines +// Music Seeking +// + +// Get Length of Music +UINT32 S_GetMusicLength(void); + +// Set LoopPoint of Music +boolean S_SetMusicLoopPoint(UINT32 looppoint); + +// Get LoopPoint of Music +UINT32 S_GetMusicLoopPoint(void); + +// Set Position of Music +boolean S_SetMusicPosition(UINT32 position); + +// Get Position of Music +UINT32 S_GetMusicPosition(void); + +// +// Music Playback // // Start music track, arbitrary, given its name, and set whether looping // note: music flags 12 bits for tracknum (gme, other formats with more than one track) // 13-15 aren't used yet // and the last bit we ignore (internal game flag for resetting music on reload) -#define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b) -void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping); +void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms); +#define S_ChangeMusicInternal(a,b) S_ChangeMusicEx(a,0,b,0,0,0) +#define S_ChangeMusic(a,b,c) S_ChangeMusicEx(a,b,c,0,0,0) // Stops the music. void S_StopMusic(void); @@ -175,6 +195,17 @@ void S_ResumeAudio(void); void S_EnableSound(void); void S_DisableSound(void); +// +// Music Fading +// + +void S_SetInternalMusicVolume(INT32 volume); +void S_StopFadingMusic(void); +boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms); +#define S_FadeMusic(a, b) S_FadeMusicFromVolume(a, -1, b) +#define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicEx(a,b,c,0,0,d) +boolean S_FadeOutStopMusic(UINT32 ms); + // // Updates music & sounds // diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c0fca64da..d24bd5ade 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -131,7 +131,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif -// Locations for searching the srb2.srb +// Locations for searching for main.kart #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2Kart" #define DEFAULTWADLOCATION2 "/usr/local/games/SRB2Kart" @@ -149,8 +149,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); /** \brief WAD file to look for */ -#define WADKEYWORD1 "srb2.srb" -#define WADKEYWORD2 "srb2.wad" +#define WADKEYWORD "main.kart" /** \brief holds wad path */ static char returnWadPath[256]; @@ -3454,15 +3453,7 @@ static boolean isWadPathOk(const char *path) if (!wad3path) return false; - sprintf(wad3path, pandf, path, WADKEYWORD1); - - if (FIL_ReadFileOK(wad3path)) - { - free(wad3path); - return true; - } - - sprintf(wad3path, pandf, path, WADKEYWORD2); + sprintf(wad3path, pandf, path, WADKEYWORD); if (FIL_ReadFileOK(wad3path)) { @@ -3487,7 +3478,7 @@ static void pathonly(char *s) } } -/** \brief search for srb2.srb in the given path +/** \brief search for main.kart in the given path \param searchDir starting path @@ -3500,7 +3491,7 @@ static const char *searchWad(const char *searchDir) static char tempsw[256] = ""; filestatus_t fstemp; - strcpy(tempsw, WADKEYWORD1); + strcpy(tempsw, WADKEYWORD); fstemp = filesearch(tempsw,searchDir,NULL,true,20); if (fstemp == FS_FOUND) { @@ -3508,19 +3499,12 @@ static const char *searchWad(const char *searchDir) return tempsw; } - strcpy(tempsw, WADKEYWORD2); - fstemp = filesearch(tempsw, searchDir, NULL, true, 20); - if (fstemp == FS_FOUND) - { - pathonly(tempsw); - return tempsw; - } return NULL; } -/** \brief go through all possible paths and look for srb2.srb +/** \brief go through all possible paths and look for main.kart - \return path to srb2.srb if any + \return path to main.kart if any */ static const char *locateWad(void) { @@ -3649,7 +3633,7 @@ const char *I_LocateWad(void) if (waddir) { - // change to the directory where we found srb2.srb + // change to the directory where we found main.kart #if defined (_WIN32) SetCurrentDirectoryA(waddir); #else diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 954ef5ee9..1617da2a3 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -75,15 +75,41 @@ UINT8 sound_started = false; static Mix_Music *music; -static UINT8 music_volume, sfx_volume; +static UINT8 music_volume, sfx_volume, internal_volume; static float loop_point; +static float song_length; // length in seconds static boolean songpaused; +static UINT32 music_bytes; +static boolean is_looping; + +// fading +static boolean is_fading; +static UINT8 fading_source; +static UINT8 fading_target; +static UINT32 fading_timer; +static UINT32 fading_duration; +static INT32 fading_id; +static void (*fading_callback)(void); #ifdef HAVE_LIBGME static Music_Emu *gme; static INT32 current_track; #endif +static void var_cleanup(void) +{ + loop_point = song_length =\ + music_bytes = fading_source = fading_target =\ + fading_timer = fading_duration = 0; + + songpaused = is_looping =\ + is_fading = false; + + fading_callback = NULL; + + internal_volume = 100; +} + /// ------------------------ /// Audio System /// ------------------------ @@ -111,6 +137,8 @@ void I_StartupSound(void) return; } + var_cleanup(); + music = NULL; music_volume = sfx_volume = 0; @@ -336,6 +364,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = malloc(len); gme_play(emu, len >> 1, mem); + gme_free_info(info); gme_delete(emu); return Mix_QuickLoad_RAW((Uint8 *)mem, len); @@ -408,6 +437,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = malloc(len); gme_play(emu, len >> 1, mem); + gme_free_info(info); gme_delete(emu); return Mix_QuickLoad_RAW((Uint8 *)mem, len); @@ -482,14 +512,102 @@ void I_SetSfxVolume(UINT8 volume) sfx_volume = volume; } +/// ------------------------ +/// Music Utilities +/// ------------------------ + +static UINT32 get_real_volume(UINT8 volume) +{ +#ifdef _WIN32 + if (I_SongType() == MU_MID) + // HACK: Until we stop using native MIDI, + // disable volume changes + return ((UINT32)31*128/31); // volume = 31 + else +#endif + // convert volume to mixer's 128 scale + // then apply internal_volume as a percentage + return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100; +} + +static UINT32 get_adjusted_position(UINT32 position) +{ + // all in milliseconds + UINT32 length = I_GetSongLength(); + UINT32 looppoint = I_GetSongLoopPoint(); + if (length) + return position >= length ? (position % (length-looppoint)) : position; + else + return position; +} + +static void do_fading_callback(void) +{ + if (fading_callback) + (*fading_callback)(); + fading_callback = NULL; +} + /// ------------------------ /// Music Hooks /// ------------------------ +static void count_music_bytes(int chan, void *stream, int len, void *udata) +{ + (void)chan; + (void)stream; + (void)udata; + + if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID) + return; + music_bytes += len; +} + static void music_loop(void) { - Mix_PlayMusic(music, 0); - Mix_SetMusicPosition(loop_point); + if (is_looping) + { + Mix_PlayMusic(music, 0); + Mix_SetMusicPosition(loop_point); + music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + } + else + I_StopSong(); +} + +static UINT32 music_fade(UINT32 interval, void *param) +{ + (void)param; + + if (!is_fading || + internal_volume == fading_target || + fading_duration == 0) + { + I_StopFadingSong(); + do_fading_callback(); + return 0; + } + else if (songpaused) // don't decrement timer + return interval; + else if ((fading_timer -= 10) <= 0) + { + internal_volume = fading_target; + Mix_VolumeMusic(get_real_volume(music_volume)); + I_StopFadingSong(); + do_fading_callback(); + return 0; + } + else + { + UINT8 delta = abs(fading_target - fading_source); + fixed_t factor = FixedDiv(fading_duration - fading_timer, fading_duration); + if (fading_target < fading_source) + internal_volume = max(min(internal_volume, fading_source - FixedMul(delta, factor)), fading_target); + else if (fading_target > fading_source) + internal_volume = min(max(internal_volume, fading_source + FixedMul(delta, factor)), fading_target); + Mix_VolumeMusic(get_real_volume(music_volume)); + return interval; + } } #ifdef HAVE_LIBGME @@ -509,7 +627,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*2 / 42; + *p = ((INT32)*p) * (music_volume*internal_volume/100)*2 / 42; } #endif @@ -586,6 +704,194 @@ boolean I_SetSongSpeed(float speed) return false; } +/// ------------------------ +/// MUSIC SEEKING +/// ------------------------ + +UINT32 I_GetSongLength(void) +{ + INT32 length; + +#ifdef HAVE_LIBGME + if (gme) + { + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + length = 0; + } + else + { + // reconstruct info->play_length, from GME source + // we only want intro + 1 loop, not 2 + length = info->length; + if (length <= 0) + { + length = info->intro_length + info->loop_length; // intro + 1 loop + if (length <= 0) + length = 150 * 1000; // 2.5 minutes + } + } + + gme_free_info(info); + return max(length, 0); + } + else +#endif + if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) + return 0; + else + { + // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! + // SDL mixer can't read music length itself. + length = (UINT32)(song_length*1000); + if (!length) + CONS_Debug(DBG_DETAILED, "Getting music length: music is missing LENGTHMS= tag. Needed for seeking.\n"); + return length; + } +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID || !is_looping) + return false; + else + { + UINT32 length = I_GetSongLength(); + + if (length > 0) + looppoint %= length; + + loop_point = max((float)(looppoint / 1000.0L), 0); + return true; + } +} + +UINT32 I_GetSongLoopPoint(void) +{ +#ifdef HAVE_LIBGME + if (gme) + { + INT32 looppoint; + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + looppoint = 0; + } + else + looppoint = info->intro_length > 0 ? info->intro_length : 0; + + gme_free_info(info); + return max(looppoint, 0); + } + else +#endif + if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) + return 0; + else + return (UINT32)(loop_point * 1000); +} + +boolean I_SetSongPosition(UINT32 position) +{ + UINT32 length; +#ifdef HAVE_LIBGME + if (gme) + { + // this is unstable, so fail silently + return true; + // this isn't required technically, but GME thread-locks for a second + // if you seek too high from the counter + // length = I_GetSongLength(); + // if (length) + // position = get_adjusted_position(position); + + // SDL_LockAudio(); + // gme_err_t gme_e = gme_seek(gme, position); + // SDL_UnlockAudio(); + + // if (gme_e != NULL) + // { + // CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + // return false; + // } + // else + // return true; + } + else +#endif + if (!music || I_SongType() == MU_MID) + return false; + else if (I_SongType() == MU_MOD) + return Mix_SetMusicPosition(position); // Goes by channels + else + { + // Because SDL mixer can't identify song length, if you have + // a position input greater than the real length, then + // music_bytes becomes inaccurate. + + length = I_GetSongLength(); // get it in MS + if (length) + position = get_adjusted_position(position); + + Mix_RewindMusic(); // needed for mp3 + if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) + music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + else + // NOTE: This block fires on incorrect song format, + // NOT if position input is greater than song length. + music_bytes = 0; + + return true; + } +} + +UINT32 I_GetSongPosition(void) +{ +#ifdef HAVE_LIBGME + if (gme) + { + INT32 position = gme_tell(gme); + + gme_info_t *info; + gme_err_t gme_e = gme_track_info(gme, &info, current_track); + + if (gme_e != NULL) + { + CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); + return position; + } + else + { + // adjust position, since GME's counter keeps going past loop + if (info->length > 0) + position %= info->length; + else if (info->intro_length + info->loop_length > 0) + position = position >= (info->intro_length + info->loop_length) ? (position % info->loop_length) : position; + else + position %= 150 * 1000; // 2.5 minutes + } + + gme_free_info(info); + return max(position, 0); + } + else +#endif + if (!music || I_SongType() == MU_MID) + return 0; + else + return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz + // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) + // This is hardcoded in I_StartupSound. Other formats for factor: + // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 +} + /// ------------------------ /// Music Playback /// ------------------------ @@ -598,6 +904,7 @@ boolean I_LoadSong(char *data, size_t len) const size_t key1len = strlen(key1); const size_t key2len = strlen(key2); const size_t key3len = strlen(key3); + char *p = data; SDL_RWops *rw; @@ -608,6 +915,9 @@ boolean I_LoadSong(char *data, size_t len) ) I_UnloadSong(); + // always do this whether or not a music already exists + var_cleanup(); + #ifdef HAVE_LIBGME if ((UINT8)data[0] == 0x1F && (UINT8)data[1] == 0x8B) @@ -717,30 +1027,35 @@ boolean I_LoadSong(char *data, size_t len) // Find the OGG loop point. loop_point = 0.0f; + song_length = 0.0f; while ((UINT32)(p - data) < len) { - if (strncmp(p++, key1, key1len)) - continue; - p += key1len-1; // skip OOP (the L was skipped in strncmp) - if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? + if (fpclassify(loop_point) == FP_ZERO && !strncmp(p, key1, key1len)) { - p += key2len; // skip POINT= - loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. - // because SDL_Mixer is USELESS and can't even tell us - // something simple like the frequency of the streaming music, - // we are unfortunately forced to assume that ALL MUSIC is 44100hz. - // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. + p += key1len; // skip LOOP + if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? + { + p += key2len; // skip POINT= + loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. + // because SDL_Mixer is USELESS and can't even tell us + // something simple like the frequency of the streaming music, + // we are unfortunately forced to assume that ALL MUSIC is 44100hz. + // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. + } + else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? + { + p += key3len; // skip MS= + loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. + // Everything that uses LOOPMS will work perfectly with SDL_Mixer. + } } - else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? - { - p += key3len; // skip MS= - loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. - // Everything that uses LOOPMS will work perfectly with SDL_Mixer. - } - // Neither?! Continue searching. - } + if (fpclassify(loop_point) != FP_ZERO) // Got what we needed + break; + else // continue searching + p++; + } return true; } @@ -764,7 +1079,6 @@ void I_UnloadSong(void) boolean I_PlaySong(boolean looping) { - boolean lpz = fpclassify(loop_point) == FP_ZERO; #ifdef HAVE_LIBGME if (gme) { @@ -778,21 +1092,37 @@ boolean I_PlaySong(boolean looping) if (!music) return false; + if (fpclassify(song_length) == FP_ZERO && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC)) + CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n"); - if (Mix_PlayMusic(music, looping && lpz ? -1 : 0) == -1) + if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1) + { + CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); + return false; + } + else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); return false; } - Mix_VolumeMusic((UINT32)music_volume*128/31); - if (!lpz) - Mix_HookMusicFinished(music_loop); + is_looping = looping; + + I_SetMusicVolume(music_volume); + + if (I_SongType() != MU_MOD && I_SongType() != MU_MID) + Mix_HookMusicFinished(music_loop); // don't bother counting if MOD + + if(I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); + return true; } void I_StopSong(void) { + I_StopFadingSong(); + #ifdef HAVE_LIBGME if (gme) { @@ -802,19 +1132,40 @@ void I_StopSong(void) #endif if (music) { + Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); Mix_HaltMusic(); } + + var_cleanup(); } void I_PauseSong(void) { + if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI??? + return; + + if(I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); + Mix_PauseMusic(); songpaused = true; } void I_ResumeSong(void) { + if (I_SongType() == MU_MID) + return; + + if (I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + { + while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { } + // HACK: fixes issue of multiple effect callbacks being registered + + if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); + } + Mix_ResumeMusic(); songpaused = false; } @@ -833,7 +1184,7 @@ void I_SetMusicVolume(UINT8 volume) #endif music_volume = volume; - Mix_VolumeMusic((UINT32)music_volume*128/31); + Mix_VolumeMusic(get_real_volume(music_volume)); } boolean I_SetSongTrack(int track) @@ -862,9 +1213,100 @@ boolean I_SetSongTrack(int track) SDL_UnlockAudio(); return false; } + else #endif + if (I_SongType() == MU_MOD) + return !Mix_SetMusicPosition(track); (void)track; return false; } +/// ------------------------ +/// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + internal_volume = volume; + if (!I_SongPlaying()) + return; + Mix_VolumeMusic(get_real_volume(music_volume)); +} + +void I_StopFadingSong(void) +{ + if (fading_id) + SDL_RemoveTimer(fading_id); + is_fading = false; + fading_source = fading_target = fading_timer = fading_duration = fading_id = 0; +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) +{ + INT16 volume_delta; + + source_volume = min(source_volume, 100); + volume_delta = (INT16)(target_volume - source_volume); + + I_StopFadingSong(); + + if (!ms && volume_delta) + { + I_SetInternalMusicVolume(target_volume); + if (callback) + (*callback)(); + return true; + + } + else if (!volume_delta) + { + if (callback) + (*callback)(); + return true; + } + + // Round MS to nearest 10 + // If n - lower > higher - n, then round up + ms = (ms - ((ms / 10) * 10) > (((ms / 10) * 10) + 10) - ms) ? + (((ms / 10) * 10) + 10) // higher + : ((ms / 10) * 10); // lower + + if (!ms) + I_SetInternalMusicVolume(target_volume); + else if (source_volume != target_volume) + { + fading_id = SDL_AddTimer(10, music_fade, NULL); + if (fading_id) + { + is_fading = true; + fading_timer = fading_duration = ms; + fading_source = source_volume; + fading_target = target_volume; + fading_callback = callback; + + if (internal_volume != source_volume) + I_SetInternalMusicVolume(source_volume); + } + } + + return is_fading; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) +{ + return I_FadeSongFromVolume(target_volume, internal_volume, ms, callback); +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + return I_FadeSongFromVolume(0, internal_volume, ms, &I_StopSong); +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + if (I_PlaySong(looping)) + return I_FadeSongFromVolume(100, 0, ms, NULL); + else + return false; +} #endif diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 9ff1dd0b2..d9967ae03 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1375,6 +1375,37 @@ boolean I_SetSongSpeed(float speed) return false; } +/// ------------------------ +// MUSIC SEEKING +/// ------------------------ + +UINT32 I_GetSongLength(void) +{ + return 0; +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetSongLoopPoint(void) +{ + return 0; +} + +boolean I_SetSongPosition(UINT32 position) +{ + (void)position; + return false; +} + +UINT32 I_GetSongPosition(void) +{ + return 0; +} + /// ------------------------ // MUSIC PLAYBACK /// ------------------------ @@ -1443,6 +1474,47 @@ boolean I_SetSongTrack(int track) return false; } +/// ------------------------ +/// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + (void)volume; +} + +void I_StopFadingSong(void) +{ +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) +{ + (void)target_volume; + (void)source_volume; + (void)ms; + return false; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) +{ + (void)target_volume; + (void)ms; + return false; +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + (void)ms; + return false; +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + (void)ms; + (void)looping; + return false; +} + /// ------------------------ // MUSIC LOADING AND CLEANUP // \todo Split logic between loading and playing, diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index d055a4ca5..62256f3a5 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -145,7 +145,7 @@ void __set_fpscr(long); // in libgcc / kernel's startup.s? #define O_BINARY 0 #endif -// Locations for searching the srb2.srb +// Locations for searching the main.kart #ifdef _arch_dreamcast #define DEFAULTWADLOCATION1 "/cd" #define DEFAULTWADLOCATION2 "/pc" @@ -217,8 +217,7 @@ void __set_fpscr(long); // in libgcc / kernel's startup.s? /** \brief WAD file to look for */ -#define WADKEYWORD1 "srb2.srb" -#define WADKEYWORD2 "srb2.wad" +#define WADKEYWORD "main.kart" /** \brief holds wad path */ static char returnWadPath[256]; @@ -3398,15 +3397,7 @@ static boolean isWadPathOk(const char *path) if (!wad3path) return false; - sprintf(wad3path, pandf, path, WADKEYWORD1); - - if (FIL_ReadFileOK(wad3path)) - { - free(wad3path); - return true; - } - - sprintf(wad3path, pandf, path, WADKEYWORD2); + sprintf(wad3path, pandf, path, WADKEYWORD); if (FIL_ReadFileOK(wad3path)) { @@ -3431,7 +3422,7 @@ static void pathonly(char *s) } } -/** \brief search for srb2.srb in the given path +/** \brief search for main.kart in the given path \param searchDir starting path @@ -3444,7 +3435,7 @@ static const char *searchWad(const char *searchDir) static char tempsw[256] = ""; filestatus_t fstemp; - strcpy(tempsw, WADKEYWORD1); + strcpy(tempsw, WADKEYWORD); fstemp = filesearch(tempsw,searchDir,NULL,true,20); if (fstemp == FS_FOUND) { @@ -3452,19 +3443,12 @@ static const char *searchWad(const char *searchDir) return tempsw; } - strcpy(tempsw, WADKEYWORD2); - fstemp = filesearch(tempsw, searchDir, NULL, true, 20); - if (fstemp == FS_FOUND) - { - pathonly(tempsw); - return tempsw; - } return NULL; } -/** \brief go through all possible paths and look for srb2.srb +/** \brief go through all possible paths and look for main.kart - \return path to srb2.srb if any + \return path to main.kart if any */ static const char *locateWad(void) { @@ -3581,7 +3565,7 @@ const char *I_LocateWad(void) if (waddir) { - // change to the directory where we found srb2.srb + // change to the directory where we found main.kart #if (defined (_WIN32) && !defined (_WIN32_WCE)) && !defined (_XBOX) SetCurrentDirectoryA(waddir); #elif !defined (_WIN32_WCE) && !defined (_PS3) diff --git a/src/st_stuff.c b/src/st_stuff.c index 50bac3eef..e59846aed 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2138,8 +2138,8 @@ void ST_Drawer(void) if (timeinmap < 15) { if (timeinmap <= 5) - V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,120); // Pure white on first few frames, to hide SRB2's awful level load artifacts + V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,0); // Pure white on first few frames, to hide SRB2's awful level load artifacts else - V_DrawFadeScreen(120, 15-timeinmap); // Then gradually fade out from there + V_DrawFadeScreen(0, 15-timeinmap); // Then gradually fade out from there } } diff --git a/src/tmap.nas b/src/tmap.nas index 78840106f..c72c1890a 100644 --- a/src/tmap.nas +++ b/src/tmap.nas @@ -17,7 +17,7 @@ [BITS 32] %define FRACBITS 16 -%define TRANSPARENTPIXEL 247 +%define TRANSPARENTPIXEL 255 %ifdef LINUX %macro cextern 1 diff --git a/src/tmap_mmx.nas b/src/tmap_mmx.nas index 39380a065..c512de8e9 100644 --- a/src/tmap_mmx.nas +++ b/src/tmap_mmx.nas @@ -18,7 +18,7 @@ [BITS 32] %define FRACBITS 16 -%define TRANSPARENTPIXEL 247 +%define TRANSPARENTPIXEL 255 %ifdef LINUX %macro cextern 1 diff --git a/src/v_video.c b/src/v_video.c index 3966924dc..4cc2ec06c 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -81,6 +81,7 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0 // console variables in development consvar_t cv_grmdls = {"gr_mdls", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif const UINT8 gammatable[5][256] = @@ -1358,16 +1359,16 @@ UINT8 *V_GetStringColormap(INT32 colorflags) return lavendermap; case 10: // 0x8A, gold return goldmap; - case 11: // 0x8B, tea-green - return teamap; - case 12: // 0x8C, steel - return steelmap; + case 11: // 0x8B, aqua-green + return aquamap; + case 12: // 0x8C, magenta + return magentamap; case 13: // 0x8D, pink return pinkmap; case 14: // 0x8E, brown return brownmap; - case 15: // 0x8F, peach - return peachmap; + case 15: // 0x8F, tan + return tanmap; default: // reset return NULL; } diff --git a/src/v_video.h b/src/v_video.h index c8485c179..a48fed4d3 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -79,11 +79,11 @@ extern UINT8 hudtrans; #define V_SKYMAP 0x00008000 #define V_LAVENDERMAP 0x00009000 #define V_GOLDMAP 0x0000A000 -#define V_TEAMAP 0x0000B000 -#define V_STEELMAP 0x0000C000 +#define V_AQUAMAP 0x0000B000 +#define V_MAGENTAMAP 0x0000C000 #define V_PINKMAP 0x0000D000 #define V_BROWNMAP 0x0000E000 -#define V_PEACHMAP 0x0000F000 +#define V_TANMAP 0x0000F000 // use bits 17-20 for alpha transparency #define V_ALPHASHIFT 16 diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index 157d97446..e6675421e 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -24,8 +24,10 @@ ifndef NOASM USEASM=1 endif +ifndef NONET ifndef MINGW64 #miniupnc is broken with MINGW64 HAVE_MINIUPNPC=1 +endif endif OPTS=-DSTDC_HEADERS diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index 454c53e37..f3e3bbed4 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -815,6 +815,60 @@ void I_SetMusicVolume(UINT8 volume) FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); } +UINT32 I_GetSongLength(void) +{ + UINT32 length; + if (I_SongType() == MU_MID) + return 0; + FMR_MUSIC(FMOD_Sound_GetLength(music_stream, &length, FMOD_TIMEUNIT_MS)); + return length; +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetSongLoopPoint(void) +{ + return 0; +} + +boolean I_SetSongPosition(UINT32 position) +{ + FMOD_RESULT e; + if(I_SongType() == MU_MID) + // Dummy out; this works for some MIDI, but not others. + // SDL does not support this for any MIDI. + return false; + e = FMOD_Channel_SetPosition(music_channel, position, FMOD_TIMEUNIT_MS); + if (e == FMOD_OK) + return true; + else if (e == FMOD_ERR_UNSUPPORTED // Only music modules, numbnuts! + || e == FMOD_ERR_INVALID_POSITION) // Out-of-bounds! + return false; + else // Congrats, you horribly broke it somehow + { + FMR_MUSIC(e); + return false; + } +} + +UINT32 I_GetSongPosition(void) +{ + FMOD_RESULT e; + unsigned int fmposition = 0; + if(I_SongType() == MU_MID) + // Dummy out because unsupported, even though FMOD does this correctly. + return 0; + e = FMOD_Channel_GetPosition(music_channel, &fmposition, FMOD_TIMEUNIT_MS); + if (e == FMOD_OK) + return (UINT32)fmposition; + else + return 0; +} + boolean I_SetSongTrack(INT32 track) { if (track != current_track) // If the track's already playing, then why bother? @@ -859,3 +913,46 @@ boolean I_SetSongTrack(INT32 track) } return false; } + +/// ------------------------ +/// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + (void)volume; +} + +void I_StopFadingSong(void) +{ +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) +{ + (void)target_volume; + (void)source_volume; + (void)ms; + (void)callback; + return false; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) +{ + (void)target_volume; + (void)ms; + (void)callback; + return false; +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + (void)ms; + return false; +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + (void)ms; + (void)looping; + return false; +} diff --git a/src/y_inter.c b/src/y_inter.c index 379694a11..c270f04ab 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1083,7 +1083,7 @@ void Y_VoteDrawer(void) V_DrawMappedPatch(BASEVIDWIDTH-124, handy, V_SNAPTORIGHT, thiscurs, colormap); if (votetic % 10 < 4) - V_DrawFill(BASEVIDWIDTH-100-sizeadd, y-sizeadd, 80+(sizeadd*2), 50+(sizeadd*2), 120|V_SNAPTORIGHT); + V_DrawFill(BASEVIDWIDTH-100-sizeadd, y-sizeadd, 80+(sizeadd*2), 50+(sizeadd*2), 0|V_SNAPTORIGHT); else V_DrawFill(BASEVIDWIDTH-100-sizeadd, y-sizeadd, 80+(sizeadd*2), 50+(sizeadd*2), color|V_SNAPTORIGHT); @@ -1154,7 +1154,7 @@ void Y_VoteDrawer(void) { V_DrawScaledPatch(x-18, y+9, V_SNAPTOLEFT, cursor); if (voteendtic != -1 && !(votetic % 4)) - V_DrawFill(x-1, y-1, 42, 27, 120|V_SNAPTOLEFT); + V_DrawFill(x-1, y-1, 42, 27, 0|V_SNAPTOLEFT); else V_DrawFill(x-1, y-1, 42, 27, levelinfo[votes[i]].gtc|V_SNAPTOLEFT); }