void AiForce::Attack(const Vec2i &pos) { RemoveDeadUnit(); if (Units.size() == 0) { this->Attacking = false; return; } if (!this->Attacking) { // Remember the original force position so we can return there after attack if (this->Role == AiForceRoleDefend || (this->Role == AiForceRoleAttack && this->State == AiForceAttackingState_Waiting)) { this->HomePos = this->Units[this->Units.size() - 1]->tilePos; } this->Attacking = true; } Vec2i goalPos(pos); if (Map.Info.IsPointOnMap(goalPos) == false) { /* Search in entire map */ const CUnit *enemy = NULL; AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &enemy); if (enemy) { goalPos = enemy->tilePos; } } this->GoalPos = goalPos; if (Map.Info.IsPointOnMap(goalPos) == false) { DebugPrint("%d: Need to plan an attack with transporter\n" _C_ AiPlayer->Player->Index); if (State == AiForceAttackingState_Waiting && !PlanAttack()) { DebugPrint("%d: Can't transport\n" _C_ AiPlayer->Player->Index); Attacking = false; } return; } // Send all units in the force to enemy. this->State = AiForceAttackingState_Attacking; for (size_t i = 0; i != this->Units.size(); ++i) { CUnit *const unit = this->Units[i]; if (unit->Container == NULL) { const int delay = i / 5; // To avoid lot of CPU consuption, send them with a small time difference. unit->Wait = delay; if (unit->Type->CanAttack) { CommandAttack(*unit, goalPos, NULL, FlushCommands); } else { CommandMove(*unit, goalPos, FlushCommands); } } } }
void AiForce::Attack(const Vec2i &pos) { bool isDefenceForce = false; RemoveDeadUnit(); if (Units.size() == 0) { this->Attacking = false; this->State = AiForceAttackingState_Waiting; return; } if (!this->Attacking) { // Remember the original force position so we can return there after attack if (this->Role == AiForceRoleDefend || (this->Role == AiForceRoleAttack && this->State == AiForceAttackingState_Waiting)) { this->HomePos = this->Units[this->Units.size() - 1]->tilePos; } this->Attacking = true; } Vec2i goalPos(pos); bool isNaval = false; for (size_t i = 0; i != this->Units.size(); ++i) { CUnit *const unit = this->Units[i]; if (unit->Type->UnitType == UnitTypeNaval && unit->Type->CanAttack) { isNaval = true; break; } } bool isTransporter = false; for (size_t i = 0; i != this->Units.size(); ++i) { CUnit *const unit = this->Units[i]; if (unit->Type->CanTransport() && unit->IsAgressive() == false) { isTransporter = true; break; } } if (Map.Info.IsPointOnMap(goalPos) == false) { /* Search in entire map */ const CUnit *enemy = NULL; if (isTransporter) { AiForceEnemyFinder<AIATTACK_AGRESSIVE>(*this, &enemy); } else if (isNaval) { AiForceEnemyFinder<AIATTACK_ALLMAP>(*this, &enemy); } else { AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &enemy); } if (enemy) { goalPos = enemy->tilePos; } } else { isDefenceForce = true; } if (Map.Info.IsPointOnMap(goalPos) == false || isTransporter) { DebugPrint("%d: Need to plan an attack with transporter\n" _C_ AiPlayer->Player->Index); if (State == AiForceAttackingState_Waiting && !PlanAttack()) { DebugPrint("%d: Can't transport\n" _C_ AiPlayer->Player->Index); Attacking = false; } return; } if (this->State == AiForceAttackingState_Waiting && isDefenceForce == false) { Vec2i resultPos; NewRallyPoint(goalPos, &resultPos); this->GoalPos = resultPos; this->State = AiForceAttackingState_GoingToRallyPoint; } else { this->GoalPos = goalPos; this->State = AiForceAttackingState_Attacking; } // Send all units in the force to enemy. CUnit *leader = NULL; for (size_t i = 0; i != this->Units.size(); ++i) { CUnit *const unit = this->Units[i]; if (unit->IsAgressive()) { leader = unit; break; } } for (size_t i = 0; i != this->Units.size(); ++i) { CUnit *const unit = this->Units[i]; if (unit->Container == NULL) { const int delay = i / 5; // To avoid lot of CPU consuption, send them with a small time difference. unit->Wait = delay; if (unit->IsAgressive()) { CommandAttack(*unit, this->GoalPos, NULL, FlushCommands); } else { if (leader) { CommandDefend(*unit, *leader, FlushCommands); } else { CommandMove(*unit, this->GoalPos, FlushCommands); } } } } }