source-engine/game/client/flashlighteffect.cpp
2025-02-02 01:43:34 +05:00

821 lines
27 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "cbase.h"
#include "flashlighteffect.h"
#include "dlight.h"
#include "iefx.h"
#include "iviewrender.h"
#include "view.h"
#include "engine/ivdebugoverlay.h"
#include "tier0/vprof.h"
#include "tier1/KeyValues.h"
#include "toolframework_client.h"
#ifdef HL2_CLIENT_DLL
#include "c_basehlplayer.h"
#endif // HL2_CLIENT_DLL
#if defined( _X360 )
extern ConVar r_flashlightdepthres;
#else
extern ConVar r_flashlightdepthres;
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar r_flashlightdepthtexture;
extern ConCommand Ez_Nvg_On; // Breadman - Probably don't need this.
void r_newflashlightCallback_f( IConVar *pConVar, const char *pOldString, float flOldValue );
static ConVar r_newflashlight( "r_newflashlight", "1", FCVAR_CHEAT, "", r_newflashlightCallback_f );
static ConVar r_swingflashlight( "r_swingflashlight", "1", FCVAR_CHEAT );
static ConVar r_flashlightlockposition( "r_flashlightlockposition", "0", FCVAR_CHEAT );
#ifdef EZ
static ConVar r_nvgfov( "r_nvgfov", "100", FCVAR_CHEAT ); // Breadman - Changed for NVG effect
static ConVar r_nvgshadows( "r_nvgshadows", "1", FCVAR_CHEAT ); // Should the NVG cast shadows?
// z33ky - workaround for Linux issue with bordercolor-support detection
#ifdef EZ2
// EZ2 does not ship the _border flashlight material?
static ConVar r_nvg_force_nonbordered( "r_nvg_force_nonbordered", "1" );
#else
static ConVar r_nvg_force_nonbordered( "r_nvg_force_nonbordered", "0" );
#endif
#endif
static ConVar r_flashlightfov( "r_flashlightfov", "45.0", FCVAR_CHEAT );
static ConVar r_flashlightoffsetx( "r_flashlightoffsetx", "10.0", FCVAR_CHEAT );
static ConVar r_flashlightoffsety( "r_flashlightoffsety", "-20.0", FCVAR_CHEAT );
static ConVar r_flashlightoffsetz( "r_flashlightoffsetz", "24.0", FCVAR_CHEAT );
static ConVar r_flashlightnear( "r_flashlightnear", "4.0", FCVAR_CHEAT );
static ConVar r_flashlightfar( "r_flashlightfar", "750.0", FCVAR_CHEAT );
static ConVar r_flashlightconstant( "r_flashlightconstant", "0.0", FCVAR_CHEAT );
static ConVar r_flashlightlinear( "r_flashlightlinear", "100.0", FCVAR_CHEAT );
static ConVar r_flashlightquadratic( "r_flashlightquadratic", "0.0", FCVAR_CHEAT );
static ConVar r_flashlightvisualizetrace( "r_flashlightvisualizetrace", "0", FCVAR_CHEAT );
static ConVar r_flashlightambient( "r_flashlightambient", "0.0", FCVAR_CHEAT );
static ConVar r_flashlightshadowatten( "r_flashlightshadowatten", "0.35", FCVAR_CHEAT );
static ConVar r_flashlightladderdist( "r_flashlightladderdist", "40.0", FCVAR_CHEAT );
#ifndef MAPBASE
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.0005", FCVAR_CHEAT );
#else
extern ConVarRef mat_slopescaledepthbias_shadowmap;
extern ConVarRef mat_depthbias_shadowmap;
#endif
#ifdef MAPBASE
static ConVar r_flashlighttextureoverride( "r_flashlighttextureoverride", "", FCVAR_CHEAT );
#endif
void r_newflashlightCallback_f( IConVar *pConVar, const char *pOldString, float flOldValue )
{
if( engine->GetDXSupportLevel() < 70 )
{
r_newflashlight.SetValue( 0 );
}
}
#ifdef EZ
//-----------------------------------------------------------------------------
// Purpose: Alternate constructor for Entropy : Zero.
// Input : type - flashlight, NVG, or muzzleflash
// nEntIndex - The m_nEntIndex of the client entity that is creating us.
// vecPos - The position of the light emitter.
// vecDir - The direction of the light emission.
//-----------------------------------------------------------------------------
CFlashlightEffect::CFlashlightEffect( int nEntIndex, flashlighttype type )
#else
//-----------------------------------------------------------------------------
// Purpose:
// Input : nEntIndex - The m_nEntIndex of the client entity that is creating us.
// vecPos - The position of the light emitter.
// vecDir - The direction of the light emission.
//-----------------------------------------------------------------------------
CFlashlightEffect::CFlashlightEffect(int nEntIndex)
#endif
{
m_FlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
m_nEntIndex = nEntIndex;
m_bIsOn = false;
m_pPointLight = NULL;
if( engine->GetDXSupportLevel() < 70 )
{
r_newflashlight.SetValue( 0 );
}
#ifdef EZ
m_iFlashLightType = type;
if ( g_pMaterialSystemHardwareConfig->SupportsBorderColor() && !r_nvg_force_nonbordered.GetBool() && IsNVG() )
{
m_FlashlightTexture.Init( "effects/Ez_MetroVision_border", TEXTURE_GROUP_OTHER, true );
}
else if ( IsNVG() )
{
m_FlashlightTexture.Init( "effects/Ez_MetroVision", TEXTURE_GROUP_OTHER, true );
}
else if ( m_iFlashLightType == HEADLAMP )
{
m_FlashlightTexture.Init( "effects/headlamp001", TEXTURE_GROUP_OTHER, true );
}
else
#endif
#ifdef MAPBASE
if ( r_flashlighttextureoverride.GetString()[0] != '\0' )
{
m_FlashlightTexture.Init( r_flashlighttextureoverride.GetString(), TEXTURE_GROUP_OTHER, true );
}
else
#endif
if (g_pMaterialSystemHardwareConfig->SupportsBorderColor())
{
m_FlashlightTexture.Init( "effects/flashlight_border", TEXTURE_GROUP_OTHER, true );
}
else
{
m_FlashlightTexture.Init( "effects/flashlight001", TEXTURE_GROUP_OTHER, true );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CFlashlightEffect::~CFlashlightEffect()
{
LightOff();
#ifdef EZ
if ( IsNVG() )
{
engine->ClientCmd( "Ez_Nvg_On" ); //Breadman - see View_scene.cpp for this Convar
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlashlightEffect::TurnOn()
{
m_bIsOn = true;
m_flDistMod = 1.0f;
#ifdef EZ
if ( IsNVG() )
{
engine->ClientCmd( "Ez_Nvg_On" ); //Breadman - see View_scene.cpp for this Convar
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlashlightEffect::TurnOff()
{
if (m_bIsOn)
{
m_bIsOn = false;
LightOff();
}
}
// Custom trace filter that skips the player and the view model.
// If we don't do this, we'll end up having the light right in front of us all
// the time.
class CTraceFilterSkipPlayerAndViewModel : public CTraceFilter
{
public:
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
{
// Test against the vehicle too?
// FLASHLIGHTFIXME: how do you know that you are actually inside of the vehicle?
C_BaseEntity *pEntity = EntityFromEntityHandle( pServerEntity );
if ( !pEntity )
return true;
if ( ( dynamic_cast<C_BaseViewModel *>( pEntity ) != NULL ) ||
( dynamic_cast<C_BasePlayer *>( pEntity ) != NULL ) ||
pEntity->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ||
pEntity->GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS )
{
return false;
}
return true;
}
};
extern ConVar cl_stunstick_flashlight_distance;
extern ConVar cl_stunstick_flashlight_intensity;
//-----------------------------------------------------------------------------
// Purpose: Do the headlight
//-----------------------------------------------------------------------------
void CFlashlightEffect::UpdateLightNew(const Vector &vecPos, const Vector &vecForward, const Vector &vecRight, const Vector &vecUp )
{
float fov, flashlightFar;
#ifdef EZ
if ( m_iFlashLightType == NVG )
{
fov = r_nvgfov.GetFloat();
flashlightFar = r_flashlightfar.GetFloat();
}
else if ( m_iFlashLightType == MUZZLEFLASH )
{
fov = 179;
flashlightFar = cl_stunstick_flashlight_distance.GetFloat();
}
else
#endif
{
fov = r_flashlightfov.GetFloat();
flashlightFar = r_flashlightfar.GetFloat();
}
VPROF_BUDGET( "CFlashlightEffect::UpdateLightNew", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
FlashlightState_t state;
// We will lock some of the flashlight params if player is on a ladder, to prevent oscillations due to the trace-rays
bool bPlayerOnLadder = ( C_BasePlayer::GetLocalPlayer()->GetMoveType() == MOVETYPE_LADDER );
const float flEpsilon = 0.1f; // Offset flashlight position along vecUp
const float flDistCutoff = 128.0f;
const float flDistDrag = 0.2;
CTraceFilterSkipPlayerAndViewModel traceFilter;
float flOffsetY = r_flashlightoffsety.GetFloat();
if( r_swingflashlight.GetBool() )
{
// This projects the view direction backwards, attempting to raise the vertical
// offset of the flashlight, but only when the player is looking down.
Vector vecSwingLight = vecPos + vecForward * -12.0f;
if( vecSwingLight.z > vecPos.z )
{
flOffsetY += (vecSwingLight.z - vecPos.z);
}
}
Vector vOrigin = vecPos + flOffsetY * vecUp;
// Not on ladder...trace a hull
if ( !bPlayerOnLadder )
{
trace_t pmOriginTrace;
UTIL_TraceHull( vecPos, vOrigin, Vector(-4, -4, -4), Vector(4, 4, 4), MASK_SOLID & ~(CONTENTS_HITBOX), &traceFilter, &pmOriginTrace );
if ( pmOriginTrace.DidHit() )
{
vOrigin = vecPos;
}
}
else // on ladder...skip the above hull trace
{
vOrigin = vecPos;
}
// Now do a trace along the flashlight direction to ensure there is nothing within range to pull back from
int iMask = MASK_OPAQUE_AND_NPCS;
iMask &= ~CONTENTS_HITBOX;
iMask |= CONTENTS_WINDOW;
Vector vTarget = vecPos + vecForward * flashlightFar;
// Work with these local copies of the basis for the rest of the function
Vector vDir = vTarget - vOrigin;
Vector vRight = vecRight;
Vector vUp = vecUp;
VectorNormalize( vDir );
VectorNormalize( vRight );
VectorNormalize( vUp );
// Orthonormalize the basis, since the flashlight texture projection will require this later...
vUp -= DotProduct( vDir, vUp ) * vDir;
VectorNormalize( vUp );
vRight -= DotProduct( vDir, vRight ) * vDir;
VectorNormalize( vRight );
vRight -= DotProduct( vUp, vRight ) * vUp;
VectorNormalize( vRight );
AssertFloatEquals( DotProduct( vDir, vRight ), 0.0f, 1e-3 );
AssertFloatEquals( DotProduct( vDir, vUp ), 0.0f, 1e-3 );
AssertFloatEquals( DotProduct( vRight, vUp ), 0.0f, 1e-3 );
trace_t pmDirectionTrace;
UTIL_TraceHull( vOrigin, vTarget, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), iMask, &traceFilter, &pmDirectionTrace );
if ( r_flashlightvisualizetrace.GetBool() == true )
{
debugoverlay->AddBoxOverlay( pmDirectionTrace.endpos, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), QAngle( 0, 0, 0 ), 0, 0, 255, 16, 0 );
debugoverlay->AddLineOverlay( vOrigin, pmDirectionTrace.endpos, 255, 0, 0, false, 0 );
}
float flDist = (pmDirectionTrace.endpos - vOrigin).Length();
if ( flDist < flDistCutoff )
{
// We have an intersection with our cutoff range
// Determine how far to pull back, then trace to see if we are clear
float flPullBackDist = bPlayerOnLadder ? r_flashlightladderdist.GetFloat() : flDistCutoff - flDist; // Fixed pull-back distance if on ladder
m_flDistMod = Lerp( flDistDrag, m_flDistMod, flPullBackDist );
if ( !bPlayerOnLadder )
{
trace_t pmBackTrace;
UTIL_TraceHull( vOrigin, vOrigin - vDir*(flPullBackDist-flEpsilon), Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), iMask, &traceFilter, &pmBackTrace );
if( pmBackTrace.DidHit() )
{
// We have an intersection behind us as well, so limit our m_flDistMod
float flMaxDist = (pmBackTrace.endpos - vOrigin).Length() - flEpsilon;
if( m_flDistMod > flMaxDist )
m_flDistMod = flMaxDist;
}
}
}
else
{
m_flDistMod = Lerp( flDistDrag, m_flDistMod, 0.0f );
}
vOrigin = vOrigin - vDir * m_flDistMod;
state.m_vecLightOrigin = vOrigin;
BasisToQuaternion( vDir, vRight, vUp, state.m_quatOrientation );
state.m_fQuadraticAtten = r_flashlightquadratic.GetFloat();
bool bFlicker = false;
#ifdef HL2_EPISODIC
C_BaseHLPlayer *pPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
if ( pPlayer )
{
float flBatteryPower = ( pPlayer->m_HL2Local.m_flFlashBattery >= 0.0f ) ? ( pPlayer->m_HL2Local.m_flFlashBattery ) : pPlayer->m_HL2Local.m_flSuitPower;
if ( flBatteryPower <= 10.0f )
{
float flScale;
if ( flBatteryPower >= 0.0f )
{
flScale = ( flBatteryPower <= 4.5f ) ? SimpleSplineRemapVal( flBatteryPower, 4.5f, 0.0f, 1.0f, 0.0f ) : 1.0f;
}
else
{
flScale = SimpleSplineRemapVal( flBatteryPower, 10.0f, 4.8f, 1.0f, 0.0f );
}
flScale = clamp( flScale, 0.0f, 1.0f );
if ( flScale < 0.35f )
{
float flFlicker = cosf( gpGlobals->curtime * 6.0f ) * sinf( gpGlobals->curtime * 15.0f );
if ( flFlicker > 0.25f && flFlicker < 0.75f )
{
// On
state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale;
}
else
{
// Off
state.m_fLinearAtten = 0.0f;
}
}
else
{
float flNoise = cosf( gpGlobals->curtime * 7.0f ) * sinf( gpGlobals->curtime * 25.0f );
state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale + 1.5f * flNoise;
}
state.m_fHorizontalFOVDegrees = fov - ( 16.0f * (1.0f-flScale) );
state.m_fVerticalFOVDegrees = fov - ( 16.0f * (1.0f-flScale) );
bFlicker = true;
}
}
#endif // HL2_EPISODIC
if ( bFlicker == false )
{
state.m_fLinearAtten = r_flashlightlinear.GetFloat();
state.m_fHorizontalFOVDegrees = fov;
state.m_fVerticalFOVDegrees = fov;
}
state.m_fConstantAtten = r_flashlightconstant.GetFloat();
#ifndef EZ
state.m_Color[0] = 1.0f;
state.m_Color[1] = 1.0f;
state.m_Color[2] = 1.0f;
#else
state.m_Color[0] = m_iFlashLightType == MUZZLEFLASH ? cl_stunstick_flashlight_intensity.GetFloat() : 1.0f;
state.m_Color[1] = m_iFlashLightType == MUZZLEFLASH ? cl_stunstick_flashlight_intensity.GetFloat() : 1.0f;
state.m_Color[2] = m_iFlashLightType == MUZZLEFLASH ? cl_stunstick_flashlight_intensity.GetFloat() : 1.0f;
#endif
state.m_Color[3] = r_flashlightambient.GetFloat();
state.m_NearZ = r_flashlightnear.GetFloat() + m_flDistMod; // Push near plane out so that we don't clip the world when the flashlight pulls back
state.m_FarZ = flashlightFar;
#ifdef EZ
// The NVG projected texture should not cast shadows
state.m_bEnableShadows = ( m_iFlashLightType == FLASHLIGHT || ( m_iFlashLightType == HEADLAMP && r_nvgshadows.GetBool() ) ) && r_flashlightdepthtexture.GetBool();
#else
state.m_bEnableShadows = r_flashlightdepthtexture.GetBool();
#endif
state.m_flShadowMapResolution = r_flashlightdepthres.GetInt();
state.m_pSpotlightTexture = m_FlashlightTexture;
state.m_nSpotlightTextureFrame = 0;
state.m_flShadowAtten = r_flashlightshadowatten.GetFloat();
state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
if( m_FlashlightHandle == CLIENTSHADOW_INVALID_HANDLE )
{
m_FlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state );
}
else
{
if( !r_flashlightlockposition.GetBool() )
{
g_pClientShadowMgr->UpdateFlashlightState( m_FlashlightHandle, state );
}
}
g_pClientShadowMgr->UpdateProjectedTexture( m_FlashlightHandle, true );
// Kill the old flashlight method if we have one.
LightOffOld();
#ifndef NO_TOOLFRAMEWORK
if ( clienttools->IsInRecordingMode() )
{
KeyValues *msg = new KeyValues( "FlashlightState" );
msg->SetFloat( "time", gpGlobals->curtime );
msg->SetInt( "entindex", m_nEntIndex );
msg->SetInt( "flashlightHandle", m_FlashlightHandle );
msg->SetPtr( "flashlightState", &state );
ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
msg->deleteThis();
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Do the headlight
//-----------------------------------------------------------------------------
void CFlashlightEffect::UpdateLightOld(const Vector &vecPos, const Vector &vecDir, int nDistance)
{
if ( !m_pPointLight || ( m_pPointLight->key != m_nEntIndex ))
{
// Set up the environment light
m_pPointLight = effects->CL_AllocDlight(m_nEntIndex);
m_pPointLight->flags = 0.0f;
m_pPointLight->radius = 80;
#ifdef EZ
if ( IsNVG() )
{
m_pPointLight->color.r = 5; // Breadman - Doesn't actually work here. Seems to be derived from the texture colour.
m_pPointLight->color.g = 230; // Breadman
m_pPointLight->color.b = 255; // Breadman
}
#endif
}
// For bumped lighting
VectorCopy(vecDir, m_pPointLight->m_Direction);
Vector end;
end = vecPos + nDistance * vecDir;
// Trace a line outward, skipping the player model and the view model.
trace_t pm;
CTraceFilterSkipPlayerAndViewModel traceFilter;
UTIL_TraceLine( vecPos, end, MASK_ALL, &traceFilter, &pm );
VectorCopy( pm.endpos, m_pPointLight->origin );
float falloff = pm.fraction * nDistance;
if ( falloff < 500 )
falloff = 1.0;
else
falloff = 500.0 / falloff;
falloff *= falloff;
m_pPointLight->radius = 80;
m_pPointLight->color.r = m_pPointLight->color.g = m_pPointLight->color.b = 255 * falloff;
m_pPointLight->color.exponent = 0;
// Make it live for a bit
m_pPointLight->die = gpGlobals->curtime + 0.2f;
// Update list of surfaces we influence
render->TouchLight( m_pPointLight );
// kill the new flashlight if we have one
LightOffNew();
}
//-----------------------------------------------------------------------------
// Purpose: Do the headlight
//-----------------------------------------------------------------------------
void CFlashlightEffect::UpdateLight(const Vector &vecPos, const Vector &vecDir, const Vector &vecRight, const Vector &vecUp, int nDistance)
{
if ( !m_bIsOn )
{
return;
}
if( r_newflashlight.GetBool() )
{
UpdateLightNew( vecPos, vecDir, vecRight, vecUp );
}
else
{
UpdateLightOld( vecPos, vecDir, nDistance );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlashlightEffect::LightOffNew()
{
#ifndef NO_TOOLFRAMEWORK
if ( clienttools->IsInRecordingMode() )
{
KeyValues *msg = new KeyValues( "FlashlightState" );
msg->SetFloat( "time", gpGlobals->curtime );
msg->SetInt( "entindex", m_nEntIndex );
msg->SetInt( "flashlightHandle", m_FlashlightHandle );
msg->SetPtr( "flashlightState", NULL );
ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
msg->deleteThis();
}
#endif
// Clear out the light
if( m_FlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
g_pClientShadowMgr->DestroyFlashlight( m_FlashlightHandle );
m_FlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlashlightEffect::LightOffOld()
{
if ( m_pPointLight && ( m_pPointLight->key == m_nEntIndex ) )
{
m_pPointLight->die = gpGlobals->curtime;
m_pPointLight = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFlashlightEffect::LightOff()
{
LightOffOld();
LightOffNew();
}
#ifdef EZ
static ConVar r_headlightfov( "r_headlightfov", "90.0", FCVAR_CHEAT );
static ConVar r_headlightfar( "r_headlightfar", "1250.0", FCVAR_CHEAT );
#endif
CHeadlightEffect::CHeadlightEffect()
{
}
CHeadlightEffect::~CHeadlightEffect()
{
}
void CHeadlightEffect::UpdateLight( const Vector &vecPos, const Vector &vecDir, const Vector &vecRight, const Vector &vecUp, int nDistance )
{
if ( IsOn() == false )
return;
FlashlightState_t state;
Vector basisX, basisY, basisZ;
basisX = vecDir;
basisY = vecRight;
basisZ = vecUp;
VectorNormalize(basisX);
VectorNormalize(basisY);
VectorNormalize(basisZ);
BasisToQuaternion( basisX, basisY, basisZ, state.m_quatOrientation );
state.m_vecLightOrigin = vecPos;
#ifdef EZ // Blixibon - Shadows don't work well with non-symmetrical FOV
state.m_fHorizontalFOVDegrees = r_headlightfov.GetFloat();
state.m_fVerticalFOVDegrees = r_headlightfov.GetFloat();
#else
state.m_fHorizontalFOVDegrees = 45.0f;
state.m_fVerticalFOVDegrees = 30.0f;
#endif
state.m_fQuadraticAtten = r_flashlightquadratic.GetFloat();
state.m_fLinearAtten = r_flashlightlinear.GetFloat();
state.m_fConstantAtten = r_flashlightconstant.GetFloat();
state.m_Color[0] = 1.0f;
state.m_Color[1] = 1.0f;
state.m_Color[2] = 1.0f;
state.m_Color[3] = r_flashlightambient.GetFloat();
state.m_NearZ = r_flashlightnear.GetFloat();
#ifdef EZ
state.m_FarZ = r_headlightfar.GetFloat();
#else
state.m_FarZ = r_flashlightfar.GetFloat();
#endif
state.m_bEnableShadows = true;
state.m_pSpotlightTexture = m_FlashlightTexture;
state.m_nSpotlightTextureFrame = 0;
if( GetFlashlightHandle() == CLIENTSHADOW_INVALID_HANDLE )
{
SetFlashlightHandle( g_pClientShadowMgr->CreateFlashlight( state ) );
}
else
{
g_pClientShadowMgr->UpdateFlashlightState( GetFlashlightHandle(), state );
}
g_pClientShadowMgr->UpdateProjectedTexture( GetFlashlightHandle(), true );
}
#ifdef EZ2
static ConVar r_turretlightbrightness( "r_turretlightbrightness", "5.0", FCVAR_CHEAT );
static ConVar r_turretlightfar( "r_turretlightfar", "500", FCVAR_CHEAT );
static ConVar r_turretlightnear( "r_turretlightnear", "1.0", FCVAR_CHEAT );
static ConVar r_turretlightconstant( "r_turretlightconstant", "0.0", FCVAR_CHEAT );
static ConVar r_turretlightlinear( "r_turretlightlinear", "0.0", FCVAR_CHEAT );
static ConVar r_turretlightquadratic( "r_turretlightquadratic", "100.0", FCVAR_CHEAT );
static ConVar r_turretlightfov( "r_turretlightfov", "60.0", FCVAR_CHEAT ); // Based on the actual turret FOV
static ConVar r_turretlightshadowsenabled( "r_turretlightshadowsenabled", "0", FCVAR_CHEAT );
static ConVar r_turretlightshadowatten( "r_turretlightshadowatten", "1.0", FCVAR_CHEAT );
static ConVar r_turretlighttexture( "r_turretlighttexture", "effects/turret_light", FCVAR_CHEAT );
CTurretLightEffect::CTurretLightEffect()
{
m_FlashlightTexture.Init( r_turretlighttexture.GetString(), TEXTURE_GROUP_OTHER, true );
m_flBrightnessScale = 1.0f;
m_flFarZ = r_turretlightfar.GetFloat();
m_flFOV = r_turretlightfov.GetFloat();
m_Color[0] = 1.0f;
m_Color[1] = 0.0f;
m_Color[2] = 0.0f;
}
CTurretLightEffect::~CTurretLightEffect()
{
}
void CTurretLightEffect::UpdateLight( const Vector &vecPos, const Vector &vecDir, const Vector &vecRight, const Vector &vecUp, int nDistance )
{
if ( IsOn() == false )
return;
FlashlightState_t state;
Vector basisX, basisY, basisZ;
basisX = vecDir;
basisY = vecRight;
basisZ = vecUp;
VectorNormalize(basisX);
VectorNormalize(basisY);
VectorNormalize(basisZ);
BasisToQuaternion( basisX, basisY, basisZ, state.m_quatOrientation );
state.m_vecLightOrigin = vecPos;
state.m_fHorizontalFOVDegrees = m_flFOV;
state.m_fVerticalFOVDegrees = m_flFOV;
state.m_fQuadraticAtten = r_turretlightquadratic.GetFloat();
state.m_fLinearAtten = r_turretlightlinear.GetFloat();
state.m_fConstantAtten = r_turretlightconstant.GetFloat();
state.m_Color[0] = m_Color[0] * (m_flBrightnessScale != 1.0f ? r_turretlightbrightness.GetFloat() * m_flBrightnessScale : r_turretlightbrightness.GetFloat());
state.m_Color[1] = m_Color[1] * (m_flBrightnessScale != 1.0f ? r_turretlightbrightness.GetFloat() * m_flBrightnessScale : r_turretlightbrightness.GetFloat());
state.m_Color[2] = m_Color[2] * (m_flBrightnessScale != 1.0f ? r_turretlightbrightness.GetFloat() * m_flBrightnessScale : r_turretlightbrightness.GetFloat());
state.m_Color[3] = r_flashlightambient.GetFloat();
state.m_NearZ = r_turretlightnear.GetFloat();
state.m_FarZ = m_flFarZ;
state.m_bEnableShadows = r_turretlightshadowsenabled.GetBool();
state.m_pSpotlightTexture = m_FlashlightTexture;
state.m_nSpotlightTextureFrame = 0;
state.m_flShadowAtten = r_turretlightshadowatten.GetFloat();
state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
if( GetFlashlightHandle() == CLIENTSHADOW_INVALID_HANDLE )
{
SetFlashlightHandle( g_pClientShadowMgr->CreateFlashlight( state ) );
}
else
{
g_pClientShadowMgr->UpdateFlashlightState( GetFlashlightHandle(), state );
}
g_pClientShadowMgr->UpdateProjectedTexture( GetFlashlightHandle(), true );
}
//-----------------------------------------------------------------------------
// Crab Synth light effect
//-----------------------------------------------------------------------------
static ConVar r_crabsynthlightbrightness( "r_crabsynthlightbrightness", "255.0", FCVAR_CHEAT );
static ConVar r_crabsynthlightfar( "r_crabsynthlightfar", "400", FCVAR_CHEAT );
static ConVar r_crabsynthlightnear( "r_crabsynthlightnear", "2.0", FCVAR_CHEAT );
static ConVar r_crabsynthlightconstant( "r_crabsynthlightconstant", "0.0", FCVAR_CHEAT );
static ConVar r_crabsynthlightlinear( "r_crabsynthlightlinear", "0.0", FCVAR_CHEAT );
static ConVar r_crabsynthlightquadratic( "r_crabsynthlightquadratic", "100.0", FCVAR_CHEAT );
static ConVar r_crabsynthlightshadowatten( "r_crabsynthlightshadowatten", "1.0", FCVAR_CHEAT );
static ConVar r_crabsynthlighttexture( "r_crabsynthlighttexture", "effects/crabsynthlight", FCVAR_CHEAT );
CCrabSynthLightEffect::CCrabSynthLightEffect()
{
m_FlashlightTexture.Init( r_crabsynthlighttexture.GetString(), TEXTURE_GROUP_OTHER, true );
m_flBrightnessScale = 1.0f;
m_Color[0] = 1.0f;
m_Color[1] = 1.0f;
m_Color[2] = 1.0f;
}
CCrabSynthLightEffect::~CCrabSynthLightEffect()
{
}
void CCrabSynthLightEffect::UpdateLight( const Vector &vecPos, const Vector &vecDir, const Vector &vecRight, const Vector &vecUp, int nDistance )
{
if ( IsOn() == false )
return;
FlashlightState_t state;
Vector basisX, basisY, basisZ;
basisX = vecDir;
basisY = vecRight;
basisZ = vecUp;
VectorNormalize(basisX);
VectorNormalize(basisY);
VectorNormalize(basisZ);
BasisToQuaternion( basisX, basisY, basisZ, state.m_quatOrientation );
state.m_vecLightOrigin = vecPos;
state.m_fHorizontalFOVDegrees = m_flHorzFOV;
state.m_fVerticalFOVDegrees = m_flFOV;
state.m_fQuadraticAtten = r_crabsynthlightquadratic.GetFloat();
state.m_fLinearAtten = r_crabsynthlightlinear.GetFloat();
state.m_fConstantAtten = r_crabsynthlightconstant.GetFloat();
state.m_Color[0] = m_Color[0] * (m_flBrightnessScale != 1.0f ? r_crabsynthlightbrightness.GetFloat() * m_flBrightnessScale : r_crabsynthlightbrightness.GetFloat());
state.m_Color[1] = m_Color[1] * (m_flBrightnessScale != 1.0f ? r_crabsynthlightbrightness.GetFloat() * m_flBrightnessScale : r_crabsynthlightbrightness.GetFloat());
state.m_Color[2] = m_Color[2] * (m_flBrightnessScale != 1.0f ? r_crabsynthlightbrightness.GetFloat() * m_flBrightnessScale : r_crabsynthlightbrightness.GetFloat());
state.m_Color[3] = r_flashlightambient.GetFloat();
state.m_NearZ = r_crabsynthlightnear.GetFloat();
state.m_FarZ = r_crabsynthlightfar.GetFloat();
state.m_bEnableShadows = m_bShadowsEnabled;
state.m_pSpotlightTexture = m_FlashlightTexture;
state.m_nSpotlightTextureFrame = 0;
state.m_flShadowAtten = r_crabsynthlightshadowatten.GetFloat();
state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
if( GetFlashlightHandle() == CLIENTSHADOW_INVALID_HANDLE )
{
SetFlashlightHandle( g_pClientShadowMgr->CreateFlashlight( state ) );
}
else
{
g_pClientShadowMgr->UpdateFlashlightState( GetFlashlightHandle(), state );
}
g_pClientShadowMgr->UpdateProjectedTexture( GetFlashlightHandle(), true );
}
#endif