From 5e77e9d0ea10e783985be42cf67f29cd2f3876df Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Sun, 27 Oct 2019 12:51:09 +0300
Subject: [PATCH 1/9] script 600-699

---
 src/control/Garages.cpp     |   9 +
 src/control/Garages.h       |   4 +
 src/control/Script.cpp      | 362 +++++++++++++++++++++++++++++++++++-
 src/control/Script.h        |   5 +-
 src/core/config.h           |   2 +-
 src/vehicles/Automobile.cpp |   4 +-
 src/vehicles/Automobile.h   |   4 +-
 7 files changed, 383 insertions(+), 7 deletions(-)

diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index b7a1fa8b..d8e8df9f 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -78,6 +78,15 @@ WRAPPER void CGarages::PlayerArrestedOrDied() { EAXJMP(0x427F60); }
 WRAPPER int16 CGarages::AddOne(float, float, float, float, float, float, uint8, uint32) { EAXJMP(0x421FA0); }
 WRAPPER void CGarages::SetTargetCarForMissonGarage(int16, CVehicle*) { EAXJMP(0x426BD0); }
 WRAPPER bool CGarages::HasCarBeenDroppedOffYet(int16) { EAXJMP(0x426C20); }
+WRAPPER void CGarages::DeActivateGarage(int16) { EAXJMP(0x426C40); }
+WRAPPER void CGarages::ActivateGarage(int16) { EAXJMP(0x426C60); }
+
+int32 CGarages::QueryCarsCollected(int16 garage)
+{
+	return 0;
+}
+
+WRAPPER bool CGarages::HasThisCarBeenCollected(int16 garage, uint8 id) { EAXJMP(0x426D50); }
 
 #if 0
 WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); }
diff --git a/src/control/Garages.h b/src/control/Garages.h
index af592716..7960e619 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -35,4 +35,8 @@ public:
 	static int16 AddOne(float, float, float, float, float, float, uint8, uint32);
 	static void SetTargetCarForMissonGarage(int16, CVehicle*);
 	static bool HasCarBeenDroppedOffYet(int16);
+	static void ActivateGarage(int16);
+	static void DeActivateGarage(int16);
+	static int32 QueryCarsCollected(int16);
+	static bool HasThisCarBeenCollected(int16, uint8);
 };
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 6d805510..b9c8bada 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -28,6 +28,7 @@
 #include "Messages.h"
 #include "ModelIndices.h"
 #include "Pad.h"
+#include "ParticleObject.h"
 #include "PedRoutes.h"
 #include "Phones.h"
 #include "Pickups.h"
@@ -5141,6 +5142,364 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
 }
 #endif
 
+#if 0
+WRAPPER int8 CRunningScript::ProcessCommandsFrom600To699(int32 command) { EAXJMP(0x444B20); }
+#else
+int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
+{
+	switch (command){
+	/* Collective commands are not implemented until LCS.
+	case COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT:
+	case COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE:
+	case COMMAND_SET_COLL_OBJ_GUARD_SPOT:
+	case COMMAND_SET_COLL_OBJ_GUARD_AREA:
+	case COMMAND_SET_COLL_OBJ_WAIT_IN_CAR:
+	case COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT:
+	case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT:
+	case COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS:
+	case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS:
+	case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:
+	case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:
+	case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS:
+	case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS:
+	case COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT:
+	case COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT:
+	case COMMAND_SET_COLL_OBJ_LEAVE_CAR:
+	case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER:
+	case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER:
+	case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR:
+	case COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:
+	case COMMAND_SET_COLL_OBJ_DESTROY_OBJECT:
+	case COMMAND_SET_COLL_OBJ_DESTROY_CAR:
+	case COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT:
+	case COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR:
+	case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
+	case COMMAND_SET_COLL_OBJ_GUARD_ATTACK:
+	case COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE:
+	case COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT:
+	case COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR:
+	case COMMAND_SET_COLL_OBJ_RUN_TO_AREA:
+	case COMMAND_SET_COLL_OBJ_RUN_TO_COORD:
+	case COMMAND_ADD_PEDS_IN_AREA_TO_COLL:
+	case COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL:
+	case COMMAND_CLEAR_COLL:
+	case COMMAND_IS_COLL_IN_CARS:
+	case COMMAND_LOCATE_COLL_ANY_MEANS_2D:
+	case COMMAND_LOCATE_COLL_ON_FOOT_2D:
+	case COMMAND_LOCATE_COLL_IN_CAR_2D:
+	case COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D:
+	case COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D:
+	case COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D:
+	case COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D:
+	case COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D:
+	case COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D:
+	case COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D:
+	case COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D:
+	case COMMAND_LOCATE_COLL_IN_CAR_CAR_2D:
+	case COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D:
+	case COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D:
+	case COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D:
+	case COMMAND_IS_COLL_IN_AREA_2D:
+	case COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D:
+	case COMMAND_IS_COLL_IN_AREA_IN_CAR_2D:
+	case COMMAND_IS_COLL_STOPPED_IN_AREA_2D:
+	case COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D:
+	case COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D:
+	case COMMAND_GET_NUMBER_OF_PEDS_IN_COLL:
+	*/
+	case COMMAND_SET_CHAR_HEED_THREATS:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bRespondsToThreats = (ScriptParams[1] != 0);
+		return 0;
+	}
+	case COMMAND_SET_PLAYER_HEED_THREATS:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		pPed->bRespondsToThreats = (ScriptParams[1] != 0);
+		return 0;
+	}
+	case COMMAND_GET_CONTROLLER_MODE:
+		ScriptParams[0] = 0;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	case COMMAND_SET_CAN_RESPRAY_CAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+		((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0);
+		return 0;
+	}
+	case COMMAND_IS_TAXI:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		int mi = pVehicle->GetModelIndex();
+		UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE);
+		return 0;
+	}
+	case COMMAND_UNLOAD_SPECIAL_CHARACTER:
+		CollectParameters(&m_nIp, 1);
+		CStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1);
+		return 0;
+	case COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER:
+		CDarkel::ResetModelsKilledByPlayer();
+		return 0;
+	case COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER:
+		CollectParameters(&m_nIp, 1);
+		ScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	case COMMAND_ACTIVATE_GARAGE:
+		CollectParameters(&m_nIp, 1);
+		CGarages::ActivateGarage(ScriptParams[0]);
+		return 0;
+	case COMMAND_SWITCH_TAXI_TIMER:
+	{
+		CollectParameters(&m_nIp, 1);
+		if (ScriptParams[0] != 0){
+			CWorld::Players[CWorld::PlayerInFocus].m_nSwitchTaxiTime = CTimer::GetTimeInMilliseconds();
+			CWorld::Players[CWorld::PlayerInFocus].m_bSwitchTaxi = true;
+		}else{
+			CWorld::Players[CWorld::PlayerInFocus].m_bSwitchTaxi = false;
+		}
+		return 0;
+	}
+	case COMMAND_CREATE_OBJECT_NO_OFFSET:
+	{
+		CollectParameters(&m_nIp, 4);
+		int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;
+		CObject* pObj = new CObject(mi, 0);
+		pObj->ObjectCreatedBy = MISSION_OBJECT;
+		CVector pos = *(CVector*)&ScriptParams[1];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		pObj->GetPosition() = pos;
+		pObj->SetOrientation(0.0f, 0.0f, 0.0f);
+		pObj->GetMatrix().UpdateRW();
+		pObj->UpdateRwFrame();
+		CTheScripts::ClearSpaceForMissionEntity(pos, pObj);
+		CWorld::Add(pObj);
+		ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
+		StoreParameters(&m_nIp, 1);
+		if (m_bIsMissionScript)
+			CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
+		return 0;
+	}
+	case COMMAND_IS_BOAT:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		UpdateCompareFlag(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+		return 0;
+	}
+	case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS:
+	{
+		CollectParameters(&m_nIp, 5);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		float infX = *(float*)&ScriptParams[1];
+		float infY = *(float*)&ScriptParams[2];
+		float supX = *(float*)&ScriptParams[3];
+		float supY = *(float*)&ScriptParams[4];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[3];
+			supX = *(float*)&ScriptParams[1];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[4];
+			supY = *(float*)&ScriptParams[2];
+		}
+		CVector pos;
+		pos.x = (infX + supX) / 2;
+		pos.y = (infY + supY) / 2;
+		pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		float radius = max(pos.x - infX, pos.y - infY);
+		pPed->bScriptObjectiveCompleted = false;
+		pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius);
+		return 0;
+	}
+	//case COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS:
+	case COMMAND_IS_PLAYER_STOPPED:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
+		UpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer));
+		return 0;
+	}
+	case COMMAND_IS_CHAR_STOPPED:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		UpdateCompareFlag(CTheScripts::IsPedStopped(pPed));
+		return 0;
+	}
+	case COMMAND_MESSAGE_WAIT:
+		CollectParameters(&m_nIp, 2);
+		m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0];
+		if (ScriptParams[1] != 0)
+			m_bSkipWakeTime = true;
+		return 1;
+	case COMMAND_ADD_PARTICLE_EFFECT:
+	{
+		CollectParameters(&m_nIp, 5);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= 100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0);
+		return 0;
+	}
+	case COMMAND_SWITCH_WIDESCREEN:
+		CollectParameters(&m_nIp, 1);
+		if (ScriptParams[0] != 0)
+			TheCamera.SetWideScreenOn();
+		else
+			TheCamera.SetWideScreenOff();
+		return 0;
+	case COMMAND_ADD_SPRITE_BLIP_FOR_CAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+		int id = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);
+		CRadar::SetBlipSprite(id, ScriptParams[1]);
+		ScriptParams[0] = id;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
+	case COMMAND_ADD_SPRITE_BLIP_FOR_CHAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+		int id = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);
+		CRadar::SetBlipSprite(id, ScriptParams[1]);
+		ScriptParams[0] = id;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
+	case COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT:
+	{
+		CollectParameters(&m_nIp, 2);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+		int id = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);
+		CRadar::SetBlipSprite(id, ScriptParams[1]);
+		ScriptParams[0] = id;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
+	case COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT:
+	{
+		CollectParameters(&m_nIp, 4);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+		int id = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);
+		CRadar::SetBlipSprite(id, ScriptParams[3]);
+		ScriptParams[0] = id;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
+	case COMMAND_ADD_SPRITE_BLIP_FOR_COORD:
+	{
+		CollectParameters(&m_nIp, 4);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+		int id = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
+		CRadar::SetBlipSprite(id, ScriptParams[3]);
+		ScriptParams[0] = id;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
+	case COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);
+		return 0;
+	}
+	case COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		pVehicle->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);
+		return 0;
+	}
+	case COMMAND_SET_CHAR_PROOFS:
+	{
+		CollectParameters(&m_nIp, 6);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bBulletProof = (ScriptParams[1] != 0);
+		pPed->bFireProof = (ScriptParams[2] != 0);
+		pPed->bExplosionProof = (ScriptParams[3] != 0);
+		pPed->bCollisionProof = (ScriptParams[4] != 0);
+		pPed->bMeleeProof = (ScriptParams[5] != 0);
+		return 0;
+	}
+	case COMMAND_SET_CAR_PROOFS:
+	{
+		CollectParameters(&m_nIp, 6);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		pVehicle->bBulletProof = (ScriptParams[1] != 0);
+		pVehicle->bFireProof = (ScriptParams[2] != 0);
+		pVehicle->bExplosionProof = (ScriptParams[3] != 0);
+		pVehicle->bCollisionProof = (ScriptParams[4] != 0);
+		pVehicle->bMeleeProof = (ScriptParams[5] != 0);
+		return 0;
+	}
+	case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D:
+	case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D:
+	case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D:
+	case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:
+	case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:
+	case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:
+	case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:
+	case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:
+	case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:
+	case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:
+	case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:
+	case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
+		PlayerInAngledAreaCheckCommand(command, &m_nIp);
+		return 0;
+	case COMMAND_DEACTIVATE_GARAGE:
+		CollectParameters(&m_nIp, 1);
+		CGarages::DeActivateGarage(ScriptParams[0]);
+		return 0;
+	case COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE:
+		CollectParameters(&m_nIp, 1);
+		ScriptParams[0] = CGarages::QueryCarsCollected(ScriptParams[0]);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	case COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE:
+		CollectParameters(&m_nIp, 2);
+		UpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1));
+		return 0;
+	default:
+		assert(0);
+	}
+	return -1;
+}
+#endif
+
 int16 CRunningScript::GetPadState(uint16 pad, uint16 button)
 {
 	CPad* pPad = CPad::GetPad(pad);
@@ -5175,7 +5534,6 @@ bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)
 	return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled;
 }
 
-WRAPPER int8 CRunningScript::ProcessCommandsFrom600To699(int32 command) { EAXJMP(0x444B20); }
 WRAPPER int8 CRunningScript::ProcessCommandsFrom700To799(int32 command) { EAXJMP(0x4458A0); }
 WRAPPER int8 CRunningScript::ProcessCommandsFrom800To899(int32 command) { EAXJMP(0x448240); }
 WRAPPER int8 CRunningScript::ProcessCommandsFrom900To999(int32 command) { EAXJMP(0x44CB80); }
@@ -5209,6 +5567,8 @@ WRAPPER void CTheScripts::CleanUpThisObject(CObject*) { EAXJMP(0x454910); }
 WRAPPER void CTheScripts::ReadObjectNamesFromScript() { EAXJMP(0x454960); }
 WRAPPER void CTheScripts::UpdateObjectIndices() { EAXJMP(0x454AD0); }
 WRAPPER void CTheScripts::ReadMultiScriptFileOffsetsFromScript() { EAXJMP(0x454BC0); }
+WRAPPER bool CTheScripts::IsPedStopped(CPed*) { EAXJMP(0x454670); }
+WRAPPER bool CTheScripts::IsPlayerStopped(CPlayerInfo*) { EAXJMP(0x4546C0); }
 
 STARTPATCHES
 InjectHook(0x437AE0, &CMissionCleanup::Init, PATCH_JUMP);
diff --git a/src/control/Script.h b/src/control/Script.h
index 2c4ec2c0..751ad9d5 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -8,6 +8,7 @@ class CBuilding;
 class CVehicle;
 class CPed;
 class CObject;
+class CPlayerInfo;
 
 struct CScriptRectangle 
 {
@@ -339,6 +340,9 @@ public:
 	static void Process();
 	static CRunningScript* StartTestScript();
 	static bool IsPlayerOnAMission();
+	static bool IsPedStopped(CPed*);
+	static bool IsPlayerStopped(CPlayerInfo*);
+	static bool IsVehicleStopped(CVehicle*);
 
 	static void ReadObjectNamesFromScript();
 	static void UpdateObjectIndices();
@@ -348,7 +352,6 @@ public:
 	static void HighlightImportantArea(uint32, float, float, float, float, float);
 	static void DrawDebugSquare(float, float, float, float);
 	static void DrawDebugCube(float, float, float, float, float, float);
-	static bool IsVehicleStopped(CVehicle*);
 
 	static int32 Read4BytesFromScript(uint32* pIp){
 		int32 retval = 0;
diff --git a/src/core/config.h b/src/core/config.h
index 12cb7be8..ae9e2ea4 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -162,6 +162,6 @@ enum Config {
 
 // Peds
 #define ANIMATE_PED_COL_MODEL
-#define VC_PED_PORTS
+//#define VC_PED_PORTS
 #define NEW_WALK_AROUND_ALGORITHM
 #define CANCELLABLE_CAR_ENTER
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 12c9c940..d3257f91 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -61,8 +61,8 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
 	m_fFireBlowUpTimer = 0.0f;
 	field_4E0 = 0;
 	bTaxiLight = m_sAllTaxiLights;
-	m_auto_flagA20 = false;
-	m_auto_flagA40 = false;
+	bFixedColour = false;
+	bBigWheels = false;
 	bWaterTight = false;
 
 	SetModelIndex(id);
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index 534f28a4..561ab566 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -87,8 +87,8 @@ public:
 	uint8 m_bombType : 3;
 	uint8 bTaxiLight : 1;
 	uint8 bHadDriver : 1;		// for bombs
-	uint8 m_auto_flagA20 : 1;
-	uint8 m_auto_flagA40 : 1;
+	uint8 bFixedColour : 1;
+	uint8 bBigWheels : 1;
 	uint8 bWaterTight : 1;	// no damage for non-player peds
 	uint8 bNotDamagedUpsideDown : 1;
 	uint8 bMoreResistantToDamage : 1;

From cc9a49d061bc1231c32a6794322c9a07fd27973c Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Sat, 9 Nov 2019 16:44:17 +0300
Subject: [PATCH 2/9] script stubs

---
 src/control/Script.cpp | 525 ++++++++++++++++++++++++++++++++++++++++-
 src/core/config.h      |   2 +-
 2 files changed, 520 insertions(+), 7 deletions(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index b9c8bada..ccb551dd 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -5500,6 +5500,525 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 }
 #endif
 
+#if 1
+WRAPPER int8 CRunningScript::ProcessCommandsFrom700To799(int32 command) { EAXJMP(0x4458A0); }
+#else
+int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
+{
+	switch (command){
+	case COMMAND_SET_SWAT_REQUIRED:
+	case COMMAND_SET_FBI_REQUIRED:
+	case COMMAND_SET_ARMY_REQUIRED:
+	case COMMAND_IS_CAR_IN_WATER:
+	case COMMAND_GET_CLOSEST_CHAR_NODE:
+	case COMMAND_GET_CLOSEST_CAR_NODE:
+	case COMMAND_CAR_GOTO_COORDINATES_ACCURATE:
+	case COMMAND_START_PACMAN_RACE:
+	case COMMAND_START_PACMAN_RECORD:
+	case COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN:
+	case COMMAND_CLEAR_PACMAN:
+	case COMMAND_START_PACMAN_SCRAMBLE:
+	case COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED:
+	case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED:
+	case COMMAND_IS_CAR_ON_SCREEN:
+	case COMMAND_IS_CHAR_ON_SCREEN:
+	case COMMAND_IS_OBJECT_ON_SCREEN:
+	case COMMAND_GOSUB_FILE:
+	case COMMAND_GET_GROUND_Z_FOR_3D_COORD:
+	case COMMAND_START_SCRIPT_FIRE:
+	case COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED:
+	case COMMAND_REMOVE_SCRIPT_FIRE:
+	case COMMAND_SET_COMEDY_CONTROLS:
+	case COMMAND_BOAT_GOTO_COORDS:
+	case COMMAND_BOAT_STOP:
+	case COMMAND_IS_PLAYER_SHOOTING_IN_AREA:
+	case COMMAND_IS_CHAR_SHOOTING_IN_AREA:
+	case COMMAND_IS_CURRENT_PLAYER_WEAPON:
+	case COMMAND_IS_CURRENT_CHAR_WEAPON:
+	case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN:
+	case COMMAND_ADD_POWER_PILL:
+	case COMMAND_SET_BOAT_CRUISE_SPEED:
+	case COMMAND_GET_RANDOM_CHAR_IN_AREA:
+	case COMMAND_GET_RANDOM_CHAR_IN_ZONE:
+	case COMMAND_IS_PLAYER_IN_TAXI:
+	case COMMAND_IS_PLAYER_SHOOTING:
+	case COMMAND_IS_CHAR_SHOOTING:
+	case COMMAND_CREATE_MONEY_PICKUP:
+	case COMMAND_SET_CHAR_ACCURACY:
+	case COMMAND_GET_CAR_SPEED:
+	case COMMAND_LOAD_CUTSCENE:
+	case COMMAND_CREATE_CUTSCENE_OBJECT:
+	case COMMAND_SET_CUTSCENE_ANIM:
+	case COMMAND_START_CUTSCENE:
+	case COMMAND_GET_CUTSCENE_TIME:
+	case COMMAND_HAS_CUTSCENE_FINISHED:
+	case COMMAND_CLEAR_CUTSCENE:
+	case COMMAND_RESTORE_CAMERA_JUMPCUT:
+	case COMMAND_CREATE_COLLECTABLE1:
+	case COMMAND_SET_COLLECTABLE1_TOTAL:
+	case COMMAND_IS_PROJECTILE_IN_AREA:
+	case COMMAND_DESTROY_PROJECTILES_IN_AREA:
+	case COMMAND_DROP_MINE:
+	case COMMAND_DROP_NAUTICAL_MINE:
+	case COMMAND_IS_CHAR_MODEL:
+	case COMMAND_LOAD_SPECIAL_MODEL:
+	case COMMAND_CREATE_CUTSCENE_HEAD:
+	case COMMAND_SET_CUTSCENE_HEAD_ANIM:
+	case COMMAND_SIN:
+	case COMMAND_COS:
+	case COMMAND_GET_CAR_FORWARD_X:
+	case COMMAND_GET_CAR_FORWARD_Y:
+	case COMMAND_CHANGE_GARAGE_TYPE:
+	case COMMAND_ACTIVATE_CRUSHER_CRANE:
+	case COMMAND_PRINT_WITH_2_NUMBERS:
+	case COMMAND_PRINT_WITH_2_NUMBERS_NOW:
+	case COMMAND_PRINT_WITH_2_NUMBERS_SOON:
+	case COMMAND_PRINT_WITH_3_NUMBERS:
+	case COMMAND_PRINT_WITH_3_NUMBERS_NOW:
+	case COMMAND_PRINT_WITH_3_NUMBERS_SOON:
+	case COMMAND_PRINT_WITH_4_NUMBERS:
+	case COMMAND_PRINT_WITH_4_NUMBERS_NOW:
+	case COMMAND_PRINT_WITH_4_NUMBERS_SOON:
+	case COMMAND_PRINT_WITH_5_NUMBERS:
+	case COMMAND_PRINT_WITH_5_NUMBERS_NOW:
+	case COMMAND_PRINT_WITH_5_NUMBERS_SOON:
+	case COMMAND_PRINT_WITH_6_NUMBERS:
+	case COMMAND_PRINT_WITH_6_NUMBERS_NOW:
+	case COMMAND_PRINT_WITH_6_NUMBERS_SOON:
+	case COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION:
+	case COMMAND_PLAYER_MADE_PROGRESS:
+	case COMMAND_SET_PROGRESS_TOTAL:
+	case COMMAND_REGISTER_JUMP_DISTANCE:
+	case COMMAND_REGISTER_JUMP_HEIGHT:
+	case COMMAND_REGISTER_JUMP_FLIPS:
+	case COMMAND_REGISTER_JUMP_SPINS:
+	case COMMAND_REGISTER_JUMP_STUNT:
+	case COMMAND_REGISTER_UNIQUE_JUMP_FOUND:
+	case COMMAND_SET_UNIQUE_JUMPS_TOTAL:
+	case COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI:
+	case COMMAND_REGISTER_MONEY_MADE_TAXI:
+	case COMMAND_REGISTER_MISSION_GIVEN:
+	case COMMAND_REGISTER_MISSION_PASSED:
+	case COMMAND_SET_CHAR_RUNNING:
+	case COMMAND_REMOVE_ALL_SCRIPT_FIRES:
+	case COMMAND_IS_FIRST_CAR_COLOUR:
+	case COMMAND_IS_SECOND_CAR_COLOUR:
+	case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON:
+	case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON:
+	case COMMAND_IS_CHAR_IN_CHARS_GROUP:
+	default:
+		assert(0);
+	}
+	return -1;
+}
+#endif
+
+#if 1
+WRAPPER int8 CRunningScript::ProcessCommandsFrom800To899(int32 command) { EAXJMP(0x448240); }
+#else
+int8 CRunningScript::ProcessCommandsFrom800To899(int32 command)
+{
+	switch (command) {
+	case COMMAND_IS_CHAR_IN_PLAYERS_GROUP:
+	case COMMAND_EXPLODE_CHAR_HEAD:
+	case COMMAND_EXPLODE_PLAYER_HEAD:
+	case COMMAND_ANCHOR_BOAT:
+	case COMMAND_SET_ZONE_GROUP:
+	case COMMAND_START_CAR_FIRE:
+	case COMMAND_START_CHAR_FIRE:
+	case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA:
+	case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE:
+	case COMMAND_HAS_RESPRAY_HAPPENED:
+	case COMMAND_SET_CAMERA_ZOOM:
+	case COMMAND_CREATE_PICKUP_WITH_AMMO:
+	case COMMAND_SET_CAR_RAM_CAR:
+	case COMMAND_SET_CAR_BLOCK_CAR:
+	case COMMAND_SET_CHAR_OBJ_CATCH_TRAIN:
+	case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
+	case COMMAND_SET_PLAYER_NEVER_GETS_TIRED:
+	case COMMAND_SET_PLAYER_FAST_RELOAD:
+	case COMMAND_SET_CHAR_BLEEDING:
+	case COMMAND_SET_CAR_FUNNY_SUSPENSION:
+	case COMMAND_SET_CAR_BIG_WHEELS:
+	case COMMAND_SET_FREE_RESPRAYS:
+	case COMMAND_SET_PLAYER_VISIBLE:
+	case COMMAND_SET_CHAR_VISIBLE:
+	case COMMAND_SET_CAR_VISIBLE:
+	case COMMAND_IS_AREA_OCCUPIED:
+	case COMMAND_START_DRUG_RUN:
+	case COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED:
+	case COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN:
+	case COMMAND_SAVE_PLAYER_FROM_FIRES:
+	case COMMAND_DISPLAY_TEXT:
+	case COMMAND_SET_TEXT_SCALE:
+	case COMMAND_SET_TEXT_COLOUR:
+	case COMMAND_SET_TEXT_JUSTIFY:
+	case COMMAND_SET_TEXT_CENTRE:
+	case COMMAND_SET_TEXT_WRAPX:
+	case COMMAND_SET_TEXT_CENTRE_SIZE:
+	case COMMAND_SET_TEXT_BACKGROUND:
+	case COMMAND_SET_TEXT_BACKGROUND_COLOUR:
+	case COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT:
+	case COMMAND_SET_TEXT_PROPORTIONAL:
+	case COMMAND_SET_TEXT_FONT:
+	case COMMAND_INDUSTRIAL_PASSED:
+	case COMMAND_COMMERCIAL_PASSED:
+	case COMMAND_SUBURBAN_PASSED:
+	case COMMAND_ROTATE_OBJECT:
+	case COMMAND_SLIDE_OBJECT:
+	case COMMAND_REMOVE_CHAR_ELEGANTLY:
+	case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE:
+	case COMMAND_IS_NASTY_GAME:
+	case COMMAND_UNDRESS_CHAR:
+	case COMMAND_DRESS_CHAR:
+	case COMMAND_START_CHASE_SCENE:
+	case COMMAND_STOP_CHASE_SCENE:
+	case COMMAND_IS_EXPLOSION_IN_AREA:
+	case COMMAND_IS_EXPLOSION_IN_ZONE:
+	case COMMAND_START_DRUG_DROP_OFF:
+	case COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN:
+	case COMMAND_FIND_DROP_OFF_PLANE_COORDINATES:
+	case COMMAND_CREATE_FLOATING_PACKAGE:
+	case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR:
+	case COMMAND_MAKE_OBJECT_TARGETTABLE:
+	case COMMAND_ADD_ARMOUR_TO_PLAYER:
+	case COMMAND_ADD_ARMOUR_TO_CHAR:
+	case COMMAND_OPEN_GARAGE:
+	case COMMAND_CLOSE_GARAGE:
+	case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:
+	case COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE:
+	case COMMAND_HAS_CHAR_SPOTTED_CHAR:
+	case COMMAND_SET_CHAR_OBJ_HAIL_TAXI:
+	case COMMAND_HAS_OBJECT_BEEN_DAMAGED:
+	case COMMAND_START_KILL_FRENZY_HEADSHOT:
+	case COMMAND_ACTIVATE_MILITARY_CRANE:
+	case COMMAND_WARP_PLAYER_INTO_CAR:
+	case COMMAND_WARP_CHAR_INTO_CAR:
+	case COMMAND_SWITCH_CAR_RADIO:
+	case COMMAND_SET_AUDIO_STREAM:
+	case COMMAND_PRINT_WITH_2_NUMBERS_BIG:
+	case COMMAND_PRINT_WITH_3_NUMBERS_BIG:
+	case COMMAND_PRINT_WITH_4_NUMBERS_BIG:
+	case COMMAND_PRINT_WITH_5_NUMBERS_BIG:
+	case COMMAND_PRINT_WITH_6_NUMBERS_BIG:
+	case COMMAND_SET_CHAR_WAIT_STATE:
+	case COMMAND_SET_CAMERA_BEHIND_PLAYER:
+	case COMMAND_SET_MOTION_BLUR:
+	case COMMAND_PRINT_STRING_IN_STRING:
+	case COMMAND_CREATE_RANDOM_CHAR:
+	case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR:
+	case COMMAND_SET_2_REPEATED_PHONE_MESSAGES:
+	case COMMAND_SET_2_PHONE_MESSAGES:
+	case COMMAND_SET_3_REPEATED_PHONE_MESSAGES:
+	case COMMAND_SET_3_PHONE_MESSAGES:
+	case COMMAND_SET_4_REPEATED_PHONE_MESSAGES:
+	case COMMAND_SET_4_PHONE_MESSAGES:
+	case COMMAND_IS_SNIPER_BULLET_IN_AREA:
+	case COMMAND_GIVE_PLAYER_DETONATOR:
+	case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR:
+	case COMMAND_SET_OBJECT_VELOCITY:
+	case COMMAND_SET_OBJECT_COLLISION:
+	case COMMAND_IS_ICECREAM_JINGLE_ON:
+	default:
+		assert(0);
+	}
+	return -1;
+}
+#endif
+
+#if 1
+WRAPPER int8 CRunningScript::ProcessCommandsFrom900To999(int32 command) { EAXJMP(0x44CB80); }
+#else
+int8 CRunningScript::ProcessCommandsFrom900To999(int32 command)
+{
+	switch (command){
+	case COMMAND_PRINT_STRING_IN_STRING_NOW:
+	case COMMAND_PRINT_STRING_IN_STRING_SOON:
+	case COMMAND_SET_5_REPEATED_PHONE_MESSAGES:
+	case COMMAND_SET_5_PHONE_MESSAGES:
+	case COMMAND_SET_6_REPEATED_PHONE_MESSAGES:
+	case COMMAND_SET_6_PHONE_MESSAGES:
+	case COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY:
+	case COMMAND_LOAD_ALL_MODELS_NOW:
+	case COMMAND_ADD_TO_OBJECT_VELOCITY:
+	case COMMAND_DRAW_SPRITE:
+	case COMMAND_DRAW_RECT:
+	case COMMAND_LOAD_SPRITE:
+	case COMMAND_LOAD_TEXTURE_DICTIONARY:
+	case COMMAND_REMOVE_TEXTURE_DICTIONARY:
+	case COMMAND_SET_OBJECT_DYNAMIC:
+	case COMMAND_SET_CHAR_ANIM_SPEED:
+	case COMMAND_PLAY_MISSION_PASSED_TUNE:
+	case COMMAND_CLEAR_AREA:
+	case COMMAND_FREEZE_ONSCREEN_TIMER:
+	case COMMAND_SWITCH_CAR_SIREN:
+	case COMMAND_SWITCH_PED_ROADS_ON_ANGLED:
+	case COMMAND_SWITCH_PED_ROADS_OFF_ANGLED:
+	case COMMAND_SWITCH_ROADS_ON_ANGLED:
+	case COMMAND_SWITCH_ROADS_OFF_ANGLED:
+	case COMMAND_SET_CAR_WATERTIGHT:
+	case COMMAND_ADD_MOVING_PARTICLE_EFFECT:
+	case COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT:
+	case COMMAND_TURN_CAR_TO_FACE_COORD:
+	case COMMAND_IS_CRANE_LIFTING_CAR:
+	case COMMAND_DRAW_SPHERE:
+	case COMMAND_SET_CAR_STATUS:
+	case COMMAND_IS_CHAR_MALE:
+	case COMMAND_SCRIPT_NAME:
+	case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL:
+	case COMMAND_FIND_DRUG_PLANE_COORDINATES:
+	case COMMAND_SAVE_INT_TO_DEBUG_FILE:
+	case COMMAND_SAVE_FLOAT_TO_DEBUG_FILE:
+	case COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE:
+	case COMMAND_POLICE_RADIO_MESSAGE:
+	case COMMAND_SET_CAR_STRONG:
+	case COMMAND_REMOVE_ROUTE:
+	case COMMAND_SWITCH_RUBBISH:
+	case COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA:
+	case COMMAND_SWITCH_STREAMING:
+	case COMMAND_IS_GARAGE_OPEN:
+	case COMMAND_IS_GARAGE_CLOSED:
+	case COMMAND_START_CATALINA_HELI:
+	case COMMAND_CATALINA_HELI_TAKE_OFF:
+	case COMMAND_REMOVE_CATALINA_HELI:
+	case COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN:
+	case COMMAND_SWAP_NEAREST_BUILDING_MODEL:
+	case COMMAND_SWITCH_WORLD_PROCESSING:
+	case COMMAND_REMOVE_ALL_PLAYER_WEAPONS:
+	case COMMAND_GRAB_CATALINA_HELI:
+	case COMMAND_CLEAR_AREA_OF_CARS:
+	case COMMAND_SET_ROTATING_GARAGE_DOOR:
+	case COMMAND_ADD_SPHERE:
+	case COMMAND_REMOVE_SPHERE:
+	case COMMAND_CATALINA_HELI_FLY_AWAY:
+	case COMMAND_SET_EVERYONE_IGNORE_PLAYER:
+	case COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE:
+	case COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE:
+	case COMMAND_IS_PHONE_DISPLAYING_MESSAGE:
+	case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING:
+	case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING:
+	case COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK:
+	case COMMAND_IS_COLLISION_IN_MEMORY:
+	case COMMAND_SET_WANTED_MULTIPLIER:
+	case COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER:
+	case COMMAND_IS_CAR_VISIBLY_DAMAGED:
+	case COMMAND_DOES_OBJECT_EXIST:
+	case COMMAND_LOAD_SCENE:
+	case COMMAND_ADD_STUCK_CAR_CHECK:
+	case COMMAND_REMOVE_STUCK_CAR_CHECK:
+	case COMMAND_IS_CAR_STUCK:
+	case COMMAND_LOAD_MISSION_AUDIO:
+	case COMMAND_HAS_MISSION_AUDIO_LOADED:
+	case COMMAND_PLAY_MISSION_AUDIO:
+	case COMMAND_HAS_MISSION_AUDIO_FINISHED:
+	case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING:
+	case COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED:
+	case COMMAND_CLEAR_THIS_PRINT:
+	case COMMAND_CLEAR_THIS_BIG_PRINT:
+	case COMMAND_SET_MISSION_AUDIO_POSITION:
+	case COMMAND_ACTIVATE_SAVE_MENU:
+	case COMMAND_HAS_SAVE_GAME_FINISHED:
+	case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE:
+	case COMMAND_ADD_BLIP_FOR_PICKUP_OLD:
+	case COMMAND_ADD_BLIP_FOR_PICKUP:
+	case COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP:
+	case COMMAND_SET_PED_DENSITY_MULTIPLIER:
+	case COMMAND_FORCE_RANDOM_PED_TYPE:
+	case COMMAND_SET_TEXT_DRAW_BEFORE_FADE:
+	case COMMAND_GET_COLLECTABLE1S_COLLECTED:
+	case COMMAND_REGISTER_EL_BURRO_TIME:
+	case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE:
+	case COMMAND_SET_TEXT_RIGHT_JUSTIFY:
+	case COMMAND_PRINT_HELP:
+	case COMMAND_CLEAR_HELP:
+	case COMMAND_FLASH_HUD_OBJECT:
+	default:
+		assert(0);
+	}
+	return -1;
+}
+#endif
+
+#if 1
+WRAPPER int8 CRunningScript::ProcessCommandsFrom1000To1099(int32 command) { EAXJMP(0x588490); }
+#else
+int8 CRunningScript::ProcessCommandsFrom1000To1099(int32 command)
+{
+	switch (command){
+	case COMMAND_FLASH_RADAR_BLIP:
+	case COMMAND_IS_CHAR_IN_CONTROL:
+	case COMMAND_SET_GENERATE_CARS_AROUND_CAMERA:
+	case COMMAND_CLEAR_SMALL_PRINTS:
+	case COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS:
+	case COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED:
+	case COMMAND_CAN_PLAYER_START_MISSION:
+	case COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE:
+	case COMMAND_USE_TEXT_COMMANDS:
+	case COMMAND_SET_THREAT_FOR_PED_TYPE:
+	case COMMAND_CLEAR_THREAT_FOR_PED_TYPE:
+	case COMMAND_GET_CAR_COLOURS:
+	case COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED:
+	case COMMAND_SET_CAR_CAN_BE_DAMAGED:
+	case COMMAND_MAKE_PLAYER_UNSAFE:
+	case COMMAND_LOAD_COLLISION:
+	case COMMAND_GET_BODY_CAST_HEALTH:
+	case COMMAND_SET_CHARS_CHATTING:
+	case COMMAND_MAKE_PLAYER_SAFE:
+	case COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL:
+	case COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL:
+	case COMMAND_REGISTER_4X4_ONE_TIME:
+	case COMMAND_REGISTER_4X4_TWO_TIME:
+	case COMMAND_REGISTER_4X4_THREE_TIME:
+	case COMMAND_REGISTER_4X4_MAYHEM_TIME:
+	case COMMAND_REGISTER_LIFE_SAVED:
+	case COMMAND_REGISTER_CRIMINAL_CAUGHT:
+	case COMMAND_REGISTER_AMBULANCE_LEVEL:
+	case COMMAND_REGISTER_FIRE_EXTINGUISHED:
+	case COMMAND_TURN_PHONE_ON:
+	case COMMAND_REGISTER_LONGEST_DODO_FLIGHT:
+	case COMMAND_REGISTER_DEFUSE_BOMB_TIME:
+	case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES:
+	case COMMAND_BLOW_UP_RC_BUGGY:
+	case COMMAND_REMOVE_CAR_FROM_CHASE:
+	case COMMAND_IS_FRENCH_GAME:
+	case COMMAND_IS_GERMAN_GAME:
+	case COMMAND_CLEAR_MISSION_AUDIO:
+	case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST:
+	case COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH:
+	case COMMAND_SET_GANG_PED_MODEL_PREFERENCE:
+	case COMMAND_SET_CHAR_USE_PEDNODE_SEEK:
+	case COMMAND_SWITCH_VEHICLE_WEAPONS:
+	case COMMAND_SET_GET_OUT_OF_JAIL_FREE:
+	case COMMAND_SET_FREE_HEALTH_CARE:
+	case COMMAND_IS_CAR_DOOR_CLOSED:
+	case COMMAND_LOAD_AND_LAUNCH_MISSION:
+	case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL:
+	case COMMAND_SET_OBJECT_DRAW_LAST:
+	case COMMAND_GET_AMMO_IN_PLAYER_WEAPON:
+	case COMMAND_GET_AMMO_IN_CHAR_WEAPON:
+	case COMMAND_REGISTER_KILL_FRENZY_PASSED:
+	case COMMAND_SET_CHAR_SAY:
+	case COMMAND_SET_NEAR_CLIP:
+	case COMMAND_SET_RADIO_CHANNEL:
+	case COMMAND_OVERRIDE_HOSPITAL_LEVEL:
+	case COMMAND_OVERRIDE_POLICE_STATION_LEVEL:
+	case COMMAND_FORCE_RAIN:
+	case COMMAND_DOES_GARAGE_CONTAIN_CAR:
+	case COMMAND_SET_CAR_TRACTION:
+	case COMMAND_ARE_MEASUREMENTS_IN_METRES:
+	case COMMAND_CONVERT_METRES_TO_FEET:
+	case COMMAND_MARK_ROADS_BETWEEN_LEVELS:
+	case COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS:
+	case COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS:
+	case COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS:
+	case COMMAND_IS_THREAT_FOR_PED_TYPE:
+	case COMMAND_CLEAR_AREA_OF_CHARS:
+	case COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS:
+	case COMMAND_CONVERT_METRES_TO_FEET_INT:
+	case COMMAND_REGISTER_FASTEST_TIME:
+	case COMMAND_REGISTER_HIGHEST_SCORE:
+	case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER:
+	case COMMAND_IS_CAR_PASSENGER_SEAT_FREE:
+	case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT:
+	case COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL:
+	case COMMAND_START_CREDITS:
+	case COMMAND_STOP_CREDITS:
+	case COMMAND_ARE_CREDITS_FINISHED:
+	case COMMAND_CREATE_SINGLE_PARTICLE:
+	case COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS:
+	case COMMAND_GET_CHASE_CAR:
+	case COMMAND_START_BOAT_FOAM_ANIMATION:
+	case COMMAND_UPDATE_BOAT_FOAM_ANIMATION:
+	case COMMAND_SET_MUSIC_DOES_FADE:
+	case COMMAND_SET_INTRO_IS_PLAYING:
+	case COMMAND_SET_PLAYER_HOOKER:
+	case COMMAND_PLAY_END_OF_GAME_TUNE:
+	case COMMAND_STOP_END_OF_GAME_TUNE:
+	case COMMAND_GET_CAR_MODEL:
+	case COMMAND_IS_PLAYER_SITTING_IN_CAR:
+	case COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR:
+	case COMMAND_SET_SCRIPT_FIRE_AUDIO:
+	case COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED:
+	case COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS:
+	case COMMAND_IS_PLAYER_LIFTING_A_PHONE:
+	case COMMAND_IS_CHAR_SITTING_IN_CAR:
+	case COMMAND_IS_CHAR_SITTING_IN_ANY_CAR:
+	case COMMAND_IS_PLAYER_ON_FOOT:
+	case COMMAND_IS_CHAR_ON_FOOT:
+	default:
+		assert(0);
+	}
+	return -1;
+}
+#endif
+
+#if 1
+WRAPPER int8 CRunningScript::ProcessCommandsFrom1100To1199(int32 command) { EAXJMP(0x589D00); }
+#else
+int8 CRunningScript::ProcessCommandsFrom1100To1199(int32 command)
+{
+	switch (command) {
+	case COMMAND_LOAD_COLLISION_WITH_SCREEN:
+	case COMMAND_LOAD_SPLASH_SCREEN:
+	case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS:
+	case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER:
+	case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER:
+	case COMMAND_LOAD_END_OF_GAME_TUNE:
+	case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA:
+	case COMMAND_SET_OBJECT_ROTATION:
+	case COMMAND_GET_DEBUG_CAMERA_COORDINATES:
+	case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR:
+	case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR:
+	case COMMAND_IS_PLAYER_TARGETTING_CHAR:
+	case COMMAND_IS_PLAYER_TARGETTING_OBJECT:
+	case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME:
+	case COMMAND_DISPLAY_TEXT_WITH_NUMBER:
+	case COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS:
+	case COMMAND_FAIL_CURRENT_MISSION:
+	case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE:
+	case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT:
+	case COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR:
+	case COMMAND_SET_INTERPOLATION_PARAMETERS:
+	case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT:
+	case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT:
+	case COMMAND_GET_DEBUG_CAMERA_POINT_AT:
+	case COMMAND_ATTACH_CHAR_TO_CAR:
+	case COMMAND_DETACH_CHAR_FROM_CAR:
+	case COMMAND_SET_CAR_STAY_IN_FAST_LANE:
+	case COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE:
+	case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE:
+	case COMMAND_GET_RANDOM_COP_IN_AREA:
+	case COMMAND_GET_RANDOM_COP_IN_ZONE:
+	case COMMAND_SET_CHAR_OBJ_FLEE_CAR:
+	case COMMAND_GET_DRIVER_OF_CAR:
+	case COMMAND_GET_NUMBER_OF_FOLLOWERS:
+	case COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER:
+	case COMMAND_GET_CURRENT_PLAYER_WEAPON:
+	case COMMAND_GET_CURRENT_CHAR_WEAPON:
+	case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D:
+	case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D:
+	case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D:
+	case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:
+	case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:
+	case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
+	case COMMAND_SET_CAR_TEMP_ACTION:
+	case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT:
+	case COMMAND_SET_CAR_HANDBRAKE_STOP:
+	case COMMAND_IS_CHAR_ON_ANY_BIKE:
+	case COMMAND_LOCATE_SNIPER_BULLET_2D:
+	case COMMAND_LOCATE_SNIPER_BULLET_3D:
+	case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL:
+	case COMMAND_IS_PLAYER_ON_ANY_BIKE:
+	case COMMAND_IS_CHAR_LYING_DOWN:
+	case COMMAND_CAN_CHAR_SEE_DEAD_CHAR:
+	case COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER:
+	default:
+		assert(0);
+	}
+	return -1;
+}
+#endif
+
 int16 CRunningScript::GetPadState(uint16 pad, uint16 button)
 {
 	CPad* pPad = CPad::GetPad(pad);
@@ -5534,12 +6053,6 @@ bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)
 	return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled;
 }
 
-WRAPPER int8 CRunningScript::ProcessCommandsFrom700To799(int32 command) { EAXJMP(0x4458A0); }
-WRAPPER int8 CRunningScript::ProcessCommandsFrom800To899(int32 command) { EAXJMP(0x448240); }
-WRAPPER int8 CRunningScript::ProcessCommandsFrom900To999(int32 command) { EAXJMP(0x44CB80); }
-WRAPPER int8 CRunningScript::ProcessCommandsFrom1000To1099(int32 command) { EAXJMP(0x588490); }
-WRAPPER int8 CRunningScript::ProcessCommandsFrom1100To1199(int32 command) { EAXJMP(0x589D00); }
-
 WRAPPER void CRunningScript::LocatePlayerCommand(int32, uint32*) { EAXJMP(0x44FE10); }
 WRAPPER void CRunningScript::LocatePlayerCharCommand(int32, uint32*) { EAXJMP(0x4501E0); }
 WRAPPER void CRunningScript::LocatePlayerCarCommand(int32, uint32*) { EAXJMP(0x450540); }
diff --git a/src/core/config.h b/src/core/config.h
index ae9e2ea4..12cb7be8 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -162,6 +162,6 @@ enum Config {
 
 // Peds
 #define ANIMATE_PED_COL_MODEL
-//#define VC_PED_PORTS
+#define VC_PED_PORTS
 #define NEW_WALK_AROUND_ALGORITHM
 #define CANCELLABLE_CAR_ENTER

From 80453d3f4ddc13f8458e14353c318a69cfe10518 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Wed, 1 Jan 2020 02:35:54 +0300
Subject: [PATCH 3/9] some not fully tested stuff

---
 src/control/Garages.cpp        |   1 +
 src/control/Garages.h          |   1 +
 src/control/Pickups.cpp        |  15 +-
 src/control/Pickups.h          |  16 +-
 src/control/Script.cpp         | 788 ++++++++++++++++++++++++++++++++-
 src/control/Script.h           |  22 +
 src/core/Fire.cpp              |  17 +-
 src/core/Fire.h                |   9 +-
 src/core/Stats.cpp             |  15 +
 src/core/Stats.h               |  16 +
 src/peds/Ped.cpp               |  36 +-
 src/peds/Ped.h                 |  20 +-
 src/vehicles/Vehicle.h         |   2 +
 src/weapons/ProjectileInfo.cpp |   3 +-
 src/weapons/ProjectileInfo.h   |   1 +
 15 files changed, 920 insertions(+), 42 deletions(-)

diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index d8e8df9f..ca1dae1b 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -87,6 +87,7 @@ int32 CGarages::QueryCarsCollected(int16 garage)
 }
 
 WRAPPER bool CGarages::HasThisCarBeenCollected(int16 garage, uint8 id) { EAXJMP(0x426D50); }
+WRAPPER void CGarages::ChangeGarageType(int16 garage, int8 type) { EAXJMP(0x4222A0); }
 
 #if 0
 WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); }
diff --git a/src/control/Garages.h b/src/control/Garages.h
index 7960e619..f9421ae8 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -39,4 +39,5 @@ public:
 	static void DeActivateGarage(int16);
 	static int32 QueryCarsCollected(int16);
 	static bool HasThisCarBeenCollected(int16, uint8);
+	static void ChangeGarageType(int16, int8); //TODO: eGarageType
 };
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 52861e99..67c59101 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -46,8 +46,21 @@ uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 25
 uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
 float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
 
-WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
+WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); }
 WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); }
+WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); }
+WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); }
+WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); }
+WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
+WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); }
+WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); }
+WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); }
+WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); }
+WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); }
+WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); }
+WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); }
+WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); }
+WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); }
 
 
 void
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index 5f9814c3..4bb0ddff 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -105,6 +105,20 @@ extern uint16 CostOfWeapon[20];
 class CPacManPickups
 {
 public:
-	static void Render(void);
+	static void Init(void);
 	static void Update(void);
+	static void GeneratePMPickUps(CVector, float, int16, uint8);
+	static void GeneratePMPickUpsForRace(int32);
+	static void GenerateOnePMPickUp(CVector);
+	static void Render(void);
+	static void DoCleanUpPacManStuff(void);
+	static void StartPacManRace(int32);
+	static void StartPacManRecord(void);
+	static uint32 QueryPowerPillsEatenInRace(void);
+	static void ResetPowerPillsEatenInRace(void);
+	static void CleanUpPacManStuff(void);
+	static void StartPacManScramble(CVector, float, int16);
+	static uint32 QueryPowerPillsCarriedByPlayer(void);
+	static void ResetPowerPillsCarriedByPlayer(void);
+
 };
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index d361045c..6d0c596d 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -37,13 +37,16 @@
 #include "PointLights.h"
 #include "Pools.h"
 #include "Population.h"
+#include "ProjectileInfo.h"
 #include "Remote.h"
 #include "Restart.h"
 #include "Replay.h"
 #include "Shadows.h"
+#include "Stats.h"
 #include "Streaming.h"
 #include "Text.h"
 #include "User.h"
+#include "WaterLevel.h"
 #include "Weather.h"
 #include "World.h"
 #include "Zones.h"
@@ -1661,13 +1664,23 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		CGeneral::GetRandomNumber();
 		CGeneral::GetRandomNumber();
 		CGeneral::GetRandomNumber(); /* To make it EXTRA random! */
+#ifdef FIX_BUGS
+		*ptr = CGeneral::GetRandomNumberInRange(0.0f, 1.0f);
+#else
 		*ptr = CGeneral::GetRandomNumber() / 65536.0f;
 		/* Between 0 and 0.5 on PC (oh well...), never used in original script. */
+#endif
+
 		return 0;
 	}
 	case COMMAND_GENERATE_RANDOM_INT:
+#ifdef FIX_BUGS
+		// Not a very good fix but before switching to PS2 rand, it sort of works
+		*GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL) = CGeneral::GetRandomNumberInRange(0, 65535);
+#else
 		/* On PC between 0 and 32767, even though script expects values between 0 and 65536 */
 		*GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL) = CGeneral::GetRandomNumber();
+#endif
 		return 0;
 	case COMMAND_CREATE_CHAR:
 	{
@@ -1709,7 +1722,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 			ped = new CCivilianPed(ScriptParams[0], ScriptParams[1]);
 		ped->CharCreatedBy = MISSION_CHAR;
 		ped->bRespondsToThreats = false;
-		ped->m_ped_flagG2 = false;
+		ped->bAllowMedicsToReviveMe = false;
 		CVector pos = *(CVector*)&ScriptParams[2];
 		if (pos.z <= -100.0f)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -2740,7 +2753,7 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
 			pPed = new CCivilianPed(ScriptParams[1], ScriptParams[2]);
 		pPed->CharCreatedBy = MISSION_CHAR;
 		pPed->bRespondsToThreats = false;
-		pPed->m_ped_flagG2 = false;
+		pPed->bAllowMedicsToReviveMe = false;
 		pPed->GetPosition() = pVehicle->GetPosition();
 		pPed->SetOrientation(0.0f, 0.0f, 0.0f);
 		pPed->SetPedState(PED_DRIVING);
@@ -3875,6 +3888,7 @@ int8 CRunningScript::ProcessCommandsFrom400To499(int32 command)
 	{
 		CollectParameters(&m_nIp, 1);
 		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
 		CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
 		return 0;
 	}
@@ -3882,6 +3896,7 @@ int8 CRunningScript::ProcessCommandsFrom400To499(int32 command)
 	{
 		CollectParameters(&m_nIp, 1);
 		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
 		CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
 		return 0;
 	}
@@ -3889,6 +3904,7 @@ int8 CRunningScript::ProcessCommandsFrom400To499(int32 command)
 	{
 		CollectParameters(&m_nIp, 1);
 		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
 		CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
 		return 0;
 	}
@@ -3934,7 +3950,7 @@ int8 CRunningScript::ProcessCommandsFrom400To499(int32 command)
 			pPed = new CCivilianPed(ScriptParams[1], ScriptParams[2]);
 		pPed->CharCreatedBy = MISSION_CHAR;
 		pPed->bRespondsToThreats = false;
-		pPed->m_ped_flagG2 = false;
+		pPed->bAllowMedicsToReviveMe = false;
 		pPed->GetPosition() = pVehicle->GetPosition();
 		pPed->SetOrientation(0.0f, 0.0f, 0.0f);
 		pPed->SetPedState(PED_DRIVING);
@@ -4944,10 +4960,8 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
 		CollectParameters(&m_nIp, 1);
 		char name[16];
 		strncpy(name, (char*)&CTheScripts::ScriptSpace[m_nIp], 8);
-		for (int i = 0; i < 8; i++) {
-			if (name[i] >= 'A' && name[i] <= 'Z')
-				name[i] += 'a' - 'A';
-		}
+		for (int i = 0; i < 8; i++)
+			name[i] = tolower(name[i]);
 		CStreaming::RequestSpecialChar(ScriptParams[0] - 1, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
 		m_nIp += 8;
 		return 0;
@@ -5499,112 +5513,870 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 }
 #endif
 
-#if 1
+#if 0
 WRAPPER int8 CRunningScript::ProcessCommandsFrom700To799(int32 command) { EAXJMP(0x4458A0); }
 #else
 int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 {
 	switch (command){
 	case COMMAND_SET_SWAT_REQUIRED:
+		CollectParameters(&m_nIp, 1);
+		FindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0);
+		return 0;
 	case COMMAND_SET_FBI_REQUIRED:
+		CollectParameters(&m_nIp, 1);
+		FindPlayerPed()->m_pWanted->m_bFbiRequired = (ScriptParams[0] != 0);
+		return 0;
 	case COMMAND_SET_ARMY_REQUIRED:
+		CollectParameters(&m_nIp, 1);
+		FindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0);
+		return 0;
 	case COMMAND_IS_CAR_IN_WATER:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		UpdateCompareFlag(pVehicle->bIsInWater);
+		return 0;
+	}
 	case COMMAND_GET_CLOSEST_CHAR_NODE:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)];
+		*(CVector*)&ScriptParams[0] = pNode->pos;
+		StoreParameters(&m_nIp, 3);
+		return 0;
+	}
 	case COMMAND_GET_CLOSEST_CAR_NODE:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)];
+		*(CVector*)&ScriptParams[0] = pNode->pos;
+		StoreParameters(&m_nIp, 3);
+		return 0;
+	}
 	case COMMAND_CAR_GOTO_COORDINATES_ACCURATE:
+	{
+		CollectParameters(&m_nIp, 4);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		CVector pos = *(CVector*)&ScriptParams[1];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
+		if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pos, false))
+			pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;
+		else
+			pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE;
+		pVehicle->m_status = STATUS_PHYSICS;
+		pVehicle->bEngineOn = true;
+		pVehicle->AutoPilot.m_nCruiseSpeed = min(6, pVehicle->AutoPilot.m_nCruiseSpeed);
+		pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
+		return 0;
+	}
 	case COMMAND_START_PACMAN_RACE:
+		CollectParameters(&m_nIp, 1);
+		CPacManPickups::StartPacManRace(ScriptParams[0]);
+		return 0;
 	case COMMAND_START_PACMAN_RECORD:
+		CPacManPickups::StartPacManRecord();
+		return 0;
 	case COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN:
+		ScriptParams[0] = CPacManPickups::QueryPowerPillsEatenInRace();
+		StoreParameters(&m_nIp, 1);
+		return 0;
 	case COMMAND_CLEAR_PACMAN:
+		CPacManPickups::CleanUpPacManStuff();
+		return 0;
 	case COMMAND_START_PACMAN_SCRAMBLE:
+	{
+		CollectParameters(&m_nIp, 5);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		CPacManPickups::StartPacManScramble(pos, *(float*)&ScriptParams[3], ScriptParams[4]);
+		return 0;
+	}
 	case COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED:
+		ScriptParams[0] = CPacManPickups::QueryPowerPillsCarriedByPlayer();
+		return 0;
 	case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED:
+		CPacManPickups::ResetPowerPillsCarriedByPlayer();
+		return 0;
 	case COMMAND_IS_CAR_ON_SCREEN:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		UpdateCompareFlag(TheCamera.IsSphereVisible(pVehicle->GetBoundCentre(), pVehicle->GetBoundRadius()));
+		return 0;
+	}
 	case COMMAND_IS_CHAR_ON_SCREEN:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		UpdateCompareFlag(TheCamera.IsSphereVisible(pPed->GetBoundCentre(), pPed->GetBoundRadius()));
+		return 0;
+	}
 	case COMMAND_IS_OBJECT_ON_SCREEN:
+	{
+		CollectParameters(&m_nIp, 1);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		UpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius()));
+		return 0;
+	}
 	case COMMAND_GOSUB_FILE:
+	{
+		CollectParameters(&m_nIp, 2);
+		assert(m_nStackPointer < MAX_STACK_DEPTH);
+		m_anStack[m_nStackPointer++] = m_nIp;
+		m_nIp = ScriptParams[0];
+		// ScriptParams[1] == filename
+		return 0;
+	}
 	case COMMAND_GET_GROUND_Z_FOR_3D_COORD:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		bool success;
+		*(float*)&ScriptParams[0] = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &success);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_START_SCRIPT_FIRE:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		ScriptParams[0] = gFireManager.StartScriptFire(pos, nil, 0.8f, 1);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED:
+		CollectParameters(&m_nIp, 1);
+		UpdateCompareFlag(gFireManager.IsScriptFireExtinguish(ScriptParams[0]));
+		return 0;
 	case COMMAND_REMOVE_SCRIPT_FIRE:
+		CollectParameters(&m_nIp, 1);
+		gFireManager.RemoveScriptFire(ScriptParams[0]);
+		return 0;
 	case COMMAND_SET_COMEDY_CONTROLS:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		pVehicle->bComedyControls = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_BOAT_GOTO_COORDS:
+	{
+		CollectParameters(&m_nIp, 4);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+		CBoat* pBoat = (CBoat*)pVehicle;
+		CVector pos = *(CVector*)&ScriptParams[1];
+		if (pos.z <= -100.0f)
+			CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false);
+		pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS;
+		pBoat->AutoPilot.m_vecDestinationCoors = pos;
+		pBoat->m_status = STATUS_PHYSICS;
+		pBoat->AutoPilot.m_nCruiseSpeed = max(6, pBoat->AutoPilot.m_nCruiseSpeed);
+		pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
+		return 0;
+	}
 	case COMMAND_BOAT_STOP:
+	{
+		CollectParameters(&m_nIp, 4);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+		CBoat* pBoat = (CBoat*)pVehicle;
+		pBoat->AutoPilot.m_nCarMission = MISSION_NONE;
+		pBoat->m_status = STATUS_PHYSICS;
+		pBoat->bEngineOn = false;
+		pBoat->AutoPilot.m_nCruiseSpeed = 0;
+		return 0;
+	}
 	case COMMAND_IS_PLAYER_SHOOTING_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 6);
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		float x1, y1, x2, y2;
+		x1 = *(float*)&ScriptParams[1];
+		y1 = *(float*)&ScriptParams[2];
+		x2 = *(float*)&ScriptParams[3];
+		y2 = *(float*)&ScriptParams[4];
+		UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
+		if (!ScriptParams[5])
+			return 0;
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		if (CTheScripts::DbgFlag)
+			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
+		return 0;
+	}
 	case COMMAND_IS_CHAR_SHOOTING_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 6);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		float x1, y1, x2, y2;
+		x1 = *(float*)&ScriptParams[1];
+		y1 = *(float*)&ScriptParams[2];
+		x2 = *(float*)&ScriptParams[3];
+		y2 = *(float*)&ScriptParams[4];
+		UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
+		if (!ScriptParams[5])
+			return 0;
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		if (CTheScripts::DbgFlag)
+			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
+		return 0;
+	}
 	case COMMAND_IS_CURRENT_PLAYER_WEAPON:
+	{
+		CollectParameters(&m_nIp, 2); 
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
+		return 0;
+	}
 	case COMMAND_IS_CURRENT_CHAR_WEAPON:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
+		return 0;
+	}
 	case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN:
+		CPacManPickups::ResetPowerPillsEatenInRace();
+		return 0;
 	case COMMAND_ADD_POWER_PILL:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		CPacManPickups::GenerateOnePMPickUp(pos);
+		return 0;
+	}
 	case COMMAND_SET_BOAT_CRUISE_SPEED:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
+		CBoat* pBoat = (CBoat*)pVehicle;
+		pBoat->AutoPilot.m_nCruiseSpeed = ScriptParams[1];
+	}
 	case COMMAND_GET_RANDOM_CHAR_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 4);
+		int ped_handle = -1;
+		CVector pos = FindPlayerCoors();
+		float x1, y1, x2, y2;
+		x1 = *(float*)&ScriptParams[1];
+		y1 = *(float*)&ScriptParams[2];
+		x2 = *(float*)&ScriptParams[3];
+		y2 = *(float*)&ScriptParams[4];
+		int i = CPools::GetPedPool()->GetSize();
+		while (--i && ped_handle == -1){
+			CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+			if (!pPed)
+				continue;
+			if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
+				continue;
+			if (pPed->CharCreatedBy != RANDOM_CHAR)
+				continue;
+			if (!pPed->IsPedInControl())
+				continue;
+			if (pPed->bRemoveFromWorld)
+				continue;
+			if (pPed->bFadeOut)
+				continue;
+			if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+				continue;
+			if (!ThisIsAValidRandomPed(pPed->m_nPedType))
+				continue;
+			if (pPed->bIsLeader || pPed->m_leader)
+				continue;
+			if (!pPed->IsWithinArea(x1, y1, x2, y2))
+				continue;
+			if (pos.z - 5.0f > pPed->GetPosition().z)
+				continue;
+			if (pos.z + 5.0f < pPed->GetPosition().z)
+				continue;
+			ped_handle = CPools::GetPedPool()->GetIndex(pPed);
+			CTheScripts::LastRandomPedId = ped_handle;
+			pPed->CharCreatedBy = MISSION_CHAR;
+			pPed->bRespondsToThreats = false;
+			++CPopulation::ms_nTotalMissionPeds;
+			if (m_bIsMissionScript)
+				CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+		}
+		ScriptParams[0] = ped_handle;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_GET_RANDOM_CHAR_IN_ZONE:
+	{
+		char zone[8];
+		strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], 8);
+		int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+		if (nZone != -1)
+			m_nIp += 8;
+		CZone* pZone = CTheZones::GetZone(nZone);
+		int ped_handle = -1;
+		CVector pos = FindPlayerCoors();
+		int i = CPools::GetPedPool()->GetSize();
+		while (--i && ped_handle == -1) {
+			CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+			if (!pPed)
+				continue;
+			if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
+				continue;
+			if (pPed->CharCreatedBy != RANDOM_CHAR)
+				continue;
+			if (!pPed->IsPedInControl())
+				continue;
+			if (pPed->bRemoveFromWorld)
+				continue;
+			if (pPed->bFadeOut)
+				continue;
+			if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+				continue;
+			if (!ThisIsAValidRandomPed(pPed->m_nPedType))
+				continue;
+			if (pPed->bIsLeader || pPed->m_leader)
+				continue;
+			if (!CTheZones::PointLiesWithinZone(pPed->GetPosition(), pZone))
+				continue;
+			if (pos.z - 5.0f > pPed->GetPosition().z)
+				continue;
+			if (pos.z + 5.0f < pPed->GetPosition().z)
+				continue;
+			ped_handle = CPools::GetPedPool()->GetIndex(pPed);
+			CTheScripts::LastRandomPedId = ped_handle;
+			pPed->CharCreatedBy = MISSION_CHAR;
+			pPed->bRespondsToThreats = false;
+			++CPopulation::ms_nTotalMissionPeds;
+			if (m_bIsMissionScript)
+				CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+		}
+		ScriptParams[0] = ped_handle;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_IS_PLAYER_IN_TAXI:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->IsTaxi());
+		return 0;
+	}
 	case COMMAND_IS_PLAYER_SHOOTING:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		UpdateCompareFlag(pPed->bIsShooting);
+		return 0;
+	}
 	case COMMAND_IS_CHAR_SHOOTING:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		UpdateCompareFlag(pPed->bIsShooting);
+		return 0;
+	}
 	case COMMAND_CREATE_MONEY_PICKUP:
+	{
+		CollectParameters(&m_nIp, 4);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+		ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_MONEY, PICKUP_MONEY, ScriptParams[3]);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_ACCURACY:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->m_wepAccuracy = ScriptParams[1];
+		return 0;
+	}
 	case COMMAND_GET_CAR_SPEED:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		*(float*)&ScriptParams[0] = pVehicle->GetSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_LOAD_CUTSCENE:
+	{
+		char name[8];
+		strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], 8);
+		m_nIp += 8;
+		CCutsceneMgr::LoadCutsceneData(name);
+		return 0;
+	}
 	case COMMAND_CREATE_CUTSCENE_OBJECT:
+	{
+		CollectParameters(&m_nIp, 1);
+		CCutsceneObject* pCutObj = CCutsceneMgr::CreateCutsceneObject(ScriptParams[0]);
+		ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutObj);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_SET_CUTSCENE_ANIM:
+	{
+		CollectParameters(&m_nIp, 1);
+		char name[8];
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], 8);
+		m_nIp += 8;
+		CCutsceneMgr::SetCutsceneAnim(name, pObject);
+		return 0;
+	}
 	case COMMAND_START_CUTSCENE:
+		CCutsceneMgr::ms_cutsceneLoadStatus = 1;
+		return 0;
 	case COMMAND_GET_CUTSCENE_TIME:
+		ScriptParams[0] = CCutsceneMgr::GetCutsceneTimeInMilleseconds();
+		StoreParameters(&m_nIp, 1);
+		return 0;
 	case COMMAND_HAS_CUTSCENE_FINISHED:
+		UpdateCompareFlag(CCutsceneMgr::HasCutsceneFinished());
+		return 0;
 	case COMMAND_CLEAR_CUTSCENE:
+		CCutsceneMgr::DeleteCutsceneData();
+		return 0;
 	case COMMAND_RESTORE_CAMERA_JUMPCUT:
+		TheCamera.RestoreWithJumpCut();
+		return 0;
 	case COMMAND_CREATE_COLLECTABLE1:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		CPickups::GenerateNewOne(pos, MI_COLLECTABLE1, PICKUP_COLLECTABLE1, 0);
+		return 0;
+	}
 	case COMMAND_SET_COLLECTABLE1_TOTAL:
+		CollectParameters(&m_nIp, 1);
+		CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0];
+		return 0;
 	case COMMAND_IS_PROJECTILE_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 6);
+		float infX = *(float*)&ScriptParams[0];
+		float infY = *(float*)&ScriptParams[1];
+		float infZ = *(float*)&ScriptParams[2];
+		float supX = *(float*)&ScriptParams[3];
+		float supY = *(float*)&ScriptParams[4];
+		float supZ = *(float*)&ScriptParams[5];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[3];
+			supX = *(float*)&ScriptParams[0];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[4];
+			supY = *(float*)&ScriptParams[1];
+		}
+		if (infZ > supZ) {
+			infZ = *(float*)&ScriptParams[5];
+			supZ = *(float*)&ScriptParams[2];
+		}
+		UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, false));
+		if (CTheScripts::DbgFlag)
+			CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+		return 0;
+	}
 	case COMMAND_DESTROY_PROJECTILES_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 6);
+		float infX = *(float*)&ScriptParams[0];
+		float infY = *(float*)&ScriptParams[1];
+		float infZ = *(float*)&ScriptParams[2];
+		float supX = *(float*)&ScriptParams[3];
+		float supY = *(float*)&ScriptParams[4];
+		float supZ = *(float*)&ScriptParams[5];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[3];
+			supX = *(float*)&ScriptParams[0];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[4];
+			supY = *(float*)&ScriptParams[1];
+		}
+		if (infZ > supZ) {
+			infZ = *(float*)&ScriptParams[5];
+			supZ = *(float*)&ScriptParams[2];
+		}
+		UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, true));
+		if (CTheScripts::DbgFlag)
+			CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+		return 0;
+	}
 	case COMMAND_DROP_MINE:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		CPickups::GenerateNewOne(pos, MI_CARMINE, PICKUP_MINE_INACTIVE, 0);
+		return 0;
+	}
 	case COMMAND_DROP_NAUTICAL_MINE:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= -100.0f)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0);
+		return 0;
+	}
 	case COMMAND_IS_CHAR_MODEL:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		UpdateCompareFlag(ScriptParams[1] == pPed->GetModelIndex());
+		return 0;
+	}
 	case COMMAND_LOAD_SPECIAL_MODEL:
+	{
+		CollectParameters(&m_nIp, 1);
+		char name[8];
+		strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], 8);
+		for (int i = 0; i < 8; i++)
+			name[i] = tolower(name[i]);
+		CStreaming::RequestSpecialModel(ScriptParams[0], name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
+		m_nIp += 8;
+		return 0;
+	}
 	case COMMAND_CREATE_CUTSCENE_HEAD:
+	{
+		CollectParameters(&m_nIp, 2);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]);
+		ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_SET_CUTSCENE_HEAD_ANIM:
+	{
+		CollectParameters(&m_nIp, 1);
+		CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pCutHead);
+		char name[8];
+		strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], 8);
+		m_nIp += 8;
+		CTimer::Stop();
+		CCutsceneMgr::SetHeadAnim(name, pCutHead);
+		CTimer::Update();
+		return 0;
+	}
 	case COMMAND_SIN:
+		CollectParameters(&m_nIp, 1);
+		*(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0]));
+		StoreParameters(&m_nIp, 1);
+		return 0;
 	case COMMAND_COS:
+		CollectParameters(&m_nIp, 1);
+		*(float*)&ScriptParams[0] = Cos(DEGTORAD(*(float*)&ScriptParams[0]));
+		StoreParameters(&m_nIp, 1);
+		return 0;
 	case COMMAND_GET_CAR_FORWARD_X:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		float forwardX = pVehicle->GetForward().x / pVehicle->GetForward().Magnitude2D();
+		*(float*)&ScriptParams[0] = forwardX;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_GET_CAR_FORWARD_Y:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		float forwardY = pVehicle->GetForward().y / pVehicle->GetForward().Magnitude2D();
+		*(float*)&ScriptParams[0] = forwardY;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_CHANGE_GARAGE_TYPE:
+		CollectParameters(&m_nIp, 2);
+		CGarages::ChangeGarageType(ScriptParams[0], ScriptParams[1]);
+		return 0;
 	case COMMAND_ACTIVATE_CRUSHER_CRANE:
+	{
+		CollectParameters(&m_nIp, 10);
+		float infX = *(float*)&ScriptParams[2];
+		float infY = *(float*)&ScriptParams[3];
+		float supX = *(float*)&ScriptParams[4];
+		float supY = *(float*)&ScriptParams[5];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[4];
+			supX = *(float*)&ScriptParams[2];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[5];
+			supY = *(float*)&ScriptParams[3];
+		}
+		CCranes::ActivateCrane(infX, supX, infY, supY,
+			*(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
+			DEGTORAD(*(float*)&ScriptParams[8]), true, false,
+			*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_2_NUMBERS:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 4);
+		CMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_2_NUMBERS_NOW:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 4);
+		CMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_2_NUMBERS_SOON:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 4);
+		CMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_3_NUMBERS:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 5);
+		CMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_3_NUMBERS_NOW:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 5);
+		CMessages::AddMessageJumpQWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_3_NUMBERS_SOON:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 5);
+		CMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_4_NUMBERS:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 6);
+		CMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_4_NUMBERS_NOW:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 6);
+		CMessages::AddMessageJumpQWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_4_NUMBERS_SOON:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 6);
+		CMessages::AddMessageSoonWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_5_NUMBERS:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 7);
+		CMessages::AddMessageWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_5_NUMBERS_NOW:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 7);
+		CMessages::AddMessageJumpQWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_5_NUMBERS_SOON:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 7);
+		CMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_6_NUMBERS:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 8);
+		CMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_6_NUMBERS_NOW:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 8);
+		CMessages::AddMessageJumpQWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_6_NUMBERS_SOON:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 8);
+		CMessages::AddMessageSoonWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION:
+	{
+		CollectParameters(&m_nIp, 3);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+		pPed->bScriptObjectiveCompleted = false;
+		pPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, pTargetPed);
+		pPed->SetFormation((eFormation)ScriptParams[2]);
+		return 0;
+	}
 	case COMMAND_PLAYER_MADE_PROGRESS:
+		CollectParameters(&m_nIp, 1);
+		CStats::ProgressMade += ScriptParams[0];
+		return 0;
 	case COMMAND_SET_PROGRESS_TOTAL:
+		CollectParameters(&m_nIp, 1);
+		CStats::TotalProgressInGame = ScriptParams[0];
+		return 0;
 	case COMMAND_REGISTER_JUMP_DISTANCE:
+		CollectParameters(&m_nIp, 1);
+		CStats::MaximumJumpDistance = max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]);
+		return 0;
 	case COMMAND_REGISTER_JUMP_HEIGHT:
+		CollectParameters(&m_nIp, 1);
+		CStats::MaximumJumpHeight = max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]);
+		return 0;
 	case COMMAND_REGISTER_JUMP_FLIPS:
+		CollectParameters(&m_nIp, 1);
+		CStats::MaximumJumpFlips = max(CStats::MaximumJumpFlips, ScriptParams[0]);
+		return 0;
 	case COMMAND_REGISTER_JUMP_SPINS:
+		CollectParameters(&m_nIp, 1);
+		CStats::MaximumJumpSpins = max(CStats::MaximumJumpSpins, ScriptParams[0]);
+		return 0;
 	case COMMAND_REGISTER_JUMP_STUNT:
+		CollectParameters(&m_nIp, 1);
+		CStats::BestStuntJump = max(CStats::BestStuntJump, ScriptParams[0]);
+		return 0;
 	case COMMAND_REGISTER_UNIQUE_JUMP_FOUND:
+		++CStats::NumberOfUniqueJumpsFound;
+		return 0;
 	case COMMAND_SET_UNIQUE_JUMPS_TOTAL:
+		CollectParameters(&m_nIp, 1);
+		CStats::TotalNumberOfUniqueJumps = ScriptParams[0];
+		return 0;
 	case COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI:
+		++CStats::PassengersDroppedOffWithTaxi;
+		return 0;
 	case COMMAND_REGISTER_MONEY_MADE_TAXI:
+		CollectParameters(&m_nIp, 1);
+		CStats::MoneyMadeWithTaxi += ScriptParams[0];
+		return 0;
 	case COMMAND_REGISTER_MISSION_GIVEN:
+		++CStats::MissionsGiven;
+		return 0;
 	case COMMAND_REGISTER_MISSION_PASSED:
+	{
+		char name[8];
+		strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], 8);
+		m_nIp += 8;
+		strncpy(CStats::LastMissionPassedName, name, 8);
+		++CStats::MissionsPassed;
+		CStats::CheckPointReachedSuccessfully();
+		return 0;
+	}
 	case COMMAND_SET_CHAR_RUNNING:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bIsRunning = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_REMOVE_ALL_SCRIPT_FIRES:
+		gFireManager.RemoveAllScriptFires();
+		return 0;
 	case COMMAND_IS_FIRST_CAR_COLOUR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		UpdateCompareFlag(pVehicle->m_currentColour1 == ScriptParams[1]);
+		return 0;
+	}
 	case COMMAND_IS_SECOND_CAR_COLOUR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		UpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]);
+		return 0;
+	}
 	case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		if (!pPed)
+			printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n");
+		UpdateCompareFlag(pPed && pPed->m_lastWepDam == ScriptParams[1]);
+		return 0;
+	}
 	case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		if (!pVehicle)
+			printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n");
+		UpdateCompareFlag(pVehicle && pVehicle->m_nLastWeaponDamage == ScriptParams[1]);
+		return 0;
+	}
 	case COMMAND_IS_CHAR_IN_CHARS_GROUP:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+		assert(pPed);
+		assert(pLeader);
+		UpdateCompareFlag(pPed->m_leader == pLeader);
+		return 0;
+	}
 	default:
 		assert(0);
 	}
diff --git a/src/control/Script.h b/src/control/Script.h
index 751ad9d5..fa8344ae 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -1,5 +1,6 @@
 #pragma once
 #include "common.h"
+#include "PedType.h"
 #include "Text.h"
 #include "Sprite2d.h"
 
@@ -92,6 +93,27 @@ public:
 		m_anLocalVariables[NUM_LOCAL_VARS + 1] += timeStep;
 	}
 
+	bool ThisIsAValidRandomPed(uint32 pedtype){
+		switch (pedtype){
+		case PEDTYPE_CIVMALE:
+		case PEDTYPE_CIVFEMALE:
+		case PEDTYPE_GANG1:
+		case PEDTYPE_GANG2:
+		case PEDTYPE_GANG3:
+		case PEDTYPE_GANG4:
+		case PEDTYPE_GANG5:
+		case PEDTYPE_GANG6:
+		case PEDTYPE_GANG7:
+		case PEDTYPE_GANG8:
+		case PEDTYPE_GANG9:
+		case PEDTYPE_CRIMINAL:
+		case PEDTYPE_PROSTITUTE:
+			return true;
+		default:
+			return false;
+		}
+	}
+
 	void CollectParameters(uint32*, int16);
 	int32 CollectNextParameterWithoutIncreasingPC(uint32);
 	int32* GetPointerToScriptVariable(uint32*, int16);
diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp
index 0317ccbe..274c06a5 100644
--- a/src/core/Fire.cpp
+++ b/src/core/Fire.cpp
@@ -6,6 +6,13 @@ CFireManager &gFireManager = *(CFireManager*)0x8F31D0;
 
 WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); }
 
+uint32 CFireManager::GetTotalActiveFires() const
+{
+	return m_nTotalFires;
+}
+
+WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); }
+
 CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance)
 {
 	for (int i = 0; i < MAX_FIREMEN_ATTENDING; i++) {
@@ -31,6 +38,12 @@ CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance)
 	return nil;
 }
 
-WRAPPER void CFireManager::StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32) { EAXJMP(0x479590); }
-WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); }
 WRAPPER CFire *CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); }
+WRAPPER void CFireManager::StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32) { EAXJMP(0x479590); }
+WRAPPER void CFireManager::StartFire(CVector, float, uint8) { EAXJMP(0x479500); }
+WRAPPER void CFireManager::ExtinguishPoint(CVector, float) { EAXJMP(0x479DB0); }
+WRAPPER int32 CFireManager::StartScriptFire(const CVector& pos, CEntity* culprit, float, uint8) { EAXJMP(0x479E60); }
+WRAPPER bool CFireManager::IsScriptFireExtinguish(int16) { EAXJMP(0x479FC0); }
+WRAPPER void CFireManager::RemoveScriptFire(int16) { EAXJMP(0x479FE0); }
+WRAPPER void CFireManager::RemoveAllScriptFires(void) { EAXJMP(0x47A000); }
+WRAPPER void CFireManager::SetScriptFireAudio(int16, bool) { EAXJMP(0x47A040); }
diff --git a/src/core/Fire.h b/src/core/Fire.h
index c752b2a6..9d72179e 100644
--- a/src/core/Fire.h
+++ b/src/core/Fire.h
@@ -31,9 +31,16 @@ class CFireManager
 	CFire m_aFires[NUM_FIRES];
 public:
 	void StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32);
+	void StartFire(CVector, float, uint8);
 	void Update(void);
 	CFire *FindFurthestFire_NeverMindFireMen(CVector coors, float, float);
 	CFire *FindNearestFire(CVector, float*);
-	uint32 GetTotalActiveFires() const { return m_nTotalFires; }
+	uint32 GetTotalActiveFires() const;
+	void ExtinguishPoint(CVector, float);
+	int32 StartScriptFire(const CVector& pos, CEntity* culprit, float, uint8);
+	bool IsScriptFireExtinguish(int16);
+	void RemoveScriptFire(int16);
+	void RemoveAllScriptFires(void);
+	void SetScriptFireAudio(int16, bool);
 };
 extern CFireManager &gFireManager;
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index 9641e8f0..5d2401ed 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -12,6 +12,21 @@ int32 *CStats::PedsKilledOfThisType = (int32*)0x880DBC;
 int32 &CStats::TimesDied = *(int32*)0x8E2BDC;
 int32 &CStats::TimesArrested = *(int32*)0x8E2BEC;
 int32 &CStats::KillsSinceLastCheckpoint = *(int32*)0x8F2C8C;
+int32 &CStats::ProgressMade = *(int32*)0x8F6224;
+int32 &CStats::TotalProgressInGame = *(int32*)0x885B2C;
+float &CStats::MaximumJumpDistance = *(float*)0x8F2BDC;
+float &CStats::MaximumJumpHeight = *(float*)0x940564;
+int32 &CStats::MaximumJumpFlips = *(int32*)0x8F2524;
+int32 &CStats::MaximumJumpSpins = *(int32*)0x8F29B0;
+int32 &CStats::BestStuntJump = *(int32*)0x885B50;
+int32 &CStats::NumberOfUniqueJumpsFound = *(int32*)0x885B74;
+int32 &CStats::TotalNumberOfUniqueJumps = *(int32*)0x8E2DC0;
+int32 &CStats::PassengersDroppedOffWithTaxi = *(int32*)0x940724;
+int32 &CStats::MoneyMadeWithTaxi = *(int32*)0x941544;
+int32 &CStats::MissionsGiven = *(int32*)0x9430E8;
+int32 &CStats::MissionsPassed = *(int32*)0x940768;
+char(&CStats::LastMissionPassedName)[8] = *(char(*)[8])*(uintptr*)0x70D828;
+int32 &CStats::TotalLegitimateKills = *(int32*)0x8F6004;
 
 void CStats::AnotherKillFrenzyPassed()
 {
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 7bae8c51..22f0c68a 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -14,8 +14,24 @@ public:
 	static int32 &TimesDied;
 	static int32 &TimesArrested;
 	static int32 &KillsSinceLastCheckpoint;
+	static int32 &ProgressMade;
+	static int32 &TotalProgressInGame;
+	static float &MaximumJumpDistance;
+	static float &MaximumJumpHeight;
+	static int32 &MaximumJumpFlips;
+	static int32 &MaximumJumpSpins;
+	static int32 &BestStuntJump;
+	static int32 &NumberOfUniqueJumpsFound;
+	static int32 &TotalNumberOfUniqueJumps;
+	static int32 &PassengersDroppedOffWithTaxi;
+	static int32 &MoneyMadeWithTaxi;
+	static int32 &MissionsGiven;
+	static int32 &MissionsPassed;
+	static char (&LastMissionPassedName)[8];
+	static int32 &TotalLegitimateKills;
 
 public:
 	static void AnotherKillFrenzyPassed();
 	static void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; };
+	static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; };
 };
\ No newline at end of file
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 4e64c1db..11aa480b 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -502,7 +502,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
 	bChangedSeat = false;
 	bUpdateAnimHeading = false;
 	bBodyPartJustCameOff = false;
-	m_ped_flagC40 = false;
+	bIsShooting = false;
 	bFindNewNodeAfterStateRestore = false;
 
 	bHasACamera = false;
@@ -524,8 +524,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
 	bFleeAfterExitingCar = false;
 
 	bWanderPathAfterExitingCar = false;
-	m_ped_flagF2 = false;
-	m_ped_flagF4 = false;
+	bIsLeader = false;
+	bDontDragMeOutCar = false;
 	m_ped_flagF8 = false;
 	bWillBeQuickJacked = false;
 	bCancelEnteringCar = false;
@@ -533,8 +533,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
 	bDuckAndCover = false;
 
 	bStillOnValidPoly = false;
-	m_ped_flagG2 = true;
-	m_ped_flagG4 = false;
+	bAllowMedicsToReviveMe = true;
+	bResetWalkAnims = false;
 	bStartWanderPathOnFoot = false;
 	bOnBoat = false;
 	bBusJacked = false;
@@ -543,12 +543,12 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
 
 	m_ped_flagH1 = false;
 	bHitSteepSlope = false;
-	m_ped_flagH4 = false;
+	bCullExtraFarAway = false;
 	bClearObjective = false;
-	m_ped_flagH10 = false;
+	bTryingToReachDryLand = false;
 	bCollidedWithMyVehicle = false;
 	bRichFromMugging = false;
-	m_ped_flagH80 = false;
+	bChrisCriminal = false;
 
 	bShakeFist = false;
 	bNoCriticalHits = false;
@@ -6821,7 +6821,7 @@ CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg)
 {
 	CPed *ped = (CPed*)arg;
 
-	ped->m_ped_flagG4 = true;
+	ped->bResetWalkAnims = true;
 	ped->bIsLanding = false;
 
 	animAssoc->blendDelta = -1000.0f;
@@ -7696,7 +7696,7 @@ CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen)
 
 			CPed *rfPassenger = veh->pPassengers[0];
 			if (!rfPassenger
-				|| rfPassenger->m_leader != this && !rfPassenger->m_ped_flagF4 && (veh->VehicleCreatedBy != MISSION_VEHICLE || m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER)
+				|| rfPassenger->m_leader != this && !rfPassenger->bDontDragMeOutCar && (veh->VehicleCreatedBy != MISSION_VEHICLE || m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER)
 				|| veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) == 0) {
 
 				if ((veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) == 0
@@ -9184,7 +9184,7 @@ CPed::ProcessControl(void)
 	}
 
 	CVisibilityPlugins::SetClumpAlpha(GetClump(), alpha);
-	m_ped_flagC40 = false;
+	bIsShooting = false;
 	BuildPedLists();
 	bIsInWater = false;
 	ProcessBuoyancy();
@@ -10709,7 +10709,7 @@ CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)
 		}
 
 		if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
-			if (pedToDragOut && !pedToDragOut->m_ped_flagF4) {
+			if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) {
 				if (pedToDragOut->m_nPedState != PED_DRIVING) {
 					ped->QuitEnteringCar();
 					pedToDragOut = nil;
@@ -10740,9 +10740,9 @@ CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)
 			}
 		} else {
 			if (pedToDragOut) {
-				if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->m_ped_flagF4) {
+				if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) {
 
-					// BUG: Player freezes in that condition due to it's objective isn't restored. It's an unfinished feature, used in VC.
+					// BUG: Player freezes in that condition due to its objective isn't restored. It's an unfinished feature, used in VC.
 					ped->QuitEnteringCar();
 					pedToDragOut = nil;
 				} else {
@@ -14310,7 +14310,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
 							if (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) {
 								m_pCurSurface = collidingEnt;
 								collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
-								m_ped_flagH10 = false;
+								bTryingToReachDryLand = false;
 								bOnBoat = false;
 							} else {
 								m_pCurrentPhysSurface = (CPhysical*)collidingEnt;
@@ -14809,9 +14809,9 @@ CPed::ProcessBuoyancy(void)
 		bIsInWater = true;
 		ApplyMoveForce(buoyancyImpulse);
 		if (!DyingOrDead()) {
-			if (m_ped_flagH10) {
+			if (bTryingToReachDryLand) {
 				if (buoyancyImpulse.z / m_fMass > 0.0032f * CTimer::GetTimeStep()) {
-					m_ped_flagH10 = false;
+					bTryingToReachDryLand = false;
 					CVector pos = GetPosition();
 					if (PlacePedOnDryLand()) {
 						if (m_fHealth > 20.0f)
@@ -15749,7 +15749,7 @@ CPed::SeekCar(void)
 									break;
 								case STATUS_ABANDONED:
 									if (m_vehEnterType == CAR_DOOR_RF && vehToSeek->pPassengers[0]) {
-										if (vehToSeek->pPassengers[0]->m_ped_flagF4) {
+										if (vehToSeek->pPassengers[0]->bDontDragMeOutCar) {
 											if (IsPlayer())
 												CPed::SetEnterCar(vehToSeek, m_vehEnterType);
 										} else {
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 50a8bfec..446aab4b 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -313,7 +313,7 @@ public:
 	uint8 bChangedSeat : 1;
 	uint8 bUpdateAnimHeading : 1;
 	uint8 bBodyPartJustCameOff : 1;
-	uint8 m_ped_flagC40 : 1;
+	uint8 bIsShooting : 1;
 	uint8 bFindNewNodeAfterStateRestore : 1;
 
 	uint8 bHasACamera : 1; // does ped possess a camera to document accidents involves fire/explosion
@@ -335,17 +335,17 @@ public:
 	uint8 bFleeAfterExitingCar : 1;
 
 	uint8 bWanderPathAfterExitingCar : 1;
-	uint8 m_ped_flagF2 : 1;
-	uint8 m_ped_flagF4 : 1; // Unfinished feature from VC, probably bDontDragMeOutCar
+	uint8 bIsLeader : 1;
+	uint8 bDontDragMeOutCar : 1;
 	uint8 m_ped_flagF8 : 1;
 	uint8 bWillBeQuickJacked : 1;
 	uint8 bCancelEnteringCar : 1; // after door is opened or couldn't be opened due to it's locked
 	uint8 bObstacleShowedUpDuringKillObjective : 1;
 	uint8 bDuckAndCover : 1;
 
-	uint8 bStillOnValidPoly : 1;
-	uint8 m_ped_flagG2 : 1;
-	uint8 m_ped_flagG4 : 1; // bResetWalkAnims?
+	uint8 bStillOnValidPoly : 1; // set if the polygon the ped is on is still valid for collision
+	uint8 bAllowMedicsToReviveMe : 1;
+	uint8 bResetWalkAnims : 1;
 	uint8 bStartWanderPathOnFoot : 1; // exits the car if he's in it, reset after path found
 	uint8 bOnBoat : 1; // not just driver, may be just standing
 	uint8 bBusJacked : 1;
@@ -354,12 +354,12 @@ public:
 
 	uint8 m_ped_flagH1 : 1;
 	uint8 bHitSteepSlope : 1; // has ped collided/is standing on a steep slope (surface type)
-	uint8 m_ped_flagH4 : 1;
+	uint8 bCullExtraFarAway : 1; // special ped only gets culled if it's extra far away (for roadblocks)
 	uint8 bClearObjective : 1;
-	uint8 m_ped_flagH10 : 1; // bTryingToReachDryLand? reset when we landed on something not vehicle and object
+	uint8 bTryingToReachDryLand : 1; // has ped just exited boat and trying to get to dry land
 	uint8 bCollidedWithMyVehicle : 1;
-	uint8 bRichFromMugging : 1; // ped has lots of cash from mugging people - will drop money if someone points gun to him
-	uint8 m_ped_flagH80 : 1;
+	uint8 bRichFromMugging : 1; // ped has lots of cash cause they've been mugging people
+	uint8 bChrisCriminal : 1; // Is a criminal as killed during Chris' police mission (should be counted as such)
 
 	uint8 bShakeFist : 1;  // test shake hand at look entity
 	uint8 bNoCriticalHits : 1; // if set, limbs won't came off
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 3046a58f..de05a738 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -2,6 +2,7 @@
 
 #include "Physical.h"
 #include "AutoPilot.h"
+#include "ModelIndices.h"
 
 class CPed;
 class CFire;
@@ -267,6 +268,7 @@ public:
 
 	bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; }
 	CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); }
+	bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE; }
 	
 	static bool &bWheelsOnlyCheat;
 	static bool &bAllDodosCheat;
diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp
index 50d75516..a915504d 100644
--- a/src/weapons/ProjectileInfo.cpp
+++ b/src/weapons/ProjectileInfo.cpp
@@ -4,4 +4,5 @@
 #include "Projectile.h"
 
 
-WRAPPER bool CProjectileInfo::RemoveIfThisIsAProjectile(CObject *pObject) { EAXJMP(0x55BBD0); }
\ No newline at end of file
+WRAPPER bool CProjectileInfo::RemoveIfThisIsAProjectile(CObject *pObject) { EAXJMP(0x55BBD0); }
+WRAPPER bool CProjectileInfo::IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove) { EAXJMP(0x55BA50); }
diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h
index f4753b28..06ead482 100644
--- a/src/weapons/ProjectileInfo.h
+++ b/src/weapons/ProjectileInfo.h
@@ -6,4 +6,5 @@ class CProjectileInfo
 {
 public:
 	static bool RemoveIfThisIsAProjectile(CObject *pObject);
+	static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
 };
\ No newline at end of file

From 90233baffe1d394b2c9ab5203c828b2e3bf151e9 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Wed, 1 Jan 2020 02:44:13 +0300
Subject: [PATCH 4/9] fix merge

---
 src/core/Fire.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/core/Fire.h b/src/core/Fire.h
index cd6de90c..f74ddabe 100644
--- a/src/core/Fire.h
+++ b/src/core/Fire.h
@@ -42,6 +42,5 @@ public:
 	void RemoveScriptFire(int16);
 	void RemoveAllScriptFires(void);
 	void SetScriptFireAudio(int16, bool);
-	void ExtinguishPoint(CVector, float);
 };
 extern CFireManager &gFireManager;

From 402ecd63052cd3f9c4987d896d6c11e926a6f485 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Wed, 1 Jan 2020 02:55:00 +0300
Subject: [PATCH 5/9] fix merge with upstream

---
 src/control/Script.cpp | 6 +++---
 src/core/Fire.cpp      | 4 ----
 src/core/Fire.h        | 2 +-
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index c08eefe2..2e47b288 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -5294,10 +5294,10 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 	{
 		CollectParameters(&m_nIp, 1);
 		if (ScriptParams[0] != 0){
-			CWorld::Players[CWorld::PlayerInFocus].m_nSwitchTaxiTime = CTimer::GetTimeInMilliseconds();
-			CWorld::Players[CWorld::PlayerInFocus].m_bSwitchTaxi = true;
+			CWorld::Players[CWorld::PlayerInFocus].m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
+			CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = true;
 		}else{
-			CWorld::Players[CWorld::PlayerInFocus].m_bSwitchTaxi = false;
+			CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = false;
 		}
 		return 0;
 	}
diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp
index 5c777eab..f83ad2c8 100644
--- a/src/core/Fire.cpp
+++ b/src/core/Fire.cpp
@@ -5,7 +5,6 @@
 CFireManager &gFireManager = *(CFireManager*)0x8F31D0;
 
 WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); }
-WRAPPER void CFireManager::StartFire(CEntity* entityOnFire, CEntity* culprit, float, uint32) { EAXJMP(0x479590); }
 WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); }
 WRAPPER CFire* CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); }
 
@@ -14,8 +13,6 @@ uint32 CFireManager::GetTotalActiveFires() const
 	return m_nTotalFires;
 }
 
-WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); }
-
 CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance)
 {
 	for (int i = 0; i < MAX_FIREMEN_ATTENDING; i++) {
@@ -52,7 +49,6 @@ CFireManager::ExtinguishPoint(CVector point, float range)
 	}
 }
 
-WRAPPER CFire *CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); }
 WRAPPER void CFireManager::StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32) { EAXJMP(0x479590); }
 WRAPPER void CFireManager::StartFire(CVector, float, uint8) { EAXJMP(0x479500); }
 WRAPPER int32 CFireManager::StartScriptFire(const CVector& pos, CEntity* culprit, float, uint8) { EAXJMP(0x479E60); }
diff --git a/src/core/Fire.h b/src/core/Fire.h
index f74ddabe..9d72179e 100644
--- a/src/core/Fire.h
+++ b/src/core/Fire.h
@@ -35,7 +35,7 @@ public:
 	void Update(void);
 	CFire *FindFurthestFire_NeverMindFireMen(CVector coors, float, float);
 	CFire *FindNearestFire(CVector, float*);
-	uint32 GetTotalActiveFires() const { return m_nTotalFires; }
+	uint32 GetTotalActiveFires() const;
 	void ExtinguishPoint(CVector, float);
 	int32 StartScriptFire(const CVector& pos, CEntity* culprit, float, uint8);
 	bool IsScriptFireExtinguish(int16);

From b307893c9d39132221841287ff3ea98a0d7458a3 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Wed, 1 Jan 2020 15:16:38 +0300
Subject: [PATCH 6/9] bug fix

---
 src/control/Script.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 2e47b288..b3021094 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -5712,7 +5712,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	}
 	case COMMAND_BOAT_STOP:
 	{
-		CollectParameters(&m_nIp, 4);
+		CollectParameters(&m_nIp, 1);
 		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(pVehicle);
 		assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);

From 42ff0f7c586b6700dea7729e9f4e1fa5bd42fc96 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Wed, 1 Jan 2020 23:55:01 +0300
Subject: [PATCH 7/9] bug fixes

---
 src/control/Script.cpp      | 8 ++++----
 src/core/ZoneCull.cpp       | 6 ++++--
 src/objects/Object.cpp      | 2 ++
 src/objects/Object.h        | 2 ++
 src/vehicles/Automobile.cpp | 2 +-
 5 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index b3021094..d1e0f048 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -2544,7 +2544,7 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
 	{
 		CollectParameters(&m_nIp, 4);
 		int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;
-		CObject* pObj = new CObject(mi, 0);
+		CObject* pObj = new CObject(mi, false);
 		pObj->ObjectCreatedBy = MISSION_OBJECT;
 		CVector pos = *(CVector*)&ScriptParams[1];
 		if (pos.z <= -100.0f)
@@ -5305,8 +5305,8 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 	{
 		CollectParameters(&m_nIp, 4);
 		int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;
-		CObject* pObj = new CObject(mi, 0);
-		pObj->ObjectCreatedBy = MISSION_OBJECT;
+		CObject* pObj = new CObject(mi, false);
+;		pObj->ObjectCreatedBy = MISSION_OBJECT;
 		CVector pos = *(CVector*)&ScriptParams[1];
 		if (pos.z <= -100.0f)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -5380,7 +5380,7 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 	case COMMAND_ADD_PARTICLE_EFFECT:
 	{
 		CollectParameters(&m_nIp, 5);
-		CVector pos = *(CVector*)&ScriptParams[0];
+		CVector pos = *(CVector*)&ScriptParams[1];
 		if (pos.z <= 100.0f)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0);
diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp
index 6d33a1cf..6b04c213 100644
--- a/src/core/ZoneCull.cpp
+++ b/src/core/ZoneCull.cpp
@@ -134,14 +134,16 @@ CCullZones::FindAttributesForCoors(CVector coors, int32 *wantedLevel)
 	int i;
 	int32 attribs;
 
+	if (wantedLevel)
+		*wantedLevel = 0;
 	attribs = 0;
 	for(i = 0; i < NumAttributeZones; i++)
 		if(coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&
 		   coors.y >= aAttributeZones[i].miny && coors.y <= aAttributeZones[i].maxy &&
 		   coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz){
 			attribs |= aAttributeZones[i].attributes;
-			if(wantedLevel && *wantedLevel <= aAttributeZones[i].wantedLevel)
-				*wantedLevel = aAttributeZones[i].wantedLevel;
+			if(wantedLevel)
+				*wantedLevel = max(*wantedLevel, aAttributeZones[i].wantedLevel);
 		}
 	return attribs;
 }
diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp
index 9d531c9c..de98a2d6 100644
--- a/src/objects/Object.cpp
+++ b/src/objects/Object.cpp
@@ -9,6 +9,8 @@
 WRAPPER void CObject::ObjectDamage(float amount) { EAXJMP(0x4BB240); }
 WRAPPER void CObject::DeleteAllTempObjectInArea(CVector, float) { EAXJMP(0x4BBED0); }
 WRAPPER void CObject::Init(void) { EAXJMP(0x4BAEC0); }
+WRAPPER void CObject::ProcessControl(void) { EAXJMP(0x4BB040); }
+WRAPPER void CObject::Teleport(CVector) { EAXJMP(0x4BBDA0); }
 
 int16 &CObject::nNoTempObjects = *(int16*)0x95CCA2;
 int16 &CObject::nBodyCastHealth = *(int16*)0x5F7D4C;	// 1000
diff --git a/src/objects/Object.h b/src/objects/Object.h
index 47af4fbf..c07bb233 100644
--- a/src/objects/Object.h
+++ b/src/objects/Object.h
@@ -71,6 +71,8 @@ public:
 	CObject(int32, bool);
 	~CObject(void);
 
+	void ProcessControl(void);
+	void Teleport(CVector);
 	void Render(void);
 	bool SetupLighting(void);
 	void RemoveLighting(bool reset);
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index cfcfcf65..ddb75d84 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -1090,7 +1090,7 @@ CAutomobile::ProcessControl(void)
 
 
 	if(m_bSirenOrAlarm && (CTimer::GetFrameCounter()&7) == 5 &&
-	   UsesSiren(GetModelIndex()) && GetModelIndex() != MI_RCBANDIT)
+	   UsesSiren(GetModelIndex()) && GetModelIndex() != MI_MRWHOOP)
 		CCarAI::MakeWayForCarWithSiren(this);
 
 

From 0723dade768ad6118db00c7bb908f39949fb7970 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Fri, 3 Jan 2020 19:48:13 +0300
Subject: [PATCH 8/9] script 800-899

---
 src/control/CarCtrl.cpp    |    2 +-
 src/control/CarCtrl.h      |    1 +
 src/control/Garages.cpp    |   25 +-
 src/control/Garages.h      |  111 +++-
 src/control/Population.cpp |    7 +
 src/control/Population.h   |    1 +
 src/control/Record.cpp     |    4 +-
 src/control/Record.h       |    2 +
 src/control/Script.cpp     | 1246 ++++++++++++++++++++++++++++++++----
 src/control/Script.h       |    3 +
 src/core/Camera.cpp        |   10 +
 src/core/Camera.h          |    3 +
 src/core/Explosion.cpp     |    1 +
 src/core/Explosion.h       |    1 +
 src/core/Stats.cpp         |    1 +
 src/core/Stats.h           |    1 +
 src/core/World.cpp         |    8 +-
 src/core/World.h           |    6 +
 src/core/config.h          |    1 +
 src/peds/Ped.h             |    2 +-
 src/peds/PlayerPed.cpp     |   12 +
 src/peds/PlayerPed.h       |    1 +
 src/weapons/BulletInfo.cpp |    5 +
 src/weapons/BulletInfo.h   |    7 +
 24 files changed, 1329 insertions(+), 132 deletions(-)
 create mode 100644 src/weapons/BulletInfo.cpp
 create mode 100644 src/weapons/BulletInfo.h

diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index cf77b5a4..80cb8211 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -953,7 +953,7 @@ void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, f
 						if (visibilityAngle > PI)
 							visibilityAngle = TWOPI - visibilityAngle;
 						if (visibilityAngle < HALFPI || pVehicle->m_nCarHornTimer){
-							/* if ped sees the danger of if car horn is on */
+							/* if ped sees the danger or if car horn is on */
 							pPed->SetFlee(pVehicle, 2000);
 							pPed->bUsePedNodeSeek = false;
 							pPed->SetMoveState(PEDMOVE_RUN);
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index 44634e39..925552b5 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -4,6 +4,7 @@
 #include "Vehicle.h"
 
 #define GAME_SPEED_TO_METERS_PER_SECOND 50.0f
+#define METERS_PER_SECOND_TO_GAME_SPEED (1.0f / GAME_SPEED_TO_METERS_PER_SECOND)
 #define GAME_SPEED_TO_CARAI_SPEED 60.0f
 #define TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING 2500
 
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index ca1dae1b..dc77a154 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -6,7 +6,9 @@
 #include "Timer.h"
 #include "Font.h"
 #include "Messages.h"
+#include "PlayerPed.h"
 #include "Text.h"
+#include "World.h"
 
 int32 &CGarages::BankVansCollected = *(int32 *)0x8F1B34;
 bool &CGarages::BombsAreFree = *(bool *)0x95CD7A;
@@ -25,6 +27,8 @@ bool &CGarages::PlayerInGarage = *(bool *)0x95CD83;
 int32 &CGarages::PoliceCarsCollected = *(int32 *)0x941444;
 uint32 &CGarages::GarageToBeTidied = *(uint32 *)0x623570;
 
+CGarage(&CGarages::Garages)[NUM_GARAGES] = *(CGarage(*)[NUM_GARAGES])(uintptr*)0x72BCD0;
+
 WRAPPER void CGarages::Init(void) { EAXJMP(0x421C60); }
 WRAPPER void CGarages::Update(void) { EAXJMP(0x421E40); }
 
@@ -86,8 +90,27 @@ int32 CGarages::QueryCarsCollected(int16 garage)
 	return 0;
 }
 
+void CGarages::GivePlayerDetonator()
+{
+	FindPlayerPed()->GiveWeapon(WEAPONTYPE_DETONATOR, 1);
+	FindPlayerPed()->m_weapons[FindPlayerPed()->GetWeaponSlot(WEAPONTYPE_DETONATOR)].m_eWeaponState = WEAPONSTATE_READY;
+}
+
 WRAPPER bool CGarages::HasThisCarBeenCollected(int16 garage, uint8 id) { EAXJMP(0x426D50); }
-WRAPPER void CGarages::ChangeGarageType(int16 garage, int8 type) { EAXJMP(0x4222A0); }
+WRAPPER void CGarages::ChangeGarageType(int16 garage, eGarageType type) { EAXJMP(0x4222A0); }
+WRAPPER bool CGarages::HasResprayHappened(int16 garage) { EAXJMP(0x4274F0); }
+
+void CGarage::OpenThisGarage()
+{
+	if (m_eGarageState == GS_FULLYCLOSED || m_eGarageState == GS_CLOSING || m_eGarageState == GS_CLOSEDCONTAINSCAR)
+		m_eGarageState = GS_OPENING;
+}
+
+void CGarage::CloseThisGarage()
+{
+	if (m_eGarageState == GS_OPENED || m_eGarageState == GS_OPENING)
+		m_eGarageState = GS_CLOSING;
+}
 
 #if 0
 WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); }
diff --git a/src/control/Garages.h b/src/control/Garages.h
index f9421ae8..945922fe 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -1,7 +1,113 @@
 #pragma once
+#include "Automobile.h"
+#include "audio_enums.h"
+#include "config.h"
 
 class CVehicle;
 
+enum eGarageState : int8
+{
+	GS_FULLYCLOSED,
+	GS_OPENED,
+	GS_CLOSING,
+	GS_OPENING,
+	GS_OPENEDCONTAINSCAR,
+	GS_CLOSEDCONTAINSCAR,
+	GS_AFTERDROPOFF,
+};
+
+enum eGarageType : int8
+{
+	GARAGE_NONE,
+	GARAGE_MISSION,
+	GARAGE_BOMBSHOP1,
+	GARAGE_BOMBSHOP2,
+	GARAGE_BOMBSHOP3,
+	GARAGE_RESPRAY,
+	GARAGE_COLLECTORSITEMS,
+	GARAGE_COLLECTSPECIFICCARS,
+	GARAGE_COLLECTCARS_1,
+	GARAGE_COLLECTCARS_2,
+	GARAGE_COLLECTCARS_3,
+	GARAGE_FORCARTOCOMEOUTOF,
+	GARAGE_60SECONDS,
+	GARAGE_CRUSHER,
+	GARAGE_MISSION_KEEPCAR,
+	GARAGE_FOR_SCRIPT_TO_OPEN,
+	GARAGE_HIDEOUT_ONE,
+	GARAGE_HIDEOUT_TWO,
+	GARAGE_HIDEOUT_THREE,
+	GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE,
+	GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR,
+	GARAGE_MISSION_KEEPCAR_REMAINCLOSED,
+};
+
+class CStoredCar
+{
+	int32 m_nModelIndex;
+	CVector m_vecPos;
+	CVector m_vecAngle;
+	int32 m_bBulletproof : 1;
+	int32 m_bFireproof : 1;
+	int32 m_bExplosionproof : 1;
+	int32 m_bCollisionproof : 1;
+	int32 m_bMeleeproof : 1;
+	int8 m_nPrimaryColor;
+	int8 m_nSecondaryColor;
+	int8 m_nRadioStation;
+	int8 m_nVariationA;
+	int8 m_nVariationB;
+	int8 m_nCarBombType;
+};
+
+static_assert(sizeof(CStoredCar) == 0x28, "CStoredCar");
+
+class CGarage
+{
+	eGarageType m_eGarageType;
+	eGarageState m_eGarageState;
+	char field_2;
+	char m_bClosingWithoutTargetCar;
+	char m_bDeactivated;
+	char m_bResprayHappened;
+	char field_6;
+	char field_7;
+	int m_nTargetModelIndex;
+	CEntity *m_pDoor1;
+	CEntity *m_pDoor2;
+	char m_bDoor1PoolIndex;
+	char m_bDoor2PoolIndex;
+	char m_bIsDoor1Object;
+	char m_bIsDoor2Object;
+	char field_24;
+	char m_bRotatedDoor;
+	char m_bCameraFollowsPlayer;
+	char field_27;
+	CVector m_vecInf;
+	CVector m_vecSup;
+	float m_fDoorPos;
+	float m_fDoorHeight;
+	float m_fDoor1X;
+	float m_fDoor1Y;
+	float m_fDoor2X;
+	float m_fDoor2Y;
+	float m_fDoor1Z;
+	float m_fDoor2Z;
+	int m_nDoorOpenTime;
+	char m_bCollectedCarsState;
+	char field_89;
+	char field_90;
+	char field_91;
+	CVehicle *m_pTarget;
+	int field_96;
+	CStoredCar m_sStoredCar;
+public:
+	void OpenThisGarage();
+	void CloseThisGarage();
+};
+
+static_assert(sizeof(CGarage) == 140, "CGarage");
+
 class CGarages
 {
 public:
@@ -21,6 +127,7 @@ public:
 	static bool &PlayerInGarage;
 	static int32 &PoliceCarsCollected;
 	static uint32 &GarageToBeTidied;
+	static CGarage(&Garages)[NUM_GARAGES];
 
 public:
 	static bool IsModelIndexADoor(uint32 id);
@@ -39,5 +146,7 @@ public:
 	static void DeActivateGarage(int16);
 	static int32 QueryCarsCollected(int16);
 	static bool HasThisCarBeenCollected(int16, uint8);
-	static void ChangeGarageType(int16, int8); //TODO: eGarageType
+	static void ChangeGarageType(int16, eGarageType);
+	static bool HasResprayHappened(int16);
+	static void GivePlayerDetonator();
 };
diff --git a/src/control/Population.cpp b/src/control/Population.cpp
index a98721ac..d7e32dbf 100644
--- a/src/control/Population.cpp
+++ b/src/control/Population.cpp
@@ -1,6 +1,7 @@
 #include "common.h"
 #include "patcher.h"
 #include "Game.h"
+#include "General.h"
 #include "World.h"
 #include "Entity.h"
 #include "Population.h"
@@ -79,6 +80,12 @@ CPopulation::RemovePed(CEntity* ent)
 	delete ent;
 }
 
+int32
+CPopulation::ChooseCivilianOccupation(int32 group)
+{
+	return ms_pPedGroups[group].models[CGeneral::GetRandomNumberInRange(0, 8)];
+}
+
 STARTPATCHES
 InjectHook(0x4F3770, CPopulation::Initialise, PATCH_JUMP);
 ENDPATCHES
\ No newline at end of file
diff --git a/src/control/Population.h b/src/control/Population.h
index 006e6104..572d6f58 100644
--- a/src/control/Population.h
+++ b/src/control/Population.h
@@ -47,4 +47,5 @@ public:
 	static CPed *AddPedInCar(CVehicle *vehicle);
 	static bool IsPointInSafeZone(CVector *coors);
 	static void RemovePed(CEntity* ent);
+	static int32 ChooseCivilianOccupation(int32);
 };
diff --git a/src/control/Record.cpp b/src/control/Record.cpp
index 802ca516..9db9dea1 100644
--- a/src/control/Record.cpp
+++ b/src/control/Record.cpp
@@ -10,4 +10,6 @@ WRAPPER void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0
 
 WRAPPER void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4347F0); }
 WRAPPER void CRecordDataForChase::ProcessControlCars(void) { EAXJMP(0x435540); }
-WRAPPER void CRecordDataForChase::SaveOrRetrieveCarPositions(void) { EAXJMP(0x434B20); }
\ No newline at end of file
+WRAPPER void CRecordDataForChase::SaveOrRetrieveCarPositions(void) { EAXJMP(0x434B20); }
+WRAPPER void CRecordDataForChase::StartChaseScene(float) { EAXJMP(0x435690); }
+WRAPPER void CRecordDataForChase::CleanUpChaseScene() { EAXJMP(0x4357C0); }
diff --git a/src/control/Record.h b/src/control/Record.h
index 9f396c96..f36c2fd2 100644
--- a/src/control/Record.h
+++ b/src/control/Record.h
@@ -14,6 +14,8 @@ public:
 	static void SaveOrRetrieveDataForThisFrame(void);
 	static void ProcessControlCars(void);
 	static void SaveOrRetrieveCarPositions(void);
+	static void StartChaseScene(float);
+	static void CleanUpChaseScene();
 };
 
 
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index d1e0f048..34d22897 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -5,7 +5,9 @@
 #include "ScriptCommands.h"
 
 #include "Boat.h"
+#include "BulletInfo.h"
 #include "Camera.h"
+#include "CarAI.h"
 #include "CarCtrl.h"
 #include "CarGen.h"
 #include "CivilianPed.h"
@@ -32,12 +34,14 @@
 #include "PedRoutes.h"
 #include "Phones.h"
 #include "Pickups.h"
+#include "Plane.h"
 #include "PlayerInfo.h"
 #include "PlayerPed.h"
 #include "PointLights.h"
 #include "Pools.h"
 #include "Population.h"
 #include "ProjectileInfo.h"
+#include "Record.h"
 #include "Remote.h"
 #include "Restart.h"
 #include "Replay.h"
@@ -51,6 +55,9 @@
 #include "World.h"
 #include "Zones.h"
 
+#define PICKUP_PLACEMENT_OFFSET 0.5f
+#define PED_FIND_Z_OFFSET 5.0f
+
 uint8 (&CTheScripts::ScriptSpace)[SIZE_SCRIPT_SPACE] = *(uint8(*)[SIZE_SCRIPT_SPACE])*(uintptr*)0x74B248;
 CRunningScript(&CTheScripts::ScriptsArray)[MAX_NUM_SCRIPTS] = *(CRunningScript(*)[MAX_NUM_SCRIPTS])*(uintptr*)0x6F5C08;
 int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200;
@@ -1269,7 +1276,7 @@ int8 CRunningScript::ProcessCommandsFrom0To99(int32 command)
 		CWorld::Players[index].m_pPed->CharCreatedBy = MISSION_CHAR;
 		CPlayerPed::DeactivatePlayerPed(index);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pos.z += CWorld::Players[index].m_pPed->GetDistanceFromCentreOfMassToBaseOfModel();
 		CWorld::Players[index].m_pPed->GetPosition() = pos;
@@ -1296,7 +1303,7 @@ int8 CRunningScript::ProcessCommandsFrom0To99(int32 command)
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[1];
 		int index = ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CPlayerPed* ped = CWorld::Players[index].m_pPed;
 		if (!ped->bInVehicle) {
@@ -1319,18 +1326,17 @@ int8 CRunningScript::ProcessCommandsFrom0To99(int32 command)
 	{
 		CollectParameters(&m_nIp, 6);
 		CPlayerPed* ped = CWorld::Players[ScriptParams[0]].m_pPed;
-		float x1, y1, x2, y2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		x2 = *(float*)&ScriptParams[3];
-		y2 = *(float*)&ScriptParams[4];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float x2 = *(float*)&ScriptParams[3];
+		float y2 = *(float*)&ScriptParams[4];
 		if (!ped->bInVehicle)
 			UpdateCompareFlag(ped->IsWithinArea(x1, y1, x2, y2));
 		else
 			UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, x2, y2));
 		if (!ScriptParams[5])
 			return 0;
-		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
 		if (CTheScripts::DbgFlag)
 			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
 		return 0;
@@ -1339,13 +1345,12 @@ int8 CRunningScript::ProcessCommandsFrom0To99(int32 command)
 	{
 		CollectParameters(&m_nIp, 8);
 		CPlayerPed* ped = CWorld::Players[ScriptParams[0]].m_pPed;
-		float x1, y1, z1, x2, y2, z2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		z1 = *(float*)&ScriptParams[3];
-		x2 = *(float*)&ScriptParams[4];
-		y2 = *(float*)&ScriptParams[5];
-		z2 = *(float*)&ScriptParams[6];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float z1 = *(float*)&ScriptParams[3];
+		float x2 = *(float*)&ScriptParams[4];
+		float y2 = *(float*)&ScriptParams[5];
+		float z2 = *(float*)&ScriptParams[6];
 		if (ped->bInVehicle)
 			UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));
 		else
@@ -1728,7 +1733,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		ped->bRespondsToThreats = false;
 		ped->bAllowMedicsToReviveMe = false;
 		CVector pos = *(CVector*)&ScriptParams[2];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pos.z += 1.0f;
 		ped->GetPosition() = pos;
@@ -1790,7 +1795,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
 		assert(ped);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		ped->ClearAll();
 		ped->SetFollowPath(pos);
@@ -1836,7 +1841,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		else
 			vehicle = nil;
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		/* The following block was once again written
 		 * by someone not familiar with virtual functions.
@@ -1867,7 +1872,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		 * assert(ped);
 		 * CEntity* entityToMove = ped->bInVehicle ? ped->m_pMyVehicle : ped;
 		 * CVector pos = *(CVector*)&ScriptParams[1];
-		 * if (pos.z <= -100.0f)
+		 * if (pos.z <= MAP_Z_LOW_LIMIT)
 		 *	pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		 * pos.z += entityToMove->GetDistanceFromCentreOfMassToBaseOfModel();
 		 * entityToMove->Teleport(pos);
@@ -1893,18 +1898,17 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 			vehicle = ped->m_pMyVehicle;
 		else
 			vehicle = nil;
-		float x1, y1, x2, y2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		x2 = *(float*)&ScriptParams[3];
-		y2 = *(float*)&ScriptParams[4];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float x2 = *(float*)&ScriptParams[3];
+		float y2 = *(float*)&ScriptParams[4];
 		if (vehicle)
 			UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, x2, y2));
 		else
 			UpdateCompareFlag(ped->IsWithinArea(x1, y1, x2, y2));
 		if (!ScriptParams[5])
 			return 0;
-		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
 		if (CTheScripts::DbgFlag)
 			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
 		return 0;
@@ -1919,13 +1923,12 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 			vehicle = ped->m_pMyVehicle;
 		else
 			vehicle = nil;
-		float x1, y1, z1, x2, y2, z2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		z1 = *(float*)&ScriptParams[3];
-		x2 = *(float*)&ScriptParams[4];
-		y2 = *(float*)&ScriptParams[5];
-		z2 = *(float*)&ScriptParams[6];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float z1 = *(float*)&ScriptParams[3];
+		float x2 = *(float*)&ScriptParams[4];
+		float y2 = *(float*)&ScriptParams[5];
+		float z2 = *(float*)&ScriptParams[6];
 		if (vehicle)
 			UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));
 		else
@@ -1944,7 +1947,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		if (CModelInfo::IsBoatModel(ScriptParams[0])) {
 			CBoat* boat = new CBoat(ScriptParams[0], MISSION_VEHICLE);
 			CVector pos = *(CVector*)&ScriptParams[1];
-			if (pos.z <= -100.0f)
+			if (pos.z <= MAP_Z_LOW_LIMIT)
 				pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 			pos.z += boat->GetDistanceFromCentreOfMassToBaseOfModel();
 			boat->GetPosition() = pos;
@@ -1962,7 +1965,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 			if (!CModelInfo::IsBikeModel(ScriptParams[0]))
 				car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE);
 			CVector pos = *(CVector*)&ScriptParams[1];
-			if (pos.z <= -100.0f)
+			if (pos.z <= MAP_Z_LOW_LIMIT)
 				pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 			pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();
 			car->GetPosition() = pos;
@@ -2006,7 +2009,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(car);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();
 		if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(car, pos, false))
@@ -2054,7 +2057,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(car);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();
 		car->bIsStatic = false;
@@ -2137,15 +2140,14 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		CollectParameters(&m_nIp, 6);
 		CVehicle* vehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(vehicle);
-		float x1, y1, x2, y2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		x2 = *(float*)&ScriptParams[3];
-		y2 = *(float*)&ScriptParams[4];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float x2 = *(float*)&ScriptParams[3];
+		float y2 = *(float*)&ScriptParams[4];
 		UpdateCompareFlag(vehicle->IsWithinArea(x1, y1, x2, y2));
 		if (!ScriptParams[5])
 			return 0;
-		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
 		if (CTheScripts::DbgFlag)
 			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
 		return 0;
@@ -2155,13 +2157,12 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
 		CollectParameters(&m_nIp, 8);
 		CVehicle* vehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(vehicle);
-		float x1, y1, z1, x2, y2, z2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		z1 = *(float*)&ScriptParams[3];
-		x2 = *(float*)&ScriptParams[4];
-		y2 = *(float*)&ScriptParams[5];
-		z2 = *(float*)&ScriptParams[6];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float z1 = *(float*)&ScriptParams[3];
+		float x2 = *(float*)&ScriptParams[4];
+		float y2 = *(float*)&ScriptParams[5];
+		float z2 = *(float*)&ScriptParams[6];
 		UpdateCompareFlag(vehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));
 		if (!ScriptParams[7])
 			return 0;
@@ -2547,7 +2548,7 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
 		CObject* pObj = new CObject(mi, false);
 		pObj->ObjectCreatedBy = MISSION_OBJECT;
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pos.z += pObj->GetDistanceFromCentreOfMassToBaseOfModel();
 		pObj->GetPosition() = pos;
@@ -2592,7 +2593,7 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
 	{
 		CollectParameters(&m_nIp, 5);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4]), MI_RCBANDIT);
 		return 0;
@@ -2801,7 +2802,7 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[1];
 		CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		if (pPlayer->m_pPed->bInVehicle){
 			assert(pPlayer->m_pPed->m_pMyVehicle);
@@ -2900,16 +2901,15 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CollectParameters(&m_nIp, 6);
 		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(pVehicle);
-		float x1, y1, x2, y2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		x2 = *(float*)&ScriptParams[3];
-		y2 = *(float*)&ScriptParams[4];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float x2 = *(float*)&ScriptParams[3];
+		float y2 = *(float*)&ScriptParams[4];
 		UpdateCompareFlag(pVehicle->m_status == STATUS_WRECKED &&
 			pVehicle->IsWithinArea(x1, y1, x2, y2));
 		if (!ScriptParams[5])
 			return 0;
-		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
 		if (CTheScripts::DbgFlag)
 			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
 		return 0;
@@ -2919,13 +2919,12 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CollectParameters(&m_nIp, 8);
 		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(pVehicle);
-		float x1, y1, z1, x2, y2, z2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		z1 = *(float*)&ScriptParams[3];
-		x2 = *(float*)&ScriptParams[4];
-		y2 = *(float*)&ScriptParams[5];
-		z2 = *(float*)&ScriptParams[6];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float z1 = *(float*)&ScriptParams[3];
+		float x2 = *(float*)&ScriptParams[4];
+		float y2 = *(float*)&ScriptParams[5];
+		float z2 = *(float*)&ScriptParams[6];
 		UpdateCompareFlag(pVehicle->m_status == STATUS_WRECKED &&
 			pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));
 		if (!ScriptParams[7])
@@ -3146,7 +3145,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 	{
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		TheCamera.TakeControlNoEntity(pos, ScriptParams[3], 1);
 		return 0;
@@ -3200,7 +3199,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 	{
 		CollectParameters(&m_nIp, 5);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		// Useless call
 		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
@@ -3228,7 +3227,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
 		float angle = *(float*)&ScriptParams[3];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CRestart::AddHospitalRestartPoint(pos, angle);
 		return 0;
@@ -3238,7 +3237,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
 		float angle = *(float*)&ScriptParams[3];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CRestart::AddPoliceRestartPoint(pos, angle);
 		return 0;
@@ -3248,7 +3247,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
 		float angle = *(float*)&ScriptParams[3];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CRestart::OverrideNextRestart(pos, angle);
 		return 0;
@@ -3477,7 +3476,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		// Useless call
 		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
@@ -3491,7 +3490,7 @@ int8 CRunningScript::ProcessCommandsFrom300To399(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		// Useless call
 		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
@@ -3629,7 +3628,7 @@ int8 CRunningScript::ProcessCommandsFrom400To499(int32 command)
 		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
 		assert(pPed);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pPed->bScriptObjectiveCompleted = false;
 		pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos);
@@ -3794,7 +3793,7 @@ int8 CRunningScript::ProcessCommandsFrom400To499(int32 command)
 		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
 		assert(pObject);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pObject->Teleport(pos);
 		CTheScripts::ClearSpaceForMissionEntity(pos, pObject);
@@ -4574,9 +4573,8 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
 		if (model < 0)
 			model = CTheScripts::UsedObjectArray[-model].index;
 		CVector pos = *(CVector*)&ScriptParams[2];
-		if (pos.z <= -100.0f)
-			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
-		// unused?
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
 		CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
 		ScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], 0);
 		StoreParameters(&m_nIp, 1);
@@ -5118,7 +5116,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
 	{
 		CollectParameters(&m_nIp, 9);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CCoronas::RegisterCorona((uint32)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8],
 			255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f);
@@ -5149,7 +5147,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command)
 	{
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CRestart::OverrideNextRestart(pos, *(float*)&ScriptParams[3]);
 		if (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING) //TODO: enum
@@ -5308,7 +5306,7 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 		CObject* pObj = new CObject(mi, false);
 ;		pObj->ObjectCreatedBy = MISSION_OBJECT;
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pObj->GetPosition() = pos;
 		pObj->SetOrientation(0.0f, 0.0f, 0.0f);
@@ -5381,7 +5379,7 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 	{
 		CollectParameters(&m_nIp, 5);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= 100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0);
 		return 0;
@@ -5433,7 +5431,7 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 	{
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
 		int id = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);
@@ -5446,7 +5444,7 @@ int8 CRunningScript::ProcessCommandsFrom600To699(int32 command)
 	{
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
 		int id = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
@@ -5559,7 +5557,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)];
 		*(CVector*)&ScriptParams[0] = pNode->pos;
@@ -5570,7 +5568,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)];
 		*(CVector*)&ScriptParams[0] = pNode->pos;
@@ -5583,7 +5581,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
 		assert(pVehicle);
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
 		if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pos, false))
@@ -5614,7 +5612,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 5);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CPacManPickups::StartPacManScramble(pos, *(float*)&ScriptParams[3], ScriptParams[4]);
 		return 0;
@@ -5671,7 +5669,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		ScriptParams[0] = gFireManager.StartScriptFire(pos, nil, 0.8f, 1);
 		StoreParameters(&m_nIp, 1);
@@ -5701,7 +5699,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 		assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);
 		CBoat* pBoat = (CBoat*)pVehicle;
 		CVector pos = *(CVector*)&ScriptParams[1];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false);
 		pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS;
 		pBoat->AutoPilot.m_vecDestinationCoors = pos;
@@ -5728,15 +5726,14 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 		CollectParameters(&m_nIp, 6);
 		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
 		assert(pPed);
-		float x1, y1, x2, y2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		x2 = *(float*)&ScriptParams[3];
-		y2 = *(float*)&ScriptParams[4];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float x2 = *(float*)&ScriptParams[3];
+		float y2 = *(float*)&ScriptParams[4];
 		UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
 		if (!ScriptParams[5])
 			return 0;
-		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
 		if (CTheScripts::DbgFlag)
 			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
 		return 0;
@@ -5746,15 +5743,14 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 		CollectParameters(&m_nIp, 6);
 		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
 		assert(pPed);
-		float x1, y1, x2, y2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		x2 = *(float*)&ScriptParams[3];
-		y2 = *(float*)&ScriptParams[4];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float x2 = *(float*)&ScriptParams[3];
+		float y2 = *(float*)&ScriptParams[4];
 		UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));
 		if (!ScriptParams[5])
 			return 0;
-		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f);
+		CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);
 		if (CTheScripts::DbgFlag)
 			CTheScripts::DrawDebugSquare(x1, y1, x2, y2);
 		return 0;
@@ -5782,7 +5778,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
+		if (pos.z <= MAP_Z_LOW_LIMIT)
 			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
 		CPacManPickups::GenerateOnePMPickUp(pos);
 		return 0;
@@ -5801,11 +5797,10 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 		CollectParameters(&m_nIp, 4);
 		int ped_handle = -1;
 		CVector pos = FindPlayerCoors();
-		float x1, y1, x2, y2;
-		x1 = *(float*)&ScriptParams[1];
-		y1 = *(float*)&ScriptParams[2];
-		x2 = *(float*)&ScriptParams[3];
-		y2 = *(float*)&ScriptParams[4];
+		float x1 = *(float*)&ScriptParams[1];
+		float y1 = *(float*)&ScriptParams[2];
+		float x2 = *(float*)&ScriptParams[3];
+		float y2 = *(float*)&ScriptParams[4];
 		int i = CPools::GetPedPool()->GetSize();
 		while (--i && ped_handle == -1){
 			CPed* pPed = CPools::GetPedPool()->GetSlot(i);
@@ -5829,9 +5824,9 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 				continue;
 			if (!pPed->IsWithinArea(x1, y1, x2, y2))
 				continue;
-			if (pos.z - 5.0f > pPed->GetPosition().z)
+			if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
 				continue;
-			if (pos.z + 5.0f < pPed->GetPosition().z)
+			if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
 				continue;
 			ped_handle = CPools::GetPedPool()->GetIndex(pPed);
 			CTheScripts::LastRandomPedId = ped_handle;
@@ -5878,9 +5873,9 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 				continue;
 			if (!CTheZones::PointLiesWithinZone(pPed->GetPosition(), pZone))
 				continue;
-			if (pos.z - 5.0f > pPed->GetPosition().z)
+			if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
 				continue;
-			if (pos.z + 5.0f < pPed->GetPosition().z)
+			if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
 				continue;
 			ped_handle = CPools::GetPedPool()->GetIndex(pPed);
 			CTheScripts::LastRandomPedId = ped_handle;
@@ -5922,8 +5917,8 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 4);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
-			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
 		CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
 		ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_MONEY, PICKUP_MONEY, ScriptParams[3]);
 		StoreParameters(&m_nIp, 1);
@@ -5993,8 +5988,8 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
-			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
 		CPickups::GenerateNewOne(pos, MI_COLLECTABLE1, PICKUP_COLLECTABLE1, 0);
 		return 0;
 	}
@@ -6058,8 +6053,8 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
-			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
 		CPickups::GenerateNewOne(pos, MI_CARMINE, PICKUP_MINE_INACTIVE, 0);
 		return 0;
 	}
@@ -6067,8 +6062,8 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	{
 		CollectParameters(&m_nIp, 3);
 		CVector pos = *(CVector*)&ScriptParams[0];
-		if (pos.z <= -100.0f)
-			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + 0.5f;
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
 		CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0);
 		return 0;
 	}
@@ -6144,7 +6139,7 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 	}
 	case COMMAND_CHANGE_GARAGE_TYPE:
 		CollectParameters(&m_nIp, 2);
-		CGarages::ChangeGarageType(ScriptParams[0], ScriptParams[1]);
+		CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1]);
 		return 0;
 	case COMMAND_ACTIVATE_CRUSHER_CRANE:
 	{
@@ -6400,112 +6395,1085 @@ int8 CRunningScript::ProcessCommandsFrom700To799(int32 command)
 }
 #endif
 
-#if 1
+#if 0
 WRAPPER int8 CRunningScript::ProcessCommandsFrom800To899(int32 command) { EAXJMP(0x448240); }
 #else
 int8 CRunningScript::ProcessCommandsFrom800To899(int32 command)
 {
+	CMatrix tmp_matrix;
 	switch (command) {
 	case COMMAND_IS_CHAR_IN_PLAYERS_GROUP:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		CPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed;
+		assert(pPed);
+		assert(pLeader);
+		UpdateCompareFlag(pPed->m_leader == pLeader);
+		return 0;
+	}
 	case COMMAND_EXPLODE_CHAR_HEAD:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		if (pPed->m_nPedState == PED_DRIVING) {
+			pPed->SetDead();
+			if (!pPed->IsPlayer())
+				pPed->FlagToDestroyWhenNextProcessed();
+		}
+		else if (CGame::nastyGame && pPed->IsPedInControl()) {
+			RwMatrix tmp_rw;
+			CPedIK::GetWorldMatrix(pPed->m_pFrames[PED_HEAD]->frame, &tmp_rw);
+			pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, tmp_rw.pos, true);
+		}
+		else {
+			pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+		}
+		return 0;
+	}
 	case COMMAND_EXPLODE_PLAYER_HEAD:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		if (CGame::nastyGame) {
+			RwMatrix tmp_rw;
+			CPedIK::GetWorldMatrix(pPed->m_pFrames[PED_HEAD]->frame, &tmp_rw);
+			pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, tmp_rw.pos, true);
+		}
+		else {
+			pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+		}
+		return 0;
+	}
 	case COMMAND_ANCHOR_BOAT:
+	{
+		CollectParameters(&m_nIp, 2);
+		CBoat* pBoat = (CBoat*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pBoat && pBoat->m_vehType == VEHICLE_TYPE_BOAT);
+		pBoat->m_bIsAnchored = (ScriptParams[1] == 0);
+		return 0;
+	}
 	case COMMAND_SET_ZONE_GROUP:
+	{
+		char zone[8];
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
+		m_nIp += 8;
+		CollectParameters(&m_nIp, 2);
+		int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+		if (zone_id < 0) {
+			printf("Couldn't find zone - %s\n", zone);
+			return 0;
+		}
+		CTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]);
+		return 0;
+	}
 	case COMMAND_START_CAR_FIRE:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		ScriptParams[0] = gFireManager.StartScriptFire(pVehicle->GetPosition(), pVehicle, 0.8f, 1);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_START_CHAR_FIRE:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		ScriptParams[0] = gFireManager.StartScriptFire(pPed->GetPosition(), pPed, 0.8f, 1);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 5);
+		int handle = -1;
+		uint32 i = CPools::GetVehiclePool()->GetSize();
+		float infX = *(float*)&ScriptParams[0];
+		float infY = *(float*)&ScriptParams[1];
+		float supX = *(float*)&ScriptParams[2];
+		float supY = *(float*)&ScriptParams[3];
+		while (i--) {
+			CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+			if (!pVehicle)
+				continue;
+			if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0)
+				continue;
+			if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
+				continue;
+			if (!pVehicle->IsWithinArea(infX, infY, supX, supY))
+				continue;
+			handle = CPools::GetVehiclePool()->GetIndex(pVehicle);
+			pVehicle->VehicleCreatedBy = MISSION_VEHICLE;
+			++CCarCtrl::NumMissionCars;
+			--CCarCtrl::NumRandomCars;
+			if (m_bIsMissionScript)
+				CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
+		}
+		ScriptParams[0] = handle;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE:
+	{
+		char zone[8];
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
+		int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+		if (zone_id != -1)
+			m_nIp += 8;
+		CZone* pZone = CTheZones::GetZone(zone_id);
+		CollectParameters(&m_nIp, 1);
+		int handle = -1;
+		uint32 i = CPools::GetVehiclePool()->GetSize();
+		while (i--) {
+			CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+			if (!pVehicle)
+				continue;
+			if (ScriptParams[0] != pVehicle->GetModelIndex() && ScriptParams[0] >= 0)
+				continue;
+			if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
+				continue;
+			if (!CTheZones::PointLiesWithinZone(pVehicle->GetPosition(), pZone))
+				continue;
+			handle = CPools::GetVehiclePool()->GetIndex(pVehicle);
+			pVehicle->VehicleCreatedBy = MISSION_VEHICLE;
+			++CCarCtrl::NumMissionCars;
+			--CCarCtrl::NumRandomCars;
+			if (m_bIsMissionScript)
+				CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
+		}
+		ScriptParams[0] = handle;
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_HAS_RESPRAY_HAPPENED:
+	{
+		CollectParameters(&m_nIp, 1);
+		UpdateCompareFlag(CGarages::HasResprayHappened(ScriptParams[0]));
+		return 0;
+	}
 	case COMMAND_SET_CAMERA_ZOOM:
+	{
+		CollectParameters(&m_nIp, 1);
+		if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED)
+			TheCamera.SetZoomValueFollowPedScript(ScriptParams[0]);
+		else if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING)
+			TheCamera.SetZoomValueCamStringScript(ScriptParams[0]);
+		return 0;
+	}
 	case COMMAND_CREATE_PICKUP_WITH_AMMO:
+	{
+		CollectParameters(&m_nIp, 6);
+		int16 model = ScriptParams[0];
+		if (model < 0)
+			model = CTheScripts::UsedObjectArray[-model].index;
+		CVector pos = *(CVector*)&ScriptParams[3];
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+		CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+		ScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], ScriptParams[2]);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_SET_CAR_RAM_CAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+		assert(pTarget);
+		CCarAI::TellCarToRamOtherCar(pVehicle, pTarget);
+		return 0;
+	}
 	case COMMAND_SET_CAR_BLOCK_CAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+		assert(pTarget);
+		CCarAI::TellCarToBlockOtherCar(pVehicle, pTarget);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_OBJ_CATCH_TRAIN:
-	case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bScriptObjectiveCompleted = false;
+		pPed->SetObjective(OBJECTIVE_CATCH_TRAIN);
+		return 0;
+	}
+	//case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
 	case COMMAND_SET_PLAYER_NEVER_GETS_TIRED:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
+		pPlayer->m_bInfiniteSprint = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_SET_PLAYER_FAST_RELOAD:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
+		pPlayer->m_bFastReload = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_BLEEDING:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bPedIsBleeding = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_SET_CAR_FUNNY_SUSPENSION:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		// no action
+		return 0;
+	}
 	case COMMAND_SET_CAR_BIG_WHEELS:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+		CAutomobile* pCar = (CAutomobile*)pVehicle;
+		pCar->bBigWheels = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_SET_FREE_RESPRAYS:
+		CollectParameters(&m_nIp, 1);
+		CGarages::RespraysAreFree = (ScriptParams[0] != 0);
+		return 0;
 	case COMMAND_SET_PLAYER_VISIBLE:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		pPed->bIsVisible = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_VISIBLE:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bIsVisible = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_SET_CAR_VISIBLE:
+	{
+		CollectParameters(&m_nIp, 2);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		pVehicle->bIsVisible = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_IS_AREA_OCCUPIED:
+	{
+		CollectParameters(&m_nIp, 11);
+		float infX = *(float*)&ScriptParams[0];
+		float infY = *(float*)&ScriptParams[1];
+		float infZ = *(float*)&ScriptParams[2];
+		float supX = *(float*)&ScriptParams[3];
+		float supY = *(float*)&ScriptParams[4];
+		float supZ = *(float*)&ScriptParams[5];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[3];
+			supX = *(float*)&ScriptParams[0];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[4];
+			supY = *(float*)&ScriptParams[1];
+		}
+		if (infZ > supZ) {
+			infZ = *(float*)&ScriptParams[5];
+			supZ = *(float*)&ScriptParams[2];
+		}
+		int16 total;
+		CWorld::FindObjectsIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil,
+			ScriptParams[7], ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);
+		UpdateCompareFlag(total > 0);
+		return 0;
+	}
 	case COMMAND_START_DRUG_RUN:
+		CPlane::CreateIncomingCesna();
+		return 0;
 	case COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED:
+		UpdateCompareFlag(CPlane::HasCesnaLanded());
+		return 0;
 	case COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN:
+		UpdateCompareFlag(CPlane::HasCesnaBeenDestroyed());
+		return 0;
 	case COMMAND_SAVE_PLAYER_FROM_FIRES:
+		CollectParameters(&m_nIp, 1);
+		gFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f);
+		return 0;
 	case COMMAND_DISPLAY_TEXT:
+	{
+		CollectParameters(&m_nIp, 2);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
+		uint16 len = CMessages::GetWideStringLength(text);
+		for (uint16 i = 0; i < len; i++)
+			CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = text[i];
+		for (uint16 i = len; i < SCRIPT_TEXT_MAX_LENGTH; i++)
+			CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = 0;
+		++CTheScripts::NumberOfIntroTextLinesThisFrame;
+		return 0;
+	}
 	case COMMAND_SET_TEXT_SCALE:
+	{
+		CollectParameters(&m_nIp, 2);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleX = *(float*)&ScriptParams[0];
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleY = *(float*)&ScriptParams[1];
+		return 0;
+	}
 	case COMMAND_SET_TEXT_COLOUR:
+	{
+		CollectParameters(&m_nIp, 4);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sColor =
+			CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);
+		return 0;
+	}
 	case COMMAND_SET_TEXT_JUSTIFY:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bJustify = (ScriptParams[0] != 0);
+		return 0;
+	}
 	case COMMAND_SET_TEXT_CENTRE:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bCentered = (ScriptParams[0] != 0);
+		return 0;
+	}
 	case COMMAND_SET_TEXT_WRAPX:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0];
+		return 0;
+	}
 	case COMMAND_SET_TEXT_CENTRE_SIZE:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0];
+		return 0;
+	}
 	case COMMAND_SET_TEXT_BACKGROUND:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0);
+		return 0;
+	}
 	case COMMAND_SET_TEXT_BACKGROUND_COLOUR:
+	{
+		CollectParameters(&m_nIp, 4);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sBackgroundColor =
+			CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);
+		return 0;
+	}
 	case COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0);
+		return 0;
+	}
 	case COMMAND_SET_TEXT_PROPORTIONAL:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0);
+		return 0;
+	}
 	case COMMAND_SET_TEXT_FONT:
+	{
+		CollectParameters(&m_nIp, 1);
+		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_nFont = ScriptParams[0];
+		return 0;
+	}
 	case COMMAND_INDUSTRIAL_PASSED:
+		CStats::IndustrialPassed = true;
+		DMAudio.PlayRadioAnnouncement(13); //TODO: enum?
+		return 0;
 	case COMMAND_COMMERCIAL_PASSED:
+		CStats::CommercialPassed = true;
+		DMAudio.PlayRadioAnnouncement(14); //TODO: enum?
+		return 0;
 	case COMMAND_SUBURBAN_PASSED:
+		CStats::SuburbanPassed = true;
+		return 0;
 	case COMMAND_ROTATE_OBJECT:
+	{
+		CollectParameters(&m_nIp, 4);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		float heading = LimitAngleOnCircle(
+			RADTODEG(Atan2(-pObject->GetForward().x, pObject->GetForward().y)));
+		float headingTarget = *(float*)&ScriptParams[1];
+		float rotateBy = *(float*)&ScriptParams[2];
+		if (headingTarget == heading) { // using direct comparasion here is fine
+			UpdateCompareFlag(true);
+			return 0;
+		}
+		float angleClockwise = LimitAngleOnCircle(headingTarget - heading);
+		float angleCounterclockwise = LimitAngleOnCircle(heading - headingTarget);
+		float newHeading;
+		if (angleClockwise < angleCounterclockwise)
+			newHeading = rotateBy < angleClockwise ? heading + rotateBy : headingTarget;
+		else
+			newHeading = rotateBy < angleCounterclockwise ? heading - rotateBy : headingTarget;
+		bool obstacleInPath = false;
+		if (ScriptParams[3]) {
+			CVector pos = pObject->GetPosition();
+			tmp_matrix.SetRotateZ(DEGTORAD(newHeading));
+			tmp_matrix.GetPosition() += pos;
+			CColModel* pColModel = pObject->GetColModel();
+			CVector cp1 = tmp_matrix * pColModel->boundingBox.min;
+			CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);
+			CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);
+			CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);
+			int16 collisions;
+			CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos,
+				min(cp1.x, min(cp2.x, min(cp3.x, cp4.x))),
+				min(cp1.y, min(cp2.y, min(cp3.y, cp4.y))),
+				max(cp1.x, max(cp2.x, max(cp3.x, cp4.x))),
+				max(cp1.y, max(cp2.y, max(cp3.y, cp4.y))),
+				&collisions, 2, nil, false, true, true, false, false);
+			if (collisions > 0)
+				obstacleInPath = true;
+		}
+		if (obstacleInPath) {
+			UpdateCompareFlag(true);
+			return 0;
+		}
+		pObject->SetHeading(DEGTORAD(newHeading));
+		pObject->GetMatrix().UpdateRW();
+		pObject->UpdateRwFrame();
+		UpdateCompareFlag(newHeading == headingTarget); // using direct comparasion here is fine
+		return 0;
+	}
 	case COMMAND_SLIDE_OBJECT:
+	{
+		CollectParameters(&m_nIp, 8);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		CVector pos = pObject->GetPosition();
+		CVector posTarget = *(CVector*)&ScriptParams[1];
+		CVector slideBy = *(CVector*)&ScriptParams[4];
+		if (posTarget == pos) { // using direct comparasion here is fine
+			UpdateCompareFlag(true);
+			return 0;
+		}
+		CVector posDiff = pos - posTarget;
+		CVector newPosition;
+		if (posDiff.x < 0)
+			newPosition.x = -posDiff.x < slideBy.x ? posTarget.x : pos.x + slideBy.x;
+		else
+			newPosition.x = posDiff.x < slideBy.x ? posTarget.x : pos.x - slideBy.x;
+		if (posDiff.y < 0)
+			newPosition.y = -posDiff.y < slideBy.y ? posTarget.y : pos.y + slideBy.y;
+		else
+			newPosition.y = posDiff.y < slideBy.y ? posTarget.y : pos.y - slideBy.y;
+		if (posDiff.z < 0)
+			newPosition.z = -posDiff.z < slideBy.z ? posTarget.z : pos.z + slideBy.z;
+		else
+			newPosition.z = posDiff.z < slideBy.z ? posTarget.z : pos.z - slideBy.z;
+		bool obstacleInPath = false;
+		if (ScriptParams[7]) {
+			tmp_matrix = pObject->GetMatrix();
+			tmp_matrix.GetPosition() = newPosition;
+			CColModel* pColModel = pObject->GetColModel();
+			CVector cp1 = tmp_matrix * pColModel->boundingBox.min;
+			CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);
+			CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);
+			CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);
+			int16 collisions;
+			CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos,
+				min(cp1.x, min(cp2.x, min(cp3.x, cp4.x))),
+				min(cp1.y, min(cp2.y, min(cp3.y, cp4.y))),
+				max(cp1.x, max(cp2.x, max(cp3.x, cp4.x))),
+				max(cp1.y, max(cp2.y, max(cp3.y, cp4.y))),
+				&collisions, 2, nil, false, true, true, false, false);
+			if (collisions > 0)
+				obstacleInPath = true;
+		}
+		if (obstacleInPath) {
+			UpdateCompareFlag(true);
+			return 0;
+		}
+		pObject->Teleport(newPosition);
+		UpdateCompareFlag(newPosition == posTarget); // using direct comparasion here is fine
+		return 0;
+	}
 	case COMMAND_REMOVE_CHAR_ELEGANTLY:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		if (pPed && pPed->CharCreatedBy == MISSION_CHAR){
+			CWorld::RemoveReferencesToDeletedObject(pPed);
+			if (pPed->bInVehicle){
+				if (pPed->m_pMyVehicle){
+					if (pPed == pPed->m_pMyVehicle->pDriver){
+						pPed->m_pMyVehicle->RemoveDriver();
+						pPed->m_pMyVehicle->m_status = STATUS_ABANDONED;
+						if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
+							pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+						if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle())
+							pPed->m_pMyVehicle->ChangeLawEnforcerState(0);
+					}else{
+						pPed->m_pMyVehicle->RemovePassenger(pPed);
+					}
+				}
+				delete pPed;
+				--CPopulation::ms_nTotalMissionPeds;
+			}else{
+				pPed->CharCreatedBy = RANDOM_CHAR;
+				pPed->bRespondsToThreats = true;
+				pPed->bScriptObjectiveCompleted = false;
+				pPed->ClearLeader();
+				--CPopulation::ms_nTotalMissionPeds;
+				pPed->bFadeOut = true;
+			}
+		}
+		if (m_bIsMissionScript)
+			CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bKindaStayInSamePlace = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_IS_NASTY_GAME:
+		UpdateCompareFlag(CGame::nastyGame);
+		return 0;
 	case COMMAND_UNDRESS_CHAR:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		char name[8];
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, name);
+		for (int i = 0; i < 8; i++)
+			name[i] = tolower(name[i]);
+		int mi = pPed->GetModelIndex();
+		pPed->DeleteRwObject();
+		if (pPed->IsPlayer())
+			mi = 0;
+		CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
+		m_nIp += 8;
+		CWorld::Remove(pPed);
+		return 0;
+	}
 	case COMMAND_DRESS_CHAR:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		int mi = pPed->GetModelIndex();
+		pPed->m_modelIndex = -1;
+		pPed->SetModelIndex(mi);
+		CWorld::Add(pPed);
+		return 0;
+	}
 	case COMMAND_START_CHASE_SCENE:
+		CollectParameters(&m_nIp, 1);
+		CTimer::Suspend();
+		CStreaming::DeleteAllRwObjects();
+		CRecordDataForChase::StartChaseScene(*(float*)&ScriptParams[0]);
+		CTimer::Resume();
+		return 0;
 	case COMMAND_STOP_CHASE_SCENE:
+		CRecordDataForChase::CleanUpChaseScene();
+		return 0;
 	case COMMAND_IS_EXPLOSION_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 7);
+		float infX = *(float*)&ScriptParams[1];
+		float infY = *(float*)&ScriptParams[2];
+		float infZ = *(float*)&ScriptParams[3];
+		float supX = *(float*)&ScriptParams[4];
+		float supY = *(float*)&ScriptParams[5];
+		float supZ = *(float*)&ScriptParams[6];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[4];
+			supX = *(float*)&ScriptParams[1];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[5];
+			supY = *(float*)&ScriptParams[2];
+		}
+		if (infZ > supZ) {
+			infZ = *(float*)&ScriptParams[6];
+			supZ = *(float*)&ScriptParams[3];
+		}
+		UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
+			infX, supX, infY, supY, infZ, supZ));
+		return 0;
+	}
 	case COMMAND_IS_EXPLOSION_IN_ZONE:
+	{
+		CollectParameters(&m_nIp, 1);
+		char zone[8];
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
+		int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+		if (zone_id != -1)
+			m_nIp += 8;
+		CZone* pZone = CTheZones::GetZone(zone_id);
+		UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
+			pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz));
+		return 0;
+	}
 	case COMMAND_START_DRUG_DROP_OFF:
+		CPlane::CreateDropOffCesna();
+		return 0;
 	case COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN:
+		UpdateCompareFlag(CPlane::HasDropOffCesnaBeenShotDown());
+		return 0;
 	case COMMAND_FIND_DROP_OFF_PLANE_COORDINATES:
+	{
+		CVector pos = CPlane::FindDropOffCesnaCoordinates();
+		*(CVector*)&ScriptParams[0] = pos;
+		StoreParameters(&m_nIp, 3);
+		return 0;
+	}
 	case COMMAND_CREATE_FLOATING_PACKAGE:
+	{
+		CollectParameters(&m_nIp, 3);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+		ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0);
+		StoreParameters(&m_nIp, 1);
+		return 0;
+	}
 	case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR:
+	{
+		CollectParameters(&m_nIp, 5);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+		assert(pVehicle);
+		CVector offset = *(CVector*)&ScriptParams[2];
+		CPhysical::PlacePhysicalRelativeToOtherPhysical(pVehicle, pObject, offset);
+		return 0;
+	}
 	case COMMAND_MAKE_OBJECT_TARGETTABLE:
+	{
+		CollectParameters(&m_nIp, 1);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		CPlayerPed* pPlayerPed = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+		assert(pPlayerPed);
+		pPlayerPed->MakeObjectTargettable(ScriptParams[0]);
+		return 0;
+	}
 	case COMMAND_ADD_ARMOUR_TO_PLAYER:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPlayerPed);
+		pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
+		return 0;
+	}
 	case COMMAND_ADD_ARMOUR_TO_CHAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->m_fArmour = clamp(pPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
+		return 0;
+	}
 	case COMMAND_OPEN_GARAGE:
+	{
+		CollectParameters(&m_nIp, 1);
+		CGarages::Garages[ScriptParams[0]].OpenThisGarage();
+		return 0;
+	}
 	case COMMAND_CLOSE_GARAGE:
+	{
+		CollectParameters(&m_nIp, 1);
+		CGarages::Garages[ScriptParams[0]].CloseThisGarage();
+		return 0;
+	}
 	case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:
+	{
+		CollectParameters(&m_nIp, 4);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		CVector pos = *(CVector*)&ScriptParams[1];
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		if (pPed->bInVehicle){
+			if (pPed->m_pMyVehicle->bIsBus)
+				pPed->bRenderPedInCar = true;
+			if (pPed->m_pMyVehicle->pDriver == pPed){
+				pPed->m_pMyVehicle->RemoveDriver();
+				pPed->m_pMyVehicle->m_status = STATUS_ABANDONED;
+				pPed->m_pMyVehicle->bEngineOn = false;
+				pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+			}else{
+				pPed->m_pMyVehicle->RemovePassenger(pPed);
+			}
+			pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f);
+			pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f);
+		}
+		pPed->bInVehicle = false;
+		pPed->m_pMyVehicle = nil;
+		pPed->SetPedState(PED_IDLE);
+		pPed->m_nLastPedState = PED_NONE;
+		pPed->bUsesCollision = true;
+		pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+		pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId);
+		pPed->RemoveInCarAnims();
+		if (pPed->m_pVehicleAnim)
+			pPed->m_pVehicleAnim->blendDelta = -1000.0f;
+		pPed->m_pVehicleAnim = nil;
+		pPed->RestartNonPartialAnims();
+		pPed->SetMoveState(PEDMOVE_NONE);
+		CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+		pos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel();
+		pPed->Teleport(pos);
+		CTheScripts::ClearSpaceForMissionEntity(pos, pPed);
+		return 0;
+	}
 	case COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE:
+	{
+		CollectParameters(&m_nIp, 6);
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		float range = *(float*)&ScriptParams[3];
+		int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4];
+		int16 total;
+		CEntity* apEntities[16];
+		CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, true, false, false, true, true);
+		if (total == 0)
+			CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_NONE), pos, range, true, &total, 16, apEntities);
+		if (total == 0)
+			CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities);
+		CEntity* pClosestEntity = nil;
+		float min_dist = 2 * range;
+		for (int i = 0; i < total; i++) {
+			float dist = (apEntities[i]->GetPosition() - pos).Magnitude();
+			if (dist < min_dist) {
+				min_dist = dist;
+				pClosestEntity = apEntities[i];
+			}
+		}
+		if (pClosestEntity) {
+			pClosestEntity->bIsVisible = (ScriptParams[5] != 0);
+			CTheScripts::AddToInvisibilitySwapArray(pClosestEntity, ScriptParams[5] != 0);
+		}
+		return 0;
+	}
 	case COMMAND_HAS_CHAR_SPOTTED_CHAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+		assert(pTarget);
+		UpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget));
+		return 0;
+	}
 	case COMMAND_SET_CHAR_OBJ_HAIL_TAXI:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bScriptObjectiveCompleted = false;
+		pPed->SetObjective(OBJECTIVE_HAIL_TAXI);
+		return 0;
+	}
 	case COMMAND_HAS_OBJECT_BEEN_DAMAGED:
+	{
+		CollectParameters(&m_nIp, 1);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		UpdateCompareFlag(pObject->bHasBeenDamaged || !pObject->bIsVisible);
+		return 0;
+	}
 	case COMMAND_START_KILL_FRENZY_HEADSHOT:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 8);
+		CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2],
+			ScriptParams[3], text, ScriptParams[4], ScriptParams[5],
+			ScriptParams[6], ScriptParams[7] != 0, true);
+		return 0;
+	}
 	case COMMAND_ACTIVATE_MILITARY_CRANE:
+	{
+		CollectParameters(&m_nIp, 10);
+		float infX = *(float*)&ScriptParams[2];
+		float infY = *(float*)&ScriptParams[3];
+		float supX = *(float*)&ScriptParams[4];
+		float supY = *(float*)&ScriptParams[5];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[4];
+			supX = *(float*)&ScriptParams[2];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[5];
+			supY = *(float*)&ScriptParams[3];
+		}
+		CCranes::ActivateCrane(infX, supX, infY, supY,
+			*(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],
+			DEGTORAD(*(float*)&ScriptParams[9]), false, true,
+			*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
+		return 0;
+	}
 	case COMMAND_WARP_PLAYER_INTO_CAR:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+		assert(pPed);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+		assert(pVehicle);
+		pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
+		pPed->WarpPedIntoCar(pVehicle);
+		return 0;
+	}
 	case COMMAND_WARP_CHAR_INTO_CAR:
-	case COMMAND_SWITCH_CAR_RADIO:
-	case COMMAND_SET_AUDIO_STREAM:
+	{
+		CollectParameters(&m_nIp, 2);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+		assert(pVehicle);
+		pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
+		pPed->WarpPedIntoCar(pVehicle);
+		return 0;
+	}
+	//case COMMAND_SWITCH_CAR_RADIO:
+	//case COMMAND_SET_AUDIO_STREAM:
 	case COMMAND_PRINT_WITH_2_NUMBERS_BIG:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 4);
+		CMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_3_NUMBERS_BIG:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 5);
+		CMessages::AddBigMessageWithNumber(text, ScriptParams[3], ScriptParams[4] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_4_NUMBERS_BIG:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 6);
+		CMessages::AddBigMessageWithNumber(text, ScriptParams[4], ScriptParams[5] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_5_NUMBERS_BIG:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 7);
+		CMessages::AddBigMessageWithNumber(text, ScriptParams[5], ScriptParams[6] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
+		return 0;
+	}
 	case COMMAND_PRINT_WITH_6_NUMBERS_BIG:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 8);
+		CMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_WAIT_STATE:
+	{
+		CollectParameters(&m_nIp, 3);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->SetWaitState((eWaitState)ScriptParams[1], ScriptParams[2] >= 0 ? &ScriptParams[2] : nil);
+		return 0;
+	}
 	case COMMAND_SET_CAMERA_BEHIND_PLAYER:
+		TheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString();
+		return 0;
 	case COMMAND_SET_MOTION_BLUR:
+		CollectParameters(&m_nIp, 1);
+		TheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]);
+		return 0;
 	case COMMAND_PRINT_STRING_IN_STRING:
+	{
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* string = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		CollectParameters(&m_nIp, 2);
+		CMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string);
+		return 0;
+	}
 	case COMMAND_CREATE_RANDOM_CHAR:
+	{
+		CollectParameters(&m_nIp, 3);
+		CZoneInfo zoneinfo;
+		CTheZones::GetZoneInfoForTimeOfDay(&CWorld::Players[CWorld::PlayerInFocus].GetPos(), &zoneinfo);
+		int mi;
+		int pedtype = PEDTYPE_COP;
+		int attempt = 0;
+		while (pedtype != PEDTYPE_CIVMALE && pedtype != PEDTYPE_CIVFEMALE && attempt < 5) {
+			mi = CPopulation::ChooseCivilianOccupation(zoneinfo.pedGroup);
+			if (CModelInfo::GetModelInfo(mi)->GetRwObject())
+				pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;
+			attempt++;
+		}
+		if (!CModelInfo::GetModelInfo(mi)->GetRwObject()) {
+			mi = MI_MALE01;
+			pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;
+		}
+		CPed* ped = new CCivilianPed(pedtype, mi);
+		ped->CharCreatedBy = MISSION_CHAR;
+		ped->bRespondsToThreats = false;
+		ped->bAllowMedicsToReviveMe = false;
+		CVector pos = *(CVector*)&ScriptParams[0];
+		if (pos.z <= MAP_Z_LOW_LIMIT)
+			pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+		pos.z += 1.0f;
+		ped->GetPosition() = pos;
+		ped->SetOrientation(0.0f, 0.0f, 0.0f);
+		CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+		CWorld::Add(ped);
+		ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(pos);
+		CPopulation::ms_nTotalMissionPeds++;
+		ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);
+		StoreParameters(&m_nIp, 1);
+		if (m_bIsMissionScript)
+			CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+		return 0;
+	}
 	case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR:
+	{
+		CollectParameters(&m_nIp, 1);
+		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+		assert(pPed);
+		pPed->bScriptObjectiveCompleted = false;
+		pPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR);
+		return 0;
+	}
 	case COMMAND_SET_2_REPEATED_PHONE_MESSAGES:
+	{
+		CollectParameters(&m_nIp, 1);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, nil, nil, nil, nil);
+		return 0;
+	}
 	case COMMAND_SET_2_PHONE_MESSAGES:
+	{
+		CollectParameters(&m_nIp, 1);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, nil, nil, nil, nil);
+		return 0;
+	}
 	case COMMAND_SET_3_REPEATED_PHONE_MESSAGES:
+	{
+		CollectParameters(&m_nIp, 1);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, nil, nil, nil);
+		return 0;
+	}
 	case COMMAND_SET_3_PHONE_MESSAGES:
+	{
+		CollectParameters(&m_nIp, 1);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, nil, nil, nil);
+		return 0;
+	}
 	case COMMAND_SET_4_REPEATED_PHONE_MESSAGES:
+	{
+		CollectParameters(&m_nIp, 1);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, nil, nil);
+		return 0;
+	}
 	case COMMAND_SET_4_PHONE_MESSAGES:
+	{
+		CollectParameters(&m_nIp, 1);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil);
+		return 0;
+	}
 	case COMMAND_IS_SNIPER_BULLET_IN_AREA:
+	{
+		CollectParameters(&m_nIp, 6);
+		float infX = *(float*)&ScriptParams[0];
+		float infY = *(float*)&ScriptParams[1];
+		float infZ = *(float*)&ScriptParams[2];
+		float supX = *(float*)&ScriptParams[3];
+		float supY = *(float*)&ScriptParams[4];
+		float supZ = *(float*)&ScriptParams[5];
+		if (infX > supX) {
+			infX = *(float*)&ScriptParams[3];
+			supX = *(float*)&ScriptParams[0];
+		}
+		if (infY > supY) {
+			infY = *(float*)&ScriptParams[4];
+			supY = *(float*)&ScriptParams[1];
+		}
+		if (infZ > supZ) {
+			infZ = *(float*)&ScriptParams[5];
+			supZ = *(float*)&ScriptParams[2];
+		}
+		UpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ));
+		return 0;
+	}
 	case COMMAND_GIVE_PLAYER_DETONATOR:
-	case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR:
+		CGarages::GivePlayerDetonator();
+		return 0;
+	//case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR:
 	case COMMAND_SET_OBJECT_VELOCITY:
+	{
+		CollectParameters(&m_nIp, 4);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		pObject->SetMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED);
+		return 0;
+	}
 	case COMMAND_SET_OBJECT_COLLISION:
+	{
+		CollectParameters(&m_nIp, 2);
+		CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+		assert(pObject);
+		pObject->bUsesCollision = (ScriptParams[1] != 0);
+		return 0;
+	}
 	case COMMAND_IS_ICECREAM_JINGLE_ON:
+	{
+		CollectParameters(&m_nIp, 1);
+		CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+		assert(pVehicle);
+		// Adding this check to correspond to command name.
+		// All original game scripts always assume that the vehicle is actually Mr. Whoopee,
+		// but maybe there are mods that use it as "is horn activated"?
+		assert(pVehicle->GetModelIndex() == MI_MRWHOOP);
+		UpdateCompareFlag(pVehicle->m_bSirenOrAlarm);
+		return 0;
+	}
 	default:
 		assert(0);
 	}
@@ -6840,6 +7808,34 @@ bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)
 	return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled;
 }
 
+void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove)
+{
+	int i = 0;
+	bool found = false;
+	while (i < 20 && !found) {
+		if (InvisibilitySettingArray[i] == pEntity)
+			found = true;
+		else
+			i++;
+	}
+	if (found) {
+		if (remove)
+			InvisibilitySettingArray[i] = nil;
+	}
+	else if (!remove) {
+		int j = 0;
+		while (i < 20 && !found) {
+			if (InvisibilitySettingArray[i] == nil)
+				found = false;
+			else
+				i++;
+		}
+		if (found)
+			InvisibilitySettingArray[i] = pEntity;
+	}
+
+}
+
 WRAPPER void CRunningScript::LocatePlayerCommand(int32, uint32*) { EAXJMP(0x44FE10); }
 WRAPPER void CRunningScript::LocatePlayerCharCommand(int32, uint32*) { EAXJMP(0x4501E0); }
 WRAPPER void CRunningScript::LocatePlayerCarCommand(int32, uint32*) { EAXJMP(0x450540); }
diff --git a/src/control/Script.h b/src/control/Script.h
index fa8344ae..b47764fc 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -114,6 +114,8 @@ public:
 		}
 	}
 
+	float LimitAngleOnCircle(float angle) { return angle < 0.0f ? angle + 360.0f : angle; }
+
 	void CollectParameters(uint32*, int16);
 	int32 CollectNextParameterWithoutIncreasingPC(uint32);
 	int32* GetPointerToScriptVariable(uint32*, int16);
@@ -374,6 +376,7 @@ public:
 	static void HighlightImportantArea(uint32, float, float, float, float, float);
 	static void DrawDebugSquare(float, float, float, float);
 	static void DrawDebugCube(float, float, float, float, float, float);
+	static void AddToInvisibilitySwapArray(CEntity*, bool);
 
 	static int32 Read4BytesFromScript(uint32* pIp){
 		int32 retval = 0;
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 3ab7d742..1aee4edb 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -33,6 +33,8 @@ WRAPPER void CCamera::LoadPathSplines(int file) { EAXJMP(0x46D1D0); }
 WRAPPER uint32 CCamera::GetCutSceneFinishTime(void) { EAXJMP(0x46B920); }
 WRAPPER void CCamera::FinishCutscene(void) { EAXJMP(0x46B560); }
 WRAPPER void CCamera::RestoreWithJumpCut(void) { EAXJMP(0x46FAE0); };
+WRAPPER void CCamera::SetZoomValueFollowPedScript(int16) { EAXJMP(0x46FF30); }
+WRAPPER void CCamera::SetZoomValueCamStringScript(int16) { EAXJMP(0x46FF90); }
 
 bool
 CCamera::GetFading()
@@ -1357,6 +1359,14 @@ void CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString()
 		m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);
 }
 
+void CCamera::SetCameraDirectlyBehindForFollowPed_CamOnAString()
+{
+	m_bCamDirectlyBehind = true;
+	CPlayerPed *player = FindPlayerPed();
+	if (player)
+		m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);
+}
+
 void
 CCamera::SetWideScreenOn(void)
 {
diff --git a/src/core/Camera.h b/src/core/Camera.h
index 46c25436..81eaa84f 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -491,6 +491,9 @@ int     m_iModeObbeCamIsInForCar;
 	void TakeControlWithSpline(short);
 	void RestoreWithJumpCut(void);
 	void SetCameraDirectlyInFrontForFollowPed_CamOnAString(void);
+	void SetCameraDirectlyBehindForFollowPed_CamOnAString(void);
+	void SetZoomValueFollowPedScript(int16);
+	void SetZoomValueCamStringScript(int16);
 
 	void dtor(void) { this->CCamera::~CCamera(); }
 };
diff --git a/src/core/Explosion.cpp b/src/core/Explosion.cpp
index 30809dc9..7a8878f6 100644
--- a/src/core/Explosion.cpp
+++ b/src/core/Explosion.cpp
@@ -4,6 +4,7 @@
 
 WRAPPER void CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32) { EAXJMP(0x5591C0); }
 WRAPPER void CExplosion::RemoveAllExplosionsInArea(CVector, float) { EAXJMP(0x55AD40); }
+WRAPPER bool CExplosion::TestForExplosionInArea(eExplosionType, float, float, float, float, float, float) { EAXJMP(0x55AC80); }
 
 WRAPPER
 int8 CExplosion::GetExplosionActiveCounter(uint8 id)
diff --git a/src/core/Explosion.h b/src/core/Explosion.h
index 0768bbe4..e85f7892 100644
--- a/src/core/Explosion.h
+++ b/src/core/Explosion.h
@@ -28,4 +28,5 @@ public:
 	static uint8 GetExplosionType(uint8 id);
 	static void ResetExplosionActiveCounter(uint8 id);
 	static void RemoveAllExplosionsInArea(CVector, float);
+	static bool TestForExplosionInArea(eExplosionType, float, float, float, float, float, float);
 };
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index 17c3d9d7..fd6ba602 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -5,6 +5,7 @@ int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
 int32 &CStats::HeadsPopped = *(int32*)0x8F647C;
 bool& CStats::CommercialPassed = *(bool*)0x8F4334;
 bool& CStats::IndustrialPassed = *(bool*)0x8E2A68;
+bool& CStats::SuburbanPassed = *(bool*)0x8F2740;
 int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
 int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
 int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64;
diff --git a/src/core/Stats.h b/src/core/Stats.h
index add4320b..8feb3c13 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -7,6 +7,7 @@ public:
 	static int32 &HeadsPopped;
 	static bool& CommercialPassed;
 	static bool& IndustrialPassed;
+	static bool& SuburbanPassed;
 	static int32 &NumberKillFrenziesPassed;
 	static int32 &PeopleKilledByOthers;
 	static int32 &HelisDestroyed;
diff --git a/src/core/World.cpp b/src/core/World.cpp
index dac64970..0b389e42 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -44,6 +44,10 @@ WRAPPER void CWorld::RemoveStaticObjects() { EAXJMP(0x4B4D50); }
 WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); }
 WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); }
 WRAPPER void CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8) { EAXJMP(0x4B4E70) };
+WRAPPER void CWorld::FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B2E70); }
+WRAPPER void CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B3280); }
+WRAPPER void CWorld::FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool) { EAXJMP(0x4B2600); }
+WRAPPER void CWorld::FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**) { EAXJMP(0x4B2960); }
 
 void
 CWorld::Initialise()
@@ -960,7 +964,7 @@ CWorld::RemoveFallenPeds(void)
 	for(int poolIndex = poolSize-1; poolIndex >= 0; poolIndex--) {
 		CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);
 		if (ped) {
-			if (ped->GetPosition().z < -100.0f) {
+			if (ped->GetPosition().z < MAP_Z_LOW_LIMIT) {
 				if (ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) {
 					int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED, 999999.9f, false, false);
 					CVector newPos = ThePaths.m_pathNodes[closestNode].pos;
@@ -982,7 +986,7 @@ CWorld::RemoveFallenCars(void)
 	for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
 		CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
 		if (veh) {
-			if (veh->GetPosition().z < -100.0f) {
+			if (veh->GetPosition().z < MAP_Z_LOW_LIMIT) {
 				if (veh->VehicleCreatedBy == MISSION_VEHICLE || veh == FindPlayerVehicle() || (veh->pDriver && veh->pDriver->IsPlayer())) {
 					int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR, 999999.9f, false, false);
 					CVector newPos = ThePaths.m_pathNodes[closestNode].pos;
diff --git a/src/core/World.h b/src/core/World.h
index 119c6324..61a44ea0 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -22,6 +22,8 @@
 #define WORLD_MAX_X (WORLD_MIN_X + WORLD_SIZE_X)
 #define WORLD_MAX_Y (WORLD_MIN_Y + WORLD_SIZE_Y)
 
+#define MAP_Z_LOW_LIMIT -100.0f
+
 enum
 {
 	ENTITYLIST_BUILDINGS,
@@ -103,11 +105,15 @@ public:
 	static CEntity *TestSphereAgainstSectorList(CPtrList&, CVector, float, CEntity*, bool);
 	static void FindObjectsInRangeSectorList(CPtrList&, CVector&, float, bool, short*, short, CEntity**);
 	static void FindObjectsInRange(CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool);
+	static void FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**);
+	static void FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool);
 	static float FindGroundZForCoord(float x, float y);
 	static float FindGroundZFor3DCoord(float x, float y, float z, bool *found);
 	static float FindRoofZFor3DCoord(float x, float y, float z, bool *found);
 	static void RemoveReferencesToDeletedObject(CEntity*);
 	static void FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool);
+	static void FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool);
+	static void FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool);
 
 	static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); }
 	static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); }
diff --git a/src/core/config.h b/src/core/config.h
index 166c2a68..80176fca 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -85,6 +85,7 @@ enum Config {
 
 	NUM_ACCIDENTS = 20,
 	NUM_FIRES = 40,
+	NUM_GARAGES = 32,
 
 	NUMPEDROUTES = 200,
 	NUMPHONES = 50,
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 49803418..f8a063f3 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -340,7 +340,7 @@ public:
 
 	uint8 bWanderPathAfterExitingCar : 1;
 	uint8 bIsLeader : 1;
-	uint8 bDontDragMeOutCar : 1;
+	uint8 bDontDragMeOutCar : 1; // unfinished feature
 	uint8 m_ped_flagF8 : 1;
 	uint8 bWillBeQuickJacked : 1;
 	uint8 bCancelEnteringCar : 1; // after door is opened or couldn't be opened due to it's locked
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 7c946dda..a4ffdc7c 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -7,6 +7,7 @@
 #include "World.h"
 #include "RpAnimBlend.h"
 #include "General.h"
+#include "Pools.h"
 
 CPlayerPed::~CPlayerPed()
 {
@@ -73,6 +74,17 @@ CPlayerPed::SetWantedLevelNoDrop(int32 level)
 	m_pWanted->SetWantedLevelNoDrop(level);
 }
 
+void
+CPlayerPed::MakeObjectTargettable(int32 handle)
+{
+	for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
+		if (CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {
+			m_nTargettableObjects[i] = handle;
+			return;
+		}
+	}
+}
+
 // I don't know the actual purpose of parameter
 void
 CPlayerPed::AnnoyPlayerPed(bool annoyedByPassingEntity)
diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h
index 1de1b442..6a794d41 100644
--- a/src/peds/PlayerPed.h
+++ b/src/peds/PlayerPed.h
@@ -56,6 +56,7 @@ public:
 	void UseSprintEnergy(void);
 	class CPlayerInfo *GetPlayerInfoForThisPlayerPed();
 	void SetRealMoveAnim(void);
+	void MakeObjectTargettable(int32);
 
 	static void SetupPlayerPed(int32);
 	static void DeactivatePlayerPed(int32);
diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp
new file mode 100644
index 00000000..54fa6844
--- /dev/null
+++ b/src/weapons/BulletInfo.cpp
@@ -0,0 +1,5 @@
+#include "common.h"
+#include "patcher.h"
+#include "BulletInfo.h"
+
+WRAPPER bool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2) { EAXJMP(0x558D40); }
diff --git a/src/weapons/BulletInfo.h b/src/weapons/BulletInfo.h
new file mode 100644
index 00000000..3905b56d
--- /dev/null
+++ b/src/weapons/BulletInfo.h
@@ -0,0 +1,7 @@
+#pragma once
+
+class CBulletInfo
+{
+public:
+	static bool TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2);
+};
\ No newline at end of file

From c5e7de02fec64d7aab38cb424e17455443cbeba4 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Sat, 4 Jan 2020 01:10:35 +0300
Subject: [PATCH 9/9] fixes

---
 src/control/Script.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 34d22897..f3f9c5a8 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -7812,7 +7812,7 @@ void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove)
 {
 	int i = 0;
 	bool found = false;
-	while (i < 20 && !found) {
+	while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {
 		if (InvisibilitySettingArray[i] == pEntity)
 			found = true;
 		else
@@ -7824,9 +7824,9 @@ void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove)
 	}
 	else if (!remove) {
 		int j = 0;
-		while (i < 20 && !found) {
+		while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {
 			if (InvisibilitySettingArray[i] == nil)
-				found = false;
+				found = true;
 			else
 				i++;
 		}