Skip to content
Snippets Groups Projects
Unit.cpp 6.46 KiB
Newer Older
#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");
#ifdef SC2API
	m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, target.getUnitPtr());
#else
	BOT_ASSERT(false, "buildTarget shouldn't be called for BWAPI bots");
#endif
}

void Unit::train(const UnitType & type) const
{
	BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
	m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(type).buildAbility);
#else
	m_unit->train(type.getAPIUnitType());
#endif
}

void Unit::morph(const UnitType & type) const
{
	BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
	m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(type).buildAbility);
#else
	m_unit->morph(type.getAPIUnitType());
#endif
}

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);
}