From 0bfc51f55e030d355225265f80e60c0a0bba2733 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sun, 6 Nov 2022 18:12:54 +0100 Subject: [PATCH] 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 --- game/Moveable.cpp | 9 +++++++++ game/Projectile.cpp | 5 +++++ game/Weapon.cpp | 14 +++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/game/Moveable.cpp b/game/Moveable.cpp index e13ecd6..e3458b3 100644 --- a/game/Moveable.cpp +++ b/game/Moveable.cpp @@ -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 ); + } } /* diff --git a/game/Projectile.cpp b/game/Projectile.cpp index c353ca0..6460ae0 100644 --- a/game/Projectile.cpp +++ b/game/Projectile.cpp @@ -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 ); diff --git a/game/Weapon.cpp b/game/Weapon.cpp index a381ae2..727e061 100644 --- a/game/Weapon.cpp +++ b/game/Weapon.cpp @@ -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 );