//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// //========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= #include "cbase.h" #include "gamemovement.h" #include "in_buttons.h" #include #include "movevars_shared.h" #include "engine/IEngineTrace.h" #include "SoundEmitterSystem/isoundemittersystembase.h" #include "decals.h" #include "tier0/vprof.h" #include "hl1_gamemovement.h" // Expose our interface. static CHL1GameMovement g_GameMovement; IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement; EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CGameMovement, IGameMovement, INTERFACENAME_GAMEMOVEMENT, g_GameMovement ); #ifdef CLIENT_DLL #include "hl1/c_hl1mp_player.h" #else #include "hl1mp_player.h" #endif //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CHL1GameMovement::CheckJumpButton( void ) { m_pHL1Player = ToHL1Player( player ); Assert( m_pHL1Player ); if (m_pHL1Player->pl.deadflag) { mv->m_nOldButtons |= IN_JUMP ; // don't jump again until released return false; } // See if we are waterjumping. If so, decrement count and return. if (m_pHL1Player->m_flWaterJumpTime) { m_pHL1Player->m_flWaterJumpTime -= gpGlobals->frametime; if (m_pHL1Player->m_flWaterJumpTime < 0) m_pHL1Player->m_flWaterJumpTime = 0; return false; } // If we are in the water most of the way... if ( m_pHL1Player->GetWaterLevel() >= 2 ) { // swimming, not jumping SetGroundEntity( NULL ); if(m_pHL1Player->GetWaterType() == CONTENTS_WATER) // We move up a certain amount mv->m_vecVelocity[2] = 100; else if (m_pHL1Player->GetWaterType() == CONTENTS_SLIME) mv->m_vecVelocity[2] = 80; // play swiming sound if ( m_pHL1Player->m_flSwimSoundTime <= 0 ) { // Don't play sound again for 1 second m_pHL1Player->m_flSwimSoundTime = 1000; PlaySwimSound(); } return false; } // No more effect if (m_pHL1Player->GetGroundEntity() == NULL) { mv->m_nOldButtons |= IN_JUMP; return false; // in air, so no effect } if ( mv->m_nOldButtons & IN_JUMP ) return false; // don't pogo stick // In the air now. SetGroundEntity( NULL ); m_pHL1Player->PlayStepSound( (Vector &)mv->GetAbsOrigin(), player->GetSurfaceData(), 1.0, true ); MoveHelper()->PlayerSetAnimation( PLAYER_JUMP ); float flGroundFactor = 1.0f; if ( player->GetSurfaceData() ) { flGroundFactor = 1.0;//player->GetSurfaceData()->game.jumpFactor; } // Acclerate upward // If we are ducking... float startz = mv->m_vecVelocity[2]; if ( ( m_pHL1Player->m_Local.m_bDucking ) || ( m_pHL1Player->GetFlags() & FL_DUCKING ) ) { // d = 0.5 * g * t^2 - distance traveled with linear accel // t = sqrt(2.0 * 45 / g) - how long to fall 45 units // v = g * t - velocity at the end (just invert it to jump up that high) // v = g * sqrt(2.0 * 45 / g ) // v^2 = g * g * 2.0 * 45 / g // v = sqrt( g * 2.0 * 45 ) // Adjust for super long jump module // UNDONE -- note this should be based on forward angles, not current velocity. if ( m_pHL1Player->m_bHasLongJump && ( mv->m_nButtons & IN_DUCK ) && ( m_pHL1Player->m_Local.m_flDucktime > 0 ) && mv->m_vecVelocity.Length() > 50 ) { m_pHL1Player->m_Local.m_vecPunchAngle.Set( PITCH, -5 ); mv->m_vecVelocity = m_vecForward * PLAYER_LONGJUMP_SPEED * 1.6; mv->m_vecVelocity.z = sqrt(2 * 800 * 56.0); } else { mv->m_vecVelocity[2] = flGroundFactor * sqrt(2 * 800 * 45.0); // 2 * gravity * height } } else { mv->m_vecVelocity[2] += flGroundFactor * sqrt(2 * 800 * 45.0); // 2 * gravity * height } FinishGravity(); mv->m_outWishVel.z += mv->m_vecVelocity[2] - startz; mv->m_outStepHeight += 0.1f; if ( gpGlobals->maxClients > 1 ) #ifdef CLIENT_DLL (dynamic_cast(m_pHL1Player))->DoAnimationEvent( PLAYERANIMEVENT_JUMP ); #else (dynamic_cast(m_pHL1Player))->DoAnimationEvent( PLAYERANIMEVENT_JUMP ); #endif // Flag that we jumped. mv->m_nOldButtons |= IN_JUMP; // don't jump again until released return true; } //----------------------------------------------------------------------------- // Purpose: See if duck button is pressed and do the appropriate things //----------------------------------------------------------------------------- void CHL1GameMovement::Duck( void ) { int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame int buttonsPressed = buttonsChanged & mv->m_nButtons; // The changed ones still down are "pressed" int buttonsReleased = buttonsChanged & mv->m_nOldButtons; // The changed ones which were previously down are "released" // Check to see if we are in the air. bool bInAir = ( player->GetGroundEntity() == NULL ); bool bInDuck = ( player->GetFlags() & FL_DUCKING ) ? true : false; if ( mv->m_nButtons & IN_DUCK ) { mv->m_nOldButtons |= IN_DUCK; } else { mv->m_nOldButtons &= ~IN_DUCK; } // Handle death. if ( IsDead() ) { if ( bInDuck ) { // Unduck FinishUnDuck(); } return; } HandleDuckingSpeedCrop(); // If the player is holding down the duck button, the player is in duck transition, ducking, or duck-jumping. if ( ( mv->m_nButtons & IN_DUCK ) || player->m_Local.m_bDucking || bInDuck ) { if ( ( mv->m_nButtons & IN_DUCK ) ) { // Have the duck button pressed, but the player currently isn't in the duck position. if ( ( buttonsPressed & IN_DUCK ) && !bInDuck ) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME; player->m_Local.m_bDucking = true; } // The player is in duck transition and not duck-jumping. if ( player->m_Local.m_bDucking ) { float flDuckMilliseconds = MAX( 0.0f, GAMEMOVEMENT_DUCK_TIME - ( float )player->m_Local.m_flDucktime ); float flDuckSeconds = flDuckMilliseconds / GAMEMOVEMENT_DUCK_TIME; // Finish in duck transition when transition time is over, in "duck", in air. if ( ( flDuckSeconds > TIME_TO_DUCK ) || bInDuck || bInAir ) { FinishDuck(); } else { // Calc parametric time float flDuckFraction = SimpleSpline( flDuckSeconds / TIME_TO_DUCK ); SetDuckedEyeOffset( flDuckFraction ); } } } else { // Try to unduck unless automovement is not allowed // NOTE: When not onground, you can always unduck if ( player->m_Local.m_bAllowAutoMovement || bInAir ) { if ( ( buttonsReleased & IN_DUCK ) && bInDuck ) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME; } // Check to see if we are capable of unducking. if ( CanUnduck() ) { // or unducking if ( ( player->m_Local.m_bDucking || player->m_Local.m_bDucked ) ) { float flDuckMilliseconds = MAX( 0.0f, GAMEMOVEMENT_DUCK_TIME - (float)player->m_Local.m_flDucktime ); float flDuckSeconds = flDuckMilliseconds / GAMEMOVEMENT_DUCK_TIME; // Finish ducking immediately if duck time is over or not on ground if ( flDuckSeconds > TIME_TO_UNDUCK || ( bInAir ) ) { FinishUnDuck(); } else { // Calc parametric time float flDuckFraction = SimpleSpline( 1.0f - ( flDuckSeconds / TIME_TO_UNDUCK ) ); SetDuckedEyeOffset( flDuckFraction ); player->m_Local.m_bDucking = true; } } } else { // Still under something where we can't unduck, so make sure we reset this timer so // that we'll unduck once we exit the tunnel, etc. player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME; SetDuckedEyeOffset( 1.0f ); } } } } } void CHL1GameMovement::HandleDuckingSpeedCrop() { if ( !( m_iSpeedCropped & SPEED_CROPPED_DUCK ) ) { if ( player->GetFlags() & FL_DUCKING ) { float frac = 0.33333333f; mv->m_flForwardMove *= frac; mv->m_flSideMove *= frac; mv->m_flUpMove *= frac; m_iSpeedCropped |= SPEED_CROPPED_DUCK; } } } void CHL1GameMovement::CheckParameters( void ) { if ( mv->m_nButtons & IN_SPEED ) { mv->m_flClientMaxSpeed = 100; } else { mv->m_flClientMaxSpeed = mv->m_flMaxSpeed; } CHL1_Player* pHL1Player = dynamic_cast(player); if( pHL1Player && pHL1Player->IsPullingObject() ) { mv->m_flClientMaxSpeed = mv->m_flMaxSpeed * 0.5f; } BaseClass::CheckParameters(); }