//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseEntity::PhysicsCustom() { PhysicsCheckWater(); // regular thinking if ( !PhysicsRunThink() ) return; // Moving upward, off the ground, or resting on something that isn't ground if ( m_vecVelocity[2] > 0 || !GetGroundEntity() || !GetGroundEntity()->IsStandable() ) { SetGroundEntity( NULL ); } // NOTE: The entity must set the position, angles, velocity in its custom movement Vector vecNewPosition = GetAbsOrigin(); if ( vecNewPosition == vec3_origin ) { // Shouldn't be at world origin Assert( 0 ); } Vector vecNewVelocity = m_vecVelocity; QAngle angNewAngles = GetAbsAngles(); QAngle angNewAngVelocity = m_vecAngVelocity; PerformCustomPhysics( &vecNewPosition, &vecNewVelocity, &angNewAngles, &angNewAngVelocity ); // Store off all of the new state information... m_vecVelocity = vecNewVelocity; SetAbsAngles( angNewAngles ); m_vecAngVelocity = angNewAngVelocity; Vector move; VectorSubtract( vecNewPosition, GetAbsOrigin(), move ); // move origin trace_t trace; PhysicsPushEntity( move, &trace ); PhysicsCheckVelocity(); if (trace.allsolid) { // entity is trapped in another solid // UNDONE: does this entity needs to be removed? VectorCopy (vec3_origin, m_vecVelocity); VectorCopy (vec3_angle, m_vecAngVelocity); return; } #if !defined( CLIENT_DLL ) if (pev->free) return; #endif // check for in water PhysicsCheckWaterTransition(); }
void CBaseGrenadeProjectile::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ) { //Assume all surfaces have the same elasticity float flSurfaceElasticity = 1.0; //Don't bounce off of players with perfect elasticity if( trace.m_pEnt && trace.m_pEnt->IsPlayer() ) { flSurfaceElasticity = 0.3; } // if its breakable glass and we kill it, don't bounce. // give some damage to the glass, and if it breaks, pass // through it. bool breakthrough = false; if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable" ) ) { breakthrough = true; } if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable_surf" ) ) { breakthrough = true; } if (breakthrough) { CTakeDamageInfo info( this, this, 10, DMG_CLUB ); trace.m_pEnt->DispatchTraceAttack( info, GetAbsVelocity(), &trace ); ApplyMultiDamage(); if( trace.m_pEnt->m_iHealth <= 0 ) { // slow our flight a little bit Vector vel = GetAbsVelocity(); vel *= 0.4; SetAbsVelocity( vel ); return; } } float flTotalElasticity = GetElasticity() * flSurfaceElasticity; flTotalElasticity = clamp( flTotalElasticity, 0.0f, 0.9f ); // NOTE: A backoff of 2.0f is a reflection Vector vecAbsVelocity; PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, 2.0f ); vecAbsVelocity *= flTotalElasticity; // Get the total velocity (player + conveyors, etc.) VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity ); float flSpeedSqr = DotProduct( vecVelocity, vecVelocity ); // Stop if on ground. if ( trace.plane.normal.z > 0.7f ) // Floor { // Verify that we have an entity. CBaseEntity *pEntity = trace.m_pEnt; Assert( pEntity ); SetAbsVelocity( vecAbsVelocity ); if ( flSpeedSqr < ( 30 * 30 ) ) { if ( pEntity->IsStandable() ) { SetGroundEntity( pEntity ); } // Reset velocities. SetAbsVelocity( vec3_origin ); SetLocalAngularVelocity( vec3_angle ); //align to the ground so we're not standing on end QAngle angle; VectorAngles( trace.plane.normal, angle ); // rotate randomly in yaw angle[1] = random->RandomFloat( 0, 360 ); // TODO: rotate around trace.plane.normal SetAbsAngles( angle ); } else { Vector vecDelta = GetBaseVelocity() - vecAbsVelocity; Vector vecBaseDir = GetBaseVelocity(); VectorNormalize( vecBaseDir ); float flScale = vecDelta.Dot( vecBaseDir ); VectorScale( vecAbsVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, vecVelocity ); VectorMA( vecVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, GetBaseVelocity() * flScale, vecVelocity ); PhysicsPushEntity( vecVelocity, &trace ); } } else { // If we get *too* slow, we'll stick without ever coming to rest because // we'll get pushed down by gravity faster than we can escape from the wall. if ( flSpeedSqr < ( 30 * 30 ) ) { // Reset velocities. SetAbsVelocity( vec3_origin ); SetLocalAngularVelocity( vec3_angle ); } else { SetAbsVelocity( vecAbsVelocity ); } } BounceSound(); }