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