diff --git a/.gitignore b/.gitignore index 567609b1234a9b8806c5a05da6c866e480aa148d..0023a727e767c45c3521dc3f0e2ed635bb81f1ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ build/ +.idea +venv +.vs diff --git a/docs/.gitignore b/docs/.gitignore index 105f812a5862ebf713d87bb2b570654541f0b195..267169afdf7084bd04be62a6e0d70f8598c2f970 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,2 +1,4 @@ _autosummary/ _build/ +venv +.idea diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 0000000000000000000000000000000000000000..eca68a0e79ecee259c30a89b057d8958c7f68fbc --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,6 @@ +{% extends "!layout.html" %} + + {% block menu %} + {{ super() }} + <a href="py-modindex.html">modindex</a> + {% endblock %} \ No newline at end of file diff --git a/docs/constants.rst b/docs/constants.rst index f75b8535ddfbc859aa49b75c7110fb012100ea6d..a4e6275503d69b560cc017b8c1ee0eb89580e112 100644 --- a/docs/constants.rst +++ b/docs/constants.rst @@ -46,3 +46,6 @@ Race The following attribute means a randomly selected race from the three above: .. attribute:: Race.Random + + +.. toctree:: \ No newline at end of file diff --git a/docs/contributing.rst b/docs/contributing.rst index 853063d021db997dbda0cd6a6f8100b9cdfe40d7..3aa8a8297e315e6078da07097a743cbb4a8e3ff8 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -38,6 +38,27 @@ The source code for all additional dependencies (including pybind11) are registe The system is built using cmake, see the file `CMakeLists.txt <https://gitlab.liu.se/starcraft-ai-course/pycommandcenter/blob/master/CMakeLists.txt>`_ in the project root. +If a function already exist but you can't use it in python, check and see if it's exist in the library files (pybind). + +#. Create a declaration of your function in the header file. +#. Create a definition of your function in the source file. +#. Depending on which object you decided to extend, you should also add this function to the library file. The library is the pybind, making it possible to use your function in python. +#. Update the documentation. There are instructions on how you build and test the documentation. + +Example: +We want to add function to unit, returning a bool depending on if it's holding a mineral. We have discovered a function in the SC2 API containing this information (sc2_client.ccp). This is a helper function, it doesn't belong to any object. + +#. In unit.h: bool isCarryingMinerals() const; +#. In unit.cpp: bool Unit::isCarryingMinerals() const { return sc2::IsCarryingMinerals(\*m_unit); } +#. We can access m_unit in the unit file and with sc2::Function() we can access any function in the blizzard API that doesn't belong to any object. The same goes for any object, for example sc2::Point3D makes us able to access the Point3D object. +#. In lib_unit.cpp: .def_property_readonly("is_carrying_minerals", &Unit::isCarryingMinerals) +#. In the folder named docs we update the documentation. In this case, we update the file unit.rst. + +Common problems: + +#. The return in python is a memory address: Make sure that it returns a correct type. +#. The compiler complains about files I have not even touched: Make sure that the startUp is library and you have release x64. If you just added a new function in pybind, check it. +#. The bot crashes whit a exit code -1073741819 (0xC0000005): Make sure that you dont read null values. Document the new features / changes you have made ------------------------------------------------- @@ -61,3 +82,5 @@ Read the comments on your merge request and make the necessary changes In this step someone will review your changes and make comments. These comments might ask you to make changes to the code or documentation. These changes must be done before the merge request is accepted. Therefore it is important to make merge requests several days before eventual deadlines. Once the merge request has been accepted the code is now part of PyCommandCenter. Congratulations and thank you for your contribution to the project! + +.. toctree:: \ No newline at end of file diff --git a/docs/coordinates.rst b/docs/coordinates.rst index 294d8eea35bef9b8f6b70dac75a921702c1acb91..fb74871e26f4a5a45f9a16451ae9910756e8b20f 100644 --- a/docs/coordinates.rst +++ b/docs/coordinates.rst @@ -81,3 +81,4 @@ below: print(p1.distance(p2)) # prints: 2.8284... +.. toctree:: \ No newline at end of file diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index 037793e338f9110230000d487491afb6ac174866..c68a47300c4efa3530aec4bfe6a2f6f9428f5800 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -150,3 +150,4 @@ to: where ``SomeOtherBot`` is a bot defined in the same way as ``MyAgent``. +.. toctree:: \ No newline at end of file diff --git a/docs/helpers.rst b/docs/helpers.rst index 15cc665061d3ba8606024b55399998a459dd264b..68802b440ee021816569900ad82f6520ae54db31 100644 --- a/docs/helpers.rst +++ b/docs/helpers.rst @@ -188,3 +188,5 @@ BuildingPlacer If you want to place a town hall, take a look at attribute `depot_location` of :class:`library.BaseLocation`. If you want to place a refinery, take a look at attribute `geysers` of :class:`library.BaseLocation` and the method build_target of :class:`library.Unit`. + +.. toctree:: \ No newline at end of file diff --git a/docs/idabot.rst b/docs/idabot.rst index ad95df7bd7b4bcf3b5a9208f911bda67ebddf81f..6a4c6be2f210cfc04ad3b0ccc10ce43ad113caf2 100644 --- a/docs/idabot.rst +++ b/docs/idabot.rst @@ -191,3 +191,4 @@ The debug-methods are a great tool for speeding up the process. Set the amount (Float) of shield to the unit +.. toctree:: \ No newline at end of file diff --git a/docs/idareplayobserver.rst b/docs/idareplayobserver.rst new file mode 100644 index 0000000000000000000000000000000000000000..d2379aefe762981f6bd342a26c7c96c4304a485e --- /dev/null +++ b/docs/idareplayobserver.rst @@ -0,0 +1,48 @@ +IDAReplayObserver +================= + +.. class:: library.IDAReplayObserver + + This is a class for following a replay. + + Inherited methods: + + .. method:: IDAReplayObserver.on_game_start(self) + + This method is called when a replay has started, when you inherit it you have to + call the parent's on_game_start method in order to make it work (see + :ref:`replays`). + + .. method:: IDAReplayObserver.on_step(self) + + This method is called on every tick of the replay, when you inherit it you + have to call the parent's on_step method in order to make it work (see + :ref:`replays`). + + .. method:: IDAReplayObserver.on_game_end(self) + + This method is called when the replay has ended, when you inherit it you have to + call the parent's on_game_start method in order to make it work (see + :ref:`replays`). + + .. method:: IDAReplayObserver.on_unit_created(self) + + This method is called when the an unit is created, that includes when an unit leaves a refinery. This only works if replay perspective is not set to 0. + + .. method:: IDAReplayObserver.on_unit_destroyed(self) + + This unit is called when a unit is destroyed. + + Methods: + + .. method:: IDAReplayObserver.get_all_units(self) -> List[library.ReplayUnit] + + Retrieves a list of all visible units + + .. method:: IDAReplayObserver.get_player_race(self, player_id) -> library.Race + + Returns the players race + + + +.. toctree:: \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 153c9df4954c1266a97d4b7933b7fb54ae6b4344..da345dada9ea6d61e89b35860c335efcdd0aef95 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,13 +22,18 @@ Table of contents :maxdepth: 3 gettingstarted + Library<_autosummary/library> + Coordinator<_autosummary/library.Coordinator> helpers idabot unit types coordinates constants - + replays + idareplayobserver + replayunit + .. autosummary:: :toctree: _autosummary :hidden: diff --git a/docs/replays.rst b/docs/replays.rst new file mode 100644 index 0000000000000000000000000000000000000000..af3307805042078bc4de4903642b827ee6a2e08e --- /dev/null +++ b/docs/replays.rst @@ -0,0 +1,108 @@ +.. _replays: + +Replays +======= +This page will describe two different techniques for handling replays. The +first technique parses the information saved in the replay file. The second +uses the information in the replay file to actually replay the game. The +different techniques have certain advantages and disadvantages. The main +one is that the reader is a lot faster while replaying the game provides +a lot more information. + + + +SC2Reader +--------- +SC2Reader_ is a library that can be used to implement the first technique. + +Here is a short example that uses SC2Reader to extract the build order. + + +.. _SC2Reader: https://github.com/ggtracker/sc2reader + +.. code-block:: python + + import sc2reader + import json + from sc2reader.factories import SC2Factory + + # The path to the replays + PATH = "../Replays" + + def main(): + # Creates a generator of all the replays in the dictionary + replays = sc2reader.load_replays(PATH, load_level=3) + games = [] + # Loops through every relay + for replay in replays: + building_order = [] + if is_terran_vs_terran(replay): + # Loops through every event + for event in replay.events: + # Check if the event is that a building is crated + if type(event) == sc2reader.events.tracker.UnitInitEvent: + if event.unit.name not in building_order: + building_order.append(event.unit.name) + games.append(building_order) + return games + + + def is_terran_vs_terran(replay): + try: + return sc2reader.constants.LOCALIZED_RACES[replay.players[0].play_race] == "Terran" \ + and sc2reader.constants.LOCALIZED_RACES[replay.players[1].play_race] == "Terran" + except(KeyError): + return False + + if __name__ == '__main__': + games = main() + text = json.dumps(games) + print("Res: " + text) + + +SC2Reader has good documation_ that also describe what information +could be found. `What is in a Replay`_ and Events_ gives a good idea +if the information you want could be collected with SC2Reader. + +.. _documation: https://sc2reader.readthedocs.io/en/latest/index.html +.. _What is in a Replay: https://sc2reader.readthedocs.io/en/latest/articles/whatsinareplay.html +.. _Events: https://sc2reader.readthedocs.io/en/latest/events/index.html + +ReplayObserver +-------------- +This is the second technique it is much like using a bot but with the difference +that no action can be preform just observations. + + +.. code-block:: python + + from library import * + + + class MyObserver(ReplayObserver): + def __init__(self): + ReplayObserver.__init__(self) + + def on_game_start(self): + ReplayObserver.on_game_start(self) + + def on_step(self): + ReplayObserver.on_step(self) + + + def main(): + + coordinator = Coordinator(r"D:/StarCraft II/Versions/Base69232/SC2_x64.exe") + if coordinator.load_replay_list("D:/Replays/"): + observer = MyObserver() + coordinator.add_replay_observer(observer) + while coordinator.update(): + pass + else: + print("No replays found") + + + if __name__ == "__main__": + main() + +.. toctree:: \ No newline at end of file diff --git a/docs/replayunit.rst b/docs/replayunit.rst new file mode 100644 index 0000000000000000000000000000000000000000..7d27a67eb9e9e956856a5bced9a4a11723f47285 --- /dev/null +++ b/docs/replayunit.rst @@ -0,0 +1,75 @@ +ReplayUnit +========== + +.. class:: library.ReplayUnit + + An instance of the class Unit represents one unit in a replay. A ReplayUnit is a + :class:`library.Unit` white some limitations. + + It is possible to use ReplayUnit as keys in a dictionary, which might be helpful + for bookkeeping. + + Properties: + + .. autoattribute:: buffs + + Returns a list of BuffID + + .. autoattribute:: build_percentage + .. autoattribute:: energy + .. autoattribute:: facing + + Returns the direction the unit is facing + + .. autoattribute:: hit_points + .. autoattribute:: max_hit_points + .. autoattribute:: id + .. autoattribute:: is_alive + .. autoattribute:: is_blip + + Returns true if unit is a "blip" - a ping on the map. + + .. autoattribute:: is_being_constructed + + Returns build_progress > 0 + + .. autoattribute:: is_burrowed + .. autoattribute:: is_cloaked + .. autoattribute:: is_completed + + Returns build_progress >= 1 + + .. autoattribute:: is_flying + .. autoattribute:: is_idle + .. autoattribute:: is_powered + .. autoattribute:: is_training + .. autoattribute:: is_valid + .. attribute:: ReplayUnit.player + + Returns the constant corresponding to player which this unit belongs to. + See :ref:`playerconstants` for more information. + + .. autoattribute:: position + .. autoattribute:: current_ability_id + + .. autoattribute:: progress + + Returns the progress of currently used ability (-1 if not using ability) + + .. autoattribute:: radius + + Retruns the radius of the unit + + .. autoattribute:: shields + .. autoattribute:: tile_position + .. autoattribute:: unit_type + + Returns the :class:`library.UnitType` of the unit + + .. autoattribute:: weapon_cooldown + .. autoattribute:: is_carrying_minerals + + Returns if this unit is currently holding minerals + + +.. toctree:: \ No newline at end of file diff --git a/docs/types.rst b/docs/types.rst index dd9986f59ffb4543fb5b1165a395d28ff6b5a251..1227e4b87db0148a47be1d818a784188e00a98e8 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -53,3 +53,4 @@ EffectID is for things like ravager bile, or fungal or even a scan. :members: :undoc-members: +.. toctree:: \ No newline at end of file diff --git a/docs/unit.rst b/docs/unit.rst index 16aa1d46c7c8d7ef33073845d400bb05cf11f9ee..55a65d72c4c4f55dfd892d81ad19027c5bbaefc1 100644 --- a/docs/unit.rst +++ b/docs/unit.rst @@ -133,3 +133,5 @@ Unit .. automethod:: stop_dance Stop and dance + +.. toctree:: \ No newline at end of file diff --git a/python-api-src/lib_replay_unit.cpp b/python-api-src/lib_replay_unit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e898aaa64ed3a2b1f86e52eab7f817629b693e8 --- /dev/null +++ b/python-api-src/lib_replay_unit.cpp @@ -0,0 +1,42 @@ +#include "library.h" + +namespace py = pybind11; + +void define_replay_unit(py::module & m) +{ + py::class_<ReplayUnit>(m, "ReplayUnit") + .def_property_readonly("id", &ReplayUnit::getID) + .def_property_readonly("unit_type", &ReplayUnit::getType, "The :class :`library.UnitType` of the unit") + .def_property_readonly("position", &ReplayUnit::getPosition, "The :class:`library.Point2D` of the unit") + .def_property_readonly("tile_position", &ReplayUnit::getTilePosition, "The :class:`library.Point2DI` of the unit") + .def_property_readonly("hit_points", &ReplayUnit::getHitPoints) + .def_property_readonly("shields", &ReplayUnit::getShields) + .def_property_readonly("energy", &ReplayUnit::getEnergy) + .def_property_readonly("player", &ReplayUnit::getPlayer) + .def_property_readonly("build_percentage", &ReplayUnit::getBuildPercentage) + .def_property_readonly("weapon_cooldown", &ReplayUnit::getWeaponCooldown) + .def_property_readonly("is_completed", &ReplayUnit::isCompleted) + .def_property_readonly("is_being_constructed", &ReplayUnit::isBeingConstructed) + .def_property_readonly("is_cloaked", &ReplayUnit::isCloaked) + .def_property_readonly("is_flying", &ReplayUnit::isFlying) + .def_property_readonly("buffs", &ReplayUnit::buffs) + .def_property_readonly("is_alive", &ReplayUnit::isAlive) + .def_property_readonly("is_powered", &ReplayUnit::isPowered) + .def_property_readonly("is_idle", &ReplayUnit::isIdle) + .def_property_readonly("is_burrowed", &ReplayUnit::isBurrowed) + .def_property_readonly("is_valid", &ReplayUnit::isValid) + .def_property_readonly("is_training", &ReplayUnit::isTraining) + .def_property_readonly("is_blip", &ReplayUnit::isBlip) + .def_property_readonly("target", &ReplayUnit::getTarget) + .def_property_readonly("has_target", &ReplayUnit::hasTarget) + .def_property_readonly("max_hit_points", &ReplayUnit::getMaxHitPoints) + .def_property_readonly("progress", &ReplayUnit::getProgress) + .def_property_readonly("current_ability_id", &ReplayUnit::getCurrentAbilityID, "The AbilityID of currently used ability") + .def_property_readonly("facing", &ReplayUnit::getFacing) + .def_property_readonly("radius", &ReplayUnit::getRadius) + .def_property_readonly("is_carrying_minerals", &ReplayUnit::isCarryingMinerals) + .def("__hash__", [](const ReplayUnit & unit) { return std::hash<const sc2::Unit *>{}(unit.getUnitPtr()); }) + .def(py::self == py::self) + .def("__repr__", [](const ReplayUnit & unit) { return "<Unit of type: '" + unit.getType().getName() + "'>"; }) + ; +} diff --git a/python-api-src/lib_tech_tree.cpp b/python-api-src/lib_tech_tree.cpp index 44012c40d5833fb2530e2c3c156786885473b442..2f388455f8a9647e486b910a7be5f090bb8be353 100644 --- a/python-api-src/lib_tech_tree.cpp +++ b/python-api-src/lib_tech_tree.cpp @@ -26,5 +26,7 @@ void define_tech_tree(py::module & m) py::class_<TechTree>(m, "TechTree") .def("get_data", py::overload_cast<const UnitType &>(&TechTree::getData, py::const_)) - .def("get_data", py::overload_cast<const CCUpgrade &>(&TechTree::getData, py::const_)); + .def("get_data", py::overload_cast<const CCUpgrade &>(&TechTree::getData, py::const_)) + .def("suppress_warnings", &TechTree::setSuppressWarnings, "Suppress type and uppgrade warnings" ,"b"_a) + ; } diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp index 09e5067015fa373382a85cf07039dbf87b1cfc83..07700758413ec714ed641ee4bd360ee1333952b8 100644 --- a/python-api-src/library.cpp +++ b/python-api-src/library.cpp @@ -8,6 +8,7 @@ PYBIND11_MODULE(library, m) define_typeenums(m); define_unit(m); + define_replay_unit(m); define_unittype(m); define_util(m); define_point(m); @@ -26,7 +27,11 @@ PYBIND11_MODULE(library, m) .def("launch_starcraft", &sc2::Coordinator::LaunchStarcraft) .def("start_game", &sc2::Coordinator::StartGame, "map_path"_a) .def("update", &sc2::Coordinator::Update) - .def("set_real_time", &sc2::Coordinator::SetRealtime); + .def("set_real_time", &sc2::Coordinator::SetRealtime) + .def("load_replay_list",&sc2::Coordinator::SetReplayPath, "replay_path"_a) + .def("add_replay_observer",&sc2::Coordinator::AddReplayObserver, "replay_observer"_a) + .def("set_replay_perspective",&sc2::Coordinator::SetReplayPerspective, "perspective"_a) + ; py::enum_<sc2::Race>(m, "Race") .value("Terran", sc2::Race::Terran) @@ -121,6 +126,33 @@ PYBIND11_MODULE(library, m) // API extended summer 2020 + + + py::class_<sc2::ReplayObserver>(m, "ReplayObserver") + .def(py::init()); + + py::class_<IDAReplayObserver, PyReplayObserver, sc2::ReplayObserver>(m, "IDAReplayObserver") + .def(py::init()) + .def("on_game_start", &IDAReplayObserver::OnGameStart) + .def("on_step", &IDAReplayObserver::OnStep) + .def("on_game_end", &IDAReplayObserver::OnGameEnd) + .def("get_all_units", &IDAReplayObserver::GetAllUnits, "Returns a list of all units") + .def("get_player_race", &IDAReplayObserver::GetPlayerRace,"player_id"_a) + .def("get_replay_path", &IDAReplayObserver::GetReplayPath) + .def("get_result_for_player", &IDAReplayObserver::GetResultForPlayer, "player_id"_a) + .def("on_unit_destroyed", &IDAReplayObserver::OnReplayUnitDestroyed, "unit"_a) + .def("on_unit_created", &IDAReplayObserver::OnReplayUnitCreated, "unit"_a) + .def_property_readonly("tech_tree", &IDAReplayObserver::GetTechTree) + ; + + + + py::enum_<sc2::GameResult>(m, "GameResult") + .value("Win", sc2::GameResult::Win) + .value("Loss", sc2::GameResult::Loss) + .value("Tie", sc2::GameResult::Tie) + .value("Undecided", sc2::GameResult::Undecided); + py::class_<sc2::PlayerSetup>(m, "PlayerSetup"); py::enum_<sc2::Difficulty>(m, "Difficulty") diff --git a/python-api-src/library.h b/python-api-src/library.h index fb671e11555b6bfad74f8fc45baf7093a3b89e6c..3f9114d0685218dec0f51e838031976f622c5709 100644 --- a/python-api-src/library.h +++ b/python-api-src/library.h @@ -3,6 +3,7 @@ #include <pybind11/pybind11.h> #include <sc2api/sc2_api.h> #include "../src/IDABot.h" +#include "../src/IDAReplayObserver.h" #include <iostream> #include <pybind11/stl.h> /* Automatic conversion from std::vector to Python lists */ #include <pybind11/operators.h> /* Convenient operator support */ @@ -21,7 +22,7 @@ public: } Coordinator(std::string path) : sc2::Coordinator() - { + { std::vector<std::string> arguments = { "pycommandcenter", "-e", path }; CustomLoadSettings(arguments); } @@ -61,10 +62,67 @@ public: } }; + +class PyReplayObserver : public IDAReplayObserver +{ +public: + using IDAReplayObserver::IDAReplayObserver; + void OnGameStart() override + { + PYBIND11_OVERLOAD_NAME( + void, + IDAReplayObserver, + "on_game_start", + OnGameStart + ); + } + void OnStep() override + { + PYBIND11_OVERLOAD_NAME( + void, + IDAReplayObserver, + "on_step", + OnStep + ); + } + void OnGameEnd() override + { + PYBIND11_OVERLOAD_NAME( + void, + IDAReplayObserver, + "on_game_end", + OnGameEnd + + ); + } + void OnReplayUnitDestroyed(const ReplayUnit *unit) override + { + PYBIND11_OVERLOAD_NAME( + void, + IDAReplayObserver, + "on_unit_destroyed", + OnReplayUnitDestroyed, + unit + ); + } + void OnReplayUnitCreated(const ReplayUnit *unit) override + { + PYBIND11_OVERLOAD_NAME( + void, + IDAReplayObserver, + "on_unit_created", + OnReplayUnitCreated, + unit + ); + } + +}; + // The functions below are all defined in different .cpp files, in order // to keep compilation snappy void define_typeenums(pybind11::module & m); void define_unit(pybind11::module & m); +void define_replay_unit(pybind11::module & m); void define_unittype(pybind11::module &m); void define_util(pybind11::module &m); void define_point(pybind11::module &m); diff --git a/src/IDABot.cpp b/src/IDABot.cpp index cda0ce75922c415a037b86161fb74089a09cede9..10c29c16ce0c28d2cd0b6bf40a7a62ea33ee1140 100644 --- a/src/IDABot.cpp +++ b/src/IDABot.cpp @@ -72,12 +72,11 @@ void IDABot::OnStep() m_map.onFrame(); m_unitInfo.onFrame(); m_bases.onFrame(); - // ----------------------------------------------------------------- // Draw debug interface, and send debug interface to the Sc2 client. // ----------------------------------------------------------------- Debug()->SendDebug(); - m_buildingPlacer.drawReservedTiles(); + m_buildingPlacer.drawReservedTiles(); } void IDABot::setUnits() diff --git a/src/IDAReplayObserver.cpp b/src/IDAReplayObserver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53be250dbb8a6acd746c432716f35c400fd8ea0c --- /dev/null +++ b/src/IDAReplayObserver.cpp @@ -0,0 +1,132 @@ +#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()); +} + + diff --git a/src/IDAReplayObserver.h b/src/IDAReplayObserver.h new file mode 100644 index 0000000000000000000000000000000000000000..fe620b535372e15d5a11ba18c6e46d7b86269ce4 --- /dev/null +++ b/src/IDAReplayObserver.h @@ -0,0 +1,51 @@ +#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; + +}; + diff --git a/src/ReplayUnit.cpp b/src/ReplayUnit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e2c100d73ed4efdb9f69a491794688d58f018f2 --- /dev/null +++ b/src/ReplayUnit.cpp @@ -0,0 +1,56 @@ +#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; +} + + diff --git a/src/ReplayUnit.h b/src/ReplayUnit.h new file mode 100644 index 0000000000000000000000000000000000000000..23fc50c1e7fc37de672ae04f9e39a8767f559e70 --- /dev/null +++ b/src/ReplayUnit.h @@ -0,0 +1,22 @@ +#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 diff --git a/src/TechTree.cpp b/src/TechTree.cpp index aca2be4e7d6614d41de6714f8523e2cbbc634b5d..d0a94c49e05cc43eb9f9f6063029dc40783fb284 100644 --- a/src/TechTree.cpp +++ b/src/TechTree.cpp @@ -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) { } @@ -31,7 +31,7 @@ void TechTree::onStart() for (const BuildDescription & description : tree.BuildDescriptions()) { - if (m_unitTypeData.count(UnitType(description.result_type, m_bot)) == 0) + if (m_unitTypeData.count(UnitType(description.result_type, m_client)) == 0) { //std::cout << "Inserting new information about UNIT_TYPEID: " // << sc2::UnitTypeToName(description.result_type) << " (" @@ -39,7 +39,7 @@ void TechTree::onStart() // << std::endl; } - TypeData & data = m_unitTypeData[UnitType(description.result_type, m_bot)]; + 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) @@ -53,19 +53,19 @@ void TechTree::onStart() data.buildAbility = sc2::ABILITY_ID::INVALID; } - data.whatBuilds.push_back(UnitType(description.producer_type, m_bot)); + 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_bot)); + 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_bot)); + data.requiredAddons.push_back(UnitType(unit_typeid, m_client)); } } @@ -81,11 +81,11 @@ void TechTree::onStart() for (const ResearchDescription & description : tree.HowToResearch(id)) { data.buildAbility = description.ability_used; - data.whatBuilds.push_back(UnitType(description.producer_type, m_bot)); + 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_bot)); + data.requiredUnits.push_back(UnitType(unit_typeid, m_client)); } for (sc2::UPGRADE_ID upgrade_id : description.upgrades_needed) @@ -96,158 +96,163 @@ void TechTree::onStart() } } +void TechTree::setSuppressWarnings(bool b) +{ + suppressWarnings = b; +} + 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::MORPH_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() @@ -256,102 +261,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_CYCLONELOCKONDAMAGE, 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; } @@ -362,7 +370,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; } diff --git a/src/TechTree.h b/src/TechTree.h index c20274588af9ba27576510abbd5c8013f7997960..412aaf49c0b50c5781dbb4825a1fadc1a62651b0 100644 --- a/src/TechTree.h +++ b/src/TechTree.h @@ -31,18 +31,21 @@ struct TypeData 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); + const TypeData & getData(const UnitType & type) const; const TypeData & getData(const CCUpgrade & type) const; const TypeData & getData(const MetaType & type) const; diff --git a/src/Unit.cpp b/src/Unit.cpp index 6f4bcee54eae7b0ead9ce2d19d5fed2757c780af..50b5fa4df5485a7fba382a06bcc2431fceedec02 100644 --- a/src/Unit.cpp +++ b/src/Unit.cpp @@ -13,7 +13,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) { } @@ -328,17 +335,14 @@ void Unit::ability(sc2::AbilityID ability, const Unit& target) const 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; - // IDABot finds the unit with this tag - return m_bot->GetUnit(t_id); + // t_id is set to the unit tag of the target + CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag; + // IDABot finds the unit with this tag + return m_bot->GetUnit(t_id); } - - Unit this_unit = Unit(m_unit, *m_bot); - return this_unit; + return *this; } bool Unit::hasTarget() const diff --git a/src/Unit.h b/src/Unit.h index ebb2f44bccbcdc022d810269268e66bb2847ef01..f68a09bf1b3e4dd4fad4043265e52cf85a0a49e9 100644 --- a/src/Unit.h +++ b/src/Unit.h @@ -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; diff --git a/src/UnitType.cpp b/src/UnitType.cpp index dd564f7e0b74ee97125b95faff718bd3becde1c5..56b113e6ca713f53de307fefad181b39ec6c437e 100644 --- a/src/UnitType.cpp +++ b/src/UnitType.cpp @@ -1,20 +1,43 @@ #include "UnitType.h" #include "IDABot.h" +#include "IDAReplayObserver.h" UnitType::UnitType() - : m_bot(nullptr) + : m_client(nullptr) , m_type(0) { } -UnitType::UnitType(const sc2::UnitTypeID & type, IDABot & bot) - : m_bot(&bot) +UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client) + : m_client(&client) , m_type(type) + , m_bot(nullptr) + , m_observer(nullptr) + { } +UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDABot & bot) + : m_client(&client) + , m_type(type) + , m_bot(&bot) + , m_observer(nullptr) +{ +} + +UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDAReplayObserver & observer) + : m_client(&client) + , m_type(type) + , m_observer(&observer) + , m_bot(nullptr) + +{ +} + + + sc2::UnitTypeID UnitType::getAPIUnitType() const { return m_type; @@ -47,7 +70,7 @@ std::string UnitType::getName() const CCRace UnitType::getRace() const { - return m_bot->Observation()->GetUnitTypeData()[m_type].race; + return m_client->Observation()->GetUnitTypeData()[m_type].race; } bool UnitType::isCombatUnit() const @@ -192,7 +215,7 @@ bool UnitType::isWorker() const CCPositionType UnitType::getAttackRange() const { #ifdef SC2API - auto & weapons = m_bot->Observation()->GetUnitTypeData()[m_type].weapons; + auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons; if (weapons.empty()) { @@ -220,7 +243,20 @@ int UnitType::tileWidth() const #ifdef SC2API if (isMineral()) { return 2; } if (isGeyser()) { return 3; } - else { return (int)(2 * m_bot->Observation()->GetAbilityData()[m_bot->Data(*this).buildAbility].footprint_radius); } + else { + if (m_bot != nullptr) + { + return (int)(2 * m_client->Observation()->GetAbilityData()[m_bot->Data(*this).buildAbility].footprint_radius); + } + else if (m_observer != nullptr) + { + return (int)(2 * m_client->Observation()->GetAbilityData()[m_observer->Data(*this).buildAbility].footprint_radius); + } + else + { + return -1; + } + } #else return m_type.tileWidth(); #endif @@ -231,16 +267,42 @@ int UnitType::tileHeight() const #ifdef SC2API if (isMineral()) { return 1; } if (isGeyser()) { return 3; } - else { return (int)(2 * m_bot->Observation()->GetAbilityData()[m_bot->Data(*this).buildAbility].footprint_radius); } + else { + if (m_bot != nullptr) + { + return (int)(2 * m_client->Observation()->GetAbilityData()[m_bot->Data(*this).buildAbility].footprint_radius); + } + else if (m_observer != nullptr) + { + return (int)(2 * m_client->Observation()->GetAbilityData()[m_observer->Data(*this).buildAbility].footprint_radius); + } + else + { + return -1; + } + } #else return m_type.tileHeight(); #endif + } bool UnitType::isAddon() const { #ifdef SC2API - return m_bot->Data(*this).isAddon; + if (m_bot != nullptr) + { + return m_bot->Data(*this).isAddon; + } + else if (m_observer != nullptr) + { + return m_observer->Data(*this).isAddon; + } + else + { + return false; + } + #else return m_type.isAddon(); #endif @@ -249,7 +311,19 @@ bool UnitType::isAddon() const bool UnitType::isBuilding() const { #ifdef SC2API - return m_bot->Data(*this).isBuilding; + if (m_bot != nullptr) + { + return m_bot->Data(*this).isBuilding; + } + else if (m_observer != nullptr) + { + return m_observer->Data(*this).isBuilding; + } + else + { + return false; + } + #else return m_type.isBuilding(); #endif @@ -258,7 +332,7 @@ bool UnitType::isBuilding() const int UnitType::supplyProvided() const { #ifdef SC2API - return (int)m_bot->Observation()->GetUnitTypeData()[m_type].food_provided; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].food_provided; #else return m_type.supplyProvided(); #endif @@ -267,7 +341,7 @@ int UnitType::supplyProvided() const int UnitType::supplyRequired() const { #ifdef SC2API - return (int)m_bot->Observation()->GetUnitTypeData()[m_type].food_required; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].food_required; #else return m_type.supplyRequired(); #endif @@ -276,7 +350,7 @@ int UnitType::supplyRequired() const int UnitType::mineralPrice() const { #ifdef SC2API - return (int)m_bot->Observation()->GetUnitTypeData()[m_type].mineral_cost; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].mineral_cost; #else return m_type.mineralPrice(); #endif @@ -285,7 +359,7 @@ int UnitType::mineralPrice() const int UnitType::gasPrice() const { #ifdef SC2API - return (int)m_bot->Observation()->GetUnitTypeData()[m_type].vespene_cost; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].vespene_cost; #else return m_type.gasPrice(); #endif @@ -377,30 +451,30 @@ bool UnitType::isMorphedBuilding() const int UnitType::getMovementSpeed() const { - return m_bot->Observation()->GetUnitTypeData()[m_type].movement_speed; + return m_client->Observation()->GetUnitTypeData()[m_type].movement_speed; } int UnitType::getSightRange() const { - return m_bot->Observation()->GetUnitTypeData()[m_type].sight_range; + return m_client->Observation()->GetUnitTypeData()[m_type].sight_range; } UnitTypeID UnitType::getRequiredStructure() const { - return m_bot->Observation()->GetUnitTypeData()[m_type].tech_requirement; + return m_client->Observation()->GetUnitTypeData()[m_type].tech_requirement; } std::vector<sc2::UnitTypeID> UnitType::getEquivalentUnits() const { - return m_bot->Observation()->GetUnitTypeData()[m_type].tech_alias; + return m_client->Observation()->GetUnitTypeData()[m_type].tech_alias; } bool UnitType::requiredAttached() const { - return m_bot->Observation()->GetUnitTypeData()[m_type].require_attached; + return m_client->Observation()->GetUnitTypeData()[m_type].require_attached; } float UnitType::getBuildTime() const { - return m_bot->Observation()->GetUnitTypeData()[m_type].build_time; + return m_client->Observation()->GetUnitTypeData()[m_type].build_time; } \ No newline at end of file diff --git a/src/UnitType.h b/src/UnitType.h index 7f3bbbe530ffc6859f7ceb8cff1c691af42afb31..1491bb11d335f2b9ed01dd7fcf60b01b8dc9eea6 100644 --- a/src/UnitType.h +++ b/src/UnitType.h @@ -4,17 +4,24 @@ class IDABot; +class IDAReplayObserver; class UnitType { - mutable IDABot * m_bot; + mutable sc2::Client * m_client; + mutable IDABot * m_bot; + mutable IDAReplayObserver * m_observer; + sc2::UnitTypeID m_type; public: UnitType(); - UnitType(const sc2::UnitTypeID & type, IDABot & bot); + UnitType(const sc2::UnitTypeID & type, sc2::Client & client); + UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDABot & m_bot); + UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDAReplayObserver & observer); + sc2::UnitTypeID getAPIUnitType() const; bool is(const sc2::UnitTypeID & type) const;