7
int ATask::counter = 0;
9
ATask::ATask(AIClasses *_ai):ARegistrar(++counter, std::string("task")) {
16
initFrame = ai->cb->GetCurrentFrame();
17
validateInterval = 5 * 30; // 5 sec by default
18
nextValidateFrame = validateInterval;
23
void ATask::remove() {
24
LOG_II("ATask::remove " << (*this))
26
// NOTE: removal order below is VERY important
28
// remove current task from CTaskHandler, so it will mark this task
29
// to be killed on next update
30
std::list<ARegistrar*>::iterator j = records.begin();
31
while (j != records.end()) {
32
ARegistrar *regobj = *j; ++j;
33
regobj->remove(*this);
36
// remove all assisting tasks...
37
std::list<ATask*>::iterator i = assisters.begin();
38
while (i != assisters.end()) {
39
ATask *task = *i; ++i;
42
assert(assisters.size() == 0);
44
// detach task from groups...
45
std::list<CGroup*>::iterator itGroup = groups.begin();
46
while(itGroup != groups.end()) {
47
CGroup *g = *itGroup; ++itGroup;
54
// called on Group removing
55
void ATask::remove(ARegistrar &group) {
56
CGroup *g = dynamic_cast<CGroup*>(&group);
63
LOG_II("ATask::remove " << (*g))
69
CGroup* ATask::firstGroup() const {
72
return groups.front();
75
void ATask::addGroup(CGroup &g) {
76
// FIXME: remove this when queue tasks will be supported
80
ATask *task = ai->tasks->getTask(g);
81
assert(task != NULL && task != this);
82
task->suspended = true;
83
// TODO: nextTask = task;
97
void ATask::removeGroup(CGroup &g) {
105
if (isMoving) g.stop();
111
bool ATask::enemyScan() {
112
CGroup *group = firstGroup();
113
bool scout = group->cats&SCOUTER;
114
bool aircraft = group->cats&AIR;
118
tf.threatCeiling = 1.1f;
119
tf.threatRadius = 300.0f;
123
if (group->cats&ASSAULT)
124
tf.threatCeiling = group->strength;
126
tf.threatCeiling = 1.1f;
127
// TODO: replace with maneuvering radius?
128
tf.threatRadius = 300.0f;
131
tf.exclude = SCOUTER;
132
tf.threatFactor = 0.001f;
133
tf.threatCeiling = group->strength;
134
tf.threatRadius = 0.0f;
138
// do not chase after aircraft by non-aircraft groups...
142
int target = group->selectTarget(group->getScanRange(), tf);
145
group->attack(target);
148
LOG_II("ATask::enemyScan scout " << (*group) << " is microing enemy target Unit(" << target << ")")
150
LOG_II("ATask::enemyScan engage " << (*group) << " is microing enemy target Unit(" << target << ")")
157
bool ATask::resourceScan() {
158
bool isFeature = true;
159
int bestFeature = -1;
160
float bestDist = std::numeric_limits<float>::max();
161
CGroup *group = firstGroup();
162
// NOTE: do not use group->los because it is too small and do not
163
// correspond to real map units
164
float radius = group->buildRange;
165
float3 gpos = group->pos();
167
assert(radius > EPS);
169
// reclaim features when we can store metal only...
170
if (!ai->economy->mexceeding) {
171
const int numFeatures = ai->cb->GetFeatures(&ai->unitIDs[0], MAX_FEATURES, gpos, 1.5f * radius);
172
for (int i = 0; i < numFeatures; i++) {
173
const int uid = ai->unitIDs[i];
174
const FeatureDef *fd = ai->cb->GetFeatureDef(uid);
175
if (fd->metal > 0.0f) {
176
float3 fpos = ai->cb->GetFeaturePos(uid);
177
float dist = gpos.distance2D(fpos);
178
if (dist < bestDist) {
186
// if there is no feature available then reclaim enemy unarmed building,
188
if (bestFeature == -1) {
189
std::map<int, bool> occupied;
192
tf.exclude = ATTACKER;
193
tf.threatCeiling = 1.1f;
194
tf.threatRadius = radius;
196
bestFeature = group->selectTarget(radius, tf);
201
if (bestFeature != -1) {
202
group->reclaim(bestFeature, isFeature);
204
LOG_II("ATask::resourceScan group " << (*group) << " is reclaiming")
211
bool ATask::repairScan() {
212
if (ai->economy->mstall || ai->economy->estall)
216
float bestScore = 0.0f;
217
CGroup *group = firstGroup();
218
float radius = group->buildRange;
219
float3 gpos = group->pos();
221
const int numUnits = ai->cb->GetFriendlyUnits(&ai->unitIDs[0], gpos, 2.0f * radius, MAX_FEATURES);
222
for (int i = 0; i < numUnits; i++) {
223
const int uid = ai->unitIDs[i];
225
if (ai->cb->UnitBeingBuilt(uid) || group->firstUnit()->key == uid)
228
const float healthDamage = ai->cb->GetUnitMaxHealth(uid) - ai->cb->GetUnitHealth(uid);
229
if (healthDamage > EPS) {
230
// TODO: somehow limit number of repairing builders per unit
231
const UnitDef *ud = ai->cb->GetUnitDef(uid);
232
const float score = healthDamage + (CUnit::isDefense(ud) ? 10000.0f: 0.0f) + (CUnit::isStatic(ud) ? 5000.0f: 0.0f);
233
if (score > bestScore) {
240
if (bestUnit != -1) {
241
group->repair(bestUnit);
243
LOG_II("ATask::repairScan group " << (*group) << " is repairing")
250
int ATask::lifeFrames() const {
251
return ai->cb->GetCurrentFrame() - initFrame;
254
float ATask::lifeTime() const {
255
return (float)(ai->cb->GetCurrentFrame() - initFrame) / 30.0f;
258
void ATask::update() {
261
if (validateInterval > 0) {
262
int lifetime = lifeFrames();
263
if (lifetime >= nextValidateFrame) {
269
nextValidateFrame = lifetime + validateInterval;
273
if (suspended) return;
278
std::ostream& operator<<(std::ostream &out, const ATask &atask) {
281
if (atask.assisters.size() > 0) {
282
out << " Assisters: amount(" << atask.assisters.size() << ") [";
283
std::list<ATask*>::const_iterator i;
284
for (i = atask.assisters.begin(); i != atask.assisters.end(); ++i) {
285
CGroup *group = (*i)->firstGroup();