Team Fortress 2 Source Code as on 22/4/2020
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.

574 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "const.h"
  8. #include "toolframework/itoolentity.h"
  9. #include "entitylist.h"
  10. #include "toolframework/itoolsystem.h"
  11. #include "KeyValues.h"
  12. #include "icliententity.h"
  13. #include "iserverentity.h"
  14. #include "sceneentity.h"
  15. #include "particles/particles.h"
  16. //-----------------------------------------------------------------------------
  17. // Interface from engine to tools for manipulating entities
  18. //-----------------------------------------------------------------------------
  19. class CServerTools : public IServerTools
  20. {
  21. public:
  22. // Inherited from IServerTools
  23. virtual IServerEntity *GetIServerEntity( IClientEntity *pClientEntity );
  24. virtual bool GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer = NULL );
  25. virtual bool SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer = NULL );
  26. virtual int GetPlayerFOV( IClientEntity *pClientPlayer = NULL );
  27. virtual bool SetPlayerFOV( int fov, IClientEntity *pClientPlayer = NULL );
  28. virtual bool IsInNoClipMode( IClientEntity *pClientPlayer = NULL );
  29. virtual CBaseEntity *FirstEntity( void );
  30. virtual CBaseEntity *NextEntity( CBaseEntity *pEntity );
  31. virtual CBaseEntity *FindEntityByHammerID( int iHammerID );
  32. virtual bool GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen );
  33. virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue );
  34. virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue );
  35. virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue );
  36. virtual CBaseEntity *CreateEntityByName( const char *szClassName );
  37. virtual void DispatchSpawn( CBaseEntity *pEntity );
  38. virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen );
  39. virtual void AddOriginToPVS( const Vector &org );
  40. virtual void MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles );
  41. virtual bool DestroyEntityByHammerId( int iHammerID );
  42. virtual CBaseEntity *GetBaseEntityByEntIndex( int iEntIndex );
  43. virtual void RemoveEntity( CBaseEntity *pEntity );
  44. virtual void RemoveEntityImmediate( CBaseEntity *pEntity );
  45. virtual IEntityFactoryDictionary *GetEntityFactoryDictionary( void );
  46. virtual void SetMoveType( CBaseEntity *pEntity, int val );
  47. virtual void SetMoveType( CBaseEntity *pEntity, int val, int moveCollide );
  48. virtual void ResetSequence( CBaseAnimating *pEntity, int nSequence );
  49. virtual void ResetSequenceInfo( CBaseAnimating *pEntity );
  50. virtual void ClearMultiDamage( void );
  51. virtual void ApplyMultiDamage( void );
  52. virtual void AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity );
  53. virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore );
  54. virtual ITempEntsSystem *GetTempEntsSystem( void );
  55. virtual CBaseTempEntity *GetTempEntList( void );
  56. virtual CGlobalEntityList *GetEntityList( void );
  57. virtual bool IsEntityPtr( void *pTest );
  58. virtual CBaseEntity *FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName );
  59. virtual CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL );
  60. virtual CBaseEntity *FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius );
  61. virtual CBaseEntity *FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName );
  62. virtual CBaseEntity *FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName );
  63. virtual CBaseEntity *FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
  64. virtual CBaseEntity *FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
  65. virtual CBaseEntity *FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius );
  66. virtual CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius );
  67. virtual CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecMins, const Vector &vecMaxs );
  68. virtual CBaseEntity *FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
  69. virtual CBaseEntity *FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
  70. virtual CBaseEntity *FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
  71. virtual CBaseEntity *FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold );
  72. virtual CBaseEntity *FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname );
  73. virtual CBaseEntity *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
  74. };
  75. //-----------------------------------------------------------------------------
  76. // Singleton
  77. //-----------------------------------------------------------------------------
  78. static CServerTools g_ServerTools;
  79. // VSERVERTOOLS_INTERFACE_VERSION_1 is compatible with the latest since we're only adding things to the end, so expose that as well.
  80. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools001, VSERVERTOOLS_INTERFACE_VERSION_1, g_ServerTools );
  81. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools002, VSERVERTOOLS_INTERFACE_VERSION_2, g_ServerTools );
  82. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION, g_ServerTools );
  83. // When bumping the version to this interface, check that our assumption is still valid and expose the older version in the same way
  84. COMPILE_TIME_ASSERT( VSERVERTOOLS_INTERFACE_VERSION_INT == 3 );
  85. IServerEntity *CServerTools::GetIServerEntity( IClientEntity *pClientEntity )
  86. {
  87. if ( pClientEntity == NULL )
  88. return NULL;
  89. CBaseHandle ehandle = pClientEntity->GetRefEHandle();
  90. if ( ehandle.GetEntryIndex() >= MAX_EDICTS )
  91. return NULL; // the first MAX_EDICTS entities are networked, the rest are client or server only
  92. #if 0
  93. // this fails, since the server entities have extra bits in their serial numbers,
  94. // since 20 bits are reserved for serial numbers, except for networked entities, which are restricted to 10
  95. // Brian believes that everything should just restrict itself to 10 to make things simpler,
  96. // so if/when he changes NUM_SERIAL_NUM_BITS to 10, we can switch back to this simpler code
  97. IServerNetworkable *pNet = gEntList.GetServerNetworkable( ehandle );
  98. if ( pNet == NULL )
  99. return NULL;
  100. CBaseEntity *pServerEnt = pNet->GetBaseEntity();
  101. return pServerEnt;
  102. #else
  103. IHandleEntity *pEnt = gEntList.LookupEntityByNetworkIndex( ehandle.GetEntryIndex() );
  104. if ( pEnt == NULL )
  105. return NULL;
  106. CBaseHandle h = gEntList.GetNetworkableHandle( ehandle.GetEntryIndex() );
  107. const int mask = ( 1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS ) - 1;
  108. if ( !h.IsValid() || ( ( h.GetSerialNumber() & mask ) != ( ehandle.GetSerialNumber() & mask ) ) )
  109. return NULL;
  110. IServerUnknown *pUnk = static_cast< IServerUnknown* >( pEnt );
  111. return pUnk->GetBaseEntity();
  112. #endif
  113. }
  114. bool CServerTools::GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer )
  115. {
  116. IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
  117. CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
  118. if ( pPlayer == NULL )
  119. return false;
  120. org = pPlayer->EyePosition();
  121. ang = pPlayer->EyeAngles();
  122. return true;
  123. }
  124. bool CServerTools::SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer )
  125. {
  126. IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
  127. CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
  128. if ( pPlayer == NULL )
  129. return false;
  130. pPlayer->SetAbsOrigin( org - pPlayer->GetViewOffset() );
  131. pPlayer->SnapEyeAngles( ang );
  132. // Disengage from hierarchy
  133. pPlayer->SetParent( NULL );
  134. return true;
  135. }
  136. int CServerTools::GetPlayerFOV( IClientEntity *pClientPlayer )
  137. {
  138. IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
  139. CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
  140. if ( pPlayer == NULL )
  141. return 0;
  142. return pPlayer->GetFOV();
  143. }
  144. bool CServerTools::SetPlayerFOV( int fov, IClientEntity *pClientPlayer )
  145. {
  146. IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
  147. CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
  148. if ( pPlayer == NULL )
  149. return false;
  150. pPlayer->SetDefaultFOV( fov );
  151. CBaseEntity *pFOVOwner = pPlayer->GetFOVOwner();
  152. return pPlayer->SetFOV( pFOVOwner ? pFOVOwner : pPlayer, fov );
  153. }
  154. bool CServerTools::IsInNoClipMode( IClientEntity *pClientPlayer )
  155. {
  156. IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer );
  157. CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer();
  158. if ( pPlayer == NULL )
  159. return true;
  160. return pPlayer->GetMoveType() == MOVETYPE_NOCLIP;
  161. }
  162. CBaseEntity *CServerTools::FirstEntity( void )
  163. {
  164. return gEntList.FirstEnt();
  165. }
  166. CBaseEntity *CServerTools::NextEntity( CBaseEntity *pEntity )
  167. {
  168. CBaseEntity *pEnt;
  169. if ( pEntity == NULL )
  170. {
  171. pEnt = gEntList.FirstEnt();
  172. }
  173. else
  174. {
  175. pEnt = gEntList.NextEnt( (CBaseEntity *)pEntity );
  176. }
  177. return pEnt;
  178. }
  179. CBaseEntity *CServerTools::FindEntityByHammerID( int iHammerID )
  180. {
  181. CBaseEntity *pEntity = gEntList.FirstEnt();
  182. while (pEntity)
  183. {
  184. if (pEntity->m_iHammerID == iHammerID)
  185. return pEntity;
  186. pEntity = gEntList.NextEnt( pEntity );
  187. }
  188. return NULL;
  189. }
  190. bool CServerTools::GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen )
  191. {
  192. return pEntity->GetKeyValue( szField, szValue, iMaxLen );
  193. }
  194. bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue )
  195. {
  196. return pEntity->KeyValue( szField, szValue );
  197. }
  198. bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue )
  199. {
  200. return pEntity->KeyValue( szField, flValue );
  201. }
  202. bool CServerTools::SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue )
  203. {
  204. return pEntity->KeyValue( szField, vecValue );
  205. }
  206. //-----------------------------------------------------------------------------
  207. // entity spawning
  208. //-----------------------------------------------------------------------------
  209. CBaseEntity *CServerTools::CreateEntityByName( const char *szClassName )
  210. {
  211. return ::CreateEntityByName( szClassName );
  212. }
  213. void CServerTools::DispatchSpawn( CBaseEntity *pEntity )
  214. {
  215. ::DispatchSpawn( pEntity );
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Reload particle definitions
  219. //-----------------------------------------------------------------------------
  220. void CServerTools::ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen )
  221. {
  222. // FIXME: Use file name to determine if we care about this data
  223. CUtlBuffer buf( pBufData, nLen, CUtlBuffer::READ_ONLY );
  224. g_pParticleSystemMgr->ReadParticleConfigFile( buf, true );
  225. }
  226. void CServerTools::AddOriginToPVS( const Vector &org )
  227. {
  228. engine->AddOriginToPVS( org );
  229. }
  230. void CServerTools::MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles )
  231. {
  232. CBasePlayer *pPlayer = UTIL_GetListenServerHost();
  233. if ( !pPlayer )
  234. return;
  235. extern void EnableNoClip( CBasePlayer *pPlayer );
  236. EnableNoClip( pPlayer );
  237. Vector zOffset = pPlayer->EyePosition() - pPlayer->GetAbsOrigin();
  238. pPlayer->SetAbsOrigin( vPos - zOffset );
  239. pPlayer->SnapEyeAngles( vAngles );
  240. }
  241. bool CServerTools::DestroyEntityByHammerId( int iHammerID )
  242. {
  243. CBaseEntity *pEntity = (CBaseEntity*)FindEntityByHammerID( iHammerID );
  244. if ( !pEntity )
  245. return false;
  246. UTIL_Remove( pEntity );
  247. return true;
  248. }
  249. void CServerTools::RemoveEntity( CBaseEntity *pEntity )
  250. {
  251. UTIL_Remove( pEntity );
  252. }
  253. void CServerTools::RemoveEntityImmediate( CBaseEntity *pEntity )
  254. {
  255. UTIL_RemoveImmediate( pEntity );
  256. }
  257. CBaseEntity *CServerTools::GetBaseEntityByEntIndex( int iEntIndex )
  258. {
  259. edict_t *pEdict = INDEXENT( iEntIndex );
  260. if ( pEdict )
  261. return CBaseEntity::Instance( pEdict );
  262. else
  263. return NULL;
  264. }
  265. IEntityFactoryDictionary *CServerTools::GetEntityFactoryDictionary( void )
  266. {
  267. return ::EntityFactoryDictionary();
  268. }
  269. void CServerTools::SetMoveType( CBaseEntity *pEntity, int val )
  270. {
  271. pEntity->SetMoveType( (MoveType_t)val );
  272. }
  273. void CServerTools::SetMoveType( CBaseEntity *pEntity, int val, int moveCollide )
  274. {
  275. pEntity->SetMoveType( (MoveType_t)val, (MoveCollide_t)moveCollide );
  276. }
  277. void CServerTools::ResetSequence( CBaseAnimating *pEntity, int nSequence )
  278. {
  279. pEntity->ResetSequence( nSequence );
  280. }
  281. void CServerTools::ResetSequenceInfo( CBaseAnimating *pEntity )
  282. {
  283. pEntity->ResetSequenceInfo();
  284. }
  285. void CServerTools::ClearMultiDamage( void )
  286. {
  287. ::ClearMultiDamage();
  288. }
  289. void CServerTools::ApplyMultiDamage( void )
  290. {
  291. ::ApplyMultiDamage();
  292. }
  293. void CServerTools::AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity )
  294. {
  295. ::AddMultiDamage( pTakeDamageInfo, pEntity );
  296. }
  297. void CServerTools::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore )
  298. {
  299. ::RadiusDamage( info, vecSrc, flRadius, iClassIgnore, pEntityIgnore );
  300. }
  301. ITempEntsSystem *CServerTools::GetTempEntsSystem( void )
  302. {
  303. return (ITempEntsSystem *)te;
  304. }
  305. CBaseTempEntity *CServerTools::GetTempEntList( void )
  306. {
  307. return CBaseTempEntity::GetList();
  308. }
  309. CGlobalEntityList *CServerTools::GetEntityList( void )
  310. {
  311. return &gEntList;
  312. }
  313. bool CServerTools::IsEntityPtr( void *pTest )
  314. {
  315. return gEntList.IsEntityPtr( pTest );
  316. }
  317. CBaseEntity *CServerTools::FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName )
  318. {
  319. return gEntList.FindEntityByClassname( pStartEntity, szName );
  320. }
  321. CBaseEntity *CServerTools::FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller, IEntityFindFilter *pFilter )
  322. {
  323. return gEntList.FindEntityByName( pStartEntity, szName, pSearchingEntity, pActivator, pCaller, pFilter );
  324. }
  325. CBaseEntity *CServerTools::FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius )
  326. {
  327. return gEntList.FindEntityInSphere( pStartEntity, vecCenter, flRadius );
  328. }
  329. CBaseEntity *CServerTools::FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName )
  330. {
  331. return gEntList.FindEntityByTarget( pStartEntity, szName );
  332. }
  333. CBaseEntity *CServerTools::FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName )
  334. {
  335. return gEntList.FindEntityByModel( pStartEntity, szModelName );
  336. }
  337. CBaseEntity *CServerTools::FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller )
  338. {
  339. return gEntList.FindEntityByNameNearest( szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller );
  340. }
  341. CBaseEntity *CServerTools::FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller )
  342. {
  343. return gEntList.FindEntityByNameWithin( pStartEntity, szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller );
  344. }
  345. CBaseEntity *CServerTools::FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius )
  346. {
  347. return gEntList.FindEntityByClassnameNearest( szName, vecSrc, flRadius );
  348. }
  349. CBaseEntity *CServerTools::FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius )
  350. {
  351. return gEntList.FindEntityByClassnameWithin( pStartEntity, szName, vecSrc, flRadius );
  352. }
  353. CBaseEntity *CServerTools::FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecMins, const Vector &vecMaxs )
  354. {
  355. return gEntList.FindEntityByClassnameWithin( pStartEntity, szName, vecMins, vecMaxs );
  356. }
  357. CBaseEntity *CServerTools::FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller )
  358. {
  359. return gEntList.FindEntityGeneric( pStartEntity, szName, pSearchingEntity, pActivator, pCaller );
  360. }
  361. CBaseEntity *CServerTools::FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller )
  362. {
  363. return gEntList.FindEntityGenericWithin( pStartEntity, szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller );
  364. }
  365. CBaseEntity *CServerTools::FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller )
  366. {
  367. return gEntList.FindEntityGenericNearest( szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller );
  368. }
  369. CBaseEntity *CServerTools::FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold )
  370. {
  371. return gEntList.FindEntityNearestFacing( origin, facing, threshold );
  372. }
  373. CBaseEntity *CServerTools::FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname )
  374. {
  375. return gEntList.FindEntityClassNearestFacing( origin, facing, threshold, classname );
  376. }
  377. CBaseEntity *CServerTools::FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller )
  378. {
  379. return gEntList.FindEntityProcedural( szName, pSearchingEntity, pActivator, pCaller );
  380. }
  381. // Interface from engine to tools for manipulating entities
  382. class CServerChoreoTools : public IServerChoreoTools
  383. {
  384. public:
  385. // Iterates through ALL entities (separate list for client vs. server)
  386. virtual EntitySearchResult NextChoreoEntity( EntitySearchResult currentEnt )
  387. {
  388. CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( currentEnt );
  389. ent = gEntList.FindEntityByClassname( ent, "logic_choreographed_scene" );
  390. return reinterpret_cast< EntitySearchResult >( ent );
  391. }
  392. virtual const char *GetSceneFile( EntitySearchResult sr )
  393. {
  394. CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr );
  395. if ( !sr )
  396. return "";
  397. if ( Q_stricmp( ent->GetClassname(), "logic_choreographed_scene" ) )
  398. return "";
  399. return GetSceneFilename( ent );
  400. }
  401. // For interactive editing
  402. virtual int GetEntIndex( EntitySearchResult sr )
  403. {
  404. CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr );
  405. if ( !ent )
  406. return -1;
  407. return ent->entindex();
  408. }
  409. virtual void ReloadSceneFromDisk( int entindex )
  410. {
  411. CBaseEntity *ent = CBaseEntity::Instance( entindex );
  412. if ( !ent )
  413. return;
  414. ::ReloadSceneFromDisk( ent );
  415. }
  416. };
  417. static CServerChoreoTools g_ServerChoreoTools;
  418. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerChoreoTools, IServerChoreoTools, VSERVERCHOREOTOOLS_INTERFACE_VERSION, g_ServerChoreoTools );
  419. //------------------------------------------------------------------------------
  420. // Applies keyvalues to the entity by hammer ID.
  421. //------------------------------------------------------------------------------
  422. void CC_Ent_Keyvalue( const CCommand &args )
  423. {
  424. // Must have an odd number of arguments.
  425. if ( ( args.ArgC() < 4 ) || ( args.ArgC() & 1 ) )
  426. {
  427. Msg( "Format: ent_keyvalue <entity id> \"key1\" \"value1\" \"key2\" \"value2\" ... \"keyN\" \"valueN\"\n" );
  428. return;
  429. }
  430. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  431. CBaseEntity *pEnt;
  432. if ( FStrEq( args[1], "" ) || FStrEq( args[1], "!picker" ) )
  433. {
  434. if (!pPlayer)
  435. return;
  436. extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer );
  437. pEnt = FindPickerEntity( pPlayer );
  438. if ( !pEnt )
  439. {
  440. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "No entity in front of player.\n" );
  441. return;
  442. }
  443. }
  444. else if ( FStrEq( args[1], "!self" ) || FStrEq( args[1], "!caller" ) || FStrEq( args[1], "!activator" ) )
  445. {
  446. if (!pPlayer)
  447. return;
  448. pEnt = pPlayer;
  449. }
  450. else
  451. {
  452. int nID = atoi( args[1] );
  453. pEnt = g_ServerTools.FindEntityByHammerID( nID );
  454. if ( !pEnt )
  455. {
  456. Msg( "Entity ID %d not found.\n", nID );
  457. return;
  458. }
  459. }
  460. int nArg = 2;
  461. while ( nArg < args.ArgC() )
  462. {
  463. const char *pszKey = args[ nArg ];
  464. const char *pszValue = args[ nArg + 1 ];
  465. nArg += 2;
  466. g_ServerTools.SetKeyValue( pEnt, pszKey, pszValue );
  467. }
  468. }
  469. 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);