Skip to content
Snippets Groups Projects
Forked from Starcraft AI Course / PyCommandCenter
182 commits behind the upstream repository.
  • David Bergström's avatar
    6ea4b918
    Consolidate raw ability methods · 6ea4b918
    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.
    6ea4b918
    History
    Consolidate raw ability methods
    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.
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);
}