mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-29 17:43:01 +00:00
269 lines
8.1 KiB
C++
269 lines
8.1 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: A camera entity that's used by the -makedevshots system to take
|
||
|
// dev screenshots everytime the map is checked into source control.
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "tier0/icommandline.h"
|
||
|
#include "igamesystem.h"
|
||
|
#include "filesystem.h"
|
||
|
#include <KeyValues.h>
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
int g_iDevShotCameraCount = 0;
|
||
|
#define DEVSHOT_INITIAL_WAIT 5 // Time after the level spawn before the first devshot camera takes it's shot
|
||
|
#define DEVSHOT_INTERVAL 5 // Time between each devshot camera taking it's shot
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: A camera entity that's used by the -makedevshots system to take
|
||
|
// dev screenshots everytime the map is checked into source control.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CPointDevShotCamera : public CBaseEntity
|
||
|
{
|
||
|
DECLARE_CLASS( CPointDevShotCamera, CBaseEntity );
|
||
|
public:
|
||
|
DECLARE_DATADESC();
|
||
|
|
||
|
void Spawn( void );
|
||
|
void DevShotThink_Setup( void );
|
||
|
void DevShotThink_TakeShot( void );
|
||
|
void DevShotThink_PostShot( void );
|
||
|
|
||
|
// Always transmit to clients so they know where to move the view to
|
||
|
virtual int UpdateTransmitState();
|
||
|
|
||
|
private:
|
||
|
string_t m_iszCameraName;
|
||
|
int m_iFOV;
|
||
|
};
|
||
|
|
||
|
BEGIN_DATADESC( CPointDevShotCamera )
|
||
|
DEFINE_FUNCTION( DevShotThink_Setup ),
|
||
|
DEFINE_FUNCTION( DevShotThink_TakeShot ),
|
||
|
DEFINE_FUNCTION( DevShotThink_PostShot ),
|
||
|
|
||
|
DEFINE_KEYFIELD( m_iszCameraName, FIELD_STRING, "cameraname" ),
|
||
|
DEFINE_KEYFIELD( m_iFOV, FIELD_INTEGER, "FOV" ),
|
||
|
END_DATADESC()
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( point_devshot_camera, CPointDevShotCamera );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Convenience function so we don't have to make this check all over
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static CBasePlayer * UTIL_GetLocalPlayerOrListenServerHost( void )
|
||
|
{
|
||
|
if ( gpGlobals->maxClients > 1 )
|
||
|
{
|
||
|
if ( engine->IsDedicatedServer() )
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return UTIL_GetListenServerHost();
|
||
|
}
|
||
|
|
||
|
return UTIL_GetLocalPlayer();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPointDevShotCamera::Spawn( void )
|
||
|
{
|
||
|
BaseClass::Spawn();
|
||
|
|
||
|
// Remove this entity immediately if we're not making devshots
|
||
|
if ( !CommandLine()->FindParm("-makedevshots") )
|
||
|
{
|
||
|
UTIL_Remove( this );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Take a screenshot when it's my turn
|
||
|
SetThink( &CPointDevShotCamera::DevShotThink_Setup );
|
||
|
SetNextThink( gpGlobals->curtime + DEVSHOT_INITIAL_WAIT + (g_iDevShotCameraCount * DEVSHOT_INTERVAL) );
|
||
|
|
||
|
g_iDevShotCameraCount++;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CPointDevShotCamera::UpdateTransmitState()
|
||
|
{
|
||
|
// always transmit if currently used by a monitor
|
||
|
return SetTransmitState( FL_EDICT_ALWAYS );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPointDevShotCamera::DevShotThink_Setup( void )
|
||
|
{
|
||
|
// Move the player to the devshot camera
|
||
|
CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost();
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
// Hide stuff
|
||
|
engine->ClientCommand( pPlayer->edict(), "developer 0" );
|
||
|
engine->ClientCommand( pPlayer->edict(), "cl_drawhud 0" );
|
||
|
engine->ClientCommand( pPlayer->edict(), "sv_cheats 1" );
|
||
|
engine->ClientCommand( pPlayer->edict(), "god" );
|
||
|
engine->ClientCommand( pPlayer->edict(), "notarget" );
|
||
|
|
||
|
pPlayer->AddSolidFlags( FSOLID_NOT_SOLID );
|
||
|
pPlayer->EnableControl(FALSE);
|
||
|
pPlayer->SetViewEntity( this );
|
||
|
pPlayer->SetFOV( this, m_iFOV );
|
||
|
|
||
|
// Hide the player's viewmodel
|
||
|
if ( pPlayer->GetActiveWeapon() )
|
||
|
{
|
||
|
pPlayer->GetActiveWeapon()->AddEffects( EF_NODRAW );
|
||
|
}
|
||
|
|
||
|
DispatchUpdateTransmitState();
|
||
|
|
||
|
// Now take the shot next frame
|
||
|
SetThink( &CPointDevShotCamera::DevShotThink_TakeShot );
|
||
|
SetNextThink( gpGlobals->curtime );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPointDevShotCamera::DevShotThink_TakeShot( void )
|
||
|
{
|
||
|
// Take the screenshot
|
||
|
CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost();
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
engine->ClientCommand( pPlayer->edict(), "devshots_screenshot \"%s\"", STRING(m_iszCameraName) );
|
||
|
|
||
|
// Now take the shot next frame
|
||
|
SetThink( &CPointDevShotCamera::DevShotThink_PostShot );
|
||
|
SetNextThink( gpGlobals->curtime + (DEVSHOT_INTERVAL - 1) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CPointDevShotCamera::DevShotThink_PostShot( void )
|
||
|
{
|
||
|
// Take the screenshot
|
||
|
CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost();
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
pPlayer->SetFOV( this, 0 );
|
||
|
|
||
|
// If all cameras have taken their shots, move to the next map
|
||
|
g_iDevShotCameraCount--;
|
||
|
if ( !g_iDevShotCameraCount )
|
||
|
{
|
||
|
engine->ClientCommand( pPlayer->edict(), "devshots_nextmap" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Game system to detect maps without cameras in them, and move on
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CDevShotSystem : public CAutoGameSystemPerFrame
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CDevShotSystem( char const *name ) : CAutoGameSystemPerFrame( name )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual void LevelInitPreEntity()
|
||
|
{
|
||
|
m_bIssuedNextMapCommand = false;
|
||
|
g_iDevShotCameraCount = 0;
|
||
|
m_bParsedMapFile = false;
|
||
|
}
|
||
|
|
||
|
virtual void SafeRemoveIfDesired( void )
|
||
|
{
|
||
|
// If we're not making devshots, remove this system immediately
|
||
|
if ( !CommandLine()->FindParm("-makedevshots") )
|
||
|
{
|
||
|
Remove( this );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void FrameUpdatePostEntityThink( void )
|
||
|
{
|
||
|
// Wait until we're all spawned in
|
||
|
if ( gpGlobals->curtime < 5 )
|
||
|
return;
|
||
|
|
||
|
if ( m_bIssuedNextMapCommand )
|
||
|
return;
|
||
|
|
||
|
if ( !m_bParsedMapFile )
|
||
|
{
|
||
|
m_bParsedMapFile = true;
|
||
|
|
||
|
// See if we've got a camera file to import cameras from
|
||
|
char szFullName[512];
|
||
|
Q_snprintf(szFullName,sizeof(szFullName), "maps/%s.txt", STRING( gpGlobals->mapname ));
|
||
|
KeyValues *pkvMapCameras = new KeyValues( "MapCameras" );
|
||
|
if ( pkvMapCameras->LoadFromFile( filesystem, szFullName, "MOD" ) )
|
||
|
{
|
||
|
Warning( "Devshots: Loading point_devshot_camera positions from %s. \n", szFullName );
|
||
|
|
||
|
// Get each camera, and add it to our list
|
||
|
KeyValues *pkvCamera = pkvMapCameras->GetFirstSubKey();
|
||
|
while ( pkvCamera )
|
||
|
{
|
||
|
// Get camera name
|
||
|
const char *pCameraName = pkvCamera->GetName();
|
||
|
|
||
|
// Make a camera, and move it to the position specified
|
||
|
CPointDevShotCamera *pCamera = (CPointDevShotCamera*)CreateEntityByName( "point_devshot_camera" );
|
||
|
Assert( pCamera );
|
||
|
pCamera->KeyValue( "cameraname", pCameraName );
|
||
|
pCamera->KeyValue( "origin", pkvCamera->GetString( "origin", "0 0 0" ) );
|
||
|
pCamera->KeyValue( "angles", pkvCamera->GetString( "angles", "0 0 0" ) );
|
||
|
pCamera->KeyValue( "FOV", pkvCamera->GetString( "FOV", "75" ) );
|
||
|
DispatchSpawn( pCamera );
|
||
|
pCamera->Activate();
|
||
|
|
||
|
// Move to next camera
|
||
|
pkvCamera = pkvCamera->GetNextKey();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !g_iDevShotCameraCount )
|
||
|
{
|
||
|
Warning( "Devshots: No point_devshot_camera in %s. Moving to next map.\n", STRING( gpGlobals->mapname ) );
|
||
|
|
||
|
CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost();
|
||
|
if ( pPlayer )
|
||
|
{
|
||
|
engine->ClientCommand( pPlayer->edict(), "devshots_nextmap" );
|
||
|
m_bIssuedNextMapCommand = true;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
bool m_bIssuedNextMapCommand;
|
||
|
bool m_bParsedMapFile;
|
||
|
};
|
||
|
|
||
|
CDevShotSystem DevShotSystem( "CDevShotSystem" );
|