📄 aaiconstructor.cpp
字号:
if(assistant)
{
assistants.insert(assistant->unit_id);
assistant->AssistConstruction(unit_id, construction_unit_id);
}
}
}
}
double AAIConstructor::GetMyQueBuildtime()
{
double buildtime = 0;
for(list<int>::iterator unit = buildque->begin(); unit != buildque->end(); ++unit)
buildtime += bt->unitList[(*unit)-1]->buildTime;
return buildtime;
}
void AAIConstructor::GiveReclaimOrder(int unit_id)
{
if(assistance >= 0)
{
ai->ut->units[assistance].cons->RemoveAssitant(unit_id);
assistance = -1;
}
task = RECLAIMING;
Command c;
c.id = CMD_RECLAIM;
c.params.push_back(unit_id);
cb->GiveOrder(this->unit_id, &c);
}
void AAIConstructor::GiveConstructionOrder(int id_building, float3 pos, bool water)
{
// get def and final position
const UnitDef *def = ai->bt->unitList[id_building-1];
ai->map->Pos2FinalBuildPos(&pos, def);
build_pos = pos;
// determine target sector
int x = build_pos.x/ai->map->xSectorSize;
int y = build_pos.z/ai->map->ySectorSize;
// drop bad sectors (should only happen when defending mexes at the edge of the map)
if(x < 0 || y < 0 || x >= ai->map->xSectors || y >= ai->map->ySectors)
return;
order_tick = cb->GetCurrentFrame();
// check if builder was previously assisting other builders/factories
if(assistance >= 0)
{
ai->ut->units[assistance].cons->RemoveAssitant(unit_id);
assistance = -1;
}
// set building as current task and order construction
construction_def_id = id_building;
task = BUILDING;
construction_category = ai->bt->units_static[id_building].category;
// order builder to construct building
Command c;
c.id = - id_building;
c.params.resize(3);
c.params[0] = build_pos.x;
c.params[1] = build_pos.y;
c.params[2] = build_pos.z;
cb->GiveOrder(unit_id, &c);
// increase number of active units of that type/category
ai->bt->units_dynamic[def->id].active += 1;
ai->futureUnits[construction_category] += 1;
if(bt->IsFactory(id_building))
++ai->futureFactories;
// increase number of units of that category in the target sector
++ai->map->sector[x][y].unitsOfType[construction_category];
ai->map->sector[x][y].own_structures += ai->bt->units_static[construction_def_id].cost;
// update buildmap of sector
ai->map->Pos2BuildMapPos(&pos, def);
// factory
if(construction_category == STATIONARY_CONSTRUCTOR)
{
bool water = false;
int value = 1;
if(!bt->CanPlacedLand(id_building))
{
water = true;
value = 5;
}
ai->map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, value);
ai->map->BlockCells(pos.x, pos.z - 8, def->xsize, 8, true, water);
ai->map->BlockCells(pos.x + def->xsize, pos.z - 8, cfg->X_SPACE, def->ysize + 1.5 * cfg->Y_SPACE, true, water);
ai->map->BlockCells(pos.x, pos.z + def->ysize, def->xsize, 1.5 * cfg->Y_SPACE - 8, true, water);
}
// normal building
else
{
if(water)
ai->map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 5);
else
ai->map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 1);
}
// prevent ai from building too many things in a row
ai->map->CheckRows(pos.x, pos.z, def->xsize, def->ysize, true, water);
}
void AAIConstructor::AssistConstruction(int constructor, int target_unit)
{
if(target_unit == -1)
{
Command c;
// Check if the target can be assisted at all. If not, try to repair it instead
const UnitDef *def;
def = cb->GetUnitDef(constructor);
if(def->canBeAssisted)
{
c.id = CMD_GUARD;
} else
{
c.id = CMD_REPAIR;
}
c.params.push_back(constructor);
cb->GiveOrder(unit_id, &c);
task = ASSISTING;
assistance = constructor;
}
else
{
Command c;
c.id = CMD_REPAIR;
c.params.push_back(target_unit);
cb->GiveOrder(unit_id, &c);
task = ASSISTING;
assistance = constructor;
}
}
void AAIConstructor::TakeOverConstruction(AAIBuildTask *build_task)
{
if(assistance >= 0)
{
ai->ut->units[assistance].cons->RemoveAssitant(unit_id);
assistance = -1;
}
order_tick = build_task->order_tick;
construction_unit_id = build_task->unit_id;
construction_def_id = build_task->def_id;
construction_category = ai->bt->units_static[construction_def_id].category;
build_pos = build_task->build_pos;
Command c;
c.id = CMD_REPAIR;
c.params.push_back(build_task->unit_id);
task = BUILDING;
cb->GiveOrder(unit_id, &c);
}
void AAIConstructor::ConstructionFailed()
{
// tells the builder construction has finished
ConstructionFinished();
}
void AAIConstructor::ConstructionFinished()
{
task = UNIT_IDLE;
build_pos = ZeroVector;
construction_def_id = 0;
construction_unit_id = -1;
construction_category = UNKNOWN;
build_task = 0;
// release assisters
ReleaseAllAssistants();
}
void AAIConstructor::ReleaseAllAssistants()
{
// release assisters
for(set<int>::iterator i = assistants.begin(); i != assistants.end(); ++i)
{
if(ai->ut->units[*i].cons)
ai->ut->units[*i].cons->StopAssisting();
}
assistants.clear();
}
void AAIConstructor::StopAssisting()
{
task = UNIT_IDLE;
assistance = -1;
Command c;
c.id = CMD_STOP;
cb->GiveOrder(unit_id, &c);
}
void AAIConstructor::RemoveAssitant(int unit_id)
{
assistants.erase(unit_id);
}
void AAIConstructor::Killed()
{
if(builder)
{
// when builder was killed on the way to the buildsite, inform ai that construction
// of building hasnt been started
if(task == BUILDING)
{
//if buildling has not begun yet, decrease some values
if(construction_unit_id == -1)
{
ai->bt->units_dynamic[construction_def_id].requested -= 1;
ai->futureUnits[construction_category] -= 1;
// killed on the way to the buildsite
int x = build_pos.x / ai->map->xSectorSize;
int y = build_pos.z / ai->map->ySectorSize;
if(ai->map->sector[x][y].distance_to_base > 0)
ai->map->sector[x][y].lost_units[MOBILE_CONSTRUCTOR-COMMANDER] += 1;
// clear up buildmap etc.
ai->execute->ConstructionFailed(build_pos, construction_def_id);
}
// building has begun
else
{
if(build_task)
build_task->BuilderDestroyed();
}
}
else if(task == ASSISTING)
{
ai->ut->units[assistance].cons->RemoveAssitant(unit_id);
}
}
ReleaseAllAssistants();
task = UNIT_KILLED;
}
void AAIConstructor::Retreat(UnitCategory attacked_by)
{
if(task != UNIT_KILLED)
{
float3 pos = cb->GetUnitPos(unit_id);
int x = pos.x / ai->map->xSectorSize;
int y = pos.z / ai->map->ySectorSize;
// attacked by scout
if(attacked_by == SCOUT)
{
// dont flee from scouts in your own base
if(x >= 0 && y >= 0 && x < ai->map->xSectors && y < ai->map->ySectors)
{
// builder is within base
if(ai->map->sector[x][y].distance_to_base == 0)
return;
// dont flee outside of the base if health is > 50%
else
{
if(cb->GetUnitHealth(unit_id) > ai->bt->unitList[def_id-1]->health / 2.0)
return;
}
}
}
else
{
if(x >= 0 && y >= 0 && x < ai->map->xSectors && y < ai->map->ySectors)
{
// builder is within base
if(ai->map->sector[x][y].distance_to_base == 0)
return;
}
}
// get safe position
pos = ai->execute->GetSafePos(def_id);
if(pos.x > 0)
{
Command c;
c.id = CMD_MOVE;
c.params.push_back(pos.x);
c.params.push_back(cb->GetElevation(pos.x, pos.z));
c.params.push_back(pos.z);
cb->GiveOrder(unit_id, &c);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -