📄 aaiconstructor.cpp
字号:
#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 + -