- sanitized the 'frozen level' code.

This had two different flags that were checked totally inconsistently, and one was not even saved.
Moved everything into a few subfunctions so that these checks do not have to be scattered all over the code.
This commit is contained in:
Christoph Oelckers 2019-01-28 20:15:48 +01:00
parent 3721771934
commit 259ae41774
25 changed files with 124 additions and 65 deletions

View File

@ -1425,6 +1425,7 @@ public:
void DeleteAttachedLights();
static void DeleteAllAttachedLights();
static void RecreateAllAttachedLights();
bool isFrozen();
bool hasmodel;
};

View File

@ -107,7 +107,7 @@ inline DVector3 AActor::Vec2OffsetZ(double dx, double dy, double atz, bool absol
{
return{ X() + dx, Y() + dy, atz };
}
else
else
{
DVector2 v = Level->GetPortalOffsetPosition(X(), Y(), dx, dy);
return DVector3(v, atz);
@ -133,7 +133,7 @@ inline DVector3 AActor::Vec3Offset(double dx, double dy, double dz, bool absolut
return { X() + dx, Y() + dy, Z() + dz };
}
else
{
{
DVector2 v = Level->GetPortalOffsetPosition(X(), Y(), dx, dy);
return DVector3(v, Z() + dz);
}
@ -151,8 +151,30 @@ inline DVector3 AActor::Vec3Angle(double length, DAngle angle, double dz, bool a
return{ X() + length * angle.Cos(), Y() + length * angle.Sin(), Z() + dz };
}
else
{
{
DVector2 v = Level->GetPortalOffsetPosition(X(), Y(), length*angle.Cos(), length*angle.Sin());
return DVector3(v, Z() + dz);
}
}
inline bool AActor::isFrozen()
{
if (!(flags5 & MF5_NOTIMEFREEZE))
{
auto state = Level->isFrozen();
if (state)
{
if (player == nullptr || player->Bot != nullptr) return true;
// This is the only place in the entire game where the two freeze flags need different treatment.
// The time freezer flag also freezes other players, the global setting does not.
if ((state & 1) && player->timefreezer == 0)
{
return true;
}
}
}
return false;
}

View File

@ -49,6 +49,7 @@
#include "d_player.h"
#include "w_wad.h"
#include "vm.h"
#include "g_levellocals.h"
IMPLEMENT_CLASS(DBot, false, true)
@ -137,7 +138,7 @@ void DBot::Tick ()
{
Super::Tick ();
if (player->mo == nullptr || bglobal.freeze)
if (player->mo == nullptr || Level->isFrozen())
{
return;
}

View File

@ -116,7 +116,7 @@ public:
void ClearPlayer (int playernum, bool keepTeam);
//(b_game.cpp)
void Main ();
void Main (FLevelLocals *Level);
void Init ();
void End();
bool SpawnBot (const char *name, int color = NOCOLOR);

View File

@ -129,7 +129,7 @@ FCajunMaster::~FCajunMaster()
}
//This function is called every tick (from g_game.c).
void FCajunMaster::Main ()
void FCajunMaster::Main(FLevelLocals *Level)
{
BotThinkCycles.Reset();
@ -137,7 +137,7 @@ void FCajunMaster::Main ()
return;
//Add new bots?
if (wanted_botnum > botnum && !freeze)
if (wanted_botnum > botnum && !Level->isFrozen())
{
if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY))
{

View File

@ -1184,7 +1184,7 @@ void DDecalFader::Tick ()
}
else
{
if (Level->maptime < TimeToStartDecay || bglobal.freeze)
if (Level->maptime < TimeToStartDecay || Level->isFrozen())
{
return;
}
@ -1271,7 +1271,7 @@ void DDecalStretcher::Tick ()
Destroy ();
return;
}
if (Level->maptime < TimeToStart || bglobal.freeze)
if (Level->maptime < TimeToStart || Level->isFrozen())
{
return;
}
@ -1339,7 +1339,7 @@ void DDecalSlider::Tick ()
Destroy ();
return;
}
if (Level->maptime < TimeToStart || bglobal.freeze)
if (Level->maptime < TimeToStart || Level->isFrozen())
{
return;
}
@ -1407,7 +1407,7 @@ void DDecalColorer::Tick ()
}
else
{
if (Level->maptime < TimeToStartDecay || bglobal.freeze)
if (Level->maptime < TimeToStartDecay || Level->isFrozen())
{
return;
}

View File

@ -1112,7 +1112,7 @@ void G_Ticker ()
uint32_t rngsum = FRandom::StaticSumSeeds ();
//Added by MC: For some of that bot stuff. The main bot function.
bglobal.Main ();
bglobal.Main (&level);
for (i = 0; i < MAXPLAYERS; i++)
{

View File

@ -369,6 +369,11 @@ public:
return it.Next();
}
int isFrozen()
{
return frozenstate;
}
sector_t *PointInSector(const DVector2 &pos)
{
return P_PointInSector(pos);
@ -497,6 +502,7 @@ public:
bool FromSnapshot; // The current map was restored from a snapshot
bool HasHeightSecs; // true if some Transfer_Heights effects are present in the map. If this is false, some checks in the renderer can be shortcut.
bool HasDynamicLights; // Another render optimization for maps with no lights at all.
uint8_t frozenstate;
double teamdamage;

View File

@ -1198,7 +1198,7 @@ void GLSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *
const auto &vp = di->Viewpoint;
double timefrac = vp.TicFrac;
if (paused || bglobal.freeze || (di->Level->flags2 & LEVEL2_FROZEN))
if (paused || di->Level->isFrozen())
timefrac = 0.;
float xvf = (particle->Vel.X) * timefrac;
float yvf = (particle->Vel.Y) * timefrac;

View File

@ -243,7 +243,7 @@ void P_ThinkParticles ()
{
particle = &Particles[i];
i = particle->tnext;
if (!particle->notimefreeze && ((bglobal.freeze) || (level.flags2 & LEVEL2_FROZEN)))
if (!particle->notimefreeze && level.isFrozen())
{
prev = particle;
continue;

View File

@ -3505,18 +3505,15 @@ void AActor::Tick ()
// apply velocity
// ensure that the actor is not linked into the blockmap
if (!(flags5 & MF5_NOTIMEFREEZE))
//Added by MC: Freeze mode.
if (isFrozen())
{
//Added by MC: Freeze mode.
if (bglobal.freeze || Level->flags2 & LEVEL2_FROZEN)
// Boss cubes shouldn't be accelerated by timefreeze
if (flags6 & MF6_BOSSCUBE)
{
// Boss cubes shouldn't be accelerated by timefreeze
if (flags6 & MF6_BOSSCUBE)
{
special2++;
}
return;
special2++;
}
return;
}
if (!Vel.isZero() || !(flags & MF_NOBLOCKMAP))
@ -3555,27 +3552,16 @@ void AActor::Tick ()
return;
}
if (!(flags5 & MF5_NOTIMEFREEZE))
if (isFrozen())
{
// Boss cubes shouldn't be accelerated by timefreeze
if (flags6 & MF6_BOSSCUBE)
{
special2++;
}
//Added by MC: Freeze mode.
if (bglobal.freeze && !(player && player->Bot == NULL))
{
return;
}
// Apply freeze mode.
if ((Level->flags2 & LEVEL2_FROZEN) && (player == NULL || player->timefreezer == 0))
{
return;
}
return;
}
if (effects & FX_ROCKET)
{
if (++smokecounter == 4)

View File

@ -965,7 +965,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
("impactdecalcount", ImpactDecalCount)
("scrolls", Scrolls)
("automap", automap)
("interpolator", interpolator);
("interpolator", interpolator)
("frozenstate", frozenstate);
// Hub transitions must keep the current total time
@ -978,6 +979,7 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
sky2texture = skytexture2;
R_InitSkyMap();
AirControlChanged();
bglobal.freeze = !!(frozenstate & 2);
}
Behaviors.SerializeModuleStates(arc);

View File

@ -99,6 +99,7 @@ void P_Ticker (void)
{
if (bglobal.changefreeze)
{
level.frozenstate ^= 2;
bglobal.freeze ^= 1;
bglobal.changefreeze = 0;
}
@ -134,8 +135,7 @@ void P_Ticker (void)
P_ThinkParticles(); // [RH] make the particles think
for (i = 0; i<MAXPLAYERS; i++)
if (playeringame[i] &&
/*Added by MC: Freeze mode.*/!(bglobal.freeze && players[i].Bot != NULL))
if (playeringame[i])
P_PlayerThink (&players[i]);
// [ZZ] call the WorldTick hook
@ -145,13 +145,13 @@ void P_Ticker (void)
DThinker::RunThinkers ();
//if added by MC: Freeze mode.
if (!bglobal.freeze && !(level.flags2 & LEVEL2_FROZEN))
if (!level.isFrozen())
{
P_UpdateSpecials (&level);
P_RunEffects (); // [RH] Run particle effects
}
// for par times
// for par times
level.time++;
level.maptime++;
level.totaltime++;

View File

@ -1219,6 +1219,12 @@ void P_PlayerThink (player_t *player)
I_Error ("No player %td start\n", player - players + 1);
}
// Bots do not think in freeze mode.
if (player->mo->Level->isFrozen() && player->Bot != nullptr)
{
return;
}
if (debugfile && !(player->cheats & CF_PREDICTING))
{
fprintf (debugfile, "tic %d for pl %d: (%f, %f, %f, %f) b:%02x p:%d y:%d f:%d s:%d u:%d\n",
@ -1682,7 +1688,7 @@ bool P_IsPlayerTotallyFrozen(const player_t *player)
return
gamestate == GS_TITLELEVEL ||
player->cheats & CF_TOTALLYFROZEN ||
((player->mo->Level->flags2 & LEVEL2_FROZEN) && player->timefreezer == 0);
player->mo->isFrozen();
}

View File

@ -35,7 +35,7 @@ EXTERN_CVAR(Int, gl_particles_style)
void RenderPolyParticle::Render(PolyRenderThread *thread, particle_t *particle, subsector_t *sub, uint32_t stencilValue)
{
double timefrac = r_viewpoint.TicFrac;
if (paused || bglobal.freeze || (PolyRenderer::Instance()->Level->flags2 & LEVEL2_FROZEN))
if (paused || r_viewpoint.ViewLevel->isFrozen())
timefrac = 0.;
DVector3 pos = particle->Pos + (particle->Vel * timefrac);
double psize = particle->size / 8.0;

View File

@ -229,7 +229,7 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf, const FStat
// [BB] To interpolate at more than 35 fps we take tic fractions into account.
float ticFraction = 0.;
// [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN))
if (ConsoleState == c_up && menuactive != MENU_On && !level.isFrozen())
{
ticFraction = I_GetTimeFrac();
}

View File

@ -2682,7 +2682,32 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, Vec3Offset, Vec3Offset)
ACTION_RETURN_VEC3(result);
}
static int isFrozen(FLevelLocals *self)
{
return self->isFrozen();
}
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, isFrozen, isFrozen)
{
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
return isFrozen(self);
}
void setFrozen(FLevelLocals *self, int on)
{
self->frozenstate = (self->frozenstate & ~1) | !!on;
// For compatibility. The engine itself never checks this.
if (on) self->flags2 |= LEVEL2_FROZEN;
else self->flags2 &= ~LEVEL2_FROZEN;
}
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, setFrozen, setFrozen)
{
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_BOOL(on);
setFrozen(self, on);
return 0;
}
//=====================================================================================
//
@ -2764,6 +2789,7 @@ DEFINE_FIELD(FLevelLocals, outsidefogdensity)
DEFINE_FIELD(FLevelLocals, skyfog)
DEFINE_FIELD(FLevelLocals, pixelstretch)
DEFINE_FIELD(FLevelLocals, deathsequence)
DEFINE_FIELD_BIT(FLevelLocals, flags, noinventorybar, LEVEL_NOINVENTORYBAR)
DEFINE_FIELD_BIT(FLevelLocals, flags, monsterstelefrag, LEVEL_MONSTERSTELEFRAG)
DEFINE_FIELD_BIT(FLevelLocals, flags, actownspecial, LEVEL_ACTOWNSPECIAL)

View File

@ -1654,6 +1654,18 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFor3DCeilingHit, CheckFor3DCeilingHit
static int isFrozen(AActor *self)
{
return self->isFrozen();
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, isFrozen, isFrozen)
{
PARAM_SELF_PROLOGUE(AActor);
ACTION_RETURN_BOOL(isFrozen(self));
}
//===========================================================================
//
// PlayerPawn functions

View File

@ -79,7 +79,7 @@ namespace swrenderer
sector_t* heightsec = NULL;
double timefrac = r_viewpoint.TicFrac;
if (paused || bglobal.freeze || (sector->Level->flags2 & LEVEL2_FROZEN))
if (paused || r_viewpoint.ViewLevel->isFrozen())
timefrac = 0.;
double ippx = particle->Pos.X + particle->Vel.X * timefrac;

View File

@ -448,6 +448,7 @@ class Actor : Thinker native
return sin(fb * (180./32)) * 8;
}
native bool isFrozen();
virtual native void BeginPlay();
virtual native void Activate(Actor activator);
virtual native void Deactivate(Actor activator);

View File

@ -20,7 +20,6 @@ struct _ native // These are the global variables, the struct is only here to av
native play uint gameaction;
native readonly int gamestate;
native readonly TextureID skyflatnum;
native readonly uint8 globalfreeze;
native readonly int consoleplayer;
native readonly Font smallfont;
native readonly Font smallfont2;
@ -46,6 +45,7 @@ struct _ native // These are the global variables, the struct is only here to av
native readonly Weapon WP_NOCHANGE;
native int LocalViewPitch;
native ui readonly LevelLocals currentUILevel;
deprecated("3.8") native readonly bool globalfreeze;
}
@ -635,9 +635,9 @@ struct LevelLocals native
native readonly Array<@Vertex> Vertexes;
native internal Array<@SectorPortal> SectorPortals;
deprecated("3.8") native readonly int time;
native readonly int time;
native readonly int maptime;
deprecated("3.8") native readonly int totaltime;
native readonly int totaltime;
native readonly int starttime;
native readonly int partime;
native readonly int sucktime;
@ -648,10 +648,10 @@ struct LevelLocals native
native readonly String MapName;
native String NextMap;
native String NextSecretMap;
deprecated("3.8") native readonly String F1Pic;
native readonly String F1Pic;
native readonly int maptype;
deprecated("3.8") native readonly String Music;
deprecated("3.8") native readonly int musicorder;
native readonly String Music;
native readonly int musicorder;
native readonly TextureID skytexture1;
native readonly TextureID skytexture2;
native float skyspeed1;
@ -678,7 +678,7 @@ struct LevelLocals native
native readonly bool polygrind;
native readonly bool nomonsters;
native readonly bool allowrespawn;
native bool frozen;
deprecated("3.8") native bool frozen;
native readonly bool infinite_flight;
native readonly bool no_dlg_freeze;
native readonly bool keepfullinventory;
@ -711,6 +711,8 @@ struct LevelLocals native
native void ReplaceTextures(String from, String to, int flags);
native vector3, int PickDeathmatchStart();
native vector3, int PickPlayerStart(int pnum, int flags = 0);
native int isFrozen();
native void setFrozen(bool on);
native static clearscope bool IsPointInMap(vector3 p);

View File

@ -1531,7 +1531,7 @@ class PowerTimeFreezer : Powerup
// Make sure the effect starts and ends on an even tic.
if ((Level.maptime & 1) == 0)
{
level.frozen = true;;
Level.SetFrozen(true);
}
else
{
@ -1560,7 +1560,7 @@ class PowerTimeFreezer : Powerup
// [RH] The "blinking" can't check against EffectTics exactly or it will
// never happen, because InitEffect ensures that EffectTics will always
// be odd when Level.maptime is even.
Level.frozen = ( EffectTics > 4*32
Level.SetFrozen ( EffectTics > 4*32
|| (( EffectTics > 3*32 && EffectTics <= 4*32 ) && ((EffectTics + 1) & 15) != 0 )
|| (( EffectTics > 2*32 && EffectTics <= 3*32 ) && ((EffectTics + 1) & 7) != 0 )
|| (( EffectTics > 32 && EffectTics <= 2*32 ) && ((EffectTics + 1) & 3) != 0 )
@ -1598,7 +1598,7 @@ class PowerTimeFreezer : Powerup
}
// No, so allow other actors to move about freely once again.
level.frozen = false;
Level.SetFrozen(false);
// Also, turn the music back on.
S_ResumeSound(false);

View File

@ -50,14 +50,8 @@ class FastProjectile : Actor
ClearInterpolation();
double oldz = pos.Z;
if (!bNoTimeFreeze)
{
//Added by MC: Freeze mode.
if (globalfreeze || level.Frozen)
{
return;
}
}
if (isFrozen())
return;
// [RH] Ripping is a little different than it was in Hexen
FCheckPosition tm;

View File

@ -2765,7 +2765,7 @@ struct PlayerInfo native play // self is what internally is known as player_t
return
gamestate == GS_TITLELEVEL ||
(cheats & CF_TOTALLYFROZEN) ||
(mo && mo.Level.frozen && timefreezer == 0);
mo.isFrozen();
}
void Uncrouch()

View File

@ -210,7 +210,7 @@ extend class PlayerPawn
{ // You can't use items if you're totally frozen
return false;
}
if ((level.FROZEN) && (player == NULL || player.timefreezer == 0))
if (isFrozen())
{
// Time frozen
return false;