- started cleaning up g_level.cpp.

This works up to the point where it tries to apply snapshots, it doesn't start the level yet.
This commit is contained in:
Christoph Oelckers 2019-01-11 19:31:56 +01:00
parent e0826726ba
commit 70ee43a95a
35 changed files with 548 additions and 631 deletions

View file

@ -170,7 +170,7 @@ CUSTOM_CVAR (Int, fraglimit, 0, CVAR_SERVERINFO)
if (playeringame[i] && self <= D_GetFragCount(&players[i]))
{
Printf ("%s\n", GStrings("TXT_FRAGLIMIT"));
G_ExitLevel (0, false);
G_ExitLevel (currentSession->Levelinfo[0], 0, false);
break;
}
}

View file

@ -2228,8 +2228,9 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
// That was a long time ago. Maybe it works now?
if (currentSession)
{
currentSession->Levelinfo[0]->flags |= LEVEL_CHANGEMAPCHEAT;
G_ChangeLevel(s, pos, 0);
auto Level = currentSession->Levelinfo[0];
Level->flags |= LEVEL_CHANGEMAPCHEAT;
G_ChangeLevel(Level, s, pos, 0);
}
break;
@ -2667,7 +2668,11 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
case DEM_FINISHGAME:
// Simulate an end-of-game action
G_ChangeLevel(NULL, 0, 0);
if (currentSession)
{
auto Level = currentSession->Levelinfo[0];
G_ChangeLevel(Level, nullptr, 0, 0);
}
break;
case DEM_NETEVENT:

View file

@ -229,7 +229,7 @@ void DThinker::SerializeThinkers(FSerializer &arc, bool hubLoad)
void DThinker::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
Level = &level; // Must be written out once a real object.
Level = arc.Level;
}
//==========================================================================
@ -242,7 +242,7 @@ DThinker::DThinker (int statnum) throw()
{
NextThinker = NULL;
PrevThinker = NULL;
Level = &level; // do this properly later.
Level = bSerialOverride? nullptr : currentSession->Levelinfo[0]; // do this properly later.
if (bSerialOverride)
{ // The serializer will insert us into the right list
return;

View file

@ -77,7 +77,7 @@ static void FS_Gimme(const char * what)
//
//==========================================================================
void FS_MapCmd(FScanner &sc)
void FS_MapCmd(FLevelLocals *Level, FScanner &sc)
{
char nextmap[9];
int NextSkill = -1;
@ -108,7 +108,7 @@ void FS_MapCmd(FScanner &sc)
flags &= ~(CHANGELEVEL_RESETINVENTORY|CHANGELEVEL_RESETHEALTH);
}
}
G_ChangeLevel(nextmap, 0, flags, NextSkill);
G_ChangeLevel(Level, nextmap, 0, flags, NextSkill);
}
//==========================================================================
@ -168,7 +168,7 @@ void FS_EmulateCmd(FLevelLocals *Level, char * string)
}
else if (sc.Compare("map"))
{
FS_MapCmd(sc);
FS_MapCmd(Level, sc);
}
else if (sc.Compare("gr_fogdensity"))
{
@ -177,7 +177,7 @@ void FS_EmulateCmd(FLevelLocals *Level, char * string)
Level->fogdensity = sc.Number * 70 / 400;
Level->outsidefogdensity = 0;
Level->skyfog = 0;
Level->info->outsidefog = 0;
Level->outsidefog = 0;
}
else if (sc.Compare("gr_fogcolor"))
{

View file

@ -635,7 +635,7 @@ void FParser::SF_Clock(void)
void FParser::SF_ExitLevel(void)
{
G_ExitLevel(0, false);
G_ExitLevel(Level, 0, false);
}
//==========================================================================
@ -2853,7 +2853,7 @@ void FParser::SF_AmbientSound(void)
void FParser::SF_ExitSecret(void)
{
G_SecretExitLevel(0);
G_SecretExitLevel(Level, 0);
}

View file

@ -150,7 +150,7 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc)
{
sc.MustGetStringName("=");
sc.MustGetString();
Level->info->ExitPic = sc.String;
const_cast<level_info_t*>(Level->info)->ExitPic = sc.String;
}
else if (sc.Compare("gravity"))
{

View file

@ -179,7 +179,7 @@ void DFsScript::Serialize(FSerializer &arc)
// don't save a reference to the global script, which contains unserializable data.
if (parent == Level->FraggleScriptThinker->GlobalScript) parent = nullptr;
if (arc.isReading()) Level = &level; // must later be written out.
if (arc.isReading()) Level = arc.Level;
arc("data", data)
("scriptnum", scriptnum)

View file

@ -1028,7 +1028,7 @@ void G_Ticker ()
switch (gameaction)
{
case ga_loadlevel:
G_DoLoadLevel (-1, false, false);
G_DoLoadLevel (currentSession->nextlevel, -1, false, false);
break;
case ga_recordgame:
G_CheckDemoStatus();
@ -1103,7 +1103,8 @@ void G_Ticker ()
uint32_t rngsum = FRandom::StaticSumSeeds ();
//Added by MC: For some of that bot stuff. The main bot function.
bglobal.Main (currentSession->Levelinfo[0]);
if (currentSession->Levelinfo.Size() > 0)
bglobal.Main (currentSession->Levelinfo[0]);
for (i = 0; i < MAXPLAYERS; i++)
{
@ -1925,8 +1926,7 @@ void G_DoLoadGame ()
NextSkill = -1;
arc("nextskill", NextSkill);
if (level.info != nullptr)
level.info->Snapshot.Clean();
//currentSession->Snapshots.Remove(MapName); fixme
BackupSaveName = savename;
@ -2137,7 +2137,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
{
// delete the snapshot. Since the save failed it is broken.
insave = false;
level.info->Snapshot.Clean();
//level.info->Snapshot.Clean();
Printf(PRINT_HIGH, "Save failed\n");
Printf(PRINT_HIGH, "%s\n", err.GetMessage());
// The time freeze must be reset if the save fails.
@ -2236,8 +2236,8 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
// delete the JSON buffers we created just above. Everything else will
// either still be needed or taken care of automatically.
savegame_content[1].Clean();
savegame_content[2].Clean();
//savegame_content[1].Clean();
//savegame_content[2].Clean();
// Check whether the file is ok by trying to open it.
FResourceFile *test = FResourceFile::OpenResourceFile(filename, true);
@ -2253,7 +2253,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
BackupSaveName = filename;
// We don't need the snapshot any longer.
level.info->Snapshot.Clean();
//currentSession->Snapshots.Remove(???);
insave = false;

File diff suppressed because it is too large Load diff

View file

@ -42,6 +42,7 @@
struct level_info_t;
struct cluster_info_t;
class FSerializer;
struct FLevelLocals;
#if defined(_MSC_VER)
#pragma section(".yreg$u",read)
@ -191,7 +192,7 @@ enum ELevelFlags : unsigned int
LEVEL_SWAPSKIES = 0x10000000, // Used by lightning
LEVEL_NOALLIES = 0x20000000, // i.e. Inside Strife's front base
LEVEL_CHANGEMAPCHEAT = 0x40000000, // Don't display cluster messages
LEVEL_VISITED = 0x80000000, // Used for intermission map
//LEVEL_VISITED = 0x80000000, // Used for intermission map
// The flags uint64_t is now split into 2 DWORDs
LEVEL2_RANDOMPLAYERSTARTS = 0x00000001, // Select single player starts randomnly (no voodoo dolls)
@ -325,8 +326,6 @@ struct level_info_t
FString LevelName;
int8_t WallVertLight, WallHorizLight;
int musicorder;
FCompressedBuffer Snapshot;
TArray<acsdefered_t> deferred;
float skyspeed1;
float skyspeed2;
uint32_t fadeto;
@ -393,19 +392,10 @@ struct level_info_t
{
Reset();
}
~level_info_t()
{
Snapshot.Clean();
ClearDefered();
}
void Reset();
bool isValid();
FString LookupLevelName ();
void ClearDefered()
{
deferred.Clear();
}
level_info_t *CheckLevelRedirect ();
bool isValid() const;
FString LookupLevelName () const;
level_info_t *CheckLevelRedirect () const;
};
@ -454,10 +444,10 @@ void G_DeferedInitNew (const char *mapname, int skill = -1);
struct FGameStartup;
void G_DeferedInitNew (FGameStartup *gs);
void G_ExitLevel (int position, bool keepFacing);
void G_SecretExitLevel (int position);
const char *G_GetExitMap();
const char *G_GetSecretExitMap();
void G_ExitLevel (FLevelLocals *Level, int position, bool keepFacing);
void G_SecretExitLevel (FLevelLocals *Level, int position);
const char *G_GetExitMap(FLevelLocals *Level);
const char *G_GetSecretExitMap(FLevelLocals *Level);
enum
{
@ -470,12 +460,12 @@ enum
CHANGELEVEL_PRERAISEWEAPON = 64,
};
void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill=-1);
void G_ChangeLevel(FLevelLocals *Level, const char *levelname, int position, int flags, int nextSkill=-1);
void G_StartTravel ();
int G_FinishTravel ();
int G_FinishTravel (FLevelLocals *);
void G_DoLoadLevel (int position, bool autosave, bool newGame);
void G_DoLoadLevel (const FString &mapname, int position, bool autosave, bool newGame);
void G_InitLevelLocals (void);
@ -493,7 +483,7 @@ void G_ParseMapInfo (FString basemapinfo);
void G_ClearSnapshots (void);
void P_RemoveDefereds ();
void G_SnapshotLevel (void);
void G_UnSnapshotLevel (bool keepPlayers);
void G_UnSnapshotLevel(const TArray<FLevelLocals *> &levels, bool hubLoad);
void G_ReadSnapshots (FResourceFile *);
void G_WriteSnapshots (TArray<FString> &, TArray<FCompressedBuffer> &);
void G_WriteVisited(FSerializer &arc);

View file

@ -47,6 +47,7 @@
#include "p_tags.h"
#include "p_effect.h"
#include "p_destructible.h"
#include "p_conversation.h"
#include "r_data/r_interpolate.h"
#include "r_data/r_sections.h"
#include "r_data/r_canvastexture.h"
@ -88,7 +89,7 @@ struct FLevelData
FDisplacementTable Displacements;
FPortalBlockmap PortalBlockmap;
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups.
TArray<FSectorPortalGroup *> portalGroups;
TDeletingArray<FSectorPortalGroup *> portalGroups;
TArray<FLinePortalSpan> linePortalSpans;
FSectionContainer sections;
FCanvasTextureInfo canvasTextureInfo;
@ -112,7 +113,7 @@ struct FLevelData
FBehaviorContainer Behaviors;
TArray<FStrifeDialogueNode *> StrifeDialogues;
TDeletingArray<FStrifeDialogueNode *> StrifeDialogues;
FDialogueIDMap DialogueRoots;
FDialogueMap ClassRoots;
@ -129,7 +130,16 @@ struct FLevelData
struct FLevelLocals : public FLevelData
{
void *operator new(size_t blocksize)
{
// Null the allocated memory before running the constructor.
// This was previously static memory that relied on being nulled to avoid uninitialized parts.
auto block = ::operator new(blocksize);
memset(block, 0, blocksize);
return block;
}
FLevelLocals() : tagManager(this) {}
~FLevelLocals();
void Tick();
void Mark();
@ -137,13 +147,12 @@ struct FLevelLocals : public FLevelData
void SetInterMusic(const char *nextmap);
void SetMusic();
void ClearLevelData();
void ClearPortals();
bool CheckIfExitIsGood(AActor *self, level_info_t *newmap);
void FormatMapName(FString &mapname, const char *mapnamecolor);
void TranslateTeleportThings(void);
void ClearAllSubsectorLinks();
void ChangeAirControl(double newval);
void InitLevelLocals();
void InitLevelLocals(const level_info_t *info, bool isprimary);
bool IsTIDUsed(int tid);
int FindUniqueTID(int start_tid, int limit);
int GetConversation(int conv_id);
@ -175,7 +184,7 @@ struct FLevelLocals : public FLevelData
int sucktime;
uint32_t spawnindex;
level_info_t *info;
const level_info_t * info; // The info is supposed to be immutable.
int cluster;
int clusterflags;
int levelnum;
@ -299,8 +308,8 @@ struct FLevelLocals : public FLevelData
// Returns true if level is loaded from saved game or is being revisited as a part of a hub
bool IsReentering() const
{
return savegamerestore
|| (info != nullptr && info->Snapshot.mBuffer != nullptr && info->isValid());
// This is actually very simple: A reentered map never has a map time of 0 when it starts. If the map time is 0 it must be a freshly loaded instance.
return maptime > 0;
}
};
@ -309,21 +318,39 @@ class FGameSession
{
public:
TArray<FLevelLocals *> Levelinfo;
TMap<FName, FCompressedBuffer> Snapshots;
TMap<FName, TArray<acsdefered_t>> DeferredScripts;
TMap<FName, bool> Visited;
FString F1Pic;
float MusicVolume;
int time; // time in the hub
int totaltime; // time in the game
FString nextlevel; // Level to go to on exit
int nextstartpos; // [RH] Support for multiple starts per level
void SetMusicVolume(float vol);
void Reset();
bool isValid();
FString LookupLevelName ();
void ClearDefered()
{
DeferredScripts.Clear();
}
void ClearSnapshots()
{
Snapshots.Clear();
}
};
extern FGameSession *currentSession;
#ifndef NO_DEFINE_LEVEL
extern FLevelLocals level;
inline FSectorPortal *line_t::GetTransferredPortal()
{
auto Level = GetLevel();
@ -430,5 +457,3 @@ inline void ForAllLevels(T func)
for (auto Level : currentSession->Levelinfo) func(Level);
}
}
#endif

View file

@ -184,37 +184,6 @@ cluster_info_t *FindClusterInfo (int cluster)
return &TheDefaultClusterInfo;
}
//==========================================================================
//
//
//==========================================================================
void G_ClearSnapshots (void)
{
for (unsigned int i = 0; i < wadlevelinfos.Size(); i++)
{
wadlevelinfos[i].Snapshot.Clean();
}
// Since strings are only locked when snapshotting a level, unlock them
// all now, since we got rid of all the snapshots that cared about them.
GlobalACSStrings.UnlockAll();
}
//==========================================================================
//
// Remove any existing defereds
//
//==========================================================================
void P_RemoveDefereds (void)
{
for (unsigned int i = 0; i < wadlevelinfos.Size(); i++)
{
wadlevelinfos[i].ClearDefered();
}
}
//==========================================================================
//
//
@ -245,8 +214,6 @@ void level_info_t::Reset()
WallVertLight = +8;
F1Pic = "";
musicorder = 0;
Snapshot = { 0,0,0,0,0,nullptr };
deferred.Clear();
skyspeed1 = skyspeed2 = 0.f;
fadeto = 0;
outsidefog = 0xff000000;
@ -298,7 +265,7 @@ void level_info_t::Reset()
//
//==========================================================================
FString level_info_t::LookupLevelName()
FString level_info_t::LookupLevelName() const
{
if (flags & LEVEL_LOOKUPLEVELNAME)
{
@ -353,7 +320,7 @@ FString level_info_t::LookupLevelName()
//
//==========================================================================
level_info_t *level_info_t::CheckLevelRedirect ()
level_info_t *level_info_t::CheckLevelRedirect () const
{
if (RedirectType != NAME_None)
{
@ -382,7 +349,7 @@ level_info_t *level_info_t::CheckLevelRedirect ()
//
//==========================================================================
bool level_info_t::isValid()
bool level_info_t::isValid() const
{
return MapName.Len() != 0 || this == &TheDefaultLevelInfo;
}
@ -2284,7 +2251,6 @@ static void ClearMapinfo()
AllSkills.Clear();
DefaultSkill = -1;
DeinitIntermissions();
level.info = NULL;
currentSession->F1Pic = "";
}

View file

@ -46,7 +46,7 @@ protected:
TArray<float> mLights;
// Used to detect when a level change requires the AABB tree to be regenerated
level_info_t *mLastLevel = nullptr;
const level_info_t *mLastLevel = nullptr;
unsigned mLastNumNodes = 0;
unsigned mLastNumSegs = 0;

View file

@ -200,7 +200,7 @@ float HWDrawInfo::GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfog
density = 0;
}
}
else if (Level->outsidefogdensity != 0 && APART(Level->info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (Level->info->outsidefog & 0xffffff))
else if (Level->outsidefogdensity != 0 && APART(Level->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (Level->outsidefog & 0xffffff))
{
// case 3. outsidefogdensity has already been set as needed
density = (float)Level->outsidefogdensity;
@ -248,7 +248,7 @@ bool HWDrawInfo::CheckFog(sector_t *frontsector, sector_t *backsector)
else if (fogcolor.a != 0)
{
}
else if (Level->outsidefogdensity != 0 && APART(Level->info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (Level->info->outsidefog & 0xffffff))
else if (Level->outsidefogdensity != 0 && APART(Level->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (Level->outsidefog & 0xffffff))
{
}
else if (Level->fogdensity!=0 || lightmode == ELightMode::DoomLegacy)
@ -266,7 +266,7 @@ bool HWDrawInfo::CheckFog(sector_t *frontsector, sector_t *backsector)
if ((fogcolor.d & 0xffffff) == 0)
{
}
else if (Level->outsidefogdensity != 0 && APART(Level->info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (Level->info->outsidefog & 0xffffff))
else if (Level->outsidefogdensity != 0 && APART(Level->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (Level->outsidefog & 0xffffff))
{
return false;
}

View file

@ -1988,11 +1988,7 @@ bool FBehaviorContainer::CheckAllGood ()
void FBehaviorContainer::UnloadModules ()
{
for (unsigned int i = StaticModules.Size(); i-- > 0; )
{
delete StaticModules[i];
}
StaticModules.Clear ();
StaticModules.DeleteAndClear ();
}
FBehavior *FBehaviorContainer::GetModule (int lib)
@ -3447,8 +3443,7 @@ void DLevelScript::Serialize(FSerializer &arc)
uint32_t pcofs;
uint16_t lib;
// This cannot be serialized yet.
if(arc.isReading()) Level = &level;
if(arc.isReading()) Level = arc.Level;
if (arc.isWriting())
{
@ -9928,7 +9923,7 @@ scriptwait:
case PCD_CHANGELEVEL:
{
G_ChangeLevel(Level->Behaviors.LookupString(STACK(4)), STACK(3), STACK(2), STACK(1));
G_ChangeLevel(Level, Level->Behaviors.LookupString(STACK(4)), STACK(3), STACK(2), STACK(1));
sp -= 4;
}
break;
@ -10321,70 +10316,73 @@ void P_DoDeferedScripts (FLevelLocals *Level)
FBehavior *module;
// Handle defered scripts in this step, too
for(int i = Level->info->deferred.Size()-1; i>=0; i--)
auto deferred = currentSession->DeferredScripts.CheckKey(Level->MapName);
if (deferred)
{
acsdefered_t *def = &Level->info->deferred[i];
switch (def->type)
for(int i = deferred->Size()-1; i>=0; i--)
{
case acsdefered_t::defexecute:
case acsdefered_t::defexealways:
scriptdata = Level->Behaviors.FindScript (def->script, module);
if (scriptdata)
acsdefered_t *def = &(*deferred)[i];
switch (def->type)
{
P_GetScriptGoing (Level, (unsigned)def->playernum < MAXPLAYERS &&
playeringame[def->playernum] ? players[def->playernum].mo : NULL,
NULL, def->script,
scriptdata, module,
def->args, 3,
def->type == acsdefered_t::defexealways ? ACS_ALWAYS : 0);
case acsdefered_t::defexecute:
case acsdefered_t::defexealways:
scriptdata = Level->Behaviors.FindScript (def->script, module);
if (scriptdata)
{
P_GetScriptGoing (Level, (unsigned)def->playernum < MAXPLAYERS &&
playeringame[def->playernum] ? players[def->playernum].mo : NULL,
NULL, def->script,
scriptdata, module,
def->args, 3,
def->type == acsdefered_t::defexealways ? ACS_ALWAYS : 0);
}
else
{
Printf ("P_DoDeferredScripts: Unknown %s\n", ScriptPresentation(def->script).GetChars());
}
break;
case acsdefered_t::defsuspend:
SetScriptState (Level->ACSThinker, def->script, DLevelScript::SCRIPT_Suspended);
DPrintf (DMSG_SPAMMY, "Deferred suspend of %s\n", ScriptPresentation(def->script).GetChars());
break;
case acsdefered_t::defterminate:
SetScriptState (Level->ACSThinker, def->script, DLevelScript::SCRIPT_PleaseRemove);
DPrintf (DMSG_SPAMMY, "Deferred terminate of %s\n", ScriptPresentation(def->script).GetChars());
break;
}
else
{
Printf ("P_DoDeferredScripts: Unknown %s\n", ScriptPresentation(def->script).GetChars());
}
break;
case acsdefered_t::defsuspend:
SetScriptState (Level->ACSThinker, def->script, DLevelScript::SCRIPT_Suspended);
DPrintf (DMSG_SPAMMY, "Deferred suspend of %s\n", ScriptPresentation(def->script).GetChars());
break;
case acsdefered_t::defterminate:
SetScriptState (Level->ACSThinker, def->script, DLevelScript::SCRIPT_PleaseRemove);
DPrintf (DMSG_SPAMMY, "Deferred terminate of %s\n", ScriptPresentation(def->script).GetChars());
break;
}
}
Level->info->deferred.Clear();
currentSession->DeferredScripts.Remove(Level->MapName);
}
static void addDefered (level_info_t *i, acsdefered_t::EType type, int script, const int *args, int argcount, AActor *who)
static void addDefered (FLevelLocals *Level, acsdefered_t::EType type, int script, const int *args, int argcount, AActor *who)
{
if (i)
auto &deferred = currentSession->DeferredScripts[Level->MapName];
acsdefered_t &def = deferred[deferred.Reserve(1)];
int j;
def.type = type;
def.script = script;
for (j = 0; (size_t)j < countof(def.args) && j < argcount; ++j)
{
acsdefered_t &def = i->deferred[i->deferred.Reserve(1)];
int j;
def.type = type;
def.script = script;
for (j = 0; (size_t)j < countof(def.args) && j < argcount; ++j)
{
def.args[j] = args[j];
}
while ((size_t)j < countof(def.args))
{
def.args[j++] = 0;
}
if (who != NULL && who->player != NULL)
{
def.playernum = int(who->player - players);
}
else
{
def.playernum = -1;
}
DPrintf (DMSG_SPAMMY, "%s on map %s deferred\n", ScriptPresentation(script).GetChars(), i->MapName.GetChars());
def.args[j] = args[j];
}
while ((size_t)j < countof(def.args))
{
def.args[j++] = 0;
}
if (who != NULL && who->player != NULL)
{
def.playernum = int(who->player - players);
}
else
{
def.playernum = -1;
}
DPrintf (DMSG_SPAMMY, "%s on map %s deferred\n", ScriptPresentation(script).GetChars(), Level->MapName.GetChars());
}
EXTERN_CVAR (Bool, sv_cheats)
@ -10436,9 +10434,7 @@ int P_StartScript (FLevelLocals *Level, AActor *who, line_t *where, int script,
}
else
{
addDefered (FindLevelInfo (map),
(flags & ACS_ALWAYS) ? acsdefered_t::defexealways : acsdefered_t::defexecute,
script, args, argcount, who);
addDefered (Level, (flags & ACS_ALWAYS) ? acsdefered_t::defexealways : acsdefered_t::defexecute, script, args, argcount, who);
return true;
}
return false;
@ -10447,7 +10443,7 @@ int P_StartScript (FLevelLocals *Level, AActor *who, line_t *where, int script,
void P_SuspendScript (FLevelLocals *Level, int script, const char *map)
{
if (strnicmp (Level->MapName, map, 8))
addDefered (FindLevelInfo (map), acsdefered_t::defsuspend, script, NULL, 0, NULL);
addDefered (Level, acsdefered_t::defsuspend, script, NULL, 0, NULL);
else
SetScriptState (Level->ACSThinker, script, DLevelScript::SCRIPT_Suspended);
}
@ -10455,7 +10451,7 @@ void P_SuspendScript (FLevelLocals *Level, int script, const char *map)
void P_TerminateScript (FLevelLocals *Level, int script, const char *map)
{
if (strnicmp (Level->MapName, map, 8))
addDefered (FindLevelInfo (map), acsdefered_t::defterminate, script, NULL, 0, NULL);
addDefered (Level, acsdefered_t::defterminate, script, NULL, 0, NULL);
else
SetScriptState (Level->ACSThinker, script, DLevelScript::SCRIPT_PleaseRemove);
}

View file

@ -428,7 +428,7 @@ private:
struct FBehaviorContainer
{
TArray<FBehavior *> StaticModules;
TDeletingArray<FBehavior *> StaticModules;
FBehavior *LoadModule(FLevelLocals *Level, int lumpnum, FileReader *fr = nullptr, int len = 0);
void LoadDefaultModules(FLevelLocals *Level);

View file

@ -3168,11 +3168,11 @@ void A_BossDeath(AActor *self)
}
}
// [RH] If noexit, then don't end the Level->
// [RH] If noexit, then don't end the map.
if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT))
return;
G_ExitLevel (0, false);
G_ExitLevel (Level, 0, false);
}
//----------------------------------------------------------------------------

View file

@ -543,7 +543,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
fraglimit <= D_GetFragCount (source->player))
{
Printf ("%s\n", GStrings("TXT_FRAGLIMIT"));
G_ExitLevel (0, false);
G_ExitLevel (Level, 0, false);
}
}
}

View file

@ -1061,9 +1061,9 @@ FUNC(LS_Generic_Lift)
FUNC(LS_Exit_Normal)
// Exit_Normal (position)
{
if (Level->CheckIfExitIsGood (it, FindLevelInfo(G_GetExitMap())))
if (Level->CheckIfExitIsGood (it, FindLevelInfo(G_GetExitMap(Level))))
{
G_ExitLevel (arg0, false);
G_ExitLevel (Level, arg0, false);
return true;
}
return false;
@ -1072,9 +1072,9 @@ FUNC(LS_Exit_Normal)
FUNC(LS_Exit_Secret)
// Exit_Secret (position)
{
if (Level->CheckIfExitIsGood (it, FindLevelInfo(G_GetSecretExitMap())))
if (Level->CheckIfExitIsGood (it, FindLevelInfo(G_GetSecretExitMap(Level))))
{
G_SecretExitLevel (arg0);
G_SecretExitLevel (Level, arg0);
return true;
}
return false;
@ -1089,7 +1089,7 @@ FUNC(LS_Teleport_NewMap)
if (info && Level->CheckIfExitIsGood (it, info))
{
G_ChangeLevel(info->MapName, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0);
G_ChangeLevel(Level, info->MapName, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0);
return true;
}
}
@ -1182,9 +1182,9 @@ FUNC(LS_TeleportInSector)
FUNC(LS_Teleport_EndGame)
// Teleport_EndGame ()
{
if (!backSide && Level->CheckIfExitIsGood (it, NULL))
if (!backSide && Level->CheckIfExitIsGood (it, nullptr))
{
G_ChangeLevel(NULL, 0, 0);
G_ChangeLevel(Level, nullptr, 0, 0);
return true;
}
return false;

View file

@ -939,6 +939,7 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
("skytexture2", Level->skytexture2)
("fogdensity", Level->fogdensity)
("outsidefogdensity", Level->outsidefogdensity)
("outsidefog", Level->outsidefog)
("skyfog", Level->skyfog)
("deathsequence", Level->deathsequence)
("bodyqueslot", Level->bodyqueslot)

View file

@ -199,144 +199,6 @@ static void PrecacheLevel(FLevelLocals *Level)
}
//============================================================================
//
// clears all portal data for a new level start
//
//============================================================================
void FLevelLocals::ClearPortals()
{
Displacements.Create(1);
linePortals.Clear();
linkedPortals.Clear();
sectorPortals.Resize(2);
PortalBlockmap.Clear();
// The first entry must always be the default skybox. This is what every sector gets by default.
memset(&sectorPortals[0], 0, sizeof(sectorPortals[0]));
sectorPortals[0].mType = PORTS_SKYVIEWPOINT;
sectorPortals[0].mFlags = PORTSF_SKYFLATONLY;
// The second entry will be the default sky. This is for forcing a regular sky through the skybox picker
memset(&sectorPortals[1], 0, sizeof(sectorPortals[0]));
sectorPortals[1].mType = PORTS_SKYVIEWPOINT;
sectorPortals[1].mFlags = PORTSF_SKYFLATONLY;
// also clear the render data
for (auto &sub : subsectors)
{
for (int j = 0; j < 2; j++)
{
if (sub.portalcoverage[j].subsectors != nullptr)
{
delete[] sub.portalcoverage[j].subsectors;
sub.portalcoverage[j].subsectors = nullptr;
}
}
}
for (unsigned i = 0; i < portalGroups.Size(); i++)
{
delete portalGroups[i];
}
portalGroups.Clear();
linePortalSpans.Clear();
}
//==========================================================================
//
//
//
//==========================================================================
void FLevelLocals::ClearLevelData()
{
total_monsters = total_items = total_secrets =
killed_monsters = found_items = found_secrets =
wminfo.maxfrags = 0;
for (int i = 0; i < 4; i++)
{
UDMFKeys[i].Clear();
}
SN_StopAllSequences(this);
FStrifeDialogueNode *node;
while (StrifeDialogues.Pop (node))
{
delete node;
}
DialogueRoots.Clear();
ClassRoots.Clear();
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh map.
ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
DThinker::DestroyAllThinkers();
// delete allocated data in the level arrays.
if (sectors.Size() > 0)
{
delete[] sectors[0].e;
}
for (auto &sub : subsectors)
{
if (sub.BSP != nullptr) delete sub.BSP;
}
ClearPortals();
tagManager.Clear();
// [RH] Clear all ThingID hash chains.
ClearTIDHashes();
Behaviors.UnloadModules();
SpotState = nullptr;
ACSThinker = nullptr;
FraggleScriptThinker = nullptr;
CorpseQueue.Clear();
canvasTextureInfo.EmptyList();
sections.Clear();
segs.Clear();
sectors.Clear();
linebuffer.Clear();
subsectorbuffer.Clear();
lines.Clear();
sides.Clear();
segbuffer.Clear();
loadsectors.Clear();
loadlines.Clear();
loadsides.Clear();
vertexes.Clear();
nodes.Clear();
gamenodes.Reset();
subsectors.Clear();
gamesubsectors.Reset();
rejectmatrix.Clear();
Zones.Clear();
blockmap.Clear();
Polyobjects.Clear();
for (auto &pb : PolyBlockMap)
{
polyblock_t *link = pb;
while (link != nullptr)
{
polyblock_t *next = link->next;
delete link;
link = next;
}
}
PolyBlockMap.Reset();
deathmatchstarts.Clear();
AllPlayerStarts.Clear();
memset(playerstarts, 0, sizeof(playerstarts));
Scrolls.Clear();
}
//==========================================================================
//
//
@ -349,7 +211,6 @@ void P_FreeLevelData ()
// [ZZ] delete per-map event handlers
E_Shutdown(true);
R_FreePastViewers();
level.ClearLevelData();
}
//===========================================================================

View file

@ -468,7 +468,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
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)))
{
G_ExitLevel(0, false);
G_ExitLevel(player->mo->Level, 0, false);
}
if (sector->Flags & SECF_DMGTERRAINFX)
{
@ -683,7 +683,7 @@ void P_UpdateSpecials (FLevelLocals *Level)
if (Level->maptime >= (int)(timelimit * TICRATE * 60))
{
Printf ("%s\n", GStrings("TXT_TIMELIMIT"));
G_ExitLevel(0, false);
G_ExitLevel(Level, 0, false);
}
}
}

View file

@ -62,7 +62,8 @@ bool P_CheckTickerPaused ()
&& players[consoleplayer].viewz != NO_VALUE
&& wipegamestate == gamestate)
{
S_PauseSound (!currentSession || !(currentSession->Levelinfo[0]->flags2 & LEVEL2_PAUSE_MUSIC_IN_MENUS), false);
auto nopause = gamestate != GS_LEVEL || !(currentSession->Levelinfo[0]->flags2 & LEVEL2_PAUSE_MUSIC_IN_MENUS);
S_PauseSound (nopause, false);
return true;
}
return false;

View file

@ -1116,7 +1116,7 @@ void P_CheckMusicChange(player_t *player)
if (player->MUSINFOactor->args[0] != 0)
{
auto Level = player->mo->Level;
FName *music = Level->info->MusicMap.CheckKey(player->MUSINFOactor->args[0]);
const FName *music = Level->info->MusicMap.CheckKey(player->MUSINFOactor->args[0]);
if (music != NULL)
{

View file

@ -100,7 +100,7 @@ struct FPortalBlock
struct FPortalBlockmap
{
TArray<FPortalBlock> data;
int dx, dy;
int dx = 0, dy = 0;
bool containsLines;
bool hasLinkedSectorPortals; // global flag to shortcut portal checks if the map has none.
bool hasLinkedPolyPortals; // this means that any early-outs in P_CheckSight need to be disabled if a block contains polyobjects.

View file

@ -59,6 +59,10 @@ public:
didInterp = false;
count = 0;
}
~FInterpolator()
{
ClearInterpolations();
}
void UpdateInterpolations();
void AddInterpolation(DInterpolation *);
void RemoveInterpolation(DInterpolation *);

View file

@ -19,7 +19,7 @@ struct FCompressedBuffer
char *mBuffer;
bool Decompress(char *destbuffer);
void Clean()
~FCompressedBuffer()
{
mSize = mCompressedSize = 0;
if (mBuffer != nullptr)

View file

@ -354,7 +354,7 @@ void DSeqNode::Serialize(FSerializer &arc)
}
else
{
Level = &level; // temporary solution
Level = arc.Level;
seqnum = FindSequence (seqName);
if (seqnum >= 0)
{

View file

@ -476,7 +476,7 @@ void S_Start (FLevelLocals *Level)
//
//==========================================================================
void S_PrecacheLevel (TArray<int> &levelsounds)
void S_PrecacheLevel (const TArray<int> &levelsounds)
{
unsigned int i;

View file

@ -218,7 +218,7 @@ void S_Shutdown ();
void S_Start (FLevelLocals *Level);
// Called after a level is loaded. Ensures that most sounds are loaded.
void S_PrecacheLevel (TArray<int> &levelsounds);
void S_PrecacheLevel (const TArray<int> &levelsounds);
// Loads a sound, including any random sounds it might reference.
void S_CacheSound (sfxinfo_t *sfx);

View file

@ -2705,7 +2705,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_AltHUD, GetLatency, Net_GetLatency)
//
//
//==========================================================================
DEFINE_GLOBAL(level);
DEFINE_FIELD(FLevelLocals, sectors)
DEFINE_FIELD(FLevelLocals, lines)
DEFINE_FIELD(FLevelLocals, sides)
@ -2770,6 +2769,7 @@ DEFINE_FIELD(FGameSession, time)
DEFINE_FIELD(FGameSession, totaltime)
DEFINE_GLOBAL(currentSession)
DEFINE_FIELD_X(Sector, sector_t, Level)
DEFINE_FIELD_X(Sector, sector_t, floorplane)
DEFINE_FIELD_X(Sector, sector_t, ceilingplane)
DEFINE_FIELD_X(Sector, sector_t, Colormap)

View file

@ -437,7 +437,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level)
// record the current level's stats.
StoreLevelStats(Level);
level_info_t *thisinfo = Level->info;
const level_info_t *thisinfo = Level->info;
level_info_t *nextinfo = NULL;
if (strncmp(newl, "enDSeQ", 6))

View file

@ -620,13 +620,11 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
switch (a->type & ANIM_CONDITION)
{
case ANIM_IFVISITED:
li = FindLevelInfo(a->LevelName);
if (li == NULL || !(li->flags & LEVEL_VISITED)) continue;
if (!currentSession->Visited.CheckKey(a->LevelName)) continue;
break;
case ANIM_IFNOTVISITED:
li = FindLevelInfo(a->LevelName);
if (li == NULL || (li->flags & LEVEL_VISITED)) continue;
if (currentSession->Visited.CheckKey(a->LevelName)) continue;
break;
// StatCount means 'leaving' - everything else means 'entering'!
@ -663,8 +661,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
{
for (i = 0; i<lnodes.Size(); i++)
{
level_info_t * li = FindLevelInfo(lnodes[i].Level);
if (li && li->flags & LEVEL_VISITED) drawOnLnode(i, &splat, 1); // draw a splat on taken cities.
if (currentSession->Visited.CheckKey(lnodes[i].Level)) drawOnLnode(i, &splat, 1); // draw a splat on taken cities.
}
}

View file

@ -7,7 +7,7 @@ struct _ native // These are the global variables, the struct is only here to av
native readonly Array<@Team> Teams;
native int validcount;
native readonly bool multiplayer;
native play @LevelLocals level;
//native play @LevelLocals level;
native @KeyBindings Bindings;
native @KeyBindings AutomapBindings;
native play @DehInfo deh;
@ -506,10 +506,10 @@ class BlockThingsIterator : Object native
native static BlockThingsIterator Create(Actor origin, double checkradius = -1, bool ignorerestricted = false);
native static BlockThingsIterator CreateFromPosition(LevelLocals Level, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted);
// Since this depends on the global level variable it should not be used any longer because this may block compatibility with future features.
// Since this has no good means to deduce the level from its parameters it should not be used any longer because this may block compatibility with future features.
deprecated("3.8") static BlockThingsIterator CreateFromPos(double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted)
{
return CreateFromPosition(level, checkx, checky, checkz, checkh, checkradius, ignorerestricted);
return CreateFromPosition(currentSession.LevelInfo[0], checkx, checky, checkz, checkh, checkradius, ignorerestricted);
}
native bool Next();
}
@ -523,10 +523,10 @@ class BlockLinesIterator : Object native
native static BlockLinesIterator Create(Actor origin, double checkradius = -1);
native static BlockLinesIterator CreateFromPosition(LevelLocals Level, Vector3 pos, double checkh, double checkradius, Sector sec = null);
// Since this depends on the global level variable it should not be used any longer because this may block compatibility with future features.
// Since this has no good means to deduce the level from its parameters it should not be used any longer because this may block compatibility with future features.
deprecated("3.8") static BlockLinesIterator CreateFromPos(Vector3 pos, double checkh, double checkradius, Sector sec = null)
{
return CreateFromPosition(level, pos, checkh, checkradius, sec);
return CreateFromPosition(currentSession.LevelInfo[0], pos, checkh, checkradius, sec);
}
native bool Next();
}

View file

@ -99,15 +99,15 @@ struct Side native play
int GetUDMFInt(Name nm)
{
return Level.GetUDMFInt(LevelLocals.UDMF_Side, Index(), nm);
return sector.Level.GetUDMFInt(LevelLocals.UDMF_Side, Index(), nm);
}
double GetUDMFFloat(Name nm)
{
return Level.GetUDMFFloat(LevelLocals.UDMF_Side, Index(), nm);
return sector.Level.GetUDMFFloat(LevelLocals.UDMF_Side, Index(), nm);
}
String GetUDMFString(Name nm)
{
return Level.GetUDMFString(LevelLocals.UDMF_Side, Index(), nm);
return sector.Level.GetUDMFString(LevelLocals.UDMF_Side, Index(), nm);
}
};
@ -182,15 +182,15 @@ struct Line native play
int GetUDMFInt(Name nm)
{
return Level.GetUDMFInt(LevelLocals.UDMF_Line, Index(), nm);
return frontsector.Level.GetUDMFInt(LevelLocals.UDMF_Line, Index(), nm);
}
double GetUDMFFloat(Name nm)
{
return Level.GetUDMFFloat(LevelLocals.UDMF_Line, Index(), nm);
return frontsector.Level.GetUDMFFloat(LevelLocals.UDMF_Line, Index(), nm);
}
String GetUDMFString(Name nm)
{
return Level.GetUDMFString(LevelLocals.UDMF_Line, Index(), nm);
return frontsector.Level.GetUDMFString(LevelLocals.UDMF_Line, Index(), nm);
}
native clearscope int GetHealth();
@ -241,6 +241,7 @@ struct Sector native play
native readonly Color SpecialColors[5];
native readonly Color AdditiveColors[5];
native LevelLocals Level;
native Actor SoundTarget;
native int16 special;