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.

213 lines
5.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Game-specific impact effect hooks
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "c_te_effect_dispatch.h"
  8. #include "tempent.h"
  9. #include "c_te_legacytempents.h"
  10. #include "tf_shareddefs.h"
  11. #include "c_rope.h"
  12. // NOTE: Always include this last!
  13. #include "tier0/memdbgon.h"
  14. // Used for cycling so that they're sequencially ordered on each strand
  15. int g_nHolidayLightColor = 0;
  16. // 4 light colors
  17. Color g_rgbaHolidayRed( 255, 0, 0, 255 );
  18. Color g_rgbaHolidayYellow( 2, 110, 197, 255 );
  19. Color g_rgbaHolidayGreen( 117, 193, 8, 255 );
  20. Color g_rgbaHolidayBlue( 255, 151, 29, 255 );
  21. Color *(rgbaHolidayLightColors[]) = { &g_rgbaHolidayRed,
  22. &g_rgbaHolidayYellow,
  23. &g_rgbaHolidayGreen,
  24. &g_rgbaHolidayBlue };
  25. struct HolidayLightData_t
  26. {
  27. Vector vOrigin;
  28. int nID;
  29. int nSubID;
  30. float fScale;
  31. };
  32. void CreateHolidayLight( const HolidayLightData_t &holidayLight );
  33. class CHolidayLightManager : public CAutoGameSystemPerFrame
  34. {
  35. public:
  36. CHolidayLightManager( char const *name );
  37. // Methods of IGameSystem
  38. virtual void Update( float frametime );
  39. virtual void LevelInitPostEntity( void );
  40. virtual void LevelShutdownPreEntity();
  41. void AddHolidayLight( const CEffectData &data );
  42. private:
  43. CUtlVector< HolidayLightData_t > m_PendingLightData;
  44. };
  45. CHolidayLightManager g_CHolidayLightManager( "CHolidayLightManager" );
  46. CHolidayLightManager::CHolidayLightManager( char const *name ) : CAutoGameSystemPerFrame( name )
  47. {
  48. }
  49. // Methods of IGameSystem
  50. void CHolidayLightManager::Update( float frametime )
  51. {
  52. for ( int i = 0; i < m_PendingLightData.Count(); ++i )
  53. {
  54. CreateHolidayLight( m_PendingLightData[ i ] );
  55. }
  56. m_PendingLightData.RemoveAll();
  57. }
  58. void CHolidayLightManager::LevelInitPostEntity( void )
  59. {
  60. m_PendingLightData.RemoveAll();
  61. }
  62. void CHolidayLightManager::LevelShutdownPreEntity()
  63. {
  64. m_PendingLightData.RemoveAll();
  65. }
  66. void CHolidayLightManager::AddHolidayLight( const CEffectData &data )
  67. {
  68. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  69. if ( !pPlayer )
  70. return;
  71. // Too far away?
  72. if ( pPlayer->GetAbsOrigin().DistTo( data.m_vOrigin ) > 2000.0f )
  73. return;
  74. // In the skybox?
  75. sky3dparams_t *pSky = &(pPlayer->m_Local.m_skybox3d);
  76. if ( pSky->origin->DistTo( data.m_vOrigin ) < 2000.0f )
  77. return;
  78. HolidayLightData_t newData;
  79. newData.vOrigin = data.m_vOrigin;
  80. // HACK: Use these ints to ID the light later
  81. newData.nID = data.m_nMaterial;
  82. newData.nSubID = data.m_nHitBox;
  83. // Skybox lights pass in a smaller scale
  84. newData.fScale = data.m_flScale;
  85. if ( m_PendingLightData.Count() < CTempEnts::MAX_TEMP_ENTITIES / 2 )
  86. {
  87. m_PendingLightData.AddToTail( newData );
  88. }
  89. }
  90. void TF_HolidayLightCallback( const CEffectData &data )
  91. {
  92. g_CHolidayLightManager.AddHolidayLight( data );
  93. }
  94. void CreateHolidayLight( const HolidayLightData_t &holidayLight )
  95. {
  96. int nHolidayLightStyle = RopeManager()->GetHolidayLightStyle();
  97. const model_t *pModel = ( nHolidayLightStyle == 0 ? engine->LoadModel( "effects/christmas_bulb.vmt" ) : engine->LoadModel( "effects/mtp_fluff.vmt" ) );
  98. if ( !pModel )
  99. return;
  100. Assert( pModel );
  101. C_LocalTempEntity *pTemp = tempents->FindTempEntByID( holidayLight.nID, holidayLight.nSubID );
  102. if ( !pTemp )
  103. {
  104. // Didn't find one with that ID, so make a new one!
  105. // Randomize the angle
  106. QAngle angOrientation = ( nHolidayLightStyle == 0 ? QAngle( 0.0f, 0.0f, RandomFloat( -180.0f, 180.0f ) ) : vec3_angle );
  107. pTemp = tempents->SpawnTempModel( pModel, holidayLight.vOrigin, angOrientation, vec3_origin, 2.0f, FTENT_NEVERDIE );
  108. if ( !pTemp )
  109. {
  110. return;
  111. }
  112. pTemp->clientIndex = 0;
  113. // HACK: Use these ints to ID the light later
  114. pTemp->m_nSkin = holidayLight.nID;
  115. pTemp->hitSound = holidayLight.nSubID;
  116. // Skybox lights pass in a smaller scale
  117. pTemp->m_flSpriteScale = holidayLight.fScale;
  118. // Smuggle the color index here
  119. pTemp->m_nHitboxSet = g_nHolidayLightColor;
  120. // Set the color
  121. pTemp->SetRenderColor( rgbaHolidayLightColors[ g_nHolidayLightColor ]->r(),
  122. rgbaHolidayLightColors[ g_nHolidayLightColor ]->g(),
  123. rgbaHolidayLightColors[ g_nHolidayLightColor ]->b(),
  124. rgbaHolidayLightColors[ g_nHolidayLightColor ]->a() );
  125. // Next color in the pattern
  126. g_nHolidayLightColor = ( g_nHolidayLightColor + 1 ) % ARRAYSIZE( rgbaHolidayLightColors );
  127. // Animate if needed
  128. pTemp->m_flFrameMax = modelinfo->GetModelFrameCount( pModel ) - 1;
  129. pTemp->flags = ( FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP );
  130. pTemp->m_flFrameRate = 10;
  131. }
  132. else
  133. {
  134. // Update the position
  135. pTemp->SetAbsOrigin( holidayLight.vOrigin );
  136. // Every 10 light strands have a blink cycle
  137. if ( pTemp->m_nSkin % 5 == 0 )
  138. {
  139. // Magic! Basically this makes the on/off cycle of each color different and offsets it by the segment index.
  140. // That way it looks like a timed pattern but is also chaotic.
  141. int nCycle = ( pTemp->hitSound + static_cast< int >( gpGlobals->curtime * 2.0f ) ) % ( pTemp->m_nHitboxSet + ARRAYSIZE( rgbaHolidayLightColors ) + 1 );
  142. pTemp->SetRenderColorA( nCycle < ARRAYSIZE( rgbaHolidayLightColors ) ? 255 : 64 );
  143. }
  144. // Update the scale
  145. pTemp->m_flSpriteScale = holidayLight.fScale;
  146. // Extend it's life
  147. pTemp->die = gpGlobals->curtime + 2.0f;
  148. }
  149. }
  150. DECLARE_CLIENT_EFFECT( "TF_HolidayLight", TF_HolidayLightCallback );
  151. void RopesHolidayLightColor( const CCommand &args )
  152. {
  153. if ( args.ArgC() < 5 )
  154. return;
  155. int nLight = atoi( args[ 1 ] );
  156. if ( nLight < 0 || nLight >= ARRAYSIZE( rgbaHolidayLightColors ) )
  157. return;
  158. rgbaHolidayLightColors[ nLight ]->SetColor( atoi( args[ 2 ] ), atoi( args[ 3 ] ), atoi( args[ 4 ] ) );
  159. }
  160. ConCommand r_ropes_holiday_light_color( "r_ropes_holiday_light_color", RopesHolidayLightColor, "Set each light's color: [light0-3] [r0-255] [g0-255] [b0-255]", FCVAR_NONE );