- 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])) if (playeringame[i] && self <= D_GetFragCount(&players[i]))
{ {
Printf ("%s\n", GStrings("TXT_FRAGLIMIT")); Printf ("%s\n", GStrings("TXT_FRAGLIMIT"));
G_ExitLevel (0, false); G_ExitLevel (currentSession->Levelinfo[0], 0, false);
break; 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? // That was a long time ago. Maybe it works now?
if (currentSession) if (currentSession)
{ {
currentSession->Levelinfo[0]->flags |= LEVEL_CHANGEMAPCHEAT; auto Level = currentSession->Levelinfo[0];
G_ChangeLevel(s, pos, 0); Level->flags |= LEVEL_CHANGEMAPCHEAT;
G_ChangeLevel(Level, s, pos, 0);
} }
break; break;
@ -2667,7 +2668,11 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
case DEM_FINISHGAME: case DEM_FINISHGAME:
// Simulate an end-of-game action // 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; break;
case DEM_NETEVENT: case DEM_NETEVENT:

View file

@ -229,7 +229,7 @@ void DThinker::SerializeThinkers(FSerializer &arc, bool hubLoad)
void DThinker::Serialize(FSerializer &arc) void DThinker::Serialize(FSerializer &arc)
{ {
Super::Serialize(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; NextThinker = NULL;
PrevThinker = NULL; PrevThinker = NULL;
Level = &level; // do this properly later. Level = bSerialOverride? nullptr : currentSession->Levelinfo[0]; // do this properly later.
if (bSerialOverride) if (bSerialOverride)
{ // The serializer will insert us into the right list { // The serializer will insert us into the right list
return; 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]; char nextmap[9];
int NextSkill = -1; int NextSkill = -1;
@ -108,7 +108,7 @@ void FS_MapCmd(FScanner &sc)
flags &= ~(CHANGELEVEL_RESETINVENTORY|CHANGELEVEL_RESETHEALTH); 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")) else if (sc.Compare("map"))
{ {
FS_MapCmd(sc); FS_MapCmd(Level, sc);
} }
else if (sc.Compare("gr_fogdensity")) else if (sc.Compare("gr_fogdensity"))
{ {
@ -177,7 +177,7 @@ void FS_EmulateCmd(FLevelLocals *Level, char * string)
Level->fogdensity = sc.Number * 70 / 400; Level->fogdensity = sc.Number * 70 / 400;
Level->outsidefogdensity = 0; Level->outsidefogdensity = 0;
Level->skyfog = 0; Level->skyfog = 0;
Level->info->outsidefog = 0; Level->outsidefog = 0;
} }
else if (sc.Compare("gr_fogcolor")) else if (sc.Compare("gr_fogcolor"))
{ {

View file

@ -635,7 +635,7 @@ void FParser::SF_Clock(void)
void FParser::SF_ExitLevel(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) 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.MustGetStringName("=");
sc.MustGetString(); sc.MustGetString();
Level->info->ExitPic = sc.String; const_cast<level_info_t*>(Level->info)->ExitPic = sc.String;
} }
else if (sc.Compare("gravity")) 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. // don't save a reference to the global script, which contains unserializable data.
if (parent == Level->FraggleScriptThinker->GlobalScript) parent = nullptr; 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) arc("data", data)
("scriptnum", scriptnum) ("scriptnum", scriptnum)

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -47,6 +47,7 @@
#include "p_tags.h" #include "p_tags.h"
#include "p_effect.h" #include "p_effect.h"
#include "p_destructible.h" #include "p_destructible.h"
#include "p_conversation.h"
#include "r_data/r_interpolate.h" #include "r_data/r_interpolate.h"
#include "r_data/r_sections.h" #include "r_data/r_sections.h"
#include "r_data/r_canvastexture.h" #include "r_data/r_canvastexture.h"
@ -88,7 +89,7 @@ struct FLevelData
FDisplacementTable Displacements; FDisplacementTable Displacements;
FPortalBlockmap PortalBlockmap; FPortalBlockmap PortalBlockmap;
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups. 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; TArray<FLinePortalSpan> linePortalSpans;
FSectionContainer sections; FSectionContainer sections;
FCanvasTextureInfo canvasTextureInfo; FCanvasTextureInfo canvasTextureInfo;
@ -112,7 +113,7 @@ struct FLevelData
FBehaviorContainer Behaviors; FBehaviorContainer Behaviors;
TArray<FStrifeDialogueNode *> StrifeDialogues; TDeletingArray<FStrifeDialogueNode *> StrifeDialogues;
FDialogueIDMap DialogueRoots; FDialogueIDMap DialogueRoots;
FDialogueMap ClassRoots; FDialogueMap ClassRoots;
@ -129,7 +130,16 @@ struct FLevelData
struct FLevelLocals : public 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() : tagManager(this) {}
~FLevelLocals();
void Tick(); void Tick();
void Mark(); void Mark();
@ -137,13 +147,12 @@ struct FLevelLocals : public FLevelData
void SetInterMusic(const char *nextmap); void SetInterMusic(const char *nextmap);
void SetMusic(); void SetMusic();
void ClearLevelData(); void ClearLevelData();
void ClearPortals();
bool CheckIfExitIsGood(AActor *self, level_info_t *newmap); bool CheckIfExitIsGood(AActor *self, level_info_t *newmap);
void FormatMapName(FString &mapname, const char *mapnamecolor); void FormatMapName(FString &mapname, const char *mapnamecolor);
void TranslateTeleportThings(void); void TranslateTeleportThings(void);
void ClearAllSubsectorLinks(); void ClearAllSubsectorLinks();
void ChangeAirControl(double newval); void ChangeAirControl(double newval);
void InitLevelLocals(); void InitLevelLocals(const level_info_t *info, bool isprimary);
bool IsTIDUsed(int tid); bool IsTIDUsed(int tid);
int FindUniqueTID(int start_tid, int limit); int FindUniqueTID(int start_tid, int limit);
int GetConversation(int conv_id); int GetConversation(int conv_id);
@ -175,7 +184,7 @@ struct FLevelLocals : public FLevelData
int sucktime; int sucktime;
uint32_t spawnindex; uint32_t spawnindex;
level_info_t *info; const level_info_t * info; // The info is supposed to be immutable.
int cluster; int cluster;
int clusterflags; int clusterflags;
int levelnum; 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 // Returns true if level is loaded from saved game or is being revisited as a part of a hub
bool IsReentering() const bool IsReentering() const
{ {
return savegamerestore // 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.
|| (info != nullptr && info->Snapshot.mBuffer != nullptr && info->isValid()); return maptime > 0;
} }
}; };
@ -309,21 +318,39 @@ class FGameSession
{ {
public: public:
TArray<FLevelLocals *> Levelinfo; TArray<FLevelLocals *> Levelinfo;
TMap<FName, FCompressedBuffer> Snapshots;
TMap<FName, TArray<acsdefered_t>> DeferredScripts;
TMap<FName, bool> Visited;
FString F1Pic; FString F1Pic;
float MusicVolume; float MusicVolume;
int time; // time in the hub int time; // time in the hub
int totaltime; // time in the game 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 SetMusicVolume(float vol);
void Reset();
bool isValid();
FString LookupLevelName ();
void ClearDefered()
{
DeferredScripts.Clear();
}
void ClearSnapshots()
{
Snapshots.Clear();
}
}; };
extern FGameSession *currentSession; extern FGameSession *currentSession;
#ifndef NO_DEFINE_LEVEL
extern FLevelLocals level;
inline FSectorPortal *line_t::GetTransferredPortal() inline FSectorPortal *line_t::GetTransferredPortal()
{ {
auto Level = GetLevel(); auto Level = GetLevel();
@ -430,5 +457,3 @@ inline void ForAllLevels(T func)
for (auto Level : currentSession->Levelinfo) func(Level); for (auto Level : currentSession->Levelinfo) func(Level);
} }
} }
#endif

View file

@ -184,37 +184,6 @@ cluster_info_t *FindClusterInfo (int cluster)
return &TheDefaultClusterInfo; 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; WallVertLight = +8;
F1Pic = ""; F1Pic = "";
musicorder = 0; musicorder = 0;
Snapshot = { 0,0,0,0,0,nullptr };
deferred.Clear();
skyspeed1 = skyspeed2 = 0.f; skyspeed1 = skyspeed2 = 0.f;
fadeto = 0; fadeto = 0;
outsidefog = 0xff000000; 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) 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) 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; return MapName.Len() != 0 || this == &TheDefaultLevelInfo;
} }
@ -2284,7 +2251,6 @@ static void ClearMapinfo()
AllSkills.Clear(); AllSkills.Clear();
DefaultSkill = -1; DefaultSkill = -1;
DeinitIntermissions(); DeinitIntermissions();
level.info = NULL;
currentSession->F1Pic = ""; currentSession->F1Pic = "";
} }

View file

@ -46,7 +46,7 @@ protected:
TArray<float> mLights; TArray<float> mLights;
// Used to detect when a level change requires the AABB tree to be regenerated // 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 mLastNumNodes = 0;
unsigned mLastNumSegs = 0; unsigned mLastNumSegs = 0;

View file

@ -200,7 +200,7 @@ float HWDrawInfo::GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfog
density = 0; 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 // case 3. outsidefogdensity has already been set as needed
density = (float)Level->outsidefogdensity; density = (float)Level->outsidefogdensity;
@ -248,7 +248,7 @@ bool HWDrawInfo::CheckFog(sector_t *frontsector, sector_t *backsector)
else if (fogcolor.a != 0) 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) 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) 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; return false;
} }

View file

@ -1988,11 +1988,7 @@ bool FBehaviorContainer::CheckAllGood ()
void FBehaviorContainer::UnloadModules () void FBehaviorContainer::UnloadModules ()
{ {
for (unsigned int i = StaticModules.Size(); i-- > 0; ) StaticModules.DeleteAndClear ();
{
delete StaticModules[i];
}
StaticModules.Clear ();
} }
FBehavior *FBehaviorContainer::GetModule (int lib) FBehavior *FBehaviorContainer::GetModule (int lib)
@ -3447,8 +3443,7 @@ void DLevelScript::Serialize(FSerializer &arc)
uint32_t pcofs; uint32_t pcofs;
uint16_t lib; uint16_t lib;
// This cannot be serialized yet. if(arc.isReading()) Level = arc.Level;
if(arc.isReading()) Level = &level;
if (arc.isWriting()) if (arc.isWriting())
{ {
@ -9928,7 +9923,7 @@ scriptwait:
case PCD_CHANGELEVEL: 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; sp -= 4;
} }
break; break;
@ -10321,70 +10316,73 @@ void P_DoDeferedScripts (FLevelLocals *Level)
FBehavior *module; FBehavior *module;
// Handle defered scripts in this step, too // 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]; for(int i = deferred->Size()-1; i>=0; i--)
switch (def->type)
{ {
case acsdefered_t::defexecute: acsdefered_t *def = &(*deferred)[i];
case acsdefered_t::defexealways: switch (def->type)
scriptdata = Level->Behaviors.FindScript (def->script, module);
if (scriptdata)
{ {
P_GetScriptGoing (Level, (unsigned)def->playernum < MAXPLAYERS && case acsdefered_t::defexecute:
playeringame[def->playernum] ? players[def->playernum].mo : NULL, case acsdefered_t::defexealways:
NULL, def->script, scriptdata = Level->Behaviors.FindScript (def->script, module);
scriptdata, module, if (scriptdata)
def->args, 3, {
def->type == acsdefered_t::defexealways ? ACS_ALWAYS : 0); 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)]; def.args[j] = args[j];
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());
} }
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) EXTERN_CVAR (Bool, sv_cheats)
@ -10436,9 +10434,7 @@ int P_StartScript (FLevelLocals *Level, AActor *who, line_t *where, int script,
} }
else else
{ {
addDefered (FindLevelInfo (map), addDefered (Level, (flags & ACS_ALWAYS) ? acsdefered_t::defexealways : acsdefered_t::defexecute, script, args, argcount, who);
(flags & ACS_ALWAYS) ? acsdefered_t::defexealways : acsdefered_t::defexecute,
script, args, argcount, who);
return true; return true;
} }
return false; 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) void P_SuspendScript (FLevelLocals *Level, int script, const char *map)
{ {
if (strnicmp (Level->MapName, map, 8)) 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 else
SetScriptState (Level->ACSThinker, script, DLevelScript::SCRIPT_Suspended); 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) void P_TerminateScript (FLevelLocals *Level, int script, const char *map)
{ {
if (strnicmp (Level->MapName, map, 8)) 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 else
SetScriptState (Level->ACSThinker, script, DLevelScript::SCRIPT_PleaseRemove); SetScriptState (Level->ACSThinker, script, DLevelScript::SCRIPT_PleaseRemove);
} }

View file

@ -428,7 +428,7 @@ private:
struct FBehaviorContainer struct FBehaviorContainer
{ {
TArray<FBehavior *> StaticModules; TDeletingArray<FBehavior *> StaticModules;
FBehavior *LoadModule(FLevelLocals *Level, int lumpnum, FileReader *fr = nullptr, int len = 0); FBehavior *LoadModule(FLevelLocals *Level, int lumpnum, FileReader *fr = nullptr, int len = 0);
void LoadDefaultModules(FLevelLocals *Level); 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)) if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT))
return; 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)) fraglimit <= D_GetFragCount (source->player))
{ {
Printf ("%s\n", GStrings("TXT_FRAGLIMIT")); 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) FUNC(LS_Exit_Normal)
// Exit_Normal (position) // 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 true;
} }
return false; return false;
@ -1072,9 +1072,9 @@ FUNC(LS_Exit_Normal)
FUNC(LS_Exit_Secret) FUNC(LS_Exit_Secret)
// Exit_Secret (position) // 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 true;
} }
return false; return false;
@ -1089,7 +1089,7 @@ FUNC(LS_Teleport_NewMap)
if (info && Level->CheckIfExitIsGood (it, info)) 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; return true;
} }
} }
@ -1182,9 +1182,9 @@ FUNC(LS_TeleportInSector)
FUNC(LS_Teleport_EndGame) FUNC(LS_Teleport_EndGame)
// 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 true;
} }
return false; return false;

View file

@ -939,6 +939,7 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
("skytexture2", Level->skytexture2) ("skytexture2", Level->skytexture2)
("fogdensity", Level->fogdensity) ("fogdensity", Level->fogdensity)
("outsidefogdensity", Level->outsidefogdensity) ("outsidefogdensity", Level->outsidefogdensity)
("outsidefog", Level->outsidefog)
("skyfog", Level->skyfog) ("skyfog", Level->skyfog)
("deathsequence", Level->deathsequence) ("deathsequence", Level->deathsequence)
("bodyqueslot", Level->bodyqueslot) ("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 // [ZZ] delete per-map event handlers
E_Shutdown(true); E_Shutdown(true);
R_FreePastViewers(); 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 (!(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))) 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) if (sector->Flags & SECF_DMGTERRAINFX)
{ {
@ -683,7 +683,7 @@ void P_UpdateSpecials (FLevelLocals *Level)
if (Level->maptime >= (int)(timelimit * TICRATE * 60)) if (Level->maptime >= (int)(timelimit * TICRATE * 60))
{ {
Printf ("%s\n", GStrings("TXT_TIMELIMIT")); 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 && players[consoleplayer].viewz != NO_VALUE
&& wipegamestate == gamestate) && 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 true;
} }
return false; return false;

View file

@ -1116,7 +1116,7 @@ void P_CheckMusicChange(player_t *player)
if (player->MUSINFOactor->args[0] != 0) if (player->MUSINFOactor->args[0] != 0)
{ {
auto Level = player->mo->Level; 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) if (music != NULL)
{ {

View file

@ -100,7 +100,7 @@ struct FPortalBlock
struct FPortalBlockmap struct FPortalBlockmap
{ {
TArray<FPortalBlock> data; TArray<FPortalBlock> data;
int dx, dy; int dx = 0, dy = 0;
bool containsLines; bool containsLines;
bool hasLinkedSectorPortals; // global flag to shortcut portal checks if the map has none. 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. 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; didInterp = false;
count = 0; count = 0;
} }
~FInterpolator()
{
ClearInterpolations();
}
void UpdateInterpolations(); void UpdateInterpolations();
void AddInterpolation(DInterpolation *); void AddInterpolation(DInterpolation *);
void RemoveInterpolation(DInterpolation *); void RemoveInterpolation(DInterpolation *);

View file

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

View file

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

View file

@ -218,7 +218,7 @@ void S_Shutdown ();
void S_Start (FLevelLocals *Level); void S_Start (FLevelLocals *Level);
// Called after a level is loaded. Ensures that most sounds are loaded. // 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. // Loads a sound, including any random sounds it might reference.
void S_CacheSound (sfxinfo_t *sfx); 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, sectors)
DEFINE_FIELD(FLevelLocals, lines) DEFINE_FIELD(FLevelLocals, lines)
DEFINE_FIELD(FLevelLocals, sides) DEFINE_FIELD(FLevelLocals, sides)
@ -2770,6 +2769,7 @@ DEFINE_FIELD(FGameSession, time)
DEFINE_FIELD(FGameSession, totaltime) DEFINE_FIELD(FGameSession, totaltime)
DEFINE_GLOBAL(currentSession) DEFINE_GLOBAL(currentSession)
DEFINE_FIELD_X(Sector, sector_t, Level)
DEFINE_FIELD_X(Sector, sector_t, floorplane) DEFINE_FIELD_X(Sector, sector_t, floorplane)
DEFINE_FIELD_X(Sector, sector_t, ceilingplane) DEFINE_FIELD_X(Sector, sector_t, ceilingplane)
DEFINE_FIELD_X(Sector, sector_t, Colormap) 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. // record the current level's stats.
StoreLevelStats(Level); StoreLevelStats(Level);
level_info_t *thisinfo = Level->info; const level_info_t *thisinfo = Level->info;
level_info_t *nextinfo = NULL; level_info_t *nextinfo = NULL;
if (strncmp(newl, "enDSeQ", 6)) 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) switch (a->type & ANIM_CONDITION)
{ {
case ANIM_IFVISITED: case ANIM_IFVISITED:
li = FindLevelInfo(a->LevelName); if (!currentSession->Visited.CheckKey(a->LevelName)) continue;
if (li == NULL || !(li->flags & LEVEL_VISITED)) continue;
break; break;
case ANIM_IFNOTVISITED: case ANIM_IFNOTVISITED:
li = FindLevelInfo(a->LevelName); if (currentSession->Visited.CheckKey(a->LevelName)) continue;
if (li == NULL || (li->flags & LEVEL_VISITED)) continue;
break; break;
// StatCount means 'leaving' - everything else means 'entering'! // 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++) for (i = 0; i<lnodes.Size(); i++)
{ {
level_info_t * li = FindLevelInfo(lnodes[i].Level); if (currentSession->Visited.CheckKey(lnodes[i].Level)) drawOnLnode(i, &splat, 1); // draw a splat on taken cities.
if (li && li->flags & LEVEL_VISITED) 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 readonly Array<@Team> Teams;
native int validcount; native int validcount;
native readonly bool multiplayer; native readonly bool multiplayer;
native play @LevelLocals level; //native play @LevelLocals level;
native @KeyBindings Bindings; native @KeyBindings Bindings;
native @KeyBindings AutomapBindings; native @KeyBindings AutomapBindings;
native play @DehInfo deh; 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 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); 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) 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(); native bool Next();
} }
@ -523,10 +523,10 @@ class BlockLinesIterator : Object native
native static BlockLinesIterator Create(Actor origin, double checkradius = -1); native static BlockLinesIterator Create(Actor origin, double checkradius = -1);
native static BlockLinesIterator CreateFromPosition(LevelLocals Level, Vector3 pos, double checkh, double checkradius, Sector sec = null); 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) 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(); native bool Next();
} }

View file

@ -99,15 +99,15 @@ struct Side native play
int GetUDMFInt(Name nm) 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) 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) 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) 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) 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) 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(); native clearscope int GetHealth();
@ -241,6 +241,7 @@ struct Sector native play
native readonly Color SpecialColors[5]; native readonly Color SpecialColors[5];
native readonly Color AdditiveColors[5]; native readonly Color AdditiveColors[5];
native LevelLocals Level;
native Actor SoundTarget; native Actor SoundTarget;
native int16 special; native int16 special;