Skip to content

Commit

Permalink
Fix oxygen consumption code (idPlayer::airTics) for > 60Hz
Browse files Browse the repository at this point in the history
it already mostly worked, but picking up oxygen bottles gave too little
oxygen at >60fps and changing com_gameHz while being "outside" would
screw up the remaining oxygen and the implementation was needlessly
invasive anyway.
I reverted most changes, turned idPlayer::airTics into a float (so they
are now virtual 60Hz tics instead of actual number of tics) and adjusted
the code that increases or decreases the airTics (idPlayer::UpdateAir())
to scale the values added/subtracted accordingly.
Apart from that it's only a few changes to accomodate the fact that
it's a float now.
  • Loading branch information
DanielGibson committed Dec 28, 2024
1 parent 025386f commit 5a2113e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 40 deletions.
40 changes: 19 additions & 21 deletions neo/d3xp/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1599,8 +1599,8 @@ void idPlayer::Init( void ) {
// stamina always initialized to maximum
stamina = pm_stamina.GetFloat();

// air always initialized to maximum too - DG: pm_airTics must be scaled for actual FPS from com_gameHz
airTics = idMath::Rint( pm_airTics.GetFloat() * gameLocal.gameTicScale );
// air always initialized to maximum too
airTics = pm_airTics.GetFloat();
airless = false;

gibDeath = false;
Expand Down Expand Up @@ -2152,7 +2152,7 @@ void idPlayer::Save( idSaveGame *savefile ) const {
savefile->WriteInt( numProjectileHits );

savefile->WriteBool( airless );
savefile->WriteInt( airTics );
savefile->WriteInt( (int)airTics );
savefile->WriteInt( lastAirDamage );

savefile->WriteBool( gibDeath );
Expand Down Expand Up @@ -2420,7 +2420,11 @@ void idPlayer::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( numProjectileHits );

savefile->ReadBool( airless );
savefile->ReadInt( airTics );
// DG: I made made airTics float for high-fps (where we have fractions of 60Hz tics),
// but for saving ints should still suffice (and this preserves savegame compat)
int iairTics;
savefile->ReadInt( iairTics );
airTics = iairTics;
savefile->ReadInt( lastAirDamage );

savefile->ReadBool( gibDeath );
Expand Down Expand Up @@ -3516,14 +3520,12 @@ bool idPlayer::Give( const char *statname, const char *value ) {
}

} else if ( !idStr::Icmp( statname, "air" ) ) {
// DG: pm_airTics must be scaled for actual FPS from com_gameHz
int airTicsCnt = idMath::Rint( pm_airTics.GetFloat() * gameLocal.gameTicScale );
if ( airTics >= airTicsCnt ) {
if ( airTics >= pm_airTics.GetFloat() ) { // DG: airTics are floats now for high-fps support
return false;
}
airTics += atoi( value ) / 100.0 * pm_airTics.GetInteger();
if ( airTics > airTicsCnt ) {
airTics = airTicsCnt;
airTics += atoi( value ) / 100.0 * pm_airTics.GetFloat();
if ( airTics > pm_airTics.GetFloat() ) {
airTics = pm_airTics.GetFloat();
}
#ifdef _D3XP
} else if ( !idStr::Icmp( statname, "enviroTime" ) ) {
Expand Down Expand Up @@ -6078,9 +6080,6 @@ void idPlayer::UpdateAir( void ) {
return;
}

// DG: pm_airTics must be scaled for actual FPS from com_gameHz
int airTicsCnt = idMath::Rint( pm_airTics.GetFloat() * gameLocal.gameTicScale );

// see if the player is connected to the info_vacuum
bool newAirless = false;

Expand Down Expand Up @@ -6115,7 +6114,8 @@ void idPlayer::UpdateAir( void ) {
hud->HandleNamedEvent( "noAir" );
}
}
airTics--;
// DG: was airTics--, but airTics assume 60Hz tics and we support other ticrates now (com_gameHz)
airTics -= 1.0f / gameLocal.gameTicScale;
if ( airTics < 0 ) {
airTics = 0;
// check for damage
Expand All @@ -6135,16 +6135,16 @@ void idPlayer::UpdateAir( void ) {
hud->HandleNamedEvent( "Air" );
}
}
airTics+=2; // regain twice as fast as lose
if ( airTics > airTicsCnt ) {
airTics = airTicsCnt;
airTics += 2.0f / gameLocal.gameTicScale; // regain twice as fast as lose - DG: scale for com_gameHz
if ( airTics > pm_airTics.GetFloat() ) {
airTics = pm_airTics.GetFloat();
}
}

airless = newAirless;

if ( hud ) {
hud->SetStateInt( "player_air", 100 * airTics / airTicsCnt );
hud->SetStateInt( "player_air", 100 * (airTics / pm_airTics.GetFloat()) );
}
}

Expand Down Expand Up @@ -7662,9 +7662,7 @@ bool idPlayer::CanGive( const char *statname, const char *value ) {
return true;

} else if ( !idStr::Icmp( statname, "air" ) ) {
// DG: pm_airTics must be scaled for actual FPS from com_gameHz
int airTicsCnt = idMath::Rint( pm_airTics.GetFloat() * gameLocal.gameTicScale );
if ( airTics >= airTicsCnt ) {
if ( airTics >= pm_airTics.GetFloat() ) {
return false;
}
return true;
Expand Down
3 changes: 2 additions & 1 deletion neo/d3xp/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,8 @@ class idPlayer : public idActor {
int numProjectileHits; // number of hits on mobs

bool airless;
int airTics; // set to pm_airTics at start, drops in vacuum
// DG: Note: airTics are tics at 60Hz, so no real tics (unless com_gameHz happens to be 60)
float airTics; // set to pm_airTics at start, drops in vacuum
int lastAirDamage;

bool gibDeath;
Expand Down
35 changes: 18 additions & 17 deletions neo/game/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1294,8 +1294,8 @@ void idPlayer::Init( void ) {
// stamina always initialized to maximum
stamina = pm_stamina.GetFloat();

// air always initialized to maximum too - DG: pm_airTics must be scaled for actual FPS for com_gameHz
airTics = idMath::Rint( pm_airTics.GetFloat() * gameLocal.gameTicScale );
// air always initialized to maximum too
airTics = pm_airTics.GetFloat();
airless = false;

gibDeath = false;
Expand Down Expand Up @@ -1747,7 +1747,7 @@ void idPlayer::Save( idSaveGame *savefile ) const {
savefile->WriteInt( numProjectileHits );

savefile->WriteBool( airless );
savefile->WriteInt( airTics );
savefile->WriteInt( (int)airTics );
savefile->WriteInt( lastAirDamage );

savefile->WriteBool( gibDeath );
Expand Down Expand Up @@ -1979,7 +1979,11 @@ void idPlayer::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( numProjectileHits );

savefile->ReadBool( airless );
savefile->ReadInt( airTics );
// DG: I made made airTics float for high-fps (where we have fractions of 60Hz tics),
// but for saving ints should still suffice (and this preserves savegame compat)
int iairTics;
savefile->ReadInt( iairTics );
airTics = iairTics;
savefile->ReadInt( lastAirDamage );

savefile->ReadBool( gibDeath );
Expand Down Expand Up @@ -2903,14 +2907,12 @@ bool idPlayer::Give( const char *statname, const char *value ) {
}

} else if ( !idStr::Icmp( statname, "air" ) ) {
// DG: pm_airTics must be scaled for actual FPS from com_gameHz
int airTicsCnt = idMath::Rint( pm_airTics.GetFloat() * gameLocal.gameTicScale );
if ( airTics >= airTicsCnt ) {
if ( airTics >= pm_airTics.GetFloat() ) { // DG: airTics are floats now for high-fps support
return false;
}
airTics += atoi( value ) / 100.0 * pm_airTics.GetInteger();
if ( airTics > airTicsCnt ) {
airTics = airTicsCnt;
airTics += atoi( value ) / 100.0 * pm_airTics.GetFloat();
if ( airTics > pm_airTics.GetFloat() ) {
airTics = pm_airTics.GetFloat();
}
} else {
return inventory.Give( this, spawnArgs, statname, value, &idealWeapon, true );
Expand Down Expand Up @@ -5071,8 +5073,6 @@ void idPlayer::UpdateAir( void ) {

// see if the player is connected to the info_vacuum
bool newAirless = false;
// DG: pm_airTics must be scaled for actual FPS from com_gameHz
int airTicsCnt = idMath::Rint( pm_airTics.GetFloat() * gameLocal.gameTicScale );

if ( gameLocal.vacuumAreaNum != -1 ) {
int num = GetNumPVSAreas();
Expand All @@ -5099,7 +5099,8 @@ void idPlayer::UpdateAir( void ) {
hud->HandleNamedEvent( "noAir" );
}
}
airTics--;
// DG: was airTics--, but airTics assume 60Hz tics and we support other ticrates now (com_gameHz)
airTics -= 1.0f / gameLocal.gameTicScale;
if ( airTics < 0 ) {
airTics = 0;
// check for damage
Expand All @@ -5119,16 +5120,16 @@ void idPlayer::UpdateAir( void ) {
hud->HandleNamedEvent( "Air" );
}
}
airTics+=2; // regain twice as fast as lose
if ( airTics > airTicsCnt ) {
airTics = airTicsCnt;
airTics += 2.0f / gameLocal.gameTicScale; // regain twice as fast as lose - DG: scale for com_gameHz
if ( airTics > pm_airTics.GetFloat() ) {
airTics = pm_airTics.GetFloat();
}
}

airless = newAirless;

if ( hud ) {
hud->SetStateInt( "player_air", 100 * airTics / airTicsCnt );
hud->SetStateInt( "player_air", 100 * (airTics / pm_airTics.GetFloat()) );
}
}

Expand Down
3 changes: 2 additions & 1 deletion neo/game/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,8 @@ class idPlayer : public idActor {
int numProjectileHits; // number of hits on mobs

bool airless;
int airTics; // set to pm_airTics at start, drops in vacuum
// DG: Note: airTics are tics at 60Hz, so no real tics (unless com_gameHz happens to be 60)
float airTics; // set to pm_airTics at start, drops in vacuum
int lastAirDamage;

bool gibDeath;
Expand Down

0 comments on commit 5a2113e

Please sign in to comment.