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");
}
Esempio n. 2
0
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);
	}
}
Esempio n. 5
0
// 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;
}