diff --git a/src/core/main.cpp b/src/core/main.cpp
index 4e94c202..7f73c311 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -76,7 +76,7 @@
 
 GlobalScene Scene;
 
-uint8 work_buff[55000];
+uint8 work_buff[102400];
 char gString[256];
 char gString2[512];
 wchar gUString[256];
diff --git a/src/core/main.h b/src/core/main.h
index 19dd57ba..0f9ceb08 100644
--- a/src/core/main.h
+++ b/src/core/main.h
@@ -7,7 +7,7 @@ struct GlobalScene
 };
 extern GlobalScene Scene;
 
-extern uint8 work_buff[55000];
+extern uint8 work_buff[102400];
 extern char gString[256];
 extern char gString2[512];
 extern wchar gUString[256];
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index 2749e3f7..c7a6f881 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -24,11 +24,11 @@ enum eEntityStatus
 	STATUS_PHYSICS,
 	STATUS_ABANDONED,
 	STATUS_WRECKED,
-	STATUS_TRAIN_MOVING,
+	STATUS_TRAIN_MOVING,	// these probably copied for FERRY
 	STATUS_TRAIN_NOT_MOVING,
 	STATUS_HELI,
 	STATUS_PLANE,
-	STATUS_PLAYER_REMOTE,
+	STATUS_PLAYER_REMOTE,	// 12 in LCS
 	STATUS_PLAYER_DISABLED,
 	STATUS_GHOST
 };
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index 07d1d0b4..5ce7bd72 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -21,11 +21,7 @@
 #include "Pickups.h"
 #include "Physical.h"
 
-//--MIAMI: file done
-
-#ifdef WALLCLIMB_CHEAT
 bool gGravityCheat;
-#endif
 
 
 CPhysical::CPhysical(void)
@@ -359,7 +355,7 @@ CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
 	return numSpheres;
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 void
 CPhysical::ProcessControl(void)
 {
@@ -427,7 +423,7 @@ CPhysical::GetSpeed(const CVector &r)
 	return m_vecMoveSpeed + m_vecMoveFriction + CrossProduct(m_vecTurnFriction + m_vecTurnSpeed, r);
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 void
 CPhysical::ApplyMoveSpeed(void)
 {
@@ -437,13 +433,13 @@ CPhysical::ApplyMoveSpeed(void)
 		GetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep());
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 void
 CPhysical::ApplyTurnSpeed(void)
 {
 	if(bIsFrozen){
 		m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
-	}else{
+	}else if(!m_vecTurnSpeed.IsZero()){
 		// Move the coordinate axes by their speed
 		// Note that this denormalizes the matrix
 		CVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep();
@@ -453,29 +449,36 @@ CPhysical::ApplyTurnSpeed(void)
 	}
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 void
 CPhysical::ApplyMoveForce(float jx, float jy, float jz)
 {
 	m_vecMoveSpeed += CVector(jx, jy, jz)*(1.0f/m_fMass);
+	m_vecTurnSpeed.x = clamp(m_vecTurnSpeed.x, -4.0f, 4.0f);
+	m_vecTurnSpeed.y = clamp(m_vecTurnSpeed.y, -4.0f, 4.0f);
+	m_vecTurnSpeed.z = clamp(m_vecTurnSpeed.z, -4.0f, 4.0f);
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 void
 CPhysical::ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz)
 {
 	CVector com = Multiply3x3(m_matrix, m_vecCentreOfMass);
 	CVector turnimpulse = CrossProduct(CVector(px, py, pz)-com, CVector(jx, jy, jz));
 	m_vecTurnSpeed += turnimpulse*(1.0f/m_fTurnMass);
+	m_vecTurnSpeed.x = clamp(m_vecTurnSpeed.x, -4.0f, 4.0f);
+	m_vecTurnSpeed.y = clamp(m_vecTurnSpeed.y, -4.0f, 4.0f);
+	m_vecTurnSpeed.z = clamp(m_vecTurnSpeed.z, -4.0f, 4.0f);
 }
 
+//--LCS: done
 void
 CPhysical::ApplyFrictionMoveForce(float jx, float jy, float jz)
 {
 	m_vecMoveFriction += CVector(jx, jy, jz)*(1.0f/m_fMass);
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 void
 CPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float py, float pz)
 {
@@ -484,7 +487,7 @@ CPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float
 	m_vecTurnFriction += turnimpulse*(1.0f/m_fTurnMass);
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 bool
 CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias)
 {
@@ -498,16 +501,16 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &
 	return true;
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 bool
-CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir)
+CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir, float &impulse)
 {
 	float compression = 1.0f - springRatio;
 	if(compression > 0.0f){
 		if(DotProduct(springDir, forceDir) > 0.0f)
 			forceDir *= -1.0f;
 		float step = Min(CTimer::GetTimeStep(), 3.0f);
-		float impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f;
+		impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f;
 		if(bIsHeavy)
 			impulse *= 0.75f;
 		ApplyMoveForce(forceDir*impulse);
@@ -516,58 +519,75 @@ CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVecto
 	return true;
 }
 
-// --MIAMI: Proof-read once
+float DAMPING_LIMIT_OF_SPRING_FORCE = 0.999f;
+float DAMPING_LIMIT_IN_FRAME= 0.25f;
+
+//--LCS: done
 // What exactly is speed?
 bool
-CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)
+CPhysical::ApplySpringDampening(float damping, float dampingLimit, CVector &springDir, CVector &point, CVector &speed)
 {
 	float speedA = DotProduct(speed, springDir);
 	float speedB = DotProduct(GetSpeed(point), springDir);
 	float step = Min(CTimer::GetTimeStep(), 3.0f);
-	float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f;
+	damping *= step;
 	if(bIsHeavy)
-		impulse *= 2.0f;
+		damping *= 2.0f;
+	damping = clamp(damping, -DAMPING_LIMIT_IN_FRAME, DAMPING_LIMIT_IN_FRAME);
 
 	// what is this?
-	float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass);
-	a = Min(a, 1.0f);
-	float b = Abs(impulse / (speedB * m_fMass));
-	if(a < b)
-		impulse *= a/b;
+	float fSpeed = -speedA * damping;
+	if(fSpeed > 0.0f && fSpeed+speedB > 0.0f){
+		if(speedB < 0.0f)
+			fSpeed = -speedB;
+		else
+			fSpeed = 0.0f;
+	}else if(fSpeed < 0.0f && fSpeed+speedB < 0.0f){
+		if(speedB > 0.0f)
+			fSpeed = -speedB;
+		else
+			fSpeed = 0.0f;
+	}
+
+	CVector com = Multiply3x3(m_matrix, m_vecCentreOfMass);
+	float impulse = fSpeed*GetMass(point-com, springDir);
+	float limit = Abs(dampingLimit)*DAMPING_LIMIT_OF_SPRING_FORCE;
+	if(impulse > limit)
+		impulse = limit;
 
 	ApplyMoveForce(springDir*impulse);
 	ApplyTurnForce(springDir*impulse, point);
 	return true;
 }
 
+//--LCS: done
 void
 CPhysical::ApplyGravity(void)
 {
 	if (!bAffectedByGravity)
 		return;
-#ifdef WALLCLIMB_CHEAT
 	if (gGravityCheat && this == FindPlayerVehicle()) {
-		static CVector v1(0.0f, 0.0f, 1.0f), v2(0.0f, 0.0f, 1.0f);
-		CVector prop = GetPosition() - (GetUp() + GetUp());
+		static CVector gravityUp(0.0f, 0.0f, 1.0f), surfaceUp(0.0f, 0.0f, 1.0f);
+		CVector belowCar = GetPosition() - 2.0f*GetUp();
 		CColPoint point;
 		CEntity* entity;
-		if (CWorld::ProcessLineOfSight(GetPosition(), prop, point, entity, true, false, false, false, false, false))
-			v2 = point.normal;
+		if (CWorld::ProcessLineOfSight(GetPosition(), belowCar, point, entity, true, false, false, false, false, false))
+			surfaceUp = point.normal;
 		else
-			v2 = CVector(0.0f, 0.0f, 1.0f);
-		float coef = clamp(CTimer::GetTimeStep() * 0.5f, 0.05f, 0.8f);
-		v1 = v1 * (1.0f - coef) + v2 * coef;
-		if (v1.MagnitudeSqr() < 0.1f)
-			v1 = CVector(0.0f, 0.0f, 1.0f);
+			surfaceUp = CVector(0.0f, 0.0f, 1.0f);
+		float t = clamp(CTimer::GetTimeStep() * 0.5f, 0.05f, 0.8f);
+		gravityUp = gravityUp * (1.0f - t) + surfaceUp * t;
+		if (gravityUp.MagnitudeSqr() < 0.1f)
+			gravityUp = CVector(0.0f, 0.0f, 1.0f);
 		else
-			v1.Normalise();
-		m_vecMoveSpeed -= GRAVITY * CTimer::GetTimeStep() * v1;
+			gravityUp.Normalise();
+		m_vecMoveSpeed -= GRAVITY * CTimer::GetTimeStep() * gravityUp;
 		return;
 	}
-#endif
 	m_vecMoveSpeed.z -= GRAVITY * CTimer::GetTimeStep();
 }
 
+//--LCS: done
 void
 CPhysical::ApplyFriction(void)
 {
@@ -577,7 +597,7 @@ CPhysical::ApplyFriction(void)
 	m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);
 }
 
-// --MIAMI: Proof-read once
+//--LCS: done
 void
 CPhysical::ApplyAirResistance(void)
 {
@@ -585,8 +605,8 @@ CPhysical::ApplyAirResistance(void)
 		float f = Pow(m_fAirResistance, CTimer::GetTimeStep());
 		m_vecMoveSpeed *= f;
 		m_vecTurnSpeed *= f;
-	}else if(GetStatus() != STATUS_GHOST){ 
-		float f = Pow(1.0f/Abs(1.0f + m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr()), CTimer::GetTimeStep());
+	}else{
+		float f = Pow(1.0f - m_fAirResistance*m_vecMoveSpeed.Magnitude(), CTimer::GetTimeStep());
 		m_vecMoveSpeed *= f;
 		m_vecTurnSpeed *= 0.99f;
 	}
@@ -2310,3 +2330,44 @@ CPhysical::ProcessCollision(void)
 	m_fElasticity = savedElasticity;
 	RemoveAndAdd();
 }
+
+
+
+// TEMP old VC code until bikes are done
+bool
+CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir)
+{
+	float compression = 1.0f - springRatio;
+	if(compression > 0.0f){
+		if(DotProduct(springDir, forceDir) > 0.0f)
+			forceDir *= -1.0f;
+		float step = Min(CTimer::GetTimeStep(), 3.0f);
+		float impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f;
+		if(bIsHeavy)
+			impulse *= 0.75f;
+		ApplyMoveForce(forceDir*impulse);
+		ApplyTurnForce(forceDir*impulse, point);
+	}
+	return true;
+}
+bool
+CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)
+{
+	float speedA = DotProduct(speed, springDir);
+	float speedB = DotProduct(GetSpeed(point), springDir);
+	float step = Min(CTimer::GetTimeStep(), 3.0f);
+	float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f;
+	if(bIsHeavy)
+		impulse *= 2.0f;
+
+	// what is this?
+	float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass);
+	a = Min(a, 1.0f);
+	float b = Abs(impulse / (speedB * m_fMass));
+	if(a < b)
+		impulse *= a/b;
+
+	ApplyMoveForce(springDir*impulse);
+	ApplyTurnForce(springDir*impulse, point);
+	return true;
+}
diff --git a/src/entities/Physical.h b/src/entities/Physical.h
index 926b9762..290c267c 100644
--- a/src/entities/Physical.h
+++ b/src/entities/Physical.h
@@ -158,8 +158,8 @@ public:
 	void ApplyFrictionTurnForce(const CVector &j, const CVector &p) { ApplyFrictionTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); }
 	// springRatio: 1.0 fully extended, 0.0 fully compressed
 	bool ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias);
-	bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir);
-	bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed);
+	bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir, float &impulse);
+	bool ApplySpringDampening(float damping, float dampingLimit, CVector &springDir, CVector &point, CVector &speed);
 	void ApplyGravity(void);
 	void ApplyFriction(void);
 	void ApplyAirResistance(void);
@@ -174,4 +174,8 @@ public:
 	bool ProcessCollisionSectorList(CPtrList *lists);
 	bool CheckCollision(void);
 	bool CheckCollision_SimpleCar(void);
+
+	// TEMP
+	bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir);
+	bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed);
 };
diff --git a/src/modelinfo/VehicleModelInfo.h b/src/modelinfo/VehicleModelInfo.h
index 6c654284..f9217a41 100644
--- a/src/modelinfo/VehicleModelInfo.h
+++ b/src/modelinfo/VehicleModelInfo.h
@@ -3,8 +3,8 @@
 #include "ClumpModelInfo.h"
 
 enum {
-	NUM_FIRST_MATERIALS = 24,
-	NUM_SECOND_MATERIALS = 20,
+	NUM_FIRST_MATERIALS = 25,
+	NUM_SECOND_MATERIALS = 25,
 	NUM_VEHICLE_COLOURS = 8,
 };
 
@@ -98,7 +98,7 @@ public:
 	uint8 m_lastColorVariation;
 	uint8 m_currentColour1;
 	uint8 m_currentColour2;
-	RpAtomic *m_comps[6];
+	RpAtomic *m_comps[6];	// LCS(TODO): pointer
 	// This is stupid, CClumpModelInfo already has it!
 	union {
 		int32 m_animFileIndex;
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index c1a6fc0c..93861aa5 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -50,8 +50,6 @@
 #include "Automobile.h"
 #include "Bike.h"
 
-//--MIAMI: file done
-
 bool bAllCarCheat;
 
 RwObject *GetCurrentAtomicObjectCB(RwObject *object, void *data);
@@ -103,6 +101,8 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
 	pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);
 	pFlyingHandling =  mod_HandlingManager.GetFlyingPointer((tVehicleType)mi->m_handlingId);
 
+	m_fEngineInertiaVar1 = 0.0f;
+	m_fEngineInertiaVar2 = 0.0f;
 	m_auto_unused1 = 20.0f;
 	m_auto_unused2 = 0;
 
@@ -151,7 +151,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
 	m_fMass = pHandling->fMass;
 	m_fTurnMass = pHandling->fTurnMass;
 	m_vecCentreOfMass = pHandling->CentreOfMass;
-	m_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass;
+	m_fAirResistance = pHandling->fDragMult > 0.01f ? pHandling->fDragMult*0.0005f : pHandling->fDragMult;
 	m_fElasticity = 0.05f;
 	m_fBuoyancy = pHandling->fBuoyancy;
 
@@ -192,12 +192,6 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
 	m_fTraction = 1.0f;
 	m_fTireTemperature = 1.0f;
 
-	CColModel *colModel = mi->GetColModel();
-	if(colModel->lines == nil){
-		colModel->lines = (CColLine*)RwMalloc(4*sizeof(CColLine));
-		colModel->numLines = 4;
-	}
-
 	SetupSuspensionLines();
 
 	SetStatus(STATUS_SIMPLE);
@@ -257,6 +251,10 @@ CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f);
 void
 CAutomobile::ProcessControl(void)
 {
+	// TODO(LCS):
+	// TheCamera can remove service vehicles
+	// some audio (?) stuff
+
 	int i;
 	float wheelRot;
 	CColModel *colModel;
@@ -311,7 +309,7 @@ CAutomobile::ProcessControl(void)
 	if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED &&
 	   GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PLAYER_DISABLED){
 		switch(GetModelIndex())
-		case MI_FBIRANCH:
+		case MI_FBICAR:
 		case MI_POLICE:
 		case MI_ENFORCER:
 		case MI_SECURICA:
@@ -320,16 +318,18 @@ CAutomobile::ProcessControl(void)
 			ScanForCrimes();
 	}
 
+	// TODO(LCS): the fields used by this function are weird
+	ActivateBombWhenEntered();
+
 	// Process driver
-	if(pDriver)
+	if(pDriver){
 		if(IsUpsideDown() && CanPedEnterCar()){
 			if(!pDriver->IsPlayer() &&
 			   !(pDriver->m_leader && pDriver->m_leader->bInVehicle) &&
 			   pDriver->CharCreatedBy != MISSION_CHAR)
 				pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, this);
 		}
-
-	ActivateBombWhenEntered();
+	}
 
 	// Process passengers
 	if(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){
@@ -352,7 +352,7 @@ CAutomobile::ProcessControl(void)
 	if(strongGrip1 || bCheat3)
 		m_vecCentreOfMass.z = 0.3f*m_aSuspensionSpringLength[0] + -1.0f*m_fHeightAboveRoad;
 	else if(pHandling->Flags & HANDLING_NONPLAYER_STABILISER && GetStatus() == STATUS_PHYSICS)
-		m_vecCentreOfMass.z = pHandling->CentreOfMass.z - 0.2f*pHandling->Dimension.z;
+		m_vecCentreOfMass.z = pHandling->CentreOfMass.z + (colModel->boundingBox.min.z - pHandling->CentreOfMass.z)*0.4f;
 	else
 		m_vecCentreOfMass = pHandling->CentreOfMass;
 
@@ -372,7 +372,7 @@ CAutomobile::ProcessControl(void)
 	bool playerRemote = false;
 	switch(GetStatus()){
 	case STATUS_PLAYER_REMOTE:
-		if(CPad::GetPad(0)->WeaponJustDown() && !bDisableRemoteDetonation){
+		if(CPad::GetPad(0)->CarGunJustDown() && !bDisableRemoteDetonation){
 			BlowUpCar(FindPlayerPed());
 			CRemote::TakeRemoteControlledCarFromPlayer();
 		}
@@ -391,6 +391,7 @@ CAutomobile::ProcessControl(void)
 		// fall through
 	case STATUS_PLAYER:
 		if(playerRemote ||
+			// TODO(LCS): ped state 64
 		   pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR && pDriver->GetPedState() != PED_ARRESTED){
 			// process control input if controlled by player
 			if(playerRemote || pDriver->m_nPedType == PEDTYPE_PLAYER1)
@@ -416,6 +417,8 @@ CAutomobile::ProcessControl(void)
 			}else
 				m_vecCentreOfMass.z = pHandling->CentreOfMass.z;
 
+			// TODO(LCS): some in air handling?
+
 			if(bHoverCheat)
 				DoHoverSuspensionRatios();
 
@@ -451,8 +454,6 @@ CAutomobile::ProcessControl(void)
 			m_fBrakePedal = 1.0f;
 			m_fGasPedal = 0.0f;
 		}
-		if(CPad::GetPad(0)->CarGunJustDown())
-			ActivateBomb();
 		break;
 
 	case STATUS_SIMPLE:
@@ -492,7 +493,7 @@ CAutomobile::ProcessControl(void)
 		   m_aSuspensionSpringRatio[1] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[1].surfaceB) == ADHESIVE_SAND ||
 		   m_aSuspensionSpringRatio[2] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[2].surfaceB) == ADHESIVE_SAND ||
 		   m_aSuspensionSpringRatio[3] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[3].surfaceB) == ADHESIVE_SAND){
-			if(GetModelIndex() != MI_RCBANDIT && GetModelIndex() != MI_SANDKING && GetModelIndex() != MI_BFINJECT){
+			if(GetModelIndex() != MI_RCBANDIT /*&& GetModelIndex() != MI_SANDKING*/ && GetModelIndex() != MI_BFINJECT){
 				bStuckInSand = true;
 				if(CWeather::WetRoads > 0.0f)
 					ApplyMoveForce(m_vecMoveSpeed * -CTimer::GetTimeStep()*SAND_SLOWDOWN*m_fMass * (1.0f-CWeather::WetRoads));
@@ -527,8 +528,10 @@ CAutomobile::ProcessControl(void)
 
 		m_fSteerAngle = 0.0f;
 		m_fGasPedal = 0.0f;
-		if(!IsAlarmOn())
-			m_nCarHornTimer = 0;
+		m_nCarHornTimer = 0;
+		// TODO(LCS):
+		// CWeapon::::RemovePlayersRemoteDetonatorForThisVehicle
+		m_pBombRigger = nil;
 		break;
 
 	case STATUS_PLAYER_DISABLED:
@@ -622,14 +625,13 @@ CAutomobile::ProcessControl(void)
 
 	// special control
 	switch(GetModelIndex()){
-	case MI_FIRETRUCK:
-		FireTruckControl();
-		break;
+		// FireTruckControl in PreRender now
 	case MI_RHINO:
 		TankControl();
 		BlowUpCarsInPath();
 		break;
-	case MI_VOODOO:
+	// LCS: this is gone but i'm keeping it!
+	case MI_YARDIE:
 		HydraulicControl();
 		break;
 	default:
@@ -719,7 +721,7 @@ CAutomobile::ProcessControl(void)
 				ApplyTurnSpeed();
 			}
 			bIsInSafePosition = true;
-			bIsStuck = false;			
+			bIsStuck = false;		
 		}
 
 		CPhysical::ProcessControl();
@@ -737,7 +739,8 @@ CAutomobile::ProcessControl(void)
 		float fwdSpeed = Abs(DotProduct(m_vecMoveSpeed, GetForward()));
 		CVector contactPoints[4];	// relative to model
 		CVector contactSpeeds[4];	// speed at contact points
-		CVector springDirections[4];	// normalized, in model space
+		CVector springDirections[4];	// normalized, in world space
+		float springForces[4];
 
 		for(i = 0; i < 4; i++){
 			// Set spring under certain circumstances
@@ -761,10 +764,13 @@ CAutomobile::ProcessControl(void)
 			}
 
 			// get points and directions if spring is compressed
+			springDirections[i] = -GetUp();	// springs are always pointing down anyway
 			if(m_aSuspensionSpringRatio[i] < 1.0f){
 				contactPoints[i] = m_aWheelColPoints[i].point - GetPosition();
-				springDirections[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1 - colModel->lines[i].p0);
-				springDirections[i].Normalise();
+//				springDirections[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1 - colModel->lines[i].p0);
+//				springDirections[i].Normalise();
+			}else{
+				contactPoints[i] = CVector(0.0f, 0.0f, 0.0f);
 			}
 		}
 
@@ -777,7 +783,7 @@ CAutomobile::ProcessControl(void)
 
 				ApplySpringCollisionAlt(pHandling->fSuspensionForceLevel,
 					springDirections[i], contactPoints[i],
-					m_aSuspensionSpringRatio[i], bias, m_aWheelColPoints[i].normal);
+					m_aSuspensionSpringRatio[i], bias, m_aWheelColPoints[i].normal, springForces[i]);
 
 				m_aWheelSkidmarkUnk[i] = false;
 				if(m_aWheelColPoints[i].surfaceB == SURFACE_GRASS ||
@@ -789,8 +795,8 @@ CAutomobile::ProcessControl(void)
 					m_aWheelSkidmarkUnk[i] = true;
 				}else
 					m_aWheelSkidmarkType[i] = SKIDMARK_NORMAL;
-			}else{
-				contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1);
+//			}else{
+//				contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1);
 			}
 		}
 
@@ -812,7 +818,7 @@ CAutomobile::ProcessControl(void)
 		// dampen springs
 		for(i = 0; i < 4; i++)
 			if(m_aSuspensionSpringRatio[i] < 0.99999f)
-				ApplySpringDampening(pHandling->fSuspensionDampingLevel,
+				ApplySpringDampening(pHandling->fSuspensionDampingLevel, springForces[i],
 					springDirections[i], contactPoints[i], contactSpeeds[i]);
 
 		// Get speed at contact points again
@@ -825,42 +831,6 @@ CAutomobile::ProcessControl(void)
 			}
 		}
 
-		bool gripCheat = true;
-		fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());
-		if(!strongGrip1 && !CVehicle::bCheat3)
-			gripCheat = false;
-		float acceleration = pHandling->Transmission.CalculateDriveAcceleration(m_fGasPedal, m_nCurrentGear, m_fChangeGearTime, fwdSpeed, gripCheat);
-		acceleration /= m_fForceMultiplier;
-
-		if(IsRealHeli() || IsRealPlane())
-			acceleration = 0.0f;
-
-		if(bAudioChangingGear && m_fGasPedal > 0.4f && m_fBrakePedal < 0.1f && fwdSpeed > 0.15f &&
-		   this == FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){
-			if(GetStatus() == STATUS_PLAYER && !(pHandling->Flags & HANDLING_IS_BUS)){
-				if(m_nBusDoorTimerEnd == 0)
-					m_nBusDoorTimerEnd = 1000;
-				else {
-					uint32 timeStepInMs = CTimer::GetTimeStepInMilliseconds();
-					if(m_nBusDoorTimerEnd > timeStepInMs)
-						m_nBusDoorTimerEnd -= timeStepInMs;
-					else
-						m_nBusDoorTimerEnd = 0;
-				}
-			}
-
-			if((m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[2] < 1.0f) &&
-			   (m_aSuspensionSpringRatio[1] < 1.0f || m_aSuspensionSpringRatio[3] < 1.0f))
-				ApplyTurnForce(-GRAVITY*Min(m_fTurnMass, 2500.0f)*GetUp(), -1.0f*GetForward());
-		}
-
-		brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();
-		bool neutralHandling = GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && (pHandling->Flags & HANDLING_NEUTRALHANDLING);
-		float brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias;
-		float brakeBiasRear  = neutralHandling ? 1.0f : 2.0f-pHandling->fBrakeBias;	// looks like a bug, but it was correct in III...
-		float tractionBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias;
-		float tractionBiasRear  = neutralHandling ? 1.0f : 2.0f-tractionBiasFront;
-
 		// Count how many wheels are touching the ground
 
 		m_nWheelsOnGround = 0;
@@ -891,16 +861,36 @@ CAutomobile::ProcessControl(void)
 			}
 		}
 
+		bool gripCheat = true;
+		fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());
+		if(!strongGrip1 && !CVehicle::bCheat3)
+			gripCheat = false;
+		float acceleration = pHandling->Transmission.CalculateDriveAcceleration(m_fGasPedal, m_nCurrentGear, m_fChangeGearTime, fwdSpeed,
+					&m_fEngineInertiaVar1, &m_fEngineInertiaVar2, m_nDriveWheelsOnGround, gripCheat);
+		acceleration /= m_fForceMultiplier;
+
+		if(IsRealHeli() || IsRealPlane())
+			acceleration = 0.0f;
+
+		if(Abs(acceleration) > 0.0f)
+			m_fEngineEnergy += Abs(acceleration);
+		else
+			m_fEngineEnergy = 0.0f;
+
 		float traction;
 		if(GetStatus() == STATUS_PHYSICS)
 			traction = 0.004f * m_fTraction;
 		else
 			traction = 0.004f;
-		traction *= pHandling->fTractionMultiplier / 4.0f;
+		traction *= pHandling->GetTractionMultiplier() / 4.0f;
 		traction /= m_fForceMultiplier;
 		if(CVehicle::bCheat3)
 			traction *= 4.0f;
 
+		if(FindPlayerVehicle() && FindPlayerVehicle() == this)
+			if(CPad::GetPad(0)->CarGunJustDown())
+				ActivateBomb();
+
 		if(FindPlayerVehicle() != this && (strongGrip1 || CVehicle::bCheat3)){
 			traction *= 1.2f;
 			acceleration *= 1.4f;
@@ -910,448 +900,73 @@ CAutomobile::ProcessControl(void)
 			}
 		}
 
-		static float fThrust;
-		static tWheelState WheelState[4];
-
-		bool rearWheelsFirst = !!(pHandling->Flags & HANDLING_REARWHEEL_1ST);
-
-		// Process front wheels on ground - first try
-
-		if(!rearWheelsFirst){
-		if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){
-			float s = Sin(m_fSteerAngle);
-			float c = Cos(m_fSteerAngle);
-
-			CVector wheelFwd, wheelRight, tmp;
-
-			if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))
-					fThrust = 0.0f;
-				else
-					fThrust = acceleration;
-
-				wheelFwd = GetForward();
-				wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal;
-				wheelFwd.Normalise();
-				wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal);
-				wheelRight.Normalise();
-				tmp = c*wheelFwd - s*wheelRight;
-				wheelRight = s*wheelFwd + c*wheelRight;
-				wheelFwd = tmp;
-
-				m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_WHEELBASE;
-				float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction;
-				if(GetStatus() == STATUS_PLAYER)
-					adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB);
-				WheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT];
-
-				if(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST)
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,
-						CARWHEEL_FRONT_LEFT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],
-						&WheelState[CARWHEEL_FRONT_LEFT],
-						WHEEL_STATUS_BURST);
-				else
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront,
-						CARWHEEL_FRONT_LEFT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],
-						&WheelState[CARWHEEL_FRONT_LEFT],
-						WHEEL_STATUS_OK);
-			}
-
-			if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))
-					fThrust = 0.0f;
-				else
-					fThrust = acceleration;
-
-				wheelFwd = GetForward();
-				wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal;
-				wheelFwd.Normalise();
-				wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal);
-				wheelRight.Normalise();
-				tmp = c*wheelFwd - s*wheelRight;
-				wheelRight = s*wheelFwd + c*wheelRight;
-				wheelFwd = tmp;
-
-				m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_WHEELBASE;
-				float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction;
-				if(GetStatus() == STATUS_PLAYER)
-					adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB);
-				WheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT];
-
-				if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,
-						CARWHEEL_FRONT_RIGHT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],
-						&WheelState[CARWHEEL_FRONT_RIGHT],
-						WHEEL_STATUS_BURST);
-				else
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront,
-						CARWHEEL_FRONT_RIGHT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],
-						&WheelState[CARWHEEL_FRONT_RIGHT],
-						WHEEL_STATUS_OK);
-			}
-		}
-
-		// Process front wheels off ground
-
-		if(!IsRealHeli()){
-			if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] <= 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
-					m_aWheelSpeed[CARWHEEL_FRONT_LEFT] *= 0.95f;
-				else{
-					if(acceleration > 0.0f){
-						if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] < 2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_LEFT] -= 0.2f;
-					}else{
-						if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] > -2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_LEFT] += 0.1f;
-					}
+		// TODO(LCS): where did this go?
+/*
+		if(bAudioChangingGear && m_fGasPedal > 0.4f && m_fBrakePedal < 0.1f && fwdSpeed > 0.15f &&
+		   this == FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){
+			if(GetStatus() == STATUS_PLAYER && !(pHandling->Flags & HANDLING_IS_BUS)){
+				if(m_nBusDoorTimerEnd == 0)
+					m_nBusDoorTimerEnd = 1000;
+				else {
+					uint32 timeStepInMs = CTimer::GetTimeStepInMilliseconds();
+					if(m_nBusDoorTimerEnd > timeStepInMs)
+						m_nBusDoorTimerEnd -= timeStepInMs;
+					else
+						m_nBusDoorTimerEnd = 0;
 				}
-				m_aWheelRotation[CARWHEEL_FRONT_LEFT] += m_aWheelSpeed[CARWHEEL_FRONT_LEFT];
-			}
-			if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] <= 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
-					m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] *= 0.95f;
-				else{
-					if(acceleration > 0.0f){
-						if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] < 2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] -= 0.2f;
-					}else{
-						if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] > -2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] += 0.1f;
-					}
-				}
-				m_aWheelRotation[CARWHEEL_FRONT_RIGHT] += m_aWheelSpeed[CARWHEEL_FRONT_RIGHT];
 			}
+
+			if((m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[2] < 1.0f) &&
+			   (m_aSuspensionSpringRatio[1] < 1.0f || m_aSuspensionSpringRatio[3] < 1.0f))
+				ApplyTurnForce(-GRAVITY*Min(m_fTurnMass, 2500.0f)*GetUp(), -1.0f*GetForward());
 		}
-		}
+*/
 
-		// Process rear wheels
+		float steerRange;
+		if(fwdSpeed > 0.01f && m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f && m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f && GetStatus() == STATUS_PLAYER){
+			CColPoint point;
+			point.surfaceA = SURFACE_WHEELBASE;
+			point.surfaceB = SURFACE_TARMAC;
+			float rightSpeed = DotProduct(m_vecMoveSpeed, GetRight());
+			float adhesion = CSurfaceTable::GetAdhesiveLimit(point);
+			// i have no idea what's going on here
+			float magic = traction * adhesion * 16.0f / SQR(fwdSpeed);
+			magic = clamp(magic, -1.0f, 1.0f);
+			magic = Asin(magic);
+			if(m_fSteerAngle < 0.0f && rightSpeed > 0.05f ||
+			   m_fSteerAngle > 0.0f && rightSpeed < -0.05f ||
+			   bIsHandbrakeOn)
+				steerRange = 1.0f;
+			else
+				steerRange = Min(magic/DEGTORAD(pHandling->fSteeringLock), 1.0f);
+		
+		}else
+			steerRange = 1.0f;
+		m_fSteerAngle *= steerRange;
 
-		if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f){
-			CVector wheelFwd = GetForward();
-			CVector wheelRight = GetRight();	// overwritten for resp. wheel
+		brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();
 
-			float rearBrake = brake;
-			float rearTraction = traction;
-			if(bIsHandbrakeOn){
-#ifdef FIX_BUGS
-				// Not sure if this is needed, but brake usually has timestep as a factor
-				rearBrake = 20000.0f * CTimer::GetTimeStepFix();
-#else
-				rearBrake = 20000.0f;
-#endif
-				if(fwdSpeed > 0.1f && pHandling->Flags & HANDLING_HANDBRAKE_TYRE){
-					m_fTireTemperature += 0.005*CTimer::GetTimeStep();
-					if(m_fTireTemperature > 2.0f)
-						m_fTireTemperature = 2.0f;
-				}
-			}else if(m_doingBurnout && !mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)){
-				rearBrake = 0.0f;
-				rearTraction = 0.0f;
-				// BUG: missing timestep
-				ApplyTurnForce(contactPoints[CARWHEEL_REAR_LEFT], -0.001f*m_fTurnMass*m_fSteerAngle*GetRight());
-			}else if(m_fTireTemperature > 1.0f){
-				rearTraction *= m_fTireTemperature;
-			}
-
-			if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){
-				if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))
-					fThrust = 0.0f;
-				else
-					fThrust = acceleration;
-
-				wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal)*m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal;
-				wheelFwd.Normalise();
-				wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal);
-				wheelRight.Normalise();
-
-				m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_WHEELBASE;
-				float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_LEFT])*rearTraction;
-				if(GetStatus() == STATUS_PLAYER)
-					adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB);
-				WheelState[CARWHEEL_REAR_LEFT] = m_aWheelState[CARWHEEL_REAR_LEFT];
-
-				if(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT],
-						m_nWheelsOnGround, fThrust,
-						rearBrake*brakeBiasRear,
-						adhesion*tractionBiasRear*Damage.m_fWheelDamageEffect,
-						CARWHEEL_REAR_LEFT,
-						&m_aWheelSpeed[CARWHEEL_REAR_LEFT],
-						&WheelState[CARWHEEL_REAR_LEFT],
-						WHEEL_STATUS_BURST);
-				else
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT],
-						m_nWheelsOnGround, fThrust,
-						rearBrake*brakeBiasRear,
-						adhesion*tractionBiasRear,
-						CARWHEEL_REAR_LEFT,
-						&m_aWheelSpeed[CARWHEEL_REAR_LEFT],
-						&WheelState[CARWHEEL_REAR_LEFT],
-						WHEEL_STATUS_OK);
-			}
-
-#ifdef FIX_BUGS
-			// Shouldn't we reset these after the left wheel?
-			wheelFwd = GetForward();
-			wheelRight = GetRight();	// actually useless
-#endif
-
-			if(m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f){
-				if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))
-					fThrust = 0.0f;
-				else
-					fThrust = acceleration;
-
-				wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal;
-				wheelFwd.Normalise();
-				wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal);
-				wheelRight.Normalise();
-
-				m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_WHEELBASE;
-				float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_RIGHT])*rearTraction;
-				if(GetStatus() == STATUS_PLAYER)
-					adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB);
-				WheelState[CARWHEEL_REAR_RIGHT] = m_aWheelState[CARWHEEL_REAR_RIGHT];
-
-				if(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT],
-						m_nWheelsOnGround, fThrust,
-						rearBrake*brakeBiasRear,
-						adhesion*tractionBiasRear*Damage.m_fWheelDamageEffect,
-						CARWHEEL_REAR_RIGHT,
-						&m_aWheelSpeed[CARWHEEL_REAR_RIGHT],
-						&WheelState[CARWHEEL_REAR_RIGHT],
-						WHEEL_STATUS_BURST);
-				else
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT],
-						m_nWheelsOnGround, fThrust,
-						rearBrake*brakeBiasRear,
-						adhesion*tractionBiasRear,
-						CARWHEEL_REAR_RIGHT,
-						&m_aWheelSpeed[CARWHEEL_REAR_RIGHT],
-						&WheelState[CARWHEEL_REAR_RIGHT],
-						WHEEL_STATUS_OK);
-			}
-		}
-
-		if(m_doingBurnout && !mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) &&
-	           (m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING || m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)){
-			m_fTireTemperature += 0.001f*CTimer::GetTimeStep();
-			if(m_fTireTemperature > 3.0f)
-				m_fTireTemperature = 3.0f;
-		}else if(m_fTireTemperature > 1.0f){
-			m_fTireTemperature = (m_fTireTemperature - 1.0f)*Pow(0.995f, CTimer::GetTimeStep()) + 1.0f;
-		}
-
-		// Process rear wheels off ground
-
-		if(!IsRealHeli()){
-			if(m_aWheelTimer[CARWHEEL_REAR_LEFT] <= 0.0f){
-				if(bIsHandbrakeOn)
-					m_aWheelSpeed[CARWHEEL_REAR_LEFT] = 0.0f;
-				else if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
-					m_aWheelSpeed[CARWHEEL_REAR_LEFT] *= 0.95f;
-				else{
-					if(acceleration > 0.0f){
-						if(m_aWheelSpeed[CARWHEEL_REAR_LEFT] < 2.0f)
-							m_aWheelSpeed[CARWHEEL_REAR_LEFT] -= 0.2f;
-					}else{
-						if(m_aWheelSpeed[CARWHEEL_REAR_LEFT] > -2.0f)
-							m_aWheelSpeed[CARWHEEL_REAR_LEFT] += 0.1f;
-					}
-				}
-				m_aWheelRotation[CARWHEEL_REAR_LEFT] += m_aWheelSpeed[CARWHEEL_REAR_LEFT];
-			}
-			if(m_aWheelTimer[CARWHEEL_REAR_RIGHT] <= 0.0f){
-				if(bIsHandbrakeOn)
-					m_aWheelSpeed[CARWHEEL_REAR_RIGHT] = 0.0f;
-				else if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
-					m_aWheelSpeed[CARWHEEL_REAR_RIGHT] *= 0.95f;
-				else{
-					if(acceleration > 0.0f){
-						if(m_aWheelSpeed[CARWHEEL_REAR_RIGHT] < 2.0f)
-							m_aWheelSpeed[CARWHEEL_REAR_RIGHT] -= 0.2f;
-					}else{
-						if(m_aWheelSpeed[CARWHEEL_REAR_RIGHT] > -2.0f)
-							m_aWheelSpeed[CARWHEEL_REAR_RIGHT] += 0.1f;
-					}
-				}
-				m_aWheelRotation[CARWHEEL_REAR_RIGHT] += m_aWheelSpeed[CARWHEEL_REAR_RIGHT];
-			}
-		}
-
-		// Process front wheels on ground - second try
-
-		if(rearWheelsFirst){
-		if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){
-			float s = Sin(m_fSteerAngle);
-			float c = Cos(m_fSteerAngle);
-
-			CVector wheelFwd, wheelRight, tmp;
-
-			if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))
-					fThrust = 0.0f;
-				else
-					fThrust = acceleration;
-
-				wheelFwd = GetForward();
-				wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal;
-				wheelFwd.Normalise();
-				wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal);
-				wheelRight.Normalise();
-				tmp = c*wheelFwd - s*wheelRight;
-				wheelRight = s*wheelFwd + c*wheelRight;
-				wheelFwd = tmp;
-
-				m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_WHEELBASE;
-				float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction;
-				if(GetStatus() == STATUS_PLAYER)
-					adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB);
-				WheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT];
-
-				if(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST)
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,
-						CARWHEEL_FRONT_LEFT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],
-						&WheelState[CARWHEEL_FRONT_LEFT],
-						WHEEL_STATUS_BURST);
-				else
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront,
-						CARWHEEL_FRONT_LEFT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],
-						&WheelState[CARWHEEL_FRONT_LEFT],
-						WHEEL_STATUS_OK);
-			}
-
-			if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))
-					fThrust = 0.0f;
-				else
-					fThrust = acceleration;
-
-				wheelFwd = GetForward();
-				wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal;
-				wheelFwd.Normalise();
-				wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal);
-				wheelRight.Normalise();
-				tmp = c*wheelFwd - s*wheelRight;
-				wheelRight = s*wheelFwd + c*wheelRight;
-				wheelFwd = tmp;
-
-				m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_WHEELBASE;
-				float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction;
-				if(GetStatus() == STATUS_PLAYER)
-					adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB);
-				WheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT];
-
-				if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,
-						CARWHEEL_FRONT_RIGHT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],
-						&WheelState[CARWHEEL_FRONT_RIGHT],
-						WHEEL_STATUS_BURST);
-				else
-					ProcessWheel(wheelFwd, wheelRight,
-						contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],
-						m_nWheelsOnGround, fThrust,
-						brake*brakeBiasFront,
-						adhesion*tractionBiasFront,
-						CARWHEEL_FRONT_RIGHT,
-						&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],
-						&WheelState[CARWHEEL_FRONT_RIGHT],
-						WHEEL_STATUS_OK);
-			}
-		}
-
-		// Process front wheels off ground
-
-		if (!IsRealHeli()) {
-			if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] <= 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
-					m_aWheelSpeed[CARWHEEL_FRONT_LEFT] *= 0.95f;
-				else{
-					if(acceleration > 0.0f){
-						if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] < 2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_LEFT] -= 0.2f;
-					}else{
-						if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] > -2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_LEFT] += 0.1f;
-					}
-				}
-				m_aWheelRotation[CARWHEEL_FRONT_LEFT] += m_aWheelSpeed[CARWHEEL_FRONT_LEFT];
-			}
-			if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] <= 0.0f){
-				if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
-					m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] *= 0.95f;
-				else{
-					if(acceleration > 0.0f){
-						if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] < 2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] -= 0.2f;
-					}else{
-						if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] > -2.0f)
-							m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] += 0.1f;
-					}
-				}
-				m_aWheelRotation[CARWHEEL_FRONT_RIGHT] += m_aWheelSpeed[CARWHEEL_FRONT_RIGHT];
-			}
-		}
+		if(pHandling->Flags & HANDLING_REARWHEEL_1ST){
+			ProcessCarWheelPair(CARWHEEL_REAR_LEFT, CARWHEEL_REAR_RIGHT, -999.0f, contactSpeeds, contactPoints,
+				traction, acceleration, brake, false);
+			ProcessCarWheelPair(CARWHEEL_FRONT_LEFT, CARWHEEL_FRONT_RIGHT, m_fSteerAngle, contactSpeeds, contactPoints,
+				traction, acceleration, brake, true);
+		}else{
+			ProcessCarWheelPair(CARWHEEL_FRONT_LEFT, CARWHEEL_FRONT_RIGHT, m_fSteerAngle, contactSpeeds, contactPoints,
+				traction, acceleration, brake, true);
+			ProcessCarWheelPair(CARWHEEL_REAR_LEFT, CARWHEEL_REAR_RIGHT, -999.0f, contactSpeeds, contactPoints,
+				traction, acceleration, brake, false);
 		}
 
 		for(i = 0; i < 4; i++){
 			float wheelPos = colModel->lines[i].p0.z;
 			if(m_aSuspensionSpringRatio[i] > 0.0f)
 				wheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionSpringLength[i];
-			if(GetModelIndex() == MI_VOODOO && bUsingSpecialColModel)
+			if(GetModelIndex() == MI_YARDIE && bUsingSpecialColModel)	// not original LCS
 				m_aWheelPosition[i] = wheelPos;
 			else
 				m_aWheelPosition[i] += (wheelPos - m_aWheelPosition[i])*0.75f;
 		}
-		for(i = 0; i < 4; i++)
-			m_aWheelState[i] = WheelState[i];
-		if(m_fGasPedal < 0.0f){
-			if(m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING)
-				m_aWheelState[CARWHEEL_REAR_LEFT] = WHEEL_STATE_NORMAL;
-			if(m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)
-				m_aWheelState[CARWHEEL_REAR_RIGHT] = WHEEL_STATE_NORMAL;
-		}
 
 		// Process horn
 
@@ -1710,6 +1325,207 @@ CAutomobile::ProcessControl(void)
 
 #pragma optimize("", on)
 
+//--LCS: done
+void
+CAutomobile::ProcessCarWheelPair(int leftWheel, int rightWheel, float steerAngle, CVector *contactSpeeds, CVector *contactPoints, float traction, float acceleration, float brake, bool bFront)
+{
+	bool driveWheels;
+	float suspensionBias;
+
+	if(bFront){
+		driveWheels = mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier);
+		suspensionBias = 2.0f*pHandling->fSuspensionBias;
+	}else{
+		driveWheels = mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier);
+		suspensionBias = 2.0f*(1.0f-pHandling->fSuspensionBias);
+
+		float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());	
+		if(bIsHandbrakeOn && Abs(fwdSpeed) > 0.1f){
+#ifdef FIX_BUGS
+			// Not sure if this is needed, but brake usually has timestep as a factor
+			brake = 20000.0f * CTimer::GetTimeStepFix();
+#else
+			brake = 20000.0f;
+#endif
+/*
+			if(fwdSpeed > 0.1f && pHandling->Flags & HANDLING_HANDBRAKE_TYRE){
+				m_fTireTemperature += 0.005*CTimer::GetTimeStep();
+				if(m_fTireTemperature > 2.0f)
+					m_fTireTemperature = 2.0f;
+			}
+*/
+		}else if(driveWheels && m_doingBurnout){
+			brake = 0.0f;
+			traction = 0.0f;
+			// BUG: missing timestep
+			ApplyTurnForce(contactPoints[leftWheel], -0.003f*m_fTurnMass*Min(3000.0f/m_fTurnMass, 1.0f)*m_fSteerAngle*GetRight());
+		}else if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)){
+			traction *= m_fTireTemperature;
+		}
+	}
+
+	// Wheels on ground
+	if(m_aWheelTimer[leftWheel] > 0.0f || m_aWheelTimer[rightWheel] > 0.0f){
+		CVector wheelFwd, wheelRight;
+		float s, c;
+		bool canSteer = steerAngle > -100.0f;
+		if(canSteer){
+			s = Sin(steerAngle);
+			c = Cos(steerAngle);
+		}
+
+		bool neutralHandling = GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && (pHandling->Flags & HANDLING_NEUTRALHANDLING);
+		float brakeBias, tractionBias;
+		if(bFront){
+			brakeBias = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias;
+			tractionBias = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias;
+		}else{
+			brakeBias = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fBrakeBias);
+			tractionBias = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fTractionBias);
+		}
+
+		if(m_aWheelTimer[leftWheel] > 0.0f){
+			float fThrust = driveWheels ? acceleration : 0.0f;
+
+			wheelFwd = GetForward();
+			wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[leftWheel].normal)*m_aWheelColPoints[leftWheel].normal;
+			wheelFwd.Normalise();
+			wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[leftWheel].normal);
+			wheelRight.Normalise();
+			if(canSteer){
+				CVector tmp = c*wheelFwd - s*wheelRight;
+				wheelRight = s*wheelFwd + c*wheelRight;
+				wheelFwd = tmp;
+			}
+
+			m_aWheelColPoints[leftWheel].surfaceA = SURFACE_WHEELBASE;
+			float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[leftWheel])*traction;
+			if(GetStatus() == STATUS_PLAYER){
+				adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[leftWheel].surfaceB);
+				adhesion *= Min(suspensionBias*pHandling->fSuspensionForceLevel*4.0f*(1.0f-m_aSuspensionSpringRatio[leftWheel]), 2.0f);
+			}
+			tWheelState WheelState = m_aWheelState[leftWheel];
+			if(Damage.GetWheelStatus(leftWheel) == WHEEL_STATUS_BURST)
+				ProcessWheel(wheelFwd, wheelRight,
+					contactSpeeds[leftWheel], contactPoints[leftWheel],
+					m_nWheelsOnGround, fThrust,
+					brake*brakeBias,
+					adhesion*tractionBias*Damage.m_fWheelDamageEffect,
+					leftWheel,
+					&m_aWheelRotation[leftWheel],
+					&WheelState,
+					WHEEL_STATUS_BURST);
+			else
+				ProcessWheel(wheelFwd, wheelRight,
+					contactSpeeds[leftWheel], contactPoints[leftWheel],
+					m_nWheelsOnGround, fThrust,
+					brake*brakeBias,
+					adhesion*tractionBias,
+					leftWheel,
+					&m_aWheelRotation[leftWheel],
+					&WheelState,
+					WHEEL_STATUS_OK);
+
+			if(driveWheels && m_fGasPedal < 0.0f && WheelState == WHEEL_STATE_SPINNING)
+				m_aWheelState[leftWheel] = WHEEL_STATE_NORMAL;
+			else
+				m_aWheelState[leftWheel] = WheelState;
+		}
+
+		if(m_aWheelTimer[rightWheel] > 0.0f){
+			float fThrust = driveWheels ? acceleration : 0.0f;
+
+			wheelFwd = GetForward();
+			wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[rightWheel].normal)*m_aWheelColPoints[rightWheel].normal;
+			wheelFwd.Normalise();
+			wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[rightWheel].normal);
+			wheelRight.Normalise();
+			if(canSteer){
+				CVector tmp = c*wheelFwd - s*wheelRight;
+				wheelRight = s*wheelFwd + c*wheelRight;
+				wheelFwd = tmp;
+			}
+
+			m_aWheelColPoints[rightWheel].surfaceA = SURFACE_WHEELBASE;
+			float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[rightWheel])*traction;
+			if(GetStatus() == STATUS_PLAYER){
+				adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[rightWheel].surfaceB);
+				adhesion *= Min(suspensionBias*pHandling->fSuspensionForceLevel*4.0f*(1.0f-m_aSuspensionSpringRatio[rightWheel]), 2.0f);
+			}
+			tWheelState WheelState = m_aWheelState[rightWheel];
+			if(Damage.GetWheelStatus(rightWheel) == WHEEL_STATUS_BURST)
+				ProcessWheel(wheelFwd, wheelRight,
+					contactSpeeds[rightWheel], contactPoints[rightWheel],
+					m_nWheelsOnGround, fThrust,
+					brake*brakeBias,
+					adhesion*tractionBias*Damage.m_fWheelDamageEffect,
+					rightWheel,
+					&m_aWheelRotation[rightWheel],
+					&WheelState,
+					WHEEL_STATUS_BURST);
+			else
+				ProcessWheel(wheelFwd, wheelRight,
+					contactSpeeds[rightWheel], contactPoints[rightWheel],
+					m_nWheelsOnGround, fThrust,
+					brake*brakeBias,
+					adhesion*tractionBias,
+					rightWheel,
+					&m_aWheelRotation[rightWheel],
+					&WheelState,
+					WHEEL_STATUS_OK);
+
+			if(driveWheels && m_fGasPedal < 0.0f && WheelState == WHEEL_STATE_SPINNING)
+				m_aWheelState[rightWheel] = WHEEL_STATE_NORMAL;
+			else
+				m_aWheelState[rightWheel] = WheelState;
+		}
+	}
+
+	if(!bFront){
+		if(m_doingBurnout && driveWheels &&
+		   (m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING || m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)){
+			m_fTireTemperature += 0.001f*CTimer::GetTimeStep();
+			if(m_fTireTemperature > 3.0f)
+				m_fTireTemperature = 3.0f;
+		}else if(m_fTireTemperature > 1.0f){
+			m_fTireTemperature = (m_fTireTemperature - 1.0f)*Pow(0.995f, CTimer::GetTimeStep()) + 1.0f;
+		}
+	}
+
+	// Process wheels off ground
+
+	if(!IsRealHeli()){
+		if(m_aWheelTimer[leftWheel] <= 0.0f){
+			if(driveWheels && acceleration != 0.0f){
+				if(acceleration > 0.0f){
+					if(m_aWheelSpeed[leftWheel] < 1.0f)
+						m_aWheelSpeed[leftWheel] -= 0.1f;
+				}else{
+					if(m_aWheelSpeed[leftWheel] > -1.0f)
+						m_aWheelSpeed[leftWheel] += 0.05f;
+				}
+			}else{
+				m_aWheelSpeed[leftWheel] *= 0.95f;
+			}
+			m_aWheelRotation[leftWheel] += m_aWheelSpeed[leftWheel]*CTimer::GetTimeStep();
+		}
+		if(m_aWheelTimer[rightWheel] <= 0.0f){
+			if(driveWheels && acceleration != 0.0f){
+				if(acceleration > 0.0f){
+					if(m_aWheelSpeed[rightWheel] < 1.0f)
+						m_aWheelSpeed[rightWheel] -= 0.1f;
+				}else{
+					if(m_aWheelSpeed[rightWheel] > -1.0f)
+						m_aWheelSpeed[rightWheel] += 0.05f;
+				}
+			}else{
+				m_aWheelSpeed[rightWheel] *= 0.95f;
+			}
+			m_aWheelRotation[rightWheel] += m_aWheelSpeed[rightWheel]*CTimer::GetTimeStep();
+		}
+	}
+}
+
 void
 CAutomobile::Teleport(CVector pos)
 {
@@ -1731,6 +1547,11 @@ CAutomobile::PreRender(void)
 	int i, j, n;
 	CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
 
+	if(GetModelIndex() == MI_FIRETRUCK)
+		FireTruckControl();
+
+	CVehicle::PreRender();
+
 	if(GetModelIndex() == MI_RHINO && m_aCarNodes[CAR_WINDSCREEN]){
 		// Rotate Rhino turret
 		CMatrix m;
@@ -3009,6 +2830,7 @@ CAutomobile::Render(void)
 		CEntity::Render();
 }
 
+//--LCS: done
 int32
 CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
 {
@@ -3080,9 +2902,13 @@ static float fMouseCentreRange = 0.35f;
 static float fMouseSteerSens = -0.0035f;
 static float fMouseCentreMult = 0.975f;
 
+//--LCS: done except TODO
 void
 CAutomobile::ProcessControlInputs(uint8 pad)
 {
+	if(this == FindPlayerVehicle() && CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
+		return;
+
 	float speed = DotProduct(m_vecMoveSpeed, GetForward());
 
 	if(!CPad::GetPad(pad)->GetExitVehicle() ||
@@ -3093,6 +2919,7 @@ CAutomobile::ProcessControlInputs(uint8 pad)
 		bIsHandbrakeOn = true;
 
 	// Steer left/right
+#if 0	// LCS: removed, need mouse for free cam
 	if(CCamera::m_bUseMouse3rdPerson && !CVehicle::m_bDisableMouseSteering){
 		if(CPad::GetPad(pad)->GetMouseX() != 0.0f){
 			m_fSteerInput += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX();
@@ -3105,7 +2932,9 @@ CAutomobile::ProcessControlInputs(uint8 pad)
 				0.2f*CTimer::GetTimeStep();
 			nLastControlInput = 0;
 		}
-	}else{
+	}else
+#endif
+	{
 		m_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)*
 			0.2f*CTimer::GetTimeStep();
 		nLastControlInput = 0;
@@ -3198,6 +3027,7 @@ CAutomobile::ProcessControlInputs(uint8 pad)
 
 	// Brake if player isn't in control
 	// BUG: game always uses pad 0 here
+	// TODO(LCS): more conditions here
 #ifdef FIX_BUGS
 	if(CPad::GetPad(pad)->ArePlayerControlsDisabled()){
 #else
@@ -3920,6 +3750,7 @@ CAutomobile::DoDriveByShootings(void)
 	}
 }
 
+//--LCS: done
 void
 CAutomobile::DoHoverSuspensionRatios(void)
 {
@@ -5016,6 +4847,7 @@ CAutomobile::ResetSuspension(void)
 	}
 }
 
+//--LCS: done
 void
 CAutomobile::SetupSuspensionLines(void)
 {
@@ -5024,6 +4856,14 @@ CAutomobile::SetupSuspensionLines(void)
 	CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
 	CColModel *colModel = mi->GetColModel();
 
+	bool adjustColModel;
+	if(colModel->lines == nil){
+		adjustColModel = true;
+		colModel->lines = new CColLine[4];
+		colModel->numLines = 4;
+	}else
+		adjustColModel = false;
+
 	// Each suspension line starts at the uppermost wheel position
 	// and extends down to the lowermost point on the tyre
 	for(i = 0; i < 4; i++){
@@ -5063,6 +4903,21 @@ CAutomobile::SetupSuspensionLines(void)
 		for(i = 0; i < colModel->numSpheres; i++)
 			colModel->spheres[i].radius = 0.3f;
 	}
+
+	if(pHandling->Flags & HANDLING_FORCE_GRND_CLR && adjustColModel){
+		// 0.25 is the min distance between ground and col spheres, everything above it is safe
+		float safePos = 0.25f - m_fHeightAboveRoad;
+		for(i = 0; i < colModel->numSpheres; i++){
+			CColSphere *sph = &colModel->spheres[i];
+			if(sph->center.z - sph->radius < safePos){
+				// sphere extends too far down, so move it up
+				// or decrease the radius for bigger spheres
+				if(radius > 0.4f)
+					sph->radius = Max(sph->center.z - safePos, 0.4f);
+				sph->center.z = safePos + sph->radius;
+			}
+		}
+	}
 }
 
 // called on police cars
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index 16d86917..4f4ab500 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -26,6 +26,8 @@ public:
 	float m_aSuspensionSpringRatioPrev[4];
 	float m_aWheelTimer[4];		// set to 4.0 when wheel is touching ground, then decremented
 	float m_auto_unused1;
+	float m_fEngineInertiaVar1;
+	float m_fEngineInertiaVar2;
 	eSkidmarkType m_aWheelSkidmarkType[4];
 	bool m_aWheelSkidmarkBloody[4];
 	bool m_aWheelSkidmarkUnk[4];
@@ -114,6 +116,7 @@ public:
 	float GetHeightAboveRoad(void);
 	void PlayCarHorn(void);
 
+	void ProcessCarWheelPair(int leftWheel, int rightWheel, float steerAngle, CVector *contactSpeeds, CVector *contactPoints, float traction, float acceleration, float brake, bool bFront);
 	void FireTruckControl(void);
 	void TankControl(void);
 	void HydraulicControl(void);
diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp
index 72188a17..cc57f1b4 100644
--- a/src/vehicles/Bike.cpp
+++ b/src/vehicles/Bike.cpp
@@ -111,7 +111,7 @@ CBike::CBike(int32 id, uint8 CreatedBy)
 	m_fTurnMass = pHandling->fTurnMass;
 	m_vecCentreOfMass = pHandling->CentreOfMass;
 	m_vecCentreOfMass.z = 0.1f;
-	m_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass;
+	m_fAirResistance = pHandling->fDragMult > 0.01f ? pHandling->fDragMult*0.0005f : pHandling->fDragMult;
 	m_fElasticity = 0.05f;
 	m_fBuoyancy = pHandling->fBuoyancy;
 
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index 8dec0f89..622573b0 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -72,7 +72,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner)
 	m_fMass = pHandling->fMass;
 	m_fTurnMass = pHandling->fTurnMass / 2.0f;
 	m_vecCentreOfMass = pHandling->CentreOfMass;
-	m_fAirResistance = pHandling->Dimension.x * pHandling->Dimension.z / m_fMass;
+	m_fAirResistance = pHandling->fDragMult > 0.01f ? pHandling->fDragMult*0.0005f : pHandling->fDragMult;
 	m_fElasticity = 0.1f;
 	m_fBuoyancy = pHandling->fBuoyancy;
 	m_fSteerAngle = 0.0f;
diff --git a/src/vehicles/DamageManager.cpp b/src/vehicles/DamageManager.cpp
index 8ba235b7..b74e7086 100644
--- a/src/vehicles/DamageManager.cpp
+++ b/src/vehicles/DamageManager.cpp
@@ -10,7 +10,8 @@ float G_aComponentDamage[] = { 2.5f, 1.25f, 3.2f, 1.4f, 2.5f, 2.8f, 0.5f };
 CDamageManager::CDamageManager(void)
 {
 	ResetDamageStatus();
-	m_fWheelDamageEffect = 0.5f;
+	m_fWheelDamageEffect = 0.65f;
+	m_bSmashedDoorDoesntClose = false;
 	field_18 = 1;
 }
 
@@ -136,6 +137,8 @@ void
 CDamageManager::SetDoorStatus(int32 door, uint32 status)
 {
 	m_doorStatus[door] = status;
+	if(m_bSmashedDoorDoesntClose && door != DOOR_BONNET && status == DOOR_STATUS_SMASHED)
+		m_doorStatus[door] = DOOR_STATUS_SWINGING;
 }
 
 int32
diff --git a/src/vehicles/DamageManager.h b/src/vehicles/DamageManager.h
index 312006e3..1f836429 100644
--- a/src/vehicles/DamageManager.h
+++ b/src/vehicles/DamageManager.h
@@ -81,6 +81,7 @@ class CDamageManager
 public:
 
 	float m_fWheelDamageEffect;
+	bool m_bSmashedDoorDoesntClose;
 	uint8 m_engineStatus;
 	uint8 m_wheelStatus[4];
 	uint8 m_doorStatus[6];
diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp
index 040b6972..1a8d059c 100644
--- a/src/vehicles/HandlingMgr.cpp
+++ b/src/vehicles/HandlingMgr.cpp
@@ -115,18 +115,17 @@ void
 cHandlingDataMgr::LoadHandlingData(void)
 {
 	char *start, *end;
-	char line[201];	// weird value
+	char line[300];
 	char delim[4];	// not sure
 	char *word;
 	int field, handlingId;
-	int keepGoing;
 	tHandlingData *handling;
 	tFlyingHandlingData *flyingHandling;
 	tBoatHandlingData *boatHandling;
 	tBikeHandlingData *bikeHandling;
 
 	CFileMgr::SetDir("DATA");
-	CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r");
+	ssize_t filesz = CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r");
 	CFileMgr::SetDir("");
 
 	start = (char*)work_buff;
@@ -135,21 +134,18 @@ cHandlingDataMgr::LoadHandlingData(void)
 	flyingHandling = nil;
 	boatHandling = nil;
 	bikeHandling = nil;
-	keepGoing = 1;
 
-	while(keepGoing){
+	while(start < (char*)&work_buff[filesz]){
 		// find end of line
 		while(*end != '\n') end++;
 
 		// get line
 		strncpy(line, start, end - start);
 		line[end - start] = '\0';
-		start = end+1;
-		end = start+1;
 
 		// yeah, this is kinda crappy
 		if(strcmp(line, ";the end") == 0)
-			keepGoing = 0;
+			break;
 		else if(line[0] != ';'){
 			if(line[0] == '!'){
 				// Bike data
@@ -263,19 +259,19 @@ cHandlingDataMgr::LoadHandlingData(void)
 						handling->nIdentifier = (tVehicleType)handlingId;
 						break;
 					case  1: handling->fMass = atof(word); break;
-					case  2: handling->Dimension.x = atof(word); break;
-					case  3: handling->Dimension.y = atof(word); break;
-					case  4: handling->Dimension.z = atof(word); break;
-					case  5: handling->CentreOfMass.x = atof(word); break;
-					case  6: handling->CentreOfMass.y = atof(word); break;
-					case  7: handling->CentreOfMass.z = atof(word); break;
-					case  8: handling->nPercentSubmerged = atoi(word); break;
-					case  9: handling->fTractionMultiplier = atof(word); break;
-					case 10: handling->fTractionLoss = atof(word); break;
-					case 11: handling->fTractionBias = atof(word); break;
-					case 12: handling->Transmission.nNumberOfGears = atoi(word); break;
-					case 13: handling->Transmission.fMaxVelocity = atof(word); break;
-					case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4; break;
+					case  2: handling->fTurnMass = atof(word); break;
+					case  3: handling->fDragMult = atof(word); break;
+					case  4: handling->CentreOfMass.x = atof(word); break;
+					case  5: handling->CentreOfMass.y = atof(word); break;
+					case  6: handling->CentreOfMass.z = atof(word); break;
+					case  7: handling->nPercentSubmerged = atoi(word); break;
+					case  8: handling->fTractionMultiplier = atof(word); break;
+					case  9: handling->fTractionLoss = atof(word); break;
+					case 10: handling->fTractionBias = atof(word); break;
+					case 11: handling->Transmission.nNumberOfGears = atoi(word); break;
+					case 12: handling->Transmission.fMaxVelocity = atof(word); break;
+					case 13: handling->Transmission.fEngineAcceleration = atof(word) * 0.4; break;
+					case 14: handling->Transmission.fEngineInertia = atof(word); break;
 					case 15: handling->Transmission.nDriveType = word[0]; break;
 					case 16: handling->Transmission.nEngineType = word[0]; break;
 					case 17: handling->fBrakeDeceleration = atof(word); break;
@@ -284,25 +280,28 @@ cHandlingDataMgr::LoadHandlingData(void)
 					case 20: handling->fSteeringLock = atof(word); break;
 					case 21: handling->fSuspensionForceLevel = atof(word); break;
 					case 22: handling->fSuspensionDampingLevel = atof(word); break;
-					case 23: handling->fSeatOffsetDistance = atof(word); break;
-					case 24: handling->fCollisionDamageMultiplier = atof(word); break;
-					case 25: handling->nMonetaryValue = atoi(word); break;
-					case 26: handling->fSuspensionUpperLimit = atof(word); break;
-					case 27: handling->fSuspensionLowerLimit = atof(word); break;
-					case 28: handling->fSuspensionBias = atof(word); break;
-					case 29: handling->fSuspensionAntidiveMultiplier = atof(word); break;
-					case 30:
+					// case 23:	// fSuspensionHighSpdComDamp unused
+					case 24: handling->fSuspensionUpperLimit = atof(word); break;
+					case 25: handling->fSuspensionLowerLimit = atof(word); break;
+					case 26: handling->fSuspensionBias = atof(word); break;
+					case 27: handling->fSuspensionAntidiveMultiplier = atof(word); break;
+					case 28: handling->fSeatOffsetDistance = atof(word); break;
+					case 29: handling->fCollisionDamageMultiplier = atof(word); break;
+					case 30: handling->nMonetaryValue = atoi(word); break;
+					case 31:
 						sscanf(word, "%x", &handling->Flags);
-						handling->Transmission.Flags = handling->Flags;
+					//	handling->Transmission.Flags = handling->Flags;
 						break;
-					case 31: handling->FrontLights = atoi(word); break;
-					case 32: handling->RearLights = atoi(word); break;
+					case 32: handling->FrontLights = atoi(word); break;
+					case 33: handling->RearLights = atoi(word); break;
 					}
 					field++;
 				}
 				ConvertDataToGameUnits(handling);
 			}
 		}
+		start = end+1;
+		end = start+1;
 	}
 }
 
@@ -330,12 +329,9 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
 	handling->Transmission.fEngineAcceleration *= 1.0f/(50.0f*50.0f);
 	handling->Transmission.fMaxVelocity *= 1000.0f/(60.0f*60.0f * 50.0f);
 	handling->fBrakeDeceleration *= 1.0f/(50.0f*50.0f);
-	handling->fTurnMass = (sq(handling->Dimension.x) + sq(handling->Dimension.y)) * handling->fMass / 12.0f;
-	if(handling->fTurnMass < 10.0f)
-		handling->fTurnMass *= 5.0f;
-	handling->fInvMass = 1.0f/handling->fMass;
-	handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass;
-	handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * GRAVITY*handling->fMass;
+	handling->fInvMass = 1.0f/handling->GetMass();
+	handling->fCollisionDamageMultiplier = handling->GetCollisionDamageMultiplier() * 2000.0f/handling->GetMass();
+	handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * GRAVITY*handling->GetMass();
 
 	// Don't quite understand this. What seems to be going on is that
 	// we calculate a drag (air resistance) deceleration for a given velocity and
@@ -348,10 +344,13 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
 		velocity -= 0.01f;
 		// what's the 1/6?
 		a = handling->Transmission.fEngineAcceleration/6.0f;
-		// no density or drag coefficient here...
-		float a_drag = 0.5f*SQR(velocity) * handling->Dimension.x*handling->Dimension.z / handling->fMass;
-		// can't make sense of this... maybe  v - v/(drag + 1)  ? but that doesn't make so much sense either
-		b = -velocity * (1.0f/(a_drag + 1.0f) - 1.0f);
+		// no idea what's happening here
+		float drag;
+		if(handling->fDragMult < 0.01f)
+			drag = 1.0f - 1.0f/(SQR(velocity)*handling->fDragMult + 1.0f);
+		else
+			drag = 0.0005f*handling->fDragMult * velocity;
+		b = velocity * drag;
 	}
 
 	if(handling->nIdentifier == HANDLING_RCBANDIT){
diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h
index e6b5236f..2d49761c 100644
--- a/src/vehicles/HandlingMgr.h
+++ b/src/vehicles/HandlingMgr.h
@@ -93,7 +93,7 @@ enum tVehicleType
 
 	NUMBIKEHANDLINGS = HANDLING_FREEWAY+1 - HANDLING_BIKE,
 	NUMFLYINGHANDLINGS = HANDLING_RCCOPTER+1 - HANDLING_MAVERICK,
-	NUMBOATHANDLINGS = HANDLING_COASTMAV+1 - HANDLING_PREDATOR,
+	NUMBOATHANDLINGS = HANDLING_REEFER+1 - HANDLING_PREDATOR,
 };
 
 enum tField // most likely a handling field enum, never used so :shrug:
@@ -131,19 +131,21 @@ enum
 	HANDLING_NARROW_FRONTW = 0x2000000,
 	HANDLING_GOOD_INSAND = 0x4000000,
 	HANDLING_UNKNOWN = 0x8000000,	// something for helis and planes
+	HANDLING_FORCE_GRND_CLR = 0x10000000
 };
 
 struct tHandlingData
 {
-	tVehicleType nIdentifier;
 	float fMass;
-	float fInvMass;
 	float fTurnMass;
-	CVector Dimension;
+	float fTractionMultiplier;
+	float fCollisionDamageMultiplier;
+	tVehicleType nIdentifier;
+	float fInvMass;
+	float fDragMult;
 	CVector CentreOfMass;
 	int8 nPercentSubmerged;
 	float fBuoyancy;
-	float fTractionMultiplier;
 	cTransmission Transmission;
 	float fBrakeDeceleration;
 	float fBrakeBias;
@@ -158,12 +160,17 @@ struct tHandlingData
 	float fSuspensionLowerLimit;
 	float fSuspensionBias;
 	float fSuspensionAntidiveMultiplier;
-	float fCollisionDamageMultiplier;
 	uint32 Flags;
 	float fSeatOffsetDistance;
 	int32 nMonetaryValue;
 	int8 FrontLights;
 	int8 RearLights;
+	int unk[4];
+
+	float GetMass(void) const { return fMass; }
+	float GetTurnMass(void) const { return fTurnMass; }
+	float GetTractionMultiplier(void) const { return fTractionMultiplier; }
+	float GetCollisionDamageMultiplier(void) const { return fCollisionDamageMultiplier; }
 };
 
 struct tBikeHandlingData
@@ -249,7 +256,7 @@ public:
 	tBikeHandlingData *GetBikePointer(uint8 id) { return &BikeHandlingData[id-HANDLING_BIKE]; }
 	tFlyingHandlingData *GetFlyingPointer(uint8 id);
 	tBoatHandlingData *GetBoatPointer(uint8 id);
-	bool HasRearWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType == 'R'; }
-	bool HasFrontWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType == 'F'; }
+	bool HasRearWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType != 'F'; }
+	bool HasFrontWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType != 'R'; }
 };
 extern cHandlingDataMgr mod_HandlingManager;
diff --git a/src/vehicles/Transmission.cpp b/src/vehicles/Transmission.cpp
index b3e1af7d..ce4b97f4 100644
--- a/src/vehicles/Transmission.cpp
+++ b/src/vehicles/Transmission.cpp
@@ -4,7 +4,7 @@
 #include "HandlingMgr.h"
 #include "Transmission.h"
 
-//--MIAMI: done
+//--LCS: file done
 
 void
 cTransmission::InitGearRatios(void)
@@ -16,11 +16,14 @@ cTransmission::InitGearRatios(void)
 
 	memset(Gears, 0, sizeof(Gears));
 
+	float baseVelocity = 0.5f*fMaxVelocity / nNumberOfGears;
+	float step = (fMaxVelocity - baseVelocity) / nNumberOfGears;
+
 	for(i = 1; i <= nNumberOfGears; i++){
 		pGearRatio0 = &Gears[i-1];
 		pGearRatio1 = &Gears[i];
 
-		pGearRatio1->fMaxVelocity = (float)i / nNumberOfGears * fMaxVelocity;
+		pGearRatio1->fMaxVelocity = baseVelocity + i*step;
 
 		velocityDiff = pGearRatio1->fMaxVelocity - pGearRatio0->fMaxVelocity;
 
@@ -47,9 +50,12 @@ cTransmission::CalculateGearForSimpleCar(float speed, uint8 &gear)
 
 	pGearRatio = &Gears[gear];
 	fCurVelocity = speed;
-	if(speed > pGearRatio->fShiftUpVelocity)
-		gear++;
-	else if(speed < pGearRatio->fShiftDownVelocity){
+	if(speed > pGearRatio->fShiftUpVelocity){
+		if(gear + 1 > nNumberOfGears)
+			gear = nNumberOfGears;
+		else
+			gear++;
+	}else if(speed < pGearRatio->fShiftDownVelocity){
 		if(gear - 1 < 0)
 			gear = 0;
 		else
@@ -57,6 +63,110 @@ cTransmission::CalculateGearForSimpleCar(float speed, uint8 &gear)
 	}
 }
 
+float TRANSMISSION_NITROS_INERTIA_MULT = 0.5f;
+float TRANSMISSION_AI_CHEAT_INERTIA_MULT = 0.75f;
+float TRANSMISSION_NITROS_MULT = 2.0f;
+float TRANSMISSION_AI_CHEAT_MULT = 1.2f;
+float TRANSMISSION_SMOOTHER_FRAC = 0.85f;
+float TRANSMISSION_FREE_ACCELERATION = 0.1f;
+
+//--LCS: done
+float
+cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, float *inertiaVar1, float *inertiaVar2, uint8 nDriveWheels, uint8 cheat)
+{
+	static float fAcceleration = 0.0f;
+	static float fVelocity;
+	static float fCheat;
+	static tGear *pGearRatio;
+
+	fVelocity = velocity;
+	if(fVelocity < fMaxReverseVelocity)
+		return 0.0f;
+	if(fVelocity > fMaxVelocity)
+		return 0.0f;
+	fCurVelocity = fVelocity;
+
+	assert(gear <= nNumberOfGears);
+
+	pGearRatio = &Gears[gear];
+	if(fVelocity > pGearRatio->fShiftUpVelocity){
+		if(gear != 0 || gasPedal > 0.0f){
+			gear++;
+			return CalculateDriveAcceleration(gasPedal, gear, time, fVelocity, nil, nil, 0, false);
+		}
+	}else if(fVelocity < pGearRatio->fShiftDownVelocity && gear != 0){
+		if(gear != 1 || gasPedal < 0.0f){
+			gear--;
+			return CalculateDriveAcceleration(gasPedal, gear, time, fVelocity, nil, nil, 0, false);
+		}
+	}
+
+	float accelMul;
+
+	if(nNumberOfGears == 1){
+		accelMul = 1.0f;
+	}else if(gear == 0){
+		accelMul = 4.5f;
+	}else{
+		float f = 1.0f - (gear-1.0f)/(nNumberOfGears-1.0f);
+		if(Flags & HANDLING_1G_BOOST)
+			accelMul = SQR(f)*5.0f + 1.0f;
+		else if(Flags & HANDLING_2G_BOOST)
+			accelMul = SQR(f)*4.0f + 1.0f;
+		else
+			accelMul = SQR(f)*3.0f + 1.0f;
+	}
+
+	fCheat = 1.0f;
+	float nitroMult = 1.0f;
+	if(cheat == 1)
+		fCheat = TRANSMISSION_AI_CHEAT_MULT;
+	else if(cheat == 2)
+		nitroMult = TRANSMISSION_NITROS_MULT;
+
+	fAcceleration = fEngineAcceleration*CTimer::GetTimeStep()*0.4f*accelMul*gasPedal*fCheat*nitroMult;
+
+	if(inertiaVar1 != nil && inertiaVar2 != nil){
+		if(nDriveWheels == 0){
+			float f = TRANSMISSION_FREE_ACCELERATION*CTimer::GetTimeStep()*Abs(gasPedal)/fEngineInertia;
+			*inertiaVar1 = Min(*inertiaVar1 + f, 1.0f);
+			*inertiaVar2 = 0.1f;
+		}else{
+			float var1;
+			// What is being calculated here?
+			// TODO: find better names for the inertia vars
+			if(gear == 0){
+				var1 = ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) - fVelocity) /
+				       ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) - Gears[gear].fShiftDownVelocity);
+			}else if(gear == 1){
+				var1 = ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) + fVelocity) /
+				       ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) + Gears[gear].fShiftUpVelocity);
+			}else{
+				var1 = (fVelocity - Gears[gear].fShiftDownVelocity) /
+				       (Gears[gear].fShiftUpVelocity - Gears[gear].fShiftDownVelocity);
+			}
+			float inertiaMult = var1 - *inertiaVar1;
+			if(cheat == 1)
+				inertiaMult *= TRANSMISSION_AI_CHEAT_INERTIA_MULT;
+			else if(cheat == 2)
+				inertiaMult *= TRANSMISSION_NITROS_INERTIA_MULT;
+			float var2target = 1.0f - inertiaMult*fEngineInertia;
+			var2target = clamp(var2target, 0.1f, 1.0f);
+			*inertiaVar2 = (1.0f-TRANSMISSION_SMOOTHER_FRAC)*var2target + TRANSMISSION_SMOOTHER_FRAC*(*inertiaVar2);
+			*inertiaVar1 = var1;
+			fAcceleration *= *inertiaVar2;
+		}
+	}
+
+	float targetVelocity = Gears[gear].fMaxVelocity*fCheat;
+	if(Gears[gear].fMaxVelocity < 0.0f && targetVelocity > fVelocity)
+		fAcceleration *= 1.0f - Min((targetVelocity - fVelocity)/0.05f, 1.0f);
+	else if(Gears[gear].fMaxVelocity > 0.0f && targetVelocity < fVelocity)
+		fAcceleration *= 1.0f - Min((fVelocity - targetVelocity)/0.05f, 1.0f);
+	return fAcceleration;
+}
+
+// TEMP old VC code until we have bikes
 float
 cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, bool cheat)
 {
diff --git a/src/vehicles/Transmission.h b/src/vehicles/Transmission.h
index a3d15513..8aea7b02 100644
--- a/src/vehicles/Transmission.h
+++ b/src/vehicles/Transmission.h
@@ -17,6 +17,7 @@ public:
 	int8 nNumberOfGears;
 	uint8 Flags;
 	float fEngineAcceleration;
+	float fEngineInertia;
 	float fMaxVelocity;
 	float fMaxCruiseVelocity;
 	float fMaxReverseVelocity;
@@ -24,5 +25,6 @@ public:
 
 	void InitGearRatios(void);
 	void CalculateGearForSimpleCar(float speed, uint8 &gear);
+	float CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, float *inertiaVar1, float *inertiaVar2, uint8 nDriveWheels, uint8 cheat);
 	float CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, bool cheat);
 };
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 145611b1..2625ab78 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -33,8 +33,6 @@
 #include "Weather.h"
 #include "Coronas.h"
 
-//--MIAMI: done
-
 bool CVehicle::bWheelsOnlyCheat;
 bool CVehicle::bAllDodosCheat;
 bool CVehicle::bCheat3;
@@ -764,7 +762,9 @@ CVehicle::BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix &
 }
 
 
-float fBurstSpeedMax = 0.3f;
+float WS_ALREADY_SPINNING_LOSS = 0.2f;
+float WS_TRAC_FRAC_LIMIT = 0.3f;
+float fBurstSpeedMax = 0.2f;
 float fBurstTyreMod = 0.13f;
 
 void
@@ -792,13 +792,15 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
 	float contactSpeedFwd = DotProduct(wheelContactSpeed, wheelFwd);
 	float contactSpeedRight = DotProduct(wheelContactSpeed, wheelRight);
 
-	if(*wheelState != WHEEL_STATE_NORMAL)
+	adhesion *= CTimer::GetTimeStep();
+	if(*wheelState != WHEEL_STATE_NORMAL){
 		bAlreadySkidding = true;
+		adhesion *= pHandling->fTractionLoss;
+		if(*wheelState == WHEEL_STATE_SPINNING && (GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_REMOTE))
+			adhesion *= 1.0f - Abs(m_fGasPedal) * WS_ALREADY_SPINNING_LOSS;
+	}
 	*wheelState = WHEEL_STATE_NORMAL;
 
-	adhesion *= CTimer::GetTimeStep();
-	if(bAlreadySkidding)
-		adhesion *= pHandling->fTractionLoss;
 
 	// moving sideways
 	if(contactSpeedRight != 0.0f){
@@ -838,13 +840,15 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
 		if(!bBraking){
 			if(m_fGasPedal < 0.01f){
 				if(IsBike())
-					brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f);
-				else if(pHandling->fMass < 500.0f)
-					brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;
+					brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->GetMass() + 200.0f);
+				else if(IsPlane())
+					brake = 0.0f;
+				else if(pHandling->GetMass() < 500.0f)
+					brake = 0.1f * mod_HandlingManager.fWheelFriction / pHandling->GetMass();
 				else if(GetModelIndex() == MI_RCBANDIT)
-					brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;
+					brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->GetMass();
 				else
-					brake = mod_HandlingManager.fWheelFriction / pHandling->fMass;
+					brake = mod_HandlingManager.fWheelFriction / pHandling->GetMass();
 #ifdef FIX_BUGS
 				brake *= CTimer::GetTimeStepFix();
 #endif
@@ -868,7 +872,10 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
 	float speedSq = sq(right) + sq(fwd);
 	if(sq(adhesion) < speedSq){
 		if(*wheelState != WHEEL_STATE_FIXED){
-			if(bDriving && contactSpeedFwd < 0.2f)
+			float tractionLimit = WS_TRAC_FRAC_LIMIT;
+			if(contactSpeedFwd > 0.15f && (wheelId == CARWHEEL_FRONT_LEFT || wheelId == CARWHEEL_FRONT_RIGHT))
+				tractionLimit *= 2.0f;
+			if(bDriving && tractionLimit*adhesion < Abs(fwd))
 				*wheelState = WHEEL_STATE_SPINNING;
 			else
 				*wheelState = WHEEL_STATE_SKIDDING;
@@ -876,6 +883,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
 
 		float l = Sqrt(speedSq);
 		float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss;
+		if(*wheelState == WHEEL_STATE_SPINNING && (GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_REMOTE))
+			tractionLoss *= 1.0f - Abs(m_fGasPedal) * WS_ALREADY_SPINNING_LOSS;
 		right *= adhesion * tractionLoss / l;
 		fwd *= adhesion * tractionLoss / l;
 	}
@@ -884,7 +893,7 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
 		CVector totalSpeed = fwd*wheelFwd + right*wheelRight;
 
 		CVector turnDirection = totalSpeed;
-		bool separateTurnForce = false;	// BUG: not initialized on PC
+		bool separateTurnForce = false;
 		if(pHandling->fSuspensionAntidiveMultiplier > 0.0f){
 			if(bBraking){
 				separateTurnForce = true;
@@ -921,6 +930,7 @@ float fBurstBikeSpeedMax = 0.12f;
 float fBurstBikeTyreMod = 0.05f;
 float fTweakBikeWheelTurnForce = 2.0f;
 
+//--LCS: done
 void
 CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
 	int32 wheelsOnGround, float thrust, float brake, float adhesion, float destabTraction, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus)
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 795161bf..29a4eea1 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -250,6 +250,7 @@ public:
 	int8 m_nPacManPickupsCarried;
 	uint8 m_nRoadblockType;
 	float m_fHealth;           // 1000.0f = full health. 250.0f = fire. 0 -> explode
+	float m_fEngineEnergy;	// TODO(LCS): better name. it adds up acceleration force, so possibly kinetic energy??
 	uint8 m_nCurrentGear;
 	float m_fChangeGearTime;
 #if (!defined GTA_PS2 || defined FIX_BUGS)
@@ -288,6 +289,7 @@ public:
 	~CVehicle(void);
 	// from CEntity
 	void SetModelIndex(uint32 id);
+	void PreRender(void) {}
 	bool SetupLighting(void);
 	void RemoveLighting(bool);
 	void FlagToDestroyWhenNextProcessed(void) {}