void BuildHandler::AddTask (aiTask *task) { tasks.add(task); if (task->resourceType>=0) ai->taskHandlers[task->resourceType]->AddTask (task); BuildTable::UDef *cd = buildTable.GetCachedDef (task->def->id); if (cd->IsBuilding ()) { task->flags |= BT_BUILDING; if (task->pos.x >= 0.0f) buildMap.Mark (task->def,task->pos,true); } if (cd->IsBuilder ()) task->MarkBuilder (); if (task->resourceType < 0) { TakeResources (ai->ResourceValue (task->def->energyCost, task->def->metalCost)); task->MarkAllocated (); } task->startFrame=ai->cb->GetCurrentFrame(); currentUnitBuilds[task->def->id-1] ++; ChatDebugPrintf (ai->cb, "Added task: %s (%s)", task->def->name.c_str(), task->resourceType >= 0 ? ai->taskHandlers[task->resourceType]->GetName() : "BuildHandler"); }
void BuildTask::Initialize (CGlobals *g) { if (resourceType>=0) { TaskFactory *tf = g->taskFactories [resourceType]; tf->AddTask (this); isAllocated = false; } else { g->resourceManager->TakeResources (g->resourceManager->ResourceValue (def->energyCost,def->metalCost)); isAllocated=true; } BuildTable::UDef *cd = buildTable.GetCachedDef (def->id); if (cd->IsBuilding ()) { flags |= BT_BUILDING; // Find a build position SetupBuildLocation (g); } if (cd->IsBuilder ()) MarkBuilder (); g->taskManager->currentUnitBuilds[def->id-1] ++; }
bool BuildHandler::DoInitialBuildOrders () { // initial build orders completed? assert (config.InitialOrders); if (initialBuildOrderTask) return true; for (int a=0;a<initialBuildOrderState.size();a++) { int &state = initialBuildOrderState[a]; if (state < config.InitialOrders->builds[a]->count) { int type=-1; int id=config.InitialOrders->builds[a]->def; BuildTable::UDef *cd = buildTable.GetCachedDef(id); CfgList* info = config.InitialOrders->builds[a]->info; const char *handler = info ? info->GetLiteral ("Handler") : 0; if (handler) { for (int h=0;h<NUM_TASK_TYPES;h++) { if(!STRCASECMP(handler, handlerStr[h])) { type=h; break; } } if (h == BTF_Force) { ChatMsgPrintf (ai->cb, "Error: No force units possible in the initial build orders.\n"); state=config.InitialOrders->builds[a]->count; return false; } } else { if(!cd->IsBuilder()) { ChatMsgPrintf (ai->cb, "Error in initial buildorder list: unit %s is not a builder\n", cd->name.c_str()); state=config.InitialOrders->builds[a]->count; return false; } } aiTask *t = initialBuildOrderTask = AddTask (buildTable.GetDef(id), type); t->MarkAllocated (); state ++; return true; } } // all initial build tasks are done if (!initialBuildOrdersFinished) { ChatDebugPrintf (ai->cb,"Initial build orders finished."); DistributeResources (); initialBuildOrdersFinished=true; } return false; }
void BuildHandler::InitBuilderTypes (const UnitDef* commdr) { for (int a=0;a<buildTable.numDefs;a++) { BuildTable::UDef *d = &buildTable.deflist [a]; // Builder? if (!d->IsBuilder() || d->IsShip()) continue; // Can it be build directly or indirectly? BuildPathNode& bpn = buildTable.GetBuildPath (commdr->id, a); if (bpn.id >= 0) builderTypes.push_back (a + 1); } }
// default version finds a build position in a safe sector that is not filled. bool BuildTask::InitBuildPos (CGlobals *g) { BuildTable::UDef* cd = buildTable.GetCachedDef (def->id); // Find a sector to build in float3 st (g->map->baseCenter.x, 0.0f, g->map->baseCenter.y); int2 sector = g->map->FindSafeBuildingSector (st, aiConfig.safeSectorRadius, cd->IsBuilder () ? BLD_FACTORY : 1); if (sector.x < 0) return false; // find a position for the unit float3 tpos = float3(sector.x+0.5f,0.0f,sector.y+0.5f)*g->map->mblocksize; if(!g->buildmap->FindBuildPosition (def, tpos, pos)) return false; return true; }
void BuildHandler::InitiateTask (aiTask *task) { BuildUnit *lead = 0; assert (!task->constructors.empty()); assert (!task->lead); // Find a new lead builder for (int a=0;a<task->constructors.size();a++) { BuildUnit *b = task->constructors [a]; if (task->constructors[a]->tasks.front () != task) continue; if (buildTable.UnitCanBuild (b->def, task->def)) { lead = b; break; } } if (!lead) { for (int a=0;a<task->constructors.size();a++) { BuildUnit *u = task->constructors[a]; task->DeleteDeathDependence (u); u->DependentDied (task); u->DeleteDeathDependence (task); } task->constructors.clear(); task->buildSpeed = 0.0f; return; } float3 builderPos = ai->cb->GetUnitPos (lead->id); Command c; BuildTable::UDef* cd = buildTable.GetCachedDef (task->def->id); if (cd->IsBuilding()) { if (!FindTaskBuildPos (task,lead)) return; c.params.resize(3); c.params[0]=task->pos.x; c.params[1]=task->pos.y; c.params[2]=task->pos.z; MapInfo *i = ai->map.GetMapInfo (task->pos); if (i)i->buildstate += cd->IsBuilder () ? BLD_FACTORY : 1; if (aiConfig.debug) ai->cb->DrawUnit (task->def->name.c_str(), task->pos, 0.0f, 800, ai->cb->GetMyTeam(), true, true); } else task->pos = builderPos; c.id = -task->def->id; ai->cb->GiveOrder (lead->id, &c); task->lead = lead; }
bool BuildHandler::FindTaskBuildPos (aiTask *t, BuildUnit*lead) { float3 pos; BuildTable::UDef* cd = buildTable.GetCachedDef (t->def->id); float3 builderPos = ai->cb->GetUnitPos (lead->id); // Find a sector to build in if (t->def->extractsMetal > 0) { while(1) { // Find an empty metal spot float3 st (ai->map.baseCenter.x, 0.0f, ai->map.baseCenter.y); int2 msect = ai->metalmap.GetEmptySpot (st, &ai->map, false); if(msect.x < 0) { // no spots left return false; } MetalSpotInfo *info = ai->metalmap.Get (msect.x,msect.y); pos = float3(info->spotpos.x, 0.0f, info->spotpos.y) * SQUARE_SIZE; if (buildMap.FindBuildPosition (t->def, pos, t->pos)) { ai->metalmap.MarkSpot (msect, true); pos = t->pos; // logPrintf ("Estimated metal production of extractor: %f\n", def->extractsMetal * info->metalProduction); break; } ai->metalmap.MarkSpot (msect, true);// spill the metalspot as it seems it can't be used anyway } } else // it's a non-metal extractor { int2 sector = ai->map.RequestSafeBuildingSector (builderPos, aiConfig.safeSectorRadius, cd->IsBuilder () ? BLD_FACTORY : 1); if (sector.x < 0) return false; // find a position for the unit pos = float3(sector.x+0.5f,0.0f,sector.y+0.5f)*ai->map.mblocksize; if(!buildMap.FindBuildPosition (t->def, pos, t->pos)) return false; pos = t->pos; } // Mark the unit on the buildmap buildMap.Mark (t->def, pos, true); return true; }