diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index 2c9caaec3..63bda28ff 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -349,3 +349,58 @@ CCMD(targetinv) "the NOBLOCKMAP flag or have height/radius of 0.\n"); } + +//========================================================================== +// +// Lists all currently defined maps +// +//========================================================================== + +CCMD(listmaps) +{ + for (unsigned i = 0; i < wadlevelinfos.Size(); i++) + { + level_info_t *info = &wadlevelinfos[i]; + MapData *map = P_OpenMapData(info->MapName, true); + + if (map != NULL) + { + Printf("%s: '%s' (%s)\n", info->MapName.GetChars(), info->LookupLevelName().GetChars(), + Wads.GetWadName(Wads.GetLumpFile(map->lumpnum))); + delete map; + } + } +} + +//========================================================================== +// +// For testing sky fog sheets +// +//========================================================================== +CCMD(skyfog) +{ + if (argv.argc() > 1) + { + // Do this only on the primary level. + primaryLevel->skyfog = MAX(0, (int)strtoull(argv[1], NULL, 0)); + } +} + + +//========================================================================== +// +// +//========================================================================== + +CCMD(listsnapshots) +{ + for (unsigned i = 0; i < wadlevelinfos.Size(); ++i) + { + FCompressedBuffer *snapshot = &wadlevelinfos[i].Snapshot; + if (snapshot->mBuffer != nullptr) + { + Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), snapshot->mCompressedSize, snapshot->mSize); + } + } +} + diff --git a/src/g_level.cpp b/src/g_level.cpp index 991849e56..0d27c6d1a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1634,68 +1634,6 @@ void FLevelLocals::Init() notexturefill = info->notexturefill < 0 ? gl_notexturefill : !!info->notexturefill; } -//========================================================================== -// -// -//========================================================================== - -bool FLevelLocals::IsJumpingAllowed() const -{ - if (dmflags & DF_NO_JUMP) - return false; - if (dmflags & DF_YES_JUMP) - return true; - return !(flags & LEVEL_JUMP_NO); -} - -DEFINE_ACTION_FUNCTION(FLevelLocals, IsJumpingAllowed) -{ - PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); - ACTION_RETURN_BOOL(self->IsJumpingAllowed()); -} - - -//========================================================================== -// -// -//========================================================================== - -bool FLevelLocals::IsCrouchingAllowed() const -{ - if (dmflags & DF_NO_CROUCH) - return false; - if (dmflags & DF_YES_CROUCH) - return true; - return !(flags & LEVEL_CROUCH_NO); -} - -DEFINE_ACTION_FUNCTION(FLevelLocals, IsCrouchingAllowed) -{ - PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); - ACTION_RETURN_BOOL(self->IsCrouchingAllowed()); -} - -//========================================================================== -// -// -//========================================================================== - -bool FLevelLocals::IsFreelookAllowed() const -{ - if (dmflags & DF_NO_FREELOOK) - return false; - if (dmflags & DF_YES_FREELOOK) - return true; - return !(flags & LEVEL_FREELOOK_NO); -} - -DEFINE_ACTION_FUNCTION(FLevelLocals, IsFreelookAllowed) -{ - PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); - ACTION_RETURN_BOOL(self->IsFreelookAllowed()); -} - - //========================================================================== // // @@ -1735,89 +1673,6 @@ void FLevelLocals::AirControlChanged () } } -//========================================================================== -// -// Archives the current level -// -//========================================================================== - -void FLevelLocals::SnapshotLevel () -{ - info->Snapshot.Clean(); - - if (info->isValid()) - { - FSerializer arc(this); - - if (arc.OpenWriter(save_formatted)) - { - SaveVersion = SAVEVER; - Serialize(arc, false); - info->Snapshot = arc.GetCompressedOutput(); - } - } -} - -//========================================================================== -// -// Unarchives the current level based on its snapshot -// The level should have already been loaded and setup. -// -//========================================================================== - -void FLevelLocals::UnSnapshotLevel (bool hubLoad) -{ - if (info->Snapshot.mBuffer == nullptr) - return; - - if (info->isValid()) - { - FSerializer arc(this); - if (!arc.OpenReader(&info->Snapshot)) - { - I_Error("Failed to load savegame"); - return; - } - - Serialize (arc, hubLoad); - FromSnapshot = true; - - auto it = GetThinkerIterator(NAME_PlayerPawn); - AActor *pawn, *next; - - next = it.Next(); - while ((pawn = next) != 0) - { - next = it.Next(); - if (pawn->player == nullptr || pawn->player->mo == nullptr || !PlayerInGame(pawn->player)) - { - int i; - - // If this isn't the unmorphed original copy of a player, destroy it, because it's extra. - for (i = 0; i < MAXPLAYERS; ++i) - { - if (PlayerInGame(i) && Players[i]->morphTics && Players[i]->mo->alternative == pawn) - { - break; - } - } - if (i == MAXPLAYERS) - { - pawn->Destroy (); - } - } - } - arc.Close(); - } - // No reason to keep the snapshot around once the level's been entered. - info->Snapshot.Clean(); - if (hubLoad) - { - // Unlock ACS global strings that were locked when the snapshot was made. - Behaviors.UnlockLevelVarStrings(levelnum); - } -} - //========================================================================== // // @@ -1968,23 +1823,6 @@ void G_ReadVisited(FSerializer &arc) // //========================================================================== -CCMD(listsnapshots) -{ - for (unsigned i = 0; i < wadlevelinfos.Size(); ++i) - { - FCompressedBuffer *snapshot = &wadlevelinfos[i].Snapshot; - if (snapshot->mBuffer != nullptr) - { - Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), snapshot->mCompressedSize, snapshot->mSize); - } - } -} - -//========================================================================== -// -// -//========================================================================== - void P_WriteACSDefereds (FSerializer &arc) { bool found = false; @@ -2322,64 +2160,3 @@ int IsPointInMap(FLevelLocals *Level, double x, double y, double z) return true; } -//========================================================================== -// -// Lists all currently defined maps -// -//========================================================================== - -CCMD(listmaps) -{ - for(unsigned i = 0; i < wadlevelinfos.Size(); i++) - { - level_info_t *info = &wadlevelinfos[i]; - MapData *map = P_OpenMapData(info->MapName, true); - - if (map != NULL) - { - Printf("%s: '%s' (%s)\n", info->MapName.GetChars(), info->LookupLevelName().GetChars(), - Wads.GetWadName(Wads.GetLumpFile(map->lumpnum))); - delete map; - } - } -} - -//========================================================================== -// -// For testing sky fog sheets -// -//========================================================================== -CCMD(skyfog) -{ - if (argv.argc()>1) - { - // Do this only on the primary level. - primaryLevel->skyfog = MAX(0, (int)strtoull(argv[1], NULL, 0)); - } -} - - -//========================================================================== -// -// ZScript counterpart to ACS ChangeSky, uses TextureIDs -// -//========================================================================== -DEFINE_ACTION_FUNCTION(FLevelLocals, ChangeSky) -{ - PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); - PARAM_INT(sky1); - PARAM_INT(sky2); - self->skytexture1 = FSetTextureID(sky1); - self->skytexture2 = FSetTextureID(sky2); - InitSkyMap(self); - return 0; -} - -DEFINE_ACTION_FUNCTION(FLevelLocals, StartIntermission) -{ - PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); - PARAM_NAME(seq); - PARAM_INT(state); - F_StartIntermission(seq, (uint8_t)state); - return 0; -} diff --git a/src/g_levellocals.h b/src/g_levellocals.h index afa6dd454..37b280b5d 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -143,6 +143,13 @@ private: void AddDisplacementForPortal(FSectorPortal *portal); void AddDisplacementForPortal(FLinePortal *portal); bool ConnectPortalGroups(); + + void SerializePlayers(FSerializer &arc, bool skipload); + void CopyPlayer(player_t *dst, player_t *src, const char *name); + void ReadOnePlayer(FSerializer &arc, bool skipload); + void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload); + void SerializeSounds(FSerializer &arc); + public: void SnapshotLevel(); void UnSnapshotLevel(bool hubLoad); @@ -646,9 +653,47 @@ public: TObjPtr SpotState = nullptr; - bool IsJumpingAllowed() const; - bool IsCrouchingAllowed() const; - bool IsFreelookAllowed() const; + //========================================================================== + // + // + //========================================================================== + + bool IsJumpingAllowed() const + { + if (dmflags & DF_NO_JUMP) + return false; + if (dmflags & DF_YES_JUMP) + return true; + return !(flags & LEVEL_JUMP_NO); + } + + //========================================================================== + // + // + //========================================================================== + + bool IsCrouchingAllowed() const + { + if (dmflags & DF_NO_CROUCH) + return false; + if (dmflags & DF_YES_CROUCH) + return true; + return !(flags & LEVEL_CROUCH_NO); + } + + //========================================================================== + // + // + //========================================================================== + + bool IsFreelookAllowed() const + { + if (dmflags & DF_NO_FREELOOK) + return false; + if (dmflags & DF_YES_FREELOOK) + return true; + return !(flags & LEVEL_FREELOOK_NO); + } node_t *HeadNode() const { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 55c04c944..61b9ec267 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -58,8 +58,11 @@ #include "events.h" #include "p_destructible.h" #include "r_sky.h" +#include "version.h" #include "fragglescript/t_script.h" +EXTERN_CVAR(Bool, save_formatted) + //========================================================================== // // @@ -486,6 +489,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FPolyObj &poly, FPolyO ("blocked", poly.bBlocked) ("hasportals", poly.bHasPortals) ("specialdata", poly.specialdata) + ("level", poly.Level) .EndObject(); if (arc.isReading()) @@ -526,46 +530,39 @@ FSerializer &Serialize(FSerializer &arc, const char *key, zone_t &z, zone_t *def // //========================================================================== -void P_SerializeSounds(FLevelLocals *Level, FSerializer &arc) +void FLevelLocals::SerializeSounds(FSerializer &arc) { - S_SerializeSounds(arc); - const char *name = NULL; - uint8_t order; - float musvol = Level->MusicVolume; - - if (arc.isWriting()) + if (isPrimaryLevel()) { - order = S_GetMusic(&name); - } - arc.StringPtr("musicname", name) - ("musicorder", order) - ("musicvolume", musvol); + S_SerializeSounds(arc); + const char *name = NULL; + uint8_t order; + float musvol = MusicVolume; - if (arc.isReading()) - { - if (!S_ChangeMusic(name, order)) - Level->SetMusic(); - Level->SetMusicVolume(musvol); + if (arc.isWriting()) + { + order = S_GetMusic(&name); + } + arc.StringPtr("musicname", name) + ("musicorder", order) + ("musicvolume", musvol); + + if (arc.isReading()) + { + if (!S_ChangeMusic(name, order)) + SetMusic(); + SetMusicVolume(musvol); + } } } -//========================================================================== -// -// -// -//========================================================================== - -void CopyPlayer(player_t *dst, player_t *src, const char *name); -static void ReadOnePlayer(FSerializer &arc, bool skipload); -static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload); - //========================================================================== // // P_ArchivePlayers // //========================================================================== -void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload) +void FLevelLocals::SerializePlayers(FSerializer &arc, bool skipload) { int numPlayers, numPlayersNow; int i; @@ -573,7 +570,7 @@ void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload) // Count the number of players present right now. for (numPlayersNow = 0, i = 0; i < MAXPLAYERS; ++i) { - if (Level->PlayerInGame(i)) + if (PlayerInGame(i)) { ++numPlayersNow; } @@ -588,13 +585,13 @@ void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload) // Record each player's name, followed by their data. for (i = 0; i < MAXPLAYERS; ++i) { - if (Level->PlayerInGame(i)) + if (PlayerInGame(i)) { if (arc.BeginObject(nullptr)) { - const char *n = Level->Players[i]->userinfo.GetName(); + const char *n = Players[i]->userinfo.GetName(); arc.StringPtr("playername", n); - Level->Players[i]->Serialize(arc); + Players[i]->Serialize(arc); arc.EndObject(); } } @@ -622,10 +619,10 @@ void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload) } if (!skipload && numPlayersNow > numPlayers) { - Level->SpawnExtraPlayers(); + SpawnExtraPlayers(); } // Redo pitch limits, since the spawned player has them at 0. - auto p = Level->GetConsolePlayer(); + auto p = GetConsolePlayer(); if (p) p->SendPitchLimits(); } } @@ -636,7 +633,7 @@ void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload) // //========================================================================== -static void ReadOnePlayer(FSerializer &arc, bool skipload) +void FLevelLocals::ReadOnePlayer(FSerializer &arc, bool skipload) { int i; const char *name = NULL; @@ -663,20 +660,20 @@ static void ReadOnePlayer(FSerializer &arc, bool skipload) // via a net command, but that won't be processed in time for a screen // wipe, so we need something here. playerTemp.MaxPitch = playerTemp.MinPitch = playerTemp.mo->Angles.Pitch; - CopyPlayer(&players[i], &playerTemp, name); + CopyPlayer(Players[i], &playerTemp, name); } else { // we need the player actor, so that G_FinishTravel can destroy it later. - players[i].mo = playerTemp.mo; + Players[i]->mo = playerTemp.mo; } } else { - if (players[i].mo != NULL) + if (Players[i]->mo != NULL) { - players[i].mo->Destroy(); - players[i].mo = NULL; + Players[i]->mo->Destroy(); + Players[i]->mo = NULL; } } } @@ -691,7 +688,7 @@ static void ReadOnePlayer(FSerializer &arc, bool skipload) // //========================================================================== -static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload) +void FLevelLocals::ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload) { // For two or more players, read each player into a temporary array. int i, j; @@ -729,7 +726,7 @@ static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayers if (playerUsed[j] == 0 && stricmp(players[j].userinfo.GetName(), nametemp[i]) == 0) { // Found a match, so copy our temp player to the real player Printf("Found player %d (%s) at %d\n", i, nametemp[i], j); - CopyPlayer(&players[j], &playertemp[i], nametemp[i]); + CopyPlayer(Players[j], &playertemp[i], nametemp[i]); playerUsed[j] = 1; tempPlayerUsed[i] = 1; break; @@ -802,7 +799,7 @@ static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayers // //========================================================================== -void CopyPlayer(player_t *dst, player_t *src, const char *name) +void FLevelLocals::CopyPlayer(player_t *dst, player_t *src, const char *name) { // The userinfo needs to be saved for real players, but it // needs to come from the save for bots. @@ -823,7 +820,7 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name) if (dst->Bot != nullptr) { - botinfo_t *thebot = src->mo->Level->BotInfo.botinfo; + botinfo_t *thebot = BotInfo.botinfo; while (thebot && stricmp(name, thebot->name)) { thebot = thebot->next; @@ -832,14 +829,14 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name) { thebot->inuse = BOTINUSE_Yes; } - src->mo->Level->BotInfo.botnum++; + BotInfo.botnum++; dst->userinfo.TransferFrom(uibackup2); } else { dst->userinfo.TransferFrom(uibackup); // The player class must come from the save, so that the menu reflects the currently playing one. - dst->userinfo.PlayerClassChanged(src->mo->GetInfo()->DisplayName); + dst->userinfo.PlayerClassChanged(src->mo->GetInfo()->DisplayName); } // Validate the skin @@ -868,6 +865,7 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name) dst->usedown = usedown; } + //========================================================================== // // @@ -1006,8 +1004,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) StatusBar->SerializeMessages(arc); FRemapTable::StaticSerializeTranslations(arc); canvasTextureInfo.Serialize(arc); - P_SerializePlayers(this, arc, hubload); - P_SerializeSounds(this, arc); + SerializePlayers(arc, hubload); + SerializeSounds(arc); // Regenerate some data that wasn't saved if (arc.isReading()) @@ -1036,3 +1034,87 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) } } + +//========================================================================== +// +// Archives the current level +// +//========================================================================== + +void FLevelLocals::SnapshotLevel() +{ + info->Snapshot.Clean(); + + if (info->isValid()) + { + FSerializer arc(this); + + if (arc.OpenWriter(save_formatted)) + { + SaveVersion = SAVEVER; + Serialize(arc, false); + info->Snapshot = arc.GetCompressedOutput(); + } + } +} + +//========================================================================== +// +// Unarchives the current level based on its snapshot +// The level should have already been loaded and setup. +// +//========================================================================== + +void FLevelLocals::UnSnapshotLevel(bool hubLoad) +{ + if (info->Snapshot.mBuffer == nullptr) + return; + + if (info->isValid()) + { + FSerializer arc(this); + if (!arc.OpenReader(&info->Snapshot)) + { + I_Error("Failed to load savegame"); + return; + } + + Serialize(arc, hubLoad); + FromSnapshot = true; + + auto it = GetThinkerIterator(NAME_PlayerPawn); + AActor *pawn, *next; + + next = it.Next(); + while ((pawn = next) != 0) + { + next = it.Next(); + if (pawn->player == nullptr || pawn->player->mo == nullptr || !PlayerInGame(pawn->player)) + { + int i; + + // If this isn't the unmorphed original copy of a player, destroy it, because it's extra. + for (i = 0; i < MAXPLAYERS; ++i) + { + if (PlayerInGame(i) && Players[i]->morphTics && Players[i]->mo->alternative == pawn) + { + break; + } + } + if (i == MAXPLAYERS) + { + pawn->Destroy(); + } + } + } + arc.Close(); + } + // No reason to keep the snapshot around once the level's been entered. + info->Snapshot.Clean(); + if (hubLoad) + { + // Unlock ACS global strings that were locked when the snapshot was made. + Behaviors.UnlockLevelVarStrings(levelnum); + } +} + diff --git a/src/rendering/hwrenderer/utility/hw_cvars.h b/src/rendering/hwrenderer/utility/hw_cvars.h index 025880fc4..29fe587fa 100644 --- a/src/rendering/hwrenderer/utility/hw_cvars.h +++ b/src/rendering/hwrenderer/utility/hw_cvars.h @@ -68,3 +68,7 @@ EXTERN_CVAR(Int, gl_enhanced_nv_stealth) EXTERN_CVAR(Int, gl_fuzztype) EXTERN_CVAR(Int, gl_shadowmap_filter) + +EXTERN_CVAR(Bool, gl_brightfog) +EXTERN_CVAR(Bool, gl_lightadditivesurfaces) +EXTERN_CVAR(Bool, gl_notexturefill) diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index dfbf559f7..39201c79a 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -49,6 +49,8 @@ #include "i_music.h" #include "am_map.h" #include "v_video.h" +#include "gi.h" +#include "intermission/intermission.h" DVector2 AM_GetPosition(); int Net_GetLatency(int *ld, int *ad); @@ -1627,6 +1629,76 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) // //===================================================================================== + static int IsJumpingAllowed(FLevelLocals *self) + { + return self->IsJumpingAllowed(); + } + + DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, IsJumpingAllowed, IsJumpingAllowed) + { + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + ACTION_RETURN_BOOL(self->IsJumpingAllowed()); + } + + //========================================================================== + // + // + //========================================================================== + + static int IsCrouchingAllowed(FLevelLocals *self) + { + return self->IsCrouchingAllowed(); + } + + + DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, IsCrouchingAllowed, IsCrouchingAllowed) + { + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + ACTION_RETURN_BOOL(self->IsCrouchingAllowed()); + } + + //========================================================================== + // + // + //========================================================================== + + static int IsFreelookAllowed(FLevelLocals *self) + { + return self->IsFreelookAllowed(); + } + + DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, IsFreelookAllowed, IsFreelookAllowed) + { + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + ACTION_RETURN_BOOL(self->IsFreelookAllowed()); + } + + //========================================================================== +// +// ZScript counterpart to ACS ChangeSky, uses TextureIDs +// +//========================================================================== + DEFINE_ACTION_FUNCTION(FLevelLocals, ChangeSky) + { + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_INT(sky1); + PARAM_INT(sky2); + self->skytexture1 = FSetTextureID(sky1); + self->skytexture2 = FSetTextureID(sky2); + InitSkyMap(self); + return 0; + } + + DEFINE_ACTION_FUNCTION(FLevelLocals, StartIntermission) + { + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_NAME(seq); + PARAM_INT(state); + F_StartIntermission(seq, (uint8_t)state); + return 0; + } + + // This is needed to convert the strings to char pointers. static void ReplaceTextures(FLevelLocals *self, const FString &from, const FString &to, int flags) {