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.

5621 lines
154 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include <stdarg.h>
  8. #include "baseflex.h"
  9. #include "entitylist.h"
  10. #include "choreoevent.h"
  11. #include "choreoactor.h"
  12. #include "choreochannel.h"
  13. #include "choreoscene.h"
  14. #include "studio.h"
  15. #include "networkstringtable_gamedll.h"
  16. #include "ai_basenpc.h"
  17. #include "engine/IEngineSound.h"
  18. #include "ai_navigator.h"
  19. #include "saverestore_utlvector.h"
  20. #include "ai_baseactor.h"
  21. #include "AI_Criteria.h"
  22. #include "tier1/strtools.h"
  23. #include "checksum_crc.h"
  24. #include "SoundEmitterSystem/isoundemittersystembase.h"
  25. #include "utlbuffer.h"
  26. #include "tier0/icommandline.h"
  27. #include "sceneentity.h"
  28. #include "datacache/idatacache.h"
  29. #include "dt_utlvector_send.h"
  30. #include "ichoreoeventcallback.h"
  31. #include "scenefilecache/ISceneFileCache.h"
  32. #include "SceneCache.h"
  33. #include "scripted.h"
  34. #include "env_debughistory.h"
  35. #ifdef HL2_EPISODIC
  36. #include "npc_alyx_episodic.h"
  37. #endif // HL2_EPISODIC
  38. // memdbgon must be the last include file in a .cpp file!!!
  39. #include "tier0/memdbgon.h"
  40. extern ISoundEmitterSystemBase *soundemitterbase;
  41. extern ISceneFileCache *scenefilecache;
  42. class CSceneEntity;
  43. class CBaseFlex;
  44. // VCDS are loaded from their compiled/binary format (much faster)
  45. // Requies vcds be saved as compiled assets
  46. //#define COMPILED_VCDS 1
  47. static ConVar scene_forcecombined( "scene_forcecombined", "0", 0, "When playing back, force use of combined .wav files even in english." );
  48. static ConVar scene_maxcaptionradius( "scene_maxcaptionradius", "1200", 0, "Only show closed captions if recipient is within this many units of speaking actor (0==disabled)." );
  49. // Assume sound system is 100 msec lagged (only used if we can't find snd_mixahead cvar!)
  50. #define SOUND_SYSTEM_LATENCY_DEFAULT ( 0.1f )
  51. // Think every 50 msec (FIXME: Try 10hz?)
  52. #define SCENE_THINK_INTERVAL 0.001 // FIXME: make scene's think in concert with their npc's
  53. #define FINDNAMEDENTITY_MAX_ENTITIES 32 // max number of entities to be considered for random entity selection in FindNamedEntity
  54. // List of the last 5 lines of speech from NPCs for bug reports
  55. static recentNPCSpeech_t speechListSounds[ SPEECH_LIST_MAX_SOUNDS ] = { { 0, "", "" }, { 0, "", "" }, { 0, "", "" }, { 0, "", "" }, { 0, "", "" } };
  56. static int speechListIndex = 0;
  57. // Only allow scenes to change their pitch within a range of values
  58. #define SCENE_MIN_PITCH 0.25f
  59. #define SCENE_MAX_PITCH 2.5f
  60. //===========================================================================================================
  61. // SCENE LIST MANAGER
  62. //===========================================================================================================
  63. #define SCENE_LIST_MANAGER_MAX_SCENES 16
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Entity that manages a list of scenes
  66. //-----------------------------------------------------------------------------
  67. class CSceneListManager : public CLogicalEntity
  68. {
  69. DECLARE_CLASS( CSceneListManager, CLogicalEntity );
  70. public:
  71. DECLARE_DATADESC();
  72. virtual void Activate( void );
  73. void ShutdownList( void );
  74. void SceneStarted( CBaseEntity *pSceneOrManager );
  75. void AddListManager( CSceneListManager *pManager );
  76. void RemoveScene( int iIndex );
  77. // Inputs
  78. void InputShutdown( inputdata_t &inputdata );
  79. private:
  80. CUtlVector< CHandle< CSceneListManager > > m_hListManagers;
  81. string_t m_iszScenes[SCENE_LIST_MANAGER_MAX_SCENES];
  82. EHANDLE m_hScenes[SCENE_LIST_MANAGER_MAX_SCENES];
  83. };
  84. //-----------------------------------------------------------------------------
  85. // Purpose: This class exists solely to call think on all scene entities in a deterministic order
  86. //-----------------------------------------------------------------------------
  87. class CSceneManager : public CBaseEntity
  88. {
  89. DECLARE_CLASS( CSceneManager, CBaseEntity );
  90. DECLARE_DATADESC();
  91. public:
  92. virtual void Spawn()
  93. {
  94. BaseClass::Spawn();
  95. SetNextThink( gpGlobals->curtime );
  96. }
  97. virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_DONT_SAVE; }
  98. virtual void Think();
  99. void ClearAllScenes();
  100. void AddSceneEntity( CSceneEntity *scene );
  101. void RemoveSceneEntity( CSceneEntity *scene );
  102. void QueueRestoredSound( CBaseFlex *actor, char const *soundname, soundlevel_t soundlevel, float time_in_past );
  103. void OnClientActive( CBasePlayer *player );
  104. void RemoveActorFromScenes( CBaseFlex *pActor, bool bInstancedOnly, bool bNonIdleOnly, const char *pszThisSceneOnly );
  105. void RemoveScenesInvolvingActor( CBaseFlex *pActor );
  106. void PauseActorsScenes( CBaseFlex *pActor, bool bInstancedOnly );
  107. bool IsInInterruptableScenes( CBaseFlex *pActor );
  108. void ResumeActorsScenes( CBaseFlex *pActor, bool bInstancedOnly );
  109. void QueueActorsScenesToResume( CBaseFlex *pActor, bool bInstancedOnly );
  110. bool IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes );
  111. bool IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes );
  112. bool IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes );
  113. bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes );
  114. private:
  115. struct CRestoreSceneSound
  116. {
  117. CRestoreSceneSound()
  118. {
  119. actor = NULL;
  120. soundname[ 0 ] = NULL;
  121. soundlevel = SNDLVL_NORM;
  122. time_in_past = 0.0f;
  123. }
  124. CHandle< CBaseFlex > actor;
  125. char soundname[ 128 ];
  126. soundlevel_t soundlevel;
  127. float time_in_past;
  128. };
  129. CUtlVector< CHandle< CSceneEntity > > m_ActiveScenes;
  130. CUtlVector< CRestoreSceneSound > m_QueuedSceneSounds;
  131. };
  132. //---------------------------------------------------------
  133. // Save/Restore
  134. //---------------------------------------------------------
  135. BEGIN_DATADESC( CSceneManager )
  136. DEFINE_UTLVECTOR( m_ActiveScenes, FIELD_EHANDLE ),
  137. // DEFINE_FIELD( m_QueuedSceneSounds, CUtlVector < CRestoreSceneSound > ), // Don't save/restore this, it's created and used by OnRestore only
  138. END_DATADESC()
  139. #ifdef DISABLE_DEBUG_HISTORY
  140. #define LocalScene_Printf Scene_Printf
  141. #else
  142. //-----------------------------------------------------------------------------
  143. // Purpose:
  144. // Input : *pFormat -
  145. // ... -
  146. // Output : static void
  147. //-----------------------------------------------------------------------------
  148. void LocalScene_Printf( const char *pFormat, ... )
  149. {
  150. va_list marker;
  151. char msg[8192];
  152. va_start(marker, pFormat);
  153. Q_vsnprintf(msg, sizeof(msg), pFormat, marker);
  154. va_end(marker);
  155. Scene_Printf( "%s", msg );
  156. ADD_DEBUG_HISTORY( HISTORY_SCENE_PRINT, UTIL_VarArgs( "(%0.2f) %s", gpGlobals->curtime, msg ) );
  157. }
  158. #endif
  159. //-----------------------------------------------------------------------------
  160. // Purpose:
  161. // Input : *filename -
  162. // **buffer -
  163. // Output : Returns true on success, false on failure.
  164. //-----------------------------------------------------------------------------
  165. bool CopySceneFileIntoMemory( char const *pFilename, void **pBuffer, int *pSize )
  166. {
  167. size_t bufSize = scenefilecache->GetSceneBufferSize( pFilename );
  168. if ( bufSize > 0 )
  169. {
  170. *pBuffer = new byte[bufSize];
  171. *pSize = bufSize;
  172. return scenefilecache->GetSceneData( pFilename, (byte *)(*pBuffer), bufSize );
  173. }
  174. *pBuffer = 0;
  175. *pSize = 0;
  176. return false;
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Purpose:
  180. //-----------------------------------------------------------------------------
  181. void FreeSceneFileMemory( void *buffer )
  182. {
  183. delete[] (byte*) buffer;
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Binary compiled VCDs get their strings from a pool
  187. //-----------------------------------------------------------------------------
  188. class CChoreoStringPool : public IChoreoStringPool
  189. {
  190. public:
  191. short FindOrAddString( const char *pString )
  192. {
  193. // huh?, no compilation at run time, only fetches
  194. Assert( 0 );
  195. return -1;
  196. }
  197. bool GetString( short stringId, char *buff, int buffSize )
  198. {
  199. // fetch from compiled pool
  200. const char *pString = scenefilecache->GetSceneString( stringId );
  201. if ( !pString )
  202. {
  203. V_strncpy( buff, "", buffSize );
  204. return false;
  205. }
  206. V_strncpy( buff, pString, buffSize );
  207. return true;
  208. }
  209. };
  210. CChoreoStringPool g_ChoreoStringPool;
  211. //-----------------------------------------------------------------------------
  212. // Purpose: Singleton scene manager. Created by first placed scene or recreated it it's deleted for some unknown reason
  213. // Output : CSceneManager
  214. //-----------------------------------------------------------------------------
  215. CSceneManager *GetSceneManager()
  216. {
  217. // Create it if it doesn't exist
  218. static CHandle< CSceneManager > s_SceneManager;
  219. if ( s_SceneManager == NULL )
  220. {
  221. s_SceneManager = ( CSceneManager * )CreateEntityByName( "scene_manager" );
  222. Assert( s_SceneManager );
  223. if ( s_SceneManager )
  224. {
  225. s_SceneManager->Spawn();
  226. }
  227. }
  228. Assert( s_SceneManager );
  229. return s_SceneManager;
  230. }
  231. //-----------------------------------------------------------------------------
  232. // Purpose:
  233. // Input : *player -
  234. //-----------------------------------------------------------------------------
  235. void SceneManager_ClientActive( CBasePlayer *player )
  236. {
  237. Assert( GetSceneManager() );
  238. if ( GetSceneManager() )
  239. {
  240. GetSceneManager()->OnClientActive( player );
  241. }
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose: FIXME, need to deal with save/restore
  245. //-----------------------------------------------------------------------------
  246. class CSceneEntity : public CPointEntity, public IChoreoEventCallback
  247. {
  248. friend class CInstancedSceneEntity;
  249. public:
  250. enum
  251. {
  252. SCENE_ACTION_UNKNOWN = 0,
  253. SCENE_ACTION_CANCEL,
  254. SCENE_ACTION_RESUME,
  255. };
  256. enum
  257. {
  258. SCENE_BUSYACTOR_DEFAULT = 0,
  259. SCENE_BUSYACTOR_WAIT,
  260. SCENE_BUSYACTOR_INTERRUPT,
  261. SCENE_BUSYACTOR_INTERRUPT_CANCEL,
  262. };
  263. DECLARE_CLASS( CSceneEntity, CPointEntity );
  264. DECLARE_SERVERCLASS();
  265. CSceneEntity( void );
  266. ~CSceneEntity( void );
  267. // From IChoreoEventCallback
  268. virtual void StartEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
  269. virtual void EndEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
  270. virtual void ProcessEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
  271. virtual bool CheckEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
  272. virtual int UpdateTransmitState();
  273. virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo );
  274. void SetRecipientFilter( IRecipientFilter *filter );
  275. virtual void Activate();
  276. virtual void Precache( void );
  277. virtual void Spawn( void );
  278. virtual void UpdateOnRemove( void );
  279. virtual void OnRestore();
  280. virtual void OnLoaded();
  281. DECLARE_DATADESC();
  282. virtual void OnSceneFinished( bool canceled, bool fireoutput );
  283. virtual void DoThink( float frametime );
  284. virtual void PauseThink( void );
  285. bool IsPlayingBack() const { return m_bIsPlayingBack; }
  286. bool IsPaused() const { return m_bPaused; }
  287. bool IsMultiplayer() const { return m_bMultiplayer; }
  288. bool IsInterruptable();
  289. virtual void ClearInterrupt();
  290. virtual void CheckInterruptCompletion();
  291. virtual bool InterruptThisScene( CSceneEntity *otherScene );
  292. void RequestCompletionNotification( CSceneEntity *otherScene );
  293. virtual void NotifyOfCompletion( CSceneEntity *interruptor );
  294. void AddListManager( CSceneListManager *pManager );
  295. void ClearActivatorTargets( void );
  296. void SetBreakOnNonIdle( bool bBreakOnNonIdle ) { m_bBreakOnNonIdle = bBreakOnNonIdle; }
  297. bool ShouldBreakOnNonIdle( void ) { return m_bBreakOnNonIdle; }
  298. // Inputs
  299. void InputStartPlayback( inputdata_t &inputdata );
  300. void InputPausePlayback( inputdata_t &inputdata );
  301. void InputResumePlayback( inputdata_t &inputdata );
  302. void InputCancelPlayback( inputdata_t &inputdata );
  303. void InputCancelAtNextInterrupt( inputdata_t &inputdata );
  304. void InputPitchShiftPlayback( inputdata_t &inputdata );
  305. void InputTriggerEvent( inputdata_t &inputdata );
  306. // If the scene is playing, finds an actor in the scene who can respond to the specified concept token
  307. void InputInterjectResponse( inputdata_t &inputdata );
  308. // If this scene is waiting on an actor, give up and quit trying.
  309. void InputStopWaitingForActor( inputdata_t &inputdata );
  310. virtual void StartPlayback( void );
  311. virtual void PausePlayback( void );
  312. virtual void ResumePlayback( void );
  313. virtual void CancelPlayback( void );
  314. virtual void PitchShiftPlayback( float fPitch );
  315. virtual void QueueResumePlayback( void );
  316. bool ValidScene() const;
  317. // Scene load/unload
  318. static CChoreoScene *LoadScene( const char *filename, IChoreoEventCallback *pCallback );
  319. void UnloadScene( void );
  320. struct SpeakEventSound_t
  321. {
  322. CUtlSymbol m_Symbol;
  323. float m_flStartTime;
  324. };
  325. static bool SpeakEventSoundLessFunc( const SpeakEventSound_t& lhs, const SpeakEventSound_t& rhs );
  326. bool GetSoundNameForPlayer( CChoreoEvent *event, CBasePlayer *player, char *buf, size_t buflen, CBaseEntity *pActor );
  327. void BuildSortedSpeakEventSoundsPrefetchList(
  328. CChoreoScene *scene,
  329. CUtlSymbolTable& table,
  330. CUtlRBTree< SpeakEventSound_t >& soundnames,
  331. float timeOffset );
  332. void PrefetchSpeakEventSounds( CUtlSymbolTable& table, CUtlRBTree< SpeakEventSound_t >& soundnames );
  333. // Event handlers
  334. virtual void DispatchStartExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  335. virtual void DispatchEndExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  336. virtual void DispatchStartFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  337. virtual void DispatchEndFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  338. virtual void DispatchStartGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  339. virtual void DispatchEndGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  340. virtual void DispatchStartLookAt( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event );
  341. virtual void DispatchEndLookAt( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  342. virtual void DispatchStartMoveTo( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event );
  343. virtual void DispatchEndMoveTo( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  344. virtual void DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event, soundlevel_t iSoundlevel );
  345. virtual void DispatchEndSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  346. virtual void DispatchStartFace( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event );
  347. virtual void DispatchEndFace( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  348. virtual void DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  349. virtual void DispatchEndSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  350. virtual void DispatchStartSubScene( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  351. virtual void DispatchStartInterrupt( CChoreoScene *scene, CChoreoEvent *event );
  352. virtual void DispatchEndInterrupt( CChoreoScene *scene, CChoreoEvent *event );
  353. virtual void DispatchStartGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  354. virtual void DispatchEndGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  355. // NPC can play interstitial vcds (such as responding to the player doing something during a scene)
  356. virtual void DispatchStartPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  357. virtual void DispatchEndPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event );
  358. // Global events
  359. virtual void DispatchProcessLoop( CChoreoScene *scene, CChoreoEvent *event );
  360. virtual void DispatchPauseScene( CChoreoScene *scene, const char *parameters );
  361. virtual void DispatchStopPoint( CChoreoScene *scene, const char *parameters );
  362. virtual float EstimateLength( void );
  363. void CancelIfSceneInvolvesActor( CBaseEntity *pActor );
  364. bool InvolvesActor( CBaseEntity *pActor ); // NOTE: returns false if scene hasn't loaded yet
  365. void GenerateSoundScene( CBaseFlex *pActor, const char *soundname );
  366. virtual float GetPostSpeakDelay() { return 1.0; }
  367. bool HasUnplayedSpeech( void );
  368. bool HasFlexAnimation( void );
  369. void SetCurrentTime( float t, bool forceClientSync );
  370. void InputScriptPlayerDeath( inputdata_t &inputdata );
  371. // Data
  372. public:
  373. string_t m_iszSceneFile;
  374. string_t m_iszResumeSceneFile;
  375. EHANDLE m_hWaitingForThisResumeScene;
  376. bool m_bWaitingForResumeScene;
  377. string_t m_iszTarget1;
  378. string_t m_iszTarget2;
  379. string_t m_iszTarget3;
  380. string_t m_iszTarget4;
  381. string_t m_iszTarget5;
  382. string_t m_iszTarget6;
  383. string_t m_iszTarget7;
  384. string_t m_iszTarget8;
  385. EHANDLE m_hTarget1;
  386. EHANDLE m_hTarget2;
  387. EHANDLE m_hTarget3;
  388. EHANDLE m_hTarget4;
  389. EHANDLE m_hTarget5;
  390. EHANDLE m_hTarget6;
  391. EHANDLE m_hTarget7;
  392. EHANDLE m_hTarget8;
  393. CNetworkVar( bool, m_bIsPlayingBack );
  394. CNetworkVar( bool, m_bPaused );
  395. CNetworkVar( bool, m_bMultiplayer );
  396. CNetworkVar( float, m_flForceClientTime );
  397. float m_flCurrentTime;
  398. float m_flFrameTime;
  399. bool m_bCancelAtNextInterrupt;
  400. float m_fPitch;
  401. bool m_bAutomated;
  402. int m_nAutomatedAction;
  403. float m_flAutomationDelay;
  404. float m_flAutomationTime;
  405. // A pause from an input requires another input to unpause (it's a hard pause)
  406. bool m_bPausedViaInput;
  407. // Waiting for the actor to be able to speak.
  408. bool m_bWaitingForActor;
  409. // Waiting for a point at which we can interrupt our actors
  410. bool m_bWaitingForInterrupt;
  411. bool m_bInterruptedActorsScenes;
  412. bool m_bBreakOnNonIdle;
  413. public:
  414. virtual CBaseFlex *FindNamedActor( int index );
  415. virtual CBaseFlex *FindNamedActor( CChoreoActor *pChoreoActor );
  416. virtual CBaseFlex *FindNamedActor( const char *name );
  417. virtual CBaseEntity *FindNamedEntity( const char *name, CBaseEntity *pActor = NULL, bool bBaseFlexOnly = false, bool bUseClear = false );
  418. CBaseEntity *FindNamedTarget( string_t iszTarget, bool bBaseFlexOnly = false );
  419. virtual CBaseEntity *FindNamedEntityClosest( const char *name, CBaseEntity *pActor = NULL, bool bBaseFlexOnly = false, bool bUseClear = false, const char *pszSecondary = NULL );
  420. private:
  421. CUtlVector< CHandle< CBaseFlex > > m_hActorList;
  422. CUtlVector< CHandle< CBaseEntity > > m_hRemoveActorList;
  423. private:
  424. inline void SetRestoring( bool bRestoring );
  425. // Prevent derived classed from using this!
  426. virtual void Think( void ) {};
  427. void ClearSceneEvents( CChoreoScene *scene, bool canceled );
  428. void ClearSchedules( CChoreoScene *scene );
  429. float GetSoundSystemLatency( void );
  430. void PrecacheScene( CChoreoScene *scene );
  431. CChoreoScene *GenerateSceneForSound( CBaseFlex *pFlexActor, const char *soundname );
  432. bool CheckActors();
  433. void PrefetchAnimBlocks( CChoreoScene *scene );
  434. bool ShouldNetwork() const;
  435. // Set if we tried to async the scene but the FS returned that the data was not loadable
  436. bool m_bSceneMissing;
  437. CChoreoScene *m_pScene;
  438. CNetworkVar( int, m_nSceneStringIndex );
  439. static const ConVar *m_pcvSndMixahead;
  440. COutputEvent m_OnStart;
  441. COutputEvent m_OnCompletion;
  442. COutputEvent m_OnCanceled;
  443. COutputEvent m_OnTrigger1;
  444. COutputEvent m_OnTrigger2;
  445. COutputEvent m_OnTrigger3;
  446. COutputEvent m_OnTrigger4;
  447. COutputEvent m_OnTrigger5;
  448. COutputEvent m_OnTrigger6;
  449. COutputEvent m_OnTrigger7;
  450. COutputEvent m_OnTrigger8;
  451. COutputEvent m_OnTrigger9;
  452. COutputEvent m_OnTrigger10;
  453. COutputEvent m_OnTrigger11;
  454. COutputEvent m_OnTrigger12;
  455. COutputEvent m_OnTrigger13;
  456. COutputEvent m_OnTrigger14;
  457. COutputEvent m_OnTrigger15;
  458. COutputEvent m_OnTrigger16;
  459. int m_nInterruptCount;
  460. bool m_bInterrupted;
  461. CHandle< CSceneEntity > m_hInterruptScene;
  462. bool m_bCompletedEarly;
  463. bool m_bInterruptSceneFinished;
  464. CUtlVector< CHandle< CSceneEntity > > m_hNotifySceneCompletion;
  465. CUtlVector< CHandle< CSceneListManager > > m_hListManagers;
  466. bool m_bRestoring;
  467. bool m_bGenerated;
  468. string_t m_iszSoundName;
  469. CHandle< CBaseFlex > m_hActor;
  470. EHANDLE m_hActivator;
  471. int m_BusyActor;
  472. int m_iPlayerDeathBehavior;
  473. CRecipientFilter *m_pRecipientFilter;
  474. public:
  475. void SetBackground( bool bIsBackground );
  476. bool IsBackground( void );
  477. };
  478. LINK_ENTITY_TO_CLASS( logic_choreographed_scene, CSceneEntity );
  479. LINK_ENTITY_TO_CLASS( scripted_scene, CSceneEntity );
  480. IMPLEMENT_SERVERCLASS_ST_NOBASE( CSceneEntity, DT_SceneEntity )
  481. SendPropInt(SENDINFO(m_nSceneStringIndex),MAX_CHOREO_SCENES_STRING_BITS,SPROP_UNSIGNED),
  482. SendPropBool(SENDINFO(m_bIsPlayingBack)),
  483. SendPropBool(SENDINFO(m_bPaused)),
  484. SendPropBool(SENDINFO(m_bMultiplayer)),
  485. SendPropFloat(SENDINFO(m_flForceClientTime)),
  486. SendPropUtlVector(
  487. SENDINFO_UTLVECTOR( m_hActorList ),
  488. MAX_ACTORS_IN_SCENE, // max elements
  489. SendPropEHandle( NULL, 0 ) ),
  490. END_SEND_TABLE()
  491. BEGIN_DATADESC( CSceneEntity )
  492. // Keys
  493. DEFINE_KEYFIELD( m_iszSceneFile, FIELD_STRING, "SceneFile" ),
  494. DEFINE_KEYFIELD( m_iszResumeSceneFile, FIELD_STRING, "ResumeSceneFile" ),
  495. DEFINE_FIELD( m_hWaitingForThisResumeScene, FIELD_EHANDLE ),
  496. DEFINE_FIELD( m_bWaitingForResumeScene, FIELD_BOOLEAN ),
  497. DEFINE_KEYFIELD( m_iszTarget1, FIELD_STRING, "target1" ),
  498. DEFINE_KEYFIELD( m_iszTarget2, FIELD_STRING, "target2" ),
  499. DEFINE_KEYFIELD( m_iszTarget3, FIELD_STRING, "target3" ),
  500. DEFINE_KEYFIELD( m_iszTarget4, FIELD_STRING, "target4" ),
  501. DEFINE_KEYFIELD( m_iszTarget5, FIELD_STRING, "target5" ),
  502. DEFINE_KEYFIELD( m_iszTarget6, FIELD_STRING, "target6" ),
  503. DEFINE_KEYFIELD( m_iszTarget7, FIELD_STRING, "target7" ),
  504. DEFINE_KEYFIELD( m_iszTarget8, FIELD_STRING, "target8" ),
  505. DEFINE_KEYFIELD( m_BusyActor, FIELD_INTEGER, "busyactor" ),
  506. DEFINE_FIELD( m_hTarget1, FIELD_EHANDLE ),
  507. DEFINE_FIELD( m_hTarget2, FIELD_EHANDLE ),
  508. DEFINE_FIELD( m_hTarget3, FIELD_EHANDLE ),
  509. DEFINE_FIELD( m_hTarget4, FIELD_EHANDLE ),
  510. DEFINE_FIELD( m_hTarget5, FIELD_EHANDLE ),
  511. DEFINE_FIELD( m_hTarget6, FIELD_EHANDLE ),
  512. DEFINE_FIELD( m_hTarget7, FIELD_EHANDLE ),
  513. DEFINE_FIELD( m_hTarget8, FIELD_EHANDLE ),
  514. DEFINE_FIELD( m_bIsPlayingBack, FIELD_BOOLEAN ),
  515. DEFINE_FIELD( m_bPaused, FIELD_BOOLEAN ),
  516. DEFINE_FIELD( m_flCurrentTime, FIELD_FLOAT ), // relative, not absolute time
  517. DEFINE_FIELD( m_flForceClientTime, FIELD_FLOAT ),
  518. DEFINE_FIELD( m_flFrameTime, FIELD_FLOAT ), // last frametime
  519. DEFINE_FIELD( m_bCancelAtNextInterrupt, FIELD_BOOLEAN ),
  520. DEFINE_FIELD( m_fPitch, FIELD_FLOAT ),
  521. DEFINE_FIELD( m_bAutomated, FIELD_BOOLEAN ),
  522. DEFINE_FIELD( m_nAutomatedAction, FIELD_INTEGER ),
  523. DEFINE_FIELD( m_flAutomationDelay, FIELD_FLOAT ),
  524. DEFINE_FIELD( m_flAutomationTime, FIELD_FLOAT ), // relative, not absolute time
  525. DEFINE_FIELD( m_bPausedViaInput, FIELD_BOOLEAN ),
  526. DEFINE_FIELD( m_bWaitingForActor, FIELD_BOOLEAN ),
  527. DEFINE_FIELD( m_bWaitingForInterrupt, FIELD_BOOLEAN ),
  528. DEFINE_FIELD( m_bInterruptedActorsScenes, FIELD_BOOLEAN ),
  529. DEFINE_FIELD( m_bBreakOnNonIdle, FIELD_BOOLEAN ),
  530. DEFINE_UTLVECTOR( m_hActorList, FIELD_EHANDLE ),
  531. DEFINE_UTLVECTOR( m_hRemoveActorList, FIELD_EHANDLE ),
  532. // DEFINE_FIELD( m_pScene, FIELD_XXXX ) // Special processing used for this
  533. // These are set up in the constructor
  534. // DEFINE_FIELD( m_pcvSndMixahead, FIELD_XXXXX ),
  535. // DEFINE_FIELD( m_bRestoring, FIELD_BOOLEAN ),
  536. DEFINE_FIELD( m_nInterruptCount, FIELD_INTEGER ),
  537. DEFINE_FIELD( m_bInterrupted, FIELD_BOOLEAN ),
  538. DEFINE_FIELD( m_hInterruptScene, FIELD_EHANDLE ),
  539. DEFINE_FIELD( m_bCompletedEarly, FIELD_BOOLEAN ),
  540. DEFINE_FIELD( m_bInterruptSceneFinished, FIELD_BOOLEAN ),
  541. DEFINE_FIELD( m_bGenerated, FIELD_BOOLEAN ),
  542. DEFINE_FIELD( m_iszSoundName, FIELD_STRING ),
  543. DEFINE_FIELD( m_hActor, FIELD_EHANDLE ),
  544. DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ),
  545. // DEFINE_FIELD( m_bSceneMissing, FIELD_BOOLEAN ),
  546. DEFINE_UTLVECTOR( m_hNotifySceneCompletion, FIELD_EHANDLE ),
  547. DEFINE_UTLVECTOR( m_hListManagers, FIELD_EHANDLE ),
  548. DEFINE_FIELD( m_bMultiplayer, FIELD_BOOLEAN ),
  549. // DEFINE_FIELD( m_nSceneStringIndex, FIELD_INTEGER ),
  550. // DEFINE_FIELD( m_pRecipientFilter, IRecipientFilter* ), // Multiplayer only
  551. // Inputs
  552. DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStartPlayback ),
  553. DEFINE_INPUTFUNC( FIELD_VOID, "Pause", InputPausePlayback ),
  554. DEFINE_INPUTFUNC( FIELD_VOID, "Resume", InputResumePlayback ),
  555. DEFINE_INPUTFUNC( FIELD_VOID, "Cancel", InputCancelPlayback ),
  556. DEFINE_INPUTFUNC( FIELD_VOID, "CancelAtNextInterrupt", InputCancelAtNextInterrupt ),
  557. DEFINE_INPUTFUNC( FIELD_FLOAT, "PitchShift", InputPitchShiftPlayback ),
  558. DEFINE_INPUTFUNC( FIELD_STRING, "InterjectResponse", InputInterjectResponse ),
  559. DEFINE_INPUTFUNC( FIELD_VOID, "StopWaitingForActor", InputStopWaitingForActor ),
  560. DEFINE_INPUTFUNC( FIELD_INTEGER, "Trigger", InputTriggerEvent ),
  561. DEFINE_KEYFIELD( m_iPlayerDeathBehavior, FIELD_INTEGER, "onplayerdeath" ),
  562. DEFINE_INPUTFUNC( FIELD_VOID, "ScriptPlayerDeath", InputScriptPlayerDeath ),
  563. // Outputs
  564. DEFINE_OUTPUT( m_OnStart, "OnStart"),
  565. DEFINE_OUTPUT( m_OnCompletion, "OnCompletion"),
  566. DEFINE_OUTPUT( m_OnCanceled, "OnCanceled"),
  567. DEFINE_OUTPUT( m_OnTrigger1, "OnTrigger1"),
  568. DEFINE_OUTPUT( m_OnTrigger2, "OnTrigger2"),
  569. DEFINE_OUTPUT( m_OnTrigger3, "OnTrigger3"),
  570. DEFINE_OUTPUT( m_OnTrigger4, "OnTrigger4"),
  571. DEFINE_OUTPUT( m_OnTrigger5, "OnTrigger5"),
  572. DEFINE_OUTPUT( m_OnTrigger6, "OnTrigger6"),
  573. DEFINE_OUTPUT( m_OnTrigger7, "OnTrigger7"),
  574. DEFINE_OUTPUT( m_OnTrigger8, "OnTrigger8"),
  575. DEFINE_OUTPUT( m_OnTrigger9, "OnTrigger9"),
  576. DEFINE_OUTPUT( m_OnTrigger10, "OnTrigger10"),
  577. DEFINE_OUTPUT( m_OnTrigger11, "OnTrigger11"),
  578. DEFINE_OUTPUT( m_OnTrigger12, "OnTrigger12"),
  579. DEFINE_OUTPUT( m_OnTrigger13, "OnTrigger13"),
  580. DEFINE_OUTPUT( m_OnTrigger14, "OnTrigger14"),
  581. DEFINE_OUTPUT( m_OnTrigger15, "OnTrigger15"),
  582. DEFINE_OUTPUT( m_OnTrigger16, "OnTrigger16"),
  583. END_DATADESC()
  584. const ConVar *CSceneEntity::m_pcvSndMixahead = NULL;
  585. //-----------------------------------------------------------------------------
  586. // Purpose:
  587. //-----------------------------------------------------------------------------
  588. CSceneEntity::CSceneEntity( void )
  589. {
  590. m_bWaitingForActor = false;
  591. m_bWaitingForInterrupt = false;
  592. m_bInterruptedActorsScenes = false;
  593. m_bIsPlayingBack = false;
  594. m_bPaused = false;
  595. m_bMultiplayer = false;
  596. m_fPitch = 1.0f;
  597. m_iszSceneFile = NULL_STRING;
  598. m_iszResumeSceneFile = NULL_STRING;
  599. m_hWaitingForThisResumeScene = NULL;
  600. m_bWaitingForResumeScene = false;
  601. SetCurrentTime( 0.0f, false );
  602. m_bCancelAtNextInterrupt = false;
  603. m_bAutomated = false;
  604. m_nAutomatedAction = SCENE_ACTION_UNKNOWN;
  605. m_flAutomationDelay = 0.0f;
  606. m_flAutomationTime = 0.0f;
  607. m_bPausedViaInput = false;
  608. ClearInterrupt();
  609. m_pScene = NULL;
  610. m_bCompletedEarly = false;
  611. if ( !m_pcvSndMixahead )
  612. m_pcvSndMixahead = cvar->FindVar( "snd_mixahead" );
  613. m_BusyActor = SCENE_BUSYACTOR_DEFAULT;
  614. }
  615. //-----------------------------------------------------------------------------
  616. // Purpose:
  617. //-----------------------------------------------------------------------------
  618. CSceneEntity::~CSceneEntity( void )
  619. {
  620. delete m_pRecipientFilter;
  621. m_pRecipientFilter = NULL;
  622. }
  623. //-----------------------------------------------------------------------------
  624. // Purpose: Resets time such that the client version of the .vcd is also updated, if appropriate
  625. // Input : t -
  626. // forceClientSync - forces new timestamp down to client .dll via networking
  627. //-----------------------------------------------------------------------------
  628. void CSceneEntity::SetCurrentTime( float t, bool bForceClientSync )
  629. {
  630. m_flCurrentTime = t;
  631. if ( gpGlobals->maxClients == 1 || bForceClientSync )
  632. {
  633. m_flForceClientTime = t;
  634. }
  635. }
  636. //-----------------------------------------------------------------------------
  637. // Purpose:
  638. //-----------------------------------------------------------------------------
  639. void CSceneEntity::UpdateOnRemove( void )
  640. {
  641. UnloadScene();
  642. BaseClass::UpdateOnRemove();
  643. if ( GetSceneManager() )
  644. {
  645. GetSceneManager()->RemoveSceneEntity( this );
  646. }
  647. }
  648. //-----------------------------------------------------------------------------
  649. // Purpose:
  650. // Input : *actor -
  651. // *soundname -
  652. // Output : CChoreoScene
  653. //-----------------------------------------------------------------------------
  654. CChoreoScene *CSceneEntity::GenerateSceneForSound( CBaseFlex *pFlexActor, const char *soundname )
  655. {
  656. float duration = CBaseEntity::GetSoundDuration( soundname, pFlexActor ? STRING( pFlexActor->GetModelName() ) : NULL );
  657. if( duration <= 0.0f )
  658. {
  659. Warning( "CSceneEntity::GenerateSceneForSound: Couldn't determine duration of %s\n", soundname );
  660. return NULL;
  661. }
  662. CChoreoScene *scene = new CChoreoScene( this );
  663. if ( !scene )
  664. {
  665. Warning( "CSceneEntity::GenerateSceneForSound: Failed to allocated new scene!!!\n" );
  666. }
  667. else
  668. {
  669. scene->SetPrintFunc( LocalScene_Printf );
  670. CChoreoActor *actor = scene->AllocActor();
  671. CChoreoChannel *channel = scene->AllocChannel();
  672. CChoreoEvent *event = scene->AllocEvent();
  673. Assert( actor );
  674. Assert( channel );
  675. Assert( event );
  676. if ( !actor || !channel || !event )
  677. {
  678. Warning( "CSceneEntity::GenerateSceneForSound: Alloc of actor, channel, or event failed!!!\n" );
  679. delete scene;
  680. return NULL;
  681. }
  682. // Set us up the actorz
  683. actor->SetName( "!self" ); // Could be pFlexActor->GetName()?
  684. actor->SetActive( true );
  685. // Set us up the channelz
  686. channel->SetName( STRING( m_iszSceneFile ) );
  687. channel->SetActor( actor );
  688. // Add to actor
  689. actor->AddChannel( channel );
  690. // Set us up the eventz
  691. event->SetType( CChoreoEvent::SPEAK );
  692. event->SetName( soundname );
  693. event->SetParameters( soundname );
  694. event->SetStartTime( 0.0f );
  695. event->SetUsingRelativeTag( false );
  696. event->SetEndTime( duration );
  697. event->SnapTimes();
  698. // Add to channel
  699. channel->AddEvent( event );
  700. // Point back to our owners
  701. event->SetChannel( channel );
  702. event->SetActor( actor );
  703. }
  704. return scene;
  705. }
  706. //-----------------------------------------------------------------------------
  707. // Purpose:
  708. //-----------------------------------------------------------------------------
  709. void CSceneEntity::Activate()
  710. {
  711. if ( m_bGenerated && !m_pScene )
  712. {
  713. m_pScene = GenerateSceneForSound( m_hActor, STRING( m_iszSoundName ) );
  714. }
  715. BaseClass::Activate();
  716. if ( GetSceneManager() )
  717. {
  718. GetSceneManager()->AddSceneEntity( this );
  719. }
  720. }
  721. //-----------------------------------------------------------------------------
  722. // Purpose:
  723. // Output : float
  724. //-----------------------------------------------------------------------------
  725. float CSceneEntity::GetSoundSystemLatency( void )
  726. {
  727. if ( m_pcvSndMixahead )
  728. {
  729. return m_pcvSndMixahead->GetFloat();
  730. }
  731. // Assume 100 msec sound system latency
  732. return SOUND_SYSTEM_LATENCY_DEFAULT;
  733. }
  734. //-----------------------------------------------------------------------------
  735. // Purpose:
  736. // Input : *scene -
  737. //-----------------------------------------------------------------------------
  738. void CSceneEntity::PrecacheScene( CChoreoScene *scene )
  739. {
  740. Assert( scene );
  741. // Iterate events and precache necessary resources
  742. for ( int i = 0; i < scene->GetNumEvents(); i++ )
  743. {
  744. CChoreoEvent *event = scene->GetEvent( i );
  745. if ( !event )
  746. continue;
  747. // load any necessary data
  748. switch (event->GetType() )
  749. {
  750. default:
  751. break;
  752. case CChoreoEvent::SPEAK:
  753. {
  754. // Defined in SoundEmitterSystem.cpp
  755. // NOTE: The script entries associated with .vcds are forced to preload to avoid
  756. // loading hitches during triggering
  757. PrecacheScriptSound( event->GetParameters() );
  758. if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER &&
  759. event->GetNumSlaves() > 0 )
  760. {
  761. char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ];
  762. if ( event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) ) )
  763. {
  764. PrecacheScriptSound( tok );
  765. }
  766. }
  767. }
  768. break;
  769. case CChoreoEvent::SUBSCENE:
  770. {
  771. // Only allow a single level of subscenes for now
  772. if ( !scene->IsSubScene() )
  773. {
  774. CChoreoScene *subscene = event->GetSubScene();
  775. if ( !subscene )
  776. {
  777. subscene = LoadScene( event->GetParameters(), this );
  778. subscene->SetSubScene( true );
  779. event->SetSubScene( subscene );
  780. // Now precache it's resources, if any
  781. PrecacheScene( subscene );
  782. }
  783. }
  784. }
  785. break;
  786. }
  787. }
  788. }
  789. //-----------------------------------------------------------------------------
  790. // Purpose:
  791. //-----------------------------------------------------------------------------
  792. void CSceneEntity::Precache( void )
  793. {
  794. if ( m_bGenerated )
  795. return;
  796. if ( m_iszSceneFile == NULL_STRING )
  797. return;
  798. if ( m_iszResumeSceneFile != NULL_STRING )
  799. {
  800. PrecacheInstancedScene( STRING( m_iszResumeSceneFile ) );
  801. }
  802. PrecacheInstancedScene( STRING( m_iszSceneFile ) );
  803. }
  804. //-----------------------------------------------------------------------------
  805. // Purpose:
  806. // Input : *pActor -
  807. // *soundname -
  808. //-----------------------------------------------------------------------------
  809. void CSceneEntity::GenerateSoundScene( CBaseFlex *pActor, const char *soundname )
  810. {
  811. m_bGenerated = true;
  812. m_iszSoundName = MAKE_STRING( soundname );
  813. m_hActor = pActor;
  814. }
  815. //-----------------------------------------------------------------------------
  816. // Purpose:
  817. // Output : Returns true on success, false on failure.
  818. //-----------------------------------------------------------------------------
  819. bool CSceneEntity::HasUnplayedSpeech( void )
  820. {
  821. if ( m_pScene )
  822. return m_pScene->HasUnplayedSpeech();
  823. return false;
  824. }
  825. //-----------------------------------------------------------------------------
  826. // Purpose:
  827. // Output : Returns true on success, false on failure.
  828. //-----------------------------------------------------------------------------
  829. bool CSceneEntity::HasFlexAnimation( void )
  830. {
  831. if ( m_pScene )
  832. return m_pScene->HasFlexAnimation();
  833. return false;
  834. }
  835. //-----------------------------------------------------------------------------
  836. // Purpose:
  837. // Output :
  838. //-----------------------------------------------------------------------------
  839. void CSceneEntity::SetBackground( bool bIsBackground )
  840. {
  841. if ( m_pScene )
  842. {
  843. m_pScene->SetBackground( bIsBackground );
  844. }
  845. }
  846. //-----------------------------------------------------------------------------
  847. // Purpose:
  848. // Output : Returns true on success, false on failure.
  849. //-----------------------------------------------------------------------------
  850. bool CSceneEntity::IsBackground( void )
  851. {
  852. if ( m_pScene )
  853. return m_pScene->IsBackground( );
  854. return false;
  855. }
  856. //-----------------------------------------------------------------------------
  857. // Purpose:
  858. //-----------------------------------------------------------------------------
  859. void CSceneEntity::OnRestore()
  860. {
  861. BaseClass::OnRestore();
  862. // Fix saved games that have their pitch set to zero
  863. if ( m_fPitch < SCENE_MIN_PITCH || m_fPitch > SCENE_MAX_PITCH )
  864. m_fPitch = 1.0f;
  865. if ( !m_bIsPlayingBack )
  866. return;
  867. if ( !m_pScene )
  868. {
  869. m_pScene = LoadScene( STRING( m_iszSceneFile ), this );
  870. if ( !m_pScene )
  871. {
  872. m_bSceneMissing = true;
  873. return;
  874. }
  875. OnLoaded();
  876. if ( ShouldNetwork() )
  877. {
  878. m_nSceneStringIndex = g_pStringTableClientSideChoreoScenes->AddString( CBaseEntity::IsServer(), STRING( m_iszSceneFile ) );
  879. }
  880. UpdateTransmitState();
  881. }
  882. m_bSceneMissing = false;
  883. int i;
  884. for ( i = 0 ; i < m_pScene->GetNumActors(); i++ )
  885. {
  886. CBaseFlex *pTestActor = FindNamedActor( i );
  887. if ( !pTestActor )
  888. continue;
  889. if ( !pTestActor->MyCombatCharacterPointer() )
  890. continue;
  891. // Needed?
  892. //if ( !pTestActor->MyCombatCharacterPointer()->IsAlive() )
  893. // return;
  894. pTestActor->StartChoreoScene( m_pScene );
  895. }
  896. float dt = SCENE_THINK_INTERVAL;
  897. bool paused = m_bPaused;
  898. m_bPaused = false;
  899. // roll back slightly so that pause events still trigger
  900. m_pScene->ResetSimulation( true, m_flCurrentTime - SCENE_THINK_INTERVAL, m_flCurrentTime );
  901. m_pScene->SetTime( m_flCurrentTime - SCENE_THINK_INTERVAL );
  902. SetCurrentTime( m_flCurrentTime, true );
  903. // Robin: This causes a miscount of any interrupt events in the scene.
  904. // All the variables are saved/restored properly, so we can safely leave them alone.
  905. //ClearInterrupt();
  906. SetRestoring( true );
  907. DoThink( dt );
  908. SetRestoring( false );
  909. if ( paused )
  910. {
  911. PausePlayback();
  912. }
  913. NetworkProp()->NetworkStateForceUpdate();
  914. }
  915. //-----------------------------------------------------------------------------
  916. //-----------------------------------------------------------------------------
  917. void CSceneEntity::SetRestoring( bool bRestoring )
  918. {
  919. m_bRestoring = bRestoring;
  920. if ( m_pScene )
  921. {
  922. m_pScene->SetRestoring( bRestoring );
  923. }
  924. }
  925. //-----------------------------------------------------------------------------
  926. // Purpose:
  927. //-----------------------------------------------------------------------------
  928. void CSceneEntity::Spawn( void )
  929. {
  930. Precache();
  931. }
  932. void CSceneEntity::PauseThink( void )
  933. {
  934. if ( !m_pScene )
  935. return;
  936. // Stay paused if pause occurred from interrupt
  937. if ( m_bInterrupted )
  938. return;
  939. // If entity I/O paused the scene, then it'll have to resume/cancel the scene...
  940. if ( m_bPausedViaInput )
  941. {
  942. // If we're waiting for a resume scene to finish, continue when it's done
  943. if ( m_bWaitingForResumeScene && !m_hWaitingForThisResumeScene )
  944. {
  945. // Resume scene has finished, stop waiting for it
  946. m_bWaitingForResumeScene = false;
  947. }
  948. else
  949. {
  950. return;
  951. }
  952. }
  953. if ( !m_bAutomated )
  954. {
  955. // FIXME: Game code should check for AI waiting conditions being met, etc.
  956. //
  957. //
  958. //
  959. bool bAllFinished = m_pScene->CheckEventCompletion( );
  960. if ( bAllFinished )
  961. {
  962. // Perform action
  963. switch ( m_nAutomatedAction )
  964. {
  965. case SCENE_ACTION_RESUME:
  966. ResumePlayback();
  967. break;
  968. case SCENE_ACTION_CANCEL:
  969. LocalScene_Printf( "%s : PauseThink canceling playback\n", STRING( m_iszSceneFile ) );
  970. CancelPlayback();
  971. break;
  972. default:
  973. ResumePlayback();
  974. break;
  975. }
  976. // Reset
  977. m_bAutomated = false;
  978. m_nAutomatedAction = SCENE_ACTION_UNKNOWN;
  979. m_flAutomationTime = 0.0f;
  980. m_flAutomationDelay = 0.0f;
  981. m_bPausedViaInput = false;
  982. }
  983. return;
  984. }
  985. // Otherwise, see if resume/cancel is automatic and act accordingly if enough time
  986. // has passed
  987. m_flAutomationTime += (gpGlobals->frametime);
  988. if ( m_flAutomationDelay > 0.0f &&
  989. m_flAutomationTime < m_flAutomationDelay )
  990. return;
  991. // Perform action
  992. switch ( m_nAutomatedAction )
  993. {
  994. case SCENE_ACTION_RESUME:
  995. LocalScene_Printf( "%s : Automatically resuming playback\n", STRING( m_iszSceneFile ) );
  996. ResumePlayback();
  997. break;
  998. case SCENE_ACTION_CANCEL:
  999. LocalScene_Printf( "%s : Automatically canceling playback\n", STRING( m_iszSceneFile ) );
  1000. CancelPlayback();
  1001. break;
  1002. default:
  1003. LocalScene_Printf( "%s : Unknown action %i, automatically resuming playback\n", STRING( m_iszSceneFile ), m_nAutomatedAction );
  1004. ResumePlayback();
  1005. break;
  1006. }
  1007. // Reset
  1008. m_bAutomated = false;
  1009. m_nAutomatedAction = SCENE_ACTION_UNKNOWN;
  1010. m_flAutomationTime = 0.0f;
  1011. m_flAutomationDelay = 0.0f;
  1012. m_bPausedViaInput = false;
  1013. }
  1014. //-----------------------------------------------------------------------------
  1015. // Purpose:
  1016. //-----------------------------------------------------------------------------
  1017. void CSceneEntity::DispatchPauseScene( CChoreoScene *scene, const char *parameters )
  1018. {
  1019. // Don't pause during restore, since we'll be restoring the pause state already
  1020. if ( m_bRestoring )
  1021. return;
  1022. // FIXME: Hook this up to AI, etc. somehow, perhaps poll each actor for conditions using
  1023. // scene resume condition iterator
  1024. PausePlayback();
  1025. char token[1024];
  1026. m_bPausedViaInput = false;
  1027. m_bAutomated = false;
  1028. m_nAutomatedAction = SCENE_ACTION_UNKNOWN;
  1029. m_flAutomationDelay = 0.0f;
  1030. m_flAutomationTime = 0.0f;
  1031. // Check for auto resume/cancel
  1032. const char *buffer = parameters;
  1033. buffer = engine->ParseFile( buffer, token, sizeof( token ) );
  1034. if ( !stricmp( token, "automate" ) )
  1035. {
  1036. buffer = engine->ParseFile( buffer, token, sizeof( token ) );
  1037. if ( !stricmp( token, "Cancel" ) )
  1038. {
  1039. m_nAutomatedAction = SCENE_ACTION_CANCEL;
  1040. }
  1041. else if ( !stricmp( token, "Resume" ) )
  1042. {
  1043. m_nAutomatedAction = SCENE_ACTION_RESUME;
  1044. }
  1045. if ( m_nAutomatedAction != SCENE_ACTION_UNKNOWN )
  1046. {
  1047. buffer = engine->ParseFile( buffer, token, sizeof( token ) );
  1048. m_flAutomationDelay = (float)atof( token );
  1049. if ( m_flAutomationDelay > 0.0f )
  1050. {
  1051. // Success
  1052. m_bAutomated = true;
  1053. m_flAutomationTime = 0.0f;
  1054. }
  1055. }
  1056. }
  1057. }
  1058. //-----------------------------------------------------------------------------
  1059. // Purpose:
  1060. // Input : *scene -
  1061. // *event -
  1062. //-----------------------------------------------------------------------------
  1063. void CSceneEntity::DispatchProcessLoop( CChoreoScene *scene, CChoreoEvent *event )
  1064. {
  1065. // Don't restore this event since it's implied in the current "state" of the scene timer, etc.
  1066. if ( m_bRestoring )
  1067. return;
  1068. Assert( scene );
  1069. Assert( event->GetType() == CChoreoEvent::LOOP );
  1070. float backtime = (float)atof( event->GetParameters() );
  1071. bool process = true;
  1072. int counter = event->GetLoopCount();
  1073. if ( counter != -1 )
  1074. {
  1075. int remaining = event->GetNumLoopsRemaining();
  1076. if ( remaining <= 0 )
  1077. {
  1078. process = false;
  1079. }
  1080. else
  1081. {
  1082. event->SetNumLoopsRemaining( --remaining );
  1083. }
  1084. }
  1085. if ( !process )
  1086. return;
  1087. scene->LoopToTime( backtime );
  1088. SetCurrentTime( backtime, true );
  1089. }
  1090. //-----------------------------------------------------------------------------
  1091. // Purpose: Flag the scene as already "completed"
  1092. // Input : *scene -
  1093. // *parameters -
  1094. //-----------------------------------------------------------------------------
  1095. void CSceneEntity::DispatchStopPoint( CChoreoScene *scene, const char *parameters )
  1096. {
  1097. if ( m_bCompletedEarly )
  1098. {
  1099. Assert( 0 );
  1100. Warning( "Scene '%s' with two stop point events!\n", STRING( m_iszSceneFile ) );
  1101. return;
  1102. }
  1103. // Fire completion trigger early
  1104. m_bCompletedEarly = true;
  1105. m_OnCompletion.FireOutput( this, this, 0 );
  1106. }
  1107. //-----------------------------------------------------------------------------
  1108. // Purpose:
  1109. // Output : Returns true on success, false on failure.
  1110. //-----------------------------------------------------------------------------
  1111. bool CSceneEntity::IsInterruptable()
  1112. {
  1113. return ( m_nInterruptCount > 0 ) ? true : false;
  1114. }
  1115. //-----------------------------------------------------------------------------
  1116. // Purpose:
  1117. // Input : *scene -
  1118. // *actor -
  1119. // *event -
  1120. //-----------------------------------------------------------------------------
  1121. void CSceneEntity::DispatchStartInterrupt( CChoreoScene *scene, CChoreoEvent *event )
  1122. {
  1123. // Don't re-interrupt during restore
  1124. if ( m_bRestoring )
  1125. return;
  1126. // If we're supposed to cancel at our next interrupt point, cancel now
  1127. if ( m_bCancelAtNextInterrupt )
  1128. {
  1129. m_bCancelAtNextInterrupt = false;
  1130. LocalScene_Printf( "%s : cancelled via interrupt\n", STRING( m_iszSceneFile ) );
  1131. CancelPlayback();
  1132. return;
  1133. }
  1134. ++m_nInterruptCount;
  1135. }
  1136. //-----------------------------------------------------------------------------
  1137. // Purpose:
  1138. // Input : *scene -
  1139. // *actor -
  1140. // *event -
  1141. //-----------------------------------------------------------------------------
  1142. void CSceneEntity::DispatchEndInterrupt( CChoreoScene *scene, CChoreoEvent *event )
  1143. {
  1144. // Don't re-interrupt during restore
  1145. if ( m_bRestoring )
  1146. return;
  1147. --m_nInterruptCount;
  1148. if ( m_nInterruptCount < 0 )
  1149. {
  1150. m_nInterruptCount = 0;
  1151. }
  1152. }
  1153. //-----------------------------------------------------------------------------
  1154. // Purpose:
  1155. // Input : *actor -
  1156. // *event -
  1157. //-----------------------------------------------------------------------------
  1158. void CSceneEntity::DispatchStartExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1159. {
  1160. actor->AddSceneEvent( scene, event );
  1161. }
  1162. //-----------------------------------------------------------------------------
  1163. // Purpose:
  1164. // Input : *actor -
  1165. // *event -
  1166. //-----------------------------------------------------------------------------
  1167. void CSceneEntity::DispatchEndExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1168. {
  1169. actor->RemoveSceneEvent( scene, event, false );
  1170. }
  1171. //-----------------------------------------------------------------------------
  1172. // Purpose:
  1173. // Input : *actor -
  1174. // *event -
  1175. //-----------------------------------------------------------------------------
  1176. void CSceneEntity::DispatchStartFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1177. {
  1178. actor->AddSceneEvent( scene, event );
  1179. }
  1180. //-----------------------------------------------------------------------------
  1181. // Purpose:
  1182. // Input : *actor -
  1183. // *event -
  1184. //-----------------------------------------------------------------------------
  1185. void CSceneEntity::DispatchEndFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1186. {
  1187. actor->RemoveSceneEvent( scene, event, false );
  1188. }
  1189. //-----------------------------------------------------------------------------
  1190. // Purpose:
  1191. // Input : *actor -
  1192. // *parameters -
  1193. //-----------------------------------------------------------------------------
  1194. void CSceneEntity::DispatchStartGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1195. {
  1196. // Ingore null gestures
  1197. if ( !Q_stricmp( event->GetName(), "NULL" ) )
  1198. return;
  1199. actor->AddSceneEvent( scene, event);
  1200. }
  1201. //-----------------------------------------------------------------------------
  1202. // Purpose:
  1203. // Input : *actor -
  1204. // *parameters -
  1205. //-----------------------------------------------------------------------------
  1206. void CSceneEntity::DispatchEndGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1207. {
  1208. // Ingore null gestures
  1209. if ( !Q_stricmp( event->GetName(), "NULL" ) )
  1210. return;
  1211. actor->RemoveSceneEvent( scene, event, m_bRestoring );
  1212. }
  1213. //-----------------------------------------------------------------------------
  1214. // Purpose:
  1215. // Input : *actor -
  1216. // *parameters -
  1217. //-----------------------------------------------------------------------------
  1218. void CSceneEntity::DispatchStartGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1219. {
  1220. CBaseEntity *pTarget = FindNamedEntity( event->GetParameters2( ) );
  1221. actor->AddSceneEvent( scene, event, pTarget );
  1222. }
  1223. //-----------------------------------------------------------------------------
  1224. // Purpose:
  1225. // Input : *actor -
  1226. // *parameters -
  1227. //-----------------------------------------------------------------------------
  1228. void CSceneEntity::DispatchEndGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1229. {
  1230. actor->RemoveSceneEvent( scene, event, m_bRestoring );
  1231. }
  1232. //-----------------------------------------------------------------------------
  1233. // Purpose:
  1234. // Input : *actor -
  1235. // *actor2 -
  1236. //-----------------------------------------------------------------------------
  1237. void CSceneEntity::DispatchStartLookAt( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event )
  1238. {
  1239. actor->AddSceneEvent( scene, event, actor2 );
  1240. }
  1241. void CSceneEntity::DispatchEndLookAt( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1242. {
  1243. actor->RemoveSceneEvent( scene, event, m_bRestoring );
  1244. }
  1245. //-----------------------------------------------------------------------------
  1246. // Purpose: Move to spot/actor
  1247. // FIXME: Need to allow this to take arbitrary amount of time and pause playback
  1248. // while waiting for actor to move into position
  1249. // Input : *actor -
  1250. // *parameters -
  1251. //-----------------------------------------------------------------------------
  1252. void CSceneEntity::DispatchStartMoveTo( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event )
  1253. {
  1254. actor->AddSceneEvent( scene, event, actor2 );
  1255. }
  1256. void CSceneEntity::DispatchEndMoveTo( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1257. {
  1258. actor->RemoveSceneEvent( scene, event, m_bRestoring );
  1259. }
  1260. //-----------------------------------------------------------------------------
  1261. // Purpose:
  1262. // Input : *token -
  1263. // listener -
  1264. // soundorigins -
  1265. // Output : Returns true on success, false on failure.
  1266. //-----------------------------------------------------------------------------
  1267. bool AttenuateCaption( const char *token, const Vector& listener, CUtlVector< Vector >& soundorigins )
  1268. {
  1269. if ( scene_maxcaptionradius.GetFloat() <= 0.0f )
  1270. {
  1271. return false;
  1272. }
  1273. int c = soundorigins.Count();
  1274. if ( c <= 0 )
  1275. {
  1276. return false;
  1277. }
  1278. float maxdistSqr = scene_maxcaptionradius.GetFloat() * scene_maxcaptionradius.GetFloat();
  1279. for ( int i = 0; i < c; ++i )
  1280. {
  1281. const Vector& org = soundorigins[ i ];
  1282. float distSqr = ( org - listener ).LengthSqr();
  1283. if ( distSqr <= maxdistSqr )
  1284. {
  1285. return false;
  1286. }
  1287. }
  1288. // All sound sources too far, don't show caption...
  1289. return true;
  1290. }
  1291. //-----------------------------------------------------------------------------
  1292. // Purpose:
  1293. // Input : *event - which event
  1294. // player - which recipient
  1295. // buf, buflen: where to put the data
  1296. // Output : Returns true if the sound should be played/prefetched
  1297. //-----------------------------------------------------------------------------
  1298. bool CSceneEntity::GetSoundNameForPlayer( CChoreoEvent *event, CBasePlayer *player, char *buf, size_t buflen, CBaseEntity *pActor )
  1299. {
  1300. Assert( event );
  1301. Assert( player );
  1302. Assert( buf );
  1303. Assert( buflen > 0 );
  1304. bool ismasterevent = true;
  1305. char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ];
  1306. bool validtoken = false;
  1307. tok[ 0 ] = 0;
  1308. if ( event->GetCloseCaptionType() == CChoreoEvent::CC_SLAVE ||
  1309. event->GetCloseCaptionType() == CChoreoEvent::CC_DISABLED )
  1310. {
  1311. ismasterevent = false;
  1312. }
  1313. else
  1314. {
  1315. validtoken = event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) );
  1316. }
  1317. const char* pchToken = "";
  1318. if ( pActor && pActor->IsPlayer() )
  1319. {
  1320. pchToken = dynamic_cast< CBasePlayer* >( pActor )->GetSceneSoundToken();
  1321. }
  1322. // Copy the sound name
  1323. CopySoundNameWithModifierToken( buf, event->GetParameters(), buflen, pchToken );
  1324. bool usingEnglish = true;
  1325. if ( !IsXbox() )
  1326. {
  1327. char const *cvarvalue = engine->GetClientConVarValue( player->entindex(), "english" );
  1328. if ( cvarvalue && *cvarvalue && Q_atoi( cvarvalue ) != 1 )
  1329. {
  1330. usingEnglish = false;
  1331. }
  1332. }
  1333. // This makes it like they are running in another language
  1334. if ( scene_forcecombined.GetBool() )
  1335. {
  1336. usingEnglish = false;
  1337. }
  1338. if ( usingEnglish )
  1339. {
  1340. // English sounds always play
  1341. return true;
  1342. }
  1343. if ( ismasterevent )
  1344. {
  1345. // Master event sounds always play too (master will be the combined .wav)
  1346. if ( validtoken )
  1347. {
  1348. Q_strncpy( buf, tok, buflen );
  1349. }
  1350. return true;
  1351. }
  1352. // Slave events don't play any sound...
  1353. return false;
  1354. }
  1355. //-----------------------------------------------------------------------------
  1356. // Purpose: Playback sound file that contains phonemes
  1357. // Input : *actor -
  1358. // *parameters -
  1359. //-----------------------------------------------------------------------------
  1360. void CSceneEntity::DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event, soundlevel_t iSoundlevel )
  1361. {
  1362. // Emit sound
  1363. if ( actor )
  1364. {
  1365. CPASAttenuationFilter filter( actor );
  1366. if ( m_pRecipientFilter )
  1367. {
  1368. int filterCount = filter.GetRecipientCount();
  1369. int recipientPlayerCount = m_pRecipientFilter->GetRecipientCount();
  1370. for ( int i = filterCount-1; i >= 0; --i )
  1371. {
  1372. int playerindex = filter.GetRecipientIndex( i );
  1373. bool bFound = false;
  1374. for ( int j = 0; j < recipientPlayerCount; ++j )
  1375. {
  1376. if ( m_pRecipientFilter->GetRecipientIndex(j) == playerindex )
  1377. {
  1378. bFound = true;
  1379. break;
  1380. }
  1381. }
  1382. if ( !bFound )
  1383. {
  1384. filter.RemoveRecipientByPlayerIndex( playerindex );
  1385. }
  1386. }
  1387. }
  1388. float time_in_past = m_flCurrentTime - event->GetStartTime() ;
  1389. float soundtime = gpGlobals->curtime - time_in_past;
  1390. if ( m_bRestoring )
  1391. {
  1392. // Need to queue sounds on restore because the player has not yet connected
  1393. GetSceneManager()->QueueRestoredSound( actor, event->GetParameters(), iSoundlevel, time_in_past );
  1394. return;
  1395. }
  1396. // Add padding to prevent any other talker talking right after I'm done, because I might
  1397. // be continuing speaking with another scene.
  1398. float flDuration = event->GetDuration() - time_in_past;
  1399. CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor*>(actor);
  1400. if ( pBaseActor )
  1401. {
  1402. pBaseActor->NoteSpeaking( flDuration, GetPostSpeakDelay() );
  1403. }
  1404. else if ( actor->IsNPC() )
  1405. {
  1406. GetSpeechSemaphore( actor->MyNPCPointer() )->Acquire( flDuration + GetPostSpeakDelay(), actor );
  1407. }
  1408. EmitSound_t es;
  1409. es.m_nChannel = CHAN_VOICE;
  1410. es.m_flVolume = 1;
  1411. es.m_SoundLevel = iSoundlevel;
  1412. // Only specify exact delay in single player
  1413. es.m_flSoundTime = ( gpGlobals->maxClients == 1 ) ? soundtime : 0.0f;
  1414. if ( scene->ShouldIgnorePhonemes() )
  1415. {
  1416. es.m_nFlags |= SND_IGNORE_PHONEMES;
  1417. }
  1418. if ( actor->GetSpecialDSP() != 0 )
  1419. {
  1420. es.m_nSpecialDSP = actor->GetSpecialDSP();
  1421. }
  1422. // No CC since we do it manually
  1423. // FIXME: This will change
  1424. es.m_bEmitCloseCaption = false;
  1425. int c = filter.GetRecipientCount();
  1426. for ( int i = 0; i < c; ++i )
  1427. {
  1428. int playerindex = filter.GetRecipientIndex( i );
  1429. CBasePlayer *player = UTIL_PlayerByIndex( playerindex );
  1430. if ( !player )
  1431. continue;
  1432. CSingleUserRecipientFilter filter2( player );
  1433. char soundname[ 512 ];
  1434. if ( !GetSoundNameForPlayer( event, player, soundname, sizeof( soundname ), actor ) )
  1435. {
  1436. continue;
  1437. }
  1438. es.m_pSoundName = soundname;
  1439. // keep track of the last few sounds played for bug reports
  1440. speechListSounds[ speechListIndex ].time = gpGlobals->curtime;
  1441. Q_strncpy( speechListSounds[ speechListIndex ].name, soundname, sizeof( speechListSounds[ 0 ].name ) );
  1442. Q_strncpy( speechListSounds[ speechListIndex ].sceneName, ( scene ) ? scene->GetFilename() : "", sizeof( speechListSounds[ 0 ].sceneName ) );
  1443. speechListIndex++;
  1444. if ( speechListIndex >= SPEECH_LIST_MAX_SOUNDS )
  1445. {
  1446. speechListIndex = 0;
  1447. }
  1448. // Warning( "Speak %s\n", soundname );
  1449. if ( m_fPitch != 1.0f )
  1450. {
  1451. if ( es.m_nPitch )
  1452. es.m_nPitch = static_cast<float>( es.m_nPitch ) * m_fPitch;
  1453. else
  1454. es.m_nPitch = 100.0f * m_fPitch;
  1455. es.m_nFlags |= SND_CHANGE_PITCH;
  1456. }
  1457. EmitSound( filter2, actor->entindex(), es );
  1458. actor->AddSceneEvent( scene, event );
  1459. }
  1460. // Close captioning only on master token no matter what...
  1461. if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER )
  1462. {
  1463. char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ];
  1464. bool validtoken = event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) );
  1465. if ( validtoken )
  1466. {
  1467. char lowercase[ 256 ];
  1468. Q_strncpy( lowercase, tok, sizeof( lowercase ) );
  1469. Q_strlower( lowercase );
  1470. // Remove any players who don't want close captions
  1471. CBaseEntity::RemoveRecipientsIfNotCloseCaptioning( filter );
  1472. // Certain events are marked "don't attenuate", (breencast), skip those here
  1473. if ( !event->IsSuppressingCaptionAttenuation() &&
  1474. ( filter.GetRecipientCount() > 0 ) )
  1475. {
  1476. int c = filter.GetRecipientCount();
  1477. for ( int i = c - 1 ; i >= 0; --i )
  1478. {
  1479. CBasePlayer *player = UTIL_PlayerByIndex( filter.GetRecipientIndex( i ) );
  1480. if ( !player )
  1481. continue;
  1482. Vector playerOrigin = player->GetAbsOrigin();
  1483. if ( AttenuateCaption( lowercase, playerOrigin, es.m_UtlVecSoundOrigin ) )
  1484. {
  1485. // If the player has a view entity, measure the distance to that
  1486. if ( !player->GetViewEntity() || AttenuateCaption( lowercase, player->GetViewEntity()->GetAbsOrigin(), es.m_UtlVecSoundOrigin ) )
  1487. {
  1488. filter.RemoveRecipient( player );
  1489. }
  1490. }
  1491. }
  1492. }
  1493. // Anyone left?
  1494. if ( filter.GetRecipientCount() > 0 )
  1495. {
  1496. float endtime = event->GetLastSlaveEndTime();
  1497. float durationShort = event->GetDuration();
  1498. float durationLong = endtime - event->GetStartTime();
  1499. float duration = MAX( durationShort, durationLong );
  1500. byte byteflags = CLOSE_CAPTION_WARNIFMISSING; // warnifmissing
  1501. /*
  1502. // Never for .vcds...
  1503. if ( fromplayer )
  1504. {
  1505. byteflags |= CLOSE_CAPTION_FROMPLAYER;
  1506. }
  1507. */
  1508. char const *pszActorModel = STRING( actor->GetModelName() );
  1509. gender_t gender = soundemitterbase->GetActorGender( pszActorModel );
  1510. if ( gender == GENDER_MALE )
  1511. {
  1512. byteflags |= CLOSE_CAPTION_GENDER_MALE;
  1513. }
  1514. else if ( gender == GENDER_FEMALE )
  1515. {
  1516. byteflags |= CLOSE_CAPTION_GENDER_FEMALE;
  1517. }
  1518. // Send caption and duration hint down to client
  1519. UserMessageBegin( filter, "CloseCaption" );
  1520. WRITE_STRING( lowercase );
  1521. WRITE_SHORT( MIN( 255, (int)( duration * 10.0f ) ) );
  1522. WRITE_BYTE( byteflags ); // warn on missing
  1523. MessageEnd();
  1524. }
  1525. }
  1526. }
  1527. }
  1528. }
  1529. void CSceneEntity::DispatchEndSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1530. {
  1531. actor->RemoveSceneEvent( scene, event, m_bRestoring );
  1532. }
  1533. //-----------------------------------------------------------------------------
  1534. // Purpose:
  1535. // Input : *actor -
  1536. // *actor2 -
  1537. //-----------------------------------------------------------------------------
  1538. void CSceneEntity::DispatchStartFace( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event )
  1539. {
  1540. actor->AddSceneEvent( scene, event, actor2 );
  1541. }
  1542. //-----------------------------------------------------------------------------
  1543. // Purpose:
  1544. // Input : *actor -
  1545. // *actor2 -
  1546. //-----------------------------------------------------------------------------
  1547. void CSceneEntity::DispatchEndFace( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1548. {
  1549. actor->RemoveSceneEvent( scene, event, m_bRestoring );
  1550. }
  1551. //-----------------------------------------------------------------------------
  1552. // Purpose:
  1553. // Input : *actor -
  1554. //-----------------------------------------------------------------------------
  1555. void CSceneEntity::DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1556. {
  1557. actor->AddSceneEvent( scene, event );
  1558. }
  1559. //-----------------------------------------------------------------------------
  1560. // Purpose:
  1561. // Input : *actor -
  1562. //-----------------------------------------------------------------------------
  1563. void CSceneEntity::DispatchEndSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1564. {
  1565. actor->RemoveSceneEvent( scene, event, m_bRestoring );
  1566. }
  1567. //-----------------------------------------------------------------------------
  1568. // Purpose: NPC can play interstitial vcds (such as responding to the player doing something during a scene)
  1569. // Input : *scene -
  1570. // *actor -
  1571. // *event -
  1572. //-----------------------------------------------------------------------------
  1573. void CSceneEntity::DispatchStartPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1574. {
  1575. actor->SetPermitResponse( gpGlobals->curtime + event->GetDuration() );
  1576. }
  1577. //-----------------------------------------------------------------------------
  1578. // Purpose:
  1579. // Input : *scene -
  1580. // *actor -
  1581. // *event -
  1582. //-----------------------------------------------------------------------------
  1583. void CSceneEntity::DispatchEndPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  1584. {
  1585. actor->SetPermitResponse( 0 );
  1586. }
  1587. //-----------------------------------------------------------------------------
  1588. // Purpose:
  1589. //-----------------------------------------------------------------------------
  1590. float CSceneEntity::EstimateLength( void )
  1591. {
  1592. if ( !m_pScene )
  1593. {
  1594. return GetSceneDuration( STRING( m_iszSceneFile ) );
  1595. }
  1596. return m_pScene->FindStopTime();
  1597. }
  1598. //-----------------------------------------------------------------------------
  1599. // Purpose:
  1600. // NOTE: returns false if scene hasn't loaded yet
  1601. //-----------------------------------------------------------------------------
  1602. void CSceneEntity::CancelIfSceneInvolvesActor( CBaseEntity *pActor )
  1603. {
  1604. if ( InvolvesActor( pActor ) )
  1605. {
  1606. LocalScene_Printf( "%s : cancelled for '%s'\n", STRING( m_iszSceneFile ), pActor->GetDebugName() );
  1607. CancelPlayback();
  1608. }
  1609. }
  1610. //-----------------------------------------------------------------------------
  1611. // Purpose:
  1612. // NOTE: returns false if scene hasn't loaded yet
  1613. //-----------------------------------------------------------------------------
  1614. bool CSceneEntity::InvolvesActor( CBaseEntity *pActor )
  1615. {
  1616. if ( !m_pScene )
  1617. return false;
  1618. int i;
  1619. for ( i = 0 ; i < m_pScene->GetNumActors(); i++ )
  1620. {
  1621. CBaseFlex *pTestActor = FindNamedActor( i );
  1622. if ( !pTestActor )
  1623. continue;
  1624. if ( pTestActor == pActor )
  1625. return true;
  1626. }
  1627. return false;
  1628. }
  1629. //-----------------------------------------------------------------------------
  1630. // Purpose:
  1631. //-----------------------------------------------------------------------------
  1632. void CSceneEntity::DoThink( float frametime )
  1633. {
  1634. CheckInterruptCompletion();
  1635. if ( m_bWaitingForActor || m_bWaitingForInterrupt )
  1636. {
  1637. // Try to start playback.
  1638. StartPlayback();
  1639. }
  1640. if ( !m_pScene )
  1641. return;
  1642. if ( !m_bIsPlayingBack )
  1643. return;
  1644. // catch bad pitch shifting from old save games
  1645. Assert( m_fPitch >= SCENE_MIN_PITCH && m_fPitch <= SCENE_MAX_PITCH );
  1646. m_fPitch = clamp( m_fPitch, SCENE_MIN_PITCH, SCENE_MAX_PITCH );
  1647. if ( m_bPaused )
  1648. {
  1649. PauseThink();
  1650. return;
  1651. }
  1652. // Msg("%.2f %s\n", gpGlobals->curtime, STRING( m_iszSceneFile ) );
  1653. //Msg( "SV: %d, %f for %s\n", gpGlobals->tickcount, m_flCurrentTime, m_pScene->GetFilename() );
  1654. m_flFrameTime = frametime;
  1655. m_pScene->SetSoundFileStartupLatency( GetSoundSystemLatency() );
  1656. // Tell scene to go
  1657. m_pScene->Think( m_flCurrentTime );
  1658. // Did we get to the end
  1659. if ( !m_bPaused )
  1660. {
  1661. // Drive simulation time for scene
  1662. SetCurrentTime( m_flCurrentTime + m_flFrameTime * m_fPitch, false );
  1663. if ( m_pScene->SimulationFinished() )
  1664. {
  1665. OnSceneFinished( false, true );
  1666. // Stop them from doing anything special
  1667. ClearSchedules( m_pScene );
  1668. }
  1669. }
  1670. else
  1671. {
  1672. // Drive simulation time for scene
  1673. SetCurrentTime( m_pScene->GetTime(), true );
  1674. }
  1675. }
  1676. //-----------------------------------------------------------------------------
  1677. // Purpose: Input handlers
  1678. //-----------------------------------------------------------------------------
  1679. void CSceneEntity::InputStartPlayback( inputdata_t &inputdata )
  1680. {
  1681. // Already playing, ignore
  1682. if ( m_bIsPlayingBack )
  1683. return;
  1684. // Already waiting on someone.
  1685. if ( m_bWaitingForActor || m_bWaitingForInterrupt )
  1686. return;
  1687. ClearActivatorTargets();
  1688. m_hActivator = inputdata.pActivator;
  1689. StartPlayback();
  1690. }
  1691. void CSceneEntity::InputPausePlayback( inputdata_t &inputdata )
  1692. {
  1693. PausePlayback();
  1694. m_bPausedViaInput = true;
  1695. }
  1696. void CSceneEntity::InputResumePlayback( inputdata_t &inputdata )
  1697. {
  1698. ResumePlayback();
  1699. }
  1700. void CSceneEntity::InputCancelPlayback( inputdata_t &inputdata )
  1701. {
  1702. LocalScene_Printf( "%s : cancelled via input\n", STRING( m_iszSceneFile ) );
  1703. CancelPlayback();
  1704. }
  1705. void CSceneEntity::InputScriptPlayerDeath( inputdata_t &inputdata )
  1706. {
  1707. if ( m_iPlayerDeathBehavior == SCRIPT_CANCEL )
  1708. {
  1709. LocalScene_Printf( "%s : cancelled via player death\n", STRING( m_iszSceneFile ) );
  1710. CancelPlayback();
  1711. }
  1712. }
  1713. void CSceneEntity::InputCancelAtNextInterrupt( inputdata_t &inputdata )
  1714. {
  1715. // If we're currently in an interruptable point, interrupt immediately
  1716. if ( IsInterruptable() )
  1717. {
  1718. LocalScene_Printf( "%s : cancelled via input at interrupt point\n", STRING( m_iszSceneFile ) );
  1719. CancelPlayback();
  1720. return;
  1721. }
  1722. // Otherwise, cancel when we next hit an interrupt point
  1723. m_bCancelAtNextInterrupt = true;
  1724. }
  1725. void CSceneEntity::InputPitchShiftPlayback( inputdata_t &inputdata )
  1726. {
  1727. PitchShiftPlayback( inputdata.value.Float() );
  1728. }
  1729. void CSceneEntity::InputTriggerEvent( inputdata_t &inputdata )
  1730. {
  1731. CBaseEntity *pActivator = this; // at some point, find this from the inputdata
  1732. switch ( inputdata.value.Int() )
  1733. {
  1734. case 1:
  1735. m_OnTrigger1.FireOutput( pActivator, this, 0 );
  1736. break;
  1737. case 2:
  1738. m_OnTrigger2.FireOutput( pActivator, this, 0 );
  1739. break;
  1740. case 3:
  1741. m_OnTrigger3.FireOutput( pActivator, this, 0 );
  1742. break;
  1743. case 4:
  1744. m_OnTrigger4.FireOutput( pActivator, this, 0 );
  1745. break;
  1746. case 5:
  1747. m_OnTrigger5.FireOutput( pActivator, this, 0 );
  1748. break;
  1749. case 6:
  1750. m_OnTrigger6.FireOutput( pActivator, this, 0 );
  1751. break;
  1752. case 7:
  1753. m_OnTrigger7.FireOutput( pActivator, this, 0 );
  1754. break;
  1755. case 8:
  1756. m_OnTrigger8.FireOutput( pActivator, this, 0 );
  1757. break;
  1758. case 9:
  1759. m_OnTrigger9.FireOutput( pActivator, this, 0 );
  1760. break;
  1761. case 10:
  1762. m_OnTrigger10.FireOutput( pActivator, this, 0 );
  1763. break;
  1764. case 11:
  1765. m_OnTrigger11.FireOutput( pActivator, this, 0 );
  1766. break;
  1767. case 12:
  1768. m_OnTrigger12.FireOutput( pActivator, this, 0 );
  1769. break;
  1770. case 13:
  1771. m_OnTrigger13.FireOutput( pActivator, this, 0 );
  1772. break;
  1773. case 14:
  1774. m_OnTrigger14.FireOutput( pActivator, this, 0 );
  1775. break;
  1776. case 15:
  1777. m_OnTrigger15.FireOutput( pActivator, this, 0 );
  1778. break;
  1779. case 16:
  1780. m_OnTrigger16.FireOutput( pActivator, this, 0 );
  1781. break;
  1782. }
  1783. }
  1784. //-----------------------------------------------------------------------------
  1785. // Purpose:
  1786. // Input : &inputdata -
  1787. //-----------------------------------------------------------------------------
  1788. void CSceneEntity::InputInterjectResponse( inputdata_t &inputdata )
  1789. {
  1790. // Not currently playing a scene
  1791. if ( !m_pScene )
  1792. return;
  1793. CUtlVector<CAI_BaseActor *> candidates;
  1794. for ( int i = 0 ; i < m_pScene->GetNumActors(); i++ )
  1795. {
  1796. CBaseFlex *pTestActor = FindNamedActor( i );
  1797. if ( !pTestActor )
  1798. continue;
  1799. CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor *>(pTestActor);
  1800. if ( !pBaseActor || !pBaseActor->IsAlive() )
  1801. continue;
  1802. candidates.AddToTail( pBaseActor );
  1803. }
  1804. int c = candidates.Count();
  1805. if ( !c )
  1806. return;
  1807. if ( !m_bIsPlayingBack )
  1808. {
  1809. // Use any actor if not playing a scene
  1810. // int useIndex = RandomInt( 0, c - 1 );
  1811. Assert( !"m_bIsPlayBack is false and this code does nothing. Should it?");
  1812. }
  1813. else
  1814. {
  1815. CUtlString modifiers("scene:");
  1816. modifiers += STRING( GetEntityName() );
  1817. while (candidates.Count() > 0)
  1818. {
  1819. // Pick a random slot in the candidates array.
  1820. int slot = RandomInt( 0, candidates.Count() - 1 );
  1821. CAI_BaseActor *npc = candidates[ slot ];
  1822. // Try to find the response for this slot.
  1823. AI_Response response;
  1824. bool result = npc->SpeakFindResponse( response, inputdata.value.String(), modifiers.Get() );
  1825. if ( result )
  1826. {
  1827. float duration = npc->GetResponseDuration( response );
  1828. if ( ( duration > 0.0f ) && npc->PermitResponse( duration ) )
  1829. {
  1830. // If we could look it up, dispatch it and bail.
  1831. npc->SpeakDispatchResponse( inputdata.value.String(), response );
  1832. return;
  1833. }
  1834. }
  1835. // Remove this entry and look for another one.
  1836. candidates.FastRemove(slot);
  1837. }
  1838. }
  1839. }
  1840. //-----------------------------------------------------------------------------
  1841. //-----------------------------------------------------------------------------
  1842. void CSceneEntity::InputStopWaitingForActor( inputdata_t &inputdata )
  1843. {
  1844. if( m_bIsPlayingBack )
  1845. {
  1846. // Already started.
  1847. return;
  1848. }
  1849. m_bWaitingForActor = false;
  1850. }
  1851. bool CSceneEntity::CheckActors()
  1852. {
  1853. Assert( m_pScene );
  1854. if ( !m_pScene )
  1855. return false;
  1856. int i;
  1857. for ( i = 0 ; i < m_pScene->GetNumActors(); i++ )
  1858. {
  1859. CBaseFlex *pTestActor = FindNamedActor( i );
  1860. if ( !pTestActor )
  1861. continue;
  1862. if ( !pTestActor->MyCombatCharacterPointer() )
  1863. continue;
  1864. if ( !pTestActor->MyCombatCharacterPointer()->IsAlive() )
  1865. return false;
  1866. if ( m_BusyActor == SCENE_BUSYACTOR_WAIT )
  1867. {
  1868. CAI_BaseNPC *pActor = pTestActor->MyNPCPointer();
  1869. if ( pActor )
  1870. {
  1871. bool bShouldWait = false;
  1872. if ( hl2_episodic.GetBool() )
  1873. {
  1874. // Episodic waits until the NPC is fully finished with any .vcd with speech in it
  1875. if ( IsRunningScriptedSceneWithSpeech( pActor ) )
  1876. {
  1877. bShouldWait = true;
  1878. }
  1879. #ifdef HL2_EPISODIC
  1880. // HACK: Alyx cannot play scenes when she's in the middle of transitioning
  1881. if ( pActor->IsInAVehicle() )
  1882. {
  1883. CNPC_Alyx *pAlyx = dynamic_cast<CNPC_Alyx *>(pActor);
  1884. if ( pAlyx != NULL && ( pAlyx->GetPassengerState() == PASSENGER_STATE_ENTERING || pAlyx->GetPassengerState() == PASSENGER_STATE_EXITING ) )
  1885. {
  1886. bShouldWait = true;
  1887. }
  1888. }
  1889. #endif // HL2_EPISODIC
  1890. }
  1891. if ( pActor->GetExpresser() && pActor->GetExpresser()->IsSpeaking() )
  1892. {
  1893. bShouldWait = true;
  1894. }
  1895. if ( bShouldWait )
  1896. {
  1897. // One of the actors for this scene is talking already.
  1898. // Try again next think.
  1899. m_bWaitingForActor = true;
  1900. return false;
  1901. }
  1902. }
  1903. }
  1904. else if ( m_BusyActor == SCENE_BUSYACTOR_INTERRUPT || m_BusyActor == SCENE_BUSYACTOR_INTERRUPT_CANCEL )
  1905. {
  1906. CBaseCombatCharacter *pActor = pTestActor->MyCombatCharacterPointer();
  1907. if ( pActor && !IsInInterruptableScenes( pActor ) )
  1908. {
  1909. // One of the actors is in a scene that's not at an interrupt point.
  1910. // Wait until the scene finishes or an interrupt point is reached.
  1911. m_bWaitingForInterrupt = true;
  1912. return false;
  1913. }
  1914. if ( m_BusyActor == SCENE_BUSYACTOR_INTERRUPT_CANCEL )
  1915. {
  1916. // Cancel existing scenes
  1917. RemoveActorFromScriptedScenes( pActor, false );
  1918. }
  1919. else
  1920. {
  1921. // Pause existing scenes
  1922. PauseActorsScriptedScenes( pActor, false );
  1923. m_bInterruptedActorsScenes = true;
  1924. }
  1925. }
  1926. pTestActor->StartChoreoScene( m_pScene );
  1927. }
  1928. return true;
  1929. }
  1930. #if !defined( _RETAIL )
  1931. static ConVar scene_async_prefetch_spew( "scene_async_prefetch_spew", "0", 0, "Display async .ani file loading info." );
  1932. #endif
  1933. void CSceneEntity::PrefetchAnimBlocks( CChoreoScene *scene )
  1934. {
  1935. Assert( scene );
  1936. // Build a fast lookup, too
  1937. CUtlMap< CChoreoActor *, CBaseFlex *> actorMap( 0, 0, DefLessFunc( CChoreoActor * ) );
  1938. int spew =
  1939. #if !defined( _RETAIL )
  1940. scene_async_prefetch_spew.GetInt();
  1941. #else
  1942. 0;
  1943. #endif
  1944. int resident = 0;
  1945. int checked = 0;
  1946. // Iterate events and precache necessary resources
  1947. for ( int i = 0; i < scene->GetNumEvents(); i++ )
  1948. {
  1949. CChoreoEvent *event = scene->GetEvent( i );
  1950. if ( !event )
  1951. continue;
  1952. // load any necessary data
  1953. switch ( event->GetType() )
  1954. {
  1955. default:
  1956. break;
  1957. case CChoreoEvent::SEQUENCE:
  1958. case CChoreoEvent::GESTURE:
  1959. {
  1960. CChoreoActor *actor = event->GetActor();
  1961. if ( actor )
  1962. {
  1963. CBaseFlex *pActor = NULL;
  1964. int idx = actorMap.Find( actor );
  1965. if ( idx == actorMap.InvalidIndex() )
  1966. {
  1967. pActor = FindNamedActor( actor );
  1968. idx = actorMap.Insert( actor, pActor );
  1969. }
  1970. else
  1971. {
  1972. pActor = actorMap[ idx ];
  1973. }
  1974. if ( pActor )
  1975. {
  1976. int seq = pActor->LookupSequence( event->GetParameters() );
  1977. if ( seq >= 0 )
  1978. {
  1979. CStudioHdr *pStudioHdr = pActor->GetModelPtr();
  1980. if ( pStudioHdr )
  1981. {
  1982. // Now look up the animblock
  1983. mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( seq );
  1984. for ( int i = 0 ; i < seqdesc.groupsize[ 0 ] ; ++i )
  1985. {
  1986. for ( int j = 0; j < seqdesc.groupsize[ 1 ]; ++j )
  1987. {
  1988. int animation = seqdesc.anim( i, j );
  1989. int baseanimation = pStudioHdr->iRelativeAnim( seq, animation );
  1990. mstudioanimdesc_t &animdesc = pStudioHdr->pAnimdesc( baseanimation );
  1991. ++checked;
  1992. if ( spew != 0 )
  1993. {
  1994. Msg( "%s checking block %d\n", pStudioHdr->pszName(), animdesc.animblock );
  1995. }
  1996. // Async load the animation
  1997. int iFrame = 0;
  1998. const mstudioanim_t *panim = animdesc.pAnim( &iFrame );
  1999. if ( panim )
  2000. {
  2001. ++resident;
  2002. if ( spew > 1 )
  2003. {
  2004. Msg( "%s:%s[%i:%i] was resident\n", pStudioHdr->pszName(), animdesc.pszName(), i, j );
  2005. }
  2006. }
  2007. else
  2008. {
  2009. if ( spew != 0 )
  2010. {
  2011. Msg( "%s:%s[%i:%i] async load\n", pStudioHdr->pszName(), animdesc.pszName(), i, j );
  2012. }
  2013. }
  2014. }
  2015. }
  2016. }
  2017. }
  2018. }
  2019. }
  2020. }
  2021. break;
  2022. }
  2023. }
  2024. if ( !spew || checked <= 0 )
  2025. return;
  2026. Msg( "%d of %d animations resident\n", resident, checked );
  2027. }
  2028. void CSceneEntity::OnLoaded()
  2029. {
  2030. // Nothing
  2031. }
  2032. //-----------------------------------------------------------------------------
  2033. // Purpose: Initiate scene playback
  2034. //-----------------------------------------------------------------------------
  2035. void CSceneEntity::StartPlayback( void )
  2036. {
  2037. if ( !m_pScene )
  2038. {
  2039. if ( m_bSceneMissing )
  2040. return;
  2041. m_pScene = LoadScene( STRING( m_iszSceneFile ), this );
  2042. if ( !m_pScene )
  2043. {
  2044. DevMsg( "%s missing from scenes.image\n", STRING( m_iszSceneFile ) );
  2045. m_bSceneMissing = true;
  2046. return;
  2047. }
  2048. OnLoaded();
  2049. if ( ShouldNetwork() )
  2050. {
  2051. m_nSceneStringIndex = g_pStringTableClientSideChoreoScenes->AddString( CBaseEntity::IsServer(), STRING( m_iszSceneFile ) );
  2052. }
  2053. UpdateTransmitState();
  2054. }
  2055. if ( m_bIsPlayingBack )
  2056. return;
  2057. // Make sure actors are alive and able to handle this scene now, otherwise
  2058. // we'll wait for them to show up
  2059. if ( !CheckActors() )
  2060. {
  2061. return;
  2062. }
  2063. m_bCompletedEarly = false;
  2064. m_bWaitingForActor = false;
  2065. m_bWaitingForInterrupt = false;
  2066. m_bIsPlayingBack = true;
  2067. NetworkProp()->NetworkStateForceUpdate();
  2068. m_bPaused = false;
  2069. SetCurrentTime( 0.0f, true );
  2070. m_pScene->ResetSimulation();
  2071. ClearInterrupt();
  2072. // Put face back in neutral pose
  2073. ClearSceneEvents( m_pScene, false );
  2074. m_OnStart.FireOutput( this, this, 0 );
  2075. // Aysnchronously load speak sounds
  2076. CUtlSymbolTable prefetchSoundSymbolTable;
  2077. CUtlRBTree< SpeakEventSound_t > soundnames( 0, 0, SpeakEventSoundLessFunc );
  2078. BuildSortedSpeakEventSoundsPrefetchList( m_pScene, prefetchSoundSymbolTable, soundnames, 0.0f );
  2079. PrefetchSpeakEventSounds( prefetchSoundSymbolTable, soundnames );
  2080. // Tell any managers we're within that we've started
  2081. int c = m_hListManagers.Count();
  2082. for ( int i = 0; i < c; i++ )
  2083. {
  2084. if ( m_hListManagers[i] )
  2085. {
  2086. m_hListManagers[i]->SceneStarted( this );
  2087. }
  2088. }
  2089. PrefetchAnimBlocks( m_pScene );
  2090. }
  2091. //-----------------------------------------------------------------------------
  2092. // Purpose: Static method used to sort by event start time
  2093. //-----------------------------------------------------------------------------
  2094. bool CSceneEntity::SpeakEventSoundLessFunc( const SpeakEventSound_t& lhs, const SpeakEventSound_t& rhs )
  2095. {
  2096. return lhs.m_flStartTime < rhs.m_flStartTime;
  2097. }
  2098. //-----------------------------------------------------------------------------
  2099. // Purpose: Prefetches the list of sounds build by BuildSortedSpeakEventSoundsPrefetchList
  2100. //-----------------------------------------------------------------------------
  2101. void CSceneEntity::PrefetchSpeakEventSounds( CUtlSymbolTable& table, CUtlRBTree< SpeakEventSound_t >& soundnames )
  2102. {
  2103. for ( int i = soundnames.FirstInorder(); i != soundnames.InvalidIndex() ; i = soundnames.NextInorder( i ) )
  2104. {
  2105. SpeakEventSound_t& sound = soundnames[ i ];
  2106. // Look it up in the string table
  2107. char const *soundname = table.String( sound.m_Symbol );
  2108. // Warning( "Prefetch %s\n", soundname );
  2109. PrefetchScriptSound( soundname );
  2110. }
  2111. }
  2112. //-----------------------------------------------------------------------------
  2113. // Purpose: Builds list of sounds sorted by start time for prefetching
  2114. //-----------------------------------------------------------------------------
  2115. void CSceneEntity::BuildSortedSpeakEventSoundsPrefetchList(
  2116. CChoreoScene *scene,
  2117. CUtlSymbolTable& table,
  2118. CUtlRBTree< SpeakEventSound_t >& soundnames,
  2119. float timeOffset )
  2120. {
  2121. Assert( scene );
  2122. // Iterate events and precache necessary resources
  2123. for ( int i = 0; i < scene->GetNumEvents(); i++ )
  2124. {
  2125. CChoreoEvent *event = scene->GetEvent( i );
  2126. if ( !event )
  2127. continue;
  2128. // load any necessary data
  2129. switch (event->GetType() )
  2130. {
  2131. default:
  2132. break;
  2133. case CChoreoEvent::SPEAK:
  2134. {
  2135. // NOTE: The script entries associated with .vcds are forced to preload to avoid
  2136. // loading hitches during triggering
  2137. char soundname[ CChoreoEvent::MAX_CCTOKEN_STRING ];
  2138. Q_strncpy( soundname, event->GetParameters(), sizeof( soundname ) );
  2139. if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER )
  2140. {
  2141. event->GetPlaybackCloseCaptionToken( soundname, sizeof( soundname ) );
  2142. }
  2143. // In single player, try to use the combined or regular .wav files as needed
  2144. if ( gpGlobals->maxClients == 1 )
  2145. {
  2146. CBasePlayer *player = UTIL_GetLocalPlayer();
  2147. if ( player && !GetSoundNameForPlayer( event, player, soundname, sizeof( soundname ), player ) )
  2148. {
  2149. // Skip to next event
  2150. continue;
  2151. }
  2152. }
  2153. /*
  2154. else
  2155. {
  2156. // UNDONE: Probably need some other solution in multiplayer... (not sure how to "prefetch" on certain players
  2157. // with one sound, but not prefetch the same sound for others...)
  2158. }
  2159. */
  2160. SpeakEventSound_t ses;
  2161. ses.m_Symbol = table.AddString( soundname );
  2162. ses.m_flStartTime = timeOffset + event->GetStartTime();
  2163. soundnames.Insert( ses );
  2164. }
  2165. break;
  2166. case CChoreoEvent::SUBSCENE:
  2167. {
  2168. // Only allow a single level of subscenes for now
  2169. if ( !scene->IsSubScene() )
  2170. {
  2171. CChoreoScene *subscene = event->GetSubScene();
  2172. if ( !subscene )
  2173. {
  2174. subscene = LoadScene( event->GetParameters(), this );
  2175. subscene->SetSubScene( true );
  2176. event->SetSubScene( subscene );
  2177. // Now precache it's resources, if any
  2178. BuildSortedSpeakEventSoundsPrefetchList( subscene, table, soundnames, event->GetStartTime() );
  2179. }
  2180. }
  2181. }
  2182. break;
  2183. }
  2184. }
  2185. }
  2186. //-----------------------------------------------------------------------------
  2187. // Purpose:
  2188. //-----------------------------------------------------------------------------
  2189. void CSceneEntity::PausePlayback( void )
  2190. {
  2191. if ( !m_bIsPlayingBack )
  2192. return;
  2193. if ( m_bPaused )
  2194. return;
  2195. m_bPaused = true;
  2196. }
  2197. //-----------------------------------------------------------------------------
  2198. // Purpose:
  2199. //-----------------------------------------------------------------------------
  2200. void CSceneEntity::ResumePlayback( void )
  2201. {
  2202. if ( !m_bIsPlayingBack )
  2203. return;
  2204. if ( !m_bPaused )
  2205. return;
  2206. Assert( m_pScene );
  2207. if ( !m_pScene )
  2208. {
  2209. // This should never happen!!!!
  2210. return;
  2211. }
  2212. // FIXME: Iterate using m_pScene->IterateResumeConditionEvents and
  2213. // only resume if the event conditions have all been satisfied
  2214. // FIXME: Just resume for now
  2215. m_pScene->ResumeSimulation();
  2216. m_bPaused = false;
  2217. m_bPausedViaInput = false;
  2218. }
  2219. //-----------------------------------------------------------------------------
  2220. // Purpose:
  2221. //-----------------------------------------------------------------------------
  2222. void CSceneEntity::CancelPlayback( void )
  2223. {
  2224. if ( !m_bIsPlayingBack )
  2225. return;
  2226. m_bIsPlayingBack = false;
  2227. m_bPaused = false;
  2228. m_OnCanceled.FireOutput( this, this, 0 );
  2229. LocalScene_Printf( "%s : %8.2f: canceled\n", STRING( m_iszSceneFile ), m_flCurrentTime );
  2230. OnSceneFinished( true, false );
  2231. }
  2232. void CSceneEntity::PitchShiftPlayback( float fPitch )
  2233. {
  2234. fPitch = clamp( fPitch, SCENE_MIN_PITCH, SCENE_MAX_PITCH );
  2235. m_fPitch = fPitch;
  2236. if ( !m_pScene )
  2237. return;
  2238. for ( int iActor = 0 ; iActor < m_pScene->GetNumActors(); ++iActor )
  2239. {
  2240. CBaseFlex *pTestActor = FindNamedActor( iActor );
  2241. if ( !pTestActor )
  2242. continue;
  2243. char szBuff[ 256 ];
  2244. if ( m_pScene->GetPlayingSoundName( szBuff, sizeof( szBuff ) ) )
  2245. {
  2246. CPASAttenuationFilter filter( pTestActor );
  2247. EmitSound_t params;
  2248. params.m_pSoundName = szBuff;
  2249. params.m_nPitch = 100.0f * fPitch;
  2250. params.m_nFlags = SND_CHANGE_PITCH;
  2251. pTestActor->EmitSound( filter, pTestActor->entindex(), params );
  2252. }
  2253. }
  2254. }
  2255. //-----------------------------------------------------------------------------
  2256. // Purpose: Start a resume scene, if we have one, and resume playing when it finishes
  2257. //-----------------------------------------------------------------------------
  2258. void CSceneEntity::QueueResumePlayback( void )
  2259. {
  2260. // Do we have a resume scene?
  2261. if ( m_iszResumeSceneFile != NULL_STRING )
  2262. {
  2263. bool bStartedScene = false;
  2264. // If it has ".vcd" somewhere in the string, try using it as a scene file first
  2265. if ( Q_stristr( STRING(m_iszResumeSceneFile), ".vcd" ) )
  2266. {
  2267. bStartedScene = InstancedScriptedScene( NULL, STRING(m_iszResumeSceneFile), &m_hWaitingForThisResumeScene, 0, false ) != 0;
  2268. }
  2269. // HACKHACK: For now, get the first target, and see if we can find a response for him
  2270. if ( !bStartedScene )
  2271. {
  2272. CBaseFlex *pActor = FindNamedActor( 0 );
  2273. if ( pActor )
  2274. {
  2275. CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor*>(pActor);
  2276. if ( pBaseActor )
  2277. {
  2278. AI_Response response;
  2279. bool result = pBaseActor->SpeakFindResponse( response, STRING(m_iszResumeSceneFile), NULL );
  2280. if ( result )
  2281. {
  2282. const char *szResponse = response.GetResponsePtr();
  2283. bStartedScene = InstancedScriptedScene( NULL, szResponse, &m_hWaitingForThisResumeScene, 0, false ) != 0;
  2284. }
  2285. }
  2286. }
  2287. }
  2288. // If we started a scene/response, wait for it to finish
  2289. if ( bStartedScene )
  2290. {
  2291. m_bWaitingForResumeScene = true;
  2292. }
  2293. else
  2294. {
  2295. // Failed to create the scene. Resume immediately.
  2296. ResumePlayback();
  2297. }
  2298. }
  2299. else
  2300. {
  2301. // No resume scene, so just resume immediately
  2302. ResumePlayback();
  2303. }
  2304. }
  2305. //-----------------------------------------------------------------------------
  2306. // Purpose: Query whether the scene actually loaded. Only meaninful after Spawn()
  2307. //-----------------------------------------------------------------------------
  2308. bool CSceneEntity::ValidScene() const
  2309. {
  2310. return ( m_pScene != NULL );
  2311. }
  2312. //-----------------------------------------------------------------------------
  2313. // Purpose:
  2314. // Input : *pActor -
  2315. // *scene -
  2316. // *event -
  2317. //-----------------------------------------------------------------------------
  2318. void CSceneEntity::DispatchStartSubScene( CChoreoScene *scene, CBaseFlex *pActor, CChoreoEvent *event)
  2319. {
  2320. if ( !scene->IsSubScene() )
  2321. {
  2322. CChoreoScene *subscene = event->GetSubScene();
  2323. if ( !subscene )
  2324. {
  2325. Assert( 0 );
  2326. /*
  2327. subscene = LoadScene( event->GetParameters() );
  2328. subscene->SetSubScene( true );
  2329. event->SetSubScene( subscene );
  2330. */
  2331. }
  2332. if ( subscene )
  2333. {
  2334. subscene->ResetSimulation();
  2335. }
  2336. }
  2337. }
  2338. //-----------------------------------------------------------------------------
  2339. // Purpose: All events are leading edge triggered
  2340. // Input : currenttime -
  2341. // *event -
  2342. //-----------------------------------------------------------------------------
  2343. void CSceneEntity::StartEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event )
  2344. {
  2345. Assert( event );
  2346. if ( !Q_stricmp( event->GetName(), "NULL" ) )
  2347. {
  2348. LocalScene_Printf( "%s : %8.2f: ignored %s\n", STRING( m_iszSceneFile ), currenttime, event->GetDescription() );
  2349. return;
  2350. }
  2351. CBaseFlex *pActor = NULL;
  2352. CChoreoActor *actor = event->GetActor();
  2353. if ( actor )
  2354. {
  2355. pActor = FindNamedActor( actor );
  2356. if (pActor == NULL)
  2357. {
  2358. Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), actor->GetName() );
  2359. return;
  2360. }
  2361. }
  2362. LocalScene_Printf( "%s : %8.2f: start %s\n", STRING( m_iszSceneFile ), currenttime, event->GetDescription() );
  2363. switch ( event->GetType() )
  2364. {
  2365. case CChoreoEvent::SUBSCENE:
  2366. {
  2367. if ( pActor && !IsMultiplayer() )
  2368. {
  2369. DispatchStartSubScene( scene, pActor, event );
  2370. }
  2371. }
  2372. break;
  2373. case CChoreoEvent::EXPRESSION:
  2374. {
  2375. if ( pActor && !IsMultiplayer() )
  2376. {
  2377. DispatchStartExpression( scene, pActor, event );
  2378. }
  2379. }
  2380. break;
  2381. case CChoreoEvent::FLEXANIMATION:
  2382. {
  2383. if ( pActor && !IsMultiplayer() )
  2384. {
  2385. DispatchStartFlexAnimation( scene, pActor, event );
  2386. }
  2387. }
  2388. break;
  2389. case CChoreoEvent::LOOKAT:
  2390. {
  2391. if ( pActor && !IsMultiplayer() )
  2392. {
  2393. CBaseEntity *pActor2 = FindNamedEntity( event->GetParameters( ), pActor );
  2394. if ( pActor2 )
  2395. {
  2396. // Huh?
  2397. DispatchStartLookAt( scene, pActor, pActor2, event );
  2398. }
  2399. else
  2400. {
  2401. Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), event->GetParameters() );
  2402. }
  2403. }
  2404. }
  2405. break;
  2406. case CChoreoEvent::SPEAK:
  2407. {
  2408. if ( pActor )
  2409. {
  2410. // Speaking is edge triggered
  2411. // FIXME: dB hack. soundlevel needs to be moved into inside of wav?
  2412. soundlevel_t iSoundlevel = SNDLVL_TALKING;
  2413. if (event->GetParameters2())
  2414. {
  2415. iSoundlevel = (soundlevel_t)atoi( event->GetParameters2() );
  2416. if (iSoundlevel == SNDLVL_NONE)
  2417. iSoundlevel = SNDLVL_TALKING;
  2418. }
  2419. DispatchStartSpeak( scene, pActor, event, iSoundlevel );
  2420. }
  2421. }
  2422. break;
  2423. case CChoreoEvent::MOVETO:
  2424. {
  2425. // FIXME: make sure moveto's aren't edge triggered
  2426. if ( !event->HasEndTime() )
  2427. {
  2428. event->SetEndTime( event->GetStartTime() + 1.0 );
  2429. }
  2430. if ( pActor && !IsMultiplayer() )
  2431. {
  2432. CBaseEntity *pActor2 = NULL;
  2433. if ( event->GetParameters3( ) && strlen( event->GetParameters3( ) ) > 0 )
  2434. {
  2435. pActor2 = FindNamedEntityClosest( event->GetParameters( ), pActor, false, true, event->GetParameters3( ) );
  2436. }
  2437. else
  2438. {
  2439. pActor2 = FindNamedEntity( event->GetParameters( ), pActor, false, true );
  2440. }
  2441. if ( pActor2 )
  2442. {
  2443. DispatchStartMoveTo( scene, pActor, pActor2, event );
  2444. }
  2445. else
  2446. {
  2447. Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), event->GetParameters() );
  2448. }
  2449. }
  2450. }
  2451. break;
  2452. case CChoreoEvent::FACE:
  2453. {
  2454. if ( pActor && !IsMultiplayer() )
  2455. {
  2456. CBaseEntity *pActor2 = FindNamedEntity( event->GetParameters( ), pActor );
  2457. if ( pActor2 )
  2458. {
  2459. DispatchStartFace( scene, pActor, pActor2, event );
  2460. }
  2461. else
  2462. {
  2463. Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), event->GetParameters() );
  2464. }
  2465. }
  2466. }
  2467. break;
  2468. case CChoreoEvent::GESTURE:
  2469. {
  2470. if ( pActor )
  2471. {
  2472. DispatchStartGesture( scene, pActor, event );
  2473. }
  2474. }
  2475. break;
  2476. case CChoreoEvent::GENERIC:
  2477. {
  2478. // If the first token in the parameters is "debugtext", print the rest of the text
  2479. if ( event->GetParameters() && !Q_strncmp( event->GetParameters(), "debugtext", 9 ) )
  2480. {
  2481. const char *pszText = event->GetParameters() + 10;
  2482. hudtextparms_s tTextParam;
  2483. tTextParam.x = -1;
  2484. tTextParam.y = 0.65;
  2485. tTextParam.effect = 0;
  2486. tTextParam.r1 = 255;
  2487. tTextParam.g1 = 170;
  2488. tTextParam.b1 = 0;
  2489. tTextParam.a1 = 255;
  2490. tTextParam.r2 = 255;
  2491. tTextParam.g2 = 170;
  2492. tTextParam.b2 = 0;
  2493. tTextParam.a2 = 255;
  2494. tTextParam.fadeinTime = 0;
  2495. tTextParam.fadeoutTime = 0;
  2496. tTextParam.holdTime = 3.1;
  2497. tTextParam.fxTime = 0;
  2498. tTextParam.channel = 1;
  2499. UTIL_HudMessageAll( tTextParam, pszText );
  2500. break;
  2501. }
  2502. if ( pActor )
  2503. {
  2504. DispatchStartGeneric( scene, pActor, event );
  2505. }
  2506. }
  2507. break;
  2508. case CChoreoEvent::FIRETRIGGER:
  2509. {
  2510. if ( IsMultiplayer() )
  2511. break;
  2512. // Don't re-fire triggers during restore, the entities should already reflect all such state...
  2513. if ( m_bRestoring )
  2514. {
  2515. break;
  2516. }
  2517. CBaseEntity *pActivator = pActor;
  2518. if (!pActivator)
  2519. {
  2520. pActivator = this;
  2521. }
  2522. // FIXME: how do I decide who fired it??
  2523. switch( atoi( event->GetParameters() ) )
  2524. {
  2525. case 1:
  2526. m_OnTrigger1.FireOutput( pActivator, this, 0 );
  2527. break;
  2528. case 2:
  2529. m_OnTrigger2.FireOutput( pActivator, this, 0 );
  2530. break;
  2531. case 3:
  2532. m_OnTrigger3.FireOutput( pActivator, this, 0 );
  2533. break;
  2534. case 4:
  2535. m_OnTrigger4.FireOutput( pActivator, this, 0 );
  2536. break;
  2537. case 5:
  2538. m_OnTrigger5.FireOutput( pActivator, this, 0 );
  2539. break;
  2540. case 6:
  2541. m_OnTrigger6.FireOutput( pActivator, this, 0 );
  2542. break;
  2543. case 7:
  2544. m_OnTrigger7.FireOutput( pActivator, this, 0 );
  2545. break;
  2546. case 8:
  2547. m_OnTrigger8.FireOutput( pActivator, this, 0 );
  2548. break;
  2549. case 9:
  2550. m_OnTrigger9.FireOutput( pActivator, this, 0 );
  2551. break;
  2552. case 10:
  2553. m_OnTrigger10.FireOutput( pActivator, this, 0 );
  2554. break;
  2555. case 11:
  2556. m_OnTrigger11.FireOutput( pActivator, this, 0 );
  2557. break;
  2558. case 12:
  2559. m_OnTrigger12.FireOutput( pActivator, this, 0 );
  2560. break;
  2561. case 13:
  2562. m_OnTrigger13.FireOutput( pActivator, this, 0 );
  2563. break;
  2564. case 14:
  2565. m_OnTrigger14.FireOutput( pActivator, this, 0 );
  2566. break;
  2567. case 15:
  2568. m_OnTrigger15.FireOutput( pActivator, this, 0 );
  2569. break;
  2570. case 16:
  2571. m_OnTrigger16.FireOutput( pActivator, this, 0 );
  2572. break;
  2573. }
  2574. }
  2575. break;
  2576. case CChoreoEvent::SEQUENCE:
  2577. {
  2578. if ( pActor )
  2579. {
  2580. DispatchStartSequence( scene, pActor, event );
  2581. }
  2582. }
  2583. break;
  2584. case CChoreoEvent::SECTION:
  2585. {
  2586. if ( IsMultiplayer() )
  2587. break;
  2588. // Pauses scene playback
  2589. DispatchPauseScene( scene, event->GetParameters() );
  2590. }
  2591. break;
  2592. case CChoreoEvent::LOOP:
  2593. {
  2594. DispatchProcessLoop( scene, event );
  2595. }
  2596. break;
  2597. case CChoreoEvent::INTERRUPT:
  2598. {
  2599. if ( IsMultiplayer() )
  2600. break;
  2601. DispatchStartInterrupt( scene, event );
  2602. }
  2603. break;
  2604. case CChoreoEvent::STOPPOINT:
  2605. {
  2606. if ( IsMultiplayer() )
  2607. break;
  2608. DispatchStopPoint( scene, event->GetParameters() );
  2609. }
  2610. break;
  2611. case CChoreoEvent::PERMIT_RESPONSES:
  2612. {
  2613. if ( IsMultiplayer() )
  2614. break;
  2615. DispatchStartPermitResponses( scene, pActor, event );
  2616. }
  2617. break;
  2618. default:
  2619. {
  2620. // FIXME: Unhandeled event
  2621. // Assert(0);
  2622. }
  2623. break;
  2624. }
  2625. }
  2626. //-----------------------------------------------------------------------------
  2627. // Purpose:
  2628. // Input : currenttime -
  2629. // *event -
  2630. //-----------------------------------------------------------------------------
  2631. void CSceneEntity::EndEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event )
  2632. {
  2633. Assert( event );
  2634. if ( !Q_stricmp( event->GetName(), "NULL" ) )
  2635. {
  2636. return;
  2637. }
  2638. CBaseFlex *pActor = NULL;
  2639. CChoreoActor *actor = event->GetActor();
  2640. if ( actor )
  2641. {
  2642. pActor = FindNamedActor( actor );
  2643. }
  2644. LocalScene_Printf( "%s : %8.2f: finish %s\n", STRING( m_iszSceneFile ), currenttime, event->GetDescription() );
  2645. switch ( event->GetType() )
  2646. {
  2647. case CChoreoEvent::EXPRESSION:
  2648. {
  2649. if ( pActor && !IsMultiplayer() )
  2650. {
  2651. DispatchEndExpression( scene, pActor, event );
  2652. }
  2653. }
  2654. break;
  2655. case CChoreoEvent::SPEAK:
  2656. {
  2657. if ( pActor )
  2658. {
  2659. DispatchEndSpeak( scene, pActor, event );
  2660. }
  2661. }
  2662. break;
  2663. case CChoreoEvent::FLEXANIMATION:
  2664. {
  2665. if ( pActor && !IsMultiplayer() )
  2666. {
  2667. DispatchEndFlexAnimation( scene, pActor, event );
  2668. }
  2669. }
  2670. break;
  2671. case CChoreoEvent::LOOKAT:
  2672. {
  2673. if ( pActor && !IsMultiplayer() )
  2674. {
  2675. DispatchEndLookAt( scene, pActor, event );
  2676. }
  2677. }
  2678. break;
  2679. case CChoreoEvent::GESTURE:
  2680. {
  2681. if ( pActor )
  2682. {
  2683. DispatchEndGesture( scene, pActor, event );
  2684. }
  2685. }
  2686. break;
  2687. case CChoreoEvent::GENERIC:
  2688. {
  2689. // If the first token in the parameters is "debugtext", we printed it and we're done
  2690. if ( event->GetParameters() && !Q_strncmp( event->GetParameters(), "debugtext", 9 ) )
  2691. break;
  2692. if ( pActor )
  2693. {
  2694. DispatchEndGeneric( scene, pActor, event );
  2695. }
  2696. }
  2697. break;
  2698. case CChoreoEvent::SEQUENCE:
  2699. {
  2700. if ( pActor )
  2701. {
  2702. DispatchEndSequence( scene, pActor, event );
  2703. }
  2704. }
  2705. break;
  2706. case CChoreoEvent::FACE:
  2707. {
  2708. if ( pActor && !IsMultiplayer() )
  2709. {
  2710. DispatchEndFace( scene, pActor, event );
  2711. }
  2712. }
  2713. break;
  2714. case CChoreoEvent::MOVETO:
  2715. {
  2716. if ( pActor && !IsMultiplayer() )
  2717. {
  2718. DispatchEndMoveTo( scene, pActor, event );
  2719. }
  2720. }
  2721. break;
  2722. case CChoreoEvent::SUBSCENE:
  2723. {
  2724. if ( IsMultiplayer() )
  2725. break;
  2726. CChoreoScene *subscene = event->GetSubScene();
  2727. if ( subscene )
  2728. {
  2729. subscene->ResetSimulation();
  2730. }
  2731. }
  2732. break;
  2733. case CChoreoEvent::INTERRUPT:
  2734. {
  2735. if ( IsMultiplayer() )
  2736. break;
  2737. DispatchEndInterrupt( scene, event );
  2738. }
  2739. break;
  2740. case CChoreoEvent::PERMIT_RESPONSES:
  2741. {
  2742. if ( IsMultiplayer() )
  2743. break;
  2744. DispatchEndPermitResponses( scene, pActor, event );
  2745. }
  2746. break;
  2747. default:
  2748. break;
  2749. }
  2750. }
  2751. //-----------------------------------------------------------------------------
  2752. // Purpose: Only spew one time per missing scene!!!
  2753. // Input : *scenename -
  2754. //-----------------------------------------------------------------------------
  2755. void MissingSceneWarning( char const *scenename )
  2756. {
  2757. static CUtlSymbolTable missing;
  2758. // Make sure we only show the message once
  2759. if ( UTL_INVAL_SYMBOL == missing.Find( scenename ) )
  2760. {
  2761. missing.AddString( scenename );
  2762. Warning( "Scene '%s' missing!\n", scenename );
  2763. }
  2764. }
  2765. bool CSceneEntity::ShouldNetwork() const
  2766. {
  2767. if ( m_bMultiplayer )
  2768. {
  2769. if ( m_pScene &&
  2770. ( m_pScene->HasEventsOfType( CChoreoEvent::FLEXANIMATION ) ||
  2771. m_pScene->HasEventsOfType( CChoreoEvent::EXPRESSION )||
  2772. m_pScene->HasEventsOfType( CChoreoEvent::GESTURE ) ||
  2773. m_pScene->HasEventsOfType( CChoreoEvent::SEQUENCE ) ) )
  2774. {
  2775. return true;
  2776. }
  2777. }
  2778. else
  2779. {
  2780. if ( m_pScene &&
  2781. ( m_pScene->HasEventsOfType( CChoreoEvent::FLEXANIMATION ) ||
  2782. m_pScene->HasEventsOfType( CChoreoEvent::EXPRESSION ) ) )
  2783. {
  2784. return true;
  2785. }
  2786. }
  2787. return false;
  2788. }
  2789. CChoreoScene *CSceneEntity::LoadScene( const char *filename, IChoreoEventCallback *pCallback )
  2790. {
  2791. DevMsg( 2, "Blocking load of scene from '%s'\n", filename );
  2792. char loadfile[MAX_PATH];
  2793. Q_strncpy( loadfile, filename, sizeof( loadfile ) );
  2794. Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) );
  2795. Q_FixSlashes( loadfile );
  2796. // binary compiled vcd
  2797. void *pBuffer;
  2798. int fileSize;
  2799. if ( !CopySceneFileIntoMemory( loadfile, &pBuffer, &fileSize ) )
  2800. {
  2801. MissingSceneWarning( loadfile );
  2802. return NULL;
  2803. }
  2804. CChoreoScene *pScene = new CChoreoScene( NULL );
  2805. CUtlBuffer buf( pBuffer, fileSize, CUtlBuffer::READ_ONLY );
  2806. if ( !pScene->RestoreFromBinaryBuffer( buf, loadfile, &g_ChoreoStringPool ) )
  2807. {
  2808. Warning( "CSceneEntity::LoadScene: Unable to load binary scene '%s'\n", loadfile );
  2809. delete pScene;
  2810. pScene = NULL;
  2811. }
  2812. else
  2813. {
  2814. pScene->SetPrintFunc( LocalScene_Printf );
  2815. pScene->SetEventCallbackInterface( pCallback );
  2816. }
  2817. FreeSceneFileMemory( pBuffer );
  2818. return pScene;
  2819. }
  2820. CChoreoScene *BlockingLoadScene( const char *filename )
  2821. {
  2822. return CSceneEntity::LoadScene( filename, NULL );
  2823. }
  2824. //-----------------------------------------------------------------------------
  2825. // Purpose:
  2826. //-----------------------------------------------------------------------------
  2827. void CSceneEntity::UnloadScene( void )
  2828. {
  2829. if ( m_pScene )
  2830. {
  2831. ClearSceneEvents( m_pScene, false );
  2832. for ( int i = 0 ; i < m_pScene->GetNumActors(); i++ )
  2833. {
  2834. CBaseFlex *pTestActor = FindNamedActor( i );
  2835. if ( !pTestActor )
  2836. continue;
  2837. pTestActor->RemoveChoreoScene( m_pScene );
  2838. }
  2839. }
  2840. delete m_pScene;
  2841. m_pScene = NULL;
  2842. }
  2843. //-----------------------------------------------------------------------------
  2844. // Purpose: Called every frame that an event is active (Start/EndEvent as also
  2845. // called)
  2846. // Input : *event -
  2847. // Output : Returns true on success, false on failure.
  2848. //-----------------------------------------------------------------------------
  2849. void CSceneEntity::ProcessEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event )
  2850. {
  2851. switch ( event->GetType() )
  2852. {
  2853. case CChoreoEvent::SUBSCENE:
  2854. {
  2855. Assert( event->GetType() == CChoreoEvent::SUBSCENE );
  2856. CChoreoScene *subscene = event->GetSubScene();
  2857. if ( !subscene )
  2858. return;
  2859. if ( subscene->SimulationFinished() )
  2860. return;
  2861. // Have subscenes think for appropriate time
  2862. subscene->Think( m_flFrameTime );
  2863. }
  2864. break;
  2865. default:
  2866. break;
  2867. }
  2868. return;
  2869. }
  2870. //-----------------------------------------------------------------------------
  2871. // Purpose: Called for events that are part of a pause condition
  2872. // Input : *event -
  2873. // Output : Returns true on event completed, false on non-completion.
  2874. //-----------------------------------------------------------------------------
  2875. bool CSceneEntity::CheckEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event )
  2876. {
  2877. switch ( event->GetType() )
  2878. {
  2879. case CChoreoEvent::SUBSCENE:
  2880. {
  2881. }
  2882. break;
  2883. default:
  2884. {
  2885. CBaseFlex *pActor = NULL;
  2886. CChoreoActor *actor = event->GetActor();
  2887. if ( actor )
  2888. {
  2889. pActor = FindNamedActor( actor );
  2890. if (pActor == NULL)
  2891. {
  2892. Warning( "CSceneEntity %s unable to find actor \"%s\"\n", STRING(GetEntityName()), actor->GetName() );
  2893. return true;
  2894. }
  2895. }
  2896. if (pActor)
  2897. {
  2898. return pActor->CheckSceneEvent( currenttime, scene, event );
  2899. }
  2900. }
  2901. break;
  2902. }
  2903. return true;
  2904. }
  2905. //-----------------------------------------------------------------------------
  2906. // Purpose: Get a sticky version of a named actor
  2907. // Input : CChoreoActor
  2908. // Output : CBaseFlex
  2909. //-----------------------------------------------------------------------------
  2910. CBaseFlex *CSceneEntity::FindNamedActor( int index )
  2911. {
  2912. if (m_hActorList.Count() == 0)
  2913. {
  2914. m_hActorList.SetCount( m_pScene->GetNumActors() );
  2915. NetworkProp()->NetworkStateForceUpdate();
  2916. }
  2917. if ( !m_hActorList.IsValidIndex( index ) )
  2918. {
  2919. DevWarning( "Scene %s has %d actors, but scene entity only has %d actors\n", m_pScene->GetFilename(), m_pScene->GetNumActors(), m_hActorList.Size() );
  2920. return NULL;
  2921. }
  2922. CBaseFlex *pActor = m_hActorList[ index ];
  2923. if (pActor == NULL || !pActor->IsAlive() )
  2924. {
  2925. CChoreoActor *pChoreoActor = m_pScene->GetActor( index );
  2926. if ( !pChoreoActor )
  2927. return NULL;
  2928. pActor = FindNamedActor( pChoreoActor->GetName() );
  2929. if (pActor)
  2930. {
  2931. // save who we found so we'll use them again
  2932. m_hActorList[ index ] = pActor;
  2933. NetworkProp()->NetworkStateForceUpdate();
  2934. }
  2935. }
  2936. return pActor;
  2937. }
  2938. //-----------------------------------------------------------------------------
  2939. // Purpose: Get a sticky version of a named actor
  2940. // Input : CChoreoActor
  2941. // Output : CBaseFlex
  2942. //-----------------------------------------------------------------------------
  2943. CBaseFlex *CSceneEntity::FindNamedActor( CChoreoActor *pChoreoActor )
  2944. {
  2945. int index = m_pScene->FindActorIndex( pChoreoActor );
  2946. if (index >= 0)
  2947. {
  2948. return FindNamedActor( index );
  2949. }
  2950. return NULL;
  2951. }
  2952. //-----------------------------------------------------------------------------
  2953. // Purpose: Search for an actor by name, make sure it can do face poses
  2954. // Input : *name -
  2955. // Output : CBaseFlex
  2956. //-----------------------------------------------------------------------------
  2957. CBaseFlex *CSceneEntity::FindNamedActor( const char *name )
  2958. {
  2959. CBaseEntity *entity = FindNamedEntity( name, NULL, true );
  2960. if ( !entity )
  2961. {
  2962. // Couldn't find actor!
  2963. return NULL;
  2964. }
  2965. // Make sure it can actually do facial animation, etc.
  2966. CBaseFlex *flexEntity = dynamic_cast< CBaseFlex * >( entity );
  2967. if ( !flexEntity )
  2968. {
  2969. // That actor was not a CBaseFlex!
  2970. return NULL;
  2971. }
  2972. return flexEntity;
  2973. }
  2974. //-----------------------------------------------------------------------------
  2975. // Purpose: Find an entity specified by a target name
  2976. // Input : *name -
  2977. // Output : CBaseEntity
  2978. //-----------------------------------------------------------------------------
  2979. CBaseEntity *CSceneEntity::FindNamedTarget( string_t iszTarget, bool bBaseFlexOnly )
  2980. {
  2981. if ( !stricmp( STRING(iszTarget), "!activator" ) )
  2982. return m_hActivator;
  2983. // If we don't have a wildcard in the target, just return the first entity found
  2984. if ( !strchr( STRING(iszTarget), '*' ) )
  2985. return gEntList.FindEntityByName( NULL, iszTarget );
  2986. CBaseEntity *pTarget = NULL;
  2987. while ( (pTarget = gEntList.FindEntityByName( pTarget, iszTarget )) != NULL )
  2988. {
  2989. if ( bBaseFlexOnly )
  2990. {
  2991. // Make sure it can actually do facial animation, etc.
  2992. if ( dynamic_cast< CBaseFlex * >( pTarget ) )
  2993. return pTarget;
  2994. }
  2995. else
  2996. {
  2997. return pTarget;
  2998. }
  2999. }
  3000. // Failed to find one
  3001. return NULL;
  3002. }
  3003. //-----------------------------------------------------------------------------
  3004. // Purpose: Filters entities only if they're clear
  3005. //-----------------------------------------------------------------------------
  3006. class CSceneFindMarkFilter : public IEntityFindFilter
  3007. {
  3008. public:
  3009. void SetActor( CBaseEntity *pActor )
  3010. {
  3011. m_hActor = pActor;
  3012. }
  3013. bool ShouldFindEntity( CBaseEntity *pEntity )
  3014. {
  3015. if ( !m_hActor )
  3016. return true;
  3017. // If we find no truly valid marks, we'll just use the first.
  3018. if ( !m_hEntityFound.Get() )
  3019. {
  3020. m_hEntityFound = pEntity;
  3021. }
  3022. // We only want marks that are clear
  3023. trace_t tr;
  3024. Vector vecOrigin = pEntity->GetAbsOrigin();
  3025. AI_TraceHull( vecOrigin, vecOrigin, m_hActor->WorldAlignMins(), m_hActor->WorldAlignMaxs(), MASK_SOLID, m_hActor, COLLISION_GROUP_NONE, &tr );
  3026. if ( tr.startsolid )
  3027. {
  3028. return false;
  3029. }
  3030. m_hEntityFound = pEntity;
  3031. return true;
  3032. }
  3033. CBaseEntity *GetFilterResult( void )
  3034. {
  3035. return m_hEntityFound;
  3036. }
  3037. private:
  3038. EHANDLE m_hActor;
  3039. // To maintain backwards compatability, store off the first mark
  3040. // we find. If we find no truly valid marks, we'll just use the first.
  3041. EHANDLE m_hEntityFound;
  3042. };
  3043. //-----------------------------------------------------------------------------
  3044. // Purpose: Finds the entity nearest to both entities, and is clear
  3045. //-----------------------------------------------------------------------------
  3046. class CSceneFindNearestMarkFilter : public IEntityFindFilter
  3047. {
  3048. public:
  3049. CSceneFindNearestMarkFilter( const CBaseEntity *pActor, const Vector &vecPos2, float flMaxRadius = MAX_TRACE_LENGTH )
  3050. {
  3051. m_vecPos2 = vecPos2;
  3052. m_flMaxSegmentDistance = flMaxRadius;
  3053. m_flNearestToTarget = flMaxRadius;
  3054. m_pNearestToTarget = NULL;
  3055. m_flNearestToActor = flMaxRadius;
  3056. m_pNearestToActor = NULL;
  3057. m_hActor = pActor;
  3058. if (pActor)
  3059. {
  3060. m_vecPos1 = pActor->GetAbsOrigin();
  3061. m_flMaxSegmentDistance = MIN( flMaxRadius, (m_vecPos1 - m_vecPos2).Length() + 1.0 );
  3062. if (m_flMaxSegmentDistance <= 1.0)
  3063. {
  3064. // must be closest to self
  3065. m_flMaxSegmentDistance = MIN( flMaxRadius, MAX_TRACE_LENGTH );
  3066. }
  3067. }
  3068. }
  3069. bool ShouldFindEntity( CBaseEntity *pEntity )
  3070. {
  3071. if ( !m_hActor )
  3072. return true;
  3073. // If we find no truly valid marks, we'll just use the first.
  3074. if ( m_pNearestToActor == NULL )
  3075. {
  3076. m_pNearestToActor = pEntity;
  3077. }
  3078. // We only want marks that are clear
  3079. trace_t tr;
  3080. Vector vecOrigin = pEntity->GetAbsOrigin();
  3081. AI_TraceHull( vecOrigin, vecOrigin, m_hActor->WorldAlignMins(), m_hActor->WorldAlignMaxs(), MASK_SOLID, m_hActor, COLLISION_GROUP_NONE, &tr );
  3082. if ( !tr.startsolid || tr.m_pEnt == m_hActor)
  3083. {
  3084. float dist1 = (m_vecPos1 - pEntity->GetAbsOrigin()).Length();
  3085. float dist2 = (m_vecPos2 - pEntity->GetAbsOrigin()).Length();
  3086. /*
  3087. char text[256];
  3088. Q_snprintf( text, sizeof( text ), "%.0f : %.0f", dist1, dist2 );
  3089. NDebugOverlay::Text( pEntity->GetAbsOrigin() + Vector( 0, 0, 8 ), text, false, 5.0f );
  3090. */
  3091. // find the point closest to the actor
  3092. if (dist1 <= m_flNearestToActor)
  3093. {
  3094. m_pNearestToActor = pEntity;
  3095. m_flNearestToActor = dist2;
  3096. }
  3097. // find that node that's closest to both, but the distance to it from the actor isn't farther than
  3098. // the distance to the second node. This should keep the actor from walking past their point of interest
  3099. if (dist1 <= m_flMaxSegmentDistance && dist2 <= m_flMaxSegmentDistance && dist2 < m_flNearestToTarget)
  3100. {
  3101. m_pNearestToTarget = pEntity;
  3102. m_flNearestToTarget = dist2;
  3103. }
  3104. }
  3105. return false;
  3106. }
  3107. CBaseEntity *GetFilterResult( void )
  3108. {
  3109. if (m_pNearestToTarget)
  3110. return m_pNearestToTarget;
  3111. return m_pNearestToActor;
  3112. }
  3113. private:
  3114. EHANDLE m_hActor;
  3115. Vector m_vecPos1;
  3116. Vector m_vecPos2;
  3117. float m_flMaxSegmentDistance;
  3118. float m_flNearestToTarget;
  3119. CBaseEntity *m_pNearestToTarget;
  3120. float m_flNearestToActor;
  3121. CBaseEntity *m_pNearestToActor;
  3122. };
  3123. //-----------------------------------------------------------------------------
  3124. // Purpose: Search for an actor by name, make sure it can do face poses
  3125. // Input : *name -
  3126. // Output : CBaseFlex
  3127. //-----------------------------------------------------------------------------
  3128. CBaseEntity *CSceneEntity::FindNamedEntity( const char *name, CBaseEntity *pActor, bool bBaseFlexOnly, bool bUseClear )
  3129. {
  3130. CBaseEntity *entity = NULL;
  3131. if ( !stricmp( name, "Player" ) || !stricmp( name, "!player" ))
  3132. {
  3133. entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL;
  3134. }
  3135. else if ( !stricmp( name, "!target1" ) )
  3136. {
  3137. if (m_hTarget1 == NULL)
  3138. {
  3139. m_hTarget1 = FindNamedTarget( m_iszTarget1, bBaseFlexOnly );
  3140. }
  3141. return m_hTarget1;
  3142. }
  3143. else if ( !stricmp( name, "!target2" ) )
  3144. {
  3145. if (m_hTarget2 == NULL)
  3146. {
  3147. m_hTarget2 = FindNamedTarget( m_iszTarget2, bBaseFlexOnly );
  3148. }
  3149. return m_hTarget2;
  3150. }
  3151. else if ( !stricmp( name, "!target3" ) )
  3152. {
  3153. if (m_hTarget3 == NULL)
  3154. {
  3155. m_hTarget3 = FindNamedTarget( m_iszTarget3, bBaseFlexOnly );
  3156. }
  3157. return m_hTarget3;
  3158. }
  3159. else if ( !stricmp( name, "!target4" ) )
  3160. {
  3161. if (m_hTarget4 == NULL)
  3162. {
  3163. m_hTarget4 = FindNamedTarget( m_iszTarget4, bBaseFlexOnly );
  3164. }
  3165. return m_hTarget4;
  3166. }
  3167. else if ( !stricmp( name, "!target5" ) )
  3168. {
  3169. if (m_hTarget5 == NULL)
  3170. {
  3171. m_hTarget5 = FindNamedTarget( m_iszTarget5, bBaseFlexOnly );
  3172. }
  3173. return m_hTarget5;
  3174. }
  3175. else if ( !stricmp( name, "!target6" ) )
  3176. {
  3177. if (m_hTarget6 == NULL)
  3178. {
  3179. m_hTarget6 = FindNamedTarget( m_iszTarget6, bBaseFlexOnly );
  3180. }
  3181. return m_hTarget6;
  3182. }
  3183. else if ( !stricmp( name, "!target7" ) )
  3184. {
  3185. if (m_hTarget7 == NULL)
  3186. {
  3187. m_hTarget7 = FindNamedTarget( m_iszTarget7, bBaseFlexOnly );
  3188. }
  3189. return m_hTarget7;
  3190. }
  3191. else if ( !stricmp( name, "!target8" ) )
  3192. {
  3193. if (m_hTarget8 == NULL)
  3194. {
  3195. m_hTarget8 = FindNamedTarget( m_iszTarget8, bBaseFlexOnly );
  3196. }
  3197. return m_hTarget8;
  3198. }
  3199. else if (pActor && pActor->MyNPCPointer())
  3200. {
  3201. CSceneFindMarkFilter *pFilter = NULL;
  3202. if ( bUseClear )
  3203. {
  3204. pFilter = new CSceneFindMarkFilter();
  3205. pFilter->SetActor( pActor );
  3206. }
  3207. entity = pActor->MyNPCPointer()->FindNamedEntity( name, pFilter );
  3208. if ( !entity && pFilter )
  3209. {
  3210. entity = pFilter->GetFilterResult();
  3211. }
  3212. }
  3213. else
  3214. {
  3215. // search for up to 32 entities with the same name and choose one randomly
  3216. CBaseEntity *entityList[ FINDNAMEDENTITY_MAX_ENTITIES ];
  3217. int iCount;
  3218. entity = NULL;
  3219. for( iCount = 0; iCount < FINDNAMEDENTITY_MAX_ENTITIES; iCount++ )
  3220. {
  3221. entity = gEntList.FindEntityByName( entity, name, NULL, pActor );
  3222. if ( !entity )
  3223. {
  3224. break;
  3225. }
  3226. entityList[ iCount ] = entity;
  3227. }
  3228. if ( iCount > 0 )
  3229. {
  3230. entity = entityList[ RandomInt( 0, iCount - 1 ) ];
  3231. }
  3232. else
  3233. {
  3234. entity = NULL;
  3235. }
  3236. }
  3237. return entity;
  3238. }
  3239. //-----------------------------------------------------------------------------
  3240. // Purpose: Search for an actor by name, make sure it can do face poses
  3241. // Input : *name -
  3242. // Output : CBaseFlex
  3243. //-----------------------------------------------------------------------------
  3244. CBaseEntity *CSceneEntity::FindNamedEntityClosest( const char *name, CBaseEntity *pActor, bool bBaseFlexOnly, bool bUseClear, const char *pszSecondary )
  3245. {
  3246. CBaseEntity *entity = NULL;
  3247. if ( !stricmp( name, "!activator" ) )
  3248. {
  3249. return m_hActivator;
  3250. }
  3251. else if ( !stricmp( name, "Player" ) || !stricmp( name, "!player" ))
  3252. {
  3253. entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL;
  3254. return entity;
  3255. }
  3256. else if ( !stricmp( name, "!target1" ) )
  3257. {
  3258. name = STRING( m_iszTarget1 );
  3259. }
  3260. else if ( !stricmp( name, "!target2" ) )
  3261. {
  3262. name = STRING( m_iszTarget2 );
  3263. }
  3264. else if ( !stricmp( name, "!target3" ) )
  3265. {
  3266. name = STRING( m_iszTarget3 );
  3267. }
  3268. else if ( !stricmp( name, "!target4" ) )
  3269. {
  3270. name = STRING( m_iszTarget4 );
  3271. }
  3272. else if ( !stricmp( name, "!target5" ) )
  3273. {
  3274. name = STRING( m_iszTarget5 );
  3275. }
  3276. else if ( !stricmp( name, "!target6" ) )
  3277. {
  3278. name = STRING( m_iszTarget6 );
  3279. }
  3280. else if ( !stricmp( name, "!target7" ) )
  3281. {
  3282. name = STRING( m_iszTarget7 );
  3283. }
  3284. if (pActor && pActor->MyNPCPointer())
  3285. {
  3286. if (pszSecondary && strlen( pszSecondary ) > 0)
  3287. {
  3288. CBaseEntity *pActor2 = FindNamedEntityClosest( pszSecondary, pActor, false, false, NULL );
  3289. if (pActor2)
  3290. {
  3291. CSceneFindNearestMarkFilter *pFilter = new CSceneFindNearestMarkFilter( pActor, pActor2->GetAbsOrigin() );
  3292. entity = pActor->MyNPCPointer()->FindNamedEntity( name, pFilter );
  3293. if (!entity && pFilter)
  3294. {
  3295. entity = pFilter->GetFilterResult();
  3296. }
  3297. }
  3298. }
  3299. if (!entity)
  3300. {
  3301. CSceneFindMarkFilter *pFilter = NULL;
  3302. if ( bUseClear )
  3303. {
  3304. pFilter = new CSceneFindMarkFilter();
  3305. pFilter->SetActor( pActor );
  3306. }
  3307. entity = pActor->MyNPCPointer()->FindNamedEntity( name, pFilter );
  3308. if (!entity && pFilter)
  3309. {
  3310. entity = pFilter->GetFilterResult();
  3311. }
  3312. }
  3313. }
  3314. else
  3315. {
  3316. // search for up to 32 entities with the same name and choose one randomly
  3317. int iCount;
  3318. entity = NULL;
  3319. CBaseEntity *current = NULL;
  3320. for( iCount = 0; iCount < FINDNAMEDENTITY_MAX_ENTITIES; iCount++ )
  3321. {
  3322. current = gEntList.FindEntityByName( current, name, NULL, pActor );
  3323. if ( current )
  3324. {
  3325. if (RandomInt( 0, iCount ) == 0)
  3326. entity = current;
  3327. }
  3328. }
  3329. entity = NULL;
  3330. }
  3331. return entity;
  3332. }
  3333. //-----------------------------------------------------------------------------
  3334. // Purpose: Remove all "scene" expressions from all actors in this scene
  3335. //-----------------------------------------------------------------------------
  3336. void CSceneEntity::ClearSceneEvents( CChoreoScene *scene, bool canceled )
  3337. {
  3338. if ( !m_pScene )
  3339. return;
  3340. LocalScene_Printf( "%s : %8.2f: clearing events\n", STRING( m_iszSceneFile ), m_flCurrentTime );
  3341. int i;
  3342. for ( i = 0 ; i < m_pScene->GetNumActors(); i++ )
  3343. {
  3344. CBaseFlex *pActor = FindNamedActor( i );
  3345. if ( !pActor )
  3346. continue;
  3347. // Clear any existing expressions
  3348. pActor->ClearSceneEvents( scene, canceled );
  3349. }
  3350. // Iterate events and precache necessary resources
  3351. for ( i = 0; i < scene->GetNumEvents(); i++ )
  3352. {
  3353. CChoreoEvent *event = scene->GetEvent( i );
  3354. if ( !event )
  3355. continue;
  3356. // load any necessary data
  3357. switch (event->GetType() )
  3358. {
  3359. default:
  3360. break;
  3361. case CChoreoEvent::SUBSCENE:
  3362. {
  3363. // Only allow a single level of subscenes for now
  3364. if ( !scene->IsSubScene() )
  3365. {
  3366. CChoreoScene *subscene = event->GetSubScene();
  3367. if ( subscene )
  3368. {
  3369. ClearSceneEvents( subscene, canceled );
  3370. }
  3371. }
  3372. }
  3373. break;
  3374. }
  3375. }
  3376. }
  3377. //-----------------------------------------------------------------------------
  3378. // Purpose: Remove all imposed schedules from all actors in this scene
  3379. //-----------------------------------------------------------------------------
  3380. void CSceneEntity::ClearSchedules( CChoreoScene *scene )
  3381. {
  3382. if ( !m_pScene )
  3383. return;
  3384. int i;
  3385. for ( i = 0 ; i < m_pScene->GetNumActors(); i++ )
  3386. {
  3387. CBaseFlex *pActor = FindNamedActor( i );
  3388. if ( !pActor )
  3389. continue;
  3390. CAI_BaseNPC *pNPC = pActor->MyNPCPointer();
  3391. if ( pNPC )
  3392. {
  3393. /*
  3394. if ( pNPC->IsCurSchedule( SCHED_SCENE_GENERIC ) )
  3395. pNPC->ClearSchedule( "Scene entity clearing all actor schedules" );
  3396. */
  3397. }
  3398. else
  3399. {
  3400. pActor->ResetSequence( pActor->SelectWeightedSequence( ACT_IDLE ) );
  3401. pActor->SetCycle( 0 );
  3402. }
  3403. // Clear any existing expressions
  3404. }
  3405. // Iterate events and precache necessary resources
  3406. for ( i = 0; i < scene->GetNumEvents(); i++ )
  3407. {
  3408. CChoreoEvent *event = scene->GetEvent( i );
  3409. if ( !event )
  3410. continue;
  3411. // load any necessary data
  3412. switch (event->GetType() )
  3413. {
  3414. default:
  3415. break;
  3416. case CChoreoEvent::SUBSCENE:
  3417. {
  3418. // Only allow a single level of subscenes for now
  3419. if ( !scene->IsSubScene() )
  3420. {
  3421. CChoreoScene *subscene = event->GetSubScene();
  3422. if ( subscene )
  3423. {
  3424. ClearSchedules( subscene );
  3425. }
  3426. }
  3427. }
  3428. break;
  3429. }
  3430. }
  3431. }
  3432. //-----------------------------------------------------------------------------
  3433. // Purpose: If we are currently interruptable, pause this scene and wait for the other
  3434. // scene to finish
  3435. // Input : *otherScene -
  3436. //-----------------------------------------------------------------------------
  3437. bool CSceneEntity::InterruptThisScene( CSceneEntity *otherScene )
  3438. {
  3439. Assert( otherScene );
  3440. if ( !IsInterruptable() )
  3441. {
  3442. return false;
  3443. }
  3444. // Already interrupted
  3445. if ( m_bInterrupted )
  3446. {
  3447. return false;
  3448. }
  3449. m_bInterrupted = true;
  3450. m_hInterruptScene = otherScene;
  3451. // Ask other scene to tell us when it's finished or canceled
  3452. otherScene->RequestCompletionNotification( this );
  3453. PausePlayback();
  3454. return true;
  3455. }
  3456. /*
  3457. void scene_interrupt( const CCommand &args )
  3458. {
  3459. if ( args.ArgC() != 3 )
  3460. return;
  3461. const char *scene1 = args[1];
  3462. const char *scene2 = args[2];
  3463. CSceneEntity *s1 = dynamic_cast< CSceneEntity * >( gEntList.FindEntityByName( NULL, scene1 ) );
  3464. CSceneEntity *s2 = dynamic_cast< CSceneEntity * >( gEntList.FindEntityByName( NULL, scene2 ) );
  3465. if ( !s1 || !s2 )
  3466. return;
  3467. if ( s1->InterruptThisScene( s2 ) )
  3468. {
  3469. s2->StartPlayback();
  3470. }
  3471. }
  3472. static ConCommand interruptscene( "int", scene_interrupt, "interrupt scene 1 with scene 2.", FCVAR_CHEAT );
  3473. */
  3474. //-----------------------------------------------------------------------------
  3475. // Purpose:
  3476. //-----------------------------------------------------------------------------
  3477. void CSceneEntity::CheckInterruptCompletion()
  3478. {
  3479. if ( !m_bInterrupted )
  3480. return;
  3481. // If the interruptor goes away it's the same as having that scene finish up...
  3482. if ( m_hInterruptScene != NULL &&
  3483. !m_bInterruptSceneFinished )
  3484. {
  3485. return;
  3486. }
  3487. m_bInterrupted = false;
  3488. m_hInterruptScene = NULL;
  3489. ResumePlayback();
  3490. }
  3491. //-----------------------------------------------------------------------------
  3492. // Purpose:
  3493. //-----------------------------------------------------------------------------
  3494. void CSceneEntity::ClearInterrupt()
  3495. {
  3496. m_nInterruptCount = 0;
  3497. m_bInterrupted = false;
  3498. m_hInterruptScene = NULL;
  3499. }
  3500. //-----------------------------------------------------------------------------
  3501. // Purpose: Another scene is asking us to notify upon completion
  3502. // Input : *notify -
  3503. //-----------------------------------------------------------------------------
  3504. void CSceneEntity::RequestCompletionNotification( CSceneEntity *notify )
  3505. {
  3506. CHandle< CSceneEntity > h;
  3507. h = notify;
  3508. // Only add it once
  3509. if ( m_hNotifySceneCompletion.Find( h ) == m_hNotifySceneCompletion.InvalidIndex() )
  3510. {
  3511. m_hNotifySceneCompletion.AddToTail( h );
  3512. }
  3513. }
  3514. //-----------------------------------------------------------------------------
  3515. // Purpose: An interrupt scene has finished or been canceled, we can resume once we pick up this state in CheckInterruptCompletion
  3516. // Input : *interruptor -
  3517. //-----------------------------------------------------------------------------
  3518. void CSceneEntity::NotifyOfCompletion( CSceneEntity *interruptor )
  3519. {
  3520. Assert( m_bInterrupted );
  3521. Assert( m_hInterruptScene == interruptor );
  3522. m_bInterruptSceneFinished = true;
  3523. CheckInterruptCompletion();
  3524. }
  3525. //-----------------------------------------------------------------------------
  3526. // Purpose:
  3527. //-----------------------------------------------------------------------------
  3528. void CSceneEntity::AddListManager( CSceneListManager *pManager )
  3529. {
  3530. CHandle< CSceneListManager > h;
  3531. h = pManager;
  3532. // Only add it once
  3533. if ( m_hListManagers.Find( h ) == m_hListManagers.InvalidIndex() )
  3534. {
  3535. m_hListManagers.AddToTail( h );
  3536. }
  3537. }
  3538. //-----------------------------------------------------------------------------
  3539. // Purpose: Clear any targets that a referencing !activator
  3540. //-----------------------------------------------------------------------------
  3541. void CSceneEntity::ClearActivatorTargets( void )
  3542. {
  3543. if ( !stricmp( STRING(m_iszTarget1), "!activator" ) )
  3544. {
  3545. // We need to clear out actors so they're re-evaluated
  3546. m_hActorList.Purge();
  3547. NetworkProp()->NetworkStateForceUpdate();
  3548. m_hTarget1 = NULL;
  3549. }
  3550. if ( !stricmp( STRING(m_iszTarget2), "!activator" ) )
  3551. {
  3552. // We need to clear out actors so they're re-evaluated
  3553. m_hActorList.Purge();
  3554. NetworkProp()->NetworkStateForceUpdate();
  3555. m_hTarget2 = NULL;
  3556. }
  3557. if ( !stricmp( STRING(m_iszTarget3), "!activator" ) )
  3558. {
  3559. // We need to clear out actors so they're re-evaluated
  3560. m_hActorList.Purge();
  3561. NetworkProp()->NetworkStateForceUpdate();
  3562. m_hTarget3 = NULL;
  3563. }
  3564. if ( !stricmp( STRING(m_iszTarget4), "!activator" ) )
  3565. {
  3566. // We need to clear out actors so they're re-evaluated
  3567. m_hActorList.Purge();
  3568. NetworkProp()->NetworkStateForceUpdate();
  3569. m_hTarget4 = NULL;
  3570. }
  3571. if ( !stricmp( STRING(m_iszTarget5), "!activator" ) )
  3572. {
  3573. // We need to clear out actors so they're re-evaluated
  3574. m_hActorList.Purge();
  3575. NetworkProp()->NetworkStateForceUpdate();
  3576. m_hTarget5 = NULL;
  3577. }
  3578. if ( !stricmp( STRING(m_iszTarget6), "!activator" ) )
  3579. {
  3580. // We need to clear out actors so they're re-evaluated
  3581. m_hActorList.Purge();
  3582. NetworkProp()->NetworkStateForceUpdate();
  3583. m_hTarget6 = NULL;
  3584. }
  3585. if ( !stricmp( STRING(m_iszTarget7), "!activator" ) )
  3586. {
  3587. // We need to clear out actors so they're re-evaluated
  3588. m_hActorList.Purge();
  3589. NetworkProp()->NetworkStateForceUpdate();
  3590. m_hTarget7 = NULL;
  3591. }
  3592. if ( !stricmp( STRING(m_iszTarget8), "!activator" ) )
  3593. {
  3594. // We need to clear out actors so they're re-evaluated
  3595. m_hActorList.Purge();
  3596. NetworkProp()->NetworkStateForceUpdate();
  3597. m_hTarget8 = NULL;
  3598. }
  3599. }
  3600. //-----------------------------------------------------------------------------
  3601. // Purpose: Called when a scene is completed or canceled
  3602. //-----------------------------------------------------------------------------
  3603. void CSceneEntity::OnSceneFinished( bool canceled, bool fireoutput )
  3604. {
  3605. if ( !m_pScene )
  3606. return;
  3607. LocalScene_Printf( "%s : %8.2f: finished\n", STRING( m_iszSceneFile ), m_flCurrentTime );
  3608. // Notify any listeners
  3609. int c = m_hNotifySceneCompletion.Count();
  3610. int i;
  3611. for ( i = 0; i < c; i++ )
  3612. {
  3613. CSceneEntity *ent = m_hNotifySceneCompletion[ i ].Get();
  3614. if ( !ent )
  3615. continue;
  3616. ent->NotifyOfCompletion( this );
  3617. }
  3618. m_hNotifySceneCompletion.RemoveAll();
  3619. // Clear simulation
  3620. m_pScene->ResetSimulation();
  3621. m_bIsPlayingBack = false;
  3622. m_bPaused = false;
  3623. SetCurrentTime( 0.0f, false );
  3624. // Clear interrupt state if we were interrupted for some reason
  3625. ClearInterrupt();
  3626. if ( fireoutput && !m_bCompletedEarly)
  3627. {
  3628. m_OnCompletion.FireOutput( this, this, 0 );
  3629. }
  3630. // Put face back in neutral pose
  3631. ClearSceneEvents( m_pScene, canceled );
  3632. for ( i = 0 ; i < m_pScene->GetNumActors(); i++ )
  3633. {
  3634. CBaseFlex *pTestActor = FindNamedActor( i );
  3635. if ( !pTestActor )
  3636. continue;
  3637. pTestActor->RemoveChoreoScene( m_pScene, canceled );
  3638. // If we interrupted the actor's previous scenes, resume them
  3639. if ( m_bInterruptedActorsScenes )
  3640. {
  3641. QueueActorsScriptedScenesToResume( pTestActor, false );
  3642. }
  3643. }
  3644. }
  3645. //-----------------------------------------------------------------------------
  3646. // Should we transmit it to the client?
  3647. //-----------------------------------------------------------------------------
  3648. int CSceneEntity::UpdateTransmitState()
  3649. {
  3650. if ( !ShouldNetwork() )
  3651. {
  3652. return SetTransmitState( FL_EDICT_DONTSEND );
  3653. }
  3654. if ( m_pRecipientFilter )
  3655. {
  3656. return SetTransmitState( FL_EDICT_FULLCHECK );
  3657. }
  3658. return SetTransmitState( FL_EDICT_ALWAYS );
  3659. }
  3660. //-----------------------------------------------------------------------------
  3661. // Purpose: Which clients should we be transmitting to?
  3662. //-----------------------------------------------------------------------------
  3663. int CSceneEntity::ShouldTransmit( const CCheckTransmitInfo *pInfo )
  3664. {
  3665. int result = BaseClass::ShouldTransmit( pInfo );
  3666. // if we have excluded them via our recipient filter, don't send
  3667. if ( m_pRecipientFilter && result != FL_EDICT_DONTSEND )
  3668. {
  3669. bool bFound = false;
  3670. // If we can't find them in the recipient list, exclude
  3671. int i;
  3672. for ( i=0; i<m_pRecipientFilter->GetRecipientCount();i++ )
  3673. {
  3674. int iRecipient = m_pRecipientFilter->GetRecipientIndex(i);
  3675. CBasePlayer *player = static_cast< CBasePlayer * >( CBaseEntity::Instance( iRecipient ) );
  3676. if ( player && player->edict() == pInfo->m_pClientEnt )
  3677. {
  3678. bFound = true;
  3679. break;
  3680. }
  3681. }
  3682. if ( !bFound )
  3683. {
  3684. result = FL_EDICT_DONTSEND;
  3685. }
  3686. }
  3687. return result;
  3688. }
  3689. void CSceneEntity::SetRecipientFilter( IRecipientFilter *filter )
  3690. {
  3691. // create a copy of this filter
  3692. if ( filter )
  3693. {
  3694. m_pRecipientFilter = new CRecipientFilter();
  3695. m_pRecipientFilter->CopyFrom( (CRecipientFilter &)( *filter ) );
  3696. }
  3697. }
  3698. //-----------------------------------------------------------------------------
  3699. // Purpose:
  3700. // Input :
  3701. // Output :
  3702. //-----------------------------------------------------------------------------
  3703. class CInstancedSceneEntity : public CSceneEntity
  3704. {
  3705. DECLARE_DATADESC();
  3706. DECLARE_CLASS( CInstancedSceneEntity, CSceneEntity );
  3707. public:
  3708. EHANDLE m_hOwner;
  3709. bool m_bHadOwner;
  3710. float m_flPostSpeakDelay;
  3711. float m_flPreDelay;
  3712. char m_szInstanceFilename[ CChoreoScene::MAX_SCENE_FILENAME ];
  3713. bool m_bIsBackground;
  3714. virtual void StartPlayback( void );
  3715. virtual void DoThink( float frametime );
  3716. virtual CBaseFlex *FindNamedActor( const char *name );
  3717. virtual CBaseEntity *FindNamedEntity( const char *name );
  3718. virtual float GetPostSpeakDelay() { return m_flPostSpeakDelay; }
  3719. virtual void SetPostSpeakDelay( float flDelay ) { m_flPostSpeakDelay = flDelay; }
  3720. virtual float GetPreDelay() { return m_flPreDelay; }
  3721. virtual void SetPreDelay( float flDelay ) { m_flPreDelay = flDelay; }
  3722. virtual void OnLoaded();
  3723. virtual void DispatchStartMoveTo( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event )
  3724. {
  3725. if (PassThrough( actor )) BaseClass::DispatchStartMoveTo( scene, actor, actor2, event );
  3726. };
  3727. virtual void DispatchEndMoveTo( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  3728. {
  3729. if (PassThrough( actor )) BaseClass::DispatchEndMoveTo( scene, actor, event );
  3730. };
  3731. virtual void DispatchStartFace( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event )
  3732. {
  3733. if (PassThrough( actor )) BaseClass::DispatchStartFace( scene, actor, actor2, event );
  3734. };
  3735. virtual void DispatchEndFace( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  3736. {
  3737. if (PassThrough( actor )) BaseClass::DispatchEndFace( scene, actor, event );
  3738. };
  3739. virtual void DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  3740. {
  3741. if ( IsMultiplayer() )
  3742. {
  3743. BaseClass::DispatchStartSequence( scene, actor, event );
  3744. }
  3745. };
  3746. virtual void DispatchEndSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
  3747. {
  3748. if ( IsMultiplayer() )
  3749. {
  3750. BaseClass::DispatchEndSequence( scene, actor, event );
  3751. }
  3752. };
  3753. virtual void DispatchPauseScene( CChoreoScene *scene, const char *parameters ) { /* suppress */ };
  3754. void OnRestore();
  3755. virtual float EstimateLength( void );
  3756. private:
  3757. bool PassThrough( CBaseFlex *actor );
  3758. };
  3759. LINK_ENTITY_TO_CLASS( instanced_scripted_scene, CInstancedSceneEntity );
  3760. //---------------------------------------------------------
  3761. // Save/Restore
  3762. //---------------------------------------------------------
  3763. BEGIN_DATADESC( CInstancedSceneEntity )
  3764. DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
  3765. DEFINE_FIELD( m_bHadOwner, FIELD_BOOLEAN ),
  3766. DEFINE_FIELD( m_flPostSpeakDelay, FIELD_FLOAT ),
  3767. DEFINE_FIELD( m_flPreDelay, FIELD_FLOAT ),
  3768. DEFINE_AUTO_ARRAY( m_szInstanceFilename, FIELD_CHARACTER ),
  3769. DEFINE_FIELD( m_bIsBackground, FIELD_BOOLEAN ),
  3770. END_DATADESC()
  3771. //-----------------------------------------------------------------------------
  3772. // Purpose: create a one-shot scene, no movement, sequences, etc.
  3773. // Input :
  3774. // Output :
  3775. //-----------------------------------------------------------------------------
  3776. float InstancedScriptedScene( CBaseFlex *pActor, const char *pszScene, EHANDLE *phSceneEnt,
  3777. float flPostDelay, bool bIsBackground, AI_Response *response,
  3778. bool bMultiplayer, IRecipientFilter *filter /* = NULL */ )
  3779. {
  3780. VPROF( "InstancedScriptedScene" );
  3781. CInstancedSceneEntity *pScene = (CInstancedSceneEntity *)CBaseEntity::CreateNoSpawn( "instanced_scripted_scene", vec3_origin, vec3_angle );
  3782. // This code expands any $gender tags into male or female tags based on the gender of the actor (based on his/her .mdl)
  3783. if ( pActor )
  3784. {
  3785. pActor->GenderExpandString( pszScene, pScene->m_szInstanceFilename, sizeof( pScene->m_szInstanceFilename ) );
  3786. }
  3787. else
  3788. {
  3789. Q_strncpy( pScene->m_szInstanceFilename, pszScene, sizeof( pScene->m_szInstanceFilename ) );
  3790. }
  3791. pScene->m_iszSceneFile = MAKE_STRING( pScene->m_szInstanceFilename );
  3792. // FIXME: I should set my output to fire something that kills me....
  3793. // FIXME: add a proper initialization function
  3794. pScene->m_hOwner = pActor;
  3795. pScene->m_bHadOwner = pActor != NULL;
  3796. pScene->m_bMultiplayer = bMultiplayer;
  3797. pScene->SetPostSpeakDelay( flPostDelay );
  3798. DispatchSpawn( pScene );
  3799. pScene->Activate();
  3800. pScene->m_bIsBackground = bIsBackground;
  3801. pScene->SetBackground( bIsBackground );
  3802. pScene->SetRecipientFilter( filter );
  3803. if ( response )
  3804. {
  3805. float flPreDelay = response->GetPreDelay();
  3806. if ( flPreDelay )
  3807. {
  3808. pScene->SetPreDelay( flPreDelay );
  3809. }
  3810. }
  3811. pScene->StartPlayback();
  3812. if ( response )
  3813. {
  3814. // If the response wants us to abort on NPC state switch, remember that
  3815. pScene->SetBreakOnNonIdle( response->ShouldBreakOnNonIdle() );
  3816. }
  3817. if ( phSceneEnt )
  3818. {
  3819. *phSceneEnt = pScene;
  3820. }
  3821. return pScene->EstimateLength();
  3822. }
  3823. //-----------------------------------------------------------------------------
  3824. // Purpose:
  3825. // Input : *pActor -
  3826. // *soundnmame -
  3827. // *phSceneEnt -
  3828. // Output : float
  3829. //-----------------------------------------------------------------------------
  3830. float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt /*= NULL*/ )
  3831. {
  3832. if ( !pActor )
  3833. {
  3834. Warning( "InstancedAutoGeneratedSoundScene: Expecting non-NULL pActor for sound %s\n", soundname );
  3835. return 0;
  3836. }
  3837. CInstancedSceneEntity *pScene = (CInstancedSceneEntity *)CBaseEntity::CreateNoSpawn( "instanced_scripted_scene", vec3_origin, vec3_angle );
  3838. Q_strncpy( pScene->m_szInstanceFilename, UTIL_VarArgs( "AutoGenerated(%s)", soundname ), sizeof( pScene->m_szInstanceFilename ) );
  3839. pScene->m_iszSceneFile = MAKE_STRING( pScene->m_szInstanceFilename );
  3840. pScene->m_hOwner = pActor;
  3841. pScene->m_bHadOwner = pActor != NULL;
  3842. pScene->GenerateSoundScene( pActor, soundname );
  3843. pScene->Spawn();
  3844. pScene->Activate();
  3845. pScene->StartPlayback();
  3846. if ( phSceneEnt )
  3847. {
  3848. *phSceneEnt = pScene;
  3849. }
  3850. return pScene->EstimateLength();
  3851. }
  3852. //-----------------------------------------------------------------------------
  3853. void StopScriptedScene( CBaseFlex *pActor, EHANDLE hSceneEnt )
  3854. {
  3855. CBaseEntity *pEntity = hSceneEnt;
  3856. CSceneEntity *pScene = dynamic_cast<CSceneEntity *>(pEntity);
  3857. if ( pScene )
  3858. {
  3859. LocalScene_Printf( "%s : stop scripted scene\n", STRING( pScene->m_iszSceneFile ) );
  3860. pScene->CancelPlayback();
  3861. }
  3862. }
  3863. //-----------------------------------------------------------------------------
  3864. // Purpose:
  3865. // Input : *pszScene -
  3866. // Output : float
  3867. //-----------------------------------------------------------------------------
  3868. float GetSceneDuration( char const *pszScene )
  3869. {
  3870. unsigned int msecs = 0;
  3871. SceneCachedData_t cachedData;
  3872. if ( scenefilecache->GetSceneCachedData( pszScene, &cachedData ) )
  3873. {
  3874. msecs = cachedData.msecs;
  3875. }
  3876. return (float)msecs * 0.001f;
  3877. }
  3878. //-----------------------------------------------------------------------------
  3879. // Purpose:
  3880. // Input : *pszScene -
  3881. // Output : int
  3882. //-----------------------------------------------------------------------------
  3883. int GetSceneSpeechCount( char const *pszScene )
  3884. {
  3885. SceneCachedData_t cachedData;
  3886. if ( scenefilecache->GetSceneCachedData( pszScene, &cachedData ) )
  3887. {
  3888. return cachedData.numSounds;
  3889. }
  3890. return 0;
  3891. }
  3892. //-----------------------------------------------------------------------------
  3893. // Purpose: Used for precaching instanced scenes
  3894. // Input : *pszScene -
  3895. //-----------------------------------------------------------------------------
  3896. void PrecacheInstancedScene( char const *pszScene )
  3897. {
  3898. static int nMakingReslists = -1;
  3899. if ( nMakingReslists == -1 )
  3900. {
  3901. nMakingReslists = CommandLine()->FindParm( "-makereslists" ) > 0 ? 1 : 0;
  3902. }
  3903. if ( nMakingReslists == 1 )
  3904. {
  3905. // Just stat the file to add to reslist
  3906. g_pFullFileSystem->Size( pszScene );
  3907. }
  3908. // verify existence, cache is pre-populated, should be there
  3909. SceneCachedData_t sceneData;
  3910. if ( !scenefilecache->GetSceneCachedData( pszScene, &sceneData ) )
  3911. {
  3912. // Scenes are sloppy and don't always exist.
  3913. // A scene that is not in the pre-built cache image, but on disk, is a true error.
  3914. if ( developer.GetInt() && ( IsX360() && ( g_pFullFileSystem->GetDVDMode() != DVDMODE_STRICT ) && g_pFullFileSystem->FileExists( pszScene, "GAME" ) ) )
  3915. {
  3916. Warning( "PrecacheInstancedScene: Missing scene '%s' from scene image cache.\nRebuild scene image cache!\n", pszScene );
  3917. }
  3918. }
  3919. else
  3920. {
  3921. for ( int i = 0; i < sceneData.numSounds; ++i )
  3922. {
  3923. short stringId = scenefilecache->GetSceneCachedSound( sceneData.sceneId, i );
  3924. CBaseEntity::PrecacheScriptSound( scenefilecache->GetSceneString( stringId ) );
  3925. }
  3926. }
  3927. g_pStringTableClientSideChoreoScenes->AddString( CBaseEntity::IsServer(), pszScene );
  3928. }
  3929. //-----------------------------------------------------------------------------
  3930. // Purpose:
  3931. //-----------------------------------------------------------------------------
  3932. void CInstancedSceneEntity::StartPlayback( void )
  3933. {
  3934. // Wait until our pre delay is over
  3935. if ( GetPreDelay() )
  3936. return;
  3937. BaseClass::StartPlayback();
  3938. }
  3939. //-----------------------------------------------------------------------------
  3940. // Purpose:
  3941. // Input :
  3942. // Output :
  3943. //-----------------------------------------------------------------------------
  3944. void CInstancedSceneEntity::DoThink( float frametime )
  3945. {
  3946. CheckInterruptCompletion();
  3947. if ( m_flPreDelay > 0 )
  3948. {
  3949. m_flPreDelay = MAX( 0, m_flPreDelay - frametime );
  3950. StartPlayback();
  3951. if ( !m_bIsPlayingBack )
  3952. return;
  3953. }
  3954. if ( !m_pScene || !m_bIsPlayingBack || ( m_bHadOwner && m_hOwner == NULL ) )
  3955. {
  3956. UTIL_Remove( this );
  3957. return;
  3958. }
  3959. // catch bad pitch shifting from old save games
  3960. Assert( m_fPitch >= SCENE_MIN_PITCH && m_fPitch <= SCENE_MAX_PITCH );
  3961. m_fPitch = clamp( m_fPitch, SCENE_MIN_PITCH, SCENE_MAX_PITCH );
  3962. if ( m_bPaused )
  3963. {
  3964. PauseThink();
  3965. return;
  3966. }
  3967. float dt = frametime;
  3968. m_pScene->SetSoundFileStartupLatency( GetSoundSystemLatency() );
  3969. // Tell scene to go
  3970. m_pScene->Think( m_flCurrentTime );
  3971. // Drive simulation time for scene
  3972. SetCurrentTime( m_flCurrentTime + dt * m_fPitch, false );
  3973. // Did we get to the end
  3974. if ( m_pScene->SimulationFinished() )
  3975. {
  3976. OnSceneFinished( false, false );
  3977. UTIL_Remove( this );
  3978. }
  3979. }
  3980. //-----------------------------------------------------------------------------
  3981. // Purpose: Search for an actor by name, make sure it can do face poses
  3982. // Input : *name -
  3983. // Output : CBaseFlex
  3984. //-----------------------------------------------------------------------------
  3985. CBaseFlex *CInstancedSceneEntity::FindNamedActor( const char *name )
  3986. {
  3987. if ( m_pScene->GetNumActors() == 1 || stricmp( name, "!self" ) == 0 )
  3988. {
  3989. if ( m_hOwner != NULL )
  3990. {
  3991. CBaseCombatCharacter *pCharacter = m_hOwner->MyCombatCharacterPointer();
  3992. if ( pCharacter )
  3993. {
  3994. return pCharacter;
  3995. }
  3996. }
  3997. }
  3998. return BaseClass::FindNamedActor( name );
  3999. }
  4000. //-----------------------------------------------------------------------------
  4001. // Purpose: Search for an actor by name, make sure it can do face poses
  4002. // Input : *name -
  4003. // Output : CBaseFlex
  4004. //-----------------------------------------------------------------------------
  4005. CBaseEntity *CInstancedSceneEntity::FindNamedEntity( const char *name )
  4006. {
  4007. CBaseEntity *pOther = NULL;
  4008. if (m_hOwner != NULL)
  4009. {
  4010. CAI_BaseNPC *npc = m_hOwner->MyNPCPointer();
  4011. if (npc)
  4012. {
  4013. pOther = npc->FindNamedEntity( name );
  4014. }
  4015. else if ( m_hOwner->MyCombatCharacterPointer() )
  4016. {
  4017. pOther = m_hOwner;
  4018. }
  4019. }
  4020. if (!pOther)
  4021. {
  4022. pOther = BaseClass::FindNamedEntity( name );
  4023. }
  4024. return pOther;
  4025. }
  4026. //-----------------------------------------------------------------------------
  4027. // Purpose: Suppress certain events when it's instanced since they're can cause odd problems
  4028. // Input : actor
  4029. // Output : true - the event should happen, false - it shouldn't
  4030. //-----------------------------------------------------------------------------
  4031. bool CInstancedSceneEntity::PassThrough( CBaseFlex *actor )
  4032. {
  4033. if (!actor)
  4034. return false;
  4035. CAI_BaseNPC *myNpc = actor->MyNPCPointer( );
  4036. if (!myNpc)
  4037. return false;
  4038. if (myNpc->IsCurSchedule( SCHED_SCENE_GENERIC ))
  4039. {
  4040. return true;
  4041. }
  4042. if (myNpc->GetCurSchedule())
  4043. {
  4044. CAI_ScheduleBits testBits;
  4045. myNpc->GetCurSchedule()->GetInterruptMask( &testBits );
  4046. if (testBits.IsBitSet( COND_IDLE_INTERRUPT ))
  4047. {
  4048. return true;
  4049. }
  4050. }
  4051. LocalScene_Printf( "%s : event suppressed\n", STRING( m_iszSceneFile ) );
  4052. return false;
  4053. }
  4054. //-----------------------------------------------------------------------------
  4055. void CInstancedSceneEntity::OnRestore()
  4056. {
  4057. if ( m_bHadOwner && !m_hOwner )
  4058. {
  4059. // probably just came back from a level transition
  4060. UTIL_Remove( this );
  4061. return;
  4062. }
  4063. // reset background state
  4064. if ( m_pScene )
  4065. {
  4066. m_pScene->SetBackground( m_bIsBackground );
  4067. }
  4068. BaseClass::OnRestore();
  4069. }
  4070. //-----------------------------------------------------------------------------
  4071. // Purpose:
  4072. //-----------------------------------------------------------------------------
  4073. float CInstancedSceneEntity::EstimateLength( void )
  4074. {
  4075. return (BaseClass::EstimateLength() + GetPreDelay());
  4076. }
  4077. void CInstancedSceneEntity::OnLoaded()
  4078. {
  4079. BaseClass::OnLoaded();
  4080. SetBackground( m_bIsBackground );
  4081. }
  4082. bool g_bClientFlex = true;
  4083. LINK_ENTITY_TO_CLASS( scene_manager, CSceneManager );
  4084. //-----------------------------------------------------------------------------
  4085. // Purpose:
  4086. //-----------------------------------------------------------------------------
  4087. void CSceneManager::Think()
  4088. {
  4089. // Latch this only once per frame...
  4090. g_bClientFlex = scene_clientflex.GetBool();
  4091. // The manager is always thinking at 20 hz
  4092. SetNextThink( gpGlobals->curtime + SCENE_THINK_INTERVAL );
  4093. float frameTime = ( gpGlobals->curtime - GetLastThink() );
  4094. frameTime = MIN( 0.1, frameTime );
  4095. // stop if AI is diabled
  4096. if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI)
  4097. return;
  4098. bool needCleanupPass = false;
  4099. int c = m_ActiveScenes.Count();
  4100. for ( int i = 0; i < c; i++ )
  4101. {
  4102. CSceneEntity *scene = m_ActiveScenes[ i ].Get();
  4103. if ( !scene )
  4104. {
  4105. needCleanupPass = true;
  4106. continue;
  4107. }
  4108. scene->DoThink( frameTime );
  4109. if ( m_ActiveScenes.Count() < c )
  4110. {
  4111. // Scene removed self while thinking. Adjust iteration.
  4112. c = m_ActiveScenes.Count();
  4113. i--;
  4114. }
  4115. }
  4116. // Now delete any invalid ones
  4117. if ( needCleanupPass )
  4118. {
  4119. for ( int i = c - 1; i >= 0; i-- )
  4120. {
  4121. CSceneEntity *scene = m_ActiveScenes[ i ].Get();
  4122. if ( scene )
  4123. continue;
  4124. m_ActiveScenes.Remove( i );
  4125. }
  4126. }
  4127. }
  4128. //-----------------------------------------------------------------------------
  4129. // Purpose:
  4130. //-----------------------------------------------------------------------------
  4131. void CSceneManager::ClearAllScenes()
  4132. {
  4133. m_ActiveScenes.RemoveAll();
  4134. }
  4135. //-----------------------------------------------------------------------------
  4136. // Purpose:
  4137. // Input : *scene -
  4138. //-----------------------------------------------------------------------------
  4139. void CSceneManager::AddSceneEntity( CSceneEntity *scene )
  4140. {
  4141. CHandle< CSceneEntity > h;
  4142. h = scene;
  4143. // Already added/activated
  4144. if ( m_ActiveScenes.Find( h ) != m_ActiveScenes.InvalidIndex() )
  4145. {
  4146. return;
  4147. }
  4148. m_ActiveScenes.AddToTail( h );
  4149. }
  4150. //-----------------------------------------------------------------------------
  4151. // Purpose:
  4152. // Input : *scene -
  4153. //-----------------------------------------------------------------------------
  4154. void CSceneManager::RemoveSceneEntity( CSceneEntity *scene )
  4155. {
  4156. CHandle< CSceneEntity > h;
  4157. h = scene;
  4158. m_ActiveScenes.FindAndRemove( h );
  4159. }
  4160. //-----------------------------------------------------------------------------
  4161. // Purpose:
  4162. // Input : *player -
  4163. //-----------------------------------------------------------------------------
  4164. void CSceneManager::OnClientActive( CBasePlayer *player )
  4165. {
  4166. int c = m_QueuedSceneSounds.Count();
  4167. for ( int i = 0; i < c; i++ )
  4168. {
  4169. CRestoreSceneSound *sound = &m_QueuedSceneSounds[ i ];
  4170. if ( sound->actor == NULL )
  4171. continue;
  4172. // Blow off sounds too far in past to encode over networking layer
  4173. if ( fabs( 1000.0f * sound->time_in_past ) > MAX_SOUND_DELAY_MSEC )
  4174. continue;
  4175. CPASAttenuationFilter filter( sound->actor );
  4176. EmitSound_t es;
  4177. es.m_nChannel = CHAN_VOICE;
  4178. es.m_flVolume = 1;
  4179. es.m_pSoundName = sound->soundname;
  4180. es.m_SoundLevel = sound->soundlevel;
  4181. es.m_flSoundTime = gpGlobals->curtime - sound->time_in_past;
  4182. EmitSound( filter, sound->actor->entindex(), es );
  4183. }
  4184. m_QueuedSceneSounds.RemoveAll();
  4185. }
  4186. //-----------------------------------------------------------------------------
  4187. // Purpose: Deletes scenes involving the specified actor
  4188. //-----------------------------------------------------------------------------
  4189. void CSceneManager::RemoveScenesInvolvingActor( CBaseFlex *pActor )
  4190. {
  4191. if ( !pActor )
  4192. return;
  4193. // This loop can remove items from m_ActiveScenes array, so loop through backwards.
  4194. int c = m_ActiveScenes.Count();
  4195. for ( int i = c - 1 ; i >= 0; --i )
  4196. {
  4197. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4198. if ( !pScene )
  4199. {
  4200. continue;
  4201. }
  4202. if ( pScene->InvolvesActor( pActor ) ) // NOTE: returns false if scene hasn't loaded yet
  4203. {
  4204. LocalScene_Printf( "%s : removed for '%s'\n", STRING( pScene->m_iszSceneFile ), pActor ? pActor->GetDebugName() : "NULL" );
  4205. pScene->CancelPlayback();
  4206. }
  4207. else
  4208. {
  4209. CInstancedSceneEntity *pInstancedScene = dynamic_cast< CInstancedSceneEntity * >( pScene );
  4210. if ( pInstancedScene && pInstancedScene->m_hOwner )
  4211. {
  4212. if ( pInstancedScene->m_hOwner == pActor )
  4213. {
  4214. if ( pInstancedScene->m_bIsPlayingBack )
  4215. {
  4216. pInstancedScene->OnSceneFinished( true, false );
  4217. }
  4218. LocalScene_Printf( "%s : removed for '%s'\n", STRING( pInstancedScene->m_iszSceneFile ), pActor ? pActor->GetDebugName() : "NULL" );
  4219. UTIL_Remove( pInstancedScene );
  4220. }
  4221. }
  4222. }
  4223. }
  4224. }
  4225. //-----------------------------------------------------------------------------
  4226. // Purpose: Stops scenes involving the specified actor
  4227. //-----------------------------------------------------------------------------
  4228. void CSceneManager::RemoveActorFromScenes( CBaseFlex *pActor, bool bInstancedOnly, bool bNonIdleOnly, const char *pszThisSceneOnly )
  4229. {
  4230. int c = m_ActiveScenes.Count();
  4231. for ( int i = 0; i < c; i++ )
  4232. {
  4233. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4234. if ( !pScene )
  4235. {
  4236. continue;
  4237. }
  4238. // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene
  4239. if ( bInstancedOnly &&
  4240. ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) )
  4241. {
  4242. continue;
  4243. }
  4244. if ( bNonIdleOnly && !pScene->ShouldBreakOnNonIdle() )
  4245. continue;
  4246. if ( pScene->InvolvesActor( pActor ) )
  4247. {
  4248. if ( pszThisSceneOnly && pszThisSceneOnly[0] )
  4249. {
  4250. if ( Q_strcmp( pszThisSceneOnly, STRING(pScene->m_iszSceneFile) ) )
  4251. continue;
  4252. }
  4253. LocalScene_Printf( "%s : removed for '%s'\n", STRING( pScene->m_iszSceneFile ), pActor ? pActor->GetDebugName() : "NULL" );
  4254. pScene->CancelPlayback();
  4255. }
  4256. }
  4257. }
  4258. //-----------------------------------------------------------------------------
  4259. // Purpose: Pause scenes involving the specified actor
  4260. //-----------------------------------------------------------------------------
  4261. void CSceneManager::PauseActorsScenes( CBaseFlex *pActor, bool bInstancedOnly )
  4262. {
  4263. int c = m_ActiveScenes.Count();
  4264. for ( int i = 0; i < c; i++ )
  4265. {
  4266. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4267. if ( !pScene )
  4268. {
  4269. continue;
  4270. }
  4271. // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene
  4272. if ( bInstancedOnly &&
  4273. ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) )
  4274. {
  4275. continue;
  4276. }
  4277. if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() )
  4278. {
  4279. LocalScene_Printf( "Pausing actor %s scripted scene: %s\n", pActor->GetDebugName(), STRING(pScene->m_iszSceneFile) );
  4280. variant_t emptyVariant;
  4281. pScene->AcceptInput( "Pause", pScene, pScene, emptyVariant, 0 );
  4282. }
  4283. }
  4284. }
  4285. //-----------------------------------------------------------------------------
  4286. // Purpose: Return true if this Actor is only in scenes that are interruptable right now
  4287. //-----------------------------------------------------------------------------
  4288. bool CSceneManager::IsInInterruptableScenes( CBaseFlex *pActor )
  4289. {
  4290. int c = m_ActiveScenes.Count();
  4291. for ( int i = 0; i < c; i++ )
  4292. {
  4293. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4294. if ( !pScene )
  4295. continue;
  4296. //Ignore background scenes since they're harmless.
  4297. if ( pScene->IsBackground() == true )
  4298. continue;
  4299. if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() )
  4300. {
  4301. if ( pScene->IsInterruptable() == false )
  4302. return false;
  4303. }
  4304. }
  4305. return true;
  4306. }
  4307. //-----------------------------------------------------------------------------
  4308. // Purpose: Resume any paused scenes involving the specified actor
  4309. //-----------------------------------------------------------------------------
  4310. void CSceneManager::ResumeActorsScenes( CBaseFlex *pActor, bool bInstancedOnly )
  4311. {
  4312. int c = m_ActiveScenes.Count();
  4313. for ( int i = 0; i < c; i++ )
  4314. {
  4315. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4316. if ( !pScene )
  4317. {
  4318. continue;
  4319. }
  4320. // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene
  4321. if ( bInstancedOnly &&
  4322. ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) )
  4323. {
  4324. continue;
  4325. }
  4326. if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() )
  4327. {
  4328. LocalScene_Printf( "Resuming actor %s scripted scene: %s\n", pActor->GetDebugName(), STRING(pScene->m_iszSceneFile) );
  4329. variant_t emptyVariant;
  4330. pScene->AcceptInput( "Resume", pScene, pScene, emptyVariant, 0 );
  4331. }
  4332. }
  4333. }
  4334. //-----------------------------------------------------------------------------
  4335. // Purpose: Set all paused, in-playback scenes to resume when the actor is ready
  4336. //-----------------------------------------------------------------------------
  4337. void CSceneManager::QueueActorsScenesToResume( CBaseFlex *pActor, bool bInstancedOnly )
  4338. {
  4339. int c = m_ActiveScenes.Count();
  4340. for ( int i = 0; i < c; i++ )
  4341. {
  4342. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4343. if ( !pScene )
  4344. {
  4345. continue;
  4346. }
  4347. // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene
  4348. if ( bInstancedOnly &&
  4349. ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) )
  4350. {
  4351. continue;
  4352. }
  4353. if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() && pScene->IsPaused() )
  4354. {
  4355. pScene->QueueResumePlayback();
  4356. }
  4357. }
  4358. }
  4359. //-----------------------------------------------------------------------------
  4360. // Purpose: returns if there are scenes involving the specified actor
  4361. //-----------------------------------------------------------------------------
  4362. bool CSceneManager::IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4363. {
  4364. int c = m_ActiveScenes.Count();
  4365. for ( int i = 0; i < c; i++ )
  4366. {
  4367. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4368. if ( !pScene ||
  4369. !pScene->IsPlayingBack() ||
  4370. ( bIgnoreInstancedScenes && dynamic_cast<CInstancedSceneEntity *>(pScene) != NULL )
  4371. )
  4372. {
  4373. continue;
  4374. }
  4375. if ( pScene->InvolvesActor( pActor ) )
  4376. {
  4377. return true;
  4378. }
  4379. }
  4380. return false;
  4381. }
  4382. bool CSceneManager::IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4383. {
  4384. int c = m_ActiveScenes.Count();
  4385. for ( int i = 0; i < c; i++ )
  4386. {
  4387. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4388. if ( !pScene ||
  4389. !pScene->IsPlayingBack() ||
  4390. pScene->IsPaused() ||
  4391. ( bIgnoreInstancedScenes && dynamic_cast<CInstancedSceneEntity *>(pScene) != NULL )
  4392. )
  4393. {
  4394. continue;
  4395. }
  4396. if ( pScene->InvolvesActor( pActor ) )
  4397. {
  4398. return true;
  4399. }
  4400. }
  4401. return false;
  4402. }
  4403. //-----------------------------------------------------------------------------
  4404. // Purpose:
  4405. // Input : *pActor -
  4406. // Output : Returns true on success, false on failure.
  4407. //-----------------------------------------------------------------------------
  4408. bool CSceneManager::IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4409. {
  4410. int c = m_ActiveScenes.Count();
  4411. for ( int i = 0; i < c; i++ )
  4412. {
  4413. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4414. if ( !pScene ||
  4415. !pScene->IsPlayingBack() ||
  4416. ( bIgnoreInstancedScenes && dynamic_cast<CInstancedSceneEntity *>(pScene) != NULL )
  4417. )
  4418. {
  4419. continue;
  4420. }
  4421. if ( pScene->InvolvesActor( pActor ) )
  4422. {
  4423. if ( pScene->HasUnplayedSpeech() )
  4424. return true;
  4425. }
  4426. }
  4427. return false;
  4428. }
  4429. bool CSceneManager::IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4430. {
  4431. int c = m_ActiveScenes.Count();
  4432. for ( int i = 0; i < c; i++ )
  4433. {
  4434. CSceneEntity *pScene = m_ActiveScenes[ i ].Get();
  4435. if ( !pScene ||
  4436. !pScene->IsPlayingBack() ||
  4437. pScene->IsPaused() ||
  4438. ( bIgnoreInstancedScenes && dynamic_cast<CInstancedSceneEntity *>(pScene) != NULL )
  4439. )
  4440. {
  4441. continue;
  4442. }
  4443. if ( pScene->InvolvesActor( pActor ) )
  4444. {
  4445. if ( pScene->HasUnplayedSpeech() )
  4446. return true;
  4447. }
  4448. }
  4449. return false;
  4450. }
  4451. //-----------------------------------------------------------------------------
  4452. // Purpose:
  4453. // Input : *actor -
  4454. // *soundname -
  4455. // soundlevel -
  4456. // soundtime -
  4457. //-----------------------------------------------------------------------------
  4458. void CSceneManager::QueueRestoredSound( CBaseFlex *actor, char const *soundname, soundlevel_t soundlevel, float time_in_past )
  4459. {
  4460. CRestoreSceneSound e;
  4461. e.actor = actor;
  4462. Q_strncpy( e.soundname, soundname, sizeof( e.soundname ) );
  4463. e.soundlevel = soundlevel;
  4464. e.time_in_past = time_in_past;
  4465. m_QueuedSceneSounds.AddToTail( e );
  4466. }
  4467. //-----------------------------------------------------------------------------
  4468. //-----------------------------------------------------------------------------
  4469. void RemoveActorFromScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly, bool nonidlescenesonly, const char *pszThisSceneOnly )
  4470. {
  4471. GetSceneManager()->RemoveActorFromScenes( pActor, instancedscenesonly, nonidlescenesonly, pszThisSceneOnly );
  4472. }
  4473. //-----------------------------------------------------------------------------
  4474. //-----------------------------------------------------------------------------
  4475. void RemoveAllScenesInvolvingActor( CBaseFlex *pActor )
  4476. {
  4477. GetSceneManager()->RemoveScenesInvolvingActor( pActor );
  4478. }
  4479. //-----------------------------------------------------------------------------
  4480. //-----------------------------------------------------------------------------
  4481. void PauseActorsScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly )
  4482. {
  4483. GetSceneManager()->PauseActorsScenes( pActor, instancedscenesonly );
  4484. }
  4485. //-----------------------------------------------------------------------------
  4486. //-----------------------------------------------------------------------------
  4487. bool IsInInterruptableScenes( CBaseFlex *pActor )
  4488. {
  4489. return GetSceneManager()->IsInInterruptableScenes( pActor );
  4490. }
  4491. //-----------------------------------------------------------------------------
  4492. //-----------------------------------------------------------------------------
  4493. void ResumeActorsScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly )
  4494. {
  4495. GetSceneManager()->ResumeActorsScenes( pActor, instancedscenesonly );
  4496. }
  4497. //-----------------------------------------------------------------------------
  4498. //-----------------------------------------------------------------------------
  4499. void QueueActorsScriptedScenesToResume( CBaseFlex *pActor, bool instancedscenesonly )
  4500. {
  4501. GetSceneManager()->QueueActorsScenesToResume( pActor, instancedscenesonly );
  4502. }
  4503. //-----------------------------------------------------------------------------
  4504. //-----------------------------------------------------------------------------
  4505. bool IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4506. {
  4507. return GetSceneManager()->IsRunningScriptedScene( pActor, bIgnoreInstancedScenes );
  4508. }
  4509. bool IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4510. {
  4511. return GetSceneManager()->IsRunningScriptedSceneAndNotPaused( pActor, bIgnoreInstancedScenes );
  4512. }
  4513. //-----------------------------------------------------------------------------
  4514. //-----------------------------------------------------------------------------
  4515. bool IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4516. {
  4517. return GetSceneManager()->IsRunningScriptedSceneWithSpeech( pActor, bIgnoreInstancedScenes );
  4518. }
  4519. bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes )
  4520. {
  4521. return GetSceneManager()->IsRunningScriptedSceneWithSpeechAndNotPaused( pActor, bIgnoreInstancedScenes );
  4522. }
  4523. //===========================================================================================================
  4524. // SCENE LIST MANAGER
  4525. //===========================================================================================================
  4526. LINK_ENTITY_TO_CLASS( logic_scene_list_manager, CSceneListManager );
  4527. BEGIN_DATADESC( CSceneListManager )
  4528. DEFINE_UTLVECTOR( m_hListManagers, FIELD_EHANDLE ),
  4529. // Keys
  4530. DEFINE_KEYFIELD( m_iszScenes[0], FIELD_STRING, "scene0" ),
  4531. DEFINE_KEYFIELD( m_iszScenes[1], FIELD_STRING, "scene1" ),
  4532. DEFINE_KEYFIELD( m_iszScenes[2], FIELD_STRING, "scene2" ),
  4533. DEFINE_KEYFIELD( m_iszScenes[3], FIELD_STRING, "scene3" ),
  4534. DEFINE_KEYFIELD( m_iszScenes[4], FIELD_STRING, "scene4" ),
  4535. DEFINE_KEYFIELD( m_iszScenes[5], FIELD_STRING, "scene5" ),
  4536. DEFINE_KEYFIELD( m_iszScenes[6], FIELD_STRING, "scene6" ),
  4537. DEFINE_KEYFIELD( m_iszScenes[7], FIELD_STRING, "scene7" ),
  4538. DEFINE_KEYFIELD( m_iszScenes[8], FIELD_STRING, "scene8" ),
  4539. DEFINE_KEYFIELD( m_iszScenes[9], FIELD_STRING, "scene9" ),
  4540. DEFINE_KEYFIELD( m_iszScenes[10], FIELD_STRING, "scene10" ),
  4541. DEFINE_KEYFIELD( m_iszScenes[11], FIELD_STRING, "scene11" ),
  4542. DEFINE_KEYFIELD( m_iszScenes[12], FIELD_STRING, "scene12" ),
  4543. DEFINE_KEYFIELD( m_iszScenes[13], FIELD_STRING, "scene13" ),
  4544. DEFINE_KEYFIELD( m_iszScenes[14], FIELD_STRING, "scene14" ),
  4545. DEFINE_KEYFIELD( m_iszScenes[15], FIELD_STRING, "scene15" ),
  4546. DEFINE_FIELD( m_hScenes[0], FIELD_EHANDLE ),
  4547. DEFINE_FIELD( m_hScenes[1], FIELD_EHANDLE ),
  4548. DEFINE_FIELD( m_hScenes[2], FIELD_EHANDLE ),
  4549. DEFINE_FIELD( m_hScenes[3], FIELD_EHANDLE ),
  4550. DEFINE_FIELD( m_hScenes[4], FIELD_EHANDLE ),
  4551. DEFINE_FIELD( m_hScenes[5], FIELD_EHANDLE ),
  4552. DEFINE_FIELD( m_hScenes[6], FIELD_EHANDLE ),
  4553. DEFINE_FIELD( m_hScenes[7], FIELD_EHANDLE ),
  4554. DEFINE_FIELD( m_hScenes[8], FIELD_EHANDLE ),
  4555. DEFINE_FIELD( m_hScenes[9], FIELD_EHANDLE ),
  4556. DEFINE_FIELD( m_hScenes[10], FIELD_EHANDLE ),
  4557. DEFINE_FIELD( m_hScenes[11], FIELD_EHANDLE ),
  4558. DEFINE_FIELD( m_hScenes[12], FIELD_EHANDLE ),
  4559. DEFINE_FIELD( m_hScenes[13], FIELD_EHANDLE ),
  4560. DEFINE_FIELD( m_hScenes[14], FIELD_EHANDLE ),
  4561. DEFINE_FIELD( m_hScenes[15], FIELD_EHANDLE ),
  4562. // Inputs
  4563. DEFINE_INPUTFUNC( FIELD_VOID, "Shutdown", InputShutdown ),
  4564. END_DATADESC()
  4565. //-----------------------------------------------------------------------------
  4566. // Purpose:
  4567. //-----------------------------------------------------------------------------
  4568. void CSceneListManager::Activate( void )
  4569. {
  4570. BaseClass::Activate();
  4571. // Hook up scenes, but not after loading a game because they're saved.
  4572. if ( gpGlobals->eLoadType != MapLoad_LoadGame )
  4573. {
  4574. for ( int i = 0; i < SCENE_LIST_MANAGER_MAX_SCENES; i++ )
  4575. {
  4576. if ( m_iszScenes[i] != NULL_STRING )
  4577. {
  4578. m_hScenes[i] = gEntList.FindEntityByName( NULL, STRING(m_iszScenes[i]) );
  4579. if ( m_hScenes[i] )
  4580. {
  4581. CSceneEntity *pScene = dynamic_cast<CSceneEntity*>(m_hScenes[i].Get());
  4582. if ( pScene )
  4583. {
  4584. pScene->AddListManager( this );
  4585. }
  4586. else
  4587. {
  4588. CSceneListManager *pList = dynamic_cast<CSceneListManager*>(m_hScenes[i].Get());
  4589. if ( pList )
  4590. {
  4591. pList->AddListManager( this );
  4592. }
  4593. else
  4594. {
  4595. Warning( "%s(%s) found an entity that wasn't a logic_choreographed_scene or logic_scene_list_manager in slot %d, named %s\n", GetDebugName(), GetClassname(), i, STRING(m_iszScenes[i]) );
  4596. m_hScenes[i] = NULL;
  4597. }
  4598. }
  4599. }
  4600. else
  4601. {
  4602. Warning( "%s(%s) could not find scene %d, named %s\n", GetDebugName(), GetClassname(), i, STRING(m_iszScenes[i]) );
  4603. }
  4604. }
  4605. }
  4606. }
  4607. }
  4608. //-----------------------------------------------------------------------------
  4609. // Purpose: A scene or manager in our list has started playing.
  4610. // Remove all scenes earlier in the list.
  4611. //-----------------------------------------------------------------------------
  4612. void CSceneListManager::SceneStarted( CBaseEntity *pSceneOrManager )
  4613. {
  4614. // Move backwards and call remove on all scenes / managers earlier in the list to the fired one
  4615. bool bFoundStart = false;
  4616. for ( int i = SCENE_LIST_MANAGER_MAX_SCENES-1; i >= 0; i-- )
  4617. {
  4618. if ( !m_hScenes[i] )
  4619. continue;
  4620. if ( bFoundStart )
  4621. {
  4622. RemoveScene( i );
  4623. }
  4624. else if ( m_hScenes[i] == pSceneOrManager )
  4625. {
  4626. bFoundStart = true;
  4627. }
  4628. }
  4629. // Tell any managers we're within that we've started a scene
  4630. if ( bFoundStart )
  4631. {
  4632. int c = m_hListManagers.Count();
  4633. for ( int i = 0; i < c; i++ )
  4634. {
  4635. if ( m_hListManagers[i] )
  4636. {
  4637. m_hListManagers[i]->SceneStarted( this );
  4638. }
  4639. }
  4640. }
  4641. }
  4642. //-----------------------------------------------------------------------------
  4643. // Purpose:
  4644. //-----------------------------------------------------------------------------
  4645. void CSceneListManager::AddListManager( CSceneListManager *pManager )
  4646. {
  4647. CHandle< CSceneListManager > h;
  4648. h = pManager;
  4649. // Only add it once
  4650. if ( m_hListManagers.Find( h ) == m_hListManagers.InvalidIndex() )
  4651. {
  4652. m_hListManagers.AddToTail( h );
  4653. }
  4654. }
  4655. //-----------------------------------------------------------------------------
  4656. // Purpose: Shut down all scenes, and then remove this entity
  4657. //-----------------------------------------------------------------------------
  4658. void CSceneListManager::InputShutdown( inputdata_t &inputdata )
  4659. {
  4660. ShutdownList();
  4661. }
  4662. //-----------------------------------------------------------------------------
  4663. // Purpose:
  4664. //-----------------------------------------------------------------------------
  4665. void CSceneListManager::ShutdownList( void )
  4666. {
  4667. for ( int i = 0; i < SCENE_LIST_MANAGER_MAX_SCENES; i++ )
  4668. {
  4669. if ( m_hScenes[i] )
  4670. {
  4671. RemoveScene(i);
  4672. }
  4673. }
  4674. UTIL_Remove( this );
  4675. }
  4676. //-----------------------------------------------------------------------------
  4677. // Purpose:
  4678. //-----------------------------------------------------------------------------
  4679. void CSceneListManager::RemoveScene( int iIndex )
  4680. {
  4681. CSceneEntity *pScene = dynamic_cast<CSceneEntity*>(m_hScenes[iIndex].Get());
  4682. if ( pScene )
  4683. {
  4684. // Remove the scene
  4685. UTIL_Remove( pScene );
  4686. return;
  4687. }
  4688. // Tell the list manager to shut down all scenes
  4689. CSceneListManager *pList = dynamic_cast<CSceneListManager*>(m_hScenes[iIndex].Get());
  4690. if ( pList )
  4691. {
  4692. pList->ShutdownList();
  4693. }
  4694. }
  4695. void ReloadSceneFromDisk( CBaseEntity *ent )
  4696. {
  4697. CSceneEntity *scene = dynamic_cast< CSceneEntity * >( ent );
  4698. if ( !scene )
  4699. return;
  4700. Assert( 0 );
  4701. }
  4702. // Purpose:
  4703. // Input : *ent -
  4704. // Output : char const
  4705. //-----------------------------------------------------------------------------
  4706. char const *GetSceneFilename( CBaseEntity *ent )
  4707. {
  4708. CSceneEntity *scene = dynamic_cast< CSceneEntity * >( ent );
  4709. if ( !scene )
  4710. return "";
  4711. return STRING( scene->m_iszSceneFile );
  4712. }
  4713. //-----------------------------------------------------------------------------
  4714. // Purpose: Return a list of the last 5 lines of speech from NPCs for bug reports
  4715. // Input :
  4716. // Output : speech - last 5 sound files played as speech
  4717. // returns the number of sounds in the returned list
  4718. //-----------------------------------------------------------------------------
  4719. int GetRecentNPCSpeech( recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ] )
  4720. {
  4721. int i;
  4722. int num;
  4723. int index;
  4724. // clear out the output list
  4725. for( i = 0; i < SPEECH_LIST_MAX_SOUNDS; i++ )
  4726. {
  4727. speech[ i ].time = 0.0f;
  4728. speech[ i ].name[ 0 ] = 0;
  4729. speech[ i ].sceneName[ 0 ] = 0;
  4730. }
  4731. // copy the sound names into the list in order they were played
  4732. num = 0;
  4733. index = speechListIndex;
  4734. for( i = 0; i < SPEECH_LIST_MAX_SOUNDS; i++ )
  4735. {
  4736. if ( speechListSounds[ index ].name[ 0 ] )
  4737. {
  4738. // only copy names that are not zero length
  4739. speech[ num ] = speechListSounds[ index ];
  4740. num++;
  4741. }
  4742. index++;
  4743. if ( index >= SPEECH_LIST_MAX_SOUNDS )
  4744. {
  4745. index = 0;
  4746. }
  4747. }
  4748. return num;
  4749. }
  4750. //-----------------------------------------------------------------------------
  4751. // Purpose: Displays a list of the last 5 lines of speech from NPCs
  4752. // Input :
  4753. // Output :
  4754. //-----------------------------------------------------------------------------
  4755. static void ListRecentNPCSpeech( void )
  4756. {
  4757. if ( !UTIL_IsCommandIssuedByServerAdmin() )
  4758. return;
  4759. recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ];
  4760. int num;
  4761. int i;
  4762. // get any sounds that were spoken by NPCs recently
  4763. num = GetRecentNPCSpeech( speech );
  4764. Msg( "Recent NPC speech:\n" );
  4765. for( i = 0; i < num; i++ )
  4766. {
  4767. Msg( " time: %6.3f sound name: %s scene: %s\n", speech[ i ].time, speech[ i ].name, speech[ i ].sceneName );
  4768. }
  4769. Msg( "Current time: %6.3f\n", gpGlobals->curtime );
  4770. }
  4771. static ConCommand ListRecentNPCSpeechCmd( "listRecentNPCSpeech", ListRecentNPCSpeech, "Displays a list of the last 5 lines of speech from NPCs.", FCVAR_DONTRECORD|FCVAR_GAMEDLL );
  4772. CON_COMMAND( scene_flush, "Flush all .vcds from the cache and reload from disk." )
  4773. {
  4774. if ( !UTIL_IsCommandIssuedByServerAdmin() )
  4775. return;
  4776. Msg( "Reloading\n" );
  4777. scenefilecache->Reload();
  4778. Msg( " done\n" );
  4779. }