From e486556f4bf9a15490059adcd1114f9a8d91be21 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 27 Jun 2023 01:28:21 -0300 Subject: [PATCH] Refactoring, fix subtle bugs --- src/b_bot.c | 4 ++ src/d_clisrv.c | 20 +++--- src/d_netcmd.c | 15 +++-- src/doomstat.h | 8 ++- src/f_finale.c | 6 +- src/g_demo.c | 2 + src/g_game.c | 57 ++++++++--------- src/hardware/hw_main.c | 8 +++ src/lua_baselib.c | 10 +-- src/lua_script.c | 4 +- src/m_menu.c | 6 +- src/m_misc.c | 8 +-- src/p_enemy.c | 64 +++++++++---------- src/p_floor.c | 4 +- src/p_inter.c | 34 +++++----- src/p_local.h | 28 +++++---- src/p_mobj.c | 53 +++++++++------- src/p_saveg.c | 17 +++-- src/p_setup.c | 83 +++++++++++++------------ src/p_sight.c | 25 +++----- src/p_spec.c | 63 ++++++++++--------- src/p_spec.h | 3 +- src/p_tick.c | 138 +++++++++++++++-------------------------- src/p_user.c | 62 +++++++++--------- src/p_world.c | 63 ++++++++++++------- src/p_world.h | 11 ++++ src/r_bsp.c | 27 ++++---- src/r_fps.c | 4 +- src/r_main.c | 26 ++++---- src/r_portal.c | 2 +- src/r_skins.c | 2 +- src/r_things.c | 3 - src/s_sound.c | 51 ++++++++++----- src/s_sound.h | 13 ++-- src/sdl/mixer_sound.c | 4 +- src/st_stuff.c | 31 ++++----- src/v_video.c | 2 +- src/y_inter.c | 44 ++++++------- 38 files changed, 523 insertions(+), 482 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index d1465f891..a62ddcbba 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -529,6 +529,10 @@ boolean B_CheckRespawn(player_t *player) return false; } + // Not even in the same world? + if (P_GetMobjWorld(sonic) != P_GetMobjWorld(tails)) + return true; + // If you can't see Sonic, I guess we should? if (!P_CheckSight(sonic, tails) && P_AproxDistance(P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y), tails->z-sonic->z) > FixedMul(1024*FRACUNIT, tails->scale)) return true; diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 73f3b8eef..dca3f1e19 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1394,9 +1394,9 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) memset(netbuffer->u.serverinfo.maptitle, 0, sizeof netbuffer->u.serverinfo.maptitle); - if (mapheaderinfo[gamemap-1] && *mapheaderinfo[gamemap-1]->lvlttl) + if (worldmapheader && *worldmapheader->lvlttl) { - char *read = mapheaderinfo[gamemap-1]->lvlttl, *writ = netbuffer->u.serverinfo.maptitle; + char *read = worldmapheader->lvlttl, *writ = netbuffer->u.serverinfo.maptitle; while (writ < (netbuffer->u.serverinfo.maptitle+32) && *read != '\0') { if (!(*read & 0x80)) @@ -1407,18 +1407,18 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) read++; } *writ = '\0'; - //strncpy(netbuffer->u.serverinfo.maptitle, (char *)mapheaderinfo[gamemap-1]->lvlttl, 33); + //strncpy(netbuffer->u.serverinfo.maptitle, (char *)worldmapheader->lvlttl, 33); } else strncpy(netbuffer->u.serverinfo.maptitle, "UNKNOWN", 32); - if (mapheaderinfo[gamemap-1] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + if (worldmapheader && !(worldmapheader->levelflags & LF_NOZONE)) netbuffer->u.serverinfo.iszone = 1; else netbuffer->u.serverinfo.iszone = 0; - if (mapheaderinfo[gamemap-1]) - netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum; + if (worldmapheader) + netbuffer->u.serverinfo.actnum = worldmapheader->actnum; p = PutFileNeeded(0); @@ -1706,12 +1706,12 @@ static void CL_LoadReceivedSavegame(boolean reloading) // load a base level if (P_LoadNetGame(reloading)) { - const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; + const UINT8 actnum = worldmapheader->actnum; CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); - if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, "")) + if (strcmp(worldmapheader->lvlttl, "")) { - CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl); - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + CONS_Printf(": %s", worldmapheader->lvlttl); + if (!(worldmapheader->levelflags & LF_NOZONE)) CONS_Printf(M_GetText(" Zone")); if (actnum > 0) CONS_Printf(" %2d", actnum); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4889b43a4..e933c733c 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1163,7 +1163,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Force skin in effect. - if ((cv_forceskin.value != -1) || (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0')) + if ((cv_forceskin.value != -1) || (worldmapheader && worldmapheader->forcecharacter[0] != '\0')) return false; // Can change skin in intermission and whatnot. @@ -2200,10 +2200,8 @@ static void Got_Switchworld(UINT8 **cp, INT32 playernum) if (nodetach) // Don't detach from the current world, if any { -#if 1 if (player->world) - ((world_t *)player->world)->players--; -#endif + P_GetPlayerWorld(player)->players--; player->world = NULL; } @@ -4385,7 +4383,8 @@ static void Gravity_OnChange(void) if (!CV_IsSetToDefault(&cv_gravity)) G_SetUsedCheats(false); - gravity = cv_gravity.value; + if (world) + world->gravity = cv_gravity.value; } static void SoundTest_OnChange(void) @@ -4578,10 +4577,10 @@ static void Command_Showmap_f(void) { if (gamestate == GS_LEVEL) { - if (mapheaderinfo[gamemap-1]->actnum) - CONS_Printf("%s (%d): %s %d\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum); + if (worldmapheader->actnum) + CONS_Printf("%s (%d): %s %d\n", G_BuildMapName(gamemap), gamemap, worldmapheader->lvlttl, worldmapheader->actnum); else - CONS_Printf("%s (%d): %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl); + CONS_Printf("%s (%d): %s\n", G_BuildMapName(gamemap), gamemap, worldmapheader->lvlttl); } else CONS_Printf(M_GetText("You must be in a level to use this.\n")); diff --git a/src/doomstat.h b/src/doomstat.h index 9487d4146..5ffd34676 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -388,6 +388,10 @@ typedef struct extern mapheader_t* mapheaderinfo[NUMMAPS]; +extern mapheader_t* curmapheader; +extern mapheader_t* nextmapheader; +extern mapheader_t* worldmapheader; + // Gametypes #define NUMGAMETYPEFREESLOTS 128 enum GameType @@ -548,14 +552,12 @@ extern UINT8 useContinues; extern UINT8 shareEmblems; -extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations +#define NUM_EMERALD_HUNT_LOCATIONS 3 // For racing extern UINT32 countdown; extern UINT32 countdown2; -extern fixed_t gravity; - //for CTF balancing extern INT16 autobalance; extern INT16 teamscramble; diff --git a/src/f_finale.c b/src/f_finale.c index 1a4522578..ccc1dfb84 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2431,7 +2431,9 @@ void F_StartTitleScreen(void) P_UnloadWorldList(); - maptol = mapheaderinfo[gamemap-1]->typeoflevel; + curmapheader = nextmapheader = mapheaderinfo[gamemap-1]; + worldmapheader = curmapheader; + maptol = curmapheader->typeoflevel; G_DoLoadLevel(&players[displayplayer], false, true); if (!titlemap) @@ -2477,6 +2479,8 @@ void F_StartTitleScreen(void) gamemap = 1; // g_game.c if (!mapheaderinfo[gamemap-1]) P_AllocMapHeader(gamemap-1); + curmapheader = nextmapheader = mapheaderinfo[gamemap-1]; + worldmapheader = curmapheader; CON_ClearHUD(); } diff --git a/src/g_demo.c b/src/g_demo.c index f6ba1561c..470485a3a 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1868,6 +1868,8 @@ void G_DoPlayDemo(char *defdemoname) } demo_p += 4; // "PLAY" gamemap = READINT16(demo_p); + curmapheader = nextmapheader = mapheaderinfo[gamemap-1]; + worldmapheader = curmapheader; demo_p += 16; // mapmd5 demoflags = READUINT8(demo_p); diff --git a/src/g_game.c b/src/g_game.c index 82615a017..837d4afba 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -164,11 +164,13 @@ mobj_t *blueflag; mapthing_t *rflagpoint; mapthing_t *bflagpoint; -struct quake quake; - // Map Header Information mapheader_t* mapheaderinfo[NUMMAPS] = {NULL}; +mapheader_t* curmapheader = NULL; +mapheader_t* nextmapheader = NULL; +mapheader_t* worldmapheader = NULL; + static boolean exitgame = false; static boolean retrying = false; static boolean retryingmodeattack = false; @@ -221,15 +223,8 @@ UINT8 introtoplay; UINT8 creditscutscene; UINT8 useBlackRock = 1; -// Emerald locations -mobj_t *hunt1; -mobj_t *hunt2; -mobj_t *hunt3; - UINT32 countdown, countdown2; // for racing -fixed_t gravity; - INT16 autobalance; //for CTF team balance INT16 teamscramble; //for CTF team scramble INT16 scrambleplayers[MAXPLAYERS]; //for CTF team scramble @@ -1855,7 +1850,7 @@ void G_DoLoadLevel(player_t *player, boolean addworld, boolean resetplayer) return; } - P_FindEmerald(); + P_FindEmerald(world); displayplayer = consoleplayer; // view the guy you are playing if (!splitscreen && !botingame) @@ -1965,7 +1960,7 @@ boolean G_IsTitleCardAvailable(void) else if (titlecardforreload) titleflag = LF_NOTITLECARDRESPAWN; - if (mapheaderinfo[gamemap-1]->levelflags & titleflag) + if (worldmapheader->levelflags & titleflag) return false; // The current gametype doesn't have a title card. @@ -1973,7 +1968,7 @@ boolean G_IsTitleCardAvailable(void) return false; // The current level has no name. - if (!mapheaderinfo[gamemap-1]->lvlttl[0]) + if (!worldmapheader->lvlttl[0]) return false; // The title card is available. @@ -2654,7 +2649,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) if (betweenmaps || !G_IsSpecialStage(gamemap)) { - rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings); + rings = (ultimatemode ? 0 : curmapheader->startrings); spheres = 0; } else @@ -2769,23 +2764,23 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) { if (mapmusflags & MUSIC_RELOADRESET) { - strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); + strncpy(mapmusname, worldmapheader->musname, 7); mapmusname[6] = 0; - mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); - mapmusposition = mapheaderinfo[gamemap-1]->muspos; + mapmusflags = (worldmapheader->mustrack & MUSIC_TRACKMASK); + mapmusposition = worldmapheader->muspos; } // This is in S_Start, but this was not here previously. - // if (RESETMUSIC) + // if (S_ShouldResetMusic(worldmapheader)) // S_StopMusic(); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } if (gametyperules & GTR_EMERALDHUNT) - P_FindEmerald(); // scan for emeralds to hunt for + P_FindEmerald(p->world); // scan for emeralds to hunt for // If NiGHTS, find lowest mare to start with. - p->mare = P_FindLowestMare(); + p->mare = P_FindLowestMare(p->world); CONS_Debug(DBG_NIGHTS, M_GetText("Current mare is %d\n"), p->mare); @@ -3202,7 +3197,7 @@ void G_DoReborn(INT32 playernum) players[i].starpostnum = 0; } } - if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD) && !(marathonmode & MA_INIT)) + if (!countdowntimeup && (curmapheader->levelflags & LF_NORELOAD) && !(marathonmode & MA_INIT)) { P_RespawnThings(); @@ -3983,11 +3978,11 @@ void G_SetNextMap(boolean usespec, boolean inspec) // nextmap is 0-based, unlike gamemap if (nextmapoverride != 0) nextmap = (INT16)(nextmapoverride-1); - else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext) - nextmap = (INT16)(mapheaderinfo[gamemap-1]->marathonnext-1); + else if (marathonmode && curmapheader->marathonnext) + nextmap = (INT16)(curmapheader->marathonnext-1); else { - nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1); + nextmap = (INT16)(curmapheader->nextlevel-1); if (marathonmode && nextmap == spmarathon_start-1) nextmap = 1100-1; // No infinite loop for you } @@ -4161,14 +4156,14 @@ void G_AfterIntermission(void) HU_ClearCEcho(); - if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum + if ((gametyperules & GTR_CUTSCENES) && curmapheader->cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES)) && stagefailed == false) { // Start a custom cutscene. - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false, false); + F_StartCustomCutscene(curmapheader->cutscenenum-1, false, false, false); } else { @@ -5068,7 +5063,12 @@ void G_InitNew(player_t *player, if(!mapheaderinfo[gamemap-1]) P_AllocMapHeader(gamemap-1); - maptol = mapheaderinfo[gamemap-1]->typeoflevel; + nextmapheader = mapheaderinfo[gamemap-1]; + maptol = curmapheader->typeoflevel; + + if (!addworld) + curmapheader = nextmapheader; + worldmapheader = nextmapheader; // Don't carry over custom music change to another map. mapmusflags |= MUSIC_RELOADRESET; @@ -5077,14 +5077,15 @@ void G_InitNew(player_t *player, automapactive = false; imcontinuing = false; - if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene. - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer, FLS); + if (!addworld && ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && nextmapheader->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene. + F_StartCustomCutscene(nextmapheader->precutscenenum-1, true, resetplayer, FLS); else G_DoLoadLevel(player, addworld, resetplayer); if (addworld && player != &players[consoleplayer]) return; + // current world is hopefully the newly loaded world at this point if (netgame) { char *title = G_BuildMapTitle(gamemap); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 1aa9486f4..3b51fc412 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5371,6 +5371,14 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) if (viewnumber == 0) // Only do it if it's the first screen being rendered HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. + // Uh, double check? I don't know, I'm not paid for this. + if (viewworld->extrasubsectors == NULL) + HWR_CreatePlanePolygons((INT32)viewworld->numnodes - 1); + + // Same + if (viewworld->sky_dome == NULL) + HWR_BuildSkyDome(viewworld); + PS_START_TIMING(ps_hw_skyboxtime); if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind diff --git a/src/lua_baselib.c b/src/lua_baselib.c index add40a376..0a920d63a 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2577,15 +2577,15 @@ static int lib_pStartQuake(lua_State *L) q_epicenter.z = 0; lua_pop(L, 1); - quake.epicenter = &q_epicenter; + world->quake.epicenter = &q_epicenter; } else - quake.epicenter = NULL; - quake.radius = luaL_optinteger(L, 4, 512*FRACUNIT); + world->quake.epicenter = NULL; + world->quake.radius = luaL_optinteger(L, 4, 512*FRACUNIT); // These things are actually used in 2.1. - quake.intensity = q_intensity; - quake.time = q_time; + world->quake.intensity = q_intensity; + world->quake.time = q_time; return 0; } diff --git a/src/lua_script.c b/src/lua_script.c index 433078eb2..715f16e0c 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -383,7 +383,7 @@ int LUA_PushGlobals(lua_State *L, const char *word) lua_pushinteger(L, emeralds); return 1; } else if (fastcmp(word,"gravity")) { - lua_pushinteger(L, gravity); + lua_pushinteger(L, world->gravity); return 1; } else if (fastcmp(word,"VERSION")) { lua_pushinteger(L, VERSION); @@ -441,7 +441,7 @@ int LUA_CheckGlobals(lua_State *L, const char *word) else if (fastcmp(word, "token")) token = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "gravity")) - gravity = (fixed_t)luaL_checkinteger(L, 2); + world->gravity = (fixed_t)luaL_checkinteger(L, 2); else if (fastcmp(word, "stoppedclock")) stoppedclock = luaL_checkboolean(L, 2); else if (fastcmp(word, "displayplayer")) diff --git a/src/m_menu.c b/src/m_menu.c index b142abf21..cae75902b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4716,10 +4716,10 @@ static void M_DrawPauseMenu(void) // Draw any and all emblems at the top. M_DrawMapEmblems(gamemap, 272, 28, true); - if (mapheaderinfo[gamemap-1]->actnum != 0) - V_DrawString(40, 28, V_YELLOWMAP, va("%s %d", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum)); + if (curmapheader->actnum != 0) + V_DrawString(40, 28, V_YELLOWMAP, va("%s %d", curmapheader->lvlttl, curmapheader->actnum)); else - V_DrawString(40, 28, V_YELLOWMAP, mapheaderinfo[gamemap-1]->lvlttl); + V_DrawString(40, 28, V_YELLOWMAP, curmapheader->lvlttl); // Set up the detail boxes. { diff --git a/src/m_misc.c b/src/m_misc.c index c24896600..52c4cfac8 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -830,11 +830,11 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png else snprintf(maptext, 8, "Unknown"); - if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->lvlttl[0] != '\0') + if (gamestate == GS_LEVEL && worldmapheader->lvlttl[0] != '\0') snprintf(lvlttltext, 48, "%s%s%s", - mapheaderinfo[gamemap-1]->lvlttl, - (mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " Zone", - (mapheaderinfo[gamemap-1]->actnum > 0) ? va(" %d",mapheaderinfo[gamemap-1]->actnum) : ""); + worldmapheader->lvlttl, + (worldmapheader->levelflags & LF_NOZONE) ? "" : " Zone", + (worldmapheader->actnum > 0) ? va(" %d", worldmapheader->actnum) : ""); else snprintf(lvlttltext, 48, "Unknown"); diff --git a/src/p_enemy.c b/src/p_enemy.c index 7a4ed60d8..66c5a1f34 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -756,7 +756,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if (player->quittime) continue; // Ignore uncontrolled bodies - if (player->world != actor->world) + if (P_GetPlayerWorld(player) != actor->world) continue; // Different world if (dist > 0 @@ -1664,10 +1664,10 @@ static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixe actor->momx = FixedMul(FixedDiv(x, dh), speed); actor->momy = FixedMul(FixedDiv(y, dh), speed); - if (!gravity) + if (!world->gravity) return; - dh = FixedDiv(FixedMul(dh, gravity), speed); + dh = FixedDiv(FixedMul(dh, world->gravity), speed); actor->momz = (dh>>1) + FixedDiv(z, dh<<1); } @@ -2731,7 +2731,7 @@ void A_LobShot(mobj_t *actor) dist = P_AproxDistance(actor->target->x - shot->x, actor->target->y - shot->y); horizontal = dist / airtime; - vertical = FixedMul((gravity*airtime)/2, shot->scale); + vertical = FixedMul((world->gravity*airtime)/2, shot->scale); shot->momx = FixedMul(horizontal, FINECOSINE(an)); shot->momy = FixedMul(horizontal, FINESINE(an)); @@ -2753,7 +2753,7 @@ void A_LobShot(mobj_t *actor) CONS_Debug(DBG_GAMELOGIC, "orig: %d\n", (orig)>>FRACBITS); horizontal = dist / airtime; - vertical = (gravity*airtime)/2; + vertical = (world->gravity*airtime)/2; } dist -= orig; shot->momx = FixedMul(horizontal, FINECOSINE(an)); @@ -3967,26 +3967,26 @@ static void P_DoBossVictory(mobj_t *mo) EV_DoElevator(LE_CAPSULE2, NULL, elevateHighest); } - if (mapheaderinfo[gamemap-1]->muspostbossname[0] && - S_MusicExists(mapheaderinfo[gamemap-1]->muspostbossname, !midi_disabled, !digital_disabled)) + if (worldmapheader->muspostbossname[0] && + S_MusicExists(worldmapheader->muspostbossname, !midi_disabled, !digital_disabled)) { // Touching the egg trap button calls P_DoPlayerExit, which calls P_RestoreMusic. // So just park ourselves in the mapmus variables. // But don't change the mapmus variables if they were modified from their level header values (e.g., TUNES). - boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, S_MusicName(), 7); - if (!strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7)) + boolean changed = strnicmp(worldmapheader->musname, S_MusicName(), 7); + if (!strnicmp(worldmapheader->musname, mapmusname, 7)) { - strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7); + strncpy(mapmusname, worldmapheader->muspostbossname, 7); mapmusname[6] = 0; - mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET; - mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos; + mapmusflags = (worldmapheader->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET; + mapmusposition = worldmapheader->muspostbosspos; } // don't change if we're in another tune // but in case we're in jingle, use our parked mapmus variables so the correct track restores if (!changed) S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, (1*MUSICRATE)+(MUSICRATE/2), - mapheaderinfo[gamemap-1]->muspostbossfadein); + worldmapheader->muspostbossfadein); } } } @@ -4412,7 +4412,7 @@ void A_SuperSneakers(mobj_t *actor) if (P_IsLocalPlayer(player) && !player->powers[pw_super]) { - if (S_SpeedMusic(0.0f) && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) + if (S_SpeedMusic(0.0f) && (worldmapheader->levelflags & LF_SPEEDMUSIC)) S_SpeedMusic(1.4f); else P_PlayJingle(player, JT_SHOES); @@ -11591,7 +11591,7 @@ void A_BrakLobShot(mobj_t *actor) return; // Don't even bother if we've got nothing to aim at. // Look up actor's current gravity situation - g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector)); + g = FixedMul(world->gravity, P_GetSectorGravityFactor(actor->subsector->sector)); // Look up distance between actor and its target x = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); @@ -11706,7 +11706,7 @@ void A_NapalmScatter(mobj_t *actor) airtime = 16<subsector->sector)); + g = FixedMul(world->gravity, P_GetSectorGravityFactor(actor->subsector->sector)); // vy = (g*(airtime-1))/2 vy = FixedMul(g,(airtime-(1<>1; @@ -11761,12 +11761,12 @@ mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz if (!flickytype) { - if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service. + if (!worldmapheader || !worldmapheader->numFlickies) // No mapheader, no shoes, no service. return NULL; else { - INT32 prandom = P_RandomKey(mapheaderinfo[gamemap-1]->numFlickies); - flickytype = mapheaderinfo[gamemap-1]->flickies[prandom]; + INT32 prandom = P_RandomKey(worldmapheader->numFlickies); + flickytype = worldmapheader->flickies[prandom]; } } @@ -12416,7 +12416,7 @@ void A_Boss5Jump(mobj_t *actor) return; // Don't even bother if we've got nothing to aim at. // Look up actor's current gravity situation - g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector)); + g = FixedMul(world->gravity, P_GetSectorGravityFactor(actor->subsector->sector)); // Look up distance between actor and its tracer x = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); @@ -12519,10 +12519,10 @@ void A_MineExplode(mobj_t *actor) A_Scream(actor); actor->flags = MF_NOGRAVITY|MF_NOCLIP; - quake.epicenter = NULL; - quake.radius = 512*FRACUNIT; - quake.intensity = 8*FRACUNIT; - quake.time = TICRATE/3; + world->quake.epicenter = NULL; + world->quake.radius = 512*FRACUNIT; + world->quake.intensity = 8*FRACUNIT; + world->quake.time = TICRATE/3; P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, DMG_CANHURTSELF, true); P_MobjCheckWater(actor); @@ -13505,14 +13505,14 @@ void A_Boss5BombExplode(mobj_t *actor) P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale); //P_StartQuake(9*actor->scale, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius); // the above does not exist, so we set the quake values directly instead - quake.intensity = 9*actor->scale; - quake.time = TICRATE/6; + world->quake.intensity = 9*actor->scale; + world->quake.time = TICRATE/6; // the following quake values have no effect atm? ah well, may as well set them anyway { mappoint_t q_epicenter = {actor->x, actor->y, actor->z}; - quake.epicenter = &q_epicenter; + world->quake.epicenter = &q_epicenter; } - quake.radius = 20*actor->radius; + world->quake.radius = 20*actor->radius; } static mobj_t *dustdevil; @@ -13785,10 +13785,10 @@ void A_TNTExplode(mobj_t *actor) epicenter.x = actor->x; epicenter.y = actor->y; epicenter.z = actor->z; - quake.intensity = 9*FRACUNIT; - quake.time = TICRATE/6; - quake.epicenter = &epicenter; - quake.radius = 512*FRACUNIT; + world->quake.intensity = 9*FRACUNIT; + world->quake.time = TICRATE/6; + world->quake.epicenter = &epicenter; + world->quake.radius = 512*FRACUNIT; if (locvar1) { diff --git a/src/p_floor.c b/src/p_floor.c index ce983095d..d7753ef10 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -689,7 +689,7 @@ void T_BounceCheese(bouncecheese_t *bouncer) } else if (bouncer->sector->ceilingheight > bouncer->ceilingwasheight) // Up { - bouncer->speed += gravity; + bouncer->speed += world->gravity; } if (abs(bouncer->speed) < 2*FRACUNIT @@ -838,7 +838,7 @@ void T_StartCrumble(crumble_t *crumble) // Only fall like this if it isn't meant to float on water if (!(crumble->flags & CF_FLOATBOB)) { - crumble->speed += gravity; // Gain more and more speed + crumble->speed += world->gravity; // Gain more and more speed if ((!(crumble->flags & CF_REVERSE) && crumble->sector->ceilingheight >= -16384*FRACUNIT) || ((crumble->flags & CF_REVERSE) && crumble->sector->ceilingheight <= 16384*FRACUNIT)) diff --git a/src/p_inter.c b/src/p_inter.c index 046a0a198..d6cd42fec 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -725,18 +725,24 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) break; // Emerald Hunt - case MT_EMERHUNT: + case MT_EMERHUNT: { + unsigned remaining_emeralds = 0; + if (player->bot && player->bot != BOT_MPAI) return; - if (hunt1 == special) - hunt1 = NULL; - else if (hunt2 == special) - hunt2 = NULL; - else if (hunt3 == special) - hunt3 = NULL; + for (i = 0; i < NUM_EMERALD_HUNT_LOCATIONS; i++) + { + if (world->emerald_hunt_locations[i]) + { + if (world->emerald_hunt_locations[i] == special) + P_SetTarget(&world->emerald_hunt_locations[i], NULL); + else + remaining_emeralds++; + } + } - if (!hunt1 && !hunt2 && !hunt3) + if (!remaining_emeralds) { for (i = 0; i < MAXPLAYERS; i++) { @@ -748,7 +754,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) //S_StartSound(NULL, sfx_lvpass); } break; - + } // Collectible emeralds case MT_EMERALD1: case MT_EMERALD2: @@ -1678,9 +1684,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_SetObjectMomZ(toucher, FixedDiv(69*FRACUNIT,10*FRACUNIT), false); if (P_IsLocalPlayer(player)) { - quake.intensity = 9*FRACUNIT; - quake.time = TICRATE/2; - quake.epicenter = NULL; + world->quake.intensity = 9*FRACUNIT; + world->quake.time = TICRATE/2; + world->quake.epicenter = NULL; } #if 0 // camera redirection - deemed unnecessary @@ -3149,7 +3155,7 @@ static void P_NiGHTSDamage(mobj_t *target, mobj_t *source) if (oldnightstime > 10*TICRATE && player->nightstime < 10*TICRATE) { - if ((mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + if ((worldmapheader->levelflags & LF_MIXNIGHTSCOUNTDOWN) #ifdef _WIN32 // win32 MIDI volume hack means we cannot fade down the music && S_MusicType() != MU_MID @@ -3605,7 +3611,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (oldnightstime > 10*TICRATE && player->nightstime < 10*TICRATE) { - if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + if (worldmapheader->levelflags & LF_MIXNIGHTSCOUNTDOWN) { S_FadeMusic(0, 10*MUSICRATE); S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. diff --git a/src/p_local.h b/src/p_local.h index 6ea57e122..8f3bc9edc 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -208,8 +208,8 @@ boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); #define P_AnalogMove(player) (P_ControlStyle(player) == CS_LMAOGALOG) boolean P_TransferToNextMare(player_t *player); -UINT8 P_FindLowestMare(void); -void P_FindEmerald(void); +UINT8 P_FindLowestMare(world_t *w); +void P_FindEmerald(world_t *w); void P_TransferToAxis(player_t *player, INT32 axisnum); boolean P_PlayerMoving(INT32 pnum); void P_SpawnThokMobj(player_t *player); @@ -276,7 +276,7 @@ extern consvar_t cv_gravity, cv_movebob; mobjtype_t P_GetMobjtype(UINT16 mthingtype); -void P_RespawnSpecials(void); +void P_RespawnSpecials(world_t *w); mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); @@ -288,8 +288,8 @@ boolean P_MobjWasRemoved(mobj_t *th); void P_RemoveSavegameMobj(mobj_t *th); boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state); boolean P_SetMobjState(mobj_t *mobj, statenum_t state); -void P_RunShields(void); -void P_RunOverlays(void); +void P_RunShields(world_t *w); +void P_RunOverlays(world_t *w); void P_HandleMinecartSegments(mobj_t *mobj); void P_MobjThinker(mobj_t *mobj); boolean P_RailThinker(mobj_t *mobj); @@ -301,17 +301,17 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); #define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(mobj, sector, NULL, x, y, line, false, false) #define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(mobj, sector, NULL, x, y, line, true, false) -#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) -#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false) +#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(mobj, P_GetMobjWorld(mobj)->sectors + fof->secnum, sector, x, y, line, false, false) +#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(mobj, P_GetMobjWorld(mobj)->sectors + fof->secnum, sector, x, y, line, true, false) #define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(mobj, src, bound, mobj->x, mobj->y, NULL, src != bound, true) #define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(mobj, src, bound, mobj->x, mobj->y, NULL, src == bound, true) -fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_CameraFloorZ(mobj, sector, NULL, x, y, line, false, false) -#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_CameraCeilingZ(mobj, sector, NULL, x, y, line, true, false) -#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_CameraCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) -#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_CameraFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false) +fixed_t P_CameraFloorZ(camera_t *cam, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); +fixed_t P_CameraCeilingZ(camera_t *cam, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); +#define P_CameraGetFloorZ(cam, sector, x, y, line) P_CameraFloorZ(cam, sector, NULL, x, y, line, false, false) +#define P_CameraGetCeilingZ(cam, sector, x, y, line) P_CameraCeilingZ(cam, sector, NULL, x, y, line, true, false) +#define P_CameraGetFOFTopZ(cam, sector, fof, x, y, line) P_CameraCeilingZ(cam, P_GetCameraWorld(cam)->sectors + fof->secnum, sector, x, y, line, false, false) +#define P_CameraGetFOFBottomZ(cam, sector, fof, x, y, line) P_CameraFloorZ(cam, P_GetCameraWorld(cam)->sectors + fof->secnum, sector, x, y, line, true, false) boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); @@ -335,6 +335,8 @@ FUNCMATH boolean P_WeaponOrPanel(mobjtype_t type); void P_CalcChasePostImg(player_t *player, camera_t *thiscam); boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled); +world_t *P_GetCameraWorld(camera_t *cam); + void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab); mobj_t *P_GetClosestAxis(mobj_t *source); diff --git a/src/p_mobj.c b/src/p_mobj.c index 6ab222c68..02308680e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1385,6 +1385,14 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f } else // Well, that makes it easy. Just get the ceiling height return sector->ceilingheight; } + +world_t *P_GetCameraWorld(camera_t *cam) +{ + if (cam->subsector == NULL) + return NULL; + return (world_t *)cam->subsector->sector->world; +} + static void P_PlayerFlip(mobj_t *mo) { if (!mo->player) @@ -1463,7 +1471,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if (!gravsector) // If there is no 3D floor gravity, check sector's gravity gravsector = mo->subsector->sector; - gravityadd = -FixedMul(gravity, P_GetSectorGravityFactor(gravsector)); + gravityadd = -FixedMul(world->gravity, P_GetSectorGravityFactor(gravsector)); if ((gravsector->flags & MSF_GRAVITYFLIP) && gravityadd > 0) { @@ -3238,8 +3246,8 @@ void P_MobjCheckWater(mobj_t *mobj) || ((rover->fofflags & FOF_BLOCKOTHERS) && !mobj->player))) continue; - topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, sector); - bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, sector); + topheight = P_GetSpecialTopZ(mobj, P_GetMobjWorld(mobj)->sectors + rover->secnum, sector); + bottomheight = P_GetSpecialBottomZ(mobj, P_GetMobjWorld(mobj)->sectors + rover->secnum, sector); if (mobj->eflags & MFE_VERTICALFLIP) { @@ -3760,12 +3768,12 @@ static void P_CheckCrumblingPlatforms(mobj_t *mobj) if (mobj->eflags & MFE_VERTICALFLIP) { - if (P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z + mobj->height) + if (P_GetSpecialBottomZ(mobj, P_GetMobjWorld(mobj)->sectors + rover->secnum, node->m_sector) != mobj->z + mobj->height) continue; } else { - if (P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z) + if (P_GetSpecialTopZ(mobj, P_GetMobjWorld(mobj)->sectors + rover->secnum, node->m_sector) != mobj->z) continue; } @@ -5354,7 +5362,7 @@ static void P_Boss7Thinker(mobj_t *mobj) dist = P_AproxDistance(hitspot->x - mobj->x, hitspot->y - mobj->y); horizontal = dist / airtime; - vertical = (gravity*airtime)/2; + vertical = (world->gravity*airtime)/2; mobj->momx = FixedMul(horizontal, FINECOSINE(an)); mobj->momy = FixedMul(horizontal, FINESINE(an)); @@ -5482,7 +5490,7 @@ static void P_Boss9Thinker(mobj_t *mobj) { P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT); P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); - mobj->momz -= gravity; + mobj->momz -= world->gravity; if (mobj->z < mobj->watertop || mobj->z < (mobj->floorz + 16*FRACUNIT)) { mobj->watertop = mobj->floorz + 32*FRACUNIT; @@ -6758,19 +6766,16 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) return true; } -void P_RunShields(void) +void P_RunShields(world_t *w) { - INT32 i; - - // run shields - for (i = 0; i < world->numshields; i++) + for (INT32 i = 0; i < w->numshields; i++) { - if (!P_MobjWasRemoved(world->shields[i])) - P_ShieldLook(world->shields[i], world->shields[i]->threshold); - P_SetTarget(&world->shields[i], NULL); + if (!P_MobjWasRemoved(w->shields[i])) + P_ShieldLook(w->shields[i], w->shields[i]->threshold); + P_SetTarget(&w->shields[i], NULL); } - world->numshields = 0; + w->numshields = 0; } static boolean P_AddShield(mobj_t *thing) @@ -6807,13 +6812,13 @@ static boolean P_AddShield(mobj_t *thing) return true; } -void P_RunOverlays(void) +void P_RunOverlays(world_t *w) { // run overlays mobj_t *mo, *next = NULL; fixed_t destx,desty,zoffs; - for (mo = world->overlaycap; mo; mo = next) + for (mo = w->overlaycap; mo; mo = next) { I_Assert(!P_MobjWasRemoved(mo)); @@ -6878,7 +6883,7 @@ void P_RunOverlays(void) P_SetThingPosition(mo); P_CheckPosition(mo, mo->x, mo->y); } - P_SetTarget(&world->overlaycap, NULL); + P_SetTarget(&w->overlaycap, NULL); } // Called only when MT_OVERLAY thinks. @@ -11456,7 +11461,7 @@ mobjtype_t P_GetMobjtype(UINT16 mthingtype) // // P_RespawnSpecials // -void P_RespawnSpecials(void) +void P_RespawnSpecials(world_t *w) { mapthing_t *mthing = NULL; @@ -11471,15 +11476,15 @@ void P_RespawnSpecials(void) return; // nothing left to respawn? - if (world->iquehead == world->iquetail) + if (w->iquehead == w->iquetail) return; // the first item in the queue is the first to respawn // wait at least 30 seconds - if (leveltime - world->itemrespawntime[world->iquetail] < (tic_t)cv_itemrespawntime.value*TICRATE) + if (leveltime - w->itemrespawntime[w->iquetail] < (tic_t)cv_itemrespawntime.value*TICRATE) return; - mthing = world->itemrespawnque[world->iquetail]; + mthing = w->itemrespawnque[w->iquetail]; #ifdef PARANOIA if (!mthing) @@ -11490,7 +11495,7 @@ void P_RespawnSpecials(void) P_SpawnMapThing(mthing); // pull it from the que - world->iquetail = (world->iquetail+1)&(ITEMQUESIZE-1); + w->iquetail = (w->iquetail+1)&(ITEMQUESIZE-1); } // diff --git a/src/p_saveg.c b/src/p_saveg.c index 565783cff..11185d309 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4164,6 +4164,9 @@ static inline void P_NetArchiveSpecials(void) // Sky number WRITEINT32(save_p, archiveworld->skynum); + // Gravity + WRITEFIXED(save_p, archiveworld->gravity); + // Current global weather type WRITEUINT8(save_p, archiveworld->weather); @@ -4196,6 +4199,7 @@ static void P_NetUnArchiveSpecials(void) P_SetupLevelSky(j, false); // Don't call P_SetupWorldSky from there P_SetupWorldSky(j, unarchiveworld); + unarchiveworld->gravity = READFIXED(save_p); unarchiveworld->weather = READUINT8(save_p); if (world->weather) @@ -4250,7 +4254,8 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) if(!mapheaderinfo[gamemap-1]) P_AllocMapHeader(gamemap-1); - //lastmapsaved = gamemap; + curmapheader = nextmapheader = mapheaderinfo[gamemap-1]; + worldmapheader = curmapheader; lastmaploaded = gamemap; tokenlist = 0; @@ -4337,8 +4342,6 @@ static void P_NetArchiveMisc(boolean resending) WRITEUINT32(save_p, countdown); WRITEUINT32(save_p, countdown2); - WRITEFIXED(save_p, baseworld->gravity); - WRITEUINT32(save_p, countdowntimer); WRITEUINT8(save_p, countdowntimeup); @@ -4438,8 +4441,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) countdown = READUINT32(save_p); countdown2 = READUINT32(save_p); - gravity = READFIXED(save_p); - countdowntimer = (tic_t)READUINT32(save_p); countdowntimeup = (boolean)READUINT8(save_p); @@ -4798,7 +4799,7 @@ void P_SaveNetGame(boolean resending) for (w = 0; w < numworlds; w++) { - if (player->world == worldlist[w]) + if (P_GetPlayerWorld(player) == worldlist[w]) { player->worldnum = w; break; @@ -4931,6 +4932,10 @@ static void P_NetUnArchiveWorlds(boolean reloading) UnArchiveWorld(); } + gamemap = worldlist[0]->gamemap; + curmapheader = nextmapheader = mapheaderinfo[gamemap-1]; + worldmapheader = curmapheader; + P_NetUnArchiveColormaps(); RelinkWorldsToEntities(); diff --git a/src/p_setup.c b/src/p_setup.c index ae18386f9..6dbb53c73 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -6881,9 +6881,7 @@ static boolean P_LoadMapFromFile(void) static void P_InitLevelSky(INT32 skynum, player_t *player) { - if (player == &players[consoleplayer]) - P_SetupSkyTexture(skynum); - + P_SetupSkyTexture(skynum); P_SetupWorldSky(skynum, world); levelskynum = skynum; } @@ -6940,7 +6938,7 @@ static void P_InitPlayerSettings(INT32 i, boolean canresetlives) players[i].pflags &= ~(PF_GAMETYPEOVER); } -static void P_InitWorldSettings(void) +static void P_InitWorldSettings(mapheader_t *mapheader) { leveltime = 0; @@ -6953,17 +6951,14 @@ static void P_InitWorldSettings(void) if ((netgame || multiplayer) && !G_IsSpecialStage(gamemap)) nummaprings = -1; else - nummaprings = mapheaderinfo[gamemap-1]->startrings; - - // emerald hunt - hunt1 = hunt2 = hunt3 = NULL; + nummaprings = mapheader->startrings; // map time limit - if (mapheaderinfo[gamemap-1]->countdown) + if (mapheader->countdown) { INT32 i; tic_t maxtime = 0; - countdowntimer = mapheaderinfo[gamemap-1]->countdown * TICRATE; + countdowntimer = mapheader->countdown * TICRATE; for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) @@ -6991,20 +6986,17 @@ static void P_InitWorldSettings(void) stagefailed = G_IsSpecialStage(gamemap); } -static void P_InitLevelSettings(player_t *player, boolean addworld, boolean fromnetsave) +static void P_InitLevelSettings(mapheader_t *mapheader, player_t *player, boolean addworld, boolean fromnetsave) { INT32 i; boolean canresetlives = true; if (!addworld) - P_InitWorldSettings(); + P_InitWorldSettings(mapheader); // Reset temporary record data memset(&ntemprecords, 0, sizeof(nightsdata_t)); - // earthquake camera - memset(&quake,0,sizeof(struct quake)); - if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2) { for (i = 0; i < MAXPLAYERS; i++) @@ -7067,7 +7059,7 @@ void P_RespawnThings(void) P_RemoveMobj((mobj_t *)think); } - P_InitLevelSettings(NULL, false, false); + P_InitLevelSettings(worldmapheader, NULL, false, false); localaiming = 0; localaiming2 = 0; @@ -7081,7 +7073,7 @@ void P_RespawnThings(void) static void P_RunLevelScript(const char *scriptname) { - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_SCRIPTISFILE)) + if (!(worldmapheader->levelflags & LF_SCRIPTISFILE)) { lumpnum_t lumpnum; char newname[9]; @@ -7414,9 +7406,9 @@ static void P_RunSpecialStageWipe(void) S_StartSound(NULL, sfx_s3kaf); // Fade music! Time it to S3KAF: 0.25 seconds is snappy. - if (RESETMUSIC || + if (S_ShouldResetMusic(nextmapheader) || strnicmp(S_MusicName(), - (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap - 1]->musname : mapmusname, 7)) + (mapmusflags & MUSIC_RELOADRESET) ? nextmapheader->musname : mapmusname, 7)) S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE) F_WipeStartScreen(); @@ -7584,7 +7576,7 @@ static void P_InitGametype(player_t *player, boolean addworld) CV_StealthSetValue(&cv_numlaps, (cv_basenumlaps.value) ? cv_basenumlaps.value - : mapheaderinfo[gamemap - 1]->numlaps); + : nextmapheader->numlaps); } /** Loads a level from a lump or external wad. @@ -7603,7 +7595,7 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo levelloading = true; // This is needed. Don't touch. - maptol = mapheaderinfo[gamemap-1]->typeoflevel; + maptol = nextmapheader->typeoflevel; gametyperules = gametypedefaultrules[gametype]; CON_Drawer(); // let the user know what we are going to do @@ -7625,18 +7617,18 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo // Clear CECHO messages HU_ClearCEcho(); - if (mapheaderinfo[gamemap-1]->runsoc[0] != '#') - P_RunSOC(mapheaderinfo[gamemap-1]->runsoc); + if (nextmapheader->runsoc[0] != '#') + P_RunSOC(nextmapheader->runsoc); - if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#') - P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname); + if (cv_runscripts.value && nextmapheader->scriptname[0] != '#') + P_RunLevelScript(nextmapheader->scriptname); - P_InitLevelSettings(player, addworld, fromnetsave); + P_InitLevelSettings(nextmapheader, player, addworld, fromnetsave); postimgtype = postimgtype2 = postimg_none; - if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0') - P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter); + if (nextmapheader->forcecharacter[0] != '\0') + P_ForceCharacter(nextmapheader->forcecharacter); if (!dedicated) { @@ -7694,9 +7686,9 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo // Fade out music here. Deduct 2 tics so the fade volume actually reaches 0. // But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug. - if (!(reloadinggamestate || titlemapinaction) && (RESETMUSIC || + if (!(reloadinggamestate || titlemapinaction) && (S_ShouldResetMusic(nextmapheader) || strnicmp(S_MusicName(), - (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))) + (mapmusflags & MUSIC_RELOADRESET) ? nextmapheader->musname : mapmusname, 7))) { S_FadeMusic(0, FixedMul( FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)); @@ -7722,9 +7714,9 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo char tx[64]; V_DrawSmallString(1, 191, V_ALLOWLOWERCASE|V_TRANSLUCENT|V_SNAPTOLEFT|V_SNAPTOBOTTOM, M_GetText("Speeding off to...")); snprintf(tx, 63, "%s%s%s", - mapheaderinfo[gamemap-1]->lvlttl, - (mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " Zone", - (mapheaderinfo[gamemap-1]->actnum > 0) ? va(" %d",mapheaderinfo[gamemap-1]->actnum) : ""); + nextmapheader->lvlttl, + (nextmapheader->levelflags & LF_NOZONE) ? "" : " Zone", + (nextmapheader->actnum > 0) ? va(" %d",nextmapheader->actnum) : ""); V_DrawSmallString(1, 195, V_ALLOWLOWERCASE|V_TRANSLUCENT|V_SNAPTOLEFT|V_SNAPTOBOTTOM, tx); I_UpdateNoVsync(); } @@ -7732,7 +7724,7 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo // As oddly named as this is, this handles music only. // We should be fine starting it here. // Don't do this during titlemap, because the menu code handles music by itself. - S_Start(); + S_Start(nextmapheader); levelfadecol = (ranspecialwipe) ? 0 : 31; @@ -7740,10 +7732,17 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo F_EndTextPrompt(false, true); } } + else + { + S_SetMapMusic(nextmapheader); + S_StopMusic(); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); + } if (player && (!titlemapinaction)) P_UnloadWorldPlayer(player); + // Initialize the world world = P_InitNewWorld(); thlist = world->thlist; @@ -7796,7 +7795,7 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo if (lastloadedmaplumpnum == LUMPERROR) I_Error("Map %s not found.\n", maplumpname); - R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette); + R_ReInitColormaps(worldmapheader->palette); if (!addworld) { // Init Boom colormaps. @@ -7805,7 +7804,7 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo CON_SetupBackColormap(); // SRB2 determines the sky texture to be used depending on the map header. - P_InitLevelSky(mapheaderinfo[gamemap-1]->skynum, player); + P_InitLevelSky(worldmapheader->skynum, player); P_ResetSpawnpoints(); @@ -7821,6 +7820,10 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo // init anything that P_SpawnSlopes/P_LoadThings needs to know P_InitSpecials(); + // Defaults in case levels don't have them set. + sstimer = worldmapheader->sstimer*TICRATE + 6; + ssspheres = worldmapheader->ssspheres; + P_SpawnSlopes(fromnetsave); P_SpawnMapThings(!fromnetsave); @@ -7916,12 +7919,12 @@ boolean P_LoadLevel(player_t *player, boolean addworld, boolean fromnetsave, boo P_MapEnd(); // just in case MapLoad modifies tmthing } - // No render mode or reloading gamestate, stop here. - if (rendermode == render_none || reloadinggamestate) + // Done here + if (addworld) return true; - //if (!runforself || (addworld && splitscreen)) - if (addworld) + // No render mode or reloading gamestate, stop here. + if (rendermode == render_none || reloadinggamestate) return true; R_ResetViewInterpolation(0); diff --git a/src/p_sight.c b/src/p_sight.c index ec2e23561..bbca93b04 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -396,23 +396,18 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) s1 = t1->subsector->sector; s2 = t2->subsector->sector; - // Check in REJECT table. - if (s1->world == s2->world - && t1->world == t2->world - && t1->world == s1->world - && t2->world == s2->world) - { - world_t *w = s1->world; - size_t pnum = (s1-w->sectors)*w->numsectors + (s2-w->sectors); + world_t *w = P_GetMobjWorld(t1); - if (w->rejectmatrix != NULL) - { - if (w->rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected - return false; - } - } - else + // Cannot possibly be seen if the worlds don't match + if (w != P_GetMobjWorld(t2)) return false; + else if (w->rejectmatrix != NULL) + { + // Check in REJECT table. + size_t pnum = (s1-w->sectors)*w->numsectors + (s2-w->sectors); + if (w->rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected + return false; + } // killough 11/98: shortcut for melee situations // same subsector? obviously visible diff --git a/src/p_spec.c b/src/p_spec.c index d9cc23d99..4d44be1ac 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1391,11 +1391,11 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) if (specialtype == 323) { // run only when no mares are found - if (donomares && P_FindLowestMare() != UINT8_MAX) + if (donomares && P_FindLowestMare(world) != UINT8_MAX) return false; // run only if there is a mare present - if (!donomares && P_FindLowestMare() == UINT8_MAX) + if (!donomares && P_FindLowestMare(world) == UINT8_MAX) return false; // run only if player is nightserizing from non-nights @@ -1505,7 +1505,7 @@ static boolean P_CheckPlayerMareOld(line_t *triggerline) if (!(maptol & TOL_NIGHTS)) return false; - mare = P_FindLowestMare(); + mare = P_FindLowestMare(world); if (triggerline->flags & ML_NOCLIMB) return mare <= targetmare; @@ -1524,7 +1524,7 @@ static boolean P_CheckPlayerMare(line_t *triggerline) if (!(maptol & TOL_NIGHTS)) return false; - mare = P_FindLowestMare(); + mare = P_FindLowestMare(world); switch (triggerline->args[2]) { @@ -2009,10 +2009,10 @@ static void P_PlaySFX(INT32 sfxnum, mobj_t *mo, sector_t *callsec, INT16 tag, te if (!Tag_Find(&rover->master->frontsector->tags, tag)) continue; - if (camobj->z > P_GetSpecialTopZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + if (camobj->z > P_GetSpecialTopZ(camobj, P_GetMobjWorld(camobj)->sectors + rover->secnum, camobj->subsector->sector)) continue; - if (camobj->z + camobj->height < P_GetSpecialBottomZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + if (camobj->z + camobj->height < P_GetSpecialBottomZ(camobj, P_GetMobjWorld(camobj)->sectors + rover->secnum, camobj->subsector->sector)) continue; foundit = true; @@ -3000,17 +3000,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 444: // Earthquake camera { - quake.intensity = line->args[1] << FRACBITS; - quake.radius = line->args[2] << FRACBITS; - quake.time = line->args[0]; + world->quake.intensity = line->args[1] << FRACBITS; + world->quake.radius = line->args[2] << FRACBITS; + world->quake.time = line->args[0]; - quake.epicenter = NULL; /// \todo + world->quake.epicenter = NULL; /// \todo // reasonable defaults. - if (!quake.intensity) - quake.intensity = 8<quake.intensity) + world->quake.intensity = 8<quake.radius) + world->quake.radius = 512<master->frontsector->specialflags & specialflag)) continue; - if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) - && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))) + if (!(mo->z <= P_GetSpecialTopZ(mo, P_GetMobjWorld(mo)->sectors + rover->secnum, mo->subsector->sector) + && mo->z >= P_GetSpecialBottomZ(mo, P_GetMobjWorld(mo)->sectors + rover->secnum, mo->subsector->sector))) continue; return true; @@ -3993,8 +3993,8 @@ boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec) boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec) { - fixed_t topheight = P_GetSpecialTopZ(mo, sectors + ffloor->secnum, sec); - fixed_t bottomheight = P_GetSpecialBottomZ(mo, sectors + ffloor->secnum, sec); + fixed_t topheight = P_GetSpecialTopZ(mo, P_GetMobjWorld(mo)->sectors + ffloor->secnum, sec); + fixed_t bottomheight = P_GetSpecialBottomZ(mo, P_GetMobjWorld(mo)->sectors + ffloor->secnum, sec); if (((ffloor->fofflags & FOF_BLOCKPLAYER) && mo->player) || ((ffloor->fofflags & FOF_BLOCKOTHERS) && !mo->player)) @@ -5385,7 +5385,7 @@ void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable) * * \sa P_CheckTimeLimit, P_CheckPointLimit */ -void P_UpdateSpecials(void) +void P_UpdateSpecials(world_t *w) { anim_t *anim; INT32 i; @@ -5415,8 +5415,8 @@ void P_UpdateSpecials(void) /// \todo do not check the non-animate flat.. link the animated ones? /// \note its faster than the original anywaysince it animates only /// flats used in the level, and there's usually very few of them - foundflats = world->flats; - for (j = 0; j < world->numflats; j++, foundflats++) + foundflats = w->flats; + for (j = 0; j < w->numflats; j++, foundflats++) { if (foundflats->speed) // it is an animated flat { @@ -6085,32 +6085,33 @@ static void P_RunLevelLoadExecutors(void) void P_InitSpecials(void) { // Set the default gravity. Custom gravity overrides this setting. - world->gravity = gravity = mapheaderinfo[gamemap-1]->gravity; + world->gravity = worldmapheader->gravity; - // Defaults in case levels don't have them set. - sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6; - ssspheres = mapheaderinfo[gamemap-1]->ssspheres; + // Set globalweather + world->weather = worldmapheader->weather; + P_InitLocalSpecials(); +} + +void P_InitLocalSpecials(void) +{ if (numworlds < 2) CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; // Set curWeather - switch (mapheaderinfo[gamemap-1]->weather) + switch (worldmapheader->weather) { case PRECIP_SNOW: // snow case PRECIP_RAIN: // rain case PRECIP_STORM: // storm case PRECIP_STORM_NORAIN: // storm w/o rain case PRECIP_STORM_NOSTRIKES: // storm w/o lightning - curWeather = mapheaderinfo[gamemap-1]->weather; + curWeather = worldmapheader->weather; break; default: // blank/none curWeather = PRECIP_NONE; break; } - - // Set globalweather - world->weather = mapheaderinfo[gamemap-1]->weather; } void P_ApplyFlatAlignment(sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling) @@ -6247,7 +6248,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 11: // Custom global gravity! - world->gravity = gravity = sector->floorheight/1000; + world->gravity = sector->floorheight/1000; break; } } diff --git a/src/p_spec.h b/src/p_spec.h index b9e52b07b..baa4eeec4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -485,12 +485,13 @@ void P_SetupLevelFlatAnims(void); // at map load void P_InitSpecials(void); +void P_InitLocalSpecials(void); void P_ApplyFlatAlignment(sector_t* sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling); fixed_t P_GetSectorGravityFactor(sector_t *sec); void P_SpawnSpecials(boolean fromnetsave); // every tic -void P_UpdateSpecials(void); +void P_UpdateSpecials(world_t *w); sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number); sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo); sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag); diff --git a/src/p_tick.c b/src/p_tick.c index ef205e223..ae52eb9d1 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -361,18 +361,9 @@ static inline void P_RunThinkers(void) static inline void P_RunWorldThinkers(void) { - INT32 i; - PS_START_TIMING(ps_thinkertime); - if (!(netgame || multiplayer) || (numworlds < 2)) - { - P_RunThinkers(); - PS_STOP_TIMING(ps_thinkertime); - return; - } - - for (i = 0; i < numworlds; i++) + for (INT32 i = 0; i < numworlds; i++) { world_t *w = worldlist[i]; @@ -519,7 +510,7 @@ static inline void P_DoSpecialStageStuff(void) players[i].powers[pw_underwater] = players[i].powers[pw_spacetime] = 0; } - //if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) + //if (sstimer < 15*TICRATE+6 && sstimer > 7 && (worldmapheader->levelflags & LF_SPEEDMUSIC)) //S_SpeedMusic(1.4f); if (sstimer && !objectplacing) @@ -637,65 +628,27 @@ static inline void P_DoCTFStuff(void) static inline void P_RunWorldSpecials(void) { - INT32 i; - - if (!(netgame || multiplayer) || (numworlds < 2)) - { - P_RunShields(); - P_RunOverlays(); - P_UpdateSpecials(); - P_RespawnSpecials(); - return; - } - - for (i = 0; i < numworlds; i++) + for (INT32 i = 0; i < numworlds; i++) { world_t *w = worldlist[i]; if (!w->players) continue; + // Just in case. P_SetWorld(w); - P_RunShields(); - P_RunOverlays(); - P_UpdateSpecials(); - P_RespawnSpecials(); + P_RunShields(w); + P_RunOverlays(w); + P_UpdateSpecials(w); + P_RespawnSpecials(w); + P_PrecipitationEffects(w); // Lightning, rain sounds, etc. } } -static inline void P_WorldPrecipitationEffects(void) +static void RunLuaHook(int hook) { - INT32 i; - - if (!(netgame || multiplayer) || (numworlds < 2)) - { - P_PrecipitationEffects(baseworld); - return; - } - - for (i = 0; i < numworlds; i++) - { - world_t *w = worldlist[i]; - - if (!w->players) - continue; - - P_PrecipitationEffects(w); - } -} - -static inline void RunLuaHookForWorld(int hook) -{ - INT32 i; - - if (!(netgame || multiplayer) || (numworlds < 2)) - { - LUA_HookVoid(hook); - return; - } - - for (i = 0; i < numworlds; i++) + for (INT32 i = 0; i < numworlds; i++) { world_t *w = worldlist[i]; @@ -708,17 +661,9 @@ static inline void RunLuaHookForWorld(int hook) } } -static inline void RunLuaThinkFrameForWorld(void) +static inline void RunLuaThinkFrame(void) { - INT32 i; - - if (!(netgame || multiplayer) || (numworlds < 2)) - { - LUA_HookThinkFrame(); - return; - } - - for (i = 0; i < numworlds; i++) + for (INT32 i = 0; i < numworlds; i++) { world_t *w = worldlist[i]; @@ -731,6 +676,21 @@ static inline void RunLuaThinkFrameForWorld(void) } } +static void P_WorldPostUpdate(world_t *w) +{ + if (w->quake.time) + { + fixed_t ir = w->quake.intensity>>1; + /// \todo Calculate distance from epicenter if set and modulate the intensity accordingly based on radius. + w->quake.x = M_RandomRange(-ir,ir); + w->quake.y = M_RandomRange(-ir,ir); + w->quake.z = M_RandomRange(-ir,ir); + --w->quake.time; + } + else + w->quake.x = w->quake.y = w->quake.z = 0; +} + // // P_Ticker // @@ -738,6 +698,8 @@ void P_Ticker(boolean run) { INT32 i; + P_SetWorld(localworld); + // Increment jointime and quittime even if paused for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) @@ -815,7 +777,7 @@ void P_Ticker(boolean run) player_t *player = &players[i]; if (numworlds > 1 && !titlemapinaction && !player->bot) - P_SetWorld(player->world); + P_SetWorld(P_GetPlayerWorld(player)); P_PlayerThink(player); } @@ -846,22 +808,19 @@ void P_Ticker(boolean run) player_t *player = &players[i]; if (numworlds > 1 && !titlemapinaction && !player->bot) - P_SetWorld(player->world); + P_SetWorld(P_GetPlayerWorld(player)); P_PlayerAfterThink(player); } PS_START_TIMING(ps_lua_thinkframe_time); - RunLuaThinkFrameForWorld(); + RunLuaThinkFrame(); PS_STOP_TIMING(ps_lua_thinkframe_time); } // Run shield positioning P_RunWorldSpecials(); - // Lightning, rain sounds, etc. - P_WorldPrecipitationEffects(); - if (run) leveltime++; timeinmap++; @@ -898,17 +857,16 @@ void P_Ticker(boolean run) if (countdown2) countdown2--; - if (quake.time) + for (i = 0; i < numworlds; i++) { - fixed_t ir = quake.intensity>>1; - /// \todo Calculate distance from epicenter if set and modulate the intensity accordingly based on radius. - quake.x = M_RandomRange(-ir,ir); - quake.y = M_RandomRange(-ir,ir); - quake.z = M_RandomRange(-ir,ir); - --quake.time; + world_t *w = worldlist[i]; + + if (!w->players) + continue; + + P_SetWorld(w); + P_WorldPostUpdate(w); } - else - quake.x = quake.y = quake.z = 0; if (metalplayback) G_ReadMetalTic(metalplayback); @@ -921,7 +879,7 @@ void P_Ticker(boolean run) if (modeattacking) G_GhostTicker(); - RunLuaHookForWorld(HOOK(PostThinkFrame)); + RunLuaHook(HOOK(PostThinkFrame)); } if (run) @@ -962,6 +920,8 @@ void P_Ticker(boolean run) } P_MapEnd(); + + P_SetWorld(localworld); } // Abbreviated ticker for pre-loading, calls thinkers and assorted things @@ -981,7 +941,7 @@ void P_PreTicker(INT32 frames) R_UpdateAllMobjInterpolators(); - RunLuaHookForWorld(HOOK(PreThinkFrame)); + RunLuaHook(HOOK(PreThinkFrame)); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) @@ -999,7 +959,7 @@ void P_PreTicker(INT32 frames) players[i].cmd.angleturn = players[i].angleturn; if (numworlds > 1 && !titlemapinaction && !player->bot) - P_SetWorld(player->world); + P_SetWorld(P_GetPlayerWorld(player)); P_PlayerThink(player); memcpy(&players[i].cmd, &temptic, sizeof(ticcmd_t)); @@ -1014,17 +974,17 @@ void P_PreTicker(INT32 frames) player_t *player = &players[i]; if (numworlds > 1 && !titlemapinaction && !player->bot) - P_SetWorld(player->world); + P_SetWorld(P_GetPlayerWorld(player)); P_PlayerAfterThink(&players[i]); } - RunLuaThinkFrameForWorld(); + RunLuaThinkFrame(); // Run shield positioning P_RunWorldSpecials(); - RunLuaHookForWorld(HOOK(PostThinkFrame)); + RunLuaHook(HOOK(PostThinkFrame)); R_UpdateLevelInterpolators(); R_UpdateViewInterpolation(); diff --git a/src/p_user.c b/src/p_user.c index fc5fd088f..b3610a2f4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -419,7 +419,7 @@ void P_ResetScore(player_t *player) // // Returns the lowest open mare available // -UINT8 P_FindLowestMare(void) +UINT8 P_FindLowestMare(world_t *w) { thinker_t *th; mobj_t *mo2; @@ -430,7 +430,7 @@ UINT8 P_FindLowestMare(void) // scan the thinkers // to find the egg capsule with the lowest mare - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + for (th = w->thlist[THINK_MOBJ].next; th != &w->thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; @@ -469,7 +469,7 @@ boolean P_TransferToNextMare(player_t *player) mobj_t *mo2; mobj_t *closestaxis = NULL; INT32 lowestaxisnum = -1; - UINT8 mare = P_FindLowestMare(); + UINT8 mare = P_FindLowestMare(P_GetPlayerWorld(player)); fixed_t dist1, dist2 = 0; if (mare == 255) @@ -726,7 +726,7 @@ static void P_DeNightserizePlayer(player_t *player) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); // Reset music to beginning if MIXNIGHTSCOUNTDOWN - if ((mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + if ((worldmapheader->levelflags & LF_MIXNIGHTSCOUNTDOWN) #ifdef _WIN32 && S_MusicType() != MU_MID #endif @@ -742,7 +742,7 @@ static void P_DeNightserizePlayer(player_t *player) player->oldscale = 0; // Restore from drowning music - if ((mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + if ((worldmapheader->levelflags & LF_MIXNIGHTSCOUNTDOWN) #ifdef _WIN32 && S_MusicType() != MU_MID #endif @@ -755,7 +755,7 @@ static void P_DeNightserizePlayer(player_t *player) // Reset the music if you did not destroy all the capsules, because you failed. // Why make the all-capsules exception: because it's your reward for nearly finishing the level! // (unless the player auto-loses upon denightserizing; for death case, see above.) - if (P_FindLowestMare() != UINT8_MAX || G_IsSpecialStage(gamemap)) + if (P_FindLowestMare(P_GetPlayerWorld(player)) != UINT8_MAX || G_IsSpecialStage(gamemap)) S_SetMusicPosition(0); } else @@ -813,7 +813,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->bonustime = false; // Restore from drowning music - if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + if (worldmapheader->levelflags & LF_MIXNIGHTSCOUNTDOWN) { S_StopSoundByNum(sfx_timeup); S_StopFadingMusic(); @@ -1331,7 +1331,7 @@ void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound) void P_DoSuperTransformation(player_t *player, boolean giverings) { player->powers[pw_super] = 1; - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player)) + if (!(worldmapheader->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player)) P_PlayJingle(player, JT_SUPER); S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi @@ -1345,7 +1345,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) player->rings = 50; // Just in case. - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC)) + if (!(worldmapheader->levelflags & LF_NOSSMUSIC)) { player->powers[pw_extralife] = 0; player->powers[pw_invulnerability] = 0; @@ -1371,7 +1371,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) player = player->botleader; // NiGHTS does it different! - if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->typeoflevel & TOL_NIGHTS) + if (gamestate == GS_LEVEL && worldmapheader->typeoflevel & TOL_NIGHTS) { if ((netgame || multiplayer) && G_IsSpecialStage(gamemap)) { // Pseudo-shared score for multiplayer special stages. @@ -1581,7 +1581,7 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname) break; case JT_SUPER: // Super Sonic - result = (players[i].powers[pw_super] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC)); + result = (players[i].powers[pw_super] && !(worldmapheader->levelflags & LF_NOSSMUSIC)); break; case JT_GOVER: // Game Over @@ -1630,7 +1630,7 @@ void P_RestoreMusic(player_t *player) return; // Super - else if (player->powers[pw_super] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) + else if (player->powers[pw_super] && !(worldmapheader->levelflags & LF_NOSSMUSIC) && !S_RecallMusic(JT_SUPER, false)) P_PlayJingle(player, JT_SUPER); @@ -1648,7 +1648,7 @@ void P_RestoreMusic(player_t *player) { strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12); S_StartCaption(sfx_None, -1, player->powers[pw_sneakers]); - if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC) + if (worldmapheader->levelflags & LF_SPEEDMUSIC) { S_SpeedMusic(1.4f); if (!S_RecallMusic(JT_MASTER, true)) @@ -3017,7 +3017,7 @@ static void P_CheckInvincibilityTimer(player_t *player) P_SpawnShieldOrb(player); } - if (!player->powers[pw_super] || (mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC)) + if (!player->powers[pw_super] || (worldmapheader->levelflags & LF_NOSSMUSIC)) P_RestoreMusic(player); } } @@ -5579,7 +5579,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { fixed_t potentialmomz; if (player->charability == CA_SLOWFALL) - potentialmomz = FixedMul(gravity, -4*player->mo->scale); + potentialmomz = FixedMul(world->gravity, -4*player->mo->scale); else potentialmomz = ((player->speed < 10*player->mo->scale) ? (player->speed - 10*player->mo->scale)/5 @@ -7098,7 +7098,7 @@ static void P_NiGHTSMovement(player_t *player) } else if (P_IsLocalPlayer(player) && player->nightstime == 10*TICRATE) { - if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + if (worldmapheader->levelflags & LF_MIXNIGHTSCOUNTDOWN) { S_FadeMusic(0, 10*MUSICRATE); S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. @@ -9044,10 +9044,10 @@ void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius) if (inflictor->player && P_IsLocalPlayer(inflictor->player)) { - quake.epicenter = NULL; - quake.intensity = 8*inflictor->scale; - quake.time = 8; - quake.radius = scaledradius; + world->quake.epicenter = NULL; + world->quake.intensity = 8*inflictor->scale; + world->quake.time = 8; + world->quake.radius = scaledradius; } P_RadiusAttack(inflictor, source, radius, 0, false); @@ -9326,12 +9326,13 @@ boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target } // Search for emeralds -void P_FindEmerald(void) +void P_FindEmerald(world_t *w) { thinker_t *th; mobj_t *mo2; - hunt1 = hunt2 = hunt3 = NULL; + for (unsigned i = 0; i < NUM_EMERALD_HUNT_LOCATIONS; i++) + w->emerald_hunt_locations[i] = NULL; // scan the remaining thinkers // to find all emeralds @@ -9343,12 +9344,11 @@ void P_FindEmerald(void) mo2 = (mobj_t *)th; if (mo2->type == MT_EMERHUNT) { - if (!hunt1) - hunt1 = mo2; - else if (!hunt2) - hunt2 = mo2; - else if (!hunt3) - hunt3 = mo2; + for (unsigned i = 0; i < NUM_EMERALD_HUNT_LOCATIONS; i++) + { + if (w->emerald_hunt_locations[i] == NULL) + P_SetTarget(&w->emerald_hunt_locations[i], mo2); + } } } return; @@ -9476,7 +9476,7 @@ static void P_PlayerSetRaceRealTime(player_t *player) for (i = 0; i < numworlds; i++) { - if (player->world == worldlist[i]) + if (P_GetPlayerWorld(player) == worldlist[i]) break; } @@ -11043,7 +11043,7 @@ static void P_MinecartThink(player_t *player) minecart->eflags &= ~MFE_ONGROUND; minecart->z += P_MobjFlip(minecart); if (sidelock) - P_ParabolicMove(minecart, sidelock->x, sidelock->y, sidelock->z, gravity, max(currentSpeed, 10 * FRACUNIT)); + P_ParabolicMove(minecart, sidelock->x, sidelock->y, sidelock->z, world->gravity, max(currentSpeed, 10 * FRACUNIT)); else minecart->momz = 10 * FRACUNIT; @@ -11618,7 +11618,7 @@ void P_PlayerThink(player_t *player) // so we can fade music if (!exitfadestarted && player->exiting > 0 && player->exiting <= 1*TICRATE && - (!multiplayer || G_CoopGametype() ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) && + (!multiplayer || G_CoopGametype() ? !worldmapheader->musinterfadeout : true) && // don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop ((gametyperules & GTR_RACE) ? countdown2 == 0 : true) && // don't fade on timeout player->lives > 0 && // don't fade on game over (competition) diff --git a/src/p_world.c b/src/p_world.c index 07226fd0a..f6bc074ce 100644 --- a/src/p_world.c +++ b/src/p_world.c @@ -59,6 +59,9 @@ world_t *P_InitWorld(void) { world_t *w = Z_Calloc(sizeof(world_t), PU_STATIC, NULL); w->gamemap = gamemap; + if (!mapheaderinfo[w->gamemap-1]) + P_AllocMapHeader(w->gamemap-1); + w->header = mapheaderinfo[w->gamemap-1]; w->thlist = Z_Calloc(sizeof(thinker_t) * NUM_THINKERLISTS, PU_STATIC, NULL); return w; } @@ -144,9 +147,18 @@ void P_SetWorld(world_t *w) P_SetGameWorld(w); + worldmapheader = w->header; + thlist = w->thlist; gamemap = w->gamemap; - gravity = w->gravity; +} + +// +// Gets a player's current world. +// +world_t *P_GetPlayerWorld(player_t *player) +{ + return (world_t *)player->world; } // @@ -154,8 +166,8 @@ void P_SetWorld(world_t *w) // void P_DetachPlayerWorld(player_t *player) { - if (player->world != NULL) - ((world_t *)player->world)->players--; + if (P_GetPlayerWorld(player) != NULL) + P_GetPlayerWorld(player)->players--; player->world = NULL; if (player->mo && !P_MobjWasRemoved(player->mo)) @@ -199,7 +211,7 @@ void P_RoamIntoWorld(player_t *player, INT32 mapnum) } } - if (w == player->world) + if (w == P_GetPlayerWorld(player)) return; else if (w) P_SwitchWorld(player, w); @@ -263,8 +275,8 @@ void P_SwitchWorld(player_t *player, world_t *w) if (!playeringame[playernum] || !player->mo || P_MobjWasRemoved(player->mo)) return; - if (player->world) - P_RemoveMobjConnections(player->mo, player->world); + if (P_GetPlayerWorld(player)) + P_RemoveMobjConnections(player->mo, P_GetPlayerWorld(player)); if (player->followmobj) { @@ -275,19 +287,18 @@ void P_SwitchWorld(player_t *player, world_t *w) P_SwitchPlayerWorld(player, w); P_SetWorld(w); + if (local || splitscreen) - P_InitSpecials(); + P_InitLocalSpecials(); P_UnsetThingPosition(player->mo); P_MoveThinkerToWorld(w, THINK_MOBJ, (thinker_t *)(player->mo)); G_MovePlayerToSpawnOrStarpost(playernum); if (local && !splitscreen) - { localworld = world; - S_Start(); - P_SetupSkyTexture(w->skynum); - } + + P_SetupSkyTexture(w->skynum); if (player == &players[displayplayer]) P_ResetCamera(player, (splitscreen && playernum == 1) ? &camera2 : &camera); @@ -303,6 +314,13 @@ void P_SwitchWorld(player_t *player, world_t *w) if (rendermode == render_opengl) HWR_LoadLevel(); #endif + + if (local || splitscreen) + { + S_SetMapMusic(worldmapheader); + S_StopMusic(); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); + } } void Command_Switchworld_f(void) @@ -328,18 +346,12 @@ void Command_Switchworld_f(void) void Command_Listworlds_f(void) { - INT32 worldnum; - world_t *w; - - for (worldnum = 0; worldnum < numworlds; worldnum++) + for (INT32 i = 0; i < numworlds; i++) { - w = worldlist[worldnum]; - - CONS_Printf("World %d (%p)\n", worldnum, w); - CONS_Printf("Gamemap: %d\n", w->gamemap); - CONS_Printf("vt %d sg %d sc %d ss %d nd %d ld %d sd %d mt %d\n", - w->numvertexes, w->numsegs, w->numsectors, w->numsubsectors, w->numnodes, w->numlines, w->numsides, w->nummapthings); - CONS_Printf("Player count: %d\n", w->players); + world_t *w = worldlist[i]; + CONS_Printf("World %d\n", i); + CONS_Printf(" Gamemap: %d\n", w->gamemap); + CONS_Printf(" Player count: %d\n", w->players); } } @@ -466,7 +478,7 @@ void P_UnloadWorldPlayer(player_t *player) boolean P_MobjIsConnected(mobj_t *mobj1, mobj_t *mobj2) { - return (mobj2 && !P_MobjWasRemoved(mobj2) && mobj1->world == mobj2->world); + return mobj2 && !P_MobjWasRemoved(mobj2) && P_GetMobjWorld(mobj1) == P_GetMobjWorld(mobj2); } void P_RemoveMobjConnections(mobj_t *mobj, world_t *w) @@ -491,3 +503,8 @@ void P_RemoveMobjConnections(mobj_t *mobj, world_t *w) P_SetTarget(&mobj->hprev, NULL); } } + +world_t *P_GetMobjWorld(mobj_t *mobj) +{ + return (world_t *)mobj->world; +} diff --git a/src/p_world.h b/src/p_world.h index 275e3a6fc..151c279ee 100644 --- a/src/p_world.h +++ b/src/p_world.h @@ -65,6 +65,8 @@ typedef struct mobj_t *overlaycap; + mapheader_t *header; + fixed_t gravity; INT32 skynum; // used for keeping track of the current sky @@ -97,6 +99,12 @@ typedef struct tic_t itemrespawntime[ITEMQUESIZE]; size_t iquehead, iquetail; + struct quake quake; + + // Emerald locations + mobj_t *emerald_hunt_locations[NUM_EMERALD_HUNT_LOCATIONS]; + + // All that boring blockmap stuff UINT8 *rejectmatrix; // for fast sight rejection INT32 *blockmaplump; // offsets in blockmap are from here INT32 *blockmap; // Big blockmap @@ -160,12 +168,15 @@ void P_SetWorld(world_t *w); void P_RoamIntoWorld(player_t *player, INT32 mapnum); void P_SwitchWorld(player_t *player, world_t *w); +world_t *P_GetPlayerWorld(player_t *player); + void P_DetachPlayerWorld(player_t *player); void P_SwitchPlayerWorld(player_t *player, world_t *newworld); boolean P_TransferCarriedPlayers(player_t *player, world_t *w); boolean P_MobjIsConnected(mobj_t *mobj1, mobj_t *mobj2); void P_RemoveMobjConnections(mobj_t *mobj, world_t *w); +world_t *P_GetMobjWorld(mobj_t *mobj); void Command_Switchworld_f(void); void Command_Listworlds_f(void); diff --git a/src/r_bsp.c b/src/r_bsp.c index 0369cf60a..aeb6fe7e5 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -244,9 +244,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, *ceilinglightlevel = sec->ceilinglightsec == -1 ? (sec->ceilinglightabsolute ? sec->ceilinglightlevel : max(0, min(255, sec->lightlevel + sec->ceilinglightlevel))) : viewworld->sectors[sec->ceilinglightsec].lightlevel; - // if (sec->midmap != -1) - // mapnum = sec->midmap; - // In original colormap code, this block did not run if sec->midmap was set if (!sec->extra_colormap && sec->heightsec != -1) { const sector_t *s = &viewworld->sectors[sec->heightsec]; @@ -1073,18 +1070,18 @@ static void R_Subsector(size_t num) } } - // killough 9/18/98: Fix underwater slowdown, by passing real sector - // instead of fake one. Improve sprite lighting by basing sprite - // lightlevels on floor & ceiling lightlevels in the surrounding area. - // - // 10/98 killough: - // - // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! - // That is part of the 242 effect!!! If you simply pass sub->sector to - // the old code you will not get correct lighting for underwater sprites!!! - // Either you must pass the fake sector and handle validcount here, on the - // real sector, or you must account for the lighting in some other way, - // like passing it as an argument. + // killough 9/18/98: Fix underwater slowdown, by passing real sector + // instead of fake one. Improve sprite lighting by basing sprite + // lightlevels on floor & ceiling lightlevels in the surrounding area. + // + // 10/98 killough: + // + // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! + // That is part of the 242 effect!!! If you simply pass sub->sector to + // the old code you will not get correct lighting for underwater sprites!!! + // Either you must pass the fake sector and handle validcount here, on the + // real sector, or you must account for the lighting in some other way, + // like passing it as an argument. R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2); firstseg = NULL; diff --git a/src/r_fps.c b/src/r_fps.c index 35c0f342f..32d8718ed 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -696,7 +696,7 @@ void R_DestroyLevelInterpolators(void *wptr, thinker_t *thinker) // reasons. void R_AddMobjInterpolator(mobj_t *mobj) { - world_t *w = (world_t *)mobj->world; + world_t *w = P_GetMobjWorld(mobj); if (!w) return; @@ -729,7 +729,7 @@ void R_AddMobjInterpolator(mobj_t *mobj) void R_RemoveMobjInterpolator(mobj_t *mobj) { - world_t *w = (world_t *)mobj->world; + world_t *w = P_GetMobjWorld(mobj); if (!w) return; diff --git a/src/r_main.c b/src/r_main.c index 0060ef6f3..bdd4ea192 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1187,7 +1187,7 @@ void R_SetupFrame(player_t *player) } } } - newview->z += quake.z; + newview->z += viewworld->quake.z; newview->player = player; @@ -1195,8 +1195,8 @@ void R_SetupFrame(player_t *player) { newview->x = thiscam->x; newview->y = thiscam->y; - newview->x += quake.x; - newview->y += quake.y; + newview->x += viewworld->quake.x; + newview->y += viewworld->quake.y; if (thiscam->subsector) newview->sector = thiscam->subsector->sector; @@ -1207,8 +1207,8 @@ void R_SetupFrame(player_t *player) { newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; - newview->x += quake.x; - newview->y += quake.y; + newview->x += viewworld->quake.x; + newview->y += viewworld->quake.y; if (r_viewmobj->subsector) newview->sector = r_viewmobj->subsector->sector; @@ -1286,9 +1286,9 @@ void R_SkyboxFrame(player_t *player) newview->y = r_viewmobj->y; newview->z = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! - if (mapheaderinfo[gamemap-1]) + if (viewworld->header) { - mapheader_t *mh = mapheaderinfo[gamemap-1]; + mapheader_t *mh = viewworld->header; vector3_t campos = {0,0,0}; // Position of player's actual view point if (player->awayviewtics) { @@ -1307,9 +1307,9 @@ void R_SkyboxFrame(player_t *player) // Earthquake effects should be scaled in the skybox // (if an axis isn't used, the skybox won't shake in that direction) - campos.x += quake.x; - campos.y += quake.y; - campos.z += quake.z; + campos.x += viewworld->quake.x; + campos.y += viewworld->quake.y; + campos.z += viewworld->quake.z; if (viewworld->skyboxmo[1]) // Is there a viewpoint? { @@ -1509,9 +1509,9 @@ void R_PrepareViewWorld(player_t *player) R_SetViewMobj(player); if (r_viewmobj) - P_SetViewWorld(r_viewmobj->world); - else if (player->world) - P_SetViewWorld(player->world); + P_SetViewWorld(P_GetMobjWorld(r_viewmobj)); + else if (P_GetPlayerWorld(player)) + P_SetViewWorld(P_GetPlayerWorld(player)); else if (localworld && !splitscreen) // Yes? P_SetViewWorld(localworld); else diff --git a/src/r_portal.c b/src/r_portal.c index 285f29689..30658a50c 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -275,7 +275,7 @@ void Portal_AddSkybox (const visplane_t* plane) portal->viewz = viewworld->skyboxmo[0]->z; portal->viewangle = viewangle + viewworld->skyboxmo[0]->angle; - mh = mapheaderinfo[gamemap-1]; + mh = viewworld->header; // If a relative viewpoint exists, offset the viewpoint. if (viewworld->skyboxmo[1]) diff --git a/src/r_skins.c b/src/r_skins.c index 2c031ee85..a875e1915 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -225,7 +225,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) return true; } - if (Playing() && mapheaderinfo[gamemap-1] && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) + if (Playing() && worldmapheader && (R_SkinAvailable(worldmapheader->forcecharacter) == skinnum)) { // Force 1. return true; diff --git a/src/r_things.c b/src/r_things.c index fce5845ab..e63001fe1 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2380,9 +2380,6 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) INT32 lightnum; fixed_t limit_dist, hoop_limit_dist; - if (rendermode != render_soft) - return; - // BSP is traversed by subsector. // A sector might have been split into several // subsectors during BSP building. diff --git a/src/s_sound.c b/src/s_sound.c index 81fbda12a..10f86da88 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1783,6 +1783,20 @@ boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi) ); } +INT32 S_ShouldResetMusic(mapheader_t *mapheader) +{ + if (modeattacking) + return 0; + + if (cv_resetmusicbyheader.value) + { + if (mapheader->musforcereset != -1) + return mapheader->musforcereset; + } + + return cv_resetmusic.value; +} + /// ------------------------ /// Music Effects /// ------------------------ @@ -2424,25 +2438,32 @@ boolean S_FadeOutStopMusic(UINT32 ms) /// Init & Others /// ------------------------ +void S_SetMapMusic(mapheader_t *mapheader) +{ + strncpy(mapmusname, mapheader->musname, 7); + mapmusname[6] = 0; + mapmusflags = (mapheader->mustrack & MUSIC_TRACKMASK); + mapmusposition = mapheader->muspos; +} + +void S_PlayMapMusic(mapheader_t *mapheader, boolean reset) +{ + if (mapmusflags & MUSIC_RELOADRESET) + S_SetMapMusic(mapheader); + + if (S_ShouldResetMusic(mapheader) || reset) + S_StopMusic(); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); +} + // // Per level startup code. // Kills playing sounds at start of level, // determines music if any, changes music. // -void S_StartEx(boolean reset) +void S_StartEx(mapheader_t *mapheader, boolean reset) { - if (mapmusflags & MUSIC_RELOADRESET) - { - strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); - mapmusname[6] = 0; - mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK); - mapmusposition = mapheaderinfo[gamemap-1]->muspos; - } - - if (RESETMUSIC || reset) - S_StopMusic(); - S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); - + S_PlayMapMusic(mapheader, reset); S_ResetMusicStack(); music_stack_noposition = false; music_stack_fadeout = 0; @@ -2483,8 +2504,8 @@ static void Command_Tunes_f(void) } else if (!strcasecmp(tunearg, "-default")) { - tunearg = mapheaderinfo[gamemap-1]->musname; - track = mapheaderinfo[gamemap-1]->mustrack; + tunearg = worldmapheader->musname; + track = worldmapheader->mustrack; } if (strlen(tunearg) > 6) // This is automatic -- just show the error just in case diff --git a/src/s_sound.h b/src/s_sound.h index 288859c8d..b49ffe49e 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -18,6 +18,7 @@ #include "sounds.h" #include "m_fixed.h" #include "command.h" +#include "doomstat.h" #include "tables.h" // angle_t #ifdef HAVE_OPENMPT @@ -37,11 +38,7 @@ extern consvar_t cv_resetmusicbyheader; extern consvar_t cv_1upsound; -#define RESETMUSIC (!modeattacking && \ - (cv_resetmusicbyheader.value ? \ - (mapheaderinfo[gamemap-1]->musforcereset != -1 ? mapheaderinfo[gamemap-1]->musforcereset : cv_resetmusic.value) \ - : cv_resetmusic.value) \ - ) +INT32 S_ShouldResetMusic(mapheader_t *mapheader); extern consvar_t cv_gamedigimusic; extern consvar_t cv_gamemidimusic; @@ -125,8 +122,10 @@ void S_InitSfxChannels(INT32 sfxVolume); // void S_StopSounds(void); void S_ClearSfx(void); -void S_StartEx(boolean reset); -#define S_Start() S_StartEx(false) +void S_SetMapMusic(mapheader_t *mapheader); +void S_PlayMapMusic(mapheader_t *mapheader, boolean reset); +void S_StartEx(mapheader_t *mapheader, boolean reset); +#define S_Start(mapheader) S_StartEx(mapheader, false) // // Basically a W_GetNumForName that adds "ds" at the beginning of the string. Returns a lumpnum. diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index f13aaef5d..dd0d97053 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -150,7 +150,7 @@ static void Midiplayer_Onchange(void) Mix_Timidity_addToPathList(cv_miditimiditypath.string); if (restart) - S_StartEx(true); + S_StartEx(worldmapheader, true); } static void MidiSoundfontPath_Onchange(void) @@ -188,7 +188,7 @@ static void MidiSoundfontPath_Onchange(void) if (!Mix_SetSoundFonts(cv_midisoundfontpath.string)) CONS_Alert(CONS_ERROR, "Sound font error: %s", Mix_GetError()); else - S_StartEx(true); + S_StartEx(worldmapheader, true); } } } diff --git a/src/st_stuff.c b/src/st_stuff.c index dcab2bb9c..9312a8678 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -739,7 +739,7 @@ static void ST_drawTime(void) // right now before the island blows up with you on it!" // "Blows up??" *awkward silence* "I've got to get outta // here and find Amy and Tails right away!" - else if (mapheaderinfo[gamemap-1]->countdown) + else if (worldmapheader->countdown) { tics = countdowntimer; downwards = true; @@ -1232,15 +1232,15 @@ static void ST_cacheLevelTitle(void) #define SETPATCH(default, warning, custom, idx) \ { \ lumpnum_t patlumpnum = LUMPERROR; \ - if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \ + if (worldmapheader->custom[0] != '\0') \ { \ - patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \ + patlumpnum = W_CheckNumForName(worldmapheader->custom); \ if (patlumpnum != LUMPERROR) \ lt_patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \ } \ if (patlumpnum == LUMPERROR) \ { \ - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \ + if (!(worldmapheader->levelflags & LF_WARNINGTITLE)) \ lt_patches[idx] = (patch_t *)W_CachePatchName(default, PU_HUDGFX); \ else \ lt_patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \ @@ -1343,9 +1343,9 @@ void ST_runTitleCard(void) // void ST_drawTitleCard(void) { - char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl; - char *subttl = mapheaderinfo[gamemap-1]->subttl; - UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; + char *lvlttl = worldmapheader->lvlttl; + char *subttl = worldmapheader->subttl; + UINT8 actnum = worldmapheader->actnum; INT32 lvlttlxpos, ttlnumxpos, zonexpos; INT32 subttlxpos = BASEVIDWIDTH/2; INT32 ttlscroll = FixedInt(lt_scroll); @@ -1412,7 +1412,7 @@ void ST_drawTitleCard(void) } V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, V_PERPLAYER, lvlttl); - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + if (!(worldmapheader->levelflags & LF_NOZONE)) V_DrawLevelTitle(zonexpos + ttlscroll, 104, V_PERPLAYER, M_GetText("Zone")); V_DrawCenteredString(subttlxpos - ttlscroll, 135, V_PERPLAYER|V_ALLOWLOWERCASE, subttl); @@ -2558,20 +2558,21 @@ static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offse static void ST_doHuntIconsAndSound(void) { INT32 interval = 0, newinterval = 0; + mobj_t **hunt = world->emerald_hunt_locations; - if (hunt1 && hunt1->health) - interval = ST_drawEmeraldHuntIcon(hunt1, hunthoming, -20); + if (hunt[0] && hunt[0]->health) + interval = ST_drawEmeraldHuntIcon(hunt[0], hunthoming, -20); - if (hunt2 && hunt2->health) + if (hunt[1] && hunt[1]->health) { - newinterval = ST_drawEmeraldHuntIcon(hunt2, hunthoming, 0); + newinterval = ST_drawEmeraldHuntIcon(hunt[1], hunthoming, 0); if (newinterval && (!interval || newinterval < interval)) interval = newinterval; } - if (hunt3 && hunt3->health) + if (hunt[2] && hunt[2]->health) { - newinterval = ST_drawEmeraldHuntIcon(hunt3, hunthoming, 20); + newinterval = ST_drawEmeraldHuntIcon(hunt[2], hunthoming, 20); if (newinterval && (!interval || newinterval < interval)) interval = newinterval; } @@ -2671,7 +2672,7 @@ static void ST_overlayDrawer(void) // Check for a valid level title // If the HUD is enabled // And, if Lua is running, if the HUD library has the stage title enabled - if (G_IsTitleCardAvailable() && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer))) + if (G_IsTitleCardAvailable() && *worldmapheader->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer))) { stagetitle = true; ST_preDrawTitleCard(); diff --git a/src/v_video.c b/src/v_video.c index 5674603eb..8d53f06f4 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -399,7 +399,7 @@ const char *R_GetPalname(UINT16 num) const char *GetPalette(void) { if (gamestate == GS_LEVEL) - return R_GetPalname(mapheaderinfo[gamemap-1]->palette); + return R_GetPalname(worldmapheader->palette); return "PLAYPAL"; } diff --git a/src/y_inter.c b/src/y_inter.c index 6e7d362a7..747680308 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -248,8 +248,8 @@ void Y_LoadIntermissionData(void) // grab an interscreen if appropriate - if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + if (worldmapheader->interscreen[0] != '#') + interpic = W_CachePatchName(worldmapheader->interscreen, PU_PATCH); else // no interscreen? use default background bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); break; @@ -263,8 +263,8 @@ void Y_LoadIntermissionData(void) data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); // grab an interscreen if appropriate - if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + if (worldmapheader->interscreen[0] != '#') + interpic = W_CachePatchName(worldmapheader->interscreen, PU_PATCH); else // no interscreen? use default background bgtile = W_CachePatchName("SPECTILE", PU_PATCH); break; @@ -1043,15 +1043,15 @@ void Y_Ticker(void) if (!intertic) // first time only { - if (mapheaderinfo[gamemap-1]->musinterfadeout + if (worldmapheader->musinterfadeout #ifdef _WIN32 // can't fade midi due to win32 volume hack && S_MusicType() != MU_MID #endif ) - S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout); - else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) - S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it + S_FadeOutStopMusic(worldmapheader->musinterfadeout); + else if (worldmapheader->musintername[0] && S_MusicExists(worldmapheader->musintername, !midi_disabled, !digital_disabled)) + S_ChangeMusicInternal(worldmapheader->musintername, false); // don't loop it else S_ChangeMusicInternal("_clear", false); // don't loop it tallydonetic = -1; @@ -1120,15 +1120,15 @@ void Y_Ticker(void) if (!intertic) // first time only { - if (mapheaderinfo[gamemap-1]->musinterfadeout + if (worldmapheader->musinterfadeout #ifdef _WIN32 // can't fade midi due to win32 volume hack && S_MusicType() != MU_MID #endif ) - S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musinterfadeout); - else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) - S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it + S_FadeOutStopMusic(worldmapheader->musinterfadeout); + else if (worldmapheader->musintername[0] && S_MusicExists(worldmapheader->musintername, !midi_disabled, !digital_disabled)) + S_ChangeMusicInternal(worldmapheader->musintername, false); // don't loop it else S_ChangeMusicInternal("_clear", false); // don't loop it tallydonetic = -1; @@ -1348,10 +1348,10 @@ void Y_StartIntermission(void) data.coop.tics = players[consoleplayer].realtime; // get act number - data.coop.actnum = mapheaderinfo[gamemap-1]->actnum; + data.coop.actnum = worldmapheader->actnum; // grab an interscreen if appropriate - if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') + if (worldmapheader->interscreen[0] != '#') { useinterpic = true; usebuffer = false; @@ -1369,9 +1369,9 @@ void Y_StartIntermission(void) // set up the "got through act" message according to skin name if (stagefailed) { - strcpy(data.coop.passed1, mapheaderinfo[gamemap-1]->lvlttl); + strcpy(data.coop.passed1, worldmapheader->lvlttl); - if (mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) + if (worldmapheader->levelflags & LF_NOZONE) { data.spec.passed2[0] = '\0'; } @@ -1386,25 +1386,25 @@ void Y_StartIntermission(void) if (strlen(skins[players[consoleplayer].skin].realname) > 13) { strcpy(data.coop.passed1, "you got"); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + strcpy(data.coop.passed2, (worldmapheader->actnum) ? "through act" : "through the act"); } // long enough that "X GOT" won't fit so use "X PASSED THE ACT" else if (strlen(skins[players[consoleplayer].skin].realname) > 8) { strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act"); + strcpy(data.coop.passed2, (worldmapheader->actnum) ? "passed act" : "passed the act"); } // length is okay for normal use else { snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got", skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + strcpy(data.coop.passed2, (worldmapheader->actnum) ? "through act" : "through the act"); } } // set X positions - if (mapheaderinfo[gamemap-1]->actnum) + if (worldmapheader->actnum) { data.coop.passedx1 = 62 + (176 - V_LevelNameWidth(data.coop.passed1))/2; data.coop.passedx2 = 62 + (176 - V_LevelNameWidth(data.coop.passed2))/2; @@ -1418,7 +1418,7 @@ void Y_StartIntermission(void) // at the start of intermission, and precalculating it would preclude mods // changing the font to one of a slightly different width. - if ((stagefailed) && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + if ((stagefailed) && !(worldmapheader->levelflags & LF_NOZONE)) { // Bit of a hack, offset so that the "Zone" text is right aligned like title cards. data.coop.passedx2 = (data.coop.passedx1 + V_LevelNameWidth(data.coop.passed1)) - V_LevelNameWidth(data.coop.passed2); @@ -1433,7 +1433,7 @@ void Y_StartIntermission(void) Y_AwardSpecialStageBonus(); // grab an interscreen if appropriate - if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') + if (worldmapheader->interscreen[0] != '#') useinterpic = true; else useinterpic = false;