📄 aai.cpp
字号:
ut->RemovePowerPlant(unit);
}
else if(category == STATIONARY_ARTY)
{
ut->RemoveStationaryArty(unit);
}
else if(category == STATIONARY_RECON)
{
ut->RemoveRecon(unit);
}
else if(category == STATIONARY_JAMMER)
{
ut->RemoveJammer(unit);
}
else if(category == METAL_MAKER)
{
ut->RemoveMetalMaker(unit);
}
// clean up
if(category == STATIONARY_CONSTRUCTOR)
{
ut->RemoveConstructor(unit, def->id);
// speed up reconstruction
execute->urgency[category] += 1.5;
// clear buildmap
map->Pos2BuildMapPos(&pos, def);
if(bt->CanPlacedLand(def->id))
{
map->CheckRows(pos.x, pos.z, def->xsize, def->ysize, false, false);
map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 0);
map->BlockCells(pos.x, pos.z - 8, def->xsize, 8, false, false);
map->BlockCells(pos.x + def->xsize, pos.z - 8, cfg->X_SPACE, def->ysize + 1.5 * cfg->Y_SPACE, false, false);
map->BlockCells(pos.x, pos.z + def->ysize, def->xsize, 1.5 * cfg->Y_SPACE - 8, false, false);
}
else
{
map->CheckRows(pos.x, pos.z, def->xsize, def->ysize, false, true);
map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 4);
map->BlockCells(pos.x, pos.z - 8, def->xsize, 8, false, true);
map->BlockCells(pos.x + def->xsize, pos.z - 8, cfg->X_SPACE, def->ysize + 1.5 * cfg->Y_SPACE, false, true);
map->BlockCells(pos.x, pos.z + def->ysize, def->xsize, 1.5 * cfg->Y_SPACE - 8, false, true);
}
}
// hq
else if(category == COMMANDER)
{
ut->RemoveCommander(unit, def->id);
// clear buildmap
map->Pos2BuildMapPos(&pos, def);
if(def->minWaterDepth <= 0)
{
map->CheckRows(pos.x, pos.z, def->xsize, def->ysize, false, false);
map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 0);
map->BlockCells(pos.x, pos.z - 8, def->xsize, 8, false, false);
map->BlockCells(pos.x + def->xsize, pos.z - 8, cfg->X_SPACE, def->ysize + 1.5 * cfg->Y_SPACE, false, false);
map->BlockCells(pos.x, pos.z + def->ysize, def->xsize, 1.5 * cfg->Y_SPACE - 8, false, false);
}
else
{
map->CheckRows(pos.x, pos.z, def->xsize, def->ysize, false, true);
map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 4);
map->BlockCells(pos.x, pos.z - 8, def->xsize, 8, false, true);
map->BlockCells(pos.x + def->xsize, pos.z - 8, cfg->X_SPACE, def->ysize + 1.5 * cfg->Y_SPACE, false, true);
map->BlockCells(pos.x, pos.z + def->ysize, def->xsize, 1.5 * cfg->Y_SPACE - 8, false, true);
}
}
// other building
else
{
// clear buildmap
map->Pos2BuildMapPos(&pos, def);
if(def->minWaterDepth <= 0)
{
map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 0);
map->CheckRows(pos.x, pos.z, def->xsize, def->ysize, false, false);
}
else
{
map->SetBuildMap(pos.x, pos.z, def->xsize, def->ysize, 4);
map->CheckRows(pos.x, pos.z, def->xsize, def->ysize, false, true);
}
}
// if no buildings left in that sector, remove from base sectors
if(map->sector[x][y].GetNumberOfBuildings() == 0 && brain->sectors[0].size() > 0)
{
map->sector[x][y].SetBase(false);
brain->sectors[0].remove(&map->sector[x][y]);
brain->UpdateNeighbouringSectors();
brain->UpdateBaseCenter();
brain->expandable = true;
fprintf(file, "\nRemoving sector %i,%i from base; base size: %i \n", x, y, brain->sectors[0].size());
}
}
else // finished unit has been killed
{
// scout
if(category == SCOUT)
{
--activeScouts;
// remove from scout list
for(list<int>::iterator i = scouts.begin(); i != scouts.end(); i++)
{
if(*i == unit)
{
scouts.erase(i);
break;
}
}
// add building to sector
if(validSector && map->sector[x][y].distance_to_base > 0)
map->sector[x][y].enemy_structures += 5;
}
// assault units
else if(category >= GROUND_ASSAULT && category <= SUBMARINE_ASSAULT)
{
// look for a safer rallypoint if units get killed on their way
if(ut->units[unit].status == HEADING_TO_RALLYPOINT)
{
float3 pos = execute->GetRallyPoint(category, 1, 1, 10);
if(pos.x > 0)
ut->units[unit].group->rally_point = pos;
}
if(ut->units[unit].group)
ut->units[unit].group->RemoveUnit(unit, attacker);
else
fprintf(file, "ERROR: tried to remove %s but group not found\n", bt->unitList[def->id-1]->name.c_str());
}
// builder
else if(bt->IsBuilder(def->id))
{
ut->RemoveConstructor(unit, def->id);
}
else if(category == COMMANDER)
{
ut->RemoveCommander(unit, def->id);
}
}
}
ut->RemoveUnit(unit);
}
void AAI::UnitFinished(int unit)
{
if(!initialized)
return;
// get unit磗 id and side
const UnitDef *def = cb->GetUnitDef(unit);
int side = bt->GetSideByID(def->id)-1;
UnitCategory category = bt->units_static[def->id].category;
futureUnits[category] -= 1;
activeUnits[category] += 1;
bt->units_dynamic[def->id].requested -= 1;
bt->units_dynamic[def->id].active += 1;
// building was completed
if(!def->movedata && !def->canfly)
{
// delete buildtask
for(list<AAIBuildTask*>::iterator task = build_tasks.begin(); task != build_tasks.end(); task++)
{
if((*task)->unit_id == unit)
{
AAIBuildTask *build_task = *task;
if((*task)->builder_id >= 0 && ut->units[(*task)->builder_id].cons)
ut->units[(*task)->builder_id].cons->ConstructionFinished();
build_tasks.erase(task);
delete build_task;
break;
}
}
// check if building belongs to one of this groups
if(category == EXTRACTOR)
{
ut->AddExtractor(unit);
// order defence if necessary
execute->DefendMex(unit, def->id);
}
else if(category == POWER_PLANT)
{
ut->AddPowerPlant(unit, def->id);
}
else if(category == STORAGE)
{
execute->futureStoredEnergy -= bt->unitList[def->id-1]->energyStorage;
execute->futureStoredMetal -= bt->unitList[def->id-1]->metalStorage;
}
else if(category == METAL_MAKER)
{
ut->AddMetalMaker(unit, def->id);
}
else if(category == STATIONARY_RECON)
{
ut->AddRecon(unit, def->id);
}
else if(category == STATIONARY_JAMMER)
{
ut->AddJammer(unit, def->id);
}
else if(category == STATIONARY_ARTY)
{
ut->AddStationaryArty(unit, def->id);
}
else if(category == STATIONARY_CONSTRUCTOR)
{
ut->AddConstructor(unit, def->id);
}
return;
}
else // unit was completed
{
// unit
if(category >= GROUND_ASSAULT && category <= SUBMARINE_ASSAULT)
{
execute->AddUnitToGroup(unit, def->id, category);
brain->AddDefenceCapabilities(def->id, category);
ut->SetUnitStatus(unit, HEADING_TO_RALLYPOINT);
}
// scout
else if(category == SCOUT)
{
++activeScouts;
--futureScouts;
scouts.push_back(unit);
// cloak scout if cloakable
if(def->canCloak)
{
Command c;
c.id = CMD_CLOAK;
c.params.push_back(1);
cb->GiveOrder(unit, &c);
}
}
// builder
else if(bt->IsBuilder(def->id))
{
ut->AddConstructor(unit, def->id);
}
}
}
void AAI::UnitIdle(int unit)
{
// if factory is idle, start construction of further units
if(ut->units[unit].cons)
{
if(ut->units[unit].cons->assistance < 0 && ut->units[unit].cons->construction_unit_id < 0 )
{
/*if(!ut->units[unit].cons->factory)
{
char c[120];
if(ut->units[unit].cons->construction_unit_id == -1)
sprintf(c, "%s / %i is idle\n", bt->unitList[ut->units[unit].cons->def_id-1]->humanName.c_str(), unit);
else
sprintf(c, "%s is idle building %s\n", bt->unitList[ut->units[unit].cons->def_id-1]->humanName.c_str(), bt->unitList[ut->units[unit].cons->construction_def_id-1]->humanName.c_str());
cb->SendTextMsg(c,0);
}*/
ut->units[unit].cons->Idle();
if(ut->constructors.size() < 4)
execute->CheckConstruction();
ut->SetUnitStatus(unit, UNIT_IDLE);
}
}
// idle combat units will report to their groups
else if(ut->units[unit].group)
{
ut->SetUnitStatus(unit, UNIT_IDLE);
ut->units[unit].group->UnitIdle(unit);
}
else
ut->SetUnitStatus(unit, UNIT_IDLE);
}
void AAI::UnitMoveFailed(int unit)
{
// not a good solution at all, hopefully not necessary in the future due to bug fixes
// in the path finding routines
/*float3 pos = cb->GetUnitPos(unit);
int x = pos.x/map->xSectorSize;
int y = pos.z/map->ySectorSize;
if(x < 0 || y < 0 || x >= map->xSectors || y >= map->ySectors)
return;
pos = map->sector[x][y].GetCenter();
pos.x += rand()%4 * map->xSectorSize;
pos.z += rand()%4 * map->ySectorSize;
execute->moveUnitTo(unit, &pos);*/
const UnitDef *def = cb->GetUnitDef(unit);
if(ut->units[unit].cons)
{
AAIConstructor* builder = ut->units[unit].cons;
if(builder->task == BUILDING)
{
if(builder->construction_unit_id == -1)
{
--bt->units_dynamic[builder->construction_def_id].requested;
--futureUnits[builder->construction_category];
// clear up buildmap etc.
execute->ConstructionFailed(builder->build_pos, builder->construction_def_id);
// free builder
builder->ConstructionFinished();
}
}
}
}
void AAI::EnemyEnterLOS(int enemy) {}
void AAI::EnemyLeaveLOS(int enemy) {}
void AAI::EnemyEnterRadar(int enemy) {}
void AAI::EnemyLeaveRadar(int enemy) {}
void AAI::EnemyDestroyed(int enemy, int attacker)
{
// remove enemy from unittable
ut->EnemyKilled(enemy);
if(attacker)
{
// get unit磗 id
const UnitDef *def = cb->GetUnitDef(enemy);
const UnitDef *def_att = cb->GetUnitDef(attacker);
if(def_att)
{
// unit was destroyed
if(def)
{
int killer = bt->GetIDOfAssaultCategory(bt->units_static[def_att->id].category);
int killed = bt->GetIDOfAssaultCategory(bt->units_static[def->id].category);
if(killer != -1 && killed != -1)
{
bt->UpdateTable(def_att, killer, def, killed);
map->UpdateCategoryUsefulness(def_att, killer, def, killed);
}
}
}
}
}
void AAI::Update()
{
int tick = cb->GetCurrentFrame();
if(!initialized)
{
if(!(tick%450))
cb->SendTextMsg("Failed to initialize AAI! Please view ai log for further information and check if AAI supports this mod", 0);
return;
}
// scouting
if(!(tick%cfg->SCOUT_UPDATE_FREQUENCY))
{
execute->UpdateRecon(); // update threat values for all sectors, move scouts...
}
// update groups
if(!(tick%219))
{
for(list<UnitCategory>::iterator category = bt->assault_categories.begin(); category != bt->assault_categories.end(); category++)
{
for(list<AAIGroup*>::iterator group = group_list[*category].begin(); group != group_list[*category].end(); group++)
(*group)->Update();
}
return;
}
// unit management
if(!(tick%649))
{
execute->CheckBuildques();
brain->BuildUnits();
}
if(!(tick%911))
{
// check attack
am->Update();
af->BombBestUnit(2, 2);
return;
}
// ressource management
if(!(tick%199))
{
execute->CheckRessources();
}
// update sectors
if(!(tick%423))
{
brain->UpdateAttackedByValues();
map->UpdateSectors();
}
// builder management
if(!(tick%917))
{
brain->UpdateDefenceCapabilities();
}
// update income
if(!(tick%45))
{
execute->UpdateRessources();
}
// building management
if(!(tick%97))
{
execute->CheckConstruction();
}
// builder/factory management
if(!(tick%677))
{
for(set<int>::iterator builder = ut->constructors.begin(); builder != ut->constructors.end(); ++builder)
ut->units[(*builder)].cons->Update();
}
if(!(tick%437))
{
execute->CheckFactories();
}
if(!(tick%1079))
{
execute->CheckDefences();
}
// build radar/jammer
if(!(tick%1177))
{
execute->CheckRecon();
execute->CheckJammer();
execute->CheckStationaryArty();
execute->CheckAirBase();
}
// upgrade mexes
if(!(tick%2173))
{
execute->CheckMexUpgrade();
execute->CheckRadarUpgrade();
execute->CheckJammerUpgrade();
}
// recheck rally points
if(!(tick%2577))
{
for(list<UnitCategory>::iterator category = bt->assault_categories.begin(); category != bt->assault_categories.end(); category++)
{
for(list<AAIGroup*>::iterator group = group_list[*category].begin(); group != group_list[*category].end(); group++)
(*group)->rally_point = execute->GetRallyPoint(*category, 1, 1, 10);
}
}
// recalculate efficiency stats
if(!(tick%2827))
{
if(aai_instance == 1)
bt->UpdateMinMaxAvgEfficiency();
}
}
int AAI::HandleEvent(int msg,const void* data)
{
switch (msg)
{
case AI_EVENT_UNITCAPTURED: // 2
{
const IGlobalAI::ChangeTeamEvent* cte = (const IGlobalAI::ChangeTeamEvent*) data;
UnitDestroyed(cte->unit,-1);
}
break;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -