mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-24 04:37:57 +03:00
beaae8ac45
* Adds support for Visual Studio 2012 and 2013 * VR Mode: . Switches from headtrack.dll to sourcevr.dll . Improved readability of the UI in VR . Removed the IPD calibration tool. TF2 will now obey the Oculus configuration file. Use the Oculus calibration tool in your SDK or install and run "OpenVR" under Tools in Steam to calibrate your IPD. . Added dropdown to enable VR mode in the Video options. Removed the -vr command line option. . Added the ability to switch in and out of VR mode without quitting the game . By default VR mode will run full screen. To switch back to a borderless window set the vr_force_windowed convar. . Added support for VR mode on Linux * Many assorted bug fixes and other changes from Team Fortress in various shared files
459 lines
14 KiB
C++
459 lines
14 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================
|
|
#include "cbase.h"
|
|
#include "const.h"
|
|
#include "toolframework/itoolentity.h"
|
|
#include "entitylist.h"
|
|
#include "toolframework/itoolsystem.h"
|
|
#include "KeyValues.h"
|
|
#include "icliententity.h"
|
|
#include "iserverentity.h"
|
|
#include "sceneentity.h"
|
|
#include "particles/particles.h"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Interface from engine to tools for manipulating entities
|
|
//-----------------------------------------------------------------------------
|
|
class CServerTools : public IServerTools
|
|
{
|
|
public:
|
|
// Inherited from IServerTools
|
|
virtual IServerEntity *GetIServerEntity( IClientEntity *pClientEntity );
|
|
virtual bool GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer = NULL );
|
|
virtual bool SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer = NULL );
|
|
virtual int GetPlayerFOV( IClientEntity *pClientPlayer = NULL );
|
|
virtual bool SetPlayerFOV( int fov, IClientEntity *pClientPlayer = NULL );
|
|
virtual bool IsInNoClipMode( IClientEntity *pClientPlayer = NULL );
|
|
virtual CBaseEntity *FirstEntity( void );
|
|
virtual CBaseEntity *NextEntity( CBaseEntity *pEntity );
|
|
virtual CBaseEntity *FindEntityByHammerID( int iHammerID );
|
|
virtual bool GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen );
|
|
virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue );
|
|
virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue );
|
|
virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue );
|
|
virtual CBaseEntity *CreateEntityByName( const char *szClassName );
|
|
virtual void DispatchSpawn( CBaseEntity *pEntity );
|
|
virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen );
|
|
virtual void AddOriginToPVS( const Vector &org );
|
|
virtual void MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles );
|
|
virtual bool DestroyEntityByHammerId( int iHammerID );
|
|
virtual CBaseEntity *GetBaseEntityByEntIndex( int iEntIndex );
|
|
virtual void RemoveEntity( CBaseEntity *pEntity );
|
|
virtual void RemoveEntityImmediate( CBaseEntity *pEntity );
|
|
virtual IEntityFactoryDictionary *GetEntityFactoryDictionary( void );
|
|
virtual void SetMoveType( CBaseEntity *pEntity, int val );
|
|
virtual void SetMoveType( CBaseEntity *pEntity, int val, int moveCollide );
|
|
virtual void ResetSequence( CBaseAnimating *pEntity, int nSequence );
|
|
virtual void ResetSequenceInfo( CBaseAnimating *pEntity );
|
|
virtual void ClearMultiDamage( void );
|
|
virtual void ApplyMultiDamage( void );
|
|
virtual void AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity );
|
|
virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore );
|
|
virtual ITempEntsSystem *GetTempEntsSystem( void );
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Singleton
|
|
//-----------------------------------------------------------------------------
|
|
static CServerTools g_ServerTools;
|
|
|
|
// VSERVERTOOLS_INTERFACE_VERSION_1 is compatible with the latest since we're only adding things to the end, so expose that as well.
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools001, VSERVERTOOLS_INTERFACE_VERSION_1, g_ServerTools );
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION, g_ServerTools );
|
|
|
|
// When bumping the version to this interface, check that our assumption is still valid and expose the older version in the same way
|
|
COMPILE_TIME_ASSERT( VSERVERTOOLS_INTERFACE_VERSION_INT == 2 );
|
|
|
|
|
|
IServerEntity *CServerTools::GetIServerEntity( IClientEntity *pClientEntity )
|
|
{
|
|
if ( pClientEntity == NULL )
|
|
return NULL;
|
|
|
|
CBaseHandle ehandle = pClientEntity->GetRefEHandle();
|
|
if ( ehandle.GetEntryIndex() >= MAX_EDICTS )
|
|
return NULL; // the first MAX_EDICTS entities are networked, the rest are client or server only
|
|
|
|
#if 0
|
|
// this fails, since the server entities have extra bits in their serial numbers,
|
|
// since 20 bits are reserved for serial numbers, except for networked entities, which are restricted to 10
|
|
|
|
// Brian believes that everything should just restrict itself to 10 to make things simpler,
|
|
// so if/when he changes NUM_SERIAL_NUM_BITS to 10, we can switch back to this simpler code
|
|
|
|
IServerNetworkable *pNet = gEntList.GetServerNetworkable( ehandle );
|
|
if ( pNet == NULL )
|
|
return NULL;
|
|
|
|
CBaseEntity *pServerEnt = pNet->GetBaseEntity();
|
|
return pServerEnt;
|
|
#else
|
|
IHandleEntity *pEnt = gEntList.LookupEntityByNetworkIndex( ehandle.GetEntryIndex() );
|
|
if ( pEnt == NULL )
|
|
return NULL;
|
|
|
|
CBaseHandle h = gEntList.GetNetworkableHandle( ehandle.GetEntryIndex() );
|
|
const int mask = ( 1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS ) - 1;
|
|
if ( !h.IsValid() || ( ( h.GetSerialNumber() & mask ) != ( ehandle.GetSerialNumber() & mask ) ) )
|
|
return NULL;
|
|
|
|
IServerUnknown *pUnk = static_cast< IServerUnknown* >( pEnt );
|
|
return pUnk->GetBaseEntity();
|
|
#endif
|
|
}
|
|
|
|
bool CServerTools::GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer )
|
|
{
|
|
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
|
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
|
if ( pPlayer == NULL )
|
|
return false;
|
|
|
|
org = pPlayer->EyePosition();
|
|
ang = pPlayer->EyeAngles();
|
|
return true;
|
|
}
|
|
|
|
bool CServerTools::SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer )
|
|
{
|
|
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
|
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
|
if ( pPlayer == NULL )
|
|
return false;
|
|
|
|
pPlayer->SetAbsOrigin( org - pPlayer->GetViewOffset() );
|
|
pPlayer->SnapEyeAngles( ang );
|
|
|
|
// Disengage from hierarchy
|
|
pPlayer->SetParent( NULL );
|
|
|
|
return true;
|
|
}
|
|
|
|
int CServerTools::GetPlayerFOV( IClientEntity *pClientPlayer )
|
|
{
|
|
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
|
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
|
if ( pPlayer == NULL )
|
|
return 0;
|
|
|
|
return pPlayer->GetFOV();
|
|
}
|
|
|
|
bool CServerTools::SetPlayerFOV( int fov, IClientEntity *pClientPlayer )
|
|
{
|
|
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
|
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
|
if ( pPlayer == NULL )
|
|
return false;
|
|
|
|
pPlayer->SetDefaultFOV( fov );
|
|
CBaseEntity *pFOVOwner = pPlayer->GetFOVOwner();
|
|
return pPlayer->SetFOV( pFOVOwner ? pFOVOwner : pPlayer, fov );
|
|
}
|
|
|
|
bool CServerTools::IsInNoClipMode( IClientEntity *pClientPlayer )
|
|
{
|
|
IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
|
|
CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
|
|
if ( pPlayer == NULL )
|
|
return true;
|
|
|
|
return pPlayer->GetMoveType() == MOVETYPE_NOCLIP;
|
|
}
|
|
|
|
CBaseEntity *CServerTools::FirstEntity( void )
|
|
{
|
|
return gEntList.FirstEnt();
|
|
}
|
|
|
|
CBaseEntity *CServerTools::NextEntity( CBaseEntity *pEntity )
|
|
{
|
|
CBaseEntity *pEnt;
|
|
|
|
if ( pEntity == NULL )
|
|
{
|
|
pEnt = gEntList.FirstEnt();
|
|
}
|
|
else
|
|
{
|
|
pEnt = gEntList.NextEnt( (CBaseEntity *)pEntity );
|
|
}
|
|
return pEnt;
|
|
}
|
|
|
|
CBaseEntity *CServerTools::FindEntityByHammerID( int iHammerID )
|
|
{
|
|
CBaseEntity *pEntity = gEntList.FirstEnt();
|
|
|
|
while (pEntity)
|
|
{
|
|
if (pEntity->m_iHammerID == iHammerID)
|
|
return pEntity;
|
|
pEntity = gEntList.NextEnt( pEntity );
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool CServerTools::GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen )
|
|
{
|
|
return pEntity->GetKeyValue( szField, szValue, iMaxLen );
|
|
}
|
|
|
|
bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue )
|
|
{
|
|
return pEntity->KeyValue( szField, szValue );
|
|
}
|
|
|
|
bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue )
|
|
{
|
|
return pEntity->KeyValue( szField, flValue );
|
|
}
|
|
|
|
bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue )
|
|
{
|
|
return pEntity->KeyValue( szField, vecValue );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// entity spawning
|
|
//-----------------------------------------------------------------------------
|
|
CBaseEntity *CServerTools::CreateEntityByName( const char *szClassName )
|
|
{
|
|
return ::CreateEntityByName( szClassName );
|
|
}
|
|
|
|
void CServerTools::DispatchSpawn( CBaseEntity *pEntity )
|
|
{
|
|
::DispatchSpawn( pEntity );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Reload particle definitions
|
|
//-----------------------------------------------------------------------------
|
|
void CServerTools::ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen )
|
|
{
|
|
// FIXME: Use file name to determine if we care about this data
|
|
CUtlBuffer buf( pBufData, nLen, CUtlBuffer::READ_ONLY );
|
|
g_pParticleSystemMgr->ReadParticleConfigFile( buf, true );
|
|
}
|
|
|
|
void CServerTools::AddOriginToPVS( const Vector &org )
|
|
{
|
|
engine->AddOriginToPVS( org );
|
|
}
|
|
|
|
void CServerTools::MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles )
|
|
{
|
|
CBasePlayer *pPlayer = UTIL_GetListenServerHost();
|
|
if ( !pPlayer )
|
|
return;
|
|
|
|
extern void EnableNoClip( CBasePlayer *pPlayer );
|
|
EnableNoClip( pPlayer );
|
|
|
|
Vector zOffset = pPlayer->EyePosition() - pPlayer->GetAbsOrigin();
|
|
|
|
pPlayer->SetAbsOrigin( vPos - zOffset );
|
|
pPlayer->SnapEyeAngles( vAngles );
|
|
}
|
|
|
|
bool CServerTools::DestroyEntityByHammerId( int iHammerID )
|
|
{
|
|
CBaseEntity *pEntity = (CBaseEntity*)FindEntityByHammerID( iHammerID );
|
|
if ( !pEntity )
|
|
return false;
|
|
|
|
UTIL_Remove( pEntity );
|
|
return true;
|
|
}
|
|
|
|
void CServerTools::RemoveEntity( CBaseEntity *pEntity )
|
|
{
|
|
UTIL_Remove( pEntity );
|
|
}
|
|
|
|
void CServerTools::RemoveEntityImmediate( CBaseEntity *pEntity )
|
|
{
|
|
UTIL_RemoveImmediate( pEntity );
|
|
}
|
|
|
|
CBaseEntity *CServerTools::GetBaseEntityByEntIndex( int iEntIndex )
|
|
{
|
|
edict_t *pEdict = INDEXENT( iEntIndex );
|
|
if ( pEdict )
|
|
return CBaseEntity::Instance( pEdict );
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
IEntityFactoryDictionary *CServerTools::GetEntityFactoryDictionary( void )
|
|
{
|
|
return ::EntityFactoryDictionary();
|
|
}
|
|
|
|
|
|
void CServerTools::SetMoveType( CBaseEntity *pEntity, int val )
|
|
{
|
|
pEntity->SetMoveType( (MoveType_t)val );
|
|
}
|
|
|
|
void CServerTools::SetMoveType( CBaseEntity *pEntity, int val, int moveCollide )
|
|
{
|
|
pEntity->SetMoveType( (MoveType_t)val, (MoveCollide_t)moveCollide );
|
|
}
|
|
|
|
void CServerTools::ResetSequence( CBaseAnimating *pEntity, int nSequence )
|
|
{
|
|
pEntity->ResetSequence( nSequence );
|
|
}
|
|
|
|
void CServerTools::ResetSequenceInfo( CBaseAnimating *pEntity )
|
|
{
|
|
pEntity->ResetSequenceInfo();
|
|
}
|
|
|
|
|
|
void CServerTools::ClearMultiDamage( void )
|
|
{
|
|
::ClearMultiDamage();
|
|
}
|
|
|
|
void CServerTools::ApplyMultiDamage( void )
|
|
{
|
|
::ApplyMultiDamage();
|
|
}
|
|
|
|
void CServerTools::AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity )
|
|
{
|
|
::AddMultiDamage( pTakeDamageInfo, pEntity );
|
|
}
|
|
|
|
void CServerTools::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore )
|
|
{
|
|
::RadiusDamage( info, vecSrc, flRadius, iClassIgnore, pEntityIgnore );
|
|
}
|
|
|
|
|
|
ITempEntsSystem *CServerTools::GetTempEntsSystem( void )
|
|
{
|
|
return (ITempEntsSystem *)te;
|
|
}
|
|
|
|
|
|
// Interface from engine to tools for manipulating entities
|
|
class CServerChoreoTools : public IServerChoreoTools
|
|
{
|
|
public:
|
|
// Iterates through ALL entities (separate list for client vs. server)
|
|
virtual EntitySearchResult NextChoreoEntity( EntitySearchResult currentEnt )
|
|
{
|
|
CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( currentEnt );
|
|
ent = gEntList.FindEntityByClassname( ent, "logic_choreographed_scene" );
|
|
return reinterpret_cast< EntitySearchResult >( ent );
|
|
}
|
|
|
|
virtual const char *GetSceneFile( EntitySearchResult sr )
|
|
{
|
|
CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr );
|
|
if ( !sr )
|
|
return "";
|
|
|
|
if ( Q_stricmp( ent->GetClassname(), "logic_choreographed_scene" ) )
|
|
return "";
|
|
|
|
return GetSceneFilename( ent );
|
|
}
|
|
|
|
// For interactive editing
|
|
virtual int GetEntIndex( EntitySearchResult sr )
|
|
{
|
|
CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr );
|
|
if ( !ent )
|
|
return -1;
|
|
|
|
return ent->entindex();
|
|
}
|
|
|
|
virtual void ReloadSceneFromDisk( int entindex )
|
|
{
|
|
CBaseEntity *ent = CBaseEntity::Instance( entindex );
|
|
if ( !ent )
|
|
return;
|
|
|
|
::ReloadSceneFromDisk( ent );
|
|
}
|
|
};
|
|
|
|
|
|
static CServerChoreoTools g_ServerChoreoTools;
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerChoreoTools, IServerChoreoTools, VSERVERCHOREOTOOLS_INTERFACE_VERSION, g_ServerChoreoTools );
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Applies keyvalues to the entity by hammer ID.
|
|
//------------------------------------------------------------------------------
|
|
void CC_Ent_Keyvalue( const CCommand &args )
|
|
{
|
|
// Must have an odd number of arguments.
|
|
if ( ( args.ArgC() < 4 ) || ( args.ArgC() & 1 ) )
|
|
{
|
|
Msg( "Format: ent_keyvalue <entity id> \"key1\" \"value1\" \"key2\" \"value2\" ... \"keyN\" \"valueN\"\n" );
|
|
return;
|
|
}
|
|
|
|
CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
|
|
CBaseEntity *pEnt;
|
|
if ( FStrEq( args[1], "" ) || FStrEq( args[1], "!picker" ) )
|
|
{
|
|
if (!pPlayer)
|
|
return;
|
|
|
|
extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer );
|
|
pEnt = FindPickerEntity( pPlayer );
|
|
|
|
if ( !pEnt )
|
|
{
|
|
ClientPrint( pPlayer, HUD_PRINTCONSOLE, "No entity in front of player.\n" );
|
|
return;
|
|
}
|
|
}
|
|
else if ( FStrEq( args[1], "!self" ) || FStrEq( args[1], "!caller" ) || FStrEq( args[1], "!activator" ) )
|
|
{
|
|
if (!pPlayer)
|
|
return;
|
|
|
|
pEnt = pPlayer;
|
|
}
|
|
else
|
|
{
|
|
int nID = atoi( args[1] );
|
|
|
|
pEnt = g_ServerTools.FindEntityByHammerID( nID );
|
|
if ( !pEnt )
|
|
{
|
|
Msg( "Entity ID %d not found.\n", nID );
|
|
return;
|
|
}
|
|
}
|
|
|
|
int nArg = 2;
|
|
while ( nArg < args.ArgC() )
|
|
{
|
|
const char *pszKey = args[ nArg ];
|
|
const char *pszValue = args[ nArg + 1 ];
|
|
nArg += 2;
|
|
|
|
g_ServerTools.SetKeyValue( pEnt, pszKey, pszValue );
|
|
}
|
|
}
|
|
|
|
static ConCommand ent_keyvalue("ent_keyvalue", CC_Ent_Keyvalue, "Applies the comma delimited key=value pairs to the entity with the given Hammer ID.\n\tFormat: ent_keyvalue <entity id> <key1> <value1> <key2> <value2> ... <keyN> <valueN>\n", FCVAR_CHEAT);
|