📄 aaimap.cpp
字号:
metalMap = true;
metal_spots.clear();
fprintf(ai->file, "Map is considered to be a metal map\n",0);
}
else
{
metalMap = false;
// debug
/*for(list<AAIMetalSpot>::iterator spot = metal_spots.begin(); spot != metal_spots.end(); spot++)
{
cb->DrawUnit("ARMMEX", spot->pos, 0.0f, 200000, cb->GetMyAllyTeam(), false, true);
}*/
}
delete [] MexArrayA;
delete [] MexArrayB;
delete [] TempAverage;
}
void AAIMap::GetMapData()
{
}
void AAIMap::UpdateRecon()
{
const UnitDef *def;
int team, my_team = cb->GetMyAllyTeam();
float3 pos;
int x, y;
AAIAirTarget target;
int combat_category_id;
AAISector *sector;
UnitCategory cat;
// prevent aai from wasting too much time with checking too many targets
int targets_checked = 0;
// reset number of friendly units per sector && decrease mobile combat power (to reflect possible movement the units)
for(x = 0; x < xSectors; ++x)
{
for(y = 0; y < ySectors; ++y)
{
unitsInSector[x+y*xSectors] = 0;
for(int i = 0; i < bt->combat_categories; ++i)
{
this->sector[x][y].mobile_combat_power[i] *= 0.98f;
if(this->sector[x][y].mobile_combat_power[i] < 0.5f)
this->sector[x][y].mobile_combat_power[i] = 0;
}
}
}
// reset spotted units
fill(units_spotted.begin(), units_spotted.end(), 0);
// first update all sectors with friendly units
cb->GetFriendlyUnits(&(unitsInLos.front()));
// go through the list
for(int i = 0; i < cfg->MAX_UNITS; ++i)
{
// if 0 end of array reached
if(unitsInLos[i])
{
pos = cb->GetUnitPos(unitsInLos[i]);
if(pos.x != 0)
{
// calculate in which sector unit is located
x = pos.x/xSectorSize;
y = pos.z/ySectorSize;
if(x >= 0 && y >= 0 && x < xSectors && y < ySectors)
{
sector = &this->sector[x][y];
// we have a unit in that sector, reset values if not already done
if(unitsInSector[x+y*xSectors] == 0)
{
++unitsInSector[x+y*xSectors];
fill(sector->enemyUnitsOfType.begin(), sector->enemyUnitsOfType.end(), 0);
fill(sector->stat_combat_power.begin(), sector->stat_combat_power.end(), 0);
fill(sector->mobile_combat_power.begin(), sector->mobile_combat_power.end(), 0);
sector->threat = 0;
sector->allied_structures = 0;
sector->enemy_structures = 0;
sector->own_structures = 0;
}
// check if building
def = cb->GetUnitDef(unitsInLos[i]);
if(def && bt->units_static[def->id].category <= METAL_MAKER)
{
team = cb->GetUnitTeam(unitsInLos[i]);
if(team == my_team)
sector->own_structures += bt->units_static[def->id].cost;
else
sector->allied_structures += bt->units_static[def->id].cost;
}
}
}
unitsInLos[i] = 0;
}
else // end of array reached
break;
}
// get all enemies in los
cb->GetEnemyUnits(&(unitsInLos.front()));
// go through the list
for(int i = 0; i < cfg->MAX_UNITS; ++i)
{
// if 0 end of array reached
if(unitsInLos[i])
{
pos = cb->GetUnitPos(unitsInLos[i]);
// calculate in which sector unit is located
sector = GetSectorOfPos(&pos);
if(sector)
{
if(unitsInSector[sector->x + sector->y*xSectors])
{
def = cb->GetUnitDef(unitsInLos[i]);
cat = bt->units_static[def->id].category;
combat_category_id = (int) bt->GetIDOfAssaultCategory(cat);
sector->enemyUnitsOfType[(int)cat] += 1;
// check if combat unit
if(combat_category_id >= 0)
{
sector->threat += 1;
units_spotted[combat_category_id] += 1;
// count combat power of combat units
for(int i = 0; i < bt->combat_categories; ++i)
sector->mobile_combat_power[i] += bt->units_static[def->id].efficiency[i];
}
else // building or scout etc.
{
// check if promising bombing target
if(targets_checked < 3 && ( cat == EXTRACTOR || cat == STATIONARY_CONSTRUCTOR || cat == STATIONARY_ARTY || cat == STATIONARY_LAUNCHER ) )
{
// dont check targets that are already on bombing list
if(ai->ut->units[unitsInLos[i]].status != BOMB_TARGET)
{
ai->af->CheckBombTarget(unitsInLos[i], def->id);
targets_checked += 1;
cb->SendTextMsg("Checking target", 0);
}
}
// count combat power of stat defences
if(cat == STATIONARY_DEF)
{
for(int i = 0; i < bt->ass_categories; ++i)
sector->stat_combat_power[i] += bt->units_static[def->id].efficiency[i];
}
// add enemy buildings
if(cat <= METAL_MAKER)
sector->enemy_structures += bt->units_static[def->id].cost;
}
}
}
unitsInLos[i] = 0;
}
else // end of arry reached
break;
}
ai->brain->UpdateMaxCombatUnitsSpotted(units_spotted);
}
void AAIMap::UpdateSectors()
{
for(int x = 0; x < xSectors; ++x)
{
for(int y = 0; y < ySectors; ++y)
sector[x][y].Update();
}
}
void AAIMap::UpdateCategoryUsefulness(const UnitDef *killer_def, int killer, const UnitDef *killed_def, int killed)
{
// filter out aircraft
if(killer == 1 || killed == 1)
return;
UnitTypeStatic *killer_type = &bt->units_static[killer_def->id];
UnitTypeStatic *killed_type = &bt->units_static[killed_def->id];
float change = killed_type->cost / killer_type->cost;
change /= 4;
if(change > 4)
change = 4;
else if(change < 0.2)
change = 0.2f;
if(killer < 5)
{
bt->mod_usefulness[killer][killer_type->side-1][mapType] += change;
map_usefulness[killer][killer_type->side-1] += change;
}
if(killed < 5)
{
map_usefulness[killed][killed_type->side-1] -= change;
bt->mod_usefulness[killed][killed_type->side-1][mapType] -= change;
if(map_usefulness[killed][killed_type->side-1] < 1)
map_usefulness[killed][killed_type->side-1] = 1;
if(bt->mod_usefulness[killed][killed_type->side-1][mapType] < 1)
bt->mod_usefulness[killed][killed_type->side-1][mapType] = 1;
}
}
char* AAIMap::GetMapTypeString(int mapType)
{
if(mapType == 1)
return "LAND_MAP";
else if(mapType == 2)
return "AIR_MAP";
else if(mapType == 3)
return "LAND_WATER_MAP";
else if(mapType == 4)
return "WATER_MAP";
else
return "UNKNOWN_MAP";
}
char* AAIMap::GetMapTypeTextString(int mapType)
{
if(mapType == 1)
return "land map";
else if(mapType == 2)
return "air map";
else if(mapType == 3)
return "land-water map";
else if(mapType == 4)
return "water map";
else
return "unknown map type";
}
bool AAIMap::ValidSector(int x, int y)
{
if(x >= 0 && y >= 0 && x < xSectors && y < ySectors)
return true;
else
return false;
}
AAISector* AAIMap::GetSectorOfPos(float3 *pos)
{
int x = pos->x/xSectorSize;
int y = pos->z/ySectorSize;
if(ValidSector(x,y))
return &(sector[x][y]);
else
return 0;
}
void AAIMap::AddDefence(float3 *pos, int defence)
{
int range = bt->units_static[defence].range / 16;
int cell;
float power;
float air_power;
if(cfg->AIR_ONLY_MOD)
{
power = bt->fixed_eff[defence][0] + bt->fixed_eff[defence][1];
air_power = bt->fixed_eff[defence][2] + bt->fixed_eff[defence][3];
}
else
{
if(bt->unitList[defence-1]->minWaterDepth > 0)
power = bt->fixed_eff[defence][3] + bt->fixed_eff[defence][4];
else
power = bt->fixed_eff[defence][0];
air_power = bt->fixed_eff[defence][1];
}
int xPos = pos->x / 16;
int yPos = pos->z / 16;
// x range will change from line to line
int xStart;
int xEnd;
int xRange;
// y range is const
int yStart = yPos - range;
int yEnd = yPos + range;
if(yStart < 0)
yStart = 0;
if(yEnd >= yDefMapSize)
yEnd = yDefMapSize-1;
for(int y = yStart; y <= yEnd; ++y)
{
// determine x-range
xRange = (int) floor( sqrt( (float) ( range * range - (y - yPos) * (y - yPos) ) ) + 0.5f );
xStart = xPos - xRange;
xEnd = xPos + xRange;
if(xStart < 0)
xStart = 0;
if(xEnd > xDefMapSize)
xEnd = xDefMapSize;
for(int x = xStart; x < xEnd; ++x)
{
cell = x + xDefMapSize*y;
defence_map[cell] += power;
air_defence_map[cell] += air_power;
}
}
// further increase values close around the bulding (to prevent aai from packing buildings too close together)
// y range is const
yStart = yPos - 6;
yEnd = yPos + 6;
if(yStart < 0)
yStart = 0;
if(yEnd >= yDefMapSize)
yEnd = yDefMapSize-1;
for(int y = yStart; y <= yEnd; ++y)
{
// determine x-range
xRange = (int) floor( sqrt( (float) ( 36 - (y - yPos) * (y - yPos) ) ) + 0.5f );
xStart = xPos - xRange;
xEnd = xPos + xRange;
if(xStart < 0)
xStart = 0;
if(xEnd > xDefMapSize)
xEnd = xDefMapSize;
for(int x = xStart; x < xEnd; ++x)
{
cell = x + xDefMapSize*y;
defence_map[cell] += 128.0f;
air_defence_map[cell] += 128.0f;
}
}
}
void AAIMap::RemoveDefence(float3 *pos, int defence)
{
int cell;
int range = bt->units_static[defence].range / 16;
float power;
float air_power;
if(cfg->AIR_ONLY_MOD)
{
power = bt->fixed_eff[defence][0] + bt->fixed_eff[defence][1];
air_power = bt->fixed_eff[defence][2] + bt->fixed_eff[defence][3];
}
else
{
if(bt->unitList[defence-1]->minWaterDepth > 0)
power = bt->fixed_eff[defence][3] + bt->fixed_eff[defence][4];
else
power = bt->fixed_eff[defence][0];
air_power = bt->fixed_eff[defence][1];
}
int xPos = pos->x / 16;
int yPos = pos->z / 16;
// x range will change from line to line
int xStart;
int xEnd;
int xRange;
// further decrease values close around the bulding (to prevent aai from packing buildings too close together)
// y range is const
int yStart = yPos - 6;
int yEnd = yPos + 8;
if(yStart < 0)
yStart = 0;
if(yEnd >= yDefMapSize)
yEnd = yDefMapSize-1;
for(int y = yStart; y <= yEnd; ++y)
{
// determine x-range
xRange = (int) floor( sqrt( (float) ( 36 - (y - yPos) * (y - yPos) ) ) + 0.5f );
xStart = xPos - xRange;
xEnd = xPos + xRange;
if(xStart < 0)
xStart = 0;
if(xEnd > xDefMapSize)
xEnd = xDefMapSize;
for(int x = xStart; x < xEnd; ++x)
{
cell= x + xDefMapSize*y;
defence_map[cell] -= 128.0f;
air_defence_map[cell] -= 128.0f;
}
}
// y range is const
yStart = yPos - range;
yEnd = yPos + range;
if(yStart < 0)
yStart = 0;
if(yEnd >= yDefMapSize)
yEnd = yDefMapSize-1;
for(int y = yStart; y <= yEnd; ++y)
{
// determine x-range
xRange = (int) floor( sqrt( (float) ( range * range - (y - yPos) * (y - yPos) ) ) + 0.5f );
xStart = xPos - xRange;
xEnd = xPos + xRange;
if(xStart < 0)
xStart = 0;
if(xEnd > xDefMapSize)
xEnd = xDefMapSize;
for(int x = xStart; x < xEnd; ++x)
{
cell= x + xDefMapSize*y;
defence_map[cell] -= power;
air_defence_map[cell] -= air_power;
if(defence_map[cell] < 0)
defence_map[cell] = 0;
if(air_defence_map[cell] < 0)
air_defence_map[cell] = 0;
}
}
}
float AAIMap::GetDefenceBuildsite(float3 *best_pos, const UnitDef *def, int xStart, int xEnd, int yStart, int yEnd, UnitCategory category, float terrain_modifier, bool water)
{
float3 pos;
*best_pos = ZeroVector;
float my_rating, best_rating = -10000;
int edge_distance;
// get required cell-size of the building
int xSize, ySize, xPos, yPos, cell;
GetSize(def, &xSize, &ySize);
vector<float> *map = &defence_map;
if(cfg->AIR_ONLY_MOD)
{
if(category == HOVER_ASSAULT || category == SEA_ASSAULT)
map = &air_defence_map;
}
else if(category == AIR_ASSAULT)
map = &air_defence_map;
float range = bt->units_static[def->id].range / 8.0;
// check rect
for(yPos = yStart; yPos < yEnd; yPos += 4)
{
for(xPos = xStart; xPos < xEnd; xPos += 4)
{
// check if buildmap allows construction
if(CanBuildAt(xPos, yPos, xSize, ySize, water))
{
cell = xPos/2 + xDefMapSize * (yPos/2);
my_rating = terrain_modifier * plateau_map[cell] - (*map)[cell] + 0.15f * ((float) (rand()%20));
// determine minimum distance from buildpos to the edges of the map
edge_distance = xPos;
if(xMapSize - xPos < edge_distance)
edge_distance = xMapSize - xPos;
if(yPos < edge_distance)
edge_distance = yPos;
if(yMapSize - yPos < edge_distance)
edge_distance = yMapSize - yPos;
// prevent aai from building defences too close to the edges of the map
if( (float)edge_distance < range)
my_rating -= (range - (float)edge_distance);
if(my_rating > best_rating)
{
pos.x = xPos;
pos.z = yPos;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&pos, def);
Pos2FinalBuildPos(&pos, def);
if(cb->CanBuildAt(def, pos))
{
*best_pos = pos;
best_rating = my_rating;
}
}
}
}
}
return best_rating;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -