diff --git a/src/core/Explosion.h b/src/core/Explosion.h
index 69508490..93d60ab3 100644
--- a/src/core/Explosion.h
+++ b/src/core/Explosion.h
@@ -4,8 +4,16 @@ class CEntity;
 
 enum eExplosionType
 {
-	EXPLOSION_3 = 3,
-	EXPLOSION_4
+	EXPLOSION_GRENADE,
+	EXPLOSION_MOLOTOV,
+	EXPLOSION_ROCKET,
+	EXPLOSION_CAR,
+	EXPLOSION_CAR_QUICK,
+	EXPLOSION_HELI,
+	EXPLOSION_MINE,
+	EXPLOSION_BARREL,
+	EXPLOSION_TANK_GRENADE,
+	EXPLOSION_HELI_BOMB
 };
 
 class CExplosion
diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h
index d8128424..9327b9a0 100644
--- a/src/core/PlayerInfo.h
+++ b/src/core/PlayerInfo.h
@@ -45,10 +45,10 @@ public:
 	int8 field_225;
 	int8 field_226;
 	int8 field_227;
-	int32 m_nTimeLostRemoteCar;
-	int32 m_nTimeLastHealthLoss;
-	int32 m_nTimeLastArmourLoss;
-	int32 field_240;
+	uint32 m_nTimeLostRemoteCar;
+	uint32 m_nTimeLastHealthLoss;
+	uint32 m_nTimeLastArmourLoss;
+	uint32 m_nTimeTankShotGun;
 	int32 m_nUpsideDownCounter;
 	int32 field_248;
 	int16 m_nTrafficMultiplier;
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index a0032bc6..6566a282 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -296,6 +296,8 @@ DebugMenuPopulate(void)
 		DebugMenuAddCmd("Spawn", "Spawn Banshee", [](){ SpawnCar(MI_BANSHEE); });
 		DebugMenuAddCmd("Spawn", "Spawn Yakuza", [](){ SpawnCar(MI_YAKUZA); });
 		DebugMenuAddCmd("Spawn", "Spawn Dodo", [](){ SpawnCar(MI_DODO); });
+		DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); });
+		DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); });
 
 
 		DebugMenuAddCmd("Debug", "Fix Car", FixCar);
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index bc0c8593..0c4d0ff9 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -1421,9 +1421,111 @@ CAutomobile::FireTruckControl(void)
 { EAXJMP(0x522590);
 }
 
-WRAPPER void
+void
 CAutomobile::TankControl(void)
-{ EAXJMP(0x53D530);
+{
+	int i;
+
+	// These coords are 1 unit higher then they should be relative to model center
+	CVector turrentBase(0.0f, -1.394f, 2.296f);
+	CVector gunEnd(0.0f, 1.813f, 2.979f);
+	CVector baseToEnd = gunEnd - turrentBase;
+
+	if(this != FindPlayerVehicle())
+		return;
+	if(CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING)
+		return;
+
+	// Rotate turret
+	float prevAngle = m_fCarGunLR;
+	m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep();
+	if(m_fCarGunLR < 0.0f)
+		m_fCarGunLR += TWOPI;
+	if(m_fCarGunLR > TWOPI)
+		m_fCarGunLR -= TWOPI;
+	if(m_fCarGunLR != prevAngle)
+		DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_TANK_TURRET_ROTATE, Abs(m_fCarGunLR - prevAngle));
+
+	// Shoot
+	if(CPad::GetPad(0)->CarGunJustDown() &&
+	   CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeTankShotGun + 800){
+		CWorld::Players[CWorld::PlayerInFocus].m_nTimeTankShotGun = CTimer::GetTimeInMilliseconds();
+
+		// more like -sin(angle), cos(angle), i.e. rotated (0,1,0)
+		CVector turretDir = CVector(Sin(-m_fCarGunLR), Cos(-m_fCarGunLR), 0.0f);
+		turretDir = Multiply3x3(GetMatrix(), turretDir);
+
+		float c = Cos(m_fCarGunLR);
+		float s = Sin(m_fCarGunLR);
+		CVector rotatedEnd(
+			c*baseToEnd.x - s*baseToEnd.y,
+			s*baseToEnd.x + c*baseToEnd.y,
+			baseToEnd.z - 1.0f);	// correct offset here
+		rotatedEnd += turrentBase;
+
+		CVector point1 = GetMatrix() * rotatedEnd;
+		CVector point2 = point1 + 60.0f*turretDir;
+		m_vecMoveSpeed -= 0.06f*turretDir;
+		m_vecMoveSpeed.z += 0.05f;
+
+		CWeapon::DoTankDoomAiming(FindPlayerVehicle(), FindPlayerPed(), &point1, &point2);
+		CColPoint colpoint;
+		CEntity *entity = nil;
+		CWorld::ProcessLineOfSight(point1, point2, colpoint, entity, true, true, true, true, true, true, false);
+		if(entity)
+			point2 = colpoint.point - 0.04f*(colpoint.point - point1);
+
+		CExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_TANK_GRENADE, point2, 0);
+
+		// Add particles on the way to the explosion;
+		float shotDist = (point2 - point1).Magnitude();
+		int n = shotDist/4.0f;
+		RwRGBA black = { 0, 0, 0, 0 };
+		for(i = 0; i < n; i++){
+			float f = (float)i/n;
+			CParticle::AddParticle(PARTICLE_HELI_DUST,
+				point1 + f*(point2 - point1),
+				CVector(0.0f, 0.0f, 0.0f),
+				nil, 0.1f, black);
+		}
+
+		// More particles
+		CVector shotDir = point2 - point1;
+		shotDir.Normalise();
+		for(i = 0; i < 15; i++){
+			float f = i/15.0f;
+			CParticle::AddParticle(PARTICLE_GUNSMOKE2, point1,
+				shotDir*CGeneral::GetRandomNumberInRange(0.3f, 1.0f)*f,
+				nil, CGeneral::GetRandomNumberInRange(0.5f, 1.0f)*f, black);
+		}
+
+		// And some gun flashes near the gun
+		CVector flashPos = point1;
+		CVector nullDir(0.0f, 0.0f, 0.0f);
+		int lifeSpan = 250;
+		if(m_vecMoveSpeed.Magnitude() > 0.08f){
+			lifeSpan = 125;
+			flashPos.x += 0.5f*m_vecMoveSpeed.x;
+			flashPos.y += 0.5f*m_vecMoveSpeed.y;
+		}
+		CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.4f, black, 0, 0, 0, lifeSpan);
+		flashPos += 0.3f*shotDir;
+		CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.2f, black, 0, 0, 0, lifeSpan);
+		flashPos += 0.1f*shotDir;
+		CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.15f, black, 0, 0, 0, lifeSpan);
+	}
+
+	// Actually update turret node
+	if(m_aCarNodes[CAR_WINDSCREEN]){
+		CMatrix mat;
+		CVector pos;
+
+		mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN]));
+		pos = mat.GetPosition();
+		mat.SetRotateZ(m_fCarGunLR);
+		mat.Translate(pos);
+		mat.UpdateRW();
+	}
 }
 
 WRAPPER void
@@ -2313,9 +2415,9 @@ CAutomobile::BlowUpCar(CEntity *culprit)
 	gFireManager.StartFire(this, culprit, 0.8f, 1);	// TODO
 	CDarkel::RegisterCarBlownUpByPlayer(this);
 	if(GetModelIndex() == MI_RCBANDIT)
-		CExplosion::AddExplosion(this, culprit, EXPLOSION_4, GetPosition(), 0);	// TODO
+		CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR_QUICK, GetPosition(), 0);
 	else
-		CExplosion::AddExplosion(this, culprit, EXPLOSION_3, GetPosition(), 0);	// TODO
+		CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0);
 }
 
 bool
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp
index 0fc89637..056c584a 100644
--- a/src/weapons/Weapon.cpp
+++ b/src/weapons/Weapon.cpp
@@ -8,6 +8,7 @@ WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); }
 WRAPPER void CWeapon::FireFromCar(CAutomobile *car, bool left) { EAXJMP(0x55C940); }
 WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); }
 WRAPPER void CWeapon::Update(int32 audioEntity) { EAXJMP(0x563A10); }
+WRAPPER void CWeapon::DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end) { EAXJMP(0x563200); }
 
 void
 CWeapon::Initialise(eWeaponType type, int ammo)
diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h
index 71fe1f45..71c1f344 100644
--- a/src/weapons/Weapon.h
+++ b/src/weapons/Weapon.h
@@ -70,5 +70,7 @@ public:
 	void AddGunshell(CEntity*, CVector const&, CVector2D const&, float);
 	bool IsTypeMelee(void);
 	bool IsType2Handed(void);
+
+	static void DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end);
 };
 static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error");