File: Attack.cpp

package info (click to toggle)
spring 98.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 41,928 kB
  • ctags: 60,665
  • sloc: cpp: 356,167; ansic: 39,434; python: 12,228; java: 12,203; awk: 5,856; sh: 1,719; xml: 997; perl: 405; php: 253; objc: 194; makefile: 72; sed: 2
file content (138 lines) | stat: -rw-r--r-- 3,206 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "Attack.h"

#include "../CGroup.h"
#include "../CUnitTable.h"
#include "../CDefenseMatrix.h"
#include "../CPathfinder.h"

AttackTask::AttackTask(AIClasses *_ai, int target, CGroup &group): ATask(_ai) {
	const UnitDef *eud = ai->cbc->GetUnitDef(target);

	this->t = TASK_ATTACK;
	this->target = target;
	this->pos    = ai->cbc->GetUnitPos(target);
	if (eud)
		this->enemy = eud->humanName;
	targetAlt = -1;

	addGroup(group);
}

bool AttackTask::onValidate() {
	CGroup *group = firstGroup();

	if (targetAlt >= 0) {
		if (ai->cbc->IsUnitCloaked(targetAlt) || !group->canAttack(targetAlt)) {
			group->stop();
		}
	}

	const UnitDef *eud = ai->cbc->GetUnitDef(target);
	if (eud == NULL)
		return false;

	if (!isMoving) {
		if (ai->cbc->IsUnitCloaked(target))
			return false;
		return true;
	}

	if (!group->canAttack(target))
		return false;

	// don't chase scout groups too long if they are out of base...
	bool scoutGroup = (group->cats&SCOUTER).any();
	if (!scoutGroup && lifeTime() > 20.0f) {
		const unitCategory ecats = UC(eud->id);
		if ((ecats&SCOUTER).any() && !ai->defensematrix->isPosInBounds(pos))
			return false;
	}

	float targetDistance = pos.distance2D(group->pos());
	if (targetDistance > 1000.0f)
		return true; // too far to panic

	if (ai->cbc->IsUnitCloaked(target))
		return false;

	bool isBaseThreat = ai->defensematrix->isPosInBounds(pos);

	// if there is no threat to our base then prevent useless attack for groups
	// which are not too cheap
	if (!isBaseThreat && (group->costMetal / group->units.size()) >= 100.0f) {
		float threatRange;
		if (scoutGroup)
			threatRange = 300.0f;
		else
			threatRange = 0.0f;

		if (group->getThreat(pos, threatRange) > group->strength)
			return false;
	}

	return true;
}

void AttackTask::onUpdate() {
	CGroup *group = firstGroup();

	if (group->isMicroing() && group->isIdle()) {
		targetAlt = -1; // for sure
		group->micro(false);
	}

	if (isMoving) {
		/* Keep tracking the target */
		pos = ai->cbc->GetUnitPos(target);

		float3 gpos = group->pos();
		float dist = gpos.distance2D(pos);
		float range = group->getRange();

		/* See if we can attack our target already */
		if (dist <= range) {
			bool canAttack = true;

			/*
			// for ground units prevent shooting across hill...
			if ((group->cats&AIR).none()) {
				// FIXME: improve
				dist = ai->pathfinder->getPathLength(*group, pos);
				canAttack = (dist <= range * 1.1f);
			}
			*/

			if (canAttack) {
				if ((group->cats&BUILDER).any())
					group->reclaim(target);
				else
					group->attack(target);
				isMoving = false;
				ai->pathfinder->remove(*group);
				group->micro(true);
			}
		}
	}

	/* See if we can attack a target we found on our path */
	if (!(group->isMicroing() || urgent())) {
		if ((group->cats&BUILDER).any())
			resourceScan(); // builders should not be too aggressive
		else
			enemyScan(targetAlt);
	}
}

void AttackTask::toStream(std::ostream& out) const {
	out << "AttackTask(" << key << ") target(" << enemy << ") ";
	CGroup *group = firstGroup();
	if (group)
		out << (*group);
}

void AttackTask::onEnemyDestroyed(int enemy, int attacker) {
	if (target == enemy) {
		LOG_II("AttackTask::onEnemyDestroyed")
		remove();
	}
}