Newer
Older
#include "Unit.h"
#include "IDABot.h"
#include "sc2api/sc2_gametypes.h"
Unit::Unit()
: m_bot(nullptr)
, m_unit(nullptr)
, m_unitID(0)
{
}
Unit::Unit(const sc2::Unit * unit, IDABot & bot)
: m_bot(&bot)
, m_unit(unit)
, m_unitID(unit->tag)
{
}
Unit::Unit(const sc2::Unit * unit)
: m_unit(unit)
, m_unitID(unit->tag)
{
}
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
const sc2::Unit * Unit::getUnitPtr() const
{
return m_unit;
}
const sc2::UnitTypeID & Unit::getAPIUnitType() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->unit_type;
}
bool Unit::operator < (const Unit & rhs) const
{
return m_unit < rhs.m_unit;
}
bool Unit::operator == (const Unit & rhs) const
{
return m_unit == rhs.m_unit;
}
const UnitType & Unit::getType() const
{
return m_unitType;
}
CCPosition Unit::getPosition() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->pos;
}
CCTilePosition Unit::getTilePosition() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return Util::GetTilePosition(m_unit->pos);
}
CCHealth Unit::getHitPoints() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->health;
}
CCHealth Unit::getShields() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->shield;
}
CCHealth Unit::getEnergy() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->energy;
}
float Unit::getBuildPercentage() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->build_progress;
}
CCPlayer Unit::getPlayer() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
switch (m_unit->alliance)
{
case sc2::Unit::Alliance::Self: return Players::Self;
case sc2::Unit::Alliance::Enemy: return Players::Enemy;
case sc2::Unit::Alliance::Neutral: return Players::Neutral;
case sc2::Unit::Alliance::Ally: return Players::Ally;
default: return Players::None;
}
}
CCUnitID Unit::getID() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
CCUnitID id = m_unit->tag;
BOT_ASSERT(id == m_unitID, "Unit ID changed somehow");
return id;
}
bool Unit::isCompleted() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->build_progress >= 1.0f;
}
bool Unit::isTraining() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->orders.size() > 0 && m_unitType.isBuilding();
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
}
bool Unit::isBeingConstructed() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return !isCompleted() && m_unit->build_progress > 0.0f;
}
int Unit::getWeaponCooldown() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return (int)m_unit->weapon_cooldown;
}
bool Unit::isCloaked() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->cloak;
#else
return m_unit->isCloaked();
#endif
}
bool Unit::isFlying() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->is_flying;
#else
return m_unit->isFlying();
#endif
}
std::vector<CCBuff> Unit::buffs() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->buffs;
#else
return m_unit->buffs();
#endif
}
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
bool Unit::isAlive() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->is_alive;
#else
return m_unit->getHitPoints() > 0;
#endif
}
bool Unit::isPowered() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->is_powered;
#else
return m_unit->isPowered();
#endif
}
bool Unit::isIdle() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->orders.empty();
#else
return m_unit->isIdle() && !m_unit->isMoving() && !m_unit->isGatheringGas() && !m_unit->isGatheringMinerals();
#endif
}
bool Unit::isBurrowed() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->is_burrowed;
#else
return m_unit->isBurrowed();
#endif
}
bool Unit::isValid() const
{
return m_unit != nullptr;
}
void Unit::stop() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP);
#else
m_unit->stop();
#endif
}
void Unit::attackUnit(const Unit & target) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
BOT_ASSERT(target.isValid(), "Target is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::ATTACK_ATTACK, target.getUnitPtr());
#else
m_unit->attack(target.getUnitPtr());
#endif
}
void Unit::attackMove(const CCPosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::ATTACK_ATTACK, targetPosition);
#else
m_unit->attack(targetPosition);
#endif
}
void Unit::move(const CCPosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_MOVE, targetPosition);
#else
m_unit->move(targetPosition);
#endif
}
void Unit::move(const CCTilePosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_MOVE, CCPosition((float)targetPosition.x, (float)targetPosition.y));
#else
m_unit->move(CCPosition(targetPosition));
#endif
}
void Unit::rightClick(const Unit & target) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::SMART, target.getUnitPtr());
#else
m_unit->rightClick(target.getUnitPtr());
#endif
}
void Unit::repair(const Unit & target) const
{
rightClick(target);
}
void Unit::build(const UnitType & buildingType, CCTilePosition pos) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
if (m_bot->Map().isConnected(getTilePosition(), pos))
{
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
}
else
{
printf("Warning! Cannot build at location (%d, %d) and therefore ignoring command.", pos.x, pos.y);
}
}
void Unit::buildTarget(const UnitType & buildingType, const Unit & target) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, target.getUnitPtr());
}
void Unit::train(const UnitType & type) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(type).buildAbility);
}
void Unit::morph(const UnitType & type) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(type).morphAbility);
}
void Unit::research(sc2::UpgradeID upgrade) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(upgrade).buildAbility);
}
bool Unit::isConstructing(const UnitType & type) const
{
sc2::AbilityID buildAbility = m_bot->Data(type).buildAbility;
return (getUnitPtr()->orders.size() > 0) && (getUnitPtr()->orders[0].ability_id == buildAbility);
void Unit::ability(sc2::AbilityID ability) const
{
m_bot->Actions()->UnitCommand(getUnitPtr(), ability, false);
}
void Unit::ability(sc2::AbilityID ability, const sc2::Point2D& point) const
{
m_bot->Actions()->UnitCommand(getUnitPtr(), ability, point, false);
}
void Unit::ability(sc2::AbilityID ability, const Unit& target) const
{
m_bot->Actions()->UnitCommand(getUnitPtr(), ability, target.getUnitPtr(), false);
}
// if unit has order, check tag of target of first order
// t_id is set to the unit tag of the target
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
// Make sure the returned tag is not the NullTag
if (t_id == sc2::NullTag) {
return *this;
}
// Make sure the Tag references a valid unit
if (m_bot->Observation()->GetUnit(t_id) == nullptr) {
return *this;
}
// Convert the tag to a Unit object
Unit unit = m_bot->GetUnit(t_id);
if (unit.isValid()) {
return unit;
} else {
return *this;
}
if (getUnitPtr()->orders[0].target_unit_tag != sc2::NullTag) {
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
if (m_bot->Observation()->GetUnit(t_id) == nullptr) {
return false;
}
Unit unit = m_bot->GetUnit(t_id);
return unit.isValid();
}
bool Unit::isBlip() const
{
CCHealth Unit::getMaxHitPoints() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->health_max;
float Unit::getFacing() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->facing;
}
float Unit::getRadius() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->radius;
}
float Unit::getProgress() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// If unit has order, return progress of first order
if (getUnitPtr()->orders.size() > 0) {
return getUnitPtr()->orders[0].progress;
}
return -1;
}
const std::vector<float> Unit::getAllProgress() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// If unit has order, return progress of first order
std::vector<float> progressions;
if (getUnitPtr()->orders.size() > 0) {
for(int i = 0; i < getUnitPtr()->orders.size(); i++) {
progressions.push_back(getUnitPtr()->orders[i].progress);
}
}
return progressions;
}
{
BOT_ASSERT(isValid(), "Unit is not valid");
// If unit has order, return AbilityID of first order
if (getUnitPtr()->orders.size() > 0) {
return getUnitPtr()->orders[0].ability_id;
}
// return invalid AbilityID
return sc2::ABILITY_ID::INVALID;
}
void Unit::holdPosition() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_HOLDPOSITION);
}
void Unit::patrol(const CCPosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_PATROL, targetPosition);
}
void Unit::stopDance() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP_DANCE);
}
/*
// Implementation by Dawid Abucewicz
bool Unit::isCarryingMinerals() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
std::vector<CCBuff> buffs = m_unit->buffs;
for (auto & b : buffs)
{
if (b.to_string() == "271" or b.to_string() == "272")
{
return true;
}
}
return false;
int Unit::gasLeftInGeyser() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->vespene_contents;
}
int Unit::mineralsLeftInMineralfield() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->mineral_contents;
}
int Unit::getOwner() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->owner;
}
// Implemented with Blizzard SC2 API
bool Unit::isCarryingGas() const
{
return sc2::IsCarryingVespene(*m_unit);
}
bool Unit::isCarryingMinerals() const
{
return sc2::IsCarryingMinerals(*m_unit);
}
float Unit::maxShields() const
{
return m_unit->shield_max;
}
float Unit::maxEnergy() const
{
return m_unit->energy_max;