//----------------------------------------------------------------------------- // Purpose: Returns true if the player is on a ladder // Input : &trace - ignored //----------------------------------------------------------------------------- bool CHL2GameMovement::OnLadder( trace_t &trace ) { #ifndef HL2SB return ( GetLadder() != NULL ) ? true : false; #else return ( GetLadder() != NULL ) ? true : BaseClass::OnLadder( trace ); #endif }
//----------------------------------------------------------------------------- // Purpose: // Input : *ladder - //----------------------------------------------------------------------------- inline void CHL2GameMovement::SetLadder( CFuncLadder *ladder ) { CFuncLadder* oldLadder = GetLadder(); if ( !ladder && oldLadder ) { oldLadder->PlayerGotOff( GetHL2Player() ); } GetHL2Player()->m_HL2Local.m_hLadder.Set( ladder ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CHL2GameMovement::LadderMove( void ) { if ( player->GetMoveType() == MOVETYPE_NOCLIP ) { SetLadder( NULL ); return false; } // If being forced to mount/dismount continue to act like we are on the ladder if ( IsForceMoveActive() && ContinueForcedMove() ) { return true; } CFuncLadder *bestLadder = NULL; Vector bestOrigin( 0, 0, 0 ); CFuncLadder *ladder = GetLadder(); // Something 1) deactivated the ladder... or 2) something external applied // a force to us. In either case make the player fall, etc. if ( ladder && ( !ladder->IsEnabled() || ( player->GetBaseVelocity().LengthSqr() > 1.0f ) ) ) { GetHL2Player()->ExitLadder(); ladder = NULL; } if ( !ladder ) { Findladder( 64.0f, &bestLadder, bestOrigin, NULL ); } #if !defined (CLIENT_DLL) if( !ladder && bestLadder && sv_ladder_useonly.GetBool() ) { GetHL2Player()->DisplayLadderHudHint(); } #endif int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame int buttonsPressed = buttonsChanged & mv->m_nButtons; bool pressed_use = ( buttonsPressed & IN_USE ) ? true : false; // If I'm already moving on a ladder, use the previous ladder direction if ( !ladder && !pressed_use ) { // If flying through air, allow mounting ladders if we are facing < 15 degress from the ladder and we are close if ( !ladder && !sv_ladder_useonly.GetBool() ) { // Tracker 6625: Don't need to be leaping to auto mount using this method... // But if we are on the ground, then we must not be backing into the ladder (Tracker 12961) bool onground = player->GetGroundEntity() ? true : false; if ( !onground || ( mv->m_flForwardMove > 0.0f ) ) { if ( CheckLadderAutoMountCone( bestLadder, bestOrigin, 15.0f, 32.0f ) ) { return true; } } // Pressing forward while looking at ladder and standing (or floating) near a mounting point if ( mv->m_flForwardMove > 0.0f ) { if ( CheckLadderAutoMountEndPoint( bestLadder, bestOrigin ) ) { return true; } } } return false; } if ( !ladder && LookingAtLadder( bestLadder ) && CheckLadderAutoMount( bestLadder, bestOrigin ) ) { return true; } // Reassign the ladder ladder = GetLadder(); if ( !ladder ) { return false; } // Don't play the deny sound if ( pressed_use ) { GetHL2Player()->m_bPlayUseDenySound = false; } // Make sure we are on the ladder player->SetMoveType( MOVETYPE_LADDER ); player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); player->SetGravity( 0.0f ); float forwardSpeed = 0.0f; float rightSpeed = 0.0f; float speed = player->MaxSpeed(); if ( mv->m_nButtons & IN_BACK ) { forwardSpeed -= speed; } if ( mv->m_nButtons & IN_FORWARD ) { forwardSpeed += speed; } if ( mv->m_nButtons & IN_MOVELEFT ) { rightSpeed -= speed; } if ( mv->m_nButtons & IN_MOVERIGHT ) { rightSpeed += speed; } if ( mv->m_nButtons & IN_JUMP ) { player->SetMoveType( MOVETYPE_WALK ); // Remove from ladder SetLadder( NULL ); // Jump in view direction Vector jumpDir = m_vecForward; // unless pressing backward or something like that if ( mv->m_flForwardMove < 0.0f ) { jumpDir = -jumpDir; } VectorNormalize( jumpDir ); VectorScale( jumpDir, MAX_CLIMB_SPEED, mv->m_vecVelocity ); // Tracker 13558: Don't add any extra z velocity if facing downward at all if ( m_vecForward.z >= 0.0f ) { mv->m_vecVelocity.z = mv->m_vecVelocity.z + 50; } return false; } if ( forwardSpeed != 0 || rightSpeed != 0 ) { // See if the player is looking toward the top or the bottom Vector velocity; VectorScale( m_vecForward, forwardSpeed, velocity ); VectorMA( velocity, rightSpeed, m_vecRight, velocity ); VectorNormalize( velocity ); Vector ladderUp; ladder->ComputeLadderDir( ladderUp ); VectorNormalize( ladderUp ); Vector topPosition; Vector bottomPosition; ladder->GetTopPosition( topPosition ); ladder->GetBottomPosition( bottomPosition ); // Check to see if we've mounted the ladder in a bogus spot and, if so, just fall off the ladder... float dummyt = 0.0f; float distFromLadderSqr = CalcDistanceSqrToLine( mv->GetAbsOrigin(), topPosition, bottomPosition, &dummyt ); if ( distFromLadderSqr > 36.0f ) { // Uh oh, we fell off zee ladder... player->SetMoveType( MOVETYPE_WALK ); // Remove from ladder SetLadder( NULL ); return false; } bool ishorizontal = fabs( topPosition.z - bottomPosition.z ) < 64.0f ? true : false; float changeover = ishorizontal ? 0.0f : 0.3f; float factor = 1.0f; if ( velocity.z >= 0 ) { float dotTop = ladderUp.Dot( velocity ); if ( dotTop < -changeover ) { // Aimed at bottom factor = -1.0f; } } else { float dotBottom = -ladderUp.Dot( velocity ); if ( dotBottom > changeover ) { factor = -1.0f; } } #ifdef _XBOX if( sv_ladders_useonly.GetBool() ) { // Stick up climbs up, stick down climbs down. No matter which way you're looking. if ( mv->m_nButtons & IN_FORWARD ) { factor = 1.0f; } else if( mv->m_nButtons & IN_BACK ) { factor = -1.0f; } } #endif//_XBOX mv->m_vecVelocity = MAX_CLIMB_SPEED * factor * ladderUp; } else { mv->m_vecVelocity.Init(); } return true; }
//----------------------------------------------------------------------------- // Purpose: // Input : bOnLadder - //----------------------------------------------------------------------------- void CHL2GameMovement::FullLadderMove() { #if !defined( CLIENT_DLL ) CFuncLadder *ladder = GetLadder(); Assert( ladder ); if ( !ladder ) { return; } CheckWater(); // Was jump button pressed? If so, don't do anything here if ( mv->m_nButtons & IN_JUMP ) { CheckJumpButton(); return; } else { mv->m_nOldButtons &= ~IN_JUMP; } player->SetGroundEntity( NULL ); // Remember old positions in case we cancel this movement Vector oldVelocity = mv->m_vecVelocity; Vector oldOrigin = mv->GetAbsOrigin(); Vector topPosition; Vector bottomPosition; ladder->GetTopPosition( topPosition ); ladder->GetBottomPosition( bottomPosition ); // Compute parametric distance along ladder vector... float oldt; CalcDistanceSqrToLine( mv->GetAbsOrigin(), topPosition, bottomPosition, &oldt ); // Perform the move accounting for any base velocity. VectorAdd (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); TryPlayerMove(); VectorSubtract (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); // Pressed buttons are "changed(xor)" and'ed with the mask of currently held buttons int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame int buttonsPressed = buttonsChanged & mv->m_nButtons; bool pressed_use = ( buttonsPressed & IN_USE ) ? true : false; bool pressing_forward_or_side = mv->m_flForwardMove != 0.0f || mv->m_flSideMove != 0.0f; Vector ladderVec = topPosition - bottomPosition; float LadderLength = VectorNormalize( ladderVec ); // This test is not perfect by any means, but should help a bit bool moving_along_ladder = false; if ( pressing_forward_or_side ) { float fwdDot = m_vecForward.Dot( ladderVec ); if ( fabs( fwdDot ) > 0.9f ) { moving_along_ladder = true; } } // Compute parametric distance along ladder vector... float newt; CalcDistanceSqrToLine( mv->GetAbsOrigin(), topPosition, bottomPosition, &newt ); // Fudge of 2 units float tolerance = 1.0f / LadderLength; bool wouldleaveladder = false; // Moving pPast top or bottom? if ( newt < -tolerance ) { wouldleaveladder = newt < oldt; } else if ( newt > ( 1.0f + tolerance ) ) { wouldleaveladder = newt > oldt; } // See if we are near the top or bottom but not moving float dist1sqr, dist2sqr; dist1sqr = ( topPosition - mv->GetAbsOrigin() ).LengthSqr(); dist2sqr = ( bottomPosition - mv->GetAbsOrigin() ).LengthSqr(); float dist = MIN( dist1sqr, dist2sqr ); bool neardismountnode = ( dist < 16.0f * 16.0f ) ? true : false; float ladderUnitsPerTick = ( MAX_CLIMB_SPEED * gpGlobals->interval_per_tick ); bool neardismountnode2 = ( dist < ladderUnitsPerTick * ladderUnitsPerTick ) ? true : false; // Really close to node, cvar is set, and pressing a key, then simulate a +USE bool auto_dismount_use = ( neardismountnode2 && sv_autoladderdismount.GetBool() && pressing_forward_or_side && !moving_along_ladder ); bool fully_underwater = ( player->GetWaterLevel() == WL_Eyes ) ? true : false; // If the user manually pressed use or we're simulating it, then use_dismount will occur bool use_dismount = pressed_use || auto_dismount_use; if ( fully_underwater && !use_dismount ) { // If fully underwater, we require looking directly at a dismount node /// to "float off" a ladder mid way... if ( ExitLadderViaDismountNode( ladder, true ) ) { // See if they +used a dismount point mid-span.. return; } } // If the movement would leave the ladder and they're not automated or pressing use, disallow the movement if ( !use_dismount ) { if ( wouldleaveladder ) { // Don't let them leave the ladder if they were on it mv->m_vecVelocity = oldVelocity; mv->SetAbsOrigin( oldOrigin ); } return; } // If the move would not leave the ladder and we're near close to the end, then just accept the move if ( !wouldleaveladder && !neardismountnode ) { // Otherwise, if the move would leave the ladder, disallow it. if ( pressed_use ) { if ( ExitLadderViaDismountNode( ladder, false, IsX360() ) ) { // See if they +used a dismount point mid-span.. return; } player->SetMoveType( MOVETYPE_WALK ); player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); SetLadder( NULL ); GetHL2Player()->m_bPlayUseDenySound = false; // Dismount with a bit of velocity in facing direction VectorScale( m_vecForward, USE_DISMOUNT_SPEED, mv->m_vecVelocity ); mv->m_vecVelocity.z = 50; } return; } // Debounce the use key if ( pressed_use ) { SwallowUseKey(); } // Try auto exit, if possible if ( ExitLadderViaDismountNode( ladder, false, pressed_use ) ) { return; } if ( wouldleaveladder ) { // Otherwise, if the move would leave the ladder, disallow it. if ( pressed_use ) { player->SetMoveType( MOVETYPE_WALK ); player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); SetLadder( NULL ); // Dismount with a bit of velocity in facing direction VectorScale( m_vecForward, USE_DISMOUNT_SPEED, mv->m_vecVelocity ); mv->m_vecVelocity.z = 50; } else { mv->m_vecVelocity = oldVelocity; mv->SetAbsOrigin( oldOrigin ); } } #endif }
//----------------------------------------------------------------------------- // Purpose: Returns true if the player is on a ladder // Input : &trace - ignored //----------------------------------------------------------------------------- bool CHL2GameMovement::OnLadder( trace_t &trace ) { return ( GetLadder() != NULL ) ? true : false; }