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