Skip to content
Snippets Groups Projects
Unit.cpp 6.99 KiB
Newer Older
  • Learn to ignore specific revisions
  • #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");
    
            //if unit has order, check tag of target of first order
            if(getUnitPtr()->orders.size() > 0){
              //pray that this value can be declared as CCUnitID
    
    	      CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
    
              //let IDAbot find the unit with this tag
              return m_bot->GetUnit(t_id);
    
    }
    
    bool Unit::isBlip() const
    {
    	BOT_ASSERT(isValid(), "Unit is not valid");
    #ifdef SC2API
    	return m_unit->is_blip;
    #else
    	return m_unit->isBlip();
    #endif
    }