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.

899 lines
26 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "Sprite.h"
  9. #include "model_types.h"
  10. #include "engine/ivmodelinfo.h"
  11. #include "tier0/vprof.h"
  12. #include "engine/ivdebugoverlay.h"
  13. #if defined( CLIENT_DLL )
  14. #include "enginesprite.h"
  15. #include "iclientmode.h"
  16. #include "c_baseviewmodel.h"
  17. #else
  18. #include "baseviewmodel.h"
  19. #endif
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. const float MAX_SPRITE_SCALE = 64.0f;
  23. const float MAX_GLOW_PROXY_SIZE = 64.0f;
  24. #if !defined( CLIENT_DLL )
  25. LINK_ENTITY_TO_CLASS( env_glow, CSprite ); // For backwards compatibility, remove when no longer needed.
  26. LINK_ENTITY_TO_CLASS( env_sprite_clientside, CSprite );
  27. #endif
  28. #if !defined( CLIENT_DLL )
  29. BEGIN_DATADESC( CSprite )
  30. DEFINE_FIELD( m_flLastTime, FIELD_TIME ),
  31. DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ),
  32. DEFINE_FIELD( m_hAttachedToEntity, FIELD_EHANDLE ),
  33. DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ),
  34. DEFINE_FIELD( m_flDieTime, FIELD_TIME ),
  35. DEFINE_FIELD( m_nBrightness, FIELD_INTEGER ),
  36. DEFINE_FIELD( m_flBrightnessTime, FIELD_FLOAT ),
  37. DEFINE_KEYFIELD( m_flSpriteScale, FIELD_FLOAT, "scale" ),
  38. DEFINE_KEYFIELD( m_flSpriteFramerate, FIELD_FLOAT, "framerate" ),
  39. DEFINE_KEYFIELD( m_flFrame, FIELD_FLOAT, "frame" ),
  40. DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ),
  41. DEFINE_KEYFIELD( m_flGlowProxySize, FIELD_FLOAT, "GlowProxySize" ),
  42. DEFINE_FIELD( m_flScaleTime, FIELD_FLOAT ),
  43. DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ),
  44. DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ),
  45. DEFINE_FIELD( m_flScaleTimeStart, FIELD_TIME ),
  46. DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ),
  47. DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ),
  48. DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_TIME ),
  49. DEFINE_FIELD( m_bWorldSpaceScale, FIELD_BOOLEAN ),
  50. // Function Pointers
  51. DEFINE_FUNCTION( AnimateThink ),
  52. DEFINE_FUNCTION( ExpandThink ),
  53. DEFINE_FUNCTION( AnimateUntilDead ),
  54. DEFINE_FUNCTION( BeginFadeOutThink ),
  55. // Inputs
  56. DEFINE_INPUT( m_flSpriteScale, FIELD_FLOAT, "SetScale" ),
  57. DEFINE_INPUTFUNC( FIELD_VOID, "HideSprite", InputHideSprite ),
  58. DEFINE_INPUTFUNC( FIELD_VOID, "ShowSprite", InputShowSprite ),
  59. DEFINE_INPUTFUNC( FIELD_VOID, "ToggleSprite", InputToggleSprite ),
  60. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorRedValue", InputColorRedValue ),
  61. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorGreenValue", InputColorGreenValue ),
  62. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorBlueValue", InputColorBlueValue ),
  63. END_DATADESC()
  64. #else
  65. BEGIN_PREDICTION_DATA( CSprite )
  66. // Networked
  67. DEFINE_PRED_FIELD( m_hAttachedToEntity, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
  68. DEFINE_PRED_FIELD( m_nAttachment, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  69. DEFINE_PRED_FIELD( m_flScaleTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  70. DEFINE_PRED_FIELD( m_flSpriteScale, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  71. DEFINE_PRED_FIELD( m_flSpriteFramerate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  72. DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  73. DEFINE_PRED_FIELD( m_flBrightnessTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  74. DEFINE_PRED_FIELD( m_nBrightness, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  75. DEFINE_FIELD( m_flLastTime, FIELD_FLOAT ),
  76. DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ),
  77. DEFINE_FIELD( m_flDieTime, FIELD_FLOAT ),
  78. // DEFINE_FIELD( m_flHDRColorScale, FIELD_FLOAT ),
  79. // DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), //Starting scale
  80. // DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ), //Destination scale
  81. // DEFINE_FIELD( m_flScaleTimeStart, FIELD_FLOAT ), //Real time for start of scale
  82. // DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ), //Starting brightness
  83. // DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ), //Destination brightness
  84. // DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_FLOAT ), //Real time for brightness
  85. END_PREDICTION_DATA()
  86. #endif
  87. IMPLEMENT_NETWORKCLASS_ALIASED( Sprite, DT_Sprite );
  88. #if defined( CLIENT_DLL )
  89. static void RecvProxy_SpriteScale( const CRecvProxyData *pData, void *pStruct, void *pOut )
  90. {
  91. ((CSprite*)pStruct)->SetSpriteScale( pData->m_Value.m_Float );
  92. }
  93. #endif
  94. BEGIN_NETWORK_TABLE( CSprite, DT_Sprite )
  95. #if !defined( CLIENT_DLL )
  96. SendPropEHandle( SENDINFO(m_hAttachedToEntity )),
  97. SendPropInt( SENDINFO(m_nAttachment ), 8 ),
  98. SendPropFloat( SENDINFO(m_flScaleTime ), 0, SPROP_NOSCALE ),
  99. #ifdef HL2_DLL
  100. SendPropFloat( SENDINFO(m_flSpriteScale ), 0, SPROP_NOSCALE),
  101. #else
  102. SendPropFloat( SENDINFO(m_flSpriteScale ), 8, SPROP_ROUNDUP, 0.0f, MAX_SPRITE_SCALE),
  103. #endif
  104. SendPropFloat( SENDINFO(m_flGlowProxySize ), 6, SPROP_ROUNDUP, 0.0f, MAX_GLOW_PROXY_SIZE),
  105. SendPropFloat( SENDINFO(m_flHDRColorScale ), 0, SPROP_NOSCALE, 0.0f, 100.0f),
  106. SendPropFloat( SENDINFO(m_flSpriteFramerate ), 8, SPROP_ROUNDUP, 0, 60.0f),
  107. SendPropFloat( SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN, 0.0f, 256.0f),
  108. SendPropFloat( SENDINFO(m_flBrightnessTime ), 0, SPROP_NOSCALE ),
  109. SendPropInt( SENDINFO(m_nBrightness), 8, SPROP_UNSIGNED ),
  110. SendPropBool( SENDINFO(m_bWorldSpaceScale) ),
  111. #else
  112. RecvPropEHandle(RECVINFO(m_hAttachedToEntity)),
  113. RecvPropInt(RECVINFO(m_nAttachment)),
  114. RecvPropFloat(RECVINFO(m_flScaleTime)),
  115. RecvPropFloat(RECVINFO(m_flSpriteScale), 0, RecvProxy_SpriteScale),
  116. RecvPropFloat(RECVINFO(m_flSpriteFramerate)),
  117. RecvPropFloat(RECVINFO(m_flGlowProxySize)),
  118. RecvPropFloat( RECVINFO(m_flHDRColorScale )),
  119. RecvPropFloat(RECVINFO(m_flFrame)),
  120. RecvPropFloat(RECVINFO(m_flBrightnessTime)),
  121. RecvPropInt(RECVINFO(m_nBrightness)),
  122. RecvPropBool( RECVINFO(m_bWorldSpaceScale) ),
  123. #endif
  124. END_NETWORK_TABLE()
  125. LINK_ENTITY_TO_CLASS_ALIASED( env_sprite, Sprite );
  126. #ifdef CLIENT_DLL
  127. extern CUtlVector< CSprite * > g_ClientsideSprites;
  128. #endif // CLIENT_DLL
  129. CSprite::CSprite()
  130. {
  131. #ifdef CLIENT_DLL
  132. m_bClientOnly = false;
  133. #endif // CLIENT_DLL
  134. m_flGlowProxySize = 2.0f;
  135. m_flHDRColorScale = 1.0f;
  136. }
  137. CSprite::~CSprite()
  138. {
  139. #ifdef CLIENT_DLL
  140. if ( m_bClientOnly )
  141. {
  142. g_ClientsideSprites.FindAndFastRemove( this );
  143. }
  144. #endif // CLIENT_DLL
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Purpose:
  148. //-----------------------------------------------------------------------------
  149. void CSprite::Spawn( void )
  150. {
  151. SetSolid( SOLID_NONE );
  152. SetMoveType( MOVETYPE_NONE );
  153. m_flFrame = 0;
  154. Precache();
  155. SetModel( STRING( GetModelName() ) );
  156. CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE );
  157. m_flMaxFrame = (float)modelinfo->GetModelFrameCount( GetModel() ) - 1;
  158. AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW );
  159. #if !defined( CLIENT_DLL )
  160. if ( m_flGlowProxySize > MAX_GLOW_PROXY_SIZE )
  161. {
  162. // Clamp on Spawn to prevent per-frame spew
  163. DevWarning( "env_sprite at setpos %0.0f %0.0f %0.0f has invalid glow size %f - clamping to %f\n",
  164. GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, m_flGlowProxySize.Get(), MAX_GLOW_PROXY_SIZE );
  165. m_flGlowProxySize = MAX_GLOW_PROXY_SIZE;
  166. }
  167. if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_SPRITE_STARTON) )
  168. {
  169. TurnOff();
  170. }
  171. else
  172. #endif
  173. {
  174. TurnOn();
  175. }
  176. // Worldcraft only sets y rotation, copy to Z
  177. if ( GetLocalAngles().y != 0 && GetLocalAngles().z == 0 )
  178. {
  179. QAngle angles = GetLocalAngles();
  180. angles.z = angles.y;
  181. angles.y = 0;
  182. SetLocalAngles( angles );
  183. }
  184. // Clamp our scale if necessary
  185. float scale = m_flSpriteScale;
  186. if ( scale < 0 || scale > MAX_SPRITE_SCALE )
  187. {
  188. #if !defined( CLIENT_DLL )
  189. DevMsg( "LEVEL DESIGN ERROR: Sprite %s with bad scale %f [0..%f]\n", GetDebugName(), m_flSpriteScale.Get(), MAX_SPRITE_SCALE );
  190. #endif
  191. scale = clamp( m_flSpriteScale.Get(), 0, MAX_SPRITE_SCALE );
  192. }
  193. //Set our state
  194. SetBrightness( GetRenderAlpha() );
  195. SetScale( scale );
  196. #if defined( CLIENT_DLL )
  197. m_flStartScale = m_flDestScale = m_flSpriteScale;
  198. m_nStartBrightness = m_nDestBrightness = m_nBrightness;
  199. #endif
  200. #ifndef CLIENT_DLL
  201. // Server has no use for client-only entities.
  202. // Seems like a waste to create the entity, only to UTIL_Remove it on Spawn, but this pattern works safely...
  203. if ( FClassnameIs( this, "env_sprite_clientside" ) )
  204. {
  205. UTIL_Remove( this );
  206. }
  207. #endif // !CLIENT_DLL
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Purpose: Initialize absmin & absmax to the appropriate box
  211. //-----------------------------------------------------------------------------
  212. void CSprite::EnableWorldSpaceScale( bool bEnable )
  213. {
  214. m_bWorldSpaceScale = bEnable;
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Purpose: Initialize absmin & absmax to the appropriate box
  218. //-----------------------------------------------------------------------------
  219. void CSprite::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
  220. {
  221. float flScale = m_flSpriteScale * 0.5f;
  222. if ( m_bWorldSpaceScale == false )
  223. {
  224. // Find the height and width of the source of the sprite
  225. float width = modelinfo->GetModelSpriteWidth( GetModel() );
  226. float height = modelinfo->GetModelSpriteHeight( GetModel() );
  227. flScale *= MAX( width, height );
  228. }
  229. pVecWorldMins->Init( -flScale, -flScale, -flScale );
  230. pVecWorldMaxs->Init( flScale, flScale, flScale );
  231. *pVecWorldMins += GetAbsOrigin();
  232. *pVecWorldMaxs += GetAbsOrigin();
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose:
  236. // Input : *szModelName -
  237. //-----------------------------------------------------------------------------
  238. void CSprite::SetModel( const char *szModelName )
  239. {
  240. int index = modelinfo->GetModelIndex( szModelName );
  241. const model_t *model = modelinfo->GetModel( index );
  242. if ( model && modelinfo->GetModelType( model ) != mod_sprite )
  243. {
  244. Msg( "Setting CSprite to non-sprite model %s\n", szModelName?szModelName:"NULL" );
  245. }
  246. #if !defined( CLIENT_DLL )
  247. UTIL_SetModel( this, szModelName );
  248. #else
  249. BaseClass::SetModel( szModelName );
  250. #endif
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Purpose:
  254. //-----------------------------------------------------------------------------
  255. void CSprite::Precache( void )
  256. {
  257. if ( GetModelName() != NULL_STRING )
  258. {
  259. PrecacheModel( STRING( GetModelName() ) );
  260. }
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Purpose:
  264. // Input : *pSpriteName -
  265. // &origin -
  266. //-----------------------------------------------------------------------------
  267. void CSprite::SpriteInit( const char *pSpriteName, const Vector &origin )
  268. {
  269. SetModelName( MAKE_STRING(pSpriteName) );
  270. SetLocalOrigin( origin );
  271. Spawn();
  272. }
  273. #if !defined( CLIENT_DLL )
  274. int CSprite::UpdateTransmitState( void )
  275. {
  276. if ( GetMoveParent() )
  277. {
  278. // we must call ShouldTransmit() if we have a move parent
  279. return SetTransmitState( FL_EDICT_FULLCHECK );
  280. }
  281. else
  282. {
  283. return SetTransmitState( FL_EDICT_ALWAYS );
  284. }
  285. }
  286. int CSprite::ShouldTransmit( const CCheckTransmitInfo *pInfo )
  287. {
  288. // Certain entities like sprites and ropes are strewn throughout the level and they rarely change.
  289. // For these entities, it's more efficient to transmit them once and then always leave them on
  290. // the client. Otherwise, the server will have to send big bursts of data with the entity states
  291. // as they come in and out of the PVS.
  292. if ( GetMoveParent() )
  293. {
  294. CBaseViewModel *pViewModel = ToBaseViewModel( GetMoveParent() );
  295. if ( pViewModel )
  296. {
  297. return pViewModel->ShouldTransmit( pInfo );
  298. }
  299. }
  300. return FL_EDICT_ALWAYS;
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose: Fixup parent after restore
  304. //-----------------------------------------------------------------------------
  305. void CSprite::OnRestore()
  306. {
  307. BaseClass::OnRestore();
  308. // Reset attachment after save/restore
  309. if ( GetFollowedEntity() )
  310. {
  311. SetAttachment( GetFollowedEntity(), m_nAttachment );
  312. }
  313. else
  314. {
  315. // Clear attachment
  316. m_hAttachedToEntity = NULL;
  317. m_nAttachment = 0;
  318. }
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose:
  322. // Input : *pSpriteName -
  323. // &origin -
  324. // animate -
  325. // Output : CSprite
  326. //-----------------------------------------------------------------------------
  327. CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, bool animate )
  328. {
  329. CSprite *pSprite = CREATE_ENTITY( CSprite, "env_sprite" );
  330. pSprite->SpriteInit( pSpriteName, origin );
  331. pSprite->SetSolid( SOLID_NONE );
  332. UTIL_SetSize( pSprite, vec3_origin, vec3_origin );
  333. pSprite->SetMoveType( MOVETYPE_NONE );
  334. if ( animate )
  335. pSprite->TurnOn();
  336. return pSprite;
  337. }
  338. #endif
  339. //-----------------------------------------------------------------------------
  340. // Purpose:
  341. // Input : *pSpriteName -
  342. // &origin -
  343. // animate -
  344. // Output : CSprite
  345. //-----------------------------------------------------------------------------
  346. CSprite *CSprite::SpriteCreatePredictable( const char *module, int line, const char *pSpriteName, const Vector &origin, bool animate )
  347. {
  348. CSprite *pSprite = ( CSprite * )CBaseEntity::CreatePredictedEntityByName( "env_sprite", module, line );
  349. if ( pSprite )
  350. {
  351. pSprite->SpriteInit( pSpriteName, origin );
  352. pSprite->SetSolid( SOLID_NONE );
  353. pSprite->SetSize( vec3_origin, vec3_origin );
  354. pSprite->SetMoveType( MOVETYPE_NONE );
  355. if ( animate )
  356. pSprite->TurnOn();
  357. }
  358. return pSprite;
  359. }
  360. //-----------------------------------------------------------------------------
  361. // Purpose:
  362. //-----------------------------------------------------------------------------
  363. void CSprite::AnimateThink( void )
  364. {
  365. Animate( m_flSpriteFramerate * (gpGlobals->curtime - m_flLastTime) );
  366. SetNextThink( gpGlobals->curtime );
  367. m_flLastTime = gpGlobals->curtime;
  368. }
  369. //-----------------------------------------------------------------------------
  370. // Purpose:
  371. //-----------------------------------------------------------------------------
  372. void CSprite::AnimateUntilDead( void )
  373. {
  374. if ( gpGlobals->curtime > m_flDieTime )
  375. {
  376. Remove( );
  377. }
  378. else
  379. {
  380. AnimateThink();
  381. SetNextThink( gpGlobals->curtime );
  382. }
  383. }
  384. //-----------------------------------------------------------------------------
  385. // Purpose:
  386. // Input : scaleSpeed -
  387. // fadeSpeed -
  388. //-----------------------------------------------------------------------------
  389. void CSprite::Expand( float scaleSpeed, float fadeSpeed )
  390. {
  391. m_flSpeed = scaleSpeed;
  392. m_iHealth = fadeSpeed;
  393. SetThink( &CSprite::ExpandThink );
  394. SetNextThink( gpGlobals->curtime );
  395. m_flLastTime = gpGlobals->curtime;
  396. }
  397. //-----------------------------------------------------------------------------
  398. // Purpose:
  399. //-----------------------------------------------------------------------------
  400. void CSprite::ExpandThink( void )
  401. {
  402. float frametime = gpGlobals->curtime - m_flLastTime;
  403. SetSpriteScale( m_flSpriteScale + m_flSpeed * frametime );
  404. int sub = (int)(m_iHealth * frametime);
  405. if ( sub > GetRenderAlpha() )
  406. {
  407. SetRenderAlpha( 0 );
  408. Remove( );
  409. }
  410. else
  411. {
  412. SetRenderAlpha( GetRenderAlpha() - sub );
  413. SetNextThink( gpGlobals->curtime );
  414. m_flLastTime = gpGlobals->curtime;
  415. }
  416. }
  417. //-----------------------------------------------------------------------------
  418. // Purpose:
  419. // Input : frames -
  420. //-----------------------------------------------------------------------------
  421. void CSprite::Animate( float frames )
  422. {
  423. m_flFrame += frames;
  424. if ( m_flFrame > m_flMaxFrame )
  425. {
  426. #if !defined( CLIENT_DLL )
  427. if ( m_spawnflags & SF_SPRITE_ONCE )
  428. {
  429. TurnOff();
  430. }
  431. else
  432. #endif
  433. {
  434. if ( m_flMaxFrame > 0 )
  435. m_flFrame = fmod( m_flFrame, m_flMaxFrame );
  436. }
  437. }
  438. }
  439. //-----------------------------------------------------------------------------
  440. // Purpose:
  441. //-----------------------------------------------------------------------------
  442. void CSprite::SetBrightness( int brightness, float time )
  443. {
  444. m_nBrightness = brightness; //Take our current position as our starting position
  445. m_flBrightnessTime = time;
  446. }
  447. //-----------------------------------------------------------------------------
  448. // Purpose:
  449. //-----------------------------------------------------------------------------
  450. void CSprite::SetSpriteScale( float scale )
  451. {
  452. if ( scale != m_flSpriteScale )
  453. {
  454. m_flSpriteScale = scale; //Take our current position as our new starting position
  455. // The surrounding box is based on sprite scale... it changes, box is dirty
  456. CollisionProp()->MarkSurroundingBoundsDirty();
  457. }
  458. }
  459. void CSprite::SetScale( float scale, float time )
  460. {
  461. m_flScaleTime = time;
  462. SetSpriteScale( scale );
  463. // The surrounding box is based on sprite scale... it changes, box is dirty
  464. }
  465. //-----------------------------------------------------------------------------
  466. // Purpose:
  467. //-----------------------------------------------------------------------------
  468. void CSprite::TurnOff( void )
  469. {
  470. AddEffects( EF_NODRAW );
  471. SetNextThink( TICK_NEVER_THINK );
  472. }
  473. //-----------------------------------------------------------------------------
  474. // Purpose:
  475. //-----------------------------------------------------------------------------
  476. void CSprite::TurnOn( void )
  477. {
  478. RemoveEffects( EF_NODRAW );
  479. if ( (m_flSpriteFramerate && m_flMaxFrame > 1.0)
  480. #if !defined( CLIENT_DLL )
  481. || (m_spawnflags & SF_SPRITE_ONCE)
  482. #endif
  483. )
  484. {
  485. SetThink( &CSprite::AnimateThink );
  486. SetNextThink( gpGlobals->curtime );
  487. m_flLastTime = gpGlobals->curtime;
  488. }
  489. m_flFrame = 0;
  490. }
  491. #if !defined( CLIENT_DLL )
  492. // DVS TODO: Obsolete Use handler
  493. void CSprite::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  494. {
  495. int on = !IsEffectActive( EF_NODRAW );
  496. if ( ShouldToggle( useType, on ) )
  497. {
  498. if ( on )
  499. {
  500. TurnOff();
  501. }
  502. else
  503. {
  504. TurnOn();
  505. }
  506. }
  507. }
  508. //-----------------------------------------------------------------------------
  509. // Purpose: Input handler that hides the sprite.
  510. //-----------------------------------------------------------------------------
  511. void CSprite::InputHideSprite( inputdata_t &inputdata )
  512. {
  513. TurnOff();
  514. }
  515. //-----------------------------------------------------------------------------
  516. // Purpose: Input handler that hides the sprite.
  517. //-----------------------------------------------------------------------------
  518. void CSprite::InputShowSprite( inputdata_t &inputdata )
  519. {
  520. TurnOn();
  521. }
  522. void CSprite::InputColorRedValue( inputdata_t &inputdata )
  523. {
  524. int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
  525. SetColor( nNewColor, m_clrRender->g, m_clrRender->b );
  526. }
  527. void CSprite::InputColorGreenValue( inputdata_t &inputdata )
  528. {
  529. int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
  530. SetColor( m_clrRender->r, nNewColor, m_clrRender->b );
  531. }
  532. void CSprite::InputColorBlueValue( inputdata_t &inputdata )
  533. {
  534. int nNewColor = clamp( inputdata.value.Float(), 0, 255 );
  535. SetColor( m_clrRender->r, m_clrRender->g, nNewColor );
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Purpose: Input handler that toggles the sprite between hidden and shown.
  539. //-----------------------------------------------------------------------------
  540. void CSprite::InputToggleSprite( inputdata_t &inputdata )
  541. {
  542. if ( !IsEffectActive( EF_NODRAW ) )
  543. {
  544. TurnOff();
  545. }
  546. else
  547. {
  548. TurnOn();
  549. }
  550. }
  551. #endif
  552. #if defined( CLIENT_DLL )
  553. //-----------------------------------------------------------------------------
  554. // Purpose:
  555. // Output : float
  556. //-----------------------------------------------------------------------------
  557. float CSprite::GetRenderScale( void )
  558. {
  559. //See if we're done scaling
  560. if ( ( m_flScaleTime == 0 ) || ( (m_flScaleTimeStart+m_flScaleTime) < gpGlobals->curtime ) )
  561. return m_flSpriteScale;
  562. //Get our percentage
  563. float timeDelta = ( gpGlobals->curtime - m_flScaleTimeStart ) / m_flScaleTime;
  564. //Return the result
  565. return ( m_flStartScale + ( ( m_flDestScale - m_flStartScale ) * timeDelta ) );
  566. }
  567. float CSprite::GetMaxRenderScale( void )
  568. {
  569. //See if we're done scaling
  570. if ( m_flScaleTime == 0 )
  571. return m_flSpriteScale;
  572. // return the max scale over the interval
  573. return MAX(m_flStartScale, m_flDestScale);
  574. }
  575. //-----------------------------------------------------------------------------
  576. // Purpose: Get the rendered extents of the sprite
  577. //-----------------------------------------------------------------------------
  578. void CSprite::GetRenderBounds( Vector &vecMins, Vector &vecMaxs )
  579. {
  580. // NOTE: Don't call GetRenderScale here because the bounds will get cached
  581. // if we don't blow away that cache every time the interpolant (curtime) changes
  582. // then it will be wrong as long as this is animating.
  583. // instead while animating just use the
  584. float flScale = GetMaxRenderScale() * 0.5f;
  585. // If our scale is normalized we need to convert that to actual world units
  586. if ( m_bWorldSpaceScale == false )
  587. {
  588. CEngineSprite *psprite = (CEngineSprite *) modelinfo->GetModelExtraData( GetModel() );
  589. if ( psprite )
  590. {
  591. float flSize = MAX( psprite->GetWidth(), psprite->GetHeight() );
  592. flScale *= flSize;
  593. }
  594. }
  595. vecMins.Init( -flScale, -flScale, -flScale );
  596. vecMaxs.Init( flScale, flScale, flScale );
  597. #if 0
  598. // Visualize the bounds
  599. debugoverlay->AddBoxOverlay( GetRenderOrigin(), vecMins, vecMaxs, GetRenderAngles(), 255, 255, 255, 0, 0.01f );
  600. #endif
  601. }
  602. //-----------------------------------------------------------------------------
  603. // Purpose:
  604. //-----------------------------------------------------------------------------
  605. int CSprite::GetRenderBrightness( void )
  606. {
  607. //See if we're done scaling
  608. if ( ( m_flBrightnessTime == 0 ) || ( (m_flBrightnessTimeStart+m_flBrightnessTime) < gpGlobals->curtime ) )
  609. {
  610. return m_nBrightness;
  611. }
  612. //Get our percentage
  613. float timeDelta = ( gpGlobals->curtime - m_flBrightnessTimeStart ) / m_flBrightnessTime;
  614. float brightness = ( (float) m_nStartBrightness + ( (float) ( m_nDestBrightness - m_nStartBrightness ) * timeDelta ) );
  615. //Return the result
  616. return (int) brightness;
  617. }
  618. //-----------------------------------------------------------------------------
  619. // Purpose:
  620. //-----------------------------------------------------------------------------
  621. void CSprite::OnDataChanged( DataUpdateType_t updateType )
  622. {
  623. BaseClass::OnDataChanged( updateType );
  624. if ( updateType == DATA_UPDATE_CREATED )
  625. {
  626. m_flStartScale = m_flDestScale = m_flSpriteScale;
  627. m_nStartBrightness = m_nDestBrightness = m_nBrightness;
  628. }
  629. UpdateVisibility();
  630. if ( m_flSpriteScale != m_flDestScale || m_nBrightness != m_nDestBrightness )
  631. {
  632. SetNextClientThink( CLIENT_THINK_ALWAYS );
  633. }
  634. else
  635. {
  636. SetNextClientThink( CLIENT_THINK_NEVER );
  637. }
  638. }
  639. void CSprite::ClientThink( void )
  640. {
  641. bool bDisableThink = true;
  642. // Module render colors over time
  643. if ( m_flSpriteScale != m_flDestScale )
  644. {
  645. m_flStartScale = m_flDestScale;
  646. m_flDestScale = m_flSpriteScale;
  647. m_flScaleTimeStart = gpGlobals->curtime;
  648. bDisableThink = false;
  649. }
  650. if ( m_nBrightness != m_nDestBrightness )
  651. {
  652. m_nStartBrightness = m_nDestBrightness;
  653. m_nDestBrightness = m_nBrightness;
  654. m_flBrightnessTimeStart = gpGlobals->curtime;
  655. bDisableThink = false;
  656. }
  657. // changed bounds
  658. InvalidatePhysicsRecursive(BOUNDS_CHANGED);
  659. if ( bDisableThink )
  660. {
  661. SetNextClientThink(CLIENT_THINK_NEVER);
  662. }
  663. }
  664. extern bool g_bRenderingScreenshot;
  665. extern ConVar r_drawviewmodel;
  666. //-----------------------------------------------------------------------------
  667. // Purpose:
  668. // Input : flags -
  669. // Output : int
  670. //-----------------------------------------------------------------------------
  671. int CSprite::DrawModel( int flags, const RenderableInstance_t &instance )
  672. {
  673. VPROF_BUDGET( "CSprite::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  674. //See if we should draw
  675. if ( !IsVisible() || ( m_bReadyToDraw == false ) )
  676. return 0;
  677. // Tracker 16432: If rendering a savegame screenshot then don't draw sprites
  678. // who have viewmodels as their moveparent
  679. if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() )
  680. {
  681. C_BaseViewModel *vm = ToBaseViewModel( GetMoveParent() );
  682. if ( vm )
  683. {
  684. return 0;
  685. }
  686. }
  687. //Must be a sprite
  688. if ( modelinfo->GetModelType( GetModel() ) != mod_sprite )
  689. {
  690. const char *modelName = modelinfo->GetModelName( GetModel() );
  691. char msg[256];
  692. V_snprintf( msg, 256, "Sprite %d has non-mod_sprite model %s (type %d)\n",
  693. entindex(), modelName, modelinfo->GetModelType( GetModel() ) );
  694. AssertMsgOnce( 0, msg );
  695. return 0;
  696. }
  697. float renderscale = GetRenderScale();
  698. if ( m_bWorldSpaceScale )
  699. {
  700. CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() );
  701. float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() );
  702. renderscale /= flMinSize;
  703. }
  704. //Draw it
  705. int drawn = DrawSprite(
  706. this,
  707. GetModel(),
  708. GetAbsOrigin(),
  709. GetAbsAngles(),
  710. m_flFrame, // sprite frame to render
  711. m_hAttachedToEntity, // attach to
  712. m_nAttachment, // attachment point
  713. GetRenderMode(), // rendermode
  714. GetRenderFX(),
  715. (float)( GetRenderBrightness() * instance.m_nAlpha ) * ( 1.0f / 255.0f ) + 0.5f, // alpha
  716. GetRenderColorR(),
  717. GetRenderColorG(),
  718. GetRenderColorB(),
  719. renderscale, // sprite scale
  720. GetHDRColorScale() // HDR Color Scale
  721. );
  722. return drawn;
  723. }
  724. const Vector& CSprite::GetRenderOrigin()
  725. {
  726. static Vector vOrigin;
  727. vOrigin = GetAbsOrigin();
  728. if ( m_hAttachedToEntity )
  729. {
  730. C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity();
  731. if ( ent )
  732. {
  733. QAngle dummyAngles;
  734. ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles );
  735. }
  736. }
  737. return vOrigin;
  738. }
  739. #endif
  740. //-----------------------------------------------------------------------------
  741. // Purpose: oriented sprites
  742. // CSprites swap the roll and yaw angle inputs, and rotate the yaw 180 degrees
  743. //-----------------------------------------------------------------------------
  744. #if !defined( CLIENT_DLL )
  745. IMPLEMENT_SERVERCLASS_ST( CSpriteOriented, DT_SpriteOriented )
  746. END_SEND_TABLE()
  747. #else
  748. #undef CSpriteOriented
  749. IMPLEMENT_CLIENTCLASS_DT(C_SpriteOriented, DT_SpriteOriented, CSpriteOriented)
  750. #define CSpriteOriented C_SpriteOriented
  751. END_RECV_TABLE()
  752. #endif
  753. LINK_ENTITY_TO_CLASS_ALIASED( env_sprite_oriented, SpriteOriented );
  754. #if !defined( CLIENT_DLL )
  755. void CSpriteOriented::Spawn( void )
  756. {
  757. // save a copy of the angles, CSprite swaps the yaw and roll
  758. QAngle angles = GetAbsAngles();
  759. BaseClass::Spawn();
  760. // ORIENTED sprites "forward" vector points in the players "view" direction, not the direction "out" from the sprite (gah)
  761. angles.y = anglemod( angles.y + 180 );
  762. SetAbsAngles( angles );
  763. }
  764. #else
  765. RenderableTranslucencyType_t CSpriteOriented::ComputeTranslucencyType()
  766. {
  767. return RENDERABLE_IS_TRANSLUCENT;
  768. }
  769. #endif