📄 attackgroup.cpp
字号:
#include "AttackGroup.h"
#define UNIT_STUCK_MOVE_DISTANCE 2.0f
// not moving for 5 * 60 frames = stuck
#define UNIT_STUCK_COUNTER_MANEUVER_LIMIT 5
// gives it (STUCK_COUNTER_LIMIT - STUCK_COUNTER_MANEUVER_LIMIT) * 60 seconds to move (longer than UNIT_STUCK_MOVE_DISTANCE (7 sec))
#define UNIT_STUCK_COUNTER_LIMIT 15
// stuck maneuver distance should be the movement map res since threat is not really relevant when maneuvering from a stuck pos
#define UNIT_STUCK_MANEUVER_DISTANCE (THREATRES * 8)
// the max amount of difference in height there may be at the position to maneuver to (don't retreat into a hole)
#define UNIT_MAX_MANEUVER_HEIGHT_DIFFERENCE_UP 20
// minimum of offset between my maxrange and the enemys position before considering moving
#define UNIT_MIN_MANEUVER_RANGE_DELTA (THREATRES * 8)
// minimum amount to maneuver when getting to max range
#define UNIT_MIN_MANEUVER_DISTANCE (THREATRES * 4)
// second requirement, minimum percentage of my range to move when getting to max range (too stop slow long range from dancing around)
#define UNIT_MIN_MANEUVER_RANGE_PERCENTAGE 0.2f
// minimum time to maneuver (frames), used for setting maneuvercounter (in case the speed / dist formula is weird)
#define UNIT_MIN_MANEUVER_TIME 15
#define UNIT_DESTINATION_SLACK (THREATRES * 4.0f * 1.4f)
#define GROUP_DESTINATION_SLACK THREATRES * 8
#define GROUP_MEDIAN_UNIT_SELECTION_SLACK 10.0f
CR_BIND(CAttackGroup, (NULL, 0));
CR_REG_METADATA(CAttackGroup, (
CR_MEMBER(ai),
CR_MEMBER(units),
CR_MEMBER(groupID),
CR_MEMBER(isMoving),
CR_MEMBER(pathIterator),
CR_MEMBER(lowestAttackRange),
CR_MEMBER(highestAttackRange),
CR_MEMBER(isShooting),
CR_MEMBER(movementCounterForStuckChecking),
CR_RESERVED(16)
));
CAttackGroup::CAttackGroup() {
this->ai = NULL;
this->groupID = 0;
this->pathIterator = 0;
this->lowestAttackRange = 100000;
this->highestAttackRange = 1;
this->movementCounterForStuckChecking = 0;
this->defending = false;
this->isMoving = false;
this->isShooting = false;
this->attackPosition = ZEROVECTOR;
this->attackRadius = 1;
}
CAttackGroup::CAttackGroup(AIClasses* ai, int groupID_in) {
this->ai = ai;
this->groupID = groupID_in;
this->pathIterator = 0;
this->lowestAttackRange = 100000;
this->highestAttackRange = 1;
this->movementCounterForStuckChecking = 0;
this->defending = false;
this->isMoving = false;
this->isShooting = false;
this->attackPosition = ZEROVECTOR;
this->attackRadius = 1;
}
CAttackGroup::~CAttackGroup() {
}
void CAttackGroup::Log() {
}
void CAttackGroup::AddUnit(int unitID) {
if (ai->cb->GetUnitDef(unitID)) {
// add to my structure
units.push_back(unitID);
// set its group ID:
ai->MyUnits[unitID]->groupID = this->groupID;
// update the attack range properties of this group
this->lowestAttackRange = min(this->lowestAttackRange, this->ai->ut->GetMaxRange(ai->cb->GetUnitDef(unitID)));
this->highestAttackRange = max(this->highestAttackRange, this->ai->ut->GetMaxRange(ai->cb->GetUnitDef(unitID)));
}
else {
bool dead_unit_added_to_group = false;
assert(dead_unit_added_to_group);
}
}
bool CAttackGroup::RemoveUnit(int unitID) {
bool found = false;
vector<int>::iterator it;
for (it = units.begin(); it != units.end(); it++) {
if (*it == unitID) {
found = true;
// L("AttackGroup: erasing unit with id:" << unitID);
break;
}
}
if (found) {
units.erase(it);
// L("AttackGroup: about to attempt to reset the group ID of a removed unit");
if (ai->cb->GetUnitDef(unitID) != NULL) {
ai->MyUnits[unitID]->groupID = 0;
// L("AttackGroup: groupid = 0 ==> success");
// L("AttackGroup: this unit's stuck counter was " << ai->MyUnits[unitID]->stuckCounter);
}
}
assert(found);
// update lowestAttackRange and highestAttackRange
this->lowestAttackRange = 10000.0f;
this->highestAttackRange = 1.0f;
for (unsigned int i = 0; i < units.size(); i++) {
int unitID = units[i];
if (ai->cb->GetUnitDef(unitID) != NULL) {
this->lowestAttackRange = min(this->lowestAttackRange, this->ai->ut->GetMaxRange(ai->cb->GetUnitDef(unitID)));
this->highestAttackRange = max(this->highestAttackRange, this->ai->ut->GetMaxRange(ai->cb->GetUnitDef(unitID)));
}
}
return found;
}
void CAttackGroup::MoveTo(float3 newPosition) {
newPosition = newPosition;
}
int CAttackGroup::Size() {
// LONG DEAD-UNIT TEST
int unitCounter = 0;
int numUnits = units.size();
int invalid = -2;
for (int i = 0; i < numUnits; i++) {
int unit = units[i];
if (ai->cb->GetUnitDef(unit) != NULL) {
unitCounter++;
}
else {
invalid = unit;
}
}
if (numUnits != unitCounter) {
// size mismatch in group
}
return units.size();
}
int CAttackGroup::GetGroupID() {
return groupID;
}
int CAttackGroup::GetWorstMoveType() {
return PATHTOUSE;
}
vector<int>* CAttackGroup::GetAllUnits() {
return &(this->units);
}
// combined unit power of the group
float CAttackGroup::Power() {
float sum = 0.00001f;
for (vector<int>::iterator it = units.begin(); it != units.end(); it++) {
if (ai->cb->GetUnitDef(*it) != NULL) {
sum += ai->cb->GetUnitPower(*it);
}
}
return sum;
}
int CAttackGroup::PopStuckUnit() {
// removes a stuck unit from the group if there is one, and puts a marker on the map
for (vector<int>::iterator it = units.begin(); it != units.end(); it++) {
if (ai->MyUnits[*it]->stuckCounter > UNIT_STUCK_COUNTER_LIMIT) {
int id = *it;
// mark it
char text[512];
sprintf(text, "stuck %i: %i, dropping from group: %i. isMoving = %i", id, ai->MyUnits[*it]->stuckCounter, groupID, isMoving);
sprintf(text, "humanName: %s", ai->MyUnits[*it]->def()->humanName.c_str());
ai->MyUnits[*it]->stuckCounter = 0;
units.erase(it);
return id;
}
}
return -1;
}
bool CAttackGroup::CloakedFix(int enemy) {
const UnitDef* ud = ai->cheat->GetUnitDef(enemy);
return ((ud != NULL) && !(ud->canCloak && ud->startCloaked && (ai->cb->GetUnitPos(enemy) == ZEROVECTOR)));
}
float3 CAttackGroup::GetGroupPos() {
// what's the group's position (for distance checking when selecting targets)
int unitCounter = 0;
float3 groupPosition = float3(0, 0, 0);
int numUnits = units.size();
for (int i = 0; i < numUnits; i++) {
int unit = units[i];
if (ai->cb->GetUnitDef(unit) != NULL) {
unitCounter++;
groupPosition += ai->cb->GetUnitPos(unit);
}
}
if (unitCounter > 0) {
groupPosition /= unitCounter;
// find the unit closest to the center (since the actual center might be on a hill or something)
float closestSoFar = FLT_MAX;
int closestUnitID = -1;
float temp;
int unit;
for (int i = 0; i < numUnits; i++) {
unit = units[i];
// is it closer. consider also low unit counts, then the first will be used since it's < and not <= (assuming sufficient float accuracy)
if (ai->cb->GetUnitDef(unit) != NULL && (temp = groupPosition.distance2D(ai->cb->GetUnitPos(unit))) < closestSoFar - GROUP_MEDIAN_UNIT_SELECTION_SLACK) {
closestSoFar = temp;
closestUnitID = unit;
}
}
assert(closestUnitID != -1);
groupPosition = ai->cb->GetUnitPos(closestUnitID);
}
else {
// L("AttackGroup: empty attack group when calcing group pos!");
return ERRORVECTOR;
}
return groupPosition;
}
// returns enemies in my attack area
list<int> CAttackGroup::GetAssignedEnemies() {
list<int> takenEnemies;
if (!defending) {
int numTaken = ai->cheat->GetEnemyUnits(unitArray, attackPosition, attackRadius);
for (int i = 0; i < numTaken; i++) {
int takenEnemy = unitArray[i];
takenEnemies.push_back(takenEnemy);
}
}
return takenEnemies;
}
void CAttackGroup::AssignTarget(vector<float3> path, float3 position, float radius) {
this->attackPosition = position;
this->attackRadius = radius;
this->pathToTarget = path;
this->isMoving = true;
this->isShooting = false;
this->pathIterator = 0;
this->defending = false;
}
// attack routine (the "find new enemy" part)
void CAttackGroup::FindDefenseTarget(float3 groupPosition, int frameNr) {
char tx[512];
sprintf(tx, "AG: FindDefenseTarget(), group %i, frame %i, numUnits %i",
this->groupID, frameNr, this->units.size());
// KLOOTNOTE: numEnemies will be zero if no enemies in LOS or radar when
// non-cheat callback used, rely on AttackHandler to pick "global" targets
// and on this function for "local" ones
// int numEnemies = ai->cheat->GetEnemyUnits(unitArray);
int numEnemies = ai->cb->GetEnemyUnitsInRadarAndLos(unitArray);
if (numEnemies) {
// build vector of enemies
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -