bool CUnitHandler::BuildTaskAddBuilder(int builderID, UnitCategory category) { assert(category < CAT_LAST); assert(builderID >= 0); assert(ai->GetUnit(builderID) != NULL); CUNIT* u = ai->GetUnit(builderID); BuilderTracker* builderTracker = GetBuilderTracker(builderID); const UnitDef* builderDef = ai->cb->GetUnitDef(builderID); const int frame = ai->cb->GetCurrentFrame(); // make sure this builder is free const bool b1 = (builderTracker->taskPlanId == 0); const bool b2 = (builderTracker->buildTaskId == 0); const bool b3 = (builderTracker->factoryId == 0); const bool b4 = builderDef->canAssist; const bool b5 = (category == CAT_FACTORY && frame >= 18000); if (!b1 || !b2 || !b3 || !b4) { if (b5) { // note that FactoryBuilderAdd() asserts b1 through b4 // immediately after BuildTaskAddBuilder() is tried and // fails in BuildUp(), so at least those must be true // (and so should b5 in most of the *A mods) std::stringstream msg; msg << "[CUnitHandler::BuildTaskAddBuilder()][frame=" << frame << "]\n"; msg << "\tbuilder " << builderID << " not able to be added to CAT_FACTORY build-task\n"; msg << "\tb1: " << b1 << ", b2: " << b2 << ", b3: " << b3; msg << ", b4: " << b4 << ", b5: " << b5; ai->GetLogger()->Log(msg.str()); } return false; } // see if there are any BuildTasks that it can join if (BuildTasks[category].size() > 0) { float largestTime = 0.0f; std::list<BuildTask>::iterator task; std::list<BuildTask>::iterator bestTask; for (task = BuildTasks[category].begin(); task != BuildTasks[category].end(); task++) { float buildTime = ai->math->ETT(*task) - ai->math->ETA(builderID, ai->cb->GetUnitPos(task->id)); if (buildTime > largestTime) { largestTime = buildTime; bestTask = task; } } if (largestTime > 0.0f) { BuildTaskAddBuilder(&*bestTask, builderTracker); u->Repair(bestTask->id); return true; } } // see if there any joinable TaskPlans if (TaskPlans[category].size() > 0) { float largestTime = 0.0f; std::list<TaskPlan>::iterator plan; std::list<TaskPlan>::iterator bestPlan; for (plan = TaskPlans[category].begin(); plan != TaskPlans[category].end(); plan++) { float buildTime = (plan->def->buildTime / plan->currentBuildPower) - ai->math->ETA(builderID, plan->pos); // must test if this builder can make this unit/building too if (buildTime > largestTime) { const std::vector<int>* canBuildList = &ai->ut->unitTypes[builderDef->id].canBuildList; const int buildListSize = canBuildList->size(); for (int j = 0; j < buildListSize; j++) { if (canBuildList->at(j) == plan->def->id) { largestTime = buildTime; bestPlan = plan; break; } } } } if (largestTime > 10.0f) { assert(builderID >= 0); // bad, CUNIT::Build() uses TaskPlanCreate() // should we really give build orders here? // return u->Build(bestPlan->pos, bestPlan->def, -1); // TaskPlanCreate(builderID, bestPlan->pos, bestPlan->def); return true; } } if (b5) { std::stringstream msg; msg << "[CUnitHandler::BuildTaskAddBuilder()][frame=" << frame << "]\n"; msg << "\tno joinable CAT_FACTORY build-tasks or task-plans for builder " << builderID; ai->GetLogger()->Log(msg.str()); } return false; }