Ejemplo n.º 1
0
void
AbstractTask::UpdateStatsDistances(const GeoPoint &location,
                                   const bool full_update)
{
  stats.total.remaining.set_distance(ScanDistanceRemaining(location));

  const TaskPoint *active = GetActiveTaskPoint();
  if (active != NULL) {
    stats.current_leg.location_remaining = active->GetLocationRemaining();
    stats.current_leg.vector_remaining = active->GetVectorRemaining(location);
  } else {
    stats.current_leg.location_remaining = GeoPoint::Invalid();
    stats.current_leg.vector_remaining = GeoVector::Invalid();
  }

  if (full_update)
    stats.distance_nominal = ScanDistanceNominal();

  ScanDistanceMinMax(location, full_update,
                       &stats.distance_min, &stats.distance_max);

  stats.total.travelled.set_distance(ScanDistanceTravelled(location));
  stats.total.planned.set_distance(ScanDistancePlanned());

  if (IsScored()) {
    if (!TaskStarted()) 
      stats.distance_scored = fixed_zero;
    else if (!TaskFinished()) 
      stats.distance_scored = ScanDistanceScored(location);
  } else
    stats.distance_scored = fixed_zero;
}
Ejemplo n.º 2
0
AircraftState 
OrderedTask::GetFinishState() const
{
  if (HasFinish() && TaskFinished())
    return taskpoint_finish->GetEnteredState();

  AircraftState null_state;
  return null_state;
}
Ejemplo n.º 3
0
void
AbstractTask::UpdateStatsTimes(const AircraftState &state)
{
  // default for tasks with no start time...
  stats.Time = state.time;
  if (!TaskFinished()) {
    stats.total.SetTimes(ScanTotalStartTime(state), state);
    stats.current_leg.SetTimes(ScanLegStartTime(state),state);
  }
}
Ejemplo n.º 4
0
//----------------------------------------------------------------------------------------------------------------
void CBot_HL2DM::Think()
{
	if ( !m_bAlive )
	{
		m_cCmd.buttons = rand() & IN_ATTACK; // Force bot to respawn by hitting randomly attack button.
		return;
	}

	bool bForceNewTask = false;

	// Check for move failure.
	if ( m_bMoveFailure || m_bStuck )
	{
		if ( iCurrentWaypoint == m_iFailWaypoint )
			m_iFailsCount++;
		else
		{
			m_iFailWaypoint = iCurrentWaypoint;
			m_iFailsCount = 1;
		}
	
		if ( m_iFailsCount >= 3 )
		{
			BotMessage("Failed to follow path on same waypoint %d 3 times, marking task as finished.", iCurrentWaypoint);
			TaskFinished();
			m_bNeedTaskCheck = bForceNewTask = true;
			m_iFailsCount = 0;
			m_iFailWaypoint = -1;
		}
		else if ( m_bMoveFailure )
		{
			// Recalculate the route.
			m_iDestinationWaypoint = m_iTaskDestination;
			m_bNeedMove = m_bUseNavigatorToMove = m_bDestinationChanged = true;
		}		

		m_bMoveFailure = m_bStuck = false;
	}

	// Check if needs to add new tasks. Objectives have more priority than task, but not when bot flees.
	if ( m_bNeedTaskCheck )
	{
		m_bNeedTaskCheck = false;
		if ( bForceNewTask || m_bFlee || (!m_bObjectiveChanged && (m_iObjective == EBotChatUnknown)) )
			CheckNewTasks(bForceNewTask);
	}

	if ( m_bFlee )
		m_bNeedSprint = true; // Force bot to move rapidly. TODO: check if stops.
}
Ejemplo n.º 5
0
void
AbstractTask::UpdateStatsSpeeds(const AircraftState &state, 
                                const AircraftState &state_last)
{
  if (!TaskFinished()) {
    if (TaskStarted()) {
      const fixed dt = state.time - state_last.time;
      stats_computer.total.CalcSpeeds(stats.total, dt);
      stats_computer.current_leg.CalcSpeeds(stats.current_leg, dt);
    } else {
      stats_computer.total.Reset(stats.total);
      stats_computer.current_leg.Reset(stats.current_leg);
    }
  }
}
Ejemplo n.º 6
0
bool 
OrderedTask::CheckTransitions(const AircraftState &state,
                              const AircraftState &state_last)
{
  if (!taskpoint_start)
    return false;

  taskpoint_start->ScanActive(*task_points[active_task_point]);

  if (!state.flying)
    return false;

  const int n_task = task_points.size();

  if (!n_task)
    return false;

  FlatBoundingBox bb_last(task_projection.project(state_last.location),1);
  FlatBoundingBox bb_now(task_projection.project(state.location),1);

  bool last_started = TaskStarted();
  const bool last_finished = TaskFinished();

  const int t_min = max(0, (int)active_task_point - 1);
  const int t_max = min(n_task - 1, (int)active_task_point);
  bool full_update = false;

  for (int i = t_min; i <= t_max; i++) {

    bool transition_enter = false;
    bool transition_exit = false;

    if (i==0) {
      full_update |= CheckTransitionOptionalStart(state, state_last,
                                                  bb_now, bb_last,
                                                  transition_enter,
                                                  transition_exit,
                                                  last_started);
    }

    full_update |= CheckTransitionPoint(*task_points[i],
                                        state, state_last, bb_now, bb_last,
                                        transition_enter, transition_exit,
                                        last_started, i == 0);

    if (i == (int)active_task_point) {
      const bool last_request_armed = task_advance.NeedToArm();

      if (task_advance.CheckReadyToAdvance(*task_points[i], state,
                                           transition_enter,
                                           transition_exit)) {
        task_advance.SetArmed(false);
        
        if (i + 1 < n_task) {
          i++;
          SetActiveTaskPoint(i);
          taskpoint_start->ScanActive(*task_points[active_task_point]);
          
          if (task_events != NULL)
            task_events->ActiveAdvanced(*task_points[i], i);

          // on sector exit, must update samples since start sector
          // exit transition clears samples
          full_update = true;
        }
      } else if (!last_request_armed && task_advance.NeedToArm()) {
        if (task_events != NULL)
          task_events->RequestArm(*task_points[i]);
      }
    }
  }

  taskpoint_start->ScanActive(*task_points[active_task_point]);

  stats.task_finished = TaskFinished();
  stats.task_started = TaskStarted();

  if (stats.task_started)
    taskpoint_finish->set_fai_finish_height(GetStartState().altitude - fixed(1000));

  if (task_events != NULL) {
    if (stats.task_started && !last_started)
      task_events->TaskStart();

    if (stats.task_finished && !last_finished)
      task_events->TaskFinish();
  }

  return full_update;
}
Ejemplo n.º 7
0
//----------------------------------------------------------------------------------------------------------------
void CBot_HL2DM::CheckNewTasks( bool bForceTaskChange )
{
	TBotTaskHL2DM iNewTask = EBotTaskInvalid;
	bool bForce = bForceTaskChange || (m_iCurrentTask == EBotTaskInvalid);

	const CWeapon* pWeapon = m_aWeapons[m_iBestWeapon].GetBaseWeapon();
	TBotIntelligence iWeaponPreference = m_iIntelligence;

	bool bNeedHealth = CMod::HasMapItems(EEntityTypeHealth) && ( m_pPlayerInfo->GetHealth() < CUtil::iPlayerMaxHealth );
	bool bNeedHealthBad = bNeedHealth && ( m_pPlayerInfo->GetHealth() < (CUtil::iPlayerMaxHealth/2) );
	bool bAlmostDead = bNeedHealthBad && ( m_pPlayerInfo->GetHealth() < (CUtil::iPlayerMaxHealth/5) );
	bool bNeedWeapon = CMod::HasMapItems(EEntityTypeWeapon), bNeedAmmo = CMod::HasMapItems(EEntityTypeAmmo);
	
	TWeaponId iWeapon;
	bool bSecondary = false;

	const CEntityClass* pEntityClass = NULL; // Weapon or ammo class to search for.

	if ( bAlmostDead )
	{
		m_bDontAttack = true; // TODO: try to not to pass to zones with enemy.
		m_bFlee = true;
	}

	int retries = 0;

restart_find_task:
	retries++;
	if ( retries == 5 )
	{
		m_bNeedTaskCheck = true;
		DebugAssert(m_iCurrentTask == EBotTaskInvalid);
		BotMessage("%s -> No task, will continue to look for task on new frame.", GetName());
		return;
	}

	if ( bNeedHealthBad ) // Need health pretty much.
	{
		iNewTask = EBotTaskFindHealth;
		bForce = true;
	}
	else if ( bNeedWeapon && (pWeapon->iBotPreference < iWeaponPreference) ) // Need some weapon with higher preference.
	{
		iNewTask = EBotTaskFindWeapon;
	}
	else if ( bNeedAmmo )
	{
		// Need ammunition.
		bool bNeedAmmo0 = (m_aWeapons[m_iBestWeapon].ExtraBullets(0) < pWeapon->iClipSize[0]); // Has less than 1 extra clip.
		bool bNeedAmmo1 = pWeapon->bHasSecondary && !pWeapon->bSecondaryUseSameBullets &&      // Has secondary function, but no secondary bullets.
		                  !m_aWeapons[m_iBestWeapon].HasAmmoInClip(1) && !m_aWeapons[m_iBestWeapon].HasAmmoExtra(1);

		if ( bNeedAmmo0 || bNeedAmmo1 )
		{
			iNewTask = EBotTaskFindAmmo;
			// Prefer search for secondary ammo only if has extra bullets for primary.
			bSecondary = bNeedAmmo1 && (m_aWeapons[m_iBestWeapon].ExtraBullets(0) > 0);
			pEntityClass = pWeapon->aAmmos[bSecondary][ rand() % pWeapon->aAmmos[bSecondary].size() ];
		}
		else if ( bNeedHealth ) // Need health (but has more than 50%).
			iNewTask = EBotTaskFindHealth;
		else if ( CMod::HasMapItems(EEntityTypeArmor) && (m_pPlayerInfo->GetArmorValue() < CUtil::iPlayerMaxArmor) ) // Need armor.
			iNewTask = EBotTaskFindArmor;
		else if ( bNeedWeapon && (pWeapon->iBotPreference < EBotPro) ) // Check if can find a better weapon.
		{
			iNewTask = EBotTaskFindWeapon;
			iWeaponPreference = pWeapon->iBotPreference+1;
		}
		else if ( CMod::HasMapItems(EEntityTypeAmmo) && !m_aWeapons[m_iBestWeapon].FullAmmo(1) ) // Check if weapon needs secondary ammo.
		{
			iNewTask = EBotTaskFindAmmo;
			bSecondary = true;
		}
		else if ( CMod::HasMapItems(EEntityTypeAmmo) && !m_aWeapons[m_iBestWeapon].FullAmmo(0) ) // Check if weapon needs primary ammo.
		{
			iNewTask = EBotTaskFindAmmo;
			bSecondary = false;
		}
		else
			iNewTask = EBotTaskFindEnemy;
	}

	switch(iNewTask)
	{
	case EBotTaskFindWeapon:
		pEntityClass = NULL;

		// Get weapon entity class to search for. Search for better weapons that actually have.
		for ( TBotIntelligence iPreference = iWeaponPreference; iPreference < EBotIntelligenceTotal; ++iPreference )
		{
			iWeapon = CWeapons::GetRandomWeapon(iPreference, m_cSkipWeapons);
			if ( iWeapon != -1 )
			{
				pEntityClass = CWeapons::Get(iWeapon)->pWeaponClass;
				break;
			}
		}
		if ( pEntityClass == NULL )
		{
			// None found, search for worst weapons.
			for ( TBotIntelligence iPreference = iWeaponPreference-1; iPreference >= 0; --iPreference )
			{
				iWeapon = CWeapons::GetRandomWeapon(iPreference, m_cSkipWeapons);
				if ( iWeapon != -1 )
				{
					pEntityClass = CWeapons::Get(iWeapon)->pWeaponClass;
					break;
				}
			}
		}
		if ( pEntityClass == NULL )
		{
			bNeedWeapon = false;
			goto restart_find_task;
		}
		break;

	case EBotTaskFindAmmo:
		// Get ammo entity class to search for.
		iWeapon = m_iBestWeapon;
	
		// Randomly search for weapon instead, as it gives same primary bullets.
		if ( !bSecondary && bNeedWeapon && CItems::ExistsOnMap(pWeapon->pWeaponClass) && (rand() & 1) )
		{
			iNewTask = EBotTaskFindWeapon;
			pEntityClass = pWeapon->pWeaponClass;
		}
		else
		{
			int iIdx = rand() % pWeapon->aAmmos[bSecondary].size();
			pEntityClass = pWeapon->aAmmos[bSecondary][ iIdx ]; // Randomly search for ammo.
		}
		
		if ( !CItems::ExistsOnMap(pEntityClass) ) // There are no such weapon/ammo on the map.
		{
			iNewTask = EBotTaskFindEnemy; // Just find enemy.
			pEntityClass = NULL;
		}
		break;

	case EBotTaskFindHealth:
	case EBotTaskFindArmor:
		pEntityClass = CItems::GetRandomItemClass(EEntityTypeHealth + (iNewTask - EBotTaskFindHealth));
		break;
	}
	
	DebugAssert( iNewTask != EBotTaskInvalid );

	// Check if need task switch.
	if ( bForce || (m_iCurrentTask != iNewTask) )
	{
		m_iCurrentTask = iNewTask;
		if ( pEntityClass ) // Health, armor, weapon, ammo.
		{
			TEntityType iType = EEntityTypeHealth + (iNewTask - EBotTaskFindHealth);
			TEntityIndex iItemToSearch = CItems::GetNearestItem( iType, GetHead(), m_aPickedItems, pEntityClass );

			if ( iItemToSearch == -1 )
			{
				m_cSkipWeapons.set(iWeapon);
				m_iCurrentTask = EBotTaskInvalid;
				goto restart_find_task;
			}
			else
			{
				m_iTaskDestination = CItems::GetItems(iType)[iItemToSearch].iWaypoint;
				m_cItemToSearch.iType = iType;
				m_cItemToSearch.iIndex = iItemToSearch;
			}
		}
		else if (m_iCurrentTask == EBotTaskFindEnemy)
		{
			// Just go to some random waypoint.
			m_iTaskDestination = -1;
			if ( CWaypoints::Size() >= 2 )
			{
				do {
					m_iTaskDestination = rand() % CWaypoints::Size();
				} while ( m_iTaskDestination == iCurrentWaypoint );
			}
		}

		// Check if waypoint to go to is valid.
		if ( (m_iTaskDestination == -1) || (m_iTaskDestination == iCurrentWaypoint) )
		{
			BotMessage( "%s -> task %s, invalid waypoint %d (current %d), recalculate task.", GetName(), 
			            CTypeToString::BotTaskToString(m_iCurrentTask).c_str(), m_iTaskDestination, iCurrentWaypoint );
			m_iCurrentTask = -1;
			m_bNeedTaskCheck = true; // Check new task in next frame.
			m_bNeedMove = m_bUseNavigatorToMove = m_bDestinationChanged = false;

			// Bot searched for item at current waypoint, but item was not there. Add it to array of picked items.
			TaskFinished();
		}
		else
		{
			BotMessage( "%s -> new task: %s %s, waypoint %d (current %d).", GetName(), CTypeToString::BotTaskToString(m_iCurrentTask).c_str(),
			            pEntityClass ? pEntityClass->sClassName.c_str() : "", m_iTaskDestination, iCurrentWaypoint );

			m_iDestinationWaypoint = m_iTaskDestination;
			m_bNeedMove = m_bUseNavigatorToMove = m_bDestinationChanged = true;
		}
	}
	m_cSkipWeapons.reset();
}