diff --git a/readme.txt b/readme.txt index 8a09f0bc5..c1898d491 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -Here it is! SRB2 v2.1.12 source code! +Here it is! SRB2 v2.1.14 source code! (why do we keep the version number up to date when everything else in this file is hilariously old? - Inuyasha) diff --git a/src/command.c b/src/command.c index 09588eb84..e10787f1b 100644 --- a/src/command.c +++ b/src/command.c @@ -379,11 +379,13 @@ void COM_AddCommand(const char *name, com_func_t func) { if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! { +#ifdef HAVE_BLUA // don't I_Error for Lua commands // Lua commands can replace game commands, and they have priority. // BUT, if for some reason we screwed up and made two console commands with the same name, // it's good to have this here so we find out. if (cmd->function != COM_Lua_f) +#endif I_Error("Command %s already exists\n", name); return; @@ -397,6 +399,7 @@ void COM_AddCommand(const char *name, com_func_t func) com_commands = cmd; } +#ifdef HAVE_BLUA /** Adds a console command for Lua. * No I_Errors allowed; return a negative code instead. * @@ -429,6 +432,7 @@ int COM_AddLuaCommand(const char *name) com_commands = cmd; return 0; } +#endif /** Tests if a command exists. * @@ -1284,6 +1288,8 @@ void CV_LoadNetVars(UINT8 **p) serverloading = false; } +static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth); + void CV_ResetCheatNetVars(void) { consvar_t *cvar; @@ -1291,7 +1297,7 @@ void CV_ResetCheatNetVars(void) // Stealthset everything back to default. for (cvar = consvar_vars; cvar; cvar = cvar->next) if (cvar->flags & CV_CHEAT) - Setvalue(cvar, cvar->defaultvalue, true); + CV_SetCVar(cvar, cvar->defaultvalue, true); } // Returns true if the variable's current value is its default value @@ -1428,11 +1434,7 @@ void CV_AddValue(consvar_t *var, INT32 increment) INT32 newvalue, max; // count pointlimit better - if (var == &cv_pointlimit && (gametype == GT_MATCH -#ifdef CHAOSISNOTDEADYET - || gametype == GT_CHAOS -#endif - )) + if (var == &cv_pointlimit && (gametype == GT_MATCH)) increment *= 50; newvalue = var->value + increment; diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e24a1426a..c0179ca1b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -823,7 +823,7 @@ static inline void resynch_read_ctf(resynchend_pak *p) { if (!playeringame[p->flagplayer[1]]) I_Error("Invalid blue flag player %d who isn't in the game!", (INT32)p->flagplayer[1]); - players[p->flagplayer[1]].gotflag = GF_REDFLAG; + players[p->flagplayer[1]].gotflag = GF_BLUEFLAG; if (blueflag) { P_RemoveMobj(blueflag); diff --git a/src/d_main.c b/src/d_main.c index 4cea94a81..95808b274 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -90,6 +90,9 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "hardware/hw3sound.h" #endif +// platform independant focus loss +UINT8 window_notinfocus = false; + // // DEMO LOOP // @@ -437,6 +440,17 @@ static void D_Display(void) CON_Drawer(); M_Drawer(); // menu is drawn even on top of everything + + // focus lost notification goes on top of everything, even the former everything + if (window_notinfocus) + { + M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2); + if (gamestate == GS_LEVEL && (P_AutoPause() || paused)) + V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), V_YELLOWMAP, "Game Paused"); + else + V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), V_YELLOWMAP, "Focus Lost"); + } + NetUpdate(); // send out any new accumulation // It's safe to end the game now. @@ -635,6 +649,7 @@ void D_AdvanceDemo(void) // void D_StartTitle(void) { + INT32 i; if (netgame) { if (gametype == GT_COOP) @@ -661,6 +676,16 @@ void D_StartTitle(void) SV_StopServer(); SV_ResetServer(); + for (i = 0; i < MAXPLAYERS; i++) + CL_ClearPlayer(i); + + splitscreen = false; + SplitScreen_OnChange(); + botingame = false; + botskin = 0; + cv_debug = 0; + emeralds = 0; + // In case someone exits out at the same time they start a time attack run, // reset modeattacking modeattacking = ATTACKING_NONE; @@ -803,7 +828,7 @@ static void IdentifyVersion(void) D_AddFile(va(pandf,srb2waddir,"rings.dta")); // Add our crappy patches to fix our bugs - D_AddFile(va(pandf,srb2waddir,"patch.dta")); + // D_AddFile(va(pandf,srb2waddir,"patch.dta")); #if !defined (HAVE_SDL) || defined (HAVE_MIXER) { @@ -1087,19 +1112,19 @@ void D_SRB2Main(void) #endif D_CleanFile(); -#if 1 // md5s last updated 11/10/14 +#if 1 // md5s last updated 12/14/14 // Check MD5s of autoloaded files - W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad - W_VerifyFileMD5(1, "f39b6c849295e3c81875726e8cc0e2c7"); // zones.dta + W_VerifyFileMD5(0, "c1b9577687f8a795104aef4600720ea7"); // srb2.srb/srb2.wad + W_VerifyFileMD5(1, "303838c6c534d9540288360fa49cca60"); // zones.dta W_VerifyFileMD5(2, "cfca0f1c73023cbbd8f844f45480f799"); // player.dta W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta - W_VerifyFileMD5(4, "a45cc59d13dce924f2112b3e4201d0ae"); // patch.dta + //W_VerifyFileMD5(4, "0c66790502e648bfce90fdc5bb15722e"); // patch.dta // don't check music.dta because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. #endif - mainwads = 5; // there are 5 wads not to unload + mainwads = 4; // there are 5 wads not to unload cht_Init(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 377da8433..266161c7c 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -277,21 +277,6 @@ consvar_t cv_matchboxes = {"matchboxes", "Normal", CV_NETVAR|CV_CHEAT, matchboxe consvar_t cv_specialrings = {"specialrings", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_powerstones = {"powerstones", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -#ifdef CHAOSISNOTDEADYET -consvar_t cv_chaos_bluecrawla = {"chaos_bluecrawla", "8", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_redcrawla = {"chaos_redcrawla", "8", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_crawlacommander = {"chaos_crawlacommander", "2", CV_NETVAR, chances_cons_t, - NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_jettysynbomber = {"chaos_jettysynbomber", "5", CV_NETVAR, chances_cons_t, - NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_jettysyngunner = {"chaos_jettysyngunner", "2", CV_NETVAR, chances_cons_t, - NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_eggmobile1 = {"chaos_eggmobile1", "2", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_eggmobile2 = {"chaos_eggmobile2", "2", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_skim = {"chaos_skim", "5", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chaos_spawnrate = {"chaos_spawnrate", "30",CV_NETVAR, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif - consvar_t cv_recycler = {"tv_recycler", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_teleporters = {"tv_teleporter", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_superring = {"tv_superring", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -498,18 +483,6 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_competitionboxes); CV_RegisterVar(&cv_matchboxes); -#ifdef CHAOSISNOTDEADYET - CV_RegisterVar(&cv_chaos_bluecrawla); - CV_RegisterVar(&cv_chaos_redcrawla); - CV_RegisterVar(&cv_chaos_crawlacommander); - CV_RegisterVar(&cv_chaos_jettysynbomber); - CV_RegisterVar(&cv_chaos_jettysyngunner); - CV_RegisterVar(&cv_chaos_eggmobile1); - CV_RegisterVar(&cv_chaos_eggmobile2); - CV_RegisterVar(&cv_chaos_skim); - CV_RegisterVar(&cv_chaos_spawnrate); -#endif - CV_RegisterVar(&cv_recycler); CV_RegisterVar(&cv_teleporters); CV_RegisterVar(&cv_superring); @@ -699,6 +672,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_invertmouse2); CV_RegisterVar(&cv_mousesens); CV_RegisterVar(&cv_mousesens2); + CV_RegisterVar(&cv_mouseysens); + CV_RegisterVar(&cv_mouseysens2); CV_RegisterVar(&cv_mousemove); CV_RegisterVar(&cv_mousemove2); @@ -734,9 +709,6 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_height); - // p_fab.c - CV_RegisterVar(&cv_translucency); - CV_RegisterVar(&cv_soundtest); // ingame object placing @@ -3374,18 +3346,6 @@ void D_GameTypeChanged(INT32 lastgametype) switch (gametype) { -#ifdef CHAOSISNOTDEADYET - case GT_CHAOS: - if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits - { - // default settings for chaos: timelimit 2 mins, no pointlimit - CV_SetValue(&cv_pointlimit, 0); - CV_SetValue(&cv_timelimit, 2); - } - if (!cv_itemrespawntime.changed) - CV_SetValue(&cv_itemrespawntime, 90); // respawn sparingly in chaos - break; -#endif case GT_MATCH: case GT_TEAMMATCH: if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits @@ -3905,14 +3865,18 @@ static void Command_Cheats_f(void) { if (COM_CheckParm("off")) { - CV_ResetCheatNetVars(); + if (!(server || (adminplayer == consoleplayer))) + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); + else + CV_ResetCheatNetVars(); return; } if (CV_CheatsEnabled()) { CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed -- Cheats are enabled.\n")); - CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.\n")); + if (server || (adminplayer == consoleplayer)) + CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.\n")); } else CONS_Printf(M_GetText("No CHEAT-marked variables are changed -- Cheats are disabled.\n")); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index c1cc27cea..31a7cf818 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -44,6 +44,7 @@ extern consvar_t cv_invertmouse2; extern consvar_t cv_alwaysfreelook2; extern consvar_t cv_mousemove2; extern consvar_t cv_mousesens2; +extern consvar_t cv_mouseysens2; // normally in p_mobj but the .h is not read extern consvar_t cv_itemrespawntime; @@ -80,7 +81,6 @@ extern consvar_t cv_useranalog, cv_useranalog2; extern consvar_t cv_analog, cv_analog2; extern consvar_t cv_netstat; -extern consvar_t cv_translucency; extern consvar_t cv_splats; extern consvar_t cv_countdowntime; @@ -113,12 +113,6 @@ extern consvar_t cv_ringslinger, cv_soundtest; extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes; -#ifdef CHAOSISNOTDEADYET -extern consvar_t cv_chaos_spawnrate, cv_chaos_bluecrawla, cv_chaos_redcrawla; -extern consvar_t cv_chaos_crawlacommander, cv_chaos_jettysynbomber, cv_chaos_jettysyngunner; -extern consvar_t cv_chaos_eggmobile1, cv_chaos_eggmobile2, cv_chaos_skim; -#endif - #ifdef NEWPING extern consvar_t cv_maxping; #endif diff --git a/src/dehacked.c b/src/dehacked.c index ccb7248e3..2dc9d742e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5052,7 +5052,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ARROWDOWN", // Trapgoyle Demon fire - "S_DEMONFIRE", + "S_DEMONFIRE1", + "S_DEMONFIRE2", + "S_DEMONFIRE3", + "S_DEMONFIRE4", + "S_DEMONFIRE5", + "S_DEMONFIRE6", "S_GFZFLOWERA", "S_GFZFLOWERA2", @@ -7062,7 +7067,6 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_NIGHTOPIANHELPER", // the actual helper object that orbits you // Utility Objects - "MT_CHAOSSPAWNER", "MT_TELEPORTMAN", "MT_ALTVIEWMAN", "MT_CRUMBLEOBJ", // Sound generator for crumbling platform @@ -7453,6 +7457,17 @@ struct { {"FF_FULLBRIGHT",FF_FULLBRIGHT}, {"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSSHIFT",FF_TRANSSHIFT}, + // new preshifted translucency (used in source) + {"FF_TRANS10",FF_TRANS10}, + {"FF_TRANS20",FF_TRANS20}, + {"FF_TRANS30",FF_TRANS30}, + {"FF_TRANS40",FF_TRANS40}, + {"FF_TRANS50",FF_TRANS50}, + {"FF_TRANS60",FF_TRANS60}, + {"FF_TRANS70",FF_TRANS70}, + {"FF_TRANS80",FF_TRANS80}, + {"FF_TRANS90",FF_TRANS90}, + // compatibility // Transparency for SOCs is pre-shifted {"TR_TRANS10",tr_trans10<= 'A' && *word <= 'Z') || (*word >= 'a' && *word <= 'z')) { + ((*word >= 'A' && *word <= 'Z') || (*word >= 'a' && *word <= 'z'))) { r = R_Char2Frame(*word); free(word); return r; diff --git a/src/doomdef.h b/src/doomdef.h index c4896a764..d14cd5ddb 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -144,8 +144,8 @@ extern FILE *logstream; #define VERSIONSTRING "Trunk" #else #define VERSION 201 // Game version -#define SUBVERSION 12 // more precise version number -#define VERSIONSTRING "v2.1.12" +#define SUBVERSION 14 // more precise version number +#define VERSIONSTRING "v2.1.14" // Hey! If you change this, add 1 to the MODVERSION below! // Otherwise we can't force updates! #endif @@ -203,7 +203,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 17 +#define MODVERSION 19 @@ -449,10 +449,6 @@ extern const char *compdate, *comptime, *comprevision; /// Dumps the contents of a network save game upon consistency failure for debugging. //#define DUMPCONSISTENCY -/// Pre-1.08 Chaos gametype code -/// \note Code severely out of date, does not take new enemies/bosses into account. -//#define CHAOSISNOTDEADYET - /// Polyobject fake flat code #define POLYOBJECTS_PLANES diff --git a/src/doomstat.h b/src/doomstat.h index b05b3833c..44cf6feaa 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -103,6 +103,7 @@ extern boolean digital_disabled; extern boolean menuactive; // Menu overlaid? extern UINT8 paused; // Game paused? +extern UINT8 window_notinfocus; // are we in focus? (backend independant -- handles auto pausing and display of "focus lost" message) extern boolean nodrawers; extern boolean noblit; diff --git a/src/g_game.c b/src/g_game.c index 50f30dfca..c59f23c07 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -967,7 +967,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) // why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. - if (paused || P_MenuActivePause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN)) + if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN)) { cmd->angleturn = (INT16)(localangle >> 16); cmd->aiming = G_ClipAimingPitch(&localaiming); @@ -1257,7 +1257,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) //why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. - if (paused || P_MenuActivePause() || player->playerstate == PST_REBORN) + if (paused || P_AutoPause() || player->playerstate == PST_REBORN) { cmd->angleturn = (INT16)(localangle2 >> 16); cmd->aiming = G_ClipAimingPitch(&localaiming2); @@ -2299,11 +2299,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- DM/Tag/CTF-spectator/etc -- // Order: DM->CTF->Coop else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF - || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT)) -#ifdef CHAOSISNOTDEADYET - || gametype == GT_CHAOS -#endif - ) + || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) { if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start && !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start @@ -2709,9 +2705,6 @@ INT16 G_TOLFlag(INT32 pgametype) if (pgametype == GT_RACE) return TOL_RACE; if (pgametype == GT_MATCH) return TOL_MATCH; if (pgametype == GT_TEAMMATCH) return TOL_MATCH; -#ifdef CHAOSISNOTDEADYET - if (pgametype == GT_CHAOS) return TOL_CHAOS; -#endif if (pgametype == GT_TAG) return TOL_TAG; if (pgametype == GT_HIDEANDSEEK) return TOL_TAG; if (pgametype == GT_CTF) return TOL_CTF; diff --git a/src/g_input.c b/src/g_input.c index f8170dd3a..f12ddb711 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -28,6 +28,8 @@ static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several" // mouse values are used once consvar_t cv_mousesens = {"mousesens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mousesens2 = {"mousesens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mouseysens = {"mouseysens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mouseysens2 = {"mouseysens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; INT32 mousex, mousey; @@ -99,7 +101,7 @@ void G_MapEventsToControls(event_t *ev) case ev_mouse: // buttons are virtual keys mousex = (INT32)(ev->data2*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f)); mousey = (INT32)(ev->data3*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f)); - mlooky = mousey; + mlooky = (INT32)(ev->data3*((cv_mouseysens.value*cv_mousesens.value)/110.0f + 0.1f)); break; case ev_joystick: // buttons are virtual keys @@ -121,7 +123,7 @@ void G_MapEventsToControls(event_t *ev) case ev_mouse2: // buttons are virtual keys mouse2x = (INT32)(ev->data2*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); mouse2y = (INT32)(ev->data3*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); - mlook2y = mouse2y; + mlook2y = (INT32)(ev->data3*((cv_mouseysens2.value*cv_mousesens2.value)/110.0f + 0.1f)); break; default: diff --git a/src/g_input.h b/src/g_input.h index 699542a8a..eca40591f 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -125,7 +125,7 @@ typedef enum } gamecontrols_e; // mouse values are used once -extern consvar_t cv_mousesens; +extern consvar_t cv_mousesens, cv_mouseysens; extern INT32 mousex, mousey; extern INT32 mlooky; //mousey with mlookSensitivity diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index ee68edd41..fb369387f 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -278,6 +278,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[SMALLREDBALL_L], // SPR_TRLS &lspr[NOLIGHT], // SPR_CBLL &lspr[NOLIGHT], // SPR_AROW + &lspr[NOLIGHT], // SPR_CFIR // Greenflower Scenery &lspr[NOLIGHT], // SPR_FWR1 diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ae940d96c..9d7101db8 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3796,7 +3796,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) }*/ // shadow is always half as translucent as the sprite itself - if (spr->mobj->flags2 & MF2_SHADOW) + if (!cv_translucency.value) + ; // translucency disabled + else if (spr->mobj->flags2 & MF2_SHADOW) sSurf.FlatColor.s.alpha = 0x20; else if (spr->mobj->frame & FF_TRANSMASK) { diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index 5cc075cea..eb9a31a7d 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -39,7 +39,7 @@ #ifdef DEBUG_TO_FILE static unsigned long nb_frames = 0; static clock_t my_clock; -FILE *logstream; +FILE *gllogstream; #endif static HDC hDC = NULL; // the window's device context @@ -81,8 +81,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module // Initialize once for each new process. // Return FALSE to fail DLL load. #ifdef DEBUG_TO_FILE - logstream = fopen("ogllog.txt", "wt"); - if (logstream == NULL) + gllogstream = fopen("ogllog.txt", "wt"); + if (gllogstream == NULL) return FALSE; #endif DisableThreadLibraryCalls(hinstDLL); @@ -99,10 +99,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module case DLL_PROCESS_DETACH: // Perform any necessary cleanup. #ifdef DEBUG_TO_FILE - if (logstream) + if (gllogstream) { - fclose(logstream); - logstream = NULL; + fclose(gllogstream); + gllogstream = NULL; } #endif break; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 028bc9889..76543e259 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -168,7 +168,6 @@ static boolean gl13 = false; // whether we can use opengl 1.3 functions // : else do nothing // Returns : // -----------------+ -#if !(defined (HAVE_SDL) && defined (STATIC3DS)) FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) { #ifdef DEBUG_TO_FILE @@ -178,13 +177,12 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) va_start (arglist, lpFmt); vsnprintf (str, 4096, lpFmt, arglist); va_end (arglist); - if (logstream) - fwrite(str, strlen(str), 1, logstream); + if (gllogstream) + fwrite(str, strlen(str), 1, gllogstream); #else (void)lpFmt; #endif } -#endif #ifdef STATIC_OPENGL /* 1.0 functions */ @@ -673,7 +671,7 @@ static void GLProject(GLdouble objX, GLdouble objY, GLdouble objZ, // -----------------+ void SetModelView(GLint w, GLint h) { - DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); +// DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); screen_width = w; screen_height = h; @@ -714,7 +712,7 @@ void SetStates(void) GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; #endif - DBG_Printf("SetStates()\n"); +// DBG_Printf("SetStates()\n"); // Hurdler: not necessary, is it? pglShadeModel(GL_SMOOTH); // iterate vertice colors diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index f4d4f77e0..7ffefbb58 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -57,9 +57,19 @@ #undef DEBUG_TO_FILE // maybe defined in previous *.h #define DEBUG_TO_FILE // output debugging msgs to ogllog.txt -#if defined ( HAVE_SDL ) && !defined ( LOGMESSAGES ) + +// todo: find some way of getting SDL to log to ogllog.txt, without +// interfering with r_opengl.dll +#ifdef HAVE_SDL #undef DEBUG_TO_FILE #endif +//#if defined(HAVE_SDL) && !defined(_DEBUG) +//#undef DEBUG_TO_FILE +//#endif + +#ifdef DEBUG_TO_FILE +extern FILE *gllogstream; +#endif #ifndef DRIVER_STRING // #define USE_PALETTED_TEXTURE @@ -117,9 +127,6 @@ extern PFNglGetString pglGetString; extern const GLubyte *gl_extensions; extern RGBA_t myPaletteData[]; -#ifndef HAVE_SDL -extern FILE *logstream; -#endif extern GLint screen_width; extern GLint screen_height; extern GLbyte screen_depth; diff --git a/src/info.c b/src/info.c index c8f754b54..fb30258c3 100644 --- a/src/info.c +++ b/src/info.c @@ -37,23 +37,23 @@ char sprnames[NUMSPRITES + 1][5] = "STEM","SPIK","SFLM","USPK","STPT","BMNE","SRBX","RRBX","BRBX","SHTV", "PINV","YLTV","BLTV","BKTV","WHTV","GRTV","ELTV","EGGB","MIXU","RECY", "QUES","GBTV","PRUP","PTTV","MTEX","MISL","TORP","ENRG","MINE","JBUL", - "TRLS","CBLL","AROW","FWR1","FWR2","FWR3","FWR4","BUS1","BUS2","THZP", - "ALRM","GARG","SEWE","DRIP","CRL1","CRL2","CRL3","BCRY","CHAN","FLAM", - "ESTA","SMCH","BMCH","SMCE","BMCE","BTBL","STBL","CACT","FLME","DFLM", - "XMS1","XMS2","XMS3","BSZ1","BSZ2","BSZ3","BSZ4","BSZ5","BSZ6","BSZ7", - "BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN","ELEM", - "FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC","COWZ", - "RBRD","SPRY","SPRR","SPRB","YSPR","RSPR","RAIN","SNO1","SPLH","SPLA", - "SMOK","BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR", - "DRWN","TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS", - "RNGG","PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR", - "COIN","CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP", - "BFLM","MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK", - "NBMP","HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3", - "BOM4","ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII", - "ROIJ","ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR", - "SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ", - "SRBK","SRBL","SRBM","SRBN","SRBO", + "TRLS","CBLL","AROW","CFIR","FWR1","FWR2","FWR3","FWR4","BUS1","BUS2", + "THZP","ALRM","GARG","SEWE","DRIP","CRL1","CRL2","CRL3","BCRY","CHAN", + "FLAM","ESTA","SMCH","BMCH","SMCE","BMCE","BTBL","STBL","CACT","FLME", + "DFLM","XMS1","XMS2","XMS3","BSZ1","BSZ2","BSZ3","BSZ4","BSZ5","BSZ6", + "BSZ7","BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN", + "ELEM","FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC", + "COWZ","RBRD","SPRY","SPRR","SPRB","YSPR","RSPR","RAIN","SNO1","SPLH", + "SPLA","SMOK","BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL", + "SCOR","DRWN","TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE", + "RNGS","RNGG","PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE", + "TSCR","COIN","CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM", + "KOOP","BFLM","MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL", + "NSPK","NBMP","HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2", + "BOM3","BOM4","ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH", + "ROII","ROIJ","ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG", + "GWLR","SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI", + "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -61,6 +61,9 @@ state_t states[NUMSTATES] = { // frame is masked through FF_FRAMEMASK // FF_FULLBRIGHT (0x8000) activates the fullbright colormap + // use FF_TRANS10 - FF_TRANS90 for easy translucency + // (or tr_trans10<typeoflevel & TOL_COMPETITION)) || (cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) || ((cv_newgametype.value == GT_MATCH || cv_newgametype.value == GT_TEAMMATCH) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_MATCH)) || -#ifdef CHAOSISNOTDEADYET - (cv_newgametype.value == GT_CHAOS && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_CHAOS)) || -#endif ((cv_newgametype.value == GT_TAG || cv_newgametype.value == GT_HIDEANDSEEK) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_TAG)) || (cv_newgametype.value == GT_CTF && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_CTF))) { @@ -3468,11 +3466,6 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) return true; -#ifdef CHAOSISNOTDEADYET - if (gt == GT_CHAOS && (mapheaderinfo[mapnum]->typeoflevel & TOL_CHAOS)) - return true; -#endif - return false; case LLM_LEVELSELECT: diff --git a/src/p_enemy.c b/src/p_enemy.c index 54e151123..18a4ec5ff 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2715,14 +2715,6 @@ void A_BossDeath(mobj_t *mo) P_LinedefExecute(LE_BOSSDEAD, mo, NULL); mo->health = 0; -#ifdef CHAOSISNOTDEADYET - if (mo->flags2 & MF2_CHAOSBOSS) - { - P_RemoveMobj(mo); - return; - } -#endif - // Boss is dead (but not necessarily fleeing...) // Lua may use this to ignore bosses after they start fleeing mo->flags2 |= MF2_BOSSDEAD; @@ -5635,10 +5627,11 @@ void A_MixUp(mobj_t *actor) // void A_RecyclePowers(mobj_t *actor) { -#ifdef WEIGHTEDRECYCLER INT32 i, j, k, numplayers = 0; +#ifdef WEIGHTEDRECYCLER UINT8 beneficiary = 255; +#endif UINT8 playerslist[MAXPLAYERS]; UINT8 postscramble[MAXPLAYERS]; @@ -5651,6 +5644,11 @@ void A_RecyclePowers(mobj_t *actor) return; #endif +#if !defined(WEIGHTEDRECYCLER) && !defined(HAVE_BLUA) + // actor is used in all scenarios but this one, funny enough + (void)actor; +#endif + if (!multiplayer) return; @@ -5665,9 +5663,11 @@ void A_RecyclePowers(mobj_t *actor) numplayers++; postscramble[j] = playerslist[j] = (UINT8)i; +#ifdef WEIGHTEDRECYCLER // The guy who started the recycle gets the best result if (actor && actor->target && actor->target->player && &players[i] == actor->target->player) beneficiary = (UINT8)i; +#endif // Save powers for (k = 0; k < NUMPOWERS; k++) @@ -5684,6 +5684,13 @@ void A_RecyclePowers(mobj_t *actor) return; //nobody to touch! //shuffle the post scramble list, whee! + // hardcoded 0-1 to 1-0 for two players + if (numplayers == 2) + { + postscramble[0] = playerslist[1]; + postscramble[1] = playerslist[0]; + } + else for (j = 0; j < numplayers; j++) { UINT8 tempint; @@ -5694,6 +5701,7 @@ void A_RecyclePowers(mobj_t *actor) postscramble[i] = tempint; } +#ifdef WEIGHTEDRECYCLER //the joys of qsort... if (beneficiary != 255) { qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare); @@ -5710,6 +5718,7 @@ void A_RecyclePowers(mobj_t *actor) } } } +#endif // now assign! for (i = 0; i < numplayers; i++) @@ -5737,137 +5746,6 @@ void A_RecyclePowers(mobj_t *actor) P_RestoreMusic(&players[recv_pl]); P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10); } -#else - INT32 i, numplayers = 0; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RecyclePowers", actor)) - return; -#endif - if (!multiplayer) - return; - - numplayers = 0; - - // Count the number of players in the game - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !players[i].powers[pw_super] && !((netgame || multiplayer) && players[i].spectator)) - numplayers++; - - if (numplayers <= 1) - return; //nobody to touch! - - else if (numplayers == 2) //simple swap is all that's needed - { - UINT16 temp[NUMPOWERS]; - INT32 weapons; - INT32 weaponheld; - - INT32 one = -1, two = 0; // default value 0 to make the compiler shut up - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !players[i].powers[pw_super] && !((netgame || multiplayer) && players[i].spectator)) - { - if (one == -1) - one = i; - else - two = i; - } - for (i = 0; i < NUMPOWERS; i++) - { - if (i == pw_flashing || i == pw_underwater || i == pw_spacetime - || i == pw_tailsfly || i == pw_extralife || i == pw_super || i == pw_nocontrol) - continue; - temp[i] = players[one].powers[i]; - players[one].powers[i] = players[two].powers[i]; - players[two].powers[i] = temp[i]; - } - //1.1: weapons need to be swapped too - weapons = players[one].ringweapons; - players[one].ringweapons = players[two].ringweapons; - players[two].ringweapons = weapons; - - weaponheld = players[one].currentweapon; - players[one].currentweapon = players[two].currentweapon; - players[two].currentweapon = weaponheld; - - P_SpawnShieldOrb(players[one].mo->player); - P_SpawnShieldOrb(players[two].mo->player); - P_FlashPal(&players[one], PAL_RECYCLE, 10); - P_FlashPal(&players[two], PAL_RECYCLE, 10); - //piece o' cake, eh? - } - else - { - //well, the cake is a LIE! - UINT16 temp[MAXPLAYERS][NUMPOWERS]; - INT32 weapons[MAXPLAYERS]; - INT32 weaponheld[MAXPLAYERS]; - INT32 counter = 0, j = 0, prandom = 0, recyclefrom = 0; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] - && !((netgame || multiplayer) && players[i].spectator)) - { - for (j = 0; j < NUMPOWERS; j++) - temp[counter][j] = players[i].powers[j]; - //1.1: ring weapons too - weapons[counter] = players[i].ringweapons; - weaponheld[counter] = players[i].currentweapon; - counter++; - } - } - counter = 0; - - // Mix them up! - for (;;) - { - if (counter > 255) // fail-safe to avoid endless loop - break; - prandom = P_Random(); - prandom %= numplayers; // I love modular arithmetic, don't you? - if (prandom) // Make sure it's not a useless mix - break; - counter++; - } - - counter = 0; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] - && !((netgame || multiplayer) && players[i].spectator)) - { - recyclefrom = (counter + prandom) % numplayers; - for (j = 0; j < NUMPOWERS; j++) - { - if (j == pw_flashing || j == pw_underwater || j == pw_spacetime - || j == pw_tailsfly || j == pw_extralife || j == pw_super || j == pw_nocontrol) - continue; - players[i].powers[j] = temp[recyclefrom][j]; - } - //1.1: weapon rings too - players[i].ringweapons = weapons[recyclefrom]; - players[i].currentweapon = weaponheld[recyclefrom]; - - P_SpawnShieldOrb(players[i].mo->player); - P_FlashPal(&players[i], PAL_RECYCLE, 10); - counter++; - } - } - } - for (i = 0; i < MAXPLAYERS; i++) //just for sneakers/invinc. - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] - && !((netgame || multiplayer) && players[i].spectator)) - if (P_IsLocalPlayer(players[i].mo->player)) - P_RestoreMusic(players[i].mo->player); -#endif S_StartSound(NULL, sfx_gravch); //heh, the sound effect I used is already in } @@ -6160,13 +6038,7 @@ void A_Boss2Pogo(mobj_t *actor) goop->momy = FixedMul(FINESINE(fa),ns); goop->momz = FixedMul(4*FRACUNIT, actor->scale); - -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS) - goop->fuse = 5*TICRATE; - else -#endif - goop->fuse = 10*TICRATE; + goop->fuse = 10*TICRATE; } actor->reactiontime = 0; // we already shot goop, so don't do it again! if (actor->info->attacksound) diff --git a/src/p_fab.c b/src/p_fab.c index 77abccccd..7ccb93a94 100644 --- a/src/p_fab.c +++ b/src/p_fab.c @@ -11,124 +11,5 @@ /// \brief some new action routines, separated from the original doom /// sources, so that you can include it or remove it easy. -#include "doomdef.h" -#include "g_game.h" -#include "p_local.h" -#include "m_random.h" - -static void Translucency_OnChange(void); - -/** \brief cv_translucency - console variables to turn on and off translucency -*/ -consvar_t cv_translucency = {"translucency", "On", CV_CALL|CV_SAVE, CV_OnOff, - Translucency_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -/** \brief Reset Translucency -*/ - -static boolean resettrans = false; - -/** \brief The R_SetTrans function - Set the translucency map for each frame state of mobj - - \param state1 1st state - \param state2 last state - \param transmap translucency - - \return void - - -*/ -static void R_SetTrans(statenum_t state1, statenum_t state2, transnum_t transmap) -{ - state_t *state = &states[state1]; - - do - { - state->frame &= ~FF_TRANSMASK; - if (!resettrans) - state->frame |= (transmap<player->score /= 2; // Halve the player's score in Chaos Mode - else -#endif if (gametype == GT_MATCH && cv_match_scoring.value == 0 // note, no team match suicide penalty && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) { // Suicide penalty @@ -1896,39 +1864,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) { INT32 score = 0; -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS) - { - if ((target->flags & MF_ENEMY) - && !(target->flags & MF_MISSILE)) - source->player->scoreadd++; - - switch (target->type) - { - case MT_BLUECRAWLA: - case MT_GOOMBA: - score = 100*source->player->scoreadd; - break; - case MT_REDCRAWLA: - case MT_BLUEGOOMBA: - score = 150*source->player->scoreadd; - break; - case MT_JETTBOMBER: - score = 400*source->player->scoreadd; - break; - case MT_JETTGUNNER: - score = 500*source->player->scoreadd; - break; - case MT_CRAWLACOMMANDER: - score = 300*source->player->scoreadd; - break; - default: - score = 100*source->player->scoreadd; - break; - } - } - else -#endif if (maptol & TOL_NIGHTS) // Enemies always worth 200, bosses don't do anything. { if ((target->flags & MF_ENEMY) && !(target->flags & (MF_MISSILE|MF_BOSS))) @@ -2089,9 +2024,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) // This determines the kind of object spawned // during the death frame of a thing. if (!mariomode // Don't show birds, etc. in Mario Mode Tails 12-23-2001 -#ifdef CHAOSISNOTDEADYET - && gametype != GT_CHAOS // Or Chaos Mode! -#endif && target->flags & MF_ENEMY) { if (cv_soniccd.value) @@ -2512,11 +2444,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj return false; // In COOP/RACE/CHAOS, you can't hurt other players unless cv_friendlyfire is on - if (!cv_friendlyfire.value && (G_PlatformGametype() -#ifdef CHAOSISNOTDEADYET - || gametype == GT_CHAOS -#endif - )) + if (!cv_friendlyfire.value && (G_PlatformGametype())) return false; // Tag handling @@ -2843,17 +2771,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (target->health > 1) { - -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS && source && source->player) - { - player = source->player; - if (!((player->pflags & PF_USEDOWN) && player->dashspeed - && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING))) - player->scoreadd++; - P_AddPlayerScore(player, 300*player->scoreadd); - } -#endif if (target->info->painsound) S_StartSound(target, target->info->painsound); @@ -2882,14 +2799,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (target->health > 1) target->flags2 |= MF2_FRET; - -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS && source && source->player) - { - source->player->scoreadd++; - P_AddPlayerScore(source->player, 300*source->player->scoreadd); - } -#endif } #ifdef HAVE_BLUA else if (target->flags & MF_ENEMY) diff --git a/src/p_local.h b/src/p_local.h index 9f8918cd8..0b27c40f3 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -144,7 +144,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives); UINT8 P_GetNextEmerald(void); void P_GiveEmerald(boolean spawnObj); void P_ResetScore(player_t *player); -boolean P_MenuActivePause(void); +boolean P_AutoPause(void); void P_DoJumpShield(player_t *player); void P_BlackOw(player_t *player); diff --git a/src/p_mobj.c b/src/p_mobj.c index e85e25b05..cac4bc24b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1354,6 +1354,133 @@ static void P_SceneryXYMovement(mobj_t *mo) P_SceneryXYFriction(mo, oldx, oldy); } +// +// P_AdjustMobjFloorZ_FFloors +// +// Utility function for P_ZMovement and related +// Adjusts mo->floorz/mo->ceiling accordingly for FFloors +// +// "motype" determines what behaviour to use exactly +// This is to keep things consistent in case these various object types NEED to be different +// +// motype options: +// 0 - normal +// 1 - forces false check for water (rings) +// 2 - forces false check for water + different quicksand behaviour (scenery) +// +static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype) +{ + ffloor_t *rover; + fixed_t delta1, delta2, thingtop; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + thingtop = mo->z + mo->height; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected + ; + else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only + continue; + else if (rover->flags & FF_QUICKSAND) // quicksand + ; + else if (!((rover->flags & FF_BLOCKPLAYER && mo->player) // solid to players? + || (rover->flags & FF_BLOCKOTHERS && !mo->player))) // solid to others? + continue; + if (rover->flags & FF_QUICKSAND) + { + switch (motype) + { + case 2: // scenery does things differently for some reason + if (mo->z < *rover->topheight && *rover->bottomheight < thingtop) + { + mo->floorz = mo->z; + continue; + } + break; + default: + if (mo->z < *rover->topheight && *rover->bottomheight < thingtop) + { + if (mo->floorz < mo->z) + mo->floorz = mo->z; + } + continue; // This is so you can jump/spring up through quicksand from below. + } + } + + delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); + delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); + if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2) + && !(rover->flags & FF_REVERSEPLATFORM)) + { + mo->floorz = *rover->topheight; + } + if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) + && !(rover->flags & FF_PLATFORM)) + { + mo->ceilingz = *rover->bottomheight; + } + } +} + +// +// P_AdjustMobjFloorZ_PolyObjs +// +// Utility function for P_ZMovement and related +// Adjusts mo->floorz/mo->ceiling accordingly for PolyObjs +// +static void P_AdjustMobjFloorZ_PolyObjs(mobj_t *mo, subsector_t *subsec) +{ + polyobj_t *po = subsec->polyList; + sector_t *polysec; + fixed_t delta1, delta2, thingtop; + fixed_t polytop, polybottom; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + thingtop = mo->z + mo->height; + + while(po) + { + if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID)) + { + po = (polyobj_t *)(po->link.next); + continue; + } + + // We're inside it! Yess... + polysec = po->lines[0]->backsector; + + if (po->flags & POF_CLIPPLANES) + { + polytop = polysec->ceilingheight; + polybottom = polysec->floorheight; + } + else + { + polytop = INT32_MAX; + polybottom = INT32_MIN; + } + + delta1 = mo->z - (polybottom + ((polytop - polybottom)/2)); + delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); + + if (polytop > mo->floorz && abs(delta1) < abs(delta2)) + mo->floorz = polytop; + + if (polybottom < mo->ceilingz && abs(delta1) >= abs(delta2)) + mo->ceilingz = polybottom; + + po = (polyobj_t *)(po->link.next); + } +} + static void P_RingZMovement(mobj_t *mo) { I_Assert(mo != NULL); @@ -1361,43 +1488,9 @@ static void P_RingZMovement(mobj_t *mo) // Intercept the stupid 'fall through 3dfloors' bug if (mo->subsector->sector->ffloors) - { - ffloor_t *rover; - fixed_t delta1, delta2; - INT32 thingtop = mo->z + mo->height; - - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - if ((!(rover->flags & FF_BLOCKOTHERS || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE))) - continue; - - if (rover->flags & FF_QUICKSAND) - { - if (mo->z < *rover->topheight && *rover->bottomheight < thingtop) - { - if (mo->floorz < mo->z) - mo->floorz = mo->z; - } - continue; - } - - delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2) - && (!(rover->flags & FF_REVERSEPLATFORM))) - { - mo->floorz = *rover->topheight; - } - if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) - && (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM))) - { - mo->ceilingz = *rover->bottomheight; - } - } - } + P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 1); + if (mo->subsector->polyList) + P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector); // adjust height if (mo->pmomz && mo->z != mo->floorz) @@ -1443,7 +1536,7 @@ boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - if ((rover->flags & FF_SWIMMABLE) && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + 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 > *rover->topheight - FixedMul(16*FRACUNIT, mo->scale))) return true; @@ -1464,55 +1557,9 @@ static boolean P_ZMovement(mobj_t *mo) // Intercept the stupid 'fall through 3dfloors' bug if (mo->subsector->sector->ffloors) - { - ffloor_t *rover; - fixed_t delta1, delta2, thingtop = mo->z + mo->height; - - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) - { -#if 0 // I question the utility of having four seperate z movement functions. - if (!(rover->flags & FF_EXISTS) - || (!((((rover->flags & FF_BLOCKPLAYER) && mo->player) - || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) || rover->flags & FF_QUICKSAND) - || (rover->flags & FF_SWIMMABLE))) - { - continue; - } -#else - if (!(rover->flags & FF_EXISTS)) - continue; - - if (mo->player && P_CheckSolidLava(mo, rover)) // only the player should be affected - ; - else if (!((((rover->flags & FF_BLOCKPLAYER) && mo->player) - || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) - || rover->flags & FF_QUICKSAND)) - continue; -#endif - if (rover->flags & FF_QUICKSAND) - { - if (mo->z < *rover->topheight && *rover->bottomheight < thingtop) - { - if (mo->floorz < mo->z) - mo->floorz = mo->z; - } - continue; - } - - delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2) - && (!(rover->flags & FF_REVERSEPLATFORM))) - { - mo->floorz = *rover->topheight; - } - if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) - && (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM))) - { - mo->ceilingz = *rover->bottomheight; - } - } - } + P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0); + if (mo->subsector->polyList) + P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector); // adjust height if (mo->pmomz && mo->z != mo->floorz) @@ -1922,45 +1969,9 @@ static void P_PlayerZMovement(mobj_t *mo) // Intercept the stupid 'fall through 3dfloors' bug if (mo->subsector->sector->ffloors) - { - ffloor_t *rover; - fixed_t delta1, delta2; - INT32 thingtop = mo->z + mo->height; - - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - if (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover)) - ; - else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) - continue; - - if (rover->flags & FF_QUICKSAND) - { - if (mo->z < *rover->topheight && *rover->bottomheight < thingtop) - { - if (mo->floorz < mo->z) - mo->floorz = mo->z; - } - continue; // This is so you can jump/spring up through quicksand from below. - } - - delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2) - && (!(rover->flags & FF_REVERSEPLATFORM))) - { - mo->floorz = *rover->topheight; - } - if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) - && (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM))) - { - mo->ceilingz = *rover->bottomheight; - } - } - } + P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0); + if (mo->subsector->polyList) + P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector); // check for smooth step up if ((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height > mo->ceilingz) @@ -2052,26 +2063,24 @@ static void P_PlayerZMovement(mobj_t *mo) while(po) { - if (!P_MobjInsidePolyobj(po, mo)) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - polysec = po->lines[0]->backsector; - - // Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red - if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && (po->flags & POF_SOLID) && po->thinker) - stopmovecut = true; - - if (!(po->flags & POF_LDEXEC) - || !(po->flags & POF_SOLID)) + if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID)) { po = (polyobj_t *)(po->link.next); continue; } // We're inside it! Yess... + polysec = po->lines[0]->backsector; + + // Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red + if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && po->thinker) + stopmovecut = true; + + if (!(po->flags & POF_LDEXEC)) + { + po = (polyobj_t *)(po->link.next); + continue; + } if (mo->z == polysec->ceilingheight) { @@ -2241,42 +2250,9 @@ static boolean P_SceneryZMovement(mobj_t *mo) { // Intercept the stupid 'fall through 3dfloors' bug if (mo->subsector->sector->ffloors) - { - ffloor_t *rover; - fixed_t delta1, delta2; - INT32 thingtop = mo->z + mo->height; - - for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - if ((!(rover->flags & FF_BLOCKOTHERS || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE))) - continue; - - if (rover->flags & FF_QUICKSAND) - { - if (mo->z < *rover->topheight && *rover->bottomheight < thingtop) - { - mo->floorz = mo->z; - continue; - } - } - - delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); - if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2) - && (!(rover->flags & FF_REVERSEPLATFORM))) - { - mo->floorz = *rover->topheight; - } - if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) - && (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM))) - { - mo->ceilingz = *rover->bottomheight; - } - } - } + P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 2); + if (mo->subsector->polyList) + P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector); // adjust height if (mo->pmomz && mo->z != mo->floorz) @@ -3371,11 +3347,7 @@ static void P_Boss2Thinker(mobj_t *mobj) if (!mobj->movecount) mobj->flags2 &= ~MF2_FRET; - if (!mobj->tracer -#ifdef CHAOSISNOTDEADYET - && gametype != GT_CHAOS -#endif - ) + if (!mobj->tracer) { var1 = 0; A_BossJetFume(mobj); @@ -3398,11 +3370,7 @@ static void P_Boss2Thinker(mobj_t *mobj) return; } - if (mobj->state == &states[mobj->info->spawnstate] && mobj->health > mobj->info->damage -#ifdef CHAOSISNOTDEADYET - && gametype != GT_CHAOS -#endif - ) + if (mobj->state == &states[mobj->info->spawnstate] && mobj->health > mobj->info->damage) A_Boss2Chase(mobj); else if (mobj->health > 0 && mobj->state != &states[mobj->info->painstate] && mobj->state != &states[mobjinfo[mobj->info->missilestate].raisestate]) { @@ -5116,32 +5084,6 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale) } } -// Returns true if no boss with health is in the level. -// Used for Chaos mode - -#ifdef CHAOSISNOTDEADYET -static boolean P_BossDoesntExist(void) -{ - thinker_t *th; - mobj_t *mo2; - - // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->flags & MF_BOSS && mo2->health) - return false; - } - - // No boss found! - return true; -} -#endif - void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on your target { fixed_t dist, ndist, speedmul; @@ -6130,14 +6072,6 @@ void P_MobjThinker(mobj_t *mobj) return; } -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS && mobj->target->health <= 0) - { - P_RemoveMobj(mobj); - return; - } -#endif - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); @@ -6209,14 +6143,6 @@ void P_MobjThinker(mobj_t *mobj) return; } -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS && mobj->target->health <= 0) - { - P_RemoveMobj(mobj); - return; - } -#endif - 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)); @@ -6239,13 +6165,6 @@ void P_MobjThinker(mobj_t *mobj) return; } -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS && mobj->target->health <= 0) - { - P_RemoveMobj(mobj); - return; - } -#endif P_UnsetThingPosition(mobj); mobj->x = mobj->target->x; mobj->y = mobj->target->y; @@ -6677,148 +6596,6 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s } P_RemoveMobj(mobj); // make sure they disappear return; - case MT_CHAOSSPAWNER: // Chaos Mode spawner thingy - { - // 8 enemies: Blue Crawla, Red Crawla, Crawla Commander, - // Jett-Synn Bomber, Jett-Synn Gunner, Skim, - // Egg Mobile, Egg Slimer. - // Max. 3 chances per enemy. - -#ifdef CHAOSISNOTDEADYET - - mobjtype_t spawnchance[8*3], enemy; - mobj_t *spawnedmo; - INT32 i = 0, numchoices = 0, stop; - fixed_t sfloorz, space, airspace, spawnz[8*3]; - - sfloorz = mobj->floorz; - space = mobj->ceilingz - sfloorz; - - // This makes the assumption there is no gravity-defying water. - // A fair assumption to make, if you ask me. - airspace = min(space, mobj->ceilingz - mobj->watertop); - - mobj->fuse = cv_chaos_spawnrate.value*TICRATE; - prandom = P_Random(); // Gotta love those random numbers! - - if (cv_chaos_bluecrawla.value && space >= mobjinfo[MT_BLUECRAWLA].height) - { - stop = i + cv_chaos_bluecrawla.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_BLUECRAWLA; - spawnz[i] = sfloorz; - numchoices++; - } - } - if (cv_chaos_redcrawla.value && space >= mobjinfo[MT_REDCRAWLA].height) - { - stop = i + cv_chaos_redcrawla.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_REDCRAWLA; - spawnz[i] = sfloorz; - numchoices++; - } - } - if (cv_chaos_crawlacommander.value - && space >= mobjinfo[MT_CRAWLACOMMANDER].height + 33*FRACUNIT) - { - stop = i + cv_chaos_crawlacommander.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_CRAWLACOMMANDER; - spawnz[i] = sfloorz + 33*FRACUNIT; - numchoices++; - } - } - if (cv_chaos_jettysynbomber.value - && airspace >= mobjinfo[MT_JETTBOMBER].height + 33*FRACUNIT) - { - stop = i + cv_chaos_jettysynbomber.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_JETTBOMBER; - spawnz[i] = max(sfloorz, mobj->watertop) + 33*FRACUNIT; - numchoices++; - } - } - if (cv_chaos_jettysyngunner.value - && airspace >= mobjinfo[MT_JETTGUNNER].height + 33*FRACUNIT) - { - stop = i + cv_chaos_jettysyngunner.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_JETTGUNNER; - spawnz[i] = max(sfloorz, mobj->watertop) + 33*FRACUNIT; - numchoices++; - } - } - if (cv_chaos_skim.value - && mobj->watertop < mobj->ceilingz - mobjinfo[MT_SKIM].height - && mobj->watertop - sfloorz > mobjinfo[MT_SKIM].height/2) - { - stop = i + cv_chaos_skim.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_SKIM; - spawnz[i] = mobj->watertop; - numchoices++; - } - } - if (P_BossDoesntExist()) - { - if (cv_chaos_eggmobile1.value - && space >= mobjinfo[MT_EGGMOBILE].height + 33*FRACUNIT) - { - stop = i + cv_chaos_eggmobile1.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_EGGMOBILE; - spawnz[i] = sfloorz + 33*FRACUNIT; - numchoices++; - } - } - if (cv_chaos_eggmobile2.value - && space >= mobjinfo[MT_EGGMOBILE2].height + 33*FRACUNIT) - { - stop = i + cv_chaos_eggmobile2.value; - for (; i < stop; i++) - { - spawnchance[i] = MT_EGGMOBILE2; - spawnz[i] = sfloorz + 33*FRACUNIT; - numchoices++; - } - } - } - - if (numchoices) - { - fixed_t fogz; - - i = prandom % numchoices; - enemy = spawnchance[i]; - - fogz = spawnz[i] - 32*FRACUNIT; - if (fogz < sfloorz) - fogz = sfloorz; - - spawnedmo = P_SpawnMobj(mobj->x, mobj->y, spawnz[i], enemy); - P_SpawnMobj(mobj->x, mobj->y, fogz, MT_TFOG); - - P_SupermanLook4Players(spawnedmo); - if (spawnedmo->target && spawnedmo->type != MT_SKIM) - P_SetMobjState(spawnedmo, spawnedmo->info->seestate); - - if (spawnedmo->flags & MF_BOSS) - { - spawnedmo->flags2 |= MF2_CHAOSBOSS; - spawnedmo->momx = spawnedmo->momy = 0; - } - } -#endif - break; - } case MT_METALSONIC_BATTLE: break; // don't remove case MT_SPIKE: @@ -8178,7 +7955,8 @@ void P_SpawnMapThing(mapthing_t *mthing) if (i == NUMMOBJTYPES) { - if (mthing->type == 3328) // 3D Mode start Thing + if (mthing->type == 3328 // 3D Mode start Thing + || mthing->type == 750) // Chaos mode spawn return; CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); i = MT_UNKNOWN; @@ -8597,15 +8375,6 @@ ML_NOCLIMB : Direction not controllable if (mthing->angle > 0) mobj->health = mthing->angle; break; - case MT_CHAOSSPAWNER: -#ifndef CHAOSISNOTDEADYET - return; -#else - if (gametype != GT_CHAOS) - return; - mobj->fuse = P_Random()*2; - break; -#endif case MT_TRAPGOYLE: case MT_TRAPGOYLEUP: case MT_TRAPGOYLEDOWN: diff --git a/src/p_pspr.h b/src/p_pspr.h index 339dd1f96..e0b57675c 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -43,6 +43,16 @@ #define FF_TRANSMASK 0xf0000 /// \brief shift for FF_TRANSMASK #define FF_TRANSSHIFT 16 +/// \brief preshifted translucency flags +#define FF_TRANS10 (tr_trans10<type == MT_HOOP) + return; + + // These are NEVER saved. + if (mobj->type == MT_HOOPCOLLIDE) + return; + + // This hoop has already been collected. + if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242) + return; + + if (mobj->spawnpoint && mobj->info->doomednum != -1) + { + // spawnpoint is not modified but we must save it since it is an identifier + diff = MD_SPAWNPOINT; + + if ((mobj->x != mobj->spawnpoint->x << FRACBITS) || + (mobj->y != mobj->spawnpoint->y << FRACBITS) || + (mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT))) + diff |= MD_POS; + + if (mobj->info->doomednum != mobj->spawnpoint->type) + diff |= MD_TYPE; + } + else + diff = MD_POS | MD_TYPE; // not a map spawned thing so make it from scratch + + diff2 = 0; + + // not the default but the most probable + if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0) + diff |= MD_MOM; + if (mobj->radius != mobj->info->radius) + diff |= MD_RADIUS; + if (mobj->height != mobj->info->height) + diff |= MD_HEIGHT; + if (mobj->flags != mobj->info->flags) + diff |= MD_FLAGS; + if (mobj->flags2) + diff |= MD_FLAGS2; + if (mobj->health != mobj->info->spawnhealth) + diff |= MD_HEALTH; + if (mobj->reactiontime != mobj->info->reactiontime) + diff |= MD_RTIME; + if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) + diff |= MD_STATE; + if (mobj->tics != mobj->state->tics) + diff |= MD_TICS; + if (mobj->sprite != mobj->state->sprite) + diff |= MD_SPRITE; + if (mobj->frame != mobj->state->frame) + diff |= MD_FRAME; + if (mobj->eflags) + diff |= MD_EFLAGS; + if (mobj->player) + diff |= MD_PLAYER; + + if (mobj->movedir) + diff |= MD_MOVEDIR; + if (mobj->movecount) + diff |= MD_MOVECOUNT; + if (mobj->threshold) + diff |= MD_THRESHOLD; + if (mobj->lastlook != -1) + diff |= MD_LASTLOOK; + if (mobj->target) + diff |= MD_TARGET; + if (mobj->tracer) + diff |= MD_TRACER; + if (mobj->friction != ORIG_FRICTION) + diff |= MD_FRICTION; + if (mobj->movefactor != ORIG_FRICTION_FACTOR) + diff |= MD_MOVEFACTOR; + if (mobj->fuse) + diff |= MD_FUSE; + if (mobj->watertop) + diff |= MD_WATERTOP; + if (mobj->waterbottom) + diff |= MD_WATERBOTTOM; + if (mobj->scale != FRACUNIT) + diff |= MD_SCALE; + if (mobj->destscale != mobj->scale) + diff |= MD_DSCALE; + if (mobj->scalespeed != FRACUNIT/12) + diff2 |= MD2_SCALESPEED; + + if (mobj == redflag) + diff |= MD_REDFLAG; + if (mobj == blueflag) + diff |= MD_BLUEFLAG; + + if (mobj->cusval) + diff2 |= MD2_CUSVAL; + if (mobj->cvmem) + diff2 |= MD2_CVMEM; + if (mobj->color) + diff2 |= MD2_COLOR; + if (mobj->skin) + diff2 |= MD2_SKIN; + if (mobj->extravalue1) + diff2 |= MD2_EXTVAL1; + if (mobj->extravalue2) + diff2 |= MD2_EXTVAL2; + if (mobj->hnext) + diff2 |= MD2_HNEXT; + if (mobj->hprev) + diff2 |= MD2_HPREV; + if (diff2 != 0) + diff |= MD_MORE; + + // Scrap all of that. If we're a hoop center, this is ALL we're saving. + if (mobj->type == MT_HOOPCENTER) + diff = MD_SPAWNPOINT; + + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, diff); + if (diff & MD_MORE) + WRITEUINT16(save_p, diff2); + + // save pointer, at load time we will search this pointer to reinitilize pointers + WRITEUINT32(save_p, (size_t)mobj); + + WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise. + WRITEFIXED(save_p, mobj->floorz); + WRITEFIXED(save_p, mobj->ceilingz); + + if (diff & MD_SPAWNPOINT) + { + size_t z; + + for (z = 0; z < nummapthings; z++) + if (&mapthings[z] == mobj->spawnpoint) + WRITEUINT16(save_p, z); + if (mobj->type == MT_HOOPCENTER) + return; + } + + if (diff & MD_TYPE) + WRITEUINT32(save_p, mobj->type); + if (diff & MD_POS) + { + WRITEFIXED(save_p, mobj->x); + WRITEFIXED(save_p, mobj->y); + WRITEANGLE(save_p, mobj->angle); + } + if (diff & MD_MOM) + { + WRITEFIXED(save_p, mobj->momx); + WRITEFIXED(save_p, mobj->momy); + WRITEFIXED(save_p, mobj->momz); + } + if (diff & MD_RADIUS) + WRITEFIXED(save_p, mobj->radius); + if (diff & MD_HEIGHT) + WRITEFIXED(save_p, mobj->height); + if (diff & MD_FLAGS) + WRITEUINT32(save_p, mobj->flags); + if (diff & MD_FLAGS2) + WRITEUINT32(save_p, mobj->flags2); + if (diff & MD_HEALTH) + WRITEINT32(save_p, mobj->health); + if (diff & MD_RTIME) + WRITEINT32(save_p, mobj->reactiontime); + if (diff & MD_STATE) + WRITEUINT16(save_p, mobj->state-states); + if (diff & MD_TICS) + WRITEINT32(save_p, mobj->tics); + if (diff & MD_SPRITE) + WRITEUINT16(save_p, mobj->sprite); + if (diff & MD_FRAME) + WRITEUINT32(save_p, mobj->frame); + if (diff & MD_EFLAGS) + WRITEUINT8(save_p, mobj->eflags); + if (diff & MD_PLAYER) + WRITEUINT8(save_p, mobj->player-players); + if (diff & MD_MOVEDIR) + WRITEANGLE(save_p, mobj->movedir); + if (diff & MD_MOVECOUNT) + WRITEINT32(save_p, mobj->movecount); + if (diff & MD_THRESHOLD) + WRITEINT32(save_p, mobj->threshold); + if (diff & MD_LASTLOOK) + WRITEINT32(save_p, mobj->lastlook); + if (diff & MD_TARGET) + WRITEUINT32(save_p, mobj->target->mobjnum); + if (diff & MD_TRACER) + WRITEUINT32(save_p, mobj->tracer->mobjnum); + if (diff & MD_FRICTION) + WRITEFIXED(save_p, mobj->friction); + if (diff & MD_MOVEFACTOR) + WRITEFIXED(save_p, mobj->movefactor); + if (diff & MD_FUSE) + WRITEINT32(save_p, mobj->fuse); + if (diff & MD_WATERTOP) + WRITEFIXED(save_p, mobj->watertop); + if (diff & MD_WATERBOTTOM) + WRITEFIXED(save_p, mobj->waterbottom); + if (diff & MD_SCALE) + WRITEFIXED(save_p, mobj->scale); + if (diff & MD_DSCALE) + WRITEFIXED(save_p, mobj->destscale); + if (diff2 & MD2_SCALESPEED) + WRITEFIXED(save_p, mobj->scalespeed); + if (diff2 & MD2_CUSVAL) + WRITEINT32(save_p, mobj->cusval); + if (diff2 & MD2_CVMEM) + WRITEINT32(save_p, mobj->cvmem); + if (diff2 & MD2_SKIN) + WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins)); + if (diff2 & MD2_COLOR) + WRITEUINT8(save_p, mobj->color); + if (diff2 & MD2_EXTVAL1) + WRITEINT32(save_p, mobj->extravalue1); + if (diff2 & MD2_EXTVAL2) + WRITEINT32(save_p, mobj->extravalue2); + if (diff2 & MD2_HNEXT) + WRITEUINT32(save_p, mobj->hnext->mobjnum); + if (diff2 & MD2_HPREV) + WRITEUINT32(save_p, mobj->hprev->mobjnum); + + WRITEUINT32(save_p, mobj->mobjnum); +} + // // SaveSpecialLevelThinker // @@ -1395,9 +1630,6 @@ static inline void SaveWhatThinker(const thinker_t *th, const UINT8 type) static void P_NetArchiveThinkers(void) { const thinker_t *th; - const mobj_t *mobj; - UINT32 diff; - UINT16 diff2; WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS); @@ -1406,230 +1638,8 @@ static void P_NetArchiveThinkers(void) { if (th->function.acp1 == (actionf_p1)P_MobjThinker) { - mobj = (const mobj_t *)th; - - // Ignore stationary hoops - these will be respawned from mapthings. - if (mobj->type == MT_HOOP) - continue; - - // These are NEVER saved. - if (mobj->type == MT_HOOPCOLLIDE) - continue; - - // This hoop has already been collected. - if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242) - continue; - - if (mobj->spawnpoint && mobj->info->doomednum != -1) - { - // spawnpoint is not modified but we must save it since it is an identifier - diff = MD_SPAWNPOINT; - - if ((mobj->x != mobj->spawnpoint->x << FRACBITS) || - (mobj->y != mobj->spawnpoint->y << FRACBITS) || - (mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT))) - diff |= MD_POS; - - if (mobj->info->doomednum != mobj->spawnpoint->type) - diff |= MD_TYPE; - } - else - diff = MD_POS | MD_TYPE; // not a map spawned thing so make it from scratch - - diff2 = 0; - - // not the default but the most probable - if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0) - diff |= MD_MOM; - if (mobj->radius != mobj->info->radius) - diff |= MD_RADIUS; - if (mobj->height != mobj->info->height) - diff |= MD_HEIGHT; - if (mobj->flags != mobj->info->flags) - diff |= MD_FLAGS; - if (mobj->flags2) - diff |= MD_FLAGS2; - if (mobj->health != mobj->info->spawnhealth) - diff |= MD_HEALTH; - if (mobj->reactiontime != mobj->info->reactiontime) - diff |= MD_RTIME; - if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) - diff |= MD_STATE; - if (mobj->tics != mobj->state->tics) - diff |= MD_TICS; - if (mobj->sprite != mobj->state->sprite) - diff |= MD_SPRITE; - if (mobj->frame != mobj->state->frame) - diff |= MD_FRAME; - if (mobj->eflags) - diff |= MD_EFLAGS; - if (mobj->player) - diff |= MD_PLAYER; - - if (mobj->movedir) - diff |= MD_MOVEDIR; - if (mobj->movecount) - diff |= MD_MOVECOUNT; - if (mobj->threshold) - diff |= MD_THRESHOLD; - if (mobj->lastlook != -1) - diff |= MD_LASTLOOK; - if (mobj->target) - diff |= MD_TARGET; - if (mobj->tracer) - diff |= MD_TRACER; - if (mobj->friction != ORIG_FRICTION) - diff |= MD_FRICTION; - if (mobj->movefactor != ORIG_FRICTION_FACTOR) - diff |= MD_MOVEFACTOR; - if (mobj->fuse) - diff |= MD_FUSE; - if (mobj->watertop) - diff |= MD_WATERTOP; - if (mobj->waterbottom) - diff |= MD_WATERBOTTOM; - if (mobj->scale != FRACUNIT) - diff |= MD_SCALE; - if (mobj->destscale != mobj->scale) - diff |= MD_DSCALE; - if (mobj->scalespeed != FRACUNIT/12) - diff2 |= MD2_SCALESPEED; - - if (mobj == redflag) - diff |= MD_REDFLAG; - if (mobj == blueflag) - diff |= MD_BLUEFLAG; - - if (mobj->cusval) - diff2 |= MD2_CUSVAL; - if (mobj->cvmem) - diff2 |= MD2_CVMEM; - if (mobj->color) - diff2 |= MD2_COLOR; - if (mobj->skin) - diff2 |= MD2_SKIN; - if (mobj->extravalue1) - diff2 |= MD2_EXTVAL1; - if (mobj->extravalue2) - diff2 |= MD2_EXTVAL2; - if (mobj->hnext) - diff2 |= MD2_HNEXT; - if (mobj->hprev) - diff2 |= MD2_HPREV; - if (diff2 != 0) - diff |= MD_MORE; - - // Scrap all of that. If we're a hoop center, this is ALL we're saving. - if (mobj->type == MT_HOOPCENTER) - diff = MD_SPAWNPOINT; - - WRITEUINT8(save_p, tc_mobj); - WRITEUINT32(save_p, diff); - if (diff & MD_MORE) - WRITEUINT16(save_p, diff2); - - // save pointer, at load time we will search this pointer to reinitilize pointers - WRITEUINT32(save_p, (size_t)mobj); - - WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise. - WRITEFIXED(save_p, mobj->floorz); - WRITEFIXED(save_p, mobj->ceilingz); - - if (diff & MD_SPAWNPOINT) - { - size_t z; - - for (z = 0; z < nummapthings; z++) - if (&mapthings[z] == mobj->spawnpoint) - WRITEUINT16(save_p, z); - if (mobj->type == MT_HOOPCENTER) - continue; - } - - if (diff & MD_TYPE) - WRITEUINT32(save_p, mobj->type); - if (diff & MD_POS) - { - WRITEFIXED(save_p, mobj->x); - WRITEFIXED(save_p, mobj->y); - WRITEANGLE(save_p, mobj->angle); - } - if (diff & MD_MOM) - { - WRITEFIXED(save_p, mobj->momx); - WRITEFIXED(save_p, mobj->momy); - WRITEFIXED(save_p, mobj->momz); - } - if (diff & MD_RADIUS) - WRITEFIXED(save_p, mobj->radius); - if (diff & MD_HEIGHT) - WRITEFIXED(save_p, mobj->height); - if (diff & MD_FLAGS) - WRITEUINT32(save_p, mobj->flags); - if (diff & MD_FLAGS2) - WRITEUINT32(save_p, mobj->flags2); - if (diff & MD_HEALTH) - WRITEINT32(save_p, mobj->health); - if (diff & MD_RTIME) - WRITEINT32(save_p, mobj->reactiontime); - if (diff & MD_STATE) - WRITEUINT16(save_p, mobj->state-states); - if (diff & MD_TICS) - WRITEINT32(save_p, mobj->tics); - if (diff & MD_SPRITE) - WRITEUINT16(save_p, mobj->sprite); - if (diff & MD_FRAME) - WRITEUINT32(save_p, mobj->frame); - if (diff & MD_EFLAGS) - WRITEUINT8(save_p, mobj->eflags); - if (diff & MD_PLAYER) - WRITEUINT8(save_p, mobj->player-players); - if (diff & MD_MOVEDIR) - WRITEANGLE(save_p, mobj->movedir); - if (diff & MD_MOVECOUNT) - WRITEINT32(save_p, mobj->movecount); - if (diff & MD_THRESHOLD) - WRITEINT32(save_p, mobj->threshold); - if (diff & MD_LASTLOOK) - WRITEINT32(save_p, mobj->lastlook); - if (diff & MD_TARGET) - WRITEUINT32(save_p, mobj->target->mobjnum); - if (diff & MD_TRACER) - WRITEUINT32(save_p, mobj->tracer->mobjnum); - if (diff & MD_FRICTION) - WRITEFIXED(save_p, mobj->friction); - if (diff & MD_MOVEFACTOR) - WRITEFIXED(save_p, mobj->movefactor); - if (diff & MD_FUSE) - WRITEINT32(save_p, mobj->fuse); - if (diff & MD_WATERTOP) - WRITEFIXED(save_p, mobj->watertop); - if (diff & MD_WATERBOTTOM) - WRITEFIXED(save_p, mobj->waterbottom); - if (diff & MD_SCALE) - WRITEFIXED(save_p, mobj->scale); - if (diff & MD_DSCALE) - WRITEFIXED(save_p, mobj->destscale); - if (diff2 & MD2_SCALESPEED) - WRITEFIXED(save_p, mobj->scalespeed); - if (diff2 & MD2_CUSVAL) - WRITEINT32(save_p, mobj->cusval); - if (diff2 & MD2_CVMEM) - WRITEINT32(save_p, mobj->cvmem); - if (diff2 & MD2_SKIN) - WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins)); - if (diff2 & MD2_COLOR) - WRITEUINT8(save_p, mobj->color); - if (diff2 & MD2_EXTVAL1) - WRITEINT32(save_p, mobj->extravalue1); - if (diff2 & MD2_EXTVAL2) - WRITEINT32(save_p, mobj->extravalue2); - if (diff2 & MD2_HNEXT) - WRITEUINT32(save_p, mobj->hnext->mobjnum); - if (diff2 & MD2_HPREV) - WRITEUINT32(save_p, mobj->hprev->mobjnum); - - WRITEUINT32(save_p, mobj->mobjnum); + SaveMobjThinker(th, tc_mobj); + continue; } #ifdef PARANOIA else if (th->function.acp1 == (actionf_p1)P_RainThinker @@ -1862,6 +1872,232 @@ static inline player_t *LoadPlayer(UINT32 player) return &players[player]; } +// +// LoadMobjThinker +// +// Loads a mobj_t from a save game +// +static void LoadMobjThinker(actionf_p1 thinker) +{ + thinker_t *next; + mobj_t *mobj; + UINT32 diff; + UINT16 diff2; + INT32 i; + fixed_t z, floorz, ceilingz; + + diff = READUINT32(save_p); + if (diff & MD_MORE) + diff2 = READUINT16(save_p); + else + diff2 = 0; + + next = (void *)(size_t)READUINT32(save_p); + + z = READFIXED(save_p); // Force this so 3dfloor problems don't arise. + floorz = READFIXED(save_p); + ceilingz = READFIXED(save_p); + + if (diff & MD_SPAWNPOINT) + { + UINT16 spawnpointnum = READUINT16(save_p); + + if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case + { + P_SpawnHoopsAndRings(&mapthings[spawnpointnum]); + return; + } + + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + + mobj->spawnpoint = &mapthings[spawnpointnum]; + mapthings[spawnpointnum].mobj = mobj; + } + else + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + + // declare this as a valid mobj as soon as possible. + mobj->thinker.function.acp1 = thinker; + + mobj->z = z; + mobj->floorz = floorz; + mobj->ceilingz = ceilingz; + + if (diff & MD_TYPE) + mobj->type = READUINT32(save_p); + else + { + for (i = 0; i < NUMMOBJTYPES; i++) + if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum) + break; + if (i == NUMMOBJTYPES) + { + if (mobj->spawnpoint) + CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type); + else + CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n"); + I_Error("Savegame corrupted"); + } + mobj->type = i; + } + mobj->info = &mobjinfo[mobj->type]; + if (diff & MD_POS) + { + mobj->x = READFIXED(save_p); + mobj->y = READFIXED(save_p); + mobj->angle = READANGLE(save_p); + } + else + { + mobj->x = mobj->spawnpoint->x << FRACBITS; + mobj->y = mobj->spawnpoint->y << FRACBITS; + mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); + } + if (diff & MD_MOM) + { + mobj->momx = READFIXED(save_p); + mobj->momy = READFIXED(save_p); + mobj->momz = READFIXED(save_p); + } // otherwise they're zero, and the memset took care of it + + if (diff & MD_RADIUS) + mobj->radius = READFIXED(save_p); + else + mobj->radius = mobj->info->radius; + if (diff & MD_HEIGHT) + mobj->height = READFIXED(save_p); + else + mobj->height = mobj->info->height; + if (diff & MD_FLAGS) + mobj->flags = READUINT32(save_p); + else + mobj->flags = mobj->info->flags; + if (diff & MD_FLAGS2) + mobj->flags2 = READUINT32(save_p); + if (diff & MD_HEALTH) + mobj->health = READINT32(save_p); + else + mobj->health = mobj->info->spawnhealth; + if (diff & MD_RTIME) + mobj->reactiontime = READINT32(save_p); + else + mobj->reactiontime = mobj->info->reactiontime; + + if (diff & MD_STATE) + mobj->state = &states[READUINT16(save_p)]; + else + mobj->state = &states[mobj->info->spawnstate]; + if (diff & MD_TICS) + mobj->tics = READINT32(save_p); + else + mobj->tics = mobj->state->tics; + if (diff & MD_SPRITE) + mobj->sprite = READUINT16(save_p); + else + mobj->sprite = mobj->state->sprite; + if (diff & MD_FRAME) + mobj->frame = READUINT32(save_p); + else + mobj->frame = mobj->state->frame; + if (diff & MD_EFLAGS) + mobj->eflags = READUINT8(save_p); + if (diff & MD_PLAYER) + { + i = READUINT8(save_p); + mobj->player = &players[i]; + mobj->player->mo = mobj; + // added for angle prediction + if (consoleplayer == i) + localangle = mobj->angle; + if (secondarydisplayplayer == i) + localangle2 = mobj->angle; + } + if (diff & MD_MOVEDIR) + mobj->movedir = READANGLE(save_p); + if (diff & MD_MOVECOUNT) + mobj->movecount = READINT32(save_p); + if (diff & MD_THRESHOLD) + mobj->threshold = READINT32(save_p); + if (diff & MD_LASTLOOK) + mobj->lastlook = READINT32(save_p); + else + mobj->lastlook = -1; + if (diff & MD_TARGET) + mobj->target = (mobj_t *)(size_t)READUINT32(save_p); + if (diff & MD_TRACER) + mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p); + if (diff & MD_FRICTION) + mobj->friction = READFIXED(save_p); + else + mobj->friction = ORIG_FRICTION; + if (diff & MD_MOVEFACTOR) + mobj->movefactor = READFIXED(save_p); + else + mobj->movefactor = ORIG_FRICTION_FACTOR; + if (diff & MD_FUSE) + mobj->fuse = READINT32(save_p); + if (diff & MD_WATERTOP) + mobj->watertop = READFIXED(save_p); + if (diff & MD_WATERBOTTOM) + mobj->waterbottom = READFIXED(save_p); + if (diff & MD_SCALE) + mobj->scale = READFIXED(save_p); + else + mobj->scale = FRACUNIT; + if (diff & MD_DSCALE) + mobj->destscale = READFIXED(save_p); + else + mobj->destscale = mobj->scale; + if (diff2 & MD2_SCALESPEED) + mobj->scalespeed = READFIXED(save_p); + else + mobj->scalespeed = FRACUNIT/12; + if (diff2 & MD2_CUSVAL) + mobj->cusval = READINT32(save_p); + if (diff2 & MD2_CVMEM) + mobj->cvmem = READINT32(save_p); + if (diff2 & MD2_SKIN) + mobj->skin = &skins[READUINT8(save_p)]; + if (diff2 & MD2_COLOR) + mobj->color = READUINT8(save_p); + if (diff2 & MD2_EXTVAL1) + mobj->extravalue1 = READINT32(save_p); + if (diff2 & MD2_EXTVAL2) + mobj->extravalue2 = READINT32(save_p); + if (diff2 & MD2_HNEXT) + mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p); + if (diff2 & MD2_HPREV) + mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); + + if (diff & MD_REDFLAG) + { + redflag = mobj; + rflagpoint = mobj->spawnpoint; + } + if (diff & MD_BLUEFLAG) + { + blueflag = mobj; + bflagpoint = mobj->spawnpoint; + } + + // set sprev, snext, bprev, bnext, subsector + P_SetThingPosition(mobj); + + mobj->mobjnum = READUINT32(save_p); + + if (mobj->player) + { + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->player->viewz = mobj->z + mobj->height - mobj->player->viewheight; + else + mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; + } + + P_AddThinker(&mobj->thinker); + + mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function +} + // // LoadSpecialLevelThinker // @@ -2131,11 +2367,15 @@ static void LoadPusherThinker(actionf_p1 thinker) static inline void LoadLaserThinker(actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ffloor_t *rover = NULL; ht->thinker.function.acp1 = thinker; ht->sector = LoadSector(READUINT32(save_p)); - ht->ffloor = NULL; ht->sec = LoadSector(READUINT32(save_p)); ht->sourceline = LoadLine(READUINT32(save_p)); + for (rover = ht->sector->ffloors; rover; rover = rover->next) + if (rover->secnum == (size_t)(ht->sec - sectors) + && rover->master == ht->sourceline) + ht->ffloor = rover; P_AddThinker(&ht->thinker); } @@ -2333,13 +2573,8 @@ static void P_NetUnArchiveThinkers(void) { thinker_t *currentthinker; thinker_t *next; - mobj_t *mobj; - UINT32 diff; - UINT16 diff2; - INT32 i; UINT8 tclass; UINT8 restoreNum = false; - fixed_t z, floorz, ceilingz; if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS) I_Error("Bad $$$.sav at archive block Thinkers"); @@ -2350,7 +2585,6 @@ static void P_NetUnArchiveThinkers(void) { next = currentthinker->next; - mobj = (mobj_t *)currentthinker; if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it else @@ -2372,216 +2606,7 @@ static void P_NetUnArchiveThinkers(void) switch (tclass) { case tc_mobj: - diff = READUINT32(save_p); - if (diff & MD_MORE) - diff2 = READUINT16(save_p); - else - diff2 = 0; - - next = (void *)(size_t)READUINT32(save_p); - - z = READFIXED(save_p); // Force this so 3dfloor problems don't arise. - floorz = READFIXED(save_p); - ceilingz = READFIXED(save_p); - - if (diff & MD_SPAWNPOINT) - { - UINT16 spawnpointnum = READUINT16(save_p); - - if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case - { - P_SpawnHoopsAndRings(&mapthings[spawnpointnum]); - continue; - } - - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); - - mobj->spawnpoint = &mapthings[spawnpointnum]; - mapthings[spawnpointnum].mobj = mobj; - } - else - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); - - // declare this as a valid mobj as soon as possible. - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; - - mobj->z = z; - mobj->floorz = floorz; - mobj->ceilingz = ceilingz; - - if (diff & MD_TYPE) - mobj->type = READUINT32(save_p); - else - { - for (i = 0; i < NUMMOBJTYPES; i++) - if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum) - break; - if (i == NUMMOBJTYPES) - { - if (mobj->spawnpoint) - CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type); - else - CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n"); - I_Error("Savegame corrupted"); - } - mobj->type = i; - } - mobj->info = &mobjinfo[mobj->type]; - if (diff & MD_POS) - { - mobj->x = READFIXED(save_p); - mobj->y = READFIXED(save_p); - mobj->angle = READANGLE(save_p); - } - else - { - mobj->x = mobj->spawnpoint->x << FRACBITS; - mobj->y = mobj->spawnpoint->y << FRACBITS; - mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); - } - if (diff & MD_MOM) - { - mobj->momx = READFIXED(save_p); - mobj->momy = READFIXED(save_p); - mobj->momz = READFIXED(save_p); - } // otherwise they're zero, and the memset took care of it - - if (diff & MD_RADIUS) - mobj->radius = READFIXED(save_p); - else - mobj->radius = mobj->info->radius; - if (diff & MD_HEIGHT) - mobj->height = READFIXED(save_p); - else - mobj->height = mobj->info->height; - if (diff & MD_FLAGS) - mobj->flags = READUINT32(save_p); - else - mobj->flags = mobj->info->flags; - if (diff & MD_FLAGS2) - mobj->flags2 = READUINT32(save_p); - if (diff & MD_HEALTH) - mobj->health = READINT32(save_p); - else - mobj->health = mobj->info->spawnhealth; - if (diff & MD_RTIME) - mobj->reactiontime = READINT32(save_p); - else - mobj->reactiontime = mobj->info->reactiontime; - - if (diff & MD_STATE) - mobj->state = &states[READUINT16(save_p)]; - else - mobj->state = &states[mobj->info->spawnstate]; - if (diff & MD_TICS) - mobj->tics = READINT32(save_p); - else - mobj->tics = mobj->state->tics; - if (diff & MD_SPRITE) - mobj->sprite = READUINT16(save_p); - else - mobj->sprite = mobj->state->sprite; - if (diff & MD_FRAME) - mobj->frame = READUINT32(save_p); - else - mobj->frame = mobj->state->frame; - if (diff & MD_EFLAGS) - mobj->eflags = READUINT8(save_p); - if (diff & MD_PLAYER) - { - i = READUINT8(save_p); - mobj->player = &players[i]; - mobj->player->mo = mobj; - // added for angle prediction - if (consoleplayer == i) - localangle = mobj->angle; - if (secondarydisplayplayer == i) - localangle2 = mobj->angle; - } - if (diff & MD_MOVEDIR) - mobj->movedir = READANGLE(save_p); - if (diff & MD_MOVECOUNT) - mobj->movecount = READINT32(save_p); - if (diff & MD_THRESHOLD) - mobj->threshold = READINT32(save_p); - if (diff & MD_LASTLOOK) - mobj->lastlook = READINT32(save_p); - else - mobj->lastlook = -1; - if (diff & MD_TARGET) - mobj->target = (mobj_t *)(size_t)READUINT32(save_p); - if (diff & MD_TRACER) - mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p); - if (diff & MD_FRICTION) - mobj->friction = READFIXED(save_p); - else - mobj->friction = ORIG_FRICTION; - if (diff & MD_MOVEFACTOR) - mobj->movefactor = READFIXED(save_p); - else - mobj->movefactor = ORIG_FRICTION_FACTOR; - if (diff & MD_FUSE) - mobj->fuse = READINT32(save_p); - if (diff & MD_WATERTOP) - mobj->watertop = READFIXED(save_p); - if (diff & MD_WATERBOTTOM) - mobj->waterbottom = READFIXED(save_p); - if (diff & MD_SCALE) - mobj->scale = READFIXED(save_p); - else - mobj->scale = FRACUNIT; - if (diff & MD_DSCALE) - mobj->destscale = READFIXED(save_p); - else - mobj->destscale = mobj->scale; - if (diff2 & MD2_SCALESPEED) - mobj->scalespeed = READFIXED(save_p); - else - mobj->scalespeed = FRACUNIT/12; - if (diff2 & MD2_CUSVAL) - mobj->cusval = READINT32(save_p); - if (diff2 & MD2_CVMEM) - mobj->cvmem = READINT32(save_p); - if (diff2 & MD2_SKIN) - mobj->skin = &skins[READUINT8(save_p)]; - if (diff2 & MD2_COLOR) - mobj->color = READUINT8(save_p); - if (diff2 & MD2_EXTVAL1) - mobj->extravalue1 = READINT32(save_p); - if (diff2 & MD2_EXTVAL2) - mobj->extravalue2 = READINT32(save_p); - if (diff2 & MD2_HNEXT) - mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p); - if (diff2 & MD2_HPREV) - mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); - - if (diff & MD_REDFLAG) - { - redflag = mobj; - rflagpoint = mobj->spawnpoint; - } - if (diff & MD_BLUEFLAG) - { - blueflag = mobj; - bflagpoint = mobj->spawnpoint; - } - - // set sprev, snext, bprev, bnext, subsector - P_SetThingPosition(mobj); - - mobj->mobjnum = READUINT32(save_p); - - if (mobj->player) - { - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->player->viewz = mobj->z + mobj->height - mobj->player->viewheight; - else - mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; - } - - P_AddThinker(&mobj->thinker); - - mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function + LoadMobjThinker((actionf_p1)P_MobjThinker); break; case tc_ceiling: diff --git a/src/p_setup.c b/src/p_setup.c index ca78db05a..f2b0c49d8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1502,22 +1502,26 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1) { - fixed_t bx2 = bx1 + MAPBLOCKUNITS; - fixed_t by2 = by1 + MAPBLOCKUNITS; - line_t boxline, testline; - vertex_t vbox, vtest; + fixed_t bbox[4]; + line_t testline; + vertex_t vtest; + + bbox[BOXRIGHT] = bx1 + MAPBLOCKUNITS; + bbox[BOXTOP] = by1 + MAPBLOCKUNITS; + bbox[BOXLEFT] = bx1; + bbox[BOXBOTTOM] = by1; // Trivial rejection - if (cx1 < bx1 && cx2 < bx1) + if (cx1 < bbox[BOXLEFT] && cx2 < bbox[BOXLEFT]) return false; - if (cx1 > bx2 && cx2 > bx2) + if (cx1 > bbox[BOXRIGHT] && cx2 > bbox[BOXRIGHT]) return false; - if (cy1 < by1 && cy2 < by1) + if (cy1 < bbox[BOXBOTTOM] && cy2 < bbox[BOXBOTTOM]) return false; - if (cy1 > by2 && cy2 > by2) + if (cy1 > bbox[BOXTOP] && cy2 > bbox[BOXTOP]) return false; // Rats, guess we gotta check @@ -1527,12 +1531,11 @@ static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, f cy1 <<= FRACBITS; cx2 <<= FRACBITS; cy2 <<= FRACBITS; - bx1 <<= FRACBITS; - by1 <<= FRACBITS; - bx2 <<= FRACBITS; - by2 <<= FRACBITS; + bbox[BOXTOP] <<= FRACBITS; + bbox[BOXBOTTOM] <<= FRACBITS; + bbox[BOXLEFT] <<= FRACBITS; + bbox[BOXRIGHT] <<= FRACBITS; - boxline.v1 = &vbox; testline.v1 = &vtest; testline.v1->x = cx1; @@ -1540,47 +1543,12 @@ static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, f testline.dx = cx2 - cx1; testline.dy = cy2 - cy1; - // Test line against bottom edge of box - boxline.v1->x = bx1; - boxline.v1->y = by1; - boxline.dx = bx2 - bx1; - boxline.dy = 0; + if ((testline.dx > 0) ^ (testline.dy > 0)) + testline.slopetype = ST_NEGATIVE; + else + testline.slopetype = ST_POSITIVE; - if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline) - && P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline)) - return true; - - // Right edge of box - boxline.v1->x = bx2; - boxline.v1->y = by1; - boxline.dx = 0; - boxline.dy = by2-by1; - - if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline) - && P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline)) - return true; - - // Top edge of box - boxline.v1->x = bx1; - boxline.v1->y = by2; - boxline.dx = bx2 - bx1; - boxline.dy = 0; - - if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline) - && P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline)) - return true; - - // Left edge of box - boxline.v1->x = bx1; - boxline.v1->y = by1; - boxline.dx = 0; - boxline.dy = by2-by1; - - if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline) - && P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline)) - return true; - - return false; + return P_BoxOnLineSide(bbox, &testline) == -1; } // @@ -2435,11 +2403,8 @@ boolean P_SetupLevel(boolean skipprecip) // chasecam on in chaos, race, coop // chasecam off in match, tag, capture the flag - chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP -#ifdef CHAOSISNOTDEADYET - || gametype == GT_CHAOS -#endif - ) || (maptol & TOL_2D); + chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP) + || (maptol & TOL_2D); if (!dedicated) { diff --git a/src/p_spec.c b/src/p_spec.c index 323b93c6d..8228c60b3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -94,6 +94,7 @@ typedef struct thinker_t **thinkers; } thinkerlist_t; +static void P_SearchForDisableLinedefs(void); static void P_SpawnScrollers(void); static void P_SpawnFriction(void); static void P_SpawnPushers(void); @@ -4776,6 +4777,18 @@ void P_UpdateSpecials(void) } } +static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) +{ + ffloor_t *rover; + + if (!sec->ffloors) + return NULL; + for (rover = sec->ffloors; rover; rover = rover->next) + if (rover->secnum == (size_t)(sec2 - sectors)) + return rover; + return NULL; +} + /** Adds a newly formed 3Dfloor structure to a sector's ffloors list. * * \param sec Target sector. @@ -4822,7 +4835,9 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f size_t i; if (sec == sec2) - return false; //Don't need a fake floor on a control sector. + return NULL; //Don't need a fake floor on a control sector. + if ((ffloor = (P_GetFFloorBySec(sec, sec2)))) + return ffloor; // If this ffloor already exists, return it if (sec2->ceilingheight < sec2->floorheight) { @@ -5312,9 +5327,6 @@ void T_LaserFlash(laserthink_t *flash) ffloor_t *ffloor = flash->ffloor; sector_t *sector = flash->sector; - if (!ffloor) - flash->ffloor = ffloor = P_AddFakeFloor(sector, flash->sec, flash->sourceline, laserflags, NULL); - if (!ffloor || !(ffloor->flags & FF_EXISTS)) return; @@ -5409,6 +5421,10 @@ void P_SpawnSpecials(INT32 fromnetsave) thinkerlist_t *secthinkers; thinker_t *th; + // This used to be used, and *should* be used in the future, + // but currently isn't. + (void)fromnetsave; + // Set the default gravity. Custom gravity overrides this setting. gravity = FRACUNIT/2; @@ -5480,37 +5496,12 @@ void P_SpawnSpecials(INT32 fromnetsave) curWeather = PRECIP_NONE; P_InitTagLists(); // Create xref tables for tags + P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line + P_SpawnScrollers(); // Add generalized scrollers P_SpawnFriction(); // Friction model using linedefs P_SpawnPushers(); // Pusher model using linedefs - // Look for disable linedefs - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 6) - { - // Ability flags can disable disable linedefs now, lol - if (netgame || multiplayer) - { - // future: nonet flag? - } - else if (((lines[i].flags & ML_NETONLY) != ML_NETONLY) - && !(players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) - && !(players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) - && !(players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX ))) - { - for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) - { - lines[j].tag = 0; - lines[j].special = 0; - } - } - lines[i].special = 0; - lines[i].tag = 0; - } - } - - // Look for thinkers that affect FOFs, and sort them by sector secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL); @@ -5993,12 +5984,7 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 160: // Float/bob platform - sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - { - P_AddFakeFloor(§ors[s], §ors[sec], lines + i, - FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB, secthinkers); - } + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB, secthinkers); break; case 170: // Crumbling platform @@ -6043,13 +6029,8 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits - sec = sides[*lines[i].sidenum].sector - sectors; + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers); lines[i].flags |= ML_BLOCKMONSTERS; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - { - P_AddFakeFloor(§ors[s], §ors[sec], lines + i, - FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers); - } P_AddOldAirbob(lines[i].frontsector, lines + i, true); break; @@ -6061,21 +6042,11 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 178: // Crumbling platform that will float when it hits water - sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - { - P_AddFakeFloor(§ors[s], §ors[sec], lines + i, - FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE|FF_FLOATBOB, secthinkers); - } + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE|FF_FLOATBOB, secthinkers); break; case 179: // Crumbling platform that will float when it hits water, but not return - sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - { - P_AddFakeFloor(§ors[s], §ors[sec], lines + i, - FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB|FF_NORETURN, secthinkers); - } + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB|FF_NORETURN, secthinkers); break; case 180: // Air bobbing platform that will crumble @@ -6158,14 +6129,13 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 202: // Fog + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES; sec = sides[*lines[i].sidenum].sector - sectors; // SoM: Because it's fog, check for an extra colormap and set // the fog flag... if (sectors[sec].extra_colormap) sectors[sec].extra_colormap->fog = 1; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - P_AddFakeFloor(§ors[s], §ors[sec], lines + i, - FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES, secthinkers); + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 220: // Like opaque water, but not swimmable. (Good for snow effect on FOFs) @@ -6195,12 +6165,7 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 250: // Mario Block - sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - { - P_AddFakeFloor(§ors[s], §ors[sec], lines + i, - FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers); - } + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers); break; case 251: // A THWOMP! @@ -6247,13 +6212,11 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 258: // Laser block - if (!fromnetsave) // This creates a FOF which disrupts net saves - { - sec = sides[*lines[i].sidenum].sector - sectors; + sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - EV_AddLaserThinker(§ors[s], §ors[sec], lines + i, secthinkers); - } + // No longer totally disrupts netgames + for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + EV_AddLaserThinker(§ors[s], §ors[sec], lines + i, secthinkers); break; case 259: // Make-Your-Own FOF! @@ -7720,3 +7683,39 @@ static void P_SpawnPushers(void) break; } } + +static void P_SearchForDisableLinedefs(void) +{ + size_t i; + INT32 j; + + // Look for disable linedefs + for (i = 0; i < numlines; i++) + { + if (lines[i].special == 6) + { + // Remove special + // Do *not* remove tag. That would mess with the tag lists + // that P_InitTagLists literally just created! + lines[i].special = 0; + + // Ability flags can disable disable linedefs now, lol + if (netgame || multiplayer) + { + // future: nonet flag? + } + else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) + continue; // Net-only never triggers in single player + else if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) + continue; + else if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) + continue; + else if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)) + continue; + + // Disable any linedef specials with our tag. + for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) + lines[j].special = 0; + } + } +} diff --git a/src/p_tick.c b/src/p_tick.c index 3b7d3683b..2973505f3 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -587,7 +587,7 @@ void P_Ticker(boolean run) } // Check for pause or menu up in single player - if (paused || P_MenuActivePause()) + if (paused || P_AutoPause()) return; postimgtype = postimgtype2 = postimg_none; diff --git a/src/p_user.c b/src/p_user.c index 8070a67bd..6844d2cba 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -160,15 +160,17 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move) return FixedMul(move, FINESINE(angle)); } -boolean P_MenuActivePause(void) +// +// P_AutoPause +// Returns true when gameplay should be halted even if the game isn't necessarily paused. +// +boolean P_AutoPause(void) { - if (netgame || !menuactive) + // Don't pause even on menu-up or focus-lost in netgames or record attack + if (netgame || modeattacking) return false; - if (modeattacking) - return false; - - return true; + return (menuactive || window_notinfocus); } // @@ -328,14 +330,10 @@ void P_GiveEmerald(boolean spawnObj) // // P_ResetScore // -// This is called when your chain is reset. If in -// Chaos mode, it displays what chain you got. +// This is called when your chain is reset. void P_ResetScore(player_t *player) { -#ifdef CHAOSISNOTDEADYET - if (gametype == GT_CHAOS && player->scoreadd >= 5) - CONS_Printf(M_GetText("%s got a chain of %u!\n"), player_names[player-players], player->scoreadd); -#endif + // Formally a host for Chaos mode behavior player->scoreadd = 0; } @@ -2540,6 +2538,7 @@ static void P_DoClimbing(player_t *player) thinker_t *think; scroll_t *scroller; angle_t sideangle; + fixed_t dx, dy; for (think = thinkercap.next; think != &thinkercap; think = think->next) { @@ -2554,14 +2553,25 @@ static void P_DoClimbing(player_t *player) if (scroller->affectee != player->lastsidehit) continue; + if (scroller->accel) + { + dx = scroller->vdx; + dy = scroller->vdy; + } + else + { + dx = scroller->dx; + dy = scroller->dy; + } + if (cmd->forwardmove != 0) { - player->mo->momz += scroller->dy; + player->mo->momz += dy; climb = true; } else { - player->mo->momz = scroller->dy; + player->mo->momz = dy; climb = false; } @@ -2569,12 +2579,12 @@ static void P_DoClimbing(player_t *player) if (cmd->sidemove != 0) { - P_Thrust(player->mo, sideangle, scroller->dx); + P_Thrust(player->mo, sideangle, dx); climb = true; } else { - P_InstaThrust(player->mo, sideangle, scroller->dx); + P_InstaThrust(player->mo, sideangle, dx); climb = false; } } @@ -2652,6 +2662,125 @@ static void P_DoClimbing(player_t *player) } } +// +// PIT_CheckSolidsTeeter +// AKA: PIT_HacksToStopPlayersTeeteringOnGargoyles +// + +static mobj_t *teeterer; // the player checking for teetering +static boolean solidteeter; // saves whether the player can teeter on this or not +static fixed_t highesttop; // highest floor found so far +// reserved for standing on multiple objects +static boolean couldteeter; +static fixed_t teeterxl, teeterxh; +static fixed_t teeteryl, teeteryh; + +static boolean PIT_CheckSolidsTeeter(mobj_t *thing) +{ + fixed_t blockdist; + fixed_t tiptop = FixedMul(MAXSTEPMOVE, teeterer->scale); + fixed_t thingtop = thing->z + thing->height; + fixed_t teeterertop = teeterer->z + teeterer->height; + + if (!teeterer || !thing) + return true; + + if (!(thing->flags & MF_SOLID)) + return true; + + if (thing->flags & MF_NOCLIP) + return true; + + if (thing == teeterer) + return true; + + if (thing->player && cv_tailspickup.value && gametype != GT_HIDEANDSEEK) + return true; + + blockdist = teeterer->radius + thing->radius; + + if (abs(thing->x - teeterer->x) >= blockdist || abs(thing->y - teeterer->y) >= blockdist) + return true; // didn't hit it + + if (teeterer->eflags & MFE_VERTICALFLIP) + { + if (thingtop < teeterer->z) + return true; + if (thing->z > highesttop) + return true; + highesttop = thing->z; + if (thing->z > teeterertop + tiptop) + { + solidteeter = true; + return true; + } + } + else + { + if (thing->z > teeterertop) + return true; + if (thingtop < highesttop) + return true; + highesttop = thingtop; + if (thingtop < teeterer->z - tiptop) + { + solidteeter = true; + return true; + } + } + + // are you standing on this? + if ((teeterer->eflags & MFE_VERTICALFLIP && thing->z - FixedMul(FRACUNIT, teeterer->scale) == teeterertop) + || (!(teeterer->eflags & MFE_VERTICALFLIP) && thingtop + FixedMul(FRACUNIT, teeterer->scale) == teeterer->z)) + { + fixed_t teeterdist = thing->radius - FixedMul(5*FRACUNIT, teeterer->scale); + // how far are you from the edge? + if (abs(teeterer->x - thing->x) > teeterdist || abs(teeterer->y - thing->y) > teeterdist) + { + if (couldteeter) // player is standing on another object already, see if we can stand on both and not teeter! + { + if (thing->x - teeterdist < teeterxl) + teeterxl = thing->x - teeterdist; + if (thing->x + teeterdist > teeterxh) + teeterxh = thing->x + teeterdist; + if (thing->y - teeterdist < teeteryl) + teeteryl = thing->y - teeterdist; + if (thing->y + teeterdist > teeteryh) + teeteryh = thing->y + teeterdist; + + if (teeterer->x < teeterxl) + return true; + if (teeterer->x > teeterxh) + return true; + if (teeterer->y < teeteryl) + return true; + if (teeterer->y > teeteryh) + return true; + + solidteeter = false; // you can stop teetering now! + couldteeter = false; // just in case... + return false; + } + else + { + // too far! don't change teeter status though + // save teeter x/y limits to bring up later + teeterxl = thing->x - teeterdist; + teeterxh = thing->x + teeterdist; + teeteryl = thing->y - teeterdist; + teeteryh = thing->y + teeterdist; + } + couldteeter = true; + return true; + } + solidteeter = false; + couldteeter = false; + return false; // you're definitely not teetering, that's the end of the matter + } + solidteeter = false; + return true; // you're not teetering but it's not neccessarily over, YET +} + // // P_DoTeeter // @@ -2826,18 +2955,18 @@ static void P_DoTeeter(player_t *player) } } -#ifdef POLYOBJECTS - // Polyobjects { INT32 bx, by, xl, xh, yl, yh; - validcount++; - yh = (unsigned)(player->mo->y + player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT; yl = (unsigned)(player->mo->y - player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT; xh = (unsigned)(player->mo->x + player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT; xl = (unsigned)(player->mo->x - player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT; + // Polyobjects +#ifdef POLYOBJECTS + validcount++; + for (by = yl; by <= yh; by++) for (bx = xl; bx <= xh; bx++) { @@ -2898,16 +3027,12 @@ static void P_DoTeeter(player_t *player) } if (polybottom > player->mo->z + player->mo->height + tiptop - || (polybottom < player->mo->z - && player->mo->z + player->mo->height < player->mo->ceilingz - tiptop)) - { + || (polybottom < player->mo->z + && player->mo->z + player->mo->height < player->mo->ceilingz - tiptop)) teeter = true; - roverfloor = true; - } else { teeter = false; - roverfloor = true; break; } } @@ -2920,16 +3045,12 @@ static void P_DoTeeter(player_t *player) } if (polytop < player->mo->z - tiptop - || (polytop > player->mo->z + player->mo->height - && player->mo->z > player->mo->floorz + tiptop)) - { + || (polytop > player->mo->z + player->mo->height + && player->mo->z > player->mo->floorz + tiptop)) teeter = true; - roverfloor = true; - } else { teeter = false; - roverfloor = true; break; } } @@ -2937,8 +3058,27 @@ static void P_DoTeeter(player_t *player) plink = (polymaplink_t *)(plink->link.next); } } - } #endif + if (teeter) // only bother with objects as a last resort if you were already teetering + { + mobj_t *oldtmthing = tmthing; + tmthing = teeterer = player->mo; + teeterxl = teeterxh = player->mo->x; + teeteryl = teeteryh = player->mo->y; + couldteeter = false; + solidteeter = teeter; + for (by = yl; by <= yh; by++) + for (bx = xl; bx <= xh; bx++) + { + highesttop = INT32_MIN; + if (!P_BlockThingsIterator(bx, by, PIT_CheckSolidsTeeter)) + goto teeterdone; // we've found something that stops us teetering at all, how about we stop already + } +teeterdone: + teeter = solidteeter; + tmthing = oldtmthing; // restore old tmthing, goodness knows what the game does with this before mobj thinkers + } + } if (teeter) { if ((player->mo->state == &states[S_PLAY_STND] || player->mo->state == &states[S_PLAY_TAP1] || player->mo->state == &states[S_PLAY_TAP2] || player->mo->state == &states[S_PLAY_SUPERSTAND])) diff --git a/src/r_bsp.c b/src/r_bsp.c index e5e0942e3..e967e28ce 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -572,8 +572,8 @@ static boolean R_CheckBBox(fixed_t *bspcoord) py2 = bspcoord[checkcoord[boxpos][3]]; // check clip list for an open space - angle1 = R_PointToAngle(px1, py1) - viewangle; - angle2 = R_PointToAngle(px2, py2) - viewangle; + angle1 = R_PointToAngle2(viewx>>1, viewy>>1, px1>>1, py1>>1) - viewangle; + angle2 = R_PointToAngle2(viewx>>1, viewy>>1, px2>>1, py2>>1) - viewangle; span = angle1 - angle2; @@ -702,21 +702,62 @@ static int R_PolysegCompare(const void *p1, const void *p2) { const seg_t *seg1 = *(const seg_t * const *)p1; const seg_t *seg2 = *(const seg_t * const *)p2; - fixed_t dist1, dist2; + fixed_t dist1v1, dist1v2, dist2v1, dist2v2; // TODO might be a better way to get distance? -#define vxdist(v) FixedMul(R_PointToDist(v->x, v->y), FINECOSINE((R_PointToAngle(v->x, v->y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF +#define pdist(x, y) (FixedMul(R_PointToDist(x, y), FINECOSINE((R_PointToAngle(x, y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF) +#define vxdist(v) pdist(v->x, v->y) - dist1 = min(vxdist(seg1->v1), vxdist(seg1->v2)); - dist2 = min(vxdist(seg2->v1), vxdist(seg2->v2)); + dist1v1 = vxdist(seg1->v1); + dist1v2 = vxdist(seg1->v2); + dist2v1 = vxdist(seg2->v1); + dist2v2 = vxdist(seg2->v2); - if (dist1 == dist2) { // Segs connect toward the front, so use the back verts to determine order! - dist1 = max(vxdist(seg1->v1), vxdist(seg1->v2)); - dist2 = max(vxdist(seg2->v1), vxdist(seg2->v2)); + if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2)) + return min(dist1v1, dist1v2) - min(dist2v1, dist2v2); + + { // That didn't work, so now let's try this....... + fixed_t delta1, delta2, x1, y1, x2, y2; + vertex_t *near1, *near2, *far1, *far2; // wherever you are~ + + delta1 = R_PointToDist2(seg1->v1->x, seg1->v1->y, seg1->v2->x, seg1->v2->y); + delta2 = R_PointToDist2(seg2->v1->x, seg2->v1->y, seg2->v2->x, seg2->v2->y); + + delta1 = FixedDiv(128<v1; + far1 = seg1->v2; + } + else + { + near1 = seg1->v2; + far1 = seg1->v1; + } + + if (dist2v1 < dist2v2) + { + near2 = seg2->v1; + far2 = seg2->v2; + } + else + { + near2 = seg2->v2; + far2 = seg2->v1; + } + + x1 = near1->x + FixedMul(far1->x-near1->x, delta1); + y1 = near1->y + FixedMul(far1->y-near1->y, delta1); + + x2 = near2->x + FixedMul(far2->x-near2->x, delta2); + y2 = near2->y + FixedMul(far2->y-near2->y, delta2); + + return pdist(x1, y1)-pdist(x2, y2); } #undef vxdist - - return dist1-dist2; +#undef pdist } // @@ -835,6 +876,7 @@ static void R_Subsector(size_t num) numffloors = 0; ffloor[numffloors].plane = NULL; + ffloor[numffloors].polyobj = NULL; if (frontsector->ffloors) { ffloor_t *rover; @@ -854,6 +896,7 @@ static void R_Subsector(size_t num) } ffloor[numffloors].plane = NULL; + ffloor[numffloors].polyobj = NULL; if (*rover->bottomheight <= frontsector->ceilingheight && *rover->bottomheight >= frontsector->floorheight && ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) @@ -872,6 +915,7 @@ static void R_Subsector(size_t num) if (numffloors >= MAXFFLOORS) break; ffloor[numffloors].plane = NULL; + ffloor[numffloors].polyobj = NULL; if (*rover->topheight >= frontsector->floorheight && *rover->topheight <= frontsector->ceilingheight && ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) diff --git a/src/r_data.c b/src/r_data.c index 930b70bf5..0aba42750 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -946,10 +946,12 @@ static void R_InitExtraColormaps(void) CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps)); } +// 12/14/14 -- only take flats in F_START/F_END lumpnum_t R_GetFlatNumForName(const char *name) { - lumpnum_t lump = W_CheckNumForName(name); - + lumpnum_t lump = W_CheckNumForNameInBlock(name, "F_START", "F_END"); + if (lump == LUMPERROR) + lump = W_CheckNumForNameInBlock(name, "FF_START", "FF_END"); // deutex, some other old things if (lump == LUMPERROR) { if (strcmp(name, SKYFLATNAME)) diff --git a/src/r_main.c b/src/r_main.c index f2c641f6a..ffd4d5d50 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -162,6 +162,7 @@ consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NU consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1406,6 +1407,7 @@ void R_RegisterEngineStuff(void) return; CV_RegisterVar(&cv_precipdensity); + CV_RegisterVar(&cv_translucency); CV_RegisterVar(&cv_drawdist); CV_RegisterVar(&cv_drawdist_nights); CV_RegisterVar(&cv_drawdist_precip); diff --git a/src/r_main.h b/src/r_main.h index 0d3f2def5..13383451d 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -88,6 +88,7 @@ extern consvar_t cv_homremoval; extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow, cv_shadowoffs; +extern consvar_t cv_translucency; extern consvar_t cv_precipdensity, cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; diff --git a/src/r_segs.c b/src/r_segs.c index c73cfdf9f..7467f5324 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -528,7 +528,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) else xwalllights = scalelight[rlight->lightnum]; - pindex = spryscale>>LIGHTSCALESHIFT; + pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; @@ -573,7 +573,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // calculate lighting - pindex = spryscale>>LIGHTSCALESHIFT; + pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; @@ -1130,8 +1130,8 @@ static void R_RenderSegLoop (void) for (i = 0; i < numffloors; i++) { #ifdef POLYOBJECTS_PLANES - //if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)) - //continue; // Causes issues with FOF planes in The Wall -Red + if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) + continue; // FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red if (curline->polyseg) { @@ -1203,7 +1203,7 @@ static void R_RenderSegLoop (void) if (segtextured) { // calculate lighting - pindex = rw_scale>>LIGHTSCALESHIFT; + pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE-1; @@ -1238,7 +1238,7 @@ static void R_RenderSegLoop (void) else xwalllights = scalelight[lightnum]; - pindex = rw_scale>>LIGHTSCALESHIFT; + pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE-1; @@ -1359,9 +1359,9 @@ static void R_RenderSegLoop (void) for (i = 0; i < numffloors; i++) { -#if 0 //#ifdef POLYOBJECTS_PLANES - if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)) - continue; // Causes issues with FOF planes in The Wall -Red +#ifdef POLYOBJECTS_PLANES + if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) + continue; #endif ffloor[i].f_frac += ffloor[i].f_step; @@ -1371,9 +1371,9 @@ static void R_RenderSegLoop (void) { INT32 y_w; -#if 0 //#ifdef POLYOBJECTS_PLANES - if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)) - continue; // Causes issues with FOF planes in The Wall -Red +#ifdef POLYOBJECTS_PLANES + if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) + continue; #endif y_w = ffloor[i].b_frac >> HEIGHTBITS; @@ -1520,9 +1520,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) { for (i = 0; i < numffloors; i++) { -#if 0 //#ifdef POLYOBJECTS_PLANES - if (ds_p->curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != ds_p->curline->polyseg)) - continue; // Causes issues with FOF planes in The Wall -Red +#ifdef POLYOBJECTS_PLANES + if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg)) + continue; #endif ffloor[i].f_pos = ffloor[i].height - viewz; } @@ -2021,9 +2021,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) { for (i = 0; i < numffloors; i++) { -#if 0 //#ifdef POLYOBJECTS_PLANES - if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)) - continue; // Causes issues with FOF planes in The Wall -Red +#ifdef POLYOBJECTS_PLANES + if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) + continue; #endif ffloor[i].f_pos >>= 4; @@ -2126,7 +2126,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) #ifdef POLYOBJECTS_PLANES if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES)) { - if (i < MAXFFLOORS && backsector->floorheight <= frontsector->ceilingheight && + while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++; + if (i < numffloors && backsector->floorheight <= frontsector->ceilingheight && backsector->floorheight >= frontsector->floorheight && (viewz < backsector->floorheight)) { @@ -2142,7 +2143,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); i++; } - if (i < MAXFFLOORS && backsector->ceilingheight >= frontsector->floorheight && + if (i < numffloors && backsector->ceilingheight >= frontsector->floorheight && backsector->ceilingheight <= frontsector->ceilingheight && (viewz > backsector->ceilingheight)) { diff --git a/src/r_things.c b/src/r_things.c index 6372ddb4c..9a8b1319b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1293,7 +1293,9 @@ static void R_ProjectSprite(mobj_t *thing) vis->transmap = NULL; // specific translucency - if (thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) + if (!cv_translucency.value) + ; // no translucency + else if (thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) vis->transmap = ((tr_trans80-1)<frame & FF_TRANSMASK) vis->transmap = (thing->frame & FF_TRANSMASK) - 0x10000 + transtables; diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 1c438e083..976f7eb35 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -195,15 +195,15 @@ int main(int argc, char **argv) #ifdef LOGMESSAGES #if defined(_WIN32_WCE) || defined(GP2X) - logstream = fopen(va("%s.log",argv[0]), "a"); + logstream = fopen(va("%s.log",argv[0]), "wt"); #elif defined (_WII) - logstream = fopen(va("%s/srb2log.txt",logdir), "a"); + logstream = fopen(va("%s/log.txt",logdir), "wt"); #elif defined (DEFAULTDIR) if (logdir) - logstream = fopen(va("%s/"DEFAULTDIR"/srb2log.txt",logdir), "a"); + logstream = fopen(va("%s/"DEFAULTDIR"/log.txt",logdir), "wt"); else #endif - logstream = fopen("./srb2log.txt", "a"); + logstream = fopen("./log.txt", "wt"); #endif //I_OutputMsg("I_StartupSystem() ...\n"); @@ -228,9 +228,9 @@ int main(int argc, char **argv) #endif #endif // startup SRB2 - CONS_Printf("%s", M_GetText("Setting up SRB2...\n")); + CONS_Printf("Setting up SRB2...\n"); D_SRB2Main(); - CONS_Printf("%s", M_GetText("Entering main game loop...\n")); + 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 a1e91ec75..9c13b716c 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -301,6 +301,7 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; +#if !defined (DC) FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { //static char msg[] = "oh no! back to reality!\r\n"; @@ -318,7 +319,7 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) sigmsg = "SIGILL - illegal instruction - invalid function image"; break; case SIGFPE: - sigmsg = "SIGFPE - floating point exception"; + sigmsg = "SIGFPE - mathematical exception"; break; case SIGSEGV: sigmsg = "SIGSEGV - segment violation"; @@ -339,7 +340,7 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) sigmsg = sigdef; } - I_OutputMsg("signal_handler() error: %s\n", sigmsg); + I_OutputMsg("\nsignal_handler() error: %s\n", sigmsg); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Signal caught", @@ -350,7 +351,6 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) I_Quit(); } -#if !defined (DC) FUNCNORETURN static ATTRNORETURN void quit_handler(int num) { signal(num, SIG_DFL); //default signal action @@ -743,24 +743,15 @@ static inline void I_ShutdownConsole(void){} void I_StartupKeyboard (void) { #if !defined (DC) -#ifdef SIGILL - signal(SIGILL , signal_handler); -#endif -#ifdef SIGINT + // If these defines don't exist, + // then compilation would have failed above us... signal(SIGINT , quit_handler); -#endif -#ifdef SIGSEGV - signal(SIGSEGV , signal_handler); -#endif -#ifdef SIGBREAK signal(SIGBREAK , quit_handler); -#endif -#ifdef SIGABRT - signal(SIGABRT , signal_handler); -#endif -#ifdef SIGTERM signal(SIGTERM , quit_handler); -#endif + signal(SIGILL , signal_handler); + signal(SIGSEGV , signal_handler); + signal(SIGABRT , signal_handler); + signal(SIGFPE , signal_handler); #endif } @@ -2375,62 +2366,38 @@ void I_Error(const char *error, ...) } if (errorcount > 20) { -#ifdef MAC_ALERT va_start(argptr, error); vsprintf(buffer, error, argptr); va_end(argptr); - // 2004-03-03 AJR Since the Mac user is most likely double clicking to run the game, give them a panel. - MacShowAlert("Recursive Error", buffer, "Quit", NULL, NULL); -#elif (defined (_WIN32) || (defined (_WIN32_WCE)) && !defined (__GNUC__)) && !defined (_XBOX) - va_start(argptr,error); - vsprintf(buffer, error, argptr); - va_end(argptr); -#ifndef _WIN32_WCE - { - HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD bytesWritten; - if (co != INVALID_HANDLE_VALUE) - { - if (GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &bytesWritten)) - WriteConsoleA(co, buffer, (DWORD)strlen(buffer), NULL, NULL); - else - WriteFile(co, buffer, (DWORD)strlen(buffer), &bytesWritten, NULL); - } - } -#endif - OutputDebugStringA(buffer); - MessageBoxA(vid.WndParent, buffer, "SRB2 Recursive Error", MB_OK|MB_ICONERROR); -#else - // Don't print garbage - va_start(argptr, error); - if (!framebuffer) - vfprintf (stderr, error, argptr); - va_end(argptr); -#endif + // Implement message box with SDL_ShowSimpleMessageBox, + // which should fail gracefully if it can't put a message box up + // on the target system + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + "SRB2 "VERSIONSTRING" Recursive Error", + buffer, NULL); + W_Shutdown(); + #ifdef GP2X chdir("/usr/gp2x"); execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL); #endif + exit(-1); // recursive errors detected } } - shutdowning = true; - I_ShutdownConsole(); -#ifndef MAC_ALERT - // Message first. - va_start(argptr,error); - if (!framebuffer) - { - fprintf(stderr, "Error: "); - vfprintf(stderr,error,argptr); - fprintf(stderr, "\n"); - } - va_end(argptr); - if (!framebuffer) - fflush(stderr); -#endif + shutdowning = true; + + // Display error message in the console before we start shutting it down + va_start(argptr, error); + vsprintf(buffer, error, argptr); + va_end(argptr); + I_OutputMsg("\nI_Error(): %s\n", buffer); + // --- + + I_ShutdownConsole(); + M_SaveConfig(NULL); // save game config, cvars.. #ifndef NONET D_SaveBan(); // save the ban list @@ -2454,21 +2421,30 @@ void I_Error(const char *error, ...) #ifndef _arch_dreamcast SDL_Quit(); #endif -#ifdef MAC_ALERT - va_start(argptr, error); - vsprintf(buffer, error, argptr); - va_end(argptr); - // 2004-03-03 AJR Since the Mac user is most likely double clicking to run the game, give them a panel. - MacShowAlert("Critical Error", buffer, "Quit", NULL, NULL); -#endif + + // Implement message box with SDL_ShowSimpleMessageBox, + // which should fail gracefully if it can't put a message box up + // on the target system + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + "SRB2 "VERSIONSTRING" Error", + buffer, NULL); + // Note that SDL_ShowSimpleMessageBox does *not* require SDL to be + // initialized at the time, so calling it after SDL_Quit() is + // perfectly okay! In addition, we do this on purpose so the + // fullscreen window is closed before displaying the error message + // in case the fullscreen window blocks it for some absurd reason. + W_Shutdown(); + #if defined (PARANOIA) && defined (__CYGWIN__) - *(INT32 *)2 = 4; //Alam: Debug! + *(INT32 *)2 = 4; //Alam: Debug! #endif + #ifdef GP2X chdir("/usr/gp2x"); execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL); #endif + exit(-1); } @@ -2534,6 +2510,7 @@ void I_ShutdownSystem(void) #ifdef LOGMESSAGES if (logstream) { + I_OutputMsg("I_ShutdownSystem(): end of logstream.\n"); fclose(logstream); logstream = NULL; } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 660263b3f..cddc9e83d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -667,31 +667,28 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) if (mousefocus && kbfocus) { + // Tell game we got focus back, resume music if necessary + window_notinfocus = false; + if (!paused) + I_ResumeSong(0); //resume it + if (!firsttimeonmouse) { if (cv_usemouse.value) I_StartupMouse(); } //else firsttimeonmouse = SDL_FALSE; - if (gamestate == GS_LEVEL) - { - if (!paused) I_ResumeSong(0); //resume it - } } else if (!mousefocus && !kbfocus) { + // Tell game we lost focus, pause music + window_notinfocus = true; + I_PauseSong(0); + if (!disable_mouse) { SDLforceUngrabMouse(); } - if (!netgame && gamestate == GS_LEVEL && !demoplayback && !demorecording && !modeattacking) - { - paused = true; - } memset(gamekeydown, 0, NUMKEYS); // TODO this is a scary memset - if (gamestate == GS_LEVEL) - { - I_PauseSong(0); - } if (MOUSE_MENU) { @@ -1570,7 +1567,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) #ifdef HWRENDER if (rendermode == render_opengl) { - window = SDL_CreateWindow("SRB2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, realwidth, realheight, flags | SDL_WINDOW_OPENGL); if (window != NULL) { @@ -1590,7 +1587,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) #endif if (rendermode == render_soft) { - window = SDL_CreateWindow("SRB2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, realwidth, realheight, flags); if (window != NULL) { @@ -1775,7 +1772,7 @@ void I_StartupGraphics(void) // Create window //Impl_CreateWindow(USE_FULLSCREEN); - //Impl_SetWindowName("SRB2"); + //Impl_SetWindowName("SRB2 "VERSIONSTRING); VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); vid.buffer = NULL; // For software mode @@ -1835,12 +1832,17 @@ void I_ShutdownGraphics(void) bufSurface = NULL; } + I_OutputMsg("I_ShutdownGraphics(): "); + // was graphics initialized anyway? if (!graphics_started) + { + I_OutputMsg("graphics never started\n"); return; - CONS_Printf("I_ShutdownGraphics: "); + } graphics_started = false; - CONS_Printf("%s", M_GetText("shut down\n")); + I_OutputMsg("shut down\n"); + #ifdef HWRENDER if (GLUhandle) hwClose(GLUhandle); diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index a205d30ce..98599fb60 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.12; + CURRENT_PROJECT_VERSION = 2.1.14; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.12; + CURRENT_PROJECT_VERSION = 2.1.14; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj index a205d30ce..98599fb60 100644 --- a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.12; + CURRENT_PROJECT_VERSION = 2.1.14; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.12; + CURRENT_PROJECT_VERSION = 2.1.14; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/st_stuff.c b/src/st_stuff.c index 0d0cb1aef..a9bdacf71 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -203,7 +203,7 @@ void ST_doPaletteStuff(void) { INT32 palette; - if (paused || P_MenuActivePause()) + if (paused || P_AutoPause()) palette = 0; else if (stplyr && stplyr->flashcount) palette = stplyr->flashpal; @@ -1576,15 +1576,6 @@ static inline void ST_drawTeamName(void) V_DrawString(244, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR"); } -#ifdef CHAOSISNOTDEADYET -static inline void ST_drawChaosHUD(void) -{ - char chains[33]; - sprintf(chains, "CHAINS: %u", stplyr->scoreadd); - V_DrawString(8, STRINGY(184), V_HUDTRANSHALF, chains); -} -#endif - static void ST_drawSpecialStageHUD(void) { if (totalrings > 0) @@ -1667,7 +1658,7 @@ static void ST_doHuntIconsAndSound(void) interval = newinterval; } - if (!(P_MenuActivePause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) + if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) S_StartSound(NULL, sfx_emfind); } @@ -1727,7 +1718,7 @@ static void ST_doItemFinderIconsAndSound(void) } } - if (!(P_MenuActivePause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) + if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) S_StartSound(NULL, sfx_emfind); } @@ -1814,12 +1805,6 @@ static void ST_overlayDrawer(void) if (G_GametypeHasTeams()) ST_drawTeamName(); - // Chaos HUD Stuff -#ifdef CHAOSISNOTDEADYET - else if (gametype == GT_CHAOS) - ST_drawChaosHUD(); -#endif - // Special Stage HUD if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayer]) ST_drawSpecialStageHUD(); diff --git a/src/w_wad.c b/src/w_wad.c index adcbb4811..79ed1f478 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -662,6 +662,32 @@ lumpnum_t W_GetNumForName(const char *name) return i; } +// +// W_CheckNumForNameInBlock +// Checks only in blocks from blockstart lump to blockend lump +// +lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend) +{ + INT32 i; + lumpnum_t bsid, beid; + lumpnum_t check = INT16_MAX; + + // scan wad files backwards so patch lump files take precedence + for (i = numwadfiles - 1; i >= 0; i--) + { + bsid = W_CheckNumForNamePwad(blockstart,(UINT16)i,0); + if (bsid == INT16_MAX) + continue; // block doesn't exist, keep going + beid = W_CheckNumForNamePwad(blockend,(UINT16)i,0); + // if block end doesn't exist, just search through everything + + check = W_CheckNumForNamePwad(name,(UINT16)i,bsid); + if (check < beid) + return (i<<16)+check; // found it, in our constraints + } + return LUMPERROR; +} + // Used by Lua. Case sensitive lump checking, quickly... #include "fastcmp.h" UINT8 W_LumpExists(const char *name) diff --git a/src/w_wad.h b/src/w_wad.h index 76f52b004..614b7e4ae 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -102,6 +102,7 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum); UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad lumpnum_t W_CheckNumForName(const char *name); lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR +lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend); UINT8 W_LumpExists(const char *name); // Lua uses this. size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump); diff --git a/src/y_inter.c b/src/y_inter.c index 498afa7cf..2f2edf7ca 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -588,7 +588,7 @@ void Y_Ticker(void) return; // Check for pause or menu up in single player - if (paused || P_MenuActivePause()) + if (paused || P_AutoPause()) return; intertic++; @@ -907,11 +907,7 @@ void Y_StartIntermission(void) intertype = int_teammatch; else if (gametype == GT_MATCH || gametype == GT_TAG - || gametype == GT_HIDEANDSEEK -#ifdef CHAOSISNOTDEADYET - || gametype == GT_CHAOS -#endif - ) + || gametype == GT_HIDEANDSEEK) intertype = int_match; else if (gametype == GT_RACE) intertype = int_race; diff --git a/src/y_inter.h b/src/y_inter.h index 67ab4f4e2..a3620cea7 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -25,9 +25,6 @@ typedef enum int_teammatch,// Team Match // int_tag, // Tag int_ctf, // CTF -#ifdef CHAOSISNOTDEADYET - int_chaos, // Chaos -#endif int_spec, // Special Stage int_nights, // NiGHTS into Dreams int_nightsspec,// NiGHTS special stage