From b6dbecd2f830fd90d40cbf9fc6e2261e3ed404d8 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Aug 2018 21:08:47 +0100 Subject: [PATCH 01/37] Addons menu. Bitch. --- src/console.c | 4 + src/d_clisrv.h | 3 +- src/d_main.c | 34 ++- src/d_netcmd.c | 50 ++-- src/d_netfil.c | 81 ++----- src/d_netfil.h | 1 - src/filesrch.c | 473 +++++++++++++++++++++++++++++++++++++- src/filesrch.h | 67 ++++++ src/m_menu.c | 608 +++++++++++++++++++++++++++++++++++++++++++++++-- src/m_menu.h | 5 + src/p_setup.c | 3 + src/w_wad.c | 76 ++++--- src/w_wad.h | 1 + 13 files changed, 1259 insertions(+), 147 deletions(-) diff --git a/src/console.c b/src/console.c index 212e6c8d..b335885d 100644 --- a/src/console.c +++ b/src/console.c @@ -33,6 +33,7 @@ #include "i_system.h" #include "d_main.h" #include "m_menu.h" +#include "filesrch.h" #ifdef _WINDOWS #include "win32/win_main.h" @@ -1281,12 +1282,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...) switch (level) { case CONS_NOTICE: + // no notice for notices, hehe CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:")); break; case CONS_WARNING: + refreshdirmenu |= REFRESHDIR_WARNING; CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:")); break; case CONS_ERROR: + refreshdirmenu |= REFRESHDIR_ERROR; CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:")); break; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 12ff0a96..c8e8b008 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -343,6 +343,7 @@ typedef struct } ATTRPACK clientconfig_pak; #define MAXSERVERNAME 32 +#define MAXFILENEEDED 915 // This packet is too large typedef struct { @@ -364,7 +365,7 @@ typedef struct unsigned char mapmd5[16]; UINT8 actnum; UINT8 iszone; - UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h) + UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK serverinfo_pak; typedef struct diff --git a/src/d_main.c b/src/d_main.c index 6c3f9a42..65a2bc5a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" +#include "filesrch.h" // refreshdirmenu, mainwadstally #ifdef CMAKECONFIG #include "config.h" @@ -681,6 +682,8 @@ void D_SRB2Loop(void) realtics = entertic - oldentertics; oldentertics = entertic; + refreshdirmenu = 0; // not sure where to put this, here as good as any? + #ifdef DEBUGFILE if (!realtics) if (debugload) @@ -1253,23 +1256,38 @@ void D_SRB2Main(void) #ifndef DEVELOP // md5s last updated 12/14/14 // Check MD5s of autoloaded files - mainwads = 0; - W_VerifyFileMD5(mainwads, ASSET_HASH_SRB2_SRB); mainwads++; // srb2.srb/srb2.wad + W_VerifyFileMD5(mainwads, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad #ifdef USE_PATCH_DTA - W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_DTA); mainwads++; // patch.dta + W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_DTA); // patch.dta #endif - W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); mainwads++; // gfx.kart - W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); mainwads++; // chars.kart - W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); mainwads++; // maps.kart - //W_VerifyFileMD5(mainwads, ASSET_HASH_SOUNDS_KART); mainwads++; // sounds.kart - doesn't trigger modifiedgame, doesn't need an MD5...? + W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.kart + W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart + W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart + /*W_VerifyFileMD5(mainwads, ASSET_HASH_SOUNDS_KART);*/ // sounds.kart - doesn't trigger modifiedgame, doesn't need an MD5...? #ifdef USE_PATCH_KART - W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); mainwads++; // patch.kart + W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); // patch.kart #endif // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. #endif //ifndef DEVELOP + mainwads = 0; + mainwads++; // srb2.srb/srb2.wad +#ifdef USE_PATCH_DTA + mainwads++; // patch.dta +#endif + mainwads++; // gfx.kart + mainwads++; // chars.kart + mainwads++; // maps.kart + mainwads++; // sounds.kart +#ifdef USE_PATCH_KART + mainwads++; // patch.kart +#endif + mainwads++; // music.kart + + mainwadstally = packetsizetally; + cht_Init(); //---------------------------------------------------- READY SCREEN diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9b635cb0..304ff5e9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -38,6 +38,7 @@ #include "d_main.h" #include "m_random.h" #include "f_finale.h" +#include "filesrch.h" #include "mserv.h" #include "md5.h" #include "z_zone.h" @@ -824,6 +825,14 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_driftaxis3); CV_RegisterVar(&cv_driftaxis4); + // filesrch.c + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); + CV_RegisterVar(&cv_addons_md5); + CV_RegisterVar(&cv_addons_showall); + CV_RegisterVar(&cv_addons_search_type); + CV_RegisterVar(&cv_addons_search_case); + // WARNING: the order is important when initialising mouse2 // we need the mouse2port CV_RegisterVar(&cv_mouse2port); @@ -3749,25 +3758,12 @@ static void Command_Addfile(void) break; ++p; // check total packet size and no of files currently loaded + // See W_LoadWadFile in w_wad.c + if ((numwadfiles >= MAX_WADFILES) + || ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8))) { - size_t packetsize = 0; - serverinfo_pak *dummycheck = NULL; - - // Shut the compiler up. - (void)dummycheck; - - // See W_LoadWadFile in w_wad.c - for (i = 0; i < numwadfiles; i++) - packetsize += nameonlylength(wadfiles[i]->filename) + 22; - - packetsize += nameonlylength(fn) + 22; - - if ((numwadfiles >= MAX_WADFILES) - || (packetsize > sizeof(dummycheck->fileneeded))) - { - CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); - return; - } + CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); + return; } WRITESTRINGN(buf_p,p,240); @@ -3853,11 +3849,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) boolean kick = false; boolean toomany = false; INT32 i,j; - size_t packetsize = 0; - serverinfo_pak *dummycheck = NULL; - - // Shut the compiler up. - (void)dummycheck; READSTRINGN(*cp, filename, 240); READMEM(*cp, md5sum, 16); @@ -3884,13 +3875,8 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) } // See W_LoadWadFile in w_wad.c - for (i = 0; i < numwadfiles; i++) - packetsize += nameonlylength(wadfiles[i]->filename) + 22; - - packetsize += nameonlylength(filename) + 22; - if ((numwadfiles >= MAX_WADFILES) - || (packetsize > sizeof(dummycheck->fileneeded))) + || ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8))) toomany = true; else ncs = findfile(filename,md5sum,true); @@ -4059,6 +4045,9 @@ static void Command_Playintro_f(void) if (netgame) return; + if (dirmenu) + closefilemenu(true); + F_StartIntro(); } @@ -4768,6 +4757,9 @@ void Command_ExitGame_f(void) cv_debug = 0; emeralds = 0; + if (dirmenu) + closefilemenu(true); + if (!modeattacking) D_StartTitle(); } diff --git a/src/d_netfil.c b/src/d_netfil.c index 6742cfe2..7927c4ec 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -104,6 +104,7 @@ INT32 lastfilenum = -1; /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. + * Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c * */ UINT8 *PutFileNeeded(void) @@ -112,29 +113,22 @@ UINT8 *PutFileNeeded(void) UINT8 *p = netbuffer->u.serverinfo.fileneeded; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - size_t bytesused = 0; for (i = 0; i < numwadfiles; i++) { - // If it has only music/sound lumps, mark it as unimportant - if (W_VerifyNMUSlumps(wadfiles[i]->filename)) - filestatus = 0; - else - filestatus = 1; // Important + // If it has only music/sound lumps, don't put it in the list + if (!wadfiles[i]->important) + continue; + + filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS // Store in the upper four bits if (!cv_downloading.value) filestatus += (2 << 4); // Won't send - else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)) - filestatus += (0 << 4); // Won't send - else + else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)) filestatus += (1 << 4); // Will send if requested - - bytesused += (nameonlylength(wadfilename) + 22); - - // Don't write too far... - if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded)) - I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename); + // else + // filestatus += (0 << 4); -- Won't send, too big WRITEUINT8(p, filestatus); @@ -167,7 +161,6 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) { fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet filestatus = READUINT8(p); // The first byte is the file status - fileneeded[i].important = (UINT8)(filestatus & 3); fileneeded[i].willsend = (UINT8)(filestatus >> 4); fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size fileneeded[i].file = NULL; // The file isn't open yet @@ -197,7 +190,7 @@ boolean CL_CheckDownloadable(void) UINT8 i,dlstatus = 0; for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important) + if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { if (fileneeded[i].willsend == 1) continue; @@ -218,7 +211,7 @@ boolean CL_CheckDownloadable(void) // not downloadable, put reason in console CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n")); for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important) + if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10); @@ -271,7 +264,7 @@ boolean CL_SendRequestFile(void) for (i = 0; i < fileneedednum; i++) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN - && fileneeded[i].important && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) + && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) { I_Error("Attempted to download files that were not sendable"); } @@ -280,8 +273,7 @@ boolean CL_SendRequestFile(void) netbuffer->packettype = PT_REQUESTFILE; p = (char *)netbuffer->u.textcmd; for (i = 0; i < fileneedednum; i++) - if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) - && fileneeded[i].important) + if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) { totalfreespaceneeded += fileneeded[i].totalsize; nameonly(fileneeded[i].filename); @@ -339,10 +331,6 @@ INT32 CL_CheckFiles(void) INT32 ret = 1; size_t packetsize = 0; size_t filestoget = 0; - serverinfo_pak *dummycheck = NULL; - - // Shut the compiler up. - (void)dummycheck; // if (M_CheckParm("-nofiles")) // return 1; @@ -360,13 +348,7 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;) { - if (i < fileneedednum && !fileneeded[i].important) - { - // Eh whatever, don't care - ++i; - continue; - } - if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename)) + if (j < numwadfiles && !wadfiles[j]->important) { // Unimportant on our side. still don't care. ++j; @@ -392,8 +374,7 @@ INT32 CL_CheckFiles(void) } // See W_LoadWadFile in w_wad.c - for (i = 0; i < numwadfiles; i++) - packetsize += nameonlylength(wadfiles[i]->filename) + 22; + packetsize = packetsizetally; for (i = 1; i < fileneedednum; i++) { @@ -411,13 +392,13 @@ INT32 CL_CheckFiles(void) break; } } - if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important) + if (fileneeded[i].status != FS_NOTFOUND) continue; packetsize += nameonlylength(fileneeded[i].filename) + 22; if ((numwadfiles+filestoget >= MAX_WADFILES) - || (packetsize > sizeof(dummycheck->fileneeded))) + || (packetsize > MAXFILENEEDED*sizeof(UINT8))) return 3; filestoget++; @@ -449,27 +430,8 @@ void CL_LoadServerFiles(void) fileneeded[i].status = FS_OPEN; } else if (fileneeded[i].status == FS_MD5SUMBAD) - { - // If the file is marked important, don't even bother proceeding. - if (fileneeded[i].important) - I_Error("Wrong version of important file %s", fileneeded[i].filename); - - // If it isn't, no need to worry the user with a console message, - // although it can't hurt to put something in the debug file. - - // ...but wait a second. What if the local version is "important"? - if (!W_VerifyNMUSlumps(fileneeded[i].filename)) - I_Error("File %s should only contain music and sound effects!", - fileneeded[i].filename); - - // Okay, NOW we know it's safe. Whew. - P_AddWadFile(fileneeded[i].filename, NULL); - if (fileneeded[i].important) - G_SetGameModified(true); - fileneeded[i].status = FS_OPEN; - DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename)); - } - else if (fileneeded[i].important) + I_Error("Wrong version of file %s", fileneeded[i].filename); + else { const char *s; switch(fileneeded[i].status) @@ -939,10 +901,11 @@ void nameonly(char *s) { ns = &(s[j+1]); len = strlen(ns); - if (false) +#if 0 M_Memcpy(s, ns, len+1); - else +#else memmove(s, ns, len+1); +#endif return; } } diff --git a/src/d_netfil.h b/src/d_netfil.h index b9b7b2f2..6fdd0a8a 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -35,7 +35,6 @@ typedef enum typedef struct { - UINT8 important; UINT8 willsend; // Is the server willing to send it? char filename[MAX_WADPATH]; UINT8 md5sum[16]; diff --git a/src/filesrch.c b/src/filesrch.c index 2463e717..59868653 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -31,6 +31,8 @@ #include "filesrch.h" #include "d_netfil.h" #include "m_misc.h" +#include "z_zone.h" +#include "m_menu.h" // Addons_option_Onchange #if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX) @@ -255,6 +257,28 @@ readdir (DIR * dirp) return (struct dirent *) 0; } +/* + * rewinddir + * + * Makes the next readdir start from the beginning. + */ +int +rewinddir (DIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return -1; + } + + dirp->dd_stat = 0; + + return 0; +} + /* * closedir * @@ -285,6 +309,41 @@ closedir (DIR * dirp) return rc; } #endif + +static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"}, +#if 1 + {1, "HOME"}, {2, "SRB2"}, +#endif + {3, "CUSTOM"}, {0, NULL}}; + +consvar_t cv_addons_option = {"addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_folder = {"addons_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}}; +consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}}; +consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +char menupath[1024]; +size_t menupathindex[menudepth]; +size_t menudepthleft = menudepth; + +char menusearch[MAXSTRINGLENGTH+1]; + +char **dirmenu, **coredirmenu; // core only local for this file +size_t sizedirmenu, sizecoredirmenu; // ditto +size_t dir_on[menudepth]; +UINT8 refreshdirmenu = 0; +char *refreshdirname = NULL; + +size_t packetsizetally = 0; +size_t mainwadstally = 0; + #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) @@ -296,6 +355,25 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want completepath = false; return FS_NOTFOUND; } + +void closefilemenu(boolean validsize) +{ + (void)validsize; + return; +} + +void searchfilemenu(char *tempname) +{ + (void)tempname; + return; +} + +boolean preparefilemenu(boolean samedepth) +{ + (void)samedepth; + return false; +} + #elif defined (_WIN32_WCE) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) @@ -346,7 +424,27 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want #endif return FS_NOTFOUND; } + +void closefilemenu(boolean validsize) +{ + (void)validsize; + return; +} + +void searchfilemenu(char *tempname) +{ + (void)tempname; + return; +} + +boolean preparefilemenu(boolean samedepth) +{ + (void)samedepth; + return false; +} + #else + filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) { filestatus_t retval = FS_NOTFOUND; @@ -387,25 +485,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want { searchpath[searchpathindex[depthleft]]=0; dent = readdir(dirhandle[depthleft]); - if (dent) - strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); if (!dent) + { closedir(dirhandle[depthleft++]); - else if (dent->d_name[0]=='.' && + continue; + } + + if (dent->d_name[0]=='.' && (dent->d_name[1]=='\0' || (dent->d_name[1]=='.' && dent->d_name[2]=='\0'))) { // we don't want to scan uptree + continue; } - else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat - { - // was the file (re)moved? can't stat it - } + + // okay, now we actually want searchpath to incorporate d_name + strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); + + if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it else if (S_ISDIR(fsstat.st_mode) && depthleft) { - strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); searchpathindex[--depthleft] = strlen(searchpath) + 1; dirhandle[depthleft] = opendir(searchpath); if (!dirhandle[depthleft]) @@ -444,6 +546,361 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want free(searchname); free(searchpathindex); free(dirhandle); + return retval; } + +char exttable[NUM_EXT_TABLE][5] = { + ".txt", ".cfg", // exec + ".wad", /*".pk3",*/ ".soc", ".lua"}; // addfile + +char filenamebuf[MAX_WADFILES][MAX_WADPATH]; + + +static boolean filemenucmp(char *haystack, char *needle) +{ + static char localhaystack[128]; + strlcpy(localhaystack, haystack, 128); + if (!cv_addons_search_case.value) + strupr(localhaystack); + return ((cv_addons_search_type.value) + ? (strstr(localhaystack, needle) != 0) + : (!strncmp(localhaystack, needle, menusearch[0]))); +} + +void closefilemenu(boolean validsize) +{ + // search + if (dirmenu) + { + if (dirmenu != coredirmenu) + { + if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS)) + { + Z_Free(dirmenu[0]); + dirmenu[0] = NULL; + } + Z_Free(dirmenu); + } + dirmenu = NULL; + sizedirmenu = 0; + } + + if (coredirmenu) + { + // core + if (validsize) + { + for (; sizecoredirmenu > 0; sizecoredirmenu--) + { + Z_Free(coredirmenu[sizecoredirmenu-1]); + coredirmenu[sizecoredirmenu-1] = NULL; + } + } + else + sizecoredirmenu = 0; + + Z_Free(coredirmenu); + coredirmenu = NULL; + } + + if (refreshdirname) + Z_Free(refreshdirname); + refreshdirname = NULL; +} + +void searchfilemenu(char *tempname) +{ + size_t i, first; + char localmenusearch[MAXSTRINGLENGTH] = ""; + + if (dirmenu) + { + if (dirmenu != coredirmenu) + { + if (dirmenu[0] && ((UINT8)(dirmenu[0][DIR_TYPE]) == EXT_NORESULTS)) + { + Z_Free(dirmenu[0]); + dirmenu[0] = NULL; + } + //Z_Free(dirmenu); -- Z_Realloc later tho... + } + else + dirmenu = NULL; + } + + first = (((UINT8)(coredirmenu[0][DIR_TYPE]) == EXT_UP) ? 1 : 0); // skip UP... + + if (!menusearch[0]) + { + if (dirmenu) + Z_Free(dirmenu); + dirmenu = coredirmenu; + sizedirmenu = sizecoredirmenu; + + if (tempname) + { + for (i = first; i < sizedirmenu; i++) + { + if (!strcmp(dirmenu[i]+DIR_STRING, tempname)) + { + dir_on[menudepthleft] = i; + break; + } + } + + if (i == sizedirmenu) + dir_on[menudepthleft] = first; + + Z_Free(tempname); + } + + return; + } + + strcpy(localmenusearch, menusearch+1); + if (!cv_addons_search_case.value) + strupr(localmenusearch); + + sizedirmenu = 0; + for (i = first; i < sizecoredirmenu; i++) + { + if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) + sizedirmenu++; + } + + if (!sizedirmenu) // no results... + { + if ((!(dirmenu = Z_Realloc(dirmenu, sizeof(char *), PU_STATIC, NULL))) + || !(dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + sizedirmenu = 1; + dir_on[menudepthleft] = 0; + if (tempname) + Z_Free(tempname); + return; + } + + if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + + sizedirmenu = 0; + for (i = first; i < sizecoredirmenu; i++) + { + if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) + { + if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname)) + { + dir_on[menudepthleft] = sizedirmenu; + Z_Free(tempname); + tempname = NULL; + } + dirmenu[sizedirmenu++] = coredirmenu[i]; // pointer reuse + } + } + + if (tempname) + { + dir_on[menudepthleft] = first; + Z_Free(tempname); + } +} + +boolean preparefilemenu(boolean samedepth) +{ + DIR *dirhandle; + struct dirent *dent; + struct stat fsstat; + size_t pos = 0, folderpos = 0, numfolders = 0; + char *tempname = NULL; + + if (samedepth) + { + if (dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL + } + else + menusearch[0] = menusearch[1] = 0; // clear search + + if (!(dirhandle = opendir(menupath))) // get directory + { + closefilemenu(true); + return false; + } + + for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items + { + Z_Free(coredirmenu[sizecoredirmenu-1]); + coredirmenu[sizecoredirmenu-1] = NULL; + } + + while (true) + { + menupath[menupathindex[menudepthleft]] = 0; + dent = readdir(dirhandle); + + if (!dent) + break; + else if (dent->d_name[0]=='.' && + (dent->d_name[1]=='\0' || + (dent->d_name[1]=='.' && + dent->d_name[2]=='\0'))) + continue; // we don't want to scan uptree + + strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); + + if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it + else // is a file or directory + { + if (!S_ISDIR(fsstat.st_mode)) // file + { + if (!cv_addons_showall.value) + { + size_t len = strlen(dent->d_name)+1; + UINT8 ext; + for (ext = 0; ext < NUM_EXT_TABLE; ext++) + if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison + if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + } + } + else // directory + numfolders++; + + sizecoredirmenu++; + } + } + + if (!sizecoredirmenu) + { + closedir(dirhandle); + closefilemenu(false); + if (tempname) + Z_Free(tempname); + return false; + } + + if (menudepthleft != menudepth-1) // Make room for UP... + { + sizecoredirmenu++; + numfolders++; + folderpos++; + } + + if (dirmenu && dirmenu == coredirmenu) + dirmenu = NULL; + + if (!(coredirmenu = Z_Realloc(coredirmenu, sizecoredirmenu*sizeof(char *), PU_STATIC, NULL))) + { + closedir(dirhandle); // just in case + I_Error("Ran out of memory whilst preparing add-ons menu"); + } + + rewinddir(dirhandle); + + while ((pos+folderpos) < sizecoredirmenu) + { + menupath[menupathindex[menudepthleft]] = 0; + dent = readdir(dirhandle); + + if (!dent) + break; + else if (dent->d_name[0]=='.' && + (dent->d_name[1]=='\0' || + (dent->d_name[1]=='.' && + dent->d_name[2]=='\0'))) + continue; // we don't want to scan uptree + + strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); + + if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it + else // is a file or directory + { + char *temp; + size_t len = strlen(dent->d_name)+1; + UINT8 ext = EXT_FOLDER; + UINT8 folder; + + if (!S_ISDIR(fsstat.st_mode)) // file + { + if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention + for (; ext < NUM_EXT_TABLE; ext++) + if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison + if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file + ext += EXT_START; // moving to be appropriate position + + if (ext >= EXT_LOADSTART) + { + size_t i; + for (i = 0; i < numwadfiles; i++) + { + if (!filenamebuf[i][0]) + { + strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH); + filenamebuf[i][MAX_WADPATH - 1] = '\0'; + nameonly(filenamebuf[i]); + } + + if (strcmp(dent->d_name, filenamebuf[i])) + continue; + if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum)) + continue; + + ext |= EXT_LOADED; + } + } + else if (ext == EXT_TXT) + { + if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) + ext |= EXT_LOADED; + } + + if (!strcmp(dent->d_name, configfile)) + ext |= EXT_LOADED; + + folder = 0; + } + else // directory + len += (folder = 1); + + if (len > 255) + len = 255; + + if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + temp[DIR_TYPE] = ext; + temp[DIR_LEN] = (UINT8)(len); + strlcpy(temp+DIR_STRING, dent->d_name, len); + if (folder) + { + strcpy(temp+len, PATHSEP); + coredirmenu[folderpos++] = temp; + } + else + coredirmenu[numfolders + pos++] = temp; + } + } + + closedir(dirhandle); + + if ((menudepthleft != menudepth-1) // now for UP... entry + && !(coredirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + + menupath[menupathindex[menudepthleft]] = 0; + sizecoredirmenu = (numfolders+pos); // just in case things shrink between opening and rewind + + if (!sizecoredirmenu) + { + dir_on[menudepthleft] = 0; + closefilemenu(false); + return false; + } + + searchfilemenu(tempname); + + return true; +} + #endif diff --git a/src/filesrch.h b/src/filesrch.h index 33b148d4..51615308 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -6,6 +6,9 @@ #include "doomdef.h" #include "d_netfil.h" +#include "m_menu.h" // MAXSTRINGLENGTH + +extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type; /** \brief The filesearch function @@ -25,4 +28,68 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth); +#define menudepth 20 + +extern char menupath[1024]; +extern size_t menupathindex[menudepth]; +extern size_t menudepthleft; + +extern char menusearch[MAXSTRINGLENGTH+1]; + +extern char **dirmenu; +extern size_t sizedirmenu; +extern size_t dir_on[menudepth]; +extern UINT8 refreshdirmenu; +extern char *refreshdirname; + +extern size_t packetsizetally; +extern size_t mainwadstally; + +typedef enum +{ + EXT_FOLDER = 0, + EXT_UP, + EXT_NORESULTS, + EXT_START, + EXT_TXT = EXT_START, + EXT_CFG, + EXT_LOADSTART, + EXT_WAD = EXT_LOADSTART, + //EXT_PK3, + EXT_SOC, + EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt + NUM_EXT, + NUM_EXT_TABLE = NUM_EXT-EXT_START, + EXT_LOADED = 0x80 + /* + obviously there can only be 0x7F supported extensions in + addons menu because we're cramming this into a char out of + laziness/easy memory allocation (what's the difference?) + and have stolen a bit to show whether it's loaded or not + in practice the size of the data type is probably overkill + toast 02/05/17 + */ +} ext_enum; + +typedef enum +{ + DIR_TYPE = 0, + DIR_LEN, + DIR_STRING +} dirname_enum; + +typedef enum +{ + REFRESHDIR_NORMAL = 1, + REFRESHDIR_ADDFILE = 2, + REFRESHDIR_WARNING = 4, + REFRESHDIR_ERROR = 8, + REFRESHDIR_NOTLOADED = 16, + REFRESHDIR_MAX = 32 +} refreshdir_enum; + +void closefilemenu(boolean validsize); +void searchfilemenu(char *tempname); +boolean preparefilemenu(boolean samedepth); + #endif // __FILESRCH_H__ diff --git a/src/m_menu.c b/src/m_menu.c index eb8123e9..5ba5d81b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -33,6 +33,9 @@ #include "s_sound.h" #include "i_system.h" +// Addfile +#include "filesrch.h" + #include "v_video.h" #include "i_video.h" #include "keys.h" @@ -67,6 +70,10 @@ int snprintf(char *str, size_t n, const char *fmt, ...); //int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); #endif +#if defined (__GNUC__) && (__GNUC__ >= 4) +#define FIXUPO0 +#endif + #define SKULLXOFF -32 #define LINEHEIGHT 16 #define STRINGHEIGHT 8 @@ -74,7 +81,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #define SMALLLINEHEIGHT 8 #define SLIDER_RANGE 10 #define SLIDER_WIDTH (8*SLIDER_RANGE+6) -#define MAXSTRINGLENGTH 32 #define SERVERS_PER_PAGE 11 typedef enum @@ -206,6 +212,8 @@ menu_t MessageDef; menu_t SPauseDef; +#define lsheadingheight 16 + // Sky Room //static void M_CustomLevelSelect(INT32 choice); //static void M_CustomWarp(INT32 choice); @@ -321,9 +329,16 @@ menu_t OP_MonitorToggleDef; static void M_ScreenshotOptions(INT32 choice); static void M_EraseData(INT32 choice); +static void M_Addons(INT32 choice); +static void M_AddonsOptions(INT32 choice); +static patch_t *addonsp[NUM_EXT+5]; + +#define numaddonsshown 4 + // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawCenteredMenu(void); +static void M_DrawAddons(void); static void M_DrawSkyRoom(void); static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); @@ -359,6 +374,7 @@ static boolean M_CancelConnect(void); #endif static boolean M_ExitPandorasBox(void); static boolean M_QuitMultiPlayerMenu(void); +static void M_HandleAddons(INT32 choice); static void M_HandleSoundTest(INT32 choice); static void M_HandleImageDef(INT32 choice); static void M_HandleLoadSave(INT32 choice); @@ -479,15 +495,16 @@ static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDEN|CV_CALL, dummystaf // --------- static menuitem_t MainMenu[] = { - {IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_UnlockChecklistDef, 84}, - {IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 92}, + {IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_UnlockChecklistDef, 76}, + {IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84}, #ifdef NONET M_StartSplitServerMenu - {IT_CALL |IT_STRING, NULL, "Splitscreen", M_StartSplitServerMenu,100}, + {IT_CALL |IT_STRING, NULL, "Splitscreen", M_StartSplitServerMenu, 92}, #else - {IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 100}, + {IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 92}, #endif - {IT_CALL |IT_STRING, NULL, "Options", M_Options, 108}, + {IT_CALL |IT_STRING, NULL, "Options", M_Options, 100}, + {IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108}, {IT_CALL |IT_STRING, NULL, "Quit Game", M_QuitSRB2, 116}, }; @@ -497,9 +514,15 @@ typedef enum singleplr, multiplr, options, + addons, quitdoom } main_e; +static menuitem_t MISC_AddonsMenu[] = +{ + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func +}; + // --------------------------------- // Pause Menu Mode Attacking Edition // --------------------------------- @@ -522,8 +545,9 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, + {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, + {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, + {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, {IT_CALL | IT_STRING, NULL, "P1 Setup...", M_SetupMultiPlayer, 48}, // splitscreen @@ -546,7 +570,8 @@ static menuitem_t MPauseMenu[] = typedef enum { - mpause_scramble = 0, + mpause_addons = 0, + mpause_scramble, mpause_switchmap, mpause_continue, @@ -1054,9 +1079,10 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU|IT_STRING, NULL, "Gameplay Options...", &OP_GameOptionsDef, 90}, {IT_SUBMENU|IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 100}, + {IT_STRING|IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 110}, - {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 120}, - {IT_SUBMENU|IT_STRING, NULL, "Erase Data...", &OP_EraseDataDef, 130}, + {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 130}, + {IT_SUBMENU|IT_STRING, NULL, "Erase Data...", &OP_EraseDataDef, 140}, }; static menuitem_t OP_ControlsMenu[] = @@ -1413,6 +1439,24 @@ static menuitem_t OP_EraseDataMenu[] = {IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40}, }; +static menuitem_t OP_AddonsOptionsMenu[] = +{ + {IT_HEADER, NULL, "Menu", NULL, 0}, + {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 20}, + {IT_STRING|IT_CVAR, NULL, "Identify add-ons via", &cv_addons_md5, 48}, + {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 58}, + + {IT_HEADER, NULL, "Search", NULL, 76}, + {IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 86}, + {IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 96}, +}; + +enum +{ + op_addons_folder = 2, +}; + static menuitem_t OP_HUDOptionsMenu[] = { {IT_STRING | IT_CVAR, NULL, "Show HUD (F3)", &cv_showhud, 10}, @@ -1549,6 +1593,18 @@ static menuitem_t OP_MonitorToggleMenu[] = // Main Menu and related menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72); +menu_t MISC_AddonsDef = +{ + NULL, + sizeof (MISC_AddonsMenu)/sizeof (menuitem_t), + &MainDef, + MISC_AddonsMenu, + M_DrawAddons, + 50, 28, + 0, + NULL +}; + menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); @@ -2004,7 +2060,8 @@ menu_t OP_OpenGLColorDef = #endif //menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_MainDef, 30, 30); -menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_MainDef, 60, 30); +menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_MainDef, 30, 30); +menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_MainDef, 30, 30); // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE @@ -2223,6 +2280,12 @@ void Moviemode_mode_Onchange(void) OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR; } +void Addons_option_Onchange(void) +{ + OP_AddonsOptionsMenu[op_addons_folder].status = + (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== @@ -2877,6 +2940,7 @@ void M_StartControlPanel(void) else // multiplayer { MPauseMenu[mpause_switchmap].status = IT_DISABLED; + MPauseMenu[mpause_addons].status = IT_DISABLED; MPauseMenu[mpause_scramble].status = IT_DISABLED; MPauseMenu[mpause_psetupsplit].status = IT_DISABLED; MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED; @@ -2897,6 +2961,7 @@ void M_StartControlPanel(void) if ((server || IsPlayerAdmin(consoleplayer))) { MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL; + MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL; if (G_GametypeHasTeams()) MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU; } @@ -4215,6 +4280,521 @@ static void M_HandleImageDef(INT32 choice) // MISC MAIN MENU OPTIONS // ====================== +static void M_AddonsOptions(INT32 choice) +{ + (void)choice; + Addons_option_Onchange(); + + M_SetupNextMenu(&OP_AddonsOptionsDef); +} + +#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!" +#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!" + +static void M_Addons(INT32 choice) +{ + const char *pathname = "."; + + (void)choice; + +#if 1 + if (cv_addons_option.value == 0) + pathname = usehome ? srb2home : srb2path; + else if (cv_addons_option.value == 1) + pathname = srb2home; + else if (cv_addons_option.value == 2) + pathname = srb2path; + else +#endif + if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0') + pathname = cv_addons_folder.string; + + strlcpy(menupath, pathname, 1024); + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; + + if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0]) + { + menupath[menupathindex[menudepthleft]-1] = PATHSEP[0]; + menupath[menupathindex[menudepthleft]] = 0; + } + else + --menupathindex[menudepthleft]; + + if (!preparefilemenu(false)) + { + M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n", (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)),NULL,MM_NOTHING); + return; + } + else + dir_on[menudepthleft] = 0; + + if (addonsp[0]) // never going to have some provided but not all, saves individually checking + { + size_t i; + for (i = 0; i < NUM_EXT+5; i++) + W_UnlockCachedPatch(addonsp[i]); + } + + addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); + addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); + addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC); + addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); + addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); + addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); + //addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); + addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); + addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); + addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC); + addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_STATIC); + addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_STATIC); + addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC); + addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_STATIC); + + MISC_AddonsDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_AddonsDef); +} + +#define width 4 +#define vpadding 27 +#define h (BASEVIDHEIGHT-(2*vpadding)) +#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker +static void M_DrawTemperature(INT32 x, fixed_t t) +{ + INT32 y; + + // bounds check + if (t > FRACUNIT) + t = FRACUNIT; + /*else if (t < 0) -- not needed + t = 0;*/ + + // scale + if (t > 1) + 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); + + // bar itself + y = h; + if (t) + for (t = h - t; y > 0; y--) + { + UINT8 colours[NUMCOLOURS] = {135, 133, 92, 77, 114, 178, 161, 162}; + UINT8 c; + if (y <= t) break; + if (y+vpadding >= BASEVIDHEIGHT/2) + c = 185; + else + c = colours[(NUMCOLOURS*(y-1))/(h/2)]; + V_DrawFill(x, y-1 + vpadding, width, 1, c); + } + + // fill the rest of the backing + if (y) + V_DrawFill(x, vpadding, width, y, 30); +} +#undef width +#undef vpadding +#undef h +#undef NUMCOLOURS + +static char *M_AddonsHeaderPath(void) +{ + UINT32 len; + static char header[1024]; + + strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024); + len = strlen(header); + if (len > 34) + { + len = len-34; + header[len] = header[len+1] = header[len+2] = '.'; + } + else + len = 0; + + return header+len; +} + +#define UNEXIST S_StartSound(NULL, sfx_lose);\ + M_SetupNextMenu(MISC_AddonsDef.prevMenu);\ + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) + +#define CLEARNAME Z_Free(refreshdirname);\ + refreshdirname = NULL + +static void M_AddonsClearName(INT32 choice) +{ + CLEARNAME; + M_StopMessage(choice); +} + +// returns whether to do message draw +static boolean M_AddonsRefresh(void) +{ + if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) + { + UNEXIST; + return true; + } + + if (refreshdirmenu & REFRESHDIR_ADDFILE) + { + char *message = NULL; + + if (refreshdirmenu & REFRESHDIR_NOTLOADED) + { + S_StartSound(NULL, sfx_lose); + if (refreshdirmenu & REFRESHDIR_MAX) + message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + else + message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + } + else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) + { + S_StartSound(NULL, sfx_skid); + message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")); + } + + if (message) + { + M_StartMessage(message,M_AddonsClearName,MM_EVENTHANDLER); + return true; + } + + S_StartSound(NULL, sfx_strpst); + CLEARNAME; + } + + return false; +} + +#ifdef FIXUPO0 +#pragma GCC optimize ("0") +#endif + +static void M_DrawAddons(void) +{ + INT32 x, y; + ssize_t i, max; + const UINT8 *flashcol = NULL; + + // hack - need to refresh at end of frame to handle addfile... + if (refreshdirmenu & M_AddonsRefresh()) + { + M_DrawMessageMenu(); + return; + } + + if (Playing()) + V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); + else + V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)); + + if (numwadfiles <= mainwads+1) + y = 0; + else if (numwadfiles >= MAX_WADFILES) + y = FRACUNIT; + else + { + x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< y) + y = x; + if (y > FRACUNIT) // happens because of how we're shrinkin' it a little + y = FRACUNIT; + } + + M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y); + + // DRAW MENU + x = currentMenu->x; + y = currentMenu->y + 1; + + 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), 1, V_GetStringColormap(highlightflags)[120]); + V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 30); + V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 30); + + V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1), 239); + + // get bottom... + max = dir_on[menudepthleft] + numaddonsshown + 1; + if (max > (ssize_t)sizedirmenu) + max = sizedirmenu; + + // then top... + i = max - (2*numaddonsshown + 1); + + // then adjust! + if (i < 0) + { + if ((max -= i) > (ssize_t)sizedirmenu) + max = sizedirmenu; + i = 0; + } + + if (i != 0) + V_DrawString(19, y+4 - (skullAnimCounter/5), highlightflags, "\x1A"); + + if (skullAnimCounter < 4) + flashcol = V_GetStringColormap(highlightflags); + + for (; i < max; i++) + { + UINT32 flags = V_ALLOWLOWERCASE; + if (y > BASEVIDHEIGHT) break; + if (dirmenu[i]) +#define type (UINT8)(dirmenu[i][DIR_TYPE]) + { + if (type & EXT_LOADED) + flags |= V_TRANSLUCENT; + + V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); + + if (type & EXT_LOADED) + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]); + + if ((size_t)i == dir_on[menudepthleft]) + { + V_DrawFixedPatch((x-(16+4))< (charsonside*2 + 3)) + V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1))); +#undef charsonside + else + V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING); + } +#undef type + y += 16; + } + + if (max != (ssize_t)sizedirmenu) + V_DrawString(19, y-12 + (skullAnimCounter/5), highlightflags, "\x1B"); + + y = BASEVIDHEIGHT - currentMenu->y + 1; + + M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); + if (menusearch[0]) + V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); + else + V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search..."); + if (skullAnimCounter < 4) + V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8, + '_' | 0x80, false); + + x -= (21 + 5 + 16); + V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]); + + x = BASEVIDWIDTH - x - 16; + V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); + + if (modifiedgame) + V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]); +} + +#ifdef FIXUPO0 +#pragma GCC reset_options +#endif + +static void M_AddonExec(INT32 ch) +{ + if (ch != 'y' && ch != KEY_ENTER) + return; + + S_StartSound(NULL, sfx_zoom); + COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); +} + +#define len menusearch[0] +static boolean M_ChangeStringAddons(INT32 choice) +{ + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + + switch (choice) + { + case KEY_DEL: + if (len) + { + len = menusearch[1] = 0; + return true; + } + break; + case KEY_BACKSPACE: + if (len) + { + menusearch[1+--len] = 0; + return true; + } + break; + default: + if (choice >= 32 && choice <= 127) + { + if (len < MAXSTRINGLENGTH - 1) + { + menusearch[1+len++] = (char)choice; + menusearch[1+len] = 0; + return true; + } + } + break; + } + return false; +} +#undef len + +static void M_HandleAddons(INT32 choice) +{ + boolean exitmenu = false; // exit to previous menu + + if (M_ChangeStringAddons(choice)) + { + char *tempname = NULL; + if (dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL + searchfilemenu(tempname); + /*if (!preparefilemenu(true)) + { + UNEXIST; + return; + }*/ + } + + switch (choice) + { + case KEY_DOWNARROW: + if (dir_on[menudepthleft] < sizedirmenu-1) + dir_on[menudepthleft]++; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_UPARROW: + if (dir_on[menudepthleft]) + dir_on[menudepthleft]--; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_PGDN: + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--) + dir_on[menudepthleft]++; + } + S_StartSound(NULL, sfx_menu1); + break; + case KEY_PGUP: + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--) + dir_on[menudepthleft]--; + } + S_StartSound(NULL, sfx_menu1); + break; + case KEY_ENTER: + { + boolean refresh = true; + if (!dirmenu[dir_on[menudepthleft]]) + S_StartSound(NULL, sfx_lose); + else + { + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + if (menudepthleft) + { + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false)) + { + S_StartSound(NULL, sfx_skid); + M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true)) + { + UNEXIST; + return; + } + } + else + { + S_StartSound(NULL, sfx_menu1); + dir_on[menudepthleft] = 1; + } + refresh = false; + } + else + { + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; + } + break; + case EXT_UP: + S_StartSound(NULL, sfx_menu1); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false)) + { + UNEXIST; + return; + } + break; + case EXT_TXT: + M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO); + break; + case EXT_CFG: + M_AddonExec(KEY_ENTER); + break; + case EXT_LUA: +#ifndef HAVE_BLUA + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("%c%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); + break; +#endif + // else intentional fallthrough + case EXT_SOC: + case EXT_WAD: + //case EXT_PK3: + COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + break; + default: + S_StartSound(NULL, sfx_lose); + } + } + if (refresh) + refreshdirmenu |= REFRESHDIR_NORMAL; + } + break; + + case KEY_ESCAPE: + exitmenu = true; + break; + + default: + break; + } + if (exitmenu) + { + closefilemenu(true); + + // secrets disabled by addfile... + MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + } +} + static void M_PandorasBox(INT32 choice) { (void)choice; @@ -4317,8 +4897,8 @@ static void M_Options(INT32 choice) OP_MainMenu[5].status = OP_MainMenu[6].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); // if the player is playing _at all_, disable the erase data & credits options - OP_MainMenu[7].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); - OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); + OP_MainMenu[9].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); OP_MainDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_MainDef); diff --git a/src/m_menu.h b/src/m_menu.h index 51559489..cb083b0e 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -124,6 +124,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); #define IT_HEADER (IT_SPACE +IT_HEADERTEXT) #define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS) +#define MAXSTRINGLENGTH 32 + typedef union { struct menu_s *submenu; // IT_SUBMENU @@ -223,6 +225,9 @@ void M_CheatActivationResponder(INT32 ch); void Moviemode_mode_Onchange(void); void Screenshot_option_Onchange(void); +// Addons menu updating +void Addons_option_Onchange(void); + // These defines make it a little easier to make menus #define DEFAULTMENUSTYLE(header, source, prev, x, y)\ {\ diff --git a/src/p_setup.c b/src/p_setup.c index f4c28663..704df2a5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -54,6 +54,8 @@ #include "v_video.h" +#include "filesrch.h" // refreshdirmenu + // wipes #include "f_finale.h" @@ -3126,6 +3128,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX) { + refreshdirmenu |= REFRESHDIR_NOTLOADED; CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename); return false; } diff --git a/src/w_wad.c b/src/w_wad.c index 3a828559..c4850905 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -34,6 +34,8 @@ #include "z_zone.h" #include "fastcmp.h" +#include "filesrch.h" + #include "i_video.h" // rendermode #include "d_netfil.h" #include "dehacked.h" @@ -294,12 +296,22 @@ UINT16 W_LoadWadFile(const char *filename) UINT32 numlumps; size_t i; INT32 compressed = 0; - size_t packetsize = 0; - serverinfo_pak *dummycheck = NULL; + size_t packetsize; UINT8 md5sum[16]; + boolean important; - // Shut the compiler up. - (void)dummycheck; + if (!(refreshdirmenu & REFRESHDIR_ADDFILE)) + refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier + + if (refreshdirname) + Z_Free(refreshdirname); + if (dirmenu) + { + refreshdirname = Z_StrDup(filename); + nameonly(refreshdirname); + } + else + refreshdirname = NULL; //CONS_Debug(DBG_SETUP, "Loading %s\n", filename); // @@ -308,6 +320,7 @@ UINT16 W_LoadWadFile(const char *filename) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; return INT16_MAX; } @@ -317,21 +330,21 @@ UINT16 W_LoadWadFile(const char *filename) // Check if wad files will overflow fileneededbuffer. Only the filename part // is send in the packet; cf. - for (i = 0; i < numwadfiles; i++) + // see PutFileNeeded in d_netfil.c + if ((important = !W_VerifyNMUSlumps(filename))) { - packetsize += nameonlylength(wadfiles[i]->filename); - packetsize += 22; // MD5, etc. - } + packetsize = packetsizetally + nameonlylength(filename) + 22; - packetsize += nameonlylength(filename); - packetsize += 22; + if (packetsize > MAXFILENEEDED*sizeof(UINT8)) + { + CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; + if (handle) + fclose(handle); + return INT16_MAX; + } - if (packetsize > sizeof(dummycheck->fileneeded)) - { - CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); - if (handle) - fclose(handle); - return INT16_MAX; + packetsizetally = packetsize; } // detect dehacked file with the "soc" extension @@ -470,6 +483,7 @@ UINT16 W_LoadWadFile(const char *filename) wadfile->handle = handle; wadfile->numlumps = (UINT16)numlumps; wadfile->lumpinfo = lumpinfo; + wadfile->important = important; fseek(handle, 0, SEEK_END); wadfile->filesize = (unsigned)ftell(handle); @@ -1217,19 +1231,27 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, */ int W_VerifyNMUSlumps(const char *filename) { - // MIDI, MOD/S3M/IT/XM/OGG/MP3/WAV, WAVE SFX - // ENDOOM text and palette lumps lumpchecklist_t NMUSlist[] = { - {"D_", 2}, - {"O_", 2}, - {"DS", 2}, - {"ENDOOM", 6}, - {"PLAYPAL", 7}, - {"COLORMAP", 8}, - {"PAL", 3}, - {"CLM", 3}, - {"TRANS", 5}, + {"D_", 2}, // MIDI music + {"O_", 2}, // Digital music + {"DS", 2}, // Sound effects + + {"ENDOOM", 6}, // ENDOOM text lump + {"PLAYPAL", 7}, // Palette + {"COLORMAP", 8}, // Colormap + {"PAL", 3}, // Palette changes + {"CLM", 3}, // Colormap changes + {"TRANS", 5}, // Translucency map + + {"LTFNT", 5}, // Level title font changes + {"STCFN", 5}, // Console font changes + {"TNYFN", 5}, // Tiny console font changes + {"MKFNT", 5}, // Kart font changes + + {"M_", 2}, // Menu changes + {"K_", 2}, // Kart graphic changes + {NULL, 0}, }; return W_VerifyFile(filename, NMUSlist, false); diff --git a/src/w_wad.h b/src/w_wad.h index f7ea64a5..8da22804 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -70,6 +70,7 @@ typedef struct wadfile_s FILE *handle; UINT32 filesize; // for network UINT8 md5sum[16]; + boolean important; } wadfile_t; #define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word From 0776460643463490c475eb22f26bc0efb89ff3f6 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Aug 2018 12:50:25 +0100 Subject: [PATCH 02/37] * Make some minor performance improvements. * Make the I_Errors in filesrch.c more descriptive. * Fix up the loading of sounds.kart such that it has SOME protection against being loaded with game-modifying lumps. * SERIOUSLY fix up the MD5/mainwads++ section in D_SRB2Main, since 1) I broke it and 2) it was already a little broken in the first place but we just didn't notice it because #ifndef DEVELOP. --- src/d_main.c | 68 +++++++++++++++++++++----------------------------- src/filesrch.c | 16 ++++++------ src/v_video.c | 7 ++++++ 3 files changed, 43 insertions(+), 48 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 65a2bc5a..f2063861 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -957,43 +957,29 @@ static void IdentifyVersion(void) D_AddFile(va(pandf,srb2waddir,"patch.dta")); #endif +#define MUSICTEST(str) \ + {\ + const char *musicpath = va(pandf,srb2waddir,str);\ + int ms = W_VerifyNMUSlumps(musicpath); \ + if (ms == 1) \ + D_AddFile(musicpath); \ + else if (ms == 0) \ + I_Error("File "str" has been modified with non-music/sound lumps"); \ + } + // SRB2kart - Add graphics (temp) // The command for md5 checks is "W_VerifyFileMD5" - looks for ASSET_HASH_SRB2_SRB in config.h.in D_AddFile(va(pandf,srb2waddir,"gfx.kart")); D_AddFile(va(pandf,srb2waddir,"chars.kart")); D_AddFile(va(pandf,srb2waddir,"maps.kart")); - D_AddFile(va(pandf,srb2waddir,"sounds.kart")); + //D_AddFile(va(pandf,srb2waddir,"sounds.kart")); + MUSICTEST("sounds.kart") #ifdef USE_PATCH_KART D_AddFile(va(pandf,srb2waddir,"patch.kart")); #endif -#if !defined (HAVE_SDL) || defined (HAVE_MIXER) - { -#if defined (DC) && 0 - const char *musicfile = "music_dc.dta"; -#else - const char *musicfile = "music.dta"; -#endif - const char *kmusicfile; - const char *musicpath = va(pandf,srb2waddir,musicfile); - const char *kmusicpath; - int ms = W_VerifyNMUSlumps(musicpath); // Don't forget the music! - int kms; - if (ms == 1) - D_AddFile(musicpath); - else if (ms == 0) - I_Error("File %s has been modified with non-music lumps",musicfile); - - kmusicfile = "music.kart"; - kmusicpath = va(pandf,srb2waddir,kmusicfile); - kms = W_VerifyNMUSlumps(kmusicpath); // kill me now - - if (kms == 1) - D_AddFile(kmusicpath); - else if (kms == 0) - I_Error("File %s has been modified with non-music lumps",kmusicfile); - } -#endif + MUSICTEST("music.dta") + MUSICTEST("music.kart") } /* ======================================================================== */ @@ -1253,27 +1239,27 @@ void D_SRB2Main(void) #endif D_CleanFile(); + mainwads = 0; + #ifndef DEVELOP // md5s last updated 12/14/14 // Check MD5s of autoloaded files W_VerifyFileMD5(mainwads, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad #ifdef USE_PATCH_DTA - W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_DTA); // patch.dta + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_DTA); // patch.dta #endif - W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.kart - W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart - W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart - /*W_VerifyFileMD5(mainwads, ASSET_HASH_SOUNDS_KART);*/ // sounds.kart - doesn't trigger modifiedgame, doesn't need an MD5...? + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.kart + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart + mainwads++; //W_VerifyFileMD5(5, ASSET_HASH_SOUNDS_KART); -- sounds.kart - doesn't trigger modifiedgame, doesn't need an MD5...? #ifdef USE_PATCH_KART - W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); // patch.kart + mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); // patch.kart #endif - - // don't check music.dta because people like to modify it, and it doesn't matter if they do + mainwads++; // music.dta + mainwads++; // music.kart + // don't check music.dta or kart because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. -#endif //ifndef DEVELOP - - mainwads = 0; - mainwads++; // srb2.srb/srb2.wad +#else #ifdef USE_PATCH_DTA mainwads++; // patch.dta #endif @@ -1284,7 +1270,9 @@ void D_SRB2Main(void) #ifdef USE_PATCH_KART mainwads++; // patch.kart #endif + mainwads++; // music.dta mainwads++; // music.kart +#endif //ifndef DEVELOP mainwadstally = packetsizetally; diff --git a/src/filesrch.c b/src/filesrch.c index 59868653..94c1190b 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -563,9 +563,9 @@ static boolean filemenucmp(char *haystack, char *needle) strlcpy(localhaystack, haystack, 128); if (!cv_addons_search_case.value) strupr(localhaystack); - return ((cv_addons_search_type.value) - ? (strstr(localhaystack, needle) != 0) - : (!strncmp(localhaystack, needle, menusearch[0]))); + if (cv_addons_search_type.value) + return (strstr(localhaystack, needle) != 0); + return (!strncmp(localhaystack, needle, menusearch[0])); } void closefilemenu(boolean validsize) @@ -673,7 +673,7 @@ void searchfilemenu(char *tempname) { if ((!(dirmenu = Z_Realloc(dirmenu, sizeof(char *), PU_STATIC, NULL))) || !(dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)))) - I_Error("Ran out of memory whilst preparing add-ons menu"); + I_Error("searchfilemenu(): could not create \"No results...\"."); sizedirmenu = 1; dir_on[menudepthleft] = 0; if (tempname) @@ -682,7 +682,7 @@ void searchfilemenu(char *tempname) } if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) - I_Error("Ran out of memory whilst preparing add-ons menu"); + I_Error("searchfilemenu(): could not reallocate dirmenu."); sizedirmenu = 0; for (i = first; i < sizecoredirmenu; i++) @@ -793,7 +793,7 @@ boolean preparefilemenu(boolean samedepth) if (!(coredirmenu = Z_Realloc(coredirmenu, sizecoredirmenu*sizeof(char *), PU_STATIC, NULL))) { closedir(dirhandle); // just in case - I_Error("Ran out of memory whilst preparing add-ons menu"); + I_Error("preparefilemenu(): could not reallocate coredirmenu."); } rewinddir(dirhandle); @@ -868,7 +868,7 @@ boolean preparefilemenu(boolean samedepth) len = 255; if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL))) - I_Error("Ran out of memory whilst preparing add-ons menu"); + I_Error("preparefilemenu(): could not create file entry."); temp[DIR_TYPE] = ext; temp[DIR_LEN] = (UINT8)(len); strlcpy(temp+DIR_STRING, dent->d_name, len); @@ -886,7 +886,7 @@ boolean preparefilemenu(boolean samedepth) if ((menudepthleft != menudepth-1) // now for UP... entry && !(coredirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)))) - I_Error("Ran out of memory whilst preparing add-ons menu"); + I_Error("searchfilemenu(): could not create \"UP...\"."); menupath[menupathindex[menudepthleft]] = 0; sizecoredirmenu = (numfolders+pos); // just in case things shrink between opening and rewind diff --git a/src/v_video.c b/src/v_video.c index e39663a7..8c8bd342 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1250,6 +1250,7 @@ void V_DrawFadeConsBack(INT32 plines) // const UINT8 *V_GetStringColormap(INT32 colorflags) { +#if 0 // perfect switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT) { case 1: // 0x81, purple @@ -1271,6 +1272,12 @@ const UINT8 *V_GetStringColormap(INT32 colorflags) default: // reset return NULL; } +#else // optimised + colorflags = ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT); + if (!colorflags || colorflags > 8) // INT32 is signed, but V_CHARCOLORMASK is a very restrictive mask. + return NULL; + return (purplemap+((colorflags-1)<<8)); +#endif } // Writes a single character (draw WHITE if bit 7 set) From 7a758708c63ac9df92d07fcb7879eca431228fd3 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Aug 2018 14:19:08 +0100 Subject: [PATCH 03/37] * Add support for .kart files. * Wrap behind-the-scenes `addfile/exec` contents in quotation marks to allow for files with spaces in them. --- src/filesrch.c | 10 +++++----- src/filesrch.h | 1 + src/m_menu.c | 6 ++++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 94c1190b..e1e2b39d 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -550,9 +550,9 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want return retval; } -char exttable[NUM_EXT_TABLE][5] = { - ".txt", ".cfg", // exec - ".wad", /*".pk3",*/ ".soc", ".lua"}; // addfile +char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two) + "\5.txt", "\5.cfg", // exec + "\5.wad", "\6.kart", /*"\5.pk3",*/ "\5.soc", "\5.lua"}; // addfile char filenamebuf[MAX_WADFILES][MAX_WADPATH]; @@ -760,7 +760,7 @@ boolean preparefilemenu(boolean samedepth) size_t len = strlen(dent->d_name)+1; UINT8 ext; for (ext = 0; ext < NUM_EXT_TABLE; ext++) - if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison + if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file } } @@ -826,7 +826,7 @@ boolean preparefilemenu(boolean samedepth) { if (!((numfolders+pos) < sizecoredirmenu)) continue; // crash prevention for (; ext < NUM_EXT_TABLE; ext++) - if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison + if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file ext += EXT_START; // moving to be appropriate position diff --git a/src/filesrch.h b/src/filesrch.h index 51615308..75fd70af 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -55,6 +55,7 @@ typedef enum EXT_CFG, EXT_LOADSTART, EXT_WAD = EXT_LOADSTART, + EXT_KART, //EXT_PK3, EXT_SOC, EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt diff --git a/src/m_menu.c b/src/m_menu.c index 5ba5d81b..dcfe4fb8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4341,6 +4341,7 @@ static void M_Addons(INT32 choice) addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); + addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_STATIC); //addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); @@ -4610,7 +4611,7 @@ static void M_AddonExec(INT32 ch) return; S_StartSound(NULL, sfx_zoom); - COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + COM_BufAddText(va("exec \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); } #define len menusearch[0] @@ -4762,8 +4763,9 @@ static void M_HandleAddons(INT32 choice) // else intentional fallthrough case EXT_SOC: case EXT_WAD: + case EXT_KART: //case EXT_PK3: - COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); break; default: S_StartSound(NULL, sfx_lose); From 4de68f7fe2e10346c3fe9a43bf00ce2606bbb545 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 6 Sep 2018 22:17:29 +0100 Subject: [PATCH 04/37] Dropping items! * Shield Drop... * Whatever you've got orbiting or trailing you, DROP THEM WHERE THEY STAND. (Except for the ghost sink. That one's OK.) * Pops your Thunder Shield. * Happens upon ANY hit, except for deathpits. * HUD Drop... * Also does the above, except for the Thunder Shield thing. * If there's any item left in your item box, pop it out as a little hovering, rotating Minecraft item! * You can pick up the Minecraft item by driving over it if your item box is sufficiently empty, or the item which is contained within it is of the same type. * Happens upon Size Down and battle elimination. * Can also be forced on with `cv_kartdebughuddrop on`! * Some other random stuff. * Fix a bunch of `a->scale = b`'s into `P_SetScale(a, b)` form, for maximum validity. * Make K_CleanHnextList and K_UpdateHnextList one function, since they only differed by one continue clause (and the type of their input parameter). * Allow shrunken players to pick up item boxes again. * Fix MF_NOCLIPTHING. (Gonna pass this fix to vanilla when I get the chance, too.) * Break NiGHTS a little through my machinations. --- src/d_netcmd.c | 1 + src/d_netcmd.h | 2 +- src/dehacked.c | 3 + src/info.c | 29 ++++++ src/info.h | 3 + src/k_kart.c | 268 ++++++++++++++++++++++++++++++++++++++++--------- src/k_kart.h | 6 +- src/p_inter.c | 38 +++++-- src/p_map.c | 2 +- src/p_mobj.c | 202 +++++++++++++++++++++++++++---------- src/sounds.c | 1 + src/sounds.h | 1 + 12 files changed, 446 insertions(+), 110 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8e046d92..c9343b07 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -370,6 +370,7 @@ static CV_PossibleValue_t kartdebugamount_cons_t[] = {{1, "MIN"}, {255, "MAX"}, consvar_t cv_kartdebugamount = {"kartdebugamount", "1", CV_NETVAR|CV_CHEAT, kartdebugamount_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugshrink = {"kartdebugshrink", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugdistribution = {"kartdebugdistribution", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartdebughuddrop = {"kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 3f118944..97dac8a9 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -133,7 +133,7 @@ extern consvar_t cv_karteliminatelast; extern consvar_t cv_votetime; -extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution; +extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop; extern consvar_t cv_kartdebugcheckpoint; extern consvar_t cv_itemfinder; diff --git a/src/dehacked.c b/src/dehacked.c index 3473eb87..78d6c4df 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6233,6 +6233,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_RANDOMITEMPOP4", //} + "S_ITEMICON", + // Drift Sparks "S_DRIFTSPARK1", "S_DRIFTSPARK2", @@ -7208,6 +7210,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BLUEDIAG", "MT_RANDOMITEM", "MT_RANDOMITEMPOP", + "MT_FLOATINGITEM", "MT_SNEAKERTRAIL", "MT_SPARKLETRAIL", diff --git a/src/info.c b/src/info.c index 60cac109..75a7655f 100644 --- a/src/info.c +++ b/src/info.c @@ -2566,6 +2566,8 @@ state_t states[NUMSTATES] = {SPR_RPOP, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_RANDOMITEMPOP4}, // S_RANDOMITEMPOP3 {SPR_RPOP, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_NULL}, // S_RANDOMITEMPOP4 + {SPR_NULL, 0|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMICON + {SPR_DRIF, 0|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK2}, // S_DRIFTSPARK1 {SPR_DRIF, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK3}, // S_DRIFTSPARK2 {SPR_DRIF, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DRIFTSPARK1}, // S_DRIFTSPARK3 @@ -14390,6 +14392,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FLOATINGITEM + -1, // doomednum + S_ITEMICON, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_mcitm1, // deathsound + 0, // speed + 24*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SLIDEME|MF_SPECIAL, // flags + S_NULL // raisestate + }, + { // MT_SNEAKERTRAIL -1, // doomednum S_KARTFIRE1, // spawnstate diff --git a/src/info.h b/src/info.h index 736fdfde..ad876dc7 100644 --- a/src/info.h +++ b/src/info.h @@ -3078,6 +3078,8 @@ typedef enum state S_RANDOMITEMPOP4, //} + S_ITEMICON, + // Drift Sparks S_DRIFTSPARK1, S_DRIFTSPARK2, @@ -4070,6 +4072,7 @@ typedef enum mobj_type MT_BLUEDIAG, MT_RANDOMITEM, MT_RANDOMITEMPOP, + MT_FLOATINGITEM, MT_SNEAKERTRAIL, MT_SPARKLETRAIL, diff --git a/src/k_kart.c b/src/k_kart.c index 40956016..0c75635b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -414,6 +414,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartdebugamount); CV_RegisterVar(&cv_kartdebugshrink); CV_RegisterVar(&cv_kartdebugdistribution); + CV_RegisterVar(&cv_kartdebughuddrop); CV_RegisterVar(&cv_kartdebugcheckpoint); } @@ -1101,7 +1102,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) fx->eflags |= MFE_VERTICALFLIP; else fx->eflags &= ~MFE_VERTICALFLIP; - fx->scale = mobj1->scale; + P_SetScale(fx, mobj1->scale); // Because this is done during collision now, rmomx and rmomy need to be recalculated // so that friction doesn't immediately decide to stop the player if they're at a standstill @@ -1715,6 +1716,10 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem P_SetPlayerMobjState(player->mo, S_KART_SPIN); player->kartstuff[k_instashield] = 15; + if (cv_kartdebughuddrop.value) + K_DropItems(player); + else + K_DropHnextList(player); return; } @@ -1784,6 +1789,10 @@ void K_SquishPlayer(player_t *player, mobj_t *source) P_PlayRinglossSound(player->mo); player->kartstuff[k_instashield] = 15; + if (cv_kartdebughuddrop.value) + K_DropItems(player); + else + K_DropHnextList(player); return; } @@ -1861,6 +1870,10 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju } player->kartstuff[k_instashield] = 15; + if (cv_kartdebughuddrop.value) + K_DropItems(player); + else + K_DropHnextList(player); return; } @@ -1936,6 +1949,10 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force) victim->kartstuff[k_comebacktimer] = comebacktime;*/ victim->kartstuff[k_instashield] = 15; + if (cv_kartdebughuddrop.value) + K_DropItems(victim); + else + K_DropHnextList(victim); return; } @@ -2043,14 +2060,14 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) { dust = P_SpawnMobj(source->x, source->y, source->z, MT_SMOKE); dust->angle = (ANGLE_180/16) * i; - dust->scale = source->scale; + P_SetScale(dust, source->scale); dust->destscale = source->scale*10; P_InstaThrust(dust, dust->angle, FixedMul(20*FRACUNIT, source->scale)); truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, source->y + P_RandomRange(-radius, radius)*FRACUNIT, source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMEXPLODE); - truc->scale = source->scale*2; + P_SetScale(truc, source->scale); truc->destscale = source->scale*6; speed = FixedMul(10*FRACUNIT, source->scale)>>FRACBITS; truc->momx = P_RandomRange(-speed, speed)*FRACUNIT; @@ -2065,7 +2082,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) dust = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, source->y + P_RandomRange(-radius, radius)*FRACUNIT, source->z + P_RandomRange(0, height)*FRACUNIT, MT_SMOKE); - dust->scale = source->scale; + P_SetScale(dust, source->scale); dust->destscale = source->scale*10; dust->tics = 30; dust->momz = P_RandomRange(FixedMul(3*FRACUNIT, source->scale)>>FRACBITS, FixedMul(7*FRACUNIT, source->scale)>>FRACBITS)*FRACUNIT; @@ -2073,7 +2090,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, source->y + P_RandomRange(-radius, radius)*FRACUNIT, source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMPARTICLE); - truc->scale = source->scale; + P_SetScale(truc, source->scale); truc->destscale = source->scale*5; speed = FixedMul(20*FRACUNIT, source->scale)>>FRACBITS; truc->momx = P_RandomRange(-speed, speed)*FRACUNIT; @@ -2350,7 +2367,7 @@ void K_DriftDustHandling(mobj_t *spawner) dust->momx = FixedMul(spawner->momx + (P_RandomRange(-speedrange, speedrange)<momy = FixedMul(spawner->momy + (P_RandomRange(-speedrange, speedrange)<momz = P_MobjFlip(spawner) * P_RandomRange(1, 4)<scale = spawner->scale/2; + P_SetScale(dust, spawner->scale/2); dust->destscale = spawner->scale * 3; if (leveltime % 6 == 0) @@ -2808,46 +2825,190 @@ killnext: } // Just for firing/dropping items. -void K_CleanHnextList(mobj_t *work) -{ - mobj_t *nextwork; - - if (!work) - return; - - work = work->hnext; - - while (work && !P_MobjWasRemoved(work)) - { - nextwork = work->hnext; - - P_RemoveMobj(work); - - work = nextwork; - } -} - -// Ditto. -void K_UpdateHnextList(player_t *player) +void K_UpdateHnextList(player_t *player, boolean clean) { mobj_t *work = player->mo, *nextwork; if (!work) return; - work = work->hnext; + nextwork = work->hnext; - while (work && !P_MobjWasRemoved(work)) + while ((work = nextwork) && !P_MobjWasRemoved(work)) { nextwork = work->hnext; - if (work->movedir > 0 && work->movedir > (UINT16)player->kartstuff[k_itemamount]) - P_RemoveMobj(work); + if (!clean && (!work->movedir || work->movedir <= (UINT16)player->kartstuff[k_itemamount])) + continue; - work = nextwork; + P_RemoveMobj(work); } } +// For getting hit! +void K_DropHnextList(player_t *player) +{ + mobj_t *work = player->mo, *nextwork, *dropwork; + INT32 flip; + mobjtype_t type; + boolean orbit, ponground; + + if (!work) + return; + + flip = P_MobjFlip(player->mo); + ponground = P_IsObjectOnGround(player->mo); + + if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD && player->kartstuff[k_itemamount]) + { + K_DoThunderShield(player); + player->kartstuff[k_itemamount] = 0; + player->kartstuff[k_itemtype] = KITEM_NONE; + } + + nextwork = work->hnext; + + while ((work = nextwork) && !P_MobjWasRemoved(work)) + { + nextwork = work->hnext; + + switch (work->type) + { + // Kart orbit items + case MT_ORBINAUT_SHIELD: + orbit = true; + type = MT_ORBINAUT; + break; + case MT_JAWZ_SHIELD: + orbit = true; + type = MT_JAWZ_DUD; + break; + // Kart trailing items + case MT_BANANA_SHIELD: + orbit = false; + type = MT_BANANA; + break; + case MT_SSMINE_SHIELD: + orbit = false; + type = MT_SSMINE; + break; + case MT_FAKESHIELD: + orbit = false; + type = MT_FAKEITEM; + break; + // intentionally do nothing + case MT_SINK_SHIELD: + return; + default: + continue; + } + + dropwork = P_SpawnMobj(work->x, work->y, work->z, type); + P_SetTarget(&dropwork->target, player->mo); + dropwork->angle = work->angle; + dropwork->flags2 = work->flags2; + dropwork->flags |= MF_NOCLIPTHING; + dropwork->floorz = work->floorz; + dropwork->ceilingz = work->ceilingz; + + if (ponground) + { + // floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn + // This should set it for FOFs + //P_TeleportMove(dropwork, dropwork->x, dropwork->y, dropwork->z); -- handled better by above floorz/ceilingz passing + + if (flip == 1) + { + if (dropwork->floorz > dropwork->target->z - dropwork->height) + { + dropwork->z = dropwork->floorz; + } + } + else + { + if (dropwork->ceilingz < dropwork->target->z + dropwork->target->height + dropwork->height) + { + dropwork->z = dropwork->ceilingz - dropwork->height; + } + } + } + + if (orbit) // splay out + { + dropwork->flags2 |= MF2_AMBUSH; + dropwork->z += flip; + dropwork->momx = player->mo->momx>>1; + dropwork->momy = player->mo->momy>>1; + dropwork->momz = 3*flip*mapheaderinfo[gamemap-1]->mobj_scale; + P_Thrust(dropwork, work->angle - ANGLE_90, 6*(mapheaderinfo[gamemap-1]->mobj_scale)); + dropwork->movecount = 2; + dropwork->movedir = work->angle - ANGLE_90; + P_SetMobjState(dropwork, dropwork->info->deathstate); + dropwork->tics = -1; + if (type == MT_JAWZ_DUD) + dropwork->z += 20*flip*dropwork->scale; + else + { + dropwork->color = work->color; + dropwork->angle -= ANGLE_90; + } + } + else // plop on the ground + { + dropwork->flags &= ~MF_NOCLIPTHING; + dropwork->threshold = 10; + } + + P_RemoveMobj(work); + } + + { + // we need this here too because this is done in afterthink - pointers are cleaned up at the START of each tic... + P_SetTarget(&player->mo->hnext, NULL); + player->kartstuff[k_bananadrag] = 0; + if (player->kartstuff[k_eggmanheld]) + player->kartstuff[k_eggmanheld] = 0; + else if (player->kartstuff[k_itemheld]) + { + player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; + player->kartstuff[k_itemtype] = KITEM_NONE; + } + } +} + +// For getting EXTRA hit! +void K_DropItems(player_t *player) +{ + boolean thunderhack = (player->kartstuff[k_curshield] && player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD); + + if (thunderhack) + player->kartstuff[k_itemtype] = KITEM_NONE; + + K_DropHnextList(player); + + if (player->mo && player->kartstuff[k_itemamount]) + { + mobj_t *drop = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FLOATINGITEM); + P_SetScale(drop, drop->scale>>5); + drop->destscale = (3*drop->destscale)/2;; + + drop->angle = player->mo->angle + ANGLE_90; + drop->momx = player->mo->momx>>1; + drop->momy = player->mo->momy>>1; + P_Thrust(drop, + FixedAngle(P_RandomFixed()*180) + player->mo->angle + ANGLE_90, + 8*(mapheaderinfo[gamemap-1]->mobj_scale)); + drop->momz = P_MobjFlip(player->mo)*3*(mapheaderinfo[gamemap-1]->mobj_scale); + + drop->threshold = (thunderhack ? KITEM_THUNDERSHIELD : player->kartstuff[k_itemtype]); + drop->movecount = player->kartstuff[k_itemamount]; + + drop->flags |= MF_NOCLIPTHING; + } + + K_StripItems(player); +} + // When an item in the hnext chain dies. void K_RepairOrbitChain(mobj_t *orbit) { @@ -3859,20 +4020,18 @@ static void K_KartUpdatePosition(player_t *player) // void K_StripItems(player_t *player) { - player->kartstuff[k_itemtype] = 0; + player->kartstuff[k_itemtype] = KITEM_NONE; player->kartstuff[k_itemamount] = 0; player->kartstuff[k_itemheld] = 0; - player->kartstuff[k_itemroulette] = 0; - player->kartstuff[k_roulettetype] = 0; - player->kartstuff[k_rocketsneakertimer] = 0; - player->kartstuff[k_invincibilitytimer] = 0; - player->kartstuff[k_growshrinktimer] = 0; + if (!player->kartstuff[k_itemroulette] || player->kartstuff[k_roulettetype] != 2) + { + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + } player->kartstuff[k_eggmanheld] = 0; - player->kartstuff[k_eggmanexplode] = 0; - player->kartstuff[k_eggmanblame] = 0; player->kartstuff[k_hyudorotimer] = 0; player->kartstuff[k_stealingtimer] = 0; @@ -3884,7 +4043,19 @@ void K_StripItems(player_t *player) player->kartstuff[k_sadtimer] = 0; - K_CleanHnextList(player->mo); + K_UpdateHnextList(player, true); +} + +void K_StripOther(player_t *player) +{ + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + + player->kartstuff[k_invincibilitytimer] = 0; + player->kartstuff[k_growshrinktimer] = 0; + + player->kartstuff[k_eggmanexplode] = 0; + player->kartstuff[k_eggmanblame] = 0; } // @@ -3950,7 +4121,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_ThrowKartItem(player, false, MT_FAKEITEM, -1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_eggmanheld] = 0; - K_CleanHnextList(player->mo); + K_UpdateHnextList(player, true); } // Rocket Sneaker else if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO @@ -4037,7 +4208,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_ThrowKartItem(player, false, MT_BANANA, -1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; - K_UpdateHnextList(player); + K_UpdateHnextList(player, false); } break; case KITEM_EGGMAN: @@ -4097,7 +4268,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; - K_UpdateHnextList(player); + K_UpdateHnextList(player, false); } break; case KITEM_JAWZ: @@ -4140,7 +4311,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0); K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; - K_UpdateHnextList(player); + K_UpdateHnextList(player, false); } break; case KITEM_MINE: @@ -4166,7 +4337,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; player->kartstuff[k_itemheld] = 0; - K_CleanHnextList(player->mo); + K_UpdateHnextList(player, true); } break; case KITEM_BALLHOG: @@ -4293,7 +4464,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_PlayTauntSound(player->mo); player->kartstuff[k_itemamount]--; player->kartstuff[k_itemheld] = 0; - K_CleanHnextList(player->mo); + K_UpdateHnextList(player, true); } break; case KITEM_SAD: @@ -4372,7 +4543,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) // dead in match? you da bomb { - K_StripItems(player); + K_DropItems(player); //K_StripItems(player); + K_StripOther(player); player->mo->flags2 |= MF2_SHADOW; player->powers[pw_flashing] = player->kartstuff[k_comebacktimer]; } diff --git a/src/k_kart.h b/src/k_kart.h index 9865d373..bbef6c00 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -39,14 +39,16 @@ void K_DriftDustHandling(mobj_t *spawner); void K_DoSneaker(player_t *player, boolean doPFlag); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, boolean mute); void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); -void K_CleanHnextList(mobj_t *work); -void K_UpdateHnextList(player_t *player); +void K_UpdateHnextList(player_t *player, boolean clean); +void K_DropHnextList(player_t *player); void K_RepairOrbitChain(mobj_t *orbit); player_t *K_FindJawzTarget(mobj_t *actor, player_t *source); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); fixed_t K_GetKartDriftSparkValue(player_t *player); +void K_DropItems(player_t *player); void K_StripItems(player_t *player); +void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartAccel(player_t *player); diff --git a/src/p_inter.c b/src/p_inter.c index 7e35731a..c8d42b23 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -181,13 +181,13 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) { // Item-specific timer going off if (player->kartstuff[k_stealingtimer] || player->kartstuff[k_stolentimer] - || player->kartstuff[k_growshrinktimer] != 0 || player->kartstuff[k_rocketsneakertimer] + || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_rocketsneakertimer] || player->kartstuff[k_eggmanexplode]) return false; // Item slot already taken up if (player->kartstuff[k_itemroulette] - || player->kartstuff[k_itemamount] + || (weapon != 3 && player->kartstuff[k_itemamount]) || player->kartstuff[k_itemheld]) return false; } @@ -429,6 +429,27 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // We now identify by object type, not sprite! Tails 04-11-2001 switch (special->type) { + case MT_FLOATINGITEM: // SRB2kart + if (!P_CanPickupItem(player, 3) || (player->kartstuff[k_itemamount] && player->kartstuff[k_itemtype] != special->threshold)) + return; + + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + return; + + player->kartstuff[k_itemtype] = special->threshold; + player->kartstuff[k_itemamount] += special->movecount; + if (player->kartstuff[k_itemamount] > 255) + player->kartstuff[k_itemamount] = 255; + + S_StartSound(special, special->info->deathsound); + + P_SetTarget(&special->tracer, toucher); + special->flags2 |= MF2_NIGHTSPULL; + special->destscale = mapheaderinfo[gamemap-1]->mobj_scale>>5; + special->scalespeed <<= 1; + + special->flags &= ~MF_SPECIAL; + return; case MT_RANDOMITEM: // SRB2kart if (!P_CanPickupItem(player, 1)) return; @@ -469,9 +490,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE); S_StartSound(poof, special->info->deathsound); - K_StripItems(player); - if (player->kartstuff[k_itemroulette] <= 0) - player->kartstuff[k_itemroulette] = 1; + K_DropItems(player); //K_StripItems(player); + K_StripOther(player); + player->kartstuff[k_itemroulette] = 1; player->kartstuff[k_roulettetype] = 2; if (special->target && special->target->player && (G_RaceGametype() || special->target->player->kartstuff[k_bumper] > 0)) @@ -2626,6 +2647,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) } } + if ((target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD) && !(target->flags2 & MF2_AMBUSH)) + { + target->z += P_MobjFlip(target)*20*target->scale; + } + if (target->type == MT_SPIKE && inflictor && target->info->deathstate != S_NULL) { const fixed_t x=target->x,y=target->y,z=target->z; @@ -3335,6 +3361,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da player->mo->destscale = 6*player->mo->destscale/8; // Wipeout + K_DropItems(player); K_SpinPlayer(player, source, 1, false); damage = player->mo->health - 1; P_RingDamage(player, inflictor, source, damage); @@ -3346,7 +3373,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da quake.time = 5; } - K_StripItems(player); player->kartstuff[k_growshrinktimer] -= (200+(40*(16-player->kartstuff[k_position]))); } // Grow? Let's take that away. diff --git a/src/p_map.c b/src/p_map.c index 88045a3e..c97ee909 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -497,7 +497,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE))) + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE)) || (thing->flags & MF_NOCLIPTHING)) return true; // Don't collide with your buddies while NiGHTS-flying. diff --git a/src/p_mobj.c b/src/p_mobj.c index fb6eed54..dc4ac036 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6006,7 +6006,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y return; // change angle - source->angle = R_PointToAngle2(source->x, source->y, tx, ty); + //source->angle = R_PointToAngle2(source->x, source->y, tx, ty); // change slope dist = P_AproxDistance(P_AproxDistance(tx - source->x, ty - source->y), tz - source->z); @@ -6015,7 +6015,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y dist = 1; if (nightsgrab) - speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(8*FRACUNIT, source->scale); + speedmul = P_AproxDistance(dest->momx, dest->momy) + source->scale; else speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(source->info->speed, source->scale); @@ -6348,6 +6348,9 @@ void P_RunShadows(void) break; } } + + if (mobj->target->type == MT_FLOATINGITEM) + P_SetScale(mobj, mobj->scale/2); } P_SetTarget(&shadowcap, NULL); } @@ -6727,7 +6730,7 @@ void P_MobjThinker(mobj_t *mobj) /*if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->health > 0 && !mobj->target->player->spectator) { - // Was this so hard? -- Handled this with K_UpdateHnextList and K_ClearHnextList instead of thinking it away... + // Was this so hard? -- Handled this with K_UpdateHnextList instead of thinking it away... if ((mobj->type == MT_ORBINAUT_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_ORBINAUT) || (mobj->type == MT_JAWZ_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_JAWZ) || (mobj->movedir > 0 && ((UINT16)mobj->target->player->kartstuff[k_itemamount] < mobj->movedir)) @@ -6911,14 +6914,16 @@ void P_MobjThinker(mobj_t *mobj) mobj->x = mobj->target->x; mobj->y = mobj->target->y; + mobj->angle = R_PointToAngle(mobj->x, mobj->y) + ANGLE_90; // literally only happened because i wanted to ^L^R the SPR_ITEM's + if (!(mobj->target->eflags & MFE_VERTICALFLIP)) { - mobj->z = mobj->target->z + P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT; + mobj->z = mobj->target->z + P_GetPlayerHeight(mobj->target->player)+(16+11)*mapheaderinfo[gamemap-1]->mobj_scale; mobj->eflags &= ~MFE_VERTICALFLIP; } else { - mobj->z = mobj->target->z - P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT; + mobj->z = mobj->target->z - P_GetPlayerHeight(mobj->target->player)+(16+11)*mapheaderinfo[gamemap-1]->mobj_scale; mobj->eflags |= MFE_VERTICALFLIP; } P_SetThingPosition(mobj); @@ -6934,7 +6939,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->tracer = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); P_SetTarget(&mobj->tracer->target, mobj); P_SetMobjState(mobj->tracer, S_PLAYERARROW_ITEM); - P_SetScale(mobj->tracer, mobj->scale); + P_SetMobjState(mobj->tracer, S_ITEMICON); // null sprite and frame to be overwritten later + P_SetScale(mobj->tracer, (mobj->tracer->destscale = mobj->scale)); } if (!(mobj->flags2 & MF2_DONTDRAW)) @@ -7027,7 +7033,7 @@ void P_MobjThinker(mobj_t *mobj) else { P_SetMobjState(mobj, S_PLAYERARROW); - P_SetMobjState(mobj->tracer, S_INVISIBLE); + P_SetMobjState(mobj->tracer, S_ITEMICON); // null sprite and frame to be overwritten later } mobj->tracer->destscale = scale; @@ -7097,12 +7103,12 @@ void P_MobjThinker(mobj_t *mobj) if (!(mobj->target->eflags & MFE_VERTICALFLIP)) { - mobj->z = mobj->target->z + (P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT+(64*mobj->scale)); + mobj->z = mobj->target->z + (P_GetPlayerHeight(mobj->target->player)+16*mapheaderinfo[gamemap-1]->mobj_scale+(64*mobj->scale)); mobj->eflags &= ~MFE_VERTICALFLIP; } else { - mobj->z = mobj->target->z - (P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT+(64*mobj->scale)); + mobj->z = mobj->target->z - (P_GetPlayerHeight(mobj->target->player)+16*mapheaderinfo[gamemap-1]->mobj_scale+(64*mobj->scale)); mobj->eflags |= MFE_VERTICALFLIP; } P_SetThingPosition(mobj); @@ -8007,46 +8013,120 @@ void P_MobjThinker(mobj_t *mobj) mobj->threshold = 0; } break; - case MT_ORBINAUT: + case MT_FLOATINGITEM: { - sector_t *sec2; - fixed_t finalspeed = mobj->info->speed; - - P_SpawnGhostMobj(mobj); - - if (gamespeed == 0) - finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); - else if (gamespeed == 2) - finalspeed = FixedMul(finalspeed, FRACUNIT+FRACUNIT/4); - - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - if (mobj->health <= 5) + if (mobj->flags & MF_NOCLIPTHING) { - INT32 i; - for (i = 5; i >= mobj->health; i--) + if (P_IsObjectOnGround(mobj)) { - finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); + mobj->momx = 1; + mobj->momy = 0; + mobj->flags &= ~MF_NOCLIPTHING; + mobj->flags |= MF_NOGRAVITY; } - finalspeed = FixedMul(finalspeed, mapheaderinfo[gamemap-1]->mobj_scale); - P_InstaThrust(mobj, mobj->angle, finalspeed); } else { - finalspeed = FixedMul(finalspeed, mapheaderinfo[gamemap-1]->mobj_scale); - P_InstaThrust(mobj, mobj->angle, finalspeed); + mobj->angle += 2*ANG2; + if (mobj->flags2 & MF2_NIGHTSPULL) + { + if (!mobj->tracer || !mobj->tracer->health + || mobj->scale <= mapheaderinfo[gamemap-1]->mobj_scale>>5) + { + P_RemoveMobj(mobj); + return; + } + P_Attract(mobj, mobj->tracer, true); + } + else + { + fixed_t adj = FixedMul(FRACUNIT - FINECOSINE((mobj->movedir>>ANGLETOFINESHIFT) & FINEMASK), (mapheaderinfo[gamemap-1]->mobj_scale<<3)); + mobj->movedir += 2*ANG2; + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->ceilingz - mobj->height - adj; + else + mobj->z = mobj->floorz + adj; + } } - sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) - || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) - && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) - K_DoPogoSpring(mobj, 0, false); + switch (mobj->threshold) + { + case KITEM_ORBINAUT: + mobj->sprite = SPR_ITMO; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(min(mobj->movecount-1, 3)); + break; + case KITEM_INVINCIBILITY: + mobj->sprite = SPR_ITMI; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|((leveltime % (7*3)) / 3); + break; + case KITEM_SAD: + mobj->sprite = SPR_ITEM; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE; + break; + default: + mobj->sprite = SPR_ITEM; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(mobj->threshold); + break; + } + break; + } + case MT_ORBINAUT: + { + boolean grounded = P_IsObjectOnGround(mobj); + if (mobj->flags2 & MF2_AMBUSH) + { + if (grounded && (mobj->flags & MF_NOCLIPTHING)) + { + mobj->momx = 1; + mobj->momy = 0; + mobj->frame = 3; + S_StartSound(mobj, mobj->info->activesound); + mobj->flags &= ~MF_NOCLIPTHING; + } + else if (mobj->movecount) + mobj->movecount--; + else if (mobj->frame < 3) + { + mobj->movecount = 2; + mobj->frame++; + } + } + else + { + fixed_t finalspeed = mobj->info->speed; - if (mobj->threshold > 0) - mobj->threshold--; + P_SpawnGhostMobj(mobj); - if (leveltime % 6 == 0) - S_StartSound(mobj, mobj->info->activesound); + if (gamespeed == 0) + finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); + else if (gamespeed == 2) + finalspeed = FixedMul(finalspeed, FRACUNIT+FRACUNIT/4); + + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + if (mobj->health <= 5) + { + INT32 i; + for (i = 5; i >= mobj->health; i--) + finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); + } + finalspeed = FixedMul(finalspeed, mapheaderinfo[gamemap-1]->mobj_scale); + P_InstaThrust(mobj, mobj->angle, finalspeed); + + if (grounded) + { + sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj); + if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) + || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) + && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) + K_DoPogoSpring(mobj, 0, false); + } + + if (mobj->threshold > 0) + mobj->threshold--; + + if (leveltime % 6 == 0) + S_StartSound(mobj, mobj->info->activesound); + } break; } case MT_JAWZ: @@ -8119,23 +8199,38 @@ void P_MobjThinker(mobj_t *mobj) } case MT_JAWZ_DUD: { - sector_t *sec2; + boolean grounded = P_IsObjectOnGround(mobj); + if (mobj->flags2 & MF2_AMBUSH) + { + if (grounded && (mobj->flags & MF_NOCLIPTHING)) + { + mobj->momx = 1; + mobj->momy = 0; + S_StartSound(mobj, mobj->info->deathsound); + mobj->flags &= ~MF_NOCLIPTHING; + } + } + else + { + P_SpawnGhostMobj(mobj); + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + P_InstaThrust(mobj, mobj->angle, mobj->info->speed); - P_SpawnGhostMobj(mobj); - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_InstaThrust(mobj, mobj->angle, mobj->info->speed); + if (grounded) + { + sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj); + if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) + || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) + && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) + K_DoPogoSpring(mobj, 0, false); + } - sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) - || (P_IsObjectOnRealGround(mobj, mobj->subsector->sector) - && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) - K_DoPogoSpring(mobj, 0, false); + if (mobj->threshold > 0) + mobj->threshold--; - if (mobj->threshold > 0) - mobj->threshold--; - - if (leveltime % TICRATE == 0) - S_StartSound(mobj, mobj->info->activesound); + if (leveltime % TICRATE == 0) + S_StartSound(mobj, mobj->info->activesound); + } break; } @@ -9155,6 +9250,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_BIGMACE: case MT_SMALLMACE: case MT_FALLINGROCK: //case MT_RANDOMITEM: + case MT_FLOATINGITEM: case MT_BATTLEBUMPER: case MT_BANANA: case MT_BANANA_SHIELD: //case MT_FAKEITEM: case MT_FAKESHIELD: @@ -9254,6 +9350,8 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster) if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->mobj_scale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN) mobj->destscale = mapheaderinfo[gamemap-1]->mobj_scale; + P_SetScale(mobj, mobj->destscale); + // set subsector and/or block links P_SetThingPosition(mobj); I_Assert(mobj->subsector != NULL); diff --git a/src/sounds.c b/src/sounds.c index 6e956260..b68c8afa 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -811,6 +811,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"noooo1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"mcitm1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds diff --git a/src/sounds.h b/src/sounds.h index 2f073273..86319c33 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -883,6 +883,7 @@ typedef enum sfx_noooo1, sfx_noooo2, sfx_hogbom, + sfx_mcitm1, sfx_dbgsal, sfx_kwin, From baf50a1dbfc35eb1b1888def5a93bdd571e43baf Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 7 Sep 2018 14:26:00 +0100 Subject: [PATCH 05/37] * Slightly more papersprite stability! * Slightly more sane Minecraft item scaling! --- src/k_kart.c | 2 +- src/p_inter.c | 2 +- src/p_mobj.c | 2 +- src/r_things.c | 9 +++------ 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 477f710e..55c1802a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3008,7 +3008,7 @@ void K_DropItems(player_t *player) if (player->mo && player->kartstuff[k_itemamount]) { mobj_t *drop = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FLOATINGITEM); - P_SetScale(drop, drop->scale>>5); + P_SetScale(drop, drop->scale>>4); drop->destscale = (3*drop->destscale)/2;; drop->angle = player->mo->angle + ANGLE_90; diff --git a/src/p_inter.c b/src/p_inter.c index c8d42b23..aab44b5f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -445,7 +445,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_SetTarget(&special->tracer, toucher); special->flags2 |= MF2_NIGHTSPULL; - special->destscale = mapheaderinfo[gamemap-1]->mobj_scale>>5; + special->destscale = mapheaderinfo[gamemap-1]->mobj_scale>>4; special->scalespeed <<= 1; special->flags &= ~MF_SPECIAL; diff --git a/src/p_mobj.c b/src/p_mobj.c index 7093e781..baf0f1f2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8031,7 +8031,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags2 & MF2_NIGHTSPULL) { if (!mobj->tracer || !mobj->tracer->health - || mobj->scale <= mapheaderinfo[gamemap-1]->mobj_scale>>5) + || mobj->scale <= mapheaderinfo[gamemap-1]->mobj_scale>>4) { P_RemoveMobj(mobj); return; diff --git a/src/r_things.c b/src/r_things.c index 5adcecd4..dbe31cb1 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1266,7 +1266,6 @@ static void R_ProjectSprite(mobj_t *thing) if (papersprite) { fixed_t yscale2, cosmul, sinmul, tz2; - INT32 range; if (ang >= ANGLE_180) { @@ -1296,12 +1295,10 @@ static void R_ProjectSprite(mobj_t *thing) if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; - if (x2 > x1) - range = (x2 - x1); - else - range = 1; + if (x2 <= x1) + return; - scalestep = (yscale2 - yscale)/range; + scalestep = (yscale2 - yscale)/(x2 - x1); // The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2? // sortscale = max(yscale, yscale2); From f887ae6628b8ac3a3db3bb63b0637c5d4d03d421 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 8 Sep 2018 12:12:28 +0100 Subject: [PATCH 06/37] Watertight fix I was avoiding because it's definitely slower to check ranges at runtime, but papersprites are used intermittently enough that I don't think it's a super big deal. --- src/r_things.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index dbe31cb1..6166c762 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -917,6 +917,16 @@ static void R_DrawVisSprite(vissprite_t *vis) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) { + if (vis->scalestep) // currently papersprites only + { +#ifndef RANGECHECK + if ((frac>>FRACBITS) >= SHORT(patch->width)) // slower but kills intermittent crashes... + break; +#endif + sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); + dc_iscale = (0xffffffffu / (unsigned)spryscale); + spryscale += vis->scalestep; + } #ifdef RANGECHECK texturecolumn = frac>>FRACBITS; @@ -926,16 +936,10 @@ static void R_DrawVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); #endif - if (vis->scalestep) - { - sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - dc_iscale = (0xffffffffu / (unsigned)spryscale); - } if (vis->vflip) R_DrawFlippedMaskedColumn(column, patch->height); else R_DrawMaskedColumn(column); - spryscale += vis->scalestep; } colfunc = basecolfunc; @@ -1257,7 +1261,7 @@ static void R_ProjectSprite(mobj_t *thing) offset2 = FixedMul(spritecachedinfo[lump].width, this_scale); tx += FixedMul(offset2, ang_scale); - x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - (papersprite ? 2 : 1); + x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - 1; // off the left side if (x2 < 0) From 9eeefde0f42ae11ab4d5c6dd17190d041024401b Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 8 Sep 2018 23:45:51 +0100 Subject: [PATCH 07/37] Make bomb attacks HUD drop. (Karma may be changed later, but Oni said let's try all together first...) --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index a53eb7f4..61c9446d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1886,10 +1886,10 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju } player->kartstuff[k_instashield] = 15; - if (cv_kartdebughuddrop.value) + //if (cv_kartdebughuddrop.value) K_DropItems(player); - else - K_DropHnextList(player); + /*else + K_DropHnextList(player);*/ return; } From dc0144540b55ef12d196824150395bb5d88f4a74 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 9 Sep 2018 13:47:19 +0100 Subject: [PATCH 08/37] `// if this doesn't work i'm removing papersprites` (check both the left and right side overflow of the sprite column being drawn) --- src/r_things.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 6166c762..7f6e3974 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -920,7 +920,7 @@ static void R_DrawVisSprite(vissprite_t *vis) if (vis->scalestep) // currently papersprites only { #ifndef RANGECHECK - if ((frac>>FRACBITS) >= SHORT(patch->width)) // slower but kills intermittent crashes... + if ((frac>>FRACBITS) < 0 || (frac>>FRACBITS) >= SHORT(patch->width)) // if this doesn't work i'm removing papersprites break; #endif sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); @@ -1271,6 +1271,9 @@ static void R_ProjectSprite(mobj_t *thing) { fixed_t yscale2, cosmul, sinmul, tz2; + if (x2 <= x1) + return; + if (ang >= ANGLE_180) { offset *= -1; @@ -1299,9 +1302,6 @@ static void R_ProjectSprite(mobj_t *thing) if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; - if (x2 <= x1) - return; - scalestep = (yscale2 - yscale)/(x2 - x1); // The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2? From 1010950148edeea34f797010850f892abebb1d19 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 9 Sep 2018 15:17:41 +0100 Subject: [PATCH 09/37] This isn't vanilla, don't be a shit about secrets and addfile (plus it helps that this fixes a crash) --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index dcfe4fb8..5becef4e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4787,8 +4787,8 @@ static void M_HandleAddons(INT32 choice) { closefilemenu(true); - // secrets disabled by addfile... - MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + // Secret menu! + //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); From b1db70b38a0f4039ed01cd652518fec5cd4cab89 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 12 Sep 2018 19:03:45 +0100 Subject: [PATCH 10/37] * Chao audience! * Replaces the CZ64-era hopping Mario guys. * ~50% randomised colours! * 1/9 are FANS! * On mapload, some Chao select a random player in the server (even spectators) as their idol. * The fans cheer for their idol when they cross the finish line in a winning position! * They also sob when their idol loses. * The remaining percentage are the canon Aqua. * Minor on-field spikeball/fake radius alterations requested by Oni. --- src/dehacked.c | 15 ++++------- src/info.c | 27 +++++++++---------- src/info.h | 15 ++++------- src/p_mobj.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/sounds.c | 1 + src/sounds.h | 1 + 6 files changed, 93 insertions(+), 37 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 6365453f..a6f3074d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6519,16 +6519,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Audience Members "S_RANDOMAUDIENCE", - "S_AUDIENCE_TOAD1", - "S_AUDIENCE_TOAD2", - "S_AUDIENCE_BOO1", - "S_AUDIENCE_BOO2", - "S_AUDIENCE_GMBA1", - "S_AUDIENCE_GMBA2", - "S_AUDIENCE_SHYG1", - "S_AUDIENCE_SHYG2", - "S_AUDIENCE_SNIF1", - "S_AUDIENCE_SNIF2", + "S_AUDIENCE_CHAO_CHEER1", + "S_AUDIENCE_CHAO_CHEER2", + "S_AUDIENCE_CHAO_WIN1", + "S_AUDIENCE_CHAO_WIN2", + "S_AUDIENCE_CHAO_LOSE", "S_FANCHAR_KOTE", "S_FANCHAR_RYAN", diff --git a/src/info.c b/src/info.c index e7c40cb9..554f410a 100644 --- a/src/info.c +++ b/src/info.c @@ -2831,18 +2831,15 @@ state_t states[NUMSTATES] = {SPR_POKE, 3, 2, {A_MoveAbsolute}, 180, 2, S_POKEY5}, // S_POKEY8 {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_POKEYIDLE - {SPR_NULL, 0, 1, {A_RandomStateRange}, S_AUDIENCE_TOAD1, S_AUDIENCE_SNIF1, S_RANDOMAUDIENCE}, // S_RANDOMAUDIENCE + {SPR_NULL, 0, 1, {A_RandomStateRange}, S_AUDIENCE_CHAO_CHEER1, S_AUDIENCE_CHAO_CHEER2, S_RANDOMAUDIENCE}, // S_RANDOMAUDIENCE - {SPR_AUDI, 0, 5, {NULL}, 0, 0, S_AUDIENCE_TOAD2}, // S_AUDIENCE_TOAD1 - {SPR_AUDI, 1, 20, {A_BunnyHop}, 7, 0, S_AUDIENCE_TOAD1}, // S_AUDIENCE_TOAD2 - {SPR_AUDI, 2, 5, {NULL}, 0, 0, S_AUDIENCE_BOO2}, // S_AUDIENCE_BOO1 - {SPR_AUDI, 3, 20, {A_BunnyHop}, 7, 0, S_AUDIENCE_BOO1}, // S_AUDIENCE_BOO2 - {SPR_AUDI, 4, 5, {NULL}, 0, 0, S_AUDIENCE_GMBA2}, // S_AUDIENCE_GMBA1 - {SPR_AUDI, 5, 20, {A_BunnyHop}, 7, 0, S_AUDIENCE_GMBA1}, // S_AUDIENCE_GMBA2 - {SPR_AUDI, 6, 5, {NULL}, 0, 0, S_AUDIENCE_SHYG2}, // S_AUDIENCE_SHYG1 - {SPR_AUDI, 7, 20, {A_BunnyHop}, 7, 0, S_AUDIENCE_SHYG1}, // S_AUDIENCE_SHYG2 - {SPR_AUDI, 8, 5, {NULL}, 0, 0, S_AUDIENCE_SNIF2}, // S_AUDIENCE_SNIF1 - {SPR_AUDI, 9, 20, {A_BunnyHop}, 7, 0, S_AUDIENCE_SNIF1}, // S_AUDIENCE_SNIF2 + {SPR_AUDI, 0, 5, {NULL}, 0, 0, S_AUDIENCE_CHAO_CHEER2}, // S_AUDIENCE_CHAO_CHEER1 + {SPR_AUDI, 1, 20, {A_BunnyHop}, 7, 0, S_AUDIENCE_CHAO_CHEER1}, // S_AUDIENCE_CHAO_CHEER2 + + {SPR_AUDI, 2, 5, {NULL}, 0, 0, S_AUDIENCE_CHAO_WIN2}, // S_AUDIENCE_CHAO_WIN1 + {SPR_AUDI, 3, 25, {A_BunnyHop}, 10, 0, S_AUDIENCE_CHAO_WIN1}, // S_AUDIENCE_CHAO_WIN2 + + {SPR_AUDI, 4|FF_ANIMATE, -1, {NULL}, 1, 17, S_NULL}, // S_AUDIENCE_CHAO_LOSE {SPR_AUDI, 10, -1, {NULL}, 0, 0, S_NULL}, // S_FANCHAR_KOTE {SPR_AUDI, 11, -1, {NULL}, 0, 0, S_NULL}, // S_FANCHAR_RYAN @@ -14691,7 +14688,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_kc2e, // deathsound 0, // speed - 16*FRACUNIT, // radius + 24*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass @@ -14772,7 +14769,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_s3k5d, // deathsound 64*FRACUNIT, // speed - 16*FRACUNIT, // radius + 24*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass @@ -15501,8 +15498,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 8, // speed - 16*FRACUNIT, // radius - 40*FRACUNIT, // height + 8*FRACUNIT, // radius + 20*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage diff --git a/src/info.h b/src/info.h index 53b5809a..c5f98983 100644 --- a/src/info.h +++ b/src/info.h @@ -3366,16 +3366,11 @@ typedef enum state // Audience Members S_RANDOMAUDIENCE, - S_AUDIENCE_TOAD1, - S_AUDIENCE_TOAD2, - S_AUDIENCE_BOO1, - S_AUDIENCE_BOO2, - S_AUDIENCE_GMBA1, - S_AUDIENCE_GMBA2, - S_AUDIENCE_SHYG1, - S_AUDIENCE_SHYG2, - S_AUDIENCE_SNIF1, - S_AUDIENCE_SNIF2, + S_AUDIENCE_CHAO_CHEER1, + S_AUDIENCE_CHAO_CHEER2, + S_AUDIENCE_CHAO_WIN1, + S_AUDIENCE_CHAO_WIN2, + S_AUDIENCE_CHAO_LOSE, S_FANCHAR_KOTE, S_FANCHAR_RYAN, diff --git a/src/p_mobj.c b/src/p_mobj.c index 59b5c6cf..6c946e09 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8927,6 +8927,39 @@ void P_SceneryThinker(mobj_t *mobj) } P_CycleMobjState(mobj); + + if (mobj->type != MT_RANDOMAUDIENCE) + return; + + { + if (!mobj->colorized) // a fan of someone? + return; + + if (mobj->threshold >= 0) // not already happy or sad? + { + if (!playeringame[mobj->threshold] || players[mobj->threshold].spectator) // focused on a valid player? + return; + + if (!(players[mobj->threshold].exiting) && !(players[mobj->threshold].pflags & PF_TIMEOVER)) // not finished yet? + return; + + if (K_IsPlayerLosing(&players[mobj->threshold])) + mobj->threshold = -2; + else + { + mobj->threshold = -1; + S_StartSound(mobj, sfx_chaooo); + } + } + + if (mobj->threshold == -1) + mobj->angle += ANGLE_22h; + + if (((statenum_t)(mobj->state-states) != S_AUDIENCE_CHAO_CHEER2) || (mobj->tics != states[S_AUDIENCE_CHAO_CHEER2].tics)) // not at the start of your cheer jump? + return; + + P_SetMobjState(mobj, ((mobj->threshold == -1) ? S_AUDIENCE_CHAO_WIN2 : S_AUDIENCE_CHAO_LOSE)); + } } // @@ -9174,9 +9207,43 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } break; case MT_BIGRING: - mobj->destscale = 3*FRACUNIT; - P_SetScale(mobj, 3*FRACUNIT); + P_SetScale(mobj, (mobj->destscale = 3*FRACUNIT)); break; + case MT_RANDOMAUDIENCE: + { + fixed_t randu = P_RandomFixed(); + P_SetScale(mobj, (mobj->destscale <<= 1)); + if (randu < (FRACUNIT/9)) // a fan of someone? + { + UINT8 i, pcount = 0; + UINT8 pnum[MAXPLAYERS]; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + pnum[pcount] = i; + pcount++; + } + + if (pcount) + { + mobj->threshold = pnum[P_RandomKey(pcount)]; + mobj->color = players[mobj->threshold].skincolor; + mobj->colorized = true; + break; + } + } + + if (randu > (FRACUNIT/2)) + { + mobj->color = P_RandomKey(MAXSKINCOLORS-1)+1; + break; + } + + mobj->color = SKINCOLOR_AQUA; + break; + } default: break; } diff --git a/src/sounds.c b/src/sounds.c index 7c69eed7..938f35ea 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -813,6 +813,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mcitm1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"chaooo", false, 110, 24, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds diff --git a/src/sounds.h b/src/sounds.h index 13669e3a..9aaaf281 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -885,6 +885,7 @@ typedef enum sfx_hogbom, sfx_ddash, sfx_mcitm1, + sfx_chaooo, sfx_dbgsal, sfx_kwin, From 591ef1e3945849cf4bb0e722b1661ceb1d09742e Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 13 Sep 2018 14:34:41 +0100 Subject: [PATCH 11/37] Make the chao quieter (if it's still too loud, I can tone it down further, but not by much) --- src/sounds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sounds.c b/src/sounds.c index 938f35ea..c30a3e52 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -813,7 +813,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mcitm1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"chaooo", false, 110, 24, -1, NULL, 0, -1, -1, LUMPERROR}, + {"chaooo", false, 110, 64, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds From 395a83a56cd57ce3fc16b6cbf1d18c8ec8aec91f Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 13 Sep 2018 14:36:48 +0100 Subject: [PATCH 12/37] Dark SPB background --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 32b4a894..270bdf8a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5652,7 +5652,7 @@ static void K_drawKartItem(void) case KITEM_JAWZ: localpatch = kp_jawz[offset]; break; case KITEM_MINE: localpatch = kp_mine[offset]; break; case KITEM_BALLHOG: localpatch = kp_ballhog[offset]; break; - case KITEM_SPB: localpatch = kp_selfpropelledbomb[offset]; break; + case KITEM_SPB: localpatch = kp_selfpropelledbomb[offset]; localbg = kp_itembg[offset+1]; break; case KITEM_GROW: localpatch = kp_grow[offset]; break; case KITEM_SHRINK: localpatch = kp_shrink[offset]; break; case KITEM_THUNDERSHIELD: localpatch = kp_thundershield[offset]; break; From fd721d37614533dac45ddda6b84bd8fc9f5c116b Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 13 Sep 2018 14:40:50 +0100 Subject: [PATCH 13/37] Bugfix sad chao jumping in their sad state --- src/p_mobj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 6c946e09..c6bcc2ba 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8958,6 +8958,8 @@ void P_SceneryThinker(mobj_t *mobj) if (((statenum_t)(mobj->state-states) != S_AUDIENCE_CHAO_CHEER2) || (mobj->tics != states[S_AUDIENCE_CHAO_CHEER2].tics)) // not at the start of your cheer jump? return; + mobj->momz = 0; + P_SetMobjState(mobj, ((mobj->threshold == -1) ? S_AUDIENCE_CHAO_WIN2 : S_AUDIENCE_CHAO_LOSE)); } } From 57d333b6b552d22182d49cf0e66048e6876b5d1e Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 13 Sep 2018 19:01:36 +0100 Subject: [PATCH 14/37] Thunder shield stuff! * Slightly bigger visual size! * Light-shadow! * Makes player fullbright if you have it! * Visuals finally removed instantly on shield drop! * Uses dark background for item icons! * Goes behind the player on some frames, faking layering! --- src/info.c | 50 +++++++++++++++++++++++++------------------------- src/k_kart.c | 7 +++++-- src/p_mobj.c | 43 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 32 deletions(-) diff --git a/src/info.c b/src/info.c index 554f410a..172439f7 100644 --- a/src/info.c +++ b/src/info.c @@ -2784,30 +2784,30 @@ state_t states[NUMSTATES] = {SPR_LIGH, 2, 2, {NULL}, 0, 0, S_LIGHTNING4}, // S_LIGHTNING3 {SPR_LIGH, 3, 2, {NULL}, 0, 0, S_NULL}, // S_LIGHTNING4 - {SPR_THNS, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_THUNDERSHIELD2}, // S_THUNDERSHIELD1 - {SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_THUNDERSHIELD3}, // S_THUNDERSHIELD2 - {SPR_THNS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_THUNDERSHIELD4}, // S_THUNDERSHIELD3 - {SPR_THNS, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_THUNDERSHIELD5}, // S_THUNDERSHIELD4 - {SPR_THNS, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_THUNDERSHIELD6}, // S_THUNDERSHIELD5 - {SPR_THNS, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_THUNDERSHIELD7}, // S_THUNDERSHIELD6 - {SPR_THNS, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_THUNDERSHIELD8}, // S_THUNDERSHIELD7 - {SPR_THNS, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_THUNDERSHIELD9}, // S_THUNDERSHIELD8 - {SPR_THNS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_THUNDERSHIELD10}, // S_THUNDERSHIELD9 - {SPR_THNS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_THUNDERSHIELD11}, // S_THUNDERSHIELD10 - {SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD12}, // S_THUNDERSHIELD11 - {SPR_THNS, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_THUNDERSHIELD13}, // S_THUNDERSHIELD12 - {SPR_THNS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_THUNDERSHIELD14}, // S_THUNDERSHIELD13 - {SPR_THNS, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_THUNDERSHIELD15}, // S_THUNDERSHIELD14 - {SPR_THNS, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_THUNDERSHIELD16}, // S_THUNDERSHIELD15 - {SPR_THNS, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_THUNDERSHIELD17}, // S_THUNDERSHIELD16 - {SPR_THNS, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_THUNDERSHIELD18}, // S_THUNDERSHIELD17 - {SPR_THNS, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_THUNDERSHIELD19}, // S_THUNDERSHIELD18 - {SPR_THNS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_THUNDERSHIELD20}, // S_THUNDERSHIELD19 - {SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_THUNDERSHIELD21}, // S_THUNDERSHIELD20 - {SPR_THNS, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_THUNDERSHIELD22}, // S_THUNDERSHIELD21 - {SPR_THNS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_THUNDERSHIELD23}, // S_THUNDERSHIELD22 - {SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 - {SPR_THNS, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 + {SPR_THNS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_THUNDERSHIELD2}, // S_THUNDERSHIELD1 + {SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD3}, // S_THUNDERSHIELD2 + {SPR_THNS, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_THUNDERSHIELD4}, // S_THUNDERSHIELD3 + {SPR_THNS, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_THUNDERSHIELD5}, // S_THUNDERSHIELD4 + {SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_THUNDERSHIELD6}, // S_THUNDERSHIELD5 + {SPR_THNS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_THUNDERSHIELD7}, // S_THUNDERSHIELD6 + {SPR_THNS, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_THUNDERSHIELD8}, // S_THUNDERSHIELD7 + {SPR_THNS, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_THUNDERSHIELD9}, // S_THUNDERSHIELD8 + {SPR_THNS, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_THUNDERSHIELD10}, // S_THUNDERSHIELD9 + {SPR_THNS, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_THUNDERSHIELD11}, // S_THUNDERSHIELD10 + {SPR_THNS, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_THUNDERSHIELD12}, // S_THUNDERSHIELD11 + {SPR_THNS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_THUNDERSHIELD13}, // S_THUNDERSHIELD12 + {SPR_THNS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_THUNDERSHIELD14}, // S_THUNDERSHIELD13 + {SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD15}, // S_THUNDERSHIELD14 + {SPR_THNS, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_THUNDERSHIELD16}, // S_THUNDERSHIELD15 + {SPR_THNS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_THUNDERSHIELD17}, // S_THUNDERSHIELD16 + {SPR_THNS, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_THUNDERSHIELD18}, // S_THUNDERSHIELD17 + {SPR_THNS, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_THUNDERSHIELD19}, // S_THUNDERSHIELD18 + {SPR_THNS, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_THUNDERSHIELD20}, // S_THUNDERSHIELD19 + {SPR_THNS, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_THUNDERSHIELD21}, // S_THUNDERSHIELD20 + {SPR_THNS, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_THUNDERSHIELD22}, // S_THUNDERSHIELD21 + {SPR_THNS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_THUNDERSHIELD23}, // S_THUNDERSHIELD22 + {SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 + {SPR_THNS, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 {SPR_SINK, 0, 1, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK {SPR_SINK, 0|FF_TRANS80|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_SINK_SHIELD}, // S_SINK_SHIELD @@ -15255,7 +15255,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 8, // speed - 16*FRACUNIT, // radius + 20*FRACUNIT, // radius 56*FRACUNIT, // height 1, // display offset 16, // mass diff --git a/src/k_kart.c b/src/k_kart.c index 270bdf8a..ed13612f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2985,6 +2985,7 @@ void K_DropHnextList(player_t *player) K_DoThunderShield(player); player->kartstuff[k_itemamount] = 0; player->kartstuff[k_itemtype] = KITEM_NONE; + player->kartstuff[k_curshield] = 0; } nextwork = work->hnext; @@ -3771,7 +3772,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) void K_KartPlayerAfterThink(player_t *player) { - if (player->kartstuff[k_invincibilitytimer] + if (player->kartstuff[k_curshield] + || player->kartstuff[k_invincibilitytimer] || (player->kartstuff[k_growshrinktimer] != 0 && player->kartstuff[k_growshrinktimer] % 5 == 4)) // 4 instead of 0 because this is afterthink! { player->mo->frame |= FF_FULLBRIGHT; @@ -4539,6 +4541,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_curshield] <= 0) { mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD); + P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2)); P_SetTarget(&shield->target, player->mo); player->kartstuff[k_curshield] = 1; } @@ -5655,7 +5658,7 @@ static void K_drawKartItem(void) case KITEM_SPB: localpatch = kp_selfpropelledbomb[offset]; localbg = kp_itembg[offset+1]; break; case KITEM_GROW: localpatch = kp_grow[offset]; break; case KITEM_SHRINK: localpatch = kp_shrink[offset]; break; - case KITEM_THUNDERSHIELD: localpatch = kp_thundershield[offset]; break; + case KITEM_THUNDERSHIELD: localpatch = kp_thundershield[offset]; localbg = kp_itembg[offset+1]; break; case KITEM_HYUDORO: localpatch = kp_hyudoro[offset]; break; case KITEM_POGOSPRING: localpatch = kp_pogospring[offset]; break; case KITEM_KITCHENSINK: localpatch = kp_kitchensink[offset]; break; diff --git a/src/p_mobj.c b/src/p_mobj.c index c6bcc2ba..1381cefa 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6276,8 +6276,7 @@ static void P_RemoveOverlay(mobj_t *thing) void P_RunShadows(void) { - mobj_t *mobj; - mobj_t *next; + mobj_t *mobj, *next, *dest; for (mobj = shadowcap; mobj; mobj = next) { @@ -6322,7 +6321,12 @@ void P_RunShadows(void) // First scale to the same radius P_SetScale(mobj, FixedDiv(mobj->target->radius, mobj->info->radius)); - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + dest = mobj->target; + + if (dest->type == MT_THUNDERSHIELD) + dest = dest->target; + + P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z); if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height)) || (!(mobj->eflags & MFE_VERTICALFLIP) && (mobj->floorz < mobj->z))) @@ -6340,7 +6344,7 @@ void P_RunShadows(void) P_SetScale(mobj, FixedDiv(mobj->scale, max(FRACUNIT, ((mobj->target->z-mobj->z)/200)+FRACUNIT))); // Check new position to see if you should still be on that ledge - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->z); + P_TeleportMove(mobj, dest->x, dest->y, mobj->z); mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : mobj->floorz); @@ -8301,13 +8305,41 @@ void P_MobjThinker(mobj_t *mobj) P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); break; case MT_THUNDERSHIELD: + { + fixed_t destx, desty; if (!mobj->target || !mobj->target->health || (mobj->target->player && mobj->target->player->kartstuff[k_curshield] != 1)) { P_RemoveMobj(mobj); return; } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + P_SetScale(mobj, (mobj->destscale = (5*mobj->target->destscale)>>2)); + + if (!splitscreen /*&& rendermode != render_soft*/) + { + angle_t viewingangle; + statenum_t curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); + + if (players[displayplayer].awayviewtics) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); + else if (!camera.chase && players[displayplayer].mo) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); + else + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera.x, camera.y); + + if (curstate > S_THUNDERSHIELD15) + viewingangle += ANGLE_180; + destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); + desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); + } + else + { + destx = mobj->target->x; + desty = mobj->target->y; + } + + P_TeleportMove(mobj, destx, desty, mobj->target->z); break; + } case MT_KARMAHITBOX: if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator || (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper])) @@ -9264,6 +9296,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_JAWZ: case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: case MT_SSMINE: case MT_SSMINE_SHIELD: case MT_BALLHOG: case MT_SINK: + case MT_THUNDERSHIELD: P_SpawnShadowMobj(mobj); default: break; From ccc615e9b16eeab2e9c4f50a559233f3233506e0 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 13 Sep 2018 20:41:12 +0100 Subject: [PATCH 15/37] Fix a potential crash vector in the shadows code. (It DEFINITELY crashed when I was testing the thunder shield, for example.) --- src/p_mobj.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1381cefa..79d9c994 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6283,8 +6283,11 @@ void P_RunShadows(void) next = mobj->hnext; P_SetTarget(&mobj->hnext, NULL); - if (!mobj->target) + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + mobj->flags2 |= MF2_DONTDRAW; continue; // shouldn't you already be dead? + } if ((mobj->target->flags2 & MF2_DONTDRAW) || (((mobj->target->eflags & MFE_VERTICALFLIP) && mobj->target->z+mobj->target->height > mobj->target->ceilingz) From 32d64a8282361c1bb0721124e9ebed4c94a5ed74 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 13 Sep 2018 20:51:30 +0100 Subject: [PATCH 16/37] Make these sparks fullbright (thanks, Ancient Tomb!) --- src/info.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/info.c b/src/info.c index 172439f7..9581f238 100644 --- a/src/info.c +++ b/src/info.c @@ -1756,11 +1756,11 @@ state_t states[NUMSTATES] = {SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP // Super Sonic Spark - {SPR_SSPK, 0, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1 - {SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK3}, // S_SSPK2 - {SPR_SSPK, 2, 2, {NULL}, 0, 0, S_SSPK4}, // S_SSPK3 - {SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4 - {SPR_SSPK, 0, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5 + {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1 + {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK3}, // S_SSPK2 + {SPR_SSPK, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK4}, // S_SSPK3 + {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4 + {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5 // Freed Birdie {SPR_BIRD, 0, 4, {NULL}, 0, 0, S_BIRD2}, // S_BIRD1 From fadef55b1e5d295105a9d06d93619c2d5f2c71d2 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 14 Sep 2018 00:19:23 +0100 Subject: [PATCH 17/37] angel island drift strat plus ketchup --- src/d_player.h | 1 + src/dehacked.c | 4 ++++ src/info.c | 31 ++++++++++++++++++++++++- src/info.h | 6 +++++ src/k_kart.c | 63 ++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 97 insertions(+), 8 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 822ea305..373110dd 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -305,6 +305,7 @@ typedef enum k_accelboost, // Boost value smoothing for acceleration k_boostcam, // Camera push forward on boost k_destboostcam, // Ditto + k_aizdriftstrat, // Let go of your drift while boosting? Helper for the SICK STRATZ you have just unlocked k_itemroulette, // Used for the roulette when deciding what item to give you (was "pw_kartitem") k_roulettetype, // Used for the roulette, for deciding type (currently only used for Battle, to give you better items from Karma items) diff --git a/src/dehacked.c b/src/dehacked.c index 4658108a..fc0529a9 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6271,6 +6271,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KARTFIRE7", "S_KARTFIRE8", + // Angel Island Drift Strat Dust (what a mouthful!) + "S_KARTAIZDRIFTSTRAT", + // Invincibility Sparks "S_KARTINVULN_SMALL1", "S_KARTINVULN_SMALL2", @@ -7220,6 +7223,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BOOSTFLAME", "MT_BOOSTSMOKE", "MT_SNEAKERTRAIL", + "MT_AIZDRIFTSTRAT", "MT_SPARKLETRAIL", "MT_INVULNFLASH", "MT_WIPEOUTTRAIL", diff --git a/src/info.c b/src/info.c index 9581f238..b0783a69 100644 --- a/src/info.c +++ b/src/info.c @@ -60,7 +60,7 @@ char sprnames[NUMSPRITES + 1][5] = "BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI","DECO", "DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD","BRNG", "BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO","ITMI", - "ITMN","WANT","PBOM","RETI","VIEW" + "ITMN","WANT","PBOM","RETI","AIDU","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2601,6 +2601,8 @@ state_t states[NUMSTATES] = {SPR_KFRE, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_KARTFIRE8}, // S_KARTFIRE7 {SPR_KFRE, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_NULL}, // S_KARTFIRE8 + {SPR_AIDU, FF_ANIMATE|FF_PAPERSPRITE, 5*2, {NULL}, 5, 2, S_NULL}, // S_KARTAIZDRIFTSTRAT + {SPR_KINV, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KARTINVULN_SMALL2}, // S_KARTINVULN_SMALL1 {SPR_KINV, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_KARTINVULN_SMALL3}, // S_KARTINVULN_SMALL2 {SPR_KINV, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_KARTINVULN_SMALL4}, // S_KARTINVULN_SMALL3 @@ -14509,6 +14511,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_AIZDRIFTSTRAT + -1, // doomednum + S_KARTAIZDRIFTSTRAT,// spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 14*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_SPARKLETRAIL -1, // doomednum S_KARTINVULN_SMALL1, // spawnstate diff --git a/src/info.h b/src/info.h index c5f98983..13498810 100644 --- a/src/info.h +++ b/src/info.h @@ -641,6 +641,8 @@ typedef enum sprite SPR_PBOM, // player bomb SPR_RETI, // player reticule + SPR_AIDU, + SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw! SPR_FIRSTFREESLOT, @@ -3118,6 +3120,9 @@ typedef enum state S_KARTFIRE7, S_KARTFIRE8, + // Angel Island Drift Strat Dust (what a mouthful!) + S_KARTAIZDRIFTSTRAT, + // Invincibility Sparks S_KARTINVULN_SMALL1, S_KARTINVULN_SMALL2, @@ -4084,6 +4089,7 @@ typedef enum mobj_type MT_BOOSTFLAME, MT_BOOSTSMOKE, MT_SNEAKERTRAIL, + MT_AIZDRIFTSTRAT, MT_SPARKLETRAIL, MT_INVULNFLASH, MT_WIPEOUTTRAIL, diff --git a/src/k_kart.c b/src/k_kart.c index ed13612f..6ab905dc 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2271,7 +2271,7 @@ static void K_SpawnDriftSparks(player_t *player) if (player->kartstuff[k_driftcharge] <= (K_GetKartDriftSparkValue(player)*2)+(32*3)) spark->color = SKINCOLOR_DUSK; // transition else - spark->color = SKINCOLOR_RUBY; + spark->color = SKINCOLOR_KETCHUP; } else spark->color = SKINCOLOR_SAPPHIRE; @@ -2306,6 +2306,46 @@ static void K_SpawnDriftSparks(player_t *player) } } +static void K_SpawnAIZDust(player_t *player) +{ + fixed_t newx; + fixed_t newy; + mobj_t *spark; + angle_t travelangle; + + I_Assert(player != NULL); + I_Assert(player->mo != NULL); + I_Assert(!P_MobjWasRemoved(player->mo)); + + if (leveltime % 2 == 1) + return; + + if (!P_IsObjectOnGround(player->mo)) + return; + + travelangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + + { + newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle - (player->kartstuff[k_aizdriftstrat]*ANGLE_45), FixedMul(24*FRACUNIT, player->mo->scale)); + newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle - (player->kartstuff[k_aizdriftstrat]*ANGLE_45), FixedMul(24*FRACUNIT, player->mo->scale)); + spark = P_SpawnMobj(newx, newy, player->mo->z, MT_AIZDRIFTSTRAT); + + spark->angle = travelangle+(player->kartstuff[k_aizdriftstrat]*ANGLE_90); + P_SetScale(spark, (spark->destscale = (3*player->mo->scale)>>2)); + + spark->momx = (6*player->mo->momx)/5; + spark->momy = (6*player->mo->momy)/5; + //spark->momz = player->mo->momz/2; + + spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->eflags & MF2_DONTDRAW); + spark->eflags = (spark->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP3)|(player->mo->eflags & MFE_DRAWONLYFORP3); + spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP4)|(player->mo->eflags & MFE_DRAWONLYFORP4); + } +} + void K_SpawnBoostTrail(player_t *player) { fixed_t newx; @@ -3947,16 +3987,14 @@ static void K_KartDrift(player_t *player, boolean onground) { // Starting left drift player->kartstuff[k_drift] = 1; - player->kartstuff[k_driftend] = 0; - player->kartstuff[k_driftcharge] = 0; + player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0; } else if ((player->cmd.driftturn < 0) && player->speed > FixedMul(10<<16, player->mo->scale) && player->kartstuff[k_jmp] == 1 && (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != -1) { // Starting right drift player->kartstuff[k_drift] = -1; - player->kartstuff[k_driftend] = 0; - player->kartstuff[k_driftcharge] = 0; + player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0; } else if (player->kartstuff[k_jmp] == 0) // || player->kartstuff[k_turndir] == 0) { @@ -4015,9 +4053,20 @@ static void K_KartDrift(player_t *player, boolean onground) if (player->kartstuff[k_spinouttimer] > 0 // banana peel || player->speed < FixedMul(10<<16, player->mo->scale)) // you're too slow! { - player->kartstuff[k_drift] = 0; - player->kartstuff[k_driftcharge] = 0; + player->kartstuff[k_drift] = player->kartstuff[k_driftcharge] = player->kartstuff[k_aizdriftstrat] = 0; } + + if ((!player->kartstuff[k_sneakertimer]) + || (!player->cmd.driftturn) + || (player->cmd.driftturn > 0) != (player->kartstuff[k_aizdriftstrat] > 0)) + { + if (!player->kartstuff[k_drift]) + player->kartstuff[k_aizdriftstrat] = 0; + else + player->kartstuff[k_aizdriftstrat] = ((player->kartstuff[k_drift] > 0) ? 1 : -1); + } + else if (player->kartstuff[k_aizdriftstrat] && !player->kartstuff[k_drift]) + K_SpawnAIZDust(player); } // // K_KartUpdatePosition From 6532c9ccf7176f5cb64d3a6a4e288760eb629d0c Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 14 Sep 2018 00:29:39 -0400 Subject: [PATCH 18/37] Add to DeHackEd! --- src/dehacked.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dehacked.c b/src/dehacked.c index fc0529a9..4621357a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7703,6 +7703,7 @@ static const char *const KARTSTUFF_LIST[] = { "ACCELBOOST", "BOOSTCAM", "DESTBOOSTCAM", + "AIZDRIFTSTRAT", "ITEMROULETTE", "ROULETTETYPE", From ce5abdc6e361ea075eed701563ebcb6f4ae16d1b Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 16 Sep 2018 10:31:24 +0200 Subject: [PATCH 19/37] Thunder Shield effect hardcode. --- src/dehacked.c | 1 + src/info.c | 53 ++++++++++++++++++++++++++++++- src/info.h | 54 +++++++++++++++++++++++++++++++ src/k_kart.c | 86 ++++++++++++++++++++++++++++++++++++++------------ src/k_kart.h | 2 +- src/p_enemy.c | 20 ++++++++++++ 6 files changed, 194 insertions(+), 22 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 05be2583..040c403b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1828,6 +1828,7 @@ static actionpointer_t actionpointers[] = {{A_JawzExplode}, "A_JAWZEXPLODE"}, // SRB2kart {{A_MineExplode}, "A_MINEEXPLODE"}, // SRB2kart {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, // SRB2kart + {{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart {{A_OrbitNights}, "A_ORBITNIGHTS"}, {{A_GhostMe}, "A_GHOSTME"}, {{A_SetObjectState}, "A_SETOBJECTSTATE"}, diff --git a/src/info.c b/src/info.c index 74a7a4d3..a9c86c03 100644 --- a/src/info.c +++ b/src/info.c @@ -60,7 +60,7 @@ char sprnames[NUMSPRITES + 1][5] = "BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI", "DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD", "BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO", - "ITMI","ITMN","WANT","PBOM","RETI","VIEW" + "ITMI","ITMN","WANT","PBOM","RETI","VIEW","KSPK","LZI1","LZI2","KLIT" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -3016,6 +3016,57 @@ state_t states[NUMSTATES] = {SPR_RNDM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERITEM {SPR_PBOM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL + + // Oh no it's annoying lightning states....... + // Lightning Sparks (it's the ones we'll use for the radius) + {SPR_KSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KSPARK2}, // S_KSPARK1 + {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK3}, // S_KSPARK2 + {SPR_KSPK, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_KSPARK4}, // S_KSPARK3 + {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK5}, // S_KSPARK4 + {SPR_KSPK, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_KSPARK6}, // S_KSPARK5 + {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK7}, // S_KSPARK6 + {SPR_KSPK, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_KSPARK8}, // S_KSPARK7 + {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK9}, // S_KSPARK8 + {SPR_KSPK, FF_TRANS40|FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_KSPARK10}, // S_KSPARK9 + {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK11}, // S_KSPARK10 + {SPR_KSPK, FF_TRANS50|FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_KSPARK12}, // S_KSPARK11 + {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK13}, // S_KSPARK12 + {SPR_KSPK, FF_TRANS60|FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_NULL}, // S_KSPARK13 + + // The straight bolt... + {SPR_LZI1, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO12}, // S_LZIO11 + {SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO13}, // S_LZIO12 + {SPR_LZI1, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO14}, // S_LZIO13 + {SPR_LZI1, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO15}, // S_LZIO14 + {SPR_NULL, FF_FULLBRIGHT, 4, {A_LightningFollowPlayer}, 0, 0, S_LZIO16}, // S_LZIO15 + {SPR_LZI1, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO17}, // S_LZIO16 + {SPR_NULL, 0, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO18}, // S_LZIO17 + {SPR_LZI1, FF_TRANS50|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO19}, // S_LZIO18 + {SPR_LZI1, FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO19 + + {SPR_NULL, FF_FULLBRIGHT, 6, {A_LightningFollowPlayer}, 0, 0, S_LZIO22}, // S_LZIO21 + {SPR_LZI2, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO23}, // S_LZIO22 + {SPR_LZI2, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO24}, // S_LZIO23 + {SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO25}, // S_LZIO24 + {SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO26}, // S_LZIO25 + {SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO27}, // S_LZIO26 + {SPR_LZI2, FF_TRANS30|FF_FULLBRIGHT|2, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO28}, // S_LZIO27 + {SPR_NULL, 0, 4, {A_LightningFollowPlayer}, 0, 0, S_LZIO29}, // S_LZIO28 + {SPR_LZI2, FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO29 + + // The slanted bolt. Man these states are boring as all heck to do. + {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT2}, // S_KLIT1 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT3}, // S_KLIT2 + {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|1, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT4}, // S_KLIT3 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT5}, // S_KLIT4 + {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|2, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT6}, // S_KLIT5 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT7}, // S_KLIT6 + {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|3, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT8}, // S_KLIT7 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT9}, // S_KLIT8 + {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT10}, // S_KLIT9 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT11}, // S_KLIT10 + {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT12}, // S_KLIT11 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1}, // S_KLIT12 #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK diff --git a/src/info.h b/src/info.h index 8d27944f..b5b12d27 100644 --- a/src/info.h +++ b/src/info.h @@ -168,6 +168,7 @@ void A_JawzChase(); // SRB2kart void A_JawzExplode(); // SRB2kart void A_MineExplode(); // SRB2kart void A_BallhogExplode(); // SRB2kart +void A_LightningFollowPlayer(); // SRB2kart: Lightning shield effect player chasing void A_OrbitNights(); void A_GhostMe(); void A_SetObjectState(); @@ -643,6 +644,11 @@ typedef enum sprite SPR_RETI, // player reticule SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw! + + SPR_KSPK, // Spark radius for the lightning shield + SPR_LZI1, // Lightning that falls on the player for lightning shield + SPR_LZI2, // ditto + SPR_KLIT, // You have a twisted mind. But this actually is for the diagonal lightning. SPR_FIRSTFREESLOT, SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, @@ -3556,6 +3562,54 @@ typedef enum state S_PLAYERITEM, S_KARMAWHEEL, + + // Lightning shield use stuff; + S_KSPARK1, // Sparkling Radius + S_KSPARK2, + S_KSPARK3, + S_KSPARK4, + S_KSPARK5, + S_KSPARK6, + S_KSPARK7, + S_KSPARK8, + S_KSPARK9, + S_KSPARK10, + S_KSPARK11, + S_KSPARK12, + S_KSPARK13, // ... that's an awful lot. + + S_LZIO11, // Straight lightning bolt + S_LZIO12, + S_LZIO13, + S_LZIO14, + S_LZIO15, + S_LZIO16, + S_LZIO17, + S_LZIO18, + S_LZIO19, + + S_LZIO21, // Straight lightning bolt (flipped) + S_LZIO22, + S_LZIO23, + S_LZIO24, + S_LZIO25, + S_LZIO26, + S_LZIO27, + S_LZIO28, + S_LZIO29, + + S_KLIT1, // Diagonal lightning. No, it not being straight doesn't make it gay. + S_KLIT2, + S_KLIT3, + S_KLIT4, + S_KLIT5, + S_KLIT6, + S_KLIT7, + S_KLIT8, + S_KLIT9, + S_KLIT10, + S_KLIT11, + S_KLIT12, #ifdef SEENAMES S_NAMECHECK, diff --git a/src/k_kart.c b/src/k_kart.c index 94cdc399..755f8a92 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2706,11 +2706,57 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map return mo; } +INT32 LightningRadius = 320; + static void K_DoThunderShield(player_t *player) { + mobj_t *mo; + int i = 0; + fixed_t sx; + fixed_t sy; + S_StartSound(player->mo, sfx_s3k45); //player->kartstuff[k_thunderanim] = 35; P_NukeEnemies(player->mo, player->mo, RING_DIST/4); + + // spawn vertical bolt + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); + P_SetTarget(&mo->target, player->mo); + P_SetMobjState(mo, S_LZIO11); + mo->color = SKINCOLOR_TEAL; + mo->scale = player->mo->scale*3 + (player->mo->scale/2); + + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); + P_SetTarget(&mo->target, player->mo); + P_SetMobjState(mo, S_LZIO21); + mo->color = SKINCOLOR_CYAN; + mo->scale = player->mo->scale*3 + (player->mo->scale/2); + + // spawn horizontal bolts; + for (i=0; i<7; i++) + { + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); + mo->angle = P_RandomRange(0, 359)*ANG1; + mo->fuse = P_RandomRange(20, 50); + P_SetTarget(&mo->target, player->mo); + P_SetMobjState(mo, S_KLIT1); + } + + // spawn the radius thing: + /*x = source->x + source->momx + FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); + y = source->y + source->momy + FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT));*/ + + angle_t an = ANGLE_22h; + + for (i=0; i<15; i++) + { + sx = player->mo->x + FixedMul((player->mo->scale*LightningRadius), FINECOSINE((an*i)>>ANGLETOFINESHIFT)); + sy = player->mo->y + FixedMul((player->mo->scale*LightningRadius), FINESINE((an*i)>>ANGLETOFINESHIFT)); + mo = P_SpawnMobj(sx, sy, player->mo->z, MT_THOK); + mo->scale = player->mo->scale*3; + P_SetMobjState(mo, S_KSPARK1); + } + } static void K_DoHyudoroSteal(player_t *player) @@ -5179,52 +5225,52 @@ void K_LoadKartHUDGraphics(void) } // For the item toggle menu -const char *K_GetItemPatch(UINT8 item, boolean small) +const char *K_GetItemPatch(UINT8 item, boolean smoll) { switch (item) { case KITEM_SNEAKER: case KRITEM_TRIPLESNEAKER: - return (small ? "K_ISSHOE" : "K_ITSHOE"); + return (smoll ? "K_ISSHOE" : "K_ITSHOE"); case KITEM_ROCKETSNEAKER: - return (small ? "K_ISRSHE" : "K_ITRSHE"); + return (smoll ? "K_ISRSHE" : "K_ITRSHE"); case KITEM_INVINCIBILITY: - return (small ? "K_ISINV1" : "K_ITINV1"); + return (smoll ? "K_ISINV1" : "K_ITINV1"); case KITEM_BANANA: case KRITEM_TRIPLEBANANA: case KRITEM_TENFOLDBANANA: - return (small ? "K_ISBANA" : "K_ITBANA"); + return (smoll ? "K_ISBANA" : "K_ITBANA"); case KITEM_EGGMAN: - return (small ? "K_ISEGGM" : "K_ITEGGM"); + return (smoll ? "K_ISEGGM" : "K_ITEGGM"); case KITEM_ORBINAUT: - return (small ? "K_ISORBN" : "K_ITORB1"); + return (smoll ? "K_ISORBN" : "K_ITORB1"); case KITEM_JAWZ: case KRITEM_DUALJAWZ: - return (small ? "K_ISJAWZ" : "K_ITJAWZ"); + return (smoll ? "K_ISJAWZ" : "K_ITJAWZ"); case KITEM_MINE: - return (small ? "K_ISMINE" : "K_ITMINE"); + return (smoll ? "K_ISMINE" : "K_ITMINE"); case KITEM_BALLHOG: - return (small ? "K_ISBHOG" : "K_ITBHOG"); + return (smoll ? "K_ISBHOG" : "K_ITBHOG"); case KITEM_SPB: - return (small ? "K_ISSPB" : "K_ITSPB"); + return (smoll ? "K_ISSPB" : "K_ITSPB"); case KITEM_GROW: - return (small ? "K_ISGROW" : "K_ITGROW"); + return (smoll ? "K_ISGROW" : "K_ITGROW"); case KITEM_SHRINK: - return (small ? "K_ISSHRK" : "K_ITSHRK"); + return (smoll ? "K_ISSHRK" : "K_ITSHRK"); case KITEM_THUNDERSHIELD: - return (small ? "K_ISTHNS" : "K_ITTHNS"); + return (smoll ? "K_ISTHNS" : "K_ITTHNS"); case KITEM_HYUDORO: - return (small ? "K_ISHYUD" : "K_ITHYUD"); + return (smoll ? "K_ISHYUD" : "K_ITHYUD"); case KITEM_POGOSPRING: - return (small ? "K_ISPOGO" : "K_ITPOGO"); + return (smoll ? "K_ISPOGO" : "K_ITPOGO"); case KITEM_KITCHENSINK: - return (small ? "K_ISSINK" : "K_ITSINK"); + return (smoll ? "K_ISSINK" : "K_ITSINK"); case KRITEM_TRIPLEORBINAUT: - return (small ? "K_ISORBN" : "K_ITORB3"); + return (smoll ? "K_ISORBN" : "K_ITORB3"); case KRITEM_QUADORBINAUT: - return (small ? "K_ISORBN" : "K_ITORB4"); + return (smoll ? "K_ISORBN" : "K_ITORB4"); default: - return (small ? "K_ISSAD" : "K_ITSAD"); + return (smoll ? "K_ISSAD" : "K_ITSAD"); } } diff --git a/src/k_kart.h b/src/k_kart.h index 9865d373..8a30537c 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -57,7 +57,7 @@ void K_CalculateBattleWanted(void); void K_CheckBumpers(void); void K_CheckSpectateStatus(void); -const char *K_GetItemPatch(UINT8 item, boolean small); +const char *K_GetItemPatch(UINT8 item, boolean smoll); INT32 K_calcSplitFlags(INT32 snapflags); void K_LoadKartHUDGraphics(void); fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my); diff --git a/src/p_enemy.c b/src/p_enemy.c index 83011674..74feba68 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -192,6 +192,7 @@ void A_JawzChase(mobj_t *actor); // SRB2kart void A_JawzExplode(mobj_t *actor); // SRB2kart void A_MineExplode(mobj_t *actor); // SRB2kart void A_BallhogExplode(mobj_t *actor); // SRB2kart +void A_LightningFollowPlayer(mobj_t *actor); // SRB2kart void A_OrbitNights(mobj_t *actor); void A_GhostMe(mobj_t *actor); void A_SetObjectState(mobj_t *actor); @@ -8313,6 +8314,25 @@ void A_BallhogExplode(mobj_t *actor) S_StartSound(mo2, actor->info->deathsound); return; } + +// A_LightningFollowPlayer: +// Dumb simple function that gives a mobj its target's momentums without updating its angle. +void A_LightningFollowPlayer(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LightningFollowPlayer", actor)) + return; +#endif + if (actor->target) + { + P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); + actor->momx = actor->target->momx; + actor->momy = actor->target->momy; + actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame. + } + return; +} + //} // Function: A_OrbitNights From 09287df89084e125a1d1e5926e9cda9009a0030b Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 16 Sep 2018 11:16:30 +0200 Subject: [PATCH 20/37] Radius is now a define --- src/k_kart.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 755f8a92..d9365752 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2706,7 +2706,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map return mo; } -INT32 LightningRadius = 320; +#define THUNDERRADIUS 320 static void K_DoThunderShield(player_t *player) { @@ -2742,21 +2742,16 @@ static void K_DoThunderShield(player_t *player) P_SetMobjState(mo, S_KLIT1); } - // spawn the radius thing: - /*x = source->x + source->momx + FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); - y = source->y + source->momy + FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT));*/ - + // spawn the radius thing: angle_t an = ANGLE_22h; - for (i=0; i<15; i++) { - sx = player->mo->x + FixedMul((player->mo->scale*LightningRadius), FINECOSINE((an*i)>>ANGLETOFINESHIFT)); - sy = player->mo->y + FixedMul((player->mo->scale*LightningRadius), FINESINE((an*i)>>ANGLETOFINESHIFT)); + sx = player->mo->x + FixedMul((player->mo->scale*THUNDERRADIUS), FINECOSINE((an*i)>>ANGLETOFINESHIFT)); + sy = player->mo->y + FixedMul((player->mo->scale*THUNDERRADIUS), FINESINE((an*i)>>ANGLETOFINESHIFT)); mo = P_SpawnMobj(sx, sy, player->mo->z, MT_THOK); mo->scale = player->mo->scale*3; P_SetMobjState(mo, S_KSPARK1); } - } static void K_DoHyudoroSteal(player_t *player) From a1045d232bc488e2dd61884916560ac228a5434f Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 18 Sep 2018 17:40:39 +0100 Subject: [PATCH 21/37] :boi: (fix driftsparks, and subsequently sliptides because i copypasted most of the code for them, disappearing underwater) --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6ab905dc..b294b9f5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2297,7 +2297,7 @@ static void K_SpawnDriftSparks(player_t *player) P_SetMobjState(spark, S_DRIFTSPARK_A1); } - spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->eflags & MF2_DONTDRAW); + spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->flags2 & MF2_DONTDRAW); spark->eflags = (spark->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); @@ -2337,7 +2337,7 @@ static void K_SpawnAIZDust(player_t *player) spark->momy = (6*player->mo->momy)/5; //spark->momz = player->mo->momz/2; - spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->eflags & MF2_DONTDRAW); + spark->flags2 = (spark->flags2 & ~MF2_DONTDRAW)|(player->mo->flags2 & MF2_DONTDRAW); spark->eflags = (spark->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP1)|(player->mo->eflags & MFE_DRAWONLYFORP1); spark->eflags = (spark->eflags & ~MFE_DRAWONLYFORP2)|(player->mo->eflags & MFE_DRAWONLYFORP2); From 73c66e3bc49eb17547dc6aa6aff2f864a387e968 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 20 Sep 2018 18:31:38 +0200 Subject: [PATCH 22/37] Spark radius now follows players --- src/info.c | 26 +++++++++++++------------- src/k_kart.c | 3 +++ src/p_enemy.c | 11 ++++++++++- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/info.c b/src/info.c index a9c86c03..4bc35d4c 100644 --- a/src/info.c +++ b/src/info.c @@ -3019,19 +3019,19 @@ state_t states[NUMSTATES] = // Oh no it's annoying lightning states....... // Lightning Sparks (it's the ones we'll use for the radius) - {SPR_KSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KSPARK2}, // S_KSPARK1 - {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK3}, // S_KSPARK2 - {SPR_KSPK, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_KSPARK4}, // S_KSPARK3 - {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK5}, // S_KSPARK4 - {SPR_KSPK, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_KSPARK6}, // S_KSPARK5 - {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK7}, // S_KSPARK6 - {SPR_KSPK, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_KSPARK8}, // S_KSPARK7 - {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK9}, // S_KSPARK8 - {SPR_KSPK, FF_TRANS40|FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_KSPARK10}, // S_KSPARK9 - {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK11}, // S_KSPARK10 - {SPR_KSPK, FF_TRANS50|FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_KSPARK12}, // S_KSPARK11 - {SPR_NULL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_KSPARK13}, // S_KSPARK12 - {SPR_KSPK, FF_TRANS60|FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_NULL}, // S_KSPARK13 + {SPR_KSPK, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK2}, // S_KSPARK1 + {SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK3}, // S_KSPARK2 + {SPR_KSPK, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK4}, // S_KSPARK3 + {SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK5}, // S_KSPARK4 + {SPR_KSPK, FF_FULLBRIGHT|2, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK6}, // S_KSPARK5 + {SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK7}, // S_KSPARK6 + {SPR_KSPK, FF_FULLBRIGHT|3, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK8}, // S_KSPARK7 + {SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK9}, // S_KSPARK8 + {SPR_KSPK, FF_TRANS40|FF_FULLBRIGHT|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK10}, // S_KSPARK9 + {SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK11}, // S_KSPARK10 + {SPR_KSPK, FF_TRANS50|FF_FULLBRIGHT|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK12}, // S_KSPARK11 + {SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK13}, // S_KSPARK12 + {SPR_KSPK, FF_TRANS60|FF_FULLBRIGHT|6, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_KSPARK13 // The straight bolt... {SPR_LZI1, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO12}, // S_LZIO11 diff --git a/src/k_kart.c b/src/k_kart.c index d9365752..962b7003 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2749,7 +2749,10 @@ static void K_DoThunderShield(player_t *player) sx = player->mo->x + FixedMul((player->mo->scale*THUNDERRADIUS), FINECOSINE((an*i)>>ANGLETOFINESHIFT)); sy = player->mo->y + FixedMul((player->mo->scale*THUNDERRADIUS), FINESINE((an*i)>>ANGLETOFINESHIFT)); mo = P_SpawnMobj(sx, sy, player->mo->z, MT_THOK); + mo-> angle = an*i; + mo->extravalue1 = THUNDERRADIUS; // Used to know whether we should teleport by radius or something. mo->scale = player->mo->scale*3; + P_SetTarget(&mo->target, player->mo); P_SetMobjState(mo, S_KSPARK1); } } diff --git a/src/p_enemy.c b/src/p_enemy.c index 74feba68..123aa265 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8323,9 +8323,18 @@ void A_LightningFollowPlayer(mobj_t *actor) if (LUA_CallAction("A_LightningFollowPlayer", actor)) return; #endif + fixed_t sx, sy; if (actor->target) { - P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); + if (actor->extravalue1) // Make the radius also follow the player somewhat accuratly + { + sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT)); + sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT)); + P_TeleportMove(actor, sx, sy, actor->target->z); + } + else // else just teleport to player directly + P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); + actor->momx = actor->target->momx; actor->momy = actor->target->momy; actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame. From 20222c47e70e62ca267ddf7f1a88be667f9e97b6 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 21 Sep 2018 22:06:27 +0100 Subject: [PATCH 23/37] Okay, seems like reducing it to 1x is enough - making it singular is overkill and means that often if the furthest one away from you is the one to yell, you'll barely hear it. At least this way you'll only hear overkill chao if you're super close to the stands and the mapper's placed way too many --- src/sounds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sounds.c b/src/sounds.c index 469427ae..a85da8e0 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -814,7 +814,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kpogos", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mcitm1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"chaooo", false, 110, 64, -1, NULL, 0, -1, -1, LUMPERROR}, + {"chaooo", false, 110, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds From 23090e82b59600eb8ac5f55ef1848a1cdbb14201 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 22 Sep 2018 01:15:04 +0200 Subject: [PATCH 24/37] Changed thundershield sound --- src/k_kart.c | 2 +- src/sounds.c | 1 + src/sounds.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 962b7003..2f60f257 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2715,7 +2715,7 @@ static void K_DoThunderShield(player_t *player) fixed_t sx; fixed_t sy; - S_StartSound(player->mo, sfx_s3k45); + S_StartSound(player->mo, sfx_zio3); //player->kartstuff[k_thunderanim] = 35; P_NukeEnemies(player->mo, player->mo, RING_DIST/4); diff --git a/src/sounds.c b/src/sounds.c index ec88786c..4ab11a28 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -813,6 +813,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"zio3", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds {"kwin", false, 64, 0, -1, NULL, 0, SKSWIN, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 980c097e..35b0fb53 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -885,6 +885,7 @@ typedef enum sfx_hogbom, sfx_ddash, sfx_dbgsal, + sfx_zio3, sfx_kwin, sfx_klose, From f8c9ef94317770725e5a41fcebf299397f6c78c4 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 22 Sep 2018 01:47:13 +0200 Subject: [PATCH 25/37] Did everything toaster suggested --- src/info.c | 2 +- src/info.h | 6 +++--- src/k_kart.c | 2 ++ src/sounds.c | 2 +- src/sounds.h | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/info.c b/src/info.c index 4bc35d4c..397bdfce 100644 --- a/src/info.c +++ b/src/info.c @@ -60,7 +60,7 @@ char sprnames[NUMSPRITES + 1][5] = "BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI", "DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD", "BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO", - "ITMI","ITMN","WANT","PBOM","RETI","VIEW","KSPK","LZI1","LZI2","KLIT" + "ITMI","ITMN","WANT","PBOM","RETI","KSPK","LZI1","LZI2","KLIT","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) diff --git a/src/info.h b/src/info.h index b5b12d27..152b9df0 100644 --- a/src/info.h +++ b/src/info.h @@ -642,14 +642,14 @@ typedef enum sprite SPR_PBOM, // player bomb SPR_RETI, // player reticule - - SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw! SPR_KSPK, // Spark radius for the lightning shield SPR_LZI1, // Lightning that falls on the player for lightning shield SPR_LZI2, // ditto SPR_KLIT, // You have a twisted mind. But this actually is for the diagonal lightning. - + + SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw! + SPR_FIRSTFREESLOT, SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, NUMSPRITES diff --git a/src/k_kart.c b/src/k_kart.c index 2f60f257..6460c94e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2757,6 +2757,8 @@ static void K_DoThunderShield(player_t *player) } } +#undef THUNDERRADIUS + static void K_DoHyudoroSteal(player_t *player) { INT32 i, numplayers = 0; diff --git a/src/sounds.c b/src/sounds.c index 4ab11a28..b794045f 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -812,8 +812,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"hogbom", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"zio3", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"dbgsal", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds {"kwin", false, 64, 0, -1, NULL, 0, SKSWIN, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 35b0fb53..449c50aa 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -884,8 +884,8 @@ typedef enum sfx_noooo2, sfx_hogbom, sfx_ddash, - sfx_dbgsal, sfx_zio3, + sfx_dbgsal, sfx_kwin, sfx_klose, From 2e158f2c2144d910ddf9906d921e1804e87d7e7d Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 13:22:00 +0100 Subject: [PATCH 26/37] Add a scroll bar to the addons menu. Should hopefully make the temperature gauge a little less problematic... --- src/m_menu.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index cbcd44dd..055eab80 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4530,8 +4530,9 @@ static boolean M_AddonsRefresh(void) static void M_DrawAddons(void) { INT32 x, y; - ssize_t i, max; + ssize_t i, m; const UINT8 *flashcol = NULL; + UINT8 hilicol; // hack - need to refresh at end of frame to handle addfile... if (refreshdirmenu & M_AddonsRefresh()) @@ -4565,26 +4566,45 @@ static void M_DrawAddons(void) x = currentMenu->x; y = currentMenu->y + 1; + hilicol = V_GetStringColormap(highlightflags)[120]; + 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), 1, V_GetStringColormap(highlightflags)[120]); - V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 30); + 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); - V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1), 239); + m = (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1); + V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 239); + + // scrollbar! + if (sizedirmenu <= (2*numaddonsshown + 1)) + i = 0; + else + { + ssize_t q = m; + m = ((2*numaddonsshown + 1) * m)/sizedirmenu; + if (dir_on[menudepthleft] <= numaddonsshown) // all the way up + i = 0; + else if (sizedirmenu <= (dir_on[menudepthleft] + numaddonsshown + 1)) // all the way down + i = q-m; + else + i = ((dir_on[menudepthleft] - numaddonsshown) * (q-m))/(sizedirmenu - (2*numaddonsshown + 1)); + } + + V_DrawFill(x + MAXSTRINGLENGTH*8+5 - 21, (y - 1) + i, 1, m, hilicol); // get bottom... - max = dir_on[menudepthleft] + numaddonsshown + 1; - if (max > (ssize_t)sizedirmenu) - max = sizedirmenu; + m = dir_on[menudepthleft] + numaddonsshown + 1; + if (m > (ssize_t)sizedirmenu) + m = sizedirmenu; // then top... - i = max - (2*numaddonsshown + 1); + i = m - (2*numaddonsshown + 1); // then adjust! if (i < 0) { - if ((max -= i) > (ssize_t)sizedirmenu) - max = sizedirmenu; + if ((m -= i) > (ssize_t)sizedirmenu) + m = sizedirmenu; i = 0; } @@ -4594,7 +4614,7 @@ static void M_DrawAddons(void) if (skullAnimCounter < 4) flashcol = V_GetStringColormap(highlightflags); - for (; i < max; i++) + for (; i < m; i++) { UINT32 flags = V_ALLOWLOWERCASE; if (y > BASEVIDHEIGHT) break; @@ -4626,7 +4646,7 @@ static void M_DrawAddons(void) y += 16; } - if (max != (ssize_t)sizedirmenu) + if (m != (ssize_t)sizedirmenu) V_DrawString(19, y-12 + (skullAnimCounter/5), highlightflags, "\x1B"); y = BASEVIDHEIGHT - currentMenu->y + 1; From c5e16f183eb06e772996ab1445883ff597d4adf5 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 13:23:03 +0100 Subject: [PATCH 27/37] Fix Sryder's crash (incorrect setting of dir_on when searching in subfolders). Also, correct a minor copypaste failure in one of the I_Errors' messages. --- src/filesrch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index e1e2b39d..98be1f39 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -701,7 +701,7 @@ void searchfilemenu(char *tempname) if (tempname) { - dir_on[menudepthleft] = first; + dir_on[menudepthleft] = 0; //first; -- can't be first, causes problems Z_Free(tempname); } } @@ -886,7 +886,7 @@ boolean preparefilemenu(boolean samedepth) if ((menudepthleft != menudepth-1) // now for UP... entry && !(coredirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)))) - I_Error("searchfilemenu(): could not create \"UP...\"."); + I_Error("preparefilemenu(): could not create \"UP...\"."); menupath[menupathindex[menudepthleft]] = 0; sizecoredirmenu = (numfolders+pos); // just in case things shrink between opening and rewind From fa65cbb43efb7a07e38fa5425bc2bc60633720ee Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 13:34:49 +0100 Subject: [PATCH 28/37] Somehow butchered the code cleanliness (indentation/not taking advantage of a macro I defined specifically for this) here a little by accident - tidied up. --- src/m_menu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 055eab80..6199ecf3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4622,12 +4622,13 @@ static void M_DrawAddons(void) #define type (UINT8)(dirmenu[i][DIR_TYPE]) { if (type & EXT_LOADED) - flags |= V_TRANSLUCENT; - - V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); - - if (type & EXT_LOADED) + { + flags |= V_TRANSLUCENT; + V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, addonsp[(type & ~EXT_LOADED)]); V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]); + } + else + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]); if ((size_t)i == dir_on[menudepthleft]) { From 73116f2b6009dd1d4ce2aea120a1fff5fbd9c872 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 16:13:58 +0100 Subject: [PATCH 29/37] The pipeline halted for some reason, so here's the smallest possible legitimate change to bump it back into action: Replacing commenting-out with `#ifdef`ing. --- src/m_menu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6199ecf3..5d0448ce 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4731,12 +4731,15 @@ static void M_HandleAddons(INT32 choice) char *tempname = NULL; if (dirmenu && dirmenu[dir_on[menudepthleft]]) tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL - searchfilemenu(tempname); - /*if (!preparefilemenu(true)) +#if 0 // much slower + if (!preparefilemenu(true)) { UNEXIST; return; - }*/ + } +#else // streamlined + searchfilemenu(tempname); +#endif } switch (choice) From d2d6e67f48c1a246f107dc4db6d5a39b63523e84 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 16:39:07 +0100 Subject: [PATCH 30/37] Forgot I did this optimisation! Updated for the new colours. --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index f8842cda..46d34acc 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1291,7 +1291,7 @@ UINT8 *V_GetStringColormap(INT32 colorflags) } #else // optimised colorflags = ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT); - if (!colorflags || colorflags > 8) // INT32 is signed, but V_CHARCOLORMASK is a very restrictive mask. + if (!colorflags || colorflags > 15) // INT32 is signed, but V_CHARCOLORMASK is a very restrictive mask. return NULL; return (purplemap+((colorflags-1)<<8)); #endif From a1ad4d79d00244e556fb2169517ce7dab091226a Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 19:58:15 +0100 Subject: [PATCH 31/37] Turns out `Playing()` evaluates to false when playing back demos. Who knew? --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index dd0c6011..384cc099 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6348,7 +6348,7 @@ static void K_drawKartMinimap(void) // Draw the HUD only when playing in a level. // hu_stuff needs this, unlike st_stuff. - if (!(Playing() && gamestate == GS_LEVEL)) + if (!demoplayback && !(Playing() && gamestate == GS_LEVEL)) return; if (stplyr != &players[displayplayer]) From de91eb97935ec5ad071e1826debb35110c2846a8 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 22:34:59 +0100 Subject: [PATCH 32/37] You're right, this works fine --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 384cc099..cc3fff96 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6348,7 +6348,7 @@ static void K_drawKartMinimap(void) // Draw the HUD only when playing in a level. // hu_stuff needs this, unlike st_stuff. - if (!demoplayback && !(Playing() && gamestate == GS_LEVEL)) + if (gamestate != GS_LEVEL) return; if (stplyr != &players[displayplayer]) From c9e994ae07b0fec961be839aacd1b77e68895091 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 23 Sep 2018 23:07:38 +0100 Subject: [PATCH 33/37] smoll to tiny --- src/k_kart.c | 40 ++++++++++++++++++++-------------------- src/k_kart.h | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 1a8cb9b7..138d3b39 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5540,52 +5540,52 @@ void K_LoadKartHUDGraphics(void) } // For the item toggle menu -const char *K_GetItemPatch(UINT8 item, boolean smoll) +const char *K_GetItemPatch(UINT8 item, boolean tiny) { switch (item) { case KITEM_SNEAKER: case KRITEM_TRIPLESNEAKER: - return (smoll ? "K_ISSHOE" : "K_ITSHOE"); + return (tiny ? "K_ISSHOE" : "K_ITSHOE"); case KITEM_ROCKETSNEAKER: - return (smoll ? "K_ISRSHE" : "K_ITRSHE"); + return (tiny ? "K_ISRSHE" : "K_ITRSHE"); case KITEM_INVINCIBILITY: - return (smoll ? "K_ISINV1" : "K_ITINV1"); + return (tiny ? "K_ISINV1" : "K_ITINV1"); case KITEM_BANANA: case KRITEM_TRIPLEBANANA: case KRITEM_TENFOLDBANANA: - return (smoll ? "K_ISBANA" : "K_ITBANA"); + return (tiny ? "K_ISBANA" : "K_ITBANA"); case KITEM_EGGMAN: - return (smoll ? "K_ISEGGM" : "K_ITEGGM"); + return (tiny ? "K_ISEGGM" : "K_ITEGGM"); case KITEM_ORBINAUT: - return (smoll ? "K_ISORBN" : "K_ITORB1"); + return (tiny ? "K_ISORBN" : "K_ITORB1"); case KITEM_JAWZ: case KRITEM_DUALJAWZ: - return (smoll ? "K_ISJAWZ" : "K_ITJAWZ"); + return (tiny ? "K_ISJAWZ" : "K_ITJAWZ"); case KITEM_MINE: - return (smoll ? "K_ISMINE" : "K_ITMINE"); + return (tiny ? "K_ISMINE" : "K_ITMINE"); case KITEM_BALLHOG: - return (smoll ? "K_ISBHOG" : "K_ITBHOG"); + return (tiny ? "K_ISBHOG" : "K_ITBHOG"); case KITEM_SPB: - return (smoll ? "K_ISSPB" : "K_ITSPB"); + return (tiny ? "K_ISSPB" : "K_ITSPB"); case KITEM_GROW: - return (smoll ? "K_ISGROW" : "K_ITGROW"); + return (tiny ? "K_ISGROW" : "K_ITGROW"); case KITEM_SHRINK: - return (smoll ? "K_ISSHRK" : "K_ITSHRK"); + return (tiny ? "K_ISSHRK" : "K_ITSHRK"); case KITEM_THUNDERSHIELD: - return (smoll ? "K_ISTHNS" : "K_ITTHNS"); + return (tiny ? "K_ISTHNS" : "K_ITTHNS"); case KITEM_HYUDORO: - return (smoll ? "K_ISHYUD" : "K_ITHYUD"); + return (tiny ? "K_ISHYUD" : "K_ITHYUD"); case KITEM_POGOSPRING: - return (smoll ? "K_ISPOGO" : "K_ITPOGO"); + return (tiny ? "K_ISPOGO" : "K_ITPOGO"); case KITEM_KITCHENSINK: - return (smoll ? "K_ISSINK" : "K_ITSINK"); + return (tiny ? "K_ISSINK" : "K_ITSINK"); case KRITEM_TRIPLEORBINAUT: - return (smoll ? "K_ISORBN" : "K_ITORB3"); + return (tiny ? "K_ISORBN" : "K_ITORB3"); case KRITEM_QUADORBINAUT: - return (smoll ? "K_ISORBN" : "K_ITORB4"); + return (tiny ? "K_ISORBN" : "K_ITORB4"); default: - return (smoll ? "K_ISSAD" : "K_ITSAD"); + return (tiny ? "K_ISSAD" : "K_ITSAD"); } } diff --git a/src/k_kart.h b/src/k_kart.h index c0fe58bc..7c37ef67 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -59,7 +59,7 @@ void K_CalculateBattleWanted(void); void K_CheckBumpers(void); void K_CheckSpectateStatus(void); -const char *K_GetItemPatch(UINT8 item, boolean smoll); +const char *K_GetItemPatch(UINT8 item, boolean tiny); INT32 K_calcSplitFlags(INT32 snapflags); void K_LoadKartHUDGraphics(void); fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my); From 8ccaa1fceeb058de8b0edacf0359584e3ec7f10d Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 28 Sep 2018 12:58:07 +0100 Subject: [PATCH 34/37] Flip dynamic slope toggle. --- src/p_slopes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index c516fa97..35d4c423 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -251,7 +251,7 @@ void P_SpawnSlope_Line(int linenum) UINT8 flags = 0; // Slope flags if (line->flags & ML_NOSONIC) flags |= SL_NOPHYSICS; - if (line->flags & ML_NOTAILS) + if (!(line->flags & ML_NOTAILS)) flags |= SL_NODYNAMIC; if (line->flags & ML_NOKNUX) flags |= SL_ANCHORVERTEX; From 2c1db167da6dab70819b4064cf88c915a5a8183c Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 29 Sep 2018 16:18:16 +0100 Subject: [PATCH 35/37] Correct that thing Lat` found where sometimes the controls menus'd get "stuck" replacing the second key every time, effectively only allowing one key until you clear it and try again. Also, sounds. --- src/m_menu.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 5d0448ce..8be0b479 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2795,6 +2795,7 @@ boolean M_Responder(event_t *ev) { // detach any keys associated with the game control G_ClearControlKeys(setupcontrols, currentMenu->menuitems[itemOn].alphaKey); + S_StartSound(NULL, sfx_shldls); return true; } @@ -8673,23 +8674,22 @@ static void M_ChangecontrolResponse(event_t *ev) setupcontrols[control][found] = ch-KEY_4JOY1+KEY_DBL4JOY1; } else - { - // check if change key1 or key2, or replace the two by the new - found = 0; - if (setupcontrols[control][0] == KEY_NULL) - found++; - if (setupcontrols[control][1] == KEY_NULL) - found++; - if (found == 2) - { - found = 0; - setupcontrols[control][1] = KEY_NULL; //replace key 1,clear key2 - } - G_CheckDoubleUsage(ch); - setupcontrols[control][found] = ch; - } - + { + // check if change key1 or key2, or shuffle them along in a queue + found = 0; + if (setupcontrols[control][0] != KEY_NULL) + { + found++; + if (setupcontrols[control][1] != KEY_NULL) + setupcontrols[control][0] = setupcontrols[control][1]; + } + G_CheckDoubleUsage(ch); + setupcontrols[control][found] = ch; + } + S_StartSound(NULL, sfx_strpst); } + else + S_StartSound(NULL, sfx_skid); M_StopMessage(0); } From 1be13e8e2d1d3baacddff4e081e17aebe7a3406c Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 29 Sep 2018 16:43:00 +0100 Subject: [PATCH 36/37] Fix dehacked list incongruence. --- src/dehacked.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/info.h | 10 +++++----- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8b60ab61..99d95259 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6704,6 +6704,54 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KARMAWHEEL", // Karma player wheels + // Thunder shield use stuff; + "S_KSPARK1", // Sparkling Radius + "S_KSPARK2", + "S_KSPARK3", + "S_KSPARK4", + "S_KSPARK5", + "S_KSPARK6", + "S_KSPARK7", + "S_KSPARK8", + "S_KSPARK9", + "S_KSPARK10", + "S_KSPARK11", + "S_KSPARK12", + "S_KSPARK13", // ... that's an awful lot. + + "S_LZIO11", // Straight lightning bolt + "S_LZIO12", + "S_LZIO13", + "S_LZIO14", + "S_LZIO15", + "S_LZIO16", + "S_LZIO17", + "S_LZIO18", + "S_LZIO19", + + "S_LZIO21", // Straight lightning bolt (flipped) + "S_LZIO22", + "S_LZIO23", + "S_LZIO24", + "S_LZIO25", + "S_LZIO26", + "S_LZIO27", + "S_LZIO28", + "S_LZIO29", + + "S_KLIT1", // Diagonal lightning. No, it not being straight doesn't make it gay. + "S_KLIT2", + "S_KLIT3", + "S_KLIT4", + "S_KLIT5", + "S_KLIT6", + "S_KLIT7", + "S_KLIT8", + "S_KLIT9", + "S_KLIT10", + "S_KLIT11", + "S_KLIT12", + #ifdef SEENAMES "S_NAMECHECK", #endif diff --git a/src/info.h b/src/info.h index cfda742c..d0f4be59 100644 --- a/src/info.h +++ b/src/info.h @@ -3557,8 +3557,8 @@ typedef enum state S_KARMAWHEEL, - // Lightning shield use stuff; - S_KSPARK1, // Sparkling Radius + // Thunder shield use stuff; + S_KSPARK1, // Sparkling Radius S_KSPARK2, S_KSPARK3, S_KSPARK4, @@ -3571,7 +3571,7 @@ typedef enum state S_KSPARK11, S_KSPARK12, S_KSPARK13, // ... that's an awful lot. - + S_LZIO11, // Straight lightning bolt S_LZIO12, S_LZIO13, @@ -3581,7 +3581,7 @@ typedef enum state S_LZIO17, S_LZIO18, S_LZIO19, - + S_LZIO21, // Straight lightning bolt (flipped) S_LZIO22, S_LZIO23, @@ -3591,7 +3591,7 @@ typedef enum state S_LZIO27, S_LZIO28, S_LZIO29, - + S_KLIT1, // Diagonal lightning. No, it not being straight doesn't make it gay. S_KLIT2, S_KLIT3, From ab59504be0e5682e72f2353a9498e957f8ccdc9c Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 29 Sep 2018 20:28:27 +0100 Subject: [PATCH 37/37] Experimental: Making the ghetto waypoints we have right now their own mobj list in order to make them slightly less bullshit --- src/info.c | 2 +- src/k_kart.c | 11 +---------- src/p_mobj.c | 3 +++ src/p_mobj.h | 2 ++ src/p_saveg.c | 12 ++++++++---- src/p_tick.c | 1 + 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/info.c b/src/info.c index b3e4e7c7..c0fb24fb 100644 --- a/src/info.c +++ b/src/info.c @@ -4089,7 +4089,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY, // flags + MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, diff --git a/src/k_kart.c b/src/k_kart.c index ed91616b..db317803 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4235,7 +4235,6 @@ static void K_KartUpdatePosition(player_t *player) fixed_t oldposition = player->kartstuff[k_position]; fixed_t i, ppcd, pncd, ipcd, incd; fixed_t pmo, imo; - thinker_t *th; mobj_t *mo; if (player->spectator || !player->mo) @@ -4260,16 +4259,8 @@ static void K_KartUpdatePosition(player_t *player) player->kartstuff[k_nextcheck] = players[i].kartstuff[k_nextcheck] = 0; // This checks every thing on the map, and looks for MT_BOSS3WAYPOINT (the thing we're using for checkpoint wp's, for now) - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (mo = waypointcap; mo != NULL; mo = mo->tracer) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj at all, shoo - continue; - - mo = (mobj_t *)th; - - if (mo->type != MT_BOSS3WAYPOINT) // TODO: Change to 'MT_WAYPOINT'? - continue; - pmo = P_AproxDistance(P_AproxDistance( mo->x - player->mo->x, mo->y - player->mo->y), mo->z - player->mo->z) / FRACUNIT; diff --git a/src/p_mobj.c b/src/p_mobj.c index 0f065733..d22d5cb6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -48,6 +48,7 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; static mobj_t *shadowcap = NULL; +mobj_t *waypointcap = NULL; void P_InitCachedActions(void) { @@ -11076,6 +11077,8 @@ ML_NOCLIMB : Direction not controllable else if (i == MT_BOSS3WAYPOINT) // SRB2kart 120217 - Used to store checkpoint num { mobj->health = mthing->angle; + P_SetTarget(&mobj->tracer, waypointcap); + P_SetTarget(&waypointcap, mobj); } else if (i == MT_SPIKE) { diff --git a/src/p_mobj.h b/src/p_mobj.h index 34d1f644..df6e7642 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -429,6 +429,8 @@ typedef struct actioncache_s extern actioncache_t actioncachehead; +extern mobj_t *waypointcap; + void P_InitCachedActions(void); void P_RunCachedActions(void); void P_AddCachedAction(mobj_t *mobj, INT32 statenum); diff --git a/src/p_saveg.c b/src/p_saveg.c index d9f43000..ffcc8789 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -945,11 +945,10 @@ typedef enum MD2_EXTVAL2 = 1<<6, MD2_HNEXT = 1<<7, MD2_HPREV = 1<<8, + MD2_COLORIZED = 1<<9, + MD2_WAYPOINTCAP = 1<<10 #ifdef ESLOPE - MD2_SLOPE = 1<<9, - MD2_COLORIZED = 1<<10 -#else - MD2_COLORIZED = 1<<9 + , MD2_SLOPE = 1<<11 #endif } mobj_diff2_t; @@ -1146,6 +1145,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) #endif if (mobj->colorized) diff2 |= MD2_COLORIZED; + if (mobj == waypointcap) + diff2 |= MD2_WAYPOINTCAP; if (diff2 != 0) diff |= MD_MORE; @@ -2165,6 +2166,9 @@ static void LoadMobjThinker(actionf_p1 thinker) P_AddThinker(&mobj->thinker); + if (diff2 & MD2_WAYPOINTCAP) + P_SetTarget(&waypointcap, mobj); + mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function } diff --git a/src/p_tick.c b/src/p_tick.c index 3a55353d..3c5ed0b9 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -180,6 +180,7 @@ void Command_CountMobjs_f(void) void P_InitThinkers(void) { thinkercap.prev = thinkercap.next = &thinkercap; + waypointcap = NULL; } //