diff --git a/.gitattributes b/.gitattributes index d45620912..7751149ac 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,12 @@ +#Source code +/src/*.c text=auto +/src/*.h text=auto +/src/*.s text=auto +/src/*.m text=auto +/src/*.xpm text=auto +/src/Makefile text=auto +/src/Make*.cfg text=auto +/src/CMakeLists.txt text=auto # Windows EOL *.cs -crlf -whitespace *.mk -crlf -whitespace diff --git a/libs/libpng-src/pngconf.h b/libs/libpng-src/pngconf.h index 23f8313c3..5cb126197 100644 --- a/libs/libpng-src/pngconf.h +++ b/libs/libpng-src/pngconf.h @@ -62,7 +62,6 @@ #define PNG_NO_READ_iTXt #define PNG_NO_READ_APNG -#define PNG_NO_READ_UNKNOWN_CHUNKS #define PNG_NO_READ_USER_TRANSFORM #define PNG_READ_BGR_SUPPORTED #define PNG_NO_READ_SWAP_ALPHA diff --git a/libs/libpng-src/projects/libpng32.a b/libs/libpng-src/projects/libpng32.a index 74cb54e8c..5d2917502 100644 Binary files a/libs/libpng-src/projects/libpng32.a and b/libs/libpng-src/projects/libpng32.a differ diff --git a/libs/libpng-src/projects/libpng64.a b/libs/libpng-src/projects/libpng64.a index bba4c9121..cddf938dd 100644 Binary files a/libs/libpng-src/projects/libpng64.a and b/libs/libpng-src/projects/libpng64.a differ diff --git a/srb2.png b/srb2.png index 72a08f664..3bbe2c3e6 100644 Binary files a/srb2.png and b/srb2.png differ diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 01e94485d..476bb1a1e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -152,7 +152,7 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; -static consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -579,6 +579,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->starpostnum = LONG(players[i].starpostnum); rsp->starposttime = (tic_t)LONG(players[i].starposttime); rsp->starpostangle = (angle_t)LONG(players[i].starpostangle); + rsp->starpostscale = (fixed_t)LONG(players[i].starpostscale); rsp->maxlink = LONG(players[i].maxlink); rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed); @@ -714,6 +715,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].starpostnum = LONG(rsp->starpostnum); players[i].starposttime = (tic_t)LONG(rsp->starposttime); players[i].starpostangle = (angle_t)LONG(rsp->starpostangle); + players[i].starpostscale = (fixed_t)LONG(rsp->starpostscale); players[i].maxlink = LONG(rsp->maxlink); players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed); @@ -2415,7 +2417,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) // the remaining players. if (G_IsSpecialStage(gamemap)) { - INT32 i, count, increment, spheres; + INT32 i, count, sincrement, spheres, rincrement, rings; for (i = 0, count = 0; i < MAXPLAYERS; i++) { @@ -2425,18 +2427,35 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) count--; spheres = players[playernum].spheres; - increment = spheres/count; + rings = players[playernum].rings; + sincrement = spheres/count; + rincrement = rings/count; for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && i != playernum) { - if (spheres < increment) + if (spheres < 2*sincrement) + { P_GivePlayerSpheres(&players[i], spheres); + spheres = 0; + } else - P_GivePlayerSpheres(&players[i], increment); + { + P_GivePlayerSpheres(&players[i], sincrement); + spheres -= sincrement; + } - spheres -= increment; + if (rings < 2*rincrement) + { + P_GivePlayerRings(&players[i], rings); + rings = 0; + } + else + { + P_GivePlayerRings(&players[i], rincrement); + rings -= rincrement; + } } } } @@ -2946,13 +2965,13 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) CL_RemovePlayer(pnum, kickreason); } -consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; -consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done +consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}}; -consvar_t cv_resynchattempts = {"resynchattempts", "10", 0, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL }; -consvar_t cv_blamecfail = {"blamecfail", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; // max file size to send to a player (in kilobytes) static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; @@ -2993,11 +3012,6 @@ void D_ClientServerInit(void) RegisterNetXCmd(XD_KICK, Got_KickCmd); RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); #ifndef NONET - CV_RegisterVar(&cv_allownewplayer); - CV_RegisterVar(&cv_joinnextround); - CV_RegisterVar(&cv_showjoinaddress); - CV_RegisterVar(&cv_resynchattempts); - CV_RegisterVar(&cv_blamecfail); #ifdef DUMPCONSISTENCY CV_RegisterVar(&cv_dumpconsistency); #endif diff --git a/src/d_clisrv.h b/src/d_clisrv.h index a2f140f33..d09d2aa48 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -228,6 +228,7 @@ typedef struct INT32 starpostnum; tic_t starposttime; angle_t starpostangle; + fixed_t starpostscale; INT32 maxlink; fixed_t dashspeed; @@ -444,6 +445,7 @@ extern INT32 mapchangepending; // Points inside doomcom extern doomdata_t *netbuffer; +extern consvar_t cv_showjoinaddress; extern consvar_t cv_playbackspeed; #define BASEPACKETSIZE offsetof(doomdata_t, u) diff --git a/src/d_main.c b/src/d_main.c index eaeae4b10..37637edd6 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -129,6 +129,7 @@ char srb2home[256] = "."; char srb2path[256] = "."; boolean usehome = true; const char *pandf = "%s" PATHSEP "%s"; +static char addonsdir[MAX_WADPATH]; // // EVENT HANDLING @@ -287,7 +288,7 @@ static void D_Display(void) F_TitleScreenDrawer(); break; } - // Intentional fall-through + /* FALLTHRU */ case GS_LEVEL: if (!gametic) break; @@ -716,6 +717,7 @@ void D_StartTitle(void) botskin = 0; cv_debug = 0; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); lastmaploaded = 0; // In case someone exits out at the same time they start a time attack run, @@ -1038,7 +1040,6 @@ void D_SRB2Main(void) // can't use sprintf since there is %u in savegamename strcatbf(savegamename, srb2home, PATHSEP); - I_mkdir(srb2home, 0700); #else snprintf(srb2home, sizeof srb2home, "%s", userhome); snprintf(downloaddir, sizeof downloaddir, "%s", userhome); @@ -1055,6 +1056,10 @@ void D_SRB2Main(void) configfile[sizeof configfile - 1] = '\0'; } + // Create addons dir + snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons"); + I_mkdir(addonsdir, 0755); + // rand() needs seeded regardless of password srand((unsigned int)time(NULL)); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 590543f00..7d5963ecc 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -556,9 +556,16 @@ void D_RegisterServerCommands(void) // d_clisrv CV_RegisterVar(&cv_maxplayers); + CV_RegisterVar(&cv_resynchattempts); CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_noticedownload); CV_RegisterVar(&cv_downloadspeed); +#ifndef NONET + CV_RegisterVar(&cv_allownewplayer); + CV_RegisterVar(&cv_joinnextround); + CV_RegisterVar(&cv_showjoinaddress); + CV_RegisterVar(&cv_blamecfail); +#endif COM_AddCommand("ping", Command_Ping_f); CV_RegisterVar(&cv_nettimeout); @@ -630,6 +637,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_screenshot_folder); CV_RegisterVar(&cv_screenshot_colorprofile); CV_RegisterVar(&cv_moviemode); + CV_RegisterVar(&cv_movie_option); + CV_RegisterVar(&cv_movie_folder); // PNG variables CV_RegisterVar(&cv_zlib_level); CV_RegisterVar(&cv_zlib_memory); @@ -1909,7 +1918,10 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) precache = false; if (resetplayer && !FLS) + { emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); + } if (modeattacking) { @@ -2707,14 +2719,6 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } } - // Clear player score and rings if a spectator. - if (players[playernum].spectator) - { - players[playernum].score = players[playernum].rings = 0; - if (players[playernum].mo) - players[playernum].mo->health = 1; - } - // In tag, check to see if you still have a game. if (G_TagGametype()) P_CheckSurvivors(); @@ -3601,7 +3605,7 @@ static void CoopLives_OnChange(void) { case 0: CONS_Printf(M_GetText("Players can now respawn indefinitely.\n")); - return; + break; case 1: CONS_Printf(M_GetText("Lives are now per-player.\n")); return; @@ -4104,6 +4108,7 @@ void Command_ExitGame_f(void) botskin = 0; cv_debug = 0; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); if (dirmenu) closefilemenu(true); diff --git a/src/d_player.h b/src/d_player.h index 5860cf1de..69080bd9d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -441,6 +441,7 @@ typedef struct player_s INT32 starpostnum; // The number of the last starpost you hit tic_t starposttime; // Your time when you hit the starpost angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way + fixed_t starpostscale; // Scale of the player; if negative, player is gravflipped ///////////////// // NiGHTS Stuff// diff --git a/src/dehacked.c b/src/dehacked.c index 5db61a5b5..8334de61a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1181,6 +1181,20 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->muspostbosspos = (UINT32)get_number(word2); else if (fastcmp(word, "MUSICPOSTBOSSFADEIN")) mapheaderinfo[num-1]->muspostbossfadein = (UINT32)get_number(word2); + else if (fastcmp(word, "FORCERESETMUSIC")) + { + // This is a weird one because "FALSE"/"NO" could either apply to "leave to default preference" (cv_resetmusic) + // or "force off". Let's assume it means "force off", and let an unspecified value mean "default preference" + if (fastcmp(word2, "OFF") || word2[0] == 'F' || word2[0] == 'N') i = 0; + else if (fastcmp(word2, "ON") || word2[0] == 'T' || word2[0] == 'Y') i = 1; + else i = -1; // (fastcmp(word2, "DEFAULT")) + + if (i >= -1 && i <= 1) // -1 to force off, 1 to force on, 0 to honor default. + // This behavior can be disabled with cv_resetmusicbyheader + mapheaderinfo[num-1]->musforcereset = (SINT8)i; + else + deh_warning("Level header %d: invalid forceresetmusic option %d", num, i); + } else if (fastcmp(word, "FORCECHARACTER")) { strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1); @@ -2957,6 +2971,17 @@ static void readunlockable(MYFILE *f, INT32 num) Z_Free(s); } +static const char NIGHTSGRADE_LIST[] = { + 'F', // GRADE_F + 'E', // GRADE_E + 'D', // GRADE_D + 'C', // GRADE_C + 'B', // GRADE_B + 'A', // GRADE_A + 'S', // GRADE_S + '\0' +}; + #define PARAMCHECK(n) do { if (!params[n]) { deh_warning("Too few parameters, need %d", n); return; }} while (0) static void readcondition(UINT8 set, UINT32 id, char *word2) { @@ -3058,7 +3083,21 @@ static void readcondition(UINT8 set, UINT32 id, char *word2) PARAMCHECK(2); // one optional one ty = UC_NIGHTSSCORE + offset; - re = atoi(params[2 + !!(params[3])]); + i = (params[3] ? 3 : 2); + if (fastncmp("GRADE_",params[i],6)) + { + char *p = params[i]+6; + for (re = 0; NIGHTSGRADE_LIST[re]; re++) + if (*p == NIGHTSGRADE_LIST[re]) + break; + if (!NIGHTSGRADE_LIST[re]) + { + deh_warning("Invalid NiGHTS grade %s\n", params[i]); + return; + } + } + else + re = atoi(params[i]); // Convert to map number if it appears to be one if (params[1][0] >= 'A' && params[1][0] <= 'Z') @@ -4589,10 +4628,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SONIC3KBOSSEXPLOSION6", "S_JETFUME1", - "S_JETFUME2", // Boss 1 "S_EGGMOBILE_STND", + "S_EGGMOBILE_ROFL", "S_EGGMOBILE_LATK1", "S_EGGMOBILE_LATK2", "S_EGGMOBILE_LATK3", @@ -4602,7 +4641,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_LATK7", "S_EGGMOBILE_LATK8", "S_EGGMOBILE_LATK9", - "S_EGGMOBILE_LATK10", "S_EGGMOBILE_RATK1", "S_EGGMOBILE_RATK2", "S_EGGMOBILE_RATK3", @@ -4612,7 +4650,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_RATK7", "S_EGGMOBILE_RATK8", "S_EGGMOBILE_RATK9", - "S_EGGMOBILE_RATK10", "S_EGGMOBILE_PANIC1", "S_EGGMOBILE_PANIC2", "S_EGGMOBILE_PANIC3", @@ -4620,6 +4657,14 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_PANIC5", "S_EGGMOBILE_PANIC6", "S_EGGMOBILE_PANIC7", + "S_EGGMOBILE_PANIC8", + "S_EGGMOBILE_PANIC9", + "S_EGGMOBILE_PANIC10", + "S_EGGMOBILE_PANIC11", + "S_EGGMOBILE_PANIC12", + "S_EGGMOBILE_PANIC13", + "S_EGGMOBILE_PANIC14", + "S_EGGMOBILE_PANIC15", "S_EGGMOBILE_PAIN", "S_EGGMOBILE_PAIN2", "S_EGGMOBILE_DIE1", @@ -4630,6 +4675,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE_FLEE2", "S_EGGMOBILE_BALL", "S_EGGMOBILE_TARGET", + "S_BOSSEGLZ1", + "S_BOSSEGLZ2", // Boss 2 "S_EGGMOBILE2_STND", @@ -4661,11 +4708,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Boss 3 "S_EGGMOBILE3_STND", - "S_EGGMOBILE3_LAUGH1", - "S_EGGMOBILE3_LAUGH2", - "S_EGGMOBILE3_LAUGH3", - "S_EGGMOBILE3_LAUGH4", - "S_EGGMOBILE3_LAUGH5", + "S_EGGMOBILE3_SHOCK", "S_EGGMOBILE3_ATK1", "S_EGGMOBILE3_ATK2", "S_EGGMOBILE3_ATK3A", @@ -4674,21 +4717,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE3_ATK3D", "S_EGGMOBILE3_ATK4", "S_EGGMOBILE3_ATK5", - "S_EGGMOBILE3_LAUGH6", - "S_EGGMOBILE3_LAUGH7", - "S_EGGMOBILE3_LAUGH8", - "S_EGGMOBILE3_LAUGH9", - "S_EGGMOBILE3_LAUGH10", - "S_EGGMOBILE3_LAUGH11", - "S_EGGMOBILE3_LAUGH12", - "S_EGGMOBILE3_LAUGH13", - "S_EGGMOBILE3_LAUGH14", - "S_EGGMOBILE3_LAUGH15", - "S_EGGMOBILE3_LAUGH16", - "S_EGGMOBILE3_LAUGH17", - "S_EGGMOBILE3_LAUGH18", - "S_EGGMOBILE3_LAUGH19", - "S_EGGMOBILE3_LAUGH20", + "S_EGGMOBILE3_ROFL", "S_EGGMOBILE3_PAIN", "S_EGGMOBILE3_PAIN2", "S_EGGMOBILE3_DIE1", @@ -4698,15 +4727,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE3_FLEE1", "S_EGGMOBILE3_FLEE2", - // Boss 3 Propeller - "S_PROPELLER1", - "S_PROPELLER2", - "S_PROPELLER3", - "S_PROPELLER4", - "S_PROPELLER5", - "S_PROPELLER6", - "S_PROPELLER7", - // Boss 3 pinch "S_FAKEMOBILE_INIT", "S_FAKEMOBILE", @@ -4719,6 +4739,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FAKEMOBILE_DIE1", "S_FAKEMOBILE_DIE2", + "S_BOSSSEBH1", + "S_BOSSSEBH2", + // Boss 4 "S_EGGMOBILE4_STND", "S_EGGMOBILE4_LATK1", @@ -5122,16 +5145,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_MSSHIELD_F1", "S_MSSHIELD_F2", - "S_MSSHIELD_F3", - "S_MSSHIELD_F4", - "S_MSSHIELD_F5", - "S_MSSHIELD_F6", - "S_MSSHIELD_F7", - "S_MSSHIELD_F8", - "S_MSSHIELD_F9", - "S_MSSHIELD_F10", - "S_MSSHIELD_F11", - "S_MSSHIELD_F12", // Ring "S_RING", @@ -5565,14 +5578,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_DRIPC1", "S_DRIPC2", - // Coral 1 + // Coral "S_CORAL1", - - // Coral 2 "S_CORAL2", - - // Coral 3 "S_CORAL3", + "S_CORAL4", + "S_CORAL5", // Blue Crystal "S_BLUECRYSTAL1", @@ -5580,6 +5591,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Kelp, "S_KELP", + // Animated algae + "S_ANIMALGAETOP1", + "S_ANIMALGAETOP2", + "S_ANIMALGAESEG", + // DSZ Stalagmites "S_DSZSTALAGMITE", "S_DSZ2STALAGMITE", @@ -5724,6 +5740,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CACTI7", "S_CACTI8", "S_CACTI9", + "S_CACTI10", + "S_CACTI11", + "S_CACTITINYSEG", + "S_CACTISMALLSEG", // Warning signs sprites "S_ARIDSIGN_CAUTION", @@ -7215,6 +7235,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_EGGTRAP", "MT_BOSS3WAYPOINT", "MT_BOSS9GATHERPOINT", + "MT_BOSSJUNK", // Boss 1 "MT_EGGMOBILE", @@ -7226,15 +7247,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Boss 2 "MT_EGGMOBILE2", "MT_EGGMOBILE2_POGO", - "MT_BOSSTANK1", - "MT_BOSSTANK2", - "MT_BOSSSPIGOT", "MT_GOOP", "MT_GOOPTRAIL", // Boss 3 "MT_EGGMOBILE3", - "MT_PROPELLER", "MT_FAKEMOBILE", "MT_SHOCK", @@ -7445,11 +7462,15 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SEAWEED", // DSZ Seaweed "MT_WATERDRIP", // Dripping Water source "MT_WATERDROP", // Water drop from dripping water - "MT_CORAL1", // Coral 1 - "MT_CORAL2", // Coral 2 - "MT_CORAL3", // Coral 3 + "MT_CORAL1", // Coral + "MT_CORAL2", + "MT_CORAL3", + "MT_CORAL4", + "MT_CORAL5", "MT_BLUECRYSTAL", // Blue Crystal "MT_KELP", // Kelp + "MT_ANIMALGAETOP", // Animated algae top + "MT_ANIMALGAESEG", // Animated algae segment "MT_DSZSTALAGMITE", // Deep Sea 1 Stalagmite "MT_DSZ2STALAGMITE", // Deep Sea 2 Stalagmite "MT_LIGHTBEAM", // DSZ Light beam @@ -7509,6 +7530,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CACTI7", "MT_CACTI8", "MT_CACTI9", + "MT_CACTI10", + "MT_CACTI11", + "MT_CACTITINYSEG", + "MT_CACTISMALLSEG", "MT_ARIDSIGN_CAUTION", "MT_ARIDSIGN_CACTI", "MT_ARIDSIGN_SHARPTURN", @@ -8474,15 +8499,6 @@ struct { {"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED}, {"LF2_WIDEICON",LF2_WIDEICON}, - // NiGHTS grades - {"GRADE_F",GRADE_F}, - {"GRADE_E",GRADE_E}, - {"GRADE_D",GRADE_D}, - {"GRADE_C",GRADE_C}, - {"GRADE_B",GRADE_B}, - {"GRADE_A",GRADE_A}, - {"GRADE_S",GRADE_S}, - // Emeralds {"EMERALD1",EMERALD1}, {"EMERALD2",EMERALD2}, @@ -9304,6 +9320,19 @@ static fixed_t find_const(const char **rword) free(word); return 0; } + else if (fastncmp("GRADE_",word,6)) + { + char *p = word+6; + for (i = 0; NIGHTSGRADE_LIST[i]; i++) + if (*p == NIGHTSGRADE_LIST[i]) + { + free(word); + return i; + } + const_warning("NiGHTS grade",word); + free(word); + return 0; + } for (i = 0; INT_CONST[i].n; i++) if (fastcmp(word,INT_CONST[i].n)) { free(word); @@ -9752,6 +9781,18 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "skincolor '%s' could not be found.\n", word); return 0; } + else if (fastncmp("GRADE_",word,6)) + { + p = word+6; + for (i = 0; NIGHTSGRADE_LIST[i]; i++) + if (*p == NIGHTSGRADE_LIST[i]) + { + lua_pushinteger(L, i); + return 1; + } + if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word); + return 0; + } else if (fastncmp("MN_",word,3)) { p = word+3; for (i = 0; i < NUMMENUTYPES; i++) diff --git a/src/doomdef.h b/src/doomdef.h index 6e7db2143..4a0174369 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -616,4 +616,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +#ifndef HAVE_PNG +#define NO_PNG_LUMPS +#endif + #endif // __DOOMDEF__ diff --git a/src/doomstat.h b/src/doomstat.h index b6c376d1c..57e37f72d 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -333,6 +333,8 @@ typedef struct UINT32 muspostbosspos; ///< Post-bossdeath position UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds. + SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) + // Lua stuff. // (This is not ifdeffed so the map header structure can stay identical, just in case.) UINT8 numCustomOptions; ///< Internal. For Lua custom value support. @@ -418,6 +420,10 @@ extern UINT16 emeralds; #define EMERALD7 64 #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) +// yes, even in non HAVE_BLUA +#define NUM_LUABANKS 16 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8 +extern INT32 luabanks[NUM_LUABANKS]; + extern INT32 nummaprings; //keep track of spawned rings/coins /** Time attack information, currently a very small structure. diff --git a/src/f_finale.c b/src/f_finale.c index da042abeb..ee22ecb2f 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1584,22 +1584,22 @@ void F_StartEnding(void) UINT8 skinnum = players[consoleplayer].skin; spritedef_t *sprdef; spriteframe_t *sprframe; - if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 5) + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 7) { sprdef = &skins[skinnum].sprites[SPR2_XTRA]; // character head, skin specific - sprframe = &sprdef->spriteframes[2]; - endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); - sprframe = &sprdef->spriteframes[3]; - endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); sprframe = &sprdef->spriteframes[4]; + endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + sprframe = &sprdef->spriteframes[5]; + endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + sprframe = &sprdef->spriteframes[6]; endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); } - else // eh, yknow what? too lazy to put MISSINGs here. eggman wins if you don't give your character an ending firework display. + else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) { - endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL); - endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL); - endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL); + endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_LEVEL); + endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_LEVEL); + endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_LEVEL); } endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_LEVEL); @@ -2465,6 +2465,11 @@ void F_TitleDemoTicker(void) // ========== // CONTINUE // ========== + +static skin_t *contskins[2]; +static UINT8 cont_spr2[2][6]; +static UINT8 *contcolormaps[2]; + void F_StartContinue(void) { I_Assert(!netgame && !multiplayer); @@ -2488,7 +2493,44 @@ void F_StartContinue(void) S_ChangeMusicInternal("_conti", false); S_StopSounds(); - timetonext = TICRATE*11; + contskins[0] = &skins[players[consoleplayer].skin]; + cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT1, NULL); + cont_spr2[0][2] = contskins[0]->contangle & 7; + contcolormaps[0] = R_GetTranslationColormap(players[consoleplayer].skin, players[consoleplayer].skincolor, GTC_CACHE); + cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; + cont_spr2[0][5] = max(1, contskins[0]->contspeed); + + if (botskin) + { + INT32 secondplaya; + + if (secondarydisplayplayer != consoleplayer) + secondplaya = secondarydisplayplayer; + else // HACK + secondplaya = 1; + + contskins[1] = &skins[players[secondplaya].skin]; + cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT4, NULL); + cont_spr2[1][2] = (contskins[1]->contangle >> 3) & 7; + contcolormaps[1] = R_GetTranslationColormap(players[secondplaya].skin, players[secondplaya].skincolor, GTC_CACHE); + cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; + if (cont_spr2[1][0] == SPR2_CNT4) + cont_spr2[1][5] = 4; // sorry, this one is hardcoded + else + cont_spr2[1][5] = max(1, contskins[1]->contspeed); + } + else + { + contskins[1] = NULL; + contcolormaps[1] = NULL; + cont_spr2[1][0] = cont_spr2[1][2] = cont_spr2[1][4] = cont_spr2[1][5] = 0; + } + + cont_spr2[0][1] = cont_spr2[0][3] =\ + cont_spr2[1][1] = cont_spr2[1][3] = 0; + + timetonext = (11*TICRATE)+11; + continuetime = 0; } // @@ -2497,47 +2539,198 @@ void F_StartContinue(void) // void F_ContinueDrawer(void) { - patch_t *contsonic; - INT32 i, x = (BASEVIDWIDTH/2) + 4, ncontinues = players[consoleplayer].continues; - if (ncontinues > 20) - ncontinues = 20; + spritedef_t *sprdef; + spriteframe_t *sprframe; + patch_t *patch; + INT32 i, x = (BASEVIDWIDTH>>1), ncontinues = players[consoleplayer].continues; + char numbuf[9] = "CONTNUM*"; + tic_t timeleft = (timetonext/TICRATE); + INT32 offsx = 0, offsy = 0, lift[2] = {0, 0}; - if (imcontinuing) - contsonic = W_CachePatchName("CONT2", PU_CACHE); - else - contsonic = W_CachePatchName("CONT1", PU_CACHE); + if (continuetime >= 3*TICRATE) + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); + return; + } V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - V_DrawCenteredString(BASEVIDWIDTH/2, 100, 0, "CONTINUE?"); - // Draw a Sonic! - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 32, 0, contsonic); + if (timetonext >= (11*TICRATE)+10) + return; - // Draw the continue markers! Show continues minus one. - x -= ncontinues * 6; - for (i = 0; i < ncontinues; ++i) - V_DrawContinueIcon(x + (i*12), 140, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawLevelTitle(x - (V_LevelNameWidth("CONTINUE")>>1), 16, 0, "CONTINUE"); - V_DrawCenteredString(BASEVIDWIDTH/2, 168, 0, va("\x82*\x80" " %02d " "\x82*\x80", timetonext/TICRATE)); + // Two stars... + patch = W_CachePatchName("CONTSTAR", PU_CACHE); + V_DrawScaledPatch(x-32, 160, 0, patch); + V_DrawScaledPatch(x+32, 160, 0, patch); + + // Time left! + if (timeleft > 9) + { + numbuf[7] = '1'; + V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + numbuf[7] = '0'; + V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + } + else + { + numbuf[7] = '0'+timeleft; + V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + } + + // Draw the continue markers! Show continues. + if (ncontinues > 10) + { + if (!(continuetime & 1) || continuetime > 17) + V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawScaledPatch(x+12, 68-2, 0, stlivex); + V_DrawRightAlignedString(x+36, 69-5, 0, + va("%d",(imcontinuing ? ncontinues-1 : ncontinues))); + } + else + { + x += (ncontinues/2) * 30; + if (!(ncontinues & 1)) + x -= 15; + for (i = 0; i < ncontinues; ++i) + { + if (i == (ncontinues/2) && ((continuetime & 1) || continuetime > 17)) + continue; + V_DrawContinueIcon(x - (i*30), 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + } + x = BASEVIDWIDTH>>1; + } + + // Spotlight + V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_CACHE)); + + // warping laser + if (continuetime) + { + INT32 w = min(continuetime, 28), brightness = (continuetime>>1) & 7; + if (brightness > 3) + brightness = 8-brightness; + V_DrawFadeFill(x-w, 0, w<<1, 140, 0, 0, (3+brightness)); + } + + if (contskins[1]) + { + if (continuetime > 15) + { + angle_t work = FixedAngle((10*(continuetime-15))<>ANGLETOFINESHIFT; + offsy = FINESINE(work)<<1; + offsx = (27*FINECOSINE(work))>>1; + } + else + offsx = 27<<(FRACBITS-1); + lift[1] = continuetime-10; + if (lift[1] < 0) + lift[1] = 0; + else if (lift[1] > TICRATE+5) + lift[1] = TICRATE+5; + } + + lift[0] = continuetime-5; + if (lift[0] < 0) + lift[0] = 0; + else if (lift[0] > TICRATE+5) + lift[0] = TICRATE+5; + +#define drawchar(dx, dy, n) {\ + sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\ + sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\ + patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_CACHE);\ + V_DrawFixedPatch((dx), (dy), FRACUNIT, (sprframe->flip & (1<= 0) + drawchar((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])< (11*TICRATE)) + V_DrawFadeScreen(31, timetonext-(11*TICRATE)); + if (continuetime > ((3*TICRATE) - 10)) + V_DrawFadeScreen(0, (continuetime - ((3*TICRATE) - 10))); } void F_ContinueTicker(void) { if (!imcontinuing) { - // note the setup to prevent 2x reloading - if (timetonext >= 0) - timetonext--; - if (timetonext == 0) - Command_ExitGame_f(); + if (timetonext > 0) + { + if (!(--timetonext)) + { + Command_ExitGame_f(); + return; + } + } } else { - // note the setup to prevent 2x reloading - if (continuetime >= 0) - continuetime--; - if (continuetime == 0) + if (++continuetime == 3*TICRATE) + { G_Continue(); + return; + } + + if (continuetime > 5 && ((continuetime & 1) || continuetime > TICRATE) && (++cont_spr2[0][2]) >= 8) + cont_spr2[0][2] = 0; + + if (continuetime > 10 && (!(continuetime & 1) || continuetime > TICRATE+5) && (++cont_spr2[1][2]) >= 8) + cont_spr2[1][2] = 0; + + if (continuetime == (3*TICRATE)-10) + S_StartSound(NULL, sfx_cdfm56); // or 31 + else if (continuetime == 5) + { + cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT2, NULL); + cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; + cont_spr2[0][1] = cont_spr2[0][3] = 0; + cont_spr2[0][5] = 2; + } + else if (continuetime == TICRATE) + { + cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT3, NULL); + cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; + cont_spr2[0][1] = cont_spr2[0][3] = 0; + } + else if (contskins[1]) + { + if (continuetime == 10) + { + cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT2, NULL); + cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; + cont_spr2[1][1] = cont_spr2[1][3] = 0; + cont_spr2[1][5] = 2; + } + else if (continuetime == TICRATE+5) + { + cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT3, NULL); + cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; + cont_spr2[1][1] = cont_spr2[1][3] = 0; + } + } + } + + if ((++cont_spr2[0][3]) >= cont_spr2[0][5]) + { + cont_spr2[0][3] = 0; + if (++cont_spr2[0][1] >= cont_spr2[0][4]) + cont_spr2[0][1] = 0; + } + + if (contskins[1] && (++cont_spr2[1][3]) >= cont_spr2[1][5]) + { + cont_spr2[1][3] = 0; + if (++cont_spr2[1][1] >= cont_spr2[1][4]) + cont_spr2[1][1] = 0; } } @@ -2568,8 +2761,9 @@ boolean F_ContinueResponder(event_t *event) keypressed = true; imcontinuing = true; - continuetime = TICRATE; - S_StartSound(NULL, sfx_itemup); + S_StartSound(NULL, sfx_kc6b); + I_FadeSong(0, MUSICRATE, &S_StopMusic); + return true; } diff --git a/src/filesrch.c b/src/filesrch.c index 8f157bdd5..13d73b6f4 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -751,7 +751,7 @@ boolean preparefilemenu(boolean samedepth) } else if (ext == EXT_TXT) { - if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) + if (!strncmp(dent->d_name, "log-", 4) || !strcmp(dent->d_name, "errorlog.txt")) ext |= EXT_LOADED; } diff --git a/src/g_game.c b/src/g_game.c index d5faf6846..a3025f949 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -172,6 +172,7 @@ static boolean retrying = false; UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage. UINT16 emeralds; +INT32 luabanks[NUM_LUABANKS]; // yes, even in non HAVE_BLUA UINT32 token; // Number of tokens collected in a level UINT32 tokenlist; // List of tokens collected boolean gottoken; // Did you get a token? Used for end of act @@ -215,7 +216,7 @@ UINT16 spacetimetics = 11*TICRATE + (TICRATE/2); UINT16 extralifetics = 4*TICRATE; UINT16 nightslinktics = 2*TICRATE; -INT32 gameovertics = 15*TICRATE; +INT32 gameovertics = 11*TICRATE; UINT8 ammoremovaltics = 2*TICRATE; @@ -2083,6 +2084,7 @@ static inline void G_PlayerFinishLevel(INT32 player) p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility P_FlashPal(p, 0, 0); // Resets + p->starpostscale = 0; p->starpostangle = 0; p->starposttime = 0; p->starpostx = 0; @@ -2098,7 +2100,7 @@ static inline void G_PlayerFinishLevel(INT32 player) // G_PlayerReborn // Called after a player dies. Almost everything is cleared and initialized. // -void G_PlayerReborn(INT32 player) +void G_PlayerReborn(INT32 player, boolean betweenmaps) { player_t *p; INT32 score; @@ -2129,6 +2131,7 @@ void G_PlayerReborn(INT32 player) INT16 starpostz; INT32 starpostnum; INT32 starpostangle; + fixed_t starpostscale; fixed_t jumpfactor; fixed_t height; fixed_t spinheight; @@ -2145,6 +2148,8 @@ void G_PlayerReborn(INT32 player) boolean outofcoop; INT16 bot; SINT8 pity; + INT16 rings; + INT16 spheres; score = players[player].score; lives = players[player].lives; @@ -2184,6 +2189,7 @@ void G_PlayerReborn(INT32 player) starpostz = players[player].starpostz; starpostnum = players[player].starpostnum; starpostangle = players[player].starpostangle; + starpostscale = players[player].starpostscale; jumpfactor = players[player].jumpfactor; height = players[player].height; spinheight = players[player].spinheight; @@ -2199,6 +2205,17 @@ void G_PlayerReborn(INT32 player) bot = players[player].bot; pity = players[player].pity; + if (betweenmaps || !G_IsSpecialStage(gamemap)) + { + rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); + spheres = 0; + } + else + { + rings = players[player].rings; + spheres = players[player].spheres; + } + p = &players[player]; memset(p, 0, sizeof (*p)); @@ -2239,6 +2256,7 @@ void G_PlayerReborn(INT32 player) p->starpostz = starpostz; p->starpostnum = starpostnum; p->starpostangle = starpostangle; + p->starpostscale = starpostscale; p->jumpfactor = jumpfactor; p->height = height; p->spinheight = spinheight; @@ -2252,6 +2270,8 @@ void G_PlayerReborn(INT32 player) if (bot) p->bot = 1; // reset to AI-controlled p->pity = pity; + p->rings = rings; + p->spheres = spheres; // Don't do anything immediately p->pflags |= PF_USEDOWN; @@ -2259,44 +2279,11 @@ void G_PlayerReborn(INT32 player) p->pflags |= PF_JUMPDOWN; p->playerstate = PST_LIVE; - p->rings = p->spheres = 0; // 0 rings p->panim = PA_IDLE; // standing animation //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there //p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent - if (p-players == consoleplayer) - { - if (mapmusflags & MUSIC_RELOADRESET) - { - strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); - mapmusname[6] = 0; - mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); - mapmusposition = mapheaderinfo[gamemap-1]->muspos; - } - - // This is in S_Start, but this was not here previously. - // if (cv_resetmusic.value) - // S_StopMusic(); - S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); - } - - if (gametype == GT_COOP) - P_FindEmerald(); // scan for emeralds to hunt for - - // Reset Nights score and max link to 0 on death - p->marescore = p->maxlink = 0; - - // If NiGHTS, find lowest mare to start with. - p->mare = P_FindLowestMare(); - - CONS_Debug(DBG_NIGHTS, M_GetText("Current mare is %d\n"), p->mare); - - if (p->mare == 255) - p->mare = 0; - - p->marelap = p->marebonuslap = 0; - // Check to make sure their color didn't change somehow... if (G_GametypeHasTeams()) { @@ -2315,6 +2302,36 @@ void G_PlayerReborn(INT32 player) CV_SetValue(&cv_playercolor2, skincolor_blueteam); } } + + if (betweenmaps) + return; + + if (p-players == consoleplayer) + { + if (mapmusflags & MUSIC_RELOADRESET) + { + strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); + mapmusname[6] = 0; + mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); + mapmusposition = mapheaderinfo[gamemap-1]->muspos; + } + + // This is in S_Start, but this was not here previously. + // if (RESETMUSIC) + // S_StopMusic(); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); + } + + if (gametype == GT_COOP) + P_FindEmerald(); // scan for emeralds to hunt for + + // If NiGHTS, find lowest mare to start with. + p->mare = P_FindLowestMare(); + + CONS_Debug(DBG_NIGHTS, M_GetText("Current mare is %d\n"), p->mare); + + if (p->mare == 255) + p->mare = 0; } // @@ -2370,8 +2387,6 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) P_SpawnPlayer(playernum); - players[playernum].rings = mapheaderinfo[gamemap-1]->startrings; - if (starpost) //Don't even bother with looking for a place to spawn. { P_MovePlayerToStarpost(playernum); @@ -2594,7 +2609,7 @@ void G_DoReborn(INT32 playernum) if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP)) resetlevel = true; - else if (gametype == GT_COOP && (netgame || multiplayer)) + else if (gametype == GT_COOP && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) { boolean notgameover = true; @@ -2657,6 +2672,7 @@ void G_DoReborn(INT32 playernum) { if (!playeringame[i]) continue; + players[i].starpostscale = 0; players[i].starpostangle = 0; players[i].starposttime = 0; players[i].starpostx = 0; @@ -2779,6 +2795,7 @@ void G_AddPlayer(INT32 playernum) if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum))) continue; + p->starpostscale = players[i].starpostscale; p->starposttime = players[i].starposttime; p->starpostx = players[i].starpostx; p->starposty = players[i].starposty; @@ -3782,7 +3799,29 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) // File end marker check CHECKPOS - if (READUINT8(save_p) != 0x1d) BADSAVE; + switch (READUINT8(save_p)) + { + case 0xb7: + { + UINT8 i, banksinuse; + CHECKPOS + banksinuse = READUINT8(save_p); + CHECKPOS + if (banksinuse > NUM_LUABANKS) + BADSAVE + for (i = 0; i < banksinuse; i++) + { + (void)READINT32(save_p); + CHECKPOS + } + if (READUINT8(save_p) != 0x1d) + BADSAVE + } + case 0x1d: + break; + default: + BADSAVE + } // done saved = FIL_WriteFile(backup, savebuffer, length); @@ -3866,7 +3905,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean for (i = 0; i < MAXPLAYERS; i++) { players[i].playerstate = PST_REBORN; - players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0; + players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0; players[i].starpostx = players[i].starposty = players[i].starpostz = 0; if (netgame || multiplayer) @@ -4577,7 +4616,7 @@ void G_GhostTicker(void) default: case GHC_RETURNSKIN: g->mo->skin = g->oldmo.skin; - // fallthru + /* FALLTHRU */ case GHC_NORMAL: // Go back to skin color g->mo->color = g->oldmo.color; break; diff --git a/src/g_game.h b/src/g_game.h index e161bc8ed..df1301dd7 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -100,7 +100,7 @@ extern INT32 localaiming, localaiming2; // should be an angle_t but signed // void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo); void G_DoReborn(INT32 playernum); -void G_PlayerReborn(INT32 player); +void G_PlayerReborn(INT32 player, boolean betweenmaps); void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean skipprecutscene, boolean FLS); char *G_BuildMapTitle(INT32 mapnum); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 6bc2c712e..02df290b8 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -30,6 +30,7 @@ #include "../z_zone.h" #include "../v_video.h" #include "../r_draw.h" +#include "../p_setup.h" //Hurdler: 25/04/2000: used for new colormap code in hardware mode //static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized) @@ -60,7 +61,6 @@ static const INT32 format2bpp[16] = 2, //14 GR_TEXFMT_AP_88 }; - // This code was originally placed directly in HWR_DrawPatchInCache. // It is now split from it for my sanity! (and the sanity of others) // -- Monster Iestyn (13/02/19) @@ -138,18 +138,37 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm // Alam: SRB2 uses Mingw, HUGS switch (bpp) { - case 2 : texelu16 = (UINT16)((alpha<<8) | texel); + case 2 : // uhhhhhhhh.......... + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 - default: *dest = texel; + default: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; break; } @@ -233,18 +252,37 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, // Alam: SRB2 uses Mingw, HUGS switch (bpp) { - case 2 : texelu16 = (UINT16)((alpha<<8) | texel); + case 2 : // uhhhhhhhh.......... + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3 : colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4 : colortemp = V_GetColor(texel); colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } memcpy(dest, &colortemp, sizeof(RGBA_t)); break; // default is 1 - default: *dest = texel; + default: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; break; } @@ -331,16 +369,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, if (texture->width <= 0 || texture->height <= 0) return; - /*if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then. - continue; - ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawTransFlippedColumnInCache : HWR_DrawTransColumnInCache; - } - else*/ - { - ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; - } + ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; x1 = patch->originx; width = SHORT(realpatch->width); @@ -420,6 +449,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, GrTexInfo *grInfo) { +#ifdef GLIDE_API_COMPATIBILITY // Build the full textures from patches. static const GrLOD_t gr_lods[9] = { @@ -456,6 +486,9 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, INT32 j,k; INT32 max,min; +#else + (void)grInfo; +#endif // find a power of 2 width/height if (cv_grrounddown.value) @@ -511,6 +544,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, } else { +#ifdef GLIDE_API_COMPATIBILITY //size up to nearest power of 2 blockwidth = 1; while (blockwidth < originalwidth) @@ -528,9 +562,14 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockheight > 2048) blockheight = 2048; //I_Error("3D GenerateTexture : too big"); +#else + blockwidth = originalwidth; + blockheight = originalheight; +#endif } // do the boring LOD stuff.. blech! +#ifdef GLIDE_API_COMPATIBILITY if (blockwidth >= blockheight) { max = blockwidth; @@ -562,6 +601,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, if (blockwidth < blockheight) j += 4; grInfo->aspectRatioLog2 = gr_aspects[j].aspect; +#endif blocksize = blockwidth * blockheight; @@ -650,7 +690,12 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { + size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); +#endif HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, @@ -679,6 +724,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm { INT32 newwidth, newheight; +#ifndef NO_PNG_LUMPS + // lump is a png so convert it + size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum); + if ((patch != NULL) && R_IsLumpPNG((const UINT8 *)patch, len)) + patch = R_PNGToPatch((const UINT8 *)patch, len, NULL, true); +#endif + // don't do it twice (like a cache) if (grMipmap->width == 0) { @@ -756,11 +808,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm static size_t gr_numtextures; static GLTexture_t *gr_textures; // for ALL Doom textures +static GLTexture_t *gr_textures2; void HWR_InitTextureCache(void) { gr_numtextures = 0; gr_textures = NULL; + gr_textures2 = NULL; } @@ -799,7 +853,10 @@ void HWR_FreeTextureCache(void) // texturecache info, we can free it if (gr_textures) free(gr_textures); + if (gr_textures2) + free(gr_textures2); gr_textures = NULL; + gr_textures2 = NULL; gr_numtextures = 0; } @@ -817,6 +874,9 @@ void HWR_PrepLevelCache(size_t pnumtextures) gr_textures = calloc(pnumtextures, sizeof (*gr_textures)); if (gr_textures == NULL) I_Error("3D can't alloc gr_textures"); + gr_textures2 = calloc(pnumtextures, sizeof (*gr_textures2)); + if (gr_textures2 == NULL) + I_Error("3D can't alloc gr_textures2"); } void HWR_SetPalette(RGBA_t *palette) @@ -847,7 +907,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex) GLTexture_t *grtex; #ifdef PARANOIA if ((unsigned)tex >= gr_numtextures) - I_Error(" HWR_GetTexture: tex >= numtextures\n"); + I_Error("HWR_GetTexture: tex >= numtextures\n"); #endif grtex = &gr_textures[tex]; @@ -862,15 +922,39 @@ GLTexture_t *HWR_GetTexture(INT32 tex) return grtex; } +// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch. +lumpnum_t gr_patchflat; + +static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) +{ + UINT8 *flat; + patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC); + size_t lumplength = W_LumpLength(flatlumpnum); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)patch, lumplength)) + patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL, false); +#endif + + grMipmap->width = (UINT16)SHORT(patch->width); + grMipmap->height = (UINT16)SHORT(patch->height); + + flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); + memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); + + R_PatchToFlat(patch, flat); +} static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { size_t size, pflatsize; // setup the texture info +#ifdef GLIDE_API_COMPATIBILITY grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -900,15 +984,20 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) pflatsize = 64; break; } - grMipmap->width = (UINT16)pflatsize; - grMipmap->height = (UINT16)pflatsize; - // the flat raw data needn't be converted with palettized textures - W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), - PU_HWRCACHE, &grMipmap->grInfo.data)); + if (R_CheckIfPatch(flatlumpnum)) + HWR_LoadPatchFlat(grMipmap, flatlumpnum); + else + { + grMipmap->width = (UINT16)pflatsize; + grMipmap->height = (UINT16)pflatsize; + + // the flat raw data needn't be converted with palettized textures + W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), + PU_HWRCACHE, &grMipmap->grInfo.data)); + } } - // Download a Doom 'flat' to the hardware cache and make it ready for use void HWR_GetFlat(lumpnum_t flatlumpnum) { @@ -923,6 +1012,52 @@ void HWR_GetFlat(lumpnum_t flatlumpnum) // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + + gr_patchflat = 0; + if (R_CheckIfPatch(flatlumpnum)) + gr_patchflat = flatlumpnum; +} + +static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum) +{ + UINT8 *flat; + + // setup the texture info +#ifdef GLIDE_API_COMPATIBILITY + grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; + grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif + grMipmap->grInfo.format = GR_TEXFMT_P_8; + grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; + + flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data); + memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height); + + R_TextureToFlat(texturenum, flat); +} + +void HWR_GetTextureFlat(INT32 texturenum) +{ + GLTexture_t *grtex; +#ifdef PARANOIA + if ((unsigned)texturenum >= gr_numtextures) + I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n"); +#endif + if (texturenum == 0 || texturenum == -1) + return; + grtex = &gr_textures2[texturenum]; + + if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) + HWR_LoadTextureFlat(&grtex->mipmap, texturenum); + + HWD.pfnSetTexture(&grtex->mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); } // diff --git a/src/hardware/hw_glide.h b/src/hardware/hw_glide.h index 2625d5864..bf91229ef 100644 --- a/src/hardware/hw_glide.h +++ b/src/hardware/hw_glide.h @@ -59,9 +59,11 @@ typedef FxI32 GrTextureFormat_t; typedef struct { +#ifdef GLIDE_API_COMPATIBILITY GrLOD_t smallLodLog2; GrLOD_t largeLodLog2; GrAspectRatio_t aspectRatioLog2; +#endif GrTextureFormat_t format; void *data; } GrTexInfo; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 9656e54e9..c7b06edfd 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -101,6 +101,7 @@ void HWR_FreeTextureCache(void); void HWR_FreeExtraSubsectors(void); void HWR_GetFlat(lumpnum_t flatlumpnum); +void HWR_GetTextureFlat(INT32 texturenum); GLTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetPatch(GLPatch_t *gpatch); void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); @@ -114,6 +115,8 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- +extern lumpnum_t gr_patchflat; + extern float gr_patch_scalex; extern float gr_patch_scaley; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index a52d72869..1de20cad7 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -186,17 +186,16 @@ light_t *t_lspr[NUMSPRITES] = // Boss 1, (Greenflower) &lspr[NOLIGHT], // SPR_EGGM + &lspr[NOLIGHT], // SPR_EGLZ // Boss 2, (Techno Hill) &lspr[NOLIGHT], // SPR_EGGN - &lspr[NOLIGHT], // SPR_TNKA - &lspr[NOLIGHT], // SPR_TNKB - &lspr[NOLIGHT], // SPR_SPNK + &lspr[NOLIGHT], // SPR_TANK &lspr[NOLIGHT], // SPR_GOOP // Boss 3 (Deep Sea) &lspr[NOLIGHT], // SPR_EGGO - &lspr[NOLIGHT], // SPR_PRPL + &lspr[NOLIGHT], // SPR_SEBH &lspr[NOLIGHT], // SPR_FAKE // Boss 4 (Castle Eggman) @@ -1226,9 +1225,11 @@ static void HWR_SetLight(void) lightmappatch.height = 128; lightmappatch.mipmap.width = 128; lightmappatch.mipmap.height = 128; +#ifdef GLIDE_API_COMPATIBILITY lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128; lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif lightmappatch.mipmap.flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! } HWD.pfnSetTexture(&lightmappatch.mipmap); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c600800fd..4a075d376 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -70,9 +70,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif #ifdef SORTING -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); #else static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, @@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) + FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -530,8 +530,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is INT32 nrPlaneVerts; //verts original define of convex flat polygon INT32 i; float flatxref,flatyref; - float fflatsize; + float fflatwidth, fflatheight; INT32 flatflag; + boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; @@ -540,6 +541,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is #ifdef ESLOPE pslope_t *slope = NULL; #endif + patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -580,9 +582,10 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > (INT32)UINT16_MAX) // FIXME: exceeds plVerts size + // This check is so inconsistent between functions, it hurts. + if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); + CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX); return; } @@ -599,38 +602,47 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is switch (len) { case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; + fflatwidth = fflatheight = 2048.0f; break; case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; + fflatwidth = fflatheight = 1024.0f; break; case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; + fflatwidth = fflatheight = 512.0f; break; case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; + fflatwidth = fflatheight = 256.0f; break; case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; + fflatwidth = fflatheight = 128.0f; break; case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; + fflatwidth = fflatheight = 32.0f; break; default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; + fflatwidth = fflatheight = 64.0f; break; } + flatflag = ((INT32)fflatwidth)-1; + + if (texturenum != 0 && texturenum != -1) + { + fflatwidth = textures[texturenum]->width; + fflatheight = textures[texturenum]->height; + } + else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = SHORT(patch->width); + fflatheight = SHORT(patch->height); + } + else + texflat = false; + // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize); + flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); + flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight); // transform v3d = planeVerts; @@ -639,14 +651,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; angle = FOFsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; angle = FOFsector->ceilingpic_angle; } } @@ -654,14 +666,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; angle = gr_frontsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; angle = gr_frontsector->ceilingpic_angle; } } @@ -680,17 +692,24 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly); - - //v3d->sow = (float)(pv->x / fflatsize); - //v3d->tow = (float)(pv->y / fflatsize); + if (texflat) + { + v3d->sow = (float)(pv->x / fflatwidth) + scrollx; + v3d->tow = -(float)(pv->y / fflatheight) + scrolly; + } + else + { + v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx); + v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly); + } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); + if (texflat) + tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } @@ -3164,21 +3183,23 @@ static inline void HWR_AddPolyObjectSegs(void) #ifdef POLYOBJECTS_PLANES static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, - FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, + FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { float height; //constant y for all points on the convex flat polygon FOutVector *v3d; INT32 i; float flatxref,flatyref; - float fflatsize; + float fflatwidth, fflatheight; INT32 flatflag; + boolean texflat = true; size_t len; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; fixed_t tempxsow, tempytow; size_t nrPlaneVerts; + patch_t *patch; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; @@ -3209,38 +3230,47 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, switch (len) { case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; + fflatwidth = fflatheight = 2048.0f; break; case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; + fflatwidth = fflatheight = 1024.0f; break; case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; + fflatwidth = fflatheight = 512.0f; break; case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; + fflatwidth = fflatheight = 256.0f; break; case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; + fflatwidth = fflatheight = 128.0f; break; case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; + fflatwidth = fflatheight = 32.0f; break; default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; + fflatwidth = fflatheight = 64.0f; break; } + flatflag = ((INT32)fflatwidth)-1; + + if (texturenum != 0 && texturenum != -1) + { + fflatwidth = textures[texturenum]->width; + fflatheight = textures[texturenum]->height; + } + else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case? + { + patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC); + fflatwidth = SHORT(patch->width); + fflatheight = SHORT(patch->height); + } + else + texflat = false; + // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize); + flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); + flatyref = (float)((polysector->origVerts[0].y & (~flatflag)) / fflatheight); // transform v3d = planeVerts; @@ -3249,14 +3279,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3264,14 +3294,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight; angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight; angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; } } @@ -3294,15 +3324,26 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { - // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations + // Go from the polysector's original vertex locations + // Means the flat is offset based on the original vertex locations + if (texflat) + { + v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; + v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; + } + else + { + v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); + v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); + } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); + if (texflat) + tempytow = -tempytow; v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); } @@ -3333,6 +3374,7 @@ static void HWR_AddPolyObjectPlanes(void) { size_t i; sector_t *polyobjsector; + INT32 light = 0; // Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves // It should be okay because polyobjects should always be convex anyway @@ -3351,19 +3393,23 @@ static void HWR_AddPolyObjectPlanes(void) && polyobjsector->floorheight >= gr_frontsector->floorheight && (viewz < polyobjsector->floorheight)) { + light = R_GetPlaneLight(gr_frontsector, polyobjsector->floorheight, true); if (po_ptrs[i]->translucency > 0) { FSurfaceInfo Surf; - FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight, - polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + FBITFIELD blendmode; + memset(&Surf, 0x00, sizeof(Surf)); + blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight, + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); + HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, - polyobjsector, 255, NULL); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, + polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } @@ -3371,21 +3417,23 @@ static void HWR_AddPolyObjectPlanes(void) && polyobjsector->ceilingheight <= gr_frontsector->ceilingheight && (viewz > polyobjsector->ceilingheight)) { + light = R_GetPlaneLight(gr_frontsector, polyobjsector->ceilingheight, true); if (po_ptrs[i]->translucency > 0) { FSurfaceInfo Surf; FBITFIELD blendmode; memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight, - polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight, + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); + HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, - polyobjsector, 255, NULL); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, + polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } } } @@ -3536,11 +3584,12 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum); + HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum); HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap); } } else @@ -3558,11 +3607,12 @@ static void HWR_Subsector(size_t num) if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum); + HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum); HWR_RenderPlane(NULL, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap); } } else @@ -3621,7 +3671,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, + HWR_AddTransparentFloor(0, 0, &extrasubsectors[num], false, *rover->bottomheight, @@ -3640,6 +3690,7 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum, + levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], false, *rover->bottomheight, @@ -3651,8 +3702,9 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); + HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, + HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum, rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3684,7 +3736,7 @@ static void HWR_Subsector(size_t num) else alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - HWR_AddTransparentFloor(0, + HWR_AddTransparentFloor(0, 0, &extrasubsectors[num], true, *rover->topheight, @@ -3703,6 +3755,7 @@ static void HWR_Subsector(size_t num) rover->alpha-1, rover->master->frontsector); #else HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum, + levelflats[*rover->bottompic].texturenum, &extrasubsectors[num], true, *rover->topheight, @@ -3715,8 +3768,9 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->toppic].lumpnum); + HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, + HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum, rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -5045,6 +5099,7 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; + INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5063,6 +5118,7 @@ typedef struct fixed_t fixedheight; INT32 lightlevel; lumpnum_t lumpnum; + INT32 texturenum; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -5093,7 +5149,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, +void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -5112,6 +5168,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean planeinfo[numplanes].fixedheight = fixedheight; planeinfo[numplanes].lightlevel = lightlevel; planeinfo[numplanes].lumpnum = lumpnum; + planeinfo[numplanes].texturenum = texturenum; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].FOFSector = FOFSector; @@ -5125,7 +5182,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -5144,6 +5201,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, polyplaneinfo[numpolyplanes].fixedheight = fixedheight; polyplaneinfo[numpolyplanes].lightlevel = lightlevel; polyplaneinfo[numpolyplanes].lumpnum = lumpnum; + polyplaneinfo[numpolyplanes].texturenum = texturenum; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; polyplaneinfo[numpolyplanes].FOFSector = FOFSector; @@ -5305,9 +5363,12 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) + { HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum); + HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum); + } HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { @@ -5315,9 +5376,12 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) + { HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum); + HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum); + } HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, - sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d4728315a..cd1b957f0 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -26,6 +26,7 @@ #include #include +#include "../d_main.h" #include "../doomdef.h" #include "../doomstat.h" #include "../fastcmp.h" @@ -70,6 +71,10 @@ #endif #endif +#ifndef errno +#include "errno.h" +#endif + #define NUMVERTEXNORMALS 162 float avertexnormals[NUMVERTEXNORMALS][3] = { {-0.525731f, 0.000000f, 0.850651f}, @@ -294,7 +299,8 @@ static md2_model_t *md2_readModel(const char *filename) if (model == NULL) return 0; - file = fopen(filename, "rb"); + //Filename checking fixed ~Monster Iestyn and Golden + file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb"); if (!file) { free(model); @@ -523,7 +529,8 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ #endif #endif png_FILE_p png_FILE; - char *pngfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); @@ -651,7 +658,8 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h, size_t pw, ph, size, ptr = 0; INT32 ch, rep; FILE *file; - char *pcxfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pcxfilename, ".pcx"); file = fopen(pcxfilename, "rb"); @@ -747,10 +755,12 @@ static void md2_loadTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; +#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif } HWD.pfnSetTexture(&grpatch->mipmap); HWR_UnlockCachedPatch(grpatch); @@ -798,10 +808,12 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->mipmap.width = (UINT16)w; grpatch->mipmap.height = (UINT16)h; +#ifdef GLIDE_API_COMPATIBILITY // not correct! grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256; grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; +#endif } HWD.pfnSetTexture(&grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary HWR_UnlockCachedPatch(grpatch); @@ -841,11 +853,12 @@ void HWR_InitMD2(void) } // read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { - CONS_Printf("%s", M_GetText("Error while loading md2.dat\n")); + CONS_Printf("%s %s\n", M_GetText("Error while loading md2.dat:"), strerror(errno)); nomd2s = true; return; } @@ -907,7 +920,8 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup CONS_Printf("AddPlayerMD2()...\n"); // read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { @@ -952,7 +966,8 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu return; // Read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { @@ -1198,7 +1213,7 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p if (!md2 || !skin) return 0; - if ((unsigned)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) return 0; while (!(md2->model->spr2frames[spr2*2 + 1]) diff --git a/src/info.c b/src/info.c index 18f0e838a..da8022cd4 100644 --- a/src/info.c +++ b/src/info.c @@ -73,18 +73,17 @@ char sprnames[NUMSPRITES + 1][5] = "JETF", // Boss jet fumes // Boss 1 (Greenflower) - "EGGM", + "EGGM", // Boss 1 + "EGLZ", // Boss 1 Junk // Boss 2 (Techno Hill) "EGGN", // Boss 2 - "TNKA", // Boss 2 Tank 1 - "TNKB", // Boss 2 Tank 2 - "SPNK", // Boss 2 Spigot + "TANK", // Boss 2 Junk "GOOP", // Boss 2 Goop // Boss 3 (Deep Sea) "EGGO", // Boss 3 - "PRPL", // Boss 3 Propeller + "SEBH", // Boss 3 Junk "FAKE", // Boss 3 Fakemobile // Boss 4 (Castle Eggman) @@ -213,11 +212,11 @@ char sprnames[NUMSPRITES + 1][5] = "GARG", // Deep Sea Gargoyle "SEWE", // Deep Sea Seaweed "DRIP", // Dripping water - "CRL1", // Coral 1 - "CRL2", // Coral 2 - "CRL3", // Coral 3 + "CORL", // Coral "BCRY", // Blue Crystal "KELP", // Kelp + "ALGA", // Animated algae top + "ALGB", // Animated algae segment "DSTG", // DSZ Stalagmites "LIBE", // DSZ Light beam @@ -247,7 +246,7 @@ char sprnames[NUMSPRITES + 1][5] = // Arid Canyon Scenery "BTBL", // Big tumbleweed "STBL", // Small tumbleweed - "CACT", // Cacti sprites + "CACT", // Cacti "WWSG", // Caution Sign "WWS2", // Cacti Sign "WWS3", // Sharp Turn Sign @@ -577,8 +576,14 @@ char spr2names[NUMPLAYERSPRITES][5] = "TALA", "TALB", + "CNT1", + "CNT2", + "CNT3", + "CNT4", + "SIGN", "LIFE", + "XTRA", }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; @@ -674,8 +679,14 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_TAL9, // SPR2_TALA, SPR2_TAL0, // SPR2_TALB, + SPR2_WAIT, // SPR2_CNT1, + SPR2_FALL, // SPR2_CNT2, + SPR2_SPNG, // SPR2_CNT3, + SPR2_CNT1, // SPR2_CNT4, + 0, // SPR2_SIGN, 0, // SPR2_LIFE, + 0, // SPR2_XTRA (should never be referenced) }; @@ -728,7 +739,7 @@ state_t states[NUMSTATES] = // CA_FLY/CA_SWIM {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY - {SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM + {SPR_PLAY, SPR2_SWIM, 4, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED // CA_GLIDEANDCLIMB @@ -1179,49 +1190,58 @@ state_t states[NUMSTATES] = {SPR_BOM3, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION6}, // S_SONIC3KBOSSEXPLOSION5 {SPR_BOM3, FF_FULLBRIGHT|5, 4, {NULL}, 0, 0, S_NULL}, // S_SONIC3KBOSSEXPLOSION6 - {SPR_JETF, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETFUME2}, // S_JETFUME1 - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_JETFUME1}, // S_JETFUME2 + {SPR_JETF, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 2, 1, S_NULL}, // S_JETFUME1 // Boss 1 {SPR_EGGM, 0, 1, {A_Boss1Chase}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_STND + {SPR_EGGM, FF_ANIMATE|17, 35, {A_FaceTarget}, 1, 2, S_EGGMOBILE_STND}, // S_EGGMOBILE_ROFL {SPR_EGGM, 1, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK2}, // S_EGGMOBILE_LATK1 {SPR_EGGM, 2, 15, {NULL}, 0, 0, S_EGGMOBILE_LATK3}, // S_EGGMOBILE_LATK2 - {SPR_EGGM, 3, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK4}, // S_EGGMOBILE_LATK3 - {SPR_EGGM, 4, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK5}, // S_EGGMOBILE_LATK4 - {SPR_EGGM, 5, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK6}, // S_EGGMOBILE_LATK5 - {SPR_EGGM, 6, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK7}, // S_EGGMOBILE_LATK6 - {SPR_EGGM, 7, 1, {NULL}, 0, 0, S_EGGMOBILE_LATK8}, // S_EGGMOBILE_LATK7 - {SPR_EGGM, 8, 45, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK9}, // S_EGGMOBILE_LATK8 - {SPR_EGGM, 9, 10, {NULL}, 0, 0, S_EGGMOBILE_LATK10}, // S_EGGMOBILE_LATK9 - {SPR_EGGM, 10, 2, {NULL}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_LATK10 - {SPR_EGGM, 11, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2}, // S_EGGMOBILE_RATK1 - {SPR_EGGM, 12, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3}, // S_EGGMOBILE_RATK2 - {SPR_EGGM, 13, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK4}, // S_EGGMOBILE_RATK3 - {SPR_EGGM, 14, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK5}, // S_EGGMOBILE_RATK4 - {SPR_EGGM, 15, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK6}, // S_EGGMOBILE_RATK5 - {SPR_EGGM, 16, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK7}, // S_EGGMOBILE_RATK6 - {SPR_EGGM, 17, 1, {NULL}, 0, 0, S_EGGMOBILE_RATK8}, // S_EGGMOBILE_RATK7 - {SPR_EGGM, 18, 45, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK9}, // S_EGGMOBILE_RATK8 - {SPR_EGGM, 19, 10, {NULL}, 0, 0, S_EGGMOBILE_RATK10}, // S_EGGMOBILE_RATK9 - {SPR_EGGM, 20, 2, {NULL}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_RATK10 - {SPR_EGGM, 3, 12, {NULL}, 0, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1 - {SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2 - {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3 - {SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC5 }, // S_EGGMOBILE_PANIC4 - {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5 - {SPR_EGGM, 4, 45, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC7 }, // S_EGGMOBILE_PANIC6 - {SPR_EGGM, 0, 35, {NULL}, 0, 0, S_EGGMOBILE_STND }, // S_EGGMOBILE_PANIC7 - {SPR_EGGM, 21, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN - {SPR_EGGM, 21, 16, {A_SkullAttack}, 1, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2 - {SPR_EGGM, 22, 2, {A_Fall}, 0, 0, S_EGGMOBILE_DIE2}, // S_EGGMOBILE_DIE1 - {SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3}, // S_EGGMOBILE_DIE2 - {SPR_EGGM, 22, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4}, // S_EGGMOBILE_DIE3 - {SPR_EGGM, 22, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE_DIE4 - {SPR_EGGM, 23, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2}, // S_EGGMOBILE_FLEE1 - {SPR_EGGM, 24, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1}, // S_EGGMOBILE_FLEE2 + {SPR_EGGM, 3, 2, {NULL}, 0, 0, S_EGGMOBILE_LATK4}, // S_EGGMOBILE_LATK3 + {SPR_EGGM, 4, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK5}, // S_EGGMOBILE_LATK4 + {SPR_EGGM, 6, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_LATK6}, // S_EGGMOBILE_LATK5 + {SPR_EGGM, 5, 1, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK7}, // S_EGGMOBILE_LATK6 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, (1<<16), S_EGGMOBILE_LATK8}, // S_EGGMOBILE_LATK7 + {SPR_EGGM, 5, 0, {A_Repeat}, 45, S_EGGMOBILE_LATK6, S_EGGMOBILE_LATK9}, // S_EGGMOBILE_LATK8 + {SPR_EGGM, 8, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_LATK9 + {SPR_EGGM, 9, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2}, // S_EGGMOBILE_RATK1 + {SPR_EGGM, 10, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3}, // S_EGGMOBILE_RATK2 + {SPR_EGGM, 11, 2, {NULL}, 0, 0, S_EGGMOBILE_RATK4}, // S_EGGMOBILE_RATK3 + {SPR_EGGM, 12, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK5}, // S_EGGMOBILE_RATK4 + {SPR_EGGM, 14, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_RATK6}, // S_EGGMOBILE_RATK5 + {SPR_EGGM, 13, 1, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK7}, // S_EGGMOBILE_RATK6 + {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 1|(1<<16), S_EGGMOBILE_RATK8}, // S_EGGMOBILE_RATK7 + {SPR_EGGM, 13, 0, {A_Repeat}, 45, S_EGGMOBILE_RATK6, S_EGGMOBILE_RATK9}, // S_EGGMOBILE_RATK8 + {SPR_EGGM, 16, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_RATK9 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1 + {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2 + {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC5}, // S_EGGMOBILE_PANIC4 + {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC3, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC7}, // S_EGGMOBILE_PANIC6 + {SPR_EGGM, FF_ANIMATE|9, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC8}, // S_EGGMOBILE_PANIC7 + {SPR_EGGM, 15, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC9}, // S_EGGMOBILE_PANIC8 + {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC10}, // S_EGGMOBILE_PANIC9 + {SPR_EGGM, 14, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC8, S_EGGMOBILE_PANIC11}, // S_EGGMOBILE_PANIC10 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC12}, // S_EGGMOBILE_PANIC11 + {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC13}, // S_EGGMOBILE_PANIC12 + {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC14}, // S_EGGMOBILE_PANIC13 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC15}, // S_EGGMOBILE_PANIC14 + {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC13, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_PANIC15 + {SPR_EGGM, 19, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN + {SPR_EGGM, 19, 16, {A_SkullAttack}, 3, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2 + {SPR_EGGM, 20, 2, {A_Fall}, 17, 0, S_EGGMOBILE_DIE2}, // S_EGGMOBILE_DIE1 + {SPR_EGGM, 20, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3}, // S_EGGMOBILE_DIE2 + {SPR_EGGM, 20, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4}, // S_EGGMOBILE_DIE3 + {SPR_EGGM, 20, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE_DIE4 + {SPR_EGGM, 21, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2}, // S_EGGMOBILE_FLEE1 + {SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1}, // S_EGGMOBILE_FLEE2 {SPR_UNID, 1, 1, {A_UnidusBall}, 2, 0, S_EGGMOBILE_BALL}, // S_EGGMOBILE_BALL {SPR_NULL, 0, 1, {A_FocusTarget}, 0, 0, S_EGGMOBILE_TARGET}, // S_EGGMOBILE_TARGET + {SPR_EGLZ, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ1 + {SPR_EGLZ, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ2 + // Boss 2 {SPR_EGGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE2_STND {SPR_EGGN, 1, 4, {NULL}, 0, 0, S_EGGMOBILE2_POGO2}, // S_EGGMOBILE2_POGO1 @@ -1240,9 +1260,9 @@ state_t states[NUMSTATES] = {SPR_EGGN, 6, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE2}, // S_EGGMOBILE2_FLEE1 {SPR_EGGN, 7, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE1}, // S_EGGMOBILE2_FLEE2 - {SPR_TNKA, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1 - {SPR_TNKB, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2 - {SPR_SPNK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT + {SPR_TANK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1 + {SPR_TANK, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2 + {SPR_TANK, 2, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT // Boss 2 Goop {SPR_GOOP, 0, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP2}, // S_GOOP1 @@ -1252,34 +1272,16 @@ state_t states[NUMSTATES] = // Boss 3 {SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_ATK1}, // S_EGGMOBILE3_LAUGH5 - {SPR_EGGO, 1, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1 + {SPR_EGGO, FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_SHOCK + {SPR_EGGO, 6|FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1 {SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A}, // S_EGGMOBILE3_ATK2 {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B}, // S_EGGMOBILE3_ATK3A {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 4, S_EGGMOBILE3_ATK3C}, // S_EGGMOBILE3_ATK3B {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D}, // S_EGGMOBILE3_ATK3C {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4}, // S_EGGMOBILE3_ATK3D {SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5}, // S_EGGMOBILE3_ATK4 - {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_ATK5 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH7}, // S_EGGMOBILE3_LAUGH6 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH8}, // S_EGGMOBILE3_LAUGH7 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH9}, // S_EGGMOBILE3_LAUGH8 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH10}, // S_EGGMOBILE3_LAUGH9 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH11}, // S_EGGMOBILE3_LAUGH10 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH12}, // S_EGGMOBILE3_LAUGH11 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH13}, // S_EGGMOBILE3_LAUGH12 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH14}, // S_EGGMOBILE3_LAUGH13 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH15}, // S_EGGMOBILE3_LAUGH14 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH16}, // S_EGGMOBILE3_LAUGH15 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH17}, // S_EGGMOBILE3_LAUGH16 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH18}, // S_EGGMOBILE3_LAUGH17 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH19}, // S_EGGMOBILE3_LAUGH18 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH20}, // S_EGGMOBILE3_LAUGH19 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_LAUGH20 + {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_ROFL}, // S_EGGMOBILE3_ATK5 + {SPR_EGGO, 6|FF_ANIMATE, 60, {NULL}, 1, 2, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_ROFL {SPR_EGGO, 8, 1, {A_Boss3TakeDamage}, 0, 0, S_EGGMOBILE3_PAIN2}, // S_EGGMOBILE3_PAIN {SPR_EGGO, 8, 23, {A_Pain}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_PAIN2 {SPR_EGGO, 9, 2, {A_Fall}, 0, 0, S_EGGMOBILE3_DIE2}, // S_EGGMOBILE3_DIE1 @@ -1289,17 +1291,8 @@ state_t states[NUMSTATES] = {SPR_EGGO, 10, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE2}, // S_EGGMOBILE3_FLEE1 {SPR_EGGO, 11, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE1}, // S_EGGMOBILE3_FLEE2 - // Boss 3 Propeller - {SPR_PRPL, 0, 1, {NULL}, 0, 0, S_PROPELLER2}, // S_PROPELLER1 - {SPR_PRPL, 1, 1, {NULL}, 0, 0, S_PROPELLER3}, // S_PROPELLER2 - {SPR_PRPL, 2, 1, {NULL}, 0, 0, S_PROPELLER4}, // S_PROPELLER3 - {SPR_PRPL, 3, 1, {NULL}, 0, 0, S_PROPELLER5}, // S_PROPELLER4 - {SPR_PRPL, 4, 1, {NULL}, 0, 0, S_PROPELLER6}, // S_PROPELLER5 - {SPR_PRPL, 5, 1, {NULL}, 0, 0, S_PROPELLER7}, // S_PROPELLER6 - {SPR_PRPL, 6, 1, {NULL}, 0, 0, S_PROPELLER1}, // S_PROPELLER7 - // Boss 3 Pinch - {SPR_FAKE, 0, 1, {A_BossJetFume}, 1, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT + {SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT {SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE {SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1 {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A}, // S_FAKEMOBILE_ATK2 @@ -1307,33 +1300,36 @@ state_t states[NUMSTATES] = {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C}, // S_FAKEMOBILE_ATK3B {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D}, // S_FAKEMOBILE_ATK3C {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK3D - {SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1 + {SPR_FAKE, 1, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1 {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1}, // S_FAKEMOBILE_DIE2 + {SPR_SEBH, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH1 + {SPR_SEBH, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH2 + // Boss 4 {SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND {SPR_EGGP, 1, 3, {NULL}, 0, 0, S_EGGMOBILE4_LATK2}, // S_EGGMOBILE4_LATK1 {SPR_EGGP, 2, 15, {NULL}, 0, 0, S_EGGMOBILE4_LATK3}, // S_EGGMOBILE4_LATK2 {SPR_EGGP, 3, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK4}, // S_EGGMOBILE4_LATK3 - {SPR_EGGP, 4, 4, {NULL}, 0, 0, S_EGGMOBILE4_LATK5}, // S_EGGMOBILE4_LATK4 - {SPR_EGGP, 4, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6}, // S_EGGMOBILE4_LATK5 - {SPR_EGGP, 5, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_LATK6 - {SPR_EGGP, 6, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2}, // S_EGGMOBILE4_RATK1 - {SPR_EGGP, 7, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3}, // S_EGGMOBILE4_RATK2 - {SPR_EGGP, 8, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4}, // S_EGGMOBILE4_RATK3 - {SPR_EGGP, 9, 4, {NULL}, 0, 0, S_EGGMOBILE4_RATK5}, // S_EGGMOBILE4_RATK4 - {SPR_EGGP, 9,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5 - {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6 - {SPR_EGGP, 0, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1 - {SPR_EGGP,13|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2 - {SPR_EGGP,11, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1 - {SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2 - {SPR_EGGP,12, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1 - {SPR_EGGP,12, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2 - {SPR_EGGP,12, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3 - {SPR_EGGP,12, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE4_DIE4 - {SPR_EGGP,13, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1 - {SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2 + {SPR_EGGP, 4, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK5}, // S_EGGMOBILE4_LATK4 + {SPR_EGGP, 5, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6}, // S_EGGMOBILE4_LATK5 + {SPR_EGGP, 6, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_LATK6 + {SPR_EGGP, 7, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2}, // S_EGGMOBILE4_RATK1 + {SPR_EGGP, 8, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3}, // S_EGGMOBILE4_RATK2 + {SPR_EGGP, 9, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4}, // S_EGGMOBILE4_RATK3 + {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK5}, // S_EGGMOBILE4_RATK4 + {SPR_EGGP,11,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5 + {SPR_EGGP,12, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6 + {SPR_EGGP,13, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1 + {SPR_EGGP,15|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2 + {SPR_EGGP,13, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1 + {SPR_EGGP,13, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2 + {SPR_EGGP,14, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1 + {SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2 + {SPR_EGGP,14, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3 + {SPR_EGGP,14, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE4_DIE4 + {SPR_EGGP,15, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1 + {SPR_EGGP,16, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2 {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_MACE {SPR_BMCE, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE2}, // S_EGGMOBILE4_MACE_DIE1 {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE3}, // S_EGGMOBILE4_MACE_DIE2 @@ -1732,18 +1728,8 @@ state_t states[NUMSTATES] = {SPR_METL, 11, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 {SPR_METL, 11, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 2, 1, {NULL}, 0, 0, S_MSSHIELD_F4}, // S_MSSHIELD_F3 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 3, 1, {NULL}, 0, 0, S_MSSHIELD_F5}, // S_MSSHIELD_F4 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 4, 1, {NULL}, 0, 0, S_MSSHIELD_F6}, // S_MSSHIELD_F5 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 5, 1, {NULL}, 0, 0, S_MSSHIELD_F7}, // S_MSSHIELD_F6 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 6, 1, {NULL}, 0, 0, S_MSSHIELD_F8}, // S_MSSHIELD_F7 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 7, 1, {NULL}, 0, 0, S_MSSHIELD_F9}, // S_MSSHIELD_F8 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 8, 1, {NULL}, 0, 0, S_MSSHIELD_F10}, // S_MSSHIELD_F9 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 9, 1, {NULL}, 0, 0, S_MSSHIELD_F11}, // S_MSSHIELD_F10 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|10, 1, {NULL}, 0, 0, S_MSSHIELD_F12}, // S_MSSHIELD_F11 - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1}, // S_MSSHIELD_F12 + {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1 + {SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2 // Ring {SPR_RING, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING}, // S_RING @@ -2178,14 +2164,12 @@ state_t states[NUMSTATES] = {SPR_DRIP, FF_TRANS30|4, 1, {NULL}, 0, 0, S_DRIPC2}, // S_DRIPC1 {SPR_DRIP, FF_TRANS30|5, 1, {NULL}, 0, 0, S_NULL}, // S_DRIPC2 - // Coral 1 - {SPR_CRL1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL1 - - // Coral 2 - {SPR_CRL2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL2 - - // Coral 3 - {SPR_CRL3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL3 + // Coral + {SPR_CORL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL1 + {SPR_CORL, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL2 + {SPR_CORL, 2, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL3 + {SPR_CORL, 3, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL4 + {SPR_CORL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL5 // Blue Crystal {SPR_BCRY, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_BLUECRYSTAL1 @@ -2193,6 +2177,11 @@ state_t states[NUMSTATES] = // Kelp {SPR_KELP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KELP + // Animated algae + {SPR_ALGA, 0, 1, {A_ConnectToGround}, MT_ANIMALGAESEG, 0, S_ANIMALGAETOP2}, // S_ANIMALGAETOP1 + {SPR_ALGA, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL}, // S_ANIMALGAETOP2 + {SPR_ALGB, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL}, // S_ANIMALGAESEG + // DSZ Stalagmites {SPR_DSTG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_DSZSTALAGMITE {SPR_DSTG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_DSZ2STALAGMITE @@ -2337,16 +2326,20 @@ state_t states[NUMSTATES] = {SPR_STBL, 6, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL8}, // S_LITTLETUMBLEWEED_ROLL7 {SPR_STBL, 7, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL1}, // S_LITTLETUMBLEWEED_ROLL8 - // Cacti Sprites - {SPR_CACT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI1 - {SPR_CACT, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI2 - {SPR_CACT, 2, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI3 - {SPR_CACT, 3, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI4 + // Cacti + {SPR_CACT, 0, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI1 + {SPR_CACT, 1, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI2 + {SPR_CACT, 2, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI3 + {SPR_CACT, 3, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI4 {SPR_CACT, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI5 {SPR_CACT, 5, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI6 {SPR_CACT, 6, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI7 {SPR_CACT, 7, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI8 {SPR_CACT, 8, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI9 + {SPR_CACT, 9, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI10 + {SPR_CACT, 10, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI11 + {SPR_CACT, 11, -1, {NULL}, 0, 0, S_NULL}, // S_CACTITINYSEG + {SPR_CACT, 12, -1, {NULL}, 0, 0, S_NULL}, // S_CACTISMALLSEG // Warning Signs {SPR_WWSG, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_ARIDSIGN_CAUTION @@ -5144,6 +5137,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BOSSJUNK + -1, // doomednum + S_BOSSEGLZ1, // 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 + 0, // speed + 8*FRACUNIT, // radius + 64*FRACUNIT, // height + 2, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_EGGMOBILE 200, // doomednum S_EGGMOBILE_STND, // spawnstate @@ -5333,87 +5353,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_EGGMOBILE2_POGO5 // raisestate }, - { // MT_BOSSTANK1 - -1, // doomednum - S_BOSSTANK1, // 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 - 0, // speed - 8*FRACUNIT, // radius - 64*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate - }, - - { // MT_BOSSTANK2 - -1, // doomednum - S_BOSSTANK2, // 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 - 0, // speed - 8*FRACUNIT, // radius - 64*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate - }, - - { // MT_BOSSSPIGOT - -1, // doomednum - S_BOSSSPIGOT, // 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 - 0, // speed - 8*FRACUNIT, // radius - 24*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate - }, - { // MT_GOOP -1, // doomednum S_GOOP1, // spawnstate @@ -5477,10 +5416,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // reactiontime sfx_None, // attacksound S_EGGMOBILE3_PAIN, // painstate - MT_PROPELLER, // painchance + MT_NULL, // painchance sfx_dmpain, // painsound S_NULL, // meleestate - S_EGGMOBILE3_LAUGH1,// missilestate + S_EGGMOBILE3_SHOCK, // missilestate S_EGGMOBILE3_DIE1, // deathstate S_EGGMOBILE3_FLEE1, // xdeathstate sfx_s3kb4, // deathsound @@ -5492,34 +5431,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 3, // damage sfx_telept, // activesound MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY|MF_BOSS|MF_NOCLIPHEIGHT, // flags - S_EGGMOBILE3_LAUGH20 // raisestate - }, - - { // MT_PROPELLER - -1, // doomednum - S_PROPELLER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 1, // speed - 4*FRACUNIT, // radius - 4*FRACUNIT, // height - 0, // display offset - 4, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate + S_EGGMOBILE3_ROFL // raisestate }, { // MT_FAKEMOBILE @@ -5531,7 +5443,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate - MT_PROPELLER, // painchance + MT_NULL, // painchance sfx_s3k7b, // painsound S_NULL, // meleestate S_FAKEMOBILE_ATK1, // missilestate @@ -6592,8 +6504,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 16*FRACUNIT, // radius + 32*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage @@ -6673,8 +6585,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_ncitem, // deathsound 1, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 16*FRACUNIT, // radius + 30*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage @@ -9211,7 +9123,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 20, // damage sfx_None, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags S_NULL // raisestate }, @@ -10129,7 +10041,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, @@ -10156,7 +10068,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_SCENERY, // flags + MF_SPECIAL|MF_SCENERY, // flags S_NULL // raisestate }, @@ -10177,13 +10089,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 29*FRACUNIT, // radius + 40*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags S_NULL // raisestate }, @@ -10204,13 +10116,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 30*FRACUNIT, // radius + 53*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags S_NULL // raisestate }, @@ -10231,13 +10143,67 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 28*FRACUNIT, // radius + 41*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CORAL4 + 1014, // doomednum + S_CORAL4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 56*FRACUNIT, // radius + 112*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CORAL5 + 1015, // doomednum + S_CORAL5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 56*FRACUNIT, // radius + 112*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags S_NULL // raisestate }, @@ -10264,13 +10230,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags S_NULL // raisestate }, { // MT_KELP 1007, // doomednum - S_KELP, // spawnstate + S_KELP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -10285,19 +10251,73 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 292*FRACUNIT, // height + 16*FRACUNIT, // radius + 292*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP, // flags + MF_SCENERY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_ANIMALGAETOP + 1013, // doomednum + S_ANIMALGAETOP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 120*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIP|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_ANIMALGAESEG + -1, // doomednum + S_ANIMALGAESEG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 120*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIP|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_DSZSTALAGMITE 1008, // doomednum - S_DSZSTALAGMITE, // spawnstate + S_DSZSTALAGMITE,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -10313,12 +10333,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 8*FRACUNIT, // radius - 116*FRACUNIT, // height + 116*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage sfx_None, // activesound - MF_SCENERY|MF_SOLID, // flags + MF_SCENERY|MF_SOLID, // flags S_NULL // raisestate }, @@ -10340,18 +10360,18 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 8*FRACUNIT, // radius - 116*FRACUNIT, // height + 116*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage sfx_None, // activesound - MF_SCENERY|MF_SOLID, // flags + MF_SCENERY|MF_SOLID, // flags S_NULL // raisestate }, { // MT_LIGHTBEAM 1010, // doomednum - S_LIGHTBEAM1, // spawnstate + S_LIGHTBEAM1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -10366,7 +10386,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius + 16*FRACUNIT, // radius 16*FRACUNIT, // height 0, // display offset 4, // mass @@ -10432,7 +10452,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_FLAMEPARTICLE -1, // doomednum - S_FLAMEPARTICLE, // spawnstate + S_FLAMEPARTICLE,// spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -11554,13 +11574,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 13*FRACUNIT, // radius + 24*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11581,13 +11601,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height + 15*FRACUNIT, // radius + 52*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11608,13 +11628,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 13*FRACUNIT, // radius + 24*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11635,13 +11655,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 16*FRACUNIT, // radius - 80*FRACUNIT, // height + 15*FRACUNIT, // radius + 52*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags S_NULL // raisestate }, @@ -11665,7 +11685,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 32*FRACUNIT, // radius 96*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11692,7 +11712,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 20*FRACUNIT, // radius 128*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11717,9 +11737,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 24*FRACUNIT, // radius - 224*FRACUNIT, // height + 224*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11744,9 +11764,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 24*FRACUNIT, // radius - 256*FRACUNIT, // height + 256*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags @@ -11773,13 +11793,121 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 48*FRACUNIT, // radius 96*FRACUNIT, // height 0, // display offset - 100, // mass + DMG_SPIKE, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SCENERY|MF_PAIN, // flags S_NULL // raisestate }, + { // MT_CACTI10 + 1230, // doomednum + S_CACTI10, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 13*FRACUNIT, // radius + 28*FRACUNIT, // height + 0, // display offset + DMG_SPIKE, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_CACTI11 + 1231, // doomednum + S_CACTI11, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 15*FRACUNIT, // radius + 60*FRACUNIT, // height + 0, // display offset + DMG_SPIKE, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_PAIN|MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_CACTITINYSEG + -1, // doomednum + S_CACTITINYSEG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 13*FRACUNIT, // radius + 28*FRACUNIT, // height + 0, // display offset + DMG_SPIKE, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_CACTISMALLSEG + -1, // doomednum + S_CACTISMALLSEG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 15*FRACUNIT, // radius + 60*FRACUNIT, // height + 0, // display offset + DMG_SPIKE, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_ARIDSIGN_CAUTION 1212, // doomednum S_ARIDSIGN_CAUTION, // spawnstate diff --git a/src/info.h b/src/info.h index 593c1fb7c..74e4b87a2 100644 --- a/src/info.h +++ b/src/info.h @@ -319,18 +319,17 @@ typedef enum sprite SPR_JETF, // Boss jet fumes // Boss 1 (Greenflower) - SPR_EGGM, + SPR_EGGM, // Boss 1 + SPR_EGLZ, // Boss 1 Junk // Boss 2 (Techno Hill) SPR_EGGN, // Boss 2 - SPR_TNKA, // Boss 2 Tank 1 - SPR_TNKB, // Boss 2 Tank 2 - SPR_SPNK, // Boss 2 Spigot + SPR_TANK, // Boss 2 Junk SPR_GOOP, // Boss 2 Goop // Boss 3 (Deep Sea) SPR_EGGO, // Boss 3 - SPR_PRPL, // Boss 3 Propeller + SPR_SEBH, // Boss 3 Junk SPR_FAKE, // Boss 3 Fakemobile // Boss 4 (Castle Eggman) @@ -459,11 +458,11 @@ typedef enum sprite SPR_GARG, // Deep Sea Gargoyle SPR_SEWE, // Deep Sea Seaweed SPR_DRIP, // Dripping water - SPR_CRL1, // Coral 1 - SPR_CRL2, // Coral 2 - SPR_CRL3, // Coral 3 + SPR_CORL, // Coral SPR_BCRY, // Blue Crystal SPR_KELP, // Kelp + SPR_ALGA, // Animated algae top + SPR_ALGB, // Animated algae segment SPR_DSTG, // DSZ Stalagmites SPR_LIBE, // DSZ Light beam @@ -493,7 +492,7 @@ typedef enum sprite // Arid Canyon Scenery SPR_BTBL, // Big tumbleweed SPR_STBL, // Small tumbleweed - SPR_CACT, // Cacti sprites + SPR_CACT, // Cacti SPR_WWSG, // Caution Sign SPR_WWS2, // Cacti Sign SPR_WWS3, // Sharp Turn Sign @@ -833,9 +832,15 @@ typedef enum playersprite SPR2_TALA, SPR2_TALB, + SPR2_CNT1, // continue disappointment + SPR2_CNT2, // continue lift + SPR2_CNT3, // continue spin + SPR2_CNT4, // continue "soooooooniiic!" tugging + SPR2_SIGN, // end sign head SPR2_LIFE, // life monitor icon - SPR2_XTRA, // stuff that isn't in-game - keep this last in the list + + SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?" SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, @@ -1333,10 +1338,10 @@ typedef enum state S_SONIC3KBOSSEXPLOSION6, S_JETFUME1, - S_JETFUME2, // Boss 1 S_EGGMOBILE_STND, + S_EGGMOBILE_ROFL, S_EGGMOBILE_LATK1, S_EGGMOBILE_LATK2, S_EGGMOBILE_LATK3, @@ -1346,7 +1351,6 @@ typedef enum state S_EGGMOBILE_LATK7, S_EGGMOBILE_LATK8, S_EGGMOBILE_LATK9, - S_EGGMOBILE_LATK10, S_EGGMOBILE_RATK1, S_EGGMOBILE_RATK2, S_EGGMOBILE_RATK3, @@ -1356,7 +1360,6 @@ typedef enum state S_EGGMOBILE_RATK7, S_EGGMOBILE_RATK8, S_EGGMOBILE_RATK9, - S_EGGMOBILE_RATK10, S_EGGMOBILE_PANIC1, S_EGGMOBILE_PANIC2, S_EGGMOBILE_PANIC3, @@ -1364,6 +1367,14 @@ typedef enum state S_EGGMOBILE_PANIC5, S_EGGMOBILE_PANIC6, S_EGGMOBILE_PANIC7, + S_EGGMOBILE_PANIC8, + S_EGGMOBILE_PANIC9, + S_EGGMOBILE_PANIC10, + S_EGGMOBILE_PANIC11, + S_EGGMOBILE_PANIC12, + S_EGGMOBILE_PANIC13, + S_EGGMOBILE_PANIC14, + S_EGGMOBILE_PANIC15, S_EGGMOBILE_PAIN, S_EGGMOBILE_PAIN2, S_EGGMOBILE_DIE1, @@ -1375,6 +1386,9 @@ typedef enum state S_EGGMOBILE_BALL, S_EGGMOBILE_TARGET, + S_BOSSEGLZ1, + S_BOSSEGLZ2, + // Boss 2 S_EGGMOBILE2_STND, S_EGGMOBILE2_POGO1, @@ -1405,11 +1419,7 @@ typedef enum state // Boss 3 S_EGGMOBILE3_STND, - S_EGGMOBILE3_LAUGH1, - S_EGGMOBILE3_LAUGH2, - S_EGGMOBILE3_LAUGH3, - S_EGGMOBILE3_LAUGH4, - S_EGGMOBILE3_LAUGH5, + S_EGGMOBILE3_SHOCK, S_EGGMOBILE3_ATK1, S_EGGMOBILE3_ATK2, S_EGGMOBILE3_ATK3A, @@ -1418,21 +1428,7 @@ typedef enum state S_EGGMOBILE3_ATK3D, S_EGGMOBILE3_ATK4, S_EGGMOBILE3_ATK5, - S_EGGMOBILE3_LAUGH6, - S_EGGMOBILE3_LAUGH7, - S_EGGMOBILE3_LAUGH8, - S_EGGMOBILE3_LAUGH9, - S_EGGMOBILE3_LAUGH10, - S_EGGMOBILE3_LAUGH11, - S_EGGMOBILE3_LAUGH12, - S_EGGMOBILE3_LAUGH13, - S_EGGMOBILE3_LAUGH14, - S_EGGMOBILE3_LAUGH15, - S_EGGMOBILE3_LAUGH16, - S_EGGMOBILE3_LAUGH17, - S_EGGMOBILE3_LAUGH18, - S_EGGMOBILE3_LAUGH19, - S_EGGMOBILE3_LAUGH20, + S_EGGMOBILE3_ROFL, S_EGGMOBILE3_PAIN, S_EGGMOBILE3_PAIN2, S_EGGMOBILE3_DIE1, @@ -1442,15 +1438,6 @@ typedef enum state S_EGGMOBILE3_FLEE1, S_EGGMOBILE3_FLEE2, - // Boss 3 Propeller - S_PROPELLER1, - S_PROPELLER2, - S_PROPELLER3, - S_PROPELLER4, - S_PROPELLER5, - S_PROPELLER6, - S_PROPELLER7, - // Boss 3 Pinch S_FAKEMOBILE_INIT, S_FAKEMOBILE, @@ -1463,6 +1450,9 @@ typedef enum state S_FAKEMOBILE_DIE1, S_FAKEMOBILE_DIE2, + S_BOSSSEBH1, + S_BOSSSEBH2, + // Boss 4 S_EGGMOBILE4_STND, S_EGGMOBILE4_LATK1, @@ -1866,16 +1856,6 @@ typedef enum state S_MSSHIELD_F1, S_MSSHIELD_F2, - S_MSSHIELD_F3, - S_MSSHIELD_F4, - S_MSSHIELD_F5, - S_MSSHIELD_F6, - S_MSSHIELD_F7, - S_MSSHIELD_F8, - S_MSSHIELD_F9, - S_MSSHIELD_F10, - S_MSSHIELD_F11, - S_MSSHIELD_F12, // Ring S_RING, @@ -2309,14 +2289,12 @@ typedef enum state S_DRIPC1, S_DRIPC2, - // Coral 1 + // Coral S_CORAL1, - - // Coral 2 S_CORAL2, - - // Coral 3 S_CORAL3, + S_CORAL4, + S_CORAL5, // Blue Crystal S_BLUECRYSTAL1, @@ -2324,6 +2302,11 @@ typedef enum state // Kelp, S_KELP, + // Animated algae + S_ANIMALGAETOP1, + S_ANIMALGAETOP2, + S_ANIMALGAESEG, + // DSZ Stalagmites S_DSZSTALAGMITE, S_DSZ2STALAGMITE, @@ -2458,7 +2441,7 @@ typedef enum state S_LITTLETUMBLEWEED_ROLL7, S_LITTLETUMBLEWEED_ROLL8, - // Cacti Sprites + // Cacti S_CACTI1, S_CACTI2, S_CACTI3, @@ -2468,8 +2451,12 @@ typedef enum state S_CACTI7, S_CACTI8, S_CACTI9, + S_CACTI10, + S_CACTI11, + S_CACTITINYSEG, + S_CACTISMALLSEG, - // Warning signs sprites + // Warning signs S_ARIDSIGN_CAUTION, S_ARIDSIGN_CACTI, S_ARIDSIGN_SHARPTURN, @@ -3981,6 +3968,7 @@ typedef enum mobj_type MT_EGGTRAP, MT_BOSS3WAYPOINT, MT_BOSS9GATHERPOINT, + MT_BOSSJUNK, // Boss 1 MT_EGGMOBILE, @@ -3992,15 +3980,11 @@ typedef enum mobj_type // Boss 2 MT_EGGMOBILE2, MT_EGGMOBILE2_POGO, - MT_BOSSTANK1, - MT_BOSSTANK2, - MT_BOSSSPIGOT, MT_GOOP, MT_GOOPTRAIL, // Boss 3 MT_EGGMOBILE3, - MT_PROPELLER, MT_FAKEMOBILE, MT_SHOCK, @@ -4211,11 +4195,15 @@ typedef enum mobj_type MT_SEAWEED, // DSZ Seaweed MT_WATERDRIP, // Dripping Water source MT_WATERDROP, // Water drop from dripping water - MT_CORAL1, // Coral 1 - MT_CORAL2, // Coral 2 - MT_CORAL3, // Coral 3 + MT_CORAL1, // Coral + MT_CORAL2, + MT_CORAL3, + MT_CORAL4, + MT_CORAL5, MT_BLUECRYSTAL, // Blue Crystal MT_KELP, // Kelp + MT_ANIMALGAETOP, // Animated algae top + MT_ANIMALGAESEG, // Animated algae segment MT_DSZSTALAGMITE, // Deep Sea 1 Stalagmite MT_DSZ2STALAGMITE, // Deep Sea 2 Stalagmite MT_LIGHTBEAM, // DSZ Light beam @@ -4266,15 +4254,19 @@ typedef enum mobj_type // Arid Canyon Scenery MT_BIGTUMBLEWEED, MT_LITTLETUMBLEWEED, - MT_CACTI1, - MT_CACTI2, - MT_CACTI3, - MT_CACTI4, - MT_CACTI5, // Harmful Cactus 1 - MT_CACTI6, // Harmful Cactus 2 - MT_CACTI7, // Harmful Cactus 3 - MT_CACTI8, // Harmful Cactus 4 - MT_CACTI9, // Harmful Cactus 5 + MT_CACTI1, // Tiny Red Flower Cactus + MT_CACTI2, // Small Red Flower Cactus + MT_CACTI3, // Tiny Blue Flower Cactus + MT_CACTI4, // Small Blue Flower Cactus + MT_CACTI5, // Prickly Pear + MT_CACTI6, // Barrel Cactus + MT_CACTI7, // Tall Barrel Cactus + MT_CACTI8, // Armed Cactus + MT_CACTI9, // Ball Cactus + MT_CACTI10, // Tiny Cactus + MT_CACTI11, // Small Cactus + MT_CACTITINYSEG, // Tiny Cactus Segment + MT_CACTISMALLSEG, // Small Cactus Segment MT_ARIDSIGN_CAUTION, // Caution Sign MT_ARIDSIGN_CACTI, // Cacti Sign MT_ARIDSIGN_SHARPTURN, // Sharp Turn Sign diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 3c136a436..a69e8a188 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -182,6 +182,8 @@ static const struct { {META_CAMERA, "camera_t"}, {META_ACTION, "action"}, + + {META_LUABANKS, "luabanks[]"}, {NULL, NULL} }; @@ -228,6 +230,18 @@ static int lib_isPlayerAdmin(lua_State *L) return 1; } +static int lib_reserveLuabanks(lua_State *L) +{ + static boolean reserved = false; + if (!lua_lumploading) + return luaL_error(L, "luabanks[] cannot be reserved from within a hook or coroutine!"); + if (reserved) + return luaL_error(L, "luabanks[] has already been reserved! Only one savedata-enabled mod at a time may use this feature."); + reserved = true; + LUA_PushUserdata(L, &luabanks, META_LUABANKS); + return 1; +} + // M_RANDOM ////////////// @@ -2736,6 +2750,7 @@ static luaL_Reg lib[] = { {"chatprintf", lib_chatprintf}, {"userdataType", lib_userdataType}, {"IsPlayerAdmin", lib_isPlayerAdmin}, + {"reserveLuabanks", lib_reserveLuabanks}, // m_random {"P_RandomFixed",lib_pRandomFixed}, diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 77f37f8ec..8ef0bafcf 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -18,6 +18,7 @@ #include "p_mobj.h" #include "p_local.h" #include "z_zone.h" +#include "doomstat.h" // luabanks[] #include "lua_script.h" #include "lua_libs.h" @@ -146,7 +147,7 @@ static int lib_getSpr2default(lua_State *L) return luaL_error(L, "spr2defaults[] invalid index"); if (i >= free_spr2) - return 0; + return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, 0, free_spr2-1); lua_pushinteger(L, spr2defaults[i]); return 1; @@ -1026,6 +1027,61 @@ static int sfxinfo_num(lua_State *L) return 1; } +////////////// +// LUABANKS // +////////////// + +static int lib_getluabanks(lua_State *L) +{ + UINT8 i; + + lua_remove(L, 1); // don't care about luabanks[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else + return luaL_error(L, "luabanks[] invalid index"); + + if (i >= NUM_LUABANKS) + luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1); + + lua_pushinteger(L, luabanks[i]); + return 1; +} + +static int lib_setluabanks(lua_State *L) +{ + UINT8 i; + INT32 j = 0; + + if (hud_running) + return luaL_error(L, "Do not alter luabanks[] in HUD rendering code!"); + + lua_remove(L, 1); // don't care about luabanks[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else + return luaL_error(L, "luabanks[] invalid index"); + + if (i >= NUM_LUABANKS) + luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1); + + if (lua_isnumber(L, 2)) + j = lua_tonumber(L, 2); + else + return luaL_error(L, "luabanks[] invalid set"); + + luabanks[i] = j; + return 0; +} + +static int lib_luabankslen(lua_State *L) +{ + lua_pushinteger(L, NUM_LUABANKS); + return 1; +} + ////////////////////////////// // // Now push all these functions into the Lua state! @@ -1147,6 +1203,18 @@ int LUA_InfoLib(lua_State *L) lua_pushvalue(L, -1); lua_setglobal(L, "S_sfx"); lua_setglobal(L, "sfxinfo"); + + luaL_newmetatable(L, META_LUABANKS); + lua_pushcfunction(L, lib_getluabanks); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setluabanks); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_luabankslen); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + return 0; } diff --git a/src/lua_libs.h b/src/lua_libs.h index 827c1d798..7609971ce 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -67,6 +67,8 @@ extern lua_State *gL; #define META_ACTION "ACTIONF_T*" +#define META_LUABANKS "LUABANKS[]*" + boolean luaL_checkboolean(lua_State *L, int narg); int LUA_EnumLib(lua_State *L); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 74b259921..dbb69b7e2 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2017,6 +2017,8 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->muspostbosspos); else if (fastcmp(field,"muspostbossfadein")) lua_pushinteger(L, header->muspostbossfadein); + else if (fastcmp(field,"musforcereset")) + lua_pushinteger(L, header->musforcereset); else if (fastcmp(field,"forcecharacter")) lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index addd707e1..dd9959afb 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -262,6 +262,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->starposttime); else if (fastcmp(field,"starpostangle")) lua_pushangle(L, plr->starpostangle); + else if (fastcmp(field,"starpostscale")) + lua_pushfixed(L, plr->starpostscale); else if (fastcmp(field,"angle_pos")) lua_pushangle(L, plr->angle_pos); else if (fastcmp(field,"old_angle_pos")) @@ -570,6 +572,8 @@ static int player_set(lua_State *L) plr->starposttime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"starpostangle")) plr->starpostangle = luaL_checkangle(L, 3); + else if (fastcmp(field,"starpostscale")) + plr->starpostscale = luaL_checkfixed(L, 3); else if (fastcmp(field,"angle_pos")) plr->angle_pos = luaL_checkangle(L, 3); else if (fastcmp(field,"old_angle_pos")) diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index a28f6a359..7f68905aa 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -52,6 +52,8 @@ enum skin { skin_supercolor, skin_prefoppositecolor, skin_highresscale, + skin_contspeed, + skin_contangle, skin_soundsid, skin_availability }; @@ -88,6 +90,8 @@ static const char *const skin_opt[] = { "supercolor", "prefoppositecolor", "highresscale", + "contspeed", + "contangle", "soundsid", "availability", NULL}; @@ -199,6 +203,12 @@ static int skin_get(lua_State *L) case skin_highresscale: lua_pushinteger(L, skin->highresscale); break; + case skin_contspeed: + lua_pushinteger(L, skin->contspeed); + break; + case skin_contangle: + lua_pushinteger(L, skin->contangle); + break; case skin_soundsid: LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID); break; diff --git a/src/m_cheat.c b/src/m_cheat.c index da449b2f7..bb757839a 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -831,6 +831,12 @@ void Command_Savecheckpoint_f(void) players[consoleplayer].starposty = players[consoleplayer].mo->y>>FRACBITS; players[consoleplayer].starpostz = players[consoleplayer].mo->floorz>>FRACBITS; players[consoleplayer].starpostangle = players[consoleplayer].mo->angle; + players[consoleplayer].starpostscale = players[consoleplayer].mo->destscale; + if (players[consoleplayer].mo->flags2 & MF2_OBJECTFLIP) + { + players[consoleplayer].starpostscale *= -1; + players[consoleplayer].starpostz += players[consoleplayer].mo->height; + } CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz); } diff --git a/src/m_menu.c b/src/m_menu.c index 49e54c153..e1b2b5c90 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -125,7 +125,7 @@ const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 description_t description[MAXSKINS]; -INT16 char_on = -1, startchar = 1; +INT16 char_on = -1, startchar = 0; static char *char_notes = NULL; static fixed_t char_scroll = 0; @@ -272,6 +272,7 @@ static void M_ServerOptions(INT32 choice); #ifndef NONET static void M_StartServerMenu(INT32 choice); static void M_ConnectMenu(INT32 choice); +static void M_ConnectMenuModChecks(INT32 choice); static void M_Refresh(INT32 choice); static void M_Connect(INT32 choice); static void M_ChooseRoom(INT32 choice); @@ -282,9 +283,10 @@ menu_t MP_MainDef; // Split into multiple parts due to size // Controls menu_t OP_ChangeControlsDef; -menu_t OP_MPControlsDef, OP_CameraControlsDef, OP_MiscControlsDef; +menu_t OP_MPControlsDef, OP_MiscControlsDef; menu_t OP_P1ControlsDef, OP_P2ControlsDef, OP_MouseOptionsDef; menu_t OP_Mouse2OptionsDef, OP_Joystick1Def, OP_Joystick2Def; +menu_t OP_CameraOptionsDef, OP_Camera2OptionsDef; static void M_VideoModeMenu(INT32 choice); static void M_Setup1PControlsMenu(INT32 choice); static void M_Setup2PControlsMenu(INT32 choice); @@ -891,12 +893,12 @@ static menuitem_t MP_SplitServerMenu[] = static menuitem_t MP_MainMenu[] = { - {IT_HEADER, NULL, "Host a game", NULL, 0}, - {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 12}, - {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 22}, - {IT_HEADER, NULL, "Join a game", NULL, 40}, - {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 52}, - {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 62}, + {IT_HEADER, NULL, "Join a game", NULL, 0}, + {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenuModChecks, 12}, + {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 22}, + {IT_HEADER, NULL, "Host a game", NULL, 54}, + {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 66}, + {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 76}, {IT_HEADER, NULL, "Player setup", NULL, 94}, {IT_STRING|IT_CALL, NULL, "Player 1...", M_SetupMultiPlayer, 106}, {IT_STRING|IT_CALL, NULL, "Player 2... ", M_SetupMultiPlayer2, 116}, @@ -955,7 +957,7 @@ enum static menuitem_t MP_RoomMenu[] = { - {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, + {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, {IT_DISABLED, NULL, "", M_ChooseRoom, 18}, {IT_DISABLED, NULL, "", M_ChooseRoom, 27}, {IT_DISABLED, NULL, "", M_ChooseRoom, 36}, @@ -1009,13 +1011,11 @@ static menuitem_t OP_P1ControlsMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 20}, {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def , 30}, - {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam , 50}, - {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam , 60}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 70}, + {IT_SUBMENU | IT_STRING, NULL, "Camera Options...", &OP_CameraOptionsDef, 50}, - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 90}, - {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar, 90}, - {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake, 100}, + //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 100}, + {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar, 70}, + {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake, 80}, }; static menuitem_t OP_P2ControlsMenu[] = @@ -1024,13 +1024,11 @@ static menuitem_t OP_P2ControlsMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Second Mouse Options...", &OP_Mouse2OptionsDef, 20}, {IT_SUBMENU | IT_STRING, NULL, "Second Gamepad Options...", &OP_Joystick2Def , 30}, - {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam2 , 50}, - {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam2 , 60}, - {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 70}, + {IT_SUBMENU | IT_STRING, NULL, "Camera Options...", &OP_Camera2OptionsDef, 50}, - //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 90}, - {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar2, 90}, - {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake2, 100}, + //{IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 100}, + {IT_STRING | IT_CVAR, NULL, "Character angle", &cv_directionchar2, 70}, + {IT_STRING | IT_CVAR, NULL, "Automatic braking", &cv_autobrake2, 80}, }; static menuitem_t OP_ChangeControlsMenu[] = @@ -1159,6 +1157,34 @@ static menuitem_t OP_Mouse2OptionsMenu[] = NULL, "Mouse Y Sensitivity", &cv_mouseysens2, 80}, }; +static menuitem_t OP_CameraOptionsMenu[] = +{ + {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam , 10}, + {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam , 20}, + {IT_STRING | IT_CVAR, NULL, "Orbital Looking" , &cv_cam_orbit , 30}, + {IT_STRING | IT_CVAR, NULL, "Downhill Slope Adjustment", &cv_cam_adjust, 40}, + + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam_dist, 60}, + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam_height, 70}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam_speed, 80}, + + {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 100}, +}; + +static menuitem_t OP_Camera2OptionsMenu[] = +{ + {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam2 , 10}, + {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam2 , 20}, + {IT_STRING | IT_CVAR, NULL, "Orbital Looking" , &cv_cam2_orbit , 30}, + {IT_STRING | IT_CVAR, NULL, "Downhill Slope Adjustment", &cv_cam2_adjust, 40}, + + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam2_dist, 60}, + {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam2_height, 70}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam2_speed, 80}, + + {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 100}, +}; + static menuitem_t OP_VideoOptionsMenu[] = { {IT_HEADER, NULL, "Screen", NULL, 0}, @@ -1329,6 +1355,12 @@ static menuitem_t OP_SoundOptionsMenu[] = #define OPENMPT_MENUOFFSET 0 #endif +#ifdef HAVE_MIXERX +#define MIXERX_MENUOFFSET 81 +#else +#define MIXERX_MENUOFFSET 0 +#endif + static menuitem_t OP_SoundAdvancedMenu[] = { #ifdef HAVE_OPENMPT @@ -1340,12 +1372,15 @@ static menuitem_t OP_SoundAdvancedMenu[] = {IT_HEADER, NULL, "MIDI Settings", NULL, OPENMPT_MENUOFFSET+10}, {IT_STRING | IT_CVAR, NULL, "MIDI Player", &cv_midiplayer, OPENMPT_MENUOFFSET+22}, {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "FluidSynth Sound Font File", &cv_midisoundfontpath, OPENMPT_MENUOFFSET+34}, - {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "TiMidity++ Config Folder", &cv_miditimiditypath, OPENMPT_MENUOFFSET+61} + {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "TiMidity++ Config Folder", &cv_miditimiditypath, OPENMPT_MENUOFFSET+61}, #endif + + {IT_HEADER, NULL, "Miscellaneous", NULL, OPENMPT_MENUOFFSET+MIXERX_MENUOFFSET+10}, + {IT_STRING | IT_CVAR, NULL, "Let Levels Force Reset Music", &cv_resetmusicbyheader, OPENMPT_MENUOFFSET+MIXERX_MENUOFFSET+22}, }; #undef OPENMPT_MENUOFFSET - +#undef MIXERX_MENUOFFSET #endif static menuitem_t OP_DataOptionsMenu[] = @@ -1360,36 +1395,39 @@ static menuitem_t OP_ScreenshotOptionsMenu[] = { {IT_HEADER, NULL, "General", NULL, 0}, {IT_STRING|IT_CVAR, NULL, "Use color profile", &cv_screenshot_colorprofile, 6}, - {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_screenshot_option, 11}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_screenshot_folder, 16}, - {IT_HEADER, NULL, "Screenshots (F8)", NULL, 30}, - {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memory, 36}, - {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_level, 41}, - {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategy, 46}, - {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 51}, + {IT_HEADER, NULL, "Screenshots (F8)", NULL, 16}, + {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_screenshot_option, 22}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_screenshot_folder, 27}, + {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memory, 42}, + {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_level, 47}, + {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategy, 52}, + {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 57}, - {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 60}, - {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 66}, + {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 64}, + {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75}, + {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90}, - {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 71}, - {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 76}, + {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 95}, + {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 100}, - {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 71}, - {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 76}, - {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 81}, - {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 86}, + {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 95}, + {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 100}, + {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 105}, + {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 110}, }; enum { op_screenshot_colorprofile = 1, - op_screenshot_folder = 3, - op_screenshot_capture = 10, - op_screenshot_gif_start = 11, - op_screenshot_gif_end = 12, - op_screenshot_apng_start = 13, - op_screenshot_apng_end = 16, + op_screenshot_folder = 4, + op_movie_folder = 11, + op_screenshot_capture = 12, + op_screenshot_gif_start = 13, + op_screenshot_gif_end = 14, + op_screenshot_apng_start = 15, + op_screenshot_apng_end = 18, }; static menuitem_t OP_EraseDataMenu[] = @@ -1884,6 +1922,13 @@ menu_t OP_JoystickSetDef = 0, NULL }; +menu_t OP_CameraOptionsDef = DEFAULTMENUSTYLE( + MN_OP_MAIN + (MN_OP_P1CONTROLS << 6) + (MN_OP_P1CAMERA << 12), + "M_CONTRO", OP_CameraOptionsMenu, &OP_P1ControlsDef, 35, 30); +menu_t OP_Camera2OptionsDef = DEFAULTMENUSTYLE( + MN_OP_MAIN + (MN_OP_P2CONTROLS << 6) + (MN_OP_P2CAMERA << 12), + "M_CONTRO", OP_Camera2OptionsMenu, &OP_P2ControlsDef, 35, 30); + menu_t OP_VideoOptionsDef = { @@ -2207,6 +2252,12 @@ void Addons_option_Onchange(void) (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); } +void Moviemode_option_Onchange(void) +{ + OP_ScreenshotOptionsMenu[op_movie_folder].status = + (cv_movie_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== @@ -2745,13 +2796,27 @@ static void M_ChangeCvar(INT32 choice) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_NOMOD)) { - CV_SetValue(cv,cv->value+(choice)); + if (cv->flags & CV_FLOAT && (currentMenu->menuitems[itemOn].status & IT_CV_FLOATSLIDER) == IT_CV_FLOATSLIDER) + { + char s[20]; + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); + CV_Set(cv,s); + } + else + CV_SetValue(cv,cv->value+(choice)); } else if (cv->flags & CV_FLOAT) { - char s[20]; - sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); - CV_Set(cv,s); + if (currentMenu->menuitems[itemOn].status & IT_CV_INTEGERSTEP) + { + CV_SetValue(cv,FIXED_TO_FLOAT(cv->value)+(choice)); + } + else + { + char s[20]; + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); + CV_Set(cv,s); + } } else CV_AddValue(cv,choice); @@ -3641,7 +3706,12 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) for (i = 0; cv->PossibleValue[i+1].strvalue; i++); - if ((range = atoi(cv->defaultvalue)) != cv->value) + if (cv->flags & CV_FLOAT) + range = (INT32)(atof(cv->defaultvalue)*FRACUNIT); + else + range = atoi(cv->defaultvalue); + + if (range != cv->value) { range = ((range - cv->PossibleValue[0].value) * 100 / (cv->PossibleValue[i].value - cv->PossibleValue[0].value)); @@ -4517,6 +4587,9 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) return false; + if (G_IsSpecialStage(mapnum+1)) + return false; + if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) return true; @@ -5610,7 +5683,7 @@ static boolean M_AddonsRefresh(void) { 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); + message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you wish 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); } @@ -6892,6 +6965,7 @@ static void M_StartTutorial(INT32 choice) tutorialmode = true; // turn on tutorial mode emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); M_ClearMenus(true); gamecomplete = false; cursaveslot = 0; @@ -7058,7 +7132,7 @@ static void M_DrawLoadGameData(void) } } - y -= 13; + y -= 4; // character heads, lives, and continues { @@ -7067,7 +7141,7 @@ static void M_DrawLoadGameData(void) patch_t *patch; UINT8 *colormap = NULL; - INT32 tempx = (x+40)<highresscale, 0, patch, colormap); Z_Free(colormap); - tempx -= (15<spriteframes[0]; patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); - if ((calc = SHORT(patch->topoffset) - 42) > 0) - tempy += ((4+calc)<highresscale, flip, patch, colormap); skipsign: - y += 25; + y += 16; tempx = x + 10; if (savegameinfo[savetodraw].lives != INFLIVES @@ -7300,7 +7372,29 @@ static void M_ReadSavegameInfo(UINT32 slot) // File end marker check CHECKPOS - if (READUINT8(save_p) != 0x1d) BADSAVE; + switch (READUINT8(save_p)) + { + case 0xb7: + { + UINT8 i, banksinuse; + CHECKPOS + banksinuse = READUINT8(save_p); + CHECKPOS + if (banksinuse > NUM_LUABANKS) + BADSAVE + for (i = 0; i < banksinuse; i++) + { + (void)READINT32(save_p); + CHECKPOS + } + if (READUINT8(save_p) != 0x1d) + BADSAVE + } + case 0x1d: + break; + default: + BADSAVE + } // done Z_Free(savebuffer); @@ -8486,8 +8580,8 @@ static void M_NightsAttack(INT32 choice) M_PatchSkinNameTable(); G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching - M_SetupNextMenu(&SP_NightsAttackDef); titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please + M_SetupNextMenu(&SP_NightsAttackDef); if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0]) CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]); else @@ -8502,6 +8596,7 @@ static void M_ChooseNightsAttack(INT32 choice) char nameofdemo[256]; (void)choice; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); M_ClearMenus(true); modeattacking = ATTACKING_NIGHTS; @@ -8526,6 +8621,7 @@ static void M_ChooseTimeAttack(INT32 choice) char nameofdemo[256]; (void)choice; emeralds = 0; + memset(&luabanks, 0, sizeof(luabanks)); M_ClearMenus(true); modeattacking = ATTACKING_RECORD; @@ -8879,7 +8975,7 @@ static void M_DrawConnectMenu(void) // Room name if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_connect_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); @@ -9029,11 +9125,32 @@ static void M_ConnectMenu(INT32 choice) // first page of servers serverlistpage = 0; - M_SetupNextMenu(&MP_ConnectDef); + if (ms_RoomId < 0) + { + M_RoomMenu(0); // Select a room instead of staring at an empty list + // This prevents us from returning to the modified game alert. + currentMenu->prevMenu = &MP_MainDef; + } + else + M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; M_Refresh(0); } +static void M_ConnectMenuModChecks(INT32 choice) +{ + (void)choice; + // okay never mind we want to COMMUNICATE to the player pre-emptively instead of letting them try and then get confused when it doesn't work + + if (modifiedgame) + { + M_StartMessage(M_GetText("Add-ons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing add-ons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER); + return; + } + + M_ConnectMenu(-1); +} + static UINT32 roomIds[NUM_LIST_ROOMS]; static void M_RoomMenu(INT32 choice) @@ -9088,7 +9205,16 @@ static void M_ChooseRoom(INT32 choice) } serverlistpage = 0; - M_SetupNextMenu(currentMenu->prevMenu); + /* + We were on the Multiplayer menu? That means that we must have been trying to + view the server browser, but we hadn't selected a room yet. So we need to go + to the browser next, not back there. + */ + if (currentMenu->prevMenu == &MP_MainDef) + M_SetupNextMenu(&MP_ConnectDef); + else + M_SetupNextMenu(currentMenu->prevMenu); + if (currentMenu == &MP_ConnectDef) M_Refresh(0); } @@ -9147,7 +9273,7 @@ static void M_DrawServerMenu(void) M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false); if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, - V_YELLOWMAP, (itemOn == mp_server_room) ? "" : ""); else V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); @@ -9254,7 +9380,7 @@ static void M_StartServerMenu(INT32 choice) // CONNECT VIA IP // ============== -static char setupm_ip[16]; +static char setupm_ip[28]; // Draw the funky Connect IP menu. Tails 11-19-2002 // So much work for such a little thing! @@ -9266,30 +9392,26 @@ static void M_DrawMPMainMenu(void) // use generic drawer for cursor, items and title M_DrawGenericMenu(); -#if MAXPLAYERS == 32 - V_DrawRightAlignedString(BASEVIDWIDTH-x, y+12, - ((itemOn == 1) ? V_YELLOWMAP : 0), "(2-32 players)"); -#else -Update the maxplayers label... -#endif + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+66, + ((itemOn == 4) ? V_YELLOWMAP : 0), va("(2-%d players)", MAXPLAYERS)); - V_DrawRightAlignedString(BASEVIDWIDTH-x, y+22, - ((itemOn == 2) ? V_YELLOWMAP : 0), "(2 players)"); + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+76, + ((itemOn == 5) ? V_YELLOWMAP : 0), "(2 players)"); V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116, ((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)"); - y += 62; + y += 22; V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); // draw name string - V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip); + V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip); // draw text cursor for name - if (itemOn == 5 //0 + if (itemOn == 2 //0 && skullAnimCounter < 4) //blink cursor - V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false); + V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false); } // Tails 11-19-2002 @@ -9360,10 +9482,11 @@ static void M_HandleConnectIP(INT32 choice) default: l = strlen(setupm_ip); - if (l >= 16-1) + if (l >= 28-1) break; - if (choice == 46 || (choice >= 48 && choice <= 57)) // Rudimentary number and period enforcing + // Rudimentary number and period enforcing - also allows letters so hostnames can be used instead + if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z')) { S_StartSound(NULL,sfx_menu1); // Tails setupm_ip[l] = (char)choice; diff --git a/src/m_menu.h b/src/m_menu.h index 38be5a347..05962d2b1 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -72,10 +72,12 @@ typedef enum MN_OP_P1MOUSE, MN_OP_P1JOYSTICK, MN_OP_JOYSTICKSET, // OP_JoystickSetDef shared with P2 + MN_OP_P1CAMERA, MN_OP_P2CONTROLS, MN_OP_P2MOUSE, MN_OP_P2JOYSTICK, + MN_OP_P2CAMERA, MN_OP_VIDEO, MN_OP_VIDEOMODE, @@ -241,6 +243,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); #define IT_CV_NOPRINT 1536 #define IT_CV_NOMOD 2048 #define IT_CV_INVISSLIDER 2560 +#define IT_CV_INTEGERSTEP 4096 // if IT_CV_NORMAL and cvar is CV_FLOAT, modify it by 1 instead of 0.0625 +#define IT_CV_FLOATSLIDER 4608 // IT_CV_SLIDER, value modified by 0.0625 instead of 1 (for CV_FLOAT cvars) //call/submenu specific // There used to be a lot more here but ... @@ -400,6 +404,9 @@ void Screenshot_option_Onchange(void); // Addons menu updating void Addons_option_Onchange(void); +// Moviemode menu updating +void Moviemode_option_Onchange(void); + // These defines make it a little easier to make menus #define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\ {\ diff --git a/src/m_misc.c b/src/m_misc.c index 22e19df73..aaaf30d67 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -108,6 +108,9 @@ consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAV static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}}; consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_movie_option = {"movie_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Moviemode_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_movie_folder = {"movie_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t zlib_mem_level_t[] = { {1, "(Min Memory) 1"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"}, {7, "7"}, @@ -1124,19 +1127,25 @@ static inline moviemode_t M_StartMovieGIF(const char *pathname) void M_StartMovie(void) { #if NUMSCREENS > 2 - const char *pathname = "."; + char pathname[MAX_WADPATH]; if (moviemode) return; - if (cv_screenshot_option.value == 0) - pathname = usehome ? srb2home : srb2path; - else if (cv_screenshot_option.value == 1) - pathname = srb2home; - else if (cv_screenshot_option.value == 2) - pathname = srb2path; - else if (cv_screenshot_option.value == 3 && *cv_screenshot_folder.string != '\0') - pathname = cv_screenshot_folder.string; + if (cv_movie_option.value == 0) + strcpy(pathname, usehome ? srb2home : srb2path); + else if (cv_movie_option.value == 1) + strcpy(pathname, srb2home); + else if (cv_movie_option.value == 2) + strcpy(pathname, srb2path); + else if (cv_movie_option.value == 3 && *cv_movie_folder.string != '\0') + strcpy(pathname, cv_movie_folder.string); + + if (cv_movie_option.value != 3) + { + strcat(pathname, PATHSEP"movies"PATHSEP); + I_mkdir(pathname, 0755); + } if (rendermode == render_none) I_Error("Can't make a movie without a render system\n"); @@ -1474,7 +1483,8 @@ void M_ScreenShot(void) void M_DoScreenShot(void) { #if NUMSCREENS > 2 - const char *freename = NULL, *pathname = "."; + const char *freename = NULL; + char pathname[MAX_WADPATH]; boolean ret = false; UINT8 *linear = NULL; @@ -1486,13 +1496,19 @@ void M_DoScreenShot(void) return; if (cv_screenshot_option.value == 0) - pathname = usehome ? srb2home : srb2path; + strcpy(pathname, usehome ? srb2home : srb2path); else if (cv_screenshot_option.value == 1) - pathname = srb2home; + strcpy(pathname, srb2home); else if (cv_screenshot_option.value == 2) - pathname = srb2path; + strcpy(pathname, srb2path); else if (cv_screenshot_option.value == 3 && *cv_screenshot_folder.string != '\0') - pathname = cv_screenshot_folder.string; + strcpy(pathname, cv_screenshot_folder.string); + + if (cv_screenshot_option.value != 3) + { + strcat(pathname, PATHSEP"screenshots"PATHSEP); + I_mkdir(pathname, 0755); + } #ifdef USE_PNG freename = Newsnapshotfile(pathname,"png"); diff --git a/src/m_misc.h b/src/m_misc.h index 6ac92dbcc..7038e3e48 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -30,7 +30,7 @@ typedef enum { extern moviemode_t moviemode; extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_colorprofile; -extern consvar_t cv_moviemode; +extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option; extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits; extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa; extern consvar_t cv_apng_delay; diff --git a/src/m_swap.h b/src/m_swap.h index 2d42f6138..3b50dc623 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -14,29 +14,39 @@ #ifndef __M_SWAP__ #define __M_SWAP__ -#include "endian.h" - // Endianess handling. // WAD files are stored little endian. +#include "endian.h" + +// Little to big endian #ifdef SRB2_BIG_ENDIAN -#define SHORT(x) ((INT16)(\ -(((UINT16)(x) & (UINT16)0x00ffU) << 8) \ -| \ -(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \ + #define SHORT(x) ((INT16)(\ + (((UINT16)(x) & (UINT16)0x00ffU) << 8) \ + | \ + (((UINT16)(x) & (UINT16)0xff00U) >> 8))) \ -#define LONG(x) ((INT32)(\ -(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \ -| \ -(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \ -| \ -(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \ -| \ -(((UINT32)(x) & (UINT32)0xff000000UL) >> 24))) + #define LONG(x) ((INT32)(\ + (((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \ + | \ + (((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \ + | \ + (((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \ + | \ + (((UINT32)(x) & (UINT32)0xff000000UL) >> 24))) #else -#define SHORT(x) ((INT16)(x)) -#define LONG(x) ((INT32)(x)) + #define SHORT(x) ((INT16)(x)) + #define LONG(x) ((INT32)(x)) +#endif + +// Big to little endian +#ifdef SRB2_LITTLE_ENDIAN + #define BIGENDIAN_LONG(x) ((INT32)(((x)>>24)&0xff)|(((x)<<8)&0xff0000)|(((x)>>8)&0xff00)|(((x)<<24)&0xff000000)) + #define BIGENDIAN_SHORT(x) ((INT16)(((x)>>8)|((x)<<8))) +#else + #define BIGENDIAN_LONG(x) ((INT32)(x)) + #define BIGENDIAN_SHORT(x) ((INT16)(x)) #endif #endif diff --git a/src/p_enemy.c b/src/p_enemy.c index b60e5e68b..bc3665237 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3006,16 +3006,19 @@ void A_Boss7FireMissiles(mobj_t *actor) // 0 - Boss 1 Left side // 1 - Boss 1 Right side // 2 - Triple laser -// >3 - Boss 1 Middle +// 3 - Boss 1 Middle +// >=3 - Generic middle // void A_Boss1Laser(mobj_t *actor) { fixed_t x, y, z, floorz, speed; INT32 locvar1 = var1; - INT32 locvar2 = var2; + INT32 locvar2 = (var2 & 65535); + INT32 upperend = (var2>>16); INT32 i; angle_t angle; mobj_t *point; + tic_t dur; #ifdef HAVE_BLUA if (LUA_CallAction("A_Boss1Laser", actor)) @@ -3024,19 +3027,24 @@ void A_Boss1Laser(mobj_t *actor) if (!actor->target) return; + if ((upperend & 1) && (actor->extravalue2 > 1)) + actor->extravalue2--; + + dur = actor->extravalue2; + switch (locvar2) { case 0: - x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; else z = actor->z + FixedMul(56*FRACUNIT, actor->scale); break; case 1: - x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; else @@ -3051,6 +3059,11 @@ void A_Boss1Laser(mobj_t *actor) A_Boss1Laser(actor); return; break; + case 3: + x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale)); + z = actor->z + actor->height/2; + break; default: x = actor->x; y = actor->y; @@ -3058,7 +3071,7 @@ void A_Boss1Laser(mobj_t *actor) break; } - if (!(actor->flags2 & MF2_FIRING) && actor->tics > 1) + if (!(actor->flags2 & MF2_FIRING) && dur > 1) { actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); if (mobjinfo[locvar1].seesound) @@ -3067,7 +3080,7 @@ void A_Boss1Laser(mobj_t *actor) { point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); point->angle = actor->angle; - point->fuse = actor->tics+1; + point->fuse = dur+1; P_SetTarget(&point->target, actor->target); P_SetTarget(&actor->target, point); } @@ -3076,9 +3089,9 @@ void A_Boss1Laser(mobj_t *actor) else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/ - if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) - angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); - else + /*if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) + angle = FixedAngle(FixedDiv(dur*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); + else*/ angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); point = P_SpawnMobj(x, y, z, locvar1); @@ -3112,7 +3125,7 @@ void A_Boss1Laser(mobj_t *actor) point->fuse = TICRATE; } - if (actor->tics > 1) + if (dur > 1) actor->flags2 |= MF2_FIRING; else actor->flags2 &= ~MF2_FIRING; @@ -3256,6 +3269,7 @@ void A_Boss4Raise(mobj_t *actor) // 0 - Fly at the player // 1 - Fly away from the player // 2 - Strafe in relation to the player +// 3 - Dynamic mode - don't get too close to walls // var2: // 0 - Fly horizontally and vertically // 1 - Fly horizontal-only (momz = 0) @@ -3286,16 +3300,83 @@ void A_SkullAttack(mobj_t *actor) S_StartSound(actor, actor->info->activesound); A_FaceTarget(actor); + dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); + if (locvar1 == 1) actor->angle += ANGLE_180; else if (locvar1 == 2) actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90; + else if (locvar1 == 3) + { + statenum_t oldspawnstate = mobjinfo[MT_NULL].spawnstate; + UINT32 oldflags = mobjinfo[MT_NULL].flags; + fixed_t oldradius = mobjinfo[MT_NULL].radius; + fixed_t oldheight = mobjinfo[MT_NULL].height; + mobj_t *check; + INT32 i, j, k; + boolean allow; + angle_t testang; + + mobjinfo[MT_NULL].spawnstate = S_INVISIBLE; + mobjinfo[MT_NULL].flags = MF_NOGRAVITY|MF_NOTHINK|MF_NOCLIPTHING|MF_NOBLOCKMAP; + mobjinfo[MT_NULL].radius = mobjinfo[actor->type].radius; + mobjinfo[MT_NULL].height = mobjinfo[actor->type].height; + + if (P_RandomChance(FRACUNIT/2)) // port priority 1? + { + i = 9; + j = 27; + } + else + { + i = 27; + j = 9; + } + +#define dostuff(q) check = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_NULL);\ + testang = actor->angle + ((i+(q))*ANG10);\ + allow = (P_TryMove(check,\ + P_ReturnThrustX(check, testang, dist + 2*actor->radius),\ + P_ReturnThrustY(check, testang, dist + 2*actor->radius),\ + true));\ + P_RemoveMobj(check);\ + if (allow)\ + break; + + if (P_RandomChance(FRACUNIT/2)) // port priority 2? + { + for (k = 0; k < 9; k++) + { + dostuff(i+k) + dostuff(i-k) + dostuff(j+k) + dostuff(j-k) + } + } + else + { + for (k = 0; k < 9; k++) + { + dostuff(i-k) + dostuff(i+k) + dostuff(j-k) + dostuff(j+k) + } + } + actor->angle = testang; + +#undef dostuff + + mobjinfo[MT_NULL].spawnstate = oldspawnstate; + mobjinfo[MT_NULL].flags = oldflags; + mobjinfo[MT_NULL].radius = oldradius; + mobjinfo[MT_NULL].height = oldheight; + } an = actor->angle >> ANGLETOFINESHIFT; actor->momx = FixedMul(speed, FINECOSINE(an)); actor->momy = FixedMul(speed, FINESINE(an)); - dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); dist = dist / speed; if (dist < 1) @@ -3445,11 +3526,13 @@ void A_Pain(mobj_t *actor) // // Description: Changes a dying object's flags to reflect its having fallen to the ground. // -// var1 = unused +// var1 = value to set repeat to if nonzero // var2 = unused // void A_Fall(mobj_t *actor) { + INT32 locvar1 = var1; + #ifdef HAVE_BLUA if (LUA_CallAction("A_Fall", actor)) return; @@ -3462,6 +3545,9 @@ void A_Fall(mobj_t *actor) // So change this if corpse objects // are meant to be obstacles. + + if (locvar1) + actor->extravalue2 = locvar1; } #define LIVESBOXDISPLAYPLAYER // Use displayplayer instead of closest player @@ -3857,6 +3943,72 @@ bossjustdie: else if (P_MobjWasRemoved(mo)) return; #endif + + // Spawn your junk + switch (mo->type) + { + default: + break; + case MT_EGGMOBILE: // twin laser pods + { + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ1); + + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ2); + } + break; + case MT_EGGMOBILE2: // twin tanks + spigot + { + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK1); + + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK2); + + mo2 = P_SpawnMobjFromMobj(mo, 0, 0, + mobjinfo[MT_EGGMOBILE2].height + (32<angle = mo->angle; + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + mo2->momz += mo->momz; + P_SetMobjState(mo2, S_BOSSSPIGOT); + } + break; + case MT_EGGMOBILE3: + { + mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK); + mo2->angle = mo->angle; + P_SetMobjState(mo2, S_BOSSSEBH1); + } + break; + } + + // now do another switch case for escaping switch (mo->type) { case MT_BLACKEGGMAN: @@ -3954,7 +4106,7 @@ bossjustdie: mo->movedir = 0; mo->extravalue1 = 35; mo->flags2 |= MF2_BOSSFLEE; - mo->momz = 2*mo->scale; + mo->momz = P_MobjFlip(mo)*2*mo->scale; if (mo->target) { @@ -3972,50 +4124,6 @@ bossjustdie: break; } } - - if (mo->type == MT_EGGMOBILE2) - { - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK1].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK1); // Right tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_InstaThrust(mo2, mo2->angle - ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK2].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK2); // Left tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_InstaThrust(mo2, mo2->angle + ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - - mo2 = P_SpawnMobj(mo->x, mo->y, - mo->z + ((mo->eflags & MFE_VERTICALFLIP)? mobjinfo[MT_BOSSSPIGOT].height-FixedMul(32*FRACUNIT,mo->scale): mo->height + FixedMul(32*FRACUNIT, mo->scale)), MT_BOSSSPIGOT); - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - return; - } } // Function: A_CustomPower @@ -6358,6 +6466,7 @@ void A_MixUp(mobj_t *actor) INT32 starpostnum; tic_t starposttime; angle_t starpostangle; + fixed_t starpostscale; INT32 mflags2; @@ -6405,6 +6514,7 @@ void A_MixUp(mobj_t *actor) starposty = players[one].starposty; starpostz = players[one].starpostz; starpostangle = players[one].starpostangle; + starpostscale = players[one].starpostscale; starpostnum = players[one].starpostnum; starposttime = players[one].starposttime; @@ -6413,15 +6523,11 @@ void A_MixUp(mobj_t *actor) P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle, players[two].starpostx, players[two].starposty, players[two].starpostz, players[two].starpostnum, players[two].starposttime, players[two].starpostangle, - players[two].mo->flags2); - - players[one].drawangle = players[two].drawangle; + players[two].starpostscale, players[two].drawangle, players[two].mo->flags2); P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz, starpostnum, starposttime, starpostangle, - mflags2); - - players[two].drawangle = drawangle; + starpostscale, drawangle, mflags2); //carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for... //but not all of it! So we need to make sure they aren't set wrong or anything. @@ -6448,6 +6554,7 @@ void A_MixUp(mobj_t *actor) INT32 starpostnum[MAXPLAYERS]; tic_t starposttime[MAXPLAYERS]; angle_t starpostangle[MAXPLAYERS]; + fixed_t starpostscale[MAXPLAYERS]; INT32 flags2[MAXPLAYERS]; @@ -6485,6 +6592,7 @@ void A_MixUp(mobj_t *actor) starpostnum[counter] = players[i].starpostnum; starposttime[counter] = players[i].starposttime; starpostangle[counter] = players[i].starpostangle; + starpostscale[counter] = players[i].starpostscale; flags2[counter] = players[i].mo->flags2; @@ -6525,9 +6633,7 @@ void A_MixUp(mobj_t *actor) P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom][0], spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2], starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom], - flags2[teleportfrom]); - - players[i].drawangle = anglepos[teleportfrom][1]; + starpostscale[teleportfrom], anglepos[teleportfrom][1], flags2[teleportfrom]); //...carry after. same reasoning. players[i].powers[pw_carry] = transcarry[teleportfrom]; @@ -8702,7 +8808,7 @@ void A_SetObjectFlags2(mobj_t *actor) // // var1: // 0 - Triple jet fume pattern -// 1 - Boss 3's propeller +// 1 - Unused (formerly Boss 3's propeller) // 2 - Metal Sonic jet fume // 3 - Boss 4 jet flame // var2 = unused @@ -8762,7 +8868,7 @@ void A_BossJetFume(mobj_t *actor) P_SetTarget(&actor->tracer, filler); } - else if (locvar1 == 1) // Boss 3 propeller + /*else if (locvar1 == 1) // Boss 3 propeller { fixed_t jetx, jety, jetz; @@ -8782,14 +8888,14 @@ void A_BossJetFume(mobj_t *actor) filler->angle = actor->angle - ANGLE_180; P_SetTarget(&actor->tracer, filler); - } + }*/ else if (locvar1 == 2) // Metal Sonic jet fumes { filler = P_SpawnMobj(actor->x, actor->y, actor->z, MT_JETFUME1); P_SetTarget(&filler->target, actor); filler->fuse = 59; P_SetTarget(&actor->tracer, filler); - filler->destscale = actor->scale/2; + filler->destscale = actor->scale/3; P_SetScale(filler, filler->destscale); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; diff --git a/src/p_inter.c b/src/p_inter.c index 0030e8e58..bfdec3e23 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1427,6 +1427,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) players[i].starposty = player->mo->y>>FRACBITS; players[i].starpostz = special->z>>FRACBITS; players[i].starpostangle = special->angle; + players[i].starpostscale = player->mo->destscale; + if (special->flags2 & MF2_OBJECTFLIP) + { + players[i].starpostscale *= -1; + players[i].starpostz += special->height>>FRACBITS; + } players[i].starpostnum = special->health; if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i])) @@ -1443,6 +1449,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->starposty = toucher->y>>FRACBITS; player->starpostz = special->z>>FRACBITS; player->starpostangle = special->angle; + player->starpostscale = player->mo->destscale; + if (special->flags2 & MF2_OBJECTFLIP) + { + player->starpostscale *= -1; + player->starpostz += special->height>>FRACBITS; + } player->starpostnum = special->health; S_StartSound(toucher, special->info->painsound); } @@ -1583,6 +1595,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Buenos Dias Mandy P_SetPlayerMobjState(toucher, S_PLAY_STUN); player->pflags &= ~PF_APPLYAUTOBRAKE; + P_ResetPlayer(player); player->drawangle = special->angle + ANGLE_180; P_InstaThrust(toucher, special->angle, FixedMul(3*special->info->speed, special->scale/2)); toucher->z += P_MobjFlip(toucher); @@ -1688,13 +1701,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; if (mariomode) return; + if (special->state-states != S_EXTRALARGEBUBBLE) + return; // Don't grab the bubble during its spawn animation else if (toucher->eflags & MFE_VERTICALFLIP) { - if (special->z+special->height < toucher->z + toucher->height / 3 - || special->z+special->height > toucher->z + (toucher->height*2/3)) + if (special->z+special->height < toucher->z + || special->z+special->height > toucher->z + (toucher->height*2/3)) return; // Only go in the mouth } - else if (special->z < toucher->z + toucher->height / 3 + else if (special->z < toucher->z || special->z > toucher->z + (toucher->height*2/3)) return; // Only go in the mouth @@ -2469,8 +2484,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget else if (P_IsLocalPlayer(target->player)) gameovermus = true; - if (gameovermus) - P_PlayJingle(target->player, JT_GOVER); // Yousa dead now, Okieday? Tails 03-14-2000 + if (gameovermus) // Yousa dead now, Okieday? Tails 03-14-2000 + S_ChangeMusicEx("_gover", 0, 0, 0, (2*MUSICRATE) - (MUSICRATE/25), 0); // 1.96 seconds + //P_PlayJingle(target->player, JT_GOVER); // can't be used because incompatible with track fadeout if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers) { @@ -2594,6 +2610,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget case MT_EGGMOBILE3: { + mobj_t *mo2; thinker_t *th; UINT32 i = 0; // to check how many clones we've removed @@ -2614,6 +2631,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE); mo->momz = mo->info->speed; mo->angle = FixedAngle((P_RandomKey(36)*10)<angle = mo->angle; + P_SetMobjState(mo2, S_BOSSSEBH2); + if (++i == 2) // we've already removed 2 of these, let's stop now break; else @@ -3418,7 +3440,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Make sure that boxes cannot be popped by enemies, red rings, etc. - if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot) || (inflictor && !inflictor->player))) + if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot) + || (inflictor && inflictor->type >= MT_REDRING && inflictor->type <= MT_GRENADERING))) return false; } @@ -3500,7 +3523,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return true; } - if (G_IsSpecialStage(gamemap)) + if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK)) { P_SpecialStageDamage(player, inflictor, source); return true; @@ -3524,10 +3547,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Instant-Death if (damagetype & DMG_DEATHMASK) - { P_KillPlayer(player, source, damage); - player->rings = player->spheres = 0; - } else if (metalrecording) { if (!inflictor) diff --git a/src/p_local.h b/src/p_local.h index 3a0146e54..4a5865027 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -115,10 +115,10 @@ typedef struct camera_s extern camera_t camera, camera2; extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height; -extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed; +extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_orbit, cv_cam_adjust; extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height; -extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed; +extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_orbit, cv_cam2_adjust; extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate; extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; @@ -509,7 +509,7 @@ extern INT32 ceilmovesound; void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, INT16 starpostx, INT16 starposty, INT16 starpostz, INT32 starpostnum, tic_t starposttime, angle_t starpostangle, - INT32 flags2); + fixed_t starpostscale, angle_t drawangle, INT32 flags2); boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove); boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state); boolean P_CheckMissileSpawn(mobj_t *th); diff --git a/src/p_map.c b/src/p_map.c index 15fa97c8f..01c41131b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -345,17 +345,14 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (horizspeed) { object->player->drawangle = spring->angle; - if (vertispeed || (object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0)) - { - object->angle = spring->angle; + object->angle = spring->angle; - if (!demoplayback || P_AnalogMove(object->player)) - { - if (object->player == &players[consoleplayer]) - localangle = spring->angle; - else if (object->player == &players[secondarydisplayplayer]) - localangle2 = spring->angle; - } + if (!demoplayback || P_AnalogMove(object->player)) + { + if (object->player == &players[consoleplayer]) + localangle = spring->angle; + else if (object->player == &players[secondarydisplayplayer]) + localangle2 = spring->angle; } } @@ -1022,7 +1019,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // underneath if (tmthing->flags & MF_SHOOTABLE && thing->health > 0) { - UINT8 damagetype = (thing->info->mass & 0xFF); + UINT32 damagetype = (thing->info->mass & 0xFF); if (!damagetype && thing->flags & MF_FIRE) // BURN! damagetype = DMG_FIRE; if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) @@ -1039,7 +1036,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // underneath if (thing->flags & MF_SHOOTABLE && tmthing->health > 0) { - UINT8 damagetype = (tmthing->info->mass & 0xFF); + UINT32 damagetype = (tmthing->info->mass & 0xFF); if (!damagetype && tmthing->flags & MF_FIRE) // BURN! damagetype = DMG_FIRE; if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8))) @@ -2884,11 +2881,8 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->z = thing->ceilingz - thing->height; } - if (thing->z != oldz) - { - if (thing->player) - P_PlayerHitFloor(thing->player, !onfloor); - } + if (P_MobjFlip(thing)*(thing->z - oldz) > 0 && thing->player) + P_PlayerHitFloor(thing->player, !onfloor); // debug: be sure it falls to the floor thing->eflags &= ~MFE_ONGROUND; @@ -3202,7 +3196,7 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle) && glidesector->sector->ceilingpic == skyflatnum) return false; - if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < ceilingz) + if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz) || (player->mo->z >= ceilingz)) floorclimb = true; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 1ee90d250..5dfb7a5ab 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2381,22 +2381,42 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) { + fixed_t topheight; + I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - { - fixed_t topheight = - #ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : - #endif - *rover->topheight; + // not a lava block with solid planes + if (!(rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + && !(rover->master->flags & ML_BLOCKMONSTERS))) + return false; - if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 - && !(rover->master->flags & ML_BLOCKMONSTERS) - && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale))) + // is solid from the sides + if (rover->master->flags & ML_EFFECT3) + return true; + + if (mo->eflags & MFE_VERTICALFLIP) + { + topheight = + #ifdef ESLOPE + *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : + #endif + *rover->bottomheight; + + if (mo->z+mo->height-mo->momz < topheight + FixedMul(16*FRACUNIT, mo->scale)) return true; + return false; } + topheight = + #ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : + #endif + *rover->topheight; + + if (mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale)) + return true; + return false; } @@ -2954,7 +2974,7 @@ static void P_PlayerZMovement(mobj_t *mo) } // Get up if you fell. if (mo->player->panim == PA_PAIN) - P_SetPlayerMobjState(mo, S_PLAY_STND); + P_SetPlayerMobjState(mo, S_PLAY_WALK); #ifdef ESLOPE if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { @@ -3760,7 +3780,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled if (thiscam->momx || thiscam->momy) { - if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) + if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) // Thanks for the greatly improved camera, Lach -- Sev { // Never fails for 2D mode. mobj_t dummy; dummy.thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -3770,9 +3790,22 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.z = thiscam->z; dummy.height = thiscam->height; if (!resetcalled && !(player->pflags & PF_NOCLIP) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. + { P_ResetCamera(player, thiscam); + resetcalled = true; + } else + { + fixed_t camspeed = P_AproxDistance(thiscam->momx, thiscam->momy); + P_SlideCameraMove(thiscam); + + if (!resetcalled && P_AproxDistance(thiscam->momx, thiscam->momy) == camspeed) + { + P_ResetCamera(player, thiscam); + resetcalled = true; + } + } if (resetcalled) // Okay this means the camera is fully reset. return true; } @@ -3981,6 +4014,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { +#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling mobj->player->pflags &= ~PF_STARTJUMP; mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); @@ -3990,6 +4024,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->player->powers[pw_tailsfly] = 0; P_SetPlayerMobjState(mobj, S_PLAY_WALK); } +#endif mobj->eflags &= ~MFE_JUSTHITFLOOR; } @@ -4359,12 +4394,6 @@ static void P_Boss3Thinker(mobj_t *mobj) if (mobj->flags2 & MF2_FRET) mobj->movedir = 1; - if (!mobj->tracer) - { - var1 = 1; - A_BossJetFume(mobj); - } - if (mobj->health <= 0) return; /* @@ -4493,7 +4522,7 @@ static void P_Boss3Thinker(mobj_t *mobj) if (mobj->health <= mobj->info->damage) // pinch phase mobj->movecount--; // limited number of shots before diving again if (mobj->movecount) - P_SetMobjState(mobj, mobj->info->missilestate); + P_SetMobjState(mobj, mobj->info->missilestate+1); } } else if (mobj->threshold >= 0) // Traveling mode @@ -4592,6 +4621,15 @@ static void P_Boss3Thinker(mobj_t *mobj) ang += (ANGLE_MAX/64); } S_StartSound(mobj, sfx_fizzle); + + // look for a new target + P_BossTargetPlayer(mobj, false); + + if (mobj->target && mobj->target->player) + { + A_FaceTarget(mobj); + P_SetMobjState(mobj, mobj->info->missilestate); + } } else if (mobj->flags2 & (MF2_STRONGBOX|MF2_CLASSICPUSH)) // just hit the bottom of your tube { @@ -5527,8 +5565,7 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); P_SetScale(mobj->tracer, mobj->tracer->destscale); } - else - mobj->tracer->frame &= ~FF_TRANSMASK; // this causes a flicker but honestly i like it this way + P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); mobj->tracer->momx = mobj->momx; mobj->tracer->momy = mobj->momy; @@ -5645,12 +5682,12 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health > mobj->info->damage) { - P_SetScale(missile, FRACUNIT/2); + P_SetScale(missile, FRACUNIT/3); missile->color = SKINCOLOR_GOLD; // sonic cd electric power } else { - P_SetScale(missile, FRACUNIT/4); + P_SetScale(missile, FRACUNIT/5); missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power } missile->destscale = missile->scale*2; @@ -5940,9 +5977,7 @@ static void P_Boss9Thinker(mobj_t *mobj) P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); shield->height -= 20*FRACUNIT; // different offset... - shield->color = SKINCOLOR_MAGENTA; - shield->colorized = true; - P_SetMobjState(shield, S_FIRS1); + P_SetMobjState(shield, S_MSSHIELD_F2); //P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2... } mobj->fuse = 4*TICRATE; @@ -7093,9 +7128,7 @@ void P_MobjThinker(mobj_t *mobj) switch (mobj->type) { - case MT_BOSSTANK1: - case MT_BOSSTANK2: - case MT_BOSSSPIGOT: + case MT_BOSSJUNK: mobj->flags2 ^= MF2_DONTDRAW; break; case MT_MACEPOINT: @@ -7681,12 +7714,22 @@ void P_MobjThinker(mobj_t *mobj) switch (mobj->type) { case MT_EGGMOBILE: - if (mobj->health < mobj->info->damage+1 && leveltime & 1 && mobj->health > 0) - P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMOKE); + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } if (mobj->flags2 & MF2_SKULLFLY) #if 1 P_SpawnGhostMobj(mobj); -#else +#else // all the way back from final demo... MT_THOK isn't even the same size anymore! { mobj_t *spawnmobj; spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance); @@ -7697,12 +7740,48 @@ void P_MobjThinker(mobj_t *mobj) P_Boss1Thinker(mobj); break; case MT_EGGMOBILE2: + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } P_Boss2Thinker(mobj); break; case MT_EGGMOBILE3: + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } P_Boss3Thinker(mobj); break; case MT_EGGMOBILE4: + if (mobj->health < mobj->info->damage+1 && leveltime & 2) + { + fixed_t rad = mobj->radius>>FRACBITS; + fixed_t hei = mobj->height>>FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad)<momz += mobj->momz; + } P_Boss4Thinker(mobj); break; case MT_FANG: @@ -8318,30 +8397,6 @@ void P_MobjThinker(mobj_t *mobj) mobj->fuse++; } break; - case MT_PROPELLER: - { - fixed_t jetx, jety; - - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale)); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale)); - - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - mobj->z = mobj->target->z + FixedMul(17*FRACUNIT, mobj->target->scale); - mobj->angle = mobj->target->angle - ANGLE_180; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; case MT_JETFLAME: { if (!mobj->target // if you have no target @@ -8405,6 +8460,17 @@ void P_MobjThinker(mobj_t *mobj) } else { + + fixed_t basex = mobj->cusval, basey = mobj->cvmem; + + if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) + { + angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90); + fixed_t oscillate = FixedMul(FINESINE(((leveltime*ANG1)>>(ANGLETOFINESHIFT+2)) & FINEMASK), 250*mobj->scale); + basex += P_ReturnThrustX(mobj, sideang, oscillate); + basey += P_ReturnThrustY(mobj, sideang, oscillate); + } + mobj->z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK), 8*mobj->scale); if (mobj->state != &states[mobj->info->meleestate]) { @@ -8433,8 +8499,8 @@ void P_MobjThinker(mobj_t *mobj) if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) continue; compdist = P_AproxDistance( - players[i].mo->x + players[i].mo->momx - mobj->cusval, - players[i].mo->y + players[i].mo->momy - mobj->cvmem); + players[i].mo->x + players[i].mo->momx - basex, + players[i].mo->y + players[i].mo->momy - basey); if (compdist >= dist) continue; dist = compdist; @@ -8448,14 +8514,14 @@ void P_MobjThinker(mobj_t *mobj) mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); if (P_AproxDistance( - mobj->x - mobj->cusval, - mobj->y - mobj->cvmem) + mobj->x - basex, + mobj->y - basey) < mobj->scale) S_StartSound(mobj, mobj->info->seesound); P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (mobj->cusval>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4), - (15*(mobj->y>>4)) + (mobj->cvmem>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4), + (15*(mobj->x>>4)) + (basex>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4), + (15*(mobj->y>>4)) + (basey>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4), mobj->z); } else @@ -8478,18 +8544,12 @@ void P_MobjThinker(mobj_t *mobj) if (!didmove) { - if (P_AproxDistance( - mobj->x - mobj->cusval, - mobj->y - mobj->cvmem) - < mobj->scale) - P_TeleportMove(mobj, - mobj->cusval, - mobj->cvmem, - mobj->z); + if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale) + P_TeleportMove(mobj, basex, basey, mobj->z); else P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (mobj->cusval>>4), - (15*(mobj->y>>4)) + (mobj->cvmem>>4), + (15*(mobj->x>>4)) + (basex>>4), + (15*(mobj->y>>4)) + (basey>>4), mobj->z); } } @@ -9038,9 +9098,9 @@ void P_MobjThinker(mobj_t *mobj) { if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) { - var1 = mobj->state->var1; - var2 = mobj->state->var2; - mobj->state->action.acp1(mobj); + /*var1 = mobj->state->var1; + var2 = mobj->state->var2 & 65535; + mobj->state->action.acp1(mobj);*/ } else if (leveltime & 1) // Fire mode { @@ -10387,7 +10447,7 @@ void P_SpawnPlayer(INT32 playernum) mobj_t *mobj; if (p->playerstate == PST_REBORN) - G_PlayerReborn(playernum); + G_PlayerReborn(playernum, false); // spawn as spectator determination if (!G_GametypeHasSpectators()) @@ -10395,9 +10455,9 @@ void P_SpawnPlayer(INT32 playernum) p->spectator = p->outofcoop = (((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop && ((leveltime > 0 - && ((G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) // late join special stage + && ((G_IsSpecialStage(gamemap)) // late join special stage || (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop - || (((cv_cooplives.value == 1) || !P_GetLives(p)) && p->lives <= 0))); // game over and can't redistribute lives + || (!P_GetLives(p) && p->lives <= 0))); // game over and can't redistribute lives } else { @@ -10464,7 +10524,6 @@ void P_SpawnPlayer(INT32 playernum) P_SetupStateAnimation(mobj, mobj->state); mobj->health = 1; - p->rings = p->spheres = 0; p->playerstate = PST_LIVE; p->bonustime = false; @@ -10521,10 +10580,6 @@ void P_AfterPlayerSpawn(INT32 playernum) else p->viewz = p->mo->z + p->viewheight; - if (p->powers[pw_carry] != CR_NIGHTSMODE) - P_SetPlayerMobjState(p->mo, S_PLAY_STND); - p->pflags &= ~PF_SPINNING; - if (playernum == consoleplayer) { // wake up the status bar @@ -10609,6 +10664,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) mobj->eflags |= MFE_VERTICALFLIP; mobj->flags2 |= MF2_OBJECTFLIP; } + if (mthing->options & MTF_AMBUSH) + P_SetPlayerMobjState(mobj, S_PLAY_FALL); } else z = floor; @@ -10627,7 +10684,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) P_SetThingPosition(mobj); mobj->z = z; - if (mobj->z == mobj->floorz) + if (mobj->flags2 & MF2_OBJECTFLIP) + { + if (mobj->z + mobj->height == mobj->ceilingz) + mobj->eflags |= MFE_ONGROUND; + } + else if (mobj->z == mobj->floorz) mobj->eflags |= MFE_ONGROUND; mobj->angle = angle; @@ -10663,17 +10725,29 @@ void P_MovePlayerToStarpost(INT32 playernum) sector->ceilingheight; z = p->starpostz << FRACBITS; - if (z < floor) + + P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale))); + + if (p->starpostscale < 0) + { + mobj->flags2 |= MF2_OBJECTFLIP; + if (z >= ceiling) + { + mobj->eflags |= MFE_ONGROUND; + z = ceiling; + } + z -= mobj->height; + } + else if (z <= floor) + { + mobj->eflags |= MFE_ONGROUND; z = floor; - else if (z > ceiling - mobjinfo[MT_PLAYER].height) - z = ceiling - mobjinfo[MT_PLAYER].height; + } mobj->floorz = floor; mobj->ceilingz = ceiling; mobj->z = z; - if (mobj->z == mobj->floorz) - mobj->eflags |= MFE_ONGROUND; mobj->angle = p->starpostangle; diff --git a/src/p_saveg.c b/src/p_saveg.c index 7c073b151..69c942236 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -189,6 +189,7 @@ static void P_NetArchivePlayers(void) WRITEINT16(save_p, players[i].starpostz); WRITEINT32(save_p, players[i].starpostnum); WRITEANGLE(save_p, players[i].starpostangle); + WRITEFIXED(save_p, players[i].starpostscale); WRITEANGLE(save_p, players[i].angle_pos); WRITEANGLE(save_p, players[i].old_angle_pos); @@ -397,6 +398,7 @@ static void P_NetUnArchivePlayers(void) players[i].starpostz = READINT16(save_p); players[i].starpostnum = READINT32(save_p); players[i].starpostangle = READANGLE(save_p); + players[i].starpostscale = READFIXED(save_p); players[i].angle_pos = READANGLE(save_p); players[i].old_angle_pos = READANGLE(save_p); @@ -4117,12 +4119,54 @@ static inline boolean P_NetUnArchiveMisc(void) return true; } +static inline void P_ArchiveLuabanksAndConsistency(void) +{ + UINT8 i, banksinuse = NUM_LUABANKS; + + while (banksinuse && !luabanks[banksinuse-1]) + banksinuse--; // get the last used bank + + if (banksinuse) + { + WRITEUINT8(save_p, 0xb7); // luabanks marker + WRITEUINT8(save_p, banksinuse); + for (i = 0; i < banksinuse; i++) + WRITEINT32(save_p, luabanks[i]); + } + + WRITEUINT8(save_p, 0x1d); // consistency marker +} + +static inline boolean P_UnArchiveLuabanksAndConsistency(void) +{ + switch (READUINT8(save_p)) + { + case 0xb7: + { + UINT8 i, banksinuse = READUINT8(save_p); + if (banksinuse > NUM_LUABANKS) + return false; + for (i = 0; i < banksinuse; i++) + luabanks[i] = READINT32(save_p); + if (READUINT8(save_p) != 0x1d) + return false; + } + case 0x1d: + break; + default: + return false; + } + + return true; +} + void P_SaveGame(void) { P_ArchiveMisc(); P_ArchivePlayer(); - WRITEUINT8(save_p, 0x1d); // consistency marker + // yes, even in non HAVE_BLUA + P_ArchiveLuabanksAndConsistency(); } void P_SaveNetGame(void) @@ -4161,7 +4205,7 @@ void P_SaveNetGame(void) LUA_Archive(); #endif - WRITEUINT8(save_p, 0x1d); // consistency marker + P_ArchiveLuabanksAndConsistency(); } boolean P_LoadGame(INT16 mapoverride) @@ -4173,8 +4217,7 @@ boolean P_LoadGame(INT16 mapoverride) P_UnArchiveSPGame(mapoverride); P_UnArchivePlayer(); - // Savegame end marker - if (READUINT8(save_p) != 0x1d) + if (!P_UnArchiveLuabanksAndConsistency()) return false; // Only do this after confirming savegame is ok @@ -4215,5 +4258,5 @@ boolean P_LoadNetGame(void) // precipitation when loading a netgame save. Instead, precip has to be spawned here. // This is done in P_NetUnArchiveSpecials now. - return READUINT8(save_p) == 0x1d; + return P_UnArchiveLuabanksAndConsistency(); } diff --git a/src/p_setup.c b/src/p_setup.c index d0cd14b22..c83c8cd5c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -221,6 +221,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->muspostbosstrack = 0; mapheaderinfo[num]->muspostbosspos = 0; mapheaderinfo[num]->muspostbossfadein = 0; + mapheaderinfo[num]->musforcereset = -1; mapheaderinfo[num]->forcecharacter[0] = '\0'; mapheaderinfo[num]->weather = 0; mapheaderinfo[num]->skynum = 1; @@ -573,6 +574,11 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); + levelflat->texturenum = R_CheckTextureNumForName(flatname); + levelflat->lasttexturenum = levelflat->texturenum; + + levelflat->baselumpnum = LUMPERROR; + levelflat->basetexturenum = -1; #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); @@ -617,6 +623,11 @@ INT32 P_AddLevelFlatRuntime(const char *flatname) // store the flat lump number levelflat->lumpnum = R_GetFlatNumForName(flatname); + levelflat->texturenum = R_CheckTextureNumForName(flatname); + levelflat->lasttexturenum = levelflat->texturenum; + + levelflat->baselumpnum = LUMPERROR; + levelflat->basetexturenum = -1; #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); @@ -1480,6 +1491,7 @@ static void P_LoadRawSideDefs2(void *data) case 425: // Calls P_SetMobjState on calling mobj case 434: // Custom Power case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors + case 461: // Spawns an object on the map based on texture offsets { char process[8*3+1]; memset(process,0,8*3+1); @@ -2234,6 +2246,8 @@ static void P_LevelInitStuff(void) for (i = 0; i < MAXPLAYERS; i++) { + G_PlayerReborn(i, true); + if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) { // In Co-Op, replenish a user's lives if they are depleted. @@ -2241,41 +2255,18 @@ static void P_LevelInitStuff(void) } // obliteration station... - players[i].rings = players[i].spheres =\ - players[i].xtralife = players[i].deadtimer =\ - players[i].numboxes = players[i].totalring =\ - players[i].laps = players[i].aiming =\ - players[i].losstime = players[i].timeshit =\ - players[i].marescore = players[i].lastmarescore =\ - players[i].maxlink = players[i].startedtime =\ - players[i].finishedtime = players[i].finishedspheres =\ - players[i].finishedrings = players[i].lastmare =\ - players[i].lastmarelap = players[i].lastmarebonuslap =\ - players[i].totalmarelap = players[i].totalmarebonuslap =\ - players[i].marebegunat = players[i].textvar =\ - players[i].texttimer = players[i].linkcount =\ - players[i].linktimer = players[i].flyangle =\ - players[i].anotherflyangle = players[i].nightstime =\ - players[i].oldscale = players[i].mare = players[i].marelap =\ - players[i].marebonuslap = players[i].lapbegunat =\ - players[i].lapstartedtime = players[i].totalmarescore =\ - players[i].realtime = players[i].exiting = 0; + players[i].numboxes = players[i].totalring =\ + players[i].laps = players[i].marescore = players[i].lastmarescore =\ + players[i].mare = players[i].exiting = 0; - // i guess this could be part of the above but i feel mildly uncomfortable implicitly casting - players[i].gotcontinue = false; - - // aha, the first evidence this shouldn't be a memset! players[i].drillmeter = 40*20; - P_ResetPlayer(&players[i]); // hit these too - players[i].pflags &= ~(PF_GAMETYPEOVER|PF_TRANSFERTOCLOSEST); - - // unset ALL the pointers. P_SetTarget isn't needed here because if this - // function is being called we're just going to clobber the data anyways - players[i].mo = players[i].followmobj = players[i].awayviewmobj =\ - players[i].capsule = players[i].axis1 = players[i].axis2 = players[i].drone = NULL; + players[i].pflags &= ~(PF_GAMETYPEOVER); } + + if (botingame) + CV_SetValue(&cv_analog2, true); } // @@ -2692,7 +2683,7 @@ boolean P_SetupLevel(boolean skipprecip) S_StartSound(NULL, sfx_s3kaf); // Fade music! Time it to S3KAF: 0.25 seconds is snappy. - if (cv_resetmusic.value || + if (RESETMUSIC || strnicmp(S_MusicName(), (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)) S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE) @@ -2725,7 +2716,7 @@ boolean P_SetupLevel(boolean skipprecip) // Fade out music here. Deduct 2 tics so the fade volume actually reaches 0. // But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug. - if (!titlemapinaction && (cv_resetmusic.value || + if (!titlemapinaction && (RESETMUSIC || strnicmp(S_MusicName(), (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))) S_FadeMusic(0, FixedMul( diff --git a/src/p_setup.h b/src/p_setup.h index 7e8a5d7e6..7e3a149eb 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -37,12 +37,19 @@ typedef struct { char name[9]; // resource name from wad lumpnum_t lumpnum; // lump number of the flat + INT32 texturenum, lasttexturenum; // texture number of the flat + UINT16 width, height; + fixed_t topoffset, leftoffset; // for flat animation lumpnum_t baselumpnum; + INT32 basetexturenum; INT32 animseq; // start pos. in the anim sequence INT32 numpics; INT32 speed; + + // for patchflats + UINT8 *flatpatch; } levelflat_t; extern size_t numlevelflats; diff --git a/src/p_spec.c b/src/p_spec.c index 37a1652f0..256ca3453 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -205,8 +205,8 @@ void P_InitPicAnims(void) if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) continue; - lastanim->picnum = R_FlatNumForName(animdefs[i].endname); - lastanim->basepic = R_FlatNumForName(animdefs[i].startname); + lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); + lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); } lastanim->istexture = animdefs[i].istexture; @@ -464,7 +464,19 @@ static inline void P_FindAnimatedFlat(INT32 animnum) for (i = 0; i < numlevelflats; i++, foundflats++) { // is that levelflat from the flat anim sequence ? - if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) + if ((anims[animnum].istexture) && (foundflats->texturenum != 0 && foundflats->texturenum != -1) + && ((UINT16)foundflats->texturenum >= startflatnum && (UINT16)foundflats->texturenum <= endflatnum)) + { + foundflats->basetexturenum = startflatnum; + foundflats->animseq = foundflats->texturenum - startflatnum; + foundflats->numpics = endflatnum - startflatnum + 1; + foundflats->speed = anims[animnum].speed; + + CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", + atoi(sizeu1(i)), foundflats->name, foundflats->animseq, + foundflats->numpics,foundflats->speed); + } + else if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) { foundflats->baselumpnum = startflatnum; foundflats->animseq = foundflats->lumpnum - startflatnum; @@ -488,10 +500,7 @@ void P_SetupLevelFlatAnims(void) // the original game flat anim sequences for (i = 0; anims[i].istexture != -1; i++) - { - if (!anims[i].istexture) - P_FindAnimatedFlat(i); - } + P_FindAnimatedFlat(i); } // @@ -3953,6 +3962,39 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 461: // Spawns an object on the map based on texture offsets + { + const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture); + mobj_t *mobj; + + fixed_t x, y, z; + x = sides[line->sidenum[0]].textureoffset; + y = sides[line->sidenum[0]].rowoffset; + z = line->frontsector->floorheight; + + if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range + { + if (line->sidenum[1] != 0xffff) // Make sure the linedef has a back side + { + x = P_RandomRange(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[1]].textureoffset>>FRACBITS)<sidenum[0]].rowoffset>>FRACBITS, sides[line->sidenum[1]].rowoffset>>FRACBITS)<frontsector->floorheight>>FRACBITS, line->frontsector->ceilingheight>>FRACBITS)<special); + break; + } + } + + mobj = P_SpawnMobj(x, y, z, type); + if (mobj) + CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. + else + CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special); + } + break; + #ifdef POLYOBJECTS case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing @@ -4942,7 +4984,7 @@ DoneSection2: CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1); // Reset starposts (checkpoints) info - player->starpostangle = player->starposttime = player->starpostnum = 0; + player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0; player->starpostx = player->starposty = player->starpostz = 0; P_ResetStarposts(); @@ -5636,9 +5678,12 @@ void P_UpdateSpecials(void) { if (foundflats->speed) // it is an animated flat { + // update the levelflat texture number + if (foundflats->basetexturenum != -1) + foundflats->texturenum = foundflats->basetexturenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); // update the levelflat lump number - foundflats->lumpnum = foundflats->baselumpnum + - ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + else if (foundflats->baselumpnum != LUMPERROR) + foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); } } } diff --git a/src/p_telept.c b/src/p_telept.c index e80dd0428..632b81e04 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -33,7 +33,7 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, INT16 starpostx, INT16 starposty, INT16 starpostz, INT32 starpostnum, tic_t starposttime, angle_t starpostangle, - INT32 flags2) + fixed_t starpostscale, angle_t drawangle, INT32 flags2) { const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP; @@ -89,8 +89,11 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, thing->player->starpostz = starpostz; thing->player->starposttime = starposttime; thing->player->starpostangle = starpostangle; + thing->player->starpostscale = starpostscale; thing->player->starpostnum = starpostnum; + thing->player->drawangle = drawangle; + // Reset map starposts for the player's new info. P_ResetStarposts(); P_ClearStarPost(starpostnum); diff --git a/src/p_user.c b/src/p_user.c index 58ba00fc9..88751c143 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1109,7 +1109,7 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) } else if (P_MobjFlip(player->mo)*(topheight - (thing->z + thing->height/2)) < 0) { - if (player->charability == CA_FLY && player->panim == PA_ABILITY && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) + if (player->charability == CA_FLY && player->panim == PA_ABILITY && !(player->mo->eflags & MFE_UNDERWATER) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) return true; } @@ -2217,148 +2217,153 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) player->pflags &= ~PF_SPINNING; } - if (player->pflags & PF_SPINNING) - { - if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) - { - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); - } - } - else if (player->pflags & PF_GLIDING) // ground gliding - { - if (dorollstuff) - { - player->skidtime = TICRATE; - player->mo->tics = -1; - } - else if (!player->skidtime) - player->pflags &= ~PF_GLIDING; - } - else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - { - if (player->mo->state-states != S_PLAY_MELEE_LANDING) - { - mobjtype_t type = player->revitem; - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); - player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; - S_StartSound(player->mo, sfx_s3k8b); - player->pflags |= PF_FULLSTASIS; - - // hearticles - if (type) - { - UINT8 i = 0; - angle_t throwang = -(2*ANG30); - fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t zo = 6*player->mo->scale; - fixed_t mu = FixedMul(player->maxdash, player->mo->scale); - fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); - fixed_t ev; - mobj_t *missile = NULL; - if (mu2 < mu) - mu2 = mu; - ev = (50*FRACUNIT - (mu/25))/50; - while (i < 5) - { - missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); - P_SetTarget(&missile->target, player->mo); - missile->angle = throwang + player->drawangle; - P_Thrust(missile, player->drawangle + ANGLE_90, - P_ReturnThrustY(missile, throwang, mu)); // side to side component - P_Thrust(missile, player->drawangle, mu2); // forward component - P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); - missile->momz += player->mo->pmomz; - missile->fuse = TICRATE/2; - missile->extravalue2 = ev; - - i++; - throwang += ANG30; - } - if (mobjinfo[type].seesound && missile) - S_StartSound(missile, missile->info->seesound); - } - } - } - else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) - ; - else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH) - { - if (player->cmomx || player->cmomy) - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->rmomx || player->rmomy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } - else - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->mo->momx || player->mo->momy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } - } - - if (!(player->pflags & PF_GLIDING)) - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); - player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); - player->secondjump = 0; - player->glidetime = 0; - player->climbing = 0; - player->powers[pw_tailsfly] = 0; - - if (player->pflags & PF_SHIELDABILITY) - { - player->pflags &= ~PF_SHIELDABILITY; - - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack. - { - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound - S_StartSound(player->mo, sfx_s3k4c); - else // create a fire pattern on the ground - { - S_StartSound(player->mo, sfx_s3k47); - P_ElementalFire(player, true); - } - P_SetObjectMomZ(player->mo, - (player->mo->eflags & MFE_UNDERWATER) - ? 6*FRACUNIT/5 - : 5*FRACUNIT/2, - false); - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - player->mo->momx = player->mo->momy = 0; - clipmomz = false; - } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack. - { - P_DoBubbleBounce(player); - clipmomz = false; - } - } - if (player->pflags & PF_BOUNCING) { - P_MobjCheckWater(player->mo); - player->mo->momz *= -1; - P_DoAbilityBounce(player, true); - if (player->scoreadd) - player->scoreadd--; + if (dorollstuff && player->mo->state-states != S_PLAY_BOUNCE_LANDING) + { + P_MobjCheckWater(player->mo); + player->mo->momz *= -1; + P_DoAbilityBounce(player, true); + if (player->scoreadd) + player->scoreadd--; + } clipmomz = false; } + else + { + if (player->pflags & PF_SPINNING) + { + if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) + { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_spin); + } + } + else if (player->pflags & PF_GLIDING) // ground gliding + { + if (dorollstuff) + { + player->skidtime = TICRATE; + player->mo->tics = -1; + } + else if (!player->skidtime) + player->pflags &= ~PF_GLIDING; + } + else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + { + if (player->mo->state-states != S_PLAY_MELEE_LANDING) + { + mobjtype_t type = player->revitem; + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); + player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; + S_StartSound(player->mo, sfx_s3k8b); + player->pflags |= PF_FULLSTASIS; + + // hearticles + if (type) + { + UINT8 i = 0; + angle_t throwang = -(2*ANG30); + fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t zo = 6*player->mo->scale; + fixed_t mu = FixedMul(player->maxdash, player->mo->scale); + fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); + fixed_t ev; + mobj_t *missile = NULL; + if (mu2 < mu) + mu2 = mu; + ev = (50*FRACUNIT - (mu/25))/50; + while (i < 5) + { + missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); + P_SetTarget(&missile->target, player->mo); + missile->angle = throwang + player->drawangle; + P_Thrust(missile, player->drawangle + ANGLE_90, + P_ReturnThrustY(missile, throwang, mu)); // side to side component + P_Thrust(missile, player->drawangle, mu2); // forward component + P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); + missile->momz += player->mo->pmomz; + missile->fuse = TICRATE/2; + missile->extravalue2 = ev; + + i++; + throwang += ANG30; + } + if (mobjinfo[type].seesound && missile) + S_StartSound(missile, missile->info->seesound); + } + } + } + else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) + ; + else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH) + { + if (player->cmomx || player->cmomy) + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->rmomx || player->rmomy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + } + else + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->mo->momx || player->mo->momy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + } + } + + if (!(player->pflags & PF_GLIDING)) + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); + player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); + player->secondjump = 0; + player->glidetime = 0; + player->climbing = 0; + player->powers[pw_tailsfly] = 0; + + if (player->pflags & PF_SHIELDABILITY) + { + player->pflags &= ~PF_SHIELDABILITY; + + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack. + { + if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound + S_StartSound(player->mo, sfx_s3k4c); + else // create a fire pattern on the ground + { + S_StartSound(player->mo, sfx_s3k47); + P_ElementalFire(player, true); + } + P_SetObjectMomZ(player->mo, + (player->mo->eflags & MFE_UNDERWATER) + ? 6*FRACUNIT/5 + : 5*FRACUNIT/2, + false); + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + player->mo->momx = player->mo->momy = 0; + clipmomz = false; + } + else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack. + { + P_DoBubbleBounce(player); + clipmomz = false; + } + } + } } return clipmomz; @@ -2964,22 +2969,19 @@ static void P_DoBubbleBreath(player_t *player) P_SetScale(bubble, bubble->destscale); } - if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS Super doesn't spawn flight bubbles - return; - // Tails stirs up the water while flying in it if (player->powers[pw_tailsfly] && (leveltime & 1) && player->charability != CA_SWIM) { - fixed_t radius = (3*player->mo->radius)>>1; + fixed_t radius = player->mo->radius; angle_t fa = ((leveltime%45)*FINEANGLES/8) & FINEMASK; fixed_t stirwaterx = FixedMul(FINECOSINE(fa),radius); fixed_t stirwatery = FixedMul(FINESINE(fa),radius); fixed_t stirwaterz; if (player->mo->eflags & MFE_VERTICALFLIP) - stirwaterz = player->mo->z + player->mo->height - FixedDiv(player->mo->height,3*FRACUNIT/2); + stirwaterz = player->mo->z + player->mo->height - (4<mo->z + FixedDiv(player->mo->height,3*FRACUNIT/2); + stirwaterz = player->mo->z + (4<mo->x + stirwaterx, @@ -4886,56 +4888,185 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) // static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { - mobj_t *lockon = NULL; + mobj_t *lockonthok = NULL, *lockonshield = NULL, *visual = NULL; if (player->pflags & PF_JUMPSTASIS) return; - if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) && (lockon = P_LookForEnemies(player, true, false))) + if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) && (lockonthok = P_LookForEnemies(player, true, false))) { if (P_IsLocalPlayer(player)) // Only display it on your own view. { - mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - P_SetTarget(&visual->target, lockon); + visual = P_SpawnMobj(lockonthok->x, lockonthok->y, lockonthok->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + P_SetTarget(&visual->target, lockonthok); } } - if (cmd->buttons & BT_USE && !(player->pflags & PF_JUMPDOWN) && !player->exiting && !P_PlayerInPain(player)) + ////////////////// + //SHIELD ACTIVES// + //& SUPER FLOAT!// + ////////////////// + + if ((player->pflags & PF_JUMPED) && !player->exiting && !P_PlayerInPain(player)) { - if (player->mo->tracer && player->powers[pw_carry] == CR_MACESPIN) - {} - else if (onground || player->climbing || (player->mo->tracer && player->powers[pw_carry])) - {} - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND - && !(player->pflags & PF_JUMPED) - && !(player->pflags & PF_USEDOWN)) - P_DoJumpShield(player); - else if (!(player->pflags & PF_SLIDING) && ((gametype != GT_CTF) || (!player->gotflag))) + if (onground || player->climbing || player->powers[pw_carry]) + ; + else if (gametype == GT_CTF && player->gotflag) + ; + else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously + ; + else if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_USEDOWN) + && ((!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX)))) // thokked is optional if you're bubblewrapped { + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) + { + if ((lockonshield = P_LookForEnemies(player, false, false))) + { + if (P_IsLocalPlayer(player)) // Only display it on your own view. + { + boolean dovis = true; + if (lockonshield == lockonthok) + { + if (leveltime & 2) + dovis = false; + else if (visual) + P_RemoveMobj(visual); + } + if (dovis) + { + visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + P_SetTarget(&visual->target, lockonshield); + P_SetMobjStateNF(visual, visual->info->spawnstate+1); + } + } + } + } + if (cmd->buttons & BT_USE // Spin button effects + #ifdef HAVE_BLUA + && !LUAh_ShieldSpecial(player) + #endif + ) + { + // Force stop + if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) + { + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->mo->momx = player->mo->momy = player->mo->momz = 0; + S_StartSound(player->mo, sfx_ngskid); + } + else + { + switch (player->powers[pw_shield] & SH_NOSTACK) + { + // Whirlwind jump/Thunder jump + case SH_WHIRLWIND: + case SH_THUNDERCOIN: + P_DoJumpShield(player); + break; + // Armageddon pow + case SH_ARMAGEDDON: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_BlackOw(player); + break; + // Attraction blast + case SH_ATTRACT: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->homing = 2; + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonshield)); + if (lockonshield) + { + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonshield->x, lockonshield->y); + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_s3k40); + player->homing = 3*TICRATE; + } + else + S_StartSound(player->mo, sfx_s3ka6); + break; + // Elemental stomp/Bubble bounce + case SH_ELEMENTAL: + case SH_BUBBLEWRAP: + { + boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL); + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + if (elem) + { + player->pflags |= PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + S_StartSound(player->mo, sfx_s3k43); + } + else + { + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_s3k44); + } + player->secondjump = 0; + player->mo->momx = player->mo->momy = 0; + P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); + break; + } + // Flame burst + case SH_FLAMEAURA: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); + player->drawangle = player->mo->angle; + S_StartSound(player->mo, sfx_s3k43); + default: + break; + } + } + } + } + else if ((cmd->buttons & BT_USE)) + { + if (!(player->pflags & PF_USEDOWN) && P_SuperReady(player)) + { + // If you can turn super and aren't already, + // and you don't have a shield, do it! + P_DoSuperTransformation(player, false); + } + else #ifdef HAVE_BLUA if (!LUAh_JumpSpinSpecial(player)) #endif switch (player->charability) { - case CA_TELEKINESIS: - if (player->pflags & PF_JUMPED) + case CA_THOK: + if (player->powers[pw_super]) // Super Sonic float { - if (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) + if ((player->speed > 5*player->mo->scale) // FixedMul(5<mo->scale), but scale is FRACUNIT-based + && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) { - P_Telekinesis(player, - -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) - FixedMul(384*FRACUNIT, player->mo->scale)); + if (player->panim != PA_RUN && player->panim != PA_WALK) + { + if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); + } + + player->mo->momz = 0; + player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); } } break; - case CA_AIRDRILL: - if (player->pflags & PF_JUMPED) + case CA_TELEKINESIS: + if (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || (player->charflags & SF_MULTIABILITY)) { - if (player->pflags & PF_THOKKED) // speed up falling down - { - if (player->secondjump < 42) - player->secondjump ++; - } + P_Telekinesis(player, + -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) + FixedMul(384*FRACUNIT, player->mo->scale)); + } + break; + case CA_TWINSPIN: + if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || player->charflags & SF_MULTIABILITY)) + { + player->pflags |= PF_THOKKED; + S_StartSound(player->mo, sfx_s3k42); + player->mo->frame = 0; + P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN); } break; default: @@ -4948,6 +5079,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { if (player->pflags & PF_JUMPED) { + if (cmd->buttons & BT_USE && player->secondjump < 42) // speed up falling down + player->secondjump++; + if (player->flyangle > 0 && player->pflags & PF_THOKKED) { player->flyangle--; @@ -4966,6 +5100,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } } + /////////////// + // CHARACTER // + // ABILITIES!// + /////////////// + if (cmd->buttons & BT_JUMP && !player->exiting && !P_PlayerInPain(player)) { #ifdef HAVE_BLUA @@ -5035,7 +5174,6 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } P_InstaThrust(player->mo, player->mo->angle, FixedMul(actionspd, player->mo->scale)); - player->drawangle = player->mo->angle; if (maptol & TOL_2D) { @@ -5050,11 +5188,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (player->charability == CA_HOMINGTHOK) { - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); - if (lockon) + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonthok)); + if (lockonthok) { P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonthok->x, lockonthok->y); player->homing = 3*TICRATE; } else @@ -5066,6 +5204,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_NOJUMPDAMAGE; } + player->drawangle = player->mo->angle; + if (player->mo->info->attacksound && !player->spectator) S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound @@ -5212,6 +5352,60 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_DoJumpShield(player); } + // HOMING option. + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT // Sonic 3D Blast. + && player->pflags & PF_SHIELDABILITY) + { + if (player->homing && player->mo->tracer) + { + if (!P_HomingAttack(player->mo, player->mo->tracer)) + { + P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); + if (player->mo->eflags & MFE_UNDERWATER) + player->mo->momz = FixedMul(player->mo->momz, FRACUNIT/3); + player->homing = 0; + } + } + + // If you're not jumping, then you obviously wouldn't be homing. + if (!(player->pflags & PF_JUMPED)) + player->homing = 0; + } + else if (player->charability == CA_HOMINGTHOK) // Sonic Adventure. + { + // If you've got a target, chase after it! + if (player->homing && player->mo->tracer) + { + P_SpawnThokMobj(player); + + // But if you don't, then stop homing. + if (!P_HomingAttack(player->mo, player->mo->tracer)) + { + if (player->mo->eflags & MFE_UNDERWATER) + P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); + else + P_SetObjectMomZ(player->mo, 10*FRACUNIT, false); + + player->mo->momx = player->mo->momy = player->homing = 0; + + if (player->mo->tracer->flags2 & MF2_FRET) + P_InstaThrust(player->mo, player->mo->angle, -(player->speed>>3)); + + if (!(player->mo->tracer->flags & MF_BOSS)) + player->pflags &= ~PF_THOKKED; + + P_SetPlayerMobjState(player->mo, S_PLAY_SPRING); + player->pflags |= PF_NOJUMPDAMAGE; + } + } + + // If you're not jumping, then you obviously wouldn't be homing. + if (!(player->pflags & PF_JUMPED)) + player->homing = 0; + } + else + player->homing = 0; + if (cmd->buttons & BT_JUMP) { player->pflags |= PF_JUMPDOWN; @@ -5238,7 +5432,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_JUMPDOWN; // Repeat abilities, but not double jump! - if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) + if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP && player->charability != CA_AIRDRILL) { if (player->charflags & SF_MULTIABILITY) { @@ -7891,7 +8085,7 @@ static void P_MovePlayer(player_t *player) } else if (player->pflags & PF_BOUNCING) { - if (!(player->pflags & PF_JUMPDOWN) || (onground && P_MobjFlip(player->mo)*player->mo->momz <= 0)) // If not holding the jump button OR on flat ground + if (!(player->pflags & PF_JUMPDOWN)) // If not holding the jump button { P_ResetPlayer(player); // down, stop bouncing. player->pflags |= PF_THOKKED; @@ -7991,16 +8185,22 @@ static void P_MovePlayer(player_t *player) if (P_MobjFlip(player->mo)*player->mo->momz < FixedMul(5*actionspd, player->mo->scale)) P_SetObjectMomZ(player->mo, actionspd/2, true); + P_SetPlayerMobjState(player->mo, player->mo->state->nextstate); + player->fly1--; } } // Tails Put-Put noise - if (player->charability == CA_FLY && player->bot != 1 && leveltime % 10 == 0 && !player->spectator) + if (player->charability == CA_FLY + && player->bot != 1 + && !(player->mo->eflags & MFE_UNDERWATER) + && leveltime % 10 == 0 + && !player->spectator) S_StartSound(player->mo, sfx_putput); // Descend - if (cmd->buttons & BT_USE && !(player->pflags & PF_STASIS) && !player->exiting) + if (cmd->buttons & BT_USE && !(player->pflags & PF_STASIS) && !player->exiting && !(player->mo->eflags & MFE_GOOWATER)) if (P_MobjFlip(player->mo)*player->mo->momz > -FixedMul(5*actionspd, player->mo->scale)) P_SetObjectMomZ(player->mo, -actionspd/2, true); @@ -8008,11 +8208,12 @@ static void P_MovePlayer(player_t *player) else { // Tails-gets-tired Stuff - if (player->panim == PA_ABILITY) + if (player->panim == PA_ABILITY && player->mo->state-states != S_PLAY_FLY_TIRED) P_SetPlayerMobjState(player->mo, S_PLAY_FLY_TIRED); if (player->charability == CA_FLY && (leveltime % 10 == 0) && player->mo->state-states == S_PLAY_FLY_TIRED + && !(player->mo->eflags & MFE_UNDERWATER) && !player->spectator) S_StartSound(player->mo, sfx_pudpud); } @@ -8117,178 +8318,6 @@ static void P_MovePlayer(player_t *player) localangle2 = player->mo->angle; } - ////////////////// - //SHIELD ACTIVES// - //& SUPER FLOAT!// - ////////////////// - - if (player->pflags & PF_JUMPED && !player->exiting && player->mo->health) - { - mobj_t *lockon = NULL; - if (!player->powers[pw_super] && player->powers[pw_shield] == SH_ATTRACT && !(player->pflags & PF_THOKKED)) - { - if ((lockon = P_LookForEnemies(player, false, false))) - { - if (P_IsLocalPlayer(player)) // Only display it on your own view. - { - mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - P_SetTarget(&visual->target, lockon); - P_SetMobjStateNF(visual, visual->info->spawnstate+1); - } - } - } - if (cmd->buttons & BT_USE) // Spin button effects - { - if (player->powers[pw_super]) // Super can't use shield actives, only passives - { - if ((player->charability == CA_THOK) // Super Sonic float - && (player->speed > 5*player->mo->scale) // FixedMul(5<mo->scale), but scale is FRACUNIT-based - && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) - { - if (player->panim != PA_RUN && player->panim != PA_WALK) - { - if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) - P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); - else - P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); - } - - player->mo->momz = 0; - player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); - } - } - else -#ifdef HAVE_BLUA - if (!LUAh_ShieldSpecial(player)) -#endif - { - if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously - && (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super - { - // Force stop - if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) - { - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->mo->momx = player->mo->momy = player->mo->momz = 0; - S_StartSound(player->mo, sfx_ngskid); - } - else - { - switch (player->powers[pw_shield] & SH_NOSTACK) - { - // Super! - case SH_NONE: - if (P_SuperReady(player)) - P_DoSuperTransformation(player, false); - break; - // Whirlwind jump/Thunder jump - case SH_WHIRLWIND: - case SH_THUNDERCOIN: - P_DoJumpShield(player); - break; - // Armageddon pow - case SH_ARMAGEDDON: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - P_BlackOw(player); - break; - // Attraction blast - case SH_ATTRACT: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->homing = 2; - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); - if (lockon) - { - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); - player->pflags &= ~PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_s3k40); - player->homing = 3*TICRATE; - } - else - S_StartSound(player->mo, sfx_s3ka6); - break; - // Elemental stomp/Bubble bounce - case SH_ELEMENTAL: - case SH_BUBBLEWRAP: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->pflags &= ~PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - player->secondjump = 0; - player->mo->momx = player->mo->momy = 0; - P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); - S_StartSound(player->mo, - ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) - ? sfx_s3k43 - : sfx_s3k44); - break; - // Flame burst - case SH_FLAMEAURA: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); - player->drawangle = player->mo->angle; - S_StartSound(player->mo, sfx_s3k43); - default: - break; - } - } - } - } - } - } - - // HOMING option. - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT // Sonic 3D Blast. - && player->pflags & PF_SHIELDABILITY) - { - if (player->homing && player->mo->tracer) - { - if (!P_HomingAttack(player->mo, player->mo->tracer)) - { - P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); - if (player->mo->eflags & MFE_UNDERWATER) - player->mo->momz = FixedMul(player->mo->momz, FRACUNIT/3); - player->homing = 0; - } - } - - // If you're not jumping, then you obviously wouldn't be homing. - if (!(player->pflags & PF_JUMPED)) - player->homing = 0; - } - else if (player->charability == CA_HOMINGTHOK) // Sonic Adventure. - { - // If you've got a target, chase after it! - if (player->homing && player->mo->tracer) - { - P_SpawnThokMobj(player); - - // But if you don't, then stop homing. - if (!P_HomingAttack(player->mo, player->mo->tracer)) - { - if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); - else - P_SetObjectMomZ(player->mo, 10*FRACUNIT, false); - - player->mo->momx = player->mo->momy = player->homing = 0; - - if (player->mo->tracer->flags2 & MF2_FRET) - P_InstaThrust(player->mo, player->mo->angle, -(player->speed>>3)); - - if (!(player->mo->tracer->flags & MF_BOSS)) - player->pflags &= ~PF_THOKKED; - - // P_SetPlayerMobjState(player->mo, S_PLAY_SPRING); -- Speed didn't like it, RIP - } - } - - // If you're not jumping, then you obviously wouldn't be homing. - if (!(player->pflags & PF_JUMPED)) - player->homing = 0; - } - else - player->homing = 0; - if (player->climbing == 1) P_DoClimbing(player); @@ -8332,7 +8361,7 @@ static void P_MovePlayer(player_t *player) // Less height while spinning. Good for spinning under things...? if ((player->mo->state == &states[player->mo->info->painstate]) - || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE && player->charflags & SF_NOJUMPSPIN)) + || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) || (player->pflags & PF_SPINNING) || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) @@ -8843,7 +8872,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) // Looks for something you can hit - Used for homing attack // If nonenemies is true, includes monitors and springs! // If bullet is true, you can look up and the distance is further, -// but your total angle span you can look is limited to compensate. +// but your total angle span you can look is limited to compensate. (Also, allows monitors.) // mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) { @@ -8853,6 +8882,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) const fixed_t maxdist = FixedMul((bullet ? RING_DIST*2 : RING_DIST), player->mo->scale); const angle_t span = (bullet ? ANG30 : ANGLE_90); fixed_t dist, closestdist = 0; + const mobjflag_t nonenemiesdisregard = (bullet ? 0 : MF_MONITOR)|MF_SPRING; for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { @@ -8872,7 +8902,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) if (mo->flags2 & MF2_FRET) continue; - if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING)) + if (!nonenemies && mo->flags & nonenemiesdisregard) continue; if (!bullet && mo->type == MT_DETON) // Don't be STUPID, Sonic! @@ -9027,19 +9057,22 @@ boolean P_GetLives(player_t *player) INT32 i, maxlivesplayer = -1, livescheck = 1; if (!(netgame || multiplayer) || (gametype != GT_COOP) - || (cv_cooplives.value == 1) || (player->lives == INFLIVES)) return true; - if ((cv_cooplives.value == 2 || cv_cooplives.value == 0) && player->lives > 0) - return true; - if (cv_cooplives.value == 0) // infinite lives { - player->lives++; + if (player->lives < 1) + player->lives = 1; return true; } + if ((cv_cooplives.value == 2 || cv_cooplives.value == 1) && player->lives > 0) + return true; + + if (cv_cooplives.value == 1) + return false; + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) @@ -9146,7 +9179,7 @@ static void P_DeathThink(player_t *player) // continue logic if (!(netgame || multiplayer) && player->lives <= 0) { - if (player->deadtimer > TICRATE && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && player->continues > 0) + if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && player->continues > 0) G_UseContinue(); else if (player->deadtimer >= gameovertics) G_UseContinue(); // Even if we don't have one this handles ending the game @@ -9170,12 +9203,12 @@ static void P_DeathThink(player_t *player) // Force respawn if idle for more than 30 seconds in shooter modes. if (player->deadtimer > 30*TICRATE && !G_PlatformGametype()) player->playerstate = PST_REBORN; - else if ((player->lives > 0 || j != MAXPLAYERS) && !G_IsSpecialStage(gamemap)) // Don't allow "click to respawn" in special stages! + else if ((player->lives > 0 || j != MAXPLAYERS) && !(!(netgame || multiplayer) && G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages! { if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) { P_ConsiderAllGone(); - if ((player->deadtimer > 5*TICRATE) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) + if ((player->deadtimer > TICRATE<<1) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) { //player->spectator = true; player->outofcoop = true; @@ -9191,16 +9224,11 @@ static void P_DeathThink(player_t *player) player->playerstate = PST_REBORN; else switch(gametype) { case GT_COOP: - if (player->deadtimer > TICRATE) - player->playerstate = PST_REBORN; - break; case GT_COMPETITION: + case GT_RACE: if (player->deadtimer > TICRATE) player->playerstate = PST_REBORN; break; - case GT_RACE: - player->playerstate = PST_REBORN; - break; default: if (player->deadtimer > cv_respawntime.value*TICRATE) player->playerstate = PST_REBORN; @@ -9209,7 +9237,7 @@ static void P_DeathThink(player_t *player) } // Single player auto respawn - if (!(netgame || multiplayer) && player->deadtimer > 5*TICRATE) + if (!(netgame || multiplayer) && player->deadtimer > TICRATE<<1) player->playerstate = PST_REBORN; } } @@ -9309,12 +9337,16 @@ consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_adjust = {"cam_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_height = {"cam2_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_adjust = {"cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; fixed_t t_cam_dist = -42; fixed_t t_cam_height = -42; @@ -9368,9 +9400,9 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled) { angle_t angle = 0, focusangle = 0, focusaiming = 0; - fixed_t x, y, z, dist, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; + fixed_t x, y, z, dist, distxy, distz, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight, slopez = 0; INT32 camrotate; - boolean camstill, cameranoclip; + boolean camstill, cameranoclip, camorbit; mobj_t *mo; subsector_t *newsubsec; fixed_t f1, f2; @@ -9451,6 +9483,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // force defaults because we have a camera look section camspeed = (INT32)(atof(cv_cam_speed.defaultvalue) * FRACUNIT); camstill = (!stricmp(cv_cam_still.defaultvalue, "off")) ? false : true; + camorbit = (!stricmp(cv_cam_orbit.defaultvalue, "off")) ? false : true; camrotate = atoi(cv_cam_rotate.defaultvalue); camdist = FixedMul((INT32)(atof(cv_cam_dist.defaultvalue) * FRACUNIT), mo->scale); camheight = FixedMul((INT32)(atof(cv_cam_height.defaultvalue) * FRACUNIT), FixedMul(player->camerascale, mo->scale)); @@ -9459,6 +9492,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { camspeed = cv_cam_speed.value; camstill = cv_cam_still.value; + camorbit = cv_cam_orbit.value; camrotate = cv_cam_rotate.value; camdist = FixedMul(cv_cam_dist.value, mo->scale); camheight = FixedMul(cv_cam_height.value, FixedMul(player->camerascale, mo->scale)); @@ -9467,6 +9501,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { camspeed = cv_cam2_speed.value; camstill = cv_cam2_still.value; + camorbit = cv_cam2_orbit.value; camrotate = cv_cam2_rotate.value; camdist = FixedMul(cv_cam2_dist.value, mo->scale); camheight = FixedMul(cv_cam2_height.value, FixedMul(player->camerascale, mo->scale)); @@ -9576,13 +9611,50 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall dist <<= 1; } + + checkdist = (dist = FixedMul(dist, player->camerascale)); if (checkdist < 128*FRACUNIT) checkdist = 128*FRACUNIT; - x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); - y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); + if (!(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) // This block here is like 90% Lach's work, thanks bud + { + if ((thiscam == &camera && cv_cam_adjust.value) || (thiscam == &camera2 && cv_cam2_adjust.value)) + { + if (!(mo->eflags & MFE_JUSTHITFLOOR) && (P_IsObjectOnGround(mo)) // Check that player is grounded + && thiscam->ceilingz - thiscam->floorz >= P_GetPlayerHeight(player)) // Check that camera's sector is large enough for the player to fit into, at least + { + if (mo->eflags & MFE_VERTICALFLIP) // if player is upside-down + { + //z = min(z, thiscam->ceilingz); // solution 1: change new z coordinate to be at LEAST its ground height + slopez += min(thiscam->ceilingz - mo->z, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player + } + else // player is not upside-down + { + //z = max(z, thiscam->floorz); // solution 1: change new z coordinate to be at LEAST its ground height + slopez += max(thiscam->floorz - mo->z - mo->height, 0); // solution 2: change new z coordinate by the difference between camera's ground and top of player + } + } + } + } + + if (camorbit) //Sev here, I'm guessing this is where orbital cam lives + { + if (rendermode == render_opengl) + distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); + else + distxy = dist; + distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)) + slopez; + } + else + { + distxy = dist; + distz = slopez; + } + + x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); + y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), distxy); #if 0 if (twodlevel || (mo->flags2 & MF2_TWOD)) @@ -9619,9 +9691,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall pviewheight = FixedMul(41*player->height/48, mo->scale); if (mo->eflags & MFE_VERTICALFLIP) - z = mo->z + mo->height - pviewheight - camheight; + z = mo->z + mo->height - pviewheight - camheight + distz; else - z = mo->z + pviewheight + camheight; + z = mo->z + pviewheight + camheight + distz; // move camera down to move under lower ceilings newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); @@ -9934,6 +10006,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); + } boolean P_SpectatorJoinGame(player_t *player) @@ -10585,7 +10658,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) angle_t horizangle = player->drawangle; fixed_t zoffs = 0; fixed_t backwards = -1*FRACUNIT; - boolean doroll = (player->panim == PA_ROLL || player->panim == PA_JUMP); + boolean doswim = (player->panim == PA_ABILITY && (player->mo->eflags & MFE_UNDERWATER)); + boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || doswim); angle_t rollangle; boolean panimchange; INT32 ticnum = 0; @@ -10612,17 +10686,25 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) if (testval < FRACUNIT) testval = FRACUNIT; } - if (smilesonground && !player->mo->reactiontime) + + if (doswim) + zdist = player->mo->momz<<1; + else if (smilesonground && !player->mo->reactiontime) zdist = (player->mo->z - tails->threshold); else zdist = player->mo->momz; + rollangle = R_PointToAngle2(0, 0, testval, -P_MobjFlip(player->mo)*zdist); - zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); - backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); + + if (!doswim) + { + zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); + backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); + } } else if (player->panim == PA_RUN) backwards = -5*FRACUNIT; - else if (player->panim == PA_SPRING) + else if (player->panim == PA_SPRING || player->panim == PA_JUMP) { zoffs += 4*FRACUNIT; backwards /= 2; @@ -10644,7 +10726,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) zoffs = -7*FRACUNIT; backwards = -9*FRACUNIT; } - else if (player->mo->sprite2 == SPR2_FLY || player->mo->sprite2 == SPR2_TIRE) + else if (player->panim == PA_ABILITY) backwards = -5*FRACUNIT; // sprite... @@ -10661,7 +10743,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else chosenstate = S_TAILSOVERLAY_0DEGREES; } - else if (player->panim == PA_SPRING) + else if (player->panim == PA_SPRING || player->panim == PA_JUMP) chosenstate = S_TAILSOVERLAY_MINUS60DEGREES; else if (player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) chosenstate = S_TAILSOVERLAY_PLUS60DEGREES; @@ -10684,6 +10766,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) } else if (player->mo->sprite2 == SPR2_FLY) chosenstate = S_TAILSOVERLAY_FLY; + else if (player->mo->sprite2 == SPR2_SWIM) + chosenstate = S_TAILSOVERLAY_FLY; else if (player->mo->sprite2 == SPR2_TIRE) chosenstate = S_TAILSOVERLAY_TIRE; else if (player->panim == PA_ABILITY2) @@ -10709,8 +10793,10 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) } } +#if 0 if (player->fly1 != 0 && player->powers[pw_tailsfly] != 0 && !smilesonground) P_SetMobjState(tails, chosenstate); +#endif // animation... if (player->panim == PA_SPRING || player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) @@ -10725,7 +10811,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) else if (player->mo->state-states == S_PLAY_GASP) tails->tics = -1; else if (player->mo->sprite2 == SPR2_TIRE) - ticnum = 4; + ticnum = (doswim ? 2 : 4); else if (player->panim != PA_IDLE) ticnum = player->mo->tics; @@ -10948,7 +11034,8 @@ void P_PlayerThink(player_t *player) if (player->exiting == 2 || countdown2 == 2) { - if (cv_playersforexit.value) // Count to be sure everyone's exited + UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); + if (numneeded) // Count to be sure everyone's exited { INT32 i, total = 0, exiting = 0; @@ -10964,7 +11051,7 @@ void P_PlayerThink(player_t *player) exiting++; } - if (!total || ((4*exiting)/total) >= cv_playersforexit.value) + if (!total || ((4*exiting)/total) >= numneeded) { if (server) SendNetXCmd(XD_EXITLEVEL, NULL, 0); @@ -11011,8 +11098,6 @@ void P_PlayerThink(player_t *player) { if (gametype != GT_COOP) player->score = 0; - player->mo->health = 1; - player->rings = player->spheres = 0; } else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP) { @@ -11252,8 +11337,8 @@ void P_PlayerThink(player_t *player) { boolean currentlyonground = P_IsObjectOnGround(player->mo); - if (!player->powers[pw_carry] - && ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) + if (!player->powers[pw_carry] && !player->powers[pw_nocontrol] + && ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE|PF_STASIS)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) && !(cmd->forwardmove || cmd->sidemove) && (player->rmomx || player->rmomy) && (!player->capsule || (player->capsule->reactiontime != (player-players)+1))) @@ -11264,7 +11349,7 @@ void P_PlayerThink(player_t *player) if (!currentlyonground) acceleration /= 2; // fake skidding! see P_SkidStuff for reference on conditionals - else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed/2, player->mo->scale)) + else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed, player->mo->scale)) // modified from player->runspeed/2 'cuz the skid was just TOO frequent ngl { if (player->mo->state-states != S_PLAY_SKID) P_SetPlayerMobjState(player->mo, S_PLAY_SKID); @@ -11752,7 +11837,7 @@ void P_PlayerAfterThink(player_t *player) { if ((tails->z + tails->height + player->mo->height + FixedMul(FRACUNIT, player->mo->scale)) <= tails->ceilingz && (tails->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame - player->mo->z = tails->z + tails->height + FixedMul(FRACUNIT, player->mo->scale); + player->mo->z = tails->z + tails->height + 12*player->mo->scale; else player->powers[pw_carry] = CR_NONE; } @@ -11760,7 +11845,7 @@ void P_PlayerAfterThink(player_t *player) { if ((tails->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale)) >= tails->floorz && !(tails->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame - player->mo->z = tails->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale); + player->mo->z = tails->z - player->mo->height - 12*player->mo->scale; else player->powers[pw_carry] = CR_NONE; } @@ -11769,7 +11854,7 @@ void P_PlayerAfterThink(player_t *player) player->powers[pw_carry] = CR_NONE; else { - P_TryMove(player->mo, tails->x, tails->y, true); + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); player->mo->momx = tails->momx; player->mo->momy = tails->momy; player->mo->momz = tails->momz; @@ -11795,6 +11880,8 @@ void P_PlayerAfterThink(player_t *player) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + if ((tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) + tails->player->powers[pw_tailsfly] = 0; } else P_SetTarget(&player->mo->tracer, NULL); diff --git a/src/r_bsp.c b/src/r_bsp.c index d521d9f4d..23e751420 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1088,9 +1088,9 @@ static void R_Subsector(size_t num) { light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic, - polysec->lightlevel, polysec->floor_xoffs, polysec->floor_yoffs, + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs, polysec->floorpic_angle-po->angle, - NULL, NULL, po + (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif @@ -1115,10 +1115,10 @@ static void R_Subsector(size_t num) && polysec->ceilingheight <= ceilingcenterz && (viewz > polysec->ceilingheight)) { - light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight); + light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, - polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, - NULL, NULL, po + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, + (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif diff --git a/src/r_data.c b/src/r_data.c index 6889bddde..8594c8595 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -23,6 +23,7 @@ #include "z_zone.h" #include "p_setup.h" // levelflats #include "v_video.h" // pMasterPalette +#include "byteptr.h" #include "dehacked.h" #ifdef _WIN32 @@ -40,6 +41,28 @@ #include #endif +#ifdef HAVE_PNG + +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include "png.h" +#ifndef PNG_READ_SUPPORTED +#undef HAVE_PNG +#endif +#endif + // // Texture definition. // Each texture is composed of one or more patches, @@ -98,12 +121,11 @@ INT32 numtextures = 0; // total number of textures found, // size of following tables texture_t **textures = NULL; +textureflat_t *texflats = NULL; static UINT32 **texturecolumnofs; // column offset lookup table for each texture static UINT8 **texturecache; // graphics data for each generated full-size texture -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -INT32 *texturewidthmask; - +INT32 *texturewidth; fixed_t *textureheight; // needed for texture pegging INT32 *texturetranslation; @@ -220,15 +242,110 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex } } +UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) +{ + RGBA_t output; + if (style == AST_TRANSLUCENT) + { + if (alpha == 0) + output.rgba = background.rgba; + else if (alpha == 0xFF) + output.rgba = foreground.rgba; + else if (alpha < 0xFF) + { + UINT8 beta = (0xFF - alpha); + output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF; + output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF; + output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF; + } + // write foreground pixel alpha + // if there's no pixel in here + if (!background.rgba) + output.s.alpha = foreground.s.alpha; + } +#define clamp(c) max(min(c, 0xFF), 0x00); + else + { + float falpha = ((float)alpha / 256.0f); + float fr = ((float)foreground.s.red * falpha); + float fg = ((float)foreground.s.green * falpha); + float fb = ((float)foreground.s.blue * falpha); + if (style == AST_ADD) + { + output.s.red = clamp((int)(background.s.red + fr)); + output.s.green = clamp((int)(background.s.green + fg)); + output.s.blue = clamp((int)(background.s.blue + fb)); + } + else if (style == AST_SUBTRACT) + { + output.s.red = clamp((int)(background.s.red - fr)); + output.s.green = clamp((int)(background.s.green - fg)); + output.s.blue = clamp((int)(background.s.blue - fb)); + } + else if (style == AST_REVERSESUBTRACT) + { + output.s.red = clamp((int)((-background.s.red) + fr)); + output.s.green = clamp((int)((-background.s.green) + fg)); + output.s.blue = clamp((int)((-background.s.blue) + fb)); + } + else if (style == AST_MODULATE) + { + fr = ((float)foreground.s.red / 256.0f); + fg = ((float)foreground.s.green / 256.0f); + fb = ((float)foreground.s.blue / 256.0f); + output.s.red = clamp((int)(background.s.red * fr)); + output.s.green = clamp((int)(background.s.green * fg)); + output.s.blue = clamp((int)(background.s.blue * fb)); + } + // just copy the pixel + else if (style == AST_COPY) + output.rgba = foreground.rgba; + + output.s.alpha = 0xFF; + return output.rgba; + } +#undef clamp + return 0; +} + +UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) +{ + if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? + { + UINT8 *mytransmap; + if (alpha < 255/11) // Is the patch way too translucent? Don't render then. + return background; + // The equation's not exact but it works as intended. I'll call it a day for now. + mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); + if (background != 0xFF) + return *(mytransmap + (background<<8) + foreground); + } + // just copy the pixel + else if (style == AST_COPY) + return foreground; + // use ASTBlendPixel for all other blend modes + // and find the nearest colour in the palette + else if (style != AST_TRANSLUCENT) + { + RGBA_t texel; + RGBA_t bg = V_GetColor(background); + RGBA_t fg = V_GetColor(foreground); + texel.rgba = ASTBlendPixel(bg, fg, style, alpha); + return NearestColor(texel.s.red, texel.s.green, texel.s.blue); + } + // fallback if all above fails, somehow + // return the background pixel + return background; +} + // -// R_DrawTransColumnInCache +// R_DrawBlendColumnInCache // Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()). // -static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; - UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now. INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; @@ -258,7 +375,8 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa if (count > 0) { for (; dest < cache + position + count; source++, dest++) - if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source)); + if (*dest != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -269,11 +387,10 @@ static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpa // R_DrawTransColumnInCache // Similar to the one above except that the column is inverted. // -static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; - UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now. INT32 topdelta, prevdelta = -1; INT32 originy = originPatch->originy; @@ -302,7 +419,8 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache if (count > 0) { for (; dest < cache + position + count; --source, dest++) - if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source)); + if (*dest != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -315,7 +433,7 @@ static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache // Allocate space for full size texture, either single patch or 'composite' // Build the full textures from patches. // The texture caching system is a little more hungry of memory, but has -// been simplified for the sake of highcolor, dynamic ligthing, & speed. +// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed. // // This is not optimised, but it's supposed to be executed only once // per level, when enough memory is available. @@ -332,6 +450,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) column_t *patchcol; UINT32 *colofs; + UINT16 wadnum; + lumpnum_t lumpnum; + size_t lumplength; + I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; I_Assert(texture != NULL); @@ -346,7 +468,19 @@ static UINT8 *R_GenerateTexture(size_t texnum) { boolean holey = false; patch = texture->patches; - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + { + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); + goto multipatch; + } +#endif // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) @@ -376,7 +510,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) { texture->holes = true; texture->flip = patch->flip; - blocksize = W_LumpLengthPwad(patch->wad, patch->lump); + blocksize = lumplength; block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function &texturecache[texnum]); M_Memcpy(block, realpatch, blocksize); @@ -403,6 +537,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) } // multi-patch textures (or 'composite') +#ifndef NO_PNG_LUMPS + multipatch: +#endif texture->holes = false; texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); @@ -422,18 +559,20 @@ static UINT8 *R_GenerateTexture(size_t texnum) for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. - if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? - { - if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then. - continue; - ColumnDrawerPointer = (patch->flip & 2) ? R_DrawTransFlippedColumnInCache : R_DrawTransColumnInCache; - } + if (patch->style != AST_COPY) + ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; else - { ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; - } - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); +#endif + x1 = patch->originx; width = SHORT(realpatch->width); height = SHORT(realpatch->height); @@ -509,10 +648,14 @@ void R_CheckTextureCache(INT32 tex) UINT8 *R_GetColumn(fixed_t tex, INT32 col) { UINT8 *data; + INT32 width = texturewidth[tex]; + + if (width & (width - 1)) + col = (UINT32)col % width; + else + col &= (width - 1); - col &= texturewidthmask[tex]; data = texturecache[tex]; - if (!data) data = R_GenerateTexture(tex); @@ -550,7 +693,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); #define TX_END "TX_END" void R_LoadTextures(void) { - INT32 i, k, w; + INT32 i, w; UINT16 j; UINT16 texstart, texend, texturesLumpPos; patch_t *patchlump; @@ -567,6 +710,7 @@ void R_LoadTextures(void) } Z_Free(texturetranslation); Z_Free(textures); + Z_Free(texflats); } // Load patches and textures. @@ -627,15 +771,16 @@ void R_LoadTextures(void) // Allocate memory and initialize to 0 for all the textures we are initialising. // There are actually 5 buffers allocated in one for convenience. textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); + texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL); // Allocate texture column offset table. texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); // Allocate texture referencing cache. - texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); - // Allocate texture width mask table. - texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); - // Allocate texture height mask table. - textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); + texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); + // Allocate texture width table. + texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); + // Allocate texture height table. + textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); // Create translation table for global animation. texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); @@ -673,20 +818,39 @@ void R_LoadTextures(void) // Work through each lump between the markers in the WAD. for (j = 0; j < (texend - texstart); j++) { + UINT16 wadnum = (UINT16)w; + lumpnum_t lumpnum = texstart + j; + size_t lumplength; + if (wadfiles[w]->type == RET_PK3) { - if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder + if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder continue; // If it is then SKIP IT } - patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE); + + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name)); - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)patchlump, lumplength)) + { + INT16 width, height; + R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength); + texture->width = width; + texture->height = height; + } + else +#endif + { + texture->width = SHORT(patchlump->width); + texture->height = SHORT(patchlump->height); + } texture->patchcount = 1; texture->holes = false; texture->flip = 0; @@ -701,11 +865,7 @@ void R_LoadTextures(void) Z_Unlock(patchlump); - k = 1; - while (k << 1 <= texture->width) - k <<= 1; - - texturewidthmask[i] = k - 1; + texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; } @@ -848,8 +1008,16 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) { Z_Free(texturesToken); texturesToken = M_GetToken(NULL); - if(stricmp(texturesToken, "TRANSLUCENT")==0) + if (stricmp(texturesToken, "TRANSLUCENT")==0) style = AST_TRANSLUCENT; + else if (stricmp(texturesToken, "ADD")==0) + style = AST_ADD; + else if (stricmp(texturesToken, "SUBTRACT")==0) + style = AST_SUBTRACT; + else if (stricmp(texturesToken, "REVERSESUBTRACT")==0) + style = AST_REVERSESUBTRACT; + else if (stricmp(texturesToken, "MODULATE")==0) + style = AST_MODULATE; } else if (stricmp(texturesToken, "FLIPX")==0) flip |= 1; @@ -1097,7 +1265,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) { numTexturesInLump++; Z_Free(texturesToken); @@ -1105,7 +1273,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } @@ -1146,21 +1314,21 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) { Z_Free(texturesToken); // Get the new texture newTexture = R_ParseTexture(true); // Store the new texture textures[*texindex] = newTexture; - texturewidthmask[*texindex] = newTexture->width - 1; + texturewidth[*texindex] = newTexture->width; textureheight[*texindex] = newTexture->height << FRACBITS; // Increment i back in R_LoadTextures() (*texindex)++; } else { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); } texturesToken = M_GetToken(NULL); } @@ -1267,6 +1435,41 @@ lumpnum_t R_GetFlatNumForName(const char *name) lump = LUMPERROR; } + // Detect textures + if (lump == LUMPERROR) + { + // Scan wad files backwards so patched textures take preference. + for (i = numwadfiles - 1; i >= 0; i--) + { + switch (wadfiles[i]->type) + { + case RET_WAD: + if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) + continue; + break; + case RET_PK3: + if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) + continue; + break; + default: + continue; + } + + // Now find lump with specified name in that range. + lump = W_CheckNumForNamePwad(name, (UINT16)i, start); + if (lump < end) + { + lump += (i<<16); // found it, in our constraints + break; + } + lump = LUMPERROR; + } + } + if (lump == LUMPERROR) { if (strcmp(name, SKYFLATNAME)) @@ -1615,7 +1818,6 @@ extracolormap_t *R_ColormapForName(char *name) // static double deltas[256][3], map[256][3]; -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) @@ -2027,7 +2229,7 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex // Thanks to quake2 source! // utils3/qdata/images.c -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; @@ -2306,3 +2508,535 @@ void R_PrecacheLevel(void) "texturememory: %s k\n" "spritememory: %s k\n", sizeu1(flatmemory>>10), sizeu2(texturememory>>10), sizeu3(spritememory>>10)); } + +// https://github.com/coelckers/prboom-plus/blob/master/prboom2/src/r_patch.c#L350 +boolean R_CheckIfPatch(lumpnum_t lump) +{ + size_t size; + INT16 width, height; + patch_t *patch; + boolean result; + + size = W_LumpLength(lump); + + // minimum length of a valid Doom patch + if (size < 13) + return false; + + patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); + + width = SHORT(patch->width); + height = SHORT(patch->height); + + result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(size / 4)); + + if (result) + { + // The dimensions seem like they might be valid for a patch, so + // check the column directory for extra security. All columns + // must begin after the column directory, and none of them must + // point past the end of the patch. + INT16 x; + + for (x = 0; x < width; x++) + { + UINT32 ofs = LONG(patch->columnofs[x]); + + // Need one byte for an empty column (but there's patches that don't know that!) + if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) + { + result = false; + break; + } + } + } + + return result; +} + +void R_PatchToFlat(patch_t *patch, UINT8 *flat) +{ + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = flat; + deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); + + for (col = 0; col < SHORT(patch->width); col++, desttop++) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col])); + + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * SHORT(patch->width)); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + *dest = source[ofs]; + dest += SHORT(patch->width); + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } +} + +#ifndef NO_PNG_LUMPS +boolean R_IsLumpPNG(const UINT8 *d, size_t s) +{ + if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ + return false; + // Check for PNG file signature using memcmp + // As it may be faster on CPUs with slow unaligned memory access + // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature + return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0); +} + +#ifdef HAVE_PNG + +#if PNG_LIBPNG_VER_DLLNUM < 14 +typedef PNG_CONST png_byte *png_const_bytep; +#endif +typedef struct { + png_const_bytep buffer; + png_uint_32 bufsize; + png_uint_32 current_pos; +} png_io_t; + +static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_io_t *f = png_get_io_ptr(png_ptr); + if (length > (f->bufsize - f->current_pos)) + png_error(png_ptr, "PNG_IOReader: buffer overrun"); + memcpy(data, f->buffer + f->current_pos, length); + f->current_pos += length; +} + +typedef struct +{ + char name[4]; + void *data; + size_t size; +} png_chunk_t; + +static png_byte *chunkname = NULL; +static png_chunk_t chunk; + +static int PNG_ChunkReader(png_structp png_ptr, png_unknown_chunkp chonk) +{ + (void)png_ptr; + if (!memcmp(chonk->name, chunkname, 4)) + { + memcpy(chunk.name, chonk->name, 4); + chunk.size = chonk->size; + chunk.data = Z_Malloc(chunk.size, PU_STATIC, NULL); + memcpy(chunk.data, chonk->data, chunk.size); + return 1; + } + return 0; +} + +static void PNG_error(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); + //I_Error("libpng error at %p: %s", PNG, pngtext); +} + +static void PNG_warn(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); +} + +static png_bytep *PNG_Read(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 width, height; + int bit_depth, color_type; + png_uint_32 y; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_io_t png_io; + png_bytep *row_pointers; + + png_byte grAb_chunk[5] = {'g', 'r', 'A', 'b', (png_byte)'\0'}; + png_voidp *user_chunk_ptr; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); + if (!png_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); + return NULL; + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return NULL; + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + return NULL; + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + // set our own read_function + png_io.buffer = (png_const_bytep)png; + png_io.bufsize = size; + png_io.current_pos = 0; + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + + memset(&chunk, 0x00, sizeof(png_chunk_t)); + chunkname = grAb_chunk; // I want to read a grAb chunk + + user_chunk_ptr = png_get_user_chunk_ptr(png_ptr); + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader); + png_set_keep_unknown_chunks(png_ptr, 2, chunkname, 1); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + else if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA) + { +#if PNG_LIBPNG_VER < 10207 + png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); +#else + png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); +#endif + } + + png_read_update_info(png_ptr, png_info_ptr); + + // Read the image + row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); + for (y = 0; y < height; y++) + row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr)); + png_read_image(png_ptr, row_pointers); + + // Read grAB chunk + if ((topoffset || leftoffset) && (chunk.data != NULL)) + { + INT32 *offsets = (INT32 *)chunk.data; + // read left offset + if (leftoffset != NULL) + *leftoffset = (INT16)BIGENDIAN_LONG(*offsets); + offsets++; + // read top offset + if (topoffset != NULL) + *topoffset = (INT16)BIGENDIAN_LONG(*offsets); + } + + // bye + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + if (chunk.data) + Z_Free(chunk.data); + + *w = (INT32)width; + *h = (INT32)height; + return row_pointers; +} + +// Convert a PNG to a raw image. +static UINT8 *PNG_RawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) +{ + UINT8 *flat; + png_uint_32 x, y; + png_bytep *row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, size); + png_uint_32 width = *w, height = *h; + + if (!row_pointers) + I_Error("PNG_RawConvert: conversion failed"); + + // Convert the image to 8bpp + flat = Z_Malloc(width * height, PU_LEVEL, NULL); + memset(flat, TRANSPARENTPIXEL, width * height); + for (y = 0; y < height; y++) + { + png_bytep row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + if ((UINT8)px[3]) + flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]); + } + } + free(row_pointers); + + return flat; +} + +// Convert a PNG to a flat. +UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size) +{ + return PNG_RawConvert(png, &levelflat->width, &levelflat->height, NULL, NULL, size); +} + +// Convert a PNG to a patch. +static unsigned char imgbuf[1<<26]; +patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency) +{ + UINT16 width, height; + INT16 topoffset = 0, leftoffset = 0; + UINT8 *raw = PNG_RawConvert(png, &width, &height, &topoffset, &leftoffset, size); + + UINT32 x, y; + UINT8 *img; + UINT8 *imgptr = imgbuf; + UINT8 *colpointers, *startofspan; + + if (!raw) + I_Error("R_PNGToPatch: conversion failed"); + + // Write image size and offset + WRITEINT16(imgptr, width); + WRITEINT16(imgptr, height); + WRITEINT16(imgptr, leftoffset); + WRITEINT16(imgptr, topoffset); + + // Leave placeholder to column pointers + colpointers = imgptr; + imgptr += width*4; + + // Write columns + for (x = 0; x < width; x++) + { + int lastStartY = 0; + int spanSize = 0; + startofspan = NULL; + + //printf("%d ", x); + // Write column pointer (@TODO may be wrong) + WRITEINT32(colpointers, imgptr - imgbuf); + + // Write pixels + for (y = 0; y < height; y++) + { + UINT8 paletteIndex = raw[((y * width) + x)]; + boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true; + + // End span if we have a transparent pixel + if (!opaque) + { + if (startofspan) + WRITEUINT8(imgptr, 0); + startofspan = NULL; + continue; + } + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = y; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITEUINT8(imgptr, 0); + + if (y > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + writeY -= 254; + } + } + + startofspan = imgptr; + WRITEUINT8(imgptr, writeY);///@TODO calculate starting y pos + imgptr += 2; + spanSize = 0; + + lastStartY = y; + } + + // Write the pixel + WRITEUINT8(imgptr, paletteIndex); + spanSize++; + startofspan[1] = spanSize; + } + + if (startofspan) + WRITEUINT8(imgptr, 0); + + WRITEUINT8(imgptr, 0xFF); + } + + size = imgptr-imgbuf; + img = Z_Malloc(size, PU_STATIC, NULL); + memcpy(img, imgbuf, size); + + Z_Free(raw); + + if (destsize != NULL) + *destsize = size; + return (patch_t *)img; +} + +boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 w, h; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_io_t png_io; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + PNG_error, PNG_warn); + if (!png_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); + return false; + } + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return false; + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + return false; + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + // set our own read_function + png_io.buffer = (png_bytep)png; + png_io.bufsize = size; + png_io.current_pos = 0; + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + + png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type, + NULL, NULL, NULL); + + // okay done. stop. + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + + *width = (INT32)w; + *height = (INT32)h; + return true; +} +#endif +#endif + +void R_TextureToFlat(size_t tex, UINT8 *flat) +{ + texture_t *texture = textures[tex]; + + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = flat; + deststop = desttop + (texture->width * texture->height); + + for (col = 0; col < texture->width; col++, desttop++) + { + column = (column_t *)R_GetColumn(tex, col); + if (!texture->holes) + { + dest = desttop; + source = (UINT8 *)(column); + for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + } + else + { + INT32 topdelta, prevdelta = -1; + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * texture->width); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + } +} diff --git a/src/r_data.h b/src/r_data.h index b6b0a16a1..c2fd284ff 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -16,13 +16,19 @@ #include "r_defs.h" #include "r_state.h" +#include "p_setup.h" // levelflats #ifdef __GNUG__ #pragma interface #endif // Possible alpha types for a patch. -enum patchalphastyle {AST_COPY, AST_TRANSLUCENT}; // , AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; +enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; + +UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); +UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha); + +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); // moved here for r_sky.c (texpatch_t is used) @@ -55,12 +61,17 @@ typedef struct texpatch_t patches[0]; } texture_t; +typedef struct +{ + UINT8 *flat; + INT16 width, height; +} textureflat_t; + // all loaded and prepared textures from the start of the game extern texture_t **textures; +extern textureflat_t *texflats; -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -extern INT32 *texturewidthmask; - +extern INT32 *texturewidth; extern fixed_t *textureheight; // needed for texture pegging extern INT16 color8to16[256]; // remap color index to highcolor @@ -88,7 +99,6 @@ void R_PrecacheLevel(void); // Floor/ceiling opaque texture tiles, // lookup by name. For animation? lumpnum_t R_GetFlatNumForName(const char *name); -#define R_FlatNumForName(x) R_GetFlatNumForName(x) // Called by P_Ticker for switches and animations, // returns the texture number for the texture name. @@ -148,6 +158,20 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap); #define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b)) #define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a)) +boolean R_CheckIfPatch(lumpnum_t lump); +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); + +void R_PatchToFlat(patch_t *patch, UINT8 *flat); +void R_TextureToFlat(size_t tex, UINT8 *flat); + +#ifndef NO_PNG_LUMPS +boolean R_IsLumpPNG(const UINT8 *d, size_t s); + +UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size); +patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency); +boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size); +#endif + extern INT32 numtextures; #endif diff --git a/src/r_draw.c b/src/r_draw.c index d8b720caf..1754403c4 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -99,6 +99,8 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; +UINT16 ds_flatwidth, ds_flatheight; +boolean ds_powersoftwo; UINT8 *ds_source; // start of a 64*64 tile image UINT8 *ds_transmap; // one of the translucency tables @@ -557,9 +559,16 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U // White! if (skinnum == TC_BOSS) - dest_colormap[31] = 0; + { + for (i = 0; i < 16; i++) + dest_colormap[31-i] = i; + } else if (skinnum == TC_METALSONIC) - dest_colormap[159] = 0; + { + for (i = 0; i < 6; i++) + dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i]; + dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0; + } return; } else if (color == SKINCOLOR_NONE) diff --git a/src/r_draw.h b/src/r_draw.h index 82498eb11..3c1429722 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -57,7 +57,9 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; -extern UINT8 *ds_source; // start of a 64*64 tile image +extern UINT16 ds_flatwidth, ds_flatheight; +extern boolean ds_powersoftwo; +extern UINT8 *ds_source; extern UINT8 *ds_transmap; #ifdef ESLOPE @@ -128,6 +130,8 @@ void R_FillBackScreen(void); void R_DrawViewBorder(void); #endif +#define TRANSPARENTPIXEL 255 + // ----------------- // 8bpp DRAWING CODE // ----------------- @@ -169,6 +173,13 @@ void R_DrawFogSpan_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void); + +extern INT32 ds_bgofs; +extern INT32 ds_waterofs; +#endif + // ------------------ // 16bpp DRAWING CODE // ------------------ diff --git a/src/r_draw8.c b/src/r_draw8.c index 8a2d37fb3..77406f83c 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -105,8 +105,6 @@ void R_DrawColumn_8(void) } } -#define TRANSPARENTPIXEL 255 - void R_Draw2sMultiPatchColumn_8(void) { INT32 count; @@ -543,16 +541,19 @@ void R_DrawTranslatedColumn_8(void) */ void R_DrawSpan_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -561,62 +562,88 @@ void R_DrawSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; if (dest+8 > deststop) return; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - dest[1] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - dest[2] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - dest[3] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + *dest++ = colormap[source[((y * ds_flatwidth) + x)]]; + xposition += xstep; + yposition += ystep; + } } - while (count-- && dest <= deststop) + else { - *dest++ = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; - xposition += xstep; - yposition += ystep; + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[1] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[2] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[3] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[4] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[5] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[6] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest[7] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; + xposition += xstep; + yposition += ystep; + } } } @@ -697,7 +724,24 @@ void R_DrawTiltedSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; iz += ds_sz.x; uz += ds_su.x; @@ -734,7 +778,24 @@ void R_DrawTiltedSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -750,7 +811,24 @@ void R_DrawTiltedSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; } else { @@ -771,7 +849,24 @@ void R_DrawTiltedSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + else + *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; u += stepu; v += stepv; @@ -832,7 +927,24 @@ void R_DrawTiltedTranslucentSpan_8(void) v = (INT64)(vz*z) + viewy; colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; iz += ds_sz.x; uz += ds_su.x; @@ -869,7 +981,24 @@ void R_DrawTiltedTranslucentSpan_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -885,7 +1014,24 @@ void R_DrawTiltedTranslucentSpan_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); } else { @@ -906,7 +1052,24 @@ void R_DrawTiltedTranslucentSpan_8(void) for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + else + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; u += stepu; v += stepv; @@ -967,9 +1130,28 @@ void R_DrawTiltedSplat_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) *dest = colormap[val]; + dest++; iz += ds_sz.x; uz += ds_su.x; @@ -1006,7 +1188,24 @@ void R_DrawTiltedSplat_8(void) for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1024,7 +1223,24 @@ void R_DrawTiltedSplat_8(void) u = (INT64)(startu); v = (INT64)(startv); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; } @@ -1048,6 +1264,24 @@ void R_DrawTiltedSplat_8(void) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (!ds_powersoftwo) + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + else + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; dest++; @@ -1065,17 +1299,21 @@ void R_DrawTiltedSplat_8(void) */ void R_DrawSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); UINT32 val; + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the // texture with two shifts, an OR and one AND. (see below) @@ -1083,99 +1321,125 @@ void R_DrawSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[0] = colormap[val]; - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[1] = colormap[val]; - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[2] = colormap[val]; - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[3] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[4] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[5] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[6] = colormap[val]; - xposition += xstep; - yposition += ystep; - - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - dest[7] = colormap[val]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = source[((y * ds_flatwidth) + x)]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; - if (val != TRANSPARENTPIXEL) - *dest = colormap[val]; + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + // + // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[0] = colormap[val]; + xposition += xstep; + yposition += ystep; - dest++; - xposition += xstep; - yposition += ystep; + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[1] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[2] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[3] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[4] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[5] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[6] = colormap[val]; + xposition += xstep; + yposition += ystep; + + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + val &= 4194303; + val = source[val]; + if (val != TRANSPARENTPIXEL) + dest[7] = colormap[val]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + xposition += xstep; + yposition += ystep; + } } } @@ -1184,16 +1448,20 @@ void R_DrawSplat_8 (void) */ void R_DrawTranslucentSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; - UINT8 val; + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1202,79 +1470,107 @@ void R_DrawTranslucentSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = source[((y * ds_flatwidth) + x)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; - if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; - dest++; - xposition += xstep; - yposition += ystep; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } } @@ -1283,15 +1579,20 @@ void R_DrawTranslucentSplat_8 (void) */ void R_DrawTranslucentSpan_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1300,63 +1601,161 @@ void R_DrawTranslucentSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - while (count >= 8) + if (!ds_powersoftwo) { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); - dest[1] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - dest[2] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; + x %= ds_flatwidth; + y %= ds_flatheight; - dest[3] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - dest[4] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - dest[5] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - dest[6] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - dest[7] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; + val = ((y * ds_flatwidth) + x); + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } - while (count--) + else { - *dest = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + dest[1] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + dest[2] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + dest[3] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + dest[4] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + dest[5] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + dest[6] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + dest[7] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } } } +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + UINT8 *dsrc; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = (ds_yfrac + ds_waterofs); + xstep = ds_xstep; ystep = ds_ystep; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + if (ds_powersoftwo) + { + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + } + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + + if (!ds_powersoftwo) + { + while (count-- && dest <= deststop) + { + fixed_t x = (xposition >> FRACBITS); + fixed_t y = (yposition >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } + } + else + { + while (count-- && dest <= deststop) + { + *dest++ = colormap[*(ds_transmap + (source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } + } +} +#endif + /** \brief The R_DrawFogSpan_8 function Draws the actual span with fogging. */ diff --git a/src/r_main.c b/src/r_main.c index db351e991..9cce41288 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1182,6 +1182,8 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam_speed); CV_RegisterVar(&cv_cam_rotate); CV_RegisterVar(&cv_cam_rotspeed); + CV_RegisterVar(&cv_cam_orbit); + CV_RegisterVar(&cv_cam_adjust); CV_RegisterVar(&cv_cam2_dist); CV_RegisterVar(&cv_cam2_still); @@ -1189,6 +1191,8 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam2_speed); CV_RegisterVar(&cv_cam2_rotate); CV_RegisterVar(&cv_cam2_rotspeed); + CV_RegisterVar(&cv_cam2_orbit); + CV_RegisterVar(&cv_cam2_adjust); CV_RegisterVar(&cv_showhud); CV_RegisterVar(&cv_translucenthud); diff --git a/src/r_plane.c b/src/r_plane.c index 2f6f97240..db5fb0f24 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -127,91 +127,13 @@ void R_InitPlanes(void) // viewheight #ifndef NOWATER -static INT32 bgofs; +INT32 ds_bgofs; +INT32 ds_waterofs; + static INT32 wtofs=0; -static INT32 waterofs; static boolean itswater; #endif -#ifndef NOWATER -static void R_DrawTranslucentWaterSpan_8(void) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - - UINT8 *source; - UINT8 *colormap; - UINT8 *dest; - UINT8 *dsrc; - - size_t count; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + waterofs) << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; - - source = ds_source; - colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - dsrc = screens[1] + (ds_y+bgofs)*vid.width + ds_x1; - count = ds_x2 - ds_x1 + 1; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - } -} -#endif - void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; @@ -258,17 +180,17 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { const INT32 yay = (wtofs + (distance>>9) ) & 8191; // ripples da water texture - bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; + ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; angle = (angle + 2048) & 8191; // 90 degrees - ds_xfrac += FixedMul(FINECOSINE(angle), (bgofs<=viewheight) - bgofs = viewheight-y-1; - if (y+bgofs<0) - bgofs = -y; + if (y+ds_bgofs>=viewheight) + ds_bgofs = viewheight-y-1; + if (y+ds_bgofs<0) + ds_bgofs = -y; } #endif @@ -680,7 +602,7 @@ void R_DrawPlanes(void) } } #ifndef NOWATER - waterofs = (leveltime & 1)*16384; + ds_waterofs = (leveltime & 1)*16384; wtofs = leveltime * 140; #endif } @@ -728,13 +650,169 @@ static void R_DrawSkyPlane(visplane_t *pl) } } +boolean R_CheckPowersOfTwo(void) +{ + boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1))); + boolean hpow2 = (!(ds_flatheight & (ds_flatheight - 1))); + + // Initially, the flat isn't powers-of-two-sized. + ds_powersoftwo = false; + + // But if the width and height are powers of two, + // and are EQUAL, then it's okay :] + if ((ds_flatwidth == ds_flatheight) && (wpow2 && hpow2)) + ds_powersoftwo = true; + + // Just return ds_powersoftwo. + return ds_powersoftwo; +} + +void R_CheckFlatLength(size_t size) +{ + switch (size) + { + case 4194304: // 2048x2048 lump + nflatmask = 0x3FF800; + nflatxshift = 21; + nflatyshift = 10; + nflatshiftup = 5; + ds_flatwidth = ds_flatheight = 2048; + break; + case 1048576: // 1024x1024 lump + nflatmask = 0xFFC00; + nflatxshift = 22; + nflatyshift = 12; + nflatshiftup = 6; + ds_flatwidth = ds_flatheight = 1024; + break; + case 262144:// 512x512 lump + nflatmask = 0x3FE00; + nflatxshift = 23; + nflatyshift = 14; + nflatshiftup = 7; + ds_flatwidth = ds_flatheight = 512; + break; + case 65536: // 256x256 lump + nflatmask = 0xFF00; + nflatxshift = 24; + nflatyshift = 16; + nflatshiftup = 8; + ds_flatwidth = ds_flatheight = 256; + break; + case 16384: // 128x128 lump + nflatmask = 0x3F80; + nflatxshift = 25; + nflatyshift = 18; + nflatshiftup = 9; + ds_flatwidth = ds_flatheight = 128; + break; + case 1024: // 32x32 lump + nflatmask = 0x3E0; + nflatxshift = 27; + nflatyshift = 22; + nflatshiftup = 11; + ds_flatwidth = ds_flatheight = 32; + break; + default: // 64x64 lump + nflatmask = 0xFC0; + nflatxshift = 26; + nflatyshift = 20; + nflatshiftup = 10; + ds_flatwidth = ds_flatheight = 64; + break; + } +} + +static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) +{ + UINT8 *flat; + textureflat_t *texflat = &texflats[levelflat->texturenum]; + patch_t *patch = NULL; + boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false); + + // Check if the texture changed. + if (leveltexture && (!texturechanged)) + { + if (texflat != NULL && texflat->flat) + { + flat = texflat->flat; + ds_flatwidth = texflat->width; + ds_flatheight = texflat->height; + texturechanged = false; + } + else + texturechanged = true; + } + + // If the texture changed, or the patch doesn't exist, convert either of them to a flat. + if (levelflat->flatpatch == NULL || texturechanged) + { + if (leveltexture) + { + texture_t *texture = textures[levelflat->texturenum]; + texflat->width = ds_flatwidth = texture->width; + texflat->height = ds_flatheight = texture->height; + + texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL); + memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); + R_TextureToFlat(levelflat->texturenum, texflat->flat); + flat = texflat->flat; + + levelflat->flatpatch = flat; + levelflat->width = ds_flatwidth; + levelflat->height = ds_flatheight; + } + else + { + patch = (patch_t *)ds_source; +#ifndef NO_PNG_LUMPS + if (ispng) + { + levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum)); + levelflat->topoffset = levelflat->leftoffset = 0; + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + } + else +#endif + { + levelflat->width = ds_flatwidth = SHORT(patch->width); + levelflat->height = ds_flatheight = SHORT(patch->height); + + levelflat->topoffset = patch->topoffset * FRACUNIT; + levelflat->leftoffset = patch->leftoffset * FRACUNIT; + + levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL); + memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight); + R_PatchToFlat(patch, levelflat->flatpatch); + } + flat = levelflat->flatpatch; + } + } + else + { + flat = levelflat->flatpatch; + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + + xoffs += levelflat->leftoffset; + yoffs += levelflat->topoffset; + } + + levelflat->lasttexturenum = levelflat->texturenum; + return flat; +} + void R_DrawSinglePlane(visplane_t *pl) { + UINT8 *flat; INT32 light = 0; INT32 x; INT32 stop, angle; size_t size; ffloor_t *rover; + levelflat_t *levelflat; + boolean rawflat = false; if (!(pl->minx <= pl->maxx)) return; @@ -874,64 +952,51 @@ void R_DrawSinglePlane(visplane_t *pl) viewangle = pl->viewangle+pl->plangle; } - currentplane = pl; - - ds_source = (UINT8 *) - W_CacheLumpNum(levelflats[pl->picnum].lumpnum, - PU_STATIC); // Stay here until Z_ChangeTag - - size = W_LumpLength(levelflats[pl->picnum].lumpnum); - - switch (size) - { - case 4194304: // 2048x2048 lump - nflatmask = 0x3FF800; - nflatxshift = 21; - nflatyshift = 10; - nflatshiftup = 5; - break; - case 1048576: // 1024x1024 lump - nflatmask = 0xFFC00; - nflatxshift = 22; - nflatyshift = 12; - nflatshiftup = 6; - break; - case 262144:// 512x512 lump' - nflatmask = 0x3FE00; - nflatxshift = 23; - nflatyshift = 14; - nflatshiftup = 7; - break; - case 65536: // 256x256 lump - nflatmask = 0xFF00; - nflatxshift = 24; - nflatyshift = 16; - nflatshiftup = 8; - break; - case 16384: // 128x128 lump - nflatmask = 0x3F80; - nflatxshift = 25; - nflatyshift = 18; - nflatshiftup = 9; - break; - case 1024: // 32x32 lump - nflatmask = 0x3E0; - nflatxshift = 27; - nflatyshift = 22; - nflatshiftup = 11; - break; - default: // 64x64 lump - nflatmask = 0xFC0; - nflatxshift = 26; - nflatyshift = 20; - nflatshiftup = 10; - break; - } - xoffs = pl->xoffs; yoffs = pl->yoffs; planeheight = abs(pl->height - pl->viewz); + currentplane = pl; + levelflat = &levelflats[pl->picnum]; + size = W_LumpLength(levelflat->lumpnum); + ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag + + // Check if the flat is actually a wall texture. + if (levelflat->texturenum != 0 && levelflat->texturenum != -1) + flat = R_GetPatchFlat(levelflat, true, false); +#ifndef NO_PNG_LUMPS + // Maybe it's a PNG?! + else if (R_IsLumpPNG(ds_source, size)) + flat = R_GetPatchFlat(levelflat, false, true); +#endif + // Maybe it's just a patch, then? + else if (R_CheckIfPatch(levelflat->lumpnum)) + flat = R_GetPatchFlat(levelflat, false, false); + // It's a raw flat. + else + { + rawflat = true; + R_CheckFlatLength(size); + flat = ds_source; + } + + Z_ChangeTag(ds_source, PU_CACHE); + ds_source = flat; + + if (ds_source == NULL) + return; + + // Raw flats always have dimensions that are powers-of-two numbers. + if (rawflat) + ds_powersoftwo = true; + // Otherwise, check if this texture or patch has such dimensions. + else if (R_CheckPowersOfTwo()) + { + R_CheckFlatLength(ds_flatwidth * ds_flatheight); + if (spanfunc == basespanfunc) + spanfunc = mmxspanfunc; + } + if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; @@ -945,60 +1010,63 @@ void R_DrawSinglePlane(visplane_t *pl) floatv3_t p, m, n; float ang; float vx, vy, vz; + float fudge = 0; // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetZAt's return value each time fixed_t temp; - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red - const float fudge = ((1<plangle & (ANGLE_90-1)); yoffs *= 1; - if (hack) + if (ds_powersoftwo) { - /* - Essentially: We can't & the components along the regular axes when the plane is rotated. - This is because the distance on each regular axis in order to loop is different. - We rotate them, & the components, add them together, & them again, and then rotate them back. - These three seperate & operations are done per axis in order to prevent overflows. - toast 10/04/17 - */ - const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); + // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red + fudge = ((1<>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - temp = ox & modmask; - oy &= modmask; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + temp = ox & modmask; + oy &= modmask; + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + temp = xoffs & modmask; + yoffs &= modmask; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); + } + else + { + xoffs &= ((1 << (32-nflatshiftup))-1); + yoffs &= ((1 << (32-nflatshiftup))-1); + xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + } + xoffs = (fixed_t)(xoffs*fudge); + yoffs = (fixed_t)(yoffs/fudge); } - else - { - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - } - - xoffs = (fixed_t)(xoffs*fudge); - yoffs = (fixed_t)(yoffs/fudge); vx = FIXED_TO_FLOAT(pl->viewx+xoffs); vy = FIXED_TO_FLOAT(pl->viewy-yoffs); @@ -1033,13 +1101,16 @@ void R_DrawSinglePlane(visplane_t *pl) temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); n.y = FIXED_TO_FLOAT(temp) - zeroheight; - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; + if (ds_powersoftwo) + { + m.x /= fudge; + m.y /= fudge; + m.z /= fudge; - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; + n.x *= fudge; + n.y *= fudge; + n.z *= fudge; + } // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ @@ -1056,13 +1127,26 @@ void R_DrawSinglePlane(visplane_t *pl) ds_sz.z *= focallengthf; // Premultiply the texture vectors with the scale factors -#define SFMULT 65536.f*(1<patch, PU_CACHE); + patch_t *patch = W_CachePatchNum(vis->patch, PU_CACHE); fixed_t this_scale = vis->mobj->scale; INT32 x1, x2; INT64 overflow_test; @@ -870,7 +883,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) INT64 overflow_test; //Fab : R_InitSprites now sets a wad lump number - patch = W_CacheLumpNum(vis->patch, PU_CACHE); + patch = W_CachePatchNum(vis->patch, PU_CACHE); if (!patch) return; @@ -2511,7 +2524,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) if (!skin) return 0; - if ((unsigned)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) return 0; while (!(skin->sprites[spr2].numframes) @@ -2603,6 +2616,8 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->followitem = 0; skin->highresscale = FRACUNIT; + skin->contspeed = 17; + skin->contangle = 0; skin->availability = 0; @@ -2869,6 +2884,8 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski for (sprite2 = 0; sprite2 < free_spr2; sprite2++) R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[sprite2], wadnum, *lump, *lastlump); + if (skin->sprites[0].numframes == 0) + I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]); } // returns whether found appropriate property @@ -2907,6 +2924,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETINT(thrustfactor) GETINT(accelstart) GETINT(acceleration) + GETINT(contspeed) + GETINT(contangle) #undef GETINT #define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value); diff --git a/src/r_things.h b/src/r_things.h index 9c3d16ab0..0fa9c4b94 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -122,6 +122,8 @@ typedef struct UINT8 prefoppositecolor; // if 0 use tables instead fixed_t highresscale; // scale of highres, default is 0.5 + UINT8 contspeed; // continue screen animation speed + UINT8 contangle; // initial angle on continue screen // specific sounds per skin sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table diff --git a/src/s_sound.c b/src/s_sound.c index 3068db1df..299e4b889 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -108,7 +108,9 @@ consvar_t cv_closedcaptioning = {"closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_ consvar_t cv_numChannels = {"snd_channels", "32", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL}; static consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_resetmusic = {"resetmusic", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_resetmusic = {"resetmusic", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_resetmusicbyheader = {"resetmusicbyheader", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; // Sound system toggles, saved into the config consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -275,6 +277,7 @@ void S_RegisterSoundStuff(void) CV_RegisterVar(&surround); CV_RegisterVar(&cv_samplerate); CV_RegisterVar(&cv_resetmusic); + CV_RegisterVar(&cv_resetmusicbyheader); CV_RegisterVar(&cv_gamesounds); CV_RegisterVar(&cv_gamedigimusic); CV_RegisterVar(&cv_gamemidimusic); @@ -2096,7 +2099,7 @@ void S_StartEx(boolean reset) mapmusposition = mapheaderinfo[gamemap-1]->muspos; } - if (cv_resetmusic.value || reset) + if (RESETMUSIC || reset) S_StopMusic(); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); diff --git a/src/s_sound.h b/src/s_sound.h index e0737eff7..48128527c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -31,7 +31,16 @@ openmpt_module *openmpt_mhandle; extern consvar_t stereoreverse; extern consvar_t cv_soundvolume, cv_closedcaptioning, cv_digmusicvolume, cv_midimusicvolume; extern consvar_t cv_numChannels; + extern consvar_t cv_resetmusic; +extern consvar_t cv_resetmusicbyheader; + +#define RESETMUSIC (!modeattacking && \ + (cv_resetmusicbyheader.value ? \ + (mapheaderinfo[gamemap-1]->musforcereset != -1 ? mapheaderinfo[gamemap-1]->musforcereset : cv_resetmusic.value) \ + : cv_resetmusic.value) \ + ) + extern consvar_t cv_gamedigimusic; extern consvar_t cv_gamemidimusic; extern consvar_t cv_gamesounds; diff --git a/src/screen.c b/src/screen.c index fc3f5b8e8..547036a60 100644 --- a/src/screen.c +++ b/src/screen.c @@ -49,6 +49,7 @@ void (*fuzzcolfunc)(void); // standard fuzzy effect column drawer void (*transcolfunc)(void); // translation column drawer void (*shadecolfunc)(void); // smokie test.. void (*spanfunc)(void); // span drawer, use a 64x64 tile +void (*mmxspanfunc)(void); // span drawer in MMX assembly void (*splatfunc)(void); // span drawer w/ transparency void (*basespanfunc)(void); // default span func for color mode void (*transtransfunc)(void); // translucent translated column drawer @@ -112,7 +113,7 @@ void SCR_SetMode(void) // if (true)//vid.bpp == 1) //Always run in 8bpp. todo: remove all 16bpp code? { - spanfunc = basespanfunc = R_DrawSpan_8; + spanfunc = basespanfunc = mmxspanfunc = R_DrawSpan_8; splatfunc = R_DrawSplat_8; transcolfunc = R_DrawTranslatedColumn_8; transtransfunc = R_DrawTranslatedTranslucentColumn_8; @@ -133,7 +134,7 @@ void SCR_SetMode(void) //fuzzcolfunc = R_DrawTranslucentColumn_8_ASM; walldrawerfunc = R_DrawWallColumn_8_MMX; twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_MMX; - spanfunc = basespanfunc = R_DrawSpan_8_MMX; + mmxspanfunc = R_DrawSpan_8_MMX; } else { diff --git a/src/screen.h b/src/screen.h index 7aa6fdb63..3554b5520 100644 --- a/src/screen.h +++ b/src/screen.h @@ -123,6 +123,7 @@ extern void (*transcolfunc)(void); extern void (*shadecolfunc)(void); extern void (*spanfunc)(void); extern void (*basespanfunc)(void); +extern void (*mmxspanfunc)(void); extern void (*splatfunc)(void); extern void (*transtransfunc)(void); extern void (*twosmultipatchfunc)(void); diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index af76ec1dd..43fb4ded2 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -1,6 +1,6 @@ /* SDL_image: An example image loading library for use with SDL - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -34,7 +34,7 @@ * * Besides the standard API, also provides * - * SDL_Surface *IMG_ReadXPMFromArray(char **xpm) + * SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) * * that reads the image data from an XPM file included in the C source. * @@ -88,8 +88,8 @@ struct color_hash { struct hash_entry **table; struct hash_entry *entries; /* array of all entries */ struct hash_entry *next_free; - int size; - int maxnum; + size_t size; + size_t maxnum; }; static int hash_key(const char *key, int cpp, int size) @@ -103,14 +103,14 @@ static int hash_key(const char *key, int cpp, int size) return hash & (size - 1); } -static struct color_hash *create_colorhash(int maxnum) +static struct color_hash *create_colorhash(size_t maxnum) { - int bytes, s; + size_t bytes, s; struct color_hash *hash; /* we know how many entries we need, so we can allocate everything here */ - hash = (struct color_hash *)SDL_malloc(sizeof *hash); + hash = (struct color_hash *)SDL_calloc(1, sizeof(*hash)); if (!hash) return NULL; @@ -119,15 +119,29 @@ static struct color_hash *create_colorhash(int maxnum) ; hash->size = s; hash->maxnum = maxnum; + bytes = hash->size * sizeof(struct hash_entry **); - hash->entries = NULL; /* in case malloc fails */ - hash->table = (struct hash_entry **)SDL_malloc(bytes); + /* Check for overflow */ + if ((bytes / sizeof(struct hash_entry **)) != hash->size) { + IMG_SetError("memory allocation overflow"); + SDL_free(hash); + return NULL; + } + hash->table = (struct hash_entry **)SDL_calloc(1, bytes); if (!hash->table) { SDL_free(hash); return NULL; } - SDL_memset(hash->table, 0, bytes); - hash->entries = (struct hash_entry *)SDL_malloc(maxnum * sizeof(struct hash_entry)); + + bytes = maxnum * sizeof(struct hash_entry); + /* Check for overflow */ + if ((bytes / sizeof(struct hash_entry)) != maxnum) { + IMG_SetError("memory allocation overflow"); + SDL_free(hash->table); + SDL_free(hash); + return NULL; + } + hash->entries = (struct hash_entry *)SDL_calloc(1, bytes); if (!hash->entries) { SDL_free(hash->table); SDL_free(hash); @@ -138,7 +152,7 @@ static struct color_hash *create_colorhash(int maxnum) } static int add_colorhash(struct color_hash *hash, - char *key, int cpp, Uint32 color) + const char *key, int cpp, Uint32 color) { int index = hash_key(key, cpp, hash->size); struct hash_entry *e = hash->next_free++; @@ -995,10 +1009,11 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) { Sint64 start = 0; SDL_Surface *image = NULL; - int index; + size_t index; int x, y; - int w, h, ncolors, cpp; - int indexed; + int w, h, cpp; + size_t ncolors; + size_t indexed; Uint8 *dst; struct color_hash *colors = NULL; SDL_Color *im_colors = NULL; @@ -1029,12 +1044,17 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) * Right now we don't use the hotspots but it should be handled * one day. */ - if (SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 + if (SDL_sscanf(line, "%d %d %lu %d", &w, &h, &ncolors, &cpp) != 4 || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { error = "Invalid format description"; goto done; } + /* Check for allocation overflow */ + if ((size_t)(ncolors * cpp)/cpp != ncolors) { + error = "Invalid color specification"; + goto done; + } keystrings = (char *)SDL_malloc(ncolors * cpp); if (!keystrings) { error = "Out of memory"; @@ -1102,8 +1122,9 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) c->g = (Uint8)(rgb >> 8); c->b = (Uint8)(rgb); pixel = index; - } else + } else { pixel = rgb; + } add_colorhash(colors, nextkey, cpp, pixel); nextkey += cpp; if (rgb == 0xffffffff) @@ -1192,7 +1213,7 @@ SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) return(NULL); } -SDL_Surface *IMG_ReadXPMFromArray(char **xpm) +SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) { return NULL; } diff --git a/src/sdl/SDL_icon.xpm b/src/sdl/SDL_icon.xpm index 1d0f9d314..2180d782c 100644 --- a/src/sdl/SDL_icon.xpm +++ b/src/sdl/SDL_icon.xpm @@ -1,163 +1,99 @@ /* XPM */ -const char * SDL_icon_xpm[] = { -"96 96 64 1", +static const char *SDL_icon_xpm[] = { +"64 64 32 1", " c None", -". c #040656", -"+ c #0100B2", -"@ c #04056E", -"# c #0000BD", -"$ c #0B0C09", -"% c #0B0D26", -"& c #090C42", -"* c #060AA7", -"= c #1604DA", -"- c #020CD5", -"; c #100F8D", -"> c #040DE4", -", c #11129B", -"' c #1D1A83", -") c #2A10FD", -"! c #1318FA", -"~ c #25225B", -"{ c #252271", -"] c #312E2B", -"^ c #33334D", -"/ c #363775", -"( c #3D3B69", -"_ c #3A3B8B", -": c #373AFF", -"< c #4142AA", -"[ c #4B4864", -"} c #4D4B4A", -"| c #60492F", -"1 c #4F4C57", -"2 c #4A4A9E", -"3 c #4F4E85", -"4 c #474ADE", -"5 c #4E4FFE", -"6 c #5D5CB3", -"7 c #686663", -"8 c #666682", -"9 c #676875", -"0 c #66659E", -"a c #8B6538", -"b c #6465D5", -"c c #7F694F", -"d c #6767FF", -"e c #7272FF", -"f c #91795C", -"g c #7677FD", -"h c #828396", -"i c #A78153", -"j c #888989", -"k c #8D897E", -"l c #9190FD", -"m c #CA9048", -"n c #C09968", -"o c #A9A8A1", -"p c #A6A8B0", -"q c #B0B1FB", -"r c #EEAC61", -"s c #E3B478", -"t c #C3C4BE", -"u c #FFC68C", -"v c #FCCD90", -"w c #D4D7D3", -"x c #E3E5E0", -"y c #FCFFFB", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ttj7777777joot ", -" 9hh8830000088hh9 ", -" 9888(//__-*{^kt ", -" &,5b60^ (02*{} ", -" tp,-)!5egb3} ~_<4dgggeeeeeeeeeeeeeegb6/_2[amusf'#!<_'>))))))))))))!)>+{~ ", -" p;-))!5gb2^^'#5eggeeeeeeeeeeeeeeegg6/_23amrusi{#!+;;>))))))))))))))!!-'8p ", -" tp'#!)):d6(@*>5egeeeeeeeeeeeeeeeegg6_/<(amrrvvn{+)-,;>))))))!!!!!!)))!!>,~j ", -" p;#!))-'{'+-5eggeeeeeeeeeeeeeeeegb222(cmrruvvn{+)>,@>!)!!)!!>>>>======>-,/8 ", -" ;#)!-*.;-!5eggeeeeeeeeeeeeeeeegb2_<6|mrrsvvvn{+)!,.-!!!!>>=--######+++-#@(k ", -" h@-)+@.*>!5egeeeeeeeeeeeeeeeeeegb_>--###++++++###+;@{(9j ", -" kh,#+@@,>!:dggeeeeeeeeeeeeeeeeeeebbb_]mrruuvvsf'#)!*.+-###+++++++##+*;'3(&^9 ", -" 8*,@@*)):dggeeeeeeeeeeeeeeeeeeeeggg<(|iruvvvsc,=!!*.;*++++++++###+,@&1o ", -" 8@@@-!)!5eeeeeeeeeeeeeeeeeeeeeeeeeggb2[csvvvn^#)!!+@;*#+++++###*@~[ ", -" 9&@*!)):5geeeeeeeeeeeeeeeeeeeeeeeeegge637nsvf{>))!+;;*-######*;{.^ ", -" 9%;!!)):dgeeeeeeeeeeeeeeeeeeeeeeeeeeeggb_1ir7;>))!+;;,++++++*'(} ", -" 9{+!))!5egeeeeeeeeeeeeeeeeeddddeeeeeeeege2}|~#!))!#;@...@@@.^hp ", -" 8,=!))):dggeeeeeeeeeeeeeeeeggggeeeeeeeeggb_~,>!))!+@@@;;;;@&^o ", -" }(-)))))!:eegeeeeeeeeeeeeeegllllgeeeeeeeegd5+=))))!+;,#>--#,'/hj ", -" o8.>))))))!:dgggeeeeeeeeeeellqqqqlgeeeeggg5:!!!)))))-*+>)!:55db631 ", -" p8<*!)))))))!:5deggggggeeeegqqqqqqqqlggged5:!))))))))>->!!:5ddeegb3/ ", -" oh'#!))))))))))!:ddeeeeeeeeglqqqqqqqqlgedd:!)))))))))))))!:dggggeggg239 ", -" ^*>!))!)))))))))!::55dddeegglll600333_4:!!)))))))))))))):dggeeeeeeggb6(9o ", -" ~+=-+#>))))))))))!!!:::::5554<3889988[/,=)))))))))))))):5gggeeeeeeeggb6087 ", -" ~**@~'+>!))))))))))))))))!!>*{1kkooook7(,-!)))))))))))!:5deeeeeeeeeeeggb289 ", -" ~,'1o7(*>!))))))))))))))))=,[jtttwxxxwto^;>!))))))))))!!!::5deggeeeeeeegbb3] ", -" ~@/oxt7'#))))))))))))))))=,3ktwxxyyyyyyxk/+!))))))))))))))!:::5degggeeegggb3^ ", -" ^&8xyyt^,)))))))))))))))>,3otwxyyyyyyyyyxh'>)))))))))))))))))):5ddeeeeeeeggb3^ ", -" 771pyyyx7'=!)))))))))))!!#(jtxxyyyyyyyyyyyt3-)))))))))))))))))))!!::degggeeegb2[o ", -" 77tyyyxk/+!!)))))))))))-;9owxyyyyyyyyyyyywh*>)))))))))))))))))))))!::5ddgggggb68j ", -" owyyyyt8;>))))))))))))*(otwyyyyyyyyyyyyyxp'-)))))))))))))))))))))))!!:5deeeggg_8j ", -" jtxyyyyxh'>)))))))))!!#_ktxyyyyyyyyyyyyyyyt_+))))))))))))))))))))))))))!!:5deggg63j ", -" 7jwyyyyyyp/=))))))))))>,3owxyyyyyyyyyyyyyyyw/+))))))))))))))))))))))))))))!::5degb689 ", -" 7xyyyyyyo[#))))))))))-/jtwyyyyyyyyyyyyyyyyw/*)))))))))))))))))))))))))))))))!:5dgg_/ ", -" }xyyyyyyt9*=))))))))=*9owyyyyyyyyyyyyyyyyyw/*)))))))))))))))))))))))))))))))))!!:5d3} ", -" }xyyyyyywj'#!))))))!#@7oxyyyyyyyyyyyyyyyyyw/*)))))))))))))))))))))))))))))))))))!!:4/7 ", -" 7xyyyyyyxj&,!!))))!!,%}oyyyyyyyyyyyyyyyyyyw/*))))))))))))))))))))))))))))))))))))))>487 ", -" 7xyyyyyywk$@!!)))!!-.$]oyyyyyyyyyyyyyyyyyyw/+))))))))))))))))))))))))))))))!!!!))))!>' ", -" }xyyyyyywj$&+!!)!)>;%$]jyyyyyyyyyyyyyyyyyyt{#)))))))))))))))))))))!!!!!!))!)!!!!!!))!#' ", -" 7xyyyyyyt7$%@-!)!>*[]$$jyyyyyyyyyyyyyyyyyxp;-))))))))))))))))))!!!!!!!!!!!!>>>>>>>>>>!,^ ", -" 7xyyyyyyt}$][;-)=,(o7$$7yyyyyyyyyyyyyyyyyxp,-)))))))))))!!!!)!!!!>>>>=-----########--=+'9 ", -" jwyyyyyyo}$}o(';@~7wj$$7yyyyyyyyyyyyyyyyywh*>)))))))))))!>>>=>=---#####+########+++***;@17 ", -" otxyyyyyt}$7t7}1}7kw7$$7yyyyyyyyyyyyyyyyyt0-)))))))))!!!>--####+++++++++++++##+***,;''.&] ", -" ooowyyyyyt}$}j7owwojo}$$jyyyyyyyyyyyyyyyyyp2>)))))))!!!=##++++++++++++++###+*;@.~[8[9hph ", -" ojtyyyyywj$$}jwyyxo}$$]jyyyyyyyyyyyyyyyyyp'>))))))!>>-#++++++++++++####+,;'_3/&^}77kot ", -" 7tyyyyyxo]$$oxyyyt]$$}tyyyyyyyyyyyyyyyyx0*!)))!!!>-#++++++++++++#+##+*;.&1ko ", -" 7tyyyyyyx7]}xyyyyxj}]oxyyyyyyyyyyyyyyyyp<=)!!!!>-#++++++++++++####*;.(8h ", -" owxyxxyytooywptwwtppxyyyyyyyyyyyyyyyxp3,-=!)!>-#++++++++++###+*,'_{&1k ", -" jtwwttwtwwtj7kjowxyyyyyyyyyyyyyyyyxt7~'',+>=#+++++++++++###*;@&^j ", -" ]joojj7}]}]|innfc7jtwyyyyyyyyyyyxtjcfnnnf[@*#+++++++++###+@.&%% ", -" ]$}77}}$$$$]fsssnnifkkotwwwwwwwtpjkfinvvvsi}@*#++++++###*;@.@@&[ ", -" o7$]]]]]$$]|isvvvvvusifckopppopok7cisvvvvvvvn(,#++++++#+*@.&@*#;3o ", -" }}$]|||fnnsvvvuvvvuuvvsniffffffnnsvvvvuuuvvvc{*+#++##*@&.@*+#--<7 ", -" }]cninsuvvvvuuuuuuvvvvusnnnnnssuvvvvvuuuuvvc~*+#+++*@.@;*##=>>,^ ", -" 7fvvvvvvuuuuuuuuuuuuvvvvvvvvvvvuuuuuuuuuvvc~*+#+#+,.@*###->!!*~ ", -" pkivvvvuuuuuuuuuuuuuuuvvvvvvvvuuuvsnsuuuvvf~*+#++++*+++->!!)!#. ", -" kfsuvvuuuuuuuuuuuuuuuuuuuuuuuuuvvnfsuvuvvc{++#++++###->!!))!-;h ", -" kisvvvuuuuuuuuuuuuuuuuuuuuuuuvvvicsvvvvs1@##+++++++#>!!))))=,ho ", -" 7imuvvvuuuuuuuuuuuuuuuuuuuuvusfcivvuvvn~;##+++++++#>!!))))!#8k ", -" cimruuuuuvuuuuuuuuuuuuuuuuvsnfisuvvvsc@*#+++++++++#>!!))))-3} ", -" 7amrruuuuuuuuuuuuuuuuuuuuvsnnsvvuvvi^,##++++++++++#>!!)))>/^ ", -" kfamrruuuuvvvuuuuuuuuuuuuuvvvvvvvn1@+#++++++++++++#>!)))>{~ ", -" 7|iimrrruuuuuuuuuuuuuuuuvvvvuusn1'+#########++++++->!))>; ", -" 7cammrrrrruuuuuuvvvvvuuuuurrm|.*-#+#######+###+++->!!!*' ", -" ookcaimmrrrrrruuuuurrrrrmi|]%.@@@@@;,*,*+########->!!*6o ", -" p7}|ainiimmmmmmmmmmminnia|$%.....{3322_{''',,**+#=!!#6k ", -" j7||aaiiiiiaa||7j ookok711^&.';,*+=!>> c #2325EC", +", c #3C3883", +"' c #3D3A9E", +") c #5B5170", +"! c #4B4CFF", +"~ c #795339", +"{ c #5E5B5C", +"] c #5F5ED3", +"^ c #5E5EFB", +"/ c #7271FF", +"( c #B37F5D", +"_ c #8F8883", +": c #8887FF", +"< c #D59E76", +"[ c #ABABA9", +"} c #A9AAFF", +"| c #C1C3C1", +"1 c #FAC296", +"2 c #D4D6D3", +"3 c #F9FCF8", +" ", +" ", +" #***,,,**** ", +" *,,]]]]]]]]]]]]]',,** ", +" *,']//////////////////]]',* ", +" *,']/////////////////////////]'% ", +" *,]////////////////////^^!!>>>>>>>$+ ", +" *,]////////////////////!>---------->=@% ", +" * ,]///////////////////]^>------->==@@@$.# ", +" +', *']//////////////////],,,=---->=@@@@@$.% ", +" #.=^'* ,]//////////////////],']^]$--=@@@@@@@$+# ", +" %$=-^'* ,]/////////////////],]/!>-^'=@@@@@@@$.% ", +" +$=->/,*,//////////////////]'/^!,$-!,$@@@@@@$+* ", +" +@=--!''/////////////////]']^!,(()->%$@@@@@$+# ", +" +@=--='/////////////////]']^${(<<)->,$@@@@$% ", +" +@=->']/////////:::////]]/^'(<111)->,$@@@$% ", +" #+@@>$]////////::}}}://///!,(<1111)--%$@@.% ", +" #+@@$$^////////:}}}}}://^>$(<<1111)--+$@.% ", +" +@$.>^///////:}}}}}}:/^>->,(<111<'--+$$*# ", +" +$.=-!///////:}}}}}:^!-----@(111<@--+$,'],,* ", +" %+%=->^///////:}}}:!--------@(11(=--$=^////],* ", +" ,]]'>->^//////^^!!-----------'<1_>--@-!//////]'* ", +" '!->@--->>>>>>--->===>--------)<,-->@->^///////]', ", +" *$--->----------='){__{'>------>'=--=@-->!^///////],* ", +" %$.=---------->$)[22332[)=----------=>----->^^//////], ", +" %$_,--------->'_|3333333['----------=--------->!^////],# ", +" *'[{=--------'_2333333333_=---------------------->!^///,* ", +" #)[_@-------@_|33333333332,------------------------->!^/'* ", +" #)2[$------=)|333332|23333{>--------------------------->^'* ", +" {2|,------$[233333___3333_=----------------------------->$ ", +" ;22)=---->)|333332{2_2333[@-------------------------------$ ", +" &22{@----$_233333|{2||333|'--------------------------------$ ", +" &|3_.----,|333333[;2|[333|'--------------------------------=+ ", +" [3_%=--={2333333[&___333|'-------------------->>>====>>----@ ", +" _3[#$=@.[2333333[&&&_333[$------------->>==@@@@@@@@@@@@@@@==+", +" {3|;+$$)|3333333[&&&[333_=-------->==@@@@@@@@@@@@@@@$$$$.+++%", +" {23{*$${23333333|;&&|332)>----->=@@@@@@@@@@@@@@$$$.++%** ", +";{{;[3{&*)[333333333{&&|332,=---==@@@@@@@@@@@@$$.++%* ", +"{22_{|[;_|2333333333_&;233_$@@@@@@@@@@@@@@@@$$+%* ", +"&_|2{;{{[233333333332_[33[,$@@@@@@@@@@@@@$$+%# ", +" &;{&&&;~(_|3333333333332)$@@@@@@@@@@@@$.+%# ", +" &&&&&;(11([33333333332{$@@@@@@@@@@@$...$@$* ", +" &~((1111<[333333332{%.$@@@@@@@@@$$$$@=--$ ", +" ~<<11111<[33333|[_(<~,$@@@@@@@@@@@@@>-->. ", +" ;(<111111<(____(11111(+@@@@@@@@@@@@=----=% ", +" ~(<11111111<11111<(<<;$@@$$@@@@@@@=-----. ", +" ~(<1111111111111(~<1{$$$.$@@@@@@@=-----= ", +" ~(<1111111<<(((<11<*$+.$@@@@@@@@@>---->+ ", +" ;(<1111111<<1111<~%+$@@@@@@@@@@@=-----$ ", +" ~(<<111111111(~&*+$$$@@@@@@@@@@=----=% ", +" ;~((<<<<(~~; *%+$$@@@@@@@@@>----+ ", +" ;;; #%+$$@@@@@@@----. ", +" *+$$@@@@@=---@ ", +" *+$@@@@@>--= ", +" *.$@@@@-->% ", +" #%.$@@=->+ ", +" *+$@@>-$ ", +" %$@=-$ ", +" %.@>@ ", +" +=@ ", +" .. ", +" * ", +" ", +" "}; diff --git a/src/sdl/Srb2SDL.ico b/src/sdl/Srb2SDL.ico index 700276fd4..3b37433db 100644 Binary files a/src/sdl/Srb2SDL.ico and b/src/sdl/Srb2SDL.ico differ diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index f54f0d7c5..029febc05 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -26,6 +26,8 @@ #include #endif +#include "time.h" // For log timestamps + #ifdef HAVE_SDL #ifdef HAVE_TTF @@ -114,6 +116,7 @@ int main(int argc, char **argv) #endif { const char *logdir = NULL; + char logfile[MAX_WADPATH]; myargc = argc; myargv = argv; /// \todo pull out path to exe from this string @@ -125,15 +128,36 @@ int main(int argc, char **argv) #endif #endif - logdir = D_Home(); - #ifdef LOGMESSAGES + if (!M_CheckParm("-nolog")) + { + time_t my_time; + struct tm * timeinfo; + char buf[26]; + + logdir = D_Home(); + + my_time = time(NULL); + timeinfo = localtime(&my_time); + + strftime(buf, 26, "%Y-%m-%d %H-%M-%S", timeinfo); + strcpy(logfile, va("log-%s.txt", buf)); + #ifdef DEFAULTDIR - if (logdir) - logstream = fopen(va("%s/"DEFAULTDIR"/log.txt",logdir), "wt"); - else + if (logdir) + { + // Create dirs here because D_SRB2Main() is too late. + I_mkdir(va("%s%s"DEFAULTDIR, logdir, PATHSEP), 0755); + I_mkdir(va("%s%s"DEFAULTDIR"%slogs",logdir, PATHSEP, PATHSEP), 0755); + logstream = fopen(va("%s%s"DEFAULTDIR"%slogs%s%s",logdir, PATHSEP, PATHSEP, PATHSEP, logfile), "wt"); + } + else #endif - logstream = fopen("./log.txt", "wt"); + { + I_mkdir("."PATHSEP"logs"PATHSEP, 0755); + logstream = fopen(va("."PATHSEP"logs"PATHSEP"%s", logfile), "wt"); + } + } #endif //I_OutputMsg("I_StartupSystem() ...\n"); @@ -160,6 +184,10 @@ int main(int argc, char **argv) // startup SRB2 CONS_Printf("Setting up SRB2...\n"); D_SRB2Main(); +#ifdef LOGMESSAGES + if (!M_CheckParm("-nolog")) + CONS_Printf("Logfile: %s\n", logfile); +#endif CONS_Printf("Entering main game loop...\n"); // never return D_SRB2Loop(); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 78363c85e..97690cf7e 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -530,7 +530,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co) break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 233cb9b26..46c05aea9 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -41,7 +41,7 @@ #ifdef HAVE_IMAGE #include "SDL_image.h" -#elif 1 +#elif defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) // Windows doesn't need this, as SDL will do it for us. #define LOAD_XPM //I want XPM! #include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so #define HAVE_IMAGE //I have SDL_Image, sortof diff --git a/src/sdl/macosx/Srb2mac.icns b/src/sdl/macosx/Srb2mac.icns index 96cb8a36d..a3e37aab3 100644 Binary files a/src/sdl/macosx/Srb2mac.icns and b/src/sdl/macosx/Srb2mac.icns differ diff --git a/src/sdl/srb2icon.png b/src/sdl/srb2icon.png deleted file mode 100644 index cdee18a84..000000000 Binary files a/src/sdl/srb2icon.png and /dev/null differ diff --git a/src/sounds.c b/src/sounds.c index 11ba1e0bc..43225a615 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -35,6 +35,23 @@ sfxinfo_t S_sfx[NUMSFX] = // name, singularity, priority, pitch, volume, data, length, skinsound, usefulness, lumpnum, caption {"none" , false, 0, 0, -1, NULL, 0, -1, -1, LUMPERROR, "///////////////////////////////"}, // maximum length + // A HUMBLE REQUEST FROM YOUR FRIENDLY NEIGHBORHOOD toaster! + // + // If you see a caption that's just "" (shows the lumpname in-game), + // and you intend to use the sound associated with it in a mod, + // PLEASE give it a caption through SOC or Lua. + // + // If the first character of the caption is '/', no caption will be + // produced; only do this for "unimportant" sounds that aren't used + // to indicate gameplay. + // + // (to whomstever updates the sounds list wiki page for 2.2, please + // either copy this comment across, or make sure its desire is + // codified in the initial paragraph of the page.) + // + // Closed Captioning may be a niche feature, but it's an important one. + // Thank you! ^u^ + // Skin Sounds {"altdi1", false, 192, 16, -1, NULL, 0, SKSPLDET1, -1, LUMPERROR, "Dying"}, {"altdi2", false, 192, 16, -1, NULL, 0, SKSPLDET2, -1, LUMPERROR, "Dying"}, @@ -290,6 +307,139 @@ sfxinfo_t S_sfx[NUMSFX] = {"brakrl", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Rocket launch"}, {"brakrx", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Rocket explosion"}, + // Sonic 1 sounds + {"s1a0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1aa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1af", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1be", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ca", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ce", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + + // Sonic 2 sounds + {"s220", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s221", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s222", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s223", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s224", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s225", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s226", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s227", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s228", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s229", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s230", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s231", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s232", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s233", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s234", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s235", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s236", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s237", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s238", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s239", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s240", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s241", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s242", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s243", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s244", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s245", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s246", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s247", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s248", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s249", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s250", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s251", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s252", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s253", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s254", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s255", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s256", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s257", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s258", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s259", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + // S3&K sounds {"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // stereo in original game, identical to latter {"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // mono in original game, identical to previous @@ -492,6 +642,174 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kdbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running on water"}, {"s3kdbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running on water"}, // ditto + // 3D Blast sounds (the "missing" ones are direct copies of S3K's, no minor differences what-so-ever) + {"3db06", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Collection"}, + {"3db09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Peep"}, + {"3db14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Chirp"}, + {"3db16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + + // Sonic CD sounds + {"cdfm00", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Skid"}, + {"cdfm01", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm02", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, + {"cdfm03", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dying"}, + {"cdfm04", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ring loss"}, + {"cdfm05", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, + {"cdfm06", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop"}, + {"cdfm07", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shield"}, + {"cdfm08", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spring"}, + {"cdfm09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm10", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm11", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm12", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm13", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm15", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm17", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm18", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm19", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm20", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm21", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm22", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm23", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm24", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm25", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm26", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm27", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm28", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm29", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble gasp"}, + {"cdfm30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, + {"cdfm31", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"cdfm32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"}, + {"cdfm39", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Extra time"}, + {"cdfm45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, + {"cdfm50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"cdfm57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm64", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm70", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm74", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm75", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm76", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm77", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdpcm0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Future."}, + {"cdpcm1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Past."}, + {"cdpcm2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "All right!"}, + {"cdpcm3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "I'm outta here..."}, + {"cdpcm4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Yes!"}, + {"cdpcm5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Yeah!"}, + {"cdpcm6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Giggles"}, + {"cdpcm7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Eep!"}, + {"cdpcm8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdpcm9", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, + + // Knuckles Chaotix sounds + {"kc2a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2e", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2f", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Confirm"}, + {"kc43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc46", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Select"}, + {"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc57", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Sheer terror"}, + {"kc58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc59", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Shrink"}, + {"kc5a", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Grow"}, + {"kc5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc64", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Terrifying rumble"}, + {"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ascending"}, + {"kc6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + // skin sounds free slots to add sounds at run time (Boris HACK!!!) // initialized to NULL }; diff --git a/src/sounds.h b/src/sounds.h index 20f89d9fb..674f51d79 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -356,6 +356,139 @@ typedef enum sfx_brakrl, // Rocket launcher sfx_brakrx, // Rocket explodes + // S1 sounds + sfx_s1a0, + sfx_s1a1, + sfx_s1a2, + sfx_s1a3, + sfx_s1a4, + sfx_s1a5, + sfx_s1a6, + sfx_s1a7, + sfx_s1a8, + sfx_s1a9, + sfx_s1aa, + sfx_s1ab, + sfx_s1ac, + sfx_s1ad, + sfx_s1ae, + sfx_s1af, + sfx_s1b0, + sfx_s1b1, + sfx_s1b2, + sfx_s1b3, + sfx_s1b4, + sfx_s1b5, + sfx_s1b6, + sfx_s1b7, + sfx_s1b8, + sfx_s1b9, + sfx_s1ba, + sfx_s1bb, + sfx_s1bc, + sfx_s1bd, + sfx_s1be, + sfx_s1bf, + sfx_s1c0, + sfx_s1c1, + sfx_s1c2, + sfx_s1c3, + sfx_s1c4, + sfx_s1c5, + sfx_s1c6, + sfx_s1c7, + sfx_s1c8, + sfx_s1c9, + sfx_s1ca, + sfx_s1cb, + sfx_s1cc, + sfx_s1cd, + sfx_s1ce, + sfx_s1cf, + + // S2 sounds + sfx_s220, + sfx_s221, + sfx_s222, + sfx_s223, + sfx_s224, + sfx_s225, + sfx_s226, + sfx_s227, + sfx_s228, + sfx_s229, + sfx_s22a, + sfx_s22b, + sfx_s22c, + sfx_s22d, + sfx_s22e, + sfx_s22f, + sfx_s230, + sfx_s231, + sfx_s232, + sfx_s233, + sfx_s234, + sfx_s235, + sfx_s236, + sfx_s237, + sfx_s238, + sfx_s239, + sfx_s23a, + sfx_s23b, + sfx_s23c, + sfx_s23d, + sfx_s23e, + sfx_s23f, + sfx_s240, + sfx_s241, + sfx_s242, + sfx_s243, + sfx_s244, + sfx_s245, + sfx_s246, + sfx_s247, + sfx_s248, + sfx_s249, + sfx_s24a, + sfx_s24b, + sfx_s24c, + sfx_s24d, + sfx_s24e, + sfx_s24f, + sfx_s250, + sfx_s251, + sfx_s252, + sfx_s253, + sfx_s254, + sfx_s255, + sfx_s256, + sfx_s257, + sfx_s258, + sfx_s259, + sfx_s25a, + sfx_s25b, + sfx_s25c, + sfx_s25d, + sfx_s25e, + sfx_s25f, + sfx_s260, + sfx_s261, + sfx_s262, + sfx_s263, + sfx_s264, + sfx_s265, + sfx_s266, + sfx_s267, + sfx_s268, + sfx_s269, + sfx_s26a, + sfx_s26b, + sfx_s26c, + sfx_s26d, + sfx_s26e, + sfx_s26f, + sfx_s270, + // S3&K sounds sfx_s3k33, sfx_s3k34, @@ -558,6 +691,174 @@ typedef enum sfx_s3kdbs, sfx_s3kdbl, + // 3DB sounds + sfx_3db06, + sfx_3db09, + sfx_3db14, + sfx_3db16, + + // SCD sounds + sfx_cdfm00, + sfx_cdfm01, + sfx_cdfm02, + sfx_cdfm03, + sfx_cdfm04, + sfx_cdfm05, + sfx_cdfm06, + sfx_cdfm07, + sfx_cdfm08, + sfx_cdfm09, + sfx_cdfm10, + sfx_cdfm11, + sfx_cdfm12, + sfx_cdfm13, + sfx_cdfm14, + sfx_cdfm15, + sfx_cdfm16, + sfx_cdfm17, + sfx_cdfm18, + sfx_cdfm19, + sfx_cdfm20, + sfx_cdfm21, + sfx_cdfm22, + sfx_cdfm23, + sfx_cdfm24, + sfx_cdfm25, + sfx_cdfm26, + sfx_cdfm27, + sfx_cdfm28, + sfx_cdfm29, + sfx_cdfm30, + sfx_cdfm31, + sfx_cdfm32, + sfx_cdfm33, + sfx_cdfm34, + sfx_cdfm35, + sfx_cdfm36, + sfx_cdfm37, + sfx_cdfm38, + sfx_cdfm39, + sfx_cdfm40, + sfx_cdfm41, + sfx_cdfm42, + sfx_cdfm43, + sfx_cdfm44, + sfx_cdfm45, + sfx_cdfm46, + sfx_cdfm47, + sfx_cdfm48, + sfx_cdfm49, + sfx_cdfm50, + sfx_cdfm51, + sfx_cdfm52, + sfx_cdfm53, + sfx_cdfm54, + sfx_cdfm55, + sfx_cdfm56, + sfx_cdfm57, + sfx_cdfm58, + sfx_cdfm59, + sfx_cdfm60, + sfx_cdfm61, + sfx_cdfm62, + sfx_cdfm63, + sfx_cdfm64, + sfx_cdfm65, + sfx_cdfm66, + sfx_cdfm67, + sfx_cdfm68, + sfx_cdfm69, + sfx_cdfm70, + sfx_cdfm71, + sfx_cdfm72, + sfx_cdfm73, + sfx_cdfm74, + sfx_cdfm75, + sfx_cdfm76, + sfx_cdfm77, + sfx_cdfm78, + sfx_cdfm79, + sfx_cdpcm0, + sfx_cdpcm1, + sfx_cdpcm2, + sfx_cdpcm3, + sfx_cdpcm4, + sfx_cdpcm5, + sfx_cdpcm6, + sfx_cdpcm7, + sfx_cdpcm8, + sfx_cdpcm9, + + // KC sounds + sfx_kc2a, + sfx_kc2b, + sfx_kc2c, + sfx_kc2d, + sfx_kc2e, + sfx_kc2f, + sfx_kc30, + sfx_kc31, + sfx_kc32, + sfx_kc33, + sfx_kc34, + sfx_kc35, + sfx_kc36, + sfx_kc37, + sfx_kc38, + sfx_kc39, + sfx_kc3a, + sfx_kc3b, + sfx_kc3c, + sfx_kc3d, + sfx_kc3e, + sfx_kc3f, + sfx_kc40, + sfx_kc41, + sfx_kc42, + sfx_kc43, + sfx_kc44, + sfx_kc45, + sfx_kc46, + sfx_kc47, + sfx_kc48, + sfx_kc49, + sfx_kc4a, + sfx_kc4b, + sfx_kc4c, + sfx_kc4d, + sfx_kc4e, + sfx_kc4f, + sfx_kc50, + sfx_kc51, + sfx_kc52, + sfx_kc53, + sfx_kc54, + sfx_kc55, + sfx_kc56, + sfx_kc57, + sfx_kc58, + sfx_kc59, + sfx_kc5a, + sfx_kc5b, + sfx_kc5c, + sfx_kc5d, + sfx_kc5e, + sfx_kc5f, + sfx_kc60, + sfx_kc61, + sfx_kc62, + sfx_kc63, + sfx_kc64, + sfx_kc65, + sfx_kc66, + sfx_kc67, + sfx_kc68, + sfx_kc69, + sfx_kc6b, + sfx_kc6c, + sfx_kc6d, + sfx_kc6e, + // free slots for S_AddSoundFx() at run-time -------------------- sfx_freeslot0, // diff --git a/src/st_stuff.c b/src/st_stuff.c index a90661ef3..20a132b3a 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -64,11 +64,12 @@ patch_t *sbotime; // Time logo patch_t *sbocolon; // Colon for time patch_t *sboperiod; // Period for time centiseconds patch_t *livesback; // Lives icon background +patch_t *stlivex; static patch_t *nrec_timer; // Timer for NiGHTS records static patch_t *sborings; -static patch_t *sboover; -static patch_t *timeover; -static patch_t *stlivex; +static patch_t *slidgame; +static patch_t *slidtime; +static patch_t *slidover; static patch_t *sboredrings; static patch_t *sboredtime; static patch_t *getall; // Special Stage HUD @@ -253,8 +254,10 @@ void ST_LoadGraphics(void) sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds - sboover = W_CachePatchName("SBOOVER", PU_HUDGFX); - timeover = W_CachePatchName("TIMEOVER", PU_HUDGFX); + slidgame = W_CachePatchName("SLIDGAME", PU_HUDGFX); + slidtime = W_CachePatchName("SLIDTIME", PU_HUDGFX); + slidover = W_CachePatchName("SLIDOVER", PU_HUDGFX); + stlivex = W_CachePatchName("STLIVEX", PU_HUDGFX); livesback = W_CachePatchName("STLIVEBK", PU_HUDGFX); nrec_timer = W_CachePatchName("NGRTIMER", PU_HUDGFX); // Timer for NiGHTS @@ -768,7 +771,12 @@ static inline void ST_drawRings(void) ST_DrawPatchFromHud(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); - ringnum = ((objectplacing) ? op_currentdoomednum : max(stplyr->rings, 0)); + if (objectplacing) + ringnum = op_currentdoomednum; + else if (stplyr->rings < 0 || stplyr->spectator || stplyr->playerstate == PST_REBORN) + ringnum = 0; + else + ringnum = stplyr->rings; if (cv_timetic.value == 2) // Yes, even in modeattacking ST_DrawNumFromHud(HUD_RINGSNUMTICS, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); @@ -877,6 +885,8 @@ static void ST_drawLivesArea(void) '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); else { + if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1))) + livescount++; if (livescount > 99) livescount = 99; V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, @@ -2029,42 +2039,7 @@ static void ST_drawTextHUD(void) textHUDdraw(va("Lap:""\x82 %u/%d", stplyr->laps+1, cv_numlaps.value)) } - if (!stplyr->spectator && stplyr->exiting && cv_playersforexit.value && gametype == GT_COOP) - { - INT32 i, total = 0, exiting = 0; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - if (players[i].lives <= 0) - continue; - - total++; - if (players[i].exiting) - exiting++; - } - - if (cv_playersforexit.value != 4) - { - total *= cv_playersforexit.value; - if (total & 3) - total += 4; // round up - total /= 4; - } - - if (exiting < total) - { - if (!splitscreen && !donef12) - { - textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) - donef12 = true; - } - total -= exiting; - textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) - } - } - else if (gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1))) + if (gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1))) { if (!splitscreen && !donef12) { @@ -2072,7 +2047,7 @@ static void ST_drawTextHUD(void) donef12 = true; } } - else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. + else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text. { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; @@ -2092,7 +2067,7 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""JUMP:""\x80 Rise")) textHUDdraw(M_GetText("\x82""SPIN:""\x80 Lower")) - if (G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) + if (G_IsSpecialStage(gamemap)) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) else if (gametype == GT_COOP) { @@ -2125,7 +2100,46 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) } - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) + if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && stplyr->exiting) + { + UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); + if (numneeded) + { + INT32 i, total = 0, exiting = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + if (players[i].lives <= 0) + continue; + + total++; + if (players[i].exiting) + exiting++; + } + + if (numneeded != 4) + { + total *= cv_playersforexit.value; + if (total & 3) + total += 4; // round up + total /= 4; + } + + if (exiting < total) + { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + total -= exiting; + textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) + } + } + } + else if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) { if (leveltime < hidetime * TICRATE) { @@ -2409,25 +2423,20 @@ static void ST_overlayDrawer(void) } } - // GAME OVER pic + // GAME OVER hud if ((gametype == GT_COOP) && (netgame || multiplayer) && (cv_cooplives.value == 0)) ; - else if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) + else if ((G_GametypeUsesLives() || gametype == GT_RACE) && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) { - patch_t *p; - - if (countdown == 1) - p = timeover; - else - p = sboover; + INT32 i = MAXPLAYERS; + INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1)); if ((gametype == GT_COOP) && (netgame || multiplayer) && (cv_cooplives.value != 1)) { - INT32 i; for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) @@ -2437,15 +2446,18 @@ static void ST_overlayDrawer(void) continue; if (players[i].lives > 0) - { - p = NULL; break; - } } } - if (p) - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, BASEVIDHEIGHT/2 - (SHORT(p->height)/2), V_PERPLAYER|(stplyr->spectator ? V_HUDTRANSHALF : V_HUDTRANS), p); + if (i == MAXPLAYERS && deadtimer >= 0) + { + INT32 lvlttlx = min(6*deadtimer, BASEVIDWIDTH/2); + UINT32 flags = V_PERPLAYER|(stplyr->spectator ? V_HUDTRANSHALF : V_HUDTRANS); + + V_DrawScaledPatch(lvlttlx - 8, BASEVIDHEIGHT/2, flags, (countdown == 1 ? slidtime : slidgame)); + V_DrawScaledPatch(BASEVIDWIDTH + 8 - lvlttlx, BASEVIDHEIGHT/2, flags, slidover); + } } if (G_GametypeHasTeams()) diff --git a/src/st_stuff.h b/src/st_stuff.h index 40574f46c..aaf01ca15 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -70,6 +70,7 @@ extern patch_t *sboperiod; extern patch_t *faceprefix[MAXSKINS]; // face status patches extern patch_t *superprefix[MAXSKINS]; // super face status patches extern patch_t *livesback; +extern patch_t *stlivex; extern patch_t *ngradeletters[7]; /** HUD location information (don't move this comment) diff --git a/src/v_video.c b/src/v_video.c index 082d84915..93fefdd97 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1045,9 +1045,15 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ prevdelta = topdelta; source = (const UINT8 *)(column) + 3; dest = desttop; - dest += FixedInt(FixedMul(topdelta< 0) + { + dest += FixedInt(FixedMul((topdelta-sy)<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) + for (; dest < deststop && (ofs>>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) { if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); @@ -1064,17 +1070,17 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ // void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor) { - if (skinnum < 0 || skinnum >= numskins || (skins[skinnum].flags & SF_HIRES)) - V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); - else + if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes >= 4) { - spriteframe_t *sprframe = &skins[skinnum].sprites[SPR2_WAIT].spriteframes[0]; - patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[3]; + patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); - // No variant for translucency - V_DrawTinyMappedPatch(x, y, flags, patch, colormap); + V_DrawMappedPatch(x, y, flags, patch, colormap); } + else + V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); } // diff --git a/src/w_wad.c b/src/w_wad.c index d02ce9ce6..4d08b26dc 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -789,6 +789,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile) // set up caching // Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache); + Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache); #ifdef HWRENDER // allocates GLPatch info structures and store them in a tree @@ -1182,8 +1183,6 @@ void zerr(int ret) } #endif -#define NO_PNG_LUMPS - #ifdef NO_PNG_LUMPS static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l) { @@ -1459,6 +1458,38 @@ boolean W_IsLumpCached(lumpnum_t lumpnum, void *ptr) return W_IsLumpCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); } +// +// W_IsPatchCached +// +// If a patch is already cached return true, otherwise +// return false. +// +// no outside code uses the PWAD form, for now +static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) +{ + void *lcache; + + if (!TestValidLump(wad, lump)) + return false; + + lcache = wadfiles[wad]->patchcache[lump]; + + if (ptr) + { + if (ptr == lcache) + return true; + } + else if (lcache) + return true; + + return false; +} + +boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr) +{ + return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); +} + // ========================================================================== // W_CacheLumpName // ========================================================================== @@ -1482,18 +1513,53 @@ void *W_CacheLumpName(const char *name, INT32 tag) // Cache a patch into heap memory, convert the patch format as necessary // -// Software-only compile cache the data without conversion -#ifdef HWRENDER -static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) +void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { +#ifdef HWRENDER GLPatch_t *grPatch; - - if (rendermode == render_soft || rendermode == render_none) - return W_CacheLumpNumPwad(wad, lump, tag); +#endif if (!TestValidLump(wad, lump)) return NULL; +#ifdef HWRENDER + // Software-only compile cache the data without conversion + if (rendermode == render_soft || rendermode == render_none) + { +#endif + lumpcache_t *lumpcache = wadfiles[wad]->patchcache; + if (!lumpcache[lump]) + { + size_t len = W_LumpLengthPwad(wad, lump); + void *ptr, *lumpdata, *srcdata = NULL; + + ptr = Z_Malloc(len, tag, &lumpcache[lump]); + lumpdata = Z_Malloc(len, tag, NULL); + + // read the lump in full + W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); + +#ifndef NO_PNG_LUMPS + // lump is a png so convert it + if (R_IsLumpPNG((UINT8 *)lumpdata, len)) + { + size_t newlen; + srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen, true); + ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]); + M_Memcpy(ptr, srcdata, newlen); + Z_Free(srcdata); + } + else // just copy it into the patch cache +#endif + M_Memcpy(ptr, lumpdata, len); + } + else + Z_ChangeTag(lumpcache[lump], tag); + + return lumpcache[lump]; +#ifdef HWRENDER + } + grPatch = HWR_GetCachedGLPatchPwad(wad, lump); if (grPatch->mipmap.grInfo.data) @@ -1517,6 +1583,7 @@ static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) // return GLPatch_t, which can be casted to (patch_t) with valid patch header info return (void *)grPatch; +#endif } void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) @@ -1524,8 +1591,6 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) return W_CachePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); } -#endif // HWRENDER - void W_UnlockCachedPatch(void *patch) { // The hardware code does its own memory management, as its patches @@ -1621,13 +1686,145 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) #endif } +// Verify versions for different archive +// formats. checklist assumed to be valid. + +static int +W_VerifyName (const char *name, lumpchecklist_t *checklist, boolean status) +{ + size_t j; + for (j = 0; checklist[j].len && checklist[j].name; ++j) + { + if (( strncmp(name, checklist[j].name, + checklist[j].len) != false ) == status) + { + return true; + } + } + return false; +} + +static int +W_VerifyWAD (FILE *fp, lumpchecklist_t *checklist, boolean status) +{ + size_t i; + + // assume wad file + wadinfo_t header; + filelump_t lumpinfo; + + // read the header + if (fread(&header, 1, sizeof header, fp) == sizeof header + && header.numlumps < INT16_MAX + && strncmp(header.identification, "ZWAD", 4) + && strncmp(header.identification, "IWAD", 4) + && strncmp(header.identification, "PWAD", 4) + && strncmp(header.identification, "SDLL", 4)) + { + return true; + } + + header.numlumps = LONG(header.numlumps); + header.infotableofs = LONG(header.infotableofs); + + // let seek to the lumpinfo list + if (fseek(fp, header.infotableofs, SEEK_SET) == -1) + return true; + + for (i = 0; i < header.numlumps; i++) + { + // fill in lumpinfo for this wad file directory + if (fread(&lumpinfo, sizeof (lumpinfo), 1 , fp) != 1) + return true; + + lumpinfo.filepos = LONG(lumpinfo.filepos); + lumpinfo.size = LONG(lumpinfo.size); + + if (lumpinfo.size == 0) + continue; + + if (! W_VerifyName(lumpinfo.name, checklist, status)) + return false; + } + + return true; +} + +static int +W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) +{ + zend_t zend; + zentry_t zentry; + + UINT16 numlumps; + size_t i; + + char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; + char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; + + char lumpname[9]; + + // Haha the ResGetLumpsZip function doesn't + // check for file errors, so neither will I. + + // Central directory bullshit + + fseek(fp, 0, SEEK_END); + if (!ResFindSignature(fp, pat_end, max(0, ftell(fp) - (22 + 65536)))) + return true; + + fseek(fp, -4, SEEK_CUR); + if (fread(&zend, 1, sizeof zend, fp) < sizeof zend) + return true; + + numlumps = zend.entries; + + fseek(fp, zend.cdiroffset, SEEK_SET); + for (i = 0; i < numlumps; i++) + { + char* fullname; + char* trimname; + char* dotpos; + + if (fread(&zentry, 1, sizeof(zentry_t), fp) < sizeof(zentry_t)) + return true; + if (memcmp(zentry.signature, pat_central, 4)) + return true; + + fullname = malloc(zentry.namelen + 1); + if (fgets(fullname, zentry.namelen + 1, fp) != fullname) + return true; + + // Strip away file address and extension for the 8char name. + if ((trimname = strrchr(fullname, '/')) != 0) + trimname++; + else + trimname = fullname; // Care taken for root files. + + if (*trimname) // Ignore directories + { + if ((dotpos = strrchr(trimname, '.')) == 0) + dotpos = fullname + strlen(fullname); // Watch for files without extension. + + memset(lumpname, '\0', 9); // Making sure they're initialized to 0. Is it necessary? + strncpy(lumpname, trimname, min(8, dotpos - trimname)); + + if (! W_VerifyName(lumpname, checklist, status)) + return false; + } + + free(fullname); + } + + return true; +} + // Note: This never opens lumps themselves and therefore doesn't have to // deal with compressed lumps. static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, boolean status) { FILE *handle; - size_t i, j; int goodfile = false; if (!checklist) @@ -1636,66 +1833,18 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, if ((handle = W_OpenWadFile(&filename, false)) == NULL) return -1; - // detect wad file by the absence of the other supported extensions - if (stricmp(&filename[strlen(filename) - 4], ".soc") -#ifdef HAVE_BLUA - && stricmp(&filename[strlen(filename) - 4], ".lua") -#endif - && stricmp(&filename[strlen(filename) - 4], ".pk3")) + if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) + goodfile = W_VerifyPK3(handle, checklist, status); + else { - // assume wad file - wadinfo_t header; - filelump_t lumpinfo; - - // read the header - if (fread(&header, 1, sizeof header, handle) == sizeof header - && header.numlumps < INT16_MAX - && strncmp(header.identification, "ZWAD", 4) - && strncmp(header.identification, "IWAD", 4) - && strncmp(header.identification, "PWAD", 4) - && strncmp(header.identification, "SDLL", 4)) + // detect wad file by the absence of the other supported extensions + if (stricmp(&filename[strlen(filename) - 4], ".soc") +#ifdef HAVE_BLUA + && stricmp(&filename[strlen(filename) - 4], ".lua") +#endif + ) { - fclose(handle); - return true; - } - - header.numlumps = LONG(header.numlumps); - header.infotableofs = LONG(header.infotableofs); - - // let seek to the lumpinfo list - if (fseek(handle, header.infotableofs, SEEK_SET) == -1) - { - fclose(handle); - return false; - } - - goodfile = true; - for (i = 0; i < header.numlumps; i++) - { - // fill in lumpinfo for this wad file directory - if (fread(&lumpinfo, sizeof (lumpinfo), 1 , handle) != 1) - { - fclose(handle); - return -1; - } - - lumpinfo.filepos = LONG(lumpinfo.filepos); - lumpinfo.size = LONG(lumpinfo.size); - - if (lumpinfo.size == 0) - continue; - - for (j = 0; j < NUMSPRITES; j++) - if (sprnames[j] && !strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites - continue; - - goodfile = false; - for (j = 0; checklist[j].len && checklist[j].name && !goodfile; j++) - if ((strncmp(lumpinfo.name, checklist[j].name, checklist[j].len) != false) == status) - goodfile = true; - - if (!goodfile) - break; + goodfile = W_VerifyWAD(handle, checklist, status); } } fclose(handle); diff --git a/src/w_wad.h b/src/w_wad.h index 651738850..91d4e733e 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -102,6 +102,7 @@ typedef struct wadfile_s restype_t type; lumpinfo_t *lumpinfo; lumpcache_t *lumpcache; + lumpcache_t *patchcache; #ifdef HWRENDER aatree_t *hwrcache; // patches are cached in renderer's native format #endif @@ -167,17 +168,13 @@ void *W_CacheLumpNum(lumpnum_t lump, INT32 tag); void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag); boolean W_IsLumpCached(lumpnum_t lump, void *ptr); +boolean W_IsPatchCached(lumpnum_t lump, void *ptr); void *W_CacheLumpName(const char *name, INT32 tag); void *W_CachePatchName(const char *name, INT32 tag); -#ifdef HWRENDER -//void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch_t +void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch_t void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); // return a patch_t -#else -//#define W_CachePatchNumPwad(wad, lump, tag) W_CacheLumpNumPwad(wad, lump, tag) -#define W_CachePatchNum(lumpnum, tag) W_CacheLumpNum(lumpnum, tag) -#endif void W_UnlockCachedPatch(void *patch); diff --git a/src/win32/Srb2win.ico b/src/win32/Srb2win.ico index 700276fd4..3b37433db 100644 Binary files a/src/win32/Srb2win.ico and b/src/win32/Srb2win.ico differ diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index b60ba750d..8e7fdccc9 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -1,6 +1,7 @@ //Microsoft Developer Studio generated resource script. // #include "resource.h" +#include "winver.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// @@ -62,9 +63,11 @@ END // Version // +#include "../doomdef.h" // Needed for version string + VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,9,0 - PRODUCTVERSION 1,0,9,0 + FILEVERSION 2,2,0,0 + PRODUCTVERSION 2,2,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -82,14 +85,14 @@ BEGIN VALUE "Comments", "Visit our web site at www.srb2.org for news and updates!\0" VALUE "CompanyName", "Sonic Team Junior\0" VALUE "FileDescription", "Sonic Robo Blast 2\0" - VALUE "FileVersion", "1, 09\0" + VALUE "FileVersion", VERSIONSTRING VALUE "InternalName", "srb2\0" - VALUE "LegalCopyright", "Copyright � 1998-2018 by Sonic Team Junior\0" + VALUE "LegalCopyright", "Copyright 1998-2019 by Sonic Team Junior\0" VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" VALUE "OriginalFilename", "srb2win.exe\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Sonic Robo Blast 2\0" - VALUE "ProductVersion", "1, 09\0" + VALUE "ProductVersion", VERSIONSTRING VALUE "SpecialBuild", "\0" END END diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index d10f73b58..93b3ff523 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -327,7 +327,7 @@ static inline VOID I_GetConsoleEvents(VOID) break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char } diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index e2f32fa61..11c7a6744 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -322,9 +322,9 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - /* FALLTHRU */ //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible #ifndef CLIENT_LOADINGSCREEN + /* FALLTHRU */ case GS_WAITINGPLAYERS: #endif return skip; // Skip odd frames diff --git a/src/y_inter.c b/src/y_inter.c index 975902ab0..0d6a3d03c 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -261,7 +261,7 @@ void Y_IntermissionDrawer(void) // draw time ST_DrawPatchFromHud(HUD_TIME, sbotime); - if (cv_timetic.value == 1) + if (cv_timetic.value == 3) ST_DrawNumFromHud(HUD_SECONDS, data.coop.tics); else { @@ -275,8 +275,7 @@ void Y_IntermissionDrawer(void) ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds - // we should show centiseconds on the intermission screen too, if the conditions are right. - if (modeattacking || cv_timetic.value == 2) + if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking) // there's not enough room for tics in splitscreen, don't even bother trying! { ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics @@ -429,7 +428,7 @@ void Y_IntermissionDrawer(void) { if ((data.spec.continues & 0x80) && i == continues-1 && (endtic < 0 || intertic%20 < 10)) break; - V_DrawContinueIcon(246 + xoffset5 - (i*12), 162+yoffset, 0, *data.spec.playerchar, *data.spec.playercolor); + V_DrawContinueIcon(246 + xoffset5 - (i*20), 162+yoffset, 0, *data.spec.playerchar, *data.spec.playercolor); } } }