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; } } }
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; } }
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); } }
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; } }