From 229dde1e67222044abdea42b8ba01b0c5c1f3384 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 10 Jan 2019 23:08:35 +0100 Subject: [PATCH] - moved the non-map timers out of LevelLocals into GameSession and moved the composite compatibility flags into FLevelLocals, because they are level specific. --- src/bbannouncer.cpp | 4 +- src/d_main.cpp | 21 +++++----- src/d_net.cpp | 7 +++- src/doomstat.h | 1 - src/dsectoreffect.cpp | 4 +- src/g_game.cpp | 15 ++++--- src/g_level.cpp | 40 ++++++++++--------- src/g_levellocals.h | 17 +++++--- src/g_shared/a_lightning.cpp | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 14 +++---- src/hu_scores.cpp | 2 +- src/hwrenderer/scene/hw_drawlist.cpp | 3 +- src/hwrenderer/scene/hw_drawlist.h | 1 + src/hwrenderer/scene/hw_walls.cpp | 2 +- src/maploader/compatibility.cpp | 25 +++++++----- src/maploader/maploader.cpp | 4 +- src/maploader/slopes.cpp | 2 +- src/p_acs.cpp | 8 ++-- src/p_conversation.cpp | 2 +- src/p_doors.cpp | 2 +- src/p_enemy.cpp | 12 +++--- src/p_floor.cpp | 8 ++-- src/p_interaction.cpp | 8 ++-- src/p_lights.cpp | 2 +- src/p_lnspec.cpp | 2 +- src/p_map.cpp | 32 +++++++-------- src/p_maputl.cpp | 2 +- src/p_maputl.h | 3 +- src/p_mobj.cpp | 36 ++++++++--------- src/p_saveg.cpp | 14 +++---- src/p_sectors.cpp | 12 +++--- src/p_setup.cpp | 2 +- src/p_sight.cpp | 2 +- src/p_spec.cpp | 6 +-- src/p_teleport.cpp | 4 +- src/p_tick.cpp | 4 +- src/p_trace.cpp | 2 +- src/po_man.cpp | 2 +- src/s_sound.cpp | 22 +++++----- src/scripting/backend/codegen.cpp | 4 +- src/scripting/vmthunks.cpp | 4 +- src/scripting/vmthunks_actors.cpp | 26 ++++++++++++ src/statistics.cpp | 2 +- src/swrenderer/line/r_line.cpp | 4 +- src/swrenderer/line/r_renderdrawsegment.cpp | 6 +-- src/swrenderer/things/r_visiblespritelist.cpp | 2 +- wadsrc/static/zscript/actor.txt | 4 +- wadsrc/static/zscript/base.txt | 14 +++++-- wadsrc/static/zscript/doom/fatso.txt | 3 +- wadsrc/static/zscript/doom/painelemental.txt | 4 +- wadsrc/static/zscript/shared/morph.txt | 6 +-- wadsrc/static/zscript/statusbar/alt_hud.txt | 10 ++--- .../static/zscript/statusbar/heretic_sbar.txt | 2 +- wadsrc/static/zscript/statusbar/statusbar.txt | 2 +- 54 files changed, 248 insertions(+), 196 deletions(-) diff --git a/src/bbannouncer.cpp b/src/bbannouncer.cpp index 80de8b979f..e5a4e9e5e4 100644 --- a/src/bbannouncer.cpp +++ b/src/bbannouncer.cpp @@ -182,9 +182,9 @@ static FRandom pr_bbannounce ("BBAnnounce"); void DoVoiceAnnounce (const char *sound) { // Don't play announcements too close together - if (LastAnnounceTime == 0 || LastAnnounceTime <= level.time-5) + if (LastAnnounceTime == 0 || LastAnnounceTime <= currentSession->time-5) { - LastAnnounceTime = level.time; + LastAnnounceTime = currentSession->time; S_Sound (CHAN_VOICE, sound, 1, ATTN_NONE); } } diff --git a/src/d_main.cpp b/src/d_main.cpp index 40f58d594c..18b404bd98 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -502,9 +502,6 @@ CVAR (Flag, sv_respawnsuper, dmflags2, DF2_RESPAWN_SUPER); // //========================================================================== -int i_compatflags, i_compatflags2; // internal compatflags composed from the compatflags CVAR and MAPINFO settings -int ii_compatflags, ii_compatflags2, ib_compatflags; - EXTERN_CVAR(Int, compatmode) static int GetCompatibility(FLevelLocals *Level, int mask) @@ -521,17 +518,23 @@ static int GetCompatibility2(FLevelLocals *Level, int mask) CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) { - int old = i_compatflags; - i_compatflags = GetCompatibility(&level, self) | ii_compatflags; - if ((old ^ i_compatflags) & COMPATF_POLYOBJ) + ForAllLevels([&](FLevelLocals *Level) { - level.ClearAllSubsectorLinks(); - } + int old = Level->i_compatflags; + Level->i_compatflags = GetCompatibility(Level, self) | Level->ii_compatflags; + if ((old ^ Level->i_compatflags) & COMPATF_POLYOBJ) + { + Level->ClearAllSubsectorLinks(); + } + }); } CUSTOM_CVAR (Int, compatflags2, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) { - i_compatflags2 = GetCompatibility2(&level, self) | ii_compatflags2; + ForAllLevels([&](FLevelLocals *Level) + { + Level->i_compatflags2 = GetCompatibility2(Level, self) | Level->ii_compatflags2; + }); } CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL) diff --git a/src/d_net.cpp b/src/d_net.cpp index 89f0afec1e..1cf0e60092 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2226,8 +2226,11 @@ void Net_DoCommand (int type, uint8_t **stream, int player) s = ReadString (stream); // Using LEVEL_NOINTERMISSION tends to throw the game out of sync. // That was a long time ago. Maybe it works now? - level.flags |= LEVEL_CHANGEMAPCHEAT; - G_ChangeLevel(s, pos, 0); + if (currentSession) + { + currentSession->Levelinfo[0]->flags |= LEVEL_CHANGEMAPCHEAT; + G_ChangeLevel(s, pos, 0); + } break; case DEM_SUICIDE: diff --git a/src/doomstat.h b/src/doomstat.h index 6f0007f4c4..23356b25ff 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -248,7 +248,6 @@ EXTERN_CVAR (Int, dmflags2); // [BC] EXTERN_CVAR (Int, compatflags); EXTERN_CVAR (Int, compatflags2); -extern int i_compatflags, i_compatflags2, ii_compatflags, ii_compatflags2, ib_compatflags; // Filters from AddAutoloadFiles(). Used to filter files from archives. extern FString LumpFilterIWAD; diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index c3711f3f74..0aa8bc7d27 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -221,7 +221,7 @@ EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direct //destheight = (dest < ceilingheight) ? dest : ceilingheight; if (!ceilingplane.isSlope() && !floorplane.isSlope() && !PortalIsLinked(sector_t::ceiling) && - (!(i_compatflags2 & COMPATF2_FLOORMOVE) && -dest > ceilingplane.fD())) + (!(Level->i_compatflags2 & COMPATF2_FLOORMOVE) && -dest > ceilingplane.fD())) { dest = -ceilingplane.fD(); } @@ -311,7 +311,7 @@ EMoveResult sector_t::MoveCeiling(double speed, double dest, int crush, int dire //destheight = (dest > floorheight) ? dest : floorheight; if (!ceilingplane.isSlope() && !floorplane.isSlope() && !PortalIsLinked(sector_t::floor) && - (!(i_compatflags2 & COMPATF2_FLOORMOVE) && dest < -floorplane.fD())) + (!(Level->i_compatflags2 & COMPATF2_FLOORMOVE) && dest < -floorplane.fD())) { dest = -floorplane.fD(); } diff --git a/src/g_game.cpp b/src/g_game.cpp index f55c9a3356..d2d8572361 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1685,11 +1685,11 @@ void G_DoPlayerPop(int playernum) } // [RH] Make the player disappear - level.Behaviors.StopMyScripts(players[playernum].mo); + players[playernum].mo->Level->Behaviors.StopMyScripts(players[playernum].mo); // [ZZ] fire player disconnect hook E_PlayerDisconnected(playernum); // [RH] Let the scripts know the player left - level.Behaviors.StartTypedScripts(&level, SCRIPT_Disconnect, players[playernum].mo, true, playernum, true); + players[playernum].mo->Level->Behaviors.StartTypedScripts(&level, SCRIPT_Disconnect, players[playernum].mo, true, playernum, true); if (players[playernum].mo != NULL) { P_DisconnectEffect(players[playernum].mo); @@ -1902,7 +1902,7 @@ void G_DoLoadGame () arc("ticrate", time[0]) ("leveltime", time[1]); // dearchive all the modifications - level.time = Scale(time[1], TICRATE, time[0]); + currentSession->time = Scale(time[1], TICRATE, time[0]); G_ReadSnapshots(resfile.get()); resfile.reset(nullptr); // we no longer need the resource file below this point @@ -2081,9 +2081,8 @@ static void PutSaveComment (FSerializer &arc) }); // Append elapsed time - levelTime = level.time / TICRATE; - comment.AppendFormat("time: %02d:%02d:%02d", - levelTime/3600, (levelTime%3600)/60, levelTime%60); + levelTime = currentSession->time / TICRATE; + comment.AppendFormat("time: %02d:%02d:%02d", levelTime/3600, (levelTime%3600)/60, levelTime%60); // Write out the comment arc.AddString("Comment", comment); @@ -2196,11 +2195,11 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio savegameglobals.AddString("importantcvars", vars.GetChars()); } - if (level.time != 0 || level.maptime != 0) + if (currentSession->time != 0) { int tic = TICRATE; savegameglobals("ticrate", tic); - savegameglobals("leveltime", level.time); + savegameglobals("leveltime", currentSession->time); } STAT_Serialize(savegameglobals); diff --git a/src/g_level.cpp b/src/g_level.cpp index dac841bcab..a3c0c7299c 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -540,9 +540,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel) } FRandom::StaticClearRandom (); P_ClearACSVars(true); - level.time = 0; + currentSession->time = 0; + currentSession->totaltime = 0; + level.maptime = 0; - level.totaltime = 0; level.spawnindex = 0; if (!multiplayer || !deathmatch) @@ -610,7 +611,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill Printf (TEXTCOLOR_RED "Unloading scripts cannot exit the level again.\n"); return; } - if (gameaction == ga_completed && !(i_compatflags2 & COMPATF2_MULTIEXIT)) // do not exit multiple times. + if (gameaction == ga_completed && !(currentSession->Levelinfo[0]->i_compatflags2 & COMPATF2_MULTIEXIT)) // do not exit multiple times. { return; } @@ -665,7 +666,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill startpos = position; gameaction = ga_completed; - level.SetMusicVolume(1.0); + currentSession->SetMusicVolume(1.0); if (nextinfo != NULL) { @@ -738,18 +739,19 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill const char *G_GetExitMap() { - return level.NextMap; + return currentSession->Levelinfo[0]->NextMap; } const char *G_GetSecretExitMap() { - const char *nextmap = level.NextMap; + auto Level = currentSession->Levelinfo[0]; + const char *nextmap = Level->NextMap; - if (level.NextSecretMap.Len() > 0) + if (Level->NextSecretMap.Len() > 0) { - if (P_CheckMapData(level.NextSecretMap)) + if (P_CheckMapData(Level->NextSecretMap)) { - nextmap = level.NextSecretMap; + nextmap = Level->NextSecretMap; } } return nextmap; @@ -757,18 +759,19 @@ const char *G_GetSecretExitMap() //========================================================================== // +// The flags here must always be on the primary level. // //========================================================================== void G_ExitLevel (int position, bool keepFacing) { - level.flags3 |= LEVEL3_EXITNORMALUSED; + currentSession->Levelinfo[0]->flags3 |= LEVEL3_EXITNORMALUSED; G_ChangeLevel(G_GetExitMap(), position, keepFacing ? CHANGELEVEL_KEEPFACING : 0); } void G_SecretExitLevel (int position) { - level.flags3 |= LEVEL3_EXITSECRETUSED; + currentSession->Levelinfo[0]->flags3 |= LEVEL3_EXITSECRETUSED; G_ChangeLevel(G_GetSecretExitMap(), position, 0); } @@ -847,14 +850,14 @@ void G_DoCompleted () wminfo.partime = TICRATE * Level->partime; wminfo.sucktime = Level->sucktime; wminfo.pnum = consoleplayer; - wminfo.totaltime = Level->totaltime; + wminfo.totaltime = currentSession->totaltime; for (i=0 ; itime; memcpy (wminfo.plyr[i].frags, players[i].frags , sizeof(wminfo.plyr[i].frags)); wminfo.plyr[i].fragcount = players[i].fragcount; @@ -922,7 +925,7 @@ void G_DoCompleted () { // Reset world variables for the new hub. P_ClearACSVars(false); } - level.time = 0; + currentSession->time = 0; level.maptime = 0; level.spawnindex = 0; } @@ -1477,7 +1480,7 @@ int G_FinishTravel () VMCall(func, params, 1, nullptr, 0); } } - if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED) + if (pawn->Level->ib_compatflags & BCOMPATF_RESETPLAYERSPEED) { pawn->Speed = pawn->GetDefault()->Speed; } @@ -1505,6 +1508,8 @@ void FLevelLocals::InitLevelLocals () // Session data should be moved out of here later! currentSession->F1Pic = info->F1Pic; + currentSession->MusicVolume = 1.f; + P_InitParticles(this); P_ClearParticles(this); @@ -1560,7 +1565,6 @@ void FLevelLocals::InitLevelLocals () levelnum = info->levelnum; Music = info->Music; musicorder = info->musicorder; - MusicVolume = 1.f; HasHeightSecs = false; LevelName = info->LookupLevelName(); @@ -2198,9 +2202,9 @@ void FLevelLocals::SetMusic() // //========================================================================== -void FLevelLocals::SetMusicVolume(float f) +void FGameSession::SetMusicVolume(float f) { - MusicVolume = f; + if (currentSession) currentSession->MusicVolume = f; I_SetMusicVolume(f); } diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 2a47e37d32..4c809d787b 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -115,6 +115,11 @@ struct FLevelData FDialogueIDMap DialogueRoots; FDialogueMap ClassRoots; + int ii_compatflags = 0; + int ii_compatflags2 = 0; + int ib_compatflags = 0; + int i_compatflags = 0; + int i_compatflags2 = 0; }; @@ -128,7 +133,6 @@ struct FLevelLocals : public FLevelData void AddScroller(int secnum); void SetInterMusic(const char *nextmap); void SetMusic(); - void SetMusicVolume(float v); void ClearLevelData(); void ClearPortals(); bool CheckIfExitIsGood(AActor *self, level_info_t *newmap); @@ -162,9 +166,7 @@ struct FLevelLocals : public FLevelData DSectorMarker *SectorMarker; uint8_t md5[16]; // for savegame validation. If the MD5 does not match the savegame won't be loaded. - int time; // time in the hub - int maptime; // time in the map - int totaltime; // time in the game + int maptime; // time in the map int starttime; int partime; int sucktime; @@ -257,7 +259,6 @@ struct FLevelLocals : public FLevelData FName deathsequence; float pixelstretch; - float MusicVolume; // Hardware render stuff that can either be set via CVAR or MAPINFO ELightMode lightMode; @@ -302,6 +303,12 @@ class FGameSession public: TArray Levelinfo; FString F1Pic; + float MusicVolume; + int time; // time in the hub + int totaltime; // time in the game + + + void SetMusicVolume(float vol); }; extern FGameSession *currentSession; diff --git a/src/g_shared/a_lightning.cpp b/src/g_shared/a_lightning.cpp index 1d667bf4fe..a23934b6e1 100644 --- a/src/g_shared/a_lightning.cpp +++ b/src/g_shared/a_lightning.cpp @@ -168,7 +168,7 @@ void DLightningThinker::LightningFlash () } else { - if (pr_lightning() < 128 && !(Level->time&32)) + if (pr_lightning() < 128 && !(currentSession->time&32)) { NextLightningFlash = ((pr_lightning()&7)+2)*35; } diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index c3f2f24e85..6d5955cc47 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -918,7 +918,7 @@ class CommandDrawString : public SBarInfoCommand break; case TIME: { - int sec = Tics2Seconds(statusBar->Level->time); + int sec = Tics2Seconds(currentSession->time); str.Format("%02d:%02d:%02d", sec / 3600, (sec % 3600) / 60, sec % 60); break; } @@ -1461,7 +1461,7 @@ class CommandDrawNumber : public CommandDrawString if(statusBar->CPlayer->mo->waterlevel < 3) num = statusBar->Level->airsupply/TICRATE; else - num = clamp((statusBar->CPlayer->air_finished - statusBar->Level->time + (TICRATE-1))/TICRATE, 0, INT_MAX); + num = clamp((statusBar->CPlayer->air_finished - currentSession->time + (TICRATE-1))/TICRATE, 0, INT_MAX); break; } case SELECTEDINVENTORY: @@ -1502,7 +1502,7 @@ class CommandDrawNumber : public CommandDrawString } default: break; } - if(interpolationSpeed != 0 && (!hudChanged || statusBar->Level->time == 1)) + if(interpolationSpeed != 0 && (!hudChanged || currentSession->time == 1)) { if(num < drawValue) drawValue -= clamp((drawValue - num) >> 2, 1, interpolationSpeed); @@ -2751,7 +2751,7 @@ class CommandDrawBar : public SBarInfoCommand break; } case AIRTIME: - value = clamp(statusBar->CPlayer->air_finished - statusBar->Level->time, 0, INT_MAX); + value = clamp(statusBar->CPlayer->air_finished - currentSession->time, 0, INT_MAX); max = statusBar->Level->airsupply; break; case POWERUPTIME: @@ -2798,7 +2798,7 @@ class CommandDrawBar : public SBarInfoCommand } else value = 0; - if(interpolationSpeed != 0 && (!hudChanged || statusBar->Level->time == 1)) + if(interpolationSpeed != 0 && (!hudChanged || currentSession->time == 1)) { // [BL] Since we used a percentage (in order to get the most fluid animation) // we need to establish a cut off point so the last pixel won't hang as the animation slows @@ -3192,7 +3192,7 @@ class CommandDrawGem : public SBarInfoCommand goalValue = reverse ? 100 - goalValue : goalValue; - if(interpolationSpeed != 0 && (!hudChanged || statusBar->Level->time == 1)) // At the start force an animation + if(interpolationSpeed != 0 && (!hudChanged || currentSession->time == 1)) // At the start force an animation { if(goalValue < drawValue) drawValue -= clamp((drawValue - goalValue) >> 2, 1, interpolationSpeed); @@ -3202,7 +3202,7 @@ class CommandDrawGem : public SBarInfoCommand else drawValue = goalValue; - if(wiggle && statusBar->Level->time & 1) + if(wiggle && currentSession->time & 1) chainWiggle = pr_chainwiggle() & 1; } protected: diff --git a/src/hu_scores.cpp b/src/hu_scores.cpp index a4a261a77d..c0e084aa96 100644 --- a/src/hu_scores.cpp +++ b/src/hu_scores.cpp @@ -368,7 +368,7 @@ static void HU_DrawTimeRemaining (int y) if (deathmatch && timelimit && gamestate == GS_LEVEL) { char str[80]; - int timeleft = (int)(timelimit * TICRATE * 60) - level.maptime; + int timeleft = (int)(timelimit * TICRATE * 60) - currentSession->Levelinfo[0]->maptime; int hours, minutes, seconds; if (timeleft < 0) diff --git a/src/hwrenderer/scene/hw_drawlist.cpp b/src/hwrenderer/scene/hw_drawlist.cpp index f50c49b8bc..b6f4859f11 100644 --- a/src/hwrenderer/scene/hw_drawlist.cpp +++ b/src/hwrenderer/scene/hw_drawlist.cpp @@ -588,7 +588,7 @@ inline int HWDrawList::CompareSprites(SortNode * a,SortNode * b) int res = s1->depth - s2->depth; if (res != 0) return -res; - else return (i_compatflags & COMPATF_SPRITESORT)? s2->index-s1->index : s1->index-s2->index; + else return reverseSort? s2->index-s1->index : s1->index-s2->index; } //========================================================================== @@ -702,6 +702,7 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head) //========================================================================== void HWDrawList::Sort(HWDrawInfo *di) { + reverseSort = !!(di->Level->i_compatflags & COMPATF_SPRITESORT); SortZ = di->Viewpoint.Pos.Z; MakeSortList(); sorted = DoSort(di, SortNodes[SortNodeStart]); diff --git a/src/hwrenderer/scene/hw_drawlist.h b/src/hwrenderer/scene/hw_drawlist.h index 66ae468ed0..e4279516c2 100644 --- a/src/hwrenderer/scene/hw_drawlist.h +++ b/src/hwrenderer/scene/hw_drawlist.h @@ -67,6 +67,7 @@ struct HWDrawList int SortNodeStart; float SortZ; SortNode * sorted; + bool reverseSort; public: HWDrawList() diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index a83fb4fbc6..d6c18e84df 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -2063,7 +2063,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ FTexture *tex = TexMan.GetTexture(seg->sidedef->GetTexture(side_t::mid), true); if (tex != NULL) { - if (i_compatflags & COMPATF_MASKEDMIDTEX) + if (di->Level->i_compatflags & COMPATF_MASKEDMIDTEX) { tex = tex->GetRawTexture(); } diff --git a/src/maploader/compatibility.cpp b/src/maploader/compatibility.cpp index cecbb0e1ed..70aa5196ed 100644 --- a/src/maploader/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -279,17 +279,17 @@ FName MapLoader::CheckCompatibility(MapData *map) if (BCompatMap.CountUsed() == 0) ParseCompatibility(); - ii_compatflags = 0; - ii_compatflags2 = 0; - ib_compatflags = 0; + Level->ii_compatflags = 0; + Level->ii_compatflags2 = 0; + Level->ib_compatflags = 0; // When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT. // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. // TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD. if (Wads.GetLumpFile(map->lumpnum) == Wads.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM) { - ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; - if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX; + Level->ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; + if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX; } map->GetChecksum(md5.Bytes); @@ -319,18 +319,18 @@ FName MapLoader::CheckCompatibility(MapData *map) if (flags != NULL) { - ii_compatflags |= flags->CompatFlags[SLOT_COMPAT]; - ii_compatflags2 |= flags->CompatFlags[SLOT_COMPAT2]; - ib_compatflags |= flags->CompatFlags[SLOT_BCOMPAT]; + Level->ii_compatflags |= flags->CompatFlags[SLOT_COMPAT]; + Level->ii_compatflags2 |= flags->CompatFlags[SLOT_COMPAT2]; + Level->ib_compatflags |= flags->CompatFlags[SLOT_BCOMPAT]; } - // Reset i_compatflags + // Reset Level->i_compatflags compatflags.Callback(); compatflags2.Callback(); // Set floatbob compatibility for all maps with an original Hexen MAPINFO. if (Level->flags2 & LEVEL2_HEXENHACK) { - ib_compatflags |= BCOMPATF_FLOATBOB; + Level->ib_compatflags |= BCOMPATF_FLOATBOB; } return FName(hash, true); // if this returns NAME_None it means there is no scripted compatibility handler. } @@ -556,6 +556,9 @@ CCMD (mapchecksum) CCMD (hiddencompatflags) { - Printf("%08x %08x %08x\n", ii_compatflags, ii_compatflags2, ib_compatflags); + ForAllLevels([](FLevelLocals *Level) + { + Printf("%s: %08x %08x %08x\n", Level->MapName.GetChars(), Level->ii_compatflags, Level->ii_compatflags2, Level->ib_compatflags); + }); } diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 98212d2e64..3840869348 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -1448,7 +1448,7 @@ void MapLoader::SetLineID (int i, line_t *ld) break; case Plane_Align: - if (!(ib_compatflags & BCOMPATF_NOSLOPEID)) setid = ld->args[2]; + if (!(Level->ib_compatflags & BCOMPATF_NOSLOPEID)) setid = ld->args[2]; break; case Static_Init: @@ -2948,7 +2948,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) Level->maptype = MAPTYPE_UDMF; } FName checksum = CheckCompatibility(map); - if (ib_compatflags & BCOMPATF_REBUILDNODES) + if (Level->ib_compatflags & BCOMPATF_REBUILDNODES) { ForceNodeBuild = true; } diff --git a/src/maploader/slopes.cpp b/src/maploader/slopes.cpp index 63a2243fdb..06443ae274 100644 --- a/src/maploader/slopes.cpp +++ b/src/maploader/slopes.cpp @@ -179,7 +179,7 @@ void MapLoader::SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi DVector3 norm; - if (ib_compatflags & BCOMPATF_SETSLOPEOVERFLOW) + if (Level->ib_compatflags & BCOMPATF_SETSLOPEOVERFLOW) { // We have to consider an integer multiplication overflow here. norm[0] = FixedToFloat(FloatToFixed(zang.Cos()) * FloatToFixed(xyang.Cos())) / 65536.; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 02cc390a1e..d6e990a598 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5428,7 +5428,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } else { - return players[args[0]].air_finished - Level->time; + return players[args[0]].air_finished - currentSession->time; } } @@ -5440,7 +5440,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } else { - players[args[0]].air_finished = args[1] + Level->time; + players[args[0]].air_finished = args[1] + currentSession->time; return 1; } } @@ -6491,7 +6491,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_SetMusicVolume: - Level->SetMusicVolume(ACSToFloat(args[0])); + currentSession->SetMusicVolume(ACSToFloat(args[0])); break; case ACSF_CheckProximity: @@ -8827,7 +8827,7 @@ scriptwait: // [BC] End ST PCD's case PCD_TIMER: - PushToStack (Level->time); + PushToStack (currentSession->time); break; case PCD_SECTORSOUND: diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index e45af149d1..307455ac4f 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1077,7 +1077,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply if (isconsole) { - I_SetMusicVolume (player->mo->Level->MusicVolume); + I_SetMusicVolume (currentSession->MusicVolume); } } diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 0b9dc38e3d..18dd731079 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -350,7 +350,7 @@ DDoor::DDoor (sector_t *sec, EVlDoor type, double speed, int delay, int lightTag vertex_t *spot; double height; - if (i_compatflags & COMPATF_NODOORLIGHT) + if (Level->i_compatflags & COMPATF_NODOORLIGHT) { m_LightTag = 0; } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 6fd23f4b5c..326634a47c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -864,7 +864,7 @@ void P_NewChaseDir(AActor * actor) if (actor->floorz - actor->dropoffz > actor->MaxDropOffHeight && actor->Z() <= actor->floorz && !(actor->flags & MF_DROPOFF) && !(actor->flags2 & MF2_ONMOBJ) && - !(actor->flags & MF_FLOAT) && !(i_compatflags & COMPATF_DROPOFF)) + !(actor->flags & MF_FLOAT) && !(actor->Level->i_compatflags & COMPATF_DROPOFF)) { FBoundingBox box(actor->X(), actor->Y(), actor->radius); FBlockLinesIterator it(actor->Level, box); @@ -1717,7 +1717,7 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) // the player then, eh? if(!(actor->flags6 & MF6_SEEINVISIBLE)) { - if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) || + if ((player->mo->flags & MF_SHADOW && !(actor->Level->i_compatflags & COMPATF_INVISIBILITY)) || player->mo->flags3 & MF3_GHOST) { if (player->mo->Distance2D (actor) > 128 && player->mo->Vel.XY().LengthSquared() < 5*5) @@ -1780,7 +1780,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } else { - targ = (i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? + targ = (Level->i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? self->Sector->SoundTarget : self->LastHeard; // [RH] If the soundtarget is dead, don't chase it @@ -1915,7 +1915,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LookEx) { if (!(flags & LOF_NOSOUNDCHECK)) { - targ = (i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? + targ = (Level->i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? self->Sector->SoundTarget : self->LastHeard; if (targ != NULL) { @@ -2730,7 +2730,7 @@ bool P_CheckForResurrection(AActor *self, bool usevilestates) { corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses } - if (ib_compatflags & BCOMPATF_VILEGHOSTS) + if (self->Level->ib_compatflags & BCOMPATF_VILEGHOSTS) { corpsehit->Height *= 4; // [GZ] This was a commented-out feature, so let's make use of it, @@ -3113,7 +3113,7 @@ void A_BossDeath(AActor *self) LEVEL_SORCERER2SPECIAL)) == 0) return; - if ((i_compatflags & COMPATF_ANYBOSSDEATH) || ( // [GZ] Added for UAC_DEAD + if ((Level->i_compatflags & COMPATF_ANYBOSSDEATH) || ( // [GZ] Added for UAC_DEAD ((Level->flags & LEVEL_MAP07SPECIAL) && (type == NAME_Fatso || type == NAME_Arachnotron)) || ((Level->flags & LEVEL_BRUISERSPECIAL) && (type == NAME_BaronOfHell)) || ((Level->flags & LEVEL_CYBORGSPECIAL) && (type == NAME_Cyberdemon)) || diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 8bab22dc84..4e8475ee66 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -465,7 +465,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, // [Graf Zahl] // Don't make sounds for instant movement hacks but make an exception for // switches that activate their own back side. - if (!(i_compatflags & COMPATF_SILENT_INSTANT_FLOORS)) + if (!(sec->Level->i_compatflags & COMPATF_SILENT_INSTANT_FLOORS)) { if (!line || !(line->activation & (SPAC_Use | SPAC_Push)) || line->backsector != sec) silent = true; @@ -622,7 +622,7 @@ bool EV_BuildStairs (FLevelLocals *Level, int tag, DFloor::EStair type, line_t * FSectorTagIterator itr(Level->tagManager, tag, line); // The compatibility mode doesn't work with a hashing algorithm. // It needs the original linear search method. This was broken in Boom. - bool compatible = tag != 0 && (i_compatflags & COMPATF_STAIRINDEX); + bool compatible = tag != 0 && (Level->i_compatflags & COMPATF_STAIRINDEX); while ((secnum = itr.NextCompat(compatible, secnum)) >= 0) { sec = &Level->sectors[secnum]; @@ -711,14 +711,14 @@ bool EV_BuildStairs (FLevelLocals *Level, int tag, DFloor::EStair type, line_t * // Doom bug: Height was changed before discarding the sector as part of the stairs. // Needs to be compatibility optioned because some maps (Eternall MAP25) depend on it. - if (i_compatflags & COMPATF_STAIRINDEX) height += stairstep; + if (Level->i_compatflags & COMPATF_STAIRINDEX) height += stairstep; // if sector's floor already moving, look for another //jff 2/26/98 special lockout condition for retriggering if (tsec->PlaneMoving(sector_t::floor) || tsec->stairlock) continue; - if (!(i_compatflags & COMPATF_STAIRINDEX)) height += stairstep; + if (!(Level->i_compatflags & COMPATF_STAIRINDEX)) height += stairstep; ok = true; break; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 832af2b390..80aa82914d 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -492,7 +492,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf source->player->multicount++; if (source->player->lastkilltime > 0) { - if (source->player->lastkilltime < Level->time - 3*TICRATE) + if (source->player->lastkilltime < currentSession->time - 3*TICRATE) { source->player->multicount = 1; } @@ -535,7 +535,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf } } } - source->player->lastkilltime = Level->time; + source->player->lastkilltime = currentSession->time; } // [RH] Implement fraglimit @@ -566,7 +566,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf Level->Behaviors.StartTypedScripts (Level, SCRIPT_Death, this, true); // [RH] Force a delay between death and respawn - player->respawn_time = Level->time + TICRATE; + player->respawn_time = currentSession->time + TICRATE; //Added by MC: Respawn bots if (bglobal.botnum && !demoplayback) @@ -1807,7 +1807,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain } auto Level = player->mo->Level; - if (!(Level->time & 63) && playPainSound) + if (!(Level->maptime & 63) && playPainSound) { FState *painstate = target->FindState(NAME_Pain, player->poisonpaintype); if (painstate != NULL) diff --git a/src/p_lights.cpp b/src/p_lights.cpp index 7cb90de95a..af34820b15 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -594,7 +594,7 @@ void EV_LightTurnOn (FLevelLocals *Level, int tag, int bright) //jff 5/17/98 unless compatibility optioned //then maximum near ANY tagged sector - if (i_compatflags & COMPATF_LIGHT) + if (Level->i_compatflags & COMPATF_LIGHT) { bright = tbright; } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index b42ef3e0b3..5792056653 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -3067,7 +3067,7 @@ FUNC(LS_SetPlayerProperty) { int i; - if ((ib_compatflags & BCOMPATF_LINKFROZENPROPS) && (mask & (CF_FROZEN | CF_TOTALLYFROZEN))) + if ((Level->ib_compatflags & BCOMPATF_LINKFROZENPROPS) && (mask & (CF_FROZEN | CF_TOTALLYFROZEN))) { // Clearing one of these properties clears both of them (if the compat flag is set.) mask = CF_FROZEN | CF_TOTALLYFROZEN; } diff --git a/src/p_map.cpp b/src/p_map.cpp index 10f0858df7..cac17d2ea8 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -459,7 +459,7 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi // [RH] Z-Check // But not if not MF2_PASSMOBJ or MF3_DONTOVERLAP are set! // Otherwise those things would get stuck inside each other. - if ((thing->flags2 & MF2_PASSMOBJ || th->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) + if ((thing->flags2 & MF2_PASSMOBJ || th->flags4 & MF4_ACTLIKEBRIDGE) && !(thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { if (!(th->flags3 & thing->flags3 & MF3_DONTOVERLAP)) { @@ -516,7 +516,7 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi // If this teleport was caused by a move, P_TryMove() will handle the // sector transition messages better than we can here. // This needs to be compatibility optioned because some older maps exploited this missing feature. - if (!(thing->flags6 & MF6_INTRYMOVE) && !(i_compatflags2 & COMPATF2_TELEPORT)) + if (!(thing->flags6 & MF6_INTRYMOVE) && !(thing->Level->i_compatflags2 & COMPATF2_TELEPORT)) { thing->CheckSectorTransition(oldsec); } @@ -850,7 +850,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec // into being friendly with the MBF flag automatically gain MF3_NOBLOCKMONST, so this // just optionally generalizes the behavior to other friendly monsters. bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST) - || ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY))); + || ((tm.thing->Level->i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY))); uint32_t ProjectileBlocking = ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE; if ( tm.thing->flags8 & MF8_BLOCKASPLAYER ) ProjectileBlocking |= ML_BLOCK_PLAYERS | ML_BLOCKING; @@ -1263,7 +1263,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch // walking on other actors and unblocking is too messy through restricted portal types so disable it. if (!(cres.portalflags & FFCF_RESTRICTEDPORTAL)) { - if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY | MF_NOGRAVITY)) && + if (!(thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY | MF_NOGRAVITY)) && (thing->flags & MF_SOLID) && (thing->flags4 & MF4_ACTLIKEBRIDGE)) { // [RH] Let monsters walk on actors as well as floors @@ -1311,7 +1311,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch // [RH] If the other thing is a bridge, then treat the moving thing as if it had MF2_PASSMOBJ, so // you can use a scrolling floor to move scenery items underneath a bridge. - if ((tm.thing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) + if ((tm.thing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(tm.thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { // check if a mobj passed over/under another object if (!(tm.thing->flags & MF_MISSILE) || !(tm.thing->flags2 & MF2_RIP) || @@ -1442,7 +1442,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch { clipheight = thing->projectilepassheight; } - else if (thing->projectilepassheight < 0 && (i_compatflags & COMPATF_MISSILECLIP)) + else if (thing->projectilepassheight < 0 && (thing->Level->i_compatflags & COMPATF_MISSILECLIP)) { clipheight = -thing->projectilepassheight; } @@ -1764,7 +1764,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo AActor *BlockingMobj = thing->BlockingMobj; // If this blocks through a restricted line portal, it will always completely block. - if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL)) + if (BlockingMobj == NULL || (thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL)) { // Thing slammed into something; don't let it move now. thing->Height = realHeight; return false; @@ -2070,7 +2070,7 @@ static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, DVector2 * auto Level = mobj->Level; if (line->special && !(mobj->flags6 & MF6_NOTRIGGER)) { - if (posforwindowcheck && !(i_compatflags2 & COMPATF2_PUSHWINDOW) && line->backsector != NULL) + if (posforwindowcheck && !(Level->i_compatflags2 & COMPATF2_PUSHWINDOW) && line->backsector != NULL) { // Make sure this line actually blocks us and is not a window // or similar construct we are standing inside of. DVector3 pos = mobj->PosRelative(line); @@ -2177,7 +2177,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, goto pushline; } } - if (!(tm.thing->flags2 & MF2_PASSMOBJ) || (i_compatflags & COMPATF_NO_PASSMOBJ)) + if (!(tm.thing->flags2 & MF2_PASSMOBJ) || (tm.thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { thing->SetZ(oldz); thing->flags6 &= ~MF6_INTRYMOVE; @@ -2276,7 +2276,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, // compatibility check: Doom originally did not allow monsters to cross dropoffs at all. // If the compatibility flag is on, only allow this when the velocity comes from a scroller - if ((i_compatflags & COMPATF_CROSSDROPOFF) && !(thing->flags4 & MF4_SCROLLMOVE)) + if ((thing->Level->i_compatflags & COMPATF_CROSSDROPOFF) && !(thing->flags4 & MF4_SCROLLMOVE)) { dropoff = false; } @@ -2965,7 +2965,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end) goto isblocking; } if (li->flags & ML_BLOCKMONSTERS && !((slidemo->flags3 & MF3_NOBLOCKMONST) - || ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY)))) + || ((slidemo->Level->i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY)))) { goto isblocking; } @@ -4592,7 +4592,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, // Hit a thing, so it could be either a puff or blood DVector3 bleedpos = trace.HitPos; // position a bit closer for puffs/blood if using compatibility mode. - if (i_compatflags & COMPATF_HITSCAN) + if (Level->i_compatflags & COMPATF_HITSCAN) { DVector2 ofs = P_GetOffsetPosition(t1->Level, bleedpos.X, bleedpos.Y, -10 * trace.HitVector.X, -10 * trace.HitVector.Y); bleedpos.X = ofs.X; @@ -4785,7 +4785,7 @@ int P_LineTrace(AActor *t1, DAngle angle, double distance, if ( flags & TRF_BLOCKSELF ) { bool Projectile = ( (t1->flags&MF_MISSILE) || (t1->BounceFlags&BOUNCE_MBF) ); - bool NotBlocked = ( (t1->flags3&MF3_NOBLOCKMONST) || ( (i_compatflags&COMPATF_NOBLOCKFRIENDS) && (t1->flags&MF_FRIENDLY) ) ); + bool NotBlocked = ( (t1->flags3&MF3_NOBLOCKMONST) || ( (t1->Level->i_compatflags&COMPATF_NOBLOCKFRIENDS) && (t1->flags&MF_FRIENDLY) ) ); if ( Projectile ) lflags |= ML_BLOCKPROJECTILE; if ( !Projectile || (t1->flags8&MF8_BLOCKASPLAYER) ) lflags |= ML_BLOCKING; if ( !NotBlocked ) lflags |= ML_BLOCKMONSTERS; @@ -5103,7 +5103,7 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) newhit.HitActor = res.Actor; newhit.HitPos = res.HitPos; newhit.HitAngle = res.SrcAngleFromTarget; - if (i_compatflags & COMPATF_HITSCAN) + if (res.Actor->Level->i_compatflags & COMPATF_HITSCAN) { DVector2 ofs = P_GetOffsetPosition(res.Actor->Level, newhit.HitPos.X, newhit.HitPos.Y, -10 * res.HitVector.X, -10 * res.HitVector.Y); newhit.HitPos.X = ofs.X; @@ -5431,7 +5431,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, P_LineOpening(open, NULL, in->d.line, it.InterceptPoint(in)); } if (open.range <= 0 || - (in->d.line->special != 0 && (i_compatflags & COMPATF_USEBLOCKING))) + (in->d.line->special != 0 && (usething->Level->i_compatflags & COMPATF_USEBLOCKING))) { // [RH] Give sector a chance to intercept the use @@ -5491,7 +5491,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, //[RH] And now I've changed it again. If the line is of type // SPAC_USE, then it eats the use. Everything else passes // it through, including SPAC_USETHROUGH. - if (i_compatflags & COMPATF_USEBLOCKING) + if (usething->Level->i_compatflags & COMPATF_USEBLOCKING) { if (in->d.line->activation & SPAC_UseThrough) continue; else return true; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index e58b41a606..0edf00b632 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1540,7 +1540,7 @@ void FPathTraverse::init(double x1, double y1, double x2, double y2, int flags, // Count is present to prevent a round off error // from skipping the break statement. - bool compatible = (flags & PT_COMPATIBLE) && (i_compatflags & COMPATF_HITSCAN); + bool compatible = (flags & PT_COMPATIBLE) && (Level->i_compatflags & COMPATF_HITSCAN); // we want to use one list of checked actors for the entire operation FBlockThingsIterator btit(Level); diff --git a/src/p_maputl.h b/src/p_maputl.h index 0b69699fb3..7c9adeb899 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -5,6 +5,7 @@ #include "r_defs.h" #include "doomstat.h" #include "m_bbox.h" +#include "g_levellocals.h" extern int validcount; struct FBlockNode; @@ -50,7 +51,7 @@ inline int P_PointOnLineSidePrecise(const DVector2 &pt, const line_t *line) inline int P_PointOnLineSide (double x, double y, const line_t *line) { extern int P_VanillaPointOnLineSide(double x, double y, const line_t* line); - return i_compatflags2 & COMPATF2_POINTONLINE + return line->GetLevel()->i_compatflags2 & COMPATF2_POINTONLINE ? P_VanillaPointOnLineSide(x, y, line) : P_PointOnLineSidePrecise(x, y, line); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index ad5eeb458c..58ae72ab9e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1173,7 +1173,7 @@ bool AActor::Grind(bool items) // see rh_log entry for February 21, 1999. Don't know if it is still relevant. if (state == NULL // Only use the default crushed state if: && !(flags & MF_NOBLOOD) // 1. the monster bleeeds, - && (i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on, + && (Level->i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on, && player == NULL) // 3. and the thing isn't a player. { isgeneric = true; @@ -1829,7 +1829,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) // [anon] When friction is turned off, turn off the crouching and water // speed caps as well, since it is a sort of friction, and the modders // most likely want to deal with that themselves. - if ((mo->player != NULL && (i_compatflags & COMPATF_WALLRUN)) || ((mo->waterlevel >= 1 || + if ((mo->player != NULL && (Level->i_compatflags & COMPATF_WALLRUN)) || ((mo->waterlevel >= 1 || (mo->player != NULL && mo->player->crouchfactor < 0.75)) && !(mo->flags8 & MF8_NOFRICTION))) { // preserve the direction instead of clamping x and y independently. @@ -1951,7 +1951,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) DAngle oldangle = mo->Angles.Yaw; do { - if (i_compatflags & COMPATF_WALLRUN) pushtime++; + if (Level->i_compatflags & COMPATF_WALLRUN) pushtime++; tm.PushTime = pushtime; ptry = start + move * step / steps; @@ -2002,7 +2002,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) // actor's velocity, do not attempt to slide. if (mo->Vel.XY() == startvel) { - if (player && (i_compatflags & COMPATF_WALLRUN)) + if (player && (Level->i_compatflags & COMPATF_WALLRUN)) { // [RH] Here is the key to wall running: The move is clipped using its full speed. // If the move is done a second time (because it was too fast for one move), it @@ -2020,7 +2020,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) } else { - if (!player || !(i_compatflags & COMPATF_WALLRUN)) + if (!player || !(Level->i_compatflags & COMPATF_WALLRUN)) { move = mo->Vel; onestep = move / steps; @@ -2464,7 +2464,7 @@ void P_ZMovement (AActor *mo, double oldfloorz) // Hexen yanked all items to the floor, except those being spawned at map start in the air. // Those were kept at their original height. // Do this only if the item was actually spawned by the map above ground to avoid problems. - if (mo->specialf1 > 0 && (mo->flags2 & MF2_FLOATBOB) && (ib_compatflags & BCOMPATF_FLOATBOB)) + if (mo->specialf1 > 0 && (mo->flags2 & MF2_FLOATBOB) && (mo->Level->ib_compatflags & BCOMPATF_FLOATBOB)) { mo->SetZ(mo->floorz + mo->specialf1); } @@ -3741,7 +3741,7 @@ void AActor::Tick () scrolltype <= Scroll_SouthWest_Fast) { // Hexen scroll special scrolltype -= Scroll_North_Slow; - if (i_compatflags&COMPATF_RAVENSCROLL) + if (Level->i_compatflags&COMPATF_RAVENSCROLL) { scrollv.X -= HexenCompatSpeeds[HexenScrollies[scrolltype][0]+4] * (1. / (32 * CARRYFACTOR)); scrollv.Y += HexenCompatSpeeds[HexenScrollies[scrolltype][1]+4] * (1. / (32 * CARRYFACTOR)); @@ -3760,7 +3760,7 @@ void AActor::Tick () scrolltype -= Carry_East5; uint8_t dir = HereticScrollDirs[scrolltype / 5]; double carryspeed = HereticSpeedMuls[scrolltype % 5] * (1. / (32 * CARRYFACTOR)); - if (scrolltype < 5 && !(i_compatflags&COMPATF_RAVENSCROLL)) + if (scrolltype < 5 && !(Level->i_compatflags&COMPATF_RAVENSCROLL)) { // Use speeds that actually match the scrolling textures! carryspeed = (1 << ((scrolltype % 5) + 15)) / 65536.; @@ -3770,7 +3770,7 @@ void AActor::Tick () } else if (scrolltype == dScroll_EastLavaDamage) { // Special Heretic scroll special - if (i_compatflags&COMPATF_RAVENSCROLL) + if (Level->i_compatflags&COMPATF_RAVENSCROLL) { scrollv.X += 28. / (32*CARRYFACTOR); } @@ -3823,7 +3823,7 @@ void AActor::Tick () // Some levels designed with Boom in mind actually want things to accelerate // at neighboring scrolling sector boundaries. But it is only important for // non-player objects. - if (player != NULL || !(i_compatflags & COMPATF_BOOMSCROLL)) + if (player != NULL || !(Level->i_compatflags & COMPATF_BOOMSCROLL)) { if (countx > 1) { @@ -3916,7 +3916,7 @@ void AActor::Tick () } if (Vel.Z != 0 || BlockingMobj || Z() != floorz) { // Handle Z velocity and gravity - if (((flags2 & MF2_PASSMOBJ) || (flags & MF_SPECIAL)) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) + if (((flags2 & MF2_PASSMOBJ) || (flags & MF_SPECIAL)) && !(Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { if (!(onmo = P_CheckOnmobj (this))) { @@ -4001,7 +4001,7 @@ void AActor::Tick () } // Check for poison damage, but only once per PoisonPeriod tics (or once per second if none). - if (PoisonDurationReceived && (Level->time % (PoisonPeriodReceived ? PoisonPeriodReceived : TICRATE) == 0)) + if (PoisonDurationReceived && (Level->maptime % (PoisonPeriodReceived ? PoisonPeriodReceived : TICRATE) == 0)) { P_DamageMobj(this, NULL, Poisoner, PoisonDamageReceived, PoisonDamageTypeReceived ? PoisonDamageTypeReceived : (FName)NAME_Poison, 0); @@ -4055,7 +4055,7 @@ void AActor::Tick () if (movecount < respawn_monsters) return; - if (Level->time & 31) + if (Level->maptime & 31) return; if (pr_nightmarerespawn() > 4) @@ -4348,7 +4348,7 @@ bool AActor::UpdateWaterLevel(bool dosplash) else if (oldlevel == 3 && waterlevel < 3) { // Our head just came up. - if (player->air_finished > Level->time) + if (player->air_finished > currentSession->time) { // We hadn't run out of air yet. S_Sound(this, CHAN_VOICE, "*surface", 1, ATTN_NORM); @@ -4388,7 +4388,7 @@ AActor *AActor::StaticSpawn (FLevelLocals *Level, PClassActor *type, const DVect AActor *actor; actor = static_cast(const_cast(type)->CreateNew ()); - actor->SpawnTime = Level->totaltime; + actor->SpawnTime = currentSession->totaltime; actor->SpawnOrder = Level->spawnindex++; // Set default dialogue @@ -4972,7 +4972,7 @@ AActor *P_SpawnPlayer (FLevelLocals *Level, FPlayerStart *mthing, int playernum, // Allow full angular precision SpawnAngle = (double)mthing->angle; - if (i_compatflags2 & COMPATF2_BADANGLES) + if (Level->i_compatflags2 & COMPATF2_BADANGLES) { SpawnAngle += 0.01; } @@ -5434,7 +5434,7 @@ AActor *P_SpawnMapThing (FLevelLocals *Level, FMapThing *mthing, int position) if (sz == ONFLOORZ) { mobj->AddZ(mthing->pos.Z); - if ((mobj->flags2 & MF2_FLOATBOB) && (ib_compatflags & BCOMPATF_FLOATBOB)) + if ((mobj->flags2 & MF2_FLOATBOB) && (mobj->Level->ib_compatflags & BCOMPATF_FLOATBOB)) { mobj->specialf1 = mthing->pos.Z; } @@ -5457,7 +5457,7 @@ AActor *P_SpawnMapThing (FLevelLocals *Level, FMapThing *mthing, int position) } // For Hexen floatbob 'compatibility' we do not really want to alter the floorz. - if (mobj->specialf1 == 0 || !(mobj->flags2 & MF2_FLOATBOB) || !(ib_compatflags & BCOMPATF_FLOATBOB)) + if (mobj->specialf1 == 0 || !(mobj->flags2 & MF2_FLOATBOB) || !(mobj->Level->ib_compatflags & BCOMPATF_FLOATBOB)) { P_FindFloorCeiling(mobj, FFCF_SAMESECTOR | FFCF_ONLY3DFLOORS | FFCF_3DRESTRICT); } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index b160b7ac44..61dd0e5632 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -890,8 +890,6 @@ static void SpawnExtraPlayers(FLevelLocals *Level) void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) { - int i = Level->totaltime; - if (arc.isWriting()) { arc.Array("checksum", Level->md5, 16); @@ -937,7 +935,6 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) ("airfriction", Level->airfriction) ("teamdamage", Level->teamdamage) ("maptime", Level->maptime) - ("totaltime", i) ("skytexture1", Level->skytexture1) ("skytexture2", Level->skytexture2) ("fogdensity", Level->fogdensity) @@ -957,10 +954,6 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) ("sndseqlisthead", Level->SequenceListHead); - // Hub transitions must keep the current total time - if (!hubload) - Level->totaltime = i; - if (arc.isReading()) { sky1texture = Level->skytexture1; @@ -1000,13 +993,16 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) { order = S_GetMusic(&name); } + arc.StringPtr("musicname", name) - ("musicorder", order); + ("musicorder", order) + ("musicvolume", currentSession->MusicVolume); + if (!hubload) arc ("totaltime", currentSession->totaltime); // this must be skipped for hub transitions. if (arc.isReading()) { if (!S_ChangeMusic(name, order)) Level->SetMusic(); - level.SetMusicVolume(Level->MusicVolume); + currentSession->SetMusicVolume(currentSession->MusicVolume); } diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 1027164751..0f6ef2b8b6 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -473,9 +473,9 @@ double FindHighestCeilingSurrounding (const sector_t *sector, vertex_t **v) // jff 02/03/98 Add routine to find shortest lower texture // -static inline void CheckShortestTex (FTextureID texnum, double &minsize) +static inline void CheckShortestTex (FLevelLocals *Level, FTextureID texnum, double &minsize) { - if (texnum.isValid() || (texnum.isNull() && (i_compatflags & COMPATF_SHORTTEX))) + if (texnum.isValid() || (texnum.isNull() && (Level->i_compatflags & COMPATF_SHORTTEX))) { FTexture *tex = TexMan.GetTexture(texnum); if (tex != NULL) @@ -497,8 +497,8 @@ double FindShortestTextureAround (sector_t *sec) { if (check->flags & ML_TWOSIDED) { - CheckShortestTex (check->sidedef[0]->GetTexture(side_t::bottom), minsize); - CheckShortestTex (check->sidedef[1]->GetTexture(side_t::bottom), minsize); + CheckShortestTex (sec->Level, check->sidedef[0]->GetTexture(side_t::bottom), minsize); + CheckShortestTex (sec->Level, check->sidedef[1]->GetTexture(side_t::bottom), minsize); } } return minsize < FLT_MAX ? minsize : TexMan.ByIndex(0)->GetDisplayHeight(); @@ -522,8 +522,8 @@ double FindShortestUpperAround (sector_t *sec) { if (check->flags & ML_TWOSIDED) { - CheckShortestTex (check->sidedef[0]->GetTexture(side_t::top), minsize); - CheckShortestTex (check->sidedef[1]->GetTexture(side_t::top), minsize); + CheckShortestTex (sec->Level, check->sidedef[0]->GetTexture(side_t::top), minsize); + CheckShortestTex (sec->Level, check->sidedef[1]->GetTexture(side_t::top), minsize); } } return minsize < FLT_MAX ? minsize : TexMan.ByIndex(0)->GetDisplayHeight(); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index a025618c2a..98d8a5780e 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -378,7 +378,7 @@ void P_SetupLevel(FLevelLocals *Level, const char *lumpname, int position, bool if (!savegamerestore) { - Level->SetMusicVolume(Level->MusicVolume); + currentSession->SetMusicVolume(currentSession->MusicVolume); for (i = 0; i < MAXPLAYERS; ++i) { players[i].killcount = players[i].secretcount diff --git a/src/p_sight.cpp b/src/p_sight.cpp index 68ce350501..b926a2ae99 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -218,7 +218,7 @@ bool SightCheck::PTR_SightTraverse (intercept_t *in) // // ignore self referencing sectors if COMPAT_TRACE is on - if ((i_compatflags & COMPATF_TRACE) && li->frontsector == li->backsector) + if ((Level->i_compatflags & COMPATF_TRACE) && li->frontsector == li->backsector) return true; double trX = Trace.x + Trace.dx * in->frac; diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 77225a3f1e..fcd9998b60 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -463,7 +463,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) player->hazardtype = sector->damagetype; player->hazardinterval = sector->damageinterval; } - else if (Level->time % sector->damageinterval == 0) + else if (Level->maptime % sector->damageinterval == 0) { if (!(player->cheats & (CF_GODMODE|CF_GODMODE2))) P_DamageMobj(player->mo, NULL, NULL, sector->damageamount, sector->damagetype); if ((sector->Flags & SECF_ENDLEVEL) && player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT))) @@ -479,7 +479,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) } else if (sector->damageamount < 0) { - if (Level->time % sector->damageinterval == 0) + if (Level->maptime % sector->damageinterval == 0) { P_GiveBody(player->mo, -sector->damageamount, 100); } @@ -638,7 +638,7 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType) auto Level = player->mo->Level; if (Terrains[floorType].DamageAmount && - !(Level->time & Terrains[floorType].DamageTimeMask)) + !(Level->maptime & Terrains[floorType].DamageTimeMask)) { AActor *ironfeet = NULL; diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index 0088d712fb..062c0e2af7 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -247,7 +247,7 @@ static AActor *SelectTeleDest (FLevelLocals *Level, int tid, int tag, bool noran // sector). // Compatibility hack for some maps that fell victim to a bug in the teleport code in 2.0.9x - if (ib_compatflags & BCOMPATF_BADTELEPORTERS) tag = 0; + if (Level->ib_compatflags & BCOMPATF_BADTELEPORTERS) tag = 0; if (tid != 0) { @@ -386,7 +386,7 @@ bool EV_Teleport (FLevelLocals *Level, int tid, int tag, line_t *line, int side, { z = ONFLOORZ; } - if ((i_compatflags2 & COMPATF2_BADANGLES) && (thing->player != NULL)) + if ((Level->i_compatflags2 & COMPATF2_BADANGLES) && (thing->player != NULL)) { badangle = 0.01; } diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 61e946ecb4..85e23de987 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -159,8 +159,8 @@ void P_Ticker (void) } // for par times - Level->time++; Level->maptime++; - Level->totaltime++; }); + currentSession->time++; + currentSession->totaltime++; } diff --git a/src/p_trace.cpp b/src/p_trace.cpp index cd9bbb7869..7c62fb42b5 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -420,7 +420,7 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit, bool spec // For backwards compatibility: Ignore lines with the same sector on both sides. // This is the way Doom.exe did it and some WADs (e.g. Alien Vendetta MAP15) need it. - if (i_compatflags & COMPATF_TRACE && in->d.line->backsector == in->d.line->frontsector && !special3dpass) + if (Level->i_compatflags & COMPATF_TRACE && in->d.line->backsector == in->d.line->frontsector && !special3dpass) { // We must check special activation here because the code below is never reached. if (TraceFlags & TRACE_PCross) diff --git a/src/po_man.cpp b/src/po_man.cpp index 0c2b1e289b..43c08813e1 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1722,7 +1722,7 @@ void FPolyObj::CreateSubsectorLinks() seg->v2 = side->V2(); seg->wall = side; } - if (!(i_compatflags & COMPATF_POLYOBJ)) + if (!(Level->i_compatflags & COMPATF_POLYOBJ)) { SplitPoly(node, Level->HeadNode(), dummybbox); } diff --git a/src/s_sound.cpp b/src/s_sound.cpp index f3aa9af61b..879a2fcbea 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -861,7 +861,7 @@ static bool ValidatePosVel(const FSoundChan *const chan, const FVector3 &pos, co static void CalcSectorSoundOrg(const DVector3 &listenpos, const sector_t *sec, int channum, FVector3 &pos) { - if (!(i_compatflags & COMPATF_SECTORSOUNDS)) + if (!(sec->Level->i_compatflags & COMPATF_SECTORSOUNDS)) { // Are we inside the sector? If yes, the closest point is the one we're on. if (P_PointInSector(sec->Level, listenpos.X, listenpos.Y) == sec) @@ -991,11 +991,11 @@ static FSoundChan *S_StartSound(FLevelLocals *Level, AActor *actor, const sector return nullptr; } - if (i_compatflags & COMPATF_MAGICSILENCE) + if (Level->i_compatflags & COMPATF_MAGICSILENCE) { // For people who just can't play without a silent BFG. channel = CHAN_WEAPON; } - else if ((chanflags & CHAN_MAYBE_LOCAL) && (i_compatflags & COMPATF_SILENTPICKUP)) + else if ((chanflags & CHAN_MAYBE_LOCAL) && (Level->i_compatflags & COMPATF_SILENTPICKUP)) { if (actor != NULL && actor != players[consoleplayer].camera) { @@ -1679,7 +1679,7 @@ void S_StopSound (int channel) { FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_None && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1703,7 +1703,7 @@ void S_StopSound (AActor *actor, int channel) FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_Actor && chan->Actor == actor && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1727,7 +1727,7 @@ void S_StopSound (const sector_t *sec, int channel) FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_Sector && chan->Sector == sec && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1751,7 +1751,7 @@ void S_StopSound (const FPolyObj *poly, int channel) FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_Polyobj && chan->Poly == poly && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1840,7 +1840,7 @@ void S_ChangeSoundVolume(AActor *actor, int channel, double dvolume) { if (chan->SourceType == SOURCE_Actor && chan->Actor == actor && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { GSnd->ChannelVolume(chan, volume); chan->Volume = volume; @@ -1946,7 +1946,7 @@ static bool S_IsChannelUsed(AActor *actor, int channel, int *seen) bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) { - if (i_compatflags & COMPATF_MAGICSILENCE) + if (compatflags & COMPATF_MAGICSILENCE) { channel = 0; } @@ -2200,7 +2200,7 @@ void S_UpdateSounds (AActor *listenactor) GSnd->UpdateListener(&listener); GSnd->UpdateSounds(); - if (listenactor && listenactor->Level->time >= RestartEvictionsAt) + if (currentSession && currentSession->time >= RestartEvictionsAt) { RestartEvictionsAt = 0; S_RestoreEvictedChannels(); @@ -2506,7 +2506,7 @@ void S_SerializeSounds(FSerializer &arc, FLevelLocals *Level) // playing before the wipe, and depending on the synchronization // between the main thread and the mixer thread at the time, the // sounds might be heard briefly before pausing for the wipe. - RestartEvictionsAt = Level->time + 2; + RestartEvictionsAt = currentSession->time + 2; } GSnd->Sync(false); GSnd->UpdateSounds(); diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 90a0a6df97..fb69efd363 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6836,9 +6836,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) int *pVal; auto cv = static_cast(CVar); auto vcv = &cv->ValueVar; - if (vcv == &compatflags) pVal = &i_compatflags; - else if (vcv == &compatflags2) pVal = &i_compatflags2; - else pVal = &vcv->Value; + pVal = &vcv->Value; build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(pVal)); build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum); diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index aca9540d92..cd9d9a4f23 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2711,9 +2711,7 @@ DEFINE_FIELD(FLevelLocals, lines) DEFINE_FIELD(FLevelLocals, sides) DEFINE_FIELD(FLevelLocals, vertexes) DEFINE_FIELD(FLevelLocals, sectorPortals) -DEFINE_FIELD(FLevelLocals, time) DEFINE_FIELD(FLevelLocals, maptime) -DEFINE_FIELD(FLevelLocals, totaltime) DEFINE_FIELD(FLevelLocals, starttime) DEFINE_FIELD(FLevelLocals, partime) DEFINE_FIELD(FLevelLocals, sucktime) @@ -2768,6 +2766,8 @@ DEFINE_FIELD_BIT(FLevelLocals, flags3, removeitems, LEVEL3_REMOVEITEMS) DEFINE_FIELD(FGameSession, Levelinfo) DEFINE_FIELD(FGameSession, F1Pic) +DEFINE_FIELD(FGameSession, time) +DEFINE_FIELD(FGameSession, totaltime) DEFINE_GLOBAL(currentSession) DEFINE_FIELD_X(Sector, sector_t, floorplane) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 9f25ff0ee5..9119b86f8d 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -1652,7 +1652,33 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFor3DCeilingHit, CheckFor3DCeilingHit ACTION_RETURN_BOOL(P_CheckFor3DCeilingHit(self, z, trigger)); } +//===================================================================================== +// +// compat flags. These two are the only ones that get checked in script code +// so anything more complex isn't really needed. +// +//===================================================================================== +static int compat_limitpain_(AActor *self) +{ + return self->Level->i_compatflags & COMPATF_LIMITPAIN; +} +static int compat_mushroom_(AActor *self) +{ + return self->Level->i_compatflags & COMPATF_MUSHROOM; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, compat_limitpain, compat_limitpain_) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(compat_limitpain_(self)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, compat_mushroom, compat_mushroom_) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(compat_mushroom_(self)); +} //=========================================================================== // diff --git a/src/statistics.cpp b/src/statistics.cpp index 0cf5ce630d..6c3a9c80e8 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -481,7 +481,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level) } infostring.Format("%4d/%4d, %4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], statvals[4], statvals[5], validlevels); - FSessionStatistics *es = StatisticsEntry(sl, infostring, Level->totaltime); + FSessionStatistics *es = StatisticsEntry(sl, infostring, currentSession->totaltime); for(unsigned i = 0; i < LevelData.Size(); i++) { diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index 03b8bf25c1..bd3e64189b 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -591,7 +591,7 @@ namespace swrenderer if (mFrontSector->e && mFrontSector->e->XFloor.lightlist.Size()) return true; if (mBackSector->e && mBackSector->e->XFloor.lightlist.Size()) return true; - if (sidedef->GetTexture(side_t::mid).isValid() && ((ib_compatflags & BCOMPATF_CLIPMIDTEX) || (linedef->flags & (ML_CLIP_MIDTEX | ML_WRAP_MIDTEX)) || sidedef->Flags & (WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX))) return true; + if (sidedef->GetTexture(side_t::mid).isValid() && ((mFrontSector->Level->ib_compatflags & BCOMPATF_CLIPMIDTEX) || (linedef->flags & (ML_CLIP_MIDTEX | ML_WRAP_MIDTEX)) || sidedef->Flags & (WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX))) return true; return false; } @@ -653,7 +653,7 @@ namespace swrenderer if (sidedef->GetTexture(side_t::mid).isValid()) { - if (ib_compatflags & BCOMPATF_CLIPMIDTEX) return true; + if (mFrontSector->Level->ib_compatflags & BCOMPATF_CLIPMIDTEX) return true; if (linedef->flags & (ML_CLIP_MIDTEX | ML_WRAP_MIDTEX)) return true; if (sidedef->Flags & (WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX)) return true; } diff --git a/src/swrenderer/line/r_renderdrawsegment.cpp b/src/swrenderer/line/r_renderdrawsegment.cpp index 9d865d2bb1..263409d818 100644 --- a/src/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/swrenderer/line/r_renderdrawsegment.cpp @@ -150,7 +150,7 @@ namespace swrenderer return false; FTexture *ttex = TexMan.GetPalettedTexture(curline->sidedef->GetTexture(side_t::mid), true); - if (i_compatflags & COMPATF_MASKEDMIDTEX) + if (curline->frontsector->Level->i_compatflags & COMPATF_MASKEDMIDTEX) { ttex = ttex->GetRawTexture(); } @@ -294,7 +294,7 @@ namespace swrenderer // this drawseg. if ((curline->linedef->flags & ML_CLIP_MIDTEX) || (curline->sidedef->Flags & WALLF_CLIP_MIDTEX) || - (ib_compatflags & BCOMPATF_CLIPMIDTEX)) + (curline->frontsector->Level->ib_compatflags & BCOMPATF_CLIPMIDTEX)) { ClipMidtex(x1, x2); } @@ -356,7 +356,7 @@ namespace swrenderer // this drawseg. if ((curline->linedef->flags & ML_CLIP_MIDTEX) || (curline->sidedef->Flags & WALLF_CLIP_MIDTEX) || - (ib_compatflags & BCOMPATF_CLIPMIDTEX)) + (curline->frontsector->Level->ib_compatflags & BCOMPATF_CLIPMIDTEX)) { ClipMidtex(x1, x2); } diff --git a/src/swrenderer/things/r_visiblespritelist.cpp b/src/swrenderer/things/r_visiblespritelist.cpp index cf70ffe402..08327f8b74 100644 --- a/src/swrenderer/things/r_visiblespritelist.cpp +++ b/src/swrenderer/things/r_visiblespritelist.cpp @@ -69,7 +69,7 @@ namespace swrenderer if (count == 0) return; - if (!(i_compatflags & COMPATF_SPRITESORT)) + if (!(thread->Viewport->GetLevel()->i_compatflags & COMPATF_SPRITESORT)) { for (unsigned int i = 0; i < count; i++) SortedSprites[i] = Sprites[first + i]; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index b1eff6c5d6..b199b6694c 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -769,7 +769,7 @@ class Actor : Thinker native //========================================================================== clearscope int GetLevelSpawnTime() const { - return SpawnTime - Level.totaltime + Level.time; + return SpawnTime - currentSession.totaltime + currentSession.time; } //========================================================================== @@ -782,7 +782,7 @@ class Actor : Thinker native clearscope int GetAge() const { - return Level.totaltime - SpawnTime; + return currentSession.totaltime - SpawnTime; } double AccuracyFactor() diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 454c36f586..e0d796761f 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -626,6 +626,8 @@ struct GameSession native // all open levels. The first entry in this list is the primary one where gameplay takes place. native Array LevelInfo; native readonly String F1Pic; + native readonly int time; + native readonly int totaltime; } struct LevelLocals native @@ -645,6 +647,14 @@ struct LevelLocals native { return currentSession? currentSession.F1Pic : ""; } + deprecated("3.8") static int __getter__time__() + { + return currentSession? currentSession.time : 0; + } + deprecated("3.8") static int __getter__totaltime__() + { + return currentSession? currentSession.totaltime : 0; + } @@ -654,9 +664,7 @@ struct LevelLocals native native readonly Array<@Vertex> Vertexes; native internal Array<@SectorPortal> SectorPortals; - deprecated("3.8") native readonly int time; native readonly int maptime; - deprecated("3.8") native readonly int totaltime; native readonly int starttime; native readonly int partime; native readonly int sucktime; @@ -752,7 +760,7 @@ struct LevelLocals native String TimeFormatted(bool totals = false) { - int sec = Thinker.Tics2Seconds(totals? totaltime : time); + int sec = Thinker.Tics2Seconds(totals? currentSession.totaltime : currentSession.time); return String.Format("%02d:%02d:%02d", sec / 3600, (sec % 3600) / 60, sec % 60); } } diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt index f24b0d2e70..cbf820398a 100644 --- a/wadsrc/static/zscript/doom/fatso.txt +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -105,6 +105,7 @@ extend class Actor { const FATSPREAD = 90./8; + private native bool compat_mushroom(); void A_FatRaise() { @@ -195,7 +196,7 @@ extend class Actor aimtarget.Height = Height; bool shootmode = ((flags & MSF_Classic) || // Flag explicitly set, or no flags and compat options - (flags == 0 && CurState.bDehacked && compat_mushroom)); + (flags == 0 && CurState.bDehacked && compat_mushroom())); for (i = -numspawns; i <= numspawns; i += 8) { diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt index f953e47efb..7995eae1be 100644 --- a/wadsrc/static/zscript/doom/painelemental.txt +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -62,6 +62,8 @@ class PainElemental : Actor extend class Actor { + private native bool compat_limitpain(); + // // A_PainShootSkull // Spawn a lost soul and launch it at the target @@ -86,7 +88,7 @@ extend class Actor } // [RH] make this optional - if (limit < 0 && compat_limitpain) + if (limit < 0 && compat_limitpain()) limit = 21; if (limit > 0) diff --git a/wadsrc/static/zscript/shared/morph.txt b/wadsrc/static/zscript/shared/morph.txt index 2630212396..56a4d1ff19 100644 --- a/wadsrc/static/zscript/shared/morph.txt +++ b/wadsrc/static/zscript/shared/morph.txt @@ -118,7 +118,7 @@ extend class Actor morphed.RenderStyle = RenderStyle; morphed.Score = Score; - morphed.UnmorphTime = Level.time + ((duration) ? duration : DEFMORPHTICS) + random[morphmonst](); + morphed.UnmorphTime = currentSession.time + ((duration) ? duration : DEFMORPHTICS) + random[morphmonst](); morphed.MorphStyle = style; morphed.MorphExitFlash = (exit_flash) ? exit_flash : (class)("TeleportFog"); morphed.FlagsSave = bSolid * 2 + bShootable * 4 + bInvisible * 0x40; // The factors are for savegame compatibility @@ -656,7 +656,7 @@ class MorphedMonster : Actor override void Tick () { - if (UnmorphTime > Level.time || !UndoMonsterMorph()) + if (UnmorphTime > currentSession.time || !UndoMonsterMorph()) { Super.Tick(); } @@ -687,7 +687,7 @@ class MorphedMonster : Actor unmorphed.bSolid = false; bSolid = true; bTouchy = save; - UnmorphTime = Level.time + 5*TICRATE; // Next try in 5 seconds + UnmorphTime = currentSession.time + 5*TICRATE; // Next try in 5 seconds return false; } unmorphed.Angle = Angle; diff --git a/wadsrc/static/zscript/statusbar/alt_hud.txt b/wadsrc/static/zscript/statusbar/alt_hud.txt index f83edfc63b..51d1b7f0c0 100644 --- a/wadsrc/static/zscript/statusbar/alt_hud.txt +++ b/wadsrc/static/zscript/statusbar/alt_hud.txt @@ -798,8 +798,8 @@ class AltHud ui hud_showtime < 4 ? Level.maptime : (hud_showtime < 6 - ? Level.time - : Level.totaltime); + ? currentSession.time + : currentSession.totaltime); timeSeconds = Thinker.Tics2Seconds(timeTicks); } else @@ -818,7 +818,7 @@ class AltHud ui if (showMillis) { - int millis = (Level.time % Thinker.TICRATE) * (1000 / Thinker.TICRATE); + int millis = (currentSession.time % Thinker.TICRATE) * (1000 / Thinker.TICRATE); timeString = String.Format("%02i:%02i:%02i.%03i", hours, minutes, seconds, millis); } else if (showSeconds) @@ -950,7 +950,7 @@ class AltHud ui if (am_showtotaltime) { - DrawTimeString(SmallFont, hudcolor_ttim, Level.totaltime, hudwidth-2, bottom, 1); + DrawTimeString(SmallFont, hudcolor_ttim, currentSession.totaltime, hudwidth-2, bottom, 1); bottom -= fonth; } @@ -958,7 +958,7 @@ class AltHud ui { if (Level.clusterflags & Level.CLUSTER_HUB) { - DrawTimeString(SmallFont, hudcolor_time, Level.time, hudwidth-2, bottom, 1); + DrawTimeString(SmallFont, hudcolor_time, currentSession.time, hudwidth-2, bottom, 1); bottom -= fonth; } diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index 38569ac936..300e99d592 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -43,7 +43,7 @@ class HereticStatusBar : BaseStatusBar mHealthInterpolator.Update(CPlayer.health); // wiggle the chain if it moves - if (Level.time & 1) + if (currentSession.time & 1) { wiggle = (mHealthInterpolator.GetValue() != CPlayer.health) && Random[ChainWiggle](0, 1); } diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index 9b78d9c708..7c380dffb8 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -600,7 +600,7 @@ class BaseStatusBar native ui if(CPlayer.mo.waterlevel < 3) return Level.airsupply; else - return max(CPlayer.air_finished - Level.time, 0); + return max(CPlayer.air_finished - currentSession.time, 0); } int GetSelectedInventoryAmount()