Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Support >60Hz with com_gameHz #584

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions neo/d3xp/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ void idCameraAnim::Think( void ) {
return;
}

if ( frameRate == USERCMD_HZ ) {
if ( frameRate == gameLocal.gameFps ) {
frameTime = gameLocal.time - starttime;
frame = frameTime / gameLocal.msec;
} else {
Expand Down Expand Up @@ -568,7 +568,7 @@ void idCameraAnim::GetViewParms( renderView_t *view ) {
SetTimeState ts( timeGroup );
#endif

if ( frameRate == USERCMD_HZ ) {
if ( frameRate == gameLocal.gameFps ) {
frameTime = gameLocal.time - starttime;
frame = frameTime / gameLocal.msec;
lerp = 0.0f;
Expand Down
57 changes: 38 additions & 19 deletions neo/d3xp/Game_local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ void idGameLocal::Clear( void ) {
framenum = 0;
previousTime = 0;
time = 0;
preciseTime = 0.0f;
vacuumAreaNum = 0;
mapFileName.Clear();
mapFile = NULL;
Expand Down Expand Up @@ -323,6 +324,10 @@ void idGameLocal::Init( void ) {
const idDict *dict;
idAAS *aas;

msec = 16.0; //60fps
gameMsec = msec;
gameFps = 60; //60fps

#ifndef GAME_DLL

TestGameAPI();
Expand All @@ -340,6 +345,12 @@ void idGameLocal::Init( void ) {

#endif

//Update MSEC and gameFps
gameFps = cvarSystem->GetCVarInteger("com_gameHz");
msec = 1000.0f / cvarSystem->GetCVarFloat("com_gameHz");
msec *= 0.96f; // HACK to emulate OG D3 msec error, in order to have exactly the same game logic speed
gameMsec = msec;

Printf( "----- Initializing Game -----\n" );
Printf( "gamename: %s\n", GAME_VERSION );
Printf( "gamedate: %s\n", ID__DATE__ );
Expand Down Expand Up @@ -621,12 +632,14 @@ void idGameLocal::SaveGame( idFile *f ) {
savegame.WriteBool( isMultiplayer );
savegame.WriteInt( gameType );

savegame.WriteFloat(preciseTime); // DG: added in internalSavegameVersion 2

savegame.WriteInt( framenum );
savegame.WriteInt( previousTime );
savegame.WriteInt( time );

#ifdef _D3XP
savegame.WriteInt( msec );
savegame.WriteFloat( msec );
#endif

savegame.WriteInt( vacuumAreaNum );
Expand Down Expand Up @@ -1027,6 +1040,7 @@ void idGameLocal::LoadMap( const char *mapName, int randseed ) {

previousTime = 0;
time = 0;
preciseTime = 0.0f;
framenum = 0;
sessionCommand = "";
nextGibTime = 0;
Expand Down Expand Up @@ -1386,7 +1400,7 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo
savegame.ReadBuildNumber();

// DG: I enhanced the information in savegames a bit for dhewm3 1.5.1
// for which I bumped th BUILD_NUMBER to 1305
// for which I bumped the BUILD_NUMBER to 1305
if( savegame.GetBuildNumber() >= 1305 )
{
savegame.ReadInternalSavegameVersion();
Expand Down Expand Up @@ -1530,12 +1544,16 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo
savegame.ReadBool( isMultiplayer );
savegame.ReadInt( (int &)gameType );

if ( savegame.GetInternalSavegameVersion() >= 2 ) {
savegame.ReadFloat( preciseTime );
}

savegame.ReadInt( framenum );
savegame.ReadInt( previousTime );
savegame.ReadInt( time );

#ifdef _D3XP
savegame.ReadInt( msec );
savegame.ReadFloat( msec );
#endif

savegame.ReadInt( vacuumAreaNum );
Expand Down Expand Up @@ -1577,7 +1595,7 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo
}
}
if ( gameSoundWorld ) {
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / (float)USERCMD_MSEC );
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / (float)gameMsec );
}
#endif

Expand Down Expand Up @@ -2488,7 +2506,8 @@ gameReturn_t idGameLocal::RunFrame(const usercmd_t* clientCmds) {
// update the game time
framenum++;
previousTime = time;
time += msec;
preciseTime += msec;
time = (int)idMath::Rint(preciseTime);
realClientTime = time;

#ifdef _D3XP
Expand Down Expand Up @@ -3869,7 +3888,7 @@ idGameLocal::AlertAI
void idGameLocal::AlertAI( idEntity *ent ) {
if ( ent && ent->IsType( idActor::Type ) ) {
// alert them for the next frame
lastAIAlertTime = time + msec;
lastAIAlertTime = time + (int)idMath::Rint(msec);
lastAIAlertEntity = static_cast<idActor *>( ent );
}
}
Expand Down Expand Up @@ -4282,7 +4301,7 @@ void idGameLocal::SetCamera( idCamera *cam ) {

} else {
inCinematic = false;
cinematicStopTime = time + msec;
cinematicStopTime = time + idMath::Rint(msec);

// restore r_znear
cvarSystem->SetCVarFloat( "r_znear", 3.0f );
Expand Down Expand Up @@ -4878,7 +4897,7 @@ void idGameLocal::ComputeSlowMsec() {

// stop the state
slowmoState = SLOWMO_STATE_OFF;
slowmoMsec = USERCMD_MSEC;
slowmoMsec = gameMsec;
}

// check the player state
Expand All @@ -4899,7 +4918,7 @@ void idGameLocal::ComputeSlowMsec() {
slowmoMsec = msec;
if ( gameSoundWorld ) {
gameSoundWorld->SetSlowmo( true );
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / (float)USERCMD_MSEC );
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / gameMsec );
}
}
else if ( !powerupOn && slowmoState == SLOWMO_STATE_ON ) {
Expand All @@ -4913,25 +4932,25 @@ void idGameLocal::ComputeSlowMsec() {

// do any necessary ramping
if ( slowmoState == SLOWMO_STATE_RAMPUP ) {
delta = 4 - slowmoMsec;
delta = 4.0 * 60.0 / (float)gameFps - slowmoMsec;

if ( fabs( delta ) < g_slowmoStepRate.GetFloat() ) {
slowmoMsec = 4;
slowmoMsec = 4.0 * 60.0 / (float)gameFps;
slowmoState = SLOWMO_STATE_ON;
}
else {
slowmoMsec += delta * g_slowmoStepRate.GetFloat();
}

if ( gameSoundWorld ) {
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / (float)USERCMD_MSEC );
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / gameMsec );
}
}
else if ( slowmoState == SLOWMO_STATE_RAMPDOWN ) {
delta = 16 - slowmoMsec;
delta = 16.0 * 60.0 / gameFps - slowmoMsec;

if ( fabs( delta ) < g_slowmoStepRate.GetFloat() ) {
slowmoMsec = 16;
slowmoMsec = 16.0*60.0/(float)gameFps;
slowmoState = SLOWMO_STATE_OFF;
if ( gameSoundWorld ) {
gameSoundWorld->SetSlowmo( false );
Expand All @@ -4942,7 +4961,7 @@ void idGameLocal::ComputeSlowMsec() {
}

if ( gameSoundWorld ) {
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / (float)USERCMD_MSEC );
gameSoundWorld->SetSlowmoSpeed( slowmoMsec / gameMsec );
}
}
}
Expand All @@ -4953,19 +4972,19 @@ idGameLocal::ResetSlowTimeVars
============
*/
void idGameLocal::ResetSlowTimeVars() {
msec = USERCMD_MSEC;
slowmoMsec = USERCMD_MSEC;
msec = gameMsec;
slowmoMsec = gameMsec;
slowmoState = SLOWMO_STATE_OFF;

fast.framenum = 0;
fast.previousTime = 0;
fast.time = 0;
fast.msec = USERCMD_MSEC;
fast.msec = gameMsec;

slow.framenum = 0;
slow.previousTime = 0;
slow.time = 0;
slow.msec = USERCMD_MSEC;
slow.msec = gameMsec;
}

/*
Expand Down
19 changes: 11 additions & 8 deletions neo/d3xp/Game_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,14 @@ class idEntityPtr {
struct timeState_t {
int time;
int previousTime;
int msec;
float msec;
int framenum;
int realClientTime;

void Set( int t, int pt, int ms, int f, int rct ) { time = t; previousTime = pt; msec = ms; framenum = f; realClientTime = rct; };
void Get( int& t, int& pt, int& ms, int& f, int& rct ) { t = time; pt = previousTime; ms = msec; f = framenum; rct = realClientTime; };
void Save( idSaveGame *savefile ) const { savefile->WriteInt( time ); savefile->WriteInt( previousTime ); savefile->WriteInt( msec ); savefile->WriteInt( framenum ); savefile->WriteInt( realClientTime ); }
void Restore( idRestoreGame *savefile ) { savefile->ReadInt( time ); savefile->ReadInt( previousTime ); savefile->ReadInt( msec ); savefile->ReadInt( framenum ); savefile->ReadInt( realClientTime ); }
void Set( int t, int pt, float ms, int f, int rct ) { time = t; previousTime = pt; msec = ms; framenum = f; realClientTime = rct; };
void Get( int& t, int& pt, float& ms, int& f, int& rct ) { t = time; pt = previousTime; ms = msec; f = framenum; rct = realClientTime; };
void Save( idSaveGame *savefile ) const { savefile->WriteInt( time ); savefile->WriteInt( previousTime ); savefile->WriteFloat( msec ); savefile->WriteInt( framenum ); savefile->WriteInt( realClientTime ); }
void Restore( idRestoreGame *savefile ) { savefile->ReadInt( time ); savefile->ReadInt( previousTime ); savefile->ReadFloat( msec ); savefile->ReadInt( framenum ); savefile->ReadInt( realClientTime ); }
void Increment() { framenum++; previousTime = time; time += msec; realClientTime = time; };
};

Expand Down Expand Up @@ -298,7 +298,10 @@ class idGameLocal : public idGame {
int framenum;
int previousTime; // time in msec of last frame
int time; // in msec
int msec; // time since last update in milliseconds
float msec; // time since last update in milliseconds
float preciseTime; // added by Stradex for cm_gameHz fidelity
int gameFps; //added by Stradex for com_gameHz
float gameMsec; //added by Stradex for com_gameHz (ROE)

int vacuumAreaNum; // -1 if level doesn't have any outside areas

Expand Down Expand Up @@ -483,7 +486,7 @@ class idGameLocal : public idGame {
// added the following to assist licensees with merge issues
int GetFrameNum() const { return framenum; };
int GetTime() const { return time; };
int GetMSec() const { return msec; };
int GetMSec() const { return (int)idMath::Rint(msec); };

int GetNextClientNum( int current ) const;
idPlayer * GetClientByNum( int current ) const;
Expand Down Expand Up @@ -512,7 +515,7 @@ class idGameLocal : public idGame {

private:
const static int INITIAL_SPAWN_COUNT = 1;
const static int INTERNAL_SAVEGAME_VERSION = 1; // DG: added this for >= 1305 savegames
const static int INTERNAL_SAVEGAME_VERSION = 2; // DG: added this for >= 1305 savegames

idStr mapFileName; // name of the map, empty string if no map loaded
idMapFile * mapFile; // will be NULL during the game unless in-game editing is used
Expand Down
5 changes: 3 additions & 2 deletions neo/d3xp/Game_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ void idGameLocal::ClientReadSnapshot( int clientNum, int sequence, const int gam
// update the game time
framenum = gameFrame;
time = gameTime;
previousTime = time - msec;
previousTime = time - idMath::Rint(msec);

// so that StartSound/StopSound doesn't risk skipping
isNewFrame = true;
Expand Down Expand Up @@ -1532,7 +1532,8 @@ gameReturn_t idGameLocal::ClientPrediction( int clientNum, const usercmd_t *clie
// update the game time
framenum++;
previousTime = time;
time += msec;
preciseTime += msec;
time = (int)idMath::Rint(preciseTime);

// update the real client time and the new frame flag
if ( time > realClientTime ) {
Expand Down
4 changes: 2 additions & 2 deletions neo/d3xp/Moveable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,14 @@ bool idMoveable::FollowInitialSplinePath( void ) {
if ( initialSpline != NULL ) {
if ( gameLocal.time < initialSpline->GetTime( initialSpline->GetNumValues() - 1 ) ) {
idVec3 splinePos = initialSpline->GetCurrentValue( gameLocal.time );
idVec3 linearVelocity = ( splinePos - physicsObj.GetOrigin() ) * USERCMD_HZ;
idVec3 linearVelocity = ( splinePos - physicsObj.GetOrigin() ) * gameLocal.gameFps;
physicsObj.SetLinearVelocity( linearVelocity );

idVec3 splineDir = initialSpline->GetCurrentFirstDerivative( gameLocal.time );
idVec3 dir = initialSplineDir * physicsObj.GetAxis();
idVec3 angularVelocity = dir.Cross( splineDir );
angularVelocity.Normalize();
angularVelocity *= idMath::ACos16( dir * splineDir / splineDir.Length() ) * USERCMD_HZ;
angularVelocity *= idMath::ACos16( dir * splineDir / splineDir.Length() ) * gameLocal.gameFps;
physicsObj.SetAngularVelocity( angularVelocity );
return true;
} else {
Expand Down
4 changes: 2 additions & 2 deletions neo/d3xp/Mover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2838,9 +2838,9 @@ void idMover_Binary::Use_BinaryMover( idEntity *activator ) {
activatedBy = activator;

if ( moverState == MOVER_POS1 ) {
// FIXME: start moving USERCMD_MSEC later, because if this was player
// FIXME: start moving gameLocal.msec later, because if this was player
// triggered, gameLocal.time hasn't been advanced yet
MatchActivateTeam( MOVER_1TO2, gameLocal.slow.time + USERCMD_MSEC );
MatchActivateTeam( MOVER_1TO2, gameLocal.slow.time + gameLocal.gameMsec );

SetGuiStates( guiBinaryMoverStates[MOVER_1TO2] );
// open areaportal
Expand Down
Loading