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.

1201 lines
32 KiB

  1. //========= Copyright 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 "beam_shared.h"
  9. #include "decals.h"
  10. #include "model_types.h"
  11. #include "IEffects.h"
  12. #include "util_shared.h"
  13. #if !defined( CLIENT_DLL )
  14. #include "ndebugoverlay.h"
  15. #include "sendproxy.h"
  16. #else
  17. #include "iviewrender_beams.h"
  18. #include "c_pixel_visibility.h"
  19. #include "iclientmode.h"
  20. #include "viewrender.h"
  21. #include "view.h"
  22. #ifdef PORTAL
  23. #include "c_prop_portal.h"
  24. #endif //ifdef PORTAL
  25. #endif
  26. // memdbgon must be the last include file in a .cpp file!!!
  27. #include "tier0/memdbgon.h"
  28. #define BEAM_DEFAULT_HALO_SCALE 10
  29. #if !defined( CLIENT_DLL )
  30. // Lightning target, just alias landmark
  31. class CInfoTarget : public CPointEntity
  32. {
  33. public:
  34. DECLARE_CLASS( CInfoTarget, CPointEntity );
  35. void Spawn( void );
  36. };
  37. //info targets are like point entities except you can force them to spawn on the client
  38. void CInfoTarget::Spawn( void )
  39. {
  40. BaseClass::Spawn();
  41. if ( HasSpawnFlags(0x01) )
  42. {
  43. SetEFlags( EFL_FORCE_CHECK_TRANSMIT );
  44. }
  45. }
  46. LINK_ENTITY_TO_CLASS( info_target, CInfoTarget );
  47. #endif
  48. //-----------------------------------------------------------------------------
  49. // Purpose: Returns true if the given entity is a fixed target for lightning.
  50. //-----------------------------------------------------------------------------
  51. bool IsStaticPointEntity( CBaseEntity *pEnt )
  52. {
  53. if ( pEnt->GetMoveParent() )
  54. return false;
  55. if ( !pEnt->GetModelIndex() )
  56. return 1;
  57. if ( FClassnameIs( pEnt, "info_target" ) || FClassnameIs( pEnt, "info_landmark" ) ||
  58. FClassnameIs( pEnt, "path_corner" ) )
  59. return true;
  60. return false;
  61. }
  62. #if defined( CLIENT_DLL )
  63. extern bool ComputeBeamEntPosition( CBaseEntity *pEnt, int nAttachment, bool bInterpretAttachmentIndexAsHitboxIndex, Vector& pt );
  64. void RecvProxy_Beam_ScrollSpeed( const CRecvProxyData *pData, void *pStruct, void *pOut )
  65. {
  66. C_Beam *beam;
  67. float val;
  68. // Unpack the data.
  69. val = pData->m_Value.m_Float;
  70. val *= 0.1;
  71. beam = ( C_Beam * )pStruct;
  72. Assert( pOut == &beam->m_fSpeed );
  73. beam->m_fSpeed = val;
  74. }
  75. #else
  76. #if !defined( NO_ENTITY_PREDICTION )
  77. static void* SendProxy_SendPredictableId( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID )
  78. {
  79. CBaseEntity *pEntity = (CBaseEntity *)pStruct;
  80. if ( !pEntity || !pEntity->m_PredictableID->IsActive() )
  81. return NULL;
  82. if ( !pEntity->GetOwnerEntity() )
  83. return NULL;
  84. CBaseEntity *owner = pEntity->GetOwnerEntity();
  85. if ( !owner || !owner->IsPlayer() )
  86. return NULL;
  87. CBasePlayer *pOwner = static_cast< CBasePlayer * >( owner );
  88. if ( !pOwner )
  89. return NULL;
  90. int id_player_index = pEntity->m_PredictableID->GetPlayer();
  91. int owner_player_index = pOwner->entindex() - 1;
  92. // Only send to owner player
  93. // FIXME: Is this ever not the case due to the SetOnly call?
  94. if ( id_player_index != owner_player_index )
  95. return NULL;
  96. pRecipients->SetOnly( owner_player_index );
  97. return ( void * )pVarData;
  98. }
  99. REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendPredictableId );
  100. #endif
  101. #endif
  102. LINK_ENTITY_TO_CLASS( beam, CBeam );
  103. // This table encodes the CBeam data.
  104. IMPLEMENT_NETWORKCLASS_ALIASED( Beam, DT_Beam )
  105. #if !defined( NO_ENTITY_PREDICTION )
  106. BEGIN_NETWORK_TABLE_NOBASE( CBeam, DT_BeamPredictableId )
  107. #if !defined( CLIENT_DLL )
  108. SendPropPredictableId( SENDINFO( m_PredictableID ) ),
  109. SendPropInt( SENDINFO( m_bIsPlayerSimulated ), 1, SPROP_UNSIGNED ),
  110. #else
  111. RecvPropPredictableId( RECVINFO( m_PredictableID ) ),
  112. RecvPropInt( RECVINFO( m_bIsPlayerSimulated ) ),
  113. #endif
  114. END_NETWORK_TABLE()
  115. #endif
  116. BEGIN_NETWORK_TABLE_NOBASE( CBeam, DT_Beam )
  117. #if !defined( CLIENT_DLL )
  118. SendPropInt (SENDINFO(m_nBeamType), Q_log2(NUM_BEAM_TYPES)+1, SPROP_UNSIGNED ),
  119. SendPropInt (SENDINFO(m_nBeamFlags), NUM_BEAM_FLAGS, SPROP_UNSIGNED ),
  120. SendPropInt (SENDINFO(m_nNumBeamEnts ), 5, SPROP_UNSIGNED ),
  121. SendPropArray3
  122. (
  123. SENDINFO_ARRAY3(m_hAttachEntity),
  124. SendPropEHandle( SENDINFO_ARRAY(m_hAttachEntity) )
  125. ),
  126. SendPropArray3
  127. (
  128. SENDINFO_ARRAY3(m_nAttachIndex),
  129. SendPropInt( SENDINFO_ARRAY(m_nAttachIndex), ATTACHMENT_INDEX_BITS, SPROP_UNSIGNED)
  130. ),
  131. SendPropInt (SENDINFO(m_nHaloIndex), 16, SPROP_UNSIGNED ),
  132. SendPropFloat (SENDINFO(m_fHaloScale), 0, SPROP_NOSCALE ),
  133. SendPropFloat (SENDINFO(m_fWidth), 10, SPROP_ROUNDUP, 0.0f, MAX_BEAM_WIDTH ),
  134. SendPropFloat (SENDINFO(m_fEndWidth), 10, SPROP_ROUNDUP, 0.0f, MAX_BEAM_WIDTH ),
  135. SendPropFloat (SENDINFO(m_fFadeLength), 0, SPROP_NOSCALE ),
  136. SendPropFloat (SENDINFO(m_fAmplitude), 8, SPROP_ROUNDDOWN, 0.0f, MAX_BEAM_NOISEAMPLITUDE ),
  137. SendPropFloat (SENDINFO(m_fStartFrame), 8, SPROP_ROUNDDOWN, 0.0f, 256.0f),
  138. SendPropFloat (SENDINFO(m_fSpeed), 8, SPROP_NOSCALE, 0.0f, MAX_BEAM_SCROLLSPEED),
  139. SendPropInt (SENDINFO(m_nRenderFX), 8, SPROP_UNSIGNED ),
  140. SendPropInt (SENDINFO(m_nRenderMode), 8, SPROP_UNSIGNED ),
  141. SendPropFloat (SENDINFO(m_flFrameRate), 10, SPROP_ROUNDUP, -25.0f, 25.0f ),
  142. SendPropFloat (SENDINFO(m_flHDRColorScale), 0, SPROP_NOSCALE, 0.0f, 100.0f ),
  143. SendPropFloat (SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN | SPROP_CHANGES_OFTEN, 0.0f, 256.0f),
  144. SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED | SPROP_CHANGES_OFTEN ),
  145. SendPropVector (SENDINFO(m_vecEndPos), -1, SPROP_COORD ),
  146. #ifdef PORTAL
  147. SendPropBool (SENDINFO(m_bDrawInMainRender) ),
  148. SendPropBool (SENDINFO(m_bDrawInPortalRender) ),
  149. #endif
  150. SendPropModelIndex(SENDINFO(m_nModelIndex) ),
  151. SendPropVector (SENDINFO(m_vecOrigin), 19, SPROP_CHANGES_OFTEN, MIN_COORD_INTEGER, MAX_COORD_INTEGER),
  152. SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent) ),
  153. SendPropInt (SENDINFO(m_nMinDXLevel), 8, SPROP_UNSIGNED ),
  154. #if !defined( NO_ENTITY_PREDICTION )
  155. SendPropDataTable( "beampredictable_id", 0, &REFERENCE_SEND_TABLE( DT_BeamPredictableId ), SendProxy_SendPredictableId ),
  156. #endif
  157. #else
  158. RecvPropInt (RECVINFO(m_nBeamType)),
  159. RecvPropInt (RECVINFO(m_nBeamFlags)),
  160. RecvPropInt (RECVINFO(m_nNumBeamEnts)),
  161. RecvPropArray3
  162. (
  163. RECVINFO_ARRAY( m_hAttachEntity ),
  164. RecvPropEHandle (RECVINFO(m_hAttachEntity[0]))
  165. ),
  166. RecvPropArray3
  167. (
  168. RECVINFO_ARRAY( m_nAttachIndex ),
  169. RecvPropInt (RECVINFO(m_nAttachIndex[0]))
  170. ),
  171. RecvPropInt (RECVINFO(m_nHaloIndex)),
  172. RecvPropFloat (RECVINFO(m_fHaloScale)),
  173. RecvPropFloat (RECVINFO(m_fWidth)),
  174. RecvPropFloat (RECVINFO(m_fEndWidth)),
  175. RecvPropFloat (RECVINFO(m_fFadeLength)),
  176. RecvPropFloat (RECVINFO(m_fAmplitude)),
  177. RecvPropFloat (RECVINFO(m_fStartFrame)),
  178. RecvPropFloat (RECVINFO(m_fSpeed), 0, RecvProxy_Beam_ScrollSpeed ),
  179. RecvPropFloat(RECVINFO(m_flFrameRate)),
  180. RecvPropFloat(RECVINFO(m_flHDRColorScale)),
  181. RecvPropInt(RECVINFO(m_clrRender)),
  182. RecvPropInt(RECVINFO(m_nRenderFX)),
  183. RecvPropInt(RECVINFO(m_nRenderMode)),
  184. RecvPropFloat(RECVINFO(m_flFrame)),
  185. RecvPropVector(RECVINFO(m_vecEndPos)),
  186. #ifdef PORTAL
  187. RecvPropBool(RECVINFO(m_bDrawInMainRender) ),
  188. RecvPropBool(RECVINFO(m_bDrawInPortalRender) ),
  189. #endif
  190. RecvPropInt(RECVINFO(m_nModelIndex)),
  191. RecvPropInt(RECVINFO(m_nMinDXLevel)),
  192. RecvPropVector(RECVINFO_NAME(m_vecNetworkOrigin, m_vecOrigin)),
  193. RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
  194. #if !defined( NO_ENTITY_PREDICTION )
  195. RecvPropDataTable( "beampredictable_id", 0, 0, &REFERENCE_RECV_TABLE( DT_BeamPredictableId ) ),
  196. #endif
  197. #endif
  198. END_NETWORK_TABLE()
  199. #if !defined( CLIENT_DLL )
  200. BEGIN_DATADESC( CBeam )
  201. DEFINE_FIELD( m_nHaloIndex, FIELD_MODELINDEX ),
  202. DEFINE_FIELD( m_nBeamType, FIELD_INTEGER ),
  203. DEFINE_FIELD( m_nBeamFlags, FIELD_INTEGER ),
  204. DEFINE_FIELD( m_nNumBeamEnts, FIELD_INTEGER ),
  205. DEFINE_ARRAY( m_hAttachEntity, FIELD_EHANDLE, MAX_BEAM_ENTS ),
  206. DEFINE_ARRAY( m_nAttachIndex, FIELD_INTEGER, MAX_BEAM_ENTS ),
  207. DEFINE_FIELD( m_nMinDXLevel, FIELD_INTEGER ),
  208. DEFINE_FIELD( m_fWidth, FIELD_FLOAT ),
  209. DEFINE_FIELD( m_fEndWidth, FIELD_FLOAT ),
  210. DEFINE_FIELD( m_fFadeLength, FIELD_FLOAT ),
  211. DEFINE_FIELD( m_fHaloScale, FIELD_FLOAT ),
  212. DEFINE_FIELD( m_fAmplitude, FIELD_FLOAT ),
  213. DEFINE_FIELD( m_fStartFrame, FIELD_FLOAT ),
  214. DEFINE_FIELD( m_fSpeed, FIELD_FLOAT ),
  215. DEFINE_FIELD( m_flFrameRate, FIELD_FLOAT ),
  216. DEFINE_FIELD( m_flFrame, FIELD_FLOAT ),
  217. DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ),
  218. DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "damage" ),
  219. DEFINE_FIELD( m_flFireTime, FIELD_TIME ),
  220. DEFINE_FIELD( m_vecEndPos, FIELD_POSITION_VECTOR ),
  221. DEFINE_FIELD( m_hEndEntity, FIELD_EHANDLE ),
  222. DEFINE_KEYFIELD( m_nDissolveType, FIELD_INTEGER, "dissolvetype" ),
  223. #ifdef PORTAL
  224. DEFINE_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN ),
  225. DEFINE_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN ),
  226. #endif
  227. // Inputs
  228. DEFINE_INPUTFUNC( FIELD_FLOAT, "Width", InputWidth ),
  229. DEFINE_INPUTFUNC( FIELD_FLOAT, "Noise", InputNoise ),
  230. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorRedValue", InputColorRedValue ),
  231. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorGreenValue", InputColorGreenValue ),
  232. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorBlueValue", InputColorBlueValue ),
  233. DEFINE_INPUT( m_fSpeed, FIELD_FLOAT, "ScrollSpeed" ),
  234. // don't save this
  235. //DEFINE_FIELD( m_queryHandleHalo, FIELD_ ),
  236. END_DATADESC()
  237. #else
  238. BEGIN_PREDICTION_DATA( CBeam )
  239. DEFINE_PRED_FIELD( m_nBeamType, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  240. DEFINE_PRED_FIELD( m_nNumBeamEnts, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  241. DEFINE_PRED_ARRAY( m_hAttachEntity, FIELD_EHANDLE, MAX_BEAM_ENTS, FTYPEDESC_INSENDTABLE ),
  242. DEFINE_PRED_ARRAY( m_nAttachIndex, FIELD_INTEGER, MAX_BEAM_ENTS, FTYPEDESC_INSENDTABLE ),
  243. DEFINE_PRED_FIELD( m_nHaloIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  244. DEFINE_PRED_FIELD( m_fHaloScale, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  245. DEFINE_PRED_FIELD( m_fWidth, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  246. DEFINE_PRED_FIELD( m_fEndWidth, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  247. DEFINE_PRED_FIELD( m_fFadeLength, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  248. DEFINE_PRED_FIELD( m_fAmplitude, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  249. DEFINE_PRED_FIELD( m_fStartFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  250. DEFINE_PRED_FIELD( m_fSpeed, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  251. DEFINE_PRED_FIELD( m_nRenderFX, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  252. DEFINE_PRED_FIELD( m_nRenderMode, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  253. DEFINE_PRED_FIELD( m_flFrameRate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  254. DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  255. DEFINE_PRED_FIELD( m_clrRender, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  256. DEFINE_PRED_FIELD( m_nMinDXLevel, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  257. DEFINE_PRED_FIELD_TOL( m_vecEndPos, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.125f ),
  258. #ifdef PORTAL
  259. DEFINE_PRED_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
  260. DEFINE_PRED_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
  261. #endif
  262. DEFINE_PRED_FIELD( m_nModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
  263. DEFINE_PRED_FIELD_TOL( m_vecOrigin, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.125f ),
  264. //DEFINE_PRED_FIELD( m_pMoveParent, SendProxy_MoveParent ),
  265. //DEFINE_PRED_FIELD( m_flHDRColorScale, SendProxy_HDRColorScale ),
  266. END_PREDICTION_DATA()
  267. #endif
  268. //-----------------------------------------------------------------------------
  269. // Purpose:
  270. //-----------------------------------------------------------------------------
  271. CBeam::CBeam( void )
  272. {
  273. #ifdef _DEBUG
  274. // necessary since in debug, we initialize vectors to NAN for debugging
  275. m_vecEndPos.Init();
  276. #endif
  277. m_nMinDXLevel = 0;
  278. m_flHDRColorScale = 1.0f; // default value.
  279. #if !defined( CLIENT_DLL )
  280. m_nDissolveType = -1;
  281. #else
  282. m_queryHandleHalo = 0;
  283. #endif
  284. #ifdef PORTAL
  285. m_bDrawInMainRender = true;
  286. m_bDrawInPortalRender = true;
  287. #endif
  288. }
  289. //-----------------------------------------------------------------------------
  290. // Purpose:
  291. // Input : *szModelName -
  292. //-----------------------------------------------------------------------------
  293. void CBeam::SetModel( const char *szModelName )
  294. {
  295. int modelIndex = modelinfo->GetModelIndex( szModelName );
  296. const model_t *pModel = modelinfo->GetModel( modelIndex );
  297. if ( pModel && modelinfo->GetModelType( pModel ) != mod_sprite )
  298. {
  299. Msg( "Setting CBeam to non-sprite model %s\n", szModelName );
  300. }
  301. #if !defined( CLIENT_DLL )
  302. UTIL_SetModel( this, szModelName );
  303. #else
  304. BaseClass::SetModel( szModelName );
  305. #endif
  306. }
  307. void CBeam::Spawn( void )
  308. {
  309. SetMoveType( MOVETYPE_NONE );
  310. SetSolid( SOLID_NONE ); // Remove model & collisions
  311. SetRenderMode( kRenderTransTexture );
  312. // Opt out of all shadow routines
  313. AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW );
  314. Precache( );
  315. }
  316. void CBeam::Precache( void )
  317. {
  318. if ( GetOwnerEntity() )
  319. {
  320. SetStartEntity( GetOwnerEntity() );
  321. }
  322. if ( m_hEndEntity.Get() )
  323. {
  324. SetEndEntity( m_hEndEntity );
  325. }
  326. }
  327. void CBeam::SetType( int type )
  328. {
  329. Assert( type < NUM_BEAM_TYPES );
  330. m_nBeamType = type;
  331. }
  332. void CBeam::SetBeamFlags( int flags )
  333. {
  334. Assert( flags < (1 << NUM_BEAM_FLAGS) );
  335. m_nBeamFlags = flags;
  336. }
  337. void CBeam::SetBeamFlag( int flag )
  338. {
  339. m_nBeamFlags |= flag;
  340. }
  341. int CBeam::GetType( void ) const
  342. {
  343. return m_nBeamType;
  344. }
  345. int CBeam::GetBeamFlags( void ) const
  346. {
  347. return m_nBeamFlags;
  348. }
  349. void CBeam::SetStartEntity( CBaseEntity *pEntity )
  350. {
  351. Assert( m_nNumBeamEnts >= 2 );
  352. m_hAttachEntity.Set( 0, pEntity );
  353. SetOwnerEntity( pEntity );
  354. RelinkBeam();
  355. pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
  356. }
  357. void CBeam::SetEndEntity( CBaseEntity *pEntity )
  358. {
  359. Assert( m_nNumBeamEnts >= 2 );
  360. m_hAttachEntity.Set( m_nNumBeamEnts-1, pEntity );
  361. m_hEndEntity = pEntity;
  362. RelinkBeam();
  363. pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
  364. }
  365. //-----------------------------------------------------------------------------
  366. // This will change things so the abs position matches the requested spot
  367. //-----------------------------------------------------------------------------
  368. void CBeam::SetAbsStartPos( const Vector &pos )
  369. {
  370. if (!GetMoveParent())
  371. {
  372. SetStartPos( pos );
  373. return;
  374. }
  375. Vector vecLocalPos;
  376. matrix3x4_t worldToBeam;
  377. MatrixInvert( EntityToWorldTransform(), worldToBeam );
  378. VectorTransform( pos, worldToBeam, vecLocalPos );
  379. SetStartPos( vecLocalPos );
  380. }
  381. void CBeam::SetAbsEndPos( const Vector &pos )
  382. {
  383. if (!GetMoveParent())
  384. {
  385. SetEndPos( pos );
  386. return;
  387. }
  388. Vector vecLocalPos;
  389. matrix3x4_t worldToBeam;
  390. MatrixInvert( EntityToWorldTransform(), worldToBeam );
  391. VectorTransform( pos, worldToBeam, vecLocalPos );
  392. SetEndPos( vecLocalPos );
  393. }
  394. #if !defined( CLIENT_DLL )
  395. // These don't take attachments into account
  396. const Vector &CBeam::GetAbsStartPos( void ) const
  397. {
  398. if ( GetType() == BEAM_ENTS && GetStartEntity() )
  399. {
  400. edict_t *pent = engine->PEntityOfEntIndex( GetStartEntity() );
  401. CBaseEntity *ent = CBaseEntity::Instance( pent );
  402. if ( !ent )
  403. {
  404. return GetAbsOrigin();
  405. }
  406. return ent->GetAbsOrigin();
  407. }
  408. return GetAbsOrigin();
  409. }
  410. const Vector &CBeam::GetAbsEndPos( void ) const
  411. {
  412. if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE && GetEndEntity() )
  413. {
  414. edict_t *pent = engine->PEntityOfEntIndex( GetEndEntity() );
  415. CBaseEntity *ent = CBaseEntity::Instance( pent );
  416. if ( ent )
  417. return ent->GetAbsOrigin();
  418. }
  419. if (!const_cast<CBeam*>(this)->GetMoveParent())
  420. return m_vecEndPos.Get();
  421. // FIXME: Cache this off?
  422. static Vector vecAbsPos;
  423. VectorTransform( m_vecEndPos, EntityToWorldTransform(), vecAbsPos );
  424. return vecAbsPos;
  425. }
  426. #else
  427. //-----------------------------------------------------------------------------
  428. // Unlike the server, these take attachments into account
  429. //-----------------------------------------------------------------------------
  430. const Vector &C_Beam::GetAbsStartPos( void ) const
  431. {
  432. static Vector vecStartAbsPosition;
  433. if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE )
  434. {
  435. if (ComputeBeamEntPosition( m_hAttachEntity[0], m_nAttachIndex[0], false, vecStartAbsPosition ))
  436. return vecStartAbsPosition;
  437. }
  438. return GetAbsOrigin();
  439. }
  440. const Vector &C_Beam::GetAbsEndPos( void ) const
  441. {
  442. static Vector vecEndAbsPosition;
  443. if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE )
  444. {
  445. if (ComputeBeamEntPosition( m_hAttachEntity[m_nNumBeamEnts-1], m_nAttachIndex[m_nNumBeamEnts-1], false, vecEndAbsPosition ))
  446. return vecEndAbsPosition;
  447. }
  448. if (!const_cast<C_Beam*>(this)->GetMoveParent())
  449. return m_vecEndPos.Get();
  450. // FIXME: Cache this off?
  451. VectorTransform( m_vecEndPos, EntityToWorldTransform(), vecEndAbsPosition );
  452. return vecEndAbsPosition;
  453. }
  454. #endif
  455. CBeam *CBeam::BeamCreate( const char *pSpriteName, float width )
  456. {
  457. // Create a new entity with CBeam private data
  458. CBeam *pBeam = CREATE_ENTITY( CBeam, "beam" );
  459. pBeam->BeamInit( pSpriteName, width );
  460. return pBeam;
  461. }
  462. //-----------------------------------------------------------------------------
  463. // Purpose:
  464. // Input : *pSpriteName -
  465. // &origin -
  466. // animate -
  467. // Output : CSprite
  468. //-----------------------------------------------------------------------------
  469. CBeam *CBeam::BeamCreatePredictable( const char *module, int line, bool persist, const char *pSpriteName, float width, CBasePlayer *pOwner )
  470. {
  471. #if !defined( NO_ENTITY_PREDICTION )
  472. CBeam *pBeam = ( CBeam * )CBaseEntity::CreatePredictedEntityByName( "beam", module, line, persist );
  473. if ( pBeam )
  474. {
  475. pBeam->BeamInit( pSpriteName, width );
  476. pBeam->SetOwnerEntity( pOwner );
  477. pBeam->SetPlayerSimulated( pOwner );
  478. }
  479. return pBeam;
  480. #else
  481. return NULL;
  482. #endif
  483. }
  484. void CBeam::BeamInit( const char *pSpriteName, float width )
  485. {
  486. SetColor( 255, 255, 255 );
  487. SetBrightness( 255 );
  488. SetNoise( 0 );
  489. SetFrame( 0 );
  490. SetScrollRate( 0 );
  491. SetModelName( MAKE_STRING( pSpriteName ) );
  492. SetRenderMode( kRenderTransTexture );
  493. SetTexture( PrecacheModel( pSpriteName ) );
  494. SetWidth( width );
  495. SetEndWidth( width );
  496. SetFadeLength( 0 ); // No fade
  497. for (int i=0;i<MAX_BEAM_ENTS;i++)
  498. {
  499. m_hAttachEntity.Set( i, NULL );
  500. m_nAttachIndex.Set( i, 0 );
  501. }
  502. m_nHaloIndex = 0;
  503. m_fHaloScale = BEAM_DEFAULT_HALO_SCALE;
  504. m_nBeamType = 0;
  505. m_nBeamFlags = 0;
  506. }
  507. void CBeam::PointsInit( const Vector &start, const Vector &end )
  508. {
  509. SetType( BEAM_POINTS );
  510. m_nNumBeamEnts = 2;
  511. SetStartPos( start );
  512. SetEndPos( end );
  513. SetStartAttachment( 0 );
  514. SetEndAttachment( 0 );
  515. RelinkBeam();
  516. }
  517. void CBeam::HoseInit( const Vector &start, const Vector &direction )
  518. {
  519. SetType( BEAM_HOSE );
  520. m_nNumBeamEnts = 2;
  521. SetStartPos( start );
  522. SetEndPos( direction );
  523. SetStartAttachment( 0 );
  524. SetEndAttachment( 0 );
  525. RelinkBeam();
  526. }
  527. void CBeam::PointEntInit( const Vector &start, CBaseEntity *pEndEntity )
  528. {
  529. SetType( BEAM_ENTPOINT );
  530. m_nNumBeamEnts = 2;
  531. SetStartPos( start );
  532. SetEndEntity( pEndEntity );
  533. SetStartAttachment( 0 );
  534. SetEndAttachment( 0 );
  535. RelinkBeam();
  536. }
  537. void CBeam::EntsInit( CBaseEntity *pStartEntity, CBaseEntity *pEndEntity )
  538. {
  539. SetType( BEAM_ENTS );
  540. m_nNumBeamEnts = 2;
  541. SetStartEntity( pStartEntity );
  542. SetEndEntity( pEndEntity );
  543. SetStartAttachment( 0 );
  544. SetEndAttachment( 0 );
  545. RelinkBeam();
  546. }
  547. void CBeam::LaserInit( CBaseEntity *pStartEntity, CBaseEntity *pEndEntity )
  548. {
  549. SetType( BEAM_LASER );
  550. m_nNumBeamEnts = 2;
  551. SetStartEntity( pStartEntity );
  552. SetEndEntity( pEndEntity );
  553. SetStartAttachment( 0 );
  554. SetEndAttachment( 0 );
  555. RelinkBeam();
  556. }
  557. void CBeam::SplineInit( int nNumEnts, CBaseEntity** pEntList, int *attachment )
  558. {
  559. if (nNumEnts < 2)
  560. {
  561. Msg("ERROR: Min of 2 ents required for spline beam.\n");
  562. }
  563. else if (nNumEnts > MAX_BEAM_ENTS)
  564. {
  565. Msg("ERROR: Max of %i ents allowed for spline beam.\n",MAX_BEAM_ENTS);
  566. }
  567. SetType( BEAM_SPLINE );
  568. for (int i=0;i<nNumEnts;i++)
  569. {
  570. m_hAttachEntity.Set( i, pEntList[i] );
  571. m_nAttachIndex.Set( i, attachment[i] );
  572. }
  573. m_nNumBeamEnts = nNumEnts;
  574. RelinkBeam();
  575. }
  576. void CBeam::RelinkBeam( void )
  577. {
  578. // FIXME: Why doesn't this just define the absbox too?
  579. // It seems that we don't need to recompute the absbox
  580. // in CBaseEntity::SetObjectCollisionBox, in fact the absbox
  581. // computed there seems way too big
  582. Vector startPos = GetAbsStartPos(), endPos = GetAbsEndPos();
  583. Vector vecAbsExtra1, vecAbsExtra2;
  584. bool bUseExtraPoints = false;
  585. #ifdef PORTAL
  586. CBaseEntity *pStartEntity = GetStartEntityPtr();
  587. CTraceFilterSkipClassname traceFilter( pStartEntity, "prop_energy_ball", COLLISION_GROUP_NONE );
  588. ITraceFilter *pEntityBeamTraceFilter = NULL;
  589. if ( pStartEntity )
  590. pEntityBeamTraceFilter = pStartEntity->GetBeamTraceFilter();
  591. CTraceFilterChain traceFilterChain( &traceFilter, pEntityBeamTraceFilter );
  592. bUseExtraPoints = UTIL_Portal_Trace_Beam( this, startPos, endPos, vecAbsExtra1, vecAbsExtra2, &traceFilterChain );
  593. #endif
  594. // UNDONE: Should we do this to make the boxes smaller?
  595. //SetAbsOrigin( startPos );
  596. Vector vecBeamMin, vecBeamMax;
  597. VectorMin( startPos, endPos, vecBeamMin );
  598. VectorMax( startPos, endPos, vecBeamMax );
  599. if ( bUseExtraPoints )
  600. {
  601. VectorMin( vecBeamMin, vecAbsExtra1, vecBeamMin );
  602. VectorMin( vecBeamMin, vecAbsExtra2, vecBeamMin );
  603. VectorMax( vecBeamMax, vecAbsExtra1, vecBeamMax );
  604. VectorMax( vecBeamMax, vecAbsExtra2, vecBeamMax );
  605. }
  606. SetCollisionBounds( vecBeamMin - GetAbsOrigin(), vecBeamMax - GetAbsOrigin() );
  607. }
  608. CBaseEntity *CBeam::RandomTargetname( const char *szName )
  609. {
  610. #if !defined( CLIENT_DLL )
  611. int total = 0;
  612. CBaseEntity *pEntity = NULL;
  613. CBaseEntity *pNewEntity = NULL;
  614. while ((pNewEntity = gEntList.FindEntityByName( pNewEntity, szName )) != NULL)
  615. {
  616. total++;
  617. if (random->RandomInt(0,total-1) < 1)
  618. pEntity = pNewEntity;
  619. }
  620. return pEntity;
  621. #else
  622. return NULL;
  623. #endif
  624. }
  625. void CBeam::DoSparks( const Vector &start, const Vector &end )
  626. {
  627. #if !defined( CLIENT_DLL )
  628. if ( HasSpawnFlags(SF_BEAM_SPARKSTART|SF_BEAM_SPARKEND) )
  629. {
  630. if ( HasSpawnFlags( SF_BEAM_SPARKSTART ) )
  631. {
  632. g_pEffects->Sparks( start );
  633. }
  634. if ( HasSpawnFlags( SF_BEAM_SPARKEND ) )
  635. {
  636. g_pEffects->Sparks( end );
  637. }
  638. }
  639. #endif
  640. }
  641. //-----------------------------------------------------------------------------
  642. // Purpose: Damages anything in the beam.
  643. // Input : ptr -
  644. //-----------------------------------------------------------------------------
  645. void CBeam::BeamDamage( trace_t *ptr )
  646. {
  647. RelinkBeam();
  648. #if !defined( CLIENT_DLL )
  649. if ( ptr->fraction != 1.0 && ptr->m_pEnt != NULL )
  650. {
  651. CBaseEntity *pHit = ptr->m_pEnt;
  652. if ( pHit )
  653. {
  654. ClearMultiDamage();
  655. Vector dir = ptr->endpos - GetAbsOrigin();
  656. VectorNormalize( dir );
  657. int nDamageType = DMG_ENERGYBEAM;
  658. #ifndef HL1_DLL
  659. if (m_nDissolveType == 0)
  660. {
  661. nDamageType = DMG_DISSOLVE;
  662. }
  663. else if ( m_nDissolveType > 0 )
  664. {
  665. nDamageType = DMG_DISSOLVE | DMG_SHOCK;
  666. }
  667. #endif
  668. CTakeDamageInfo info( this, this, m_flDamage * (gpGlobals->curtime - m_flFireTime), nDamageType );
  669. CalculateMeleeDamageForce( &info, dir, ptr->endpos );
  670. pHit->DispatchTraceAttack( info, dir, ptr );
  671. ApplyMultiDamage();
  672. if ( HasSpawnFlags( SF_BEAM_DECALS ) )
  673. {
  674. if ( pHit->IsBSPModel() )
  675. {
  676. UTIL_DecalTrace( ptr, GetDecalName() );
  677. }
  678. }
  679. }
  680. }
  681. #endif
  682. m_flFireTime = gpGlobals->curtime;
  683. }
  684. //-----------------------------------------------------------------------------
  685. // Purpose:
  686. //-----------------------------------------------------------------------------
  687. void CBeam::TurnOn( void )
  688. {
  689. AddEffects( EF_NODRAW );
  690. }
  691. //-----------------------------------------------------------------------------
  692. // Purpose:
  693. //-----------------------------------------------------------------------------
  694. void CBeam::TurnOff( void )
  695. {
  696. RemoveEffects( EF_NODRAW );
  697. }
  698. #if !defined( CLIENT_DLL )
  699. //-----------------------------------------------------------------------------
  700. // Purpose: Input handler for the beam width. Sets the end width based on the
  701. // beam width.
  702. // Input : Beam width in tenths of world units.
  703. //-----------------------------------------------------------------------------
  704. void CBeam::InputWidth( inputdata_t &inputdata )
  705. {
  706. SetWidth( inputdata.value.Float() );
  707. SetEndWidth( inputdata.value.Float() );
  708. }
  709. void CBeam::InputColorRedValue( inputdata_t &inputdata )
  710. {
  711. int nNewColor = clamp( FastFloatToSmallInt(inputdata.value.Float()), 0, 255 );
  712. SetColor( nNewColor, m_clrRender->g, m_clrRender->b );
  713. }
  714. void CBeam::InputColorGreenValue( inputdata_t &inputdata )
  715. {
  716. int nNewColor =clamp( FastFloatToSmallInt(inputdata.value.Float()), 0, 255 );
  717. SetColor( m_clrRender->r, nNewColor, m_clrRender->b );
  718. }
  719. void CBeam::InputColorBlueValue( inputdata_t &inputdata )
  720. {
  721. int nNewColor = clamp( FastFloatToSmallInt(inputdata.value.Float()), 0, 255 );
  722. SetColor( m_clrRender->r, m_clrRender->g, nNewColor );
  723. }
  724. void CBeam::InputNoise( inputdata_t &inputdata )
  725. {
  726. SetNoise( inputdata.value.Float() );
  727. }
  728. int CBeam::UpdateTransmitState( void )
  729. {
  730. // we must call ShouldTransmit() if we have a move parent
  731. if ( GetMoveParent() )
  732. return SetTransmitState( FL_EDICT_FULLCHECK );
  733. return BaseClass::UpdateTransmitState( );
  734. }
  735. void CBeam::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways )
  736. {
  737. // Are we already marked for transmission?
  738. if ( pInfo->m_pTransmitEdict->Get( entindex() ) )
  739. return;
  740. BaseClass::SetTransmit( pInfo, bAlways );
  741. // Force our attached entities to go too...
  742. for ( int i=0; i < MAX_BEAM_ENTS; ++i )
  743. {
  744. if ( m_hAttachEntity[i].Get() )
  745. {
  746. m_hAttachEntity[i]->SetTransmit( pInfo, bAlways );
  747. }
  748. }
  749. }
  750. int CBeam::ShouldTransmit( const CCheckTransmitInfo *pInfo )
  751. {
  752. if ( IsEffectActive( EF_NODRAW ) )
  753. return FL_EDICT_DONTSEND;
  754. // Transmit us with the same rules as our move parent
  755. if ( GetMoveParent() )
  756. {
  757. return GetMoveParent()->ShouldTransmit( pInfo );
  758. }
  759. return BaseClass::ShouldTransmit( pInfo );
  760. }
  761. #endif
  762. //-----------------------------------------------------------------------------
  763. // Purpose: Draw any debug text overlays.
  764. // Output : Returns the new text offset from the top.
  765. //-----------------------------------------------------------------------------
  766. int CBeam::DrawDebugTextOverlays(void)
  767. {
  768. #if !defined( CLIENT_DLL )
  769. int text_offset = BaseClass::DrawDebugTextOverlays();
  770. if (m_debugOverlays & OVERLAY_TEXT_BIT)
  771. {
  772. // Print state
  773. char tempstr[512];
  774. Q_snprintf(tempstr, sizeof(tempstr), "start: (%.2f,%.2f,%.2f)", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z);
  775. EntityText(text_offset,tempstr,0);
  776. text_offset++;
  777. Q_snprintf(tempstr, sizeof(tempstr), "end : (%.2f,%.2f,%.2f)", m_vecEndPos.GetX(), m_vecEndPos.GetY(), m_vecEndPos.GetZ());
  778. EntityText(text_offset,tempstr,0);
  779. text_offset++;
  780. }
  781. return text_offset;
  782. #else
  783. return 0;
  784. #endif
  785. }
  786. #if defined( CLIENT_DLL )
  787. // Purpose:
  788. // Input : isbeingremoved -
  789. // *predicted -
  790. // Output : Returns true on success, false on failure.
  791. //-----------------------------------------------------------------------------
  792. bool CBeam::OnPredictedEntityRemove( bool isbeingremoved, C_BaseEntity *predicted )
  793. {
  794. BaseClass::OnPredictedEntityRemove( isbeingremoved, predicted );
  795. CBeam *beam = dynamic_cast< CBeam * >( predicted );
  796. if ( !beam )
  797. {
  798. // Hrm, we didn't link up to correct type!!!
  799. Assert( 0 );
  800. // Delete right away since it's fucked up
  801. return true;
  802. }
  803. if ( beam->IsEFlagSet( EFL_KILLME ) )
  804. {
  805. // Don't delete right away
  806. AddEFlags( EFL_KILLME );
  807. return false;
  808. }
  809. // Go ahead and delete if it's not short-lived
  810. return true;
  811. }
  812. extern bool g_bRenderingScreenshot;
  813. extern ConVar r_drawviewmodel;
  814. int CBeam::DrawModel( int flags )
  815. {
  816. if ( !m_bReadyToDraw )
  817. return 0;
  818. if ( IsMarkedForDeletion() )
  819. return 0;
  820. if ( CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE )
  821. return 0;
  822. #ifdef PORTAL
  823. if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) ||
  824. ( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) )
  825. {
  826. return 0;
  827. }
  828. #endif //#ifdef PORTAL
  829. // Tracker 16432: If rendering a savegame screenshot don't draw beams
  830. // who have viewmodels as their attached entity
  831. if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() )
  832. {
  833. // If the beam is attached
  834. for (int i=0;i<MAX_BEAM_ENTS;i++)
  835. {
  836. C_BaseViewModel *vm = dynamic_cast<C_BaseViewModel *>(m_hAttachEntity[i].Get());
  837. if ( vm )
  838. {
  839. return 0;
  840. }
  841. }
  842. }
  843. beams->DrawBeam( this );
  844. return 0;
  845. }
  846. void CBeam::OnDataChanged( DataUpdateType_t updateType )
  847. {
  848. MarkMessageReceived();
  849. // Make sure that the correct model is referenced for this entity
  850. SetModelPointer( modelinfo->GetModel( GetModelIndex() ) );
  851. // Convert weapon world models to viewmodels if they're weapons being carried by the local player
  852. for (int i=0;i<MAX_BEAM_ENTS;i++)
  853. {
  854. C_BaseEntity *pEnt = m_hAttachEntity[i].Get();
  855. if ( pEnt )
  856. {
  857. C_BaseCombatWeapon *pWpn = dynamic_cast<C_BaseCombatWeapon *>(pEnt);
  858. if ( pWpn && pWpn->ShouldDrawUsingViewModel() )
  859. {
  860. C_BasePlayer *player = ToBasePlayer( pWpn->GetOwner() );
  861. // Use GetRenderedWeaponModel() instead?
  862. C_BaseViewModel *pViewModel = player ? player->GetViewModel( 0 ) : NULL;
  863. if ( pViewModel )
  864. {
  865. // Get the viewmodel and use it instead
  866. m_hAttachEntity.Set( i, pViewModel );
  867. }
  868. }
  869. }
  870. }
  871. // Compute the bounds here...
  872. Vector mins, maxs;
  873. ComputeBounds( mins, maxs );
  874. SetCollisionBounds( mins, maxs );
  875. }
  876. bool CBeam::IsTransparent( void )
  877. {
  878. return true;
  879. }
  880. bool CBeam::ShouldDraw()
  881. {
  882. if ( m_nMinDXLevel != 0 )
  883. {
  884. if ( m_nMinDXLevel > g_pMaterialSystemHardwareConfig->GetDXSupportLevel() )
  885. return false;
  886. }
  887. return BaseClass::ShouldDraw();
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Purpose: Adds to beam entity list
  891. //-----------------------------------------------------------------------------
  892. void CBeam::AddEntity( void )
  893. {
  894. // If set to invisible, skip. Do this before resetting the entity pointer so it has
  895. // valid data to decide whether it's visible.
  896. if ( !ShouldDraw() )
  897. {
  898. return;
  899. }
  900. //FIXME: If we're hooked up to an attachment point, then recompute our bounds every frame
  901. if ( m_hAttachEntity[0].Get() || m_hAttachEntity[1].Get() )
  902. {
  903. // Compute the bounds here...
  904. Vector mins, maxs;
  905. ComputeBounds( mins, maxs );
  906. SetCollisionBounds( mins, maxs );
  907. }
  908. MoveToLastReceivedPosition();
  909. }
  910. //-----------------------------------------------------------------------------
  911. // Computes the bounding box of a beam local to the origin of the beam
  912. //-----------------------------------------------------------------------------
  913. void CBeam::ComputeBounds( Vector& mins, Vector& maxs )
  914. {
  915. Vector vecAbsStart = GetAbsStartPos();
  916. Vector vecAbsEnd = GetAbsEndPos();
  917. // May need extra points for creating the min/max bounds
  918. bool bUseExtraPoints = false;
  919. Vector vecAbsExtra1, vecAbsExtra2;
  920. #ifdef PORTAL
  921. CBaseEntity *pStartEntity = GetStartEntityPtr();
  922. CTraceFilterSkipClassname traceFilter( pStartEntity, "prop_energy_ball", COLLISION_GROUP_NONE );
  923. ITraceFilter *pEntityBeamTraceFilter = NULL;
  924. if ( pStartEntity )
  925. pEntityBeamTraceFilter = pStartEntity->GetBeamTraceFilter();
  926. CTraceFilterChain traceFilterChain( &traceFilter, pEntityBeamTraceFilter );
  927. bUseExtraPoints = UTIL_Portal_Trace_Beam( this, vecAbsStart, vecAbsEnd, vecAbsExtra1, vecAbsExtra2, &traceFilterChain );
  928. #endif
  929. switch( GetType() )
  930. {
  931. case BEAM_LASER:
  932. case BEAM_ENTS:
  933. case BEAM_SPLINE:
  934. case BEAM_ENTPOINT:
  935. {
  936. // Compute the bounds here...
  937. Vector attachmentPoint( 0, 0, 0 );
  938. mins.Init( 99999, 99999, 99999 );
  939. maxs.Init( -99999, -99999, -99999 );
  940. for (int i = 0; i < m_nNumBeamEnts; ++i )
  941. {
  942. C_BaseEntity *pTestEnt = m_hAttachEntity[i].Get();
  943. if ( pTestEnt )
  944. {
  945. if ( pTestEnt == this )
  946. {
  947. mins = maxs = GetAbsOrigin();
  948. }
  949. else
  950. {
  951. // We do this so we don't have to calculate attachments (and do expensive bone-setup calculations) on our attachments.
  952. Vector attMins, attMaxs;
  953. m_hAttachEntity[i]->GetRenderBoundsWorldspace( attMins, attMaxs );
  954. mins = mins.Min( attMins );
  955. mins = mins.Min( attMaxs );
  956. maxs = maxs.Max( attMins );
  957. maxs = maxs.Max( attMaxs );
  958. }
  959. //ASSERT_COORD( mins );
  960. //ASSERT_COORD( maxs );
  961. }
  962. else
  963. {
  964. if (i == 0)
  965. {
  966. VectorCopy( vecAbsStart, attachmentPoint );
  967. }
  968. else if (i == 1)
  969. {
  970. VectorCopy( vecAbsEnd, attachmentPoint );
  971. }
  972. else
  973. {
  974. Assert(0);
  975. }
  976. mins = mins.Min( attachmentPoint );
  977. maxs = maxs.Max( attachmentPoint );
  978. }
  979. }
  980. }
  981. break;
  982. case BEAM_POINTS:
  983. default:
  984. {
  985. for (int i = 0; i < 3; ++i)
  986. {
  987. if (vecAbsStart[i] < vecAbsEnd[i])
  988. {
  989. mins[i] = vecAbsStart[i];
  990. maxs[i] = vecAbsEnd[i];
  991. }
  992. else
  993. {
  994. mins[i] = vecAbsEnd[i];
  995. maxs[i] = vecAbsStart[i];
  996. }
  997. }
  998. }
  999. break;
  1000. }
  1001. if ( bUseExtraPoints )
  1002. {
  1003. mins = mins.Min( vecAbsExtra1 );
  1004. mins = mins.Min( vecAbsExtra2 );
  1005. maxs = maxs.Max( vecAbsExtra1 );
  1006. maxs = maxs.Max( vecAbsExtra2 );
  1007. }
  1008. // bloat the bounding box by the width of the beam
  1009. float rad = 0.5f * MAX( m_fWidth.Get(), m_fEndWidth.Get() );
  1010. Vector vecRad( rad, rad, rad );
  1011. mins -= vecRad;
  1012. maxs += vecRad;
  1013. // Make sure the bounds are measured in *relative coords*
  1014. Vector vecAbsOrigin = GetAbsOrigin();
  1015. mins -= vecAbsOrigin;
  1016. maxs -= vecAbsOrigin;
  1017. }
  1018. #endif