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.

984 lines
24 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Player for HL2.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "vcollide_parse.h"
  8. #include "c_hl2mp_player.h"
  9. #include "view.h"
  10. #include "takedamageinfo.h"
  11. #include "hl2mp_gamerules.h"
  12. #include "in_buttons.h"
  13. #include "iviewrender_beams.h" // flashlight beam
  14. #include "r_efx.h"
  15. #include "dlight.h"
  16. // Don't alias here
  17. #if defined( CHL2MP_Player )
  18. #undef CHL2MP_Player
  19. #endif
  20. LINK_ENTITY_TO_CLASS( player, C_HL2MP_Player );
  21. IMPLEMENT_CLIENTCLASS_DT(C_HL2MP_Player, DT_HL2MP_Player, CHL2MP_Player)
  22. RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ),
  23. RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ),
  24. RecvPropEHandle( RECVINFO( m_hRagdoll ) ),
  25. RecvPropInt( RECVINFO( m_iSpawnInterpCounter ) ),
  26. RecvPropInt( RECVINFO( m_iPlayerSoundType) ),
  27. RecvPropBool( RECVINFO( m_fIsWalking ) ),
  28. END_RECV_TABLE()
  29. BEGIN_PREDICTION_DATA( C_HL2MP_Player )
  30. DEFINE_PRED_FIELD( m_fIsWalking, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
  31. END_PREDICTION_DATA()
  32. #define HL2_WALK_SPEED 150
  33. #define HL2_NORM_SPEED 190
  34. #define HL2_SPRINT_SPEED 320
  35. static ConVar cl_playermodel( "cl_playermodel", "none", FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE, "Default Player Model");
  36. static ConVar cl_defaultweapon( "cl_defaultweapon", "weapon_physcannon", FCVAR_USERINFO | FCVAR_ARCHIVE, "Default Spawn Weapon");
  37. void SpawnBlood (Vector vecSpot, const Vector &vecDir, int bloodColor, float flDamage);
  38. C_HL2MP_Player::C_HL2MP_Player() : m_PlayerAnimState( this ), m_iv_angEyeAngles( "C_HL2MP_Player::m_iv_angEyeAngles" )
  39. {
  40. m_iIDEntIndex = 0;
  41. m_iSpawnInterpCounterCache = 0;
  42. m_angEyeAngles.Init();
  43. AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
  44. m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
  45. m_blinkTimer.Invalidate();
  46. m_pFlashlightBeam = NULL;
  47. }
  48. C_HL2MP_Player::~C_HL2MP_Player( void )
  49. {
  50. ReleaseFlashlight();
  51. }
  52. int C_HL2MP_Player::GetIDTarget() const
  53. {
  54. return m_iIDEntIndex;
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Purpose: Update this client's target entity
  58. //-----------------------------------------------------------------------------
  59. void C_HL2MP_Player::UpdateIDTarget()
  60. {
  61. if ( !IsLocalPlayer() )
  62. return;
  63. // Clear old target and find a new one
  64. m_iIDEntIndex = 0;
  65. // don't show IDs in chase spec mode
  66. if ( GetObserverMode() == OBS_MODE_CHASE ||
  67. GetObserverMode() == OBS_MODE_DEATHCAM )
  68. return;
  69. trace_t tr;
  70. Vector vecStart, vecEnd;
  71. VectorMA( MainViewOrigin(), 1500, MainViewForward(), vecEnd );
  72. VectorMA( MainViewOrigin(), 10, MainViewForward(), vecStart );
  73. UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
  74. if ( !tr.startsolid && tr.DidHitNonWorldEntity() )
  75. {
  76. C_BaseEntity *pEntity = tr.m_pEnt;
  77. if ( pEntity && (pEntity != this) )
  78. {
  79. m_iIDEntIndex = pEntity->entindex();
  80. }
  81. }
  82. }
  83. void C_HL2MP_Player::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
  84. {
  85. Vector vecOrigin = ptr->endpos - vecDir * 4;
  86. float flDistance = 0.0f;
  87. if ( info.GetAttacker() )
  88. {
  89. flDistance = (ptr->endpos - info.GetAttacker()->GetAbsOrigin()).Length();
  90. }
  91. if ( m_takedamage )
  92. {
  93. AddMultiDamage( info, this );
  94. int blood = BloodColor();
  95. CBaseEntity *pAttacker = info.GetAttacker();
  96. if ( pAttacker )
  97. {
  98. if ( HL2MPRules()->IsTeamplay() && pAttacker->InSameTeam( this ) == true )
  99. return;
  100. }
  101. if ( blood != DONT_BLEED )
  102. {
  103. SpawnBlood( vecOrigin, vecDir, blood, flDistance );// a little surface blood.
  104. TraceBleed( flDistance, vecDir, ptr, info.GetDamageType() );
  105. }
  106. }
  107. }
  108. C_HL2MP_Player* C_HL2MP_Player::GetLocalHL2MPPlayer()
  109. {
  110. return (C_HL2MP_Player*)C_BasePlayer::GetLocalPlayer();
  111. }
  112. void C_HL2MP_Player::Initialize( void )
  113. {
  114. m_headYawPoseParam = LookupPoseParameter( "head_yaw" );
  115. GetPoseParameterRange( m_headYawPoseParam, m_headYawMin, m_headYawMax );
  116. m_headPitchPoseParam = LookupPoseParameter( "head_pitch" );
  117. GetPoseParameterRange( m_headPitchPoseParam, m_headPitchMin, m_headPitchMax );
  118. CStudioHdr *hdr = GetModelPtr();
  119. for ( int i = 0; i < hdr->GetNumPoseParameters() ; i++ )
  120. {
  121. SetPoseParameter( hdr, i, 0.0 );
  122. }
  123. }
  124. CStudioHdr *C_HL2MP_Player::OnNewModel( void )
  125. {
  126. CStudioHdr *hdr = BaseClass::OnNewModel();
  127. Initialize( );
  128. return hdr;
  129. }
  130. //-----------------------------------------------------------------------------
  131. /**
  132. * Orient head and eyes towards m_lookAt.
  133. */
  134. void C_HL2MP_Player::UpdateLookAt( void )
  135. {
  136. // head yaw
  137. if (m_headYawPoseParam < 0 || m_headPitchPoseParam < 0)
  138. return;
  139. // orient eyes
  140. m_viewtarget = m_vLookAtTarget;
  141. // blinking
  142. if (m_blinkTimer.IsElapsed())
  143. {
  144. m_blinktoggle = !m_blinktoggle;
  145. m_blinkTimer.Start( RandomFloat( 1.5f, 4.0f ) );
  146. }
  147. // Figure out where we want to look in world space.
  148. QAngle desiredAngles;
  149. Vector to = m_vLookAtTarget - EyePosition();
  150. VectorAngles( to, desiredAngles );
  151. // Figure out where our body is facing in world space.
  152. QAngle bodyAngles( 0, 0, 0 );
  153. bodyAngles[YAW] = GetLocalAngles()[YAW];
  154. float flBodyYawDiff = bodyAngles[YAW] - m_flLastBodyYaw;
  155. m_flLastBodyYaw = bodyAngles[YAW];
  156. // Set the head's yaw.
  157. float desired = AngleNormalize( desiredAngles[YAW] - bodyAngles[YAW] );
  158. desired = clamp( desired, m_headYawMin, m_headYawMax );
  159. m_flCurrentHeadYaw = ApproachAngle( desired, m_flCurrentHeadYaw, 130 * gpGlobals->frametime );
  160. // Counterrotate the head from the body rotation so it doesn't rotate past its target.
  161. m_flCurrentHeadYaw = AngleNormalize( m_flCurrentHeadYaw - flBodyYawDiff );
  162. desired = clamp( desired, m_headYawMin, m_headYawMax );
  163. SetPoseParameter( m_headYawPoseParam, m_flCurrentHeadYaw );
  164. // Set the head's yaw.
  165. desired = AngleNormalize( desiredAngles[PITCH] );
  166. desired = clamp( desired, m_headPitchMin, m_headPitchMax );
  167. m_flCurrentHeadPitch = ApproachAngle( desired, m_flCurrentHeadPitch, 130 * gpGlobals->frametime );
  168. m_flCurrentHeadPitch = AngleNormalize( m_flCurrentHeadPitch );
  169. SetPoseParameter( m_headPitchPoseParam, m_flCurrentHeadPitch );
  170. }
  171. void C_HL2MP_Player::ClientThink( void )
  172. {
  173. bool bFoundViewTarget = false;
  174. Vector vForward;
  175. AngleVectors( GetLocalAngles(), &vForward );
  176. for( int iClient = 1; iClient <= gpGlobals->maxClients; ++iClient )
  177. {
  178. CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient );
  179. if(!pEnt || !pEnt->IsPlayer())
  180. continue;
  181. if ( pEnt->entindex() == entindex() )
  182. continue;
  183. Vector vTargetOrigin = pEnt->GetAbsOrigin();
  184. Vector vMyOrigin = GetAbsOrigin();
  185. Vector vDir = vTargetOrigin - vMyOrigin;
  186. if ( vDir.Length() > 128 )
  187. continue;
  188. VectorNormalize( vDir );
  189. if ( DotProduct( vForward, vDir ) < 0.0f )
  190. continue;
  191. m_vLookAtTarget = pEnt->EyePosition();
  192. bFoundViewTarget = true;
  193. break;
  194. }
  195. if ( bFoundViewTarget == false )
  196. {
  197. m_vLookAtTarget = GetAbsOrigin() + vForward * 512;
  198. }
  199. UpdateIDTarget();
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Purpose:
  203. //-----------------------------------------------------------------------------
  204. int C_HL2MP_Player::DrawModel( int flags )
  205. {
  206. if ( !m_bReadyToDraw )
  207. return 0;
  208. return BaseClass::DrawModel(flags);
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Should this object receive shadows?
  212. //-----------------------------------------------------------------------------
  213. bool C_HL2MP_Player::ShouldReceiveProjectedTextures( int flags )
  214. {
  215. Assert( flags & SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK );
  216. if ( IsEffectActive( EF_NODRAW ) )
  217. return false;
  218. if( flags & SHADOW_FLAGS_FLASHLIGHT )
  219. {
  220. return true;
  221. }
  222. return BaseClass::ShouldReceiveProjectedTextures( flags );
  223. }
  224. void C_HL2MP_Player::DoImpactEffect( trace_t &tr, int nDamageType )
  225. {
  226. if ( GetActiveWeapon() )
  227. {
  228. GetActiveWeapon()->DoImpactEffect( tr, nDamageType );
  229. return;
  230. }
  231. BaseClass::DoImpactEffect( tr, nDamageType );
  232. }
  233. void C_HL2MP_Player::PreThink( void )
  234. {
  235. QAngle vTempAngles = GetLocalAngles();
  236. if ( GetLocalPlayer() == this )
  237. {
  238. vTempAngles[PITCH] = EyeAngles()[PITCH];
  239. }
  240. else
  241. {
  242. vTempAngles[PITCH] = m_angEyeAngles[PITCH];
  243. }
  244. if ( vTempAngles[YAW] < 0.0f )
  245. {
  246. vTempAngles[YAW] += 360.0f;
  247. }
  248. SetLocalAngles( vTempAngles );
  249. BaseClass::PreThink();
  250. HandleSpeedChanges();
  251. if ( m_HL2Local.m_flSuitPower <= 0.0f )
  252. {
  253. if( IsSprinting() )
  254. {
  255. StopSprinting();
  256. }
  257. }
  258. }
  259. const QAngle &C_HL2MP_Player::EyeAngles()
  260. {
  261. if( IsLocalPlayer() )
  262. {
  263. return BaseClass::EyeAngles();
  264. }
  265. else
  266. {
  267. return m_angEyeAngles;
  268. }
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Purpose:
  272. //-----------------------------------------------------------------------------
  273. void C_HL2MP_Player::AddEntity( void )
  274. {
  275. BaseClass::AddEntity();
  276. QAngle vTempAngles = GetLocalAngles();
  277. vTempAngles[PITCH] = m_angEyeAngles[PITCH];
  278. SetLocalAngles( vTempAngles );
  279. m_PlayerAnimState.Update();
  280. // Zero out model pitch, blending takes care of all of it.
  281. SetLocalAnglesDim( X_INDEX, 0 );
  282. if( this != C_BasePlayer::GetLocalPlayer() )
  283. {
  284. if ( IsEffectActive( EF_DIMLIGHT ) )
  285. {
  286. int iAttachment = LookupAttachment( "anim_attachment_RH" );
  287. if ( iAttachment < 0 )
  288. return;
  289. Vector vecOrigin;
  290. QAngle eyeAngles = m_angEyeAngles;
  291. GetAttachment( iAttachment, vecOrigin, eyeAngles );
  292. Vector vForward;
  293. AngleVectors( eyeAngles, &vForward );
  294. trace_t tr;
  295. UTIL_TraceLine( vecOrigin, vecOrigin + (vForward * 200), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  296. if( !m_pFlashlightBeam )
  297. {
  298. BeamInfo_t beamInfo;
  299. beamInfo.m_nType = TE_BEAMPOINTS;
  300. beamInfo.m_vecStart = tr.startpos;
  301. beamInfo.m_vecEnd = tr.endpos;
  302. beamInfo.m_pszModelName = "sprites/glow01.vmt";
  303. beamInfo.m_pszHaloName = "sprites/glow01.vmt";
  304. beamInfo.m_flHaloScale = 3.0;
  305. beamInfo.m_flWidth = 8.0f;
  306. beamInfo.m_flEndWidth = 35.0f;
  307. beamInfo.m_flFadeLength = 300.0f;
  308. beamInfo.m_flAmplitude = 0;
  309. beamInfo.m_flBrightness = 60.0;
  310. beamInfo.m_flSpeed = 0.0f;
  311. beamInfo.m_nStartFrame = 0.0;
  312. beamInfo.m_flFrameRate = 0.0;
  313. beamInfo.m_flRed = 255.0;
  314. beamInfo.m_flGreen = 255.0;
  315. beamInfo.m_flBlue = 255.0;
  316. beamInfo.m_nSegments = 8;
  317. beamInfo.m_bRenderable = true;
  318. beamInfo.m_flLife = 0.5;
  319. beamInfo.m_nFlags = FBEAM_FOREVER | FBEAM_ONLYNOISEONCE | FBEAM_NOTILE | FBEAM_HALOBEAM;
  320. m_pFlashlightBeam = beams->CreateBeamPoints( beamInfo );
  321. }
  322. if( m_pFlashlightBeam )
  323. {
  324. BeamInfo_t beamInfo;
  325. beamInfo.m_vecStart = tr.startpos;
  326. beamInfo.m_vecEnd = tr.endpos;
  327. beamInfo.m_flRed = 255.0;
  328. beamInfo.m_flGreen = 255.0;
  329. beamInfo.m_flBlue = 255.0;
  330. beams->UpdateBeamInfo( m_pFlashlightBeam, beamInfo );
  331. dlight_t *el = effects->CL_AllocDlight( 0 );
  332. el->origin = tr.endpos;
  333. el->radius = 50;
  334. el->color.r = 200;
  335. el->color.g = 200;
  336. el->color.b = 200;
  337. el->die = gpGlobals->curtime + 0.1;
  338. }
  339. }
  340. else if ( m_pFlashlightBeam )
  341. {
  342. ReleaseFlashlight();
  343. }
  344. }
  345. }
  346. ShadowType_t C_HL2MP_Player::ShadowCastType( void )
  347. {
  348. if ( !IsVisible() )
  349. return SHADOWS_NONE;
  350. return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
  351. }
  352. const QAngle& C_HL2MP_Player::GetRenderAngles()
  353. {
  354. if ( IsRagdoll() )
  355. {
  356. return vec3_angle;
  357. }
  358. else
  359. {
  360. return m_PlayerAnimState.GetRenderAngles();
  361. }
  362. }
  363. bool C_HL2MP_Player::ShouldDraw( void )
  364. {
  365. // If we're dead, our ragdoll will be drawn for us instead.
  366. if ( !IsAlive() )
  367. return false;
  368. // if( GetTeamNumber() == TEAM_SPECTATOR )
  369. // return false;
  370. if( IsLocalPlayer() && IsRagdoll() )
  371. return true;
  372. if ( IsRagdoll() )
  373. return false;
  374. return BaseClass::ShouldDraw();
  375. }
  376. void C_HL2MP_Player::NotifyShouldTransmit( ShouldTransmitState_t state )
  377. {
  378. if ( state == SHOULDTRANSMIT_END )
  379. {
  380. if( m_pFlashlightBeam != NULL )
  381. {
  382. ReleaseFlashlight();
  383. }
  384. }
  385. BaseClass::NotifyShouldTransmit( state );
  386. }
  387. void C_HL2MP_Player::OnDataChanged( DataUpdateType_t type )
  388. {
  389. BaseClass::OnDataChanged( type );
  390. if ( type == DATA_UPDATE_CREATED )
  391. {
  392. SetNextClientThink( CLIENT_THINK_ALWAYS );
  393. }
  394. UpdateVisibility();
  395. }
  396. void C_HL2MP_Player::PostDataUpdate( DataUpdateType_t updateType )
  397. {
  398. if ( m_iSpawnInterpCounter != m_iSpawnInterpCounterCache )
  399. {
  400. MoveToLastReceivedPosition( true );
  401. ResetLatched();
  402. m_iSpawnInterpCounterCache = m_iSpawnInterpCounter;
  403. }
  404. BaseClass::PostDataUpdate( updateType );
  405. }
  406. void C_HL2MP_Player::ReleaseFlashlight( void )
  407. {
  408. if( m_pFlashlightBeam )
  409. {
  410. m_pFlashlightBeam->flags = 0;
  411. m_pFlashlightBeam->die = gpGlobals->curtime - 1;
  412. m_pFlashlightBeam = NULL;
  413. }
  414. }
  415. float C_HL2MP_Player::GetFOV( void )
  416. {
  417. //Find our FOV with offset zoom value
  418. float flFOVOffset = C_BasePlayer::GetFOV() + GetZoom();
  419. // Clamp FOV in MP
  420. int min_fov = GetMinFOV();
  421. // Don't let it go too low
  422. flFOVOffset = MAX( min_fov, flFOVOffset );
  423. return flFOVOffset;
  424. }
  425. //=========================================================
  426. // Autoaim
  427. // set crosshair position to point to enemey
  428. //=========================================================
  429. Vector C_HL2MP_Player::GetAutoaimVector( float flDelta )
  430. {
  431. // Never autoaim a predicted weapon (for now)
  432. Vector forward;
  433. AngleVectors( EyeAngles() + m_Local.m_vecPunchAngle, &forward );
  434. return forward;
  435. }
  436. //-----------------------------------------------------------------------------
  437. // Purpose: Returns whether or not we are allowed to sprint now.
  438. //-----------------------------------------------------------------------------
  439. bool C_HL2MP_Player::CanSprint( void )
  440. {
  441. return ( (!m_Local.m_bDucked && !m_Local.m_bDucking) && (GetWaterLevel() != 3) );
  442. }
  443. //-----------------------------------------------------------------------------
  444. //-----------------------------------------------------------------------------
  445. void C_HL2MP_Player::StartSprinting( void )
  446. {
  447. if( m_HL2Local.m_flSuitPower < 10 )
  448. {
  449. // Don't sprint unless there's a reasonable
  450. // amount of suit power.
  451. CPASAttenuationFilter filter( this );
  452. filter.UsePredictionRules();
  453. EmitSound( filter, entindex(), "HL2Player.SprintNoPower" );
  454. return;
  455. }
  456. CPASAttenuationFilter filter( this );
  457. filter.UsePredictionRules();
  458. EmitSound( filter, entindex(), "HL2Player.SprintStart" );
  459. SetMaxSpeed( HL2_SPRINT_SPEED );
  460. m_fIsSprinting = true;
  461. }
  462. //-----------------------------------------------------------------------------
  463. //-----------------------------------------------------------------------------
  464. void C_HL2MP_Player::StopSprinting( void )
  465. {
  466. SetMaxSpeed( HL2_NORM_SPEED );
  467. m_fIsSprinting = false;
  468. }
  469. void C_HL2MP_Player::HandleSpeedChanges( void )
  470. {
  471. int buttonsChanged = m_afButtonPressed | m_afButtonReleased;
  472. if( buttonsChanged & IN_SPEED )
  473. {
  474. // The state of the sprint/run button has changed.
  475. if ( IsSuitEquipped() )
  476. {
  477. if ( !(m_afButtonPressed & IN_SPEED) && IsSprinting() )
  478. {
  479. StopSprinting();
  480. }
  481. else if ( (m_afButtonPressed & IN_SPEED) && !IsSprinting() )
  482. {
  483. if ( CanSprint() )
  484. {
  485. StartSprinting();
  486. }
  487. else
  488. {
  489. // Reset key, so it will be activated post whatever is suppressing it.
  490. m_nButtons &= ~IN_SPEED;
  491. }
  492. }
  493. }
  494. }
  495. else if( buttonsChanged & IN_WALK )
  496. {
  497. if ( IsSuitEquipped() )
  498. {
  499. // The state of the WALK button has changed.
  500. if( IsWalking() && !(m_afButtonPressed & IN_WALK) )
  501. {
  502. StopWalking();
  503. }
  504. else if( !IsWalking() && !IsSprinting() && (m_afButtonPressed & IN_WALK) && !(m_nButtons & IN_DUCK) )
  505. {
  506. StartWalking();
  507. }
  508. }
  509. }
  510. if ( IsSuitEquipped() && m_fIsWalking && !(m_nButtons & IN_WALK) )
  511. StopWalking();
  512. }
  513. //-----------------------------------------------------------------------------
  514. //-----------------------------------------------------------------------------
  515. void C_HL2MP_Player::StartWalking( void )
  516. {
  517. SetMaxSpeed( HL2_WALK_SPEED );
  518. m_fIsWalking = true;
  519. }
  520. //-----------------------------------------------------------------------------
  521. //-----------------------------------------------------------------------------
  522. void C_HL2MP_Player::StopWalking( void )
  523. {
  524. SetMaxSpeed( HL2_NORM_SPEED );
  525. m_fIsWalking = false;
  526. }
  527. void C_HL2MP_Player::ItemPreFrame( void )
  528. {
  529. if ( GetFlags() & FL_FROZEN )
  530. return;
  531. // Disallow shooting while zooming
  532. if ( m_nButtons & IN_ZOOM )
  533. {
  534. //FIXME: Held weapons like the grenade get sad when this happens
  535. m_nButtons &= ~(IN_ATTACK|IN_ATTACK2);
  536. }
  537. BaseClass::ItemPreFrame();
  538. }
  539. void C_HL2MP_Player::ItemPostFrame( void )
  540. {
  541. if ( GetFlags() & FL_FROZEN )
  542. return;
  543. BaseClass::ItemPostFrame();
  544. }
  545. C_BaseAnimating *C_HL2MP_Player::BecomeRagdollOnClient()
  546. {
  547. // Let the C_CSRagdoll entity do this.
  548. // m_builtRagdoll = true;
  549. return NULL;
  550. }
  551. void C_HL2MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov )
  552. {
  553. if ( m_lifeState != LIFE_ALIVE && !IsObserver() )
  554. {
  555. Vector origin = EyePosition();
  556. IRagdoll *pRagdoll = GetRepresentativeRagdoll();
  557. if ( pRagdoll )
  558. {
  559. origin = pRagdoll->GetRagdollOrigin();
  560. origin.z += VEC_DEAD_VIEWHEIGHT_SCALED( this ).z; // look over ragdoll, not through
  561. }
  562. BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov );
  563. eyeOrigin = origin;
  564. Vector vForward;
  565. AngleVectors( eyeAngles, &vForward );
  566. VectorNormalize( vForward );
  567. VectorMA( origin, -CHASE_CAM_DISTANCE_MAX, vForward, eyeOrigin );
  568. Vector WALL_MIN( -WALL_OFFSET, -WALL_OFFSET, -WALL_OFFSET );
  569. Vector WALL_MAX( WALL_OFFSET, WALL_OFFSET, WALL_OFFSET );
  570. trace_t trace; // clip against world
  571. C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace
  572. UTIL_TraceHull( origin, eyeOrigin, WALL_MIN, WALL_MAX, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace );
  573. C_BaseEntity::PopEnableAbsRecomputations();
  574. if (trace.fraction < 1.0)
  575. {
  576. eyeOrigin = trace.endpos;
  577. }
  578. return;
  579. }
  580. BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov );
  581. }
  582. IRagdoll* C_HL2MP_Player::GetRepresentativeRagdoll() const
  583. {
  584. if ( m_hRagdoll.Get() )
  585. {
  586. C_HL2MPRagdoll *pRagdoll = (C_HL2MPRagdoll*)m_hRagdoll.Get();
  587. return pRagdoll->GetIRagdoll();
  588. }
  589. else
  590. {
  591. return NULL;
  592. }
  593. }
  594. //HL2MPRAGDOLL
  595. IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_HL2MPRagdoll, DT_HL2MPRagdoll, CHL2MPRagdoll )
  596. RecvPropVector( RECVINFO(m_vecRagdollOrigin) ),
  597. RecvPropEHandle( RECVINFO( m_hPlayer ) ),
  598. RecvPropInt( RECVINFO( m_nModelIndex ) ),
  599. RecvPropInt( RECVINFO(m_nForceBone) ),
  600. RecvPropVector( RECVINFO(m_vecForce) ),
  601. RecvPropVector( RECVINFO( m_vecRagdollVelocity ) )
  602. END_RECV_TABLE()
  603. C_HL2MPRagdoll::C_HL2MPRagdoll()
  604. {
  605. }
  606. C_HL2MPRagdoll::~C_HL2MPRagdoll()
  607. {
  608. PhysCleanupFrictionSounds( this );
  609. if ( m_hPlayer )
  610. {
  611. m_hPlayer->CreateModelInstance();
  612. }
  613. }
  614. void C_HL2MPRagdoll::Interp_Copy( C_BaseAnimatingOverlay *pSourceEntity )
  615. {
  616. if ( !pSourceEntity )
  617. return;
  618. VarMapping_t *pSrc = pSourceEntity->GetVarMapping();
  619. VarMapping_t *pDest = GetVarMapping();
  620. // Find all the VarMapEntry_t's that represent the same variable.
  621. for ( int i = 0; i < pDest->m_Entries.Count(); i++ )
  622. {
  623. VarMapEntry_t *pDestEntry = &pDest->m_Entries[i];
  624. const char *pszName = pDestEntry->watcher->GetDebugName();
  625. for ( int j=0; j < pSrc->m_Entries.Count(); j++ )
  626. {
  627. VarMapEntry_t *pSrcEntry = &pSrc->m_Entries[j];
  628. if ( !Q_strcmp( pSrcEntry->watcher->GetDebugName(), pszName ) )
  629. {
  630. pDestEntry->watcher->Copy( pSrcEntry->watcher );
  631. break;
  632. }
  633. }
  634. }
  635. }
  636. void C_HL2MPRagdoll::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName )
  637. {
  638. IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
  639. if( !pPhysicsObject )
  640. return;
  641. Vector dir = pTrace->endpos - pTrace->startpos;
  642. if ( iDamageType == DMG_BLAST )
  643. {
  644. dir *= 4000; // adjust impact strenght
  645. // apply force at object mass center
  646. pPhysicsObject->ApplyForceCenter( dir );
  647. }
  648. else
  649. {
  650. Vector hitpos;
  651. VectorMA( pTrace->startpos, pTrace->fraction, dir, hitpos );
  652. VectorNormalize( dir );
  653. dir *= 4000; // adjust impact strenght
  654. // apply force where we hit it
  655. pPhysicsObject->ApplyForceOffset( dir, hitpos );
  656. // Blood spray!
  657. // FX_CS_BloodSpray( hitpos, dir, 10 );
  658. }
  659. m_pRagdoll->ResetRagdollSleepAfterTime();
  660. }
  661. void C_HL2MPRagdoll::CreateHL2MPRagdoll( void )
  662. {
  663. // First, initialize all our data. If we have the player's entity on our client,
  664. // then we can make ourselves start out exactly where the player is.
  665. C_HL2MP_Player *pPlayer = dynamic_cast< C_HL2MP_Player* >( m_hPlayer.Get() );
  666. if ( pPlayer && !pPlayer->IsDormant() )
  667. {
  668. // move my current model instance to the ragdoll's so decals are preserved.
  669. pPlayer->SnatchModelInstance( this );
  670. VarMapping_t *varMap = GetVarMapping();
  671. // Copy all the interpolated vars from the player entity.
  672. // The entity uses the interpolated history to get bone velocity.
  673. bool bRemotePlayer = (pPlayer != C_BasePlayer::GetLocalPlayer());
  674. if ( bRemotePlayer )
  675. {
  676. Interp_Copy( pPlayer );
  677. SetAbsAngles( pPlayer->GetRenderAngles() );
  678. GetRotationInterpolator().Reset();
  679. m_flAnimTime = pPlayer->m_flAnimTime;
  680. SetSequence( pPlayer->GetSequence() );
  681. m_flPlaybackRate = pPlayer->GetPlaybackRate();
  682. }
  683. else
  684. {
  685. // This is the local player, so set them in a default
  686. // pose and slam their velocity, angles and origin
  687. SetAbsOrigin( m_vecRagdollOrigin );
  688. SetAbsAngles( pPlayer->GetRenderAngles() );
  689. SetAbsVelocity( m_vecRagdollVelocity );
  690. int iSeq = pPlayer->GetSequence();
  691. if ( iSeq == -1 )
  692. {
  693. Assert( false ); // missing walk_lower?
  694. iSeq = 0;
  695. }
  696. SetSequence( iSeq ); // walk_lower, basic pose
  697. SetCycle( 0.0 );
  698. Interp_Reset( varMap );
  699. }
  700. }
  701. else
  702. {
  703. // overwrite network origin so later interpolation will
  704. // use this position
  705. SetNetworkOrigin( m_vecRagdollOrigin );
  706. SetAbsOrigin( m_vecRagdollOrigin );
  707. SetAbsVelocity( m_vecRagdollVelocity );
  708. Interp_Reset( GetVarMapping() );
  709. }
  710. SetModelIndex( m_nModelIndex );
  711. // Make us a ragdoll..
  712. m_nRenderFX = kRenderFxRagdoll;
  713. matrix3x4_t boneDelta0[MAXSTUDIOBONES];
  714. matrix3x4_t boneDelta1[MAXSTUDIOBONES];
  715. matrix3x4_t currentBones[MAXSTUDIOBONES];
  716. const float boneDt = 0.05f;
  717. if ( pPlayer && !pPlayer->IsDormant() )
  718. {
  719. pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
  720. }
  721. else
  722. {
  723. GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
  724. }
  725. InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
  726. }
  727. void C_HL2MPRagdoll::OnDataChanged( DataUpdateType_t type )
  728. {
  729. BaseClass::OnDataChanged( type );
  730. if ( type == DATA_UPDATE_CREATED )
  731. {
  732. CreateHL2MPRagdoll();
  733. }
  734. }
  735. IRagdoll* C_HL2MPRagdoll::GetIRagdoll() const
  736. {
  737. return m_pRagdoll;
  738. }
  739. void C_HL2MPRagdoll::UpdateOnRemove( void )
  740. {
  741. VPhysicsSetObject( NULL );
  742. BaseClass::UpdateOnRemove();
  743. }
  744. //-----------------------------------------------------------------------------
  745. // Purpose: clear out any face/eye values stored in the material system
  746. //-----------------------------------------------------------------------------
  747. void C_HL2MPRagdoll::SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights )
  748. {
  749. BaseClass::SetupWeights( pBoneToWorld, nFlexWeightCount, pFlexWeights, pFlexDelayedWeights );
  750. static float destweight[128];
  751. static bool bIsInited = false;
  752. CStudioHdr *hdr = GetModelPtr();
  753. if ( !hdr )
  754. return;
  755. int nFlexDescCount = hdr->numflexdesc();
  756. if ( nFlexDescCount )
  757. {
  758. Assert( !pFlexDelayedWeights );
  759. memset( pFlexWeights, 0, nFlexWeightCount * sizeof(float) );
  760. }
  761. if ( m_iEyeAttachment > 0 )
  762. {
  763. matrix3x4_t attToWorld;
  764. if (GetAttachment( m_iEyeAttachment, attToWorld ))
  765. {
  766. Vector local, tmp;
  767. local.Init( 1000.0f, 0.0f, 0.0f );
  768. VectorTransform( local, attToWorld, tmp );
  769. modelrender->SetViewTarget( GetModelPtr(), GetBody(), tmp );
  770. }
  771. }
  772. }
  773. void C_HL2MP_Player::PostThink( void )
  774. {
  775. BaseClass::PostThink();
  776. // Store the eye angles pitch so the client can compute its animation state correctly.
  777. m_angEyeAngles = EyeAngles();
  778. }