Forked from
Starcraft AI Course / PyCommandCenter
189 commits behind the upstream repository.
-
Sofia Abaied authoredSofia Abaied authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Unit.cpp 8.81 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
}
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);
}
Unit Unit::getTarget() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
BOT_ASSERT(hasTarget(), "Unit has no target");
//if unit has order, check tag of target of first order
if(getUnitPtr()->orders.size() > 0){
//t_id is set to the unit tag of the target
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
//IDAbot finds the unit with this tag
return m_bot->GetUnit(t_id);
}
Unit this_unit = Unit(m_unit, *m_bot);
return this_unit;
}
bool Unit::hasTarget() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
if (getUnitPtr()->orders.size() > 0) {
if (getUnitPtr()->orders[0].target_unit_tag != NULL) {
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
//IDAbot finds the unit with this tag, and returns true if valid
return m_bot->GetUnit(t_id).isValid();
}
}
return false;
}
bool Unit::isBlip() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->is_blip;
#else
return m_unit->isBlip();
#endif
}
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;
}
sc2::AbilityID Unit::getCurrentAbilityID() const
{
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::HOLDPOSITION);
}
void Unit::patrol(const CCPosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::PATROL, targetPosition);
}
void Unit::stopDance() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP_DANCE);
}