⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aaiconstructor.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#include "aidef.h"
#include "AAI.h"
#include "AAIConstructor.h"
#include "AAIBuildTask.h"

AAIConstructor::AAIConstructor(AAI *ai, int unit_id, int def_id, bool factory, bool builder, bool assistant)
{
	this->ai = ai;
	cb = ai->cb;
	bt = ai->bt;

	this->unit_id = unit_id;
	this->def_id = def_id;
	buildspeed = ai->bt->unitList[def_id-1]->buildSpeed;

	construction_unit_id = -1;
	construction_def_id = 0;
	construction_category = UNKNOWN;

	assistance = -1;
	build_task = 0;
	order_tick = 0;

	task = UNIT_IDLE;

	build_pos = ZeroVector;

	this->factory = factory;
	this->builder = builder;
	this->assistant = assistant;

	buildque = ai->execute->GetBuildqueOfFactory(def_id);
}

AAIConstructor::~AAIConstructor(void)
{
}

// returns true if factory is busy
bool AAIConstructor::IsBusy()
{
	const CCommandQueue *commands = ai->cb->GetCurrentUnitCommands(unit_id);

	if(commands->empty())
		return false;
	return true;
}

void AAIConstructor::Idle()
{
	//char c[80];
	//sprintf(c, "%s is idle", bt->unitList[def_id-1]->humanName.c_str());
	//cb->SendTextMsg(c, 0);

	if(builder)
	{
		if(task == BUILDING)
		{
			if(construction_unit_id == -1)
			{
				//cb->SendTextMsg("construction aborted", 0);

				ai->bt->units_dynamic[construction_def_id].active -= 1;
				--ai->futureUnits[construction_category];

				// clear up buildmap etc.
				ai->execute->ConstructionFailed(build_pos, construction_def_id);

				// free builder
				ConstructionFinished();
			}
		}
		else if(task != UNIT_KILLED)
		{
			task = UNIT_IDLE;
			assistance = -1;

			ReleaseAllAssistants();
		}
	}
	
	if(factory)
	{
		ConstructionFinished();

		Update();
	}
}

void AAIConstructor::Update()
{
	if(factory)
	{
		if(!construction_def_id && !buildque->empty())
		{
			int def_id = (*buildque->begin());
			UnitCategory cat = ai->bt->units_static[def_id].category;

			if(ai->bt->IsBuilder(def_id) || cat == SCOUT || ai->cb->GetMetal() > 50 
				|| ai->bt->units_static[def_id].cost < ai->bt->avg_cost[ai->bt->units_static[def_id].category][ai->side-1])
			{
				// check if mobile or stationary builder
				if(bt->IsStatic(this->def_id))
				{
					// give build order
					Command c;
					c.id = -def_id;
					ai->cb->GiveOrder(unit_id, &c);
					construction_def_id = def_id;

					++ai->futureUnits[cat];

					//if(bt->IsFactory(def_id))
					//	++ai->futureFactories;

					buildque->pop_front();
				}
				else
				{
					// find buildpos for the unit
					float3 pos = ai->execute->GetUnitBuildsite(unit_id, def_id);
				
					if(pos.x > 0)
					{
						// give build order
						Command c;
						c.id = -def_id;
						c.params.resize(3);
						c.params[0] = pos.x;
						c.params[1] = pos.y;
						c.params[2] = pos.z;

						ai->cb->GiveOrder(unit_id, &c);
						construction_def_id = def_id;

						++ai->futureUnits[cat];

						//if(bt->IsFactory(def_id))
						//	++ai->futureFactories;

						buildque->pop_front();
					}
				}
			}
		}

		CheckAssistance();
	}
	
	if(builder)
	{
		if(task == BUILDING)
		{
			// if building has begun, check for possible assisters
			if(construction_unit_id >= 0) 
				CheckAssistance();
			// if building has not yet begun, check if something unexpected happened (buildsite blocked)
			else
			{
				if(!IsBusy() && construction_unit_id == -1)
				{
					//cb->SendTextMsg("idle", 0);
					ai->bt->units_dynamic[construction_def_id].active -= 1;
					ai->futureUnits[construction_category] -= 1;
	
					// clear up buildmap etc.
					ai->execute->ConstructionFailed(build_pos, construction_def_id);

					// free builder
					ConstructionFinished();
				}
			}
		}
		else if(task == UNIT_IDLE)
		{
			float3 pos = cb->GetUnitPos(unit_id);

			if(pos.x > 0)
			{
				int x = pos.x/ai->map->xSectorSize;
				int y = pos.z/ai->map->ySectorSize;

				if(x >= 0 && y >= 0 && x < ai->map->xSectors && y < ai->map->ySectors)
				{
					if(ai->map->sector[x][y].distance_to_base < 2)
					{
						pos = ai->map->sector[x][y].GetCenter();

						Command c;
						const UnitDef *def;

						def = cb->GetUnitDef(unit_id);
						// can this thing resurrect? If so, maybe we should raise the corpses instead of consuming them?
						if(def->canResurrect)
						{
							if(rand()%2 == 1)
							{
								c.id = CMD_RESURRECT;
							} else
							{
								c.id = CMD_RECLAIM;
							}
						} else {
							c.id = CMD_RECLAIM;
						}
						c.params.resize(4);
						c.params[0] = pos.x;
						c.params[1] = cb->GetElevation(pos.x, pos.z);
						c.params[2] = pos.z;
						c.params[3] = 500.0;

						cb->GiveOrder(unit_id, &c);
						task = RECLAIMING;
					}
				}
			}
		}
	}
}

void AAIConstructor::CheckAssistance()
{
	if(factory)
	{
		// check if another factory of that type needed
		if(buildque->size() >= cfg->MAX_BUILDQUE_SIZE - 1 && assistants.size() >= cfg->MAX_ASSISTANTS-1)
		{
			if(ai->bt->units_dynamic[def_id].active < cfg->MAX_FACTORIES_PER_TYPE && ai->bt->units_dynamic[def_id].requested <= 0)
			{
				ai->bt->units_dynamic[def_id].requested += 1;

				if(ai->execute->urgency[STATIONARY_CONSTRUCTOR] < 1)
					ai->execute->urgency[STATIONARY_CONSTRUCTOR] = 1;

				for(list<int>::iterator j = bt->units_static[def_id].canBuildList.begin(); j != bt->units_static[def_id].canBuildList.end(); ++j)
					bt->units_dynamic[*j].buildersRequested += 1;
			}
		}
		
		// check if support needed
		if(assistants.size() < cfg->MAX_ASSISTANTS)
		{
			bool assist = false;

			if(buildque->size() > 2)
				assist = true;
			else if(construction_def_id && (bt->unitList[construction_def_id-1]->buildTime/(30.0f * bt->unitList[def_id-1]->buildSpeed) > cfg->MIN_ASSISTANCE_BUILDTIME)) 
				assist = true;
		
			if(assist)
			{
				AAIConstructor* assistant;

				// call idle builder
				if(bt->CanPlacedWater(def_id))
				{
					if(ai->bt->unitList[def_id-1]->floater)
						assistant = ai->ut->FindClosestAssister(ai->cb->GetUnitPos(unit_id), 5, true, true, true);
					else
						assistant = ai->ut->FindClosestAssister(ai->cb->GetUnitPos(unit_id), 5, true, true, false);
				}
				else
					assistant = ai->ut->FindClosestAssister(ai->cb->GetUnitPos(unit_id), 5, true, false, false);

				if(assistant)
				{
					assistants.insert(assistant->unit_id);
					assistant->AssistConstruction(unit_id);
				}
			}
		}
		// check if assistants are needed anymore
		else if(!assistants.empty() && buildque->empty() && !construction_def_id)
		{
			//cb->SendTextMsg("factory releasing assistants",0);
			ReleaseAllAssistants();
		}
	
	}

	if(builder && build_task)
	{
		// prevent assisting when low on ressources
		if(ai->execute->averageMetalSurplus < 0.1)
		{	
			if(construction_category == METAL_MAKER)
			{
				if(ai->execute->averageEnergySurplus < 0.5 * ai->bt->unitList[construction_def_id-1]->energyUpkeep)
					return;
			}
			else if(construction_category != EXTRACTOR && construction_category != POWER_PLANT)
				return;
		}

		float buildtime = ai->bt->unitList[construction_def_id-1]->buildTime / ai->bt->unitList[def_id-1]->buildSpeed;

		if(buildtime > cfg->MIN_ASSISTANCE_BUILDTIME && assistants.size() < cfg->MAX_ASSISTANTS)
		{
			// com only allowed if buildpos is inside the base
			bool commander = false;
	
			int x = build_pos.x / ai->map->xSectorSize;
			int y = build_pos.z / ai->map->ySectorSize;

			if(x >= 0 && y >= 0 && x < ai->map->xSectors && y < ai->map->ySectors)
			{
				if(ai->map->sector[x][y].distance_to_base == 0)
					commander = true;
			}

			AAIConstructor* assistant; 

			// call idle builder
			if(ai->bt->unitList[construction_def_id-1]->minWaterDepth > 0)
				assistant = ai->ut->FindClosestAssister(build_pos, 5, commander, true, ai->bt->unitList[construction_def_id-1]->floater);
			else
				assistant = ai->ut->FindClosestAssister(build_pos, 5, commander, false, false);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -