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