diff --git a/README.md b/README.md
index fdbead22..db14f73d 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,6 @@ CPlayerPed
 CPopulation
 CRadar
 CRecordDataForChase
-CRemote
 CRoadBlocks
 CRubbish
 CSceneEdit
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index cd657815..fe727f72 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -2541,7 +2541,7 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
 		pVehicle->AutoPilot.m_aPathFindNodesInfo, &pVehicle->AutoPilot.m_nPathFindNodesCount);
 	if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2){
 		pVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0;
-		return 1;
+		return true;
 	}
 	pVehicle->AutoPilot.m_nPrevRouteNode = 0;
 	pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_aPathFindNodesInfo[0] - ThePaths.m_pathNodes;
@@ -2550,7 +2550,7 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
 	pVehicle->AutoPilot.RemoveOnePathNode();
 	FindLinksToGoWithTheseNodes(pVehicle);
 	pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0;
-	return 0;
+	return false;
 }
 
 void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
diff --git a/src/control/Remote.cpp b/src/control/Remote.cpp
index 32ee4eda..e3891502 100644
--- a/src/control/Remote.cpp
+++ b/src/control/Remote.cpp
@@ -1,6 +1,56 @@
 #include "common.h"
 #include "patcher.h"
+#include "Automobile.h"
+#include "CarCtrl.h"
+#include "Camera.h"
 #include "Remote.h"
+#include "Timer.h"
+#include "World.h"
+#include "PlayerInfo.h"
+#include "Vehicle.h"
 
-WRAPPER void CRemote::GivePlayerRemoteControlledCar(float, float, float, float, uint16) { EAXJMP(0x435C30); }
-WRAPPER void CRemote::TakeRemoteControlledCarFromPlayer(void) { EAXJMP(0x435DA0); }
+void
+CRemote::GivePlayerRemoteControlledCar(float x, float y, float z, float rot, uint16 model)
+{
+	CAutomobile *car = new CAutomobile(model, MISSION_VEHICLE);
+	bool found;
+
+	z = car->GetDistanceFromCentreOfMassToBaseOfModel() + CWorld::FindGroundZFor3DCoord(x, y, z + 2.0f, &found);
+
+	car->GetMatrix().SetRotateZOnly(rot);
+	car->GetPosition() = CVector(x, y, z);
+	car->m_status = STATUS_PLAYER_REMOTE;
+	car->bIsLocked = true;
+
+	CCarCtrl::JoinCarWithRoadSystem(car);
+	car->AutoPilot.m_nCarMission = MISSION_NONE;
+	car->AutoPilot.m_nTempAction = TEMPACT_NONE;
+	car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
+	car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f;
+	car->AutoPilot.m_nNextLane = car->AutoPilot.m_nCurrentLane = 0;
+	car->bEngineOn = true;
+	CWorld::Add(car);
+	if (FindPlayerVehicle() != nil) 
+		FindPlayerVehicle()->m_status = STATUS_PLAYER_DISABLED;
+
+	CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = car;
+	CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->RegisterReference((CEntity**)&CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle);
+	TheCamera.TakeControl(car, CCam::MODE_BEHINDCAR, INTERPOLATION, CAM_CONTROLLER_1);
+}
+
+void
+CRemote::TakeRemoteControlledCarFromPlayer(void)
+{
+	CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->VehicleCreatedBy = RANDOM_VEHICLE;
+	CCarCtrl::NumMissionCars--;
+	CCarCtrl::NumRandomCars++;
+	CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bIsLocked = false;
+	CWorld::Players[CWorld::PlayerInFocus].m_nTimeLostRemoteCar = CTimer::GetTimeInMilliseconds();
+	CWorld::Players[CWorld::PlayerInFocus].m_bInRemoteMode = true;
+	CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bRemoveFromWorld = true;
+}
+
+STARTPATCHES
+	InjectHook(0x435C30, &CRemote::GivePlayerRemoteControlledCar, PATCH_JUMP);
+	InjectHook(0x435DA0, &CRemote::TakeRemoteControlledCarFromPlayer, PATCH_JUMP);
+ENDPATCHES
\ No newline at end of file
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 50a1f726..2b3fdbc0 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -3081,7 +3081,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		// ScriptParams[0] is unused.
-		TheCamera.TakeControl(nil, ScriptParams[1], ScriptParams[2], 1);
+		TheCamera.TakeControl(nil, ScriptParams[1], ScriptParams[2], CAM_CONTROLLER_1);
 		return 0;
 	}
 	case COMMAND_POINT_CAMERA_AT_CAR:
@@ -3089,7 +3089,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CollectParameters(&m_nIp, 3);
 		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(pVehicle);
-		TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], 1);
+		TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAM_CONTROLLER_1);
 		return 0;
 	}
 	case COMMAND_POINT_CAMERA_AT_CHAR:
@@ -3097,7 +3097,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CollectParameters(&m_nIp, 3);
 		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
 		assert(pPed);
-		TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], 1);
+		TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAM_CONTROLLER_1);
 		return 0;
 	}
 	case COMMAND_RESTORE_CAMERA:
@@ -3148,7 +3148,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CVector pos = *(CVector*)&ScriptParams[0];
 		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
-		TheCamera.TakeControlNoEntity(pos, ScriptParams[3], 1);
+		TheCamera.TakeControlNoEntity(pos, ScriptParams[3], CAM_CONTROLLER_1);
 		return 0;
 	}
 	case COMMAND_ADD_BLIP_FOR_CAR_OLD:
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp
index 86b22ec5..a2d7b94a 100644
--- a/src/core/AnimViewer.cpp
+++ b/src/core/AnimViewer.cpp
@@ -289,7 +289,7 @@ CAnimViewer::Update(void)
 			}
 			newEntity->GetPosition() = CVector(0.0f, 0.0f, 0.0f);
 			CWorld::Add(newEntity);
-			TheCamera.TakeControl(pTarget, 9, 2, 1);
+			TheCamera.TakeControl(pTarget, CCam::MODE_MODELVIEW, JUMP_CUT, CAM_CONTROLLER_1);
 		}
 		if (pTarget->m_type == ENTITY_TYPE_VEHICLE || pTarget->m_type == ENTITY_TYPE_PED || pTarget->m_type == ENTITY_TYPE_OBJECT) {
 			((CPhysical*)pTarget)->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
diff --git a/src/core/Camera.h b/src/core/Camera.h
index 8f0e62d4..99028de6 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -239,6 +239,20 @@ enum
 	MBLUR_UNUSED,		// pinkish
 };
 
+enum
+{
+	NONE = 0,
+	INTERPOLATION,
+	JUMP_CUT
+};
+
+enum
+{
+	CAM_CONTROLLER_0,
+	CAM_CONTROLLER_1,
+	CAM_CONTROLLER_2
+};
+
 struct CCamera : public CPlaceable
 {
 	bool m_bAboveGroundTrainNodesLoaded;
diff --git a/src/core/CutsceneMgr.cpp b/src/core/CutsceneMgr.cpp
index 2fbc5186..3df81b2b 100644
--- a/src/core/CutsceneMgr.cpp
+++ b/src/core/CutsceneMgr.cpp
@@ -256,7 +256,7 @@ void
 CCutsceneMgr::SetupCutsceneToStart(void)
 {
 	TheCamera.SetCamCutSceneOffSet(ms_cutsceneOffset);
-	TheCamera.TakeControlWithSpline(2);
+	TheCamera.TakeControlWithSpline(JUMP_CUT);
 	TheCamera.SetWideScreenOn();
 
 	ms_cutsceneOffset.z++;