//-----------------------------------------------------------------------------
// Purpose: Check to see if we should teleport to the current path corner
//-----------------------------------------------------------------------------
void CNPC_VehicleDriver::CheckForTeleport( void )
{
	if ( !GetGoalEnt() )
		return;

	CPathTrack *pTrack = dynamic_cast<CPathTrack *>( GetGoalEnt() );
	if ( !pTrack )
		return;

	// Does it have the teleport flag set?
	if ( pTrack->HasSpawnFlags( SF_PATH_TELEPORT ) )
	{
		AddEffects( EF_NOINTERP );

		// Teleport the vehicle to the pathcorner
		Vector vecMins, vecMaxs;
		vecMins = m_hVehicleEntity->CollisionProp()->OBBMins();
		vecMaxs = m_hVehicleEntity->CollisionProp()->OBBMaxs();
		Vector vecTarget = pTrack->GetAbsOrigin() - (vecMins + vecMaxs) * 0.5;
		vecTarget.z += ((vecMaxs.z - vecMins.z) * 0.5) + 8;	// Safety buffer

		// Orient it to face the next point
		QAngle vecAngles = pTrack->GetAbsAngles();
		Vector vecToTarget = vec3_origin;
		if ( pTrack->GetNext() )
		{
			vecToTarget = (pTrack->GetNext()->GetAbsOrigin() - pTrack->GetAbsOrigin());
			VectorNormalize( vecToTarget );

			// Vehicles are rotated 90 degrees
			VectorAngles( vecToTarget, vecAngles );
			vecAngles[YAW] -= 90;
		}
		m_hVehicleEntity->Teleport( &vecTarget, &vecAngles, &vec3_origin );

		// Teleport the driver
		SetAbsOrigin( m_hVehicleEntity->WorldSpaceCenter() );
		SetAbsAngles( m_hVehicleEntity->GetAbsAngles() );

		m_vecPrevPoint = pTrack->GetAbsOrigin();

		// Move to the next waypoint, we've reached this one
		if ( GetNavigator()->GetPath() )
		{
			WaypointReached();
		}

		// Clear our waypoints, because the next waypoint is certainly invalid now.
		ClearWaypoints();
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int CNPC_VehicleDriver::SelectSchedule( void )
{
	// Vehicle driver hangs in the air inside the vehicle, so we never need to fall to ground
	ClearCondition( COND_FLOATING_OFF_GROUND );

	if ( HasSpawnFlags(SF_VEHICLEDRIVER_INACTIVE) )
	{
		SetState( NPC_STATE_IDLE );
		return SCHED_VEHICLEDRIVER_INACTIVE;
	}

	if ( GetGoalEnt() )
		return SCHED_VEHICLEDRIVER_DRIVE_PATH;

	switch ( m_NPCState )
	{
	case NPC_STATE_IDLE:
		break;

	case NPC_STATE_ALERT:
		break;

	case NPC_STATE_COMBAT:
		{
			if ( HasCondition(COND_NEW_ENEMY) || HasCondition( COND_ENEMY_DEAD ) )
				return BaseClass::SelectSchedule();

			if ( HasCondition(COND_SEE_ENEMY) )
			{
				// we can see the enemy
				if ( HasCondition(COND_CAN_RANGE_ATTACK2) )
					return SCHED_RANGE_ATTACK2;
				if ( HasCondition(COND_CAN_RANGE_ATTACK1) )
					return SCHED_RANGE_ATTACK1;

				// What to do here? Not necessarily easy to face enemy.
				//if ( HasCondition(COND_NOT_FACING_ATTACK) )
					//return SCHED_COMBAT_FACE;
			}

			// We can see him, but can't shoot him. Just wait and hope he comes closer.
			return SCHED_VEHICLEDRIVER_COMBAT_WAIT;
		}
		break;
	}

	return BaseClass::SelectSchedule();
}
Beispiel #3
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pTask - 
//-----------------------------------------------------------------------------
void CNPC_Crow::StartTask( const Task_t *pTask )
{
	switch ( pTask->iTask )
	{
		//
		// This task enables us to build a path that requires flight.
		//
//		case TASK_CROW_PREPARE_TO_FLY:
//		{
//			SetFlyingState( FlyState_Flying );
//			TaskComplete();
//			break;
//		}

		case TASK_CROW_TAKEOFF:
		{
			if ( random->RandomInt( 1, 4 ) == 1 )
			{
				AlertSound();
			}

			FlapSound();

			SetIdealActivity( ( Activity )ACT_CROW_TAKEOFF );
			break;
		}

		case TASK_CROW_PICK_EVADE_GOAL:
		{
			if ( GetEnemy() != NULL )
			{
				//
				// Get our enemy's position in x/y.
				//
				Vector vecEnemyOrigin = GetEnemy()->GetAbsOrigin();
				vecEnemyOrigin.z = GetAbsOrigin().z;

				//
				// Pick a hop goal a random distance along a vector away from our enemy.
				//
				m_vSavePosition = GetAbsOrigin() - vecEnemyOrigin;
				VectorNormalize( m_vSavePosition );
				m_vSavePosition = GetAbsOrigin() + m_vSavePosition * ( 32 + random->RandomInt( 0, 32 ) );

				GetMotor()->SetIdealYawToTarget( m_vSavePosition );
				TaskComplete();
			}
			else
			{
				TaskFail( "No enemy" );
			}
			break;
		}

		case TASK_CROW_FALL_TO_GROUND:
		{
			SetFlyingState( FlyState_Falling );
			break;
		}

		case TASK_FIND_HINTNODE:
		{
			if ( GetGoalEnt() )
			{
				TaskComplete();
				return;
			}
			// Overloaded because we search over a greater distance.
			if ( !GetHintNode() )
			{
				SetHintNode(CAI_HintManager::FindHint( this, HINT_CROW_FLYTO_POINT, bits_HINT_NODE_NEAREST | bits_HINT_NODE_USE_GROUP, 10000 ));
			}

			if ( GetHintNode() )
			{
				TaskComplete();
			}
			else
			{
				TaskFail( FAIL_NO_HINT_NODE );
			}
			break;
		}

		case TASK_GET_PATH_TO_HINTNODE:
		{
			//How did this happen?!
			if ( GetGoalEnt() == this )
			{
				SetGoalEnt( NULL );
			}

			if ( GetGoalEnt() )
			{
				SetFlyingState( FlyState_Flying );
				StartTargetHandling( GetGoalEnt() );
			
				m_bReachedMoveGoal = false;
				TaskComplete();
				SetHintNode( NULL );
				return;
			}

			if ( GetHintNode() )
			{
				Vector vHintPos;
				GetHintNode()->GetPosition(this, &vHintPos);
		
				SetNavType( NAV_FLY );
				CapabilitiesAdd( bits_CAP_MOVE_FLY );
				if ( !GetNavigator()->SetGoal( vHintPos ) )
					SetHintNode(NULL);
				CapabilitiesRemove( bits_CAP_MOVE_FLY );
			}

			if ( GetHintNode() )
			{
				m_bReachedMoveGoal = false;
				TaskComplete();
			}
			else
			{
				TaskFail( FAIL_NO_ROUTE );
			}
			break;
		}

		//
		// We have failed to fly normally. Pick a random "up" direction and fly that way.
		//
		case TASK_CROW_FLY:
		{
			float flYaw = UTIL_AngleMod( random->RandomInt( -180, 180 ) );

			Vector vecNewVelocity( cos( DEG2RAD( flYaw ) ), sin( DEG2RAD( flYaw ) ), random->RandomFloat( 0.1f, 0.5f ) );
			vecNewVelocity *= CROW_AIRSPEED;
			SetAbsVelocity( vecNewVelocity );

			SetIdealActivity( ACT_FLY );

			m_bSoar = false;
			m_flSoarTime = gpGlobals->curtime + random->RandomFloat( 2, 5 );

			break;
		}

		case TASK_CROW_PICK_RANDOM_GOAL:
		{
			m_vSavePosition = GetLocalOrigin() + Vector( random->RandomFloat( -48.0f, 48.0f ), random->RandomFloat( -48.0f, 48.0f ), 0 );
			TaskComplete();
			break;
		}

		case TASK_CROW_HOP:
		{
			SetIdealActivity( ACT_HOP );
			m_flHopStartZ = GetLocalOrigin().z;
			break;
		}

		case TASK_CROW_WAIT_FOR_BARNACLE_KILL:
		{
			break;
		}

		default:
		{
			BaseClass::StartTask( pTask );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pTask - 
//-----------------------------------------------------------------------------
void CNPC_VehicleDriver::StartTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_RUN_PATH:
	case TASK_WALK_PATH:
		TaskComplete();
		break;

	case TASK_FACE_IDEAL:
	case TASK_FACE_ENEMY:
		{
			// Vehicle ignores face commands, since it can't rotate on the spot.
			TaskComplete();
		}
		break;

	case TASK_VEHICLEDRIVER_GET_PATH:
		{
			if ( !GetGoalEnt() )
			{
				TaskFail( FAIL_NO_TARGET );
				return;
			}

			CheckForTeleport();

			if ( g_debug_vehicledriver.GetInt() & DRIVER_DEBUG_PATH )
			{
				NDebugOverlay::Box( GetGoalEnt()->GetAbsOrigin(), -Vector(50,50,50), Vector(50,50,50), 255,255,255, true, 5);
			}

	  		AI_NavGoal_t goal( GOALTYPE_PATHCORNER, GetGoalEnt()->GetLocalOrigin(), ACT_WALK, AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST);
  			if ( !GetNavigator()->SetGoal( goal ) )
   			{
				TaskFail( FAIL_NO_ROUTE );
				return;
   			}

			TaskComplete();
		}
		break;

	case TASK_WAIT_FOR_MOVEMENT:
		{
			if (GetNavigator()->GetGoalType() == GOALTYPE_NONE)
			{
				TaskComplete();
				GetNavigator()->StopMoving();		// Stop moving
			}
			else if (!GetNavigator()->IsGoalActive())
			{
				SetIdealActivity( GetStoppedActivity() );
			}
			else
			{
				// Check validity of goal type
				ValidateNavGoal();
			}
		}
		break;

	default:
		BaseClass::StartTask( pTask );
		break;
	}
}