void CSDKPlayer::FindSafePos(Vector &startPos) { bool hasSafePos = false; const float playerWidth = GetPlayerMaxs().x - GetPlayerMins().x; const int maxChecks = 5; for (int x = 0; x < maxChecks; x++) { for (int y = 0; y < maxChecks; y++) { for (int sign = -1; sign <= 1; sign += 2) { Vector checkPos = startPos + sign * Vector(x * playerWidth, y * playerWidth, 0); trace_t trace; UTIL_TraceHull(checkPos, checkPos - Vector(0, 0, 100), GetPlayerMins(), GetPlayerMaxs(), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER, &trace); if (!trace.startsolid && trace.fraction != 1.0f) { hasSafePos = true; startPos = trace.endpos; break; } } if (hasSafePos) break; } if (hasSafePos) break; } if (!hasSafePos) startPos.z += GetPlayerMaxs().z * 2; }
void CSDKGameMovement::FinishUnProne( void ) { m_pSDKPlayer->m_Shared.m_flUnProneTime = 0.0f; SetProneEyeOffset( 0.0 ); Vector vHullMin = GetPlayerMins( player->m_Local.m_bDucked ); Vector vHullMax = GetPlayerMaxs( player->m_Local.m_bDucked ); if ( m_pSDKPlayer->m_bUnProneToDuck ) { FinishDuck(); } else { CategorizePosition(); if ( mv->m_nButtons & 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; } } }
//----------------------------------------------------------------------------- // Purpose: // Input : duckFraction - //----------------------------------------------------------------------------- void CSDKGameMovement::SetSDKDuckedEyeOffset( float duckFraction ) { // Different from CGameMovement in that Vector vDuckHullMin = GetPlayerMins( true ); Vector vStandHullMin = GetPlayerMins( false ); float fMore = ( vDuckHullMin.z - vStandHullMin.z ); Vector vecStandViewOffset = GetPlayerViewOffset( false ); Vector vecDuckViewOffset = GetPlayerViewOffset( true ); Vector temp = player->GetViewOffset(); temp.z = ( ( vecDuckViewOffset.z - fMore ) * duckFraction ) + ( vecStandViewOffset.z * ( 1 - duckFraction ) ); player->SetViewOffset( temp ); }
void CPortalGameMovement::TracePlayerBBox( const Vector& start, const Vector& end, unsigned int fMask, int collisionGroup, trace_t& pm ) { VPROF( "CGameMovement::TracePlayerBBox" ); CPortal_Player *pPortalPlayer = (CPortal_Player *)((CBaseEntity *)mv->m_nPlayerHandle.Get()); Ray_t ray; ray.Init( start, end, GetPlayerMins(), GetPlayerMaxs() ); #ifdef CLIENT_DLL CTraceFilterSimple traceFilter( mv->m_nPlayerHandle.Get(), collisionGroup ); #else CTraceFilterSimple baseFilter( mv->m_nPlayerHandle.Get(), collisionGroup ); CTraceFilterTranslateClones traceFilter( &baseFilter ); #endif UTIL_Portal_TraceRay_With( pPortalPlayer->m_hPortalEnvironment, ray, fMask, &traceFilter, &pm ); // If we're moving through a portal and failed to hit anything with the above ray trace // Use UTIL_Portal_TraceEntity to test this movement through a portal and override the trace with the result if ( pm.fraction == 1.0f && UTIL_DidTraceTouchPortals( ray, pm ) && sv_player_trace_through_portals.GetBool() ) { trace_t tempTrace; UTIL_Portal_TraceEntity( pPortalPlayer, start, end, fMask, &traceFilter, &tempTrace ); if ( tempTrace.DidHit() && tempTrace.fraction < pm.fraction && !tempTrace.startsolid && !tempTrace.allsolid ) { pm = tempTrace; } } }
void CMomentumGameMovement::PlayerMove() { BaseClass::PlayerMove(); if (player->IsAlive()) { // Check if our eye height is too close to the ceiling and lower it. // This is needed because we have taller models with the old collision bounds. const float eyeClearance = 12.0f; // eye pos must be this far below the ceiling Vector offset = player->GetViewOffset(); Vector vHullMin = GetPlayerMins(player->m_Local.m_bDucked); vHullMin.z = 0.0f; Vector vHullMax = GetPlayerMaxs(player->m_Local.m_bDucked); Vector start = player->GetAbsOrigin(); start.z += vHullMax.z; Vector end = start; end.z += eyeClearance - vHullMax.z; end.z += player->m_Local.m_bDucked ? VEC_DUCK_VIEW.z : VEC_VIEW.z; vHullMax.z = 0.0f; Vector fudge(1, 1, 0); vHullMin += fudge; vHullMax -= fudge; trace_t trace; Ray_t ray; ray.Init(start, end, vHullMin, vHullMax); UTIL_TraceRay(ray, PlayerSolidMask(), mv->m_nPlayerHandle.Get(), COLLISION_GROUP_PLAYER_MOVEMENT, &trace); if (trace.fraction < 1.0f) { float est = start.z + trace.fraction * (end.z - start.z) - player->GetAbsOrigin().z - eyeClearance; if ((player->GetFlags() & FL_DUCKING) == 0 && !player->m_Local.m_bDucking && !player->m_Local.m_bDucked) { offset.z = est; } else { offset.z = min(est, offset.z); } player->SetViewOffset(offset); } else { if ((player->GetFlags() & FL_DUCKING) == 0 && !player->m_Local.m_bDucking && !player->m_Local.m_bDucked) { player->SetViewOffset(VEC_VIEW); } else if (player->m_Local.m_bDucked && !player->m_Local.m_bDucking) { player->SetViewOffset(VEC_DUCK_VIEW); } } } }
//----------------------------------------------------------------------------- // Purpose: Determines if a player can be safely moved towards a point // Input: pos - position to test move to, fVertDist - how far to trace downwards to see if the player would fall, // radius - how close the player can be to the object, objPos - position of the object to avoid, // objDir - direction the object is travelling //----------------------------------------------------------------------------- bool C_BaseHLPlayer::TestMove( const Vector &pos, float fVertDist, float radius, const Vector &objPos, const Vector &objDir ) { trace_t trUp; trace_t trOver; trace_t trDown; float flHit1, flHit2; UTIL_TraceHull( GetAbsOrigin(), pos, GetPlayerMins(), GetPlayerMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trOver ); if ( trOver.fraction < 1.0f ) { // check if the endpos intersects with the direction the object is travelling. if it doesn't, this is a good direction to move. if ( objDir.IsZero() || ( IntersectInfiniteRayWithSphere( objPos, objDir, trOver.endpos, radius, &flHit1, &flHit2 ) && ( ( flHit1 >= 0.0f ) || ( flHit2 >= 0.0f ) ) ) ) { // our first trace failed, so see if we can go farther if we step up. // trace up to see if we have enough room. UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, m_Local.m_flStepSize ), GetPlayerMins(), GetPlayerMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trUp ); // do a trace from the stepped up height UTIL_TraceHull( trUp.endpos, pos + Vector( 0, 0, trUp.endpos.z - trUp.startpos.z ), GetPlayerMins(), GetPlayerMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trOver ); if ( trOver.fraction < 1.0f ) { // check if the endpos intersects with the direction the object is travelling. if it doesn't, this is a good direction to move. if ( objDir.IsZero() || ( IntersectInfiniteRayWithSphere( objPos, objDir, trOver.endpos, radius, &flHit1, &flHit2 ) && ( ( flHit1 >= 0.0f ) || ( flHit2 >= 0.0f ) ) ) ) { return false; } } } } // trace down to see if this position is on the ground UTIL_TraceLine( trOver.endpos, trOver.endpos - Vector( 0, 0, fVertDist ), MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &trDown ); if ( trDown.fraction == 1.0f ) return false; return true; }
void CSDKPlayer::MoveToTargetPos(Vector &pos, Vector &vel, QAngle &ang) { Vector dir = m_vTargetPos - pos; dir.z = 0; float distToTarget = dir.Length2D(); dir.NormalizeInPlace(); VectorAngles(dir, ang); float wishDist = mp_remotecontrolledspeed.GetInt() * gpGlobals->frametime; vel = dir * mp_remotecontrolledspeed.GetInt(); pos = pos + vel * gpGlobals->frametime; pos.z = SDKGameRules()->m_vKickOff.GetZ(); if (wishDist >= distToTarget) { trace_t trace; UTIL_TraceHull(m_vTargetPos, m_vTargetPos, GetPlayerMins(), GetPlayerMaxs(), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER, &trace); if (trace.startsolid) { m_vTargetPos = pos + dir * (GetPlayerMaxs().x - GetPlayerMins().x); } else { m_bIsAtTargetPos = true; RemoveFlag(FL_REMOTECONTROLLED); //RemoveSolidFlags(FSOLID_NOT_SOLID); SetCollisionGroup(COLLISION_GROUP_PLAYER); if (m_bHoldAtTargetPos) AddFlag(FL_ATCONTROLS); //#ifdef GAME_DLL // if (ShotButtonsPressed()) // m_bShotButtonsReleased = false; //#endif pos = m_vTargetPos; vel = vec3_origin; } } }
//----------------------------------------------------------------------------- // Traces player movement + position //----------------------------------------------------------------------------- void CTFGameMovement::TracePlayerBBox( const Vector& start, const Vector& end, unsigned int fMask, int collisionGroup, trace_t& pm ) { if( tf_solidobjects.GetBool() == false ) return BaseClass::TracePlayerBBox( start, end, fMask, collisionGroup, pm ); Ray_t ray; ray.Init( start, end, GetPlayerMins(), GetPlayerMaxs() ); CTraceFilterObject traceFilter( mv->m_nPlayerHandle.Get(), collisionGroup ); enginetrace->TraceRay( ray, fMask, &traceFilter, &pm ); }
inline void CSDKGameMovement::TracePlayerBBoxWithStep( const Vector &vStart, const Vector &vEnd, unsigned int fMask, int collisionGroup, trace_t &trace ) { VPROF( "CSDKGameMovement::TracePlayerBBoxWithStep" ); Vector vHullMin = GetPlayerMins( player->m_Local.m_bDucked ); vHullMin.z += player->m_Local.m_flStepSize; Vector vHullMax = GetPlayerMaxs( player->m_Local.m_bDucked ); Ray_t ray; ray.Init( vStart, vEnd, vHullMin, vHullMax ); UTIL_TraceRay( ray, fMask, mv->m_nPlayerHandle.Get(), collisionGroup, &trace ); }
//----------------------------------------------------------------------------- // Traces player movement + position //----------------------------------------------------------------------------- inline void CHL2WarsGameMovement::TracePlayerBBox( const Vector& start, const Vector& end, unsigned int fMask, int collisionGroup, trace_t& pm ) { if( player->GetMoveType() != MOVETYPE_STRATEGIC ) { CGameMovement::TracePlayerBBox( start, end, fMask, collisionGroup, pm ); return; } VPROF( "CGameMovement::TracePlayerBBox" ); Ray_t ray; ray.Init( start, end, GetPlayerMins(), GetPlayerMaxs() ); CTraceFilterWars traceFilter( mv->m_nPlayerHandle.Get(), collisionGroup ); enginetrace->TraceRay( ray, fMask, &traceFilter, &pm ); }
CBaseHandle CTFGameMovement::TestPlayerPosition( const Vector& pos, int collisionGroup, trace_t& pm ) { if( tf_solidobjects.GetBool() == false ) return BaseClass::TestPlayerPosition( pos, collisionGroup, pm ); Ray_t ray; ray.Init( pos, pos, GetPlayerMins(), GetPlayerMaxs() ); CTraceFilterObject traceFilter( mv->m_nPlayerHandle.Get(), collisionGroup ); enginetrace->TraceRay( ray, PlayerSolidMask(), &traceFilter, &pm ); if ( (pm.contents & PlayerSolidMask()) && pm.m_pEnt ) { return pm.m_pEnt->GetRefEHandle(); } else { return INVALID_EHANDLE_INDEX; } }
CBaseHandle CHL2WarsGameMovement::TestPlayerPosition( const Vector& pos, int collisionGroup, trace_t& pm ) { if( player->GetMoveType() != MOVETYPE_STRATEGIC ) { return CGameMovement::TestPlayerPosition( pos, collisionGroup, pm ); } Ray_t ray; ray.Init( pos, pos, GetPlayerMins(), GetPlayerMaxs() ); CTraceFilterWars traceFilter( mv->m_nPlayerHandle.Get(), collisionGroup ); enginetrace->TraceRay( ray, PlayerSolidMask(), &traceFilter, &pm ); if ( (pm.contents & PlayerSolidMask()) && pm.m_pEnt ) { return pm.m_pEnt->GetRefEHandle(); } else { return INVALID_EHANDLE_INDEX; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFGameMovement::CheckWaterJump( void ) { Vector flatforward; Vector flatvelocity; float curspeed; // Jump button down? bool bJump = ( ( mv->m_nButtons & IN_JUMP ) != 0 ); Vector forward, right; AngleVectors( mv->m_vecViewAngles, &forward, &right, NULL ); // Determine movement angles // Already water jumping. if (player->m_flWaterJumpTime) return; // Don't hop out if we just jumped in if (mv->m_vecVelocity[2] < -180) return; // only hop out if we are moving up // See if we are backing up flatvelocity[0] = mv->m_vecVelocity[0]; flatvelocity[1] = mv->m_vecVelocity[1]; flatvelocity[2] = 0; // Must be moving curspeed = VectorNormalize( flatvelocity ); #if 1 // Copy movement amounts float fmove = mv->m_flForwardMove; float smove = mv->m_flSideMove; for ( int iAxis = 0; iAxis < 2; ++iAxis ) { flatforward[iAxis] = forward[iAxis] * fmove + right[iAxis] * smove; } #else // see if near an edge flatforward[0] = forward[0]; flatforward[1] = forward[1]; #endif flatforward[2] = 0; VectorNormalize( flatforward ); // Are we backing into water from steps or something? If so, don't pop forward if ( curspeed != 0.0 && ( DotProduct( flatvelocity, flatforward ) < 0.0 ) && !bJump ) return; Vector vecStart; // Start line trace at waist height (using the center of the player for this here) vecStart= mv->GetAbsOrigin() + (GetPlayerMins() + GetPlayerMaxs() ) * 0.5; Vector vecEnd; VectorMA( vecStart, TF_WATERJUMP_FORWARD/*tf_waterjump_forward.GetFloat()*/, flatforward, vecEnd ); trace_t tr; TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); if ( tr.fraction < 1.0 ) // solid at waist { IPhysicsObject *pPhysObj = tr.m_pEnt->VPhysicsGetObject(); if ( pPhysObj ) { if ( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) return; } vecStart.z = mv->GetAbsOrigin().z + player->GetViewOffset().z + WATERJUMP_HEIGHT; VectorMA( vecStart, TF_WATERJUMP_FORWARD/*tf_waterjump_forward.GetFloat()*/, flatforward, vecEnd ); VectorMA( vec3_origin, -50.0f, tr.plane.normal, player->m_vecWaterJumpVel ); TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); if ( tr.fraction == 1.0 ) // open at eye level { // Now trace down to see if we would actually land on a standable surface. VectorCopy( vecEnd, vecStart ); vecEnd.z -= 1024.0f; TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); if ( ( tr.fraction < 1.0f ) && ( tr.plane.normal.z >= 0.7 ) ) { mv->m_vecVelocity[2] = TF_WATERJUMP_UP/*tf_waterjump_up.GetFloat()*/; // Push up mv->m_nOldButtons |= IN_JUMP; // Don't jump again until released player->AddFlag( FL_WATERJUMP ); player->m_flWaterJumpTime = 2000.0f; // Do this for 2 seconds } } } }
void CSDKGameMovement::CategorizePosition( void ) { // Observer. if ( player->IsObserver() ) return; // Reset this each time we-recategorize, otherwise we have bogus friction when we jump into water and plunge downward really quickly player->m_surfaceFriction = 1.0f; // Doing this before we move may introduce a potential latency in water detection, but // doing it after can get us stuck on the bottom in water if the amount we move up // is less than the 1 pixel 'threshold' we're about to snap to. Also, we'll call // this several times per frame, so we really need to avoid sticking to the bottom of // water on each call, and the converse case will correct itself if called twice. CheckWater(); // If standing on a ladder we are not on ground. if ( player->GetMoveType() == MOVETYPE_LADDER ) { SetGroundEntity( NULL ); return; } // Check for a jump. if ( mv->m_vecVelocity.z > 250.0f ) { SetGroundEntity( NULL ); return; } // Calculate the start and end position. Vector vecStartPos = mv->GetAbsOrigin(); Vector vecEndPos( mv->GetAbsOrigin().x, mv->GetAbsOrigin().y, ( mv->GetAbsOrigin().z - 2.0f ) ); // NOTE YWB 7/5/07: Since we're already doing a traceline here, we'll subsume the StayOnGround (stair debouncing) check into the main traceline we do here to see what we're standing on bool bUnderwater = ( player->GetWaterLevel() >= WL_Eyes ); bool bMoveToEndPos = false; if ( player->GetMoveType() == MOVETYPE_WALK && player->GetGroundEntity() != NULL && !bUnderwater ) { // if walking and still think we're on ground, we'll extend trace down by stepsize so we don't bounce down slopes vecEndPos.z -= player->GetStepSize(); bMoveToEndPos = true; } trace_t trace; TracePlayerBBox( vecStartPos, vecEndPos, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); // Steep plane, not on ground. if ( trace.plane.normal.z < 0.7f ) { // Test four sub-boxes, to see if any of them would have found shallower slope we could actually stand on. TracePlayerBBoxForGround( vecStartPos, vecEndPos, GetPlayerMins(), GetPlayerMaxs(), mv->m_nPlayerHandle.Get(), PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); if ( trace.plane.normal[2] < 0.7f ) { // Too steep. SetGroundEntity( NULL ); if ( ( mv->m_vecVelocity.z > 0.0f ) && ( player->GetMoveType() != MOVETYPE_NOCLIP ) ) { player->m_surfaceFriction = 0.25f; } } else { SetGroundEntity( &trace ); } } else { // YWB: This logic block essentially lifted from StayOnGround implementation if ( bMoveToEndPos && !trace.startsolid && // not sure we need this check as fraction would == 0.0f? trace.fraction > 0.0f && // must go somewhere trace.fraction < 1.0f ) // must hit something { float flDelta = fabs( mv->GetAbsOrigin().z - trace.endpos.z ); // HACK HACK: The real problem is that trace returning that strange value // we can't network over based on bit precision of networking origins if ( flDelta > 0.5f * COORD_RESOLUTION ) { Vector org = mv->GetAbsOrigin(); org.z = trace.endpos.z; mv->SetAbsOrigin( org ); } } SetGroundEntity( &trace ); } }
bool CTFGameMovement::CheckWater( void ) { Vector vecPlayerMin = GetPlayerMins(); Vector vecPlayerMax = GetPlayerMaxs(); Vector vecPoint( ( mv->GetAbsOrigin().x + ( vecPlayerMin.x + vecPlayerMax.x ) * 0.5f ), ( mv->GetAbsOrigin().y + ( vecPlayerMin.y + vecPlayerMax.y ) * 0.5f ), ( mv->GetAbsOrigin().z + vecPlayerMin.z + 1 ) ); // Assume that we are not in water at all. int wl = WL_NotInWater; int wt = CONTENTS_EMPTY; // Check to see if our feet are underwater. int nContents = GetPointContentsCached( vecPoint, 0 ); if ( nContents & MASK_WATER ) { // Clear our jump flag, because we have landed in water. m_pTFPlayer->m_Shared.SetJumping( false ); // Set water type and level. wt = nContents; wl = WL_Feet; float flWaistZ = mv->GetAbsOrigin().z + ( vecPlayerMin.z + vecPlayerMax.z ) * 0.5f + 12.0f; // Now check eyes vecPoint.z = mv->GetAbsOrigin().z + player->GetViewOffset()[2]; nContents = GetPointContentsCached( vecPoint, 1 ); if ( nContents & MASK_WATER ) { // In over our eyes wl = WL_Eyes; VectorCopy( vecPoint, m_vecWaterPoint ); m_vecWaterPoint.z = flWaistZ; } else { // Now check a point that is at the player hull midpoint (waist) and see if that is underwater. vecPoint.z = flWaistZ; nContents = GetPointContentsCached( vecPoint, 2 ); if ( nContents & MASK_WATER ) { // Set the water level at our waist. wl = WL_Waist; VectorCopy( vecPoint, m_vecWaterPoint ); } } } player->SetWaterLevel( wl ); player->SetWaterType( wt ); // If we just transitioned from not in water to water, record the time for splashes, etc. if ( ( WL_NotInWater == m_nOldWaterLevel ) && ( wl > WL_NotInWater ) ) { m_flWaterEntryTime = gpGlobals->curtime; } return ( wl > WL_Feet ); }
void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) { bool bWalking; float fvol; Vector knee; Vector feet; float height; float speed; float velrun; float velwalk; int fLadder; if ( m_flStepSoundTime > 0 ) { m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; if ( m_flStepSoundTime < 0 ) { m_flStepSoundTime = 0; } } if ( m_flStepSoundTime > 0 ) return; if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) return; if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) return; if ( !sv_footsteps.GetFloat() ) return; speed = VectorLength( vecVelocity ); float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); // determine if we are on a ladder fLadder = ( GetMoveType() == MOVETYPE_LADDER ); GetStepSoundVelocities( &velwalk, &velrun ); bool onground = ( GetFlags() & FL_ONGROUND ); bool movingalongground = ( groundspeed > 0.0001f ); bool moving_fast_enough = ( speed >= velwalk ); #ifdef PORTAL // In Portal we MUST play footstep sounds even when the player is moving very slowly // This is used to count the number of footsteps they take in the challenge mode // -Jeep moving_fast_enough = true; #endif // To hear step sounds you must be either on a ladder or moving along the ground AND // You must be moving fast enough if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) ) return; // MoveHelper()->PlayerSetAnimation( PLAYER_WALK ); bWalking = speed < velrun; VectorCopy( vecOrigin, knee ); VectorCopy( vecOrigin, feet ); height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; knee[2] = vecOrigin[2] + 0.2 * height; // find out what we're stepping in or on... if ( fLadder ) { psurface = GetLadderSurface(vecOrigin); fvol = 0.5; SetStepSoundTime( STEPSOUNDTIME_ON_LADDER, bWalking ); } else if ( GetWaterLevel() == WL_Waist ) { static int iSkipStep = 0; if ( iSkipStep == 0 ) { iSkipStep++; return; } if ( iSkipStep++ == 3 ) { iSkipStep = 0; } psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) ); fvol = 0.65; SetStepSoundTime( STEPSOUNDTIME_WATER_KNEE, bWalking ); } else if ( GetWaterLevel() == WL_Feet ) { psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) ); fvol = bWalking ? 0.2 : 0.5; SetStepSoundTime( STEPSOUNDTIME_WATER_FOOT, bWalking ); } else { if ( !psurface ) return; SetStepSoundTime( STEPSOUNDTIME_NORMAL, bWalking ); switch ( psurface->game.material ) { default: case CHAR_TEX_CONCRETE: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_METAL: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_DIRT: fvol = bWalking ? 0.25 : 0.55; break; case CHAR_TEX_VENT: fvol = bWalking ? 0.4 : 0.7; break; case CHAR_TEX_GRATE: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_TILE: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_SLOSH: fvol = bWalking ? 0.2 : 0.5; break; } } // play the sound // 65% volume if ducking if ( GetFlags() & FL_DUCKING ) { fvol *= 0.65; } PlayStepSound( feet, psurface, fvol, false ); }
void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) { int fWalking; float fvol; Vector knee; Vector feet; float height; float speed; float velrun; float velwalk; float flduck; int fLadder; if ( m_flStepSoundTime > 0 ) { m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; if ( m_flStepSoundTime < 0 ) { m_flStepSoundTime = 0; } } if ( m_flStepSoundTime > 0 ) return; if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) return; if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) return; if ( !sv_footsteps.GetFloat() ) return; speed = VectorLength( vecVelocity ); float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); // determine if we are on a ladder fLadder = ( GetMoveType() == MOVETYPE_LADDER ); // UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!! if ( ( GetFlags() & FL_DUCKING) || fLadder ) { velwalk = 60; // These constants should be based on cl_movespeedkey * cl_forwardspeed somehow velrun = 80; flduck = 100; } else { velwalk = 90; velrun = 220; flduck = 0; } bool onground = ( GetFlags() & FL_ONGROUND ); bool movingalongground = ( groundspeed > 0.0f ); bool moving_fast_enough = ( speed >= velwalk ); // To hear step sounds you must be either on a ladder or moving along the ground AND // You must be moving fast enough if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) ) return; // MoveHelper()->PlayerSetAnimation( PLAYER_WALK ); fWalking = speed < velrun; VectorCopy( vecOrigin, knee ); VectorCopy( vecOrigin, feet ); height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; knee[2] = vecOrigin[2] + 0.2 * height; // find out what we're stepping in or on... if ( fLadder ) { #ifdef CLIENT_DLL psurface = GetFootstepSurface( vecOrigin, "ladder" ); #else psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "ladder" ) ); #endif fvol = 0.5; m_flStepSoundTime = 350; } else if ( enginetrace->GetPointContents( knee ) & MASK_WATER ) { static int iSkipStep = 0; if ( iSkipStep == 0 ) { iSkipStep++; return; } if ( iSkipStep++ == 3 ) { iSkipStep = 0; } psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) ); fvol = 0.65; m_flStepSoundTime = 600; } else if ( enginetrace->GetPointContents( feet ) & MASK_WATER ) { psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) ); fvol = fWalking ? 0.2 : 0.5; m_flStepSoundTime = fWalking ? 400 : 300; } else { if ( !psurface ) return; m_flStepSoundTime = fWalking ? 400 : 300; switch ( psurface->game.material ) { default: case CHAR_TEX_CONCRETE: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_METAL: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_DIRT: fvol = fWalking ? 0.25 : 0.55; break; case CHAR_TEX_VENT: fvol = fWalking ? 0.4 : 0.7; break; case CHAR_TEX_GRATE: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_TILE: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_SLOSH: fvol = fWalking ? 0.2 : 0.5; break; } } m_flStepSoundTime += flduck; // slower step time if ducking // play the sound // 65% volume if ducking if ( GetFlags() & FL_DUCKING ) { fvol *= 0.65; } PlayStepSound( feet, psurface, fvol, false ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &input - //----------------------------------------------------------------------------- void CPortalGameMovement::CategorizePosition( void ) { Vector point; trace_t pm; // if the player hull point one unit down is solid, the player // is on ground // see if standing on something solid // Doing this before we move may introduce a potential latency in water detection, but // doing it after can get us stuck on the bottom in water if the amount we move up // is less than the 1 pixel 'threshold' we're about to snap to. Also, we'll call // this several times per frame, so we really need to avoid sticking to the bottom of // water on each call, and the converse case will correct itself if called twice. CheckWater(); // observers don't have a ground entity if ( player->IsObserver() ) return; point[0] = mv->GetAbsOrigin()[0]; point[1] = mv->GetAbsOrigin()[1]; point[2] = mv->GetAbsOrigin()[2] - 2; Vector bumpOrigin; bumpOrigin = mv->GetAbsOrigin(); // Shooting up really fast. Definitely not on ground. // On ladder moving up, so not on ground either // NOTE: 145 is a jump. if ( mv->m_vecVelocity[2] > 140 || ( mv->m_vecVelocity[2] > 0.0f && player->GetMoveType() == MOVETYPE_LADDER ) ) { SetGroundEntity( NULL ); } else { // Try and move down. TracePlayerBBox( bumpOrigin, point, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, pm ); // If we hit a steep plane, we are not on ground if ( pm.plane.normal[2] < 0.7) { // Test four sub-boxes, to see if any of them would have found shallower slope we could // actually stand on TracePlayerBBoxForGround2( bumpOrigin, point, GetPlayerMins(), GetPlayerMaxs(), mv->m_nPlayerHandle.Get(), MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, pm ); if ( pm.plane.normal[2] < 0.7) { SetGroundEntity( NULL ); // too steep // probably want to add a check for a +z velocity too! if ( ( mv->m_vecVelocity.z > 0.0f ) && ( player->GetMoveType() != MOVETYPE_NOCLIP ) ) { player->m_surfaceFriction = 0.25f; } } else { SetGroundEntity( &pm ); // Otherwise, point to index of ent under us. } } else { SetGroundEntity( &pm ); // Otherwise, point to index of ent under us. } // If we are on something... if (player->GetGroundEntity() != NULL) { // Then we are not in water jump sequence player->m_flWaterJumpTime = 0; // If we could make the move, drop us down that 1 pixel if ( player->GetWaterLevel() < WL_Waist && !pm.startsolid && !pm.allsolid ) { // check distance we would like to move -- this is supposed to just keep up // "on the ground" surface not stap us back to earth (i.e. on move origin to // end position when the ground is within .5 units away) (2 units) if( pm.fraction ) // if( pm.fraction < 0.5) { mv->SetAbsOrigin( pm.endpos ); } } } #ifndef CLIENT_DLL //Adrian: vehicle code handles for us. if ( player->IsInAVehicle() == false ) { // If our gamematerial has changed, tell any player surface triggers that are watching IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); surfacedata_t *pSurfaceProp = physprops->GetSurfaceData( pm.surface.surfaceProps ); char cCurrGameMaterial = pSurfaceProp->game.material; if ( !player->GetGroundEntity() ) { cCurrGameMaterial = 0; } // Changed? if ( player->m_chPreviousTextureType != cCurrGameMaterial ) { CEnvPlayerSurfaceTrigger::SetPlayerSurface( player, cCurrGameMaterial ); } player->m_chPreviousTextureType = cCurrGameMaterial; } #endif } }
void CSDKPlayer::CheckBallShield(const Vector &oldPos, Vector &newPos, const Vector &oldVel, Vector &newVel, const QAngle &oldAng, QAngle &newAng) { bool stopPlayer = false; const float border = (GetFlags() & FL_SHIELD_KEEP_IN) ? -mp_shield_border.GetInt() : mp_shield_border.GetInt(); int forward; #ifdef CLIENT_DLL forward = GetPlayersTeam(this)->m_nForward; #else forward = GetTeam()->m_nForward; #endif if (SDKGameRules()->m_nShieldType != SHIELD_NONE) { if (SDKGameRules()->m_nShieldType == SHIELD_GOALKICK || SDKGameRules()->m_nShieldType == SHIELD_PENALTY || SDKGameRules()->m_nShieldType == SHIELD_FREEKICK || (SDKGameRules()->m_nShieldType == SHIELD_KICKOFF && !SDKGameRules()->IsIntermissionState()) || SDKGameRules()->m_nShieldType == SHIELD_CORNER) { const float radius = mp_shield_ball_radius.GetFloat(); Vector dir = newPos - SDKGameRules()->m_vShieldPos; if (dir.Length2DSqr() < pow(radius, 2)) { dir.z = 0; dir.NormalizeInPlace(); newPos = SDKGameRules()->m_vShieldPos + dir * radius; stopPlayer = true; } } if (SDKGameRules()->m_nShieldType == SHIELD_GOALKICK || SDKGameRules()->m_nShieldType == SHIELD_PENALTY || SDKGameRules()->m_nShieldType == SHIELD_KEEPERHANDS) { int side = (SDKGameRules()->m_nShieldType == SHIELD_PENALTY ? GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->GetOppTeamNumber() : SDKGameRules()->m_nShieldTeam); Vector min = GetGlobalTeam(side)->m_vPenBoxMin - border; Vector max = GetGlobalTeam(side)->m_vPenBoxMax + border; if (GetFlags() & FL_SHIELD_KEEP_OUT || SDKGameRules()->m_nShieldType == SHIELD_PENALTY) { if (SDKGameRules()->m_vKickOff.GetY() > min.y) min.y -= 500; else max.y += 500; } bool isInsideBox = newPos.x > min.x && newPos.y > min.y && newPos.x < max.x && newPos.y < max.y; Vector boxCenter = (min + max) / 2; if (GetFlags() & FL_SHIELD_KEEP_OUT && isInsideBox) { bool oldPosInBox = true; if (newPos.x > min.x && oldPos.x <= min.x && newPos.x < boxCenter.x) { newPos.x = min.x; oldPosInBox = false; } else if (newPos.x < max.x && oldPos.x >= max.x && newPos.x > boxCenter.x) { newPos.x = max.x; oldPosInBox = false; } if (newPos.y > min.y && oldPos.y <= min.y && newPos.y < boxCenter.y) { newPos.y = min.y; oldPosInBox = false; } else if (newPos.y < max.y && oldPos.y >= max.y && newPos.y > boxCenter.y) { newPos.y = max.y; oldPosInBox = false; } stopPlayer = true; if (SDKGameRules()->m_nShieldType == SHIELD_KEEPERHANDS && oldPosInBox) { Vector goalCenter = GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->m_vGoalCenter; goalCenter.y -= GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->m_nForward * 500; if ((goalCenter - newPos).Length2DSqr() < (goalCenter - oldPos).Length2DSqr()) { newPos.x = oldPos.x; newPos.y = oldPos.y; stopPlayer = true; } else stopPlayer = false; } } else if (GetFlags() & FL_SHIELD_KEEP_IN && !isInsideBox) { if (newPos.x < min.x) newPos.x = min.x; else if (newPos.x > max.x) newPos.x = max.x; if (newPos.y < min.y) newPos.y = min.y; else if (newPos.y > max.y) newPos.y = max.y; stopPlayer = true; } } if (SDKGameRules()->m_nShieldType == SHIELD_THROWIN && GetFlags() & FL_SHIELD_KEEP_OUT || SDKGameRules()->m_nShieldType == SHIELD_FREEKICK || SDKGameRules()->m_nShieldType == SHIELD_CORNER || SDKGameRules()->m_nShieldType == SHIELD_KICKOFF || SDKGameRules()->m_nShieldType == SHIELD_PENALTY && (GetFlags() & FL_SHIELD_KEEP_OUT)) { float radius = SDKGameRules()->GetShieldRadius(GetTeamNumber(), GetFlags() & FL_SHIELD_KEEP_IN) + border; Vector dir = newPos - SDKGameRules()->m_vShieldPos; if (!SDKGameRules()->IsIntermissionState() && ((GetFlags() & FL_SHIELD_KEEP_OUT) && dir.Length2D() < radius || (GetFlags() & FL_SHIELD_KEEP_IN) && dir.Length2D() > radius)) { dir.z = 0; dir.NormalizeInPlace(); newPos = SDKGameRules()->m_vShieldPos + dir * radius; stopPlayer = true; } if (SDKGameRules()->m_nShieldType == SHIELD_KICKOFF && (GetFlags() & FL_SHIELD_KEEP_OUT) && (!SDKGameRules()->IsIntermissionState() || SDKGameRules()->State_Get() == MATCH_PERIOD_WARMUP && mp_shield_block_opponent_half.GetBool())) { int forward; #ifdef CLIENT_DLL forward = GetPlayersTeam(this)->m_nForward; #else forward = GetTeam()->m_nForward; #endif float yBorder = SDKGameRules()->m_vKickOff.GetY() - abs(border) * forward; if (ZeroSign(newPos.y - yBorder) == forward) { newPos.y = yBorder; stopPlayer = true; } } if (SDKGameRules()->m_nShieldType == SHIELD_FREEKICK && mp_shield_block_sixyardbox.GetBool()) { int teamPosType; #ifdef CLIENT_DLL teamPosType = GameResources()->GetTeamPosType(entindex()); #else teamPosType = GetTeamPosType(); #endif if (teamPosType != POS_GK || GetTeamNumber() != GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->GetOppTeamNumber()) { int side = GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->GetOppTeamNumber(); Vector min = GetGlobalTeam(side)->m_vSixYardBoxMin - border; Vector max = GetGlobalTeam(side)->m_vSixYardBoxMax + border; if (GetGlobalTeam(side)->m_nForward == 1) min.y -= 500; else max.y += 500; bool isInsideBox = newPos.x > min.x && newPos.y > min.y && newPos.x < max.x && newPos.y < max.y; Vector boxCenter = (min + max) / 2; if (isInsideBox) { if (newPos.x > min.x && oldPos.x <= min.x && newPos.x < boxCenter.x) newPos.x = min.x; else if (newPos.x < max.x && oldPos.x >= max.x && newPos.x > boxCenter.x) newPos.x = max.x; if (newPos.y > min.y && oldPos.y <= min.y && newPos.y < boxCenter.y) newPos.y = min.y; else if (newPos.y < max.y && oldPos.y >= max.y && newPos.y > boxCenter.y) newPos.y = max.y; stopPlayer = true; } } } } if (SDKGameRules()->m_nShieldType == SHIELD_THROWIN && GetFlags() & FL_SHIELD_KEEP_IN) { const int xLength = mp_shield_throwin_movement_x.GetInt(); const int yLength = mp_shield_throwin_movement_y.GetInt(); Vector xSign = SDKGameRules()->m_vShieldPos.GetX() > SDKGameRules()->m_vKickOff.GetX() ? 1 : -1; Vector min = SDKGameRules()->m_vShieldPos + Vector(xSign == -1 ? -xLength : 0, -yLength / 2, 0); Vector max = SDKGameRules()->m_vShieldPos + Vector(xSign == -1 ? 0 : xLength, yLength / 2, 0); bool isInsideBox = newPos.x > min.x && newPos.y > min.y && newPos.x < max.x && newPos.y < max.y; if (!isInsideBox) { if (newPos.x < min.x) newPos.x = min.x; else if (newPos.x > max.x) newPos.x = max.x; if (newPos.y < min.y) newPos.y = min.y; else if (newPos.y > max.y) newPos.y = max.y; stopPlayer = true; } } } if (!SDKGameRules()->IsIntermissionState() && mp_field_padding_enabled.GetBool()) { float border = mp_field_padding.GetInt(); Vector min = SDKGameRules()->m_vFieldMin - border; Vector max = SDKGameRules()->m_vFieldMax + border; if (newPos.x < min.x || newPos.y < min.y || newPos.x > max.x || newPos.y > max.y) { if (newPos.x < min.x) newPos.x = min.x; else if (newPos.x > max.x) newPos.x = max.x; if (newPos.y < min.y) newPos.y = min.y; else if (newPos.y > max.y) newPos.y = max.y; stopPlayer = true; } } if (stopPlayer) { //newVel = oldVel; trace_t trace; UTIL_TraceHull(newPos, newPos, GetPlayerMins(), GetPlayerMaxs(), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER, &trace); if (trace.startsolid) { // Stay at the old pos since the new pos is taken newPos = oldPos; } Vector dir = newPos - oldPos; dir.z = 0; float speed = dir.NormalizeInPlace(); newVel = dir * min(speed * 100, mp_runspeed.GetInt()); //newVel.x = (newPos - oldPos).x * 100; //newVel.y = (newPos - oldPos).y * 100; //newPos = pos; } }
//----------------------------------------------------------------------------- // Purpose: // Input : ladders - // maxdist - // **ppLadder - // ladderOrigin - //----------------------------------------------------------------------------- void CHL2GameMovement::Findladder( float maxdist, CFuncLadder **ppLadder, Vector& ladderOrigin, const CFuncLadder *skipLadder ) { CFuncLadder *bestLadder = NULL; float bestDist = MAX_COORD_INTEGER; Vector bestOrigin; bestOrigin.Init(); float maxdistSqr = maxdist * maxdist; int c = CFuncLadder::GetLadderCount(); for ( int i = 0 ; i < c; i++ ) { CFuncLadder *ladder = CFuncLadder::GetLadder( i ); if ( !ladder->IsEnabled() ) continue; if ( skipLadder && ladder == skipLadder ) continue; Vector topPosition; Vector bottomPosition; ladder->GetTopPosition( topPosition ); ladder->GetBottomPosition( bottomPosition ); Vector closest; CalcClosestPointOnLineSegment( mv->GetAbsOrigin(), bottomPosition, topPosition, closest, NULL ); float distSqr = ( closest - mv->GetAbsOrigin() ).LengthSqr(); // Too far away if ( distSqr > maxdistSqr ) { continue; } // Need to trace to see if it's clear trace_t tr; UTIL_TraceLine( mv->GetAbsOrigin(), closest, MASK_PLAYERSOLID, player, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0f && tr.m_pEnt && tr.m_pEnt != ladder ) { // Try a trace stepped up from the ground a bit, in case there's something at ground level blocking us. float sizez = GetPlayerMaxs().z - GetPlayerMins().z; UTIL_TraceLine( mv->GetAbsOrigin() + Vector( 0, 0, sizez * 0.5f ), closest, MASK_PLAYERSOLID, player, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0f && tr.m_pEnt && tr.m_pEnt != ladder && !tr.m_pEnt->IsSolidFlagSet( FSOLID_TRIGGER ) ) { continue; } } // See if this is the best one so far if ( distSqr < bestDist ) { bestDist = distSqr; bestLadder = ladder; bestOrigin = closest; } } // Return best ladder spot *ppLadder = bestLadder; ladderOrigin = bestOrigin; }
void C_HL2MP_Player::AvoidPlayers( CUserCmd *pCmd ) { // This is only used in team play. if ( !HL2MPRules()->IsTeamplay() ) return; // Don't test if the player doesn't exist or is dead. if ( IsAlive() == false ) return; C_Team *pTeam = ( C_Team * )GetTeam(); if ( !pTeam ) return; // Up vector. static Vector vecUp( 0.0f, 0.0f, 1.0f ); Vector vecHL2MPPlayerCenter = GetAbsOrigin(); Vector vecHL2MPPlayerMin = GetPlayerMins(); Vector vecHL2MPPlayerMax = GetPlayerMaxs(); float flZHeight = vecHL2MPPlayerMax.z - vecHL2MPPlayerMin.z; vecHL2MPPlayerCenter.z += 0.5f * flZHeight; VectorAdd( vecHL2MPPlayerMin, vecHL2MPPlayerCenter, vecHL2MPPlayerMin ); VectorAdd( vecHL2MPPlayerMax, vecHL2MPPlayerCenter, vecHL2MPPlayerMax ); // Find an intersecting player or object. int nAvoidPlayerCount = 0; C_HL2MP_Player *pAvoidPlayerList[MAX_PLAYERS]; C_HL2MP_Player *pIntersectPlayer = NULL; float flAvoidRadius = 0.0f; Vector vecAvoidCenter, vecAvoidMin, vecAvoidMax; for ( int i = 0; i < pTeam->GetNumPlayers(); ++i ) { C_HL2MP_Player *pAvoidPlayer = static_cast< C_HL2MP_Player * >( pTeam->GetPlayer( i ) ); if ( pAvoidPlayer == NULL ) continue; // Is the avoid player me? if ( pAvoidPlayer == this ) continue; // Save as list to check against for objects. pAvoidPlayerList[nAvoidPlayerCount] = pAvoidPlayer; ++nAvoidPlayerCount; // Check to see if the avoid player is dormant. if ( pAvoidPlayer->IsDormant() ) continue; // Is the avoid player solid? if ( pAvoidPlayer->IsSolidFlagSet( FSOLID_NOT_SOLID ) ) continue; Vector t1, t2; vecAvoidCenter = pAvoidPlayer->GetAbsOrigin(); vecAvoidMin = pAvoidPlayer->GetPlayerMins(); vecAvoidMax = pAvoidPlayer->GetPlayerMaxs(); flZHeight = vecAvoidMax.z - vecAvoidMin.z; vecAvoidCenter.z += 0.5f * flZHeight; VectorAdd( vecAvoidMin, vecAvoidCenter, vecAvoidMin ); VectorAdd( vecAvoidMax, vecAvoidCenter, vecAvoidMax ); if ( IsBoxIntersectingBox( vecHL2MPPlayerMin, vecHL2MPPlayerMax, vecAvoidMin, vecAvoidMax ) ) { // Need to avoid this player. if ( !pIntersectPlayer ) { pIntersectPlayer = pAvoidPlayer; break; } } } // Anything to avoid? if ( !pIntersectPlayer ) return; // Calculate the push strength and direction. Vector vecDelta; // Avoid a player - they have precedence. if ( pIntersectPlayer ) { VectorSubtract( pIntersectPlayer->WorldSpaceCenter(), vecHL2MPPlayerCenter, vecDelta ); Vector vRad = pIntersectPlayer->WorldAlignMaxs() - pIntersectPlayer->WorldAlignMins(); vRad.z = 0; flAvoidRadius = vRad.Length(); } float flPushStrength = RemapValClamped( vecDelta.Length(), flAvoidRadius, 0, 0, hl2mp_max_separation_force.GetInt() ); //flPushScale; //Msg( "PushScale = %f\n", flPushStrength ); // Check to see if we have enough push strength to make a difference. if ( flPushStrength < 0.01f ) return; Vector vecPush; if ( GetAbsVelocity().Length2DSqr() > 0.1f ) { Vector vecVelocity = GetAbsVelocity(); vecVelocity.z = 0.0f; CrossProduct( vecUp, vecVelocity, vecPush ); VectorNormalize( vecPush ); } else { // We are not moving, but we're still intersecting. QAngle angView = pCmd->viewangles; angView.x = 0.0f; AngleVectors( angView, NULL, &vecPush, NULL ); } // Move away from the other player/object. Vector vecSeparationVelocity; if ( vecDelta.Dot( vecPush ) < 0 ) { vecSeparationVelocity = vecPush * flPushStrength; } else { vecSeparationVelocity = vecPush * -flPushStrength; } // Don't allow the max push speed to be greater than the max player speed. float flMaxPlayerSpeed = MaxSpeed(); float flCropFraction = 1.33333333f; if ( ( GetFlags() & FL_DUCKING ) && ( GetGroundEntity() != NULL ) ) { flMaxPlayerSpeed *= flCropFraction; } float flMaxPlayerSpeedSqr = flMaxPlayerSpeed * flMaxPlayerSpeed; if ( vecSeparationVelocity.LengthSqr() > flMaxPlayerSpeedSqr ) { vecSeparationVelocity.NormalizeInPlace(); VectorScale( vecSeparationVelocity, flMaxPlayerSpeed, vecSeparationVelocity ); } QAngle vAngles = pCmd->viewangles; vAngles.x = 0; Vector currentdir; Vector rightdir; AngleVectors( vAngles, ¤tdir, &rightdir, NULL ); Vector vDirection = vecSeparationVelocity; VectorNormalize( vDirection ); float fwd = currentdir.Dot( vDirection ); float rt = rightdir.Dot( vDirection ); float forward = fwd * flPushStrength; float side = rt * flPushStrength; //Msg( "fwd: %f - rt: %f - forward: %f - side: %f\n", fwd, rt, forward, side ); pCmd->forwardmove += forward; pCmd->sidemove += side; // Clamp the move to within legal limits, preserving direction. This is a little // complicated because we have different limits for forward, back, and side //Msg( "PRECLAMP: forwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove ); float flForwardScale = 1.0f; if ( pCmd->forwardmove > fabs( cl_forwardspeed.GetFloat() ) ) { flForwardScale = fabs( cl_forwardspeed.GetFloat() ) / pCmd->forwardmove; } else if ( pCmd->forwardmove < -fabs( cl_backspeed.GetFloat() ) ) { flForwardScale = fabs( cl_backspeed.GetFloat() ) / fabs( pCmd->forwardmove ); } float flSideScale = 1.0f; if ( fabs( pCmd->sidemove ) > fabs( cl_sidespeed.GetFloat() ) ) { flSideScale = fabs( cl_sidespeed.GetFloat() ) / fabs( pCmd->sidemove ); } float flScale = min( flForwardScale, flSideScale ); pCmd->forwardmove *= flScale; pCmd->sidemove *= flScale; //Msg( "Pforwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove ); }
void CDODPlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) { Vector knee; Vector feet; float height; int fLadder; if ( m_flStepSoundTime > 0 ) { m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; if ( m_flStepSoundTime < 0 ) { m_flStepSoundTime = 0; } } if ( m_flStepSoundTime > 0 ) return; if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) return; if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) return; if ( !sv_footsteps.GetFloat() ) return; float speed = VectorLength( vecVelocity ); float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); // determine if we are on a ladder fLadder = ( GetMoveType() == MOVETYPE_LADDER ); float flDuck; if ( ( GetFlags() & FL_DUCKING) || fLadder ) { flDuck = 100; } else { flDuck = 0; } static float flMinProneSpeed = 10.0f; static float flMinSpeed = 70.0f; static float flRunSpeed = 110.0f; bool onground = ( GetFlags() & FL_ONGROUND ); bool movingalongground = ( groundspeed > 0.0f ); bool moving_fast_enough = ( speed >= flMinSpeed ); // always play a step sound if we are moving faster than // To hear step sounds you must be either on a ladder or moving along the ground AND // You must be moving fast enough CheckProneMoveSound( groundspeed, onground ); if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) ) { return; } bool bWalking = ( speed < flRunSpeed ); // or ducking! VectorCopy( vecOrigin, knee ); VectorCopy( vecOrigin, feet ); height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; knee[2] = vecOrigin[2] + 0.2 * height; float flVol; // find out what we're stepping in or on... if ( fLadder ) { psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "ladder" ) ); flVol = 1.0; m_flStepSoundTime = 350; } else if ( enginetrace->GetPointContents( knee ) & MASK_WATER ) { static int iSkipStep = 0; if ( iSkipStep == 0 ) { iSkipStep++; return; } if ( iSkipStep++ == 3 ) { iSkipStep = 0; } psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) ); flVol = 0.65; m_flStepSoundTime = 600; } else if ( enginetrace->GetPointContents( feet ) & MASK_WATER ) { psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) ); flVol = bWalking ? 0.2 : 0.5; m_flStepSoundTime = bWalking ? 400 : 300; } else { if ( !psurface ) return; if ( bWalking ) { m_flStepSoundTime = 400; } else { if ( speed > 200 ) { int speeddiff = PLAYER_SPEED_SPRINT - PLAYER_SPEED_RUN; int diff = speed - PLAYER_SPEED_RUN; float percent = (float)diff / (float)speeddiff; m_flStepSoundTime = 300.0f - 30.0f * percent; } else { m_flStepSoundTime = 400; } } switch ( psurface->game.material ) { default: case CHAR_TEX_CONCRETE: flVol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_METAL: flVol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_DIRT: flVol = bWalking ? 0.25 : 0.55; break; case CHAR_TEX_VENT: flVol = bWalking ? 0.4 : 0.7; break; case CHAR_TEX_GRATE: flVol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_TILE: flVol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_SLOSH: flVol = bWalking ? 0.2 : 0.5; break; } } m_flStepSoundTime += flDuck; // slower step time if ducking if ( GetFlags() & FL_DUCKING ) { flVol *= 0.65; } // protect us from prediction errors a little bit if ( m_flMinNextStepSoundTime > gpGlobals->curtime ) { return; } m_flMinNextStepSoundTime = gpGlobals->curtime + 0.1f; PlayStepSound( feet, psurface, flVol, false ); }
void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) { bool bWalking; float fvol = 1.0f; Vector knee; Vector feet; float height; float speed; float velrun; float velwalk; int fLadder; if ( m_flStepSoundTime > 0 ) { m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; if ( m_flStepSoundTime < 0 ) { m_flStepSoundTime = 0; } } if ( m_flStepSoundTime > 0 ) return; if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) return; if ( GetMoveType() == MOVETYPE_NOCLIP ) return; if ( !sv_footsteps.GetFloat() ) return; speed = VectorLength( vecVelocity ); float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); // determine if we are on a ladder fLadder = false; GetStepSoundVelocities( &velwalk, &velrun ); bool onground = ( GetFlags() & FL_ONGROUND ); bool movingalongground = ( groundspeed > 0.0001f ); bool moving_fast_enough = ( speed >= velwalk ); // To hear step sounds you must be either on a ladder or moving along the ground AND // You must be moving fast enough if ( !moving_fast_enough || !( onground && movingalongground ) ) return; // MoveHelper()->PlayerSetAnimation( PLAYER_WALK ); bWalking = speed < velrun; VectorCopy( vecOrigin, knee ); VectorCopy( vecOrigin, feet ); height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; knee[2] = vecOrigin[2] + 0.2 * height; if ( !psurface ) return; SetStepSoundTime( STEPSOUNDTIME_NORMAL, bWalking ); #ifdef CLIENT_DLL if (this == GetLocalPlayer()) { fvol = 0.1f; } #endif PlayStepSound( feet, psurface, fvol, false ); }
//----------------------------------------------------------------------------- // Run this Bot's AI for one tick. //----------------------------------------------------------------------------- void CSDKBot::BotThink() { // Make sure we stay being a bot AddFlag( FL_FAKECLIENT ); if ( IsEFlagSet(EFL_BOT_FROZEN) ) return; CUserCmd cmd; Q_memset( &cmd, 0, sizeof( cmd ) ); ConVarRef bot_freeze("bot_freeze"); if ( !IsAlive() ) { HandleRespawn(cmd); } else if (bot_mimic.GetBool()) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( bot_mimic.GetInt() ); if ( pPlayer && pPlayer->GetLastUserCommand() ) { cmd = *pPlayer->GetLastUserCommand(); ConVarRef bot_mimic_yaw_offset("bot_mimic_yaw_offset"); cmd.viewangles[YAW] += bot_mimic_yaw_offset.GetFloat(); ConVarRef bot_crouch("bot_crouch"); if( bot_crouch.GetInt() ) cmd.buttons |= IN_DUCK; } } else if (!bot_freeze.GetBool()) { trace_t tr_front; Vector Forward; AngleVectors(GetLocalAngles(), &Forward); UTIL_TraceHull( GetLocalOrigin()+Vector(0,0,5), GetLocalOrigin() + Vector(0,0,5) + (Forward * 50), GetPlayerMins(), GetPlayerMaxs(), MASK_PLAYERSOLID, this, COLLISION_GROUP_NONE, &tr_front ); // enemy acquisition if( !GetEnemy() || RecheckEnemy() || !GetEnemy()->IsAlive() ) { if( GetEnemy() && !GetEnemy()->IsAlive() ) ResetNavigationParams(); AcquireEnemy(); m_flTimeToRecheckEnemy = gpGlobals->curtime + 1.0f; } // assume we have an enemy from now on InfoGathering(); Attack(cmd); if( m_flTimeToRecheckStuck < gpGlobals->curtime ) CheckStuck(cmd); if( m_flNextDealObstacles < gpGlobals->curtime ) DealWithObstacles(tr_front.m_pEnt, cmd); Navigation(cmd); CheckNavMeshAttrib(&tr_front, cmd); } // debug waypoint related position /*for( int i=0; i<m_Waypoints.Count(); i++ ) { NDebugOverlay::Cross3DOriented( m_Waypoints[i].Center, QAngle(0,0,0), 5*i+1, 200, 0, 0, false, -1 ); }*/ RunPlayerMove( cmd, gpGlobals->frametime ); }
//----------------------------------------------------------------------------- // Purpose: // Input : mounting - // transit_speed - // goalpos - // *ladder - //----------------------------------------------------------------------------- void CHL2GameMovement::StartForcedMove( bool mounting, float transit_speed, const Vector& goalpos, CFuncLadder *ladder ) { LadderMove_t* lm = GetLadderMove(); Assert( lm ); // Already active, just ignore if ( lm->m_bForceLadderMove ) { return; } #if !defined( CLIENT_DLL ) if ( ladder ) { ladder->PlayerGotOn( GetHL2Player() ); // If the Ladder only wants to be there for automount checking, abort now if ( ladder->DontGetOnLadder() ) return; } // Reserve goal slot here bool valid = false; lm->m_hReservedSpot = CReservePlayerSpot::ReserveSpot( player, goalpos, GetPlayerMins( ( player->GetFlags() & FL_DUCKING ) ? true : false ), GetPlayerMaxs( ( player->GetFlags() & FL_DUCKING ) ? true : false ), valid ); if ( !valid ) { // FIXME: Play a deny sound? if ( lm->m_hReservedSpot ) { UTIL_Remove( lm->m_hReservedSpot ); lm->m_hReservedSpot = NULL; } return; } #endif // Use current player origin as start and new origin as dest lm->m_vecGoalPosition = goalpos; lm->m_vecStartPosition = mv->GetAbsOrigin(); // Figure out how long it will take to make the gap based on transit_speed Vector delta = lm->m_vecGoalPosition - lm->m_vecStartPosition; float distance = delta.Length(); Assert( transit_speed > 0.001f ); // Compute time required to move that distance float transit_time = distance / transit_speed; if ( transit_time < 0.001f ) { transit_time = 0.001f; } lm->m_bForceLadderMove = true; lm->m_bForceMount = mounting; lm->m_flStartTime = gpGlobals->curtime; lm->m_flArrivalTime = lm->m_flStartTime + transit_time; lm->m_hForceLadder = ladder; // Don't get stuck during this traversal since we'll just be slamming the player origin player->SetMoveType( MOVETYPE_NONE ); player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); player->SetSolid( SOLID_NONE ); SetLadder( ladder ); // Debounce the use key SwallowUseKey(); }
void CMomentumGameMovement::CategorizePosition(float flReflectNormal) { Vector point; trace_t pm; // Reset this each time we-recategorize, otherwise we have bogus friction when we jump into water and plunge downward really quickly player->m_surfaceFriction = 1.0f; // if the player hull point one unit down is solid, the player // is on ground // see if standing on something solid // Doing this before we move may introduce a potential latency in water detection, but // doing it after can get us stuck on the bottom in water if the amount we move up // is less than the 1 pixel 'threshold' we're about to snap to. Also, we'll call // this several times per frame, so we really need to avoid sticking to the bottom of // water on each call, and the converse case will correct itself if called twice. CheckWater(); // observers don't have a ground entity if (player->IsObserver()) return; float flOffset = 2.0f; point[0] = mv->GetAbsOrigin()[0]; point[1] = mv->GetAbsOrigin()[1]; point[2] = mv->GetAbsOrigin()[2] - flOffset; Vector bumpOrigin; bumpOrigin = mv->GetAbsOrigin(); // Shooting up really fast. Definitely not on ground. // On ladder moving up, so not on ground either // NOTE: 145 is a jump. #define NON_JUMP_VELOCITY 140.0f float zvel = mv->m_vecVelocity[2]; bool bMovingUp = zvel > 0.0f; bool bMovingUpRapidly = zvel > NON_JUMP_VELOCITY; float flGroundEntityVelZ = 0.0f; if (bMovingUpRapidly) { // Tracker 73219, 75878: ywb 8/2/07 // After save/restore (and maybe at other times), we can get a case where we were saved on a lift and // after restore we'll have a high local velocity due to the lift making our abs velocity appear high. // We need to account for standing on a moving ground object in that case in order to determine if we really // are moving away from the object we are standing on at too rapid a speed. Note that CheckJump already sets // ground entity to NULL, so this wouldn't have any effect unless we are moving up rapidly not from the jump button. CBaseEntity *ground = player->GetGroundEntity(); if (ground) { flGroundEntityVelZ = ground->GetAbsVelocity().z; bMovingUpRapidly = (zvel - flGroundEntityVelZ) > NON_JUMP_VELOCITY; } } // Was on ground, but now suddenly am not if (bMovingUpRapidly || (bMovingUp && player->GetMoveType() == MOVETYPE_LADDER)) { SetGroundEntity(NULL); } else { // Try and move down. TryTouchGround(bumpOrigin, point, GetPlayerMins(), GetPlayerMaxs(), MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, pm); // Was on ground, but now suddenly am not. If we hit a steep plane, we are not on ground if (!pm.m_pEnt || pm.plane.normal[2] < 0.7) { // Test four sub-boxes, to see if any of them would have found shallower slope we could actually stand on TryTouchGroundInQuadrants(bumpOrigin, point, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, pm); if (!pm.m_pEnt || pm.plane.normal[2] < 0.7) { SetGroundEntity(NULL); // probably want to add a check for a +z velocity too! if ((mv->m_vecVelocity.z > 0.0f) && (player->GetMoveType() != MOVETYPE_NOCLIP)) { player->m_surfaceFriction = 0.25f; } } else { if ( flReflectNormal == NO_REFL_NORMAL_CHANGE) { DoLateReflect(); CategorizePosition(1.0f); return; } SetGroundEntity(&pm); } } else { if ( flReflectNormal == NO_REFL_NORMAL_CHANGE ) { DoLateReflect(); CategorizePosition(1.0f); return; } SetGroundEntity(&pm); // Otherwise, point to index of ent under us. } #ifndef CLIENT_DLL // If our gamematerial has changed, tell any player surface triggers that are watching IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); surfacedata_t *pSurfaceProp = physprops->GetSurfaceData(pm.surface.surfaceProps); char cCurrGameMaterial = pSurfaceProp->game.material; if (!player->GetGroundEntity()) { cCurrGameMaterial = 0; } // Changed? if (player->m_chPreviousTextureType != cCurrGameMaterial) { CEnvPlayerSurfaceTrigger::SetPlayerSurface(player, cCurrGameMaterial); } player->m_chPreviousTextureType = cCurrGameMaterial; #endif } }
//----------------------------------------------------------------------------- // Purpose: // *ladder - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CHL2GameMovement::ExitLadderViaDismountNode( CFuncLadder *ladder, bool strict, bool useAlternate ) { // Find the best ladder exit node float bestDot = -99999.0f; float bestDistance = 99999.0f; Vector bestDest; bool found = false; // For 'alternate' dismount bool foundAlternate = false; Vector alternateDest; float alternateDist = 99999.0f; CUtlRBTree< NearbyDismount_t, int > nearbyDismounts( 0, 0, NearbyDismountLessFunc ); GetSortedDismountNodeList( mv->GetAbsOrigin(), 100.0f, ladder, nearbyDismounts ); int i; for ( i = nearbyDismounts.FirstInorder(); i != nearbyDismounts.InvalidIndex() ; i = nearbyDismounts.NextInorder( i ) ) { CInfoLadderDismount *spot = nearbyDismounts[ i ].dismount; if ( !spot ) { Assert( !"What happened to the spot!!!" ); continue; } // See if it's valid to put the player there... Vector org = spot->GetAbsOrigin() + Vector( 0, 0, 1 ); trace_t tr; UTIL_TraceHull( org, org, GetPlayerMins( ( player->GetFlags() & FL_DUCKING ) ? true : false ), GetPlayerMaxs( ( player->GetFlags() & FL_DUCKING ) ? true : false ), MASK_PLAYERSOLID, player, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); // Nope... if ( tr.startsolid ) { continue; } // Find the best dot product Vector vecToSpot = org - ( mv->GetAbsOrigin() + player->GetViewOffset() ); vecToSpot.z = 0.0f; float d = VectorNormalize( vecToSpot ); float dot = vecToSpot.Dot( m_vecForward ); // We're not facing at it...ignore if ( dot < 0.5f ) { if( useAlternate && d < alternateDist ) { alternateDest = org; alternateDist = d; foundAlternate = true; } continue; } if ( dot > bestDot ) { bestDest = org; bestDistance = d; bestDot = dot; found = true; } } if ( found ) { // Require a more specific if ( strict && ( ( bestDot < 0.7f ) || ( bestDistance > 40.0f ) ) ) { return false; } StartForcedMove( false, player->MaxSpeed(), bestDest, NULL ); return true; } if( useAlternate ) { // Desperate. Don't refuse to let a person off of a ladder if it can be helped. Use the // alternate dismount if there is one. if( foundAlternate && alternateDist <= 60.0f ) { StartForcedMove( false, player->MaxSpeed(), alternateDest, NULL ); return true; } } return false; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHL2WarsGameMovement::StrategicPlayerMove() { trace_t pm; Vector move; Vector forward, right, up; Vector wishvel; Vector wishdir; float wishspeed, heightchange; float maxspeed = strategic_cam_maxspeed.GetFloat(); // Server defined max speed CHL2WarsPlayer *warsplayer = dynamic_cast<CHL2WarsPlayer *>( player ); if( !warsplayer ) return; float speed = warsplayer->GetCamSpeed(); float maxacceleration = warsplayer->GetCamAcceleration(); float friction = warsplayer->GetCamFriction(); float stopspeed = warsplayer->GetCamStopSpeed(); // Determine our current height warsplayer->CalculateHeight( mv->GetAbsOrigin() ); // Determine movement angles AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); up.z = 0.0f; right.z = 0.0f; VectorNormalize (up); VectorNormalize (right); VectorNormalize (forward); // Zoom direction // Copy movement amounts // Assume max move is 450.0, so we can scale it to the correct speed value // NOTE: Swapped fmove and umove in terms of usage. float smove = (mv->m_flSideMove/450.0f) * speed; float fmove = (mv->m_flForwardMove/450.0f) * speed; float umove = (mv->m_flUpMove/450.0f) * speed; // Zoom when there is no map boundary for (int i=0 ; i<2 ; i++) // Determine x and y parts of velocity wishvel[i] = up[i]*fmove + right[i]*smove; wishvel[2] = 0.0f; if( warsplayer->GetCamHeight() != -1 && warsplayer->GetCamHeight() > 2.0f ) ;//wishvel[2] = -warsplayer->GetCamHeight() * 4.0f; // Force player origin down else wishvel = wishvel + forward*umove*4.0; // Zooming is forward VectorCopy (wishvel, wishdir); // Determine maginitude of speed of move wishspeed = VectorNormalize(wishdir); // // Clamp to user defined wish speed // if (wishspeed > speed ) { VectorScale (wishvel, speed/wishspeed, wishvel); wishspeed = speed; } // // Clamp to server defined max speed // if (wishspeed > maxspeed ) { VectorScale (wishvel, maxspeed/wishspeed, wishvel); wishspeed = maxspeed; } if ( maxacceleration > 0.0 ) { // Set pmove velocity Accelerate ( wishdir, wishspeed, maxacceleration ); float spd = VectorLength( mv->m_vecVelocity ); if (spd < 1.0f) { mv->m_vecVelocity.Init(); return; } // Bleed off some speed, but if we have less than the bleed // threshhold, bleed the theshold amount. float control = (spd < stopspeed) ? stopspeed : spd; // Add the amount to the drop amount. float drop = control * friction * gpGlobals->frametime; // scale the velocity float newspeed = spd - drop; if (newspeed < 0) newspeed = 0; // Determine proportion of old speed we are using. newspeed /= spd; VectorScale( mv->m_vecVelocity, newspeed, mv->m_vecVelocity ); } else { VectorCopy( wishvel, mv->m_vecVelocity ); } #ifdef CLIENT_DLL if( cl_showmovementspeed.GetInt() == player->entindex() ) { engine->Con_NPrintf( 1, "CLIENT Movement speed: %6.1f | maxspeed: %6.1f | userspeed: %6.1f | pos: %6.1f %6.1f %6.1f | mins: %6.1f %6.1f %6.1f | maxs: %6.1f %6.1f %6.1f", mv->m_vecVelocity.Length(), maxspeed, speed, mv->GetAbsOrigin().x, mv->GetAbsOrigin().y, mv->GetAbsOrigin().z, GetPlayerMins().x, GetPlayerMins().y, GetPlayerMins().z, GetPlayerMaxs().x, GetPlayerMaxs().y, GetPlayerMaxs().z ); } #else if( sv_showmovementspeed.GetInt() == player->entindex() ) { engine->Con_NPrintf( 3, "SERVER Movement speed: %6.1f | maxspeed: %6.1f | userspeed: %6.1f | pos: %6.1f %6.1f %6.1f | mins: %6.1f %6.1f %6.1f | maxs: %6.1f %6.1f %6.1f", mv->m_vecVelocity.Length(), maxspeed, speed, mv->GetAbsOrigin().x, mv->GetAbsOrigin().y, mv->GetAbsOrigin().z, GetPlayerMins().x, GetPlayerMins().y, GetPlayerMins().z, GetPlayerMaxs().x, GetPlayerMaxs().y, GetPlayerMaxs().z ); } #endif // CLIENT_DLL //CheckVelocity(); // Store current height heightchange = mv->GetAbsOrigin().z; if( warsplayer->GetCamHeight() != -1 ) { //Vector vCamOffsetZ = Vector(0.0f, 0.0f, warsplayer->GetCameraOffset().z); //TracePlayerBBox( mv->GetAbsOrigin(), warsplayer->GetCamGroundPos()+vCamOffsetZ, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); TracePlayerBBox( mv->GetAbsOrigin(), warsplayer->GetCamGroundPos()+Vector(0, 0, warsplayer->GetCamMaxHeight()-48.0f), PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); mv->SetAbsOrigin( pm.endpos ); //NDebugOverlay::Box( warsplayer->GetCamGroundPos()+vCamOffsetZ, -Vector(16, 16, 16), Vector(16, 16, 16), 255, 0, 0, 255, gpGlobals->frametime ); } // Try moving, only obstructed by the map boundaries. Vector destination; VectorMA( mv->GetAbsOrigin(), gpGlobals->frametime, mv->m_vecVelocity, destination ); TracePlayerBBox( mv->GetAbsOrigin(), destination, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); if (pm.fraction == 1) { mv->SetAbsOrigin( pm.endpos ); } else { // Try moving straight along out normal path. TryStrategicMove(); } // Determine new height and return player to the ground warsplayer->CalculateHeight( mv->GetAbsOrigin() ); if( warsplayer->GetCamHeight() != -1 ) { TracePlayerBBox( mv->GetAbsOrigin(), warsplayer->GetCamGroundPos(), PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); mv->SetAbsOrigin( pm.endpos ); //NDebugOverlay::Box( pm.endpos, -Vector(16, 16, 16), Vector(16, 16, 16), 0, 255, 0, 255, gpGlobals->frametime ); // Determine new height again :) warsplayer->CalculateHeight( mv->GetAbsOrigin() ); } // Determine height change and notify input heightchange = mv->GetAbsOrigin().z - heightchange; #ifdef CLIENT_DLL if( heightchange > 0.1f ) { } #endif // CLIENT_DLL //CheckVelocity(); // Zero out velocity if in noaccel mode if ( maxacceleration < 0.0f ) { mv->m_vecVelocity.Init(); } }