- the next batch of 'level' removals.

Untested, may not work!
This commit is contained in:
Christoph Oelckers 2019-01-10 02:30:38 +01:00
parent 80427b72e9
commit 72d09c0338
20 changed files with 181 additions and 149 deletions

View file

@ -644,22 +644,26 @@ CUSTOM_CVAR (Int, am_showalllines, -1, 0) // This is a cheat so don't save it.
{
int flagged = 0;
int total = 0;
if (self > 0 && level.lines.Size() > 0)
{
for(auto &line : level.lines)
ForAllLevels([&](FLevelLocals *Level) {
for(auto &line : Level->lines)
{
// disregard intra-sector lines
if (line.frontsector == line.backsector) continue;
if (line.frontsector == line.backsector) continue;
// disregard control sectors for deep water
if (line.frontsector->e->FakeFloor.Sectors.Size() > 0) continue;
if (line.frontsector->e->FakeFloor.Sectors.Size() > 0) continue;
// disregard control sectors for 3D-floors
if (line.frontsector->e->XFloor.attached.Size() > 0) continue;
if (line.frontsector->e->XFloor.attached.Size() > 0) continue;
total++;
if (line.flags & ML_DONTDRAW) flagged++;
}
});
if (self > 0 && total > 0)
{
am_showallenabled = (flagged * 100 / total >= self);
}
else if (self == 0)
@ -1065,12 +1069,12 @@ bool AM_addMark ()
//
//=============================================================================
static void AM_findMinMaxBoundaries ()
static void AM_findMinMaxBoundaries (FLevelLocals *Level)
{
min_x = min_y = FLT_MAX;
max_x = max_y = FIXED_MIN;
for (auto &vert : level.vertexes)
for (auto &vert : Level->vertexes)
{
if (vert.fX() < min_x)
min_x = vert.fX();
@ -1363,20 +1367,20 @@ bool AM_clearMarks ()
//
//=============================================================================
void AM_LevelInit ()
void AM_LevelInit (FLevelLocals *Level)
{
if (level.info->MapBackground.Len() == 0)
if (Level->info->MapBackground.Len() == 0)
{
mapback = TexMan.CheckForTexture("AUTOPAGE", ETextureType::MiscPatch);
}
else
{
mapback = TexMan.CheckForTexture(level.info->MapBackground, ETextureType::MiscPatch);
mapback = TexMan.CheckForTexture(Level->info->MapBackground, ETextureType::MiscPatch);
}
AM_clearMarks();
AM_findMinMaxBoundaries();
AM_findMinMaxBoundaries(Level);
scale_mtof = min_scale_mtof / 0.7;
if (scale_mtof > max_scale_mtof)
scale_mtof = min_scale_mtof;
@ -1867,15 +1871,15 @@ inline void AM_drawMline (mline_t *ml, int colorindex)
//
//=============================================================================
void AM_drawGrid (int color)
void AM_drawGrid (FLevelLocals *Level, int color)
{
double x, y;
double start, end;
mline_t ml;
double minlen, extx, exty;
double minx, miny;
auto bmaporgx = level.blockmap.bmaporgx;
auto bmaporgy = level.blockmap.bmaporgy;
auto bmaporgx = Level->blockmap.bmaporgx;
auto bmaporgy = Level->blockmap.bmaporgy;
// [RH] Calculate a minimum for how long the grid lines should be so that
// they cover the screen at any rotation.
@ -2052,7 +2056,7 @@ sector_t * AM_FakeFlat(AActor *viewer, sector_t * sec, sector_t * dest)
//
//=============================================================================
void AM_drawSubsectors()
void AM_drawSubsectors(FLevelLocals *Level)
{
static TArray<FVector2> points;
std::vector<uint32_t> indices;
@ -2066,7 +2070,7 @@ void AM_drawSubsectors()
PalEntry flatcolor;
mpoint_t originpt;
auto &subsectors = level.subsectors;
auto &subsectors = Level->subsectors;
for (unsigned i = 0; i < subsectors.Size(); ++i)
{
auto sub = &subsectors[i];
@ -2206,7 +2210,7 @@ void AM_drawSubsectors()
colormap.Desaturation = 255 - (255 - colormap.Desaturation) / 4;
}
// make table based fog visible on the automap as well.
if (level.flags & LEVEL_HASFADETABLE)
if (Level->flags & LEVEL_HASFADETABLE)
{
colormap.FadeColor = PalEntry(0, 128, 128, 128);
}
@ -2243,7 +2247,7 @@ void AM_drawSubsectors()
colormap,
flatcolor,
floorlight,
level.lightMode,
Level->lightMode,
f_y + f_h,
indices.data(), indices.size());
}
@ -2303,7 +2307,7 @@ void AM_drawSeg(seg_t *seg, const AMColor &color)
AM_drawMline(&l, color);
}
void AM_drawPolySeg(FPolySeg *seg, const AMColor &color)
void AM_drawPolySeg(FLevelLocals *Level, FPolySeg *seg, const AMColor &color)
{
mline_t l;
l.a.x = seg->v1.pos.X;
@ -2319,22 +2323,22 @@ void AM_drawPolySeg(FPolySeg *seg, const AMColor &color)
AM_drawMline(&l, color);
}
void AM_showSS()
void AM_showSS(FLevelLocals *Level)
{
if (am_showsubsector >= 0 && (unsigned)am_showsubsector < level.subsectors.Size())
if (am_showsubsector >= 0 && (unsigned)am_showsubsector < Level->subsectors.Size())
{
AMColor yellow;
yellow.FromRGB(255,255,0);
AMColor red;
red.FromRGB(255,0,0);
subsector_t *sub = &level.subsectors[am_showsubsector];
subsector_t *sub = &Level->subsectors[am_showsubsector];
for (unsigned int i = 0; i < sub->numlines; i++)
{
AM_drawSeg(sub->firstline + i, yellow);
}
for (auto &poly : level.Polyobjects)
for (auto &poly : Level->Polyobjects)
{
FPolyNode *pnode = poly.subsectorlinks;
@ -2344,7 +2348,7 @@ void AM_showSS()
{
for (unsigned j = 0; j < pnode->segs.Size(); j++)
{
AM_drawPolySeg(&pnode->segs[j], red);
AM_drawPolySeg(Level, &pnode->segs[j], red);
}
}
pnode = pnode->snext;
@ -2572,19 +2576,19 @@ bool AM_isLockBoundary (line_t &line, int *lockptr = NULL)
//
//=============================================================================
void AM_drawWalls (bool allmap)
void AM_drawWalls (FLevelLocals *Level, bool allmap)
{
static mline_t l;
int lock, color;
int numportalgroups = am_portaloverlay ? level.Displacements.size : 0;
int numportalgroups = am_portaloverlay ? Level->Displacements.size : 0;
for (int p = numportalgroups - 1; p >= -1; p--)
{
if (p == MapPortalGroup) continue;
for (auto &line : level.lines)
for (auto &line : Level->lines)
{
int pg;
@ -2601,7 +2605,7 @@ void AM_drawWalls (bool allmap)
bool portalmode = numportalgroups > 0 && pg != MapPortalGroup;
if (pg == p)
{
offset = level.Displacements.getOffset(pg, MapPortalGroup);
offset = Level->Displacements.getOffset(pg, MapPortalGroup);
}
else if (p == -1 && (pg == MapPortalGroup || !am_portaloverlay))
{
@ -2979,14 +2983,14 @@ void AM_drawKeys ()
//
//
//=============================================================================
void AM_drawThings ()
void AM_drawThings (FLevelLocals *Level)
{
AMColor color;
AActor* t;
mpoint_t p;
DAngle angle;
for (auto &sec : level.sectors)
for (auto &sec : Level->sectors)
{
t = sec.thinglist;
while (t)
@ -3239,12 +3243,12 @@ void AM_drawCrosshair (const AMColor &color)
//
//=============================================================================
void AM_Drawer (int bottom)
void AM_Drawer (FLevelLocals *Level, int bottom)
{
if (!automapactive)
return;
bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0;
bool allmap = (Level->flags2 & LEVEL2_ALLMAP) != 0;
bool allthings = allmap && players[consoleplayer].mo->FindInventory(NAME_PowerScanner, true) != nullptr;
if (am_portaloverlay)
@ -3277,17 +3281,17 @@ void AM_Drawer (int bottom)
AM_activateNewScale();
if (am_textured && textured && !viewactive)
AM_drawSubsectors();
AM_drawSubsectors(Level);
if (grid)
AM_drawGrid(AMColors.GridColor);
AM_drawGrid(Level, AMColors.GridColor);
AM_drawWalls(allmap);
AM_drawWalls(Level, allmap);
AM_drawPlayers();
if (G_SkillProperty(SKILLP_EasyKey))
AM_drawKeys();
if ((am_cheat >= 2 && am_cheat != 4) || allthings)
AM_drawThings();
AM_drawThings(Level);
AM_drawAuthorMarkers();
@ -3296,7 +3300,7 @@ void AM_Drawer (int bottom)
AM_drawMarks();
AM_showSS();
AM_showSS(Level);
}
//=============================================================================

View file

@ -24,6 +24,7 @@
struct event_t;
class FSerializer;
struct FLevelLocals;
void AM_StaticInit();
@ -37,7 +38,7 @@ void AM_Ticker (void);
// Called by main loop,
// called instead of view drawer if automap active.
void AM_Drawer (int bottom);
void AM_Drawer (FLevelLocals *Level, int bottom);
// Called to force the automap to quit
// if the level is completed while it is up.
@ -45,7 +46,7 @@ void AM_Stop (void);
void AM_NewResolution ();
void AM_ToggleMap ();
void AM_LevelInit ();
void AM_LevelInit (FLevelLocals *Level);
void AM_SerializeMarkers(FSerializer &arc);

View file

@ -207,7 +207,7 @@ void FCajunMaster::End ()
{
int i;
//Arrange wanted botnum and their names, so they can be spawned next level.
//Arrange wanted botnum and their names, so they can be spawned next map.
getspawned.Clear();
if (deathmatch)
{

View file

@ -507,22 +507,22 @@ int ii_compatflags, ii_compatflags2, ib_compatflags;
EXTERN_CVAR(Int, compatmode)
static int GetCompatibility(int mask)
static int GetCompatibility(FLevelLocals *Level, int mask)
{
if (level.info == NULL) return mask;
else return (mask & ~level.info->compatmask) | (level.info->compatflags & level.info->compatmask);
if (Level->info == nullptr) return mask;
else return (mask & ~Level->info->compatmask) | (Level->info->compatflags & Level->info->compatmask);
}
static int GetCompatibility2(int mask)
static int GetCompatibility2(FLevelLocals *Level, int mask)
{
return (level.info == NULL) ? mask
: (mask & ~level.info->compatmask2) | (level.info->compatflags2 & level.info->compatmask2);
return (Level->info == nullptr) ? mask
: (mask & ~Level->info->compatmask2) | (Level->info->compatflags2 & Level->info->compatmask2);
}
CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
{
int old = i_compatflags;
i_compatflags = GetCompatibility(self) | ii_compatflags;
i_compatflags = GetCompatibility(&level, self) | ii_compatflags;
if ((old ^ i_compatflags) & COMPATF_POLYOBJ)
{
level.ClearAllSubsectorLinks();
@ -531,7 +531,7 @@ CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
CUSTOM_CVAR (Int, compatflags2, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
{
i_compatflags2 = GetCompatibility2(self) | ii_compatflags2;
i_compatflags2 = GetCompatibility2(&level, self) | ii_compatflags2;
}
CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
@ -746,19 +746,21 @@ void D_Display ()
//E_RenderFrame();
//
// Check for the presence of dynamic lights at the start of the frame once.
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4))
{
level.HasDynamicLights = !!level.lights;
}
else level.HasDynamicLights = false; // lights are off so effectively we have none.
ForAllLevels([](FLevelLocals *Level) {
// Check for the presence of dynamic lights at the start of the frame once.
if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4))
{
Level->HasDynamicLights = !!Level->lights;
}
else Level->HasDynamicLights = false; // lights are off so effectively we have none.
});
viewsec = screen->RenderView(&players[consoleplayer]);
screen->Begin2D();
screen->DrawBlend(viewsec);
if (automapactive)
{
AM_Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
AM_Drawer (&level, hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
}
// for timing the statusbar code.
@ -2580,7 +2582,9 @@ void D_DoomMain (void)
// [RH] Run any saved commands from the command line or autoexec.cfg now.
gamestate = GS_FULLCONSOLE;
Net_NewMakeTic ();
DThinker::RunThinkers ();
ForAllLevels([](FLevelLocals *Level) {
DThinker::RunThinkers (Level);
});
gamestate = GS_STARTUP;
if (!restart)

View file

@ -2341,7 +2341,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
{
if (spawned->CountsAsKill())
{
level.total_monsters--;
source->Level->total_monsters--;
}
spawned->FriendPlayer = player + 1;
spawned->flags |= MF_FRIENDLY;
@ -2702,7 +2702,7 @@ static void RunScript(uint8_t **stream, AActor *pawn, int snum, int argn, int al
arg[i] = argval;
}
}
P_StartScript(&level, pawn, NULL, snum, level.MapName, arg, MIN<int>(countof(arg), argn), ACS_NET | always);
P_StartScript(pawn->Level, pawn, NULL, snum, pawn->Level->MapName, arg, MIN<int>(countof(arg), argn), ACS_NET | always);
}
void Net_SkipCommand (int type, uint8_t **stream)

View file

@ -50,7 +50,9 @@ CVAR (Bool, alwaysapplydmflags, false, CVAR_SERVERINFO);
CUSTOM_CVAR (Float, teamdamage, 0.f, CVAR_SERVERINFO)
{
level.teamdamage = self;
ForAllLevels([&](FLevelLocals *Level) {
Level->teamdamage = self;
});
}
CUSTOM_CVAR (String, language, "auto", CVAR_ARCHIVE)

View file

@ -597,7 +597,7 @@ struct ProfileInfo
TMap<FName, ProfileInfo> Profiles;
void DThinker::RunThinkers ()
void DThinker::RunThinkers (FLevelLocals *Level)
{
int i, count;
@ -627,7 +627,7 @@ void DThinker::RunThinkers ()
}
} while (count != 0);
for (auto light = level.lights; light;)
for (auto light = Level->lights; light;)
{
auto next = light->next;
light->Tick();
@ -656,7 +656,7 @@ void DThinker::RunThinkers ()
// Also profile the internal dynamic lights, even though they are not implemented as thinkers.
auto &prof = Profiles[NAME_InternalDynamicLight];
prof.timer.Clock();
for (auto light = level.lights; light;)
for (auto light = Level->lights; light;)
{
prof.numcalls++;
auto next = light->next;

View file

@ -80,7 +80,7 @@ public:
void ChangeStatNum (int statnum);
static void RunThinkers ();
static void RunThinkers (FLevelLocals *Level);
static void RunThinkers (int statnum);
static void DestroyAllThinkers ();
static void DestroyThinkersInList(int statnum)

View file

@ -759,7 +759,7 @@ void G_AddViewPitch (int look, bool mouse)
return;
}
look = LookAdjust(look);
if (!level.IsFreelookAllowed())
if (!players[consoleplayer].mo->Level->IsFreelookAllowed())
{
LocalViewPitch = 0;
}
@ -1212,7 +1212,7 @@ void G_Ticker ()
//
// G_PlayerFinishLevel
// Called when a player completes a level.
// Called when a player completes a map.
//
// flags is checked for RESETINVENTORY and RESETHEALTH only.
@ -1325,7 +1325,7 @@ bool G_CheckSpot (FLevelLocals *Level, int playernum, FPlayerStart *mthing)
spot = mthing->pos;
if (!(level.flags & LEVEL_USEPLAYERSTARTZ))
if (!(Level->flags & LEVEL_USEPLAYERSTARTZ))
{
spot.Z = 0;
}
@ -1388,7 +1388,7 @@ static double PlayersRangeFromSpot (FPlayerStart *spot)
}
// [RH] Select the deathmatch spawn spot farthest from everyone.
static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections)
static FPlayerStart *SelectFarthestDeathmatchSpot (FLevelLocals *Level, size_t selections)
{
double bestdistance = 0;
FPlayerStart *bestspot = NULL;
@ -1396,12 +1396,12 @@ static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections)
for (i = 0; i < selections; i++)
{
double distance = PlayersRangeFromSpot (&level.deathmatchstarts[i]);
double distance = PlayersRangeFromSpot (&Level->deathmatchstarts[i]);
if (distance > bestdistance)
{
bestdistance = distance;
bestspot = &level.deathmatchstarts[i];
bestspot = &Level->deathmatchstarts[i];
}
}
@ -1416,7 +1416,7 @@ static FPlayerStart *SelectRandomDeathmatchSpot (FLevelLocals *Level, int player
for (j = 0; j < 20; j++)
{
i = pr_dmspawn() % selections;
if (G_CheckSpot (Level, playernum, &level.deathmatchstarts[i]) )
if (G_CheckSpot (Level, playernum, &Level->deathmatchstarts[i]) )
{
return &Level->deathmatchstarts[i];
}
@ -1471,7 +1471,7 @@ void G_DeathMatchSpawnPlayer (FLevelLocals *Level, int playernum)
// so we always use the random deathmatch spawn. During the game,
// though, we use whatever dmflags specifies.
if ((dmflags & DF_SPAWN_FARTHEST) && players[playernum].mo)
spot = SelectFarthestDeathmatchSpot (selections);
spot = SelectFarthestDeathmatchSpot (Level, selections);
else
spot = SelectRandomDeathmatchSpot (Level, playernum, selections);
@ -1479,14 +1479,14 @@ void G_DeathMatchSpawnPlayer (FLevelLocals *Level, int playernum)
{ // No good spot, so the player will probably get stuck.
// We were probably using select farthest above, and all
// the spots were taken.
spot = G_PickPlayerStart(playernum, PPS_FORCERANDOM);
if (!G_CheckSpot(&level, playernum, spot))
spot = G_PickPlayerStart(Level, playernum, PPS_FORCERANDOM);
if (!G_CheckSpot(Level, playernum, spot))
{ // This map doesn't have enough coop spots for this player
// to use one.
spot = SelectRandomDeathmatchSpot(Level, playernum, selections);
if (spot == NULL)
{ // We have a player 1 start, right?
spot = &level.playerstarts[0];
spot = &Level->playerstarts[0];
if (spot->type == 0)
{ // Fine, whatever.
spot = &Level->deathmatchstarts[0];
@ -1502,15 +1502,15 @@ void G_DeathMatchSpawnPlayer (FLevelLocals *Level, int playernum)
//
// G_PickPlayerStart
//
FPlayerStart *G_PickPlayerStart(int playernum, int flags)
FPlayerStart *G_PickPlayerStart(FLevelLocals *Level, int playernum, int flags)
{
if (level.AllPlayerStarts.Size() == 0) // No starts to pick
{
return NULL;
}
if ((level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) ||
level.playerstarts[playernum].type == 0)
if ((Level->flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) ||
Level->playerstarts[playernum].type == 0)
{
if (!(flags & PPS_NOBLOCKINGCHECK))
{
@ -1518,9 +1518,9 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags)
unsigned int i;
// Find all unblocked player starts.
for (i = 0; i < level.AllPlayerStarts.Size(); ++i)
for (i = 0; i < Level->AllPlayerStarts.Size(); ++i)
{
if (G_CheckSpot(&level, playernum, &level.AllPlayerStarts[i]))
if (G_CheckSpot(Level, playernum, &Level->AllPlayerStarts[i]))
{
good_starts.Push(&level.AllPlayerStarts[i]);
}
@ -1531,7 +1531,7 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags)
}
}
// Pick a spot at random, whether it's open or not.
return &level.AllPlayerStarts[pr_pspawn(level.AllPlayerStarts.Size())];
return &Level->AllPlayerStarts[pr_pspawn(Level->AllPlayerStarts.Size())];
}
return &level.playerstarts[playernum];
}
@ -1541,7 +1541,7 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart)
PARAM_PROLOGUE;
PARAM_INT(playernum);
PARAM_INT(flags);
auto ps = G_PickPlayerStart(playernum, flags);
auto ps = G_PickPlayerStart(&level, playernum, flags);
if (numret > 1)
{
ret[1].SetInt(ps? ps->angle : 0);
@ -1559,15 +1559,16 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart)
//
static void G_QueueBody (AActor *body)
{
auto Level = body->Level;
// flush an old corpse if needed
int modslot = level.bodyqueslot%level.BODYQUESIZE;
level.bodyqueslot = modslot + 1;
int modslot = level.bodyqueslot % FLevelLocals::BODYQUESIZE;
Level->bodyqueslot = modslot + 1;
if (level.bodyqueslot >= level.BODYQUESIZE && level.bodyque[modslot] != NULL)
if (Level->bodyqueslot >= FLevelLocals::BODYQUESIZE && Level->bodyque[modslot] != NULL)
{
level.bodyque[modslot]->Destroy ();
Level->bodyque[modslot]->Destroy ();
}
level.bodyque[modslot] = body;
Level->bodyque[modslot] = body;
// Copy the player's translation, so that if they change their color later, only
// their current body will change and not all their old corpses.
@ -1599,7 +1600,8 @@ static void G_QueueBody (AActor *body)
EXTERN_CVAR(Bool, sv_singleplayerrespawn)
void G_DoReborn (int playernum, bool freshbot)
{
if (!multiplayer && !(level.flags2 & LEVEL2_ALLOWRESPAWN) && !sv_singleplayerrespawn &&
auto Level = &level;
if (!multiplayer && !(Level->flags2 & LEVEL2_ALLOWRESPAWN) && !sv_singleplayerrespawn &&
!G_SkillProperty(SKILLP_PlayerRespawn))
{
if (BackupSaveName.Len() > 0 && FileExists (BackupSaveName.GetChars()))
@ -1611,7 +1613,7 @@ void G_DoReborn (int playernum, bool freshbot)
{ // Reload the level from scratch
bool indemo = demoplayback;
BackupSaveName = "";
G_InitNew (level.MapName, false);
G_InitNew (Level->MapName, false);
demoplayback = indemo;
// gameaction = ga_loadlevel;
}
@ -1629,23 +1631,23 @@ void G_DoReborn (int playernum, bool freshbot)
}
// spawn at random spot if in deathmatch
if ((deathmatch || isUnfriendly) && (level.deathmatchstarts.Size () > 0))
if ((deathmatch || isUnfriendly) && (Level->deathmatchstarts.Size () > 0))
{
G_DeathMatchSpawnPlayer (&level, playernum);
G_DeathMatchSpawnPlayer (Level, playernum);
return;
}
if (!(level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) &&
level.playerstarts[playernum].type != 0 &&
G_CheckSpot (&level, playernum, &level.playerstarts[playernum]))
if (!(Level->flags2 & LEVEL2_RANDOMPLAYERSTARTS) &&
Level->playerstarts[playernum].type != 0 &&
G_CheckSpot (Level, playernum, &Level->playerstarts[playernum]))
{
AActor *mo = P_SpawnPlayer(&level, &level.playerstarts[playernum], playernum);
AActor *mo = P_SpawnPlayer(Level, &Level->playerstarts[playernum], playernum);
if (mo != NULL) P_PlayerStartStomp(mo, true);
}
else
{ // try to spawn at any random player's spot
FPlayerStart *start = G_PickPlayerStart(playernum, PPS_FORCERANDOM);
AActor *mo = P_SpawnPlayer(&level, start, playernum);
FPlayerStart *start = G_PickPlayerStart(Level, playernum, PPS_FORCERANDOM);
AActor *mo = P_SpawnPlayer(Level, start, playernum);
if (mo != NULL) P_PlayerStartStomp(mo, true);
}
}
@ -2048,13 +2050,15 @@ static void PutSaveWads (FSerializer &arc)
// Name of IWAD
name = Wads.GetWadName (Wads.GetIwadNum());
arc.AddString("Game WAD", name);
// Name of wad the map resides in
if (Wads.GetLumpFile (level.lumpnum) > Wads.GetIwadNum())
{
name = Wads.GetWadName (Wads.GetLumpFile (level.lumpnum));
arc.AddString("Map WAD", name);
}
ForAllLevels([&](FLevelLocals *Level) {
// Name of wad the map resides in
if (Wads.GetLumpFile (Level->lumpnum) > Wads.GetIwadNum())
{
name = Wads.GetWadName (Wads.GetLumpFile (Level->lumpnum));
arc.AddString(FStringf("Map WAD %s", Level->MapName.GetChars()), name);
}
});
}
static void PutSaveComment (FSerializer &arc)
@ -2069,10 +2073,12 @@ static void PutSaveComment (FSerializer &arc)
comment.Format("%.10s%.5s%.9s", readableTime, &readableTime[19], &readableTime[10]);
arc.AddString("Creation Time", comment);
// Get level name
//strcpy (comment, level.level_name);
comment.Format("%s - %s\n", level.MapName.GetChars(), level.LevelName.GetChars());
comment = "";
ForAllLevels([&](FLevelLocals *Level) {
// Get level name
comment.AppendFormat("%s - %s\n", Level->MapName.GetChars(), Level->LevelName.GetChars());
});
// Append elapsed time
levelTime = level.time / TICRATE;
@ -2101,13 +2107,17 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
TArray<FString> savegame_filenames;
char buf[100];
// Do not even try, if we're not in a level. (Can happen after
// a demo finishes playback.)
if (level.lines.Size() == 0 || level.sectors.Size() == 0 || gamestate != GS_LEVEL)
{
return;
}
bool checkok = gamestate != GS_LEVEL;
ForAllLevels([&](FLevelLocals *Level) {
// Do not even try, if we're not in a map. (Can happen after a demo finishes playback.)
if (Level->lines.Size() == 0 || level.sectors.Size() == 0)
{
checkok = false;
}
});
if (demoplayback)
{
@ -2155,15 +2165,24 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
// put some basic info into the PNG so that this isn't lost when the image gets extracted.
M_AppendPNGText(&savepic, "Software", buf);
M_AppendPNGText(&savepic, "Title", description);
M_AppendPNGText(&savepic, "Current Map", level.MapName);
ForAllLevels([&](FLevelLocals *Level) {
M_AppendPNGText(&savepic, "Current Map", Level->MapName);
});
M_FinishPNG(&savepic);
int ver = SAVEVER;
savegameinfo.AddString("Software", buf)
.AddString("Engine", GAMESIG)
("Save Version", ver)
.AddString("Title", description)
.AddString("Current Map", level.MapName);
.AddString("Title", description);
if (savegameinfo.BeginArray("Current Maps"))
{
ForAllLevels([&](FLevelLocals *Level) {
savegameinfo.AddString(nullptr, Level->MapName);
});
}
PutSaveWads (savegameinfo);
@ -2848,17 +2867,18 @@ bool G_CheckDemoStatus (void)
return false;
}
void G_StartSlideshow(FName whichone)
void G_StartSlideshow(FLevelLocals *Level, int _whichone)
{
FName whichone = ENamedName(_whichone);
gameaction = ga_slideshow;
SelectedSlideshow = whichone == NAME_None ? level.info->slideshow : whichone;
SelectedSlideshow = whichone == NAME_None ? Level->info->slideshow : whichone;
}
DEFINE_ACTION_FUNCTION(FLevelLocals, StartSlideshow)
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, StartSlideshow, G_StartSlideshow)
{
PARAM_PROLOGUE;
PARAM_NAME(whichone);
G_StartSlideshow(whichone);
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_INT(whichone);
G_StartSlideshow(self, whichone);
return 0;
}

View file

@ -41,7 +41,7 @@ struct FLevelLocals;
//
void G_DeathMatchSpawnPlayer (FLevelLocals *Level, int playernum);
struct FPlayerStart *G_PickPlayerStart (int playernum, int flags = 0);
struct FPlayerStart *G_PickPlayerStart (FLevelLocals *Level, int playernum, int flags = 0);
enum
{
PPS_FORCERANDOM = 1,
@ -74,7 +74,7 @@ void G_Ticker (void);
bool G_Responder (event_t* ev);
void G_ScreenShot (char *filename);
void G_StartSlideshow(FName whichone);
void G_StartSlideshow(FLevelLocals *level, int whichone);
FString G_BuildSaveName (const char *prefix, int slot);

View file

@ -1039,7 +1039,7 @@ void G_DoLoadLevel (int position, bool autosave, bool newGame)
P_SetupLevel (&level, level.MapName, position, newGame);
AM_LevelInit();
AM_LevelInit(&level);
// [RH] Start lightning, if MAPINFO tells us to
if (level.flags & LEVEL_STARTLIGHTNING)
@ -1370,7 +1370,7 @@ int G_FinishTravel ()
pawndup = pawn->player->mo;
assert (pawn != pawndup);
start = G_PickPlayerStart(pnum, 0);
start = G_PickPlayerStart(&level, pnum, 0);
if (start == NULL)
{
if (pawndup != nullptr)

View file

@ -48,7 +48,7 @@ DLightningThinker::DLightningThinker ()
LightningFlashCount = 0;
NextLightningFlash = ((pr_lightning()&15)+5)*35; // don't flash at level start
LightningLightLevels.Resize(level.sectors.Size());
LightningLightLevels.Resize(Level->sectors.Size());
fillshort(&LightningLightLevels[0], LightningLightLevels.Size(), SHRT_MAX);
}

View file

@ -6657,7 +6657,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
return ScriptCall(activator, argCount, args);
case ACSF_StartSlideshow:
G_StartSlideshow(FName(Level->Behaviors.LookupString(args[0])));
G_StartSlideshow(Level, FName(Level->Behaviors.LookupString(args[0])).GetIndex());
break;
case ACSF_GetSectorHealth:

View file

@ -167,12 +167,12 @@ void P_ClearParticles (FLevelLocals *Level)
void P_FindParticleSubsectors (FLevelLocals *Level)
{
if (Level->ParticlesInSubsec.Size() < level.subsectors.Size())
if (Level->ParticlesInSubsec.Size() < Level->subsectors.Size())
{
Level->ParticlesInSubsec.Reserve (level.subsectors.Size() - Level->ParticlesInSubsec.Size());
Level->ParticlesInSubsec.Reserve (Level->subsectors.Size() - Level->ParticlesInSubsec.Size());
}
fillshort (&Level->ParticlesInSubsec[0], level.subsectors.Size(), NO_PARTICLE);
fillshort (&Level->ParticlesInSubsec[0], Level->subsectors.Size(), NO_PARTICLE);
if (!r_particles)
{
@ -236,7 +236,7 @@ void P_ThinkParticles (FLevelLocals *Level)
{
particle = &Level->Particles[i];
i = particle->tnext;
if (!particle->notimefreeze && ((level.freeze) || (level.flags2 & LEVEL2_FROZEN)))
if (!particle->notimefreeze && ((Level->freeze) || (Level->flags2 & LEVEL2_FROZEN)))
{
prev = particle;
continue;
@ -323,7 +323,7 @@ void P_RunEffects (FLevelLocals *Level)
{
if (players[consoleplayer].camera == NULL) return;
int pnum = players[consoleplayer].camera->Sector->Index() * level.sectors.Size();
int pnum = players[consoleplayer].camera->Sector->Index() * Level->sectors.Size();
AActor *actor;
TThinkerIterator<AActor> iterator;
@ -372,7 +372,7 @@ static void MakeFountain (AActor *actor, int color1, int color2)
{
particle_t *particle;
if (!(level.time & 1))
if (!(actor->Level->maptime & 1))
return;
particle = JitterParticle (actor->Level, 51);

View file

@ -1962,8 +1962,8 @@ subsector_t *P_PointInSubsector(FLevelLocals *Level, double x, double y)
sector_t *P_PointInSectorBuggy(FLevelLocals *Level, double x, double y)
{
// single subsector is a special case
auto node = level.HeadGamenode();
if (node == nullptr) return level.subsectors[0].sector;
auto node = Level->HeadGamenode();
if (node == nullptr) return Level->subsectors[0].sector;
do
{
// Use original buggy point-on-side test when spawning

View file

@ -274,8 +274,8 @@ void FLevelLocals::ClearLevelData()
DialogueRoots.Clear();
ClassRoots.Clear();
level.interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
level.ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
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.
@ -457,7 +457,7 @@ void P_SetupLevel(FLevelLocals *Level, const char *lumpname, int position, bool
if (playeringame[i])
{
players[i].mo = nullptr;
FPlayerStart *mthing = G_PickPlayerStart(i);
FPlayerStart *mthing = G_PickPlayerStart(Level, i);
P_SpawnPlayer(Level, mthing, i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
}
}

View file

@ -79,6 +79,7 @@ class FSectorTagIterator
protected:
int searchtag;
int start;
FLevelLocals *Level;
FTagManager &tagManager;
FSectorTagIterator(FTagManager &manager) : tagManager(manager)

View file

@ -149,7 +149,7 @@ void P_Ticker (void)
memset(&Level->Scrolls[0], 0, sizeof(Level->Scrolls[0]) * Level->Scrolls.Size());
}
DThinker::RunThinkers();
DThinker::RunThinkers(Level);
//if added by MC: Freeze mode.
if (!Level->freeze && !(Level->flags2 & LEVEL2_FROZEN))

View file

@ -519,7 +519,7 @@ void R_InterpolateView (FRenderViewpoint &viewpoint, player_t *player, double Fr
}
else
{
DVector2 disp = level.Displacements.getOffset(oldgroup, newgroup);
DVector2 disp = Level->Displacements.getOffset(oldgroup, newgroup);
viewpoint.Pos = iview->Old.Pos + (iview->New.Pos - iview->Old.Pos - disp) * Frac;
viewpoint.Path[0] = viewpoint.Path[1] = iview->New.Pos;
}
@ -1033,7 +1033,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor
// However, to set up a projection matrix this needs to be adjusted.
double radPitch = viewpoint.Angles.Pitch.Normalized180().Radians();
double angx = cos(radPitch);
double angy = sin(radPitch) * level.info->pixelstretch;
double angy = sin(radPitch) * actor->Level->info->pixelstretch;
double alen = sqrt(angx*angx + angy*angy);
viewpoint.HWAngles.Pitch = RAD2DEG((float)asin(angy / alen));

View file

@ -698,7 +698,7 @@ struct LevelLocals native
native double GetUDMFFloat(int type, int index, Name key);
native bool ExecuteSpecial(int special, Actor activator, line linedef, bool lineside, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0);
native void GiveSecret(Actor activator, bool printmsg = true, bool playsound = true);
native static void StartSlideshow(Name whichone = 'none');
native void StartSlideshow(Name whichone = 'none');
native static void WorldDone();
native static void RemoveAllBots(bool fromlist);
native static Vector2 GetAutomapPosition();