diff --git a/.gitignore b/.gitignore
index 567609b1234a9b8806c5a05da6c866e480aa148d..0023a727e767c45c3521dc3f0e2ed635bb81f1ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
 build/
+.idea
+venv
+.vs
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index af8acc8fe3a1bb8d928457d258d895e3aef51331..49f5cb9f08e4a01e87d1a91540b18293a1a90d41 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -19,4 +19,3 @@ pages:
       - public
   only:
     - master
-    - Doc
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/idareplayobserver.rst b/docs/idareplayobserver.rst
index c9a3b93085422fc7e1fc6656824e3c8a5701df6e..8d34f274cccc955fb370770ea0ef63b9ff8e2154 100644
--- a/docs/idareplayobserver.rst
+++ b/docs/idareplayobserver.rst
@@ -9,7 +9,7 @@ IDAReplayObserver
 
    .. method:: IDAReplayObserver.on_game_start(self)
 
-      This method is called when a replay has stared, when you inherit it you have to
+      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`).
 
@@ -25,6 +25,14 @@ IDAReplayObserver
       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.
+
+   .. 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]
diff --git a/docs/replays.rst b/docs/replays.rst
index be0b533bb32ec860c1d825713010534d76f834f6..0ca0179f6011a90ef1c6b52b4e86baa30f73e20d 100644
--- a/docs/replays.rst
+++ b/docs/replays.rst
@@ -68,7 +68,7 @@ if the information you want could be collected with SC2Reader.
 
 ReplayObserver
 --------------
-This is the second technique it is much like using a bot but whit the difference
+This is the second technique it is much like using a bot but with the difference
 that no action can be preform just observations.
 
 
diff --git a/python-api-src/lib_replay_unit.cpp b/python-api-src/lib_replay_unit.cpp
index 7a70770dffa7c1738104f451276f1b6f9aaaf3bb..63197f20a344ae22df680e8ffee70d7396aeba29 100644
--- a/python-api-src/lib_replay_unit.cpp
+++ b/python-api-src/lib_replay_unit.cpp
@@ -28,9 +28,8 @@ void define_replay_unit(py::module & m)
 		.def_property_readonly("is_valid", &ReplayUnit::isValid)
 		.def_property_readonly("is_training", &ReplayUnit::isTraining)
 		.def_property_readonly("is_blip", &ReplayUnit::isBlip)
-		// Has target and target crashes if the target died in the same frame
-		//.def_property_readonly("target", &ReplayUnit::getTarget)
-		//.def_property_readonly("has_target", &ReplayUnit::hasTarget)
+		.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")
diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp
index 0206f191b3998d9a31e31c8924e9bd72fe9623c1..023e554c8cb770a4629c15787693b08d5a6f40a9 100644
--- a/python-api-src/library.cpp
+++ b/python-api-src/library.cpp
@@ -136,8 +136,20 @@ PYBIND11_MODULE(library, m)
 		.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)
 		;
 
+	
+
+	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 89118af074c70399f6cb23c63fe5689775567451..3f9114d0685218dec0f51e838031976f622c5709 100644
--- a/python-api-src/library.h
+++ b/python-api-src/library.h
@@ -95,6 +95,27 @@ public:
 
 		);
 	}
+	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 
diff --git a/src/IDAReplayObserver.cpp b/src/IDAReplayObserver.cpp
index 491818b304e4f7a34990d04f5047504fcd13db20..0af4993668ed4d0af267e7949f6f82c06a78bd1c 100644
--- a/src/IDAReplayObserver.cpp
+++ b/src/IDAReplayObserver.cpp
@@ -1,12 +1,17 @@
 #include "IDAReplayObserver.h"
 #include "Util.h"
+#include <pybind11/pybind11.h>
+
 
 void IDAReplayObserver::setUnits()
 {
 	m_allUnits.clear();
+	m_allUnitsID.clear();
 	for (auto & unit : Observation()->GetUnits())
 	{
-		m_allUnits.push_back(ReplayUnit(unit, *this));
+		ReplayUnit replayUnit = ReplayUnit(unit, *this);
+		m_allUnits.push_back(replayUnit);
+		m_allUnitsID.insert(replayUnit.getID());
 	}
 }
 
@@ -32,18 +37,44 @@ void IDAReplayObserver::OnGameEnd()
 void IDAReplayObserver::OnUnitDestroyed(const sc2::Unit* unit)
 {
 	ReplayUnit unitInformation = ReplayUnit(unit, *this);
-	OnUnitInfomationDestroyed(&unitInformation);
+	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::OnUnitInfomationDestroyed(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);
+{	
+	
+		return ReplayUnit(Observation()->GetUnit(tag), *(IDAReplayObserver *)this);
+
+}
+
+bool IDAReplayObserver::UnitExists(const CCUnitID tag) const
+{
+	return m_allUnitsID.find(tag) != m_allUnitsID.end();
+	
 }
 
 
@@ -57,19 +88,19 @@ const std::vector<ReplayUnit>& IDAReplayObserver::GetAllUnits() const
 	return m_allUnits;
 }
 
-CCRace IDAReplayObserver::GetPlayerRace(int player) const
+CCRace IDAReplayObserver::GetPlayerRace(int player)
+{	
+	return ReplayControl()->GetReplayInfo().players[player].race;
+}
+
+std::string IDAReplayObserver::GetReplayPath()
 {
-	auto playerID = Observation()->GetPlayerID();
-	for (auto & playerInfo : Observation()->GetGameInfo().player_info)
-	{
-		if (playerInfo.player_id == playerID)
-		{
-			return playerInfo.race_actual;
-		}
-	}
+	return ReplayControl()->GetReplayInfo().replay_path;
+}
 
-	BOT_ASSERT(false, "Failed to find the player's race!");
-	return sc2::Race::Random;
+sc2::GameResult IDAReplayObserver::GetResultForPlayer(int player)
+{
+	return ReplayControl()->GetReplayInfo().players[player].game_result;
 }
 
 
diff --git a/src/IDAReplayObserver.h b/src/IDAReplayObserver.h
index d340fb1affc2a83a1544fafe31b64e297377c5d1..83bba966a4ec21cb79b4c75a92731e3c31f019bc 100644
--- a/src/IDAReplayObserver.h
+++ b/src/IDAReplayObserver.h
@@ -12,6 +12,7 @@ class IDAReplayObserver : public sc2::ReplayObserver
 {
 	void setUnits();
 	std::vector<ReplayUnit>       m_allUnits;
+	std::set<CCUnitID>         m_allUnitsID;
 
 public:
 	IDAReplayObserver();
@@ -20,12 +21,18 @@ public:
 	void OnStep() override;
 	void OnGameEnd() override;
 	void OnUnitDestroyed(const sc2::Unit*) override;
-	void OnUnitInfomationDestroyed(const ReplayUnit*);
+	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) const;
+	CCRace GetPlayerRace(int player);
+	std::string GetReplayPath();
+	sc2::GameResult GetResultForPlayer(int player);
 
 };
 
diff --git a/src/ReplayUnit.cpp b/src/ReplayUnit.cpp
index 1bab9381607394099b2d292bc4c6281db9da854f..5b6298054ac1b692f2a505336980b4f0d00146c1 100644
--- a/src/ReplayUnit.cpp
+++ b/src/ReplayUnit.cpp
@@ -22,23 +22,16 @@ ReplayUnit::ReplayUnit(const sc2::Unit * unit, IDAReplayObserver & replayObserve
 bool ReplayUnit::hasTarget() const
 {
 	BOT_ASSERT(isValid(), "Unit is not valid");
-	std::cout << "HAS TARGET" << std::endl;
 	if (getUnitPtr()->orders.size() > 0) {
 		if (getUnitPtr()->orders[0].target_unit_tag != NULL) {
 			CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
-			//The tag is for somereason a null tag
-			if (t_id == sc2::NullTag) {
-				return false;
+			// 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();
 			}
-			std::cout << "1MID HAS TARGET" << std::endl;
-			std::cout << "2MID HAS TARGET" << std::endl;
-			std::cout << "valid" << m_replayObserver->GetUnit(t_id).getType() << std::endl;
-			std::cout << "AFTER" << std::endl;
-			// IDABot finds the unit with this tag, and returns true if valid
-			return m_replayObserver->GetUnit(t_id).isValid();
 		}
 	}
-	std::cout << "END HAS TARGET" << std::endl;
 
 	return false;
 }
@@ -52,18 +45,12 @@ ReplayUnit ReplayUnit::getTarget() const
 	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;
-		//The tag is for somereason a null tag
-		if (t_id == sc2::NullTag) {
-			
-			std::cout << "nullTAG" << std::endl;
-			std::cout << "type " << sc2::UnitTypeToName(m_unit->unit_type) <<"pos " << getPosition().x << " x y "<< getPosition().y << ", id " << getID() << "player " << getPlayer() << std::endl;
-			std::cout << getUnitPtr()->orders.size() << std::endl;
-			return *this;
+		// 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);
 		}
-		// IDAReplayObserver finds the unit with this tag
-		return m_replayObserver->GetUnit(t_id);
 	}
-
 	ReplayUnit this_unit = ReplayUnit(m_unit, *m_replayObserver);
 	return this_unit;
 }