diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 2de30a0a..1ab09d52 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -36,6 +36,8 @@ int16 CPickups::NumMessages;
 int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];
 int16 CPickups::CollectedPickUpIndex;
 
+int32 CPickups::PlayerOnWeaponPickup;
+
 // unused
 bool CPickups::bPickUpcamActivated;
 CVehicle *CPickups::pPlayerVehicle;
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index 0a73696a..423f864b 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -70,6 +70,8 @@ class CPickups
 	static int16 NumMessages;
 	static tPickupMessage aMessages[NUMPICKUPMESSAGES];
 public:
+	static int32 PlayerOnWeaponPickup;
+
 	static void Init();
 	static void Update();
 	static void RenderPickUpText();
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
index fd45a374..954e8282 100644
--- a/src/core/Cam.cpp
+++ b/src/core/Cam.cpp
@@ -26,10 +26,14 @@
 #include "Camera.h"
 #include "DMAudio.h"
 #include "Bike.h"
+#include "Pickups.h"
 
 bool PrintDebugCode = false;
 int16 DebugCamMode;
 
+extern float fRangePlayerRadius;
+extern float fCloseNearClipLimit;
+
 #ifdef FREE_CAM
 bool CCamera::bFreeCam;
 int nPreviousMode = -1;
@@ -41,11 +45,11 @@ CCam::Init(void)
 	Mode = MODE_FOLLOWPED;
 	Front = CVector(0.0f, 0.0f, -1.0f);
 	Up = CVector(0.0f, 0.0f, 1.0f);
-	Rotating = 0;
+	Rotating = false;
 	m_iDoCollisionChecksOnFrameNum = 1;
 	m_iDoCollisionCheckEveryNumOfFrames = 9;
 	m_iFrameNumWereAt = 0;
-	m_bCollisionChecksOn = 1;
+	m_bCollisionChecksOn = false;
 	m_fRealGroundDist = 0.0f;
 	BetaSpeed = 0.0f;
 	AlphaSpeed = 0.0f;
@@ -53,21 +57,23 @@ CCam::Init(void)
 	f_max_role_angle = DEGTORAD(5.0f);
 	Distance = 30.0f;
 	DistanceSpeed = 0.0f;
-	m_pLastCarEntered = 0;
-	m_pLastPedLookedAt = 0;
-	ResetStatics = 1;
+	m_pLastCarEntered = nil;
+	m_pLastPedLookedAt = nil;
+	ResetStatics = true;
 	Beta = 0.0f;
-	m_bFixingBeta = 0;
+	m_fTilt = 0.0f;
+	m_fTiltSpeed = 0.0f;
+	m_bFixingBeta = false;
 	CA_MIN_DISTANCE = 0.0f;
 	CA_MAX_DISTANCE = 0.0f;
-	LookingBehind = 0;
-	LookingLeft = 0;
-	LookingRight = 0;
+	LookingBehind = false;
+	LookingLeft = false;
+	LookingRight = false;
 	m_fPlayerInFrontSyphonAngleOffSet = DEGTORAD(20.0f);
 	m_fSyphonModeTargetZOffSet = 0.5f;
 	m_fRadiusForDead = 1.5f;
 	DirectionWasLooking = LOOKING_FORWARD;
-	LookBehindCamWasInFront = 0;
+	LookBehindCamWasInFront = false;
 	f_Roll = 0.0f;
 	f_rollSpeed = 0.0f;
 	m_fCloseInPedHeightOffset = 0.0f;
@@ -231,7 +237,7 @@ CCam::Process(void)
 		ProcessArrestCamTwo();
 		break;
 	case MODE_M16_1STPERSON:
-	case MODE_HELICANNON_1STPERSON:	// miami
+	case MODE_HELICANNON_1STPERSON:
 		Process_M16_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
 		break;
 	case MODE_SPECIAL_FIXED_FOR_SYPHON:
@@ -897,10 +903,10 @@ CCam::PrintMode(void)
 			"Blood on the tracks", "Passenger", "Syphon Crim in Front",
 			"Dead Baby", "Pillow Paps", "Look at Cars", "Arrest One",
 			"Arrest Two", "M16", "Special fixed for Syphon", "Fight",
-			"Top Down Ped",
+			"Top Down Ped", "Lighthouse",
 			"Sniper run about", "Rocket run about",
 			"1st Person run about", "M16 run about", "Fight run about",
-			"Editor"
+			"Editor", "Helicannon", "Camera"
 		};
 		sprintf(buf, "Cam: %s", modes[TheCamera.Cams[TheCamera.ActiveCam].Mode]);
 		CDebug::PrintAt(buf, 2, 5);
@@ -994,97 +1000,89 @@ CCam::GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaO
 	return 0.0f;
 }
 
-static float DefaultAcceleration = 0.045f;
-static float DefaultMaxStep = 0.15f;
+float DefaultAcceleration = 0.045f;
+float DefaultMaxStep = 0.15f;
+float fDefaultSpeedStep = 0.025f;
+float fDefaultSpeedMultiplier = 0.09f;
+float fDefaultSpeedLimit = 0.15f;
+float fDefaultSpeedStep4Avoid = 0.02f;
+float fDefaultSpeedMultiplier4Avoid = 0.05f;
+float fDefaultSpeedLimit4Avoid = 0.25f;
+float fAvoidGeomThreshhold = 1.5f;
+float fMiniGunBetaOffset = 0.3f;
 
 void
 CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float)
 {
-	const float GroundDist = 1.85f;
+	if(!CamTargetEntity->IsPed())
+		return;
 
 	CVector TargetCoors, Dist, IdealSource;
 	float Length = 0.0f;
-	float LateralLeft = 0.0f;
-	float LateralRight = 0.0f;
-	float Center = 0.0f;
-	static bool PreviouslyObscured;
 	static bool PickedASide;
 	static float FixedTargetOrientation = 0.0f;
 	float AngleToGoTo = 0.0f;
-	float BetaOffsetAvoidBuildings = 0.45f;		// ~25 deg
-	float BetaOffsetGoingBehind = 0.45f;
-	bool GoingBehind = false;
-	bool Obscured = false;
-	bool BuildingCheckObscured = false;
-	bool HackPlayerOnStoppingTrain = false;
+	bool StandingInTrain = false;
+	float ZoomGroundTarget = 0.0f;
+	float ZoomZTarget = 0.0f;
 	static int TimeIndicatedWantedToGoDown = 0;
 	static bool StartedCountingForGoDown = false;
+	static float ZoomGround = 0.0f;
+	static float ZoomGroundSpeed = 0.0f;
+	static float ZoomZ = 0.0f;
+	static float ZoomZSpeed = 0.0f;
 	float DeltaBeta;
 
 	m_bFixingBeta = false;
 	bBelowMinDist = false;
 	bBehindPlayerDesired = false;
 
-#ifdef FIX_BUGS
-	if(!CamTargetEntity->IsPed())
-		return;
-#endif
-	assert(CamTargetEntity->IsPed());
-
-	// CenterDist should be > LateralDist because we don't have an angle for safety in this case
-	float CenterDist, LateralDist;
-	float AngleToGoToSpeed;
-	if(m_fCloseInPedHeightOffset > 0.00001f){
-		LateralDist = 0.55f;
-		CenterDist = 1.25f;
-		BetaOffsetAvoidBuildings = 0.9f;	// ~50 deg
-		BetaOffsetGoingBehind = 0.9f;
-		AngleToGoToSpeed = 0.88254666f;
-	}else{
-		LateralDist = 0.8f;
-		CenterDist = 1.35f;
-		if(TheCamera.PedZoomIndicator == CAM_ZOOM_1 || TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN){
-			LateralDist = 1.25f;
-			CenterDist = 1.6f;
-		}
-		AngleToGoToSpeed = 0.43254671f;
-	}
-
 	FOV = DefaultFOV;
 
 	if(ResetStatics){
 		Rotating = false;
 		m_bCollisionChecksOn = true;
 		FixedTargetOrientation = 0.0f;
-		PreviouslyObscured = false;
 		PickedASide = false;
 		StartedCountingForGoDown = false;
 		AngleToGoTo = 0.0f;
-		// unused LastAngleWithNoPickedASide
+		ZoomGround = 0.0f;
+		ZoomGroundSpeed = 0.0f;
+		ZoomZ = 0.0f;
+		ZoomZSpeed = 0.0f;
+		Distance = 500.0f;
 	}
 
 
 	TargetCoors = CameraTarget;
+
+	// Take speed of thing we're standing on into account
+	CVector GroundMovement(0.0f, 0.0f, 0.0f);
+	CPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface;
+	if(ground && (ground->IsVehicle() || ground->IsObject()))
+		GroundMovement += ground->GetSpeed(CamTargetEntity->GetPosition() - ground->GetPosition()) * CTimer::GetTimeStep();
+
+	Source += GroundMovement;
 	IdealSource = Source;
 	TargetCoors.z += m_fSyphonModeTargetZOffSet;
 
-	TargetCoors = DoAverageOnVector(TargetCoors);
-	TargetCoors.z += m_fRoadOffSet;
+	TargetCoors.z = DoAverageOnVector(TargetCoors).z;
 
 	Dist.x = IdealSource.x - TargetCoors.x;
 	Dist.y = IdealSource.y - TargetCoors.y;
 	Length = Dist.Magnitude2D();
 
 	// Cam on a string. With a fixed distance. Zoom in/out is done later.
-	if(Length != 0.0f)
-		IdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * GroundDist;
-	else
+	if(Length != 0.0f){
+		IdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * m_fMinRealGroundDist;
+		IdealSource.z += GroundMovement.z;
+	}else
 		IdealSource = TargetCoors + CVector(1.0f, 1.0f, 0.0f);
 
 	if(TheCamera.m_bUseTransitionBeta && ResetStatics){
 		CVector VecDistance;
-		IdealSource.x = TargetCoors.x + GroundDist*Cos(m_fTransitionBeta);
-		IdealSource.y = TargetCoors.y + GroundDist*Sin(m_fTransitionBeta);
+		IdealSource.x = TargetCoors.x + m_fMinRealGroundDist*Cos(m_fTransitionBeta);
+		IdealSource.y = TargetCoors.y + m_fMinRealGroundDist*Sin(m_fTransitionBeta);
 		Beta = CGeneral::GetATanOfXY(IdealSource.x - TargetCoors.x, IdealSource.y - TargetCoors.y);
 	}else
 		Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
@@ -1096,7 +1094,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 
 	if(FindPlayerVehicle())
 		if(FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_TRAIN)
-			HackPlayerOnStoppingTrain = true;
+			StandingInTrain = true;
 
 	if(TheCamera.m_bCamDirectlyInFront){
 		 m_bCollisionChecksOn = true;
@@ -1106,24 +1104,30 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 	while(Beta >= PI) Beta -= 2.0f * PI;
 	while(Beta < -PI) Beta += 2.0f * PI;
 
-	// BUG? is this ever used?
-	// The values seem to be roughly m_fPedZoomValueSmooth + 1.85
-	if(ResetStatics){
-		if(TheCamera.PedZoomIndicator == CAM_ZOOM_1) m_fRealGroundDist = 2.090556f;
-		if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) m_fRealGroundDist = 3.34973f;
-		if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) m_fRealGroundDist = 4.704914f;
-		if(TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN) m_fRealGroundDist = 2.090556f;
+	if(TheCamera.PedZoomIndicator == CAM_ZOOM_1 &&
+	   ((CPed*)CamTargetEntity)->GetPedState() != PED_ENTER_CAR &&
+	   ((CPed*)CamTargetEntity)->GetPedState() != PED_CARJACK){
+		ZoomGroundTarget = m_fTargetZoomGroundOne;
+		ZoomZTarget = m_fTargetZoomOneZExtra;
+	}else if(TheCamera.PedZoomIndicator == CAM_ZOOM_2 || TheCamera.PedZoomIndicator == CAM_ZOOM_1){
+		ZoomGroundTarget = m_fTargetZoomGroundTwo;
+		ZoomZTarget = m_fTargetZoomTwoZExtra;
+	}else if(TheCamera.PedZoomIndicator == CAM_ZOOM_3){
+		ZoomGroundTarget = m_fTargetZoomGroundThree;
+		ZoomZTarget = m_fTargetZoomThreeZExtra;
+	}
+	if(m_fCloseInPedHeightOffset >  0.00001f){
+		ZoomGroundTarget = m_fTargetCloseInDist;
+		ZoomZTarget = m_fTargetZoomZCloseIn;
+	}
+	if(ResetStatics){
+		ZoomGround = ZoomGroundTarget;
+		ZoomZ = ZoomZTarget;
 	}
-	// And what is this? It's only used for collision and rotation it seems
-	float RealGroundDist;
-	if(TheCamera.PedZoomIndicator == CAM_ZOOM_1) RealGroundDist = 2.090556f;
-	if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) RealGroundDist = 3.34973f;
-	if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) RealGroundDist = 4.704914f;
-	if(TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN) RealGroundDist = 2.090556f;
-	if(m_fCloseInPedHeightOffset >  0.00001f)
-		RealGroundDist = 1.7016f;
-
 
+	float SpeedStep = fDefaultSpeedStep;
+	float SpeedMultiplier = fDefaultSpeedMultiplier;
+	float SpeedLimit = fDefaultSpeedLimit;
 	bool Shooting = false;
 	CPed *ped = (CPed*)CamTargetEntity;
 	if(ped->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
@@ -1134,166 +1138,52 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 		Shooting = false;
 
 
-	if(m_fCloseInPedHeightOffset > 0.00001f)
-		TargetCoors.z -= m_fRoadOffSet;
-
 	// Figure out if and where we want to rotate
 
-	if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){
+	if(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup || Shooting){
 
 		// Center cam behind player
 
-		GoingBehind = true;
-		m_bCollisionChecksOn = true;
-		float OriginalBeta = Beta;
-		// Set Beta behind player
-		Beta = TargetOrientation + PI;
-		TargetCoors.z -= 0.1f;
-
-		AngleToGoTo = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false);
-		if(AngleToGoTo != 0.0f){
-			if(AngleToGoTo < 0.0f)
-				AngleToGoTo -= AngleToGoToSpeed;
-			else
-				AngleToGoTo += AngleToGoToSpeed;
-		}else{
-			float LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetGoingBehind, true, false, false, true, false);
-			float LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetGoingBehind, true, false, false, true, false);
-			if(LateralLeft == 0.0f && LateralRight != 0.0f)
-				AngleToGoTo += LateralRight;
-			else if(LateralLeft != 0.0f && LateralRight == 0.0f)
-				AngleToGoTo += LateralLeft;
-		}
-
-		TargetCoors.z += 0.1f;
-		Beta = OriginalBeta;
-
 		if(PickedASide){
-			if(AngleToGoTo == 0.0f)
+			if(AngleToGoTo == 0.0f){
 				FixedTargetOrientation = TargetOrientation + PI;
+				if(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)
+					FixedTargetOrientation -= fMiniGunBetaOffset;
+			}
 			Rotating = true;
 		}else{
-			FixedTargetOrientation = TargetOrientation + PI + AngleToGoTo;
+			FixedTargetOrientation = TargetOrientation + PI;
 			Rotating = true;
 			PickedASide = true;
+			if(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)
+				FixedTargetOrientation -= fMiniGunBetaOffset;
 		}
-	}else{
+	}else if(Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold && !Rotating ){
 
-		// Rotate cam to avoid clipping into buildings
-
-		TargetCoors.z -= 0.1f;
-
-		Center = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false);
-		if(m_bCollisionChecksOn || PreviouslyObscured || Center != 0.0f || m_fCloseInPedHeightOffset > 0.00001f){
-			if(Center != 0.0f){
-				AngleToGoTo = Center;
-			}else{
-				LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetAvoidBuildings, true, false, false, true, false);
-				LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetAvoidBuildings, true, false, false, true, false);
-				if(LateralLeft == 0.0f && LateralRight != 0.0f){
-					AngleToGoTo += LateralRight;
-					if(m_fCloseInPedHeightOffset > 0.0f)
-						RwCameraSetNearClipPlane(Scene.camera, 0.7f);
-				}else if(LateralLeft != 0.0f && LateralRight == 0.0f){
-					AngleToGoTo += LateralLeft;
-					if(m_fCloseInPedHeightOffset > 0.0f)
-						RwCameraSetNearClipPlane(Scene.camera, 0.7f);
-				}
-			}
-			if(LateralLeft != 0.0f || LateralRight != 0.0f || Center != 0.0f)
-				BuildingCheckObscured = true;
-		}
-
-		TargetCoors.z += 0.1f;
+		if(TheCamera.m_fAvoidTheGeometryProbsTimer < 0.0f)
+			FixedTargetOrientation = TargetOrientation;
+		else
+			FixedTargetOrientation = TargetOrientation + PI;
+		float dist = (Source - TargetCoors).Magnitude();
+		float mult = dist > 0.1f ? 1.0f/dist : 10.0f;
+		SpeedStep = mult * fDefaultSpeedStep4Avoid;
+		SpeedMultiplier = mult * fDefaultSpeedMultiplier4Avoid;
+		SpeedLimit = mult * fDefaultSpeedLimit4Avoid;
 	}
 
-	if(m_fCloseInPedHeightOffset > 0.00001f)
-		TargetCoors.z += m_fRoadOffSet;
-
-
-	// Have to fix to avoid collision
-
-	if(AngleToGoTo != 0.0f){
-		Obscured = true;
-		Rotating = true;
-		if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){
-			if(!PickedASide)
-				FixedTargetOrientation = Beta + AngleToGoTo;	// can this even happen?
-		}else
-			FixedTargetOrientation = Beta + AngleToGoTo;
-
-		// This calculation is only really used to figure out how fast to rotate out of collision
-
-		m_fAmountFractionObscured = 1.0f;
-		CVector PlayerPos = FindPlayerPed()->GetPosition();
-		float RotationDist = (AngleToGoTo == Center ? CenterDist : LateralDist) * RealGroundDist;
-		// What's going on here? - AngleToGoTo?
-		CVector RotatedSource = PlayerPos + CVector(Cos(Beta - AngleToGoTo), Sin(Beta - AngleToGoTo), 0.0f) * RotationDist;
-
-		CColPoint colpoint;
-		CEntity *entity;
-		if(CWorld::ProcessLineOfSight(PlayerPos, RotatedSource, colpoint, entity, true, false, false, true, false, false, false)){
-			if((PlayerPos - RotatedSource).Magnitude() != 0.0f)
-				m_fAmountFractionObscured = (PlayerPos - colpoint.point).Magnitude() / (PlayerPos - RotatedSource).Magnitude();
-			else
-				m_fAmountFractionObscured = 1.0f;
-		}
-	}
-	if(m_fAmountFractionObscured < 0.0f) m_fAmountFractionObscured = 0.0f;
-	if(m_fAmountFractionObscured > 1.0f) m_fAmountFractionObscured = 1.0f;
-
-
-
-	// Figure out speed values for Beta rotation
-
-	float Acceleration, MaxSpeed;
-	static float AccelerationMult = 0.35f;
-	static float MaxSpeedMult = 0.85f;
-	static float AccelerationMultClose = 0.7f;
-	static float MaxSpeedMultClose = 1.6f;
-	float BaseAcceleration = 0.025f;
-	float BaseMaxSpeed = 0.09f;
-	if(m_fCloseInPedHeightOffset > 0.00001f){
-		if(AngleToGoTo == 0.0f){
-			BaseAcceleration = 0.022f;
-			BaseMaxSpeed = 0.04f;
-		}else{
-			BaseAcceleration = DefaultAcceleration;
-			BaseMaxSpeed = DefaultMaxStep;
-		}
-	}
-	if(AngleToGoTo == 0.0f){
-		Acceleration = BaseAcceleration;
-		MaxSpeed = BaseMaxSpeed;
-	}else if(CPad::GetPad(0)->ForceCameraBehindPlayer() && !Shooting){
-		Acceleration = 0.051f;
-		MaxSpeed = 0.18f;
-	}else if(m_fCloseInPedHeightOffset > 0.00001f){
-		Acceleration = BaseAcceleration + AccelerationMultClose*sq(m_fAmountFractionObscured - 1.05f);
-		MaxSpeed = BaseMaxSpeed + MaxSpeedMultClose*sq(m_fAmountFractionObscured - 1.05f);
-	}else{
-		Acceleration = DefaultAcceleration + AccelerationMult*sq(m_fAmountFractionObscured - 1.05f);
-		MaxSpeed = DefaultMaxStep + MaxSpeedMult*sq(m_fAmountFractionObscured - 1.05f);
-	}
-	static float AccelerationLimit = 0.3f;
-	static float MaxSpeedLimit = 0.65f;
-	if(Acceleration > AccelerationLimit) Acceleration = AccelerationLimit;
-	if(MaxSpeed > MaxSpeedLimit) MaxSpeed = MaxSpeedLimit;
-
-
 	int MoveState = ((CPed*)CamTargetEntity)->m_nMoveState;
 	if(MoveState != PEDMOVE_NONE && MoveState != PEDMOVE_STILL &&
-	   !CPad::GetPad(0)->ForceCameraBehindPlayer() && !Obscured && !Shooting){
+	   !(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup) && !Shooting){
 		Rotating = false;
-		BetaSpeed = 0.0f;
+		if(TheCamera.m_fAvoidTheGeometryProbsTimer <= fAvoidGeomThreshhold)
+			BetaSpeed = 0.0f;
 	}
 
 	// Now do the Beta rotation
 
-	float RotDistance = (IdealSource - TargetCoors).Magnitude2D();
-	m_fDistanceBeforeChanges = RotDistance;
+	float RotDistance = m_fMinRealGroundDist;
 
-	if(Rotating){
+	if(Rotating || TheCamera.m_fAvoidTheGeometryProbsTimer > fAvoidGeomThreshhold){
 		m_bFixingBeta = true;
 
 		while(FixedTargetOrientation >= PI) FixedTargetOrientation -= 2*PI;
@@ -1303,13 +1193,23 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 		while(Beta < -PI) Beta += 2*PI;
 
 
-/*
-		// This is inlined WellBufferMe
+		// This is inlined WellBufferMe - unfortunately modified so we can't just call it
+		{
 		DeltaBeta = FixedTargetOrientation - Beta;
 		while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
 		while(DeltaBeta < -PI) DeltaBeta += 2*PI;
 
-		float ReqSpeed = DeltaBeta * MaxSpeed;
+		// this is the added bit
+		if(!Rotating){
+			if(TheCamera.m_nAvoidTheGeometryProbsDirn == -1 && DeltaBeta > 0.0f ||
+			   TheCamera.m_nAvoidTheGeometryProbsDirn == 1 && DeltaBeta < 0.0f)
+				DeltaBeta *= -1.0f;
+		}
+
+		float ReqSpeed = DeltaBeta * SpeedMultiplier;
+		// this is also added
+		ReqSpeed = clamp(ReqSpeed, -SpeedLimit, SpeedLimit);
+
 		// Add or subtract absolute depending on sign, genius!
 		if(ReqSpeed - BetaSpeed > 0.0f)
 			BetaSpeed += SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();
@@ -1324,8 +1224,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 			BetaSpeed = ReqSpeed;
 
 		Beta += BetaSpeed * Min(10.0f, CTimer::GetTimeStep());
-*/
-		WellBufferMe(FixedTargetOrientation, &Beta, &BetaSpeed, MaxSpeed, Acceleration, true);
+		}
 
 		if(ResetStatics){
 			Beta = FixedTargetOrientation;
@@ -1349,7 +1248,14 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 
 
 	if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront ||
-	   HackPlayerOnStoppingTrain || Rotating){
+	   StandingInTrain || Rotating ||
+	   TheCamera.m_bUseTransitionBeta && ResetStatics ||
+	   Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold){
+		if(TheCamera.m_bUseTransitionBeta){
+			Beta = m_fTransitionBeta;
+			Source.x = TargetCoors.x + RotDistance * Cos(m_fTransitionBeta);
+			Source.y = TargetCoors.y + RotDistance * Sin(m_fTransitionBeta);
+		}
 		if(TheCamera.m_bCamDirectlyBehind){
 			Beta = TargetOrientation + PI;
 			Source.x = TargetCoors.x + RotDistance * Cos(Beta);
@@ -1360,7 +1266,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 			Source.x = TargetCoors.x + RotDistance * Cos(Beta);
 			Source.y = TargetCoors.y + RotDistance * Sin(Beta);
 		}
-		if(HackPlayerOnStoppingTrain){
+		if(StandingInTrain){
 			Beta = TargetOrientation + PI;
 			Source.x = TargetCoors.x + RotDistance * Cos(Beta);
 			Source.y = TargetCoors.y + RotDistance * Sin(Beta);
@@ -1368,59 +1274,42 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 			m_fCamBufferedHeight = 0.0f;
 			m_fCamBufferedHeightSpeed = 0.0f;
 		}
+		if(StandingInTrain){
+			Beta = TargetOrientation + PI;
+			Source.x = TargetCoors.x + RotDistance * Cos(Beta);
+			Source.y = TargetCoors.y + RotDistance * Sin(Beta);
+			m_fDimensionOfHighestNearCar = 0.0f;
+			m_fCamBufferedHeight = 0.0f;
+			m_fCamBufferedHeightSpeed = 0.0f;
+		}
+
 		// Beta and Source already set in the rotation code
 	}else{
 		Source = IdealSource;
 		BetaSpeed = 0.0f;
 	}
+	Source.z = IdealSource.z;
 
-	// Subtract m_fRoadOffSet from both?
-	TargetCoors.z -= m_fRoadOffSet;
-	Source.z = IdealSource.z - m_fRoadOffSet;
-
-	// Apply zoom now
-	// m_fPedZoomValueSmooth makes the cam go down the further out it is
-	//  0.25 ->  0.20 for nearest dist
-	//  1.50 -> -0.05 for mid dist
-	//  2.90 -> -0.33 for far dist
-	Source.z += (2.5f - TheCamera.m_fPedZoomValueSmooth)*0.2f - 0.25f;
 	// Zoom out camera
 	Front = TargetCoors - Source;
 	Front.Normalise();
-	Source -= Front * TheCamera.m_fPedZoomValueSmooth;
-	// and then we move up again
-	//  -0.375
-	//   0.25
-	//   0.95
-	Source.z += (TheCamera.m_fPedZoomValueSmooth - 1.0f)*0.5f + m_fCloseInPedHeightOffset;
+	WellBufferMe(ZoomGroundTarget, &ZoomGround, &ZoomGroundSpeed, 0.2f, 0.07f, false);
+	WellBufferMe(ZoomZTarget, &ZoomZ, &ZoomZSpeed, 0.2f, 0.07f, false);
+	Source.x -= Front.x*ZoomGround;
+	Source.y -= Front.y*ZoomGround;
+	Source.z += ZoomZ;
 
 
 	// Process height offset to avoid peds and cars
 
-	float TargetZOffSet = m_fRoadOffSet + m_fDimensionOfHighestNearCar;
-	TargetZOffSet = Max(TargetZOffSet, m_fPedBetweenCameraHeightOffset);
+	float TargetZOffSet = Max(m_fDimensionOfHighestNearCar, m_fPedBetweenCameraHeightOffset);
 	float TargetHeight = CameraTarget.z + TargetZOffSet - Source.z;
 
 	if(TargetHeight > m_fCamBufferedHeight){
 		// Have to go up
 		if(TargetZOffSet == m_fPedBetweenCameraHeightOffset && TargetZOffSet > m_fCamBufferedHeight)
 			WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.04f, false);
-		else if(TargetZOffSet == m_fRoadOffSet && TargetZOffSet > m_fCamBufferedHeight){
-			// TODO: figure this out
-			bool foo = false;
-			switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched)
-			case SURFACE_GRASS:
-			case SURFACE_GRAVEL:
-			case SURFACE_PAVEMENT:
-			case SURFACE_THICK_METAL_PLATE:
-			case SURFACE_RUBBER:
-			case SURFACE_STEEP_CLIFF:
-				foo = true;
-			if(foo)
-				WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.4f, 0.05f, false);
-			else
-				WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);
-		}else
+		else
 			WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);
 		StartedCountingForGoDown = false;
 	}else{
@@ -1439,24 +1328,24 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 	}
 
 	Source.z += m_fCamBufferedHeight;
-
-
-	// Clip Source if necessary
-
-	bool ClipSource = m_fCloseInPedHeightOffset > 0.00001f && m_fCamBufferedHeight > 0.001f;
-	if(GoingBehind || ResetStatics || ClipSource){
-		CColPoint colpoint;
-		CEntity *entity;
-		if(CWorld::ProcessLineOfSight(TargetCoors, Source, colpoint, entity, true, false, false, true, false, true, true)){
-			Source = colpoint.point;
-			if((TargetCoors - Source).Magnitude2D() < 1.0f)
-				RwCameraSetNearClipPlane(Scene.camera, 0.05f);
-		}
-	}
-
 	TargetCoors.z += Min(1.0f, m_fCamBufferedHeight/2.0f);
 	m_cvecTargetCoorsForFudgeInter = TargetCoors;
 
+	CVector OrigSource = Source;
+	TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);
+	float TargetDist = (TargetCoors - Source).Magnitude();
+	if(TargetDist < Distance)
+		Distance = TargetDist;
+	else{
+		float f = Pow(0.97f, CTimer::GetTimeStep());
+		Distance = (1.0f - f)*TargetDist + f*Distance;
+		if(TargetDist > 0.05f)
+			Source = TargetCoors + (Source-TargetCoors)*Distance/TargetDist;
+		float clip = Distance-fRangePlayerRadius;
+		if(clip < RwCameraGetNearClipPlane(Scene.camera))
+			RwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit));
+	}
+
 	Front = TargetCoors - Source;
 	m_fRealGroundDist = Front.Magnitude2D();
 	m_fMinDistAwayFromCamWhenInterPolating = m_fRealGroundDist;	
@@ -1464,19 +1353,19 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
 	GetVectorsReadyForRW();
 	TheCamera.m_bCamDirectlyBehind = false;
 	TheCamera.m_bCamDirectlyInFront = false;
-	PreviouslyObscured = BuildingCheckObscured;
 
 	ResetStatics = false;
 }
 
-static float fBaseDist = 1.7f;
-static float fAngleDist = 2.0f;
-static float fFalloff = 3.0f;
-static float fStickSens = 0.01f;
-static float fTweakFOV = 1.05f;
-static float fTranslateCamUp = 0.8f;
-static int16 nFadeControlThreshhold = 45;
-static float fDefaultAlphaOrient = -0.22f;
+float fBaseDist = 1.7f;
+float fAngleDist = 2.0f;
+float fFalloff = 3.0f;
+float fStickSens = 0.01f;
+float fTweakFOV = 1.1f;
+float fTranslateCamUp = 0.8f;
+int16 nFadeControlThreshhold = 45;
+float fDefaultAlphaOrient = -0.22f;
+float fMouseAvoidGeomReturnRate = 0.92f;
 
 void
 CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float)
@@ -1500,30 +1389,44 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
 
 	bool OnTrain = FindPlayerVehicle() && FindPlayerVehicle()->IsTrain();
 
-	// Look around
-	bool UseMouse = false;
-	float MouseX = CPad::GetPad(0)->GetMouseX();
-	float MouseY = CPad::GetPad(0)->GetMouseY();
-	float LookLeftRight, LookUpDown;
-	if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
-		UseMouse = true;
-		LookLeftRight = -2.5f*MouseX;
-		LookUpDown = 4.0f*MouseY;
-	}else{
-		LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
-		LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
-	}
+	TargetCoors = CameraTarget;
+	TargetCoors.z += fTranslateCamUp;
+
 	float AlphaOffset, BetaOffset;
-	if(UseMouse){
-		BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;
-		AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;
+	if(CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_DISABLED_20)){
+		CVector ToCam = Source - TargetCoors;
+		ToCam.Normalise();
+		if(ToCam.z < -0.9f)
+			BetaOffset = TargetOrientation + PI;
+		else
+			BetaOffset = Atan2(ToCam.y, ToCam.x);
+		AlphaOffset = 0.0f;
 	}else{
-		BetaOffset = LookLeftRight * fStickSens * (0.5f/7.0f) * FOV/80.0f * CTimer::GetTimeStep();
-		AlphaOffset = LookUpDown * fStickSens * (0.3f/7.0f) * FOV/80.0f * CTimer::GetTimeStep();
+		// Look around
+		bool UseMouse = false;
+		float MouseX = CPad::GetPad(0)->GetMouseX();
+		float MouseY = CPad::GetPad(0)->GetMouseY();
+		float LookLeftRight, LookUpDown;
+		if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
+			UseMouse = true;
+			LookLeftRight = -2.5f*MouseX;
+			LookUpDown = 4.0f*MouseY;
+		}else{
+			LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
+			LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
+		}
+		if(UseMouse){
+			BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;
+			AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;
+		}else{
+			BetaOffset = LookLeftRight * fStickSens * (1.0f/14.0f) * FOV/80.0f * CTimer::GetTimeStep();
+			AlphaOffset = LookUpDown * fStickSens * (0.6f/14.0f) * FOV/80.0f * CTimer::GetTimeStep();
+		}
 	}
 
 	if(TheCamera.GetFading() && TheCamera.GetFadingDirection() == FADE_IN && nFadeControlThreshhold < CDraw::FadeValue ||
-	   CDraw::FadeValue > 200){
+	   CDraw::FadeValue > 200 ||
+	   CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_DISABLED_20)){
 		if(Alpha < fDefaultAlphaOrient-0.05f)
 			AlphaOffset = 0.05f;
 		else if(Alpha < fDefaultAlphaOrient)
@@ -1541,11 +1444,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
 	while(Beta >= PI) Beta -= 2*PI;
 	while(Beta < -PI) Beta += 2*PI;
 	if(Alpha > DEGTORAD(45.0f)) Alpha = DEGTORAD(45.0f);
-	if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
-
-	TargetCoors = CameraTarget;
-	TargetCoors.z += fTranslateCamUp;
-	TargetCoors = DoAverageOnVector(TargetCoors);
+	else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
 
 	// SA code
 #ifdef FREE_CAM
@@ -1558,12 +1457,12 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
 		CamDist = fBaseDist + Cos(Alpha)*fAngleDist;
 
 	if(TheCamera.m_bUseTransitionBeta)
-		Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));
+		Beta = m_fTransitionBeta;
 
 	if(TheCamera.m_bCamDirectlyBehind)
-		Beta = TheCamera.m_PedOrientForBehindOrInFront;
-	if(TheCamera.m_bCamDirectlyInFront)
 		Beta = TheCamera.m_PedOrientForBehindOrInFront + PI;
+	if(TheCamera.m_bCamDirectlyInFront)
+		Beta = TheCamera.m_PedOrientForBehindOrInFront;
 	if(OnTrain)
 		Beta = TargetOrientation;
 
@@ -1579,7 +1478,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
 	if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, true, true, true, false, false, true)){
 		float PedColDist = (TargetCoors - colPoint.point).Magnitude();
 		float ColCamDist = CamDist - PedColDist;
-		if(entity->IsPed() && ColCamDist > 1.0f){
+		if(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){
 			// Ped in the way but not clipping through
 			if(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, true, true, true, false, false, true)){
 				PedColDist = (TargetCoors - colPoint.point).Magnitude();
@@ -1617,9 +1516,12 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
 		if(dist == 0.1f)
 			Source += (TargetCoors - Source)*0.3f;
 
+		Near = RwCameraGetNearClipPlane(Scene.camera);
 #ifndef FIX_BUGS
-		// this is totally wrong...
-		radius = Tan(FOV / 2.0f) * Near;
+		// this is wrong...DEGTORAD missing
+		radius = Tan(FOV / 2.0f) * CDraw::CalculateAspectRatio() * fTweakFOV * Near;
+#else
+		radius = ViewPlaneWidth*Near;
 #endif
 		// Keep testing
 		entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
@@ -1629,13 +1531,27 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
 			entity = nil;
 	}
 
+	float TargetDist = (TargetCoors - Source).Magnitude();
+	if(TargetDist < Distance)
+		Distance = TargetDist;
+	else{
+		float f = Pow(fMouseAvoidGeomReturnRate, CTimer::GetTimeStep());
+		Distance = (1.0f - f)*TargetDist + f*Distance;
+		if(TargetDist > 0.05f)
+			Source = TargetCoors + (Source-TargetCoors)*Distance/TargetDist;
+		float clip = Distance-fRangePlayerRadius;
+		if(clip < RwCameraGetNearClipPlane(Scene.camera))
+			RwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit));
+	}
+
 	TheCamera.m_bCamDirectlyInFront = false;
 	TheCamera.m_bCamDirectlyBehind = false;
 
 	GetVectorsReadyForRW();
 
 	if(((CPed*)CamTargetEntity)->CanStrafeOrMouseControl() && CDraw::FadeValue < 250 &&
-	   (TheCamera.GetFadingDirection() != FADE_OUT || CDraw::FadeValue <= 100)){
+	   (TheCamera.GetFadingDirection() != FADE_OUT || CDraw::FadeValue <= 100) &&
+	   !CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_DISABLED_20)){
 		float Heading = Front.Heading();
 		((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;
 		((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;
@@ -1644,6 +1560,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
 	}
 }
 
+//--MIAMI: done
 void
 CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float)
 {
@@ -1672,300 +1589,173 @@ CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, fl
 	}
 	TargetCoors.z += 0.8f;
 
-	WorkOutCamHeightWeeCar(TargetCoors, TargetOrientation);
+	Alpha = DEGTORAD(25.0f);
+	Source.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha);
+
 	RotCamIfInFrontCar(TargetCoors, TargetOrientation);
-	FixCamIfObscured(TargetCoors, 1.2f, TargetOrientation);
+	m_cvecTargetCoorsForFudgeInter = TargetCoors;
+	CVector OrigSource = Source;
+	TheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV);
 
 	Front = TargetCoors - Source;
-	m_cvecTargetCoorsForFudgeInter = TargetCoors;
 	ResetStatics = false;
 	GetVectorsReadyForRW();
 }
 
-void
-CCam::WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation)
-{
-	CColPoint colpoint;
-	CEntity *ent;
-	float TargetZOffSet = 0.0f;
-	static bool PreviouslyFailedRoadHeightCheck = false;
-	static float RoadHeightFix = 0.0f;
-	static float RoadHeightFixSpeed = 0.0f;
-
-	if(ResetStatics){
-		RoadHeightFix = 0.0f;
-		RoadHeightFixSpeed = 0.0f;
-		Alpha = DEGTORAD(25.0f);
-		AlphaSpeed = 0.0f;
-	}
-	float AlphaTarget = DEGTORAD(25.0f);
-	if(CCullZones::CamNoRain() || CCullZones::PlayerNoRain())
-		AlphaTarget = DEGTORAD(14.0f);
-	WellBufferMe(AlphaTarget, &Alpha, &AlphaSpeed, 0.1f, 0.05f, true);
-	Source.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha);
-
-	if(FindPlayerVehicle()){
-		m_fRoadOffSet = 0.0f;
-		bool FoundRoad = false;
-		bool FoundRoof = false;
-		float RoadZ = 0.0f;
-		float RoofZ = 0.0f;
-
-		if(CWorld::ProcessVerticalLine(Source, -1000.0f, colpoint, ent, true, false, false, false, false, false, nil) &&
-		   ent->IsBuilding()){
-			FoundRoad = true;
-			RoadZ = colpoint.point.z;
-		}
-
-		if(FoundRoad){
-			if(Source.z - RoadZ < 0.9f){
-				PreviouslyFailedRoadHeightCheck = true;
-				TargetZOffSet = RoadZ + 0.9f - Source.z;
-			}else{
-				if(m_bCollisionChecksOn)
-					PreviouslyFailedRoadHeightCheck = false;
-				else
-					TargetZOffSet = 0.0f;
-			}
-		}else{
-			if(CWorld::ProcessVerticalLine(Source, 1000.0f, colpoint, ent, true, false, false, false, false, false, nil) &&
-			   ent->IsBuilding()){
-				FoundRoof = true;
-				RoofZ = colpoint.point.z;
-			}
-			if(FoundRoof){
-				if(Source.z - RoofZ < 0.9f){
-					PreviouslyFailedRoadHeightCheck = true;
-					TargetZOffSet = RoofZ + 0.9f - Source.z;
-				}else{
-					if(m_bCollisionChecksOn)
-						PreviouslyFailedRoadHeightCheck = false;
-					else
-						TargetZOffSet = 0.0f;
-				}
-			}
-		}
-	}
-
-	if(TargetZOffSet > RoadHeightFix)
-		RoadHeightFix = TargetZOffSet;
-	else
-		WellBufferMe(TargetZOffSet, &RoadHeightFix, &RoadHeightFixSpeed, 0.27f, 0.1f, false);
-
-	if((colpoint.surfaceB == SURFACE_DEFAULT || colpoint.surfaceB >= SURFACE_CAR) &&
-	   colpoint.surfaceB != SURFACE_THICK_METAL_PLATE && colpoint.surfaceB != SURFACE_STEEP_CLIFF &&
-	   RoadHeightFix > 1.4f)
-		RoadHeightFix = 1.4f;
-
-	Source.z += RoadHeightFix;
-}
+float ZmOneAlphaOffset[] = { -0.01f, 0.1f, 0.125f, -0.1f, -0.06f };
+float ZmTwoAlphaOffset[] = { 0.045f, 0.12f, 0.045f, 0.045f, -0.035f };
+float ZmThreeAlphaOffset[] = { 0.005f, 0.005f, 0.15f, 0.005f, 0.12f };
+float INIT_RC_HELI_HORI_EXTRA = 6.0f;
+float INIT_RC_PLANE_HORI_EXTRA = 9.5f;
+float INIT_RC_HELI_ALPHA_EXTRA = 0.2f;
+float INIT_RC_PLANE_ALPHA_EXTRA = 0.295f;
 
+//--MIAMI: done
 void
 CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight)
 {
-	static float LastTargetAlphaWithCollisionOn = 0.0f;
-	static float LastTopAlphaSpeed = 0.0f;
-	static float LastAlphaSpeedStep = 0.0f;
-	static bool PreviousNearCheckNearClipSmall = false;
+	if(!CamTargetEntity->IsVehicle())
+		return;
 
-	bool CamClear = true;
-	float ModeAlpha = 0.0f;
+	static float AlphaOffset = 0.0;
+	static float AlphaOffsetSpeed = 0.0;
+	static float AlphaDec = 0.0f;
+
+	bool isHeli = false;
+	bool isBike = false;
+	int appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();
+	if(appearance == VEHICLE_APPEARANCE_BIKE)
+		isBike = true;
+	if(appearance == VEHICLE_APPEARANCE_HELI)
+		isHeli = true;
+	int index = 0;
+	TheCamera.GetArrPosForVehicleType(appearance, index);
+
+	float ExtraOffset = 0.0f;
+	int id = CamTargetEntity->GetModelIndex();
+	if(id == MI_RCRAIDER || id == MI_RCGOBLIN)
+		ExtraOffset = INIT_RC_HELI_ALPHA_EXTRA;
+	else if(id == MI_RCBARON)
+		ExtraOffset = INIT_RC_PLANE_ALPHA_EXTRA;
 
 	if(ResetStatics){
-		LastTargetAlphaWithCollisionOn = 0.0f;
-		LastTopAlphaSpeed = 0.0f;
-		LastAlphaSpeedStep = 0.0f;
-		PreviousNearCheckNearClipSmall = false;
+		AlphaOffset = 0.0f;
+		AlphaOffsetSpeed = 0.0f;
+		AlphaDec = 0.0f;
+
+		if(TheCamera.CarZoomIndicator == CAM_ZOOM_1)
+			AlphaOffset = ZmOneAlphaOffset[index] + ExtraOffset;
+		else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2)
+			AlphaOffset = ZmTwoAlphaOffset[index] + ExtraOffset;
+		else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3)
+			AlphaOffset = ZmThreeAlphaOffset[index] + ExtraOffset;
 	}
 
-	float TopAlphaSpeed = 0.15f;
-	float AlphaSpeedStep = 0.015f;
-
-	float zoomvalue = TheCamera.CarZoomValueSmooth;
-	if(zoomvalue < 0.1f)
-		zoomvalue = 0.1f;
 	if(TheCamera.CarZoomIndicator == CAM_ZOOM_1)
-		ModeAlpha = CGeneral::GetATanOfXY(23.0f, zoomvalue);	// near
+		WellBufferMe(ZmOneAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);
 	else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2)
-		ModeAlpha = CGeneral::GetATanOfXY(10.8f, zoomvalue);	// mid
+		WellBufferMe(ZmTwoAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);
 	else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3)
-		ModeAlpha = CGeneral::GetATanOfXY(7.0f, zoomvalue);	// far
-
+		WellBufferMe(ZmThreeAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);
 
 	float Length = (Source - TargetCoors).Magnitude2D();
-	if(m_bCollisionChecksOn){	// there's another variable (on PC) but it's uninitialised
-		CVector Forward = CamTargetEntity->GetForward();
-		float CarAlpha = CGeneral::GetATanOfXY(Forward.Magnitude2D(), Forward.z);
-		// this shouldn't be necessary....
-		while(CarAlpha >= PI) CarAlpha -= 2*PI;
-		while(CarAlpha < -PI) CarAlpha += 2*PI;
 
-		while(Beta >= PI) Beta -= 2*PI;
-		while(Beta < -PI) Beta += 2*PI;
+	CVector Forward = CamTargetEntity->GetForward();
+	float CarAlpha = CGeneral::GetATanOfXY(Forward.Magnitude2D(), Forward.z);
+	// this shouldn't be necessary....
+	while(CarAlpha >= PI) CarAlpha -= 2*PI;
+	while(CarAlpha < -PI) CarAlpha += 2*PI;
 
-		float deltaBeta = Beta - TargetOrientation;
-		while(deltaBeta >= PI) deltaBeta -= 2*PI;
-		while(deltaBeta < -PI) deltaBeta += 2*PI;
+	while(Beta >= PI) Beta -= 2*PI;
+	while(Beta < -PI) Beta += 2*PI;
 
-		float BehindCarNess = Cos(deltaBeta);	// 1 if behind car, 0 if side, -1 if in front
-		CarAlpha = -CarAlpha * BehindCarNess;
-		if(CarAlpha < -0.01f)
-			CarAlpha = -0.01f;
+	float DeltaBeta = Beta - TargetOrientation;
+	while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+	while(DeltaBeta < -PI) DeltaBeta += 2*PI;
 
-		float DeltaAlpha = CarAlpha - Alpha;
-		while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
-		while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
-		// What's this?? wouldn't it make more sense to clamp?
-		float AngleLimit = DEGTORAD(1.8f);
-		if(DeltaAlpha < -AngleLimit)
-			DeltaAlpha += AngleLimit;
-		else if(DeltaAlpha > AngleLimit)
-			DeltaAlpha -= AngleLimit;
-		else
-			DeltaAlpha = 0.0f;
+	float BehindCarNess = Cos(DeltaBeta);	// 1 if behind car, 0 if side, -1 if in front
+	CarAlpha = -CarAlpha * BehindCarNess;
 
-		// Now the collision
+	float fwdSpeed = DotProduct(((CPhysical*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward())*180.0f;
+	if(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired()){
+		CarAlpha = DEGTORAD(10.0f);
+	}else if(isHeli){
+		CarAlpha = 0.0f;
+		float heliFwdZ = CamTargetEntity->GetForward().z;
+		float heliFwdXY = CamTargetEntity->GetForward().Magnitude2D();
+		float alphaAmount = Min(Abs(fwdSpeed/90.0f), 1.0f);
+		if(heliFwdXY != 0.0f || heliFwdZ != 0.0f)
+			CarAlpha = CGeneral::GetATanOfXY(heliFwdXY, Abs(heliFwdZ)) * alphaAmount;
 
-		float TargetAlpha = 0.0f;
-		bool FoundRoofCenter = false;
-		bool FoundRoofSide1 = false;
-		bool FoundRoofSide2 = false;
-		bool FoundCamRoof = false;
-		bool FoundCamGround = false;
-		float CamRoof = 0.0f;
-		float CarBottom = TargetCoors.z - TargetHeight/2.0f;
-
-		// Check car center
-		float CarRoof = CWorld::FindRoofZFor3DCoord(TargetCoors.x, TargetCoors.y, CarBottom, &FoundRoofCenter);
-
-		// Check sides of the car
-		Forward = CamTargetEntity->GetForward();	// we actually still have that...
-		Forward.Normalise();	// shouldn't be necessary
-		float CarSideAngle = CGeneral::GetATanOfXY(Forward.x, Forward.y) + PI/2.0f;
-		float SideX = 2.5f * Cos(CarSideAngle);
-		float SideY = 2.5f * Sin(CarSideAngle);
-		CWorld::FindRoofZFor3DCoord(TargetCoors.x + SideX, TargetCoors.y + SideY, CarBottom, &FoundRoofSide1);
-		CWorld::FindRoofZFor3DCoord(TargetCoors.x - SideX, TargetCoors.y - SideY, CarBottom, &FoundRoofSide2);
-
-		// Now find out at what height we'd like to place the camera
-		float CamGround = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, TargetCoors.z + Length*Sin(Alpha + ModeAlpha) + m_fCloseInCarHeightOffset, &FoundCamGround);
-		float CamTargetZ = 0.0f;
-		if(FoundCamGround){
-			// This is the normal case
-			CamRoof = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamGround + TargetHeight, &FoundCamRoof);
-			CamTargetZ = CamGround + TargetHeight*1.5f + 0.1f;
-		}else{
-			FoundCamRoof = false;
-			CamTargetZ = TargetCoors.z;
-		}
-
-		if(FoundRoofCenter && !FoundCamRoof && (FoundRoofSide1 || FoundRoofSide2)){
-			// Car is under something but camera isn't
-			// This seems weird...
-			TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, CarRoof - CamTargetZ - 1.5f);
-			CamClear = false;
-		}
-		if(FoundCamRoof){
-			// Camera is under something
-			float roof = FoundRoofCenter ? Min(CamRoof, CarRoof) : CamRoof;
-			// Same weirdness again?
-			TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, roof - CamTargetZ - 1.5f);
-			CamClear = false;
-		}
-		while(TargetAlpha >= PI) TargetAlpha -= 2*PI;
-		while(TargetAlpha < -PI) TargetAlpha += 2*PI;
-		if(TargetAlpha < DEGTORAD(-7.0f))
-			TargetAlpha = DEGTORAD(-7.0f);
-
-		// huh?
-		if(TargetAlpha > ModeAlpha)
-			CamClear = true;
-		// Camera is contrained by collision in some way
-		PreviousNearCheckNearClipSmall = false;
-		if(!CamClear){
-			PreviousNearCheckNearClipSmall = true;
-			RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
-
-			DeltaAlpha = TargetAlpha - (Alpha + ModeAlpha);
-			while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
-			while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
-
-			TopAlphaSpeed = 0.3f;
-			AlphaSpeedStep = 0.03f;
-		}
-
-		// Now do things if CamClear...but what is that anyway?
-		float CamZ = TargetCoors.z + Length*Sin(Alpha + DeltaAlpha + ModeAlpha) + m_fCloseInCarHeightOffset;
-		bool FoundGround, FoundRoof;
-		float CamGround2 = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, CamZ, &FoundGround);
-		if(FoundGround){
-			if(CamClear)
-				if(CamZ - CamGround2 < 1.5f){
-					PreviousNearCheckNearClipSmall = true;
-					RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
-
-					float a;
-					if(Length == 0.0f || CamGround2 + 1.5f - TargetCoors.z == 0.0f)
-						a = Alpha;
-					else
-						a = CGeneral::GetATanOfXY(Length, CamGround2 + 1.5f - TargetCoors.z);
-					while(a > PI) a -= 2*PI;
-					while(a < -PI) a += 2*PI;
-					DeltaAlpha = a - Alpha;
-				}
-		}else{
-			if(CamClear){
-				float CamRoof2 = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamZ, &FoundRoof);
-				if(FoundRoof && CamZ - CamRoof2 < 1.5f){
-					PreviousNearCheckNearClipSmall = true;
-					RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
-
-					if(CamRoof2 > TargetCoors.z + 3.5f)
-						CamRoof2 = TargetCoors.z + 3.5f;
-
-					float a;
-					if(Length == 0.0f || CamRoof2 + 1.5f - TargetCoors.z == 0.0f)
-						a = Alpha;
-					else
-						a = CGeneral::GetATanOfXY(Length, CamRoof2 + 1.5f - TargetCoors.z);
-					while(a > PI) a -= 2*PI;
-					while(a < -PI) a += 2*PI;
-					DeltaAlpha = a - Alpha;
-				}
-			}
-		}
-
-		LastTargetAlphaWithCollisionOn = DeltaAlpha + Alpha;
-		LastTopAlphaSpeed = TopAlphaSpeed;
-		LastAlphaSpeedStep = AlphaSpeedStep;
-	}else{
-		if(PreviousNearCheckNearClipSmall)
-			RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
+		CColPoint point;
+		CEntity *entity = nil;
+		CVector Test = Source;
+		Test.z = TargetCoors.z + 0.2f + Length*Sin(CarAlpha+AlphaOffset) + m_fCloseInCarHeightOffset;
+		if(CWorld::ProcessVerticalLine(Test, CamTargetEntity->GetPosition().z, point, entity, true, false, false, false, false, false, nil)){
+			float sin = (point.point.z - TargetCoors.z - 0.2f - m_fCloseInCarHeightOffset)/Length;
+			CarAlpha = Asin(clamp(sin, -1.0f, 1.0f)) - AlphaOffset;
+			if(CarAlpha < 0.0f)
+				AlphaOffset += CarAlpha;
+		} 
 	}
 
-	WellBufferMe(LastTargetAlphaWithCollisionOn, &Alpha, &AlphaSpeed, LastTopAlphaSpeed, LastAlphaSpeedStep, true);
+	CarAlpha = CGeneral::LimitRadianAngle(CarAlpha);
+	if(CarAlpha < 0.0f) CarAlpha = 0.0f;
+	if(CarAlpha > DEGTORAD(89.0f)) CarAlpha = DEGTORAD(89.0f);
 
-	Source.z = TargetCoors.z + Sin(Alpha + ModeAlpha)*Length + m_fCloseInCarHeightOffset;
+	if(ResetStatics)
+		Alpha = CarAlpha;
+
+	float TargetAlpha = Alpha;
+	float DeltaAlpha = CarAlpha - TargetAlpha;
+	while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
+	while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
+	if(Abs(DeltaAlpha) > 0.0f && !TheCamera.m_bVehicleSuspenHigh)
+		TargetAlpha = CarAlpha;
+
+	if(isBike)
+		WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true);
+	else if(isHeli)
+		WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true);
+	else
+		WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.15f, 0.07f, true);
+
+	Source.z = TargetCoors.z + Sin(Alpha + AlphaOffset)*Length + m_fCloseInCarHeightOffset;
+	AlphaOffset -= AlphaDec;
 }
 
+//--MIAMI: done
 // Rotate cam behind the car when the car is moving forward
 bool
 CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation)
 {
+	float BetaMaxSpeed = 0.15f;
+	float BetaAcceleration = 0.007f;
 	bool MovingForward = false;
+	float MaxDiffBeta = DEGTORAD(160.0f);
 	CPhysical *phys = (CPhysical*)CamTargetEntity;
 
 	float ForwardSpeed = DotProduct(phys->GetForward(), phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));
 	if(ForwardSpeed > 0.02f)
 		MovingForward = true;
 
+	if(phys->IsVehicle() && (phys->GetModelIndex() == MI_SPARROW || phys->GetModelIndex() == MI_HUNTER)){
+		MaxDiffBeta = DEGTORAD(160.0f);
+		BetaMaxSpeed = 0.1f;
+		BetaAcceleration = 0.003f;
+		CVector speed = phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f));
+		speed.z = 0.0f;
+		if(50.0f*speed.Magnitude() > 3.13f)
+			TargetOrientation = CGeneral::GetATanOfXY(speed.x, speed.y);
+	}
+
 	float Dist = (Source - TargetCoors).Magnitude2D();
 
 	float DeltaBeta = TargetOrientation - Beta;
 	while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
 	while(DeltaBeta < -PI) DeltaBeta += 2*PI;
 
-	if(Abs(DeltaBeta) > DEGTORAD(20.0f) && MovingForward && TheCamera.m_uiTransitionState == 0)
+	if(Abs(DeltaBeta) > PI-MaxDiffBeta && MovingForward && TheCamera.m_uiTransitionState == 0)
 		m_bFixingBeta = true;
 
 	CPad *pad = CPad::GetPad(0);
@@ -1982,7 +1772,7 @@ CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation)
 			SetBeta = true;
 
 	if(m_bFixingBeta || SetBeta){
-		WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, 0.15f, 0.007f, true);
+		WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, BetaMaxSpeed, BetaAcceleration, true);
 
 		if(TheCamera.m_bCamDirectlyBehind && &TheCamera.Cams[TheCamera.ActiveCam] == this)
 			Beta = TargetOrientation;
@@ -2006,132 +1796,157 @@ CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation)
 	return true;
 }
 
-// Move the cam to avoid clipping through buildings
-bool
-CCam::FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation)
-{
-	CVector Target = TargetCoors;
-	bool UseEntityPos = false;
-	CVector EntityPos;
-	static CColPoint colPoint;
-	static bool LastObscured = false;
-
-	if(Mode == MODE_BEHINDCAR)
-		Target.z += TargetHeight/2.0f;
-	if(Mode == MODE_CAM_ON_A_STRING){
-		UseEntityPos = true;
-		Target.z += TargetHeight/2.0f;
-		EntityPos = CamTargetEntity->GetPosition();
-	}
-
-	CVector TempSource = Source;
-
-	bool Obscured1 = false;
-	bool Obscured2 = false;
-	bool Fix1 = false;
-	float Dist1 = 0.0f;
-	float Dist2 = 0.0f;
-	CEntity *ent;
-	if(m_bCollisionChecksOn || LastObscured){
-		Obscured1 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true);
-		if(Obscured1){
-			Dist1 = (Target - colPoint.point).Magnitude2D();
-			Fix1 = true;
-			if(UseEntityPos)
-				Obscured1 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true);
-		}else if(m_bFixingBeta){
-			float d = (TempSource - Target).Magnitude();
-			TempSource.x = Target.x - d*Cos(TargetOrientation);
-			TempSource.y = Target.y - d*Sin(TargetOrientation);
-
-			// same check again
-			Obscured2 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true);
-			if(Obscured2){
-				Dist2 = (Target - colPoint.point).Magnitude2D();
-				if(UseEntityPos)
-					Obscured2 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true);
-			}
-		}
-		LastObscured = Obscured1 || Obscured2;
-	}
-
-	// nothing to do
-	if(!LastObscured)
-		return false;
-
-	if(Fix1){
-		Source.x = Target.x - Cos(Beta)*Dist1;
-		Source.y = Target.y - Sin(Beta)*Dist1;
-		if(Mode == MODE_BEHINDCAR)
-			Source = colPoint.point;
-	}else{
-		WellBufferMe(Dist2, &m_fDistanceBeforeChanges, &DistanceSpeed, 0.2f, 0.025f, false);
-		Source.x = Target.x - Cos(Beta)*m_fDistanceBeforeChanges;
-		Source.y = Target.y - Sin(Beta)*m_fDistanceBeforeChanges;
-	}
-
-	if(ResetStatics){
-		m_fDistanceBeforeChanges = (Source - Target).Magnitude2D();
-		DistanceSpeed = 0.0f;
-		Source.x = colPoint.point.x;
-		Source.y = colPoint.point.y;
-	}
-	return true;
-}
+float FIRETRUCK_TRACKING_MULT = 0.1f;
+float fTestShiftHeliCamTarget = 0.6f;
+float TiltTopSpeed[] = { 0.035f, 0.035f, 0.001f, 0.005f, 0.035f };
+float TiltSpeedStep[] = { 0.016f, 0.016f, 0.0002f, 0.0014f, 0.016f };
+float TiltOverShoot[] = { 1.05f, 1.05f, 0.0f, 0.0f, 1.0f };
 
+//--MIAMI: done
 void
 CCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float)
 {
 	if(!CamTargetEntity->IsVehicle())
 		return;
 
+	// unused
+	// ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();
+
 	FOV = DefaultFOV;
 
 	if(ResetStatics){
 		AlphaSpeed = 0.0f;
-		if(TheCamera.m_bIdleOn)
-			TheCamera.m_uiTimeWeEnteredIdle = CTimer::GetTimeInMilliseconds();
+		m_fTilt = 0.0f;
+		m_fTiltSpeed = 0.0;
 	}
 
 	CBaseModelInfo *mi = CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());
 	CVector Dimensions = mi->GetColModel()->boundingBox.max - mi->GetColModel()->boundingBox.min;
-	float BaseDist = Dimensions.Magnitude2D();
-
 	CVector TargetCoors = CameraTarget;
-	TargetCoors.z += Dimensions.z - 0.1f;	// final
+	float BaseDist = Dimensions.Magnitude();
+
+	if(((CVehicle*)CamTargetEntity)->IsBike())
+		BaseDist *= 1.45f;
+	if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI &&
+	   CamTargetEntity->GetStatus() != STATUS_PLAYER_REMOTE)
+		TargetCoors += fTestShiftHeliCamTarget * CamTargetEntity->GetUp() * Dimensions.z;
+	else
+		TargetCoors.z += 0.8f*Dimensions.z;
+
 	Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
-	while(Alpha >= PI) Alpha -= 2*PI;
-	while(Alpha < -PI) Alpha += 2*PI;
-	while(Beta >= PI) Beta -= 2*PI;
-	while(Beta < -PI) Beta += 2*PI;
+	Alpha = CGeneral::LimitRadianAngle(Alpha);
+	Beta = CGeneral::LimitRadianAngle(Beta);
+
+	if(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired() &&
+	   ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed.Magnitude2D() < 0.01f){
+		float TargetBeta = CamTargetEntity->GetForward().Heading() - ((CAutomobile*)CamTargetEntity)->m_fCarGunLR + HALFPI;
+		TargetBeta = CGeneral::LimitRadianAngle(TargetBeta);
+		float DeltaBeta = TargetBeta - Beta;
+		if(DeltaBeta > PI) DeltaBeta -= TWOPI;
+		else if(DeltaBeta < -PI) DeltaBeta += TWOPI;
+		float dist = (TargetCoors - Source).Magnitude();
+		dist = FIRETRUCK_TRACKING_MULT*dist*clamp(DeltaBeta, -0.8f, 0.8f);
+		Source += dist*CrossProduct(Front, CVector(0.0f, 0.0f, 1.0f));
+	}
 
 	m_fDistanceBeforeChanges = (Source - TargetCoors).Magnitude2D();
 
 	Cam_On_A_String_Unobscured(TargetCoors, BaseDist);
 	WorkOutCamHeight(TargetCoors, TargetOrientation, Dimensions.z);
 	RotCamIfInFrontCar(TargetCoors, TargetOrientation);
-	FixCamIfObscured(TargetCoors, Dimensions.z, TargetOrientation);
 	FixCamWhenObscuredByVehicle(TargetCoors);
 
 	m_cvecTargetCoorsForFudgeInter = TargetCoors;
+	CVector OrigSource = Source;
+	if(CWorld::GetIsLineOfSightClear(CamTargetEntity->GetPosition(), m_cvecTargetCoorsForFudgeInter, true, false, false, true, false, false, true))
+		TheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV);
+	else
+		TheCamera.AvoidTheGeometry(OrigSource, CamTargetEntity->GetPosition(), Source, FOV);
+
 	Front = TargetCoors - Source;
 	Front.Normalise();
-	GetVectorsReadyForRW();
+
+	int appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();
+	int index = 0;
+	TheCamera.GetArrPosForVehicleType(appearance, index);
+
+	if(appearance == VEHICLE_APPEARANCE_HELI){
+		float TargetTilt = DotProduct(Front, ((CVehicle*)CamTargetEntity)->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));
+		CVector UpTarget = CamTargetEntity->GetUp();
+		UpTarget.Normalise();
+		int dir = TargetTilt < 0.0f ? -1 : 1;
+		if(m_fTilt != 0.0f)
+			TargetTilt += TiltOverShoot[index]*TargetTilt/m_fTilt * dir;
+		WellBufferMe(TargetTilt, &m_fTilt, &m_fTiltSpeed, TiltTopSpeed[index], TiltSpeedStep[index], false);
+
+		Up = CVector(0.0f, 0.0f, 1.0f) - (CVector(0.0f, 0.0f, 1.0f) - UpTarget)*m_fTilt;
+		Up.Normalise();
+		Front.Normalise();
+		CVector Left = CrossProduct(Up, Front);
+		Up = CrossProduct(Front, Left);
+		Up.Normalise();
+	}else{
+		float TargetRoll;
+		if(CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetDPadRight()){
+			float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());
+			if(fwdSpeed > 210.0f) fwdSpeed = 210.0f;
+			if(CPad::GetPad(0)->GetDPadLeft())
+				TargetRoll = DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle;
+			else
+				TargetRoll = -(DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle);
+			CVector FwdTarget = CamTargetEntity->GetForward();
+			FwdTarget.Normalise();
+			float AngleDiff = DotProduct(FwdTarget, Front);
+			AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));
+			TargetRoll *= fwdSpeed/210.0f * Sin(AngleDiff);
+		}else{
+			float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());
+			if(fwdSpeed > 210.0f) fwdSpeed = 210.0f;
+			TargetRoll = CPad::GetPad(0)->GetLeftStickX()/128.0f * fwdSpeed/210.0f;
+			CVector FwdTarget = CamTargetEntity->GetForward();
+			FwdTarget.Normalise();
+			float AngleDiff = DotProduct(FwdTarget, Front);
+			AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));
+			TargetRoll *= (DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle) * Sin(AngleDiff);
+		}
+
+		WellBufferMe(TargetRoll, &f_Roll, &f_rollSpeed, 0.15f, 0.07f, false);
+		Up = CVector(Cos(f_Roll + HALFPI), 0.0f, Sin(f_Roll + HALFPI));
+		Up.Normalise();
+		Front.Normalise();
+		CVector Left = CrossProduct(Up, Front);
+		Left.Normalise();
+		Up = CrossProduct(Front, Left);
+		Up.Normalise();
+	}
+
 	ResetStatics = false;
 }
 
+//--MIAMI: done
 // Basic Cam on a string algorithm
 void
 CCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist)
 {
-	CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth;
+	int id = CamTargetEntity->GetModelIndex();
+	float ExtraDist = 0.0f;
+	if(id == MI_RCRAIDER || id == MI_RCGOBLIN)
+		ExtraDist = INIT_RC_HELI_HORI_EXTRA;
+	else if(id == MI_RCBARON)
+		ExtraDist = INIT_RC_PLANE_HORI_EXTRA;
+
+	CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth + ExtraDist;
 	CA_MIN_DISTANCE = Min(BaseDist*0.6f, 3.5f);
+	if(CA_MIN_DISTANCE > CA_MAX_DISTANCE)
+		CA_MIN_DISTANCE = CA_MAX_DISTANCE - 0.05f;
 
 	CVector Dist = Source - TargetCoors;
 
 	if(ResetStatics)
 		Source = TargetCoors + Dist*(CA_MAX_DISTANCE + 1.0f);
 
+	Dist = Source - TargetCoors;
+
 	float Length = Dist.Magnitude2D();
 	if(Length < 0.001f){
 		// This probably shouldn't happen. reset view
@@ -2152,6 +1967,7 @@ CCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist)
 	}
 }
 
+//--MIAMI: done
 void
 CCam::FixCamWhenObscuredByVehicle(const CVector &TargetCoors)
 {
@@ -2159,7 +1975,7 @@ CCam::FixCamWhenObscuredByVehicle(const CVector &TargetCoors)
 	static float HeightFixerCarsObscuring = 0.0f;
 	static float HeightFixerCarsObscuringSpeed = 0.0f;
 	CColPoint colPoint;
-	CEntity *entity;
+	CEntity *entity = nil;
 
 	float HeightTarget = 0.0f;
 	if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, false, true, false, false, false, false, false)){
@@ -2406,7 +2222,6 @@ CCam::Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, f
 	ResetStatics = false;
 }
 
-// Identical to M16
 void
 CCam::Process_Rocket(const CVector &CameraTarget, float, float, float)
 {
@@ -2456,8 +2271,8 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float)
 	}else{
 		float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
 		float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
-		Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
-		Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
 	}
 	while(Beta >= PI) Beta -= 2*PI;
 	while(Beta < -PI) Beta += 2*PI;
@@ -2506,22 +2321,31 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float)
 	((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
 }
 
-// Identical to Rocket
+float fDuckingBackOffset = 0.5f;
+float fDuckingRightOffset = 0.18f;
+
+//--MIAMI: done
 void
 CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
 {
 	if(!CamTargetEntity->IsPed())
 		return;
 
+	float BackOffset = 0.3f;
 	static bool FailedTestTwelveFramesAgo = false;
 	RwV3d HeadPos;
 	CVector TargetCoors;
 
+	bool isAttached = ((CPed*)CamTargetEntity)->IsPlayer() && ((CPed*)CamTargetEntity)->m_attachedTo;
+
 	FOV = DefaultFOV;
 	TargetCoors = CameraTarget;
 
 	if(ResetStatics){
-		Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+		if(isAttached)
+			Beta = 0.0f;
+		else
+			Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
 		Alpha = 0.0f;
 		m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
 		FailedTestTwelveFramesAgo = false;
@@ -2531,14 +2355,6 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
 		ResetStatics = false;
 	}
 
-#ifndef GTA3_1_1_PATCH
-	((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD);
-	Source = HeadPos;
-	Source.z += 0.1f;
-	Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
-	Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
-#endif
-
 	// Look around
 	bool UseMouse = false;
 	float MouseX = CPad::GetPad(0)->GetMouseX();
@@ -2555,73 +2371,151 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
 	if(UseMouse){
 		Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
 		Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
+	}else if(Mode == MODE_HELICANNON_1STPERSON){
+		LookLeftRight /= 128.0f;
+		LookUpDown /= 128.0f;
+		Beta += LookLeftRight*Abs(LookLeftRight)*0.56f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Alpha += LookUpDown*Abs(LookUpDown)*0.48f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
 	}else{
 		float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
 		float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
-		Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
-		Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
 	}
 	while(Beta >= PI) Beta -= 2*PI;
 	while(Beta < -PI) Beta += 2*PI;
 	if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
 	if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
 
-#ifdef GTA3_1_1_PATCH
-	HeadPos.x = 0.0f;
-	HeadPos.y = 0.0f;
-	HeadPos.z = 0.0f;
-	((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
-	Source = HeadPos;
-	Source.z += 0.1f;
-	Source.x -= 0.19f * Cos(m_fInitialPlayerOrientation);
-	Source.y -= 0.19f * Sin(m_fInitialPlayerOrientation);
-#endif
+	if(((CPed*)CamTargetEntity)->bIsDucking)
+		BackOffset = 0.8f;
+	if(isAttached){
+		CMatrix mat, rot;
+		CPed *TargetPed = (CPed*)CamTargetEntity;
+		TargetPed->PositionAttachedPed();
+		CamTargetEntity->GetMatrix().UpdateRW();
+		CamTargetEntity->UpdateRwFrame();
+		CamTargetEntity->UpdateRpHAnim();
 
-	TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
-	TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
-	TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
-	Front = TargetCoors - Source;
-	Front.Normalise();
-	Source += Front*0.4f;
+		HeadPos.x = 0.0f;
+		HeadPos.y = 0.0f;
+		HeadPos.z = 0.0f;
+		TargetPed->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
+		Source = HeadPos;
+		Source += 0.1f*CamTargetEntity->GetUp();
+		Source -= BackOffset*CamTargetEntity->GetForward();
 
-	if(m_bCollisionChecksOn){
-		if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
-			RwCameraSetNearClipPlane(Scene.camera, 0.4f);
-			FailedTestTwelveFramesAgo = true;
+		if(TargetPed->m_attachRotStep < PI){
+			if(Beta > TargetPed->m_attachRotStep){
+				Beta = TargetPed->m_attachRotStep;
+				CAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo;
+				if(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){
+					float heliOrient = heli->m_fHeliOrientation + CTimer::GetTimeStep()*0.01f;
+					if(heliOrient < 0.0f) heliOrient += TWOPI;
+					else if(heliOrient > TWOPI) heliOrient -= TWOPI;
+					heli->SetHeliOrientation(heliOrient);
+				}
+			}else if(Beta < -TargetPed->m_attachRotStep){
+				Beta = -TargetPed->m_attachRotStep;
+				CAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo;
+				if(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){
+					float heliOrient = heli->m_fHeliOrientation - CTimer::GetTimeStep()*0.01f;
+					if(heliOrient < 0.0f) heliOrient += TWOPI;
+					else if(heliOrient > TWOPI) heliOrient -= TWOPI;
+					heli->SetHeliOrientation(heliOrient);
+				}
+			}
 		}else{
-			CVector TestPoint;
-			TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
-			TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
-			TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
-			if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+			while(Beta < -PI) Beta += 2*PI;
+			while(Beta >= PI) Beta -= 2*PI;
+		}
+
+		mat = TargetPed->m_attachedTo->GetMatrix();
+		rot.SetRotateX(Alpha);
+		switch(TargetPed->m_attachType){
+		case 1: rot.RotateZ(Beta + HALFPI); break;
+		case 2: rot.RotateZ(Beta + PI); break;
+		case 3: rot.RotateZ(Beta - HALFPI); break;
+		}
+		mat = mat * rot;
+		Front = mat.GetForward();
+		Up = mat.GetUp();
+		TargetCoors = Source + 3.0f*Front;
+		RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+
+		float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
+		((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
+		((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
+	}else{
+		CamTargetEntity->GetMatrix().UpdateRW();
+		CamTargetEntity->UpdateRwFrame();
+		CamTargetEntity->UpdateRpHAnim();
+		HeadPos.x = 0.0f;
+		HeadPos.y = 0.0f;
+		HeadPos.z = 0.0f;
+		((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
+		Source = HeadPos;
+		Source.z += 0.1f;
+		if(((CPed*)CamTargetEntity)->bIsDucking){
+			Source.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x;
+			Source.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y;
+			Source.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x;
+			Source.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y;
+		}else{
+			Source.x -= BackOffset*CamTargetEntity->GetForward().x;
+			Source.y -= BackOffset*CamTargetEntity->GetForward().y;
+		}
+
+		TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
+		TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
+		TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
+		Front = TargetCoors - Source;
+		Front.Normalise();
+		Source += Front*0.4f;
+
+		if(m_bCollisionChecksOn){
+			if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
 				RwCameraSetNearClipPlane(Scene.camera, 0.4f);
 				FailedTestTwelveFramesAgo = true;
 			}else{
-				TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
-				TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
+				CVector TestPoint;
+				TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
+				TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
 				TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
 				if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
 					RwCameraSetNearClipPlane(Scene.camera, 0.4f);
 					FailedTestTwelveFramesAgo = true;
-				}else
-					FailedTestTwelveFramesAgo = false;
+				}else{
+					TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
+					TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
+					TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+					if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+						RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+						FailedTestTwelveFramesAgo = true;
+					}else
+						FailedTestTwelveFramesAgo = false;
+				}
 			}
 		}
+
+		if(FailedTestTwelveFramesAgo)
+			RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+		Source -= Front*0.4f;
+
+		GetVectorsReadyForRW();
+		float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
+		((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
+		((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
 	}
-
-	if(FailedTestTwelveFramesAgo)
-		RwCameraSetNearClipPlane(Scene.camera, 0.4f);
-	Source -= Front*0.4f;
-
-	GetVectorsReadyForRW();
-	float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
-	((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
-	((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
 }
 
+float fBike1stPersonOffsetZ = 0.15f;
+
+//--MIAMI: done
 void
-CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, float, float)
+CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar)
 {
+	float BackOffset = 0.3f;
 	static float DontLookThroughWorldFixer = 0.0f;
 	CVector TargetCoors;
 
@@ -2639,6 +2533,7 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl
 			Alpha = 0.0f;
 			m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
 		}
+		TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;
 		DontLookThroughWorldFixer = 0.0f;
 	}
 
@@ -2659,23 +2554,34 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl
 			ResetStatics = false;
 		}
 
+		CamTargetEntity->GetMatrix().UpdateRW();
+		CamTargetEntity->UpdateRwFrame();
+		CamTargetEntity->UpdateRpHAnim();
+
 		((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
 		Source = HeadPos;
 		Source.z += 0.1f;
-		Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
-		Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
+		if(((CPed*)CamTargetEntity)->bIsDucking){
+			Source.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x;
+			Source.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y;
+			Source.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x;
+			Source.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y;
+		}else{
+			Source.x -= BackOffset*CamTargetEntity->GetForward().x;
+			Source.y -= BackOffset*CamTargetEntity->GetForward().y;
+		}
 
 		float LookLeftRight, LookUpDown;
 		LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
 		LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
 		float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
 		float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
-		Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
-		Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
 		while(Beta >= PI) Beta -= 2*PI;
 		while(Beta < -PI) Beta += 2*PI;
 		if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
-		if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
+		else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
 
 		TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
 		TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
@@ -2719,16 +2625,48 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl
 		((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
 	}else{
 		assert(CamTargetEntity->IsVehicle());
+
+		if(((CVehicle*)CamTargetEntity)->IsBike() &&
+		   (((CBike*)CamTargetEntity)->bWheelieCam || TheCamera.m_fAvoidTheGeometryProbsTimer > 0.0f)){
+			if(CPad::GetPad(0)->GetLeftShoulder2() || CPad::GetPad(0)->GetRightShoulder2()){
+				TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;
+				((CBike*)CamTargetEntity)->bWheelieCam = false;
+			}else if(Process_WheelCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar)){
+				if(((CBike*)CamTargetEntity)->bWheelieCam)
+					TheCamera.m_fAvoidTheGeometryProbsTimer = 50.0f;
+				else{
+					TheCamera.m_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep();
+					((CBike*)CamTargetEntity)->bWheelieCam = true;
+				}
+				return;
+			}else{
+				TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;
+				((CBike*)CamTargetEntity)->bWheelieCam = false;
+			}
+		}
+
+		CMatrix *matrix = &CamTargetEntity->GetMatrix();
+		if(((CVehicle*)CamTargetEntity)->IsBike()){
+			((CBike*)CamTargetEntity)->CalculateLeanMatrix();
+			matrix = &((CBike*)CamTargetEntity)->m_leanMatrix;
+		}
+
 		CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());
 		CVector CamPos = mi->GetFrontSeatPosn();
 		CamPos.x = 0.0f;
-		CamPos.y += -0.08f;
+		CamPos.y += 0.08f;
 		CamPos.z += 0.62f;
 		FOV = 60.0f;
-		Source = Multiply3x3(CamTargetEntity->GetMatrix(), CamPos);
+		Source = Multiply3x3(*matrix, CamPos);
 		Source += CamTargetEntity->GetPosition();
 		if(((CVehicle*)CamTargetEntity)->IsBoat())
 			Source.z += 0.5f;
+		else if(((CVehicle*)CamTargetEntity)->IsBike() && ((CVehicle*)CamTargetEntity)->pDriver){
+			CVector Neck(0.0f, 0.0f, 0.0f);
+			((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(*(RwV3d*)&Neck, PED_NECK);
+			Neck += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed * CTimer::GetTimeStep();
+			Source.z = Neck.z + fBike1stPersonOffsetZ;
+		}
 
 		if(((CVehicle*)CamTargetEntity)->IsUpsideDown()){
 			if(DontLookThroughWorldFixer < 0.5f)
@@ -2746,9 +2684,9 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl
 				DontLookThroughWorldFixer = 0.0f;
 		}
 		Source.z += DontLookThroughWorldFixer;
-		Front = CamTargetEntity->GetForward();
+		Front = matrix->GetForward();
 		Front.Normalise();
-		Up = CamTargetEntity->GetUp();
+		Up = matrix->GetUp();
 		Up.Normalise();
 		CVector Right = CrossProduct(Front, Up);
 		Right.Normalise();
@@ -2849,8 +2787,8 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float,
 		}else{
 			float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
 			float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
-			Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
-			Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+			Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+			Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
 		}
 		while(Beta >= PI) Beta -= 2*PI;
 		while(Beta < -PI) Beta += 2*PI;
@@ -2952,8 +2890,8 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float
 	}else{
 		float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
 		float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
-		Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
-		Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+		Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
 	}
 	while(Beta >= PI) Beta -= 2*PI;
 	while(Beta < -PI) Beta += 2*PI;
@@ -3043,6 +2981,13 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float
 	((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
 }
 
+float INIT_SYPHON_GROUND_DIST = 2.419f;
+float INIT_SYPHON_ALPHA_OFFSET = -DEGTORAD(3.0f);
+float INIT_SYPHON_DEGREE_OFFSET = -DEGTORAD(30.0f);
+float FrontOffsetSyphon = -DEGTORAD(25.5f);	// unused
+float INIT_SYPHON_Z_OFFSET = -0.5f;
+
+//--MIAMI: done
 void
 CCam::Process_Syphon(const CVector &CameraTarget, float, float, float)
 {
@@ -3053,82 +2998,123 @@ CCam::Process_Syphon(const CVector &CameraTarget, float, float, float)
 
 	static bool CameraObscured = false;
 	// unused FailedClippingTestPrevously
-	static float BetaOffset = DEGTORAD(18.0f);
+	static float BetaOffset = INIT_SYPHON_DEGREE_OFFSET;
 	// unused AngleToGoTo
 	// unused AngleToGoToSpeed
 	// unused DistBetweenPedAndPlayerPreviouslyOn
-	static float HeightDown = -0.5f;
-	static float PreviousDistForInter;
+	static float HeightDown = INIT_SYPHON_Z_OFFSET;
+	static float AlphaOffset = INIT_SYPHON_ALPHA_OFFSET;
+	static bool NegateBetaOffset = true;
 	CVector TargetCoors;
-	CVector2D vDist;
-	float fDist, fAimingDist;
+	float fAimingDist;
 	float TargetAlpha;
-	CColPoint colPoint;
-	CEntity *entity;
 
+	bool StandingOnMovingThing = false;
 	TargetCoors = CameraTarget;
+	AlphaOffset = INIT_SYPHON_ALPHA_OFFSET;
+	float GroundDist = INIT_SYPHON_GROUND_DIST;
 
-	if(TheCamera.Cams[TheCamera.ActiveCam].Mode != MODE_SYPHON)
-		return;
-
-	vDist = Source - TargetCoors;
-	fDist = vDist.Magnitude();
-	if(fDist == 0.0f)
-		Source = TargetCoors + CVector(1.0f, 1.0f, 0.0f);
-	else
-		Source = TargetCoors + CVector(vDist.x/fDist * 1.7f, vDist.y/fDist * 1.7f, 0.0f);
-	if(fDist > 1.7f)
-		fDist = 1.7f;
-
-	Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
 	while(Beta >= PI) Beta -= 2*PI;
 	while(Beta < -PI) Beta += 2*PI;
 
 	float NewBeta = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y) + PI;
 	if(ResetStatics){
-		CameraObscured = false;
-		float TestBeta1 = NewBeta - BetaOffset - Beta;
-		float TestBeta2 = NewBeta + BetaOffset - Beta;
-		MakeAngleLessThan180(TestBeta1);
-		MakeAngleLessThan180(TestBeta2);
-		if(Abs(TestBeta1) < Abs(TestBeta2))
-			BetaOffset = -BetaOffset;
+		BetaOffset = INIT_SYPHON_DEGREE_OFFSET;
+		Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
 		// some unuseds
 		ResetStatics = false;
 	}
+	if(NegateBetaOffset)
+		BetaOffset = -INIT_SYPHON_DEGREE_OFFSET;
 	Beta = NewBeta + BetaOffset;
 	Source = TargetCoors;
-	Source.x += 1.7f*Cos(Beta);
-	Source.y += 1.7f*Sin(Beta);
+	Source.x += GroundDist*Cos(Beta);
+	Source.y += GroundDist*Sin(Beta);
+	CPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface;
+	if(ground && (ground->IsVehicle() || ground->IsObject()))
+		StandingOnMovingThing = true;
 	TargetCoors.z += m_fSyphonModeTargetZOffSet;
+
+	bool PlayerTooClose = false;
 	fAimingDist = (TheCamera.m_cvecAimingTargetCoors - TargetCoors).Magnitude2D();
-	if(fAimingDist < 6.5f)
+	if(fAimingDist < 6.5f){
 		fAimingDist = 6.5f;
+		PlayerTooClose = true;
+	}
 	TargetAlpha = CGeneral::GetATanOfXY(fAimingDist, TheCamera.m_cvecAimingTargetCoors.z - TargetCoors.z);
+	if(ResetStatics)	// BUG: can never happen
+		Alpha = -TargetAlpha;
 	while(TargetAlpha >= PI) TargetAlpha -= 2*PI;
 	while(TargetAlpha < -PI) TargetAlpha += 2*PI;
+	while(Alpha >= PI) Alpha -= 2*PI;
+	while(Alpha < -PI) Alpha += 2*PI;
 
 	// inlined
-	WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f, 0.015f, true);
+	if(StandingOnMovingThing)
+		WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f/2.0f, 0.015f/2.0f, true);
+	else
+		WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f, 0.015f, true);
 
-	Source.z += fDist*Sin(Alpha) + fDist*0.2f;
+	Source.z += GroundDist*Sin(Alpha+AlphaOffset) + GroundDist*0.2f;
 	if(Source.z < TargetCoors.z + HeightDown)
 		Source.z = TargetCoors.z + HeightDown;
 
-	CameraObscured = CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true);
-	// PreviousDistForInter unused
-	if(CameraObscured){
-		PreviousDistForInter = (TargetCoors - colPoint.point).Magnitude2D();
-		Source = colPoint.point;
-	}else
-		PreviousDistForInter = 1.7f;
+	if(!PlayerTooClose){
+		CColPoint point;
+		CEntity *entity = nil;
+		CWorld::pIgnoreEntity = CamTargetEntity;
+		if(CWorld::ProcessLineOfSight(TheCamera.m_cvecAimingTargetCoors, Source, point, entity, true, false, false, true, false, false, true)){
+			CVector TestFront = TheCamera.m_cvecAimingTargetCoors - Source;
+			TestFront.Normalise();
+			CVector CamToPlayer = CameraTarget - Source;
+			CVector CamToCol = point.point - Source;
+			if(DotProduct(TestFront, CamToCol) > DotProduct(TestFront, CamToPlayer)){
+				// collision is beyond player
+				float ColDist = (TheCamera.m_cvecAimingTargetCoors - point.point).Magnitude();
+				CVector PlayerToTarget = TheCamera.m_cvecAimingTargetCoors - CameraTarget;
+				float PlayerToTargetDist = PlayerToTarget.Magnitude();
+				PlayerToTarget.Normalise();
+				CVector Center = TheCamera.m_cvecAimingTargetCoors - ColDist*PlayerToTarget;
+				float Radius = (point.point - Center).Magnitude();
+				if(CWorld::TestSphereAgainstWorld(Center, Radius, nil, true, false, false, true, false, true)){
+					CVector LineToCol = gaTempSphereColPoints[0].point - Center;
+					LineToCol -= DotProduct(LineToCol, PlayerToTarget)*PlayerToTarget;
+					// unused
+					CVector LineToPrevCol = point.point - Center;
+					LineToPrevCol -= DotProduct(LineToPrevCol, PlayerToTarget)*PlayerToTarget;
+					float LineDist = LineToCol.Magnitude();
+					float NewBetaOffset = 0.0f;
+					if(LineDist > 0.0f && ColDist > 0.1f){
+						// scale offset at center to offset at player
+						float DistOffset = LineDist/ColDist * PlayerToTargetDist;
+						// turn into an angle
+						NewBetaOffset = 0.9f*Asin(Min(DistOffset/GroundDist, 1.0f));
+					}
+					if(NewBetaOffset < BetaOffset){
+						float Ratio = NewBetaOffset / BetaOffset;
+						BetaOffset = NewBetaOffset;
+						Beta = NewBeta + NewBetaOffset;
+						GroundDist *= Max(Ratio, 0.5f);
+						Source.x = TargetCoors.x +  GroundDist*Cos(Beta);
+						Source.y = TargetCoors.y +  GroundDist*Sin(Beta);
+						Source.z += (1.0f-Ratio)*0.5f;
+					}
+				}
+			}
+		}
+		CWorld::pIgnoreEntity = nil;
+	}
 
-	m_cvecTargetCoorsForFudgeInter = TargetCoors;
-	Front = TargetCoors - Source;
-	m_fMinDistAwayFromCamWhenInterPolating = Front.Magnitude2D();
-	if(m_fMinDistAwayFromCamWhenInterPolating < 1.1f)
-		RwCameraSetNearClipPlane(Scene.camera, Max(m_fMinDistAwayFromCamWhenInterPolating - 0.35f, 0.05f));
+	Front = TheCamera.m_cvecAimingTargetCoors - Source;
+	float TargetDistGround = Front.Magnitude2D();
 	Front.Normalise();
+	m_cvecTargetCoorsForFudgeInter = Source + TargetDistGround*Front;
+	m_cvecTargetCoorsForFudgeInter.z = TargetCoors.z;
+
+	CVector OrigSource = Source;
+	TheCamera.AvoidTheGeometry(OrigSource, CameraTarget + CVector(0.0f, 0.0f, 0.75f), Source, FOV);
+	Source.z = OrigSource.z;
+
 	GetVectorsReadyForRW();
 }
 
@@ -3589,7 +3575,7 @@ CCam::Process_FlyBy(const CVector&, float, float, float)
 	}
 }
 
-void
+bool
 CCam::Process_WheelCam(const CVector&, float, float, float)
 {
 	FOV = DefaultFOV;
@@ -3612,6 +3598,7 @@ CCam::Process_WheelCam(const CVector&, float, float, float)
 
 	float Roll = Cos((CTimer::GetTimeInMilliseconds()&0x1FFFF)/(float)0x1FFFF * TWOPI);
 	Up = Cos(Roll*0.4f)*NewUp + Sin(Roll*0.4f)*Left;
+	return true;
 }
 
 void
@@ -4481,8 +4468,8 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
 		BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;
 		AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;
 	}else{
-		BetaOffset = LookLeftRight * fStickSens * (0.5f/10.0f) * FOV/80.0f * CTimer::GetTimeStep();
-		AlphaOffset = LookUpDown * fStickSens * (0.3f/10.0f) * FOV/80.0f * CTimer::GetTimeStep();
+		BetaOffset = LookLeftRight * fStickSens * (1.0f/20.0f) * FOV/80.0f * CTimer::GetTimeStep();
+		AlphaOffset = LookUpDown * fStickSens * (0.6f/20.0f) * FOV/80.0f * CTimer::GetTimeStep();
 	}
 
 	// Stop centering once stick has been touched
@@ -4556,7 +4543,7 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
 	if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, true, true, true, false, false, true)){
 		float PedColDist = (TargetCoors - colPoint.point).Magnitude();
 		float ColCamDist = CamDist - PedColDist;
-		if(entity->IsPed() && ColCamDist > 1.0f){
+		if(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){
 			// Ped in the way but not clipping through
 			if(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, true, true, true, false, false, true)){
 				PedColDist = (TargetCoors - colPoint.point).Magnitude();
@@ -4595,6 +4582,8 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
 			Source += (TargetCoors - Source)*0.3f;
 
 		// Keep testing
+		Near = RwCameraGetNearClipPlane(Scene.camera);
+		radius = ViewPlaneWidth*Near;
 		entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
 
 		i++;
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 9ebec1a6..423a3da6 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -20,6 +20,7 @@
 #include "Replay.h"
 #include "CutsceneMgr.h"
 #include "Renderer.h"
+#include "Timecycle.h"
 #include "MBlur.h"
 #include "Text.h"
 #include "Hud.h"
@@ -61,6 +62,8 @@ enum
 CCamera TheCamera;
 bool CCamera::m_bUseMouse3rdPerson = true;
 bool bDidWeProcessAnyCinemaCam;
+float CCamera::m_fMouseAccelHorzntl;
+float CCamera::m_fMouseAccelVertical;
 float CCamera::m_f3rdPersonCHairMultX;
 float CCamera::m_f3rdPersonCHairMultY;
 
@@ -75,26 +78,16 @@ float CCamera::m_f3rdPersonCHairMultY;
 
 CCamera::CCamera(void)
 {
-#ifdef GTA3_1_1_PATCH
-	m_fMouseAccelHorzntl = 0.0025f;
-	m_fMouseAccelVertical = 0.003f;
-#endif
 	Init();
 }
 
+//--MIAMI: done
 void
 CCamera::Init(void)
 {
-#ifdef GTA3_1_1_PATCH
-	float fMouseAccelHorzntl = m_fMouseAccelHorzntl;
-	float fMouseAccelVertical = m_fMouseAccelVertical;
-#endif
 	memset(this, 0, sizeof(CCamera));	// this is fine, no vtable
-#ifdef GTA3_1_1_PATCH
-	m_fMouseAccelHorzntl = fMouseAccelHorzntl;
-	m_fMouseAccelVertical = fMouseAccelVertical;
-#endif
 	m_pRwCamera = nil;
+	m_bPlayerWasOnBike = false;
 	m_1rstPersonRunCloseToAWall = false;
 	m_fPositionAlongSpline = 0.0f;
 	m_bCameraJustRestored = false;
@@ -103,8 +96,22 @@ CCamera::Init(void)
 	Cams[2].Init();
 	Cams[0].Mode = CCam::MODE_FOLLOWPED;
 	Cams[1].Mode = CCam::MODE_FOLLOWPED;
-	unknown = 0;
-	m_bJustJumpedOutOf1stPersonBecauseOfTarget = 0;
+	m_bEnable1rstPersonCamCntrlsScript = false;
+	m_bAllow1rstPersonWeaponsCamera = false;
+	m_bVehicleSuspenHigh = false;
+	Cams[0].m_fMinRealGroundDist = 1.85f;
+	// TODO: what weird value is this?
+	Cams[0].m_fTargetCloseInDist = 2.0837801f - Cams[0].m_fMinRealGroundDist;
+	Cams[0].m_fTargetZoomGroundOne = 0.25f;
+	Cams[0].m_fTargetZoomGroundTwo = 1.5f;
+	Cams[0].m_fTargetZoomGroundThree = 4.0f;
+	Cams[0].m_fTargetZoomOneZExtra = -0.14f;
+	Cams[0].m_fTargetZoomTwoZExtra = 0.16f;
+	Cams[0].m_fTargetZoomThreeZExtra = 0.25f;
+	// TODO: another weird value
+	Cams[0].m_fTargetZoomZCloseIn = 0.90040702f;
+	m_bMoveCamToAvoidGeom = false;
+	SetMotionBlur(CTimeCycle::GetBlurRed(), CTimeCycle::GetBlurGreen(), CTimeCycle::GetBlurBlue(), m_motionBlur, MBLUR_NORMAL);
 	ClearPlayerWeaponMode();
 	m_bInATunnelAndABigVehicle = false;
 	m_iModeObbeCamIsInForCar = OBBE_INVALID;
@@ -122,8 +129,8 @@ CCamera::Init(void)
 	Cams[1].m_fPlayerVelocity = 0.0f;
 	Cams[2].m_fPlayerVelocity = 0.0f;
 	m_bHeadBob = false;
-	m_fFractionInterToStopMovingTarget = 0.25f;
-	m_fFractionInterToStopCatchUpTarget = 0.75f;
+	m_fFractionInterToStopMoving = 0.25f;
+	m_fFractionInterToStopCatchUp = 0.75f;
 	m_fGaitSwayBuffer = 0.85f;
 	m_bScriptParametersSetForInterPol = false;
 	m_uiCamShakeStart = 0;
@@ -168,10 +175,11 @@ CCamera::Init(void)
 		m_bMusicFading = false;
 		m_fTimeToFadeMusic = 0.0f;
 		m_fFLOATingFadeMusic = 0.0f;
+		m_fMouseAccelHorzntl = 0.003f;
+		m_fMouseAccelVertical = 0.0025f;
 	}
-	m_bMoveCamToAvoidGeom = false;
 	if(FrontEndMenuManager.m_bWantToRestart)
-		m_bMoveCamToAvoidGeom = true;
+		m_fTimeToFadeMusic = 0.0f;
 	m_bStartingSpline = false;
 	m_iTypeOfSwitch = INTERPOLATION;
 	m_bUseScriptZoomValuePed = false;
@@ -190,6 +198,8 @@ CCamera::Init(void)
 	m_uiTimeLastChange = 0;
 	m_uiTimeWeEnteredIdle = 0;
 	m_bIdleOn = false;
+	m_uiTimeWeLeftIdle_StillNoInput = 0;
+	m_uiTimeWeEnteredIdle = 0;
 	LODDistMultiplier = 1.0f;
 	m_bCamDirectlyBehind = false;
 	m_bCamDirectlyInFront = false;
@@ -209,12 +219,10 @@ CCamera::Init(void)
 	m_uiTransitionState = 0;
 	m_uiTimeTransitionStart = 0;
 	m_bLookingAtPlayer = true;
-#ifndef GTA3_1_1_PATCH
-	m_fMouseAccelHorzntl = 0.0025f;
-	m_fMouseAccelVertical = 0.003f;
-#endif
 	m_f3rdPersonCHairMultX = 0.53f;
 	m_f3rdPersonCHairMultY = 0.4f;
+	m_fAvoidTheGeometryProbsTimer = 0.0f;
+	m_nAvoidTheGeometryProbsDirn = 0;
 }
 
 void
@@ -322,12 +330,12 @@ CCamera::Process(void)
 			currentTime = m_uiTransitionDuration;
 		float fractionInter = (float) currentTime / m_uiTransitionDuration;
 
-		if(fractionInter <= m_fFractionInterToStopMovingTarget){
+		if(fractionInter <= m_fFractionInterToStopMoving){
 			float inter;
-			if(m_fFractionInterToStopMovingTarget == 0.0f)
+			if(m_fFractionInterToStopMoving == 0.0f)
 				inter = 0.0f;
 			else
-				inter = (m_fFractionInterToStopMovingTarget - fractionInter)/m_fFractionInterToStopMovingTarget;
+				inter = (m_fFractionInterToStopMoving - fractionInter)/m_fFractionInterToStopMoving;
 			inter = 0.5f - 0.5*Cos(inter*PI);	// smooth it
 
 			m_vecSourceWhenInterPol = m_cvecStartingSourceForInterPol + inter*m_cvecSourceSpeedAtStartInter;
@@ -381,12 +389,12 @@ CCamera::Process(void)
 			}
 			CamUp.Normalise();
 			FOV = m_fFOVWhenInterPol;
-		}else if(fractionInter > m_fFractionInterToStopMovingTarget && fractionInter <= 1.0f){
+		}else if(fractionInter > m_fFractionInterToStopMoving && fractionInter <= 1.0f){
 			float inter;
-			if(m_fFractionInterToStopCatchUpTarget == 0.0f)
+			if(m_fFractionInterToStopCatchUp == 0.0f)
 				inter = 0.0f;
 			else
-				inter = (fractionInter - m_fFractionInterToStopMovingTarget)/m_fFractionInterToStopCatchUpTarget;
+				inter = (fractionInter - m_fFractionInterToStopMoving)/m_fFractionInterToStopCatchUp;
 			inter = 0.5f - 0.5*Cos(inter*PI);	// smooth it
 
 			CamSource = m_vecSourceWhenInterPol + inter*(Cams[ActiveCam].Source - m_vecSourceWhenInterPol);
@@ -1610,7 +1618,7 @@ CCamera::UpdateSoundDistances(void)
 	}
 	f = (n + 1) / 6.0f;
 	SoundDistUp = (1.0f-f)*SoundDistUpAsReadOld + f*SoundDistUpAsRead;
-
+/*
 	// check left
 	n = (CTimer::GetFrameCounter()+2) % 12;
 	if(n == 0){
@@ -1637,6 +1645,7 @@ CCamera::UpdateSoundDistances(void)
 	}
 	f = (n + 1) / 6.0f;
 	SoundDistRight = (1.0f-f)*SoundDistRightAsReadOld + f*SoundDistRightAsRead;
+*/
 }
 
 void
@@ -1681,6 +1690,129 @@ CamShakeNoPos(CCamera *cam, float strength)
 	}
 }
 
+bool bAvoidTest1 = false;
+bool bAvoidTest2 = false;	// unused
+bool bAvoidTest3 = false;	// unused
+float fRangePlayerRadius = 0.5f;
+float fCloseNearClipLimit = 0.15f;
+float fAvoidTweakFOV = 1.15f;
+float fAvoidProbTimerDamp = 0.9f;
+
+//--MIAMI: done
+void
+CCamera::AvoidTheGeometry(const CVector &Source, const CVector &TargetPos, CVector &NewSource, float FOV)
+{
+	float Beta = 0.0f;
+	float Alpha = 0.0f;
+
+	CVector vDist = TargetPos - Source;
+	m_vecClearGeometryVec = CVector(0.0f, 0.0f, 0.0f);
+	float fDist = vDist.Magnitude();
+	float fDistOnGround = vDist.Magnitude2D();
+	if(vDist.x == 0.0f && vDist.y == 0.0f)
+		Beta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y);
+	else
+		Beta = CGeneral::GetATanOfXY(vDist.x, vDist.y);
+	if(fDistOnGround != 0.0f || vDist.z != 0.0f)
+		Alpha = CGeneral::GetATanOfXY(fDistOnGround, vDist.z);
+	CVector Front(Cos(Alpha)*Cos(Beta), Cos(Alpha)*Sin(Beta), Sin(Alpha));
+	NewSource = TargetPos - Front*fDist;
+	Front.Normalise();
+
+	// Clip camera source
+	CColPoint point;
+	CEntity *entity = nil;
+	CWorld::pIgnoreEntity = pTargetEntity;
+	if(CWorld::ProcessLineOfSight(TargetPos, NewSource, point, entity, true, false, false, true, false, false, true)){
+		CVector ClipPoint1 = point.point;
+		NewSource = point.point;
+		if(!bAvoidTest1){
+			if(CWorld::ProcessLineOfSight(NewSource, TargetPos, point, entity, false, true, true, true, false, false, true)){
+				if((NewSource - point.point).Magnitude() < RwCameraGetNearClipPlane(Scene.camera))
+					NewSource = point.point;
+				else if((NewSource - ClipPoint1).Magnitude() < RwCameraGetNearClipPlane(Scene.camera))
+					NewSource = ClipPoint1;
+			}
+		}
+	}
+	CWorld::pIgnoreEntity = nil;
+
+
+	vDist = TargetPos - NewSource;
+	fDist = vDist.Magnitude();
+	if(FindPlayerPed())
+		if(fDist - fRangePlayerRadius < RwCameraGetNearClipPlane(Scene.camera))
+			RwCameraSetNearClipPlane(Scene.camera, Max(fDist - fRangePlayerRadius, fCloseNearClipLimit));
+
+
+	static float fClearGeomAmount;
+	static float fClearGeomAmountSpeed;
+	float Near = RwCameraGetNearClipPlane(Scene.camera);
+	float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);
+	float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fAvoidTweakFOV;
+	CVector Center = NewSource + Front*Near;
+	float fClearGeomTarget = 0.0f;
+	if(CWorld::TestSphereAgainstWorld(Center, ViewPlaneWidth, nil, true, false, false, true, false, true)){
+		CVector CamToCol = gaTempSphereColPoints[0].point - NewSource;
+		float FrontDist = DotProduct(CamToCol, Front);
+		CVector CenterToCol = gaTempSphereColPoints[0].point - Center;
+		if(FrontDist < DEFAULT_NEAR && FrontDist > fCloseNearClipLimit){
+			if(FrontDist < RwCameraGetNearClipPlane(Scene.camera))
+				RwCameraSetNearClipPlane(Scene.camera, FrontDist);
+		}else if(FrontDist < fCloseNearClipLimit)
+			RwCameraSetNearClipPlane(Scene.camera, fCloseNearClipLimit);
+
+		float ColDepth = ViewPlaneWidth - CenterToCol.Magnitude();	// amount of radius in collision
+		CenterToCol.Normalise();
+		CVector Normal = gaTempSphereColPoints[0].normal;
+		Normal.Normalise();
+		if(-DotProduct(CenterToCol, Normal) < 0.0f)
+			Normal = -Normal;	// always push away from col surface
+		float DistToMove = DotProduct(-ColDepth*CenterToCol, Normal);
+		m_vecClearGeometryVec = DistToMove*Normal;	// move source so this point is out of collision
+
+		if(pTargetEntity && pTargetEntity->IsPed() && RwCameraGetNearClipPlane(Scene.camera) < 2.0f*fCloseNearClipLimit){
+			float TargetNormalDir = DotProduct(Normal, pTargetEntity->GetForward());
+			if(TargetNormalDir < 0.0f){
+				// target looking towards collision
+				if(m_fAvoidTheGeometryProbsTimer < 0.0f)
+					m_fAvoidTheGeometryProbsTimer = 0.0f;
+				m_fAvoidTheGeometryProbsTimer += CTimer::GetTimeStep();
+			}else if(TargetNormalDir > 0.5f){
+				// target looking away from collision
+				if(m_fAvoidTheGeometryProbsTimer > 0.0f)
+					m_fAvoidTheGeometryProbsTimer = 0.0f;
+				m_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep();
+			}
+
+			if(m_nAvoidTheGeometryProbsDirn == 0){
+				if(CrossProduct(pTargetEntity->GetPosition() - NewSource, Normal).z > 0.0f)
+					m_nAvoidTheGeometryProbsDirn = -1;
+				else
+					m_nAvoidTheGeometryProbsDirn = 1;
+			}
+		}
+
+		fClearGeomTarget = 1.0f;
+	}
+
+	m_fAvoidTheGeometryProbsTimer *= Pow(fAvoidProbTimerDamp, CTimer::GetTimeStep());
+	WellBufferMe(fClearGeomTarget, &fClearGeomAmount, &fClearGeomAmountSpeed, 0.2f, 0.05f, false);
+	m_vecClearGeometryVec *= fClearGeomAmount;
+	m_bMoveCamToAvoidGeom = true;
+}
+
+void
+CCamera::GetArrPosForVehicleType(int apperance, int &index)
+{
+	switch(apperance){
+	case VEHICLE_APPEARANCE_CAR: index = 0; break;
+	case VEHICLE_APPEARANCE_BIKE: index = 1; break;
+	case VEHICLE_APPEARANCE_HELI: index = 2; break;
+	case VEHICLE_APPEARANCE_PLANE: index = 3; break;
+	case VEHICLE_APPEARANCE_BOAT: index = 4; break;
+	}
+}
 
 
 void
@@ -1828,28 +1960,25 @@ CCamera::SetCamPositionForFixedMode(const CVector &Source, const CVector &UpOffS
 }
 
 
-
-/*
- * On PS2 the transition happens between Cams[1] and Cams[2].
- * On PC the whole system has been changed.
- */
+//--MIAMI: done
 void
 CCamera::StartTransition(int16 newMode)
 {
-	bool foo = false;
+	bool switchFromFixedSyphon = false;
 	bool switchSyphonMode = false;
-	bool switchPedToCar = false;
 	bool switchPedMode = false;
+	bool switchPedToCar = false;
+	bool switchFromFight = false;
+	bool switchBikeToPed = false;
 	bool switchFromFixed = false;
 	bool switch1stPersonToVehicle = false;
 	float betaOffset, targetBeta, camBeta, deltaBeta;
 	int door;
 	bool vehicleVertical;
 
-// missing on PS2
 	m_bItsOkToLookJustAtThePlayer = false;
-	m_fFractionInterToStopMovingTarget = 0.25f;
-	m_fFractionInterToStopCatchUpTarget = 0.75f;
+	m_fFractionInterToStopMoving = 0.25f;
+	m_fFractionInterToStopCatchUp = 0.75f;
 
 	if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT ||
 	   Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED ||
@@ -1859,16 +1988,19 @@ CCamera::StartTransition(int16 newMode)
 		   newMode == CCam::MODE_FOLLOWPED ||
 		   newMode == CCam::MODE_SYPHON ||
 		   newMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON)
-			m_bItsOkToLookJustAtThePlayer = true;
+			switchPedMode = true;
 		if(newMode == CCam::MODE_CAM_ON_A_STRING)
 			switchPedToCar = true;
 	}
-//
 
+	if(Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON)
+		switchFromFixedSyphon = true;
+	if(Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING && newMode == CCam::MODE_FOLLOWPED && m_bPlayerWasOnBike)
+		switchBikeToPed = true;
 	if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT && newMode == CCam::MODE_SYPHON)
 		switchSyphonMode = true;
 	if(Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM && newMode == CCam::MODE_FOLLOWPED)
-		switchPedMode = true;
+		switchFromFight = true;
 	if(Cams[ActiveCam].Mode == CCam::MODE_FIXED)
 		switchFromFixed = true;
 
@@ -1889,12 +2021,6 @@ CCamera::StartTransition(int16 newMode)
 		((CPed*)pTargetEntity)->m_fRotationDest = angle;
 	}
 
-/*	// PS2
-	ActiveCam = (ActiveCam+1)%2;
-	Cams[ActiveCam].Init();
-	Cams[ActiveCam].Mode = newMode;
- */
-
 	Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;
 	Cams[ActiveCam].CamTargetEntity = pTargetEntity;
 	Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;
@@ -1909,16 +2035,17 @@ CCamera::StartTransition(int16 newMode)
 	   newMode == CCam::MODE_1STPERSON_RUNABOUT ||
 	   newMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
 	   newMode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
-	   newMode == CCam::MODE_HELICANNON_1STPERSON)
+	   newMode == CCam::MODE_HELICANNON_1STPERSON ||
+	   newMode == CCam::MODE_CAMERA)
 		Cams[ActiveCam].Alpha = 0.0f;
 
-	// PS2 also copies values to ActiveCam here
 	switch(Cams[ActiveCam].Mode)
 	case CCam::MODE_SNIPER_RUNABOUT:
 	case CCam::MODE_ROCKETLAUNCHER_RUNABOUT:
 	case CCam::MODE_1STPERSON_RUNABOUT:
 	case CCam::MODE_M16_1STPERSON_RUNABOUT:
 	case CCam::MODE_FIGHT_CAM_RUNABOUT:
+	case CCam::MODE_CAMERA:
 		if(newMode == CCam::MODE_CAM_ON_A_STRING || newMode == CCam::MODE_BEHINDBOAT)
 			switch1stPersonToVehicle = true;
 
@@ -1932,16 +2059,6 @@ CCamera::StartTransition(int16 newMode)
 		betaOffset = DEGTORAD(55.0f);
 		if(m_bJustCameOutOfGarage){
 			m_bUseTransitionBeta = true;
-/*
-			// weird logic...
-			if(CMenuManager::m_ControlMethod == CONTROL_CLASSIC)
-				Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;
-			else if(Cams[ActiveCam].Front.x != 0.0f && Cams[ActiveCam].Front.y != 0.0f)	// && is wrong here
-				Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;
-			else
-				Cams[ActiveCam].m_fTransitionBeta = 0.0f;
-*/
-			// this is better:
 			if(Cams[ActiveCam].Front.x != 0.0f || Cams[ActiveCam].Front.y != 0.0f)
 				Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;
 			else
@@ -2010,6 +2127,7 @@ CCamera::StartTransition(int16 newMode)
 	case CCam::MODE_M16_1STPERSON_RUNABOUT:
 	case CCam::MODE_FIGHT_CAM_RUNABOUT:
 	case CCam::MODE_HELICANNON_1STPERSON:
+	case CCam::MODE_CAMERA:
 		if(FindPlayerVehicle())
 			Cams[ActiveCam].Beta = Atan2(FindPlayerVehicle()->GetForward().x, FindPlayerVehicle()->GetForward().y);
 		else
@@ -2027,42 +2145,7 @@ CCamera::StartTransition(int16 newMode)
 		if(!m_bLookingAtPlayer || m_bJustCameOutOfGarage)
 			break;
 		m_bUseTransitionBeta = true;
-		targetBeta = CGeneral::GetATanOfXY(pTargetEntity->GetForward().x, pTargetEntity->GetForward().y);
-		camBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
-		deltaBeta = targetBeta - camBeta;
-		while(deltaBeta >= PI) deltaBeta -= 2*PI;
-		while(deltaBeta < -PI) deltaBeta += 2*PI;
-		deltaBeta = Abs(deltaBeta);
-		// switchFromFixed logic again here, skipped
-		if(switchFromFixed){
-			Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
-			break;
-		}
-
-		door = FindPlayerPed()->m_vehEnterType;
-		if(deltaBeta > HALFPI){
-			if(((CVehicle*)pTargetEntity)->IsUpsideDown()){
-				if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)	// BUG: game checks LF twice
-					betaOffset = -DEGTORAD(57.0f);
-			}else{
-				if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
-					betaOffset = -DEGTORAD(57.0f);
-			}
-			Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset + PI;
-		}else{
-			if(((CVehicle*)pTargetEntity)->IsUpsideDown()){
-				if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
-					betaOffset = -DEGTORAD(57.0f);
-				else if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)
-					betaOffset = DEGTORAD(57.0f);
-			}else{
-				if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)
-					betaOffset = -DEGTORAD(57.0f);
-				else if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
-					betaOffset = DEGTORAD(57.0f);
-			}
-			Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset;
-		}
+		Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
 		break;
 
 	case CCam::MODE_BEHINDBOAT:
@@ -2087,27 +2170,34 @@ CCamera::StartTransition(int16 newMode)
 	m_uiTransitionDuration = 1350;
 	if(switchSyphonMode)
 		m_uiTransitionDuration = 1800;
-	else if(switchPedMode)
+	else if(switchFromFight)
 		m_uiTransitionDuration = 750;
-// not on PS2
 	else if(switchPedToCar){
-		m_fFractionInterToStopMovingTarget = 0.2f;
-		m_fFractionInterToStopCatchUpTarget = 0.8f;
-		m_uiTransitionDuration = 950;
+		m_fFractionInterToStopMoving = 0.1f;
+		m_fFractionInterToStopCatchUp = 0.9f;
+		m_uiTransitionDuration = 750;
+	}else if(switchFromFixedSyphon){
+		m_fFractionInterToStopMoving = 0.0f;
+		m_fFractionInterToStopCatchUp = 1.0f;
+		m_uiTransitionDuration = 600;
 	}else if(switchFromFixed){
-		m_fFractionInterToStopMovingTarget = 0.05f;
-		m_fFractionInterToStopCatchUpTarget = 0.95f;
+		m_fFractionInterToStopMoving = 0.05f;
+		m_fFractionInterToStopCatchUp = 0.95f;
+	}else if(switchBikeToPed){
+		m_uiTransitionDuration = 800;
 	}else if(switch1stPersonToVehicle){
-		m_fFractionInterToStopMovingTarget = 0.0f;
-		m_fFractionInterToStopCatchUpTarget = 1.0f;
+		m_fFractionInterToStopMoving = 0.0f;
+		m_fFractionInterToStopCatchUp = 1.0f;
 		m_uiTransitionDuration = 1;
+	}else if(switchPedMode){
+		m_fFractionInterToStopMoving = 0.5f;
+		m_fFractionInterToStopCatchUp = 0.5f;
+		m_uiTransitionDuration = 350;
 	}else
 		m_uiTransitionDuration = 1350;	// already set above
-//
 	m_uiTransitionState = 1;
 	m_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds();
 	m_uiTransitionJUSTStarted = 1;
-// PS2 returns here
 	if(m_vecDoingSpecialInterPolation){
 		m_cvecStartingSourceForInterPol = SourceDuringInter;
 		m_cvecStartingTargetForInterPol = TargetDuringInter;
@@ -2138,10 +2228,22 @@ CCamera::StartTransition(int16 newMode)
 	m_fBetaSpeedAtStartInter = Cams[ActiveCam].m_fBetaSpeedOverOneFrame;
 	m_fFOVSpeedAtStartInter = Cams[ActiveCam].m_fFovSpeedOverOneFrame;
 	Cams[ActiveCam].ResetStatics = true;
-	if(!m_bLookingAtPlayer && m_bScriptParametersSetForInterPol){
-		m_fFractionInterToStopMovingTarget = m_fScriptPercentageInterToStopMoving;
-		m_fFractionInterToStopCatchUpTarget = m_fScriptPercentageInterToCatchUp;
-		m_uiTransitionDuration = m_fScriptTimeForInterPolation;
+	if(m_bLookingAtPlayer){
+		if(switchPedMode)
+			m_uiTransitionDurationTargetCoors = 350;
+		else
+			m_uiTransitionDurationTargetCoors = 600;
+		m_fFractionInterToStopMovingTarget = 0.0f;
+		m_fFractionInterToStopCatchUpTarget = 1.0f;
+	}else{
+		if(m_bScriptParametersSetForInterPol){
+			m_fFractionInterToStopMoving = m_fScriptPercentageInterToStopMoving;
+			m_fFractionInterToStopCatchUp = m_fScriptPercentageInterToCatchUp;
+			m_uiTransitionDuration = m_fScriptTimeForInterPolation;
+		}
+		m_uiTransitionDurationTargetCoors = m_uiTransitionDuration;
+		m_fFractionInterToStopMovingTarget = m_fFractionInterToStopMoving;
+		m_fFractionInterToStopCatchUpTarget = m_fFractionInterToStopCatchUp;
 	}
 }
 
diff --git a/src/core/Camera.h b/src/core/Camera.h
index 669ac740..9cb35636 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -121,7 +121,7 @@ public:
 
 	float   f_max_role_angle; //=DEGTORAD(5.0f);    
 	float   f_Roll; //used for adding a slight roll to the camera in the
-	float	f_rollSpeed;
+	float	f_rollSpeed;	//TODO(MIAMI): remove
 	float   m_fSyphonModeTargetZOffSet;
 	float	m_fRoadOffSet;
 	float   m_fAmountFractionObscured;
@@ -146,7 +146,8 @@ public:
 	float   m_fRealGroundDist; //used for follow ped mode
 	float   m_fTargetBeta;
 	float   m_fTimeElapsedFloat;  
-  
+	float   m_fTilt;
+	float   m_fTiltSpeed;
 	float   m_fTransitionBeta;
 	float   m_fTrueBeta;
 	float   m_fTrueAlpha;
@@ -164,6 +165,16 @@ public:
 	float   CA_MAX_DISTANCE;
 	float   SpeedVar;
 
+	float m_fTargetZoomGroundOne;
+	float m_fTargetZoomGroundTwo;
+	float m_fTargetZoomGroundThree;
+	float m_fTargetZoomOneZExtra;
+	float m_fTargetZoomTwoZExtra;
+	float m_fTargetZoomThreeZExtra;
+	float m_fTargetZoomZCloseIn;
+	float m_fMinRealGroundDist;
+	float m_fTargetCloseInDist;
+
 	CVector m_cvecSourceSpeedOverOneFrame;
 	CVector m_cvecTargetSpeedOverOneFrame;
 	CVector m_cvecUpOverOneFrame;
@@ -198,10 +209,8 @@ public:
 	void GetVectorsReadyForRW(void);
 	CVector DoAverageOnVector(const CVector &vec);
 	float GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies);
-	void WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation);
 	void WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight);
 	bool RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation);
-	bool FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation);
 	void Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist);
 	void FixCamWhenObscuredByVehicle(const CVector &TargetCoors);
 	void LookBehind(void);
@@ -234,7 +243,7 @@ public:
 	void Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float);
 	void Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float);
 	void Process_FlyBy(const CVector&, float, float, float);
-	void Process_WheelCam(const CVector&, float, float, float);
+	bool Process_WheelCam(const CVector&, float, float, float);
 	void Process_Fixed(const CVector &CameraTarget, float, float, float);
 	void Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float);
 	void Process_Circle(const CVector &CameraTarget, float, float, float);
@@ -263,8 +272,6 @@ public:
 	void Process_FollowCar_SA(const CVector &CameraTarget, float TargetOrientation, float, float);
 };
 
-VALIDATE_SIZE(CCam, 0x1A4);
-
 class CCamPathSplines
 {
 public:
@@ -358,6 +365,7 @@ public:
 	bool m_bInitialNoNodeStaticsSet;
 	bool m_bIgnoreFadingStuffForMusic;
 	bool m_bPlayerIsInGarage;
+	bool m_bPlayerWasOnBike;
 	bool m_bJustCameOutOfGarage;
 	bool m_bJustInitalised;
 	bool m_bJust_Switched;
@@ -383,6 +391,8 @@ public:
 	bool m_1rstPersonRunCloseToAWall;
 	bool m_bHeadBob;
 	bool m_bVehicleSuspenHigh;
+	bool m_bEnable1rstPersonCamCntrlsScript;
+	bool m_bAllow1rstPersonWeaponsCamera;
 	bool m_bFailedCullZoneTestPreviously;
 
 	bool m_FadeTargetIsSplashScreen;
@@ -398,15 +408,16 @@ public:
 	uint8   m_uiTransitionState;        // 0:one mode 1:transition
 
 	uint32 m_uiTimeLastChange;
+	uint32 m_uiTimeWeLeftIdle_StillNoInput;
 	uint32 m_uiTimeWeEnteredIdle;
 	uint32 m_uiTimeTransitionStart;
 	uint32 m_uiTransitionDuration;
+	uint32 m_uiTransitionDurationTargetCoors;
 	int m_BlurBlue;
 	int m_BlurGreen;
 	int m_BlurRed;
 	int m_BlurType;
 
-	uint32    unknown;	// some counter having to do with music
 	int m_iWorkOutSpeedThisNumFrames;
 	int m_iNumFramesSoFar;
 
@@ -466,15 +477,16 @@ public:
 	float PedZoomIndicator;
 #endif
 	float PlayerExhaustion;
-	float SoundDistUp, SoundDistLeft, SoundDistRight;
-	float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead;
-	float SoundDistUpAsReadOld, SoundDistLeftAsReadOld, SoundDistRightAsReadOld;
+	float SoundDistUp;
+	float SoundDistUpAsRead;
+	float SoundDistUpAsReadOld;
+	float m_fAvoidTheGeometryProbsTimer;
+	int16 m_nAvoidTheGeometryProbsDirn;
 	float m_fWideScreenReductionAmount;
 	float m_fStartingFOVForInterPol;
 
-	// not static yet
-	float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls
-	float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls
+	static float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls
+	static float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls
 	static float m_f3rdPersonCHairMultX;
 	static float m_f3rdPersonCHairMultY;
 
@@ -501,7 +513,7 @@ public:
 	CVector m_vecSourceWhenInterPol;
 	CVector m_vecTargetWhenInterPol;
 	CVector m_vecUpWhenInterPol;
-
+	CVector m_vecClearGeometryVec;
 	CVector m_vecGameCamPos;
 	CVector SourceDuringInter;
 	CVector TargetDuringInter;
@@ -509,7 +521,9 @@ public:
 	RwCamera *m_pRwCamera;
 	CEntity *pTargetEntity;
 	CCamPathSplines m_arrPathArray[MAX_NUM_OF_SPLINETYPES];
+#ifdef GTA_TRAIN
 	CTrainCamNode m_arrTrainCamNode[MAX_NUM_OF_NODES];
+#endif
 	CMatrix m_cameraMatrix;
 	bool m_bGarageFixedCamPositionSet;
 	bool m_vecDoingSpecialInterPolation;
@@ -527,6 +541,8 @@ public:
 	float m_fFLOATingFadeMusic;
 	float m_fTimeToFadeOut;
 	float m_fTimeToFadeMusic;
+	float m_fFractionInterToStopMoving;
+	float m_fFractionInterToStopCatchUp;
 	float m_fFractionInterToStopMovingTarget;
 	float m_fFractionInterToStopCatchUpTarget;
 	float m_fGaitSwayBuffer;
@@ -560,6 +576,8 @@ public:
 	void InitialiseCameraForDebugMode(void);
 	void CamShake(float strength, float x, float y, float z);
 	bool Get_Just_Switched_Status() { return m_bJust_Switched; }
+	void AvoidTheGeometry(const CVector &Source, const CVector &TargetPos, CVector &NewSource, float FOV);
+	void GetArrPosForVehicleType(int apperance, int &index);
 
 	// Who's in control
 	void TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 controller);
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 12b4ef8d..e484cd50 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -19297,7 +19297,7 @@ CPed::DriveVehicle(void)
 
 		} else if (targetUDLean > -1.0f) {
 			targetUDLean = bike->m_fLeanInput;
-			bike->m_bike_flag80 = false;
+			bike->bWheelieCam = false;
 			neededAngForWheelie = 1.0f;
 			if (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f || bike->GetForward().z <= 0.0f ||
 				(0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3])) {
@@ -19307,13 +19307,13 @@ CPed::DriveVehicle(void)
 
 					stoppieAng = bike->pBikeHandling->fStoppieAng;
 					if (stoppieAng - bike->GetForward().z > 0.6f * stoppieAng)
-						bike->m_bike_flag80 = true;
+						bike->bWheelieCam = true;
 				}
 			} else {
 				float wheelieAng = bike->pBikeHandling->fWheelieAng;
 				neededAngForWheelie = wheelieAng - bike->GetForward().z;
 				if (neededAngForWheelie < wheelieAng / 2.f)
-					bike->m_bike_flag80 = true;
+					bike->bWheelieCam = true;
 			}
 			if (neededAngForWheelie >= 0.15f) {
 				if (bike->m_fBrakePedal <= 0.5f || velocityFwdDotProd <= 0.01f) {
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 98dce4ac..becac84d 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -357,7 +357,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
 		if(mi->GetModelType() != MITYPE_SIMPLE && mi->GetModelType() != MITYPE_WEAPON){
 			if(FindPlayerVehicle() == ent &&
 			   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON &&
-			   !(FindPlayerVehicle()->IsBike() && ((CBike*)FindPlayerVehicle())->m_bike_flag80)){
+			   !(FindPlayerVehicle()->IsBike() && ((CBike*)FindPlayerVehicle())->bWheelieCam)){
 				// Player's vehicle in first person mode
 				CVehicle *veh = (CVehicle*)ent;
 				int model = veh->GetModelIndex();
diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h
index 60c9e29f..832b36e2 100644
--- a/src/render/Timecycle.h
+++ b/src/render/Timecycle.h
@@ -173,6 +173,9 @@ public:
 	static int GetFogBlue(void) { return m_nCurrentFogColourBlue; }
 	static int GetFogReduction(void) { return m_FogReduction; }
 
+	static int GetBlurRed(void) { return m_fCurrentBlurRed; }
+	static int GetBlurGreen(void) { return m_fCurrentBlurGreen; }
+	static int GetBlurBlue(void) { return m_fCurrentBlurBlue; }
 	static int GetWaterRed(void) { return m_fCurrentWaterRed; }
 	static int GetWaterGreen(void) { return m_fCurrentWaterGreen; }
 	static int GetWaterBlue(void) { return m_fCurrentWaterBlue; }
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index fcf85685..97a6ce33 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -273,14 +273,14 @@ CAutomobile::ProcessControl(void)
 	if(CReplay::IsPlayingBack())
 		return;
 
-	UpdatePassengerList();
-
 	// Heli wind
 	if(IsRealHeli())
 		if((GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PHYSICS) && m_aWheelSpeed[1] > 0.075f ||
 		   GetStatus() == STATUS_SIMPLE)
 			CWindModifiers::RegisterOne(GetPosition(), 1);
 
+	UpdatePassengerList();
+
 	// Improve grip of vehicles in certain cases
 	bool strongGrip1 = false;
 	bool strongGrip2 = false;
diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp
index 0dee85ce..01b489b2 100644
--- a/src/vehicles/Bike.cpp
+++ b/src/vehicles/Bike.cpp
@@ -125,7 +125,7 @@ CBike::CBike(int32 id, uint8 CreatedBy)
 	bIsStanding = false;
 	bExtraSpeed = false;
 	bIsOnFire = false;
-	m_bike_flag80 = false;
+	bWheelieCam = false;
 
 	m_fTireTemperature = 1.0f;
 	m_fBrakeDestabilization = 0.0f;
@@ -314,7 +314,7 @@ CBike::ProcessControl(void)
 		ReduceHornCounter();
 		bVehicleColProcessed = false;
 		bAudioChangingGear = false;
-		m_bike_flag80 = false;
+		bWheelieCam = false;
 		// that's all we do for simple vehicles
 		return;
 
@@ -324,7 +324,7 @@ CBike::ProcessControl(void)
 		PlayHornIfNecessary();
 
 		bBalancedByRider = true;
-		m_bike_flag80 = false;
+		bWheelieCam = false;
 
 		if(bIsBeingCarJacked){
 			m_fGasPedal = 0.0f;
@@ -350,7 +350,7 @@ CBike::ProcessControl(void)
 		bBalancedByRider = (pDriver || pPassengers[0] || bIsBeingCarJacked) && !bIsStanding;
 		m_fPedLeanAmountLR = 0.0f;
 		m_fPedLeanAmountUD = 0.0f;
-		m_bike_flag80 = false;
+		bWheelieCam = false;
 
 		if(bIsBeingCarJacked){
 			m_fGasPedal = 0.0f;
@@ -371,7 +371,7 @@ CBike::ProcessControl(void)
 			m_nCarHornTimer = 0;
 
 		bBalancedByRider = false;
-		m_bike_flag80 = false;
+		bWheelieCam = false;
 		m_fPedLeanAmountLR = 0.0f;
 		m_fPedLeanAmountUD = 0.0f;
 		break;
@@ -393,7 +393,7 @@ CBike::ProcessControl(void)
 			m_nCarHornTimer = 0;
 
 		bBalancedByRider = true;
-		m_bike_flag80 = false;
+		bWheelieCam = false;
 		break;
 	}
 
@@ -1344,7 +1344,7 @@ CBike::PreRender(void)
 		// 1.0 if directly behind car, -1.0 if in front
 		float behindness = DotProduct(lookVector, GetForward());
 		// 0.0 if behind car, PI if in front
-		float angle = Abs(PI/2.0f - Acos(Abs(behindness)));
+		float angle = Abs(Acos(Abs(behindness)));
 
 		// Headlight
 
diff --git a/src/vehicles/Bike.h b/src/vehicles/Bike.h
index a13e4c56..669e236e 100644
--- a/src/vehicles/Bike.h
+++ b/src/vehicles/Bike.h
@@ -73,7 +73,7 @@ public:
 	uint8 bIsStanding : 1;
 	uint8 bExtraSpeed : 1;	// leaning forward
 	uint8 bIsOnFire : 1;
-	uint8 m_bike_flag80 : 1;
+	uint8 bWheelieCam : 1;
 	int16 m_doingBurnout;
 	float m_fTireTemperature;
 	float m_fBrakeDestabilization;