Guest User

Untitled

a guest
Jul 25th, 2016
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 111.64 KB | None | 0 0
  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Player for HL2.
  4. //
  5. //=============================================================================//
  6.  
  7. #include "cbase.h"
  8. #include "hl2_player.h"
  9. #include "globalstate.h"
  10. #include "game.h"
  11. #include "gamerules.h"
  12. #include "trains.h"
  13. #include "basehlcombatweapon_shared.h"
  14. #include "vcollide_parse.h"
  15. #include "in_buttons.h"
  16. #include "ai_interactions.h"
  17. #include "ai_squad.h"
  18. #include "igamemovement.h"
  19. #include "ai_hull.h"
  20. #include "hl2_shareddefs.h"
  21. #include "info_camera_link.h"
  22. #include "point_camera.h"
  23. #include "engine/IEngineSound.h"
  24. #include "ndebugoverlay.h"
  25. #include "iservervehicle.h"
  26. #include "IVehicle.h"
  27. #include "globals.h"
  28. #include "collisionutils.h"
  29. #include "coordsize.h"
  30. #include "effect_color_tables.h"
  31. #include "vphysics/player_controller.h"
  32. #include "player_pickup.h"
  33. #include "weapon_physcannon.h"
  34. #include "script_intro.h"
  35. #include "effect_dispatch_data.h"
  36. #include "te_effect_dispatch.h"
  37. #include "ai_basenpc.h"
  38. #include "AI_Criteria.h"
  39. #include "npc_barnacle.h"
  40. #include "entitylist.h"
  41. #include "env_zoom.h"
  42. #include "hl2_gamerules.h"
  43. #include "prop_combine_ball.h"
  44. #include "datacache/imdlcache.h"
  45. #include "eventqueue.h"
  46. #include "gamestats.h"
  47. #include "filters.h"
  48. #include "tier0/icommandline.h"
  49.  
  50. #ifdef HL2_EPISODIC
  51. #include "npc_alyx_episodic.h"
  52. #endif
  53.  
  54. #ifdef PORTAL
  55. #include "portal_player.h"
  56. #endif // PORTAL
  57.  
  58. // memdbgon must be the last include file in a .cpp file!!!
  59. #include "tier0/memdbgon.h"
  60.  
  61. extern ConVar weapon_showproficiency;
  62. extern ConVar autoaim_max_dist;
  63.  
  64. // Do not touch with without seeing me, please! (sjb)
  65. // For consistency's sake, enemy gunfire is traced against a scaled down
  66. // version of the player's hull, not the hitboxes for the player's model
  67. // because the player isn't aware of his model, and can't do anything about
  68. // preventing headshots and other such things. Also, game difficulty will
  69. // not change if the model changes. This is the value by which to scale
  70. // the X/Y of the player's hull to get the volume to trace bullets against.
  71. #define PLAYER_HULL_REDUCTION 0.70
  72.  
  73. // This switches between the single primary weapon, and multiple weapons with buckets approach (jdw)
  74. #define HL2_SINGLE_PRIMARY_WEAPON_MODE 0
  75.  
  76. #define TIME_IGNORE_FALL_DAMAGE 10.0
  77.  
  78. extern int gEvilImpulse101;
  79.  
  80. ConVar sv_autojump( "sv_autojump", "0" );
  81.  
  82. ConVar hl2_walkspeed( "hl2_walkspeed", "150" );
  83. ConVar hl2_normspeed( "hl2_normspeed", "190" );
  84. ConVar hl2_sprintspeed( "hl2_sprintspeed", "320" );
  85.  
  86. ConVar hl2_darkness_flashlight_factor ( "hl2_darkness_flashlight_factor", "1" );
  87.  
  88. #ifdef HL2MP
  89. #define HL2_WALK_SPEED 150
  90. #define HL2_NORM_SPEED 190
  91. #define HL2_SPRINT_SPEED 320
  92. #else
  93. #define HL2_WALK_SPEED hl2_walkspeed.GetFloat()
  94. #define HL2_NORM_SPEED hl2_normspeed.GetFloat()
  95. #define HL2_SPRINT_SPEED hl2_sprintspeed.GetFloat()
  96. #endif
  97.  
  98. ConVar player_showpredictedposition( "player_showpredictedposition", "0" );
  99. ConVar player_showpredictedposition_timestep( "player_showpredictedposition_timestep", "1.0" );
  100.  
  101. ConVar player_squad_transient_commands( "player_squad_transient_commands", "1", FCVAR_REPLICATED );
  102. ConVar player_squad_double_tap_time( "player_squad_double_tap_time", "0.25" );
  103.  
  104. ConVar sv_infinite_aux_power( "sv_infinite_aux_power", "0", FCVAR_CHEAT );
  105.  
  106. ConVar autoaim_unlock_target( "autoaim_unlock_target", "0.8666" );
  107.  
  108. ConVar sv_stickysprint("sv_stickysprint", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX);
  109.  
  110. #define FLASH_DRAIN_TIME 5 // 110 units / 5 secs
  111. #define FLASH_CHARGE_TIME 5.1111f // 2 units / 75 secs
  112.  
  113.  
  114. //==============================================================================================
  115. // CAPPED PLAYER PHYSICS DAMAGE TABLE
  116. //==============================================================================================
  117. static impactentry_t cappedPlayerLinearTable[] =
  118. {
  119. { 150*150, 5 },
  120. { 250*250, 10 },
  121. { 450*450, 20 },
  122. { 550*550, 30 },
  123. //{ 700*700, 100 },
  124. //{ 1000*1000, 500 },
  125. };
  126.  
  127. static impactentry_t cappedPlayerAngularTable[] =
  128. {
  129. { 100*100, 10 },
  130. { 150*150, 20 },
  131. { 200*200, 30 },
  132. //{ 300*300, 500 },
  133. };
  134.  
  135. static impactdamagetable_t gCappedPlayerImpactDamageTable =
  136. {
  137. cappedPlayerLinearTable,
  138. cappedPlayerAngularTable,
  139.  
  140. ARRAYSIZE(cappedPlayerLinearTable),
  141. ARRAYSIZE(cappedPlayerAngularTable),
  142.  
  143. 24*24.0f, // minimum linear speed
  144. 360*360.0f, // minimum angular speed
  145. 2.0f, // can't take damage from anything under 2kg
  146.  
  147. 5.0f, // anything less than 5kg is "small"
  148. 5.0f, // never take more than 5 pts of damage from anything under 5kg
  149. 36*36.0f, // <5kg objects must go faster than 36 in/s to do damage
  150.  
  151. 0.0f, // large mass in kg (no large mass effects)
  152. 1.0f, // large mass scale
  153. 2.0f, // large mass falling scale
  154. 320.0f, // min velocity for player speed to cause damage
  155.  
  156. };
  157.  
  158. // Flashlight utility
  159. bool g_bCacheLegacyFlashlightStatus = true;
  160. bool g_bUseLegacyFlashlight;
  161. bool Flashlight_UseLegacyVersion( void )
  162. {
  163. // If this is the first run through, cache off what the answer should be (cannot change during a session)
  164. if ( g_bCacheLegacyFlashlightStatus )
  165. {
  166. char modDir[MAX_PATH];
  167. if ( UTIL_GetModDir( modDir, sizeof(modDir) ) == false )
  168. return false;
  169.  
  170. g_bUseLegacyFlashlight = ( !Q_strcmp( modDir, "hl2" ) ||
  171. !Q_strcmp( modDir, "episodic" ) ||
  172. !Q_strcmp( modDir, "lostcoast" ) || !Q_strcmp( modDir, "hl1" ));
  173.  
  174. g_bCacheLegacyFlashlightStatus = false;
  175. }
  176.  
  177. // Return the results
  178. return g_bUseLegacyFlashlight;
  179. }
  180.  
  181. //-----------------------------------------------------------------------------
  182. // Purpose: Used to relay outputs/inputs from the player to the world and viceversa
  183. //-----------------------------------------------------------------------------
  184. class CLogicPlayerProxy : public CLogicalEntity
  185. {
  186. DECLARE_CLASS( CLogicPlayerProxy, CLogicalEntity );
  187.  
  188. private:
  189.  
  190. DECLARE_DATADESC();
  191.  
  192. public:
  193.  
  194. COutputEvent m_OnFlashlightOn;
  195. COutputEvent m_OnFlashlightOff;
  196. COutputEvent m_PlayerHasAmmo;
  197. COutputEvent m_PlayerHasNoAmmo;
  198. COutputEvent m_PlayerDied;
  199. COutputEvent m_PlayerMissedAR2AltFire; // Player fired a combine ball which did not dissolve any enemies.
  200.  
  201. COutputInt m_RequestedPlayerHealth;
  202.  
  203. void InputRequestPlayerHealth( inputdata_t &inputdata );
  204. void InputSetFlashlightSlowDrain( inputdata_t &inputdata );
  205. void InputSetFlashlightNormalDrain( inputdata_t &inputdata );
  206. void InputSetPlayerHealth( inputdata_t &inputdata );
  207. void InputRequestAmmoState( inputdata_t &inputdata );
  208. void InputLowerWeapon( inputdata_t &inputdata );
  209. void InputEnableCappedPhysicsDamage( inputdata_t &inputdata );
  210. void InputDisableCappedPhysicsDamage( inputdata_t &inputdata );
  211. void InputSetLocatorTargetEntity( inputdata_t &inputdata );
  212. #ifdef PORTAL
  213. void InputSuppressCrosshair( inputdata_t &inputdata );
  214. #endif // PORTAL2
  215.  
  216. void Activate ( void );
  217.  
  218. bool PassesDamageFilter( const CTakeDamageInfo &info );
  219.  
  220. EHANDLE m_hPlayer;
  221. };
  222.  
  223.  
  224. //------------------------------------------------------------------------------
  225. //------------------------------------------------------------------------------
  226. void CC_ToggleZoom( void )
  227. {
  228. CBasePlayer* pPlayer = UTIL_GetCommandClient();
  229.  
  230. if( pPlayer )
  231. {
  232. CHL2_Player *pHL2Player = dynamic_cast<CHL2_Player*>(pPlayer);
  233.  
  234. if( pHL2Player && pHL2Player->IsSuitEquipped() )
  235. {
  236. pHL2Player->ToggleZoom();
  237. }
  238. }
  239. }
  240.  
  241. static ConCommand toggle_zoom("toggle_zoom", CC_ToggleZoom, "Toggles zoom display" );
  242.  
  243. // ConVar cl_forwardspeed( "cl_forwardspeed", "400", FCVAR_CHEAT ); // Links us to the client's version
  244. ConVar xc_crouch_range( "xc_crouch_range", "0.85", FCVAR_ARCHIVE, "Percentarge [1..0] of joystick range to allow ducking within" ); // Only 1/2 of the range is used
  245. ConVar xc_use_crouch_limiter( "xc_use_crouch_limiter", "0", FCVAR_ARCHIVE, "Use the crouch limiting logic on the controller" );
  246.  
  247. //------------------------------------------------------------------------------
  248. //------------------------------------------------------------------------------
  249. void CC_ToggleDuck( void )
  250. {
  251. CBasePlayer* pPlayer = UTIL_GetCommandClient();
  252. if ( pPlayer == NULL )
  253. return;
  254.  
  255. // Cannot be frozen
  256. if ( pPlayer->GetFlags() & FL_FROZEN )
  257. return;
  258.  
  259. static bool bChecked = false;
  260. static ConVar *pCVcl_forwardspeed = NULL;
  261. if ( !bChecked )
  262. {
  263. bChecked = true;
  264. pCVcl_forwardspeed = ( ConVar * )cvar->FindVar( "cl_forwardspeed" );
  265. }
  266.  
  267.  
  268. // If we're not ducked, do extra checking
  269. if ( xc_use_crouch_limiter.GetBool() )
  270. {
  271. if ( pPlayer->GetToggledDuckState() == false )
  272. {
  273. float flForwardSpeed = 400.0f;
  274. if ( pCVcl_forwardspeed )
  275. {
  276. flForwardSpeed = pCVcl_forwardspeed->GetFloat();
  277. }
  278.  
  279. flForwardSpeed = MAX( 1.0f, flForwardSpeed );
  280.  
  281. // Make sure we're not in the blindspot on the crouch detection
  282. float flStickDistPerc = ( pPlayer->GetStickDist() / flForwardSpeed ); // Speed is the magnitude
  283. if ( flStickDistPerc > xc_crouch_range.GetFloat() )
  284. return;
  285. }
  286. }
  287.  
  288. // Toggle the duck
  289. pPlayer->ToggleDuck();
  290. }
  291.  
  292. static ConCommand toggle_duck("toggle_duck", CC_ToggleDuck, "Toggles duck" );
  293.  
  294. #ifndef HL2MP
  295. #ifndef PORTAL
  296. LINK_ENTITY_TO_CLASS( player, CHL2_Player );
  297. #endif
  298. #endif
  299.  
  300. PRECACHE_REGISTER(player);
  301.  
  302. CBaseEntity *FindEntityForward( CBasePlayer *pMe, bool fHull );
  303.  
  304. BEGIN_SIMPLE_DATADESC( LadderMove_t )
  305. DEFINE_FIELD( m_bForceLadderMove, FIELD_BOOLEAN ),
  306. DEFINE_FIELD( m_bForceMount, FIELD_BOOLEAN ),
  307. DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
  308. DEFINE_FIELD( m_flArrivalTime, FIELD_TIME ),
  309. DEFINE_FIELD( m_vecGoalPosition, FIELD_POSITION_VECTOR ),
  310. DEFINE_FIELD( m_vecStartPosition, FIELD_POSITION_VECTOR ),
  311. DEFINE_FIELD( m_hForceLadder, FIELD_EHANDLE ),
  312. DEFINE_FIELD( m_hReservedSpot, FIELD_EHANDLE ),
  313. END_DATADESC()
  314.  
  315. // Global Savedata for HL2 player
  316. BEGIN_DATADESC( CHL2_Player )
  317.  
  318. DEFINE_FIELD( m_nControlClass, FIELD_INTEGER ),
  319. DEFINE_EMBEDDED( m_HL2Local ),
  320.  
  321. DEFINE_FIELD( m_bSprintEnabled, FIELD_BOOLEAN ),
  322. DEFINE_FIELD( m_flTimeAllSuitDevicesOff, FIELD_TIME ),
  323. DEFINE_FIELD( m_fIsSprinting, FIELD_BOOLEAN ),
  324. DEFINE_FIELD( m_fIsWalking, FIELD_BOOLEAN ),
  325.  
  326. /*
  327. // These are initialized every time the player calls Activate()
  328. DEFINE_FIELD( m_bIsAutoSprinting, FIELD_BOOLEAN ),
  329. DEFINE_FIELD( m_fAutoSprintMinTime, FIELD_TIME ),
  330. */
  331.  
  332. // Field is used within a single tick, no need to save restore
  333. // DEFINE_FIELD( m_bPlayUseDenySound, FIELD_BOOLEAN ),
  334. // m_pPlayerAISquad reacquired on load
  335.  
  336. DEFINE_AUTO_ARRAY( m_vecMissPositions, FIELD_POSITION_VECTOR ),
  337. DEFINE_FIELD( m_nNumMissPositions, FIELD_INTEGER ),
  338.  
  339. // m_pPlayerAISquad
  340. DEFINE_EMBEDDED( m_CommanderUpdateTimer ),
  341. // m_RealTimeLastSquadCommand
  342. DEFINE_FIELD( m_QueuedCommand, FIELD_INTEGER ),
  343.  
  344. DEFINE_FIELD( m_flTimeIgnoreFallDamage, FIELD_TIME ),
  345. DEFINE_FIELD( m_bIgnoreFallDamageResetAfterImpact, FIELD_BOOLEAN ),
  346.  
  347. // Suit power fields
  348. DEFINE_FIELD( m_flSuitPowerLoad, FIELD_FLOAT ),
  349.  
  350. DEFINE_FIELD( m_flIdleTime, FIELD_TIME ),
  351. DEFINE_FIELD( m_flMoveTime, FIELD_TIME ),
  352. DEFINE_FIELD( m_flLastDamageTime, FIELD_TIME ),
  353. DEFINE_FIELD( m_flTargetFindTime, FIELD_TIME ),
  354.  
  355. DEFINE_FIELD( m_flAdmireGlovesAnimTime, FIELD_TIME ),
  356. DEFINE_FIELD( m_flNextFlashlightCheckTime, FIELD_TIME ),
  357. DEFINE_FIELD( m_flFlashlightPowerDrainScale, FIELD_FLOAT ),
  358. DEFINE_FIELD( m_bFlashlightDisabled, FIELD_BOOLEAN ),
  359.  
  360. DEFINE_FIELD( m_bUseCappedPhysicsDamageTable, FIELD_BOOLEAN ),
  361.  
  362. DEFINE_FIELD( m_hLockedAutoAimEntity, FIELD_EHANDLE ),
  363.  
  364. DEFINE_EMBEDDED( m_LowerWeaponTimer ),
  365. DEFINE_EMBEDDED( m_AutoaimTimer ),
  366.  
  367. DEFINE_INPUTFUNC( FIELD_FLOAT, "IgnoreFallDamage", InputIgnoreFallDamage ),
  368. DEFINE_INPUTFUNC( FIELD_FLOAT, "IgnoreFallDamageWithoutReset", InputIgnoreFallDamageWithoutReset ),
  369. DEFINE_INPUTFUNC( FIELD_VOID, "OnSquadMemberKilled", OnSquadMemberKilled ),
  370. DEFINE_INPUTFUNC( FIELD_VOID, "DisableFlashlight", InputDisableFlashlight ),
  371. DEFINE_INPUTFUNC( FIELD_VOID, "EnableFlashlight", InputEnableFlashlight ),
  372. DEFINE_INPUTFUNC( FIELD_VOID, "ForceDropPhysObjects", InputForceDropPhysObjects ),
  373.  
  374. DEFINE_SOUNDPATCH( m_sndLeeches ),
  375. DEFINE_SOUNDPATCH( m_sndWaterSplashes ),
  376.  
  377. DEFINE_FIELD( m_flArmorReductionTime, FIELD_TIME ),
  378. DEFINE_FIELD( m_iArmorReductionFrom, FIELD_INTEGER ),
  379.  
  380. DEFINE_FIELD( m_flTimeUseSuspended, FIELD_TIME ),
  381.  
  382. DEFINE_FIELD( m_hLocatorTargetEntity, FIELD_EHANDLE ),
  383.  
  384. DEFINE_FIELD( m_flTimeNextLadderHint, FIELD_TIME ),
  385.  
  386. //DEFINE_FIELD( m_hPlayerProxy, FIELD_EHANDLE ), //Shut up class check!
  387.  
  388. END_DATADESC()
  389.  
  390. CHL2_Player::CHL2_Player()
  391. {
  392. hasFlashlight = false;
  393. m_nNumMissPositions = 0;
  394. m_pPlayerAISquad = 0;
  395. m_bSprintEnabled = true;
  396.  
  397. m_flArmorReductionTime = 0.0f;
  398. m_iArmorReductionFrom = 0;
  399. }
  400.  
  401. //
  402. // SUIT POWER DEVICES
  403. //
  404. #define SUITPOWER_CHARGE_RATE 12.5 // 100 units in 8 seconds
  405.  
  406. #ifdef HL2MP
  407. CSuitPowerDevice SuitDeviceSprint( bits_SUIT_DEVICE_SPRINT, 25.0f ); // 100 units in 4 seconds
  408. #else
  409. CSuitPowerDevice SuitDeviceSprint( bits_SUIT_DEVICE_SPRINT, 12.5f ); // 100 units in 8 seconds
  410. #endif
  411.  
  412. #ifdef HL2_EPISODIC
  413. CSuitPowerDevice SuitDeviceFlashlight( bits_SUIT_DEVICE_FLASHLIGHT, 1.111 ); // 100 units in 90 second
  414. #else
  415. CSuitPowerDevice SuitDeviceFlashlight( bits_SUIT_DEVICE_FLASHLIGHT, 2.222 ); // 100 units in 45 second
  416. #endif
  417. CSuitPowerDevice SuitDeviceBreather( bits_SUIT_DEVICE_BREATHER, 6.7f ); // 100 units in 15 seconds (plus three padded seconds)
  418.  
  419.  
  420. IMPLEMENT_SERVERCLASS_ST(CHL2_Player, DT_HL2_Player)
  421. SendPropDataTable(SENDINFO_DT(m_HL2Local), &REFERENCE_SEND_TABLE(DT_HL2Local), SendProxy_SendLocalDataTable),
  422. SendPropBool( SENDINFO(m_fIsSprinting) ),
  423. END_SEND_TABLE()
  424.  
  425.  
  426. void CHL2_Player::Precache( void )
  427. {
  428. BaseClass::Precache();
  429.  
  430. PrecacheScriptSound( "HL2Player.SprintNoPower" );
  431. PrecacheScriptSound( "HL2Player.SprintStart" );
  432. PrecacheScriptSound( "HL2Player.UseDeny" );
  433. PrecacheScriptSound( "HL2Player.FlashLightOn" );
  434. PrecacheScriptSound( "HL2Player.FlashLightOff" );
  435. PrecacheScriptSound( "HL2Player.PickupWeapon" );
  436. PrecacheScriptSound( "HL2Player.TrainUse" );
  437. PrecacheScriptSound( "HL2Player.Use" );
  438. PrecacheScriptSound( "HL2Player.BurnPain" );
  439. }
  440.  
  441. //-----------------------------------------------------------------------------
  442. // Purpose:
  443. //-----------------------------------------------------------------------------
  444. void CHL2_Player::CheckSuitZoom( void )
  445. {
  446. //#ifndef _XBOX
  447. //Adrian - No zooming without a suit!
  448. if ( IsSuitEquipped() )
  449. {
  450. if ( m_afButtonReleased & IN_ZOOM )
  451. {
  452. StopZooming();
  453. }
  454. else if ( m_afButtonPressed & IN_ZOOM )
  455. {
  456. StartZooming();
  457. }
  458. }
  459. //#endif//_XBOX
  460. }
  461.  
  462. void CHL2_Player::EquipSuit( bool bPlayEffects )
  463. {
  464. MDLCACHE_CRITICAL_SECTION();
  465. BaseClass::EquipSuit();
  466.  
  467. m_HL2Local.m_bDisplayReticle = true;
  468.  
  469. if ( bPlayEffects == true )
  470. {
  471. StartAdmireGlovesAnimation();
  472. }
  473. }
  474.  
  475. void CHL2_Player::RemoveSuit( void )
  476. {
  477. BaseClass::RemoveSuit();
  478.  
  479. m_HL2Local.m_bDisplayReticle = false;
  480. }
  481.  
  482. void CHL2_Player::HandleSpeedChanges( void )
  483. {
  484. int buttonsChanged = m_afButtonPressed | m_afButtonReleased;
  485.  
  486. bool bCanSprint = CanSprint();
  487. bool bIsSprinting = IsSprinting();
  488. bool bWantSprint = ( bCanSprint && IsSuitEquipped() && (m_nButtons & IN_SPEED) );
  489. if ( bIsSprinting != bWantSprint && (buttonsChanged & IN_SPEED) )
  490. {
  491. // If someone wants to sprint, make sure they've pressed the button to do so. We want to prevent the
  492. // case where a player can hold down the sprint key and burn tiny bursts of sprint as the suit recharges
  493. // We want a full debounce of the key to resume sprinting after the suit is completely drained
  494. if ( bWantSprint )
  495. {
  496. if ( sv_stickysprint.GetBool() )
  497. {
  498. StartAutoSprint();
  499. }
  500. else
  501. {
  502. StartSprinting();
  503. }
  504. }
  505. else
  506. {
  507. if ( !sv_stickysprint.GetBool() )
  508. {
  509. StopSprinting();
  510. }
  511. // Reset key, so it will be activated post whatever is suppressing it.
  512. m_nButtons &= ~IN_SPEED;
  513. }
  514. }
  515.  
  516. bool bIsWalking = IsWalking();
  517. // have suit, pressing button, not sprinting or ducking
  518. bool bWantWalking;
  519.  
  520. if( IsSuitEquipped() )
  521. {
  522. bWantWalking = (m_nButtons & IN_WALK) && !IsSprinting() && !(m_nButtons & IN_DUCK);
  523. }
  524. else
  525. {
  526. bWantWalking = true;
  527. }
  528.  
  529. if( bIsWalking != bWantWalking )
  530. {
  531. if ( bWantWalking )
  532. {
  533. StartWalking();
  534. }
  535. else
  536. {
  537. StopWalking();
  538. }
  539. }
  540. }
  541.  
  542. //-----------------------------------------------------------------------------
  543. // This happens when we powerdown from the mega physcannon to the regular one
  544. //-----------------------------------------------------------------------------
  545. void CHL2_Player::HandleArmorReduction( void )
  546. {
  547. if ( m_flArmorReductionTime < gpGlobals->curtime )
  548. return;
  549.  
  550. if ( ArmorValue() <= 0 )
  551. return;
  552.  
  553. float flPercent = 1.0f - (( m_flArmorReductionTime - gpGlobals->curtime ) / ARMOR_DECAY_TIME );
  554.  
  555. int iArmor = Lerp( flPercent, m_iArmorReductionFrom, 0 );
  556.  
  557. SetArmorValue( iArmor );
  558. }
  559.  
  560. //-----------------------------------------------------------------------------
  561. // Purpose: Allow pre-frame adjustments on the player
  562. //-----------------------------------------------------------------------------
  563. void CHL2_Player::PreThink(void)
  564. {
  565. if ( player_showpredictedposition.GetBool() )
  566. {
  567. Vector predPos;
  568.  
  569. UTIL_PredictedPosition( this, player_showpredictedposition_timestep.GetFloat(), &predPos );
  570.  
  571. NDebugOverlay::Box( predPos, NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), 0, 255, 0, 0, 0.01f );
  572. NDebugOverlay::Line( GetAbsOrigin(), predPos, 0, 255, 0, 0, 0.01f );
  573. }
  574.  
  575. #ifdef HL2_EPISODIC
  576. if( m_hLocatorTargetEntity != NULL )
  577. {
  578. // Keep track of the entity here, the client will pick up the rest of the work
  579. m_HL2Local.m_vecLocatorOrigin = m_hLocatorTargetEntity->WorldSpaceCenter();
  580. }
  581. else
  582. {
  583. m_HL2Local.m_vecLocatorOrigin = vec3_invalid; // This tells the client we have no locator target.
  584. }
  585. #endif//HL2_EPISODIC
  586.  
  587. // Riding a vehicle?
  588. if ( IsInAVehicle() )
  589. {
  590. VPROF( "CHL2_Player::PreThink-Vehicle" );
  591. // make sure we update the client, check for timed damage and update suit even if we are in a vehicle
  592. UpdateClientData();
  593. CheckTimeBasedDamage();
  594.  
  595. // Allow the suit to recharge when in the vehicle.
  596. SuitPower_Update();
  597. CheckSuitUpdate();
  598. CheckSuitZoom();
  599.  
  600. WaterMove();
  601. return;
  602. }
  603.  
  604. // This is an experiment of mine- autojumping!
  605. // only affects you if sv_autojump is nonzero.
  606. if( (GetFlags() & FL_ONGROUND) && sv_autojump.GetFloat() != 0 )
  607. {
  608. VPROF( "CHL2_Player::PreThink-Autojump" );
  609. // check autojump
  610. Vector vecCheckDir;
  611.  
  612. vecCheckDir = GetAbsVelocity();
  613.  
  614. float flVelocity = VectorNormalize( vecCheckDir );
  615.  
  616. if( flVelocity > 200 )
  617. {
  618. // Going fast enough to autojump
  619. vecCheckDir = WorldSpaceCenter() + vecCheckDir * 34 - Vector( 0, 0, 16 );
  620.  
  621. trace_t tr;
  622.  
  623. UTIL_TraceHull( WorldSpaceCenter() - Vector( 0, 0, 16 ), vecCheckDir, NAI_Hull::Mins(HULL_TINY_CENTERED),NAI_Hull::Maxs(HULL_TINY_CENTERED), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER, &tr );
  624.  
  625. //NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 10 );
  626.  
  627. if( tr.fraction == 1.0 && !tr.startsolid )
  628. {
  629. // Now trace down!
  630. UTIL_TraceLine( vecCheckDir, vecCheckDir - Vector( 0, 0, 64 ), MASK_PLAYERSOLID, this, COLLISION_GROUP_NONE, &tr );
  631.  
  632. //NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 10 );
  633.  
  634. if( tr.fraction == 1.0 && !tr.startsolid )
  635. {
  636. // !!!HACKHACK
  637. // I KNOW, I KNOW, this is definitely not the right way to do this,
  638. // but I'm prototyping! (sjb)
  639. Vector vecNewVelocity = GetAbsVelocity();
  640. vecNewVelocity.z += 250;
  641. SetAbsVelocity( vecNewVelocity );
  642. }
  643. }
  644. }
  645. }
  646.  
  647. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-Speed" );
  648. HandleSpeedChanges();
  649. #ifdef HL2_EPISODIC
  650. HandleArmorReduction();
  651. #endif
  652.  
  653. if( sv_stickysprint.GetBool() && m_bIsAutoSprinting )
  654. {
  655. // If we're ducked and not in the air
  656. if( IsDucked() && GetGroundEntity() != NULL )
  657. {
  658. StopSprinting();
  659. }
  660. // Stop sprinting if the player lets off the stick for a moment.
  661. else if( GetStickDist() == 0.0f )
  662. {
  663. if( gpGlobals->curtime > m_fAutoSprintMinTime )
  664. {
  665. StopSprinting();
  666. }
  667. }
  668. else
  669. {
  670. // Stop sprinting one half second after the player stops inputting with the move stick.
  671. m_fAutoSprintMinTime = gpGlobals->curtime + 0.5f;
  672. }
  673. }
  674. else if ( IsSprinting() )
  675. {
  676. // Disable sprint while ducked unless we're in the air (jumping)
  677. if ( IsDucked() && ( GetGroundEntity() != NULL ) )
  678. {
  679. StopSprinting();
  680. }
  681. }
  682.  
  683. VPROF_SCOPE_END();
  684.  
  685. if ( g_fGameOver || IsPlayerLockedInPlace() )
  686. return; // finale
  687.  
  688. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-ItemPreFrame" );
  689. ItemPreFrame( );
  690. VPROF_SCOPE_END();
  691.  
  692. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-WaterMove" );
  693. WaterMove();
  694. VPROF_SCOPE_END();
  695.  
  696. if ( g_pGameRules && g_pGameRules->FAllowFlashlight() )
  697. m_Local.m_iHideHUD &= ~HIDEHUD_FLASHLIGHT;
  698. else
  699. m_Local.m_iHideHUD |= HIDEHUD_FLASHLIGHT;
  700.  
  701.  
  702. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CommanderUpdate" );
  703. CommanderUpdate();
  704. VPROF_SCOPE_END();
  705.  
  706. // Operate suit accessories and manage power consumption/charge
  707. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-SuitPower_Update" );
  708. SuitPower_Update();
  709. VPROF_SCOPE_END();
  710.  
  711. // checks if new client data (for HUD and view control) needs to be sent to the client
  712. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-UpdateClientData" );
  713. UpdateClientData();
  714. VPROF_SCOPE_END();
  715.  
  716. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CheckTimeBasedDamage" );
  717. CheckTimeBasedDamage();
  718. VPROF_SCOPE_END();
  719.  
  720. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CheckSuitUpdate" );
  721. CheckSuitUpdate();
  722. VPROF_SCOPE_END();
  723.  
  724. VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CheckSuitZoom" );
  725. CheckSuitZoom();
  726. VPROF_SCOPE_END();
  727.  
  728. if (m_lifeState >= LIFE_DYING)
  729. {
  730. PlayerDeathThink();
  731. return;
  732. }
  733.  
  734. #ifdef HL2_EPISODIC
  735. CheckFlashlight();
  736. #endif // HL2_EPISODIC
  737.  
  738. // So the correct flags get sent to client asap.
  739. //
  740. if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE )
  741. AddFlag( FL_ONTRAIN );
  742. else
  743. RemoveFlag( FL_ONTRAIN );
  744.  
  745. // Train speed control
  746. if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE )
  747. {
  748. CBaseEntity *pTrain = GetGroundEntity();
  749. float vel;
  750.  
  751. if ( pTrain )
  752. {
  753. if ( !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) )
  754. pTrain = NULL;
  755. }
  756.  
  757. if ( !pTrain )
  758. {
  759. if ( GetActiveWeapon() && (GetActiveWeapon()->ObjectCaps() & FCAP_DIRECTIONAL_USE) )
  760. {
  761. m_iTrain = TRAIN_ACTIVE | TRAIN_NEW;
  762.  
  763. if ( m_nButtons & IN_FORWARD )
  764. {
  765. m_iTrain |= TRAIN_FAST;
  766. }
  767. else if ( m_nButtons & IN_BACK )
  768. {
  769. m_iTrain |= TRAIN_BACK;
  770. }
  771. else
  772. {
  773. m_iTrain |= TRAIN_NEUTRAL;
  774. }
  775. return;
  776. }
  777. else
  778. {
  779. trace_t trainTrace;
  780. // Maybe this is on the other side of a level transition
  781. UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,-38),
  782. MASK_PLAYERSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trainTrace );
  783.  
  784. if ( trainTrace.fraction != 1.0 && trainTrace.m_pEnt )
  785. pTrain = trainTrace.m_pEnt;
  786.  
  787.  
  788. if ( !pTrain || !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) || !pTrain->OnControls(this) )
  789. {
  790. // Warning( "In train mode with no train!\n" );
  791. m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE;
  792. m_iTrain = TRAIN_NEW|TRAIN_OFF;
  793. return;
  794. }
  795. }
  796. }
  797. else if ( !( GetFlags() & FL_ONGROUND ) || pTrain->HasSpawnFlags( SF_TRACKTRAIN_NOCONTROL ) || (m_nButtons & (IN_MOVELEFT|IN_MOVERIGHT) ) )
  798. {
  799. // Turn off the train if you jump, strafe, or the train controls go dead
  800. m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE;
  801. m_iTrain = TRAIN_NEW|TRAIN_OFF;
  802. return;
  803. }
  804.  
  805. SetAbsVelocity( vec3_origin );
  806. vel = 0;
  807. if ( m_afButtonPressed & IN_FORWARD )
  808. {
  809. vel = 1;
  810. pTrain->Use( this, this, USE_SET, (float)vel );
  811. }
  812. else if ( m_afButtonPressed & IN_BACK )
  813. {
  814. vel = -1;
  815. pTrain->Use( this, this, USE_SET, (float)vel );
  816. }
  817.  
  818. if (vel)
  819. {
  820. m_iTrain = TrainSpeed(pTrain->m_flSpeed, ((CFuncTrackTrain*)pTrain)->GetMaxSpeed());
  821. m_iTrain |= TRAIN_ACTIVE|TRAIN_NEW;
  822. }
  823. }
  824. else if (m_iTrain & TRAIN_ACTIVE)
  825. {
  826. m_iTrain = TRAIN_NEW; // turn off train
  827. }
  828.  
  829.  
  830. //
  831. // If we're not on the ground, we're falling. Update our falling velocity.
  832. //
  833. if ( !( GetFlags() & FL_ONGROUND ) )
  834. {
  835. m_Local.m_flFallVelocity = -GetAbsVelocity().z;
  836. }
  837.  
  838. if ( m_afPhysicsFlags & PFLAG_ONBARNACLE )
  839. {
  840. bool bOnBarnacle = false;
  841. CNPC_Barnacle *pBarnacle = NULL;
  842. do
  843. {
  844. // FIXME: Not a good or fast solution, but maybe it will catch the bug!
  845. pBarnacle = (CNPC_Barnacle*)gEntList.FindEntityByClassname( pBarnacle, "npc_barnacle" );
  846. if ( pBarnacle )
  847. {
  848. if ( pBarnacle->GetEnemy() == this )
  849. {
  850. bOnBarnacle = true;
  851. }
  852. }
  853. } while ( pBarnacle );
  854.  
  855. if ( !bOnBarnacle )
  856. {
  857. Warning( "Attached to barnacle?\n" );
  858. Assert( 0 );
  859. m_afPhysicsFlags &= ~PFLAG_ONBARNACLE;
  860. }
  861. else
  862. {
  863. SetAbsVelocity( vec3_origin );
  864. }
  865. }
  866. // StudioFrameAdvance( );//!!!HACKHACK!!! Can't be hit by traceline when not animating?
  867.  
  868. // Update weapon's ready status
  869. UpdateWeaponPosture();
  870.  
  871. // Disallow shooting while zooming
  872. if ( IsX360() )
  873. {
  874. if ( IsZooming() )
  875. {
  876. if( GetActiveWeapon() && !GetActiveWeapon()->IsWeaponZoomed() )
  877. {
  878. // If not zoomed because of the weapon itself, do not attack.
  879. m_nButtons &= ~(IN_ATTACK|IN_ATTACK2);
  880. }
  881. }
  882. }
  883. else
  884. {
  885. if ( m_nButtons & IN_ZOOM )
  886. {
  887. //FIXME: Held weapons like the grenade get sad when this happens
  888. #ifdef HL2_EPISODIC
  889. // Episodic allows players to zoom while using a func_tank
  890. CBaseCombatWeapon* pWep = GetActiveWeapon();
  891. if ( !m_hUseEntity || ( pWep && pWep->IsWeaponVisible() ) )
  892. #endif
  893. m_nButtons &= ~(IN_ATTACK|IN_ATTACK2);
  894. }
  895. }
  896. }
  897.  
  898. void CHL2_Player::PostThink( void )
  899. {
  900. BaseClass::PostThink();
  901.  
  902. if ( !g_fGameOver && !IsPlayerLockedInPlace() && IsAlive() )
  903. {
  904. HandleAdmireGlovesAnimation();
  905. }
  906. }
  907.  
  908. void CHL2_Player::StartAdmireGlovesAnimation( void )
  909. {
  910. MDLCACHE_CRITICAL_SECTION();
  911. CBaseViewModel *vm = GetViewModel( 0 );
  912.  
  913. if ( vm && !GetActiveWeapon() )
  914. {
  915. vm->SetWeaponModel( "models/weapons/v_hands.mdl", NULL );
  916. ShowViewModel( true );
  917.  
  918. int idealSequence = vm->SelectWeightedSequence( ACT_VM_IDLE );
  919.  
  920. if ( idealSequence >= 0 )
  921. {
  922. vm->SendViewModelMatchingSequence( idealSequence );
  923. m_flAdmireGlovesAnimTime = gpGlobals->curtime + vm->SequenceDuration( idealSequence );
  924. }
  925. }
  926. }
  927.  
  928. void CHL2_Player::HandleAdmireGlovesAnimation( void )
  929. {
  930. CBaseViewModel *pVM = GetViewModel();
  931.  
  932. if ( pVM && pVM->GetOwningWeapon() == NULL )
  933. {
  934. if ( m_flAdmireGlovesAnimTime != 0.0 )
  935. {
  936. if ( m_flAdmireGlovesAnimTime > gpGlobals->curtime )
  937. {
  938. pVM->m_flPlaybackRate = 1.0f;
  939. pVM->StudioFrameAdvance( );
  940. }
  941. else if ( m_flAdmireGlovesAnimTime < gpGlobals->curtime )
  942. {
  943. m_flAdmireGlovesAnimTime = 0.0f;
  944. pVM->SetWeaponModel( NULL, NULL );
  945. }
  946. }
  947. }
  948. else
  949. m_flAdmireGlovesAnimTime = 0.0f;
  950. }
  951.  
  952. #define HL2PLAYER_RELOADGAME_ATTACK_DELAY 1.0f
  953.  
  954. void CHL2_Player::Activate( void )
  955. {
  956. BaseClass::Activate();
  957. InitSprinting();
  958.  
  959. #ifdef HL2_EPISODIC
  960.  
  961. // Delay attacks by 1 second after loading a game.
  962. if ( GetActiveWeapon() )
  963. {
  964. float flRemaining = GetActiveWeapon()->m_flNextPrimaryAttack - gpGlobals->curtime;
  965.  
  966. if ( flRemaining < HL2PLAYER_RELOADGAME_ATTACK_DELAY )
  967. {
  968. GetActiveWeapon()->m_flNextPrimaryAttack = gpGlobals->curtime + HL2PLAYER_RELOADGAME_ATTACK_DELAY;
  969. }
  970.  
  971. flRemaining = GetActiveWeapon()->m_flNextSecondaryAttack - gpGlobals->curtime;
  972.  
  973. if ( flRemaining < HL2PLAYER_RELOADGAME_ATTACK_DELAY )
  974. {
  975. GetActiveWeapon()->m_flNextSecondaryAttack = gpGlobals->curtime + HL2PLAYER_RELOADGAME_ATTACK_DELAY;
  976. }
  977. }
  978.  
  979. #endif
  980.  
  981. GetPlayerProxy();
  982. }
  983.  
  984. //------------------------------------------------------------------------------
  985. // Purpose :
  986. // Input :
  987. // Output :
  988. //------------------------------------------------------------------------------
  989. Class_T CHL2_Player::Classify ( void )
  990. {
  991. // If player controlling another entity? If so, return this class
  992. if (m_nControlClass != CLASS_NONE)
  993. {
  994. return m_nControlClass;
  995. }
  996. else
  997. {
  998. if(IsInAVehicle())
  999. {
  1000. IServerVehicle *pVehicle = GetVehicle();
  1001. return pVehicle->ClassifyPassenger( this, CLASS_PLAYER );
  1002. }
  1003. else
  1004. {
  1005. return CLASS_PLAYER;
  1006. }
  1007. }
  1008. }
  1009.  
  1010. //-----------------------------------------------------------------------------
  1011. // Purpose: This is a generic function (to be implemented by sub-classes) to
  1012. // handle specific interactions between different types of characters
  1013. // (For example the barnacle grabbing an NPC)
  1014. // Input : Constant for the type of interaction
  1015. // Output : true - if sub-class has a response for the interaction
  1016. // false - if sub-class has no response
  1017. //-----------------------------------------------------------------------------
  1018. bool CHL2_Player::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt)
  1019. {
  1020. if ( interactionType == g_interactionBarnacleVictimDangle )
  1021. return false;
  1022.  
  1023. if (interactionType == g_interactionBarnacleVictimReleased)
  1024. {
  1025. m_afPhysicsFlags &= ~PFLAG_ONBARNACLE;
  1026. SetMoveType( MOVETYPE_WALK );
  1027. return true;
  1028. }
  1029. else if (interactionType == g_interactionBarnacleVictimGrab)
  1030. {
  1031. #ifdef HL2_EPISODIC
  1032. CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx();
  1033. if ( pAlyx )
  1034. {
  1035. // Make Alyx totally hate this barnacle so that she saves the player.
  1036. int priority;
  1037.  
  1038. priority = pAlyx->IRelationPriority(sourceEnt);
  1039. pAlyx->AddEntityRelationship( sourceEnt, D_HT, priority + 5 );
  1040. }
  1041. #endif//HL2_EPISODIC
  1042.  
  1043. m_afPhysicsFlags |= PFLAG_ONBARNACLE;
  1044. ClearUseEntity();
  1045. return true;
  1046. }
  1047. return false;
  1048. }
  1049.  
  1050.  
  1051. void CHL2_Player::PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper)
  1052. {
  1053. // Handle FL_FROZEN.
  1054. if ( m_afPhysicsFlags & PFLAG_ONBARNACLE )
  1055. {
  1056. ucmd->forwardmove = 0;
  1057. ucmd->sidemove = 0;
  1058. ucmd->upmove = 0;
  1059. ucmd->buttons &= ~IN_USE;
  1060. }
  1061.  
  1062. // Can't use stuff while dead
  1063. if ( IsDead() )
  1064. {
  1065. ucmd->buttons &= ~IN_USE;
  1066. }
  1067.  
  1068. //Update our movement information
  1069. if ( ( ucmd->forwardmove != 0 ) || ( ucmd->sidemove != 0 ) || ( ucmd->upmove != 0 ) )
  1070. {
  1071. m_flIdleTime -= TICK_INTERVAL * 2.0f;
  1072.  
  1073. if ( m_flIdleTime < 0.0f )
  1074. {
  1075. m_flIdleTime = 0.0f;
  1076. }
  1077.  
  1078. m_flMoveTime += TICK_INTERVAL;
  1079.  
  1080. if ( m_flMoveTime > 4.0f )
  1081. {
  1082. m_flMoveTime = 4.0f;
  1083. }
  1084. }
  1085. else
  1086. {
  1087. m_flIdleTime += TICK_INTERVAL;
  1088.  
  1089. if ( m_flIdleTime > 4.0f )
  1090. {
  1091. m_flIdleTime = 4.0f;
  1092. }
  1093.  
  1094. m_flMoveTime -= TICK_INTERVAL * 2.0f;
  1095.  
  1096. if ( m_flMoveTime < 0.0f )
  1097. {
  1098. m_flMoveTime = 0.0f;
  1099. }
  1100. }
  1101.  
  1102. //Msg("Player time: [ACTIVE: %f]\t[IDLE: %f]\n", m_flMoveTime, m_flIdleTime );
  1103.  
  1104. BaseClass::PlayerRunCommand( ucmd, moveHelper );
  1105. }
  1106.  
  1107. //-----------------------------------------------------------------------------
  1108. // Purpose: Sets HL2 specific defaults.
  1109. //-----------------------------------------------------------------------------
  1110. void CHL2_Player::Spawn(void)
  1111. {
  1112.  
  1113. #ifndef HL2MP
  1114. #ifndef PORTAL
  1115. SetModel( "models/player.mdl" );
  1116. #endif
  1117. #endif
  1118.  
  1119. BaseClass::Spawn();
  1120.  
  1121. //
  1122. // Our player movement speed is set once here. This will override the cl_xxxx
  1123. // cvars unless they are set to be lower than this.
  1124. //
  1125. //m_flMaxspeed = 320;
  1126.  
  1127. if ( !IsSuitEquipped() )
  1128. StartWalking();
  1129.  
  1130. SuitPower_SetCharge( 100 );
  1131.  
  1132. m_Local.m_iHideHUD |= HIDEHUD_CHAT;
  1133.  
  1134. m_pPlayerAISquad = g_AI_SquadManager.FindCreateSquad(AllocPooledString(PLAYER_SQUADNAME));
  1135.  
  1136. InitSprinting();
  1137.  
  1138. // Setup our flashlight values
  1139. #ifdef HL2_EPISODIC
  1140. m_HL2Local.m_flFlashBattery = 100.0f;
  1141. #endif
  1142.  
  1143. GetPlayerProxy();
  1144.  
  1145. SetFlashlightPowerDrainScale( 1.0f );
  1146. }
  1147.  
  1148. //-----------------------------------------------------------------------------
  1149. //-----------------------------------------------------------------------------
  1150. void CHL2_Player::UpdateLocatorPosition( const Vector &vecPosition )
  1151. {
  1152. #ifdef HL2_EPISODIC
  1153. m_HL2Local.m_vecLocatorOrigin = vecPosition;
  1154. #endif//HL2_EPISODIC
  1155. }
  1156.  
  1157. //-----------------------------------------------------------------------------
  1158. //-----------------------------------------------------------------------------
  1159. void CHL2_Player::InitSprinting( void )
  1160. {
  1161. StopSprinting();
  1162. }
  1163.  
  1164.  
  1165. //-----------------------------------------------------------------------------
  1166. // Purpose: Returns whether or not we are allowed to sprint now.
  1167. //-----------------------------------------------------------------------------
  1168. bool CHL2_Player::CanSprint()
  1169. {
  1170. return ( m_bSprintEnabled && // Only if sprint is enabled
  1171. !IsWalking() && // Not if we're walking
  1172. !( m_Local.m_bDucked && !m_Local.m_bDucking ) && // Nor if we're ducking
  1173. (GetWaterLevel() != 3) && // Certainly not underwater
  1174. (GlobalEntity_GetState("suit_no_sprint") != GLOBAL_ON) ); // Out of the question without the sprint module
  1175. }
  1176.  
  1177. //-----------------------------------------------------------------------------
  1178. //-----------------------------------------------------------------------------
  1179. void CHL2_Player::StartAutoSprint()
  1180. {
  1181. if( IsSprinting() )
  1182. {
  1183. StopSprinting();
  1184. }
  1185. else
  1186. {
  1187. StartSprinting();
  1188. m_bIsAutoSprinting = true;
  1189. m_fAutoSprintMinTime = gpGlobals->curtime + 1.5f;
  1190. }
  1191. }
  1192.  
  1193. //-----------------------------------------------------------------------------
  1194. //-----------------------------------------------------------------------------
  1195. void CHL2_Player::StartSprinting( void )
  1196. {
  1197. if( m_HL2Local.m_flSuitPower < 10 )
  1198. {
  1199. // Don't sprint unless there's a reasonable
  1200. // amount of suit power.
  1201.  
  1202. // debounce the button for sound playing
  1203. if ( m_afButtonPressed & IN_SPEED )
  1204. {
  1205. CPASAttenuationFilter filter( this );
  1206. filter.UsePredictionRules();
  1207. EmitSound( filter, entindex(), "HL2Player.SprintNoPower" );
  1208. }
  1209. return;
  1210. }
  1211.  
  1212. if( !SuitPower_AddDevice( SuitDeviceSprint ) )
  1213. return;
  1214.  
  1215. CPASAttenuationFilter filter( this );
  1216. filter.UsePredictionRules();
  1217. EmitSound( filter, entindex(), "HL2Player.SprintStart" );
  1218.  
  1219. SetMaxSpeed( HL2_SPRINT_SPEED );
  1220. m_fIsSprinting = true;
  1221. }
  1222.  
  1223.  
  1224. //-----------------------------------------------------------------------------
  1225. //-----------------------------------------------------------------------------
  1226. void CHL2_Player::StopSprinting( void )
  1227. {
  1228. if ( m_HL2Local.m_bitsActiveDevices & SuitDeviceSprint.GetDeviceID() )
  1229. {
  1230. SuitPower_RemoveDevice( SuitDeviceSprint );
  1231. }
  1232.  
  1233. if( IsSuitEquipped() )
  1234. {
  1235. SetMaxSpeed( HL2_NORM_SPEED );
  1236. }
  1237. else
  1238. {
  1239. SetMaxSpeed( HL2_WALK_SPEED );
  1240. }
  1241.  
  1242. m_fIsSprinting = false;
  1243.  
  1244. if ( sv_stickysprint.GetBool() )
  1245. {
  1246. m_bIsAutoSprinting = false;
  1247. m_fAutoSprintMinTime = 0.0f;
  1248. }
  1249. }
  1250.  
  1251.  
  1252. //-----------------------------------------------------------------------------
  1253. // Purpose: Called to disable and enable sprint due to temporary circumstances:
  1254. // - Carrying a heavy object with the physcannon
  1255. //-----------------------------------------------------------------------------
  1256. void CHL2_Player::EnableSprint( bool bEnable )
  1257. {
  1258. if ( !bEnable && IsSprinting() )
  1259. {
  1260. StopSprinting();
  1261. }
  1262.  
  1263. m_bSprintEnabled = bEnable;
  1264. }
  1265.  
  1266.  
  1267. //-----------------------------------------------------------------------------
  1268. //-----------------------------------------------------------------------------
  1269. void CHL2_Player::StartWalking( void )
  1270. {
  1271. SetMaxSpeed( HL2_WALK_SPEED );
  1272. m_fIsWalking = true;
  1273. }
  1274.  
  1275. //-----------------------------------------------------------------------------
  1276. //-----------------------------------------------------------------------------
  1277. void CHL2_Player::StopWalking( void )
  1278. {
  1279. SetMaxSpeed( HL2_NORM_SPEED );
  1280. m_fIsWalking = false;
  1281. }
  1282.  
  1283. //-----------------------------------------------------------------------------
  1284. // Purpose:
  1285. // Output : Returns true on success, false on failure.
  1286. //-----------------------------------------------------------------------------
  1287. bool CHL2_Player::CanZoom( CBaseEntity *pRequester )
  1288. {
  1289. if ( IsZooming() )
  1290. return false;
  1291.  
  1292. //Check our weapon
  1293.  
  1294. return true;
  1295. }
  1296.  
  1297. //-----------------------------------------------------------------------------
  1298. //-----------------------------------------------------------------------------
  1299. void CHL2_Player::ToggleZoom(void)
  1300. {
  1301. if( IsZooming() )
  1302. {
  1303. StopZooming();
  1304. }
  1305. else
  1306. {
  1307. StartZooming();
  1308. }
  1309. }
  1310.  
  1311. //-----------------------------------------------------------------------------
  1312. // Purpose: +zoom suit zoom
  1313. //-----------------------------------------------------------------------------
  1314. void CHL2_Player::StartZooming( void )
  1315. {
  1316. int iFOV = 25;
  1317. if ( SetFOV( this, iFOV, 0.4f ) )
  1318. {
  1319. m_HL2Local.m_bZooming = true;
  1320. }
  1321. }
  1322.  
  1323. //-----------------------------------------------------------------------------
  1324. // Purpose:
  1325. //-----------------------------------------------------------------------------
  1326. void CHL2_Player::StopZooming( void )
  1327. {
  1328. int iFOV = GetZoomOwnerDesiredFOV( m_hZoomOwner );
  1329.  
  1330. if ( SetFOV( this, iFOV, 0.2f ) )
  1331. {
  1332. m_HL2Local.m_bZooming = false;
  1333. }
  1334. }
  1335.  
  1336. //-----------------------------------------------------------------------------
  1337. // Purpose:
  1338. // Output : Returns true on success, false on failure.
  1339. //-----------------------------------------------------------------------------
  1340. bool CHL2_Player::IsZooming( void )
  1341. {
  1342. if ( m_hZoomOwner != NULL )
  1343. return true;
  1344.  
  1345. return false;
  1346. }
  1347.  
  1348. class CPhysicsPlayerCallback : public IPhysicsPlayerControllerEvent
  1349. {
  1350. public:
  1351. int ShouldMoveTo( IPhysicsObject *pObject, const Vector &position )
  1352. {
  1353. CHL2_Player *pPlayer = (CHL2_Player *)pObject->GetGameData();
  1354. if ( pPlayer )
  1355. {
  1356. if ( pPlayer->TouchedPhysics() )
  1357. {
  1358. return 0;
  1359. }
  1360. }
  1361. return 1;
  1362. }
  1363. };
  1364.  
  1365. static CPhysicsPlayerCallback playerCallback;
  1366.  
  1367. //-----------------------------------------------------------------------------
  1368. // Purpose:
  1369. //-----------------------------------------------------------------------------
  1370. void CHL2_Player::InitVCollision( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity )
  1371. {
  1372. BaseClass::InitVCollision( vecAbsOrigin, vecAbsVelocity );
  1373.  
  1374. // Setup the HL2 specific callback.
  1375. IPhysicsPlayerController *pPlayerController = GetPhysicsController();
  1376. if ( pPlayerController )
  1377. {
  1378. pPlayerController->SetEventHandler( &playerCallback );
  1379. }
  1380. }
  1381.  
  1382.  
  1383. CHL2_Player::~CHL2_Player( void )
  1384. {
  1385. }
  1386.  
  1387. //-----------------------------------------------------------------------------
  1388. //-----------------------------------------------------------------------------
  1389.  
  1390. bool CHL2_Player::CommanderFindGoal( commandgoal_t *pGoal )
  1391. {
  1392. CAI_BaseNPC *pAllyNpc;
  1393. trace_t tr;
  1394. Vector vecTarget;
  1395. Vector forward;
  1396.  
  1397. EyeVectors( &forward );
  1398.  
  1399. //---------------------------------
  1400. // MASK_SHOT on purpose! So that you don't hit the invisible hulls of the NPCs.
  1401. CTraceFilterSkipTwoEntities filter( this, PhysCannonGetHeldEntity( GetActiveWeapon() ), COLLISION_GROUP_INTERACTIVE_DEBRIS );
  1402.  
  1403. UTIL_TraceLine( EyePosition(), EyePosition() + forward * MAX_COORD_RANGE, MASK_SHOT, &filter, &tr );
  1404.  
  1405. if( !tr.DidHitWorld() )
  1406. {
  1407. CUtlVector<CAI_BaseNPC *> Allies;
  1408. AISquadIter_t iter;
  1409. for ( pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) )
  1410. {
  1411. if ( pAllyNpc->IsCommandable() )
  1412. Allies.AddToTail( pAllyNpc );
  1413. }
  1414.  
  1415. for( int i = 0 ; i < Allies.Count() ; i++ )
  1416. {
  1417. if( Allies[ i ]->IsValidCommandTarget( tr.m_pEnt ) )
  1418. {
  1419. pGoal->m_pGoalEntity = tr.m_pEnt;
  1420. return true;
  1421. }
  1422. }
  1423. }
  1424.  
  1425. if( tr.fraction == 1.0 || (tr.surface.flags & SURF_SKY) )
  1426. {
  1427. // Move commands invalid against skybox.
  1428. pGoal->m_vecGoalLocation = tr.endpos;
  1429. return false;
  1430. }
  1431.  
  1432. if ( tr.m_pEnt->IsNPC() && ((CAI_BaseNPC *)(tr.m_pEnt))->IsCommandable() )
  1433. {
  1434. pGoal->m_vecGoalLocation = tr.m_pEnt->GetAbsOrigin();
  1435. }
  1436. else
  1437. {
  1438. vecTarget = tr.endpos;
  1439.  
  1440. Vector mins( -16, -16, 0 );
  1441. Vector maxs( 16, 16, 0 );
  1442.  
  1443. // Back up from whatever we hit so that there's enough space at the
  1444. // target location for a bounding box.
  1445. // Now trace down.
  1446. //UTIL_TraceLine( vecTarget, vecTarget - Vector( 0, 0, 8192 ), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
  1447. UTIL_TraceHull( vecTarget + tr.plane.normal * 24,
  1448. vecTarget - Vector( 0, 0, 8192 ),
  1449. mins,
  1450. maxs,
  1451. MASK_SOLID_BRUSHONLY,
  1452. this,
  1453. COLLISION_GROUP_NONE,
  1454. &tr );
  1455.  
  1456.  
  1457. if ( !tr.startsolid )
  1458. pGoal->m_vecGoalLocation = tr.endpos;
  1459. else
  1460. pGoal->m_vecGoalLocation = vecTarget;
  1461. }
  1462.  
  1463. pAllyNpc = GetSquadCommandRepresentative();
  1464. if ( !pAllyNpc )
  1465. return false;
  1466.  
  1467. vecTarget = pGoal->m_vecGoalLocation;
  1468. if ( !pAllyNpc->FindNearestValidGoalPos( vecTarget, &pGoal->m_vecGoalLocation ) )
  1469. return false;
  1470.  
  1471. return ( ( vecTarget - pGoal->m_vecGoalLocation ).LengthSqr() < Square( 15*12 ) );
  1472. }
  1473.  
  1474. //-----------------------------------------------------------------------------
  1475. //-----------------------------------------------------------------------------
  1476. CAI_BaseNPC *CHL2_Player::GetSquadCommandRepresentative()
  1477. {
  1478. if ( m_pPlayerAISquad != NULL )
  1479. {
  1480. CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember();
  1481.  
  1482. if ( pAllyNpc )
  1483. {
  1484. return pAllyNpc->GetSquadCommandRepresentative();
  1485. }
  1486. }
  1487.  
  1488. return NULL;
  1489. }
  1490.  
  1491. //-----------------------------------------------------------------------------
  1492. //-----------------------------------------------------------------------------
  1493. int CHL2_Player::GetNumSquadCommandables()
  1494. {
  1495. AISquadIter_t iter;
  1496. int c = 0;
  1497. for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) )
  1498. {
  1499. if ( pAllyNpc->IsCommandable() )
  1500. c++;
  1501. }
  1502. return c;
  1503. }
  1504.  
  1505. //-----------------------------------------------------------------------------
  1506. //-----------------------------------------------------------------------------
  1507. int CHL2_Player::GetNumSquadCommandableMedics()
  1508. {
  1509. AISquadIter_t iter;
  1510. int c = 0;
  1511. for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) )
  1512. {
  1513. if ( pAllyNpc->IsCommandable() && pAllyNpc->IsMedic() )
  1514. c++;
  1515. }
  1516. return c;
  1517. }
  1518.  
  1519. //-----------------------------------------------------------------------------
  1520. //-----------------------------------------------------------------------------
  1521. void CHL2_Player::CommanderUpdate()
  1522. {
  1523. CAI_BaseNPC *pCommandRepresentative = GetSquadCommandRepresentative();
  1524. bool bFollowMode = false;
  1525. if ( pCommandRepresentative )
  1526. {
  1527. bFollowMode = ( pCommandRepresentative->GetCommandGoal() == vec3_invalid );
  1528.  
  1529. // set the variables for network transmission (to show on the hud)
  1530. m_HL2Local.m_iSquadMemberCount = GetNumSquadCommandables();
  1531. m_HL2Local.m_iSquadMedicCount = GetNumSquadCommandableMedics();
  1532. m_HL2Local.m_fSquadInFollowMode = bFollowMode;
  1533.  
  1534. // debugging code for displaying extra squad indicators
  1535. /*
  1536. char *pszMoving = "";
  1537. AISquadIter_t iter;
  1538. for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) )
  1539. {
  1540. if ( pAllyNpc->IsCommandMoving() )
  1541. {
  1542. pszMoving = "<-";
  1543. break;
  1544. }
  1545. }
  1546.  
  1547. NDebugOverlay::ScreenText(
  1548. 0.932, 0.919,
  1549. CFmtStr( "%d|%c%s", GetNumSquadCommandables(), ( bFollowMode ) ? 'F' : 'S', pszMoving ),
  1550. 255, 128, 0, 128,
  1551. 0 );
  1552. */
  1553.  
  1554. }
  1555. else
  1556. {
  1557. m_HL2Local.m_iSquadMemberCount = 0;
  1558. m_HL2Local.m_iSquadMedicCount = 0;
  1559. m_HL2Local.m_fSquadInFollowMode = true;
  1560. }
  1561.  
  1562. if ( m_QueuedCommand != CC_NONE && ( m_QueuedCommand == CC_FOLLOW || gpGlobals->realtime - m_RealTimeLastSquadCommand >= player_squad_double_tap_time.GetFloat() ) )
  1563. {
  1564. CommanderExecute( m_QueuedCommand );
  1565. m_QueuedCommand = CC_NONE;
  1566. }
  1567. else if ( !bFollowMode && pCommandRepresentative && m_CommanderUpdateTimer.Expired() && player_squad_transient_commands.GetBool() )
  1568. {
  1569. m_CommanderUpdateTimer.Set(2.5);
  1570.  
  1571. if ( pCommandRepresentative->ShouldAutoSummon() )
  1572. CommanderExecute( CC_FOLLOW );
  1573. }
  1574. }
  1575.  
  1576. //-----------------------------------------------------------------------------
  1577. // Purpose:
  1578. //
  1579. // bHandled - indicates whether to continue delivering this order to
  1580. // all allies. Allows us to stop delivering certain types of orders once we find
  1581. // a suitable candidate. (like picking up a single weapon. We don't wish for
  1582. // all allies to respond and try to pick up one weapon).
  1583. //-----------------------------------------------------------------------------
  1584. bool CHL2_Player::CommanderExecuteOne( CAI_BaseNPC *pNpc, const commandgoal_t &goal, CAI_BaseNPC **Allies, int numAllies )
  1585. {
  1586. if ( goal.m_pGoalEntity )
  1587. {
  1588. return pNpc->TargetOrder( goal.m_pGoalEntity, Allies, numAllies );
  1589. }
  1590. else if ( pNpc->IsInPlayerSquad() )
  1591. {
  1592. pNpc->MoveOrder( goal.m_vecGoalLocation, Allies, numAllies );
  1593. }
  1594.  
  1595. return true;
  1596. }
  1597.  
  1598. //---------------------------------------------------------
  1599. //---------------------------------------------------------
  1600. void CHL2_Player::CommanderExecute( CommanderCommand_t command )
  1601. {
  1602. CAI_BaseNPC *pPlayerSquadLeader = GetSquadCommandRepresentative();
  1603.  
  1604. if ( !pPlayerSquadLeader )
  1605. {
  1606. EmitSound( "HL2Player.UseDeny" );
  1607. return;
  1608. }
  1609.  
  1610. int i;
  1611. CUtlVector<CAI_BaseNPC *> Allies;
  1612. commandgoal_t goal;
  1613.  
  1614. if ( command == CC_TOGGLE )
  1615. {
  1616. if ( pPlayerSquadLeader->GetCommandGoal() != vec3_invalid )
  1617. command = CC_FOLLOW;
  1618. else
  1619. command = CC_SEND;
  1620. }
  1621. else
  1622. {
  1623. if ( command == CC_FOLLOW && pPlayerSquadLeader->GetCommandGoal() == vec3_invalid )
  1624. return;
  1625. }
  1626.  
  1627. if ( command == CC_FOLLOW )
  1628. {
  1629. goal.m_pGoalEntity = this;
  1630. goal.m_vecGoalLocation = vec3_invalid;
  1631. }
  1632. else
  1633. {
  1634. goal.m_pGoalEntity = NULL;
  1635. goal.m_vecGoalLocation = vec3_invalid;
  1636.  
  1637. // Find a goal for ourselves.
  1638. if( !CommanderFindGoal( &goal ) )
  1639. {
  1640. EmitSound( "HL2Player.UseDeny" );
  1641. return; // just keep following
  1642. }
  1643. }
  1644.  
  1645. #ifdef _DEBUG
  1646. if( goal.m_pGoalEntity == NULL && goal.m_vecGoalLocation == vec3_invalid )
  1647. {
  1648. DevMsg( 1, "**ERROR: Someone sent an invalid goal to CommanderExecute!\n" );
  1649. }
  1650. #endif // _DEBUG
  1651.  
  1652. AISquadIter_t iter;
  1653. for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) )
  1654. {
  1655. if ( pAllyNpc->IsCommandable() )
  1656. Allies.AddToTail( pAllyNpc );
  1657. }
  1658.  
  1659. //---------------------------------
  1660. // If the trace hits an NPC, send all ally NPCs a "target" order. Always
  1661. // goes to targeted one first
  1662. #ifdef DBGFLAG_ASSERT
  1663. int nAIs = g_AI_Manager.NumAIs();
  1664. #endif
  1665. CAI_BaseNPC * pTargetNpc = (goal.m_pGoalEntity) ? goal.m_pGoalEntity->MyNPCPointer() : NULL;
  1666.  
  1667. bool bHandled = false;
  1668. if( pTargetNpc )
  1669. {
  1670. bHandled = !CommanderExecuteOne( pTargetNpc, goal, Allies.Base(), Allies.Count() );
  1671. }
  1672.  
  1673. for ( i = 0; !bHandled && i < Allies.Count(); i++ )
  1674. {
  1675. if ( Allies[i] != pTargetNpc && Allies[i]->IsPlayerAlly() )
  1676. {
  1677. bHandled = !CommanderExecuteOne( Allies[i], goal, Allies.Base(), Allies.Count() );
  1678. }
  1679. Assert( nAIs == g_AI_Manager.NumAIs() ); // not coded to support mutating set of NPCs
  1680. }
  1681. }
  1682.  
  1683. //-----------------------------------------------------------------------------
  1684. // Enter/exit commander mode, manage ally selection.
  1685. //-----------------------------------------------------------------------------
  1686. void CHL2_Player::CommanderMode()
  1687. {
  1688. float commandInterval = gpGlobals->realtime - m_RealTimeLastSquadCommand;
  1689. m_RealTimeLastSquadCommand = gpGlobals->realtime;
  1690. if ( commandInterval < player_squad_double_tap_time.GetFloat() )
  1691. {
  1692. m_QueuedCommand = CC_FOLLOW;
  1693. }
  1694. else
  1695. {
  1696. m_QueuedCommand = (player_squad_transient_commands.GetBool()) ? CC_SEND : CC_TOGGLE;
  1697. }
  1698. }
  1699.  
  1700. //-----------------------------------------------------------------------------
  1701. // Purpose:
  1702. // Input : iImpulse -
  1703. //-----------------------------------------------------------------------------
  1704. void CHL2_Player::CheatImpulseCommands( int iImpulse )
  1705. {
  1706. switch( iImpulse )
  1707. {
  1708. case 50:
  1709. {
  1710. CommanderMode();
  1711. break;
  1712. }
  1713.  
  1714. case 51:
  1715. {
  1716. // Cheat to create a dynamic resupply item
  1717. Vector vecForward;
  1718. AngleVectors( EyeAngles(), &vecForward );
  1719. CBaseEntity *pItem = (CBaseEntity *)CreateEntityByName( "item_dynamic_resupply" );
  1720. if ( pItem )
  1721. {
  1722. Vector vecOrigin = GetAbsOrigin() + vecForward * 256 + Vector(0,0,64);
  1723. QAngle vecAngles( 0, GetAbsAngles().y - 90, 0 );
  1724. pItem->SetAbsOrigin( vecOrigin );
  1725. pItem->SetAbsAngles( vecAngles );
  1726. pItem->KeyValue( "targetname", "resupply" );
  1727. pItem->Spawn();
  1728. pItem->Activate();
  1729. }
  1730. break;
  1731. }
  1732.  
  1733. case 52:
  1734. {
  1735. // Rangefinder
  1736. trace_t tr;
  1737. UTIL_TraceLine( EyePosition(), EyePosition() + EyeDirection3D() * MAX_COORD_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  1738.  
  1739. if( tr.fraction != 1.0 )
  1740. {
  1741. float flDist = (tr.startpos - tr.endpos).Length();
  1742. float flDist2D = (tr.startpos - tr.endpos).Length2D();
  1743. DevMsg( 1,"\nStartPos: %.4f %.4f %.4f --- EndPos: %.4f %.4f %.4f\n", tr.startpos.x,tr.startpos.y,tr.startpos.z,tr.endpos.x,tr.endpos.y,tr.endpos.z );
  1744. DevMsg( 1,"3D Distance: %.4f units (%.2f feet) --- 2D Distance: %.4f units (%.2f feet)\n", flDist, flDist / 12.0, flDist2D, flDist2D / 12.0 );
  1745. }
  1746.  
  1747. break;
  1748. }
  1749.  
  1750. default:
  1751. BaseClass::CheatImpulseCommands( iImpulse );
  1752. }
  1753. }
  1754.  
  1755. //-----------------------------------------------------------------------------
  1756. // Purpose:
  1757. //-----------------------------------------------------------------------------
  1758. void CHL2_Player::SetupVisibility( CBaseEntity *pViewEntity, unsigned char *pvs, int pvssize )
  1759. {
  1760. BaseClass::SetupVisibility( pViewEntity, pvs, pvssize );
  1761.  
  1762. int area = pViewEntity ? pViewEntity->NetworkProp()->AreaNum() : NetworkProp()->AreaNum();
  1763. PointCameraSetupVisibility( this, area, pvs, pvssize );
  1764.  
  1765. // If the intro script is playing, we want to get it's visibility points
  1766. if ( g_hIntroScript )
  1767. {
  1768. Vector vecOrigin;
  1769. CBaseEntity *pCamera;
  1770. if ( g_hIntroScript->GetIncludedPVSOrigin( &vecOrigin, &pCamera ) )
  1771. {
  1772. // If it's a point camera, turn it on
  1773. CPointCamera *pPointCamera = dynamic_cast< CPointCamera* >(pCamera);
  1774. if ( pPointCamera )
  1775. {
  1776. pPointCamera->SetActive( true );
  1777. }
  1778. engine->AddOriginToPVS( vecOrigin );
  1779. }
  1780. }
  1781. }
  1782.  
  1783.  
  1784. //-----------------------------------------------------------------------------
  1785. //-----------------------------------------------------------------------------
  1786. void CHL2_Player::SuitPower_Update( void )
  1787. {
  1788. if( SuitPower_ShouldRecharge() )
  1789. {
  1790. SuitPower_Charge( SUITPOWER_CHARGE_RATE * gpGlobals->frametime );
  1791. }
  1792. else if( m_HL2Local.m_bitsActiveDevices )
  1793. {
  1794. float flPowerLoad = m_flSuitPowerLoad;
  1795.  
  1796. //Since stickysprint quickly shuts off sprint if it isn't being used, this isn't an issue.
  1797. if ( !sv_stickysprint.GetBool() )
  1798. {
  1799. if( SuitPower_IsDeviceActive(SuitDeviceSprint) )
  1800. {
  1801. if( !fabs(GetAbsVelocity().x) && !fabs(GetAbsVelocity().y) )
  1802. {
  1803. // If player's not moving, don't drain sprint juice.
  1804. flPowerLoad -= SuitDeviceSprint.GetDeviceDrainRate();
  1805. }
  1806. }
  1807. }
  1808.  
  1809. if( SuitPower_IsDeviceActive(SuitDeviceFlashlight) )
  1810. {
  1811. float factor;
  1812.  
  1813. factor = 1.0f / m_flFlashlightPowerDrainScale;
  1814.  
  1815. flPowerLoad -= ( SuitDeviceFlashlight.GetDeviceDrainRate() * (1.0f - factor) );
  1816. }
  1817.  
  1818. if( !SuitPower_Drain( flPowerLoad * gpGlobals->frametime ) )
  1819. {
  1820. // TURN OFF ALL DEVICES!!
  1821. if( IsSprinting() )
  1822. {
  1823. StopSprinting();
  1824. }
  1825.  
  1826. if ( Flashlight_UseLegacyVersion() )
  1827. {
  1828. if( FlashlightIsOn() )
  1829. {
  1830. #ifndef HL2MP
  1831. FlashlightTurnOff();
  1832. #endif
  1833. }
  1834. }
  1835. }
  1836.  
  1837. if ( Flashlight_UseLegacyVersion() )
  1838. {
  1839. // turn off flashlight a little bit after it hits below one aux power notch (5%)
  1840. if( m_HL2Local.m_flSuitPower < 4.8f && FlashlightIsOn() )
  1841. {
  1842. #ifndef HL2MP
  1843. FlashlightTurnOff();
  1844. #endif
  1845. }
  1846. }
  1847. }
  1848. }
  1849.  
  1850.  
  1851. //-----------------------------------------------------------------------------
  1852. // Charge battery fully, turn off all devices.
  1853. //-----------------------------------------------------------------------------
  1854. void CHL2_Player::SuitPower_Initialize( void )
  1855. {
  1856. m_HL2Local.m_bitsActiveDevices = 0x00000000;
  1857. m_HL2Local.m_flSuitPower = 100.0;
  1858. m_flSuitPowerLoad = 0.0;
  1859. }
  1860.  
  1861.  
  1862. //-----------------------------------------------------------------------------
  1863. // Purpose: Interface to drain power from the suit's power supply.
  1864. // Input: Amount of charge to remove (expressed as percentage of full charge)
  1865. // Output: Returns TRUE if successful, FALSE if not enough power available.
  1866. //-----------------------------------------------------------------------------
  1867. bool CHL2_Player::SuitPower_Drain( float flPower )
  1868. {
  1869. // Suitpower cheat on?
  1870. if ( sv_infinite_aux_power.GetBool() )
  1871. return true;
  1872.  
  1873. m_HL2Local.m_flSuitPower -= flPower;
  1874.  
  1875. if( m_HL2Local.m_flSuitPower < 0.0 )
  1876. {
  1877. // Power is depleted!
  1878. // Clamp and fail
  1879. m_HL2Local.m_flSuitPower = 0.0;
  1880. return false;
  1881. }
  1882.  
  1883. return true;
  1884. }
  1885.  
  1886. //-----------------------------------------------------------------------------
  1887. // Purpose: Interface to add power to the suit's power supply
  1888. // Input: Amount of charge to add
  1889. //-----------------------------------------------------------------------------
  1890. void CHL2_Player::SuitPower_Charge( float flPower )
  1891. {
  1892. m_HL2Local.m_flSuitPower += flPower;
  1893.  
  1894. if( m_HL2Local.m_flSuitPower > 100.0 )
  1895. {
  1896. // Full charge, clamp.
  1897. m_HL2Local.m_flSuitPower = 100.0;
  1898. }
  1899. }
  1900.  
  1901. //-----------------------------------------------------------------------------
  1902. //-----------------------------------------------------------------------------
  1903. bool CHL2_Player::SuitPower_IsDeviceActive( const CSuitPowerDevice &device )
  1904. {
  1905. return (m_HL2Local.m_bitsActiveDevices & device.GetDeviceID()) != 0;
  1906. }
  1907.  
  1908. //-----------------------------------------------------------------------------
  1909. //-----------------------------------------------------------------------------
  1910. bool CHL2_Player::SuitPower_AddDevice( const CSuitPowerDevice &device )
  1911. {
  1912. // Make sure this device is NOT active!!
  1913. if( m_HL2Local.m_bitsActiveDevices & device.GetDeviceID() )
  1914. return false;
  1915.  
  1916. if( !IsSuitEquipped() )
  1917. return false;
  1918.  
  1919. m_HL2Local.m_bitsActiveDevices |= device.GetDeviceID();
  1920. m_flSuitPowerLoad += device.GetDeviceDrainRate();
  1921. return true;
  1922. }
  1923.  
  1924.  
  1925. //-----------------------------------------------------------------------------
  1926. //-----------------------------------------------------------------------------
  1927. bool CHL2_Player::SuitPower_RemoveDevice( const CSuitPowerDevice &device )
  1928. {
  1929. // Make sure this device is active!!
  1930. if( ! (m_HL2Local.m_bitsActiveDevices & device.GetDeviceID()) )
  1931. return false;
  1932.  
  1933. if( !IsSuitEquipped() )
  1934. return false;
  1935.  
  1936. // Take a little bit of suit power when you disable a device. If the device is shutting off
  1937. // because the battery is drained, no harm done, the battery charge cannot go below 0.
  1938. // This code in combination with the delay before the suit can start recharging are a defense
  1939. // against exploits where the player could rapidly tap sprint and never run out of power.
  1940. SuitPower_Drain( device.GetDeviceDrainRate() * 0.1f );
  1941.  
  1942. m_HL2Local.m_bitsActiveDevices &= ~device.GetDeviceID();
  1943. m_flSuitPowerLoad -= device.GetDeviceDrainRate();
  1944.  
  1945. if( m_HL2Local.m_bitsActiveDevices == 0x00000000 )
  1946. {
  1947. // With this device turned off, we can set this timer which tells us when the
  1948. // suit power system entered a no-load state.
  1949. m_flTimeAllSuitDevicesOff = gpGlobals->curtime;
  1950. }
  1951.  
  1952. return true;
  1953. }
  1954.  
  1955. //-----------------------------------------------------------------------------
  1956. //-----------------------------------------------------------------------------
  1957. #define SUITPOWER_BEGIN_RECHARGE_DELAY 0.5f
  1958. bool CHL2_Player::SuitPower_ShouldRecharge( void )
  1959. {
  1960. // Make sure all devices are off.
  1961. if( m_HL2Local.m_bitsActiveDevices != 0x00000000 )
  1962. return false;
  1963.  
  1964. // Is the system fully charged?
  1965. if( m_HL2Local.m_flSuitPower >= 100.0f )
  1966. return false;
  1967.  
  1968. // Has the system been in a no-load state for long enough
  1969. // to begin recharging?
  1970. if( gpGlobals->curtime < m_flTimeAllSuitDevicesOff + SUITPOWER_BEGIN_RECHARGE_DELAY )
  1971. return false;
  1972.  
  1973. return true;
  1974. }
  1975.  
  1976. //-----------------------------------------------------------------------------
  1977. //-----------------------------------------------------------------------------
  1978. ConVar sk_battery( "sk_battery","0" );
  1979.  
  1980. bool CHL2_Player::ApplyBattery( float powerMultiplier )
  1981. {
  1982. const float MAX_NORMAL_BATTERY = 100;
  1983. if ((ArmorValue() < MAX_NORMAL_BATTERY) && IsSuitEquipped())
  1984. {
  1985. int pct;
  1986. char szcharge[64];
  1987.  
  1988. IncrementArmorValue( sk_battery.GetFloat() * powerMultiplier, MAX_NORMAL_BATTERY );
  1989.  
  1990. CPASAttenuationFilter filter( this, "ItemBattery.Touch" );
  1991. EmitSound( filter, entindex(), "ItemBattery.Touch" );
  1992.  
  1993. CSingleUserRecipientFilter user( this );
  1994. user.MakeReliable();
  1995.  
  1996. UserMessageBegin( user, "ItemPickup" );
  1997. WRITE_STRING( "item_battery" );
  1998. MessageEnd();
  1999.  
  2000.  
  2001. // Suit reports new power level
  2002. // For some reason this wasn't working in release build -- round it.
  2003. pct = (int)( (float)(ArmorValue() * 100.0) * (1.0/MAX_NORMAL_BATTERY) + 0.5);
  2004. pct = (pct / 5);
  2005. if (pct > 0)
  2006. pct--;
  2007.  
  2008. Q_snprintf( szcharge,sizeof(szcharge),"!HEV_%1dP", pct );
  2009.  
  2010. //UTIL_EmitSoundSuit(edict(), szcharge);
  2011. //SetSuitUpdate(szcharge, FALSE, SUIT_NEXT_IN_30SEC);
  2012. return true;
  2013. }
  2014. return false;
  2015. }
  2016.  
  2017. bool CHL2_Player::AddFlashlight()
  2018. {
  2019. if (IsSuitEquipped() && !hasFlashlight) // если костюм надет и у нас пока нет фонарика
  2020. {
  2021. hasFlashlight = true; // надеваем фонарик
  2022. return true; // Функция должна возвращать истину, чтобы сам итем исчез при подбирании
  2023. }
  2024. return false; // если же нет костюма, или фонарь уже подобран, фонарь взять нельзя
  2025. }
  2026.  
  2027. //-----------------------------------------------------------------------------
  2028. //-----------------------------------------------------------------------------
  2029. int CHL2_Player::FlashlightIsOn( void )
  2030. {
  2031. return IsEffectActive( EF_DIMLIGHT );
  2032. }
  2033.  
  2034.  
  2035. //-----------------------------------------------------------------------------
  2036. //-----------------------------------------------------------------------------
  2037. void CHL2_Player::FlashlightTurnOn( void )
  2038. {
  2039. if( m_bFlashlightDisabled )
  2040. return;
  2041.  
  2042. if ( Flashlight_UseLegacyVersion() )
  2043. {
  2044. if( !SuitPower_AddDevice( SuitDeviceFlashlight ) )
  2045. return;
  2046. }
  2047. #ifdef HL2_DLL
  2048. if( !IsSuitEquipped() )
  2049. return;
  2050. #endif
  2051.  
  2052. AddEffects( EF_DIMLIGHT );
  2053. EmitSound( "HL2Player.FlashLightOn" );
  2054.  
  2055. variant_t flashlighton;
  2056. flashlighton.SetFloat( m_HL2Local.m_flSuitPower / 100.0f );
  2057. FirePlayerProxyOutput( "OnFlashlightOn", flashlighton, this, this );
  2058. }
  2059.  
  2060.  
  2061. //-----------------------------------------------------------------------------
  2062. //-----------------------------------------------------------------------------
  2063. void CHL2_Player::FlashlightTurnOff( void )
  2064. {
  2065. if ( Flashlight_UseLegacyVersion() )
  2066. {
  2067. if( !SuitPower_RemoveDevice( SuitDeviceFlashlight ) )
  2068. return;
  2069. }
  2070.  
  2071. RemoveEffects( EF_DIMLIGHT );
  2072. EmitSound( "HL2Player.FlashLightOff" );
  2073.  
  2074. variant_t flashlightoff;
  2075. flashlightoff.SetFloat( m_HL2Local.m_flSuitPower / 100.0f );
  2076. FirePlayerProxyOutput( "OnFlashlightOff", flashlightoff, this, this );
  2077. }
  2078.  
  2079. //-----------------------------------------------------------------------------
  2080. //-----------------------------------------------------------------------------
  2081. #define FLASHLIGHT_RANGE Square(600)
  2082. bool CHL2_Player::IsIlluminatedByFlashlight( CBaseEntity *pEntity, float *flReturnDot )
  2083. {
  2084. if( !FlashlightIsOn() )
  2085. return false;
  2086.  
  2087. if( pEntity->Classify() == CLASS_BARNACLE && pEntity->GetEnemy() == this )
  2088. {
  2089. // As long as my flashlight is on, the barnacle that's pulling me in is considered illuminated.
  2090. // This is because players often shine their flashlights at Alyx when they are in a barnacle's
  2091. // grasp, and wonder why Alyx isn't helping. Alyx isn't helping because the light isn't pointed
  2092. // at the barnacle. This will allow Alyx to see the barnacle no matter which way the light is pointed.
  2093. return true;
  2094. }
  2095.  
  2096. // Within 50 feet?
  2097. float flDistSqr = GetAbsOrigin().DistToSqr(pEntity->GetAbsOrigin());
  2098. if( flDistSqr > FLASHLIGHT_RANGE )
  2099. return false;
  2100.  
  2101. // Within 45 degrees?
  2102. Vector vecSpot = pEntity->WorldSpaceCenter();
  2103. Vector los;
  2104.  
  2105. // If the eyeposition is too close, move it back. Solves problems
  2106. // caused by the player being too close the target.
  2107. if ( flDistSqr < (128 * 128) )
  2108. {
  2109. Vector vecForward;
  2110. EyeVectors( &vecForward );
  2111. Vector vecMovedEyePos = EyePosition() - (vecForward * 128);
  2112. los = ( vecSpot - vecMovedEyePos );
  2113. }
  2114. else
  2115. {
  2116. los = ( vecSpot - EyePosition() );
  2117. }
  2118.  
  2119. VectorNormalize( los );
  2120. Vector facingDir = EyeDirection3D( );
  2121. float flDot = DotProduct( los, facingDir );
  2122.  
  2123. if ( flReturnDot )
  2124. {
  2125. *flReturnDot = flDot;
  2126. }
  2127.  
  2128. if ( flDot < 0.92387f )
  2129. return false;
  2130.  
  2131. if( !FVisible(pEntity) )
  2132. return false;
  2133.  
  2134. return true;
  2135. }
  2136.  
  2137. //-----------------------------------------------------------------------------
  2138. // Purpose: Let NPCs know when the flashlight is trained on them
  2139. //-----------------------------------------------------------------------------
  2140. void CHL2_Player::CheckFlashlight( void )
  2141. {
  2142. if ( !FlashlightIsOn() )
  2143. return;
  2144.  
  2145. if ( m_flNextFlashlightCheckTime > gpGlobals->curtime )
  2146. return;
  2147. m_flNextFlashlightCheckTime = gpGlobals->curtime + FLASHLIGHT_NPC_CHECK_INTERVAL;
  2148.  
  2149. // Loop through NPCs looking for illuminated ones
  2150. for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
  2151. {
  2152. CAI_BaseNPC *pNPC = g_AI_Manager.AccessAIs()[i];
  2153.  
  2154. float flDot;
  2155.  
  2156. if ( IsIlluminatedByFlashlight( pNPC, &flDot ) )
  2157. {
  2158. pNPC->PlayerHasIlluminatedNPC( this, flDot );
  2159. }
  2160. }
  2161. }
  2162.  
  2163. //-----------------------------------------------------------------------------
  2164. //-----------------------------------------------------------------------------
  2165. void CHL2_Player::SetPlayerUnderwater( bool state )
  2166. {
  2167. if ( state )
  2168. {
  2169. SuitPower_AddDevice( SuitDeviceBreather );
  2170. }
  2171. else
  2172. {
  2173. SuitPower_RemoveDevice( SuitDeviceBreather );
  2174. }
  2175.  
  2176. BaseClass::SetPlayerUnderwater( state );
  2177. }
  2178.  
  2179. //-----------------------------------------------------------------------------
  2180. bool CHL2_Player::PassesDamageFilter( const CTakeDamageInfo &info )
  2181. {
  2182. CBaseEntity *pAttacker = info.GetAttacker();
  2183. if( pAttacker && pAttacker->MyNPCPointer() && pAttacker->MyNPCPointer()->IsPlayerAlly() )
  2184. {
  2185. return false;
  2186. }
  2187.  
  2188. if( m_hPlayerProxy && !m_hPlayerProxy->PassesDamageFilter( info ) )
  2189. {
  2190. return false;
  2191. }
  2192.  
  2193. return BaseClass::PassesDamageFilter( info );
  2194. }
  2195.  
  2196. //-----------------------------------------------------------------------------
  2197. // Purpose:
  2198. //-----------------------------------------------------------------------------
  2199. void CHL2_Player::SetFlashlightEnabled( bool bState )
  2200. {
  2201. m_bFlashlightDisabled = !bState;
  2202. }
  2203.  
  2204. //-----------------------------------------------------------------------------
  2205. //-----------------------------------------------------------------------------
  2206. void CHL2_Player::InputDisableFlashlight( inputdata_t &inputdata )
  2207. {
  2208. if( FlashlightIsOn() )
  2209. FlashlightTurnOff();
  2210.  
  2211. SetFlashlightEnabled( false );
  2212. }
  2213.  
  2214. //-----------------------------------------------------------------------------
  2215. //-----------------------------------------------------------------------------
  2216. void CHL2_Player::InputEnableFlashlight( inputdata_t &inputdata )
  2217. {
  2218. SetFlashlightEnabled( true );
  2219. }
  2220.  
  2221.  
  2222. //-----------------------------------------------------------------------------
  2223. // Purpose: Prevent the player from taking fall damage for [n] seconds, but
  2224. // reset back to taking fall damage after the first impact (so players will be
  2225. // hurt if they bounce off what they hit). This is the original behavior.
  2226. //-----------------------------------------------------------------------------
  2227. void CHL2_Player::InputIgnoreFallDamage( inputdata_t &inputdata )
  2228. {
  2229. float timeToIgnore = inputdata.value.Float();
  2230.  
  2231. if ( timeToIgnore <= 0.0 )
  2232. timeToIgnore = TIME_IGNORE_FALL_DAMAGE;
  2233.  
  2234. m_flTimeIgnoreFallDamage = gpGlobals->curtime + timeToIgnore;
  2235. m_bIgnoreFallDamageResetAfterImpact = true;
  2236. }
  2237.  
  2238.  
  2239. //-----------------------------------------------------------------------------
  2240. // Purpose: Absolutely prevent the player from taking fall damage for [n] seconds.
  2241. //-----------------------------------------------------------------------------
  2242. void CHL2_Player::InputIgnoreFallDamageWithoutReset( inputdata_t &inputdata )
  2243. {
  2244. float timeToIgnore = inputdata.value.Float();
  2245.  
  2246. if ( timeToIgnore <= 0.0 )
  2247. timeToIgnore = TIME_IGNORE_FALL_DAMAGE;
  2248.  
  2249. m_flTimeIgnoreFallDamage = gpGlobals->curtime + timeToIgnore;
  2250. m_bIgnoreFallDamageResetAfterImpact = false;
  2251. }
  2252.  
  2253. //-----------------------------------------------------------------------------
  2254. // Purpose: Notification of a player's npc ally in the players squad being killed
  2255. //-----------------------------------------------------------------------------
  2256. void CHL2_Player::OnSquadMemberKilled( inputdata_t &data )
  2257. {
  2258. // send a message to the client, to notify the hud of the loss
  2259. CSingleUserRecipientFilter user( this );
  2260. user.MakeReliable();
  2261. UserMessageBegin( user, "SquadMemberDied" );
  2262. MessageEnd();
  2263. }
  2264.  
  2265. //-----------------------------------------------------------------------------
  2266. // Purpose:
  2267. //-----------------------------------------------------------------------------
  2268. void CHL2_Player::NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity )
  2269. {
  2270. CAI_BaseNPC *pAttacker = pAttackerEntity->MyNPCPointer();
  2271. if ( pAttacker )
  2272. {
  2273. const Vector &origin = GetAbsOrigin();
  2274. for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
  2275. {
  2276. const float NEAR_Z = 12*12;
  2277. const float NEAR_XY_SQ = Square( 50*12 );
  2278. CAI_BaseNPC *pNpc = g_AI_Manager.AccessAIs()[i];
  2279. if ( pNpc->IsPlayerAlly() )
  2280. {
  2281. const Vector &originNpc = pNpc->GetAbsOrigin();
  2282. if ( fabsf( originNpc.z - origin.z ) < NEAR_Z )
  2283. {
  2284. if ( (originNpc.AsVector2D() - origin.AsVector2D()).LengthSqr() < NEAR_XY_SQ )
  2285. {
  2286. pNpc->OnFriendDamaged( this, pAttacker );
  2287. }
  2288. }
  2289. }
  2290. }
  2291. }
  2292. }
  2293.  
  2294. //-----------------------------------------------------------------------------
  2295. // Purpose:
  2296. //-----------------------------------------------------------------------------
  2297. ConVar test_massive_dmg("test_massive_dmg", "30" );
  2298. ConVar test_massive_dmg_clip("test_massive_dmg_clip", "0.5" );
  2299. int CHL2_Player::OnTakeDamage( const CTakeDamageInfo &info )
  2300. {
  2301. if ( GlobalEntity_GetState( "gordon_invulnerable" ) == GLOBAL_ON )
  2302. return 0;
  2303.  
  2304. // ignore fall damage if instructed to do so by input
  2305. if ( ( info.GetDamageType() & DMG_FALL ) && m_flTimeIgnoreFallDamage > gpGlobals->curtime )
  2306. {
  2307. // usually, we will reset the input flag after the first impact. However there is another input that
  2308. // prevents this behavior.
  2309. if ( m_bIgnoreFallDamageResetAfterImpact )
  2310. {
  2311. m_flTimeIgnoreFallDamage = 0;
  2312. }
  2313. return 0;
  2314. }
  2315.  
  2316. if( info.GetDamageType() & DMG_BLAST_SURFACE )
  2317. {
  2318. if( GetWaterLevel() > 2 )
  2319. {
  2320. // Don't take blast damage from anything above the surface.
  2321. if( info.GetInflictor()->GetWaterLevel() == 0 )
  2322. {
  2323. return 0;
  2324. }
  2325. }
  2326. }
  2327.  
  2328. if ( info.GetDamage() > 0.0f )
  2329. {
  2330. m_flLastDamageTime = gpGlobals->curtime;
  2331.  
  2332. if ( info.GetAttacker() )
  2333. NotifyFriendsOfDamage( info.GetAttacker() );
  2334. }
  2335.  
  2336. // Modify the amount of damage the player takes, based on skill.
  2337. CTakeDamageInfo playerDamage = info;
  2338.  
  2339. // Should we run this damage through the skill level adjustment?
  2340. bool bAdjustForSkillLevel = true;
  2341.  
  2342. if( info.GetDamageType() == DMG_GENERIC && info.GetAttacker() == this && info.GetInflictor() == this )
  2343. {
  2344. // Only do a skill level adjustment if the player isn't his own attacker AND inflictor.
  2345. // This prevents damage from SetHealth() inputs from being adjusted for skill level.
  2346. bAdjustForSkillLevel = false;
  2347. }
  2348.  
  2349. if ( GetVehicleEntity() != NULL && GlobalEntity_GetState("gordon_protect_driver") == GLOBAL_ON )
  2350. {
  2351. if( playerDamage.GetDamage() > test_massive_dmg.GetFloat() && playerDamage.GetInflictor() == GetVehicleEntity() && (playerDamage.GetDamageType() & DMG_CRUSH) )
  2352. {
  2353. playerDamage.ScaleDamage( test_massive_dmg_clip.GetFloat() / playerDamage.GetDamage() );
  2354. }
  2355. }
  2356.  
  2357. if( bAdjustForSkillLevel )
  2358. {
  2359. playerDamage.AdjustPlayerDamageTakenForSkillLevel();
  2360. }
  2361.  
  2362. gamestats->Event_PlayerDamage( this, info );
  2363.  
  2364. return BaseClass::OnTakeDamage( playerDamage );
  2365. }
  2366.  
  2367. //-----------------------------------------------------------------------------
  2368. // Purpose:
  2369. // Input : &info -
  2370. //-----------------------------------------------------------------------------
  2371. int CHL2_Player::OnTakeDamage_Alive( const CTakeDamageInfo &info )
  2372. {
  2373. // Drown
  2374. if( info.GetDamageType() & DMG_DROWN )
  2375. {
  2376. if( m_idrowndmg == m_idrownrestored )
  2377. {
  2378. EmitSound( "Player.DrownStart" );
  2379. }
  2380. else
  2381. {
  2382. EmitSound( "Player.DrownContinue" );
  2383. }
  2384. }
  2385.  
  2386. // Burnt
  2387. if ( info.GetDamageType() & DMG_BURN )
  2388. {
  2389. EmitSound( "HL2Player.BurnPain" );
  2390. }
  2391.  
  2392.  
  2393. if( (info.GetDamageType() & DMG_SLASH) && hl2_episodic.GetBool() )
  2394. {
  2395. if( m_afPhysicsFlags & PFLAG_USING )
  2396. {
  2397. // Stop the player using a rotating button for a short time if hit by a creature's melee attack.
  2398. // This is for the antlion burrow-corking training in EP1 (sjb).
  2399. SuspendUse( 0.5f );
  2400. }
  2401. }
  2402.  
  2403.  
  2404. // Call the base class implementation
  2405. return BaseClass::OnTakeDamage_Alive( info );
  2406. }
  2407.  
  2408. //-----------------------------------------------------------------------------
  2409. //-----------------------------------------------------------------------------
  2410. void CHL2_Player::OnDamagedByExplosion( const CTakeDamageInfo &info )
  2411. {
  2412. if ( info.GetInflictor() && info.GetInflictor()->ClassMatches( "mortarshell" ) )
  2413. {
  2414. // No ear ringing for mortar
  2415. UTIL_ScreenShake( info.GetInflictor()->GetAbsOrigin(), 4.0, 1.0, 0.5, 1000, SHAKE_START, false );
  2416. return;
  2417. }
  2418. BaseClass::OnDamagedByExplosion( info );
  2419. }
  2420.  
  2421. //-----------------------------------------------------------------------------
  2422. //-----------------------------------------------------------------------------
  2423. bool CHL2_Player::ShouldShootMissTarget( CBaseCombatCharacter *pAttacker )
  2424. {
  2425. if( gpGlobals->curtime > m_flTargetFindTime )
  2426. {
  2427. // Put this off into the future again.
  2428. m_flTargetFindTime = gpGlobals->curtime + random->RandomFloat( 3, 5 );
  2429. return true;
  2430. }
  2431.  
  2432. return false;
  2433. }
  2434.  
  2435. //-----------------------------------------------------------------------------
  2436. // Purpose: Notifies Alyx that player has put a combine ball into a socket so she can comment on it.
  2437. // Input : pCombineBall - ball the was socketed
  2438. //-----------------------------------------------------------------------------
  2439. void CHL2_Player::CombineBallSocketed( CPropCombineBall *pCombineBall )
  2440. {
  2441. #ifdef HL2_EPISODIC
  2442. CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx();
  2443. if ( pAlyx )
  2444. {
  2445. pAlyx->CombineBallSocketed( pCombineBall->NumBounces() );
  2446. }
  2447. #endif
  2448. }
  2449.  
  2450. //-----------------------------------------------------------------------------
  2451. //-----------------------------------------------------------------------------
  2452. void CHL2_Player::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info )
  2453. {
  2454. BaseClass::Event_KilledOther( pVictim, info );
  2455.  
  2456. #ifdef HL2_EPISODIC
  2457.  
  2458. CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
  2459.  
  2460. for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
  2461. {
  2462. if ( ppAIs[i] && ppAIs[i]->IRelationType(this) == D_LI )
  2463. {
  2464. ppAIs[i]->OnPlayerKilledOther( pVictim, info );
  2465. }
  2466. }
  2467.  
  2468. #endif
  2469. }
  2470.  
  2471. //-----------------------------------------------------------------------------
  2472. //-----------------------------------------------------------------------------
  2473. void CHL2_Player::Event_Killed( const CTakeDamageInfo &info )
  2474. {
  2475. BaseClass::Event_Killed( info );
  2476.  
  2477. FirePlayerProxyOutput( "PlayerDied", variant_t(), this, this );
  2478. NotifyScriptsOfDeath();
  2479. }
  2480.  
  2481. //-----------------------------------------------------------------------------
  2482. //-----------------------------------------------------------------------------
  2483. void CHL2_Player::NotifyScriptsOfDeath( void )
  2484. {
  2485. CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "scripted_sequence" );
  2486.  
  2487. while( pEnt )
  2488. {
  2489. variant_t emptyVariant;
  2490. pEnt->AcceptInput( "ScriptPlayerDeath", NULL, NULL, emptyVariant, 0 );
  2491.  
  2492. pEnt = gEntList.FindEntityByClassname( pEnt, "scripted_sequence" );
  2493. }
  2494.  
  2495. pEnt = gEntList.FindEntityByClassname( NULL, "logic_choreographed_scene" );
  2496.  
  2497. while( pEnt )
  2498. {
  2499. variant_t emptyVariant;
  2500. pEnt->AcceptInput( "ScriptPlayerDeath", NULL, NULL, emptyVariant, 0 );
  2501.  
  2502. pEnt = gEntList.FindEntityByClassname( pEnt, "logic_choreographed_scene" );
  2503. }
  2504. }
  2505.  
  2506. //-----------------------------------------------------------------------------
  2507. //-----------------------------------------------------------------------------
  2508. void CHL2_Player::GetAutoaimVector( autoaim_params_t &params )
  2509. {
  2510. BaseClass::GetAutoaimVector( params );
  2511.  
  2512. if ( IsX360() )
  2513. {
  2514. if( IsInAVehicle() )
  2515. {
  2516. if( m_hLockedAutoAimEntity && m_hLockedAutoAimEntity->IsAlive() && ShouldKeepLockedAutoaimTarget(m_hLockedAutoAimEntity) )
  2517. {
  2518. if( params.m_hAutoAimEntity && params.m_hAutoAimEntity != m_hLockedAutoAimEntity )
  2519. {
  2520. // Autoaim has picked a new target. Switch.
  2521. m_hLockedAutoAimEntity = params.m_hAutoAimEntity;
  2522. }
  2523.  
  2524. // Ignore autoaim and just keep aiming at this target.
  2525. params.m_hAutoAimEntity = m_hLockedAutoAimEntity;
  2526. Vector vecTarget = m_hLockedAutoAimEntity->BodyTarget( EyePosition(), false );
  2527. Vector vecDir = vecTarget - EyePosition();
  2528. VectorNormalize( vecDir );
  2529.  
  2530. params.m_vecAutoAimDir = vecDir;
  2531. params.m_vecAutoAimPoint = vecTarget;
  2532. return;
  2533. }
  2534. else
  2535. {
  2536. m_hLockedAutoAimEntity = NULL;
  2537. }
  2538. }
  2539.  
  2540. // If the player manually gets his crosshair onto a target, make that target sticky
  2541. if( params.m_fScale != AUTOAIM_SCALE_DIRECT_ONLY )
  2542. {
  2543. // Only affect this for 'real' queries
  2544. //if( params.m_hAutoAimEntity && params.m_bOnTargetNatural )
  2545. if( params.m_hAutoAimEntity )
  2546. {
  2547. // Turn on sticky.
  2548. m_HL2Local.m_bStickyAutoAim = true;
  2549.  
  2550. if( IsInAVehicle() )
  2551. {
  2552. m_hLockedAutoAimEntity = params.m_hAutoAimEntity;
  2553. }
  2554. }
  2555. else if( !params.m_hAutoAimEntity )
  2556. {
  2557. // Turn off sticky only if there's no target at all.
  2558. m_HL2Local.m_bStickyAutoAim = false;
  2559.  
  2560. m_hLockedAutoAimEntity = NULL;
  2561. }
  2562. }
  2563. }
  2564. }
  2565.  
  2566. //-----------------------------------------------------------------------------
  2567. //-----------------------------------------------------------------------------
  2568. bool CHL2_Player::ShouldKeepLockedAutoaimTarget( EHANDLE hLockedTarget )
  2569. {
  2570. Vector vecLooking;
  2571. Vector vecToTarget;
  2572.  
  2573. vecToTarget = hLockedTarget->WorldSpaceCenter() - EyePosition();
  2574. float flDist = vecToTarget.Length2D();
  2575. VectorNormalize( vecToTarget );
  2576.  
  2577. if( flDist > autoaim_max_dist.GetFloat() )
  2578. return false;
  2579.  
  2580. float flDot;
  2581.  
  2582. vecLooking = EyeDirection3D();
  2583. flDot = DotProduct( vecLooking, vecToTarget );
  2584.  
  2585. if( flDot < autoaim_unlock_target.GetFloat() )
  2586. return false;
  2587.  
  2588. return true;
  2589. }
  2590.  
  2591. //-----------------------------------------------------------------------------
  2592. // Purpose:
  2593. // Input : iCount -
  2594. // iAmmoIndex -
  2595. // bSuppressSound -
  2596. // Output : int
  2597. //-----------------------------------------------------------------------------
  2598. int CHL2_Player::GiveAmmo( int nCount, int nAmmoIndex, bool bSuppressSound)
  2599. {
  2600. // Don't try to give the player invalid ammo indices.
  2601. if (nAmmoIndex < 0)
  2602. return 0;
  2603.  
  2604. bool bCheckAutoSwitch = false;
  2605. if (!HasAnyAmmoOfType(nAmmoIndex))
  2606. {
  2607. bCheckAutoSwitch = true;
  2608. }
  2609.  
  2610. int nAdd = BaseClass::GiveAmmo(nCount, nAmmoIndex, bSuppressSound);
  2611.  
  2612. if ( nCount > 0 && nAdd == 0 )
  2613. {
  2614. // we've been denied the pickup, display a hud icon to show that
  2615. CSingleUserRecipientFilter user( this );
  2616. user.MakeReliable();
  2617. UserMessageBegin( user, "AmmoDenied" );
  2618. WRITE_SHORT( nAmmoIndex );
  2619. MessageEnd();
  2620. }
  2621.  
  2622. //
  2623. // If I was dry on ammo for my best weapon and justed picked up ammo for it,
  2624. // autoswitch to my best weapon now.
  2625. //
  2626. if (bCheckAutoSwitch)
  2627. {
  2628. CBaseCombatWeapon *pWeapon = g_pGameRules->GetNextBestWeapon(this, GetActiveWeapon());
  2629.  
  2630. if ( pWeapon && pWeapon->GetPrimaryAmmoType() == nAmmoIndex )
  2631. {
  2632. SwitchToNextBestWeapon(GetActiveWeapon());
  2633. }
  2634. }
  2635.  
  2636. return nAdd;
  2637. }
  2638.  
  2639. //-----------------------------------------------------------------------------
  2640. //-----------------------------------------------------------------------------
  2641. bool CHL2_Player::Weapon_CanUse( CBaseCombatWeapon *pWeapon )
  2642. {
  2643. #ifndef HL2MP
  2644. if ( pWeapon->ClassMatches( "weapon_stunstick" ) )
  2645. {
  2646. if ( ApplyBattery( 0.5 ) )
  2647. UTIL_Remove( pWeapon );
  2648. return false;
  2649. }
  2650. #endif
  2651.  
  2652. return BaseClass::Weapon_CanUse( pWeapon );
  2653. }
  2654.  
  2655. //-----------------------------------------------------------------------------
  2656. // Purpose:
  2657. // Input : *pWeapon -
  2658. //-----------------------------------------------------------------------------
  2659. void CHL2_Player::Weapon_Equip( CBaseCombatWeapon *pWeapon )
  2660. {
  2661. #if HL2_SINGLE_PRIMARY_WEAPON_MODE
  2662.  
  2663. if ( pWeapon->GetSlot() == WEAPON_PRIMARY_SLOT )
  2664. {
  2665. Weapon_DropSlot( WEAPON_PRIMARY_SLOT );
  2666. }
  2667.  
  2668. #endif
  2669.  
  2670. if( GetActiveWeapon() == NULL )
  2671. {
  2672. m_HL2Local.m_bWeaponLowered = false;
  2673. }
  2674.  
  2675. BaseClass::Weapon_Equip( pWeapon );
  2676. }
  2677.  
  2678. //-----------------------------------------------------------------------------
  2679. // Purpose: Player reacts to bumping a weapon.
  2680. // Input : pWeapon - the weapon that the player bumped into.
  2681. // Output : Returns true if player picked up the weapon
  2682. //-----------------------------------------------------------------------------
  2683. bool CHL2_Player::BumpWeapon( CBaseCombatWeapon *pWeapon )
  2684. {
  2685.  
  2686. #if HL2_SINGLE_PRIMARY_WEAPON_MODE
  2687.  
  2688. CBaseCombatCharacter *pOwner = pWeapon->GetOwner();
  2689.  
  2690. // Can I have this weapon type?
  2691. if ( pOwner || !Weapon_CanUse( pWeapon ) || !g_pGameRules->CanHavePlayerItem( this, pWeapon ) )
  2692. {
  2693. if ( gEvilImpulse101 )
  2694. {
  2695. UTIL_Remove( pWeapon );
  2696. }
  2697. return false;
  2698. }
  2699.  
  2700. // ----------------------------------------
  2701. // If I already have it just take the ammo
  2702. // ----------------------------------------
  2703. if (Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType()))
  2704. {
  2705. //Only remove the weapon if we attained ammo from it
  2706. if ( Weapon_EquipAmmoOnly( pWeapon ) == false )
  2707. return false;
  2708.  
  2709. // Only remove me if I have no ammo left
  2710. // Can't just check HasAnyAmmo because if I don't use clips, I want to be removed,
  2711. if ( pWeapon->UsesClipsForAmmo1() && pWeapon->HasPrimaryAmmo() )
  2712. return false;
  2713.  
  2714. UTIL_Remove( pWeapon );
  2715. return false;
  2716. }
  2717. // -------------------------
  2718. // Otherwise take the weapon
  2719. // -------------------------
  2720. else
  2721. {
  2722. //Make sure we're not trying to take a new weapon type we already have
  2723. if ( Weapon_SlotOccupied( pWeapon ) )
  2724. {
  2725. CBaseCombatWeapon *pActiveWeapon = Weapon_GetSlot( WEAPON_PRIMARY_SLOT );
  2726.  
  2727. if ( pActiveWeapon != NULL && pActiveWeapon->HasAnyAmmo() == false && Weapon_CanSwitchTo( pWeapon ) )
  2728. {
  2729. Weapon_Equip( pWeapon );
  2730. return true;
  2731. }
  2732.  
  2733. //Attempt to take ammo if this is the gun we're holding already
  2734. if ( Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType() ) )
  2735. {
  2736. Weapon_EquipAmmoOnly( pWeapon );
  2737. }
  2738.  
  2739. return false;
  2740. }
  2741.  
  2742. pWeapon->CheckRespawn();
  2743.  
  2744. pWeapon->AddSolidFlags( FSOLID_NOT_SOLID );
  2745. pWeapon->AddEffects( EF_NODRAW );
  2746.  
  2747. Weapon_Equip( pWeapon );
  2748.  
  2749. EmitSound( "HL2Player.PickupWeapon" );
  2750.  
  2751. return true;
  2752. }
  2753. #else
  2754.  
  2755. return BaseClass::BumpWeapon( pWeapon );
  2756.  
  2757. #endif
  2758.  
  2759. }
  2760.  
  2761. //-----------------------------------------------------------------------------
  2762. // Purpose:
  2763. // Input : *cmd -
  2764. // Output : Returns true on success, false on failure.
  2765. //-----------------------------------------------------------------------------
  2766. bool CHL2_Player::ClientCommand( const CCommand &args )
  2767. {
  2768. #if HL2_SINGLE_PRIMARY_WEAPON_MODE
  2769.  
  2770. //Drop primary weapon
  2771. if ( !Q_stricmp( args[0], "DropPrimary" ) )
  2772. {
  2773. Weapon_DropSlot( WEAPON_PRIMARY_SLOT );
  2774. return true;
  2775. }
  2776.  
  2777. #endif
  2778.  
  2779. if ( !Q_stricmp( args[0], "emit" ) )
  2780. {
  2781. CSingleUserRecipientFilter filter( this );
  2782. if ( args.ArgC() > 1 )
  2783. {
  2784. EmitSound( filter, entindex(), args[ 1 ] );
  2785. }
  2786. else
  2787. {
  2788. EmitSound( filter, entindex(), "Test.Sound" );
  2789. }
  2790. return true;
  2791. }
  2792.  
  2793. return BaseClass::ClientCommand( args );
  2794. }
  2795.  
  2796. //-----------------------------------------------------------------------------
  2797. // Purpose:
  2798. // Output : void CBasePlayer::PlayerUse
  2799. //-----------------------------------------------------------------------------
  2800. void CHL2_Player::PlayerUse ( void )
  2801. {
  2802. // Was use pressed or released?
  2803. if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) )
  2804. return;
  2805.  
  2806. if ( m_afButtonPressed & IN_USE )
  2807. {
  2808. // Currently using a latched entity?
  2809. if ( ClearUseEntity() )
  2810. {
  2811. return;
  2812. }
  2813. else
  2814. {
  2815. if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE )
  2816. {
  2817. m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE;
  2818. m_iTrain = TRAIN_NEW|TRAIN_OFF;
  2819. return;
  2820. }
  2821. else
  2822. { // Start controlling the train!
  2823. CBaseEntity *pTrain = GetGroundEntity();
  2824. if ( pTrain && !(m_nButtons & IN_JUMP) && (GetFlags() & FL_ONGROUND) && (pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) && pTrain->OnControls(this) )
  2825. {
  2826. m_afPhysicsFlags |= PFLAG_DIROVERRIDE;
  2827. m_iTrain = TrainSpeed(pTrain->m_flSpeed, ((CFuncTrackTrain*)pTrain)->GetMaxSpeed());
  2828. m_iTrain |= TRAIN_NEW;
  2829. EmitSound( "HL2Player.TrainUse" );
  2830. return;
  2831. }
  2832. }
  2833. }
  2834.  
  2835. // Tracker 3926: We can't +USE something if we're climbing a ladder
  2836. if ( GetMoveType() == MOVETYPE_LADDER )
  2837. {
  2838. return;
  2839. }
  2840. }
  2841.  
  2842. if( m_flTimeUseSuspended > gpGlobals->curtime )
  2843. {
  2844. // Something has temporarily stopped us being able to USE things.
  2845. // Obviously, this should be used very carefully.(sjb)
  2846. return;
  2847. }
  2848.  
  2849. CBaseEntity *pUseEntity = FindUseEntity();
  2850.  
  2851. bool usedSomething = false;
  2852.  
  2853. // Found an object
  2854. if ( pUseEntity )
  2855. {
  2856. //!!!UNDONE: traceline here to prevent +USEing buttons through walls
  2857. int caps = pUseEntity->ObjectCaps();
  2858. variant_t emptyVariant;
  2859.  
  2860. if ( m_afButtonPressed & IN_USE )
  2861. {
  2862. // Robin: Don't play sounds for NPCs, because NPCs will allow respond with speech.
  2863. if ( !pUseEntity->MyNPCPointer() )
  2864. {
  2865. EmitSound( "HL2Player.Use" );
  2866. }
  2867. }
  2868.  
  2869. if ( ( (m_nButtons & IN_USE) && (caps & FCAP_CONTINUOUS_USE) ) ||
  2870. ( (m_afButtonPressed & IN_USE) && (caps & (FCAP_IMPULSE_USE|FCAP_ONOFF_USE)) ) )
  2871. {
  2872. if ( caps & FCAP_CONTINUOUS_USE )
  2873. m_afPhysicsFlags |= PFLAG_USING;
  2874.  
  2875. pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE );
  2876.  
  2877. usedSomething = true;
  2878. }
  2879. // UNDONE: Send different USE codes for ON/OFF. Cache last ONOFF_USE object to send 'off' if you turn away
  2880. else if ( (m_afButtonReleased & IN_USE) && (pUseEntity->ObjectCaps() & FCAP_ONOFF_USE) ) // BUGBUG This is an "off" use
  2881. {
  2882. pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE );
  2883.  
  2884. usedSomething = true;
  2885. }
  2886.  
  2887. #if HL2_SINGLE_PRIMARY_WEAPON_MODE
  2888.  
  2889. //Check for weapon pick-up
  2890. if ( m_afButtonPressed & IN_USE )
  2891. {
  2892. CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(pUseEntity);
  2893.  
  2894. if ( ( pWeapon != NULL ) && ( Weapon_CanSwitchTo( pWeapon ) ) )
  2895. {
  2896. //Try to take ammo or swap the weapon
  2897. if ( Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType() ) )
  2898. {
  2899. Weapon_EquipAmmoOnly( pWeapon );
  2900. }
  2901. else
  2902. {
  2903. Weapon_DropSlot( pWeapon->GetSlot() );
  2904. Weapon_Equip( pWeapon );
  2905. }
  2906.  
  2907. usedSomething = true;
  2908. }
  2909. }
  2910. #endif
  2911. }
  2912. else if ( m_afButtonPressed & IN_USE )
  2913. {
  2914. // Signal that we want to play the deny sound, unless the user is +USEing on a ladder!
  2915. // The sound is emitted in ItemPostFrame, since that occurs after GameMovement::ProcessMove which
  2916. // lets the ladder code unset this flag.
  2917. m_bPlayUseDenySound = true;
  2918. }
  2919.  
  2920. // Debounce the use key
  2921. if ( usedSomething && pUseEntity )
  2922. {
  2923. m_Local.m_nOldButtons |= IN_USE;
  2924. m_afButtonPressed &= ~IN_USE;
  2925. }
  2926. }
  2927.  
  2928. ConVar sv_show_crosshair_target( "sv_show_crosshair_target", "0" );
  2929.  
  2930. //-----------------------------------------------------------------------------
  2931. // Purpose: Updates the posture of the weapon from lowered to ready
  2932. //-----------------------------------------------------------------------------
  2933. void CHL2_Player::UpdateWeaponPosture( void )
  2934. {
  2935. CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(GetActiveWeapon());
  2936.  
  2937. if ( pWeapon && m_LowerWeaponTimer.Expired() && pWeapon->CanLower() )
  2938. {
  2939. m_LowerWeaponTimer.Set( .3 );
  2940. VPROF( "CHL2_Player::UpdateWeaponPosture-CheckLower" );
  2941. Vector vecAim = BaseClass::GetAutoaimVector( AUTOAIM_SCALE_DIRECT_ONLY );
  2942.  
  2943. const float CHECK_FRIENDLY_RANGE = 50 * 12;
  2944. trace_t tr;
  2945. UTIL_TraceLine( EyePosition(), EyePosition() + vecAim * CHECK_FRIENDLY_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  2946.  
  2947. CBaseEntity *aimTarget = tr.m_pEnt;
  2948.  
  2949. //If we're over something
  2950. if ( aimTarget && !tr.DidHitWorld() )
  2951. {
  2952. if ( !aimTarget->IsNPC() || aimTarget->MyNPCPointer()->GetState() != NPC_STATE_COMBAT )
  2953. {
  2954. Disposition_t dis = IRelationType( aimTarget );
  2955.  
  2956. //Debug info for seeing what an object "cons" as
  2957. if ( sv_show_crosshair_target.GetBool() )
  2958. {
  2959. int text_offset = BaseClass::DrawDebugTextOverlays();
  2960.  
  2961. char tempstr[255];
  2962.  
  2963. switch ( dis )
  2964. {
  2965. case D_LI:
  2966. Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Like" );
  2967. break;
  2968.  
  2969. case D_HT:
  2970. Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Hate" );
  2971. break;
  2972.  
  2973. case D_FR:
  2974. Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Fear" );
  2975. break;
  2976.  
  2977. case D_NU:
  2978. Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Neutral" );
  2979. break;
  2980.  
  2981. default:
  2982. case D_ER:
  2983. Q_snprintf( tempstr, sizeof(tempstr), "Disposition: !!!ERROR!!!" );
  2984. break;
  2985. }
  2986.  
  2987. //Draw the text
  2988. NDebugOverlay::EntityText( aimTarget->entindex(), text_offset, tempstr, 0 );
  2989. }
  2990.  
  2991. //See if we hates it
  2992. if ( dis == D_LI )
  2993. {
  2994. //We're over a friendly, drop our weapon
  2995. if ( Weapon_Lower() == false )
  2996. {
  2997. //FIXME: We couldn't lower our weapon!
  2998. }
  2999.  
  3000. return;
  3001. }
  3002. }
  3003. }
  3004.  
  3005. if ( Weapon_Ready() == false )
  3006. {
  3007. //FIXME: We couldn't raise our weapon!
  3008. }
  3009. }
  3010.  
  3011. if( g_pGameRules->GetAutoAimMode() != AUTOAIM_NONE )
  3012. {
  3013. if( !pWeapon )
  3014. {
  3015. // This tells the client to draw no crosshair
  3016. m_HL2Local.m_bWeaponLowered = true;
  3017. return;
  3018. }
  3019. else
  3020. {
  3021. if( !pWeapon->CanLower() && m_HL2Local.m_bWeaponLowered )
  3022. m_HL2Local.m_bWeaponLowered = false;
  3023. }
  3024.  
  3025. if( !m_AutoaimTimer.Expired() )
  3026. return;
  3027.  
  3028. m_AutoaimTimer.Set( .1 );
  3029.  
  3030. VPROF( "hl2_x360_aiming" );
  3031.  
  3032. // Call the autoaim code to update the local player data, which allows the client to update.
  3033. autoaim_params_t params;
  3034. params.m_vecAutoAimPoint.Init();
  3035. params.m_vecAutoAimDir.Init();
  3036. params.m_fScale = AUTOAIM_SCALE_DEFAULT;
  3037. params.m_fMaxDist = autoaim_max_dist.GetFloat();
  3038. GetAutoaimVector( params );
  3039. m_HL2Local.m_hAutoAimTarget.Set( params.m_hAutoAimEntity );
  3040. m_HL2Local.m_vecAutoAimPoint.Set( params.m_vecAutoAimPoint );
  3041. m_HL2Local.m_bAutoAimTarget = ( params.m_bAutoAimAssisting || params.m_bOnTargetNatural );
  3042. return;
  3043. }
  3044. else
  3045. {
  3046. // Make sure there's no residual autoaim target if the user changes the xbox_aiming convar on the fly.
  3047. m_HL2Local.m_hAutoAimTarget.Set(NULL);
  3048. }
  3049. }
  3050.  
  3051. //-----------------------------------------------------------------------------
  3052. // Purpose: Lowers the weapon posture (for hovering over friendlies)
  3053. // Output : Returns true on success, false on failure.
  3054. //-----------------------------------------------------------------------------
  3055. bool CHL2_Player::Weapon_Lower( void )
  3056. {
  3057. VPROF( "CHL2_Player::Weapon_Lower" );
  3058. // Already lowered?
  3059. if ( m_HL2Local.m_bWeaponLowered )
  3060. return true;
  3061.  
  3062. m_HL2Local.m_bWeaponLowered = true;
  3063.  
  3064. CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(GetActiveWeapon());
  3065.  
  3066. if ( pWeapon == NULL )
  3067. return false;
  3068.  
  3069. return pWeapon->Lower();
  3070. }
  3071.  
  3072. //-----------------------------------------------------------------------------
  3073. // Purpose: Returns the weapon posture to normal
  3074. // Output : Returns true on success, false on failure.
  3075. //-----------------------------------------------------------------------------
  3076. bool CHL2_Player::Weapon_Ready( void )
  3077. {
  3078. VPROF( "CHL2_Player::Weapon_Ready" );
  3079.  
  3080. // Already ready?
  3081. if ( m_HL2Local.m_bWeaponLowered == false )
  3082. return true;
  3083.  
  3084. m_HL2Local.m_bWeaponLowered = false;
  3085.  
  3086. CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(GetActiveWeapon());
  3087.  
  3088. if ( pWeapon == NULL )
  3089. return false;
  3090.  
  3091. return pWeapon->Ready();
  3092. }
  3093.  
  3094. //-----------------------------------------------------------------------------
  3095. // Purpose: Returns whether or not we can switch to the given weapon.
  3096. // Input : pWeapon -
  3097. //-----------------------------------------------------------------------------
  3098. bool CHL2_Player::Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon )
  3099. {
  3100. CBasePlayer *pPlayer = (CBasePlayer *)this;
  3101. #if !defined( CLIENT_DLL )
  3102. IServerVehicle *pVehicle = pPlayer->GetVehicle();
  3103. #else
  3104. IClientVehicle *pVehicle = pPlayer->GetVehicle();
  3105. #endif
  3106. if (pVehicle && !pPlayer->UsingStandardWeaponsInVehicle())
  3107. return false;
  3108.  
  3109. if ( !pWeapon->HasAnyAmmo() && !GetAmmoCount( pWeapon->m_iPrimaryAmmoType ) )
  3110. return false;
  3111.  
  3112. if ( !pWeapon->CanDeploy() )
  3113. return false;
  3114.  
  3115. if ( GetActiveWeapon() )
  3116. {
  3117. if ( PhysCannonGetHeldEntity( GetActiveWeapon() ) == pWeapon &&
  3118. Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType()) )
  3119. {
  3120. return true;
  3121. }
  3122.  
  3123. if ( !GetActiveWeapon()->CanHolster() )
  3124. return false;
  3125. }
  3126.  
  3127. return true;
  3128. }
  3129.  
  3130. void CHL2_Player::PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize )
  3131. {
  3132. // can't pick up what you're standing on
  3133. if ( GetGroundEntity() == pObject )
  3134. return;
  3135.  
  3136. if ( bLimitMassAndSize == true )
  3137. {
  3138. if ( CBasePlayer::CanPickupObject( pObject, 35, 128 ) == false )
  3139. return;
  3140. }
  3141.  
  3142. // Can't be picked up if NPCs are on me
  3143. if ( pObject->HasNPCsOnIt() )
  3144. return;
  3145.  
  3146. PlayerPickupObject( this, pObject );
  3147. }
  3148.  
  3149. //-----------------------------------------------------------------------------
  3150. // Purpose:
  3151. // Output : CBaseEntity
  3152. //-----------------------------------------------------------------------------
  3153. bool CHL2_Player::IsHoldingEntity( CBaseEntity *pEnt )
  3154. {
  3155. return PlayerPickupControllerIsHoldingEntity( m_hUseEntity, pEnt );
  3156. }
  3157.  
  3158. float CHL2_Player::GetHeldObjectMass( IPhysicsObject *pHeldObject )
  3159. {
  3160. float mass = PlayerPickupGetHeldObjectMass( m_hUseEntity, pHeldObject );
  3161. if ( mass == 0.0f )
  3162. {
  3163. mass = PhysCannonGetHeldObjectMass( GetActiveWeapon(), pHeldObject );
  3164. }
  3165. return mass;
  3166. }
  3167.  
  3168. //-----------------------------------------------------------------------------
  3169. // Purpose: Force the player to drop any physics objects he's carrying
  3170. //-----------------------------------------------------------------------------
  3171. void CHL2_Player::ForceDropOfCarriedPhysObjects( CBaseEntity *pOnlyIfHoldingThis )
  3172. {
  3173. if ( PhysIsInCallback() )
  3174. {
  3175. variant_t value;
  3176. g_EventQueue.AddEvent( this, "ForceDropPhysObjects", value, 0.01f, pOnlyIfHoldingThis, this );
  3177. return;
  3178. }
  3179.  
  3180. #ifdef HL2_EPISODIC
  3181. if ( hl2_episodic.GetBool() )
  3182. {
  3183. CBaseEntity *pHeldEntity = PhysCannonGetHeldEntity( GetActiveWeapon() );
  3184. if( pHeldEntity && pHeldEntity->ClassMatches( "grenade_helicopter" ) )
  3185. {
  3186. return;
  3187. }
  3188. }
  3189. #endif
  3190.  
  3191. // Drop any objects being handheld.
  3192. ClearUseEntity();
  3193.  
  3194. // Then force the physcannon to drop anything it's holding, if it's our active weapon
  3195. PhysCannonForceDrop( GetActiveWeapon(), NULL );
  3196. }
  3197.  
  3198. void CHL2_Player::InputForceDropPhysObjects( inputdata_t &data )
  3199. {
  3200. ForceDropOfCarriedPhysObjects( data.pActivator );
  3201. }
  3202.  
  3203.  
  3204. //-----------------------------------------------------------------------------
  3205. // Purpose:
  3206. //-----------------------------------------------------------------------------
  3207. void CHL2_Player::UpdateClientData( void )
  3208. {
  3209. if (m_DmgTake || m_DmgSave || m_bitsHUDDamage != m_bitsDamageType)
  3210. {
  3211. // Comes from inside me if not set
  3212. Vector damageOrigin = GetLocalOrigin();
  3213. // send "damage" message
  3214. // causes screen to flash, and pain compass to show direction of damage
  3215. damageOrigin = m_DmgOrigin;
  3216.  
  3217. // only send down damage type that have hud art
  3218. int iShowHudDamage = g_pGameRules->Damage_GetShowOnHud();
  3219. int visibleDamageBits = m_bitsDamageType & iShowHudDamage;
  3220.  
  3221. m_DmgTake = clamp( m_DmgTake, 0, 255 );
  3222. m_DmgSave = clamp( m_DmgSave, 0, 255 );
  3223.  
  3224. // If we're poisoned, but it wasn't this frame, don't send the indicator
  3225. // Without this check, any damage that occured to the player while they were
  3226. // recovering from a poison bite would register as poisonous as well and flash
  3227. // the whole screen! -- jdw
  3228. if ( visibleDamageBits & DMG_POISON )
  3229. {
  3230. float flLastPoisonedDelta = gpGlobals->curtime - m_tbdPrev;
  3231. if ( flLastPoisonedDelta > 0.1f )
  3232. {
  3233. visibleDamageBits &= ~DMG_POISON;
  3234. }
  3235. }
  3236.  
  3237. CSingleUserRecipientFilter user( this );
  3238. user.MakeReliable();
  3239. UserMessageBegin( user, "Damage" );
  3240. WRITE_BYTE( m_DmgSave );
  3241. WRITE_BYTE( m_DmgTake );
  3242. WRITE_LONG( visibleDamageBits );
  3243. WRITE_FLOAT( damageOrigin.x ); //BUG: Should be fixed point (to hud) not floats
  3244. WRITE_FLOAT( damageOrigin.y ); //BUG: However, the HUD does _not_ implement bitfield messages (yet)
  3245. WRITE_FLOAT( damageOrigin.z ); //BUG: We use WRITE_VEC3COORD for everything else
  3246. MessageEnd();
  3247.  
  3248. m_DmgTake = 0;
  3249. m_DmgSave = 0;
  3250. m_bitsHUDDamage = m_bitsDamageType;
  3251.  
  3252. // Clear off non-time-based damage indicators
  3253. int iTimeBasedDamage = g_pGameRules->Damage_GetTimeBased();
  3254. m_bitsDamageType &= iTimeBasedDamage;
  3255. }
  3256.  
  3257. // Update Flashlight
  3258. #ifdef HL2_EPISODIC
  3259. if ( Flashlight_UseLegacyVersion() == false )
  3260. {
  3261. if ( FlashlightIsOn() && sv_infinite_aux_power.GetBool() == false )
  3262. {
  3263. m_HL2Local.m_flFlashBattery -= FLASH_DRAIN_TIME * gpGlobals->frametime;
  3264. if ( m_HL2Local.m_flFlashBattery < 0.0f )
  3265. {
  3266. FlashlightTurnOff();
  3267. m_HL2Local.m_flFlashBattery = 0.0f;
  3268. }
  3269. }
  3270. else
  3271. {
  3272. m_HL2Local.m_flFlashBattery += FLASH_CHARGE_TIME * gpGlobals->frametime;
  3273. if ( m_HL2Local.m_flFlashBattery > 100.0f )
  3274. {
  3275. m_HL2Local.m_flFlashBattery = 100.0f;
  3276. }
  3277. }
  3278. }
  3279. else
  3280. {
  3281. m_HL2Local.m_flFlashBattery = -1.0f;
  3282. }
  3283. #endif // HL2_EPISODIC
  3284.  
  3285. BaseClass::UpdateClientData();
  3286. }
  3287.  
  3288. //---------------------------------------------------------
  3289. //---------------------------------------------------------
  3290. void CHL2_Player::OnRestore()
  3291. {
  3292. BaseClass::OnRestore();
  3293. m_pPlayerAISquad = g_AI_SquadManager.FindCreateSquad(AllocPooledString(PLAYER_SQUADNAME));
  3294. }
  3295.  
  3296. //---------------------------------------------------------
  3297. //---------------------------------------------------------
  3298. Vector CHL2_Player::EyeDirection2D( void )
  3299. {
  3300. Vector vecReturn = EyeDirection3D();
  3301. vecReturn.z = 0;
  3302. vecReturn.AsVector2D().NormalizeInPlace();
  3303.  
  3304. return vecReturn;
  3305. }
  3306.  
  3307. //---------------------------------------------------------
  3308. //---------------------------------------------------------
  3309. Vector CHL2_Player::EyeDirection3D( void )
  3310. {
  3311. Vector vecForward;
  3312.  
  3313. // Return the vehicle angles if we request them
  3314. if ( GetVehicle() != NULL )
  3315. {
  3316. CacheVehicleView();
  3317. EyeVectors( &vecForward );
  3318. return vecForward;
  3319. }
  3320.  
  3321. AngleVectors( EyeAngles(), &vecForward );
  3322. return vecForward;
  3323. }
  3324.  
  3325.  
  3326. //---------------------------------------------------------
  3327. //---------------------------------------------------------
  3328. bool CHL2_Player::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex )
  3329. {
  3330. MDLCACHE_CRITICAL_SECTION();
  3331.  
  3332. // Recalculate proficiency!
  3333. SetCurrentWeaponProficiency( CalcWeaponProficiency( pWeapon ) );
  3334.  
  3335. // Come out of suit zoom mode
  3336. if ( IsZooming() )
  3337. {
  3338. StopZooming();
  3339. }
  3340.  
  3341. return BaseClass::Weapon_Switch( pWeapon, viewmodelindex );
  3342. }
  3343.  
  3344.  
  3345. //-----------------------------------------------------------------------------
  3346. //-----------------------------------------------------------------------------
  3347. WeaponProficiency_t CHL2_Player::CalcWeaponProficiency( CBaseCombatWeapon *pWeapon )
  3348. {
  3349. WeaponProficiency_t proficiency;
  3350.  
  3351. proficiency = WEAPON_PROFICIENCY_PERFECT;
  3352.  
  3353. if( weapon_showproficiency.GetBool() != 0 )
  3354. {
  3355. Msg("Player switched to %s, proficiency is %s\n", pWeapon->GetClassname(), GetWeaponProficiencyName( proficiency ) );
  3356. }
  3357.  
  3358. return proficiency;
  3359. }
  3360.  
  3361. //-----------------------------------------------------------------------------
  3362. // Purpose: override how single player rays hit the player
  3363. //-----------------------------------------------------------------------------
  3364.  
  3365. bool LineCircleIntersection(
  3366. const Vector2D &center,
  3367. const float radius,
  3368. const Vector2D &vLinePt,
  3369. const Vector2D &vLineDir,
  3370. float *fIntersection1,
  3371. float *fIntersection2)
  3372. {
  3373. // Line = P + Vt
  3374. // Sphere = r (assume we've translated to origin)
  3375. // (P + Vt)^2 = r^2
  3376. // VVt^2 + 2PVt + (PP - r^2)
  3377. // Solve as quadratic: (-b +/- sqrt(b^2 - 4ac)) / 2a
  3378. // If (b^2 - 4ac) is < 0 there is no solution.
  3379. // If (b^2 - 4ac) is = 0 there is one solution (a case this function doesn't support).
  3380. // If (b^2 - 4ac) is > 0 there are two solutions.
  3381. Vector2D P;
  3382. float a, b, c, sqr, insideSqr;
  3383.  
  3384.  
  3385. // Translate circle to origin.
  3386. P[0] = vLinePt[0] - center[0];
  3387. P[1] = vLinePt[1] - center[1];
  3388.  
  3389. a = vLineDir.Dot(vLineDir);
  3390. b = 2.0f * P.Dot(vLineDir);
  3391. c = P.Dot(P) - (radius * radius);
  3392.  
  3393. insideSqr = b*b - 4*a*c;
  3394. if(insideSqr <= 0.000001f)
  3395. return false;
  3396.  
  3397. // Ok, two solutions.
  3398. sqr = (float)FastSqrt(insideSqr);
  3399.  
  3400. float denom = 1.0 / (2.0f * a);
  3401.  
  3402. *fIntersection1 = (-b - sqr) * denom;
  3403. *fIntersection2 = (-b + sqr) * denom;
  3404.  
  3405. return true;
  3406. }
  3407.  
  3408. static void Collision_ClearTrace( const Vector &vecRayStart, const Vector &vecRayDelta, CBaseTrace *pTrace )
  3409. {
  3410. pTrace->startpos = vecRayStart;
  3411. pTrace->endpos = vecRayStart;
  3412. pTrace->endpos += vecRayDelta;
  3413. pTrace->startsolid = false;
  3414. pTrace->allsolid = false;
  3415. pTrace->fraction = 1.0f;
  3416. pTrace->contents = 0;
  3417. }
  3418.  
  3419.  
  3420. bool IntersectRayWithAACylinder( const Ray_t &ray,
  3421. const Vector &center, float radius, float height, CBaseTrace *pTrace )
  3422. {
  3423. Assert( ray.m_IsRay );
  3424. Collision_ClearTrace( ray.m_Start, ray.m_Delta, pTrace );
  3425.  
  3426. // First intersect the ray with the top + bottom planes
  3427. float halfHeight = height * 0.5;
  3428.  
  3429. // Handle parallel case
  3430. Vector vStart = ray.m_Start - center;
  3431. Vector vEnd = vStart + ray.m_Delta;
  3432.  
  3433. float flEnterFrac, flLeaveFrac;
  3434. if (FloatMakePositive(ray.m_Delta.z) < 1e-8)
  3435. {
  3436. if ( (vStart.z < -halfHeight) || (vStart.z > halfHeight) )
  3437. {
  3438. return false; // no hit
  3439. }
  3440. flEnterFrac = 0.0f; flLeaveFrac = 1.0f;
  3441. }
  3442. else
  3443. {
  3444. // Clip the ray to the top and bottom of box
  3445. flEnterFrac = IntersectRayWithAAPlane( vStart, vEnd, 2, 1, halfHeight);
  3446. flLeaveFrac = IntersectRayWithAAPlane( vStart, vEnd, 2, 1, -halfHeight);
  3447.  
  3448. if ( flLeaveFrac < flEnterFrac )
  3449. {
  3450. float temp = flLeaveFrac;
  3451. flLeaveFrac = flEnterFrac;
  3452. flEnterFrac = temp;
  3453. }
  3454.  
  3455. if ( flLeaveFrac < 0 || flEnterFrac > 1)
  3456. {
  3457. return false;
  3458. }
  3459. }
  3460.  
  3461. // Intersect with circle
  3462. float flCircleEnterFrac, flCircleLeaveFrac;
  3463. if ( !LineCircleIntersection( vec3_origin.AsVector2D(), radius,
  3464. vStart.AsVector2D(), ray.m_Delta.AsVector2D(), &flCircleEnterFrac, &flCircleLeaveFrac ) )
  3465. {
  3466. return false; // no hit
  3467. }
  3468.  
  3469. Assert( flCircleEnterFrac <= flCircleLeaveFrac );
  3470. if ( flCircleLeaveFrac < 0 || flCircleEnterFrac > 1)
  3471. {
  3472. return false;
  3473. }
  3474.  
  3475. if ( flEnterFrac < flCircleEnterFrac )
  3476. flEnterFrac = flCircleEnterFrac;
  3477. if ( flLeaveFrac > flCircleLeaveFrac )
  3478. flLeaveFrac = flCircleLeaveFrac;
  3479.  
  3480. if ( flLeaveFrac < flEnterFrac )
  3481. return false;
  3482.  
  3483. VectorMA( ray.m_Start, flEnterFrac , ray.m_Delta, pTrace->endpos );
  3484. pTrace->fraction = flEnterFrac;
  3485. pTrace->contents = CONTENTS_SOLID;
  3486.  
  3487. // Calculate the point on our center line where we're nearest the intersection point
  3488. Vector collisionCenter;
  3489. CalcClosestPointOnLineSegment( pTrace->endpos, center + Vector( 0, 0, halfHeight ), center - Vector( 0, 0, halfHeight ), collisionCenter );
  3490.  
  3491. // Our normal is the direction from that center point to the intersection point
  3492. pTrace->plane.normal = pTrace->endpos - collisionCenter;
  3493. VectorNormalize( pTrace->plane.normal );
  3494.  
  3495. return true;
  3496. }
  3497.  
  3498.  
  3499. bool CHL2_Player::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr )
  3500. {
  3501. if( g_pGameRules->IsMultiplayer() )
  3502. {
  3503. return BaseClass::TestHitboxes( ray, fContentsMask, tr );
  3504. }
  3505. else
  3506. {
  3507. Assert( ray.m_IsRay );
  3508.  
  3509. Vector mins, maxs;
  3510.  
  3511. mins = WorldAlignMins();
  3512. maxs = WorldAlignMaxs();
  3513.  
  3514. if ( IntersectRayWithAACylinder( ray, WorldSpaceCenter(), maxs.x * PLAYER_HULL_REDUCTION, maxs.z - mins.z, &tr ) )
  3515. {
  3516. tr.hitbox = 0;
  3517. CStudioHdr *pStudioHdr = GetModelPtr( );
  3518. if (!pStudioHdr)
  3519. return false;
  3520.  
  3521. mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet );
  3522. if ( !set || !set->numhitboxes )
  3523. return false;
  3524.  
  3525. mstudiobbox_t *pbox = set->pHitbox( tr.hitbox );
  3526. mstudiobone_t *pBone = pStudioHdr->pBone(pbox->bone);
  3527. tr.surface.name = "**studio**";
  3528. tr.surface.flags = SURF_HITBOX;
  3529. tr.surface.surfaceProps = physprops->GetSurfaceIndex( pBone->pszSurfaceProp() );
  3530. }
  3531.  
  3532. return true;
  3533. }
  3534. }
  3535.  
  3536. //---------------------------------------------------------
  3537. // Show the player's scaled down bbox that we use for
  3538. // bullet impacts.
  3539. //---------------------------------------------------------
  3540. void CHL2_Player::DrawDebugGeometryOverlays(void)
  3541. {
  3542. BaseClass::DrawDebugGeometryOverlays();
  3543.  
  3544. if (m_debugOverlays & OVERLAY_BBOX_BIT)
  3545. {
  3546. Vector mins, maxs;
  3547.  
  3548. mins = WorldAlignMins();
  3549. maxs = WorldAlignMaxs();
  3550.  
  3551. mins.x *= PLAYER_HULL_REDUCTION;
  3552. mins.y *= PLAYER_HULL_REDUCTION;
  3553.  
  3554. maxs.x *= PLAYER_HULL_REDUCTION;
  3555. maxs.y *= PLAYER_HULL_REDUCTION;
  3556.  
  3557. NDebugOverlay::Box( GetAbsOrigin(), mins, maxs, 255, 0, 0, 100, 0 );
  3558. }
  3559. }
  3560.  
  3561. //-----------------------------------------------------------------------------
  3562. // Purpose: Helper to remove from ladder
  3563. //-----------------------------------------------------------------------------
  3564. void CHL2_Player::ExitLadder()
  3565. {
  3566. if ( MOVETYPE_LADDER != GetMoveType() )
  3567. return;
  3568.  
  3569. SetMoveType( MOVETYPE_WALK );
  3570. SetMoveCollide( MOVECOLLIDE_DEFAULT );
  3571. // Remove from ladder
  3572. m_HL2Local.m_hLadder.Set( NULL );
  3573. }
  3574.  
  3575.  
  3576. surfacedata_t *CHL2_Player::GetLadderSurface( const Vector &origin )
  3577. {
  3578. extern const char *FuncLadder_GetSurfaceprops(CBaseEntity *pLadderEntity);
  3579.  
  3580. CBaseEntity *pLadder = m_HL2Local.m_hLadder.Get();
  3581. if ( pLadder )
  3582. {
  3583. const char *pSurfaceprops = FuncLadder_GetSurfaceprops(pLadder);
  3584. // get ladder material from func_ladder
  3585. return physprops->GetSurfaceData( physprops->GetSurfaceIndex( pSurfaceprops ) );
  3586.  
  3587. }
  3588. return BaseClass::GetLadderSurface(origin);
  3589. }
  3590.  
  3591. //-----------------------------------------------------------------------------
  3592. // Purpose: Queues up a use deny sound, played in ItemPostFrame.
  3593. //-----------------------------------------------------------------------------
  3594. void CHL2_Player::PlayUseDenySound()
  3595. {
  3596. m_bPlayUseDenySound = true;
  3597. }
  3598.  
  3599.  
  3600. void CHL2_Player::ItemPostFrame()
  3601. {
  3602. BaseClass::ItemPostFrame();
  3603.  
  3604. if ( m_bPlayUseDenySound )
  3605. {
  3606. m_bPlayUseDenySound = false;
  3607. EmitSound( "HL2Player.UseDeny" );
  3608. }
  3609. }
  3610.  
  3611.  
  3612. void CHL2_Player::StartWaterDeathSounds( void )
  3613. {
  3614. CPASAttenuationFilter filter( this );
  3615.  
  3616. if ( m_sndLeeches == NULL )
  3617. {
  3618. m_sndLeeches = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "coast.leech_bites_loop" , ATTN_NORM );
  3619. }
  3620.  
  3621. if ( m_sndLeeches )
  3622. {
  3623. (CSoundEnvelopeController::GetController()).Play( m_sndLeeches, 1.0f, 100 );
  3624. }
  3625.  
  3626. if ( m_sndWaterSplashes == NULL )
  3627. {
  3628. m_sndWaterSplashes = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "coast.leech_water_churn_loop" , ATTN_NORM );
  3629. }
  3630.  
  3631. if ( m_sndWaterSplashes )
  3632. {
  3633. (CSoundEnvelopeController::GetController()).Play( m_sndWaterSplashes, 1.0f, 100 );
  3634. }
  3635. }
  3636.  
  3637. void CHL2_Player::StopWaterDeathSounds( void )
  3638. {
  3639. if ( m_sndLeeches )
  3640. {
  3641. (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndLeeches, 0.5f, true );
  3642. m_sndLeeches = NULL;
  3643. }
  3644.  
  3645. if ( m_sndWaterSplashes )
  3646. {
  3647. (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndWaterSplashes, 0.5f, true );
  3648. m_sndWaterSplashes = NULL;
  3649. }
  3650. }
  3651.  
  3652. //-----------------------------------------------------------------------------
  3653. //
  3654. //-----------------------------------------------------------------------------
  3655. void CHL2_Player::MissedAR2AltFire()
  3656. {
  3657. if( GetPlayerProxy() != NULL )
  3658. {
  3659. GetPlayerProxy()->m_PlayerMissedAR2AltFire.FireOutput( this, this );
  3660. }
  3661. }
  3662.  
  3663. //-----------------------------------------------------------------------------
  3664. //
  3665. //-----------------------------------------------------------------------------
  3666. void CHL2_Player::DisplayLadderHudHint()
  3667. {
  3668. #if !defined( CLIENT_DLL )
  3669. if( gpGlobals->curtime > m_flTimeNextLadderHint )
  3670. {
  3671. m_flTimeNextLadderHint = gpGlobals->curtime + 60.0f;
  3672.  
  3673. CFmtStr hint;
  3674. hint.sprintf( "#Valve_Hint_Ladder" );
  3675. UTIL_HudHintText( this, hint.Access() );
  3676. }
  3677. #endif//CLIENT_DLL
  3678. }
  3679.  
  3680. //-----------------------------------------------------------------------------
  3681. // Shuts down sounds
  3682. //-----------------------------------------------------------------------------
  3683. void CHL2_Player::StopLoopingSounds( void )
  3684. {
  3685. if ( m_sndLeeches != NULL )
  3686. {
  3687. (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndLeeches );
  3688. m_sndLeeches = NULL;
  3689. }
  3690.  
  3691. if ( m_sndWaterSplashes != NULL )
  3692. {
  3693. (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndWaterSplashes );
  3694. m_sndWaterSplashes = NULL;
  3695. }
  3696.  
  3697. BaseClass::StopLoopingSounds();
  3698. }
  3699.  
  3700. //-----------------------------------------------------------------------------
  3701. void CHL2_Player::ModifyOrAppendPlayerCriteria( AI_CriteriaSet& set )
  3702. {
  3703. BaseClass::ModifyOrAppendPlayerCriteria( set );
  3704.  
  3705. if ( GlobalEntity_GetIndex( "gordon_precriminal" ) == -1 )
  3706. {
  3707. set.AppendCriteria( "gordon_precriminal", "0" );
  3708. }
  3709. }
  3710.  
  3711.  
  3712. //-----------------------------------------------------------------------------
  3713. //-----------------------------------------------------------------------------
  3714. const impactdamagetable_t &CHL2_Player::GetPhysicsImpactDamageTable()
  3715. {
  3716. if ( m_bUseCappedPhysicsDamageTable )
  3717. return gCappedPlayerImpactDamageTable;
  3718.  
  3719. return BaseClass::GetPhysicsImpactDamageTable();
  3720. }
  3721.  
  3722.  
  3723. //-----------------------------------------------------------------------------
  3724. // Purpose: Makes a splash when the player transitions between water states
  3725. //-----------------------------------------------------------------------------
  3726. void CHL2_Player::Splash( void )
  3727. {
  3728. CEffectData data;
  3729. data.m_fFlags = 0;
  3730. data.m_vOrigin = GetAbsOrigin();
  3731. data.m_vNormal = Vector(0,0,1);
  3732. data.m_vAngles = QAngle( 0, 0, 0 );
  3733.  
  3734. if ( GetWaterType() & CONTENTS_SLIME )
  3735. {
  3736. data.m_fFlags |= FX_WATER_IN_SLIME;
  3737. }
  3738.  
  3739. float flSpeed = GetAbsVelocity().Length();
  3740. if ( flSpeed < 300 )
  3741. {
  3742. data.m_flScale = random->RandomFloat( 10, 12 );
  3743. DispatchEffect( "waterripple", data );
  3744. }
  3745. else
  3746. {
  3747. data.m_flScale = random->RandomFloat( 6, 8 );
  3748. DispatchEffect( "watersplash", data );
  3749. }
  3750. }
  3751.  
  3752. CLogicPlayerProxy *CHL2_Player::GetPlayerProxy( void )
  3753. {
  3754. CLogicPlayerProxy *pProxy = dynamic_cast< CLogicPlayerProxy* > ( m_hPlayerProxy.Get() );
  3755.  
  3756. if ( pProxy == NULL )
  3757. {
  3758. pProxy = (CLogicPlayerProxy*)gEntList.FindEntityByClassname(NULL, "logic_playerproxy" );
  3759.  
  3760. if ( pProxy == NULL )
  3761. return NULL;
  3762.  
  3763. pProxy->m_hPlayer = this;
  3764. m_hPlayerProxy = pProxy;
  3765. }
  3766.  
  3767. return pProxy;
  3768. }
  3769.  
  3770. void CHL2_Player::FirePlayerProxyOutput( const char *pszOutputName, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller )
  3771. {
  3772. if ( GetPlayerProxy() == NULL )
  3773. return;
  3774.  
  3775. GetPlayerProxy()->FireNamedOutput( pszOutputName, variant, pActivator, pCaller );
  3776. }
  3777.  
  3778. LINK_ENTITY_TO_CLASS( logic_playerproxy, CLogicPlayerProxy);
  3779.  
  3780. BEGIN_DATADESC( CLogicPlayerProxy )
  3781. DEFINE_OUTPUT( m_OnFlashlightOn, "OnFlashlightOn" ),
  3782. DEFINE_OUTPUT( m_OnFlashlightOff, "OnFlashlightOff" ),
  3783. DEFINE_OUTPUT( m_RequestedPlayerHealth, "PlayerHealth" ),
  3784. DEFINE_OUTPUT( m_PlayerHasAmmo, "PlayerHasAmmo" ),
  3785. DEFINE_OUTPUT( m_PlayerHasNoAmmo, "PlayerHasNoAmmo" ),
  3786. DEFINE_OUTPUT( m_PlayerDied, "PlayerDied" ),
  3787. DEFINE_OUTPUT( m_PlayerMissedAR2AltFire, "PlayerMissedAR2AltFire" ),
  3788. DEFINE_INPUTFUNC( FIELD_VOID, "RequestPlayerHealth", InputRequestPlayerHealth ),
  3789. DEFINE_INPUTFUNC( FIELD_VOID, "SetFlashlightSlowDrain", InputSetFlashlightSlowDrain ),
  3790. DEFINE_INPUTFUNC( FIELD_VOID, "SetFlashlightNormalDrain", InputSetFlashlightNormalDrain ),
  3791. DEFINE_INPUTFUNC( FIELD_INTEGER, "SetPlayerHealth", InputSetPlayerHealth ),
  3792. DEFINE_INPUTFUNC( FIELD_VOID, "RequestAmmoState", InputRequestAmmoState ),
  3793. DEFINE_INPUTFUNC( FIELD_VOID, "LowerWeapon", InputLowerWeapon ),
  3794. DEFINE_INPUTFUNC( FIELD_VOID, "EnableCappedPhysicsDamage", InputEnableCappedPhysicsDamage ),
  3795. DEFINE_INPUTFUNC( FIELD_VOID, "DisableCappedPhysicsDamage", InputDisableCappedPhysicsDamage ),
  3796. DEFINE_INPUTFUNC( FIELD_STRING, "SetLocatorTargetEntity", InputSetLocatorTargetEntity ),
  3797. #ifdef PORTAL
  3798. DEFINE_INPUTFUNC( FIELD_VOID, "SuppressCrosshair", InputSuppressCrosshair ),
  3799. #endif // PORTAL
  3800. DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ),
  3801. END_DATADESC()
  3802.  
  3803. void CLogicPlayerProxy::Activate( void )
  3804. {
  3805. BaseClass::Activate();
  3806.  
  3807. if ( m_hPlayer == NULL )
  3808. {
  3809. m_hPlayer = AI_GetSinglePlayer();
  3810. }
  3811. }
  3812.  
  3813. bool CLogicPlayerProxy::PassesDamageFilter( const CTakeDamageInfo &info )
  3814. {
  3815. if (m_hDamageFilter)
  3816. {
  3817. CBaseFilter *pFilter = (CBaseFilter *)(m_hDamageFilter.Get());
  3818. return pFilter->PassesDamageFilter(info);
  3819. }
  3820.  
  3821. return true;
  3822. }
  3823.  
  3824. void CLogicPlayerProxy::InputSetPlayerHealth( inputdata_t &inputdata )
  3825. {
  3826. if ( m_hPlayer == NULL )
  3827. return;
  3828.  
  3829. m_hPlayer->SetHealth( inputdata.value.Int() );
  3830.  
  3831. }
  3832.  
  3833. void CLogicPlayerProxy::InputRequestPlayerHealth( inputdata_t &inputdata )
  3834. {
  3835. if ( m_hPlayer == NULL )
  3836. return;
  3837.  
  3838. m_RequestedPlayerHealth.Set( m_hPlayer->GetHealth(), inputdata.pActivator, inputdata.pCaller );
  3839. }
  3840.  
  3841. void CLogicPlayerProxy::InputSetFlashlightSlowDrain( inputdata_t &inputdata )
  3842. {
  3843. if( m_hPlayer == NULL )
  3844. return;
  3845.  
  3846. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(m_hPlayer.Get());
  3847.  
  3848. if( pPlayer )
  3849. pPlayer->SetFlashlightPowerDrainScale( hl2_darkness_flashlight_factor.GetFloat() );
  3850. }
  3851.  
  3852. void CLogicPlayerProxy::InputSetFlashlightNormalDrain( inputdata_t &inputdata )
  3853. {
  3854. if( m_hPlayer == NULL )
  3855. return;
  3856.  
  3857. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(m_hPlayer.Get());
  3858.  
  3859. if( pPlayer )
  3860. pPlayer->SetFlashlightPowerDrainScale( 1.0f );
  3861. }
  3862.  
  3863. void CLogicPlayerProxy::InputRequestAmmoState( inputdata_t &inputdata )
  3864. {
  3865. if( m_hPlayer == NULL )
  3866. return;
  3867.  
  3868. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(m_hPlayer.Get());
  3869.  
  3870. for ( int i = 0 ; i < pPlayer->WeaponCount(); ++i )
  3871. {
  3872. CBaseCombatWeapon* pCheck = pPlayer->GetWeapon( i );
  3873.  
  3874. if ( pCheck )
  3875. {
  3876. if ( pCheck->HasAnyAmmo() && (pCheck->UsesPrimaryAmmo() || pCheck->UsesSecondaryAmmo()))
  3877. {
  3878. m_PlayerHasAmmo.FireOutput( this, this, 0 );
  3879. return;
  3880. }
  3881. }
  3882. }
  3883.  
  3884. m_PlayerHasNoAmmo.FireOutput( this, this, 0 );
  3885. }
  3886.  
  3887. void CLogicPlayerProxy::InputLowerWeapon( inputdata_t &inputdata )
  3888. {
  3889. if( m_hPlayer == NULL )
  3890. return;
  3891.  
  3892. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(m_hPlayer.Get());
  3893.  
  3894. pPlayer->Weapon_Lower();
  3895. }
  3896.  
  3897. void CLogicPlayerProxy::InputEnableCappedPhysicsDamage( inputdata_t &inputdata )
  3898. {
  3899. if( m_hPlayer == NULL )
  3900. return;
  3901.  
  3902. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(m_hPlayer.Get());
  3903. pPlayer->EnableCappedPhysicsDamage();
  3904. }
  3905.  
  3906. void CLogicPlayerProxy::InputDisableCappedPhysicsDamage( inputdata_t &inputdata )
  3907. {
  3908. if( m_hPlayer == NULL )
  3909. return;
  3910.  
  3911. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(m_hPlayer.Get());
  3912. pPlayer->DisableCappedPhysicsDamage();
  3913. }
  3914.  
  3915. void CLogicPlayerProxy::InputSetLocatorTargetEntity( inputdata_t &inputdata )
  3916. {
  3917. if( m_hPlayer == NULL )
  3918. return;
  3919.  
  3920. CBaseEntity *pTarget = NULL; // assume no target
  3921. string_t iszTarget = MAKE_STRING( inputdata.value.String() );
  3922.  
  3923. if( iszTarget != NULL_STRING )
  3924. {
  3925. pTarget = gEntList.FindEntityByName( NULL, iszTarget );
  3926. }
  3927.  
  3928. CHL2_Player *pPlayer = dynamic_cast<CHL2_Player*>(m_hPlayer.Get());
  3929. pPlayer->SetLocatorTargetEntity(pTarget);
  3930. }
  3931.  
  3932. #ifdef PORTAL
  3933. void CLogicPlayerProxy::InputSuppressCrosshair( inputdata_t &inputdata )
  3934. {
  3935. if( m_hPlayer == NULL )
  3936. return;
  3937.  
  3938. CPortal_Player *pPlayer = ToPortalPlayer(m_hPlayer.Get());
  3939. pPlayer->SuppressCrosshair( true );
  3940. }
  3941. #endif // PORTAL
Add Comment
Please, Sign In to add comment