//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- float CPropJetski::CalculateDrag( CUserCmd *ucmd ) { // Get the speed and ratio to max speed. float flSpeed = m_VehiclePhysics.GetSpeed(); float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); float flRatio = flSpeed / flMaxSpeed; float flDrag = 0.0f; bool bLean = UpdateLean( ucmd ); #if 0 if ( bLean ) { flDrag += JETSKI_DRAG_LEAN_ADD; } float flNormalizedRatio = ( flRatio - 0.4f ) * 1.667f; float flSplineRatio = SimpleSpline( flNormalizedRatio ); flFriction = JETSKI_FRICTION_MAX + ( JETSKI_FRICTION_MIN - JETSKI_FRICTION_MAX ) * flSplineRatio; flDrag = JETSKI_DRAG_IN_WATER + ( JETSKI_DRAG_ON_WATER - JETSKI_DRAG_IN_WATER ) * flNormalizedRatio; // Leaning backwards. if ( bLean ) { flDrag += JETSKI_DRAG_LEAN_ADD; } }
// remaps an angular variable to a 3 band function: // 0 <= t < start : f(t) = 0 // start <= t <= end : f(t) = end * spline(( t-start) / (end-start) ) // s curve between clamped and linear // end < t : f(t) = t float RemapAngleRange( float startInterval, float endInterval, float value ) { // Fixup the roll value = AngleNormalize( value ); float absAngle = fabs(value); // beneath cutoff? if ( absAngle < startInterval ) { value = 0; } // in spline range? else if ( absAngle <= endInterval ) { float newAngle = SimpleSpline( (absAngle - startInterval) / (endInterval-startInterval) ) * endInterval; // grab the sign from the initial value if ( value < 0 ) { newAngle *= -1; } value = newAngle; } // else leave it alone, in linear range return value; }
//----------------------------------------------------------------------------- // Purpose: // Input : &out - // t - // &start - // &end - //----------------------------------------------------------------------------- void CSimpleKeyInterp::Interp( Vector &out, float t, const CSimpleKeyInterp &start, const CSimpleKeyInterp &end ) { float delta = end.GetTime() - start.GetTime(); t = clamp( t-start.GetTime(), 0.f, delta ); float unitT = (delta > 0) ? (t / delta) : 1; switch( end.m_interp ) { case KEY_SPLINE: unitT = SimpleSpline( unitT ); break; case KEY_ACCELERATE: unitT *= unitT; break; case KEY_DECELERATE: unitT = sqrt(unitT); break; default: case KEY_LINEAR: //unitT = unitT; break; } out = (1-unitT) * ((Vector)start) + unitT * ((Vector)end); }
virtual void OnBind( C_BaseEntity *pC_BaseEntity ) { C_BaseAnimating *pBaseAnimating = pC_BaseEntity ? pC_BaseEntity->GetBaseAnimating() : NULL; if ( pBaseAnimating ) { float fCycle = pBaseAnimating->GetCycle(); float f = RemapValClamped( fCycle, m_fStart, m_fEnd, 0.0f, 1.0f ); if ( m_bEaseIn && m_bEaseOut ) { f = SimpleSpline( f ); } else if ( m_bEaseIn ) { f = sin( M_PI * f * 0.5f ); } else if ( m_bEaseOut ) { f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI ); } MaterialVarType_t resultType; int vecSize; ComputeResultType( resultType, vecSize ); switch( resultType ) { case MATERIAL_VAR_TYPE_VECTOR: { Vector4D vec( f, f, f, f ); m_pResult->SetVecValue( vec.Base(), vecSize ); } break; case MATERIAL_VAR_TYPE_FLOAT: case MATERIAL_VAR_TYPE_INT: default: m_pResult->SetFloatValue( f ); break; } } }
float FadeFilter::Update(float value) { float now = ENGINE_NOW; if(m_fadeInEnd == 0) { m_fadeInStart = now; m_fadeInEnd = m_fadeInStart + m_duration->GetFloat() - max(m_fadeOutEnd - now, 0); m_fadeOutStart = 0; m_fadeOutEnd = 0; m_prevVal = GetValue(); } if(now > m_fadeInEnd) return value; float p = (now - m_fadeInStart) / (m_fadeInEnd - m_fadeInStart); p = SimpleSpline(p); return (1 - p) * m_prevVal + p * value; }
//----------------------------------------------------------------------------- // Purpose: Vehicle dampening shared between server and client //----------------------------------------------------------------------------- void SharedVehicleViewSmoothing(CBasePlayer *pPlayer, Vector *pAbsOrigin, QAngle *pAbsAngles, bool bEnterAnimOn, bool bExitAnimOn, const Vector &vecEyeExitEndpoint, ViewSmoothingData_t *pData, float *pFOV ) { int eyeAttachmentIndex = pData->pVehicle->LookupAttachment( "vehicle_driver_eyes" ); matrix3x4_t vehicleEyePosToWorld; Vector vehicleEyeOrigin; QAngle vehicleEyeAngles; pData->pVehicle->GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles ); AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); // Dampen the eye positional change as we drive around. *pAbsAngles = pPlayer->EyeAngles(); if ( r_VehicleViewDampen.GetInt() && pData->bDampenEyePosition ) { CPropVehicleDriveable *pDriveable = assert_cast<CPropVehicleDriveable*>(pData->pVehicle); pDriveable->DampenEyePosition( vehicleEyeOrigin, vehicleEyeAngles ); } // Started running an entry or exit anim? bool bRunningAnim = ( bEnterAnimOn || bExitAnimOn ); if ( bRunningAnim && !pData->bWasRunningAnim ) { pData->bRunningEnterExit = true; pData->flEnterExitStartTime = gpGlobals->curtime; pData->flEnterExitDuration = pData->pVehicle->SequenceDuration( pData->pVehicle->GetSequence() ); #ifdef CLIENT_DLL pData->vecOriginSaved = PrevMainViewOrigin(); pData->vecAnglesSaved = PrevMainViewAngles(); #endif // Save our initial angular error, which we will blend out over the length of the animation. pData->vecAngleDiffSaved.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x ); pData->vecAngleDiffSaved.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y ); pData->vecAngleDiffSaved.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z ); pData->vecAngleDiffMin = pData->vecAngleDiffSaved; } pData->bWasRunningAnim = bRunningAnim; float frac = 0; float flFracFOV = 0; // If we're in an enter/exit animation, blend the player's eye angles to the attachment's if ( bRunningAnim || pData->bRunningEnterExit ) { *pAbsAngles = vehicleEyeAngles; // Forward integrate to determine the elapsed time in this entry/exit anim. frac = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / pData->flEnterExitDuration; frac = clamp( frac, 0.0f, 1.0f ); flFracFOV = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / ( pData->flEnterExitDuration * 0.85f ); flFracFOV = clamp( flFracFOV, 0.0f, 1.0f ); //Msg("Frac: %f\n", frac ); if ( frac < 1.0 ) { // Blend to the desired vehicle eye origin //Vector vecToView = (vehicleEyeOrigin - PrevMainViewOrigin()); //vehicleEyeOrigin = PrevMainViewOrigin() + (vecToView * SimpleSpline(frac)); //debugoverlay->AddBoxOverlay( vehicleEyeOrigin, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 0,255,255, 64, 10 ); } else { pData->bRunningEnterExit = false; // Enter animation has finished, align view with the eye attachment point // so they can start mouselooking around. #if !defined ( HL2MP_DEV_DLL ) && !defined ( HL2MP_DEV_VEHICLE_FIX ) if ( !bExitAnimOn ) { Vector localEyeOrigin; QAngle localEyeAngles; pData->pVehicle->GetAttachmentLocal( eyeAttachmentIndex, localEyeOrigin, localEyeAngles ); #ifdef CLIENT_DLL engine->SetViewAngles( localEyeAngles ); #endif } #else #ifdef CLIENT_DLL pPlayer = C_BasePlayer::GetLocalPlayer(); #endif if ( pPlayer ) { if ( !bExitAnimOn ) { Vector localEyeOrigin; QAngle localEyeAngles; pData->pVehicle->GetAttachmentLocal( eyeAttachmentIndex, localEyeOrigin, localEyeAngles ); #ifdef CLIENT_DLL engine->SetViewAngles( localEyeAngles ); #endif } } #endif } } // Compute the relative rotation between the unperturbed eye attachment + the eye angles matrix3x4_t cameraToWorld; AngleMatrix( *pAbsAngles, cameraToWorld ); matrix3x4_t worldToEyePos; MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); matrix3x4_t vehicleCameraToEyePos; ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); // Damp out some of the vehicle motion (neck/head would do this) if ( pData->bClampEyeAngles ) { RemapViewAngles( pData, vehicleEyeAngles ); } AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); // Now treat the relative eye angles as being relative to this new, perturbed view position... matrix3x4_t newCameraToWorld; ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); // output new view abs angles MatrixAngles( newCameraToWorld, *pAbsAngles ); // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); float flDefaultFOV; #ifdef CLIENT_DLL flDefaultFOV = default_fov.GetFloat(); #else flDefaultFOV = pPlayer->GetDefaultFOV(); #endif // If we're playing an entry or exit animation... if ( bRunningAnim || pData->bRunningEnterExit ) { float flSplineFrac = clamp( SimpleSpline( frac ), 0.f, 1.f ); // Blend out the error between the player's initial eye angles and the animation's initial // eye angles over the duration of the animation. QAngle vecAngleDiffBlend = ( ( 1 - flSplineFrac ) * pData->vecAngleDiffSaved ); // If our current error is less than the error amount that we're blending // out, use that. This lets the angles converge as quickly as possible. QAngle vecAngleDiffCur; vecAngleDiffCur.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x ); vecAngleDiffCur.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y ); vecAngleDiffCur.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z ); // In either case, never increase the error, so track the minimum error and clamp to that. for (int i = 0; i < 3; i++) { if ( fabs(vecAngleDiffCur[i] ) < fabs( pData->vecAngleDiffMin[i] ) ) { pData->vecAngleDiffMin[i] = vecAngleDiffCur[i]; } if ( fabs(vecAngleDiffBlend[i] ) < fabs( pData->vecAngleDiffMin[i] ) ) { pData->vecAngleDiffMin[i] = vecAngleDiffBlend[i]; } } // Add the error to the animation's eye angles. *pAbsAngles -= pData->vecAngleDiffMin; // Use this as the basis for the next error calculation. pData->vecAnglesSaved = *pAbsAngles; //if ( gpGlobals->frametime ) //{ // Msg("Angle : %.2f %.2f %.2f\n", target.x, target.y, target.z ); //} //Msg("Prev: %.2f %.2f %.2f\n", pData->vecAnglesSaved.x, pData->vecAnglesSaved.y, pData->vecAnglesSaved.z ); Vector vecAbsOrigin = *pAbsOrigin; // If we're exiting, our desired position is the server-sent exit position if ( bExitAnimOn ) { //debugoverlay->AddBoxOverlay( vecEyeExitEndpoint, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 255,255,255, 64, 10 ); // Blend to the exit position *pAbsOrigin = Lerp( flSplineFrac, vecAbsOrigin, vecEyeExitEndpoint ); if ( pFOV != NULL ) { if ( pData->flFOV > flDefaultFOV ) { *pFOV = Lerp( flFracFOV, pData->flFOV, flDefaultFOV ); } } } else { // Blend from our starting position to the desired origin *pAbsOrigin = Lerp( flSplineFrac, pData->vecOriginSaved, vecAbsOrigin ); if ( pFOV != NULL ) { if ( pData->flFOV > flDefaultFOV ) { *pFOV = Lerp( flFracFOV, flDefaultFOV, pData->flFOV ); } } } } else if ( pFOV != NULL ) { if ( pData->flFOV > flDefaultFOV ) { // Not running an entry/exit anim. Just use the vehicle's FOV. *pFOV = pData->flFOV; } } }
//----------------------------------------------------------------------------- // Purpose: See if duck button is pressed and do the appropriate things //----------------------------------------------------------------------------- void CHL2GameMovement::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" if (mv->m_nButtons & IN_DUCK) { mv->m_nOldButtons |= IN_DUCK; } else { mv->m_nOldButtons &= ~IN_DUCK; } if (IsDead()) { // Unduck if (player->GetFlags() & FL_DUCKING) { FinishUnDuck(); } return; } HandleDuckingSpeedCrop(); // Holding duck, in process of ducking or fully ducked? if ((mv->m_nButtons & IN_DUCK) || (player->m_Local.m_bDucking) || (player->GetFlags() & FL_DUCKING)) { if (mv->m_nButtons & IN_DUCK) { bool alreadyDucked = (player->GetFlags() & FL_DUCKING) ? true : false; if ((buttonsPressed & IN_DUCK) && !(player->GetFlags() & FL_DUCKING)) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; } float duckmilliseconds = max(0.0f, 1000.0f - (float)player->m_Local.m_flDucktime); float duckseconds = duckmilliseconds / 1000.0f; //time = max( 0.0, ( 1.0 - (float)player->m_Local.m_flDucktime / 1000.0 ) ); if (player->m_Local.m_bDucking) { // Finish ducking immediately if duck time is over or not on ground if ((duckseconds > TIME_TO_DUCK) || (player->GetGroundEntity() == NULL) || alreadyDucked) { FinishDuck(); } else { // Calc parametric time float duckFraction = SimpleSpline(duckseconds / TIME_TO_DUCK); SetDuckedEyeOffset(duckFraction); } } } else { // Try to unduck unless automovement is not allowed // NOTE: When not onground, you can always unduck if (player->m_Local.m_bAllowAutoMovement || player->GetGroundEntity() == NULL) { if ((buttonsReleased & IN_DUCK) && (player->GetFlags() & FL_DUCKING)) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; // or unducking } float duckmilliseconds = max(0.0f, 1000.0f - (float)player->m_Local.m_flDucktime); float duckseconds = duckmilliseconds / 1000.0f; if (CanUnduck()) { if (player->m_Local.m_bDucking || player->m_Local.m_bDucked) // or unducking { // Finish ducking immediately if duck time is over or not on ground if ((duckseconds > TIME_TO_UNDUCK) || (player->GetGroundEntity() == NULL)) { FinishUnDuck(); } else { // Calc parametric time float duckFraction = SimpleSpline(1.0f - (duckseconds / TIME_TO_UNDUCK)); SetDuckedEyeOffset(duckFraction); } } } 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 = 1000; } } } } }
void Interpolator_CurveInterpolate_NonNormalized( int interpolationType, const Vector &vPre, const Vector &vStart, const Vector &vEnd, const Vector &vNext, float f, Vector &vOut ) { vOut.Init(); switch ( interpolationType ) { default: Warning( "Unknown interpolation type %d\n", (int)interpolationType ); // break; // Fall through and use catmull_rom as default case INTERPOLATE_CATMULL_ROM_NORMALIZEX: case INTERPOLATE_DEFAULT: case INTERPOLATE_CATMULL_ROM: case INTERPOLATE_CATMULL_ROM_NORMALIZE: case INTERPOLATE_CATMULL_ROM_TANGENT: Catmull_Rom_Spline( vPre, vStart, vEnd, vNext, f, vOut ); break; case INTERPOLATE_EASE_IN: { f = sin( M_PI * f * 0.5f ); // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_EASE_OUT: { f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI ); // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_EASE_INOUT: { f = SimpleSpline( f ); // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_LINEAR_INTERP: // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); break; case INTERPOLATE_KOCHANEK_BARTELS: case INTERPOLATE_KOCHANEK_BARTELS_EARLY: case INTERPOLATE_KOCHANEK_BARTELS_LATE: { float t, b, c; Interpolator_GetKochanekBartelsParams( interpolationType, t, b, c ); Kochanek_Bartels_Spline ( t, b, c, vPre, vStart, vEnd, vNext, f, vOut ); } break; case INTERPOLATE_SIMPLE_CUBIC: Cubic_Spline( vPre, vStart, vEnd, vNext, f, vOut ); break; case INTERPOLATE_BSPLINE: BSpline( vPre, vStart, vEnd, vNext, f, vOut ); break; case INTERPOLATE_EXPONENTIAL_DECAY: { float dt = vEnd.x - vStart.x; if ( dt > 0.0f ) { float val = 1.0f - ExponentialDecay( 0.001, dt, f * dt ); vOut.y = vStart.y + val * ( vEnd.y - vStart.y ); } else { vOut.y = vStart.y; } } break; case INTERPOLATE_HOLD: { vOut.y = vStart.y; } break; } }
//----------------------------------------------------------------------------- // Purpose: See if duck button is pressed and do the appropriate things //----------------------------------------------------------------------------- void CSDKGameMovement::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" if ( mv->m_nButtons & IN_DUCK ) { mv->m_nOldButtons |= IN_DUCK; } else { mv->m_nOldButtons &= ~IN_DUCK; } if ( !player->IsAlive() ) { #if defined ( SDK_USE_PRONE ) if( m_pSDKPlayer->m_Shared.IsProne() ) { FinishUnProne(); } #endif // SDK_USE_PRONE // Unduck if ( player->m_Local.m_bDucking || player->m_Local.m_bDucked ) { FinishUnDuck(); } return; } static int iState = 0; #if defined ( SDK_USE_PRONE ) // Prone / UnProne - we don't duck if this is happening if( m_pSDKPlayer->m_Shared.IsGettingUpFromProne() == true ) { float pronetime = m_pSDKPlayer->m_Shared.m_flUnProneTime - gpGlobals->curtime; if( pronetime < 0 ) { FinishUnProne(); if ( !m_pSDKPlayer->m_bUnProneToDuck && ( mv->m_nButtons & IN_DUCK ) ) { buttonsPressed |= IN_DUCK; mv->m_nOldButtons &= ~IN_DUCK; } } else { // Calc parametric time float fraction = SimpleSpline( pronetime / TIME_TO_PRONE ); SetProneEyeOffset( fraction ); } // Set these, so that as soon as we stop unproning, we don't pop to standing // the information that we let go of the duck key has been lost by now. if ( m_pSDKPlayer->m_bUnProneToDuck ) { player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; } //don't deal with ducking while we're proning return; } else if ( m_pSDKPlayer->m_Shared.IsGoingProne() == true ) { float pronetime = m_pSDKPlayer->m_Shared.m_flGoProneTime - gpGlobals->curtime; if( pronetime < 0 ) { FinishProne(); } else { // Calc parametric time float fraction = SimpleSpline( 1.0f - ( pronetime / TIME_TO_PRONE ) ); SetProneEyeOffset( fraction ); } //don't deal with ducking while we're proning return; } if ( gpGlobals->curtime > m_pSDKPlayer->m_Shared.m_flNextProneCheck ) { if ( buttonsPressed & IN_ALT1 && m_pSDKPlayer->m_Shared.CanChangePosition() ) { if( m_pSDKPlayer->m_Shared.IsProne() == false && m_pSDKPlayer->m_Shared.IsGettingUpFromProne() == false ) { m_pSDKPlayer->m_Shared.StartGoingProne(); //Tony; here is where you'd want to do an animation for first person to give the effect of going prone. if ( m_pSDKPlayer->m_Shared.IsDucking() ) m_pSDKPlayer->DoAnimationEvent( PLAYERANIMEVENT_CROUCH_TO_PRONE ); else m_pSDKPlayer->DoAnimationEvent( PLAYERANIMEVENT_STAND_TO_PRONE ); } else if ( CanUnprone() ) { m_pSDKPlayer->m_Shared.SetProne( false ); m_pSDKPlayer->m_Shared.StandUpFromProne(); // //Tony; here is where you'd want to do an animation for first person to give the effect of getting up from prone. // m_pSDKPlayer->m_bUnProneToDuck = ( mv->m_nButtons & IN_DUCK ) > 0; if ( m_pSDKPlayer->m_bUnProneToDuck ) m_pSDKPlayer->DoAnimationEvent( PLAYERANIMEVENT_PRONE_TO_CROUCH ); else m_pSDKPlayer->DoAnimationEvent( PLAYERANIMEVENT_PRONE_TO_STAND ); } m_pSDKPlayer->m_Shared.m_flNextProneCheck = gpGlobals->curtime + 1.0f; return; } } if ( m_pSDKPlayer->m_Shared.IsProne() && m_pSDKPlayer->m_Shared.CanChangePosition() && ( buttonsPressed & IN_DUCK ) && CanUnprone() ) { // If the player presses duck while prone, // unprone them to the duck position m_pSDKPlayer->m_Shared.SetProne( false ); m_pSDKPlayer->m_Shared.StandUpFromProne(); m_pSDKPlayer->m_bUnProneToDuck = true; // //Tony; here is where you'd want to do an animation for first person to give the effect of going to duck from prone. // m_pSDKPlayer->DoAnimationEvent( PLAYERANIMEVENT_PRONE_TO_CROUCH ); // simulate a duck that was pressed while we were prone player->AddFlag( FL_DUCKING ); player->m_Local.m_bDucked = true; player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; } // no ducking or unducking while deployed or prone if( m_pSDKPlayer->m_Shared.IsProne() || m_pSDKPlayer->m_Shared.IsGettingUpFromProne() || !m_pSDKPlayer->m_Shared.CanChangePosition() ) { return; } #endif // SDK_USE_PRONE HandleDuckingSpeedCrop(); if ( !( player->GetFlags() & FL_DUCKING ) && ( player->m_Local.m_bDucked ) ) { player->m_Local.m_bDucked = false; } // Holding duck, in process of ducking or fully ducked? if ( ( mv->m_nButtons & IN_DUCK ) || ( player->m_Local.m_bDucking ) || ( player->GetFlags() & FL_DUCKING ) ) { if ( mv->m_nButtons & IN_DUCK ) { bool alreadyDucked = ( player->GetFlags() & FL_DUCKING ) ? true : false; if ( (buttonsPressed & IN_DUCK ) && !( player->GetFlags() & FL_DUCKING ) ) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; } float duckmilliseconds = max( 0.0f, 1000.0f - (float)player->m_Local.m_flDucktime ); float duckseconds = duckmilliseconds / 1000.0f; //time = max( 0.0, ( 1.0 - (float)player->m_Local.m_flDucktime / 1000.0 ) ); if ( player->m_Local.m_bDucking ) { // Finish ducking immediately if duck time is over or not on ground if ( ( duckseconds > TIME_TO_DUCK ) || ( player->GetGroundEntity() == NULL ) || alreadyDucked) { FinishDuck(); } else { // Calc parametric time float flDuckFraction = SimpleSpline( duckseconds / TIME_TO_DUCK ); SetSDKDuckedEyeOffset( flDuckFraction ); } } } else { // Try to unduck unless automovement is not allowed // NOTE: When not onground, you can always unduck if ( player->m_Local.m_bAllowAutoMovement || player->GetGroundEntity() == NULL ) { if ( (buttonsReleased & IN_DUCK ) && ( player->GetFlags() & FL_DUCKING ) ) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; // or unducking } float duckmilliseconds = max( 0.0f, 1000.0f - (float)player->m_Local.m_flDucktime ); float duckseconds = duckmilliseconds / 1000.0f; if ( CanUnduck() ) { if ( player->m_Local.m_bDucking || player->m_Local.m_bDucked ) // or unducking { // Finish ducking immediately if duck time is over or not on ground if ( ( duckseconds > TIME_TO_UNDUCK ) || ( player->GetGroundEntity() == NULL ) ) { FinishUnDuck(); } else { // Calc parametric time float duckFraction = SimpleSpline( 1.0f - ( duckseconds / TIME_TO_UNDUCK ) ); SetSDKDuckedEyeOffset( duckFraction ); } } } 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 = 1000; } } } } }
void CSDKGameMovement::SetPlayerSpeed( void ) { #if defined ( SDK_USE_PRONE ) // This check is now simplified, just use CanChangePosition because it checks the two things we need to check anyway. if ( m_pSDKPlayer->m_Shared.IsProne() && m_pSDKPlayer->m_Shared.CanChangePosition() && m_pSDKPlayer->GetGroundEntity() != NULL ) { mv->m_flClientMaxSpeed = m_pSDKPlayer->m_Shared.m_flProneSpeed; //Base prone speed } else //not prone - standing or crouching and possibly moving #endif // SDK_USE_PRONE { float stamina = 100.0f; #if defined ( SDK_USE_STAMINA ) || defined ( SDK_USE_SPRINTING ) stamina = m_pSDKPlayer->m_Shared.GetStamina(); #endif if ( mv->m_nButtons & IN_DUCK ) { mv->m_flClientMaxSpeed = m_pSDKPlayer->m_Shared.m_flRunSpeed; //gets cut in fraction later } else { float flMaxSpeed; #if defined ( SDK_USE_SPRINTING ) if ( ( mv->m_nButtons & IN_SPEED ) && ( stamina > 0 ) && ( mv->m_nButtons & IN_FORWARD ) ) { flMaxSpeed = m_pSDKPlayer->m_Shared.m_flSprintSpeed; //sprinting } else #endif // SDK_USE_SPRINTING { flMaxSpeed = m_pSDKPlayer->m_Shared.m_flRunSpeed; //jogging } mv->m_flClientMaxSpeed = flMaxSpeed - 100 + stamina; } } #if defined ( SDK_USE_PRONE ) if ( m_pSDKPlayer->GetGroundEntity() != NULL ) { if( m_pSDKPlayer->m_Shared.IsGoingProne() ) { float pronetime = m_pSDKPlayer->m_Shared.m_flGoProneTime - gpGlobals->curtime; //interp to prone speed float flProneFraction = SimpleSpline( pronetime / TIME_TO_PRONE ); float maxSpeed = mv->m_flClientMaxSpeed; if ( m_pSDKPlayer->m_bUnProneToDuck ) maxSpeed *= 0.33; mv->m_flClientMaxSpeed = ( ( 1 - flProneFraction ) * m_pSDKPlayer->m_Shared.m_flProneSpeed ) + ( flProneFraction * maxSpeed ); } else if ( m_pSDKPlayer->m_Shared.IsGettingUpFromProne() ) { float pronetime = m_pSDKPlayer->m_Shared.m_flUnProneTime - gpGlobals->curtime; //interp to regular speed speed float flProneFraction = SimpleSpline( pronetime / TIME_TO_PRONE ); float maxSpeed = mv->m_flClientMaxSpeed; if ( m_pSDKPlayer->m_bUnProneToDuck ) maxSpeed *= 0.33; mv->m_flClientMaxSpeed = ( flProneFraction * m_pSDKPlayer->m_Shared.m_flProneSpeed ) + ( ( 1 - flProneFraction ) * maxSpeed ); } } #endif // SDK_USE_PRONE }
mstudioanim_t *mstudioanimdesc_t::pAnim( int *piFrame, float &flStall ) const { mstudioanim_t *panim = NULL; int block = animblock; int index = animindex; int section = 0; if (sectionframes != 0) { if (numframes > sectionframes && *piFrame == numframes - 1) { // last frame on long anims is stored separately *piFrame = 0; section = (numframes / sectionframes) + 1; } else { section = *piFrame / sectionframes; *piFrame -= section * sectionframes; } block = pSection( section )->animblock; index = pSection( section )->animindex; } if (block == -1) { // model needs to be recompiled return NULL; } panim = pAnimBlock( block, index ); // force a preload on the next block if ( sectionframes != 0 ) { int count = ( numframes / sectionframes) + 2; for ( int i = section + 1; i < count; i++ ) { if ( pSection( i )->animblock != block ) { pAnimBlock( pSection( i )->animblock, pSection( i )->animindex ); break; } } } if (panim == NULL) { if (section > 0 && mod_load_showstall.GetInt() > 0) { Msg("[%8.3f] hitch on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block ); } // back up until a previously loaded block is found while (--section >= 0) { block = pSection( section )->animblock; index = pSection( section )->animindex; panim = pAnimBlock( block, index ); if (panim) { // set it to the last frame in the last valid section *piFrame = sectionframes - 1; break; } } } // try to guess a valid stall time interval (tuned for the X360) flStall = 0.0f; if (panim == NULL && section <= 0) { zeroframestalltime = Plat_FloatTime(); flStall = 1.0f; } else if (panim != NULL && zeroframestalltime != 0.0f) { float dt = Plat_FloatTime() - zeroframestalltime; if (dt >= 0.0) { flStall = SimpleSpline( clamp( (0.200f - dt) * 5.0f, 0.0f, 1.0f ) ); } if (flStall == 0.0f) { // disable stalltime zeroframestalltime = 0.0f; } else if (mod_load_showstall.GetInt() > 1) { Msg("[%8.3f] stall blend %.2f on %s:%s:%d:%d\n", Plat_FloatTime(), flStall, pStudiohdr()->pszName(), pszName(), section, block ); } } if (panim == NULL && mod_load_showstall.GetInt() > 1) { Msg("[%8.3f] stall on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block ); } return panim; }
void Interpolator_CurveInterpolate_NonNormalized( int interpolationType, const Quaternion &vPre, const Quaternion &vStart, const Quaternion &vEnd, const Quaternion &vNext, float f, Quaternion &vOut ) { vOut.Init(); switch ( interpolationType ) { default: Warning( "Unknown interpolation type %d\n", (int)interpolationType ); // break; // Fall through and use catmull_rom as default case INTERPOLATE_CATMULL_ROM_NORMALIZEX: case INTERPOLATE_DEFAULT: case INTERPOLATE_CATMULL_ROM: case INTERPOLATE_CATMULL_ROM_NORMALIZE: case INTERPOLATE_CATMULL_ROM_TANGENT: case INTERPOLATE_KOCHANEK_BARTELS: case INTERPOLATE_KOCHANEK_BARTELS_EARLY: case INTERPOLATE_KOCHANEK_BARTELS_LATE: case INTERPOLATE_SIMPLE_CUBIC: case INTERPOLATE_BSPLINE: // FIXME, since this ignores vPre and vNext we could omit computing them aove QuaternionSlerp( vStart, vEnd, f, vOut ); break; case INTERPOLATE_EASE_IN: { f = sin( M_PI * f * 0.5f ); // Fixme, since this ignores vPre and vNext we could omit computing them aove QuaternionSlerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_EASE_OUT: { f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI ); // Fixme, since this ignores vPre and vNext we could omit computing them aove QuaternionSlerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_EASE_INOUT: { f = SimpleSpline( f ); // Fixme, since this ignores vPre and vNext we could omit computing them aove QuaternionSlerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_LINEAR_INTERP: // Fixme, since this ignores vPre and vNext we could omit computing them aove QuaternionSlerp( vStart, vEnd, f, vOut ); break; case INTERPOLATE_EXPONENTIAL_DECAY: vOut.Init(); break; case INTERPOLATE_HOLD: { vOut = vStart; } break; } }
void CMomentumGameMovement::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 && player->GetMoveType() != MOVETYPE_LADDER; if (mv->m_nButtons & IN_DUCK) { mv->m_nOldButtons |= IN_DUCK; } else { mv->m_nOldButtons &= ~IN_DUCK; } if (IsDead()) { // Unduck if (player->GetFlags() & FL_DUCKING) { FinishUnDuck(); } return; } HandleDuckingSpeedCrop(); if (player->m_duckUntilOnGround) { if (!bInAir) { player->m_duckUntilOnGround = false; if (CanUnduck()) { FinishUnDuck(); } return; } else { if (mv->m_vecVelocity.z > 0.0f) return; // Check if we can un-duck. We want to unduck if we have space for the standing hull, and // if it is less than 2 inches off the ground. trace_t trace; Vector newOrigin; Vector groundCheck; VectorCopy(mv->GetAbsOrigin(), newOrigin); Vector hullSizeNormal = VEC_HULL_MAX - VEC_HULL_MIN; Vector hullSizeCrouch = VEC_DUCK_HULL_MAX - VEC_DUCK_HULL_MIN; newOrigin -= (hullSizeNormal - hullSizeCrouch); groundCheck = newOrigin; groundCheck.z -= player->GetStepSize(); UTIL_TraceHull(newOrigin, groundCheck, VEC_HULL_MIN, VEC_HULL_MAX, PlayerSolidMask(), player, COLLISION_GROUP_PLAYER_MOVEMENT, &trace); if (trace.startsolid || trace.fraction == 1.0f) return; // Can't even stand up, or there's no ground underneath us player->m_duckUntilOnGround = false; if (CanUnduck()) { FinishUnDuck(); } return; } } // Holding duck, in process of ducking or fully ducked? if ((mv->m_nButtons & IN_DUCK) || (player->m_Local.m_bDucking) || (player->GetFlags() & FL_DUCKING)) { if (mv->m_nButtons & IN_DUCK) { bool alreadyDucked = (player->GetFlags() & FL_DUCKING) ? true : false; if ((buttonsPressed & IN_DUCK) && !(player->GetFlags() & FL_DUCKING)) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; } float duckmilliseconds = max(0.0f, 1000.0f - (float)player->m_Local.m_flDucktime); float duckseconds = duckmilliseconds / 1000.0f; //time = max( 0.0, ( 1.0 - (float)player->m_Local.m_flDucktime / 1000.0 ) ); if (player->m_Local.m_bDucking) { // Finish ducking immediately if duck time is over or not on ground if ((duckseconds > TIME_TO_DUCK) || (player->GetGroundEntity() == NULL) || alreadyDucked) { FinishDuck(); } else { // Calc parametric time float duckFraction = SimpleSpline(duckseconds / TIME_TO_DUCK); SetDuckedEyeOffset(duckFraction); } } } else { // Try to unduck unless automovement is not allowed // NOTE: When not onground, you can always unduck if (player->m_Local.m_bAllowAutoMovement || player->GetGroundEntity() == NULL) { if ((buttonsReleased & IN_DUCK) && (player->GetFlags() & FL_DUCKING)) { // Use 1 second so super long jump will work player->m_Local.m_flDucktime = 1000; player->m_Local.m_bDucking = true; // or unducking } float duckmilliseconds = max(0.0f, 1000.0f - (float)player->m_Local.m_flDucktime); float duckseconds = duckmilliseconds / 1000.0f; if (CanUnduck()) { if (player->m_Local.m_bDucking || player->m_Local.m_bDucked) // or unducking { // Finish ducking immediately if duck time is over or not on ground if ((duckseconds > TIME_TO_UNDUCK) || (player->GetGroundEntity() == NULL)) { FinishUnDuck(); } else { // Calc parametric time float duckFraction = SimpleSpline(1.0f - (duckseconds / TIME_TO_UNDUCK)); SetDuckedEyeOffset(duckFraction); } } } 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 = 1000; } } } } }