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

544 lines
12 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "baseanimating.h"
  9. #include "Sprite.h"
  10. #include "SpriteTrail.h"
  11. #include <ctype.h>
  12. #include "animation.h"
  13. #include "eventlist.h"
  14. #include "npcevent.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. enum EffectType
  18. {
  19. EFFECT_TYPE_TRAIL = 1,
  20. EFFECT_TYPE_SPRITE
  21. };
  22. bool g_bUnget = false;
  23. unsigned char *buffer;
  24. char name[ 256 ];
  25. const char *currenttoken;
  26. int tokencount;
  27. char token[ 1204 ];
  28. class CEffectScriptElement
  29. {
  30. public:
  31. CEffectScriptElement();
  32. char m_szEffectName[128];
  33. CHandle<CSpriteTrail> m_pTrail;
  34. CHandle<CSprite> m_pSprite;
  35. int m_iType;
  36. int m_iRenderType;
  37. int m_iR;
  38. int m_iG;
  39. int m_iB;
  40. int m_iA;
  41. char m_szAttachment[128];
  42. char m_szMaterial[128];
  43. float m_flScale;
  44. float m_flFadeTime;
  45. float m_flTextureRes;
  46. bool m_bStopFollowOnKill;
  47. bool IsActive( void ) { return m_bActive; }
  48. void Activate( void ) { m_bActive = true; }
  49. void Deactivate( void ) { m_bActive = false; }
  50. private:
  51. bool m_bActive;
  52. };
  53. CEffectScriptElement::CEffectScriptElement()
  54. {
  55. m_pTrail = NULL;
  56. m_pSprite = NULL;
  57. m_iType = 0;
  58. Deactivate();
  59. m_iRenderType = kRenderTransAdd;
  60. m_iR = 255;
  61. m_iG = 0;
  62. m_iB = 0;
  63. m_iA = 255;
  64. m_flScale = 1.0f;
  65. m_flFadeTime = 1.0f;
  66. m_flTextureRes = -1.0f;
  67. m_bStopFollowOnKill = false;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // An entity which emits other entities at points
  71. //-----------------------------------------------------------------------------
  72. class CEnvEffectsScript : public CBaseAnimating
  73. {
  74. public:
  75. DECLARE_CLASS( CEnvEffectsScript, CBaseAnimating );
  76. DECLARE_DATADESC();
  77. virtual void Precache();
  78. virtual void Spawn();
  79. virtual int UpdateTransmitState();
  80. void InputSetSequence( inputdata_t &inputdata );
  81. void ParseScriptFile( void );
  82. void LoadFromBuffer( const char *scriptfile, const char *buffer );
  83. virtual void Think( void );
  84. void ParseNewEffect( void );
  85. const char *GetScriptFile( void )
  86. {
  87. return STRING( m_iszScriptName );
  88. }
  89. void HandleAnimEvent ( animevent_t *pEvent );
  90. void TrailEffectEvent( CEffectScriptElement *pEffect );
  91. void SpriteEffectEvent( CEffectScriptElement *pEffect );
  92. CEffectScriptElement *GetScriptElementByName( const char *pName );
  93. private:
  94. string_t m_iszScriptName;
  95. CUtlVector< CEffectScriptElement > m_ScriptElements;
  96. //-----------------------------------------------------------------------------
  97. // Purpose:
  98. // Output : Returns true on success, false on failure.
  99. //-----------------------------------------------------------------------------
  100. bool IsRootCommand( void )
  101. {
  102. if ( !Q_stricmp( token, "effect" ) )
  103. return true;
  104. return false;
  105. }
  106. };
  107. inline bool ParseToken( void )
  108. {
  109. if ( g_bUnget )
  110. {
  111. g_bUnget = false;
  112. return true;
  113. }
  114. currenttoken = engine->ParseFile( currenttoken, token, sizeof( token ) );
  115. tokencount++;
  116. return currenttoken != NULL ? true : false;
  117. }
  118. inline void Unget()
  119. {
  120. g_bUnget = true;
  121. }
  122. inline bool TokenWaiting( void )
  123. {
  124. const char *p = currenttoken;
  125. while ( *p && *p!='\n')
  126. {
  127. // Special handler for // comment blocks
  128. if ( *p == '/' && *(p+1) == '/' )
  129. return false;
  130. if ( !V_isspace( *p ) || V_isalnum( *p ) )
  131. return true;
  132. p++;
  133. }
  134. return false;
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Save/load
  138. //-----------------------------------------------------------------------------
  139. BEGIN_DATADESC( CEnvEffectsScript )
  140. // Inputs
  141. DEFINE_INPUTFUNC( FIELD_STRING, "SetSequence", InputSetSequence ),
  142. DEFINE_KEYFIELD( m_iszScriptName, FIELD_STRING, "scriptfile" ),
  143. // DEFINE_FIELD( m_ScriptElements, CUtlVector < CEffectScriptElement > ),
  144. DEFINE_FUNCTION( Think ),
  145. END_DATADESC()
  146. LINK_ENTITY_TO_CLASS( env_effectscript, CEnvEffectsScript );
  147. //-----------------------------------------------------------------------------
  148. // Should we transmit it to the client?
  149. //-----------------------------------------------------------------------------
  150. int CEnvEffectsScript::UpdateTransmitState()
  151. {
  152. return SetTransmitState( FL_EDICT_ALWAYS );
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Precache
  156. //-----------------------------------------------------------------------------
  157. void CEnvEffectsScript::Precache()
  158. {
  159. BaseClass::Precache();
  160. PrecacheModel( STRING( GetModelName() ) );
  161. if ( m_iszScriptName != NULL_STRING )
  162. ParseScriptFile();
  163. else
  164. Warning( "CEnvEffectsScript with no script!\n" );
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Spawn
  168. //-----------------------------------------------------------------------------
  169. void CEnvEffectsScript::Spawn()
  170. {
  171. Precache();
  172. BaseClass::Spawn();
  173. // We need a model for its animation sequences even though we don't render it
  174. SetModel( STRING( GetModelName() ) );
  175. AddEffects( EF_NODRAW );
  176. SetThink( &CEnvEffectsScript::Think );
  177. SetNextThink( gpGlobals->curtime + 0.1f );
  178. }
  179. void CEnvEffectsScript::Think( void )
  180. {
  181. StudioFrameAdvance();
  182. DispatchAnimEvents( this );
  183. SetNextThink( gpGlobals->curtime + 0.1f );
  184. }
  185. void CEnvEffectsScript::TrailEffectEvent( CEffectScriptElement *pEffect )
  186. {
  187. if ( pEffect->IsActive() == false )
  188. {
  189. //Only one type of this effect active at a time.
  190. if ( pEffect->m_pTrail == NULL )
  191. {
  192. pEffect->m_pTrail = CSpriteTrail::SpriteTrailCreate( pEffect->m_szMaterial, GetAbsOrigin(), true );
  193. pEffect->m_pTrail->FollowEntity( this );
  194. pEffect->m_pTrail->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone );
  195. pEffect->m_pTrail->SetStartWidth( pEffect->m_flScale );
  196. if ( pEffect->m_flTextureRes < 0.0f )
  197. {
  198. pEffect->m_pTrail->SetTextureResolution( 1.0f / ( 16.0f * pEffect->m_flScale ) );
  199. }
  200. else
  201. {
  202. pEffect->m_pTrail->SetTextureResolution( pEffect->m_flTextureRes );
  203. }
  204. pEffect->m_pTrail->SetLifeTime( pEffect->m_flFadeTime );
  205. pEffect->m_pTrail->TurnOn();
  206. pEffect->m_pTrail->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) );
  207. pEffect->Activate();
  208. }
  209. }
  210. }
  211. void CEnvEffectsScript::SpriteEffectEvent( CEffectScriptElement *pEffect )
  212. {
  213. if ( pEffect->IsActive() == false )
  214. {
  215. //Only one type of this effect active at a time.
  216. if ( pEffect->m_pSprite == NULL )
  217. {
  218. pEffect->m_pSprite = CSprite::SpriteCreate( pEffect->m_szMaterial, GetAbsOrigin(), true );
  219. pEffect->m_pSprite->FollowEntity( this );
  220. pEffect->m_pSprite->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone );
  221. pEffect->m_pSprite->SetScale( pEffect->m_flScale );
  222. pEffect->m_pSprite->TurnOn();
  223. pEffect->m_pSprite->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) );
  224. pEffect->Activate();
  225. }
  226. }
  227. }
  228. void CEnvEffectsScript::HandleAnimEvent ( animevent_t *pEvent )
  229. {
  230. int nEvent = pEvent->Event();
  231. if ( nEvent == AE_START_SCRIPTED_EFFECT )
  232. {
  233. CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options );
  234. if ( pCurrent )
  235. {
  236. if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL )
  237. TrailEffectEvent( pCurrent );
  238. else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE )
  239. SpriteEffectEvent( pCurrent );
  240. }
  241. return;
  242. }
  243. if ( nEvent == AE_STOP_SCRIPTED_EFFECT )
  244. {
  245. CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options );
  246. if ( pCurrent && pCurrent->IsActive() )
  247. {
  248. pCurrent->Deactivate();
  249. if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL )
  250. {
  251. if ( pCurrent->m_bStopFollowOnKill == true )
  252. {
  253. Vector vOrigin;
  254. GetAttachment( pCurrent->m_pTrail->m_nAttachment, vOrigin );
  255. pCurrent->m_pTrail->StopFollowingEntity();
  256. pCurrent->m_pTrail->m_hAttachedToEntity = NULL;
  257. pCurrent->m_pTrail->m_nAttachment = 0;
  258. pCurrent->m_pTrail->SetAbsOrigin( vOrigin);
  259. }
  260. pCurrent->m_pTrail->FadeAndDie( pCurrent->m_flFadeTime );
  261. pCurrent->m_pTrail = NULL;
  262. }
  263. else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE )
  264. {
  265. if ( pCurrent->m_bStopFollowOnKill == true )
  266. {
  267. Vector vOrigin;
  268. GetAttachment( pCurrent->m_pSprite->m_nAttachment, vOrigin );
  269. pCurrent->m_pSprite->StopFollowingEntity();
  270. pCurrent->m_pSprite->m_hAttachedToEntity = NULL;
  271. pCurrent->m_pSprite->m_nAttachment = 0;
  272. pCurrent->m_pSprite->SetAbsOrigin( vOrigin);
  273. }
  274. pCurrent->m_pSprite->FadeAndDie( pCurrent->m_flFadeTime );
  275. pCurrent->m_pSprite = NULL;
  276. }
  277. }
  278. return;
  279. }
  280. BaseClass::HandleAnimEvent( pEvent );
  281. }
  282. //-----------------------------------------------------------------------------
  283. // Purpose: Input that sets the sequence of the entity
  284. //-----------------------------------------------------------------------------
  285. void CEnvEffectsScript::InputSetSequence( inputdata_t &inputdata )
  286. {
  287. if ( inputdata.value.StringID() != NULL_STRING )
  288. {
  289. int nSequence = LookupSequence( STRING( inputdata.value.StringID() ) );
  290. if ( nSequence != ACT_INVALID )
  291. {
  292. SetSequence( nSequence );
  293. ResetSequenceInfo();
  294. SetCycle( 0.0f );
  295. m_flPlaybackRate = 1.0f;
  296. }
  297. }
  298. }
  299. void CEnvEffectsScript::ParseScriptFile( void )
  300. {
  301. int length = 0;
  302. m_ScriptElements.RemoveAll();
  303. const char *pScriptName = GetScriptFile();
  304. //Reset everything.
  305. g_bUnget = false;
  306. currenttoken = NULL;
  307. tokencount = 0;
  308. memset( token, 0, 1204 );
  309. memset( name, 0, 256 );
  310. unsigned char *buffer = (unsigned char *)UTIL_LoadFileForMe( pScriptName, &length );
  311. if ( length <= 0 || !buffer )
  312. {
  313. DevMsg( 1, "CEnvEffectsScript: failed to load %s\n", pScriptName );
  314. return;
  315. }
  316. currenttoken = (const char *)buffer;
  317. LoadFromBuffer( pScriptName, (const char *)buffer );
  318. UTIL_FreeFile( buffer );
  319. }
  320. void CEnvEffectsScript::LoadFromBuffer( const char *scriptfile, const char *buffer )
  321. {
  322. while ( 1 )
  323. {
  324. ParseToken();
  325. if ( !token[0] )
  326. {
  327. break;
  328. }
  329. if ( !Q_stricmp( token, "effect" ) )
  330. {
  331. ParseNewEffect();
  332. }
  333. else
  334. {
  335. Warning( "CEnvEffectsScript: Unknown entry type '%s'\n", token );
  336. break;
  337. }
  338. }
  339. }
  340. void CEnvEffectsScript::ParseNewEffect( void )
  341. {
  342. //Add a new effect to the list.
  343. CEffectScriptElement NewElement;
  344. // Effect Group Name
  345. ParseToken();
  346. Q_strncpy( NewElement.m_szEffectName, token, sizeof( NewElement.m_szEffectName ) );
  347. while ( 1 )
  348. {
  349. ParseToken();
  350. // Oops, part of next definition
  351. if( IsRootCommand() )
  352. {
  353. Unget();
  354. break;
  355. }
  356. if ( !Q_stricmp( token, "{" ) )
  357. {
  358. while ( 1 )
  359. {
  360. ParseToken();
  361. if ( !Q_stricmp( token, "}" ) )
  362. break;
  363. if ( !Q_stricmp( token, "type" ) )
  364. {
  365. ParseToken();
  366. if ( !Q_stricmp( token, "trail" ) )
  367. NewElement.m_iType = EFFECT_TYPE_TRAIL;
  368. else if ( !Q_stricmp( token, "sprite" ) )
  369. NewElement.m_iType = EFFECT_TYPE_SPRITE;
  370. continue;
  371. }
  372. if ( !Q_stricmp( token, "material" ) )
  373. {
  374. ParseToken();
  375. Q_strncpy( NewElement.m_szMaterial, token, sizeof( NewElement.m_szMaterial ) );
  376. PrecacheModel( NewElement.m_szMaterial );
  377. continue;
  378. }
  379. if ( !Q_stricmp( token, "attachment" ) )
  380. {
  381. ParseToken();
  382. Q_strncpy( NewElement.m_szAttachment, token, sizeof( NewElement.m_szAttachment ) );
  383. continue;
  384. }
  385. if ( !Q_stricmp( token, "color" ) )
  386. {
  387. ParseToken();
  388. sscanf( token, "%i %i %i %i", &NewElement.m_iR, &NewElement.m_iG, &NewElement.m_iB, &NewElement.m_iA );
  389. continue;
  390. }
  391. if ( !Q_stricmp( token, "scale" ) )
  392. {
  393. ParseToken();
  394. NewElement.m_flScale = atof( token );
  395. continue;
  396. }
  397. if ( !Q_stricmp( token, "texturescale" ) )
  398. {
  399. ParseToken();
  400. float flTextureScale = atof( token );
  401. NewElement.m_flTextureRes = (flTextureScale > 0.0f) ? 1.0f / flTextureScale : 0.0f;
  402. continue;
  403. }
  404. if ( !Q_stricmp( token, "fadetime" ) )
  405. {
  406. ParseToken();
  407. NewElement.m_flFadeTime = atof( token );
  408. continue;
  409. }
  410. if ( !Q_stricmp( token, "stopfollowonkill" ) )
  411. {
  412. ParseToken();
  413. NewElement.m_bStopFollowOnKill = !!atoi( token );
  414. continue;
  415. }
  416. }
  417. break;
  418. }
  419. }
  420. m_ScriptElements.AddToTail( NewElement );
  421. }
  422. CEffectScriptElement *CEnvEffectsScript::GetScriptElementByName( const char *pName )
  423. {
  424. for ( int i = 0; i < m_ScriptElements.Count(); i++ )
  425. {
  426. CEffectScriptElement *pCurrent = &m_ScriptElements.Element( i );
  427. if ( pCurrent && !Q_stricmp( pCurrent->m_szEffectName, pName ) )
  428. {
  429. return pCurrent;
  430. }
  431. }
  432. return NULL;
  433. }