//----------------------------------------------------------------------------- // Purpose: Aim the offset barrel at a position in parent space // Input : parentTarget - the position of the target in parent space // Output : Vector - angles in local space //----------------------------------------------------------------------------- QAngle CFuncTank::AimBarrelAt( const Vector &parentTarget ) { Vector target = parentTarget - GetLocalOrigin(); float quadTarget = target.LengthSqr(); float quadTargetXY = target.x*target.x + target.y*target.y; // Target is too close! Can't aim at it if ( quadTarget <= m_barrelPos.LengthSqr() ) { return GetLocalAngles(); } else { // We're trying to aim the offset barrel at an arbitrary point. // To calculate this, I think of the target as being on a sphere with // it's center at the origin of the gun. // The rotation we need is the opposite of the rotation that moves the target // along the surface of that sphere to intersect with the gun's shooting direction // To calculate that rotation, we simply calculate the intersection of the ray // coming out of the barrel with the target sphere (that's the new target position) // and use atan2() to get angles // angles from target pos to center float targetToCenterYaw = atan2( target.y, target.x ); float centerToGunYaw = atan2( m_barrelPos.y, sqrt( quadTarget - (m_barrelPos.y*m_barrelPos.y) ) ); float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) ); float centerToGunPitch = atan2( -m_barrelPos.z, sqrt( quadTarget - (m_barrelPos.z*m_barrelPos.z) ) ); return QAngle( -RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw - centerToGunYaw ), 0 ); } }
void Matrix4x4::SetRotation(float flAngle, const Vector& v) { // Normalize beforehand TAssert(fabs(v.LengthSqr() - 1) < 0.000001f); // c = cos(angle), s = sin(angle), t = (1-c) // [ xxt+c xyt-zs xzt+ys ] // [ yxt+zs yyt+c yzt-xs ] // [ zxt-ys zyt+xs zzt+c ] float x = v.x; float y = v.y; float z = v.z; float c = cos(flAngle*(float)M_PI/180); float s = sin(flAngle*(float)M_PI/180); float t = 1-c; m[0][0] = x*x*t + c; m[1][0] = x*y*t - z*s; m[2][0] = x*z*t + y*s; m[0][1] = y*x*t + z*s; m[1][1] = y*y*t + c; m[2][1] = y*z*t - x*s; m[0][2] = z*x*t - y*s; m[1][2] = z*y*t + x*s; m[2][2] = z*z*t + c; }
void CPlayerController::Update(const Vector &position, const Vector &velocity, float secondsToArrival, bool onground, IPhysicsObject *ground) { btVector3 bullTargetPosition, bullMaxVelocity; ConvertPosToBull(position, bullTargetPosition); ConvertPosToBull(velocity, bullMaxVelocity); // If the targets haven't changed, abort. if (bullMaxVelocity.distance2(m_maxVelocity) < FLT_EPSILON && bullTargetPosition.distance2(m_targetPosition) < FLT_EPSILON) { return; } m_targetPosition = bullTargetPosition; m_maxVelocity = bullMaxVelocity; m_enable = true; // FYI: The onground stuff includes any props we may be standing on as well as the world. // The ground is valid only if it's significantly heavier than our object ("Rideable physics" > our mass * 2) m_onground = onground; if (velocity.LengthSqr() <= 0.001f) { m_enable = false; ground = NULL; } else { MaxSpeed(velocity); } m_secondsToArrival = secondsToArrival; m_pGround = (CPhysicsObject *)ground; m_ticksSinceUpdate = 0; }
// Actual work code IterationRetval_t CASW_Scanner_Objects_Enumerator::EnumElement( IHandleEntity *pHandleEntity ) { #ifndef CLIENT_DLL CBaseEntity *pEnt = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); #else C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() ); #endif if ( pEnt == NULL ) return ITERATION_CONTINUE; if (!ValidScannerObject(pEnt)) return ITERATION_CONTINUE; Vector deltaPos = pEnt->GetAbsOrigin() - m_vecScannerCenter; if ( deltaPos.LengthSqr() > m_flRadiusSquared ) return ITERATION_CONTINUE; if ( m_vecScannerCenter.z - pEnt->GetAbsOrigin().z > m_flRadius / 3 ) return ITERATION_CONTINUE; CHandle< CBaseEntity > h; h = pEnt; m_Objects.AddToTail( h ); return ITERATION_CONTINUE; }
void CTriggerMomentumPush::OnSuccessfulTouch(CBaseEntity *pOther) { if (pOther) { Vector finalVel; if (HasSpawnFlags(SF_PUSH_DIRECTION_AS_FINAL_FORCE)) finalVel = m_vPushDir; else finalVel = m_vPushDir.Normalized() * m_fPushForce; switch (m_iIncrease) { case 0: break; case 1: finalVel += pOther->GetAbsVelocity(); break; case 2: if (finalVel.LengthSqr() < pOther->GetAbsVelocity().LengthSqr()) finalVel = pOther->GetAbsVelocity(); break; case 3: pOther->SetBaseVelocity(finalVel); break; default: DevWarning("CTriggerMomentumPush:: %i not recognised as valid for m_iIncrease", m_iIncrease); break; } pOther->SetAbsVelocity(finalVel); } }
bool C_EnvProjectedTexture::IsWithinFarZ(float flLightFOV) { //No need to check camera space lights for visibility, as they should always be close enough to the player. if (m_bCameraSpace) return true; //Trace forward to the nearest opaque brush face Vector vForward; GetVectors(&vForward, NULL, NULL); Vector vTraceStart = GetAbsOrigin(); Vector vTraceEnd = GetAbsOrigin() + vForward; trace_t tr; CTraceFilterWorldOnly filter; UTIL_TraceLine(vTraceStart, vTraceEnd, CONTENTS_SOLID && CONTENTS_OPAQUE, &filter, &tr); //Test to see if the player is close enough to the light to actually see the light's projection. This is based entirely on it's FarZ. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer) { Vector vDistance; VectorSubtract(tr.endpos, pPlayer->EyePosition(), vDistance); float fDistance = vDistance.LengthSqr(); //If distance is greater than the light's FarZ, cease to render. //FarZ determines how far away a light can be seen by the player, AND how far the light travels from it's source in stock Valve code. if (fDistance > Square(m_flFarZ + flLightFOV * 10)) return false; } return true; }
void C_Hairball::CHairballDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes ) { int nSegments = m_pParent->m_nNodesPerHair - 1; float flSpringDistSqr = m_pParent->m_flSpringDist * m_pParent->m_flSpringDist; static int nIterations = 1; for( int iIteration=0; iIteration < nIterations; iIteration++ ) { for ( int iHair=0; iHair < m_pParent->m_nHairs; iHair++ ) { CSimplePhysics::CNode *pBase = &pNodes[iHair * m_pParent->m_nNodesPerHair]; for( int i=0; i < nSegments; i++ ) { Vector &vNode1 = pBase[i].m_vPos; Vector &vNode2 = pBase[i+1].m_vPos; Vector vTo = vNode1 - vNode2; float flDistSqr = vTo.LengthSqr(); if( flDistSqr > flSpringDistSqr ) { float flDist = (float)sqrt( flDistSqr ); vTo *= 1 - (m_pParent->m_flSpringDist / flDist); vNode1 -= vTo * 0.5f; vNode2 += vTo * 0.5f; } } // Lock the base of each hair to the right spot. pBase->m_vPos = m_pParent->m_TransformedHairPositions[iHair]; } } }
void CAI_ASW_HealOtherBehavior::RunTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_HEAL_OTHER_MOVE_TO_TARGET: { if ( GetNavigator()->GetGoalType() == GOALTYPE_NONE ) { TaskComplete(); } if ( m_hHealTargetEnt.Get() ) { Vector vDiff = m_hHealTargetEnt->GetAbsOrigin() - GetAbsOrigin(); if ( vDiff.LengthSqr() <= ( m_flApproachDistance * m_flApproachDistance ) ) { GetNavigator()->StopMoving( true ); GetNavigator()->ClearGoal(); TaskComplete(); } } break; } default: BaseClass::RunTask( pTask ); break; } }
void CFlex::DoBodyLean( void ) { CAI_NPC *myNpc = MyNPCPointer( ); if (myNpc) { Vector vecDelta; Vector vecPos; Vector vecOrigin = GetAbsOrigin(); if (m_vecPrevOrigin == vec3_origin) { m_vecPrevOrigin = vecOrigin; } vecDelta = vecOrigin - m_vecPrevOrigin; vecDelta.x = clamp( vecDelta.x, -50, 50 ); vecDelta.y = clamp( vecDelta.y, -50, 50 ); vecDelta.z = clamp( vecDelta.z, -50, 50 ); float dt = gpGlobals->curtime - GetLastThink(); bool bSkip = ((GetFlags() & (FL_FLY | FL_SWIM)) != 0) || (GetMoveParent() != NULL) || (GetGroundEntity() == NULL) || (GetGroundEntity()->IsMoving()); bSkip |= myNpc->TaskRanAutomovement() || (myNpc->GetVehicleEntity() != NULL); if (!bSkip) { if (vecDelta.LengthSqr() > m_vecPrevVelocity.LengthSqr()) { float decay = ExponentialDecay( 0.6, 0.1, dt ); m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay); } else { float decay = ExponentialDecay( 0.4, 0.1, dt ); m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay); } vecPos = m_vecPrevOrigin + m_vecPrevVelocity; float decay = ExponentialDecay( 0.5, 0.1, dt ); m_vecShift = m_vecShift * (decay) + (vecOrigin - vecPos) * (1.f - decay); // FIXME: Scale this m_vecLean = (vecOrigin - vecPos) * 1.0; // FIXME: Scale this } else { m_vecPrevVelocity = vecDelta; float decay = ExponentialDecay( 0.5, 0.1, dt ); m_vecShift = m_vecLean * decay; m_vecLean = m_vecShift * decay; } m_vecPrevOrigin = vecOrigin; /* DevMsg( "%.2f %.2f %.2f (%.2f %.2f %.2f)\n", m_vecLean.Get().x, m_vecLean.Get().y, m_vecLean.Get().z, vecDelta.x, vecDelta.y, vecDelta.z ); */ } }
int CFuncShootBoost::OnTakeDamage(const CTakeDamageInfo &info) { CBaseEntity *pInflictor = info.GetAttacker(); if (pInflictor) { Vector finalVel = m_vPushDir.Normalized() * m_fPushForce; switch (m_iIncrease) { case 0: break; case 1: finalVel += pInflictor->GetAbsVelocity(); break; case 2: if (finalVel.LengthSqr() < pInflictor->GetAbsVelocity().LengthSqr()) finalVel = pInflictor->GetAbsVelocity(); break; case 3: // The description of this method says the player velocity is increaed by final velocity, // but we're just adding one vec to the other, which is not quite the same if (finalVel.LengthSqr() < pInflictor->GetAbsVelocity().LengthSqr()) finalVel += pInflictor->GetAbsVelocity(); break; case 4: pInflictor->SetBaseVelocity(finalVel); break; default: DevWarning("CFuncShootBoost:: %i not recognised as valid for m_iIncrease", m_iIncrease); break; } if (m_Destination) { if (((CBaseTrigger *) m_Destination)->IsTouching(pInflictor)) { pInflictor->SetAbsVelocity(finalVel); } } else { pInflictor->SetAbsVelocity(finalVel); } } // As we don't want to break it, we don't call BaseClass::OnTakeDamage(info); // OnTakeDamage returns the damage dealt return info.GetDamage(); }
float DistToSqr(const Vector &vOther) const { Vector delta; delta.x = x - vOther.x; delta.y = y - vOther.y; delta.z = z - vOther.z; return delta.LengthSqr(); }
//----------------------------------------------------------------------------- // Purpose: If we are shot after being stuck to the world, move a bit //----------------------------------------------------------------------------- int CTFGrenadePipebombProjectile::OnTakeDamage( const CTakeDamageInfo &info ) { if ( !info.GetAttacker() ) { Assert( !info.GetAttacker() ); return 0; } bool bSameTeam = ( info.GetAttacker()->GetTeamNumber() == GetTeamNumber() ); if ( m_bTouched && ( info.GetDamageType() & (DMG_BULLET|DMG_BUCKSHOT|DMG_BLAST) ) && bSameTeam == false ) { Vector vecForce = info.GetDamageForce(); if ( info.GetDamageType() & DMG_BULLET ) { vecForce *= tf_grenade_forcefrom_bullet.GetFloat(); } else if ( info.GetDamageType() & DMG_BUCKSHOT ) { vecForce *= tf_grenade_forcefrom_buckshot.GetFloat(); } else if ( info.GetDamageType() & DMG_BLAST ) { vecForce *= tf_grenade_forcefrom_blast.GetFloat(); } // If the force is sufficient, detach & move the pipebomb float flForce = tf_pipebomb_force_to_move.GetFloat(); if ( vecForce.LengthSqr() > (flForce*flForce) ) { if ( VPhysicsGetObject() ) { VPhysicsGetObject()->EnableMotion( true ); } CTakeDamageInfo newInfo = info; newInfo.SetDamageForce( vecForce ); VPhysicsTakeDamage( newInfo ); // The pipebomb will re-stick to the ground after this time expires m_flMinSleepTime = gpGlobals->curtime + tf_grenade_force_sleeptime.GetFloat(); m_bTouched = false; // It has moved the data is no longer valid. m_bUseImpactNormal = false; m_vecImpactNormal.Init(); return 1; } } return 0; }
//----------------------------------------------------------------------------- // System to update prop opacity //----------------------------------------------------------------------------- void CStaticPropMgr::ComputePropOpacity( const Vector &viewOrigin ) { // We need to recompute translucency information for all static props int i; #ifndef SWDS for (i = m_StaticPropDict.Size(); --i >= 0; ) { if (modelinfoclient->ModelHasMaterialProxy( m_StaticPropDict[i].m_pModel )) { modelinfoclient->RecomputeTranslucency( m_StaticPropDict[i].m_pModel ); } } #endif // Distance-based fading. // Step over the list of all things that want to be faded out and recompute alpha // Not sure if this is a fast enough way of doing it // but it's easy for now; we'll have to test later how large this list gets. // If it's <100 or so, we should be fine Vector v; for ( i = m_StaticPropFade.Count(); --i >= 0; ) { StaticPropFade_t& fade = m_StaticPropFade[i]; CStaticProp& prop = m_StaticProps[fade.m_Model]; // Calculate distance (badly) VectorSubtract( prop.GetRenderOrigin(), viewOrigin, v ); #ifndef SWDS ClientRenderHandle_t renderHandle = prop.GetRenderHandle(); float sqDist = v.LengthSqr(); if ( sqDist < fade.m_MaxDistSq ) { if ((fade.m_MinDistSq >= 0) && (sqDist > fade.m_MinDistSq)) { clientleafsystem->ChangeRenderableRenderGroup( renderHandle, RENDER_GROUP_TRANSLUCENT_ENTITY ); prop.SetAlpha( fade.m_FalloffFactor * (fade.m_MaxDistSq - sqDist) ); } else { // We can stick the prop into the opaque list clientleafsystem->ChangeRenderableRenderGroup( renderHandle, RENDER_GROUP_OPAQUE_ENTITY ); prop.SetAlpha( 255 ); } } else { // We can stick the prop into the opaque list now; we're not drawing it! clientleafsystem->ChangeRenderableRenderGroup( renderHandle, RENDER_GROUP_OPAQUE_ENTITY ); prop.SetAlpha( 0 ); } #endif } }
void Matrix4x4::SetReflection(const Vector& vecPlane) { // Normalize beforehand or use ::SetReflection() TAssert(fabs(vecPlane.LengthSqr() - 1) < 0.000001f); m[0][0] = 1 - 2 * vecPlane.x * vecPlane.x; m[1][1] = 1 - 2 * vecPlane.y * vecPlane.y; m[2][2] = 1 - 2 * vecPlane.z * vecPlane.z; m[1][0] = m[0][1] = -2 * vecPlane.x * vecPlane.y; m[2][0] = m[0][2] = -2 * vecPlane.x * vecPlane.z; m[1][2] = m[2][1] = -2 * vecPlane.y * vecPlane.z; }
// In order to do rendering we have to transform our global coordinates to be // in the local space of the camera, with the specific requirement that the // camera looks down the -Z axis. In this function we construct a matrix for // this transformation. http://youtu.be/3ZmqJb7J5wE Matrix4x4 Matrix4x4::ConstructCameraView(const Vector& vecPosition, const Vector& vecDirection, const Vector& vecUp) { TAssert(fabs(vecDirection.LengthSqr()-1) < 0.0001f); Vector vecCamRight = CrossProduct(vecDirection, vecUp).Normalized(); Vector vecCamUp = CrossProduct(vecCamRight, vecDirection); // OpenGL wants to be looking down the -Z axis. So, pass -vecDirection into the Z position. // Then invert the matrix because we're going from global space into local camera space. // Easy! return Matrix4x4(vecCamRight, vecCamUp, -vecDirection, vecPosition).InvertedTR(); }
void CNPC_Stalker::AddZigZagToPath(void) { // If already on a detour don't add a zigzag if (GetNavigator()->GetCurWaypointFlags() & bits_WP_TO_DETOUR) { return; } // If enemy isn't facing me or occluded, don't add a zigzag if (HasCondition(COND_ENEMY_OCCLUDED) || !HasCondition ( COND_ENEMY_FACING_ME )) { return; } Vector waypointPos = GetNavigator()->GetCurWaypointPos(); Vector waypointDir = (waypointPos - GetAbsOrigin()); // If the distance to the next node is greater than ZIG_ZAG_SIZE // then add a random zig/zag to the path if (waypointDir.LengthSqr() > ZIG_ZAG_SIZE) { // Pick a random distance for the zigzag (less that sqrt(ZIG_ZAG_SIZE) float distance = random->RandomFloat( 30, 60 ); // Get me a vector orthogonal to the direction of motion VectorNormalize( waypointDir ); Vector vDirUp(0,0,1); Vector vDir; CrossProduct( waypointDir, vDirUp, vDir); // Pick a random direction (left/right) for the zigzag if (random->RandomInt(0,1)) { vDir = -1 * vDir; } // Get zigzag position in direction of target waypoint Vector zigZagPos = GetAbsOrigin() + waypointDir * 60; // Now offset zigZagPos = zigZagPos + (vDir * distance); // Now make sure that we can still get to the zigzag position and the waypoint AIMoveTrace_t moveTrace1, moveTrace2; GetMoveProbe()->MoveLimit( NAV_GROUND, GetAbsOrigin(), zigZagPos, GetAITraceMask(), NULL, &moveTrace1); GetMoveProbe()->MoveLimit( NAV_GROUND, zigZagPos, waypointPos, GetAITraceMask(), NULL, &moveTrace2); if ( !IsMoveBlocked( moveTrace1 ) && !IsMoveBlocked( moveTrace2 ) ) { GetNavigator()->PrependWaypoint( zigZagPos, NAV_GROUND, bits_WP_TO_DETOUR ); } } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CMapData_Server::GetMapBounds( Vector &vecMins, Vector &vecMaxs ) { CWorld *pWorld = static_cast<CWorld*>( GetWorldEntity() ); if ( pWorld ) { // Get the world bounds. pWorld->GetWorldBounds( vecMins, vecMaxs ); // Backward compatability... if ( ( vecMins.LengthSqr() == 0.0f ) && ( vecMaxs.LengthSqr() == 0.0f ) ) { vecMins.Init( -6500.0f, -6500.0f, -6500.0f ); vecMaxs.Init( 6500.0f, 6500.0f, 6500.0f ); } } else { Assert( 0 ); vecMins.Init( 0.0f, 0.0f, 0.0f ); vecMaxs.Init( 1.0f, 1.0f, 1.0f ); } }
//------------------------------------------------------------------------------ // Purpose: //------------------------------------------------------------------------------ bool CAI_ASW_RangedAttackBehavior::FindFiringLocation( ) { CBaseEntity *pBestEnt = NULL; float flBestDistSq = FLT_MAX; AIEnemiesIter_t iter; CBaseEntity *pEnemy; pEnemy = GetEnemy(); if ( pEnemy && pEnemy->IsAlive() && GetOuter()->FVisible( pEnemy ) ) { m_hTarget = pEnemy; UpdateTargetLocation(); return true; } for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) ) { pEnemy = pEMemory->hEnemy; if ( !pEnemy || !pEnemy->IsAlive() || !GetOuter()->FVisible( pEnemy ) ) { continue; } Vector vDelta = GetAbsOrigin() - pEnemy->GetAbsOrigin(); float flLenSq = vDelta.LengthSqr(); if ( flLenSq <= flBestDistSq ) { pBestEnt = pEnemy; flBestDistSq = flLenSq; } } if ( !pBestEnt ) { // just try shooting at our enemy for now if ( pEnemy && pEnemy->IsAlive() ) { UpdateTargetLocation(); return true; } return false; } m_hTarget = pBestEnt; GetOuter()->SetEnemy( pBestEnt ); UpdateTargetLocation(); return true; }
//----------------------------------------------------------------------------- // Builds a rotation matrix that rotates one direction vector into another //----------------------------------------------------------------------------- void MatrixBuildRotation( VMatrix &dst, const Vector& initialDirection, const Vector& finalDirection ) { float angle = DotProduct( initialDirection, finalDirection ); assert( IsFinite(angle) ); Vector axis; // No rotation required if (angle - 1.0 > -1e-3) { // parallel case MatrixSetIdentity(dst); return; } else if (angle + 1.0 < 1e-3) { // antiparallel case, pick any axis in the plane // perpendicular to the final direction. Choose the direction (x,y,z) // which has the minimum component of the final direction, use that // as an initial guess, then subtract out the component which is // parallel to the final direction int idx = 0; if (FloatMakePositive(finalDirection[1]) < FloatMakePositive(finalDirection[idx])) idx = 1; if (FloatMakePositive(finalDirection[2]) < FloatMakePositive(finalDirection[idx])) idx = 2; axis.Init( 0, 0, 0 ); axis[idx] = 1.0f; VectorMA( axis, -DotProduct( axis, finalDirection ), finalDirection, axis ); VectorNormalize(axis); angle = 180.0f; } else { CrossProduct( initialDirection, finalDirection, axis ); VectorNormalize( axis ); angle = acos(angle) * 180 / M_PI; } MatrixBuildRotationAboutAxis( dst, axis, angle ); #ifdef _DEBUG Vector test; Vector3DMultiply( dst, initialDirection, test ); test -= finalDirection; assert( test.LengthSqr() < 1e-3 ); #endif }
//----------------------------------------------------------------------------- // Purpose: The turret doesn't run base AI properly, which is a bad decision. // As a result, it has to manually find enemies. //----------------------------------------------------------------------------- void CNPC_Portal_FloorTurret::HackFindEnemy( void ) { // We have to refresh our memories before finding enemies, so // dead enemies are cleared out before new ones are added. GetEnemies()->RefreshMemories(); GetSenses()->Look( PORTAL_FLOOR_TURRET_RANGE ); SetEnemy( BestEnemy() ); if ( GetEnemy() == NULL ) { // Look through the list of sensed objects for possible targets AISightIter_t iter; CBaseEntity *pObject; CBaseEntity *pNearest = NULL; float flClosestDistSqr = PORTAL_FLOOR_TURRET_RANGE * PORTAL_FLOOR_TURRET_RANGE; for ( pObject = GetSenses()->GetFirstSeenEntity( &iter, SEEN_MISC ); pObject; pObject = GetSenses()->GetNextSeenEntity( &iter ) ) { Vector vVelocity; pObject->GetVelocity( &vVelocity ); // Ignore objects going too slowly if ( vVelocity.LengthSqr() < m_fMovingTargetThreashold ) continue; float flDistSqr = pObject->WorldSpaceCenter().DistToSqr( GetAbsOrigin() ); if ( flDistSqr < flClosestDistSqr ) { flClosestDistSqr = flDistSqr; pNearest = pObject; } } if ( pNearest ) { SetEnemy( pNearest ); m_fMovingTargetThreashold += gpGlobals->curtime * 15.0f; if ( m_fMovingTargetThreashold > 800.0f ) { m_fMovingTargetThreashold = 800.0f; } } } else { m_fMovingTargetThreashold = 20.0f; } }
// Actual work code IterationRetval_t CPlayerAndObjectEnumerator::EnumElement( IHandleEntity *pHandleEntity ) { if ( !m_pLocal ) return ITERATION_STOP; C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() ); if ( pEnt == NULL ) return ITERATION_CONTINUE; if ( pEnt == m_pLocal ) return ITERATION_CONTINUE; if ( !pEnt->IsPlayer() && !pEnt->IsNPC() ) { return ITERATION_CONTINUE; } if ( pEnt->IsNPC() ) { C_AI_BaseNPC *pNPC = (C_AI_BaseNPC *)pEnt; if ( !pNPC->ShouldAvoidObstacle() ) return ITERATION_CONTINUE; } // Ignore vehicles, since they have vcollide collisions that's push me away if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_VEHICLE ) return ITERATION_CONTINUE; #ifdef INVASION_CLIENT_DLL // If it's solid to player movement, don't steer around it since we'll just bump into it if ( pEnt->GetCollisionGroup() == TFCOLLISION_GROUP_OBJECT_SOLIDTOPLAYERMOVEMENT ) return ITERATION_CONTINUE; #endif Vector deltaPos = pEnt->GetAbsOrigin() - m_pLocal->GetAbsOrigin(); if ( deltaPos.LengthSqr() > m_flRadiusSquared ) return ITERATION_CONTINUE; CHandle< C_BaseEntity > h; h = pEnt; m_Objects.AddToTail( h ); return ITERATION_CONTINUE; }
//----------------------------------------------------------------------------- // Primary gun //----------------------------------------------------------------------------- void CPropAPC::AimPrimaryWeapon( const Vector &vecWorldTarget ) { EntityMatrix parentMatrix; parentMatrix.InitFromEntity( this, m_nMachineGunBaseAttachment ); Vector target = parentMatrix.WorldToLocal( vecWorldTarget ); float quadTarget = target.LengthSqr(); float quadTargetXY = target.x*target.x + target.y*target.y; // Target is too close! Can't aim at it if ( quadTarget > m_vecBarrelPos.LengthSqr() ) { // We're trying to aim the offset barrel at an arbitrary point. // To calculate this, I think of the target as being on a sphere with // it's center at the origin of the gun. // The rotation we need is the opposite of the rotation that moves the target // along the surface of that sphere to intersect with the gun's shooting direction // To calculate that rotation, we simply calculate the intersection of the ray // coming out of the barrel with the target sphere (that's the new target position) // and use atan2() to get angles // angles from target pos to center float targetToCenterYaw = atan2( target.y, target.x ); float centerToGunYaw = atan2( m_vecBarrelPos.y, sqrt( quadTarget - (m_vecBarrelPos.y*m_vecBarrelPos.y) ) ); float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) ); float centerToGunPitch = atan2( -m_vecBarrelPos.z, sqrt( quadTarget - (m_vecBarrelPos.z*m_vecBarrelPos.z) ) ); QAngle angles; angles.Init( -RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw + centerToGunYaw ), 0 ); SetPoseParameter( "vehicle_weapon_yaw", angles.y ); SetPoseParameter( "vehicle_weapon_pitch", angles.x ); StudioFrameAdvance(); float curPitch = GetPoseParameter( "vehicle_weapon_pitch" ); float curYaw = GetPoseParameter( "vehicle_weapon_yaw" ); m_bInFiringCone = (fabs(curPitch - angles.x) < 1e-3) && (fabs(curYaw - angles.y) < 1e-3); } else { m_bInFiringCone = false; } }
Matrix4x4 Matrix4x4::ConstructCameraView(const Vector& vecPosition, const Vector& vecDirection, const Vector& vecUp) { Matrix4x4 m; m.Identity(); TAssertNoMsg(fabs(vecDirection.LengthSqr()-1) < 0.0001f); Vector vecCamSide = vecDirection.Cross(vecUp).Normalized(); Vector vecCamUp = vecCamSide.Cross(vecDirection); m.SetForwardVector(Vector(vecCamSide.x, vecCamUp.x, -vecDirection.x)); m.SetLeftVector(Vector(vecCamSide.y, vecCamUp.y, -vecDirection.y)); m.SetUpVector(Vector(vecCamSide.z, vecCamUp.z, -vecDirection.z)); m.AddTranslation(-vecPosition); return m; }
// Actual work code IterationRetval_t CPlayerAndObjectEnumerator::EnumElement( IHandleEntity *pHandleEntity ) { if ( !m_pLocal ) return ITERATION_STOP; C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() ); if ( pEnt == NULL ) return ITERATION_CONTINUE; if ( pEnt == m_pLocal ) return ITERATION_CONTINUE; if ( !pEnt->IsPlayer() && !pEnt->IsNPC() ) { return ITERATION_CONTINUE; } if ( pEnt->IsNPC() ) { C_AI_BaseNPC *pNPC = (C_AI_BaseNPC *)pEnt; if ( !pNPC->ShouldAvoidObstacle() ) return ITERATION_CONTINUE; } // Ignore vehicles, since they have vcollide collisions that's push me away if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_VEHICLE ) return ITERATION_CONTINUE; Vector deltaPos = pEnt->GetAbsOrigin() - m_pLocal->GetAbsOrigin(); if ( deltaPos.LengthSqr() > m_flRadiusSquared ) return ITERATION_CONTINUE; CHandle< C_BaseEntity > h; h = pEnt; m_Objects.AddToTail( h ); return ITERATION_CONTINUE; }
void CPlayerController::Update( const Vector& position, const Vector& velocity, bool onground, IPhysicsObject *ground ) { IVP_U_Point targetPositionIVP; IVP_U_Float_Point targetSpeedIVP; ConvertPositionToIVP( position, targetPositionIVP ); ConvertPositionToIVP( velocity, targetSpeedIVP ); // if the object hasn't moved, abort if ( targetSpeedIVP.quad_distance_to( &m_currentSpeed ) < 1e-6 ) { if ( targetPositionIVP.quad_distance_to( &m_targetPosition ) < 1e-6 ) { return; } } m_targetPosition = targetPositionIVP; m_currentSpeed = targetSpeedIVP; IVP_Real_Object *pivp = m_pObject->GetObject(); IVP_Core *pCore = pivp->get_core(); IVP_Environment *pEnv = pivp->get_environment(); pEnv->get_controller_manager()->ensure_core_in_simulation(pCore); m_enable = true; // m_onground makes this object anti-grav // UNDONE: Re-evaluate this m_onground = false;//onground; if ( velocity.LengthSqr() <= 0.1f ) { // no input velocity, just go where physics takes you. m_enable = false; ground = NULL; } else { MaxSpeed( velocity ); } }
void CLightingManager::CullLights() { Assert( m_hRenderLights.Count() == 0 ); FOR_EACH_VEC_FAST( def_light_t*, m_hDeferredLights, l ) { if ( !m_bDrawWorldLights && l->bWorldLight ) continue; if ( !render->AreAnyLeavesVisible( l->iLeaveIDs, l->iNumLeaves ) ) continue; // if the optimized bounds cause popping for you, use the naive ones or // ...improve the optimization code //if( !engine->IsBoxInViewCluster( l->bounds_min_naive, l->bounds_max_naive ) ) // continue; if ( engine->CullBox( l->bounds_min_naive, l->bounds_max_naive ) ) //if ( engine->CullBox( l->bounds_min, l->bounds_max ) ) continue; if ( l->IsSpot() && l->HasShadow() ) { if ( IntersectFrustumWithFrustum( m_matScreenToWorld, l->spotMVPInv ) ) continue; } Vector veclightDelta = l->boundsCenter - m_vecViewOrigin; if ( veclightDelta.LengthSqr() > l->flMaxDistSqr ) continue; l->flDistance_ViewOrigin = veclightDelta.Length(); l->flShadowFade = l->HasShadow() ? ( SATURATE( ( l->flDistance_ViewOrigin - l->iShadow_Dist ) / l->iShadow_Range ) ) : 1.0f; m_hRenderLights.AddToTail( l ); } FOR_EACH_VEC_FAST_END }
void C_SkeletonPlayer::UpdateClientSideAnimation() { int curSeq = GetSequence(); Vector vel = GetLocalVelocity(); //EstimateAbsVelocity( vel ); int goalSeq = curSeq; if ( vel.LengthSqr() > 4 ) { QAngle velAng; VectorAngles( vel, velAng ); goalSeq = SelectWeightedSequence( ACT_RUN ); float speed = vel.Length2D(); float yaw = AngleNormalize( -(GetRenderAngles().y - velAng.y) ); float seqspeed = 150.0f; float rate = speed / seqspeed; SetPoseParameter( LookupPoseParameter( "move_x" ), cos( DEG2RAD( yaw ) ) * rate ); SetPoseParameter( LookupPoseParameter( "move_y" ), -sin( DEG2RAD( yaw ) ) * rate ); SetPlaybackRate( clamp( rate * 0.6f, 1, 1.5f ) ); } else goalSeq = SelectWeightedSequence( ACT_IDLE ); if ( curSeq != goalSeq ) { ResetSequence( goalSeq ); } //m_flAnimTime = gpGlobals->curtime; //StudioFrameAdvance(); if ( GetCycle() >= 1.0f ) SetCycle( GetCycle() - 1.0f ); }
void CBaseRopePhysics::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes ) { // Handle springs.. // // Iterate multiple times here. If we don't, then gravity tends to // win over the constraint solver and it's impossible to get straight ropes. static int nIterations = 3; for( int iIteration=0; iIteration < nIterations; iIteration++ ) { for( int i=0; i < NumSprings(); i++ ) { CRopeSpring *s = &m_pSprings[i]; Vector vTo = *s->m_pNode1 - *s->m_pNode2; float flDistSqr = vTo.LengthSqr(); // If we don't have an overall spring distance, see if we have a per-node one float flSpringDist = m_flSpringDistSqr; if ( !flSpringDist ) { // TODO: This still isn't enough. Ropes with different spring lengths // per-node will oscillate forever. flSpringDist = m_flNodeSpringDistsSqr[i]; } if( flDistSqr > flSpringDist ) { float flDist = (float)sqrt( flDistSqr ); vTo *= 1 - (m_flSpringDist / flDist); *s->m_pNode1 -= vTo * 0.5f; *s->m_pNode2 += vTo * 0.5f; } } if( m_pDelegate ) m_pDelegate->ApplyConstraints( pNodes, nNodes ); } }
bool CColorPicker::Update(int x, int y) { if (x > BarX() && y > BarY() && x < BarX() + BarW() && y < BarY() + BarH()) { m_flLightness = RemapVal((float)y, BarY(), BarY() + BarH(), 1, 0); m_clrRGB.SetHSL(m_flHue, m_flSaturation, m_flLightness); m_hValue->SetText(sprintf("%i %i %i", m_clrRGB.r(), m_clrRGB.g(), m_clrRGB.b())); if (m_pfnChangedCallback) m_pfnChangedCallback(m_pChangedListener, sprintf("%f %f %f", GetColorVector().x, GetColorVector().y, GetColorVector().z)); return true; } float flRadius = CircleW()/2; float flRadiusSqr = flRadius*flRadius; Vector vecCenter(CircleX() + flRadius, CircleY() + flRadius, 0); Vector vecFromCenter = Vector((float)x, (float)y, 0) - vecCenter; float flDistanceSqr = vecFromCenter.LengthSqr(); if (flDistanceSqr > flRadiusSqr) return false; float flTan = atan2(vecFromCenter.y, -vecFromCenter.x); m_flHue = RemapVal(flTan, (float)-M_PI, (float)M_PI, 0.0f, 360.0f); m_flSaturation = sqrt(flDistanceSqr)/flRadius; m_clrRGB.SetHSL(m_flHue, m_flSaturation, m_flLightness); m_hValue->SetText(sprintf("%i %i %i", m_clrRGB.r(), m_clrRGB.g(), m_clrRGB.b())); if (m_pfnChangedCallback) m_pfnChangedCallback(m_pChangedListener, sprintf("%f %f %f", GetColorVector().x, GetColorVector().y, GetColorVector().z)); return true; }
void CCharacterController::PlayerWalk(btCollisionWorld* pCollisionWorld, btScalar dt) { Vector vecCurrentVelocity = m_hEntity->GetLocalVelocity(); vecCurrentVelocity.z = 0; // Calculate friction first, so that the player's movement commands can overwhelm it. if (vecCurrentVelocity.Length2DSqr() > 0.00001f) { if (m_hEntity->GetGroundEntity()) { float flSpeed2D = vecCurrentVelocity.Length2D(); float flFriction = sv_friction.GetFloat() * flSpeed2D * dt; float flNewSpeed = flSpeed2D - flFriction; if (flNewSpeed < 0) flNewSpeed = 0; float flScale = flNewSpeed / flSpeed2D; vecCurrentVelocity *= flScale; m_hEntity->SetLocalVelocity(vecCurrentVelocity); } } // Calculate a new velocity using the player's desired direction of travel. btVector3 vecWishDirection = m_vecMoveVelocity; vecWishDirection.setZ(0); float flWishVelocity = m_vecMoveVelocity.length(); if (flWishVelocity) vecWishDirection = vecWishDirection / flWishVelocity; else vecWishDirection = btVector3(0, 0, 0); if (flWishVelocity > m_hEntity->CharacterSpeed()) flWishVelocity = m_hEntity->CharacterSpeed(); float flVelocityInWishDirection = GetVelocity().dot(vecWishDirection); float flDirectionChange = flWishVelocity - flVelocityInWishDirection; if (flDirectionChange > 0) { float flAccelerationAmount = flWishVelocity * m_hEntity->CharacterAcceleration() * dt; if (flAccelerationAmount > flDirectionChange) flAccelerationAmount = flDirectionChange; vecCurrentVelocity = vecCurrentVelocity + ToTVector(vecWishDirection) * flAccelerationAmount; TAssert(vecCurrentVelocity.z == 0); } float flCurrentVelocity = vecCurrentVelocity.Length(); if (flCurrentVelocity > m_hEntity->CharacterSpeed()) vecCurrentVelocity *= m_hEntity->CharacterSpeed()/flCurrentVelocity; if (vecCurrentVelocity.LengthSqr() < 0.001f) { m_hEntity->SetLocalVelocity(Vector()); return; } btTransform mWorld = m_pGhostObject->getWorldTransform(); // Try moving the player directly, if it's possible. { btVector3 vecTargetPosition = mWorld.getOrigin() + ToBTVector(vecCurrentVelocity) * dt; CTraceResult tr; PlayerTrace(pCollisionWorld, mWorld.getOrigin(), vecTargetPosition, tr); if (tr.m_flFraction == 1) { mWorld.setOrigin(vecTargetPosition); m_pGhostObject->setWorldTransform(mWorld); m_hEntity->SetLocalVelocity(vecCurrentVelocity); return; } } // There was something blocking the way. Try walking up a step or along walls. btVector3 vecSavedStepUp(0, 0, 0); { // Move up a bit to try to clear a step. btVector3 vecStartPosition = m_pGhostObject->getWorldTransform().getOrigin(); btVector3 vecTargetPosition = m_pGhostObject->getWorldTransform().getOrigin() + GetUpVector() * m_flStepHeight; CTraceResult tr; PlayerTrace(pCollisionWorld, vecStartPosition, vecTargetPosition, tr); if (tr.m_flFraction < 1) { // we moved up only a fraction of the step height btVector3 vecInterpolated; vecInterpolated.setInterpolate3(m_pGhostObject->getWorldTransform().getOrigin(), vecTargetPosition, tr.m_flFraction); m_pGhostObject->getWorldTransform().setOrigin(vecInterpolated); vecSavedStepUp = vecInterpolated - vecStartPosition; } else { vecSavedStepUp = vecTargetPosition - vecStartPosition; m_pGhostObject->getWorldTransform().setOrigin(vecTargetPosition); } } StepForwardAndStrafe(pCollisionWorld, ToBTVector(vecCurrentVelocity) * dt); if (vecSavedStepUp.length2() > 0) { // Move back down as much as we moved up. btVector3 vecStartPosition = m_pGhostObject->getWorldTransform().getOrigin(); btVector3 vecTargetPosition = m_pGhostObject->getWorldTransform().getOrigin() - vecSavedStepUp; CTraceResult tr; PlayerTrace(pCollisionWorld, vecStartPosition, vecTargetPosition, tr); if (tr.m_flFraction < 1) { btVector3 vecInterpolated; vecInterpolated.setInterpolate3(m_pGhostObject->getWorldTransform().getOrigin(), vecTargetPosition, tr.m_flFraction); m_pGhostObject->getWorldTransform().setOrigin(vecInterpolated); } else m_pGhostObject->getWorldTransform().setOrigin(vecTargetPosition); } }