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.

355 lines
9.4 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "cbase.h"
  7. #include "dlight.h"
  8. #include "iefx.h"
  9. #include "beam_shared.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. //-----------------------------------------------------------------------------
  13. // Purpose:
  14. //-----------------------------------------------------------------------------
  15. class CSpotlightTraceCacheEntry
  16. {
  17. public:
  18. CSpotlightTraceCacheEntry()
  19. {
  20. m_origin.Init();
  21. m_radius = -1.0f;
  22. }
  23. bool IsValidFor( const Vector &origin )
  24. {
  25. if ( m_radius > 0 && m_origin.DistToSqr(origin) < 1.0f )
  26. return true;
  27. return false;
  28. }
  29. void Cache( const Vector &origin, const trace_t &tr )
  30. {
  31. m_radius = (tr.endpos - origin).Length();
  32. m_origin = origin;
  33. }
  34. Vector m_origin;
  35. float m_radius;
  36. };
  37. static const int NUM_CACHE_ENTRIES = 64;
  38. class C_BeamSpotLight : public C_BaseEntity
  39. {
  40. public:
  41. DECLARE_CLASS( C_BeamSpotLight, C_BaseEntity );
  42. DECLARE_CLIENTCLASS();
  43. C_BeamSpotLight();
  44. ~C_BeamSpotLight();
  45. bool ShouldDraw();
  46. void ClientThink( void );
  47. void OnDataChanged( DataUpdateType_t updateType );
  48. void Release( void );
  49. private:
  50. Vector SpotlightCurrentPos(void);
  51. void SpotlightCreate(void);
  52. void SpotlightDestroy(void);
  53. // Computes render info for a spotlight
  54. void ComputeRenderInfo();
  55. private:
  56. int m_nHaloIndex;
  57. int m_nRotationAxis;
  58. float m_flRotationSpeed;
  59. bool m_bSpotlightOn;
  60. bool m_bHasDynamicLight;
  61. float m_flSpotlightMaxLength;
  62. float m_flSpotlightGoalWidth;
  63. float m_flHDRColorScale;
  64. Vector m_vSpotlightTargetPos;
  65. Vector m_vSpotlightCurrentPos;
  66. Vector m_vSpotlightDir;
  67. CHandle<C_Beam> m_hSpotlight;
  68. float m_flSpotlightCurLength;
  69. float m_flLightScale;
  70. dlight_t* m_pDynamicLight;
  71. float m_lastTime;
  72. CSpotlightTraceCacheEntry *m_pCache;
  73. };
  74. IMPLEMENT_CLIENTCLASS_DT( C_BeamSpotLight, DT_BeamSpotlight, CBeamSpotlight )
  75. RecvPropInt( RECVINFO(m_nHaloIndex) ),
  76. RecvPropBool( RECVINFO(m_bSpotlightOn) ),
  77. RecvPropBool( RECVINFO(m_bHasDynamicLight) ),
  78. RecvPropFloat( RECVINFO(m_flSpotlightMaxLength) ),
  79. RecvPropFloat( RECVINFO(m_flSpotlightGoalWidth) ),
  80. RecvPropFloat( RECVINFO(m_flHDRColorScale) ),
  81. RecvPropInt( RECVINFO(m_nRotationAxis) ),
  82. RecvPropFloat( RECVINFO(m_flRotationSpeed) ),
  83. END_RECV_TABLE()
  84. LINK_ENTITY_TO_CLASS( beam_spotlight, C_BeamSpotLight );
  85. //-----------------------------------------------------------------------------
  86. C_BeamSpotLight::C_BeamSpotLight()
  87. : m_vSpotlightTargetPos( vec3_origin )
  88. , m_vSpotlightCurrentPos( vec3_origin )
  89. , m_vSpotlightDir( vec3_origin )
  90. , m_flSpotlightCurLength( 0.0f )
  91. , m_flLightScale( 100.0f )
  92. , m_pDynamicLight( NULL )
  93. , m_lastTime( 0.0f )
  94. , m_pCache(NULL)
  95. {
  96. }
  97. C_BeamSpotLight::~C_BeamSpotLight()
  98. {
  99. delete[] m_pCache;
  100. }
  101. //-----------------------------------------------------------------------------
  102. bool C_BeamSpotLight::ShouldDraw()
  103. {
  104. return false;
  105. }
  106. //-----------------------------------------------------------------------------
  107. void C_BeamSpotLight::ClientThink( void )
  108. {
  109. float dt = gpGlobals->curtime - m_lastTime;
  110. if ( !m_lastTime )
  111. {
  112. dt = 0.0f;
  113. }
  114. m_lastTime = gpGlobals->curtime;
  115. // ---------------------------------------------------
  116. // If I don't have a spotlight attempt to create one
  117. // ---------------------------------------------------
  118. if ( !m_hSpotlight )
  119. {
  120. if ( m_bSpotlightOn )
  121. {
  122. // Make the spotlight
  123. SpotlightCreate();
  124. }
  125. else
  126. {
  127. SetNextClientThink( CLIENT_THINK_NEVER );
  128. return;
  129. }
  130. }
  131. else if ( !m_bSpotlightOn )
  132. {
  133. SpotlightDestroy();
  134. SetNextClientThink( CLIENT_THINK_NEVER );
  135. return;
  136. }
  137. // update rotation
  138. if ( m_flRotationSpeed != 0.0f )
  139. {
  140. QAngle angles = GetAbsAngles();
  141. angles[m_nRotationAxis] += m_flRotationSpeed * dt;
  142. angles[m_nRotationAxis] = anglemod(angles[m_nRotationAxis]);
  143. if ( !m_pCache )
  144. {
  145. m_pCache = new CSpotlightTraceCacheEntry[NUM_CACHE_ENTRIES];
  146. }
  147. SetAbsAngles( angles );
  148. }
  149. m_vSpotlightCurrentPos = SpotlightCurrentPos();
  150. Assert( m_hSpotlight );
  151. m_hSpotlight->SetStartPos( GetAbsOrigin() );
  152. m_hSpotlight->SetEndPos( m_vSpotlightCurrentPos );
  153. // Avoid sudden change in where beam fades out when cross disconinuities
  154. Vector dir = m_vSpotlightCurrentPos - GetAbsOrigin();
  155. float flBeamLength = VectorNormalize( dir );
  156. m_flSpotlightCurLength = (0.60*m_flSpotlightCurLength) + (0.4*flBeamLength);
  157. ComputeRenderInfo();
  158. m_hSpotlight->RelinkBeam();
  159. //NDebugOverlay::Cross3D(GetAbsOrigin(),Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
  160. //NDebugOverlay::Cross3D(m_vSpotlightCurrentPos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
  161. //NDebugOverlay::Cross3D(m_vSpotlightTargetPos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1);
  162. // Do we need to keep updating?
  163. if ( !GetMoveParent() && m_flRotationSpeed == 0 )
  164. {
  165. // No reason to think again, we're not going to move unless there's a data change
  166. SetNextClientThink( CLIENT_THINK_NEVER );
  167. }
  168. }
  169. //-----------------------------------------------------------------------------
  170. void C_BeamSpotLight::OnDataChanged( DataUpdateType_t updateType )
  171. {
  172. BaseClass::OnDataChanged( updateType );
  173. if ( updateType == DATA_UPDATE_CREATED )
  174. {
  175. m_flSpotlightCurLength = m_flSpotlightMaxLength;
  176. }
  177. // On a data change always think again
  178. SetNextClientThink( CLIENT_THINK_ALWAYS );
  179. }
  180. //------------------------------------------------------------------------------
  181. void C_BeamSpotLight::Release()
  182. {
  183. SpotlightDestroy();
  184. BaseClass::Release();
  185. }
  186. //------------------------------------------------------------------------------
  187. void C_BeamSpotLight::SpotlightCreate(void)
  188. {
  189. m_vSpotlightTargetPos = SpotlightCurrentPos();
  190. {
  191. //C_Beam *beam = CBeam::BeamCreate( "sprites/spotlight.vmt", m_flSpotlightGoalWidth );
  192. C_Beam *beam = C_Beam::BeamCreate( "sprites/glow_test02.vmt", m_flSpotlightGoalWidth );
  193. // Beam only exists client side
  194. ClientEntityList().AddNonNetworkableEntity( beam );
  195. m_hSpotlight = beam;
  196. }
  197. // Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore)
  198. m_hSpotlight->SetHDRColorScale( m_flHDRColorScale );
  199. const color24 c = GetRenderColor();
  200. m_hSpotlight->SetColor( c.r, c.g, c.b );
  201. m_hSpotlight->SetHaloTexture(m_nHaloIndex);
  202. m_hSpotlight->SetHaloScale(60);
  203. m_hSpotlight->SetEndWidth(m_flSpotlightGoalWidth);
  204. m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) );
  205. m_hSpotlight->SetBrightness( 64 );
  206. m_hSpotlight->SetNoise( 0 );
  207. m_hSpotlight->PointsInit( GetAbsOrigin(), m_vSpotlightTargetPos );
  208. }
  209. //------------------------------------------------------------------------------
  210. void C_BeamSpotLight::SpotlightDestroy(void)
  211. {
  212. if ( m_hSpotlight )
  213. {
  214. UTIL_Remove( m_hSpotlight );
  215. m_hSpotlight.Term();
  216. }
  217. }
  218. //------------------------------------------------------------------------------
  219. Vector C_BeamSpotLight::SpotlightCurrentPos(void)
  220. {
  221. QAngle angles = GetAbsAngles();
  222. GetVectors( &m_vSpotlightDir, NULL, NULL );
  223. Vector position = GetAbsOrigin();
  224. int cacheIndex = -1;
  225. if ( m_pCache )
  226. {
  227. cacheIndex = int( angles[m_nRotationAxis] * float(NUM_CACHE_ENTRIES) * (1.0f / 360.0f)) & (NUM_CACHE_ENTRIES - 1);
  228. if ( m_pCache[cacheIndex].IsValidFor(GetAbsOrigin()) )
  229. {
  230. return position + m_vSpotlightDir * m_pCache[cacheIndex].m_radius;
  231. }
  232. }
  233. // Get beam end point. Only collide with solid objects, not npcs
  234. trace_t tr;
  235. UTIL_TraceLine( position, position + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
  236. if ( cacheIndex >= 0 )
  237. {
  238. m_pCache[cacheIndex].Cache(position, tr);
  239. }
  240. return tr.endpos;
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Computes render info for a spotlight
  244. //-----------------------------------------------------------------------------
  245. void C_BeamSpotLight::ComputeRenderInfo()
  246. {
  247. // Fade out spotlight end if past max length.
  248. if ( m_flSpotlightCurLength > 2*m_flSpotlightMaxLength )
  249. {
  250. SetRenderAlpha( 0 );
  251. m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
  252. }
  253. else if ( m_flSpotlightCurLength > m_flSpotlightMaxLength )
  254. {
  255. SetRenderAlpha( (1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength)) );
  256. m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
  257. }
  258. else
  259. {
  260. SetRenderAlpha( 1.0 );
  261. m_hSpotlight->SetFadeLength( m_flSpotlightCurLength );
  262. }
  263. // Adjust end width to keep beam width constant
  264. float flNewWidth = m_flSpotlightGoalWidth * (m_flSpotlightCurLength / m_flSpotlightMaxLength);
  265. flNewWidth = clamp(flNewWidth, 0, MAX_BEAM_WIDTH );
  266. m_hSpotlight->SetEndWidth(flNewWidth);
  267. if ( m_bHasDynamicLight )
  268. {
  269. // <<TODO>> - magic number 1.8 depends on sprite size
  270. m_flLightScale = 1.8*flNewWidth;
  271. if ( m_flLightScale > 0 )
  272. {
  273. const color24 c = GetRenderColor();
  274. float a = GetRenderAlpha() / 255.0f;
  275. ColorRGBExp32 color;
  276. color.r = c.r * a;
  277. color.g = c.g * a;
  278. color.b = c.b * a;
  279. color.exponent = 0;
  280. if ( color.r == 0 && color.g == 0 && color.b == 0 )
  281. return;
  282. // Deal with the environment light
  283. if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
  284. {
  285. m_pDynamicLight = effects->CL_AllocDlight( index );
  286. assert (m_pDynamicLight);
  287. }
  288. //m_pDynamicLight->flags = DLIGHT_NO_MODEL_ILLUMINATION;
  289. m_pDynamicLight->radius = m_flLightScale*3.0f;
  290. m_pDynamicLight->origin = GetAbsOrigin() + Vector(0,0,5);
  291. m_pDynamicLight->die = gpGlobals->curtime + 0.05f;
  292. m_pDynamicLight->color = color;
  293. }
  294. }
  295. }