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 2022-11-06 18:12:54 +01:00
parent e5c23adf73
commit 0bfc51f55e
3 changed files with 27 additions and 1 deletions

View file

@ -810,6 +810,15 @@ void idExplodingBarrel::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( particleTime );
savefile->ReadInt( lightTime );
savefile->ReadFloat( time );
// 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

@ -157,6 +157,11 @@ void idProjectile::Restore( idRestoreGame *savefile ) {
savefile->ReadRenderLight( renderLight );
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->ReadInt( lightStartTime );
savefile->ReadInt( lightEndTime );

View file

@ -453,12 +453,21 @@ void idWeapon::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( guiLightHandle );
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->ReadRenderLight( muzzleFlash );
if ( muzzleFlashHandle != -1 ) { // DG: enforce getting fresh handle
muzzleFlashHandle = gameRenderWorld->AddLightDef( &muzzleFlash );
}
savefile->ReadInt( worldMuzzleFlashHandle );
savefile->ReadRenderLight( worldMuzzleFlash );
if ( worldMuzzleFlashHandle != -1 ) { // DG: enforce getting fresh handle
worldMuzzleFlashHandle = gameRenderWorld->AddLightDef( &worldMuzzleFlash );
}
savefile->ReadVec3( flashColor );
savefile->ReadInt( muzzleFlashEnd );
@ -516,6 +525,9 @@ void idWeapon::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( nozzleGlowHandle );
savefile->ReadRenderLight( nozzleGlow );
if ( nozzleGlowHandle != -1 ) { // DG: enforce getting fresh handle
nozzleGlowHandle = gameRenderWorld->AddLightDef( &nozzleGlow );
}
savefile->ReadVec3( nozzleGlowColor );
savefile->ReadMaterial( nozzleGlowShader );