コード例 #1
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Determines/Calculates a path to the current movement target and sets it as the active path.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::DeterminePathToTarget(float deltaTime)
{
	if(GetCurrentOrder())
	{
		if(GetCurrentOrder()->GetOrderType() == MoveToPositionOrder && (GetCurrentOrder()->GetOrderPriority() == MediumPriority || GetCurrentOrder()->GetOrderPriority() == HighPriority) && !reinterpret_cast<MoveOrder*>(GetCurrentOrder())->GetPath()->empty())
		{
			// Use the path provided by the team AI
			SetPath(reinterpret_cast<MoveOrder*>(GetCurrentOrder())->GetPath());
			// If the path was started before, resume it.
			m_movementManager.SetCurrentNode(GetResumePathNode());
		}else
		{
			// Let the soldier find a path himself.
			SetPath(m_movementManager.CreatePathTo(GetMovementTarget()));
			m_movementManager.SetCurrentNode(0);
		}

		// If there is no path to the target of the order, notify the team AI that the current order cannot be completed.
		if(!GetPath())
		{
			UpdateOrderStateMessageData data(GetId(), FailedOrderState);
			SendMessage(GetTeamAI(), UpdateOrderStateMessageType, &data);
		}
	}else
	{
		// Let the soldier find a path himself.
		SetPath(m_movementManager.CreatePathTo(GetMovementTarget()));
		m_movementManager.SetCurrentNode(0);
	}
	
	return StatusSuccess;
}
コード例 #2
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Moves the soldier entity towards a given target.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::MoveToTarget(float deltaTime)
{
	if(m_movementManager.FollowPath(GetPath(), m_soldierProperties.m_targetReachedRadius, m_soldierProperties.m_maxSpeed))
	{
		// The target was reached
		if(GetGreatestSuspectedThreat() && GetGreatestSuspectedThreat()->m_lastKnownPosition.x == GetMovementTarget().x &&
			GetGreatestSuspectedThreat()->m_lastKnownPosition.y == GetMovementTarget().y)
		{
			int a = 4;
		}

		return StatusSuccess;
	}

	// Target not yet reached -> move the entity along the path avoiding obstacles and intersection with other soldiers
	
	// Note: Collision avoidance not really needed as pathfinding sufficient and avoidance of other entities not really
	//       important at the moment.
	// m_movementManager.AvoidCollisions(m_soldierProperties.m_maxCollisionSeeAhead, m_soldierProperties.m_maxCollisionAvoidanceForce);
	m_movementManager.Separate(m_soldierProperties.m_separationRadius, m_soldierProperties.m_maxSeparationForce);
	m_movementManager.StayAwayFromWalls(m_soldierProperties.m_avoidWallsRadius, m_soldierProperties.m_maxAvoidWallsForce);

	m_movementManager.UpdatePosition(deltaTime, m_soldierProperties.m_maxSpeed, m_soldierProperties.m_maxTotalForce, m_soldierProperties.m_speedHandicap);

	if(GetCurrentOrder() && GetCurrentOrder()->GetOrderType() == MoveToPositionOrder && GetCurrentOrder()->GetOrderPriority() != LowPriority)
	{
		// Remember the current path node in case the soldier gets interrupted by enemies. Soldier will be able to resume movement afterwards.
		// Does only work though if soldier doesn't move away (only fighting known threats)
		SetResumePathNode(m_movementManager.GetCurrentNode());
	}

	return StatusRunning;
}
コード例 #3
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Determines and sets the currently greatest known threat to the Soldier.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::DetermineGreatestKnownThreat(float deltaTime)
{
	// Reset greatest known threat
	SetGreatestKnownThreat(nullptr);

	if(GetCurrentOrder())
	{
		// Check if there is a current order that requires to attack a certain enemy.
		if(GetCurrentOrder()->GetOrderType() == AttackEnemyOrder && GetCurrentOrder()->GetOrderPriority() == HighPriority)
		{
			// If the target enemy is in a known threat of this soldier -> set him as greatest threat to make sure the soldier
			// attacks that target.
			unsigned long enemyId = reinterpret_cast<AttackOrder*>(GetCurrentOrder())->GetEnemyId();
			if(IsKnownThreat(enemyId))
			{
				SetGreatestKnownThreat(GetKnownThreat(enemyId));
			}else
			{
				// The required enemy is not visible to the soldier but due to the high priority of the attack order, the
				// soldier is not allowed to attack other threats. Moving to the position of the require enemy is now his
				// main concern. Thus, no greatest known threat is set in order to bail out of the attack behaviour.

				// Add the requested enemy as a suspected threat if it is not in the list of suspected threats of the entity
				if(!IsSuspectedThreat(enemyId))
				{
					AddSuspectedThreat(enemyId, reinterpret_cast<AttackOrder*>(GetCurrentOrder())->GetEnemyPosition(), false);
				}else
				{
					// Update the last known position of the suspected threat (entity's current value might be dated)
					GetSuspectedThreat(enemyId)->m_lastKnownPosition = reinterpret_cast<AttackOrder*>(GetCurrentOrder())->GetEnemyPosition();
				}

				SetGreatestKnownThreat(nullptr);
			}

			return StatusSuccess;
		}

		if((GetCurrentOrder()->GetOrderType() == MoveToPositionOrder && GetCurrentOrder()->GetOrderPriority() == HighPriority) ||
			((GetCurrentOrder()->GetOrderType() == DefendPositionOrder && GetCurrentOrder()->GetOrderPriority() == HighPriority) 
			&& !IsAtTarget(reinterpret_cast<DefendOrder*>(GetCurrentOrder())->GetDefendPosition())))
		{
			// The soldier has a high priority move order or has to move to a defend position asap. This means the soldier has 
			// to ignore all enemies and try to reach his target. Thus, no greatest known threat is being set.
			SetGreatestKnownThreat(nullptr);
			return StatusSuccess;
		}
	}

	// No orders given that require special measures, just choose the greatest known threat as perceived by the soldier.
	SetGreatestKnownThreat(m_combatManager.DetermineGreatestKnownThreat());

	return StatusSuccess;
}
コード例 #4
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Finalise the movement of the entity when it reaches its objective.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::FinaliseMovement(float deltaTime)
{
	SetResumePathNode(0);

	if(GetCurrentOrder() && GetCurrentOrder()->GetOrderType() == MoveToPositionOrder)
	{
		UpdateOrderStateMessageData data(GetId(), SucceededOrderState);
		SendMessage(GetTeamAI(), UpdateOrderStateMessageType, &data);
	}
	
	return StatusSuccess;
}
コード例 #5
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Tells whether the soldier is currently moving towards the greatest suspected threat in
// order to investigate it or whether there now is a greater suspected threat that the
// entity should tend to. It also factors in whether there are orders from the team AI based
// on which the soldier should stop pursuing a target and tend to other objectives instead.
// Returns true if the suspected threat being investigated is still the greatest suspected threat,
// false otherwise and also if there is no suspected threat at all.
//--------------------------------------------------------------------------------------
bool Soldier::IsInvestigatingGreatestSuspectedThreat(void)
{

	if(GetCurrentOrder() && (GetCurrentOrder()->GetOrderType() == MoveToPositionOrder || GetCurrentOrder()->GetOrderType() == DefendPositionOrder) &&
		(GetCurrentOrder()->GetOrderPriority() != LowPriority))
	{
		// A higher level move or defend order has become active -> abort the pursuit of enemies and approach the target instead.
		return false;
	}

	// No specific orders, just check if there is a greater suspected threat (also valid for attack orders)
	return Entity::IsInvestigatingGreatestSuspectedThreat();
}
コード例 #6
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Determines a point to observe for the soldier and sets it as the active observation point.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::DetermineObservationTarget(float deltaTime)
{

	// Reset observation target
	SetObservationTarget(XMFLOAT2(0.0f, 0.0f));
	SetObservationTargetSet(false);

	if(GetCurrentOrder() && GetCurrentOrder()->GetOrderType() == DefendPositionOrder)
	{
		// When being shot, react to it and attack the shooter while keeping the defend position
		for(std::vector<SuspectedThreat>::iterator it = GetSuspectedThreats().begin(); it != GetSuspectedThreats().end(); ++it)
		{
			if(it->m_hasHitEntity)
			{
				SetObservationTarget(it->m_lastKnownPosition);
				SetObservationTargetSet(true);

				return StatusSuccess;
			}
		}
		
		const XMFLOAT2& viewDirection = reinterpret_cast<DefendOrder*>(GetCurrentOrder())->GetViewDirection();
		
		if(viewDirection.x != 0.0f || viewDirection.y != 0.0f)
		{
			// There is a defend order and a specific view direction that the entity should guard has been provided
			SetObservationTarget(XMFLOAT2(GetPosition().x + viewDirection.x, GetPosition().y + viewDirection.y));
			SetObservationTargetSet(true);

			return StatusSuccess;
		}
	}

	// Otherwise determine a random look at target and change it in a fix interval

	// Update the timer
	m_changeObservationTargetTimer += deltaTime;

	// Check if the soldier should change his observation target
	if(m_changeObservationTargetTimer >= m_soldierProperties.m_lookAroundInterval)
	{
		// Determine a random lookAt position

		SetObservationTarget(XMFLOAT2(GetPosition().x + (rand() % 128 - 64), GetPosition().y + (rand() % 128 - 64)));
		SetObservationTargetSet(true);
		m_changeObservationTargetTimer = 0.0f;
	}

	return StatusSuccess;
}
コード例 #7
0
DWORD CFerianShipAI::OnCommunicate (CSpaceObject *pSender, MessageTypes iMessage, CSpaceObject *pParam1, DWORD dwParam2)

//	Communicate
//
//	Handle communications from other objects

	{
	switch (iMessage)
		{
		case msgAttack:
			{
			if (GetCurrentOrder() == IShipController::orderMine
					&& pSender == m_pBase)
				{
				SetState(stateAttackingThreat);
				m_pTarget = pParam1;
				return resAck;
				}
			else
				return resNoAnswer;
			}

		default:
			return resNoAnswer;
		}
	}
コード例 #8
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Removes the currently active suspected threat from the list of suspected threats.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::ResolveSuspectedThreat(float deltaTime)
{
	if(GetGreatestSuspectedThreat())
	{
		RemoveSuspectedThreat(GetGreatestSuspectedThreat()->m_enemyId);

		// If the soldier was investigating the suspected threat in order to find and attack an enemy that
		// was the target of an attack order, notify the team AI that the attack failed

		if(GetCurrentOrder() && GetCurrentOrder()->GetOrderType() == AttackEnemyOrder && reinterpret_cast<AttackOrder*>(GetCurrentOrder())->GetEnemyId() == GetGreatestSuspectedThreat()->m_enemyId)
		{
			// Notify team AI that attack order failed
			UpdateOrderStateMessageData data(GetId(), FailedOrderState);
			SendMessage(GetTeamAI(), UpdateOrderStateMessageType, &data);
		}
	}
	return StatusSuccess;
}
コード例 #9
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Determines and sets the currently greatest suspected threat to the Soldier.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::DetermineGreatestSuspectedThreat(float deltaTime)
{
	if(GetCurrentOrder())
	{
		if(GetCurrentOrder()->GetOrderPriority() == HighPriority || GetCurrentOrder()->GetOrderPriority() == MediumPriority)
		{
			if(GetCurrentOrder()->GetOrderPriority() == HighPriority && GetCurrentOrder()->GetOrderType() == AttackEnemyOrder)
			{
				// Only move to the requested enemy

				SetGreatestSuspectedThreat(GetSuspectedThreat(reinterpret_cast<AttackOrder*>(GetCurrentOrder())->GetEnemyId()));
				return StatusSuccess;
			}

			// For any other orders of priority high and medium, soliders should not investigate any suspected threats (that also
			// means not pursue any enemies) as there are other objectives of higher priority.
			SetGreatestSuspectedThreat(nullptr);
			return StatusSuccess;
		}
	}

	// No orders given that require special measures, just choose the greatest suspected threat as perceived by the soldier.
	SetGreatestSuspectedThreat(m_combatManager.DetermineGreatestSuspectedThreat());

	return StatusSuccess;
}
コード例 #10
0
ファイル: CZoanthropeAI.cpp プロジェクト: bmer/Mammoth
CSpaceObject *CZoanthropeAI::GetBase (void) const

//	GetBase
//
//	Returns this ship's base

	{
	switch (GetCurrentOrder())
		{
		case IShipController::orderGuard:
		case IShipController::orderPatrol:
			return GetCurrentOrderTarget();

		default:
			return NULL;
		}
	}
コード例 #11
0
CString CAutonAI::DebugCrashInfo (void)

//	DebugCrashInfo
//
//	Returns debug crash info

	{
	CString sResult;

	sResult.Append(CONSTLIT("CAutonAI\r\n"));
	sResult.Append(strPatternSubst(CONSTLIT("Order: %d\r\n"), (int)GetCurrentOrder()));
	sResult.Append(strPatternSubst(CONSTLIT("m_State: %d\r\n"), m_State));
	sResult.Append(strPatternSubst(CONSTLIT("m_pDest: %s\r\n"), CSpaceObject::DebugDescribe(m_pDest)));
	sResult.Append(strPatternSubst(CONSTLIT("m_pTarget: %s\r\n"), CSpaceObject::DebugDescribe(m_pTarget)));

	return sResult;
	}
コード例 #12
0
void CFerianShipAI::OnObjDestroyedNotify (const SDestroyCtx &Ctx)

//	OnObjDestroyedNotify
//
//	Deal with an object that has been destroyed

	{
	switch (GetCurrentOrder())
		{
		case IShipController::orderMine:
			{
			if (Ctx.pObj == GetCurrentOrderTarget())
				{
				//	Avenge the base

				if (Ctx.pDestroyer && Ctx.pDestroyer->CanAttack() && !m_pShip->IsFriend(Ctx.pDestroyer))
					AddOrder(IShipController::orderDestroyTarget, Ctx.pDestroyer, 0);
				else if (m_State == stateAttackingThreat)
					AddOrder(IShipController::orderDestroyTarget, m_pTarget, 0);

				//	Stop mining

				CancelCurrentOrder();
				}
			break;
			}
		default:
			break;
		}

	//	Reset

	if (m_pBase == Ctx.pObj)
		{
		SetState(stateNone);
		m_pBase = NULL;
		}

	if (m_pTarget == Ctx.pObj)
		{
		SetState(stateNone);
		m_pTarget = NULL;
		}
	}
コード例 #13
0
ファイル: Ships.cpp プロジェクト: bote-team/bote
void CShips::ExtractDeuterium(CShipMap& ships)
{
	AssertBotE(GetCurrentOrder() == SHIP_ORDER::EXTRACT_DEUTERIUM);
	for(CShips::iterator i = begin(); i != end();) {
		i->second->ExtractDeuterium(ships);
		if(!i->second->CanExtractDeuterium()) {
			ships.Add(i->second);
			i->second->UnsetCurrentOrder();
			RemoveShipFromFleet(i);
			continue;
		}
		++i;
	}
	CShip::ExtractDeuterium();
	if(!CShip::CanExtractDeuterium()) {
		CShip::UnsetCurrentOrder();
		if(HasFleet())
			ships.Add(GiveFleetToFleetsFirstShip());
	}
}
コード例 #14
0
ファイル: Ships.cpp プロジェクト: bote-team/bote
void CShips::RepairCommand(BOOL bAtShipPort, bool bFasterShieldRecharge, CShipMap& ships) {
	AssertBotE(GetCurrentOrder() == SHIP_ORDER::REPAIR);
	if(!bAtShipPort) {
		UnsetCurrentOrder();
		return;
	}
	for(CShips::iterator i = begin(); i != end();) {
		i->second->RepairCommand(bAtShipPort, bFasterShieldRecharge, ships);
		if(!i->second->NeedsRepair()) {
			ships.Add(i->second);
			RemoveShipFromFleet(i);
			continue;
		}
		++i;
	}
	CShip::Repair(bAtShipPort, bFasterShieldRecharge);
	if(!CShip::NeedsRepair()) {
		CShip::UnsetCurrentOrder();
		if(HasFleet())
			ships.Add(GiveFleetToFleetsFirstShip());
	}
}
コード例 #15
0
ファイル: CZoanthropeAI.cpp プロジェクト: bmer/Mammoth
CString CZoanthropeAI::DebugCrashInfo (void)

//	DebugCrashInfo
//
//	Returns debug crash info

	{
	CString sOrder;
	try
		{
		sOrder = strFromInt((int)GetCurrentOrder());
		}
	catch (...)
		{
		}

	//	If GetCurrentOrder crashes, try to determine why

	if (sOrder.IsBlank())
		{
		try
			{
			sOrder = strPatternSubst(CONSTLIT("crash in GetCurrentOrder; count = %d\r\n"), m_Orders.GetCount());
			}
		catch (...)
			{
			sOrder = CONSTLIT("crash in GetCurrentOrder\r\n");
			}
		}

	CString sResult = CONSTLIT("CZoanthropeAI\r\n");
	sResult.Append(strPatternSubst(CONSTLIT("Order: %s\r\n"), sOrder));
	sResult.Append(strPatternSubst(CONSTLIT("m_State: %d\r\n"), m_State));
	sResult.Append(strPatternSubst(CONSTLIT("m_pBase: %s\r\n"), CSpaceObject::DebugDescribe(m_pBase)));
	sResult.Append(strPatternSubst(CONSTLIT("m_pTarget: %s\r\n"), CSpaceObject::DebugDescribe(m_pTarget)));

	return sResult;
	}
コード例 #16
0
ファイル: Ships.cpp プロジェクト: bote-team/bote
void CShips::AddShipToFleet(const boost::shared_ptr<CShips>& fleet) {
	CString s;
	if(MT::CMyTrace::IsLoggingEnabledFor("ships")) {
		s.Format("CShips: adding ship with leader %s to fleet of %s", fleet->m_sName,
			m_sName);
		MYTRACE("ships")(MT::LEVEL_INFO, s);
	}
	AssertBotE(fleet->OwnerID() == OwnerID());
	const CShipMap::iterator i = m_Fleet.Add(fleet);
	const SHIP_ORDER::Typ order = GetCurrentOrder();
	AssertBotE(order != SHIP_ORDER::ASSIGN_FLAGSHIP);
	if(!i->second->CanHaveOrder(order, false))
		UnsetCurrentOrder();
	i->second->AdoptOrdersFrom(*this);
	if(fleet->HasFleet()) {
		if(MT::CMyTrace::IsLoggingEnabledFor("ships")) {
			s.Format("CShips: adding the fleet of leader %s to fleet of %s", fleet->m_sName,
				m_sName);
			MYTRACE("ships")(MT::LEVEL_INFO, s);
		}
		m_Fleet.Append(i->second->m_Fleet);
		i->second->Reset();
	}
}
コード例 #17
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Determines and sets a patrol target position for the soldier.
// Param1: The time in seconds passed since the last frame.
// Returns the current state of the action.
//--------------------------------------------------------------------------------------
BehaviourStatus Soldier::DetermineMovementTarget(float deltaTime)
{
	// Reset movement target
	SetMovementTarget(XMFLOAT2(0.0f, 0.0f));
	SetMovementTargetSet(false);

	if(GetCurrentOrder())
	{
		if(GetCurrentOrder()->GetOrderType() == DefendPositionOrder)
		{
			if(IsAtTarget(reinterpret_cast<DefendOrder*>(GetCurrentOrder())->GetDefendPosition()))
			{
				SetMovementTargetSet(false);
			}else
			{
				SetMovementTarget(reinterpret_cast<DefendOrder*>(GetCurrentOrder())->GetDefendPosition());
				SetMovementTargetSet(true);
			}
		}else if(GetCurrentOrder()->GetOrderType() == MoveToPositionOrder)
		{
			SetMovementTarget(reinterpret_cast<MoveOrder*>(GetCurrentOrder())->GetTargetPosition());
			SetMovementTargetSet(true);
		}
	}else
	{
		// If there is no order, just pick a random target position within the test environment to patrol
		XMFLOAT2 patrolTarget(0.0f, 0.0f);
		if(GetTestEnvironment()->GetRandomUnblockedTarget(patrolTarget))
		{
			m_movementManager.Reset();

			SetMovementTarget(patrolTarget);
			SetMovementTargetSet(true);
		}else
		{
			SetMovementTargetSet(false);
		}
	}
	
	// Always succeeds
	return StatusSuccess;
}
コード例 #18
0
ファイル: Soldier.cpp プロジェクト: BlurEffect/SquadAI
//--------------------------------------------------------------------------------------
// Tells whether the entity is currently moving towards the highest priority movement target 
// or whether there now is a higher priority target that the entity should move towards instead.
// Returns true if the target being moved towards is still the highest priority target,
// false otherwise and also if there is no movement target set at all.
//--------------------------------------------------------------------------------------
bool Soldier::IsMovingToHighestPriorityTarget(void)
{
	if(!IsMovementTargetSet())
	{
		return false;
	}

	if(GetCurrentOrder() && GetCurrentOrder()->GetOrderType() == MoveToPositionOrder)
	{
		// A movement order was received, which has higher priority than normal movement. Check if
		// the entity is moving towards the ordered movement target.
		const XMFLOAT2& orderTarget = reinterpret_cast<MoveOrder*>(GetCurrentOrder())->GetTargetPosition();

		if(GetMovementTarget().x != orderTarget.x || GetMovementTarget().y != orderTarget.y)
		{
			// Soldier should stop moving to current target and follow order instead
			
			// Soldier won't be able to resume the path later on
			SetResumePathNode(0);
			return false;
		}
	}else if(GetCurrentOrder() && GetCurrentOrder()->GetOrderType() == DefendPositionOrder)
	{
		// A defned order was received, which has higher priority than normal movement. Check if
		// the entity is moving towards the defend target.
		const XMFLOAT2& orderTarget = reinterpret_cast<DefendOrder*>(GetCurrentOrder())->GetDefendPosition();

		if(GetMovementTarget().x != orderTarget.x || GetMovementTarget().y != orderTarget.y)
		{
			// Soldier should stop moving to current target and follow order instead
			
			// Soldier won't be able to resume the path later on
			SetResumePathNode(0);
			return false;
		}
	}

	return true;
}
コード例 #19
0
ファイル: CZoanthropeAI.cpp プロジェクト: bmer/Mammoth
void CZoanthropeAI::BehaviorStart (void)

//	BehaviorStart
//
//	Figure out what to do based on orders

	{
	switch (GetCurrentOrder())
		{
		case IShipController::orderNone:
			{
			if (m_pShip->GetDockedObj() == NULL)
				AddOrder(IShipController::orderGate, NULL, IShipController::SData());
			break;
			}

		case IShipController::orderEscort:
			{
			CSpaceObject *pPrincipal = GetCurrentOrderTarget();
			ASSERT(pPrincipal);

			SetState(stateOnEscortCourse, pPrincipal);
			m_pShip->Communicate(m_pBase, msgEscortReportingIn, m_pShip);
			break;
			}

		case IShipController::orderFollowPlayerThroughGate:
			SetState(stateOnCourseForStargate, m_pShip->GetNearestStargate());
			break;

		case IShipController::orderGate:
			{
			//	Look for the gate

			CSpaceObject *pGate = GetCurrentOrderTarget();
			if (pGate == NULL)
				pGate = m_pShip->GetNearestStargate(true);

			//	Head for the gate

			if (pGate)
				SetState(stateOnCourseForStargate, pGate);

			break;
			}

		case IShipController::orderGuard:
			{
			CSpaceObject *pPrincipal = GetCurrentOrderTarget();
			ASSERT(pPrincipal);

			//	If we're not docked, dock with principal

			if (m_pShip->GetDockedObj() == NULL)
				SetState(stateReturningFromThreat, pPrincipal);

			//	Otherwise, wait for a threat

			else
				SetState(stateWaitingForThreat, pPrincipal);

			break;
			}

		case IShipController::orderPatrol:
			{
			CSpaceObject *pPrincipal = GetCurrentOrderTarget();
			ASSERT(pPrincipal);

			SetState(stateOnPatrolOrbit, pPrincipal);
			break;
			}

		case IShipController::orderWaitForPlayer:
			{
			SetState(stateWaiting);
			break;
			}
		}
	}
コード例 #20
0
void CAutonAI::BehaviorStart (void)

//	BehaviorStart
//
//	Initiate behavior state based on orders

	{
	switch (GetCurrentOrder())
		{
		case IShipController::orderNone:
			{
			if (m_pShip->GetDockedObj() == NULL)
				AddOrder(IShipController::orderGate, NULL, IShipController::SData());
			break;
			}

		case IShipController::orderEscort:
			{
			//	If this is a support ship, then we follow. Otherwise we
			//	are an armed escort.

			if (m_AICtx.IsNonCombatant())
				SetState(stateFollowing);
			else
				SetState(stateEscorting);

			m_pDest = GetCurrentOrderTarget();
			ASSERT(m_pDest);

			m_pShip->Communicate(m_pDest, msgEscortReportingIn, m_pShip);
			break;
			}

		case IShipController::orderFollowPlayerThroughGate:
			{
			SetState(stateOnCourseForStargate);
			m_pDest = m_pShip->GetNearestStargate();
			break;
			}

		case IShipController::orderGate:
			{
			//	Look for the gate

			CSpaceObject *pGate = GetCurrentOrderTarget();
			if (pGate == NULL)
				pGate = m_pShip->GetNearestStargate(true);

			//	Head for the gate

			if (pGate)
				{
				SetState(stateOnCourseForStargate);
				m_pDest = pGate;
				}

			break;
			}

		case IShipController::orderWaitForPlayer:
			{
			SetState(stateWaiting);
			break;
			}
		}
	}
コード例 #21
0
DWORD CAutonAI::OnCommunicate (CSpaceObject *pSender, MessageTypes iMessage, CSpaceObject *pParam1, DWORD dwParam2)

//	Communicate
//
//	Handle communications from other objects

	{
	switch (iMessage)
		{
		case msgAttack:
		case msgAttackDeter:
			{
			if (GetCurrentOrder() == IShipController::orderEscort
					&& !m_AICtx.IsNonCombatant())
				{
				SetState(stateAttackingTarget);
				m_pTarget = pParam1;
				return resAck;
				}
			else
				return resNoAnswer;
			}

		case msgAbort:
			{
			SetState(stateNone);
			return resAck;
			}

		case msgFormUp:
			{
			if (m_State == stateWaiting || m_State == stateAttackingTarget)
				{
				SetState(stateNone);
				return resAck;
				}
			else
				return resNoAnswer;
			}

		case msgQueryCommunications:
			{
			if (GetCurrentOrder() == IShipController::orderEscort)
				{
				DWORD dwRes = 0;
				if (!m_AICtx.IsNonCombatant())
					dwRes |= resCanAttack;
				if (m_State == stateAttackingTarget)
					dwRes |= (resCanAbortAttack | resCanFormUp);
				if (m_State != stateWaiting)
					dwRes |= resCanWait;
				else
					dwRes |= resCanFormUp;

				return dwRes;
				}
			else
				return 0;
			}

		case msgQueryEscortStatus:
			{
			if (GetEscortPrincipal() == pParam1)
				return resAck;
			else
				return resNoAnswer;
			}

		case msgQueryWaitStatus:
			return (m_State == stateWaiting ? resAck : resNoAnswer);

		case msgWait:
			{
			if (GetCurrentOrder() == IShipController::orderEscort)
				{
				SetState(stateWaiting);
				m_pDest = GetCurrentOrderTarget();
				return resAck;
				}
			else
				return resNoAnswer;
			}

		default:
			return resNoAnswer;
		}
	}
コード例 #22
0
void CFerianShipAI::BehaviorStart (void)

//	BehaviorStart
//
//	Figure out what to do based on orders

	{
	switch (GetCurrentOrder())
		{
		case IShipController::orderNone:
			{
			if (m_pShip->GetDockedObj() == NULL)
				AddOrder(IShipController::orderGate, NULL, 0);
			break;
			}

		case IShipController::orderDestroyTarget:
			{
			SetState(stateAttackingTarget);
			m_pTarget = GetCurrentOrderTarget();
			ASSERT(m_pTarget);
			ASSERT(m_pTarget->DebugIsValid() && m_pTarget->NotifyOthersWhenDestroyed());
			break;
			}

		case IShipController::orderMine:
			{
			m_pBase = GetCurrentOrderTarget();
			ASSERT(m_pBase);

			SetState(stateOnCourseForMine);
			m_pTarget = FindRandomAsteroid();
			if (m_pTarget == NULL)
				{
				SetState(stateOnCourseForStargate);
				m_pBase = m_pShip->GetNearestStargate(true);
				}
			break;
			}

		case IShipController::orderGate:
			{
			//	Look for the gate

			CSpaceObject *pGate = GetCurrentOrderTarget();
			if (pGate == NULL)
				pGate = m_pShip->GetNearestStargate(true);

			//	Head for the gate

			if (pGate)
				{
				SetState(stateOnCourseForStargate);
				m_pBase = pGate;
				}

			break;
			}

		case IShipController::orderDestroyPlayerOnReturn:
			{
			CSpaceObject *pGate = m_pShip->GetNearestStargate();
			if (pGate)
				{
				SetState(stateWaitForPlayerAtGate);
				m_pBase = pGate;
				}
			break;
			}
		default:
			break;
		}
	}
コード例 #23
0
void CFleetShipAI::OnObjDestroyedNotify (const SDestroyCtx &Ctx)

//	OnObjDestroyedNotify
//
//	Deal with an object that has been destroyed

	{
	switch (GetCurrentOrder())
		{
		case IShipController::orderEscort:
			if (Ctx.pObj == GetCurrentOrderTarget())
				{
				CancelCurrentOrder();

				//	Get the orders of the leader

				IShipController::OrderTypes iLeaderOrders = IShipController::orderNone;
				CSpaceObject *pLeaderTarget = NULL;
				if (Ctx.pObj && Ctx.pObj->GetCategory() == CSpaceObject::catShip)
					{
					CShip *pLeader = Ctx.pObj->AsShip();
					if (pLeader)
						iLeaderOrders = pLeader->GetController()->GetCurrentOrderEx(&pLeaderTarget);
					}

				//	Avenge the leader

				int iAvengeChance = (pLeaderTarget ? 40 : 100);
				if (Ctx.pDestroyer 
						&& Ctx.pDestroyer != pLeaderTarget
						&& Ctx.pDestroyer->CanAttack() 
						&& !m_pShip->IsFriend(Ctx.pDestroyer)
						&& mathRandom(1, 100) <= iAvengeChance)
					AddOrder(IShipController::orderDestroyTarget, Ctx.pDestroyer, 0);

				//	Take on leader's orders

				switch (iLeaderOrders)
					{
					case IShipController::orderDestroyTarget:
					case IShipController::orderGuard:
						if (pLeaderTarget)
							AddOrder(iLeaderOrders, pLeaderTarget, 0);
						break;
					default:
						break;
					}

				//	Attack other enemies

				AddOrder(IShipController::orderAttackNearestEnemy, NULL, 0);
				}
			break;

		case IShipController::orderDock:
		case IShipController::orderDestroyTarget:
		case IShipController::orderPatrol:
		case IShipController::orderGuard:
			if (Ctx.pObj == GetCurrentOrderTarget())
				CancelCurrentOrder();
			break;
		default:
			break;
		}

	//	If our target gets destroyed...

	switch (m_State)
		{
		case stateAttackTarget:
		case stateAttackOnPatrol:
			if (Ctx.pObj == m_pTarget)
				SetState(stateNone);
			break;
		default:
			break;
		}

	//	Reset

	if (m_pDest == Ctx.pObj)
		m_pDest = NULL;
	if (m_pTarget == Ctx.pObj)
		m_pTarget = NULL;
	}
コード例 #24
0
DWORD CFleetShipAI::OnCommunicate (CSpaceObject *pSender, MessageTypes iMessage, CSpaceObject *pParam1, DWORD dwParam2)

//	Communicate
//
//	Handle communications from other objects

	{
	switch (iMessage)
		{
		case msgAbort:
			{
			if (m_State == stateAttackTarget
					|| m_State == stateAttackAtWill
					|| m_State == stateAttackInFormation)
				SetState(stateNone);
			return resAck;
			}

		case msgAttack:
			{
			if (GetCurrentOrder() == IShipController::orderEscort)
				{
				SetState(stateAttackTarget);
				m_pTarget = pParam1;
				m_iCounter = 0;
				ASSERT(m_pTarget);
				return resAck;
				}
			else
				return resNoAnswer;
			}

		case msgAttackInFormation:
			{
			if (GetCurrentOrder() == IShipController::orderEscort)
				{
				SetState(stateAttackInFormation);
				m_iCounter = dwParam2;
				return resAck;
				}
			else
				return resNoAnswer;
			}

		case msgBreakAndAttack:
			{
			if (GetCurrentOrder() == IShipController::orderEscort)
				{
				SetState(stateAttackAtWill);
				return resAck;
				}
			else
				return resNoAnswer;
			}

		case msgFormUp:
			{
			if (GetCurrentOrder() == IShipController::orderEscort)
				{
				if (dwParam2 != 0xffffffff)
					SetCurrentOrderData(dwParam2);

				SetState(stateNone);
				return resAck;
				}
			else
				return resNoAnswer;
			}

		case msgQueryCommunications:
			{
			if (GetCurrentOrder() == IShipController::orderEscort && GetCurrentOrderTarget() == pSender)
				{
				DWORD dwRes = (resCanBeInFormation | resCanAttack | resCanBreakAndAttack);
				if (m_State == stateAttackTarget
						|| m_State == stateAttackAtWill
						|| m_State == stateAttackInFormation)
					dwRes |= resCanAbortAttack;
				else if (m_State == stateKeepFormation)
					dwRes |= resCanAttackInFormation;

				return dwRes;
				}
			else
				return resNoAnswer;
			}

		case msgQueryEscortStatus:
		case msgQueryFleetStatus:
			{
			if (GetEscortPrincipal() == pParam1)
				return resAck;
			else
				return resNoAnswer;
			}

		default:
			return resNoAnswer;
		}
	}
コード例 #25
0
void CFleetShipAI::BehaviorStart (void)

//	BehaviorStart
//
//	Figure out what to do based on orders

	{
	switch (GetCurrentOrder())
		{
		case IShipController::orderNone:
			{
			if (m_pShip->GetDockedObj() == NULL)
				AddOrder(IShipController::orderGate, NULL, 0);
			break;
			}

		case IShipController::orderAttackNearestEnemy:
			{
			CSpaceObject *pTarget = m_pShip->GetNearestEnemy(ATTACK_AT_WILL_RANGE, true);
			if (pTarget)
				{
				SetState(stateAttackTarget);
				m_pTarget = pTarget;
				m_iCounter = 0;
				}
			else
				CancelCurrentOrder();
			break;
			}

		case IShipController::orderDestroyTarget:
			{
			SetState(stateAttackTarget);
			m_pTarget = GetCurrentOrderTarget();
			m_iCounter = 0;
			ASSERT(m_pTarget);
			break;
			}

		case IShipController::orderDock:
			{
			CSpaceObject *pDest = GetCurrentOrderTarget();
			ASSERT(pDest);

			//	If we're docked with our destination then we're done.

			if (m_pShip->GetDockedObj() == pDest)
				CancelCurrentOrder();

			//	Otherwise, try to dock

			else
				{
				SetState(stateOnCourseForDocking);
				m_pDest = pDest;
				}

			break;
			}

		case IShipController::orderEscort:
			{
			SetState(stateKeepFormation);

			m_pLeader = GetCurrentOrderTarget();
			ASSERT(m_pLeader);

			m_iFormation = (int)HIWORD(GetCurrentOrderData());
			m_iPlace = (int)LOWORD(GetCurrentOrderData());
			ASSERT(m_iFormation < FORMATIONS_COUNT);

			//	If there is no place for this ship in the formation, then
			//	gate-out

			if (m_iFormation >= FORMATIONS_COUNT
					|| m_iPlace >= g_Formations[m_iFormation].iCount)
				{
				CancelCurrentOrder();
				break;
				}

			//	Keep formation

			m_pShip->Communicate(m_pLeader, msgEscortReportingIn, m_pShip);
			break;
			}

		case IShipController::orderFollowPlayerThroughGate:
			{
			SetState(stateOnCourseForStargate);
			m_pDest = m_pShip->GetNearestStargate();
			break;
			}

		case IShipController::orderGate:
			{
			//	Look for the gate

			CSpaceObject *pGate = GetCurrentOrderTarget();
			if (pGate == NULL)
				pGate = m_pShip->GetNearestStargate(true);

			//	Head for the gate

			if (pGate)
				{
				SetState(stateOnCourseForStargate);
				m_pDest = pGate;
				}

			break;
			}

		case IShipController::orderPatrol:
		case IShipController::orderGuard:
			{
			SetState(stateOnPatrolOrbit);
			m_pDest = GetCurrentOrderTarget();
			ASSERT(m_pDest);
			break;
			}
		default:
			break;
		}
	}