Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • stebr364/pycommandcenter
  • starcraft-ai-course/pycommandcenter
  • eriah592/pycommandcenter
  • edvbe696/pycommandcenter
  • dawab699/pycommandcenter
  • hanja189/pycommandcenter
  • teoga849/pycommandcenter
  • musab250/pycommandcenter
  • emibr898/pycommandcenter
  • chrgu102/pycommandcenter
  • axega544/pycommandcenter
  • edvth289/pycommandcenter
  • jonbo278/py-command-center-v-2
13 results
Show changes
......@@ -5,6 +5,7 @@
class IDABot;
class BaseLocation;
class UnitType;
class Unit;
class BuildingPlacer
{
......@@ -23,13 +24,16 @@ public:
BuildingPlacer(IDABot & bot);
void onStart();
void updateReserved(const std::vector<Unit> & units);
void freeAllTiles();
// determines whether we can build at a given location
bool canBuildHere(int bx, int by, const UnitType & type) const;
bool canBuildHereWithSize(int bx, int by, int width, int height);
bool canBuildHereWithSpace(int bx, int by, const UnitType & type, int buildDist) const;
// returns a build location near a building's desired location
CCTilePosition getBuildLocationNear(const CCTilePosition & p, const UnitType & type, int buildDist) const;
CCTilePosition getBuildLocationNear(const CCTilePosition & p, const UnitType & type, int buildDist, size_t search_count = 1000) const;
void drawReservedTiles();
......
......@@ -2,12 +2,13 @@
file(GLOB BOT_SOURCES "*.cpp" "*.h" "*.hpp")
include_directories(SYSTEM
${PROJECT_SOURCE_DIR}/lib/s2client-api/include
${PROJECT_SOURCE_DIR}/lib/s2client-api/contrib/protobuf/src
${PROJECT_BINARY_DIR}/lib/s2client-api/generated
${PROJECT_SOURCE_DIR}/lib/cpp-sc2/include
${PROJECT_SOURCE_DIR}/lib/cpp-sc2/contrib/protobuf/src
${PROJECT_BINARY_DIR}/lib/cpp-sc2/generated
${PROJECT_SOURCE_DIR}/lib/json/include
)
link_directories(${PROJECT_BINARY_DIR}/s2client-api/bin)
link_directories(${PROJECT_BINARY_DIR}/cpp-sc2/bin)
# Enable compilation of the SC2 version of the bot.
add_definitions(-DSC2API)
......
......@@ -24,10 +24,11 @@ typedef sc2::Tag CCUnitID;
typedef sc2::Race CCRace;
typedef float CCHealth;
typedef float CCPositionType;
typedef sc2::BuffID CCBuff;
typedef size_t CCPlayer;
namespace Players
{
enum {Self = 0u, Enemy = 1u, Neutral = 2u, Ally = 3u, Size = 4u, None = 5u};
}
\ No newline at end of file
}
#include "IDABot.h"
#include "Util.h"
#include "sc2api/sc2_score.h"
void IDABot::OnStep_UpdateIDABot()
{
// This is the entry point of the bot.
// This function is called every time the game loop is run.
//if (!Bases().getPlayerStartingBaseLocation(Players::Enemy)->isExplored())
//{
// assignScout();
//}
std::vector<UnitType> build_plan = CreateBuildPlan();
manageWorkers(build_plan);
manageBuilding(build_plan);
}
void IDABot::manageBuilding(std::vector<UnitType> & build_plan)
{
std::map<UnitType, int> currently_being_built = numberOfTypeBeingBuilt();
for (auto & pair : currently_being_built)
std::cout << "Building " << pair.second << " of " << pair.first.getName() << std::endl;
int minerals = GetMinerals();
int gas = GetGas();
// TODO: Supply
for (UnitType type : build_plan)
{
if (currently_being_built[type] > 0)
{
currently_being_built[type]--;
std::cout << "Already building " << type.getName() << std::endl;
continue;
}
// If we cannot afford the next thing, we don't want to build at all
if (type.mineralPrice() > minerals || type.gasPrice() > gas)
{
break;
}
std::vector<Unit> producers = getProducer(MetaType(type, *this));
// Reserve some resources
// TODO: Only reserve resources if the corresponding worker is in BuildingWalking
minerals -= type.mineralPrice();
gas -= type.gasPrice();
if (!producers.empty())
{
if (type.isBuilding())
{
for (Unit & worker : getWorkers())
{
if (isFree(worker))
{
CCTilePosition position = getBuildPosition(type);
BuildStatus status{ type, position };
currently_building[worker] = status;
// Reserve the location
m_buildingPlacer.reserveTiles(position.x, position.y, type.tileWidth(), type.tileHeight());
// Update economy book-keeping
if (type.isRefinery() || type.isResourceDepot())
{
economy_spending.minerals += type.mineralPrice();
economy_spending.gas += type.gasPrice();
}
else if (type.supplyProvided() == 0)
{
military_spending.minerals += type.mineralPrice();
military_spending.gas += type.gasPrice();
}
assignWork(worker, Assignment::BuildWalking);
return;
}
}
}
else if (type.isCombatUnit() || type.isWorker())
{
// TODO: Remove code-duplication
// Update economy book-keeping
if (type.isWorker())
{
economy_spending.minerals += type.mineralPrice();
economy_spending.gas += type.gasPrice();
}
else
{
military_spending.minerals += type.mineralPrice();
military_spending.gas += type.gasPrice();
}
std::cout << "Training unit " << type.getName() << std::endl;
producers.front().train(type);
return;
}
}
}
}
bool IDABot::isFree(Unit & worker)
{
if (workerAssignment.count(worker) > 0)
{
return workerAssignment[worker] == Assignment::Mineral;
}
else
{
return true;
}
}
std::vector<UnitType> IDABot::CreateBuildPlan()
{
// Count the total number of minerals, including all bases
size_t number_of_minerals{ 0 };
for (const BaseLocation * base : Bases().getOccupiedBaseLocations(Players::Self))
{
number_of_minerals += base->getMinerals().size();
}
size_t number_of_workers = getWorkers().size();
size_t available_food = GetMaxSupply() - GetCurrentSupply();
std::vector<UnitType> build_plan;
std::cout << "Military spending (minerals) " << military_spending.minerals << std::endl;
std::cout << "Economy spending (minerals) " << economy_spending.minerals << std::endl;
// TODO: Make a better decision here
if ((500 + military_spending.minerals) < economy_spending.minerals)
{
CreateMaximizeMilitaryBuildPlan(build_plan, available_food);
CreateMaximizeEconomyBuildPlan(number_of_minerals, number_of_workers, available_food, build_plan);
}
else
{
CreateMaximizeEconomyBuildPlan(number_of_minerals, number_of_workers, available_food, build_plan);
CreateMaximizeMilitaryBuildPlan(build_plan, available_food);
}
for (size_t i{}; i < build_plan.size() && i < 10; ++i)
{
std::cout << build_plan[i].getName() << ", ";
}
std::cout << std::endl;
return build_plan;
}
void IDABot::CreateMaximizeMilitaryBuildPlan(std::vector<UnitType> &build_plan, size_t &available_food)
{
for (auto & pair : military_goal)
{
// How many do we already have?
size_t units_of_type = GetUnits(pair.first).size();
// First, do we meet the military goal for this UnitType?
if (units_of_type >= pair.second) {
continue;
}
// Second, can we produce anything of UnitType?
std::vector<Unit> producers = getProducer(MetaType(pair.first, *this), true);
// TODO: Don't build too many Barracks if we don't need to
if (producers.empty())
{
// TODO: Calculate what we need to build using the TechTree
// For now, let's build a barrack
build_plan.push_back(UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, *this));
}
else
{
// TODO: This is never run, or is it??
int units_needed = pair.second - units_of_type;
int food_required = pair.first.supplyRequired();
for (int i{}; i < units_needed; ++i)
{
if (available_food >= food_required)
{
return;
}
else
{
available_food -= food_required;
build_plan.push_back(pair.first);
}
}
}
}
}
void IDABot::CreateMaximizeEconomyBuildPlan(size_t &number_of_minerals, size_t &number_of_workers, size_t &available_food, std::vector<UnitType> &build_plan)
{
const int WORKER_PER_MINERAL_DEPOSIT = 3;
const int FOOD_THRESHOLD_BUILD_DEPOT = 1;
// Plan for the two next base expansions
for (int i = 0; i < 2; i++)
{
while (WORKER_PER_MINERAL_DEPOSIT * number_of_minerals > number_of_workers)
{
if (available_food == FOOD_THRESHOLD_BUILD_DEPOT)
{
UnitType type{ sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, *this };
build_plan.push_back(type);
available_food += type.supplyProvided(); // TODO: Maybe 16 sometimes? (+16 with Calldown: Supplies)
}
else
{
build_plan.push_back(UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, *this));
available_food--;
number_of_workers++;
}
}
UnitType type{ sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, *this };
build_plan.push_back(type);
available_food += type.supplyProvided();
const BaseLocation * next_expansion = Bases().getNextExpansion(Players::Self);
if (next_expansion)
{
number_of_minerals += next_expansion->getMinerals().size();
}
}
}
void IDABot::assignScout()
{
// Assumes that at least one worker is unassigned
for (Unit worker : getWorkers())
{
if (workerAssignment.count(worker) == 0)
{
assignWork(worker, Assignment::Scout);
std::cout << "Assigned worker to Scout" << std::endl;
break;
}
}
}
void IDABot::manageWorkers(std::vector<UnitType> & build_plan)
{
std::vector<Unit> workers = getWorkers();
for (Unit worker : workers)
{
// If the worker has does not have an assignment
if (workerAssignment.count(worker) == 0)
{
assignWork(worker, Assignment::Mineral);
}
else
{
CCTilePosition position;
switch (workerAssignment[worker]) {
case Assignment::Mineral:
case Assignment::Gas:
// Never change let the gas/mineral workers rest
break;
case Assignment::Scout:
if (Bases().getPlayerStartingBaseLocation(Players::Enemy)->isExplored()) {
assignWork(worker, Assignment::Mineral);
}
break;
case Assignment::BuildWalking:
position = currently_building[worker].position;
if (position == Util::GetTilePosition(worker.getPosition()))
{
assignWork(worker, Assignment::BuildBuilding);
}
break;
case Assignment::BuildBuilding:
// Probably done,
if (worker.isIdle())
{
BuildStatus status = currently_building[worker];
m_buildingPlacer.freeTiles(status.position.x, status.position.y, status.type.tileWidth(), status.type.tileHeight());
currently_building.erase(worker);
assignWork(worker, Assignment::Mineral);
}
break;
}
}
}
}
void IDABot::assignWork(Unit & worker, Assignment assignment)
{
// Assigns worker to assignment
workerAssignment[worker] = assignment;
Unit mineral;
const BaseLocation * enemyBaseLocation;
CCTilePosition position;
AssignmentData data;
const BaseLocation * assigned_base;
switch (assignment) {
case Assignment::Mineral:
// Select which base to mine for
assigned_base = AssignBase(worker);
mineral = getClosestMineral(assigned_base->getPosition());
worker.rightClick(mineral);
break;
case Assignment::Scout:
enemyBaseLocation = Bases().getPlayerStartingBaseLocation(Players::Enemy);
if (enemyBaseLocation)
{
std::cout << "Enemy base location known!" << std::endl;
worker.move(enemyBaseLocation->getPosition());
}
else
{
std::cout << "Enemy base location unknown!" << std::endl;
for (const BaseLocation * location : Bases().getStartingBaseLocations())
{
if (!Map().isExplored(location->getPosition()))
{
worker.move(location->getPosition());
break;
}
}
}
break;
case Assignment::BuildWalking:
worker.move(currently_building[worker].position);
break;
case Assignment::BuildBuilding:
worker.build(currently_building[worker].type, currently_building[worker].position);
break;
}
}
std::map<UnitType, int> IDABot::numberOfTypeBeingBuilt() const
{
std::map<UnitType, int> being_built;
for (auto & pair : currently_building)
{
being_built[pair.second.type]++;
}
return being_built;
}
const BaseLocation * IDABot::AssignBase(Unit & worker)
{
std::set<const BaseLocation *> base_locations = Bases().getOccupiedBaseLocations(Players::Self);
int most_needed_workers_value{std::numeric_limits<int>().min()};
const BaseLocation * most_needed_workers_pointer{};
for (const BaseLocation * base_location : base_locations)
{
int workers_needed = 3 * base_location->getMinerals().size();
int number_of_workers;
if (base_assignment.count(base_location) > 0)
{
std::vector<Unit> & workers = base_assignment[base_location];
number_of_workers = workers.size();
}
else
{
number_of_workers = 0;
std::vector<Unit> workers;
base_assignment[base_location] = workers;
}
int needed_workers = workers_needed - number_of_workers;
if (needed_workers > most_needed_workers_value)
{
most_needed_workers_value = needed_workers;
most_needed_workers_pointer = base_location;
}
}
std::vector<Unit> & workers = base_assignment[most_needed_workers_pointer];
workers.push_back(worker);
return most_needed_workers_pointer;
}
CCTilePosition IDABot::getBuildPosition(UnitType & building)
{
CCTilePosition tile_position;
if (Util::GetTownHall(GetPlayerRace((int) Players::Self), *this) == building)
{
tile_position = Bases().getNextExpansion((int)Players::Self)->getDepotPosition();
}
else
{
CCPosition position = Bases().getPlayerStartingBaseLocation(Players::Self)->getPosition();
tile_position = m_buildingPlacer.getBuildLocationNear(Util::GetTilePosition(position), building, 1);
}
return tile_position;
}
Unit IDABot::getClosestMineral(const CCPosition & position) const
{
Unit bestMineral;
double bestDist = 100000;
for (auto & mineral : GetAllUnits())
{
if (!mineral.getType().isMineral()) continue;
double dist = Util::Dist(mineral, position);
if (dist < bestDist)
{
bestMineral = mineral;
bestDist = dist;
}
}
return bestMineral;
}
std::vector<Unit> IDABot::getWorkers()
{
std::vector<Unit> workers;
for (auto & unit : GetMyUnits())
{
if (unit.getType().isWorker())
{
workers.push_back(unit);
}
}
return workers;
}
std::vector<Unit> IDABot::getProducer(const MetaType & type, bool includeBusy, bool includeIncomplete)
{
// get all the types of units that cna build this type
auto & producerTypes = Data(type).whatBuilds;
// make a set of all candidate producers
std::vector<Unit> candidateProducers;
for (auto unit : UnitInfo().getUnits(Players::Self))
{
// reasons a unit can not train the desired type
if (std::find(producerTypes.begin(), producerTypes.end(), unit.getType()) == producerTypes.end()) { continue; }
if (!includeIncomplete && !unit.isCompleted()) { continue; }
if (!includeBusy && Data(unit).isBuilding && unit.isTraining()) { continue; }
if (unit.isFlying()) { continue; }
// TODO: if unit is not powered continue
// TODO: if the type is an addon, some special cases
// TODO: if the type requires an addon and the producer doesn't have one
// if we haven't cut it, add it to the set of candidates
candidateProducers.push_back(unit);
}
return candidateProducers;
}
IDABot::IDABot()
: m_map(*this)
......@@ -465,7 +10,6 @@ IDABot::IDABot()
, m_techTree(*this)
, m_buildingPlacer(*this)
{
military_goal[UnitType(sc2::UNIT_TYPEID::TERRAN_MARINE, *this)] = 30;
}
void IDABot::OnGameStart()
......@@ -487,9 +31,9 @@ void IDABot::OnGameStart()
m_map.onStart();
m_unitInfo.onStart();
m_bases.onStart();
// TODO: Maybe not include this for the students to use??
m_buildingPlacer.onStart();
/*
UnitType target { sc2::UNIT_TYPEID::TERRAN_FUSIONCORE, *this };
std::vector<UnitType> needed = { target };
build_order.clear();
......@@ -517,6 +61,7 @@ void IDABot::OnGameStart()
std::cout << "." << std::endl;
std::cout << "Created build plan of " << build_order.size() << " steps." << std::endl;
*/
}
void IDABot::OnStep()
......@@ -529,16 +74,21 @@ void IDABot::OnStep()
m_unitInfo.onFrame();
m_bases.onFrame();
// -----------------------------------------------------------------
// Run the actual bot.
// -----------------------------------------------------------------
OnStep_UpdateIDABot();
// suppress warnings while we update the tiles occupied by units
bool old_suppress = m_techTree.getSuppressWarnings();
m_techTree.setSuppressWarnings(true);
m_buildingPlacer.updateReserved(GetAllUnits());
m_techTree.setSuppressWarnings(old_suppress);
// -----------------------------------------------------------------
// Draw debug interface, and send debug interface to the Sc2 client.
// -----------------------------------------------------------------
Debug()->SendDebug();
m_buildingPlacer.drawReservedTiles();
m_buildingPlacer.drawReservedTiles();
}
void IDABot::OnGameEnd()
{
}
void IDABot::setUnits()
......@@ -586,7 +136,7 @@ int IDABot::GetCurrentFrame() const
return (int)Observation()->GetGameLoop();
}
const TechTree & IDABot::TechTree() const
const TechTree & IDABot::GetTechTree() const
{
return m_techTree;
}
......@@ -613,6 +163,10 @@ int IDABot::GetGas() const
Unit IDABot::GetUnit(const CCUnitID & tag) const
{
if (Observation()->GetUnit(tag) == nullptr) {
return Unit();
}
return Unit(Observation()->GetUnit(tag), *(IDABot *)this);
}
......@@ -656,6 +210,17 @@ void IDABot::OnError(const std::vector<sc2::ClientError> & client_errors, const
// This is called when the sc2api (Google's API) has an error.
}
BuildingPlacer & IDABot::GetBuildingPlacer()
{
return m_buildingPlacer;
}
void IDABot::SendChat(const std::string & message)
{
Actions()->SendChat(message);
}
const TypeData & IDABot::Data(const UnitType & type) const
{
return m_techTree.getData(type);
......@@ -676,3 +241,176 @@ const TypeData & IDABot::Data(const MetaType & type) const
return m_techTree.getData(type);
}
/*
API extended summer 2020
*/
void IDABot::DebugCreateUnit(UnitTypeID unit_type, const CCPosition& p, uint32_t player_id, uint32_t count)
{
switch (player_id) // playerconstants for the IDAbot is not the same as for the sc2 API
{
case 0:
Debug()->DebugCreateUnit(unit_type, p, 1, count);
break;
case 1:
Debug()->DebugCreateUnit(unit_type, p, 2, count);
break;
case 2:
Debug()->DebugCreateUnit(unit_type, p, 0, count);
break;
case 3:
Debug()->DebugCreateUnit(unit_type, p, 3, count);
default:
break;
}
}
void IDABot::DebugKillUnit(const Unit unit)
{
Debug()->DebugKillUnit(unit.getUnitPtr());
}
void IDABot::DebugShowMap()
{
Debug()->DebugShowMap();
}
void IDABot::DebugFastBuild()
{
Debug()->DebugFastBuild();
}
void IDABot::DebugEnemyControl()
{
Debug()->DebugEnemyControl();
}
void IDABot::DebugIgnoreFood()
{
Debug()->DebugIgnoreFood();
}
void IDABot::DebugIgnoreResourceCost()
{
Debug()->DebugIgnoreResourceCost();
}
void IDABot::DebugGiveAllResources()
{
Debug()->DebugGiveAllResources();
}
void IDABot::DebugGodMode()
{
Debug()->DebugGodMode();
}
void IDABot::DebugIgnoreMineral()
{
Debug()->DebugIgnoreMineral();
}
void IDABot::DebugNoCooldowns()
{
Debug()->DebugIgnoreMineral();
}
void IDABot::DebugGiveAllTech()
{
Debug()->DebugGiveAllTech();
}
void IDABot::DebugGiveAllUpgrades()
{
Debug()->DebugGiveAllUpgrades();
}
void IDABot::DebugSetScore(float score)
{
Debug()->DebugSetScore(score);
}
void IDABot::DebugEndGame(bool victory)
{
Debug()->DebugEndGame(victory);
}
void IDABot::DebugSetEnergy(float value, const Unit unit)
{
Debug()->DebugSetEnergy(value, unit.getUnitPtr());
}
void IDABot::DebugSetLife(float value, const Unit unit)
{
Debug()->DebugSetLife(value, unit.getUnitPtr());
}
void IDABot::DebugSetShields(float value, const Unit unit)
{
Debug()->DebugSetShields(value, unit.getUnitPtr());
}
// There is a bug in the latest SC2 (if using Blizzard API with game >=4.10)
// This a function to get the enemy base instead of using build location manager
// Switched over to other API where this is solved
// Leaving function incase of it breaking
const std::vector<Point2D> IDABot::GetEnemyBaseLocations()
{
return Observation()->GetGameInfo().enemy_start_locations;
}
bool IDABot::HasCreep(Point2D p) const
{
return Observation()->HasCreep(p);
}
void IDABot::CameraMove(Point2DI p)
{
ActionsFeatureLayer()->CameraMove(p);
}
sc2::ABILITY_ID IDABot::abilityForUpgrade(sc2::UpgradeID upgrade_id) const
{
return (sc2::ABILITY_ID)Observation()->GetUpgradeData()[upgrade_id].ability_id;
}
uint32_t IDABot::UpgradeMineralCost(sc2::UpgradeID upgrade_id) const
{
return Observation()->GetUpgradeData()[upgrade_id].mineral_cost;
}
uint32_t IDABot::UpgradeGasCost(sc2::UpgradeID upgrade_id) const
{
return Observation()->GetUpgradeData()[upgrade_id].vespene_cost;
}
float IDABot::UpgradeResearchTime(sc2::UpgradeID upgrade_id) const
{
return Observation()->GetUpgradeData()[upgrade_id].research_time;
}
float IDABot::RadiusEffect(sc2::EffectID effect_id) const
{
return Observation()->GetEffectData()[effect_id].radius;
}
float IDABot::GetScore() const
{
return Observation()->GetScore().score;
}
const sc2::GameResult IDABot::GetPlayerResults() const
{
auto res = Observation()->GetResults();
for(int i = 0; i < res.size(); i++)
{
if (res.at(i).player_id == Observation()->GetPlayerID()) return res.at(i).result;
}
std::cout << "The player can not be found" << std::endl;
return sc2::GameResult::Undecided;
}
bool IDABot::SaveReplay(const std::string& path)
{
return this->Control()->SaveReplay(path);
}
\ No newline at end of file
......@@ -10,16 +10,20 @@
#include "UnitInfoManager.h"
#include "BuildingPlacer.h"
#include "TechTree.h"
#include "TechTreeImproved.h"
#include "MetaType.h"
#include "Unit.h"
using sc2::UnitTypeID;
using sc2::Point2D;
using sc2::Point2DI;
class IDABot : public sc2::Agent
{
MapTools m_map;
BaseLocationManager m_bases;
UnitInfoManager m_unitInfo;
TechTree m_techTree;
// TODO: This should not be exported for student use
BuildingPlacer m_buildingPlacer;
std::vector<Unit> m_allUnits;
......@@ -34,85 +38,20 @@ public:
void OnGameStart() override;
void OnStep() override;
virtual void OnStep_UpdateIDABot();
/*
My stuff
*/
// Worker management
enum Assignment {
Scout,
Mineral,
Gas,
BuildWalking,
BuildBuilding
};
struct AssignmentData {
// When assigned to building, this corresponds to the location for the building
CCTilePosition buildGoal;
};
// Building management
// Worker assignment book-keeping
std::map<Unit, Assignment> workerAssignment;
// When workers are assigned to either minerals or gas, they get assigned a base
std::map<const BaseLocation *, std::vector<Unit>> base_assignment;
std::vector<UnitType> build_order; // TODO: Not used
std::vector<UnitType> CreateBuildPlan();
void CreateMaximizeMilitaryBuildPlan(std::vector<UnitType> &build_plan, size_t &available_food);
void CreateMaximizeEconomyBuildPlan(size_t &number_of_minerals, size_t &number_of_workers, size_t &available_food, std::vector<UnitType> &build_plan);
void assignScout();
void manageWorkers(std::vector<UnitType> & build_plan);
void manageBuilding(std::vector<UnitType> & build_plan);
bool isFree(Unit & worker);
void assignWork(Unit & worker, Assignment assignment);
std::map<UnitType, int> numberOfTypeBeingBuilt() const;
const BaseLocation * AssignBase(Unit & worker);
CCTilePosition getBuildPosition(UnitType & building);
Unit getClosestMineral(const CCPosition & unit) const;
struct BuildStatus
{
UnitType type;
CCTilePosition position;
int idle;
};
std::map<Unit, BuildStatus> currently_building;
// Military management
std::map<UnitType, int> military_goal;
// Economy
struct Resources
{
int minerals;
int gas;
};
Resources military_spending{};
Resources economy_spending{};
// Getters
std::vector<Unit> getWorkers();
// Maybe
std::vector<Unit> getProducer(const MetaType & type, bool includeBusy = false, bool include_incomplete = false);
void OnGameEnd() override;
/*
API for students
*/
const TechTree & TechTree() const;
const TechTree & GetTechTree() const;
const BaseLocationManager & Bases() const;
const MapTools & Map() const;
const UnitInfoManager & UnitInfo() const;
CCRace GetPlayerRace(int player) const;
CCPosition GetStartLocation() const;
BuildingPlacer & GetBuildingPlacer();
void SendChat(const std::string & message);
int GetCurrentFrame() const;
int GetMinerals() const;
......@@ -125,9 +64,46 @@ public:
const std::vector<Unit> GetUnits(const UnitType & type, int player = Players::Self) const;
const std::vector<CCPosition> & GetStartLocations() const;
/*
API extended summer 2020
*/
void DebugCreateUnit(UnitTypeID unit_type, const CCPosition& p, uint32_t player_id = 1, uint32_t count = 1);
void DebugKillUnit(const Unit unit);
void DebugShowMap();
void DebugFastBuild();
void DebugEnemyControl();
void DebugIgnoreFood();
void DebugIgnoreResourceCost();
void DebugGiveAllResources();
void DebugGodMode();
void DebugIgnoreMineral();
void DebugNoCooldowns();
void DebugGiveAllTech();
void DebugGiveAllUpgrades();
void DebugSetScore(float score);
void DebugEndGame(bool victory);
void DebugSetEnergy(float value, const Unit unit);
void DebugSetLife(float value, const Unit unit);
void DebugSetShields(float value, const Unit unit);
const std::vector<Point2D> GetEnemyBaseLocations();
bool HasCreep(Point2D p) const;
void CameraMove(Point2DI p);
sc2::ABILITY_ID abilityForUpgrade(sc2::UpgradeID upgrade_id) const;
uint32_t UpgradeMineralCost(sc2::UpgradeID upgrade_id) const;
uint32_t UpgradeGasCost(sc2::UpgradeID upgrade_id) const;
float UpgradeResearchTime(sc2::UpgradeID upgrade_id) const;
float RadiusEffect(sc2::EffectID effect_id) const;
float GetScore() const;
const sc2::GameResult GetPlayerResults() const;
bool SaveReplay(const std::string & path);
// Not needed, just convenience functions
const TypeData & Data(const UnitType & type) const;
const TypeData & Data(const CCUpgrade & type) const;
const TypeData & Data(const MetaType & type) const;
const TypeData & Data(const Unit & unit) const;
};
\ No newline at end of file
};
#include "IDAReplayObserver.h"
#include "Util.h"
void IDAReplayObserver::setUnits()
{
m_allUnits.clear();
m_allUnitsID.clear();
for (auto & unit : Observation()->GetUnits())
{
ReplayUnit replayUnit = ReplayUnit(unit, *this);
m_allUnits.push_back(replayUnit);
m_allUnitsID.insert(replayUnit.getID());
}
}
IDAReplayObserver::IDAReplayObserver():
sc2::ReplayObserver(),
m_techTree(*this)
{
}
void IDAReplayObserver::OnGameStart()
{
setUnits();
m_techTree.onStart();
}
void IDAReplayObserver::OnStep()
{
setUnits();
}
void IDAReplayObserver::OnGameEnd()
{
}
void IDAReplayObserver::OnUnitDestroyed(const sc2::Unit* unit)
{
ReplayUnit unitInformation = ReplayUnit(unit, *this);
OnReplayUnitDestroyed(&unitInformation);
}
void IDAReplayObserver::OnReplayUnitDestroyed(const ReplayUnit *)
{
}
void IDAReplayObserver::OnUnitCreated(const sc2::Unit * unit)
{
ReplayUnit unitInformation = ReplayUnit(unit, *this);
OnReplayUnitCreated(&unitInformation);
}
void IDAReplayObserver::OnReplayUnitCreated(const ReplayUnit *)
{
}
void IDAReplayObserver::OnBuildingConstructionComplete(const sc2::Unit *unit)
{
ReplayUnit unitInformation = ReplayUnit(unit, *this);
OnReplayUnitCreated(&unitInformation);
}
ReplayUnit IDAReplayObserver::GetUnit(const CCUnitID tag) const
{
return ReplayUnit(Observation()->GetUnit(tag), *(IDAReplayObserver *)this);
}
bool IDAReplayObserver::UnitExists(const CCUnitID tag) const
{
return m_allUnitsID.find(tag) != m_allUnitsID.end();
}
const std::vector<ReplayUnit>& IDAReplayObserver::GetAllUnits() const
{
return m_allUnits;
}
CCRace IDAReplayObserver::GetPlayerRace(int player)
{
return ReplayControl()->GetReplayInfo().players[player].race;
}
std::string IDAReplayObserver::GetReplayPath()
{
return ReplayControl()->GetReplayInfo().replay_path;
}
sc2::GameResult IDAReplayObserver::GetResultForPlayer(int player)
{
return ReplayControl()->GetReplayInfo().players[player].game_result;
}
const TechTree & IDAReplayObserver::GetTechTree() const
{
return m_techTree;
}
const TypeData & IDAReplayObserver::Data(const UnitType & type) const
{
return m_techTree.getData(type);
}
const TypeData & IDAReplayObserver::Data(const CCUpgrade & type) const
{
return m_techTree.getData(type);
}
const TypeData & IDAReplayObserver::Data(const MetaType & type) const
{
return m_techTree.getData(type);
}
const TypeData & IDAReplayObserver::Data(const Unit & unit) const
{
return m_techTree.getData(unit.getType());
}
#pragma once
#include <deque>
#include <limits>
#include "Common.h"
#include "ReplayUnit.h"
#include "TechTree.h"
class ReplayUnit;
class IDAReplayObserver : public sc2::ReplayObserver
{
void setUnits();
std::vector<ReplayUnit> m_allUnits;
std::set<CCUnitID> m_allUnitsID;
TechTree m_techTree;
public:
IDAReplayObserver();
void OnGameStart() override;
void OnStep() override;
void OnGameEnd() override;
void OnUnitDestroyed(const sc2::Unit*) override;
virtual void OnReplayUnitDestroyed(const ReplayUnit*);
void OnUnitCreated(const sc2::Unit*);
virtual void OnReplayUnitCreated(const ReplayUnit*);
void OnBuildingConstructionComplete(const sc2::Unit*);
ReplayUnit GetUnit(const CCUnitID tag) const;
bool UnitExists(const CCUnitID tag) const;
const std::vector<ReplayUnit> & GetAllUnits() const;
CCRace GetPlayerRace(int player);
std::string GetReplayPath();
sc2::GameResult GetResultForPlayer(int player);
const TechTree & GetTechTree() const;
const TypeData & Data(const UnitType & type) const;
const TypeData & Data(const CCUpgrade & type) const;
const TypeData & Data(const MetaType & type) const;
const TypeData & Data(const Unit & unit) const;
};
......@@ -7,6 +7,23 @@
#include <fstream>
#include <array>
namespace {
bool getBit(const sc2::ImageData& grid, int tileX, int tileY) {
assert(grid.bits_per_pixel == 1);
sc2::Point2DI pointI(tileX, tileY);
if (pointI.x < 0 || pointI.x >= grid.width || pointI.y < 0 || pointI.y >= grid.height)
{
return false;
}
div_t idx = div(pointI.x + pointI.y * grid.width, 8);
return (grid.data[idx.quot] >> (7 - idx.rem)) & 1;
}
} // namespace
const size_t LegalActions = 4;
const int actionX[LegalActions] ={1, -1, 0, 0};
const int actionY[LegalActions] ={0, 0, 1, -1};
......@@ -23,7 +40,8 @@ typedef std::vector<std::vector<float>> vvf;
// constructor for MapTools
MapTools::MapTools(IDABot & bot)
: m_bot (bot)
: m_bot(bot)
, m_mapName ("")
, m_width (0)
, m_height (0)
, m_maxZ (0.0f)
......@@ -37,6 +55,7 @@ void MapTools::onStart()
#ifdef SC2API
m_width = m_bot.Observation()->GetGameInfo().width;
m_height = m_bot.Observation()->GetGameInfo().height;
m_mapName= m_bot.Observation()->GetGameInfo().map_name;
#else
m_width = BWAPI::Broodwar->mapWidth();
m_height = BWAPI::Broodwar->mapHeight();
......@@ -160,8 +179,6 @@ void MapTools::onFrame()
}
}
}
draw();
}
void MapTools::computeConnectivity()
......@@ -263,7 +280,7 @@ bool MapTools::isPowered(int tileX, int tileY) const
#endif
}
float MapTools::terrainHeight(float x, float y) const
float MapTools::terrainHeightFromCoord(float x, float y) const
{
return m_terrainHeight[(int)x][(int)y];
}
......@@ -329,7 +346,8 @@ bool MapTools::isValidPosition(const CCPosition & pos) const
void MapTools::drawLine(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color) const
{
#ifdef SC2API
m_bot.Debug()->DebugLineOut(sc2::Point3D(x1, y1, terrainHeight(x1, y1) + 0.2f), sc2::Point3D(x2, y2, terrainHeight(x2, y2) + 0.2f), color);
//m_bot.Debug()->DebugLineOut(sc2::Point3D(x1, y1, terrainHeight(x1, y1) + 0.2f), sc2::Point3D(x2, y2, terrainHeight(x2, y2) + 0.2f), color);
m_bot.Debug()->DebugLineOut(sc2::Point3D(x1, y1, m_maxZ), sc2::Point3D(x2, y2, m_maxZ), color); // changed to m_maxZ instead fo terrainHeight since it doesnot work correctly
#else
BWAPI::Broodwar->drawLineMap(BWAPI::Position(x1, y1), BWAPI::Position(x2, y2), color);
#endif
......@@ -356,6 +374,10 @@ void MapTools::drawTile(int tileX, int tileY, const CCColor & color) const
drawLine(px, py + d, px, py, color);
}
void MapTools::drawTile(const CCTilePosition & pos, const CCColor & color) const {
drawTile(pos.x, pos.y, color);
}
void MapTools::drawBox(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color) const
{
#ifdef SC2API
......@@ -386,6 +408,15 @@ void MapTools::drawCircle(const CCPosition & pos, CCPositionType radius, const C
#endif
}
void MapTools::drawResourceSphere(const sc2::Point3D & pos, CCPositionType radius, const CCColor & color) const
{
#ifdef SC2API
m_bot.Debug()->DebugSphereOut(pos, radius, color);
#else
BWAPI::Broodwar->drawCircleMap(pos, radius, color);
#endif
}
void MapTools::drawCircle(CCPositionType x, CCPositionType y, CCPositionType radius, const CCColor & color) const
{
#ifdef SC2API
......@@ -514,6 +545,11 @@ int MapTools::height() const
return m_height;
}
std::string MapTools::name() const
{
return m_mapName;
}
const std::vector<CCTilePosition> & MapTools::getClosestTilesTo(const CCTilePosition & pos) const
{
return getDistanceMap(pos).getSortedTiles();
......@@ -543,17 +579,7 @@ CCTilePosition MapTools::getLeastRecentlySeenTile() const
bool MapTools::canWalk(int tileX, int tileY)
{
#ifdef SC2API
auto & info = m_bot.Observation()->GetGameInfo();
sc2::Point2DI pointI(tileX, tileY);
if (pointI.x < 0 || pointI.x >= info.width || pointI.y < 0 || pointI.y >= info.width)
{
return false;
}
assert(info.pathing_grid.data.size() == info.width * info.height);
unsigned char encodedPlacement = info.pathing_grid.data[pointI.x + ((info.height - 1) - pointI.y) * info.width];
bool decodedPlacement = encodedPlacement == 255 ? false : true;
return decodedPlacement;
return getBit(m_bot.Observation()->GetGameInfo().pathing_grid, tileX, tileY);
#else
for (int i=0; i<4; ++i)
{
......@@ -573,17 +599,7 @@ bool MapTools::canWalk(int tileX, int tileY)
bool MapTools::canBuild(int tileX, int tileY)
{
#ifdef SC2API
auto & info = m_bot.Observation()->GetGameInfo();
sc2::Point2DI pointI(tileX, tileY);
if (pointI.x < 0 || pointI.x >= info.width || pointI.y < 0 || pointI.y >= info.width)
{
return false;
}
assert(info.placement_grid.data.size() == info.width * info.height);
unsigned char encodedPlacement = info.placement_grid.data[pointI.x + ((info.height - 1) - pointI.y) * info.width];
bool decodedPlacement = encodedPlacement == 255 ? true : false;
return decodedPlacement;
return getBit(m_bot.Observation()->GetGameInfo().placement_grid, tileX, tileY);
#else
return BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tileX, tileY));
#endif
......@@ -608,48 +624,3 @@ float MapTools::terrainHeight(const CCPosition & point) const
#endif
}
void MapTools::draw() const
{
#ifdef SC2API
CCPosition camera = m_bot.Observation()->GetCameraPos();
int sx = (int)(camera.x - 12.0f);
int sy = (int)(camera.y - 8);
int ex = sx + 24;
int ey = sy + 20;
#else
BWAPI::TilePosition screen(BWAPI::Broodwar->getScreenPosition());
int sx = screen.x;
int sy = screen.y;
int ex = sx + 20;
int ey = sy + 15;
#endif
for (int x = sx; x < ex; ++x)
{
for (int y = sy; y < ey; y++)
{
if (!isValidTile((int)x, (int)y))
{
continue;
}
// TODO: This maybe should be restored somehow? (Check git blame)
if (false)
{
std::stringstream ss;
ss << getSectorNumber(x, y);
drawText(CCPosition(Util::TileToPosition(x + 0.5f), Util::TileToPosition(y + 0.5f)), ss.str());
}
if (false)
{
CCColor color = isWalkable(x, y) ? CCColor(0, 255, 0) : CCColor(255, 0, 0);
if (isWalkable(x, y) && !isBuildable(x, y)) { color = CCColor(255, 255, 0); }
if (isBuildable(x, y) && !isDepotBuildableTile(x, y)) { color = CCColor(127, 255, 255); }
drawTile(x, y, color);
}
}
}
}
......@@ -8,11 +8,12 @@ class IDABot;
class MapTools
{
IDABot & m_bot;
int m_width;
int m_height;
float m_maxZ;
int m_frame;
IDABot & m_bot;
std::string m_mapName;
int m_width;
int m_height;
float m_maxZ;
int m_frame;
// a cache of already computed distance maps, which is mutable since it only acts as a cache
......@@ -41,19 +42,22 @@ public:
void onStart();
void onFrame();
void draw() const;
int width() const;
int height() const;
float terrainHeight(float x, float y) const;
std::string name() const;
float terrainHeightFromCoord(float x, float y) const;
void drawLine(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color = CCColor(255, 255, 255)) const;
void drawLine(const CCPosition & p1, const CCPosition & p2, const CCColor & color = CCColor(255, 255, 255)) const;
void drawTile(int tileX, int tileY, const CCColor & color = CCColor(255, 255, 255)) const;
void drawTile(const CCTilePosition & pos, const CCColor & color) const;
void drawBox(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color = CCColor(255, 255, 255)) const;
void drawBox(const CCPosition & tl, const CCPosition & br, const CCColor & color = CCColor(255, 255, 255)) const;
void drawCircle(CCPositionType x1, CCPositionType x2, CCPositionType radius, const CCColor & color = CCColor(255, 255, 255)) const;
void drawCircle(const CCPosition & pos, CCPositionType radius, const CCColor & color = CCColor(255, 255, 255)) const;
void drawResourceSphere(const sc2::Point3D & pos, CCPositionType radius, const CCColor & color = CCColor(255, 255, 255)) const;
void drawText(const CCPosition & pos, const std::string & str, const CCColor & color = CCColor(255, 255, 255)) const;
void drawTextScreen(float xPerc, float yPerc, const std::string & str, const CCColor & color = CCColor(255, 255, 255)) const;
......
#include "MyAgent.h"
MyAgent::MyAgent()
{
military_goal[UnitType(sc2::UNIT_TYPEID::TERRAN_MARINE, *this)] = 30;
}
void MyAgent::OnGameStart()
{
IDABot::OnGameStart();
sc2::UnitTypeID wanted_type = sc2::UNIT_TYPEID::TERRAN_GHOST;
sc2::UnitTypeData wanted_data = Observation()->GetUnitTypeData()[wanted_type];
std::cout << "Looking up: " << wanted_data.name << std::endl;
sc2::UnitTypeData requirement = Observation()->GetUnitTypeData()[wanted_data.tech_requirement];
std::cout << "Found tech requirement: " << requirement.name << "(" << wanted_data.tech_requirement << ")" << std::endl;
std::cout << std::boolalpha;
std::cout << "Require attached (Is addon?): " << wanted_data.require_attached << std::endl;
std::cout << "Found ability_id" << wanted_data.ability_id << std::endl;
// TODO: What/who can use this ability??
sc2::AbilityData ability_to_create = Observation()->GetAbilityData()[wanted_data.ability_id];
std::cout << "Button name for ability " << ability_to_create.button_name << std::endl;
}
void MyAgent::OnStep()
{
IDABot::OnStep();
// This is the entry point of the bot.
// This function is called every time the game loop is run.
//if (!Bases().getPlayerStartingBaseLocation(Players::Enemy)->isExplored())
//{
// assignScout();
//}
std::vector<UnitType> build_plan = CreateBuildPlan();
manageWorkers(build_plan);
manageBuilding(build_plan);
}
void MyAgent::manageBuilding(std::vector<UnitType> & build_plan)
{
std::map<UnitType, int> currently_being_built = numberOfTypeBeingBuilt();
for (auto & pair : currently_being_built)
std::cout << "Building " << pair.second << " of " << pair.first.getName() << std::endl;
int minerals = GetMinerals();
int gas = GetGas();
// TODO: Supply
for (UnitType type : build_plan)
{
if (currently_being_built[type] > 0)
{
currently_being_built[type]--;
std::cout << "Already building " << type.getName() << std::endl;
continue;
}
// If we cannot afford the next thing, we don't want to build at all
if (type.mineralPrice() > minerals || type.gasPrice() > gas)
{
break;
}
std::vector<Unit> producers = getProducer(MetaType(type, *this));
// Reserve some resources
// TODO: Only reserve resources if the corresponding worker is in BuildingWalking
minerals -= type.mineralPrice();
gas -= type.gasPrice();
if (!producers.empty())
{
if (type.isBuilding())
{
for (Unit & worker : getWorkers())
{
if (isFree(worker))
{
CCTilePosition position = getBuildPosition(type);
BuildStatus status{ type, position };
currently_building[worker] = status;
// Reserve the location
GetBuildingPlacer().reserveTiles(position.x, position.y, type.tileWidth(), type.tileHeight());
// Update economy book-keeping
if (type.isRefinery() || type.isResourceDepot())
{
economy_spending.minerals += type.mineralPrice();
economy_spending.gas += type.gasPrice();
}
else if (type.supplyProvided() == 0)
{
military_spending.minerals += type.mineralPrice();
military_spending.gas += type.gasPrice();
}
assignWork(worker, Assignment::BuildWalking);
return;
}
}
}
else if (type.isCombatUnit() || type.isWorker())
{
// TODO: Remove code-duplication
// Update economy book-keeping
if (type.isWorker())
{
economy_spending.minerals += type.mineralPrice();
economy_spending.gas += type.gasPrice();
}
else
{
military_spending.minerals += type.mineralPrice();
military_spending.gas += type.gasPrice();
}
std::cout << "Training unit " << type.getName() << std::endl;
producers.front().train(type);
return;
}
}
}
}
bool MyAgent::isFree(Unit & worker)
{
if (workerAssignment.count(worker) > 0)
{
return workerAssignment[worker] == Assignment::Mineral;
}
else
{
return true;
}
}
std::vector<UnitType> MyAgent::CreateBuildPlan()
{
// Count the total number of minerals, including all bases
size_t number_of_minerals{ 0 };
for (const BaseLocation * base : Bases().getOccupiedBaseLocations(Players::Self))
{
number_of_minerals += base->getMinerals().size();
}
size_t number_of_workers = getWorkers().size();
size_t available_food = GetMaxSupply() - GetCurrentSupply();
std::vector<UnitType> build_plan;
std::cout << "Military spending (minerals) " << military_spending.minerals << std::endl;
std::cout << "Economy spending (minerals) " << economy_spending.minerals << std::endl;
// TODO: Make a better decision here
if ((500 + military_spending.minerals) < economy_spending.minerals)
{
CreateMaximizeMilitaryBuildPlan(build_plan, available_food);
CreateMaximizeEconomyBuildPlan(number_of_minerals, number_of_workers, available_food, build_plan);
}
else
{
CreateMaximizeEconomyBuildPlan(number_of_minerals, number_of_workers, available_food, build_plan);
CreateMaximizeMilitaryBuildPlan(build_plan, available_food);
}
for (size_t i{}; i < build_plan.size() && i < 10; ++i)
{
std::cout << build_plan[i].getName() << ", ";
}
std::cout << std::endl;
return build_plan;
}
void MyAgent::CreateMaximizeMilitaryBuildPlan(std::vector<UnitType> &build_plan, size_t &available_food)
{
for (auto & pair : military_goal)
{
// How many do we already have?
size_t units_of_type = GetUnits(pair.first).size();
// First, do we meet the military goal for this UnitType?
if (units_of_type >= pair.second) {
continue;
}
// Second, can we produce anything of UnitType?
std::vector<Unit> producers = getProducer(MetaType(pair.first, *this), true);
// TODO: Don't build too many Barracks if we don't need to
if (producers.empty())
{
// TODO: Calculate what we need to build using the TechTree
// For now, let's build a barrack
build_plan.push_back(UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, *this));
}
else
{
// TODO: This is never run, or is it??
int units_needed = pair.second - units_of_type;
int food_required = pair.first.supplyRequired();
for (int i{}; i < units_needed; ++i)
{
if (available_food >= food_required)
{
return;
}
else
{
available_food -= food_required;
build_plan.push_back(pair.first);
}
}
}
}
}
void MyAgent::CreateMaximizeEconomyBuildPlan(size_t &number_of_minerals, size_t &number_of_workers, size_t &available_food, std::vector<UnitType> &build_plan)
{
const int WORKER_PER_MINERAL_DEPOSIT = 3;
const int FOOD_THRESHOLD_BUILD_DEPOT = 1;
// Plan for the two next base expansions
for (int i = 0; i < 2; i++)
{
while (WORKER_PER_MINERAL_DEPOSIT * number_of_minerals > number_of_workers)
{
if (available_food == FOOD_THRESHOLD_BUILD_DEPOT)
{
UnitType type{ sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, *this };
build_plan.push_back(type);
available_food += type.supplyProvided(); // TODO: Maybe 16 sometimes? (+16 with Calldown: Supplies)
}
else
{
build_plan.push_back(UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, *this));
available_food--;
number_of_workers++;
}
}
UnitType type{ sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, *this };
build_plan.push_back(type);
available_food += type.supplyProvided();
const BaseLocation * next_expansion = Bases().getNextExpansion(Players::Self);
if (next_expansion)
{
number_of_minerals += next_expansion->getMinerals().size();
}
}
}
void MyAgent::assignScout()
{
// Assumes that at least one worker is unassigned
for (Unit worker : getWorkers())
{
if (workerAssignment.count(worker) == 0)
{
assignWork(worker, Assignment::Scout);
std::cout << "Assigned worker to Scout" << std::endl;
break;
}
}
}
void MyAgent::manageWorkers(std::vector<UnitType> & build_plan)
{
std::vector<Unit> workers = getWorkers();
for (Unit worker : workers)
{
// If the worker has does not have an assignment
if (workerAssignment.count(worker) == 0)
{
assignWork(worker, Assignment::Mineral);
}
else
{
CCTilePosition position;
switch (workerAssignment[worker]) {
case Assignment::Mineral:
case Assignment::Gas:
// Never change let the gas/mineral workers rest
break;
case Assignment::Scout:
if (Bases().getPlayerStartingBaseLocation(Players::Enemy)->isExplored()) {
assignWork(worker, Assignment::Mineral);
}
break;
case Assignment::BuildWalking:
position = currently_building[worker].position;
if (position == Util::GetTilePosition(worker.getPosition()))
{
assignWork(worker, Assignment::BuildBuilding);
}
break;
case Assignment::BuildBuilding:
// Probably done,
if (worker.isIdle())
{
BuildStatus status = currently_building[worker];
GetBuildingPlacer().freeTiles(status.position.x, status.position.y, status.type.tileWidth(), status.type.tileHeight());
currently_building.erase(worker);
assignWork(worker, Assignment::Mineral);
}
break;
}
}
}
}
void MyAgent::assignWork(Unit & worker, Assignment assignment)
{
// Assigns worker to assignment
workerAssignment[worker] = assignment;
Unit mineral;
const BaseLocation * enemyBaseLocation;
CCTilePosition position;
AssignmentData data;
const BaseLocation * assigned_base;
switch (assignment) {
case Assignment::Mineral:
// Select which base to mine for
assigned_base = AssignBase(worker);
mineral = getClosestMineral(assigned_base->getPosition());
worker.rightClick(mineral);
break;
case Assignment::Scout:
enemyBaseLocation = Bases().getPlayerStartingBaseLocation(Players::Enemy);
if (enemyBaseLocation)
{
std::cout << "Enemy base location known!" << std::endl;
worker.move(enemyBaseLocation->getPosition());
}
else
{
std::cout << "Enemy base location unknown!" << std::endl;
for (const BaseLocation * location : Bases().getStartingBaseLocations())
{
if (!Map().isExplored(location->getPosition()))
{
worker.move(location->getPosition());
break;
}
}
}
break;
case Assignment::BuildWalking:
worker.move(currently_building[worker].position);
break;
case Assignment::BuildBuilding:
worker.build(currently_building[worker].type, currently_building[worker].position);
break;
}
}
std::map<UnitType, int> MyAgent::numberOfTypeBeingBuilt() const
{
std::map<UnitType, int> being_built;
for (auto & pair : currently_building)
{
being_built[pair.second.type]++;
}
return being_built;
}
const BaseLocation * MyAgent::AssignBase(Unit & worker)
{
std::set<const BaseLocation *> base_locations = Bases().getOccupiedBaseLocations(Players::Self);
int most_needed_workers_value{std::numeric_limits<int>().min()};
const BaseLocation * most_needed_workers_pointer{};
for (const BaseLocation * base_location : base_locations)
{
int workers_needed = 3 * base_location->getMinerals().size();
int number_of_workers;
if (base_assignment.count(base_location) > 0)
{
std::vector<Unit> & workers = base_assignment[base_location];
number_of_workers = workers.size();
}
else
{
number_of_workers = 0;
std::vector<Unit> workers;
base_assignment[base_location] = workers;
}
int needed_workers = workers_needed - number_of_workers;
if (needed_workers > most_needed_workers_value)
{
most_needed_workers_value = needed_workers;
most_needed_workers_pointer = base_location;
}
}
std::vector<Unit> & workers = base_assignment[most_needed_workers_pointer];
workers.push_back(worker);
return most_needed_workers_pointer;
}
CCTilePosition MyAgent::getBuildPosition(UnitType & building)
{
CCTilePosition tile_position;
if (Util::GetTownHall(GetPlayerRace((int) Players::Self), *this) == building)
{
tile_position = Bases().getNextExpansion((int)Players::Self)->getDepotPosition();
}
else
{
CCPosition position = Bases().getPlayerStartingBaseLocation(Players::Self)->getPosition();
tile_position = GetBuildingPlacer().getBuildLocationNear(Util::GetTilePosition(position), building, 1);
}
return tile_position;
}
Unit MyAgent::getClosestMineral(const CCPosition & position) const
{
Unit bestMineral;
double bestDist = 100000;
for (auto & mineral : GetAllUnits())
{
if (!mineral.getType().isMineral()) continue;
double dist = Util::Dist(mineral, position);
if (dist < bestDist)
{
bestMineral = mineral;
bestDist = dist;
}
}
return bestMineral;
}
std::vector<Unit> MyAgent::getWorkers()
{
std::vector<Unit> workers;
for (auto & unit : GetMyUnits())
{
if (unit.getType().isWorker())
{
workers.push_back(unit);
}
}
return workers;
}
std::vector<Unit> MyAgent::getProducer(const MetaType & type, bool includeBusy, bool includeIncomplete)
{
// get all the types of units that cna build this type
auto & producerTypes = Data(type).whatBuilds;
// make a set of all candidate producers
std::vector<Unit> candidateProducers;
for (auto unit : UnitInfo().getUnits(Players::Self))
{
// reasons a unit can not train the desired type
if (std::find(producerTypes.begin(), producerTypes.end(), unit.getType()) == producerTypes.end()) { continue; }
if (!includeIncomplete && !unit.isCompleted()) { continue; }
if (!includeBusy && Data(unit).isBuilding && unit.isTraining()) { continue; }
if (unit.isFlying()) { continue; }
// TODO: if unit is not powered continue
// TODO: if the type is an addon, some special cases
// TODO: if the type requires an addon and the producer doesn't have one
// if we haven't cut it, add it to the set of candidates
candidateProducers.push_back(unit);
}
return candidateProducers;
}
#pragma once
#include "IDABot.h"
class MyAgent : public IDABot
{
// Worker management
enum Assignment {
Scout,
Mineral,
Gas,
BuildWalking,
BuildBuilding
};
struct AssignmentData {
// When assigned to building, this corresponds to the location for the building
CCTilePosition buildGoal;
};
// Building management
// Worker assignment book-keeping
std::map<Unit, Assignment> workerAssignment;
// When workers are assigned to either minerals or gas, they get assigned a base
std::map<const BaseLocation *, std::vector<Unit>> base_assignment;
std::vector<UnitType> build_order; // TODO: Not used
std::vector<UnitType> CreateBuildPlan();
void CreateMaximizeMilitaryBuildPlan(std::vector<UnitType> &build_plan, size_t &available_food);
void CreateMaximizeEconomyBuildPlan(size_t &number_of_minerals, size_t &number_of_workers, size_t &available_food, std::vector<UnitType> &build_plan);
void assignScout();
void manageWorkers(std::vector<UnitType> & build_plan);
void manageBuilding(std::vector<UnitType> & build_plan);
bool isFree(Unit & worker);
void assignWork(Unit & worker, Assignment assignment);
std::map<UnitType, int> numberOfTypeBeingBuilt() const;
const BaseLocation * AssignBase(Unit & worker);
CCTilePosition getBuildPosition(UnitType & building);
Unit getClosestMineral(const CCPosition & unit) const;
struct BuildStatus
{
UnitType type;
CCTilePosition position;
int idle;
};
std::map<Unit, BuildStatus> currently_building;
// Military management
std::map<UnitType, int> military_goal;
// Economy
struct Resources
{
int minerals;
int gas;
};
Resources military_spending{};
Resources economy_spending{};
// Getters
std::vector<Unit> getWorkers();
// Maybe
std::vector<Unit> getProducer(const MetaType & type, bool includeBusy = false, bool include_incomplete = false);
public:
MyAgent();
void OnGameStart() override;
void OnStep() override;
};
\ No newline at end of file
#include "ReplayUnit.h"
ReplayUnit::ReplayUnit(const sc2::Unit * unit, IDAReplayObserver & replayObserver)
: m_replayObserver(&replayObserver), Unit(unit), m_type(unit->unit_type, replayObserver, replayObserver)
{
}
const UnitType & ReplayUnit::getType() const
{
return m_type;
}
bool ReplayUnit::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;
// IDAReplayObserver checks if the unit with this tag still exists
if (m_replayObserver->UnitExists(t_id)){
// IDAReplayObserver finds the unit with this tag, and returns true if valid
return m_replayObserver->GetUnit(t_id).isValid();
}
}
}
return false;
}
ReplayUnit ReplayUnit::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) {
// t_id is set to the unit tag of the target
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
// Checks if the tag is a null tag or the unit have been removed
if (t_id != sc2::NullTag && m_replayObserver->UnitExists(t_id)){
// IDAReplayObserver finds the unit with this tag
return m_replayObserver->GetUnit(t_id);
}
}
return *this;
}
int ReplayUnit::getPlayer() const
{
return m_unit->owner;
}
#pragma once
#include "Unit.h"
#include "IDAReplayObserver.h"
class IDAReplayObserver;
//! A Unit that have a replayobserver insted of an Agent,
class ReplayUnit: public Unit
{
mutable IDAReplayObserver * m_replayObserver;
UnitType m_type;
public:
ReplayUnit(const sc2::Unit * unit, IDAReplayObserver & replayObserver);
const UnitType & getType() const;
bool hasTarget() const;
ReplayUnit getTarget() const;
int getPlayer() const;
};
\ No newline at end of file
......@@ -2,8 +2,8 @@
#include "IDABot.h"
#include "MetaType.h"
TechTree::TechTree(IDABot & bot)
: m_bot(bot)
TechTree::TechTree(sc2::Client & client)
: m_client(client), suppressWarnings(false)
{
}
......@@ -12,160 +12,251 @@ void TechTree::onStart()
{
initUnitTypeData();
initUpgradeData();
/* As it turns out, some of the hard-coded values are wrong. Instead of
going through each and checking, we fix them with information from a
(hopefully) up to date JSON-file. Sorry in advance, this was the best
solution at the time. Hopefully the JSON-files are still up to date. */
TechTreeImproved tree;
bool success = tree.LoadData();
// If the file was not successfully open/parsed, don't replace the unitTypeData.
if (!success)
{
return;
}
std::set<sc2::UNIT_TYPEID> updated;
for (const BuildDescription & description : tree.BuildDescriptions())
{
if (m_unitTypeData.count(UnitType(description.result_type, m_client)) == 0)
{
//std::cout << "Inserting new information about UNIT_TYPEID: "
// << sc2::UnitTypeToName(description.result_type) << " ("
// << static_cast<unsigned int>(description.result_type) << ")"
// << std::endl;
}
TypeData & data = m_unitTypeData[UnitType(description.result_type, m_client)];
// If this is the first time we a way to build this type, remove previous data
if (updated.count(description.result_type) == 0)
{
data.whatBuilds.clear();
data.requiredUnits.clear();
data.requiredUpgrades.clear();
updated.insert(description.result_type);
data.buildTime = description.buildTime; // The time in seconds it takes to create the unit
data.buildAbility = sc2::ABILITY_ID::INVALID;
}
data.whatBuilds.push_back(UnitType(description.producer_type, m_client));
if (description.build_ability != sc2::ABILITY_ID::INVALID) data.buildAbility = description.build_ability;
if (description.morph_ability != sc2::ABILITY_ID::INVALID) data.morphAbility = description.morph_ability;
for (sc2::UNIT_TYPEID unit_typeid : description.buildings_needed)
{
data.requiredUnits.push_back(UnitType(unit_typeid, m_client));
}
for (sc2::UNIT_TYPEID unit_typeid : description.addons_needed)
{
data.requiredAddons.push_back(UnitType(unit_typeid, m_client));
}
}
for (std::pair <const sc2::UpgradeID, TypeData> & pair : m_upgradeData)
{
const sc2::UpgradeID id = pair.first;
TypeData & data = pair.second;
data.whatBuilds.clear();
data.requiredUnits.clear();
data.requiredUpgrades.clear();
for (const ResearchDescription & description : tree.HowToResearch(id))
{
data.buildAbility = description.ability_used;
data.whatBuilds.push_back(UnitType(description.producer_type, m_client));
for (sc2::UNIT_TYPEID unit_typeid : description.buildings_needed)
{
data.requiredUnits.push_back(UnitType(unit_typeid, m_client));
}
for (sc2::UPGRADE_ID upgrade_id : description.upgrades_needed)
{
data.requiredUpgrades.push_back(upgrade_id);
}
}
}
}
void TechTree::setSuppressWarnings(bool b)
{
suppressWarnings = b;
}
bool TechTree::getSuppressWarnings() const
{
return suppressWarnings;
}
void TechTree::initUnitTypeData()
{
m_unitTypeData[UnitType(0, m_bot)] = TypeData();
m_unitTypeData[UnitType(0, m_client)] = TypeData();
// Protoss Buildings unit bld wrk rfn sup hall add
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PYLONOVERCHARGED, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::EFFECT_PHOTONOVERCHARGE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_MOTHERSHIPCORE, m_bot), UnitType(sc2::UNIT_TYPEID::PROTOSS_PYLON, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PYLON, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::BUILD_PYLON, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_NEXUS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ASSIMILATOR, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_ASSIMILATOR, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_CYBERNETICSCORE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot), UnitType(sc2::UNIT_TYPEID::PROTOSS_WARPGATE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_DARKSHRINE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FLEETBEACON, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FORGE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_GATEWAY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STARGATE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PHOTONCANNON, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_PHOTONCANNON, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROBOTICSBAY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROBOTICSFACILITY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_TEMPLARARCHIVE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_TWILIGHTCOUNCIL, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_WARPGATE, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_WARPGATE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot) }, {}, { sc2::UPGRADE_ID::WARPGATERESEARCH } };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PYLONOVERCHARGED, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::EFFECT_PHOTONOVERCHARGE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_MOTHERSHIPCORE, m_client), UnitType(sc2::UNIT_TYPEID::PROTOSS_PYLON, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PYLON, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::BUILD_PYLON, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_NEXUS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ASSIMILATOR, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_ASSIMILATOR, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_CYBERNETICSCORE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client), UnitType(sc2::UNIT_TYPEID::PROTOSS_WARPGATE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_DARKSHRINE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FLEETBEACON, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FORGE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_GATEWAY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STARGATE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PHOTONCANNON, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_PHOTONCANNON, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROBOTICSBAY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROBOTICSFACILITY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_TEMPLARARCHIVE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_TWILIGHTCOUNCIL, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_WARPGATE, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_WARPGATE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client) }, {}, { sc2::UPGRADE_ID::WARPGATERESEARCH } };
// Protoss Units unit bld wrk rfn sup hall add
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_bot)] = { sc2::Race::Protoss, 0, 0, 1, 0, true, false, true, false, false, false, false, sc2::ABILITY_ID::TRAIN_PROBE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_MOTHERSHIPCORE, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MOTHERSHIPCORE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ZEALOT, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ZEALOT, sc2::ABILITY_ID::TRAINWARP_ZEALOT, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_SENTRY, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SENTRY, sc2::ABILITY_ID::TRAINWARP_SENTRY, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_STALKER, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_STALKER, sc2::ABILITY_ID::TRAINWARP_STALKER, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_HIGHTEMPLAR, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HIGHTEMPLAR, sc2::ABILITY_ID::TRAINWARP_HIGHTEMPLAR, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKTEMPLAR, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DARKTEMPLAR, sc2::ABILITY_ID::TRAINWARP_DARKTEMPLAR, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ADEPT, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ADEPT, sc2::ABILITY_ID::TRAINWARP_ADEPT, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_COLOSSUS, m_bot)] = { sc2::Race::Protoss, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_COLOSSUS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_DISRUPTOR, m_bot)] = { sc2::Race::Protoss, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DISRUPTOR, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_WARPPRISM, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_WARPPRISM, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_OBSERVER, m_bot)] = { sc2::Race::Protoss, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_OBSERVER, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_IMMORTAL, m_bot)] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_IMMORTAL, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_CARRIER, m_bot)] = { sc2::Race::Protoss, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CARRIER, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ORACLE, m_bot)] = { sc2::Race::Protoss, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ORACLE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PHOENIX, m_bot)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_PHOENIX, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_VOIDRAY, m_bot)] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VOIDRAY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPEST, m_bot)] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_TEMPEST, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_INTERCEPTOR, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_INTERCEPTORS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CARRIER, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ORACLESTASISTRAP, m_bot)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STASISTRAP, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ORACLE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PROBE, m_client)] = { sc2::Race::Protoss, 0, 0, 1, 0, true, false, true, false, false, false, false, sc2::ABILITY_ID::TRAIN_PROBE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_MOTHERSHIPCORE, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MOTHERSHIPCORE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_NEXUS, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ZEALOT, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ZEALOT, sc2::ABILITY_ID::TRAINWARP_ZEALOT, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_SENTRY, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SENTRY, sc2::ABILITY_ID::TRAINWARP_SENTRY, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_STALKER, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_STALKER, sc2::ABILITY_ID::TRAINWARP_STALKER, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_HIGHTEMPLAR, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HIGHTEMPLAR, sc2::ABILITY_ID::TRAINWARP_HIGHTEMPLAR, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKTEMPLAR, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DARKTEMPLAR, sc2::ABILITY_ID::TRAINWARP_DARKTEMPLAR, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ADEPT, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ADEPT, sc2::ABILITY_ID::TRAINWARP_ADEPT, { UnitType(sc2::UNIT_TYPEID::PROTOSS_GATEWAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_COLOSSUS, m_client)] = { sc2::Race::Protoss, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_COLOSSUS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_DISRUPTOR, m_client)] = { sc2::Race::Protoss, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DISRUPTOR, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_WARPPRISM, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_WARPPRISM, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_OBSERVER, m_client)] = { sc2::Race::Protoss, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_OBSERVER, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_IMMORTAL, m_client)] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_IMMORTAL, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_CARRIER, m_client)] = { sc2::Race::Protoss, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CARRIER, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ORACLE, m_client)] = { sc2::Race::Protoss, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ORACLE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_PHOENIX, m_client)] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_PHOENIX, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_VOIDRAY, m_client)] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VOIDRAY, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPEST, m_client)] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_TEMPEST, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_STARGATE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_INTERCEPTOR, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_INTERCEPTORS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CARRIER, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::PROTOSS_ORACLESTASISTRAP, m_client)] = { sc2::Race::Protoss, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STASISTRAP, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ORACLE, m_client) }, {}, {} };
// Terran Buildings m g s t unit bld wrk rfn sup hall add
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_COMMANDCENTER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::BUILD_SUPPLYDEPOT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_REFINERY, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_REFINERY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ARMORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BARRACKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOTLOWERED, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SENSORTOWER, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SENSORTOWER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FACTORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FUSIONCORE, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FUSIONCORE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTFLYING, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STARPORT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_GHOSTACADEMY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BUNKER, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BUNKER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ENGINEERINGBAY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTERFLYING, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMANDFLYING, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MISSILETURRET, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_MISSILETURRET, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_ORBITALCOMMAND, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_PLANETARYFORTRESS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_COMMANDCENTER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::BUILD_SUPPLYDEPOT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_REFINERY, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_REFINERY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ARMORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BARRACKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOTLOWERED, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SENSORTOWER, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SENSORTOWER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FACTORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FUSIONCORE, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FUSIONCORE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTFLYING, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STARPORT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_GHOSTACADEMY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BUNKER, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BUNKER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ENGINEERINGBAY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTERFLYING, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMANDFLYING, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MISSILETURRET, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_MISSILETURRET, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_ORBITALCOMMAND, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_PLANETARYFORTRESS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {} };
// Terran Addons m g s t unit bld wrk rfn sup hall add
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSREACTOR, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_BARRACKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_BARRACKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYREACTOR, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_FACTORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_FACTORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTREACTOR, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_STARPORT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_STARPORT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSREACTOR, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_BARRACKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_BARRACKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYREACTOR, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_FACTORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_FACTORY, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTREACTOR, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_STARPORT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_STARPORT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, {}, {} };
// Terran Equivalent Buildings
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOTLOWERED, m_bot)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, m_bot)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_bot)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTERFLYING, m_bot)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING, m_bot)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMANDFLYING, m_bot)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_bot)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTFLYING, m_bot)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOTLOWERED, m_client)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, m_client)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING, m_client)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTERFLYING, m_client)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING, m_client)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMANDFLYING, m_client)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_client)];
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTFLYING, m_client)] = m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client)];
// Terran Units m g s t unit bld wrk rfn sup hall add
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot)] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, true, false, false, false, false, sc2::ABILITY_ID::TRAIN_SCV, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_GHOST, m_bot)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_GHOST, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MARAUDER, m_bot)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MARAUDER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MARINE, m_bot)] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MARINE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_REAPER, m_bot)] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_REAPER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_HELLION, m_bot)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HELLION, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_CYCLONE, m_bot)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CYCLONE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SIEGETANK, m_bot)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SIEGETANK, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_THOR, m_bot)] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_THOR, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_WIDOWMINE, m_bot)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_WIDOWMINE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_NUKE, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NUKE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BANSHEE, m_bot)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BANSHEE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BATTLECRUISER, m_bot)] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BATTLECRUISER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_LIBERATOR, m_bot)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_LIBERATOR, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_VIKINGFIGHTER, m_bot)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VIKINGFIGHTER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_RAVEN, m_bot)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_RAVEN, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_bot), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MEDIVAC, m_bot)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MEDIVAC, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MULE, m_bot)] = { sc2::Race::Terran, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::EFFECT_CALLDOWNMULE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_THORAP, m_bot)] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_THOR, 0,{ UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_bot) },{},{} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client)] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, true, false, false, false, false, sc2::ABILITY_ID::TRAIN_SCV, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_GHOST, m_client)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_GHOST, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MARAUDER, m_client)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MARAUDER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MARINE, m_client)] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MARINE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_REAPER, m_client)] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_REAPER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKS, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_HELLION, m_client)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HELLION, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_CYCLONE, m_client)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CYCLONE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_SIEGETANK, m_client)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SIEGETANK, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_THOR, m_client)] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_THOR, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_WIDOWMINE, m_client)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_WIDOWMINE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_NUKE, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NUKE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BANSHEE, m_client)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BANSHEE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_BATTLECRUISER, m_client)] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BATTLECRUISER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_LIBERATOR, m_client)] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_LIBERATOR, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_VIKINGFIGHTER, m_client)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VIKINGFIGHTER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_RAVEN, m_client)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_RAVEN, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_TECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, m_client), UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MEDIVAC, m_client)] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MEDIVAC, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORT, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_MULE, m_client)] = { sc2::Race::Terran, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::EFFECT_CALLDOWNMULE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_THORAP, m_client)] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_THOR, 0,{ UnitType(sc2::UNIT_TYPEID::TERRAN_FACTORY, m_client) },{},{} };
// Zerg Buildings m g s t unit bld wrk rfn sup hall add
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_HATCHERY, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_EXTRACTOR, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_EXTRACTOR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPAWNINGPOOL, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_EVOLUTIONCHAMBER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_BANELINGNEST, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BANELINGNEST, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_HYDRALISKDEN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_INFESTATIONPIT, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_NYDUSCANAL, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NYDUSWORM, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_NYDUSNETWORK, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_NYDUSNETWORK, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NYDUSNETWORK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROACHWARREN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPINECRAWLER, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPINECRAWLER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPIRE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_GREATERSPIRE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPORECRAWLER, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPORECRAWLER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ULTRALISKCAVERN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::MORPH_LAIR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot) }, {UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot)}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::MORPH_HIVE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_HATCHERY, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_EXTRACTOR, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_EXTRACTOR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPAWNINGPOOL, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_EVOLUTIONCHAMBER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_BANELINGNEST, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BANELINGNEST, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_HYDRALISKDEN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_INFESTATIONPIT, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_NYDUSCANAL, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NYDUSWORM, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_NYDUSNETWORK, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_NYDUSNETWORK, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NYDUSNETWORK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROACHWARREN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPINECRAWLER, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPINECRAWLER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPIRE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_GREATERSPIRE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SPORECRAWLER, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPORECRAWLER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ULTRALISKCAVERN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::MORPH_LAIR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client) }, {UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client)}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::MORPH_HIVE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_client) }, {} };
// Zerg Units m g s t unit bld wrk rfn sup hall add
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_OVERLORD, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, false, false, false, true, false, false, sc2::ABILITY_ID::TRAIN_OVERLORD, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_BANELING, m_bot)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BANELING, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_BANELINGNEST, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_CORRUPTOR, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CORRUPTOR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_bot)] = { sc2::Race::Zerg, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DRONE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISK, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HYDRALISK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_LURKERDENMP, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_INFESTOR, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_INFESTOR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_MUTALISK, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MUTALISK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ROACH, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ROACH, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SWARMHOSTMP, m_bot)] = { sc2::Race::Zerg, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SWARMHOST, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISK, m_bot)] = { sc2::Race::Zerg, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ULTRALISK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_VIPER, m_bot)] = { sc2::Race::Zerg, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VIPER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ZERGLING, m_bot)] = { sc2::Race::Zerg, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ZERGLING, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_QUEEN, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_QUEEN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, 0, 0, { UnitType() }, { UnitType() }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_EGG, m_bot)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, 0, 0, { UnitType() }, { UnitType() }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_OVERLORD, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, false, false, false, true, false, false, sc2::ABILITY_ID::TRAIN_OVERLORD, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_BANELING, m_client)] = { sc2::Race::Zerg, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::MORPH_BANELING, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_BANELINGNEST, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_CORRUPTOR, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CORRUPTOR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_DRONE, m_client)] = { sc2::Race::Zerg, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DRONE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, {}, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISK, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HYDRALISK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_LURKERDENMP, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_INFESTOR, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_INFESTOR, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_MUTALISK, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MUTALISK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ROACH, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ROACH, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_SWARMHOSTMP, m_client)] = { sc2::Race::Zerg, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SWARMHOST, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISK, m_client)] = { sc2::Race::Zerg, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ULTRALISK, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_VIPER, m_client)] = { sc2::Race::Zerg, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VIPER, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_ZERGLING, m_client)] = { sc2::Race::Zerg, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ZERGLING, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_QUEEN, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_QUEEN, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_LARVA, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, 0, 0, { UnitType() }, { UnitType() }, {} };
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_EGG, m_client)] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, 0, 0, { UnitType() }, { UnitType() }, {} };
// Set the Mineral / Gas cost of each unit
for (auto & kv : m_unitTypeData)
{
if (!kv.first.isValid()) { continue; }
auto & data = m_bot.Observation()->GetUnitTypeData()[kv.first.getAPIUnitType()];
auto & data = m_client.Observation()->GetUnitTypeData()[kv.first.getAPIUnitType()];
kv.second.mineralCost = data.mineral_cost;
kv.second.gasCost = data.vespene_cost;
}
// fix the cumulative prices of morphed buildings
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS, m_bot)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_bot)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_bot)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS, m_client)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, m_client)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, m_client)).mineralCost;
m_unitTypeData[UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client)].mineralCost -= getData(UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client)).mineralCost;
}
void TechTree::initUpgradeData()
......@@ -174,102 +265,105 @@ void TechTree::initUpgradeData()
m_upgradeData[0] = TypeData();
// Terran Upgrades
m_upgradeData[sc2::UPGRADE_ID::BANSHEECLOAK] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BANSHEECLOAKINGFIELD, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BANSHEESPEED] = { sc2::Race::Terran, 200, 200, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BANSHEEHYPERFLIGHTROTORS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BATTLECRUISERENABLESPECIALIZATIONS]= { sc2::Race::Terran, 150, 150, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BATTLECRUISERWEAPONREFIT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::DRILLCLAWS] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_DRILLINGCLAWS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::HIGHCAPACITYBARRELS] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_INFERNALPREIGNITER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::HISECAUTOTRACKING] = { sc2::Race::Terran, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_HISECAUTOTRACKING, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::LIBERATORAGRANGEUPGRADE] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ADVANCEDBALLISTICS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::MAGFIELDLAUNCHERS] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_MAGFIELDLAUNCHERS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::MEDIVACINCREASESPEEDBOOST] = { sc2::Race::Terran, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_HIGHCAPACITYFUELTANKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::NEOSTEELFRAME] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_NEOSTEELFRAME, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PERSONALCLOAKING] = { sc2::Race::Terran, 150, 150, 0, 1920, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PERSONALCLOAKING, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PUNISHERGRENADES] = { sc2::Race::Terran, 50, 50, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CONCUSSIVESHELLS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::RAVENCORVIDREACTOR] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENCORVIDREACTOR, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::RAVENRECALIBRATEDEXPLOSIVES] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENRECALIBRATEDEXPLOSIVES, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::SHIELDWALL] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_COMBATSHIELD, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::STIMPACK] = { sc2::Race::Terran, 100, 100, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_STIMPACK, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANBUILDINGARMOR] = { sc2::Race::Terran, 150, 150, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSTRUCTUREARMORUPGRADE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_bot) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_bot) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::BANSHEECLOAK] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BANSHEECLOAKINGFIELD, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BANSHEESPEED] = { sc2::Race::Terran, 200, 200, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BANSHEEHYPERFLIGHTROTORS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BATTLECRUISERENABLESPECIALIZATIONS]= { sc2::Race::Terran, 150, 150, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BATTLECRUISERWEAPONREFIT, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::DRILLCLAWS] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_DRILLINGCLAWS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::HIGHCAPACITYBARRELS] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_INFERNALPREIGNITER, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::HISECAUTOTRACKING] = { sc2::Race::Terran, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_HISECAUTOTRACKING, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::LIBERATORAGRANGEUPGRADE] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ADVANCEDBALLISTICS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::MAGFIELDLAUNCHERS] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CYCLONELOCKONDAMAGE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::MEDIVACINCREASESPEEDBOOST] = { sc2::Race::Terran, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_HIGHCAPACITYFUELTANKS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::NEOSTEELFRAME] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_NEOSTEELFRAME, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PERSONALCLOAKING] = { sc2::Race::Terran, 150, 150, 0, 1920, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PERSONALCLOAKING, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PUNISHERGRENADES] = { sc2::Race::Terran, 50, 50, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CONCUSSIVESHELLS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::RAVENCORVIDREACTOR] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENCORVIDREACTOR, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::RAVENRECALIBRATEDEXPLOSIVES] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENRECALIBRATEDEXPLOSIVES, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::SHIELDWALL] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_COMBATSHIELD, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::STIMPACK] = { sc2::Race::Terran, 100, 100, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_STIMPACK, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANBUILDINGARMOR] = { sc2::Race::Terran, 150, 150, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSTRUCTUREARMORUPGRADE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ARMORY, m_client) }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL2} };
// Protoss Upgrades
m_upgradeData[sc2::UPGRADE_ID::ADEPTPIERCINGATTACK] = { sc2::Race::Protoss, 100, 100, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ADEPTRESONATINGGLAIVES, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BLINKTECH] = { sc2::Race::Protoss, 150, 150, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BLINK, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CARRIERLAUNCHSPEEDUPGRADE] = { sc2::Race::Protoss, 150, 150, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_INTERCEPTORGRAVITONCATAPULT, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CHARGE] = { sc2::Race::Protoss, 100, 100, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CHARGE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::DARKTEMPLARBLINKUPGRADE] = { sc2::Race::Protoss, 100, 100, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_SHADOWSTRIKE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EXTENDEDTHERMALLANCE] = { sc2::Race::Protoss, 200, 200, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_EXTENDEDTHERMALLANCE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::GRAVITICDRIVE] = { sc2::Race::Protoss, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GRAVITICDRIVE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::OBSERVERGRAVITICBOOSTER] = { sc2::Race::Protoss, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GRAVITICBOOSTER, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PHOENIXRANGEUPGRADE] = { sc2::Race::Protoss, 150, 150, 0, 1440, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PHOENIXANIONPULSECRYSTALS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL1] = { sc2::Race::Protoss, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL2] = { sc2::Race::Protoss, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL3] = { sc2::Race::Protoss, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL2] = { sc2::Race::Protoss, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL3] = { sc2::Race::Protoss, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_bot) }, {sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL3} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL2] = { sc2::Race::Protoss, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, { sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL3] = { sc2::Race::Protoss, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, { sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL2] = { sc2::Race::Protoss, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, { sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL3] = { sc2::Race::Protoss, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, { sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL1] = { sc2::Race::Protoss, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL2] = { sc2::Race::Protoss, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, { sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL3] = { sc2::Race::Protoss, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_bot) }, { sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::PSISTORMTECH] = { sc2::Race::Protoss, 200, 200, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PSISTORM, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::WARPGATERESEARCH] = { sc2::Race::Protoss, 50, 50, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_WARPGATE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ADEPTPIERCINGATTACK] = { sc2::Race::Protoss, 100, 100, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ADEPTRESONATINGGLAIVES, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BLINKTECH] = { sc2::Race::Protoss, 150, 150, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BLINK, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CARRIERLAUNCHSPEEDUPGRADE] = { sc2::Race::Protoss, 150, 150, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_INTERCEPTORGRAVITONCATAPULT, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CHARGE] = { sc2::Race::Protoss, 100, 100, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CHARGE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::DARKTEMPLARBLINKUPGRADE] = { sc2::Race::Protoss, 100, 100, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_SHADOWSTRIKE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EXTENDEDTHERMALLANCE] = { sc2::Race::Protoss, 200, 200, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_EXTENDEDTHERMALLANCE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::GRAVITICDRIVE] = { sc2::Race::Protoss, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GRAVITICDRIVE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::OBSERVERGRAVITICBOOSTER] = { sc2::Race::Protoss, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GRAVITICBOOSTER, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PHOENIXRANGEUPGRADE] = { sc2::Race::Protoss, 150, 150, 0, 1440, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PHOENIXANIONPULSECRYSTALS, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL1] = { sc2::Race::Protoss, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL2] = { sc2::Race::Protoss, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL3] = { sc2::Race::Protoss, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL2] = { sc2::Race::Protoss, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL3] = { sc2::Race::Protoss, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON, m_client) }, {sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL3} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL2] = { sc2::Race::Protoss, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, { sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL3] = { sc2::Race::Protoss, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, { sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL2] = { sc2::Race::Protoss, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, { sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL3] = { sc2::Race::Protoss, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, { sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL1] = { sc2::Race::Protoss, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL2] = { sc2::Race::Protoss, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, { sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL3] = { sc2::Race::Protoss, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_FORGE, m_client) }, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL, m_client) }, { sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::PSISTORMTECH] = { sc2::Race::Protoss, 200, 200, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PSISTORM, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::WARPGATERESEARCH] = { sc2::Race::Protoss, 50, 50, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_WARPGATE, 0, { UnitType(sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE, m_client) }, {}, {} };
// Zerg Upgrades
m_upgradeData[sc2::UPGRADE_ID::BURROW] = { sc2::Race::Zerg, 100, 100, 0, 1600, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BURROW, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CENTRIFICALHOOKS] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CENTRIFUGALHOOKS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_BANELINGNEST, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CHITINOUSPLATING] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CHITINOUSPLATING, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EVOLVEGROOVEDSPINES] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GROOVEDSPINES, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EVOLVEMUSCULARAUGMENTS] = { sc2::Race::Zerg, 150, 150, 0, 1600, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_MUSCULARAUGMENTS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::GLIALRECONSTITUTION] = { sc2::Race::Zerg, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GLIALREGENERATION, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_upgradeData[sc2::UPGRADE_ID::INFESTORENERGYUPGRADE] = { sc2::Race::Zerg, 150, 150, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PATHOGENGLANDS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::NEURALPARASITE] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_NEURALPARASITE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::OVERLORDSPEED] = { sc2::Race::Zerg, 100, 100, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PNEUMATIZEDCARAPACE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TUNNELINGCLAWS] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TUNNELINGCLAWS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL1] = { sc2::Race::Zerg, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL2] = { sc2::Race::Zerg, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, { sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL3] = { sc2::Race::Zerg, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, { sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL2] = { sc2::Race::Zerg, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, { sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL3] = { sc2::Race::Zerg, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_bot) }, {UnitType( sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, { sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL1] = { sc2::Race::Zerg, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL2] = { sc2::Race::Zerg, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL3] = { sc2::Race::Zerg, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::ZERGLINGATTACKSPEED] = { sc2::Race::Zerg, 200, 200, 0, 2080, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGLINGADRENALGLANDS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGLINGMOVEMENTSPEED] = { sc2::Race::Zerg, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGLINGMETABOLICBOOST, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL2] = { sc2::Race::Zerg, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL3] = { sc2::Race::Zerg, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL2] = { sc2::Race::Zerg, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_bot), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL3] = { sc2::Race::Zerg, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_bot) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_bot) }, {sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::BURROW] = { sc2::Race::Zerg, 100, 100, 0, 1600, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BURROW, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CENTRIFICALHOOKS] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CENTRIFUGALHOOKS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_BANELINGNEST, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CHITINOUSPLATING] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CHITINOUSPLATING, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EVOLVEGROOVEDSPINES] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GROOVEDSPINES, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EVOLVEMUSCULARAUGMENTS] = { sc2::Race::Zerg, 150, 150, 0, 1600, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_MUSCULARAUGMENTS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::GLIALRECONSTITUTION] = { sc2::Race::Zerg, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GLIALREGENERATION, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_upgradeData[sc2::UPGRADE_ID::INFESTORENERGYUPGRADE] = { sc2::Race::Zerg, 150, 150, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PATHOGENGLANDS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::NEURALPARASITE] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_NEURALPARASITE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::OVERLORDSPEED] = { sc2::Race::Zerg, 100, 100, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PNEUMATIZEDCARAPACE, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_HATCHERY, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TUNNELINGCLAWS] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TUNNELINGCLAWS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_ROACHWARREN, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL1] = { sc2::Race::Zerg, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL2] = { sc2::Race::Zerg, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, { sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL3] = { sc2::Race::Zerg, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, { sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL2] = { sc2::Race::Zerg, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, { sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL3] = { sc2::Race::Zerg, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPIRE, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_GREATERSPIRE, m_client) }, {UnitType( sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, { sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL1] = { sc2::Race::Zerg, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL2] = { sc2::Race::Zerg, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL3] = { sc2::Race::Zerg, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::ZERGLINGATTACKSPEED] = { sc2::Race::Zerg, 200, 200, 0, 2080, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGLINGADRENALGLANDS, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGLINGMOVEMENTSPEED] = { sc2::Race::Zerg, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGLINGMETABOLICBOOST, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL2] = { sc2::Race::Zerg, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL3] = { sc2::Race::Zerg, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL2] = { sc2::Race::Zerg, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL2, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_LAIR, m_client), UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL3] = { sc2::Race::Zerg, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL3, 0, { UnitType(sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER, m_client) }, { UnitType(sc2::UNIT_TYPEID::ZERG_HIVE, m_client) }, {sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL2} };
}
const TypeData & TechTree::getData(const UnitType & type) const
{
if (m_unitTypeData.find(type) == m_unitTypeData.end())
{
std::cout << "WARNING: Unit type not found: " << type.getName() << "\n";
if (!suppressWarnings)
{
std::cout << "WARNING: Unit type not found: " << type.getName() << "\n";
}
return m_unitTypeData.begin()->second;
}
......@@ -280,7 +374,10 @@ const TypeData & TechTree::getData(const CCUpgrade & type) const
{
if (m_upgradeData.find(type) == m_upgradeData.end())
{
std::cout << "WARNING: Upgrade not found: " << sc2::UpgradeIDToName(type) << "\n";
if (!suppressWarnings)
{
std::cout << "WARNING: Upgrade not found: " << sc2::UpgradeIDToName(type) << "\n";
}
return m_unitTypeData.begin()->second;
}
......@@ -301,4 +398,4 @@ const TypeData & TechTree::getData(const MetaType & type) const
BOT_ASSERT(false, "Can't getData this type: %s", type.getName().c_str());
return m_unitTypeData.begin()->second;
}
\ No newline at end of file
}
......@@ -24,23 +24,29 @@ struct TypeData
sc2::AbilityID warpAbility = 0; // the ability that creates this item via warp-in
std::vector<UnitType> whatBuilds; // any of these units can build the item
std::vector<UnitType> requiredUnits; // owning ONE of these is required to make
std::vector<CCUpgrade> requiredUpgrades; // having ALL of these is required to make
std::vector<sc2::UPGRADE_ID> requiredUpgrades; // having ALL of these is required to make
std::vector<UnitType> requiredAddons; // a unit of this type must be present next to the producer
sc2::AbilityID morphAbility = 0; // the ability which morphes the producer into this type
};
class TechTree
{
IDABot & m_bot;
sc2::Client & m_client;
std::map<UnitType, TypeData> m_unitTypeData;
std::map<CCUpgrade, TypeData> m_upgradeData;
void initUnitTypeData();
void initUpgradeData();
bool suppressWarnings;
public:
TechTree(IDABot & bot);
TechTree(sc2::Client & client);
void onStart();
void setSuppressWarnings(bool b);
bool getSuppressWarnings() const;
const TypeData & getData(const UnitType & type) const;
const TypeData & getData(const CCUpgrade & type) const;
const TypeData & getData(const MetaType & type) const;
......
#include "TechTree.h"
#include "Util.h"
#include "CCBot.h"
#include "BuildType.h"
#include "Timer.hpp"
TechTree::TechTree(CCBot & bot)
: m_bot(bot)
{
}
void TechTree::onStart()
{
initUnitTypeData();
initUpgradeData();
}
void TechTree::initUnitTypeData()
{
m_upgradeData[0] = TypeData();
// Protoss Buildings unit bld wrk rfn sup hall add
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_PYLON] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::BUILD_PYLON, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_NEXUS] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_NEXUS, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_ASSIMILATOR] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_ASSIMILATOR, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_CYBERNETICSCORE, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY, sc2::UNIT_TYPEID::PROTOSS_WARPGATE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_DARKSHRINE, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FLEETBEACON, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_STARGATE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_FORGE] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FORGE, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_NEXUS }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_GATEWAY] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_GATEWAY, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_NEXUS }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_STARGATE] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STARGATE, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_PHOTONCANNON] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_PHOTONCANNON, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROBOTICSBAY, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROBOTICSFACILITY, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_TEMPLARARCHIVE, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_TWILIGHTCOUNCIL, 0, { sc2::UNIT_TYPEID::PROTOSS_PROBE }, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_WARPGATE] = { sc2::Race::Protoss, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_WARPGATE, 0, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY }, {}, { sc2::UPGRADE_ID::WARPGATERESEARCH } };
// Protoss Units unit bld wrk rfn sup hall add
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_PROBE] = { sc2::Race::Protoss, 0, 0, 1, 0, true, false, true, false, false, false, false, sc2::ABILITY_ID::TRAIN_PROBE, 0, { sc2::UNIT_TYPEID::PROTOSS_NEXUS }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_MOTHERSHIPCORE] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MOTHERSHIPCORE, 0, { sc2::UNIT_TYPEID::PROTOSS_NEXUS }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_ZEALOT] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ZEALOT, sc2::ABILITY_ID::TRAINWARP_ZEALOT, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_SENTRY] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SENTRY, sc2::ABILITY_ID::TRAINWARP_SENTRY, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY }, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_STALKER] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_STALKER, sc2::ABILITY_ID::TRAINWARP_STALKER, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY }, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_HIGHTEMPLAR] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HIGHTEMPLAR, sc2::ABILITY_ID::TRAINWARP_HIGHTEMPLAR, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY }, { sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_DARKTEMPLAR] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DARKTEMPLAR, sc2::ABILITY_ID::TRAINWARP_DARKTEMPLAR, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY }, { sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_ADEPT] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ADEPT, sc2::ABILITY_ID::TRAINWARP_ADEPT, { sc2::UNIT_TYPEID::PROTOSS_GATEWAY }, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_COLOSSUS] = { sc2::Race::Protoss, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_COLOSSUS, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY }, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_DISRUPTOR] = { sc2::Race::Protoss, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DISRUPTOR, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY }, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_WARPPRISM] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_WARPPRISM, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_OBSERVER] = { sc2::Race::Protoss, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_OBSERVER, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_IMMORTAL] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_IMMORTAL, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSFACILITY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_CARRIER] = { sc2::Race::Protoss, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CARRIER, 0, { sc2::UNIT_TYPEID::PROTOSS_STARGATE }, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_ORACLE] = { sc2::Race::Protoss, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ORACLE, 0, { sc2::UNIT_TYPEID::PROTOSS_STARGATE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_PHOENIX] = { sc2::Race::Protoss, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_PHOENIX, 0, { sc2::UNIT_TYPEID::PROTOSS_STARGATE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_VOIDRAY] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VOIDRAY, 0, { sc2::UNIT_TYPEID::PROTOSS_STARGATE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_TEMPEST] = { sc2::Race::Protoss, 0, 0, 4, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_TEMPEST, 0, { sc2::UNIT_TYPEID::PROTOSS_STARGATE }, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_INTERCEPTOR] = { sc2::Race::Protoss, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_INTERCEPTORS, 0, { sc2::UNIT_TYPEID::PROTOSS_CARRIER }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::PROTOSS_ORACLESTASISTRAP] = { sc2::Race::Protoss, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STASISTRAP, 0, { sc2::UNIT_TYPEID::PROTOSS_ORACLE }, {}, {} };
// Terran Buildings m g s t unit bld wrk rfn sup hall add
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_COMMANDCENTER, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, true, false, false, sc2::ABILITY_ID::BUILD_SUPPLYDEPOT, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_REFINERY] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_REFINERY, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_ARMORY] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ARMORY, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_FACTORY, sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BARRACKS] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BARRACKS, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT, sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOTLOWERED }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_SENSORTOWER] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SENSORTOWER, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_FACTORY] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FACTORY, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_BARRACKS, sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_FUSIONCORE] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_FUSIONCORE, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_STARPORT, sc2::UNIT_TYPEID::TERRAN_STARPORTFLYING }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_STARPORT] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_STARPORT, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_FACTORY, sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_GHOSTACADEMY, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_BARRACKS, sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BUNKER] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BUNKER, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_BARRACKS, sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ENGINEERINGBAY, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER, sc2::UNIT_TYPEID::TERRAN_COMMANDCENTERFLYING, sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS, sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND, sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMANDFLYING }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_MISSILETURRET] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_MISSILETURRET, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_ORBITALCOMMAND, 0, { sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_PLANETARYFORTRESS, 0, { sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER }, {}, {} };
// Terran Addons m g s t unit bld wrk rfn sup hall add
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BARRACKSREACTOR] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_BARRACKS, 0, { sc2::UNIT_TYPEID::TERRAN_BARRACKS }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_BARRACKS, 0, { sc2::UNIT_TYPEID::TERRAN_BARRACKS }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_FACTORYREACTOR] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_FACTORY, 0, { sc2::UNIT_TYPEID::TERRAN_FACTORY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_FACTORY, 0, { sc2::UNIT_TYPEID::TERRAN_FACTORY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_STARPORTREACTOR] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_REACTOR_STARPORT, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB] = { sc2::Race::Terran, 0, 0, 0, 0, true, true, false, false, false, false, true, sc2::ABILITY_ID::BUILD_TECHLAB_STARPORT, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, {}, {} };
// Terran Equivalent Buildings
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOTLOWERED] = m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_SUPPLYDEPOT];
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BARRACKSFLYING] = m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BARRACKS];
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_COMMANDCENTERFLYING] = m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER];
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_FACTORYFLYING] = m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_FACTORY];
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMANDFLYING] = m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND];
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_STARPORTFLYING] = m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_STARPORT];
// Terran Units m g s t unit bld wrk rfn sup hall add
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_SCV] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, true, false, false, false, false, sc2::ABILITY_ID::TRAIN_SCV, 0, { sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_GHOST] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_GHOST, 0, { sc2::UNIT_TYPEID::TERRAN_BARRACKS }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_MARAUDER] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MARAUDER, 0, { sc2::UNIT_TYPEID::TERRAN_BARRACKS }, { sc2::UNIT_TYPEID::TERRAN_TECHLAB, sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_MARINE] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MARINE, 0, { sc2::UNIT_TYPEID::TERRAN_BARRACKS }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_REAPER] = { sc2::Race::Terran, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_REAPER, 0, { sc2::UNIT_TYPEID::TERRAN_BARRACKS }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_HELLION] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HELLION, 0, { sc2::UNIT_TYPEID::TERRAN_FACTORY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_CYCLONE] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CYCLONE, 0, { sc2::UNIT_TYPEID::TERRAN_FACTORY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_SIEGETANK] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SIEGETANK, 0, { sc2::UNIT_TYPEID::TERRAN_FACTORY }, { sc2::UNIT_TYPEID::TERRAN_TECHLAB, sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_THOR] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_THOR, 0, { sc2::UNIT_TYPEID::TERRAN_FACTORY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_WIDOWMINE] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_WIDOWMINE, 0, { sc2::UNIT_TYPEID::TERRAN_FACTORY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_NUKE] = { sc2::Race::Terran, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NUKE, 0, { sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BANSHEE] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BANSHEE, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, { sc2::UNIT_TYPEID::TERRAN_TECHLAB, sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_BATTLECRUISER] = { sc2::Race::Terran, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BATTLECRUISER, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_LIBERATOR] = { sc2::Race::Terran, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_LIBERATOR, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_VIKINGFIGHTER] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VIKINGFIGHTER, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_RAVEN] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_RAVEN, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, { sc2::UNIT_TYPEID::TERRAN_TECHLAB, sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB, sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_MEDIVAC] = { sc2::Race::Terran, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MEDIVAC, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORT }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::TERRAN_MULE] = { sc2::Race::Terran, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::EFFECT_CALLDOWNMULE, 0, { sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND }, {}, {} };
// Zerg Buildings m g s t unit bld wrk rfn sup hall add
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_HATCHERY] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::BUILD_HATCHERY, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_EXTRACTOR] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, true, false, false, false, sc2::ABILITY_ID::BUILD_EXTRACTOR, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPAWNINGPOOL, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_HATCHERY, sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_EVOLUTIONCHAMBER, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_HATCHERY, sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_BANELINGNEST] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_BANELINGNEST, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_HYDRALISKDEN, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_INFESTATIONPIT, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_NYDUSCANAL] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NYDUSWORM, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_NYDUSNETWORK }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_NYDUSNETWORK] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_NYDUSNETWORK, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_ROACHWARREN] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ROACHWARREN, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_SPINECRAWLER] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPINECRAWLER, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_SPIRE] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPIRE, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_GREATERSPIRE] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::MORPH_GREATERSPIRE, 0, { sc2::UNIT_TYPEID::ZERG_SPIRE }, { sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_SPORECRAWLER] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_SPORECRAWLER, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, false, false, sc2::ABILITY_ID::BUILD_ULTRALISKCAVERN, 0, { sc2::UNIT_TYPEID::ZERG_DRONE }, { sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_LAIR] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::MORPH_LAIR, 0, { sc2::UNIT_TYPEID::ZERG_HATCHERY }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_HIVE] = { sc2::Race::Zerg, 0, 0, 0, 0, true, true, false, false, false, true, false, sc2::ABILITY_ID::MORPH_HIVE, 0, { sc2::UNIT_TYPEID::ZERG_LAIR }, {}, {} };
// Zerg Units m g s t unit bld wrk rfn sup hall add
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_OVERLORD] = { sc2::Race::Zerg, 0, 0, 0, 0, true, false, false, false, true, false, false, sc2::ABILITY_ID::TRAIN_OVERLORD, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_BANELING] = { sc2::Race::Zerg, 0, 0, 0, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_BANELING, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_BANELINGNEST }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_CORRUPTOR] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_CORRUPTOR, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_DRONE] = { sc2::Race::Zerg, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_DRONE, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, {}, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_HYDRALISK] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_HYDRALISK, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN, sc2::UNIT_TYPEID::ZERG_LURKERDENMP }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_INFESTOR] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_INFESTOR, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_MUTALISK] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_MUTALISK, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_ROACH] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ROACH, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_ROACHWARREN }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_SWARMHOSTMP] = { sc2::Race::Zerg, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_SWARMHOST, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_ULTRALISK] = { sc2::Race::Zerg, 0, 0, 6, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ULTRALISK, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_VIPER] = { sc2::Race::Zerg, 0, 0, 3, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_VIPER, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_ZERGLING] = { sc2::Race::Zerg, 0, 0, 1, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_ZERGLING, 0, { sc2::UNIT_TYPEID::ZERG_LARVA }, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_QUEEN] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, sc2::ABILITY_ID::TRAIN_QUEEN, 0, { sc2::UNIT_TYPEID::ZERG_HATCHERY }, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_LARVA] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, 0, 0, { 0 }, { 0 }, {} };
m_unitTypeData[sc2::UNIT_TYPEID::ZERG_EGG] = { sc2::Race::Zerg, 0, 0, 2, 0, true, false, false, false, false, false, false, 0, 0, { 0 }, { 0 }, {} };
// Set the Mineral / Gas cost of each unit
for (auto & kv : m_unitTypeData)
{
if (kv.first == 0) { continue; }
auto & data = m_bot.Observation()->GetUnitTypeData();
kv.second.mineralCost = m_bot.Observation()->GetUnitTypeData()[kv.first].mineral_cost;
kv.second.gasCost = m_bot.Observation()->GetUnitTypeData()[kv.first].vespene_cost;
}
}
void TechTree::initUpgradeData()
{
// 0 data for null / error return
m_upgradeData[0] = TypeData();
// Terran Upgrades
m_upgradeData[sc2::UPGRADE_ID::BANSHEECLOAK] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BANSHEECLOAKINGFIELD, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BANSHEESPEED] = { sc2::Race::Terran, 200, 200, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BANSHEEHYPERFLIGHTROTORS, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BATTLECRUISERENABLESPECIALIZATIONS]= { sc2::Race::Terran, 150, 150, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BATTLECRUISERWEAPONREFIT, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::DRILLCLAWS] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_DRILLINGCLAWS, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::HIGHCAPACITYBARRELS] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_INFERNALPREIGNITER, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::HISECAUTOTRACKING] = { sc2::Race::Terran, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_HISECAUTOTRACKING, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::LIBERATORAGRANGEUPGRADE] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ADVANCEDBALLISTICS, 0, { sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::MAGFIELDLAUNCHERS] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_MAGFIELDLAUNCHERS, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::MEDIVACINCREASESPEEDBOOST] = { sc2::Race::Terran, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_HIGHCAPACITYFUELTANKS, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::NEOSTEELFRAME] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_NEOSTEELFRAME, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PERSONALCLOAKING] = { sc2::Race::Terran, 150, 150, 0, 1920, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PERSONALCLOAKING, 0, { sc2::UNIT_TYPEID::TERRAN_GHOSTACADEMY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PUNISHERGRENADES] = { sc2::Race::Terran, 50, 50, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CONCUSSIVESHELLS, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::RAVENCORVIDREACTOR] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENCORVIDREACTOR, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::RAVENRECALIBRATEDEXPLOSIVES] = { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENRECALIBRATEDEXPLOSIVES, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::SHIELDWALL] = { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_COMBATSHIELD, 0, { sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::STIMPACK] = { sc2::Race::Terran, 100, 100, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_STIMPACK, 0, { sc2::UNIT_TYPEID::TERRAN_SCV }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANBUILDINGARMOR] = { sc2::Race::Terran, 150, 150, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSTRUCTUREARMORUPGRADE, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL1, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL2, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL3, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL1, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL2, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYWEAPONSLEVEL3, 0, { sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY }, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {sc2::UPGRADE_ID::TERRANINFANTRYWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL1, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL2, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSHIPWEAPONSLEVEL3, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {sc2::UPGRADE_ID::TERRANSHIPWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEANDSHIPARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL1] = { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL1, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL2] = { sc2::Race::Terran, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL2, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL3] = { sc2::Race::Terran, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANVEHICLEWEAPONSLEVEL3, 0, { sc2::UNIT_TYPEID::TERRAN_ARMORY }, {}, {sc2::UPGRADE_ID::TERRANVEHICLEWEAPONSLEVEL2} };
// Protoss Upgrades
m_upgradeData[sc2::UPGRADE_ID::ADEPTPIERCINGATTACK] = { sc2::Race::Protoss, 100, 100, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ADEPTRESONATINGGLAIVES, 0, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::BLINKTECH] = { sc2::Race::Protoss, 150, 150, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BLINK, 0, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CARRIERLAUNCHSPEEDUPGRADE] = { sc2::Race::Protoss, 150, 150, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_INTERCEPTORGRAVITONCATAPULT, 0, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CHARGE] = { sc2::Race::Protoss, 100, 100, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CHARGE, 0, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::DARKTEMPLARBLINKUPGRADE] = { sc2::Race::Protoss, 100, 100, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_SHADOWSTRIKE, 0, { sc2::UNIT_TYPEID::PROTOSS_DARKSHRINE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EXTENDEDTHERMALLANCE] = { sc2::Race::Protoss, 200, 200, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_EXTENDEDTHERMALLANCE, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::GRAVITICDRIVE] = { sc2::Race::Protoss, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GRAVITICDRIVE, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::OBSERVERGRAVITICBOOSTER] = { sc2::Race::Protoss, 100, 100, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GRAVITICBOOSTER, 0, { sc2::UNIT_TYPEID::PROTOSS_ROBOTICSBAY }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PHOENIXRANGEUPGRADE] = { sc2::Race::Protoss, 150, 150, 0, 1440, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PHOENIXANIONPULSECRYSTALS, 0, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL1] = { sc2::Race::Protoss, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL1, 0, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL2] = { sc2::Race::Protoss, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL2, 0, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL3] = { sc2::Race::Protoss, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRARMORLEVEL3, 0, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {sc2::UPGRADE_ID::PROTOSSAIRARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL1, 0, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL2] = { sc2::Race::Protoss, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL2, 0, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL3] = { sc2::Race::Protoss, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSAIRWEAPONSLEVEL3, 0, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, { sc2::UNIT_TYPEID::PROTOSS_FLEETBEACON }, {sc2::UPGRADE_ID::PROTOSSAIRWEAPONSLEVEL3} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL1, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL2] = { sc2::Race::Protoss, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL2, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, { sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL3] = { sc2::Race::Protoss, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDARMORLEVEL3, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, { sc2::UPGRADE_ID::PROTOSSGROUNDARMORSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL1] = { sc2::Race::Protoss, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL1, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL2] = { sc2::Race::Protoss, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL2, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, { sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL3] = { sc2::Race::Protoss, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSGROUNDWEAPONSLEVEL3, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, { sc2::UPGRADE_ID::PROTOSSGROUNDWEAPONSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL1] = { sc2::Race::Protoss, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL1, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL2] = { sc2::Race::Protoss, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL2, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, { sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL3] = { sc2::Race::Protoss, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PROTOSSSHIELDSLEVEL3, 0, { sc2::UNIT_TYPEID::PROTOSS_FORGE }, { sc2::UNIT_TYPEID::PROTOSS_TWILIGHTCOUNCIL }, { sc2::UPGRADE_ID::PROTOSSSHIELDSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::PSISTORMTECH] = { sc2::Race::Protoss, 200, 200, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PSISTORM, 0, { sc2::UNIT_TYPEID::PROTOSS_TEMPLARARCHIVE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::WARPGATERESEARCH] = { sc2::Race::Protoss, 50, 50, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_WARPGATE, 0, { sc2::UNIT_TYPEID::PROTOSS_CYBERNETICSCORE }, {}, {} };
// Zerg Upgrades
m_upgradeData[sc2::UPGRADE_ID::BURROW] = { sc2::Race::Zerg, 100, 100, 0, 1600, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_BURROW, 0, { sc2::UNIT_TYPEID::ZERG_HATCHERY, sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CENTRIFICALHOOKS] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CENTRIFUGALHOOKS, 0, { sc2::UNIT_TYPEID::ZERG_BANELINGNEST }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::CHITINOUSPLATING] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CHITINOUSPLATING, 0, { sc2::UNIT_TYPEID::ZERG_ULTRALISKCAVERN }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EVOLVEGROOVEDSPINES] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GROOVEDSPINES, 0, { sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::EVOLVEMUSCULARAUGMENTS] = { sc2::Race::Zerg, 150, 150, 0, 1600, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_MUSCULARAUGMENTS, 0, { sc2::UNIT_TYPEID::ZERG_HYDRALISKDEN }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::GLIALRECONSTITUTION] = { sc2::Race::Zerg, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_GLIALREGENERATION, 0, { sc2::UNIT_TYPEID::ZERG_ROACHWARREN }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_upgradeData[sc2::UPGRADE_ID::INFESTORENERGYUPGRADE] = { sc2::Race::Zerg, 150, 150, 0, 1280, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PATHOGENGLANDS, 0, { sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::NEURALPARASITE] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_NEURALPARASITE, 0, { sc2::UNIT_TYPEID::ZERG_INFESTATIONPIT }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::OVERLORDSPEED] = { sc2::Race::Zerg, 100, 100, 0, 960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_PNEUMATIZEDCARAPACE, 0, { sc2::UNIT_TYPEID::ZERG_HATCHERY, sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::TUNNELINGCLAWS] = { sc2::Race::Zerg, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TUNNELINGCLAWS, 0, { sc2::UNIT_TYPEID::ZERG_ROACHWARREN }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL1] = { sc2::Race::Zerg, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL1, 0, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL2] = { sc2::Race::Zerg, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL2, 0, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, { sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL3] = { sc2::Race::Zerg, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERARMORLEVEL3, 0, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, { sc2::UNIT_TYPEID::ZERG_HIVE }, { sc2::UPGRADE_ID::ZERGFLYERARMORSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL1, 0, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL2] = { sc2::Race::Zerg, 175, 175, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL2, 0, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, { sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL1 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL3] = { sc2::Race::Zerg, 250, 250, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGFLYERATTACKLEVEL3, 0, { sc2::UNIT_TYPEID::ZERG_SPIRE, sc2::UNIT_TYPEID::ZERG_GREATERSPIRE }, { sc2::UNIT_TYPEID::ZERG_HIVE }, { sc2::UPGRADE_ID::ZERGFLYERWEAPONSLEVEL2 } };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL1] = { sc2::Race::Zerg, 150, 150, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL1, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL2] = { sc2::Race::Zerg, 225, 225, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL2, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL3] = { sc2::Race::Zerg, 300, 300, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGGROUNDARMORLEVEL3, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, { sc2::UNIT_TYPEID::ZERG_HIVE }, {sc2::UPGRADE_ID::ZERGGROUNDARMORSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::ZERGLINGATTACKSPEED] = { sc2::Race::Zerg, 200, 200, 0, 2080, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGLINGADRENALGLANDS, 0, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, { sc2::UNIT_TYPEID::ZERG_HIVE }, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGLINGMOVEMENTSPEED] = { sc2::Race::Zerg, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGLINGMETABOLICBOOST, 0, { sc2::UNIT_TYPEID::ZERG_SPAWNINGPOOL }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL1, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL2] = { sc2::Race::Zerg, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL2, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL3] = { sc2::Race::Zerg, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMELEEWEAPONSLEVEL3, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, { sc2::UNIT_TYPEID::ZERG_HIVE }, {sc2::UPGRADE_ID::ZERGMELEEWEAPONSLEVEL2} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL1] = { sc2::Race::Zerg, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL1, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, {}, {} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL2] = { sc2::Race::Zerg, 150, 150, 0, 3040, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL2, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, { sc2::UNIT_TYPEID::ZERG_LAIR, sc2::UNIT_TYPEID::ZERG_HIVE }, {sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL1} };
m_upgradeData[sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL3] = { sc2::Race::Zerg, 200, 200, 0, 3520, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_ZERGMISSILEWEAPONSLEVEL3, 0, { sc2::UNIT_TYPEID::ZERG_EVOLUTIONCHAMBER }, { sc2::UNIT_TYPEID::ZERG_HIVE }, {sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL2} };
}
const TypeData & TechTree::getData(const sc2::UnitTypeID & type) const
{
if (m_unitTypeData.find(type) == m_unitTypeData.end())
{
//std::cout << "WARNING: Unit type not found: " << sc2::UnitTypeToName(type) << "\n";
return m_unitTypeData.at(0);
}
return m_unitTypeData.at(type);
}
const TypeData & TechTree::getData(const sc2::UpgradeID & type) const
{
if (m_upgradeData.find(type) == m_upgradeData.end())
{
//std::cout << "WARNING: Upgrade not found: " << sc2::UpgradeIDToName(type) << "\n";
return m_unitTypeData.at(0);
}
return m_upgradeData.at(type);
}
const TypeData & TechTree::getData(const BuildType & type) const
{
if (type.getBuildType() == BuildTypes::Unit)
{
return getData(type.getUnitTypeID());
}
else if (type.getBuildType() == BuildTypes::Upgrade)
{
return getData(type.getUpgradeID());
}
BOT_ASSERT(false, "Can't getData this type: %s", type.getName().c_str());
return m_unitTypeData.at(0);
}
#include "TechTreeImproved.h"
using json = nlohmann::json;
TechTreeImproved::TechTreeImproved() { }
sc2::UNIT_TYPEID string_to_id(const std::string & str)
{
return static_cast<sc2::UNIT_TYPEID>(std::stoi(str));
}
std::string id_to_string(int id)
{
return sc2::UnitTypeToName(static_cast<sc2::UNIT_TYPEID>(id));
}
void add_requirement(ResearchDescription & description, json & requirement)
{
std::string type = requirement["type"];
if (type == "and")
{
for (auto & subrequirement : requirement["operands"])
{
add_requirement(description, subrequirement);
}
}
else if (type == "not")
{
// Ignore this. This is used for: "We cannot do upgrade X if upgrade X is already running somewhere."
}
else if (type == "unitCount")
{
if (requirement["state"] == "CompleteOnly")
{
for (auto & unit : requirement["unit"])
{
//std::cout << "Just building: " << sc2::UnitTypeToName(static_cast<sc2::UNIT_TYPEID>(unit)) << " (" << unit << ")" << std::endl;
description.buildings_needed.push_back(static_cast<sc2::UNIT_TYPEID>(unit));
}
}
else
{
std::cout << "Unexpected state: " << requirement["state"] << std::endl;
}
}
else if (type == "eq")
{
// TODO: Should we be more careful here?
sc2::UPGRADE_ID id = static_cast<sc2::UPGRADE_ID>(requirement["operands"][0]["upgrade"]);
int count = static_cast<int>(requirement["operands"][1]["value"]);
if (count == 1)
{
description.upgrades_needed.push_back(id);
}
}
}
void add_requirement(BuildDescription & description, json & requirement)
{
std::string type = requirement["type"];
if (type == "and")
{
for (auto & subrequirement : requirement["operands"])
{
add_requirement(description, subrequirement);
}
}
else if (type == "unitCount")
{
// Units that needs to be completed at the unit location -> Addons
if (requirement["state"] == "CompleteOnlyAtUnit")
{
for (auto & unit : requirement["unit"])
{
//std::cout << "Addon: " << sc2::UnitTypeToName(static_cast<sc2::UNIT_TYPEID>(unit)) << " (" << unit << ")" << std::endl;
sc2::UNIT_TYPEID unit_typeid = static_cast<sc2::UNIT_TYPEID>(unit);
if (unit_typeid == sc2::UNIT_TYPEID::TERRAN_TECHLAB)
{
switch (description.producer_type)
{
case sc2::UNIT_TYPEID::TERRAN_BARRACKS:
unit_typeid = sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB;
break;
case sc2::UNIT_TYPEID::TERRAN_FACTORY:
unit_typeid = sc2::UNIT_TYPEID::TERRAN_FACTORYTECHLAB;
break;
case sc2::UNIT_TYPEID::TERRAN_STARPORT:
unit_typeid = sc2::UNIT_TYPEID::TERRAN_STARPORTTECHLAB;
break;
default:
std::wcout << "Unknown producer type for TECHLAB addon: " << sc2::UnitTypeToName(unit_typeid) << std::endl;
}
}
description.addons_needed.push_back(unit_typeid);
}
}
else if (requirement["state"] == "CompleteOnly")
{
for (auto & unit : requirement["unit"])
{
//std::cout << "Just building: " << sc2::UnitTypeToName(static_cast<sc2::UNIT_TYPEID>(unit)) << " (" << unit << ")" << std::endl;
description.buildings_needed.push_back(static_cast<sc2::UNIT_TYPEID>(unit));
}
}
else
{
//std::cout << "Unsupported" << std::endl;
//std::cout << requirement << std::endl;
}
}
}
void parse_build_description(BuildDescription & description, json & build_item)
{
description.result_type = static_cast<sc2::UNIT_TYPEID>(build_item["unit"]);
description.build_ability = static_cast<sc2::ABILITY_ID>(build_item["ability"]);
description.buildTime = static_cast<int>(build_item["time"]); // The time in seconds it takes to create the unit parsed from the json file
if (build_item.find("requires") != build_item.end())
{
//std::cout << "Building unit: " << id_to_string(build_item["unit"]) << " requires" << std::endl;
auto & requires = build_item["requires"][0];
add_requirement(description, requires);
}
}
void parse_research_item(ResearchDescription & description, json & research_item)
{
//std::cout << "Parsing " << research_item["upgradeName"] << std::endl;
description.result_type = static_cast<sc2::UPGRADE_ID>(research_item["upgrade"]);
description.ability_used = static_cast<sc2::ABILITY_ID>(research_item["ability"]);
if (research_item.find("requires") != research_item.end() && research_item["requires"].size() > 0)
{
auto & requires = research_item["requires"][0];
add_requirement(description, requires);
}
}
void TechTreeImproved::parse_unit(json::iterator it)
{
sc2::UNIT_TYPEID producer_id = string_to_id(it.key());
//std::string name = sc2::UnitTypeToName(producer_id);
if (it.value().find("builds") != it.value().end())
{
auto & builds = it.value()["builds"];
for (auto & build_item : builds)
{
BuildDescription description;
description.producer_type = producer_id;
parse_build_description(description, build_item);
if (result_to_data.count(description.result_type) > 0)
{
//std::cout << "Found more than one way to build " << sc2::UnitTypeToName(description.result_type) << " (" << (unsigned int) description.result_type << ")" << std::endl;
result_to_data[description.result_type].push_back(description);
}
else
{
result_to_data[description.result_type] = { description };
}
build_descriptions.push_back(description);
}
}
// TODO: Use the result from the call to find for actually looking up data later, instead of searching twice
if (it.value().find("researches") != it.value().end())
{
//std::cout << "Found upgrades on unit " << it.value()["name"] << std::endl;
for (auto & research_item : it.value()["researches"])
{
ResearchDescription description;
description.producer_type = producer_id;
parse_research_item(description, research_item);
if (upgrade_to_data.count(description.result_type))
{
upgrade_to_data[description.result_type].push_back(description);
}
else
{
upgrade_to_data[description.result_type] = { description };
}
research_descriptions.push_back(description);
}
}
if (it.value().find("morphs") != it.value().end())
{
for (auto & morph_item : it.value()["morphs"])
{
BuildDescription description;
description.producer_type = producer_id;
description.morph_ability = static_cast<sc2::ABILITY_ID>(morph_item["ability"]);
description.result_type = static_cast<sc2::UNIT_TYPEID>(morph_item["unit"]);
if (morph_item.find("requires") != morph_item.end())
{
for (auto & requirement : morph_item["requires"])
{
std::string type = requirement["type"];
if (type == "unitCount")
{
for (auto & unit : requirement["unit"])
{
sc2::UNIT_TYPEID unit_typeid = static_cast<sc2::UNIT_TYPEID>(unit);
description.buildings_needed.push_back(unit_typeid);
}
}
else if (type == "upgradeCount")
{
sc2::UPGRADE_ID upgrade_id = static_cast<sc2::UPGRADE_ID>(requirement["upgrade"]);
description.upgrades_needed.push_back(upgrade_id);
}
}
}
build_descriptions.push_back(description);
}
}
}
bool TechTreeImproved::LoadData() {
std::ifstream i("techtree.json");
if (!i.good())
{
std::wcerr << "File techtree.json cannot be found, information regarding addons and required buildings will not be up to date. Please put techtree.json in working directory." << std::endl;
return false;
}
// Parse the file's content
json j;
i >> j;
// Time to parse content of the JSON file
for (auto & race : j)
{
for (json::iterator it = race.begin(); it != race.end(); ++it)
{
parse_unit(it);
}
}
return true;
}
const std::vector<BuildDescription> & TechTreeImproved::HowToBuild(sc2::UnitTypeID unit) const
{
if (result_to_data.count(unit) > 0)
{
return result_to_data.at(unit);
}
else
{
std::cout << "No information about unit type " << sc2::UnitTypeToName(unit) << " (" << static_cast<int>(unit) << ")" << std::endl;
return empty_build;
}
}
const std::vector<ResearchDescription> & TechTreeImproved::HowToResearch(sc2::UpgradeID upgrade) const
{
if (upgrade_to_data.count(upgrade))
{
return upgrade_to_data.at(upgrade);
}
else
{
std::cout << "No information about upgrade type " << sc2::UpgradeIDToName(upgrade) << " (" << static_cast<int>(upgrade) << ")" << std::endl;
return empty_research;
}
}
#pragma once
#include "nlohmann/json.hpp"
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include "sc2api/sc2_typeenums.h"
struct BuildDescription
{
sc2::UNIT_TYPEID producer_type;
sc2::UNIT_TYPEID result_type;
sc2::AbilityID build_ability;
sc2::AbilityID morph_ability;
std::vector<sc2::UNIT_TYPEID> buildings_needed;
std::vector<sc2::UNIT_TYPEID> addons_needed;
std::vector<sc2::UPGRADE_ID> upgrades_needed;
int buildTime; // The time in seconds it takes to create the unit
};
struct ResearchDescription
{
sc2::UPGRADE_ID result_type;
sc2::UNIT_TYPEID producer_type;
sc2::AbilityID ability_used;
std::vector<sc2::UNIT_TYPEID> buildings_needed;
std::vector<sc2::UPGRADE_ID> upgrades_needed;
};
class TechTreeImproved
{
std::map<sc2::UNIT_TYPEID, std::vector<BuildDescription>> result_to_data;
std::map<sc2::UPGRADE_ID, std::vector<ResearchDescription>> upgrade_to_data;
std::vector<BuildDescription> build_descriptions;
std::vector<ResearchDescription> research_descriptions;
// If there is no BuildDescription for a given type, a reference to tihs list is returned.
const std::vector<BuildDescription> empty_build {};
const std::vector<ResearchDescription> empty_research {};
void parse_unit(nlohmann::json::iterator it);
public:
TechTreeImproved();
bool LoadData();
// Given a unit, how can we build it?
const std::vector<BuildDescription> & HowToBuild(sc2::UnitTypeID unit) const;
const std::vector<ResearchDescription> & HowToResearch(sc2::UpgradeID upgrade) const;
const std::vector<BuildDescription> & BuildDescriptions() const { return build_descriptions; }
const std::vector<ResearchDescription> & ResearchDescriptions() const { return research_descriptions; }
};
#include "Unit.h"
#include "IDABot.h"
#include "sc2api/sc2_gametypes.h"
Unit::Unit()
: m_bot(nullptr)
......@@ -13,7 +14,14 @@ Unit::Unit(const sc2::Unit * unit, IDABot & bot)
: m_bot(&bot)
, m_unit(unit)
, m_unitID(unit->tag)
, m_unitType(unit->unit_type, bot)
, m_unitType(unit->unit_type, bot, bot)
{
}
Unit::Unit(const sc2::Unit * unit)
: m_unit(unit)
, m_unitID(unit->tag)
{
}
......@@ -111,7 +119,7 @@ bool Unit::isCompleted() const
bool Unit::isTraining() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->orders.size() > 0;
return m_unit->orders.size() > 0 && m_unitType.isBuilding();
}
bool Unit::isBeingConstructed() const
......@@ -146,6 +154,16 @@ bool Unit::isFlying() const
#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");
......@@ -226,7 +244,7 @@ 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);
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_MOVE, targetPosition);
#else
m_unit->move(targetPosition);
#endif
......@@ -236,7 +254,7 @@ 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));
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_MOVE, CCPosition((float)targetPosition.x, (float)targetPosition.y));
#else
m_unit->move(CCPosition(targetPosition));
#endif
......@@ -259,47 +277,249 @@ void Unit::repair(const Unit & target) const
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
if (m_bot->Map().isConnected(getTilePosition(), pos))
{
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
}
else
{
printf("Warning! Cannot build at location (%d, %d) and therefore ignoring command.", pos.x, pos.y);
}
}
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
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);
}
\ No newline at end of file
}
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);
}
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){
// t_id is set to the unit tag of the target
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
// Make sure the returned tag is not the NullTag
if (t_id == sc2::NullTag) {
return *this;
}
// Make sure the Tag references a valid unit
if (m_bot->Observation()->GetUnit(t_id) == nullptr) {
return *this;
}
// Convert the tag to a Unit object
Unit unit = m_bot->GetUnit(t_id);
if (unit.isValid()) {
return unit;
} else {
return *this;
}
}
return *this;
}
bool Unit::hasTarget() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
if (getUnitPtr()->orders.size() > 0) {
if (getUnitPtr()->orders[0].target_unit_tag != sc2::NullTag) {
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
if (m_bot->Observation()->GetUnit(t_id) == nullptr) {
return false;
}
Unit unit = m_bot->GetUnit(t_id);
return unit.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;
}
const std::vector<float> Unit::getAllProgress() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// If unit has order, return progress of first order
std::vector<float> progressions;
if (getUnitPtr()->orders.size() > 0) {
for(int i = 0; i < getUnitPtr()->orders.size(); i++) {
progressions.push_back(getUnitPtr()->orders[i].progress);
}
}
return progressions;
}
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::GENERAL_HOLDPOSITION);
}
void Unit::patrol(const CCPosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_PATROL, targetPosition);
}
void Unit::stopDance() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP_DANCE);
}
/*
// Implementation by Dawid Abucewicz
bool Unit::isCarryingMinerals() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
std::vector<CCBuff> buffs = m_unit->buffs;
for (auto & b : buffs)
{
if (b.to_string() == "271" or b.to_string() == "272")
{
return true;
}
}
return false;
}
*/
int Unit::gasLeftInGeyser() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->vespene_contents;
}
int Unit::mineralsLeftInMineralfield() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->mineral_contents;
}
int Unit::getOwner() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->owner;
}
// Implemented with Blizzard SC2 API
bool Unit::isCarryingGas() const
{
return sc2::IsCarryingVespene(*m_unit);
}
bool Unit::isCarryingMinerals() const
{
return sc2::IsCarryingMinerals(*m_unit);
}
float Unit::maxShields() const
{
return m_unit->shield_max;
}
float Unit::maxEnergy() const
{
return m_unit->energy_max;
}
......@@ -11,13 +11,15 @@ class Unit
CCUnitID m_unitID;
UnitType m_unitType;
const sc2::Unit * m_unit;
protected:
const sc2::Unit * m_unit;
public:
Unit();
Unit(const sc2::Unit * unit, IDABot & bot);
Unit(const sc2::Unit * unit);
const sc2::Unit * getUnitPtr() const;
const sc2::UnitTypeID & getAPIUnitType() const;
......@@ -33,6 +35,7 @@ public:
CCHealth getEnergy() const;
CCPlayer getPlayer() const;
CCUnitID getID() const;
std::vector< CCBuff > buffs() const;
float getBuildPercentage() const;
int getWeaponCooldown() const;
bool isCompleted() const;
......@@ -46,6 +49,31 @@ public:
bool isValid() const;
bool isTraining() const;
bool isConstructing(const UnitType & type) const;
bool isCarryingMinerals() const;
bool isBlip() const;
bool hasTarget() const;
Unit getTarget() const;
CCHealth getMaxHitPoints() const;
float getProgress() const;
const std::vector<float> getAllProgress() const;
sc2::AbilityID getCurrentAbilityID() const;
void holdPosition() const;
void patrol(const CCPosition & targetPosition) const;
void stopDance() const;
float getFacing() const;
float getRadius() const;
/*
API extended summer 2020
*/
int gasLeftInGeyser() const;
int mineralsLeftInMineralfield() const;
int getOwner() const;
bool isCarryingGas() const;
float maxShields() const;
float maxEnergy() const;
void stop () const;
void attackUnit (const Unit & target) const;
......@@ -58,4 +86,8 @@ public:
void buildTarget (const UnitType & buildingType, const Unit & target) const;
void train (const UnitType & buildingType) const;
void morph (const UnitType & type) const;
void research (sc2::UpgradeID upgrade) const;
void ability (sc2::AbilityID ability) const;
void ability (sc2::AbilityID ability, const sc2::Point2D & point) const;
void ability (sc2::AbilityID ability, const Unit & target) const;
};