diff --git a/create-visual-studio-solution-python37.sh b/create-visual-studio-solution-python37.sh
new file mode 100644
index 0000000000000000000000000000000000000000..828e5cb115dc98eedaca8ad5cd192d18f12c5382
--- /dev/null
+++ b/create-visual-studio-solution-python37.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+mkdir build37
+cd build37
+"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python37/python.exe"
diff --git a/create-visual-studio-solution-python38.sh b/create-visual-studio-solution-python38.sh
new file mode 100644
index 0000000000000000000000000000000000000000..081c3e887218f6621b141865c47dc7dc70aabcdf
--- /dev/null
+++ b/create-visual-studio-solution-python38.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+mkdir build38
+cd build38
+"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python38/python.exe"
+
diff --git a/create-visual-studio-solution.sh b/create-visual-studio-solution.sh
deleted file mode 100644
index 713b010d401540aaa236db87f8f054f3417cb060..0000000000000000000000000000000000000000
--- a/create-visual-studio-solution.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-mkdir build
-cd build
-"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64"
diff --git a/docs/idabot.rst b/docs/idabot.rst
index 31864ba8000e44e0002e2c8bcaef839057a34066..2a3b0c0d2f9c1339bb38c7ea32f358afc5f71ae9 100644
--- a/docs/idabot.rst
+++ b/docs/idabot.rst
@@ -55,6 +55,10 @@ IDABot
 
       Returns the players race, useful if you play Race.Random
 
+   .. method:: IDABot.send_chat(self, message)
+
+      Sends the string 'message' to the game chat
+
    Attributes:
 
    .. autoattribute:: minerals
diff --git a/docs/unit.rst b/docs/unit.rst
index 88e0f527e1a9467e276dd1f72dff9f5027a73711..d298b02253208bd1905dfdd18e0aabf3010d812f 100644
--- a/docs/unit.rst
+++ b/docs/unit.rst
@@ -48,7 +48,6 @@ Unit
 
       Returns build_progress >= 1
 
-   .. autoattribute:: is_constructing 
    .. autoattribute:: is_flying 
    .. autoattribute:: is_idle 
    .. autoattribute:: is_powered 
@@ -74,6 +73,9 @@ Unit
    .. autoattribute:: tile_position 
    .. autoattribute:: unit_type 
    .. autoattribute:: weapon_cooldown 
+   .. autoattribute:: is_carrying_minerals
+   
+      Returns if this unit is currently holding minerals
 
    .. attribute:: Unit.target
 
@@ -85,6 +87,10 @@ Unit
 
       Call an ability directly, different abilities has different targets. Some target the unit itself (no argument), target a point (Point2D as argument) and some target a Unit (instance of Unit as argument).
 
+   .. method:: Unit.is_constructing(self, unit_type: library.UnitType)
+
+      Returns true if the unit is currently constructing another unit of type `unit_type`. Note that `unit_type` needs to be an instance of :class:`library.UnitType`.
+
    .. automethod:: stop
    .. automethod:: attack_unit
    .. automethod:: attack_move
diff --git a/python-api-src/lib_sc2_typeenums.cpp b/python-api-src/lib_sc2_typeenums.cpp
index 03ae7992ff11558485830f52ebb7d2aa7c934059..235056ce29cc1711fc5297aa93dd85ab90013fc3 100644
--- a/python-api-src/lib_sc2_typeenums.cpp
+++ b/python-api-src/lib_sc2_typeenums.cpp
@@ -217,7 +217,8 @@ void define_typeenums(py::module & m)
         .value("NEUTRAL_UNBUILDABLEPLATESDESTRUCTIBLE", sc2::UNIT_TYPEID::NEUTRAL_UNBUILDABLEPLATESDESTRUCTIBLE)
         .value("NEUTRAL_UTILITYBOT", sc2::UNIT_TYPEID::NEUTRAL_UTILITYBOT)
         .value("NEUTRAL_VESPENEGEYSER", sc2::UNIT_TYPEID::NEUTRAL_VESPENEGEYSER)
-        .value("NEUTRAL_XELNAGATOWER", sc2::UNIT_TYPEID::NEUTRAL_XELNAGATOWER);
+        .value("NEUTRAL_XELNAGATOWER", sc2::UNIT_TYPEID::NEUTRAL_XELNAGATOWER)
+        .def("__eq__", [](const sc2::UNIT_TYPEID &value, sc2::UnitTypeID &value2) { return value == value2; });
 
     py::enum_<sc2::ABILITY_ID>(m, "ABILITY_ID")
         .value("INVALID", sc2::ABILITY_ID::INVALID)
diff --git a/python-api-src/lib_tech_tree.cpp b/python-api-src/lib_tech_tree.cpp
index ff9b2d54fd36ce2adbb9a9be065fedb4a0242db0..69b4e27752e05c58c45a5f81dc7d7ed22977a7c5 100644
--- a/python-api-src/lib_tech_tree.cpp
+++ b/python-api-src/lib_tech_tree.cpp
@@ -9,7 +9,7 @@ void define_tech_tree(py::module & m)
         .def_readonly("mineral_cost",         &TypeData::mineralCost,                  "mineral cost of the item")
         .def_readonly("gas_cost",             &TypeData::gasCost,                      "gas cost of the item")
         .def_readonly("supply_cost",          &TypeData::supplyCost,                   "supply cost of the item")
-        .def_readonly("build_time",           &TypeData::buildTime,                    "build time of the item")
+        .def_readonly("build_time",           &TypeData::buildTime,                    "build time of the item in seconds (should be 32 game updates per tick, can someone verify this?)")
         .def_readonly("is_unit",              &TypeData::isUnit)
         .def_readonly("is_building",          &TypeData::isBuilding)
         .def_readonly("is_worker",            &TypeData::isWorker)
@@ -27,4 +27,4 @@ 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_));
-}
\ No newline at end of file
+}
diff --git a/python-api-src/lib_unit.cpp b/python-api-src/lib_unit.cpp
index cb99e65615ae22a661ef9a954f2640f316e1dbb5..83b3166272f4303cabb444eec4da2b6bda75d084 100644
--- a/python-api-src/lib_unit.cpp
+++ b/python-api-src/lib_unit.cpp
@@ -34,6 +34,7 @@ void define_unit(py::module & m)
         .def_property_readonly("current_ability_id", &Unit::getCurrentAbilityID, "The AbilityID of currently used ability")
         .def_property_readonly("facing", &Unit::getFacing)
         .def_property_readonly("radius", &Unit::getRadius)
+        .def_property_readonly("is_carrying_minerals", &Unit::isCarryingMinerals)
         .def("hold_position", &Unit::holdPosition)
         .def("patrol", py::overload_cast<const CCPosition &>(&Unit::patrol, py::const_))
         .def("stop_dance", &Unit::stopDance)
diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp
index 78e0330481d1cd51be6f418aa221143ef4614a03..b1818c27be7737444af08bed9406b16407132574 100644
--- a/python-api-src/library.cpp
+++ b/python-api-src/library.cpp
@@ -47,22 +47,17 @@ PYBIND11_MODULE(library, m)
     m.attr("PLAYER_NEUTRAL") = py::int_((int) Players::Neutral);
     m.attr("PLAYER_ALLY")    = py::int_((int) Players::Ally);
 
-    /*
-    TODO: BuffID is not defined, defined as following by Blizzard:
-    typedef SC2Type<BUFF_ID>      BuffID;
-    */
     py::class_<sc2::BuffID>(m, "BuffID")
         .def(py::init<sc2::BUFF_ID>());
 
     py::implicitly_convertible<sc2::BUFF_ID, sc2::BuffID>();
 
-
     py::class_<sc2::UnitTypeID>(m, "UnitTypeID")
-        .def(py::init<sc2::UNIT_TYPEID>());
+        .def(py::init<sc2::UNIT_TYPEID>())
+        .def("__eq__", [](const sc2::UnitTypeID &value, sc2::UNIT_TYPEID &value2) { return value == value2; });
 
     py::implicitly_convertible<sc2::UNIT_TYPEID, sc2::UnitTypeID>();
 
-
     py::class_<sc2::UpgradeID>(m, "UpgradeID")
         .def(py::init<sc2::UPGRADE_ID>());
 
@@ -82,6 +77,7 @@ PYBIND11_MODULE(library, m)
         .def(py::init())
         .def("on_game_start", &IDABot::OnGameStart)
         .def("on_step", &IDABot::OnStep)
+        .def("send_chat", &IDABot::SendChat, "Send a message to the game chat", "message"_a)
         .def("get_all_units", &IDABot::GetAllUnits, "Returns a list of all units")
         .def("get_my_units", &IDABot::GetMyUnits, "Returns a list of all units beloning to the player")
         .def("get_player_race", &IDABot::GetPlayerRace)
diff --git a/src/IDABot.cpp b/src/IDABot.cpp
index c12fe5ab76ceddd8b69575208806c514718c3265..d0908f789cb42ab5675a0028889085a4918d79bd 100644
--- a/src/IDABot.cpp
+++ b/src/IDABot.cpp
@@ -199,6 +199,12 @@ BuildingPlacer & IDABot::GetBuildingPlacer()
     return m_buildingPlacer;
 }
 
+
+void IDABot::SendChat(const std::string & message)
+{
+    Actions()->SendChat(message);
+}
+
 const TypeData & IDABot::Data(const UnitType & type) const
 {
 	return m_techTree.getData(type);
diff --git a/src/IDABot.h b/src/IDABot.h
index eca954f01a1857bf31747ae128a239b86dc19e88..a1567ac9f75b75b6d5268cb3c4f3e372e8eac23e 100644
--- a/src/IDABot.h
+++ b/src/IDABot.h
@@ -46,6 +46,8 @@ public:
     CCPosition GetStartLocation() const;
     BuildingPlacer & GetBuildingPlacer();
 
+    void SendChat(const std::string & message);
+
     int GetCurrentFrame() const;
     int GetMinerals() const;
     int GetCurrentSupply() const;
diff --git a/src/TechTree.cpp b/src/TechTree.cpp
index fdd3f3f5c8b8ae23c9b374ef6b2ae742ba9597f6..89d511f7a0d7a0fb8fc752c0c009474cab4d50a8 100644
--- a/src/TechTree.cpp
+++ b/src/TechTree.cpp
@@ -48,6 +48,7 @@ void TechTree::onStart()
             data.requiredUnits.clear();
             data.requiredUpgrades.clear();
             updated.insert(description.result_type);
+            data.buildTime = description.buildTime; // The time in seconds it takes to create the unit
 
             data.buildAbility = sc2::ABILITY_ID::INVALID;
         }
@@ -382,4 +383,4 @@ const TypeData & TechTree::getData(const MetaType & type) const
     BOT_ASSERT(false, "Can't getData this type: %s", type.getName().c_str());
 
     return m_unitTypeData.begin()->second;
-}
\ No newline at end of file
+}
diff --git a/src/TechTreeImproved.cpp b/src/TechTreeImproved.cpp
index 8b07889aeb8510c3a9eb1a4b6289bf674e521540..7e991fadd4877762531bf4d545a0ad0d870fb8ad 100644
--- a/src/TechTreeImproved.cpp
+++ b/src/TechTreeImproved.cpp
@@ -116,6 +116,7 @@ void parse_build_description(BuildDescription & description, json & build_item)
 {
     description.result_type = static_cast<sc2::UNIT_TYPEID>(build_item["unit"]);
     description.build_ability = static_cast<sc2::ABILITY_ID>(build_item["ability"]);
+    description.buildTime = static_cast<int>(build_item["time"]); // The time in seconds it takes to create the unit parsed from the json file
 
     if (build_item.find("requires") != build_item.end())
     {
diff --git a/src/TechTreeImproved.h b/src/TechTreeImproved.h
index 0948a328c5e9a9216b7a8ff7e3f85eba5ba70dd3..1b650e60d8a4f742f2fcce6803e9a8583863058b 100644
--- a/src/TechTreeImproved.h
+++ b/src/TechTreeImproved.h
@@ -18,6 +18,7 @@ struct BuildDescription
     std::vector<sc2::UNIT_TYPEID> buildings_needed;
     std::vector<sc2::UNIT_TYPEID> addons_needed;
     std::vector<sc2::UPGRADE_ID> upgrades_needed;
+    int buildTime; // The time in seconds it takes to create the unit
 };
 
 struct ResearchDescription
@@ -52,4 +53,4 @@ public:
 
     const std::vector<BuildDescription> & BuildDescriptions() const { return build_descriptions; }
     const std::vector<ResearchDescription> & ResearchDescriptions() const { return research_descriptions; }
-};
\ No newline at end of file
+};
diff --git a/src/Unit.cpp b/src/Unit.cpp
index 0bb94a9784e987fff2898534f944bc8018e7b816..9cc165a2b2a1c72aec083346c0a0235f3fc513da 100644
--- a/src/Unit.cpp
+++ b/src/Unit.cpp
@@ -328,7 +328,6 @@ void Unit::ability(sc2::AbilityID ability, const Unit& target) const
 Unit Unit::getTarget() const
 {
     BOT_ASSERT(isValid(), "Unit is not valid");
-    BOT_ASSERT(hasTarget(), "Unit has no target");
 
     // if unit has order, check tag of target of first order
     if(getUnitPtr()->orders.size() > 0){
@@ -426,3 +425,17 @@ void Unit::stopDance() const
 	BOT_ASSERT(isValid(), "Unit is not valid");
 	m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP_DANCE);
 }
+
+bool Unit::isCarryingMinerals() const
+{
+    BOT_ASSERT(isValid(), "Unit is not valid");
+    std::vector<CCBuff> buffs = m_unit->buffs;
+    for (auto & b : buffs)
+    {
+        if (b.to_string() == "271" or b.to_string() == "272")
+        {
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/src/Unit.h b/src/Unit.h
index 3d5017726eb16b1b6ccc9ede69c6e1b9cc30571d..5a7cef49664e37ee60a197e26a12cbf8065f9854 100644
--- a/src/Unit.h
+++ b/src/Unit.h
@@ -47,6 +47,7 @@ public:
     bool isValid() const;
     bool isTraining() const;
     bool isConstructing(const UnitType & type) const;
+    bool isCarryingMinerals() const;
 
     bool isBlip() const;
     bool hasTarget() const;
diff --git a/tests/unittypeid.py b/tests/unittypeid.py
new file mode 100644
index 0000000000000000000000000000000000000000..f3815d9002078987949f31beac2dec8cb93123b3
--- /dev/null
+++ b/tests/unittypeid.py
@@ -0,0 +1,25 @@
+import unittest
+import sys
+
+sys.path.append('build/python-api-src')
+
+from library import UnitTypeID, UNIT_TYPEID
+
+
+class TestUnitType(unittest.TestCase):
+
+    def test_equality(self):
+        self.assertTrue(UNIT_TYPEID.TERRAN_ARMORY == UNIT_TYPEID.TERRAN_ARMORY)
+    
+    def test_inequality(self):
+        self.assertFalse(UNIT_TYPEID.TERRAN_ARMORY != UNIT_TYPEID.TERRAN_ARMORY)
+
+    def test_convert_equality(self):
+        unit_typeid = UNIT_TYPEID.TERRAN_ARMORY
+        self.assertTrue(unit_typeid == UnitTypeID(unit_typeid))
+        self.assertTrue(UnitTypeID(unit_typeid) == unit_typeid)
+        self.assertFalse(UnitTypeID(unit_typeid) != unit_typeid)
+
+if __name__ == '__main__':
+    unittest.main()
+