示例#1
0
void CZoanthropeAI::Behavior (void)

//	Behavior

	{
	//	Reset

	ResetBehavior();

	//	Behave according to our state

	switch (m_State)
		{
		case stateNone:
			BehaviorStart();
			break;

		case stateAttackingOnPatrol:
			{
			ASSERT(m_pTarget);
			ImplementCombatManeuvers(m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip, m_pTarget);

			//	See if we're out of our zone

			Metric rRange = LIGHT_SECOND * GetCurrentOrderData();
			if (CheckOutOfZone(GetCurrentOrderTarget(),
					rRange - PATROL_SENSOR_RANGE,
					rRange + PATROL_SENSOR_RANGE,
					30))
				SetState(stateNone);
			break;
			}

		case stateAttackingThreat:
			{
			ASSERT(m_pTarget);
			ImplementCombatManeuvers(m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip, m_pTarget);

			//	Every once in a while check to see if we've wandered too far from
			//	our base.

			if (CheckOutOfRange(GetCurrentOrderTarget(), PATROL_SENSOR_RANGE, 20))
				SetState(stateNone);
			break;
			}

		case stateOnCourseForStargate:
			{
			m_AICtx.ImplementGating(m_pShip, m_pBase);
			m_AICtx.ImplementAttackNearestTarget(m_pShip, ATTACK_RANGE, &m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);
			break;
			}

		case stateOnEscortCourse:
			{
			ASSERT(m_pBase);

			CVector vFlockPos;
			CVector vFlockVel;
			int iFlockFacing;
			if (m_AICtx.CalcFlockingFormation(m_pShip, m_pBase, MAX_FLOCK_DIST, SEPARATION_RANGE, &vFlockPos, &vFlockVel, &iFlockFacing))
				{
				m_AICtx.ImplementFormationManeuver(m_pShip, vFlockPos, vFlockVel, m_pShip->AlignToRotationAngle(iFlockFacing));
				}
			else
				{
				CVector vTarget = m_pBase->GetPos() - m_pShip->GetPos();
				Metric rTargetDist2 = vTarget.Dot(vTarget);

				m_AICtx.ImplementCloseOnTarget(m_pShip, m_pBase, vTarget, rTargetDist2);
				m_AICtx.ImplementAttackNearestTarget(m_pShip, m_AICtx.GetMaxWeaponRange(), &m_pTarget);
				m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);
				}

			//	See if there is anything to attack

			CSpaceObject *pTarget;
			if (CheckForEnemiesInRange(m_pShip, PATROL_SENSOR_RANGE, 30, &pTarget))
				SetState(stateAttackingThreat, m_pBase, pTarget);

			break;
			}

		case stateOnPatrolOrbit:
			{
			ASSERT(m_pBase);

			CVector vFlockPos;
			CVector vFlockVel;
			int iFlockFacing;
			if (m_AICtx.CalcFlockingFormation(m_pShip, NULL, MAX_FLOCK_DIST, SEPARATION_RANGE, &vFlockPos, &vFlockVel, &iFlockFacing))
				{
				m_AICtx.ImplementFormationManeuver(m_pShip, vFlockPos, vFlockVel, m_pShip->AlignToRotationAngle(iFlockFacing));
				}
			else
				{
				m_AICtx.ImplementOrbit(m_pShip, m_pBase, LIGHT_SECOND * GetCurrentOrderData());
				m_AICtx.ImplementAttackNearestTarget(m_pShip, m_AICtx.GetMaxWeaponRange(), &m_pTarget);
				m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);
				}

			//	See if there is anything to attack

			CSpaceObject *pTarget;
			if (CheckForEnemiesInRange(m_pShip, PATROL_SENSOR_RANGE, 30, &pTarget))
				SetState(stateAttackingOnPatrol, m_pBase, pTarget);
			break;
			}

		case stateReturningFromThreat:
			{
			ASSERT(m_pBase);
			m_AICtx.ImplementDocking(m_pShip, m_pBase);
			m_AICtx.ImplementAttackNearestTarget(m_pShip, m_AICtx.GetMaxWeaponRange(), &m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);

			//	See if there is anything to attack

			CSpaceObject *pTarget;
			if (CheckForEnemiesInRange(m_pBase, PATROL_SENSOR_RANGE, 30, &pTarget))
				SetState(stateAttackingThreat, m_pBase, pTarget);
			break;
			}

		case stateWaiting:
			m_AICtx.ImplementStop(m_pShip);

			if (m_pTarget)
				m_AICtx.ImplementAttackTarget(m_pShip, m_pTarget, true);

			m_AICtx.ImplementAttackNearestTarget(m_pShip, m_AICtx.GetMaxWeaponRange(), &m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);
			break;

		case stateWaitingForThreat:
			{
			ASSERT(m_pBase);
			CSpaceObject *pTarget;
			if (CheckForEnemiesInRange(m_pBase, PATROL_SENSOR_RANGE, 30, &pTarget))
				SetState(stateAttackingThreat, m_pBase, pTarget);
			break;
			}
		}
	}
示例#2
0
void CFerianShipAI::Behavior (void)

//	Behavior

	{
	//	Reset

	ResetBehavior();

	//	Behave according to our state

	switch (m_State)
		{
		case stateNone:
			BehaviorStart();
			break;

		case stateAttackingTarget:
			{
			ASSERT(m_pTarget);
			ImplementAttackTarget(m_pTarget);
			ImplementFireOnTargetsOfOpportunity(m_pTarget);
			break;
			}

		case stateAttackingThreat:
			{
			ASSERT(m_pTarget);
			ASSERT(m_pBase);
			ImplementAttackTarget(m_pTarget);
			ImplementFireOnTargetsOfOpportunity(m_pTarget);

			//	Every once in a while check to see if we've wandered too far from
			//	our base.

			if (m_pShip->IsDestinyTime(20))
				{
				CVector vRange = m_pBase->GetPos() - m_pShip->GetPos();
				Metric rDistance2 = vRange.Length2();

				//	If we're outside of our patrol range and if we haven't
				//	been hit in a while then stop the attack.

				if (rDistance2 > MAX_ATTACK_DIST2)
					{
					SetState(stateNone);
					m_pTarget = NULL;
					}
				}

			break;
			}

		case stateAvoidThreat:
			{
			ASSERT(m_pTarget);

			//	Pick a direction away from the target

			ImplementEvasiveManeuvers(m_pTarget);
			ImplementFireOnTargetsOfOpportunity(m_pTarget);

			//	If we're no longer close to the target, then revert to mining

			if (m_pShip->IsDestinyTime(21))
				{
				CVector vRange = m_pTarget->GetPos() - m_pShip->GetPos();
				Metric rDistance2 = vRange.Length2();
				if (rDistance2 > MAX_THREAT_DIST2)
					{
					SetState(stateNone);
					m_pTarget = NULL;
					}
				}

			break;
			}

		case stateMining:
			{
			ASSERT(m_pTarget);

			//	If there's a threat near-by, scurry away

			CSpaceObject *pThreat;
			if (InRangeOfThreat(&pThreat))
				{
				m_pShip->ResetMaxSpeed();
				SetState(stateAvoidThreat);
				m_pTarget = pThreat;
				}

			//	Otherwise, mine stuff

			else
				{
				if (m_pShip->IsDestinyTime(MINE_CYCLE_DELAY))
					{
					//	There's a chance that we stop mining and proceed to
					//	another asteroid.

					if (mathRandom(1, 100) <= 15)
						{
						SetState(stateNone);
						m_pTarget = NULL;
						}
					}
				}

			break;
			}

		case stateOnCourseForMine:
			{
			ASSERT(m_pTarget);

			//	If there is a threat near-by, scurry away

			CSpaceObject *pThreat;
			if (InRangeOfThreat(&pThreat))
				{
				m_pShip->ResetMaxSpeed();
				SetState(stateAvoidThreat);
				m_pTarget = pThreat;
				}

			//	Otherwise, go to the mine

			else
				{
				//	If we're close enough to the mine, then start mining

				CVector vDist = m_pTarget->GetPos() - m_pShip->GetPos();
				Metric rDist2 = vDist.Length2();
				if (rDist2 < MAX_MINING_DIST2)
					{
					m_pShip->ResetMaxSpeed();
					m_pShip->ClipSpeed(0.0);
					SetState(stateMining);
					}

				//	If we're near the mine, slow down

				else if (rDist2 < MINING_APPROACH_DIST2)
					{
					m_pShip->SetMaxSpeedHalf();
					ImplementCloseOnTarget(m_pTarget, vDist, rDist2);
					}
				else
					ImplementCloseOnTarget(m_pTarget, vDist, rDist2);
				}

			break;
			}

		case stateOnCourseForStargate:
			ImplementGating(m_pBase);
			ImplementFireOnTargetsOfOpportunity();
			break;

		case stateWaitForPlayerAtGate:
			ImplementEscort(m_pBase, &m_pTarget);
			break;
		}
	}
示例#3
0
void CAutonAI::Behavior (void)

//	Behavior
//
//	Fly, fight, die

	{
	//	Reset

	ResetBehavior();

	//	Behave according to our state

	switch (m_State)
		{
		case stateNone:
			BehaviorStart();
			break;

		case stateAttackingTarget:
			ASSERT(m_pTarget);
			m_AICtx.ImplementAttackTarget(m_pShip, m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip, m_pTarget);
			break;

		case stateEscorting:
			m_AICtx.ImplementEscort(m_pShip, m_pDest, &m_pTarget);
			break;

		case stateFollowing:
			{
			ASSERT(m_pDest);
			CVector vTarget = m_pDest->GetPos() - m_pShip->GetPos();
			Metric rTargetDist2 = vTarget.Dot(vTarget);
			Metric rMaxDist = (MAX_FOLLOW_DISTANCE) + (g_KlicksPerPixel * (m_pShip->GetDestiny() % 120));

			if (rTargetDist2 > (rMaxDist * rMaxDist))
				m_AICtx.ImplementCloseOnTarget(m_pShip, m_pDest, vTarget, rTargetDist2);
			else if (rTargetDist2 < (g_KlicksPerPixel * g_KlicksPerPixel * 1024.0))
				m_AICtx.ImplementSpiralOut(m_pShip, vTarget);
			else
				m_AICtx.ImplementStop(m_pShip);

			if (m_pTarget)
				m_AICtx.ImplementAttackTarget(m_pShip, m_pTarget, true);

			m_AICtx.ImplementAttackNearestTarget(m_pShip, ATTACK_RANGE, &m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);
			break;
			}

		case stateOnCourseForStargate:
			m_AICtx.ImplementGating(m_pShip, m_pDest);
			m_AICtx.ImplementAttackNearestTarget(m_pShip, ATTACK_RANGE, &m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);
			break;

		case stateWaiting:
			m_AICtx.ImplementHold(m_pShip);

			if (m_pTarget)
				m_AICtx.ImplementAttackTarget(m_pShip, m_pTarget, true);

			m_AICtx.ImplementAttackNearestTarget(m_pShip, ATTACK_RANGE, &m_pTarget);
			m_AICtx.ImplementFireOnTargetsOfOpportunity(m_pShip);
			break;

		default:
			ASSERT(false);
		}
	}
示例#4
0
void CFleetShipAI::Behavior (void)

//	Behavior

	{
	//	Reset

	ResetBehavior();

	//	Use basic items

	UseItemsBehavior();

	//	Behave according to our state

	switch (m_State)
		{
		case stateNone:
			BehaviorStart();
			break;

		case stateAttackAtWill:
			{
			//	If we don't have a target, find one

			if (m_pTarget == NULL && m_pShip->IsDestinyTime(13))
				m_pTarget = m_pShip->GetNearestEnemy(ATTACK_AT_WILL_RANGE, true);

			//	If we have a target, attack

			if (m_pTarget)
				{
				ImplementAttackTarget(m_pTarget);
				ImplementFireOnTargetsOfOpportunity(m_pTarget);
				}

			//	Otherwise, stay in formation

			else
				{
				ImplementKeepFormation();
				ImplementFireOnTargetsOfOpportunity();
				ImplementFireOnNearestTarget();
				}

			break;
			}

		case stateAttackInFormation:
			{
			bool bInFormation;
			ImplementKeepFormation(&bInFormation);

			//	Fire the primary weapon (most of the time)

			if (bInFormation && mathRandom(1, 3) > 1)
				ImplementFireWeapon();

			//	Decrement counter

			if (m_iCounter > 0)
				{
				if (--m_iCounter == 0)
					{
					SetState(stateKeepFormation);
					m_iCounter = 0;
					}
				}

			break;
			}

		case stateAttackOnPatrol:
			ASSERT(m_pTarget);
			ImplementAttackTarget(m_pTarget);
			ImplementFireOnTargetsOfOpportunity(m_pTarget);

			//	Check to see if we've wandered outside our patrol zone

			if (m_pShip->IsDestinyTime(20))
				{
				CSpaceObject *pCenter = GetCurrentOrderTarget();
				Metric rMaxRange2 = PATROL_ORBIT_DIST + PATROL_SENSOR_RANGE;
				rMaxRange2 = rMaxRange2 * rMaxRange2;
				Metric rMinRange2 = std::max(0.0, PATROL_ORBIT_DIST - PATROL_SENSOR_RANGE);
				rMinRange2 = rMinRange2 * rMinRange2;

				int iTick = m_pShip->GetSystem()->GetTick();
				CVector vRange = pCenter->GetPos() - m_pShip->GetPos();
				Metric rDistance2 = vRange.Dot(vRange);

				//	If we're outside of our patrol range then stop the attack

				if (rDistance2 > rMaxRange2 || rDistance2 < rMinRange2)
					SetState(stateNone);
				}
			break;

		case stateAttackTarget:
			{
			ASSERT(m_pTarget);
			if (m_pTarget->CanMove())
				ImplementAttackTarget(m_pTarget);
			else
				{
				//	Attack the target as best we can

				CVector vTarget = m_pTarget->GetPos() - m_pShip->GetPos();
				Metric rTargetDist2 = vTarget.Dot(vTarget);
				ImplementFireWeaponOnTarget(-1, -1, m_pTarget, vTarget, rTargetDist2);

				//	Maneuver to a proper position near the target

				Metric rRange;
				int iCounterAdj;
				if (m_pAISettings->iCombatStyle == aicombatStandOff)
					{
					rRange = m_rBestWeaponRange / 2.0;
					iCounterAdj = 2;
					}
				else
					{
					rRange = m_rBestWeaponRange / 6.0;
					iCounterAdj = 1;
					}

				if (m_iCounter == 0)
					{
					m_vVector = ComputeAttackPos(m_pTarget, rRange, &m_iAngle);
					m_iCounter = mathRandom(130, 160) * iCounterAdj;
					}
				else
					m_iCounter--;

				ImplementFormationManeuver(m_vVector, NullVector, m_iAngle);
				}

			ImplementFireOnTargetsOfOpportunity(m_pTarget);
			break;
			}

		case stateKeepFormation:
			ImplementKeepFormation();
			ImplementFireOnTargetsOfOpportunity();
			ImplementFireOnNearestTarget();
			break;

		case stateOnCourseForDocking:
			ASSERT(m_pDest);
			ImplementDocking(m_pDest);
			ImplementFireOnTargetsOfOpportunity();
			ImplementFireOnNearestTarget();
			break;

		case stateOnCourseForStargate:
			ASSERT(m_pDest);
			ImplementGating(m_pDest);
			ImplementFireOnTargetsOfOpportunity();
			ImplementFireOnNearestTarget();
			break;

		case stateOnPatrolOrbit:
			ASSERT(m_pDest);
			ImplementOrbit(m_pDest, PATROL_ORBIT_DIST);
			ImplementAttackNearestTarget(m_rMaxWeaponRange, &m_pTarget, m_pDest);
			ImplementFireOnTargetsOfOpportunity(NULL, m_pDest);

			//	Check to see if any enemy ships appear

			if (m_pShip->IsDestinyTime(30))
				{
				CSpaceObject *pPrincipal = GetCurrentOrderTarget();
				CSpaceObject *pTarget = CalcEnemyShipInRange(pPrincipal, PATROL_SENSOR_RANGE, m_pDest);
				if (pTarget)
					{
					SetState(stateAttackOnPatrol);
					m_pTarget = pTarget;
					ASSERT(m_pTarget->DebugIsValid() && m_pTarget->NotifyOthersWhenDestroyed());
					}
				}
			break;
		}
	}