Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

218 lines
6.4 KiB

//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
//=============================================================================//
#include "cbase.h"
#include "paint_cleanser_manager.h"
#include "igameevents.h"
#ifdef CLIENT_DLL
#include "c_trigger_paint_cleanser.h"
#include "debugoverlay_shared.h"
ConVar paint_cleanser_visibility_poll_frequency( "paint_cleanser_visibility_poll_rate", "0.5", FCVAR_CHEAT );
ConVar paint_cleanser_visibility_checks_debug( "paint_cleanser_visibility_checks_debug", "0", FCVAR_DEVELOPMENTONLY );
ConVar paint_cleanser_visibility_range( "paint_cleanser_visibility_range", "1000.0f", FCVAR_CHEAT );
ConVar paint_cleanser_visibility_look_angle( "paint_cleanser_visibility_look_angle", "60.0f", FCVAR_CHEAT );
#else
#include "trigger_paint_cleanser.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CPaintCleanserManager PaintCleanserManager( "PaintCleanserManager" );
CPaintCleanserManager::CPaintCleanserManager( char const *name )
#ifdef CLIENT_DLL
: CAutoGameSystemPerFrame( name ),
m_flNextPollTime( 0.0f )
#else
: CAutoGameSystem( name )
#endif
{
#ifdef CLIENT_DLL
memset( m_ppVisibleCleanser, 0, sizeof(m_ppVisibleCleanser) );
#endif
}
CPaintCleanserManager::~CPaintCleanserManager( void )
{
}
void CPaintCleanserManager::LevelInitPreEntity()
{
#ifdef CLIENT_DLL
m_flNextPollTime = gpGlobals->curtime + paint_cleanser_visibility_poll_frequency.GetFloat();
#endif
}
void CPaintCleanserManager::LevelShutdownPreEntity()
{
m_PaintCleansers.RemoveAll();
}
void CPaintCleanserManager::AddPaintCleanser( C_TriggerPaintCleanser *pCleanser )
{
m_PaintCleansers.AddToTail( pCleanser );
}
void CPaintCleanserManager::RemovePaintCleanser( C_TriggerPaintCleanser *pCleanser )
{
m_PaintCleansers.FindAndRemove( pCleanser );
}
void CPaintCleanserManager::GetPaintCleansers( PaintCleanserVector_t& paintCleansers )
{
paintCleansers = m_PaintCleansers;
}
#ifdef CLIENT_DLL
void CPaintCleanserManager::Update( float frametime )
{
//Check if it is time to update the cleanser visibility
if( gpGlobals->curtime < m_flNextPollTime )
{
return;
}
//Set the time for the next check
m_flNextPollTime = gpGlobals->curtime + paint_cleanser_visibility_poll_frequency.GetFloat();
UpdatePaintCleanserVisibility();
}
void CPaintCleanserManager::UpdatePaintCleanserVisibility( void )
{
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer( hh );
if( !pPlayer )
continue;
Vector vecPlayerForward;
AngleVectors( pPlayer->EyeAngles(), &vecPlayerForward );
VectorNormalize( vecPlayerForward );
Vector vecPlayerEyePos = pPlayer->EyePosition();
//Max distance to check for visibility
float flVisibilityRange = paint_cleanser_visibility_range.GetFloat() * paint_cleanser_visibility_range.GetFloat();
bool bDebugging = paint_cleanser_visibility_checks_debug.GetBool();
float flClosestCleanserDist = FLT_MAX;
C_TriggerPaintCleanser *pClosestCleanser = NULL;
//If there is a cleanser visible before the check
bool bCleanserWasVisible = m_ppVisibleCleanser[hh] ? true : false;
for( int i = 0; i < m_PaintCleansers.Count(); ++i )
{
Vector vecCleanserPos = m_PaintCleansers[i]->WorldSpaceCenter();
//Don't test the cleanser if the player is too far from it
float flDistSqr = vecPlayerEyePos.DistToSqr( vecCleanserPos );
if( flDistSqr > flVisibilityRange )
{
if( m_ppVisibleCleanser[hh] == m_PaintCleansers[i] )
{
m_ppVisibleCleanser[hh] = NULL;
}
continue;
}
//Don't test the cleanser if the player isn't looking in its direction
Vector vecPlayerCleanserDir = vecCleanserPos - vecPlayerEyePos;
VectorNormalize( vecPlayerCleanserDir );
float flPlayerCleanserAngle = RAD2DEG( acos( DotProduct( vecPlayerForward, vecPlayerCleanserDir ) ) );
if( flPlayerCleanserAngle >= paint_cleanser_visibility_look_angle.GetFloat() )
{
if( m_ppVisibleCleanser[hh] == m_PaintCleansers[i] )
{
m_ppVisibleCleanser[hh] = NULL;
}
continue;
}
//Trace from the player's eye to the paint cleanser
Ray_t playerCleanserRay;
playerCleanserRay.Init( vecPlayerEyePos, vecCleanserPos );
trace_t tr;
int mask = MASK_BLOCKLOS_AND_NPCS & ~CONTENTS_BLOCKLOS;
UTIL_TraceRay( playerCleanserRay, mask, pPlayer, COLLISION_GROUP_NONE, &tr );
//If there is nothing between the player and the cleanser
if( tr.fraction == 1.0f || tr.m_pEnt == m_PaintCleansers[i] )
{
if( bDebugging )
{
NDebugOverlay::Line( pPlayer->WorldSpaceCenter(), vecCleanserPos, 0, 255, 255, false, paint_cleanser_visibility_poll_frequency.GetFloat() );
}
Color debugColor( 255, 0, 0 );
//If this is the closest visible paint cleanser
if( flDistSqr < flClosestCleanserDist )
{
flClosestCleanserDist = flDistSqr;
pClosestCleanser = m_PaintCleansers[i];
debugColor = Color( 0, 255, 0 );
}
if( bDebugging )
{
NDebugOverlay::Cross3D( vecCleanserPos, 16, debugColor.r(), debugColor.g(), debugColor.b(), false, paint_cleanser_visibility_poll_frequency.GetFloat() );
}
}
else
{
if( bDebugging )
{
NDebugOverlay::Line( pPlayer->WorldSpaceCenter(), vecCleanserPos, 0, 0, 255, false, paint_cleanser_visibility_poll_frequency.GetFloat() );
}
}
} //For all the paint cleansers
//If the player can see a different cleanser
if( pClosestCleanser && pClosestCleanser != m_ppVisibleCleanser[hh] )
{
m_ppVisibleCleanser[hh] = pClosestCleanser;
if( pPlayer->Weapon_OwnsThisType( "weapon_paintgun" ) )
{
IGameEvent *event = gameeventmanager->CreateEvent( "paint_cleanser_visible" );
if ( event )
{
event->SetInt( "userid", pPlayer->GetUserID() );
event->SetInt( "subject", m_ppVisibleCleanser[hh]->entindex() );
gameeventmanager->FireEventClientSide( event );
}
}
}
//If there is no visible cleanser
else if( !m_ppVisibleCleanser[hh] && bCleanserWasVisible )
{
IGameEvent *event = gameeventmanager->CreateEvent( "paint_cleanser_not_visible" );
if( event )
{
event->SetInt( "userid", pPlayer->GetUserID() );
gameeventmanager->FireEventClientSide( event );
}
}
} //for each pPlayer
}
#endif