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");
}
Example #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);
	}
}
Example #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;
}
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;
}
void BuildHandler::OrderNewBuilder()
{
	float bestScore;
	int best=0;

	for (int a=0;a<builderTypes.size();a++)
	{
		assert (builderTypes[a]);
		BuildTable::UDef *cd = buildTable.GetCachedDef (builderTypes[a]);

		if (cd->IsBuilding())
			continue;

		// Find the best unit we can use to build this builder
		const vector<int>& bb = *cd->buildby;
		int numBuilders=0;

		for (int i=0;i<bb.size();i++)
		{
			int n = currentBuilders [bb[i]];
			numBuilders += abs(n) + (n<0)?2:0; // an inactive builder equals 2 extra active builders
		}

		float score = std::min((1+numBuilders),3) * sqrtf(cd->numBuildOptions) * cd->buildSpeed / ai->ResourceValue(cd->cost);
		if (!best || score > bestScore)
		{
			best = builderTypes[a];
			bestScore = score;
		}
	}

	if (best)
	{
		aiTask *t = AddTask (buildTable.GetDef (best),-1);
		ChatDebugPrintf (ai->cb, "Added task to increase build speed: %s\n", t->def->name.c_str());
	}
}
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;
}
void BuildHandler::FindNewJob (BuildUnit *u)
{
	BuildTable::UDef *cd = buildTable.GetCachedDef (u->def->id);
	int curFrame=ai->cb->GetCurrentFrame();

	if (cd->IsBuilding ()) {
		// factory - find a task that is not yet initialized

		for (int a=0;a<tasks.size();a++) {
			aiTask *t = tasks[a];

			if (!t->depends && t->constructors.empty () && 
				!t->IsBuilding() && buildTable.UnitCanBuild (u->def,t->def))
			{
				SetBuilderToTask (u, t);
				return;
			}
		}
	} else {
		// mobile builder
		float3 builderPos = ai->cb->GetUnitPos(u->id);
		const UnitDef *ud = u->def;
		aiTask *best=0;
		float bestScore;
		float moveSpeed = ai->cb->GetUnitSpeed (u->id);

		for(int a=0;a<tasks.size();a++)
		{
			aiTask *t = tasks[a];

			if (t->depends || !t->AreResourcesAllocated())
				continue;

			float hp = t->unit ? ai->cb->GetUnitHealth(t->unit->id) : 0.0f;
			float buildTimeLeft = u->def->buildTime*((u->def->health-hp)/u->def->health);

			 //can we build this directly or is there someone who can start it for us
			bool canBuildThis=buildTable.UnitCanBuild (u->def, t->def) ;
			if (canBuildThis || t->lead)
			{
				float buildTime=buildTimeLeft/(t->buildSpeed+ud->buildSpeed);
				float distance=0.0f;
				if (t->lead || t->def->extractsMetal) distance = (t->pos-builderPos).Length(); // position has been estimated for metal extractors
				else distance = 40 * SQUARE_SIZE; // assume a constant distance
				float moveTime=max(0.01f,(distance-150)/moveSpeed*10);
				float travelMod=buildTime/(buildTime+moveTime);			//units prefer stuff with low travel time compared to build time
				float finishMod=t->def->buildTime/(buildTimeLeft+t->def->buildTime*0.1f);			//units prefer stuff that is nearly finished
				float canBuildThisMod=canBuildThis?1.5f:1;								//units prefer to do stuff they have in their build options (less risk of guarded unit dying etc)
				float ageMod=20+sqrtf((float)(curFrame+1)-t->startFrame);
//				float buildSpeedMod=info->buildSpeed/(qb->totalBuildSpeed+info->buildSpeed);
				float score=finishMod*canBuildThisMod*travelMod*ageMod;

				if(!best||score>bestScore)
				{
					bestScore=score;
					best = t;
				}
			}
		}

		if (best)
			SetBuilderToTask (u, best);
	}
}
Example #10
0
void BuildTask::InitializeLeadBuilder (CGlobals *g)
{
    BuildUnit *leadc = 0;// lead builder candidate

    assert (!constructors.empty());
    assert (!lead);

    // Find a new lead builder
    for (int a=0; a<constructors.size(); a++)
    {
        BuildUnit *b = constructors [a];
        if (constructors[a]->tasks.front () != this)
            continue;

        if (buildTable.UnitCanBuild (b->def, def))
        {
            leadc = b;
            break;
        }
    }

    if (!leadc) // No candidate for lead builder?
    {
        for (int a=0; a<constructors.size(); a++)
        {
            BuildUnit *u = constructors[a];
            DeleteDeathDependence (u);

            u->DependentDied (this);
            u->DeleteDeathDependence (this);
        }
        constructors.clear();
        buildSpeed = 0.0f;
        return;
    }

    float3 builderPos = g->cb->GetUnitPos (leadc->id);

    Command c;
    BuildTable::UDef* cd = buildTable.GetCachedDef (def->id);
    if (cd->IsBuilding())
    {
        if (def->extractsMetal && spotID>=0)
        {
            MetalSpot *spot = g->metalmap->GetSpot (spotID);
            if (spot->unit)
            {
                assert (spot->unit->def->extractsMetal < def->extractsMetal);

                // create a reclaim task and make this depends on the reclaim task
                ReclaimUnitTask *rt = new ReclaimUnitTask;
                g->taskManager->AddTask (rt);

                AddDeathDependence (rt);
                depends = rt;

                rt->SetReclaimTarget (spot->unit);
                return;
            }
        }

        if (pos.x < 0.0f) {
            if (!SetupBuildLocation (g))
                return;
        }

        c.params.resize(3);
        c.params[0]=pos.x;
        c.params[1]=pos.y;
        c.params[2]=pos.z;

        if (aiConfig.debug)
            g->cb->DrawUnit (def->name.c_str(), pos, 0.0f, 800, g->cb->GetMyTeam(), true, true);
    } else
        pos = builderPos;

    c.id = -def->id;
    g->cb->GiveOrder (leadc->id, &c);
    lead = leadc;
}