Forked from
Starcraft AI Course / PyCommandCenter
182 commits behind the upstream repository.
-
David Bergström authored
Instead of having two ways of using abilities directly, have one way which is consistent with the API. Now unit has one method called `ability` which takes a AbilityID and optionally either a Position or another Unit which to use the ability at.
David Bergström authoredInstead of having two ways of using abilities directly, have one way which is consistent with the API. Now unit has one method called `ability` which takes a AbilityID and optionally either a Position or another Unit which to use the ability at.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Unit.cpp 7.00 KiB
#include "Unit.h"
#include "IDABot.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)
, m_unitType(unit->unit_type, bot)
{
}
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;
}
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
}
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::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::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(m_bot->Map().isConnected(getTilePosition(), pos), "Error: Build Position is not connected to worker");
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
#else
m_unit->build(buildingType.getAPIUnitType(), pos);
#endif
}
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);
}