int CBaseTurret::MoveTurret(void) { bool bDidMove = false; int iPose; matrix3x4_t localToWorld; GetAttachment( LookupAttachment( "eyes" ), localToWorld ); Vector vecGoalDir; AngleVectors( m_vecGoalAngles, &vecGoalDir ); Vector vecGoalLocalDir; VectorIRotate( vecGoalDir, localToWorld, vecGoalLocalDir ); QAngle vecGoalLocalAngles; VectorAngles( vecGoalLocalDir, vecGoalLocalAngles ); float flDiff; QAngle vecNewAngles; // update pitch flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1 * m_iBaseTurnRate ) ); iPose = LookupPoseParameter( TURRET_BC_PITCH ); SetPoseParameter( iPose, GetPoseParameter( iPose ) + flDiff / 1.5 ); if (fabs(flDiff) > 0.1) { bDidMove = true; } // update yaw, with acceleration #if 0 float flDist = AngleNormalize( vecGoalLocalAngles.y ); float flNewDist; float flNewTurnRate; ChangeDistance( 0.1, flDist, 0.0, m_fTurnRate, m_iBaseTurnRate, m_iBaseTurnRate * 4, flNewDist, flNewTurnRate ); m_fTurnRate = flNewTurnRate; flDiff = flDist - flNewDist; #else flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1 * m_iBaseTurnRate ) ); #endif iPose = LookupPoseParameter( TURRET_BC_YAW ); SetPoseParameter( iPose, GetPoseParameter( iPose ) + flDiff / 1.5 ); if (fabs(flDiff) > 0.1) { bDidMove = true; } if (bDidMove) { // DevMsg( "(%.2f, %.2f)\n", AngleNormalize( vecGoalLocalAngles.x ), AngleNormalize( vecGoalLocalAngles.y ) ); } return bDidMove; }
//----------------------------------------------------------------------------- // Purpose: Causes the turret to face its desired angles //----------------------------------------------------------------------------- bool CNPC_CeilingTurret::UpdateFacing( void ) { bool bMoved = false; matrix3x4_t localToWorld; GetAttachment( LookupAttachment( "eyes" ), localToWorld ); Vector vecGoalDir; AngleVectors( m_vecGoalAngles, &vecGoalDir ); Vector vecGoalLocalDir; VectorIRotate( vecGoalDir, localToWorld, vecGoalLocalDir ); if ( g_debug_turret_ceiling.GetBool() ) { Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( "eyes", vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); NDebugOverlay::Cross3D( vecMuzzle+(vecMuzzleDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecMuzzleDir*256), 255, 255, 0, false, 0.05 ); NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); NDebugOverlay::Cross3D( vecMuzzle+(vecGoalDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecGoalDir*256), 255, 0, 0, false, 0.05 ); } QAngle vecGoalLocalAngles; VectorAngles( vecGoalLocalDir, vecGoalLocalAngles ); // Update pitch float flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1f * MaxYawSpeed() ) ); SetPoseParameter( m_poseAim_Pitch, GetPoseParameter( m_poseAim_Pitch ) + ( flDiff / 1.5f ) ); if ( fabs( flDiff ) > 0.1f ) { bMoved = true; } // Update yaw flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1f * MaxYawSpeed() ) ); SetPoseParameter( m_poseAim_Yaw, GetPoseParameter( m_poseAim_Yaw ) + ( flDiff / 1.5f ) ); if ( fabs( flDiff ) > 0.1f ) { bMoved = true; } InvalidateBoneCache(); return bMoved; }
//----------------------------------------------------------------------------- // Purpose: Causes the camera to face its desired angles //----------------------------------------------------------------------------- bool CNPC_CombineCamera::UpdateFacing() { bool bMoved = false; matrix3x4_t localToWorld; GetAttachment(LookupAttachment("eyes"), localToWorld); Vector vecGoalDir; AngleVectors(m_vecGoalAngles, &vecGoalDir ); Vector vecGoalLocalDir; VectorIRotate(vecGoalDir, localToWorld, vecGoalLocalDir); QAngle vecGoalLocalAngles; VectorAngles(vecGoalLocalDir, vecGoalLocalAngles); // Update pitch float flDiff = AngleNormalize(UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1f * MaxYawSpeed())); int iPose = LookupPoseParameter(COMBINE_CAMERA_BC_PITCH); SetPoseParameter(iPose, GetPoseParameter(iPose) + (flDiff / 1.5f)); if (fabs(flDiff) > 0.1f) { bMoved = true; } // Update yaw flDiff = AngleNormalize(UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1f * MaxYawSpeed())); iPose = LookupPoseParameter(COMBINE_CAMERA_BC_YAW); SetPoseParameter(iPose, GetPoseParameter(iPose) + (flDiff / 1.5f)); if (fabs(flDiff) > 0.1f) { bMoved = true; } if (bMoved && (m_flMoveSoundTime < gpGlobals->curtime)) { EmitSound("NPC_CombineCamera.Move"); m_flMoveSoundTime = gpGlobals->curtime + CAMERA_MOVE_INTERVAL; } // You're going to make decisions based on this info. So bump the bone cache after you calculate everything InvalidateBoneCache(); return bMoved; }
void CMGargantua :: FlameControls( float angleX, float angleY ) { if ( angleY < -180 ) angleY += 360; else if ( angleY > 180 ) angleY -= 360; if ( angleY < -45 ) angleY = -45; else if ( angleY > 45 ) angleY = 45; m_flameX = UTIL_ApproachAngle( angleX, m_flameX, 4 ); m_flameY = UTIL_ApproachAngle( angleY, m_flameY, 8 ); SetBoneController( 0, m_flameY ); SetBoneController( 1, m_flameX ); }
void CEnvironment::UpdateWind() { if( m_flNextWindChangeTime <= gEngfuncs.GetClientTime() ) { m_vecDesiredWindDirection.x = UTIL_RandomFloat( -80.0f, 80.0f ); m_vecDesiredWindDirection.y = UTIL_RandomFloat( -80.0f, 80.0f ); m_vecDesiredWindDirection.z = 0; m_flNextWindChangeTime = gEngfuncs.GetClientTime() + UTIL_RandomFloat( 15.0f, 30.0f ); Vector vecDir = m_vecDesiredWindDirection; m_flDesiredWindSpeed = vecDir.NormalizeInPlace(); if( vecDir.x == 0.0f && vecDir.y == 0.0f ) { m_flIdealYaw = 0; } else { m_flIdealYaw = floor( atan2( vecDir.y, vecDir.x ) * ( 180.0 / M_PI ) ); if( m_flIdealYaw < 0.0f ) m_flIdealYaw += 360.0f; } } Vector vecWindDir = m_vecWind; vecWindDir.NormalizeInPlace(); Vector vecAngles; VectorAngles( vecWindDir, vecAngles ); float flYaw; if( vecAngles.y < 0.0f ) { flYaw = 120 * ( 3 * static_cast<int>( floor( vecAngles.y / 360.0 ) ) + 3 ); } else { if( vecAngles.y < 360.0f ) { flYaw = vecAngles.y; } else { flYaw = vecAngles.y - ( 360 * floor( vecAngles.y / 360.0 ) ); } } if( m_flIdealYaw != flYaw ) { const float flSpeed = ( gEngfuncs.GetClientTime() - m_flOldTime ) * 0.5 * 10.0; vecAngles.y = UTIL_ApproachAngle( m_flIdealYaw, flYaw, flSpeed ); } Vector vecNewWind; AngleVectors( vecAngles, &vecNewWind, nullptr, nullptr ); m_vecWind = vecNewWind * m_flDesiredWindSpeed; }
void CIchthyosaur :: RunTask ( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_ICHTHYOSAUR_CIRCLE_ENEMY: if (m_hEnemy == NULL) { TaskComplete( ); } else if (FVisible( m_hEnemy )) { Vector vecFrom = m_hEnemy->EyePosition( ); Vector vecDelta = (pev->origin - vecFrom).Normalize( ); Vector vecSwim = CrossProduct( vecDelta, Vector( 0, 0, 1 ) ).Normalize( ); if (DotProduct( vecSwim, m_SaveVelocity ) < 0) vecSwim = vecSwim * -1.0; Vector vecPos = vecFrom + vecDelta * m_idealDist + vecSwim * 32; // ALERT( at_console, "vecPos %.0f %.0f %.0f\n", vecPos.x, vecPos.y, vecPos.z ); TraceResult tr; UTIL_TraceHull( vecFrom, vecPos, ignore_monsters, large_hull, m_hEnemy->edict(), &tr ); if (tr.flFraction > 0.5) vecPos = tr.vecEndPos; m_SaveVelocity = m_SaveVelocity * 0.8 + 0.2 * (vecPos - pev->origin).Normalize() * m_flightSpeed; // ALERT( at_console, "m_SaveVelocity %.2f %.2f %.2f\n", m_SaveVelocity.x, m_SaveVelocity.y, m_SaveVelocity.z ); if (HasConditions( bits_COND_ENEMY_FACING_ME ) && m_hEnemy->FVisible( this )) { m_flNextAlert -= 0.1; if (m_idealDist < m_flMaxDist) { m_idealDist += 4; } if (m_flightSpeed > m_flMinSpeed) { m_flightSpeed -= 2; } else if (m_flightSpeed < m_flMinSpeed) { m_flightSpeed += 2; } if (m_flMinSpeed < m_flMaxSpeed) { m_flMinSpeed += 0.5; } } else { m_flNextAlert += 0.1; if (m_idealDist > 128) { m_idealDist -= 4; } if (m_flightSpeed < m_flMaxSpeed) { m_flightSpeed += 4; } } // ALERT( at_console, "%.0f\n", m_idealDist ); } else { m_flNextAlert = gpGlobals->time + 0.2; } if (m_flNextAlert < gpGlobals->time) { // ALERT( at_console, "AlertSound()\n"); AlertSound( ); m_flNextAlert = gpGlobals->time + RANDOM_FLOAT( 3, 5 ); } break; case TASK_ICHTHYOSAUR_SWIM: if (m_fSequenceFinished) { TaskComplete( ); } break; case TASK_DIE: if ( m_fSequenceFinished ) { pev->deadflag = DEAD_DEAD; TaskComplete( ); } break; case TASK_ICHTHYOSAUR_FLOAT: pev->angles.x = UTIL_ApproachAngle( 0, pev->angles.x, 20 ); pev->velocity = pev->velocity * 0.8; if (pev->waterlevel > 1 && pev->velocity.z < 64) { pev->velocity.z += 8; } else { pev->velocity.z -= 8; } // ALERT( at_console, "%f\n", pev->velocity.z ); break; default: CFlyingMonster :: RunTask ( pTask ); break; } }
int CAI_BlendedMotor::BuildTurnScript( int i, int j ) { int k; Vector vecDir = m_scriptTurn[j].vecLocation - m_scriptTurn[i].vecLocation; float interiorYaw = UTIL_VecToYaw( vecDir ); float deltaYaw; deltaYaw = fabs( UTIL_AngleDiff( interiorYaw, m_scriptTurn[i].flYaw ) ); float t1 = deltaYaw / YAWSPEED; deltaYaw = fabs( UTIL_AngleDiff( m_scriptTurn[j].flYaw, interiorYaw ) ); float t2 = deltaYaw / YAWSPEED; float totalTime = m_scriptTurn[j].flElapsedTime - m_scriptTurn[i].flElapsedTime; //Assert( totalTime > 0 ); if (t1 < 0.01) { if (t2 > totalTime * 0.8) { // too close, nothing to do return 0; } // go ahead and force yaw m_scriptTurn[i].flYaw = interiorYaw; // we're already aiming close enough to the interior yaw, set the point where we need to blend out k = BuildInsertNode( i, totalTime - t2 ); m_scriptTurn[k].flYaw = interiorYaw; return 1; } else if (t2 < 0.01) { if (t1 > totalTime * 0.8) { // too close, nothing to do return 0; } // we'll finish up aiming close enough to the interior yaw, set the point where we need to blend in k = BuildInsertNode( i, t1 ); m_scriptTurn[k].flYaw = interiorYaw; return 1; } else if (t1 + t2 > totalTime) { // don't bother with interior node return 0; // waypoints need to much turning, ignore interior yaw float a = (t1 / (t1 + t2)); t1 = a * totalTime; k = BuildInsertNode( i, t1 ); deltaYaw = UTIL_AngleDiff( m_scriptTurn[j].flYaw, m_scriptTurn[i].flYaw ); m_scriptTurn[k].flYaw = UTIL_ApproachAngle( m_scriptTurn[j].flYaw, m_scriptTurn[i].flYaw, deltaYaw * (1 - a) ); return 1; } else if (t1 + t2 < totalTime * 0.8) { // turn to face interior, run a ways, then turn away k = BuildInsertNode( i, t1 ); m_scriptTurn[k].flYaw = interiorYaw; k = BuildInsertNode( i, t2 ); m_scriptTurn[k].flYaw = interiorYaw; return 2; } return 0; }
void CAI_BlendedMotor::BuildTurnScript( const AILocalMoveGoal_t &move ) { int i; AI_Movementscript_t script; script.Init(); // current location script.vecLocation = GetAbsOrigin(); script.flYaw = GetAbsAngles().y; m_scriptTurn.AddToTail( script ); //------------------------- // insert default turn parameters, try to turn 80% to goal at all corners before getting there int prev = 0; for (i = 0; i < m_scriptMove.Count(); i++) { AI_Waypoint_t *pCurWaypoint = m_scriptMove[i].pWaypoint; if (pCurWaypoint) { script.Init(); script.vecLocation = pCurWaypoint->vecLocation; script.pWaypoint = pCurWaypoint; script.flElapsedTime = m_scriptMove[i].flElapsedTime; m_scriptTurn[prev].flTime = script.flElapsedTime - m_scriptTurn[prev].flElapsedTime; if (pCurWaypoint->GetNext()) { Vector d1 = pCurWaypoint->GetNext()->vecLocation - script.vecLocation; Vector d2 = script.vecLocation - m_scriptTurn[prev].vecLocation; d1.z = 0; VectorNormalize( d1 ); d2.z = 0; VectorNormalize( d2 ); float y1 = UTIL_VecToYaw( d1 ); float y2 = UTIL_VecToYaw( d2 ); float deltaYaw = fabs( UTIL_AngleDiff( y1, y2 ) ); if (deltaYaw > 0.1) { // turn to 80% of goal script.flYaw = UTIL_ApproachAngle( y1, y2, deltaYaw * 0.8 ); m_scriptTurn.AddToTail( script ); // DevMsg("turn waypoint %.1f %.1f %.1f\n", script.vecLocation.x, script.vecLocation.y, script.vecLocation.z ); prev++; } } else { Vector vecDir = GetNavigator()->GetArrivalDirection(); script.flYaw = UTIL_VecToYaw( vecDir ); m_scriptTurn.AddToTail( script ); // DevMsg("turn waypoint %.1f %.1f %.1f\n", script.vecLocation.x, script.vecLocation.y, script.vecLocation.z ); prev++; } } } // propagate ending facing back over any nearby nodes // FIXME: this needs to minimize total turning, not just local/end turning. // depending on waypoint spacing, complexity, it may turn the wrong way! for (i = m_scriptTurn.Count()-1; i > 1; i--) { float deltaYaw = UTIL_AngleDiff( m_scriptTurn[i-1].flYaw, m_scriptTurn[i].flYaw ); float maxYaw = YAWSPEED * m_scriptTurn[i-1].flTime; if (fabs(deltaYaw) > maxYaw) { m_scriptTurn[i-1].flYaw = UTIL_ApproachAngle( m_scriptTurn[i-1].flYaw, m_scriptTurn[i].flYaw, maxYaw ); } } for (i = 0; i < m_scriptTurn.Count() - 1; ) { i = i + BuildTurnScript( i, i + 1 ) + 1; } //------------------------- }