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

📄 aaiunittable.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
字号:
// -------------------------------------------------------------------------
// AAI
//
// A skirmish AI for the TA Spring engine.
// Copyright Alexander Seizinger
// 
// Released under GPL license: see LICENSE.html for more information.
// -------------------------------------------------------------------------

#include "AAIUnitTable.h"
#include "AAI.h"

AAIUnitTable::AAIUnitTable(AAI *ai, AAIBuildTable *bt)
{
	this->ai = ai;
	this->bt = bt;
	this->cb = ai->cb;

//	units = new AAIUnit[cfg->MAX_UNITS];
	units.resize(cfg->MAX_UNITS);

	// fill buildtable 
	for(int i = 0; i < cfg->MAX_UNITS; i++)
	{
		units[i].unit_id = -1;
		units[i].def_id = 0;
		units[i].group = 0;
		units[i].cons = 0;
		units[i].status = UNIT_KILLED;
	}

	cmdr = -1;
}

AAIUnitTable::~AAIUnitTable(void)
{
	// delete constructors
	for(set<int>::iterator cons = constructors.begin(); cons != constructors.end(); ++cons)
	{
		delete units[*cons].cons;
	}

//	delete [] units;
}


bool AAIUnitTable::AddUnit(int unit_id, int def_id, AAIGroup *group, AAIConstructor *cons)
{
	if(unit_id <= cfg->MAX_UNITS)
	{
		// clear possible enemies that are still listed (since they had been killed outside of los)
		if(units[unit_id].status == ENEMY_UNIT)
		{
			if(units[unit_id].group)
				units[unit_id].group->TargetUnitKilled();
		}
		else if(units[unit_id].status == BOMB_TARGET)
		{
			ai->af->RemoveTarget(unit_id);

			if(units[unit_id].group)
				units[unit_id].group->TargetUnitKilled();
		}

		units[unit_id].unit_id = unit_id;
		units[unit_id].def_id = def_id;
		units[unit_id].group = group;
		units[unit_id].cons = cons;
		units[unit_id].status = UNIT_IDLE;
		return true;
	}
	else
	{
		fprintf(ai->file, "ERROR: AAIUnitTable::AddUnit() index %i out of range", unit_id);
		return false;
	}
}

void AAIUnitTable::RemoveUnit(int unit_id)
{
	if(unit_id <= cfg->MAX_UNITS)
	{
		units[unit_id].unit_id = -1;
		units[unit_id].def_id = 0;
		units[unit_id].group = 0;
		units[unit_id].cons = 0;
		units[unit_id].status = UNIT_KILLED;
	}
	else
	{
		fprintf(ai->file, "ERROR: AAIUnitTable::RemoveUnit() index %i out of range", unit_id);
	}
}

void AAIUnitTable::AddConstructor(int unit_id, int def_id)
{
	bool factory;
	bool builder;
	bool assister;

	if(bt->units_static[def_id].unit_type & UNIT_TYPE_FACTORY)
		factory = true;
	else 
		factory = false;

	if(bt->units_static[def_id].unit_type & UNIT_TYPE_BUILDER)
		builder = true;
	else 
		builder = false;

	if(bt->units_static[def_id].unit_type & UNIT_TYPE_ASSISTER)
		assister = true;
	else 
		assister = false;

	AAIConstructor *cons = new AAIConstructor(ai, unit_id, def_id, factory, builder, assister);
	
	constructors.insert(unit_id);
	units[unit_id].cons = cons;

	// increase/decrease number of available/requested builders for all buildoptions of the builder
	for(list<int>::iterator unit = bt->units_static[def_id].canBuildList.begin();  unit != bt->units_static[def_id].canBuildList.end(); ++unit)	
	{	
		bt->units_dynamic[*unit].buildersAvailable += 1;
		bt->units_dynamic[*unit].buildersRequested -= 1;
	}

	if(builder)
	{
		--ai->futureBuilders;
		++ai->activeBuilders;
	}

	if(factory && bt->IsStatic(def_id))
	{
		--ai->futureFactories;
		++ai->activeFactories;

		// remove future ressource demand now factory has been finished
		ai->execute->futureRequestedMetal -= bt->units_static[def_id].efficiency[0];
		ai->execute->futureRequestedEnergy -= bt->units_static[def_id].efficiency[1];
	}
}

void AAIUnitTable::RemoveConstructor(int unit_id, int def_id)
{
	if(units[unit_id].cons->builder)
		--ai->activeBuilders;

	if(units[unit_id].cons->factory)
		--ai->activeFactories;
	
	// decrease number of available builders for all buildoptions of the builder
	for(list<int>::iterator unit = bt->units_static[def_id].canBuildList.begin();  unit != bt->units_static[def_id].canBuildList.end(); ++unit)		
		bt->units_dynamic[*unit].buildersAvailable -= 1;

	// erase from builders list
	constructors.erase(unit_id);

	// clean up memory
	units[unit_id].cons->Killed();
	delete units[unit_id].cons;
	units[unit_id].cons = 0;
}

void AAIUnitTable::AddCommander(int unit_id, int def_id)
{
	bool factory;
	bool builder;
	bool assister;

	if(bt->units_static[def_id].unit_type & UNIT_TYPE_FACTORY)
		factory = true;
	else 
		factory = false;

	if(bt->units_static[def_id].unit_type & UNIT_TYPE_BUILDER)
		builder = true;
	else 
		builder = false;

	if(bt->units_static[def_id].unit_type & UNIT_TYPE_ASSISTER)
		assister = true;
	else 
		assister = false;

	AAIConstructor *cons = new AAIConstructor(ai, unit_id, def_id, factory, builder, assister);
	constructors.insert(unit_id);
	units[unit_id].cons = cons;

	cmdr = unit_id;

	// increase number of builders for all buildoptions of the commander 
	for(list<int>::iterator unit = bt->units_static[def_id].canBuildList.begin();  unit != bt->units_static[def_id].canBuildList.end(); ++unit)		
		++bt->units_dynamic[*unit].buildersAvailable;
	
}

void AAIUnitTable::RemoveCommander(int unit_id, int def_id)
{
	// decrease number of builders for all buildoptions of the commander 
	for(list<int>::iterator unit = bt->units_static[def_id].canBuildList.begin();  unit != bt->units_static[def_id].canBuildList.end(); ++unit)	
		--bt->units_dynamic[*unit].buildersAvailable;

	// erase from builders list
	constructors.erase(unit_id);

	// clean up memory
	units[unit_id].cons->Killed();
	delete units[unit_id].cons;
	units[unit_id].cons = 0;
			
	// commander has been destroyed, set pointer to zero 
	if(unit_id == cmdr)
		cmdr = -1;
}

void AAIUnitTable::AddExtractor(int unit_id)
{
	extractors.insert(unit_id);
}

void AAIUnitTable::RemoveExtractor(int unit_id)
{
	// delete mex from list
	extractors.erase(unit_id);
}

void AAIUnitTable::AddPowerPlant(int unit_id, int def_id)
{
	power_plants.insert(unit_id);

	float output = bt->units_static[def_id].efficiency[0];
			
	ai->execute->futureAvailableEnergy -= output;

	if(output > ai->brain->best_power_plant_output)
		ai->brain->best_power_plant_output = output; 
}

void AAIUnitTable::RemovePowerPlant(int unit_id)
{
	power_plants.erase(unit_id);
}

void AAIUnitTable::AddMetalMaker(int unit_id, int def_id)
{
	metal_makers.insert(unit_id);
	ai->execute->futureRequestedEnergy -= bt->unitList[def_id-1]->energyUpkeep;
}

void AAIUnitTable::RemoveMetalMaker(int unit_id)
{
	if(!cb->IsUnitActivated(unit_id))
		--ai->execute->disabledMMakers;

	metal_makers.erase(unit_id);
}

void AAIUnitTable::AddRecon(int unit_id, int def_id)
{
	recon.insert(unit_id);
	
	ai->execute->futureRequestedEnergy -= bt->units_static[def_id].efficiency[0];
}

void AAIUnitTable::RemoveRecon(int unit_id)
{
	recon.erase(unit_id);
}

void AAIUnitTable::AddJammer(int unit_id, int def_id)
{
	jammers.insert(unit_id);

	ai->execute->futureRequestedEnergy -= bt->units_static[def_id].efficiency[0];
}

void AAIUnitTable::RemoveJammer(int unit_id)
{
	jammers.erase(unit_id);
}

void AAIUnitTable::AddStationaryArty(int unit_id, int def_id)
{
	stationary_arty.insert(unit_id);
}

void AAIUnitTable::RemoveStationaryArty(int unit_id)
{
	stationary_arty.erase(unit_id);
}

AAIConstructor* AAIUnitTable::FindBuilder(int building, bool commander, int importance)
{	
	//fprintf(ai->file, "constructor for %s\n", bt->GetCategoryString(building));
	AAIConstructor *builder;

	// look for idle builder
	for(set<int>::iterator i = constructors.begin(); i != constructors.end(); ++i)
	{
		// check all builders
		if(units[*i].cons->builder)
		{
			builder = units[*i].cons;

			// find unit that can directly build that building 
			if(builder->task != BUILDING && bt->CanBuildUnit(builder->def_id, building))
			{
				//if(bt->units_static[building].category == STATIONARY_JAMMER)
				//	fprintf(ai->file, "%s can build %s\n", bt->unitList[builder->def_id-1]->humanName.c_str(), bt->unitList[building-1]->humanName.c_str()); 

				// filter out commander (if not allowed)
				if(! (!commander &&  bt->IsCommander(builder->def_id)) )
					return builder;
			}
		}
	}
	
	// no builder found 
	return 0;
}

AAIConstructor* AAIUnitTable::FindClosestBuilder(int building, float3 pos, bool commander, int importance)
{	
	float min_dist = 1000000, my_dist;
	AAIConstructor *best_builder = 0, *builder;
	float3 builder_pos;

	// look for idle builder
	for(set<int>::iterator i = constructors.begin(); i != constructors.end(); ++i)
	{
		// check all builders
		if(units[*i].cons->builder)
		{
			builder = units[*i].cons;
				
			// find idle or assisting builder, who can build this building
			if(  builder->task != BUILDING && bt->CanBuildUnit(builder->def_id, building)) 
			{
				// filter out commander
				if(!commander &&  bt->IsCommander(builder->def_id))
					my_dist = 1000000;
				else
				{
					builder_pos = cb->GetUnitPos(builder->unit_id);

					if(pos.x > 0)
					{
						my_dist = sqrt(pow(builder_pos.x - pos.x, 2)+pow(builder_pos.z - pos.z, 2));
					
						if(bt->unitList[builder->def_id-1]->speed > 0)
							my_dist /= bt->unitList[builder->def_id-1]->speed;
					}
					else
						my_dist = 1000000;	
				}
			
				if(my_dist < min_dist)
				{
					best_builder = builder;
					min_dist = my_dist;
				}
			}
		}
	}
		
	return best_builder;
}

AAIConstructor* AAIUnitTable::FindClosestAssister(float3 pos, int importance, bool commander, bool water, bool floater)
{
	AAIConstructor *best_assister = 0, *assister;
	float best_rating = 0, my_rating;
	float3 builder_pos;
	bool suitable;
	UnitCategory category;
	float temp;

	// find idle builder
	for(set<int>::iterator i = constructors.begin(); i != constructors.end(); ++i)
	{
		// check all assisters
		if(units[*i].cons->assistant)
		{
			assister = units[*i].cons;

			if(assister->task == UNIT_IDLE)
			{
				category = bt->units_static[assister->def_id].category;
				suitable = false;

				if(!water && bt->CanMoveLand(assister->def_id))
					suitable = true;
				else if(water && floater && bt->CanMoveWater(assister->def_id))
					suitable = true;
				else if(water && !floater && bt->IsSea(assister->def_id))
					suitable = true;

				if(!commander && bt->units_static[assister->def_id].category == COMMANDER)
					suitable = false;

				if(suitable)
				{
					builder_pos = cb->GetUnitPos(assister->unit_id);
					temp = pow(pos.x - builder_pos.x, 2) + pow(pos.z - builder_pos.z, 2);
				
					if(temp > 0)
						my_rating = assister->buildspeed / sqrt(temp);
					else
						my_rating = 10;
		
					if(my_rating > best_rating)
					{
						best_rating = my_rating;
						best_assister = assister;
					}
				}
			}
		}
	}
		
	// no builder found 
	if(!best_assister)
	{
		bt->AddAssister(water, floater, true);
	}

	return best_assister;
}

bool AAIUnitTable::IsUnitCommander(int unit_id)
{
	if(cmdr != -1)
		return false;
	else if(cmdr == unit_id)
		return true;
	else
		return false;
}

bool AAIUnitTable::IsDefCommander(int def_id)
{
	for(int s = 0; s < cfg->SIDES; ++s)
	{
		if(bt->startUnits[s] == def_id)
			return true;
	}

	return false;
}

void AAIUnitTable::EnemyKilled(int unit)
{
	if(units[unit].status == BOMB_TARGET)
		ai->af->RemoveTarget(unit);
	

	if(units[unit].group)
		units[unit].group->TargetUnitKilled();

	RemoveUnit(unit);
}

void AAIUnitTable::AssignGroupToEnemy(int unit, AAIGroup *group)
{
	units[unit].unit_id = unit;
	units[unit].group = group;
	units[unit].status = ENEMY_UNIT;
}


void AAIUnitTable::SetUnitStatus(int unit, UnitTask status)
{
	units[unit].status = status;
}

bool AAIUnitTable::IsBuilder(int unit_id)
{
	if(units[unit_id].cons && units[unit_id].cons->builder)
		return true;
	else
		return false;
}

⌨️ 快捷键说明

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