diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h b/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h index b66eb7dc96..35c8b4d4b0 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h @@ -542,8 +542,10 @@ class Drawable : public Thing, void setEffectiveOpacity( Real pulseFactor, Real explicitOpacity = -1.0f ); // this is for the add'l pass fx which operates completely independently of the stealth opacity effects. Draw() does the fading every frame. - Real getSecondMaterialPassOpacity() const { return m_secondMaterialPassOpacity; } ///< get alpha/opacity value used to render add'l rendering pass. - void setSecondMaterialPassOpacity( Real op ) { m_secondMaterialPassOpacity = op; }; ///< set alpha/opacity value used to render add'l rendering pass. + Real getSecondMaterialPassOpacity() const { return m_secondMaterialPassOpacity; } ///< get alpha/opacity value used to render add'l rendering pass. + void setSecondMaterialPassOpacity( Real op ) { m_secondMaterialPassOpacity = op; }; ///< set alpha/opacity value used to render add'l rendering pass. + void allowRefillSecondMaterialPassOpacity() { m_secondMaterialPassOpacityAllowRefill = TRUE; } ///< allow the second material opacity to be set to 1.0f + static void updateSecondMaterialPassOpacityScalar(); ///< update alpha/opacity scalar value used to render e.g. detected stealth units. // both of these assume that you are starting at one extreme 100% or 0% opacity and are trying to go to the other!! -- amit void fadeOut( UnsignedInt frames ); ///< fade object out...how gradually this is done is determined by frames @@ -723,7 +725,9 @@ class Drawable : public Thing, UnsignedInt m_expirationDate; ///< if nonzero, Drawable should destroy itself at this frame DrawableIconInfo* m_iconInfo; ///< lazily allocated! - Real m_secondMaterialPassOpacity; ///< drawable gets rendered again in hardware with an extra material layer + static Real s_secondMaterialPassOpacityScalar; ///< multiply opacity by scalar value; used for non-default render framerates + Real m_secondMaterialPassOpacity; ///< drawable gets rendered again in hardware with an extra material layer + Bool m_secondMaterialPassOpacityAllowRefill; ///< allow the second material opacity to be set to 1.0f // --------- BYTE-SIZED THINGS GO HERE Byte m_selected; ///< drawable is selected or not Bool m_hidden; ///< drawable is "hidden" or not (overrides stealth effects) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp index 3c183794f8..3cfd5458fd 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp @@ -1003,6 +1003,7 @@ void GameEngine::execute( void ) } TheFramePacer->update(); + Drawable::updateSecondMaterialPassOpacityScalar(); } #ifdef PERF_TIMERS diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp index 9f1f5f7eaf..32a3e9279a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp @@ -87,8 +87,7 @@ #endif -#define VERY_TRANSPARENT_MATERIAL_PASS_OPACITY (0.001f) -#define MATERIAL_PASS_OPACITY_FADE_SCALAR (0.8f) +#define MATERIAL_PASS_OPACITY_MIN (0.001f) static const char *const TheDrawableIconNames[] = { @@ -257,6 +256,8 @@ const Int MAX_ENABLED_MODULES = 16; // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ +/*static*/ Real Drawable::s_secondMaterialPassOpacityScalar = 1.0f; + /*static*/ Bool Drawable::s_staticImagesInited = false; /*static*/ const Image* Drawable::s_veterancyImage[LEVEL_COUNT] = { NULL }; /*static*/ const Image* Drawable::s_fullAmmo = NULL; @@ -433,6 +434,7 @@ Drawable::Drawable( const ThingTemplate *thingTemplate, DrawableStatusBits statu m_hidden = false; m_hiddenByStealth = false; m_secondMaterialPassOpacity = 0.0f; + m_secondMaterialPassOpacityAllowRefill = false; m_drawableFullyObscuredByShroud = false; m_receivesDynamicLights = TRUE; // a good default... overridden by one of my draw modules if at all @@ -2601,22 +2603,50 @@ void Drawable::setStealthLook(StealthLookType look) } } +void Drawable::updateSecondMaterialPassOpacityScalar() +{ + // TheSuperHackers @tweak The opacity step is no longer a fixed value. + // min opacity = (X ^ (frame rate / updates per second)) -> e.g. [ 0.05 = X ^ (100 / 2) ] -> [ X = 0.941845 ] -> [ 0.941845 ^ 50 = 0.05 ] + const Real updatesPerSec = 2.0f; + const Real scalar = pow(MATERIAL_PASS_OPACITY_MIN, updatesPerSec / TheFramePacer->getUpdateFps()); + + s_secondMaterialPassOpacityScalar = scalar; +} //------------------------------------------------------------------------------------------------- /** default draw is to just call the database defined draw */ //------------------------------------------------------------------------------------------------- void Drawable::draw() { - if ( testTintStatus( TINT_STATUS_FRENZY ) == FALSE ) + if (testTintStatus(TINT_STATUS_FRENZY) == FALSE) { - if ( getObject() && getObject()->isEffectivelyDead() ) - m_secondMaterialPassOpacity = 0.0f;//dead folks don't stealth anyway - else if ( m_secondMaterialPassOpacity > VERY_TRANSPARENT_MATERIAL_PASS_OPACITY )// keep fading any add'l material unless something has set it to zero - m_secondMaterialPassOpacity *= MATERIAL_PASS_OPACITY_FADE_SCALAR; - else - m_secondMaterialPassOpacity = 0.0f; - } + if (getObject() && getObject()->isEffectivelyDead()) + { + m_secondMaterialPassOpacity = 0.0f;//dead folks don't stealth anyway + } + else if (!TheFramePacer->isGameHalted()) + { + const Bool shouldFade = m_secondMaterialPassOpacity > MATERIAL_PASS_OPACITY_MIN; + const Bool allowRefill = m_secondMaterialPassOpacityAllowRefill; + if (shouldFade || allowRefill) + { + if (!shouldFade && allowRefill) + { + m_secondMaterialPassOpacity = s_secondMaterialPassOpacityScalar; + m_secondMaterialPassOpacityAllowRefill = FALSE; + } + else + { + m_secondMaterialPassOpacity *= s_secondMaterialPassOpacityScalar; + } + } + else + { + m_secondMaterialPassOpacity = 0.0f; + } + } + } if (m_hidden || m_hiddenByStealth || getFullyObscuredByShroud()) return; // my, that was easy diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp index 15eb2a74eb..199d0cc67d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp @@ -306,7 +306,8 @@ UpdateSleepTime StealthDetectorUpdate::update( void ) Drawable *theirDraw = them->getDrawable(); if ( theirDraw && !them->isKindOf(KINDOF_MINE)) { - theirDraw->setSecondMaterialPassOpacity( 1.0f ); + // TheSuperHackers @tweak Don't set opacity here as it should be decoupled from the logic frame rate and not be set for every stealth detector. + theirDraw->allowRefillSecondMaterialPassOpacity(); } if (data->m_IRGridParticleSysTmpl) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp index a390bc943f..80022117be 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp @@ -431,7 +431,8 @@ void StealthUpdate::hintDetectableWhileUnstealthed() { Drawable *selfDraw = self->getDrawable(); if ( selfDraw ) - selfDraw->setSecondMaterialPassOpacity( 1.0f ); + // TheSuperHackers @tweak Don't set opacity here as it should be decoupled from the logic frame rate. + selfDraw->allowRefillSecondMaterialPassOpacity(); } } }