Fix renderlights loaded from savegames aliasing other lights

Some entities wrote the handle from gameRenderWorld->AddLightDef()
into savegames and reused it after restoring it.
That's a bad idea, because at that point the handle most likely belongs
to something else (likely some idLight). The most visible issue this
can create is that the flashlight may not work correctly after loading
a savegame with flashlight on, when it happens to alias a light that's
updated each frame to (mostly) being off..

The correct way to handle this (THAT FOR SOME REASON WAS ALREADY
IMPLEMENTED IN D3XP BUT NOT THE BASE GAME - WHY?!) is to get a fresh
handle with AddLightDef() when restoring a savegame - unless the handle
was -1, which means that the light didn't exist when saving.

fixes #495
This commit is contained in:
Daniel Gibson 2024-03-18 23:56:40 +01:00
parent ce46ff9c9d
commit d6caed016e
3 changed files with 27 additions and 1 deletions

View file

@ -919,6 +919,15 @@ void idExplodingBarrel::Restore( idRestoreGame *savefile ) {
//REV GRAB //REV GRAB
savefile->ReadBool( isStable ); savefile->ReadBool( isStable );
//REV GRAB //REV GRAB
// DG: enforce getting fresh handle, else this may be tied to an unrelated light!
if ( lightDefHandle != -1 ) {
lightDefHandle = gameRenderWorld->AddLightDef( &light );
}
// DG: same for render entity
if ( particleModelDefHandle != -1 ) {
particleModelDefHandle = gameRenderWorld->AddEntityDef( &particleRenderEntity );
}
} }
/* /*

View file

@ -174,6 +174,11 @@ void idProjectile::Restore( idRestoreGame *savefile ) {
savefile->ReadRenderLight( renderLight ); savefile->ReadRenderLight( renderLight );
savefile->ReadInt( (int &)lightDefHandle ); savefile->ReadInt( (int &)lightDefHandle );
// DG: enforce getting fresh handle, else this may be tied to an unrelated light!
if ( lightDefHandle != -1 ) {
lightDefHandle = gameRenderWorld->AddLightDef( &renderLight );
}
savefile->ReadVec3( lightOffset ); savefile->ReadVec3( lightOffset );
savefile->ReadInt( lightStartTime ); savefile->ReadInt( lightStartTime );
savefile->ReadInt( lightEndTime ); savefile->ReadInt( lightEndTime );

View file

@ -662,13 +662,22 @@ void idWeapon::Restore( idRestoreGame *savefile ) {
/* /*
savefile->ReadInt( guiLightHandle ); savefile->ReadInt( guiLightHandle );
savefile->ReadRenderLight( guiLight ); savefile->ReadRenderLight( guiLight );
// DG: we need to get a fresh handle, otherwise this will be tied to a completely unrelated light!
if ( guiLightHandle != -1 ) {
guiLightHandle = gameRenderWorld->AddLightDef( &guiLight );
}
savefile->ReadInt( muzzleFlashHandle ); savefile->ReadInt( muzzleFlashHandle );
savefile->ReadRenderLight( muzzleFlash ); savefile->ReadRenderLight( muzzleFlash );
if ( muzzleFlashHandle != -1 ) { // DG: enforce getting fresh handle
muzzleFlashHandle = gameRenderWorld->AddLightDef( &muzzleFlash );
}
*/ */
savefile->ReadInt( worldMuzzleFlashHandle ); savefile->ReadInt( worldMuzzleFlashHandle );
savefile->ReadRenderLight( worldMuzzleFlash ); savefile->ReadRenderLight( worldMuzzleFlash );
if ( worldMuzzleFlashHandle != -1 ) { // DG: enforce getting fresh handle
worldMuzzleFlashHandle = gameRenderWorld->AddLightDef( &worldMuzzleFlash );
}
savefile->ReadVec3( flashColor ); savefile->ReadVec3( flashColor );
savefile->ReadInt( muzzleFlashEnd ); savefile->ReadInt( muzzleFlashEnd );
@ -765,6 +774,9 @@ void idWeapon::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( nozzleGlowHandle ); savefile->ReadInt( nozzleGlowHandle );
savefile->ReadRenderLight( nozzleGlow ); savefile->ReadRenderLight( nozzleGlow );
if ( nozzleGlowHandle != -1 ) { // DG: enforce getting fresh handle
nozzleGlowHandle = gameRenderWorld->AddLightDef( &nozzleGlow );
}
savefile->ReadVec3( nozzleGlowColor ); savefile->ReadVec3( nozzleGlowColor );
savefile->ReadMaterial( nozzleGlowShader ); savefile->ReadMaterial( nozzleGlowShader );