From 750d3229a38cfa449ebb51e4936ca9b33e581695 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?eray=20or=C3=A7unus?= <erayorcunus@gmail.com>
Date: Thu, 27 Feb 2020 19:07:36 +0300
Subject: [PATCH 1/3] CPopulation 3 and fixes

---
 src/control/Script.cpp  |   2 +-
 src/core/Frontend.cpp   | 140 +++++++++---------
 src/core/Frontend.h     |   8 --
 src/objects/Object.cpp  |  40 +++++-
 src/objects/Object.h    |   3 +
 src/peds/Ped.cpp        |  19 ++-
 src/peds/Population.cpp | 305 ++++++++++++++++++++++++++++++++++++++--
 src/peds/Population.h   |   8 +-
 8 files changed, 430 insertions(+), 95 deletions(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 3d8807d8..4ef3821e 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -3757,7 +3757,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
 		CollectParameters(&m_nIp, 2);
 		CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
 		if (ScriptParams[1]){
-			if (CReplay::IsPlayingBack() || CTheScripts::DelayMakingPlayerUnsafeThisTime){
+			if (CGame::playingIntro || CTheScripts::DelayMakingPlayerUnsafeThisTime){
 				CTheScripts::CountdownToMakePlayerUnsafe = 50;
 				if (CTheScripts::DelayMakingPlayerUnsafeThisTime)
 					CTheScripts::DelayMakingPlayerUnsafeThisTime--;
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index 751ca23f..d43f24d7 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -580,23 +580,26 @@ void CMenuManager::Draw()
 	float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider
 	float freeSpaceInLine = lineHeight * 0.1f; // also height of smallest bar in slider(weird)
 	bool foundTheHoveringItem = false;
+	wchar unicodeTemp[64];
+
 	for (int i = 0; i < NUM_MENUROWS; ++i) {
 		if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') {
-			wchar *textToPrint[MENUCOLUMNS] = { nil, nil, nil };
+			wchar *rightText = nil;
+			wchar *leftText;
 
 			if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) {
 				CFont::SetRightJustifyOff();
-				textToPrint[MENUCOLUMN_LEFT] = GetNameOfSavedGame(i - 1);
+				leftText = GetNameOfSavedGame(i - 1);
 
 				if (Slots[i] != SLOT_EMPTY)
-					textToPrint[MENUCOLUMN_RIGHT] = GetSavedGameDateAndTime(i - 1);
+					rightText = GetSavedGameDateAndTime(i - 1);
 
-				if (textToPrint[MENUCOLUMN_LEFT][0] == '\0') {
+				if (leftText[0] == '\0') {
 					sprintf(gString, "FEM_SL%d", i);
-					textToPrint[MENUCOLUMN_LEFT] = TheText.Get(gString);
+					leftText = TheText.Get(gString);
 				}
 			} else {
-				textToPrint[MENUCOLUMN_LEFT] = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName);
+				leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName);
 			}
 
 			switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) {
@@ -605,28 +608,28 @@ void CMenuManager::Draw()
 					case MENUPAGE_MULTIPLAYER_MAP:
 						switch (sthWithButtons) {
 							case 0:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA0");
+								rightText = TheText.Get("FEM_MA0");
 								break;
 							case 1:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA1");
+								rightText = TheText.Get("FEM_MA1");
 								break;
 							case 2:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA2");
+								rightText = TheText.Get("FEM_MA2");
 								break;
 							case 3:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA3");
+								rightText = TheText.Get("FEM_MA3");
 								break;
 							case 4:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA4");
+								rightText = TheText.Get("FEM_MA4");
 								break;
 							case 5:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA5");
+								rightText = TheText.Get("FEM_MA5");
 								break;
 							case 6:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA6");
+								rightText = TheText.Get("FEM_MA6");
 								break;
 							case 7:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_MA7");
+								rightText = TheText.Get("FEM_MA7");
 								break;
 							default:
 								break;
@@ -635,28 +638,28 @@ void CMenuManager::Draw()
 					case MENUPAGE_MULTIPLAYER_MODE:
 						switch (sthWithButtons2) {
 							case 0:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY0");
+								rightText = TheText.Get("FEN_TY0");
 								break;
 							case 1:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY1");
+								rightText = TheText.Get("FEN_TY1");
 								break;
 							case 2:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY2");
+								rightText = TheText.Get("FEN_TY2");
 								break;
 							case 3:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY3");
+								rightText = TheText.Get("FEN_TY3");
 								break;
 							case 4:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY4");
+								rightText = TheText.Get("FEN_TY4");
 								break;
 							case 5:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY5");
+								rightText = TheText.Get("FEN_TY5");
 								break;
 							case 6:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY6");
+								rightText = TheText.Get("FEN_TY6");
 								break;
 							case 7:
-								textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEN_TY7");
+								rightText = TheText.Get("FEN_TY7");
 								break;
 							default:
 								break;
@@ -669,57 +672,57 @@ void CMenuManager::Draw()
 			}
 			case MENUACTION_CTRLVIBRATION:
 				if (CMenuManager::m_PrefsUseVibration)
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_ON");
+					rightText = TheText.Get("FEM_ON");
 				else
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEM_OFF");
+					rightText = TheText.Get("FEM_OFF");
 				break;
 			case MENUACTION_CTRLCONFIG:
 				switch (CPad::GetPad(0)->Mode) {
 				case 0:
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF1");
+					rightText = TheText.Get("FEC_CF1");
 					break;
 				case 1:
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF2");
+					rightText = TheText.Get("FEC_CF2");
 					break;
 				case 2:
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF3");
+					rightText = TheText.Get("FEC_CF3");
 					break;
 				case 3:
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_CF4");
+					rightText = TheText.Get("FEC_CF4");
 					break;
 				}
 				break;
 			case MENUACTION_CTRLDISPLAY:
 				if (m_DisplayControllerOnFoot)
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_ONF");
+					rightText = TheText.Get("FEC_ONF");
 				else
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEC_INC");
+					rightText = TheText.Get("FEC_INC");
 				break;
 			case MENUACTION_FRAMESYNC:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_FRAMELIMIT:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_TRAILS:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(CMBlur::BlurOn ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(CMBlur::BlurOn ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_SUBTITLES:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_WIDESCREEN:
 #ifndef ASPECT_RATIO_SCALE
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF");
 #else
 				switch (m_PrefsUseWideScreen) {
 				case AR_AUTO:
-					textToPrint[MENUCOLUMN_RIGHT] = (wchar*)L"AUTO";
+					rightText = (wchar*)L"AUTO";
 					break;
 				case AR_4_3:
-					textToPrint[MENUCOLUMN_RIGHT] = (wchar*)L"4:3";
+					rightText = (wchar*)L"4:3";
 					break;
 				case AR_16_9:
-					textToPrint[MENUCOLUMN_RIGHT] = (wchar*)L"16:9";
+					rightText = (wchar*)L"16:9";
 					break;
 				}
 #endif
@@ -729,42 +732,39 @@ void CMenuManager::Draw()
 					break;
 
 				sprintf(gString, "FEA_FM%d", m_PrefsRadioStation);
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(gString);
+				rightText = TheText.Get(gString);
 				break;
 			case MENUACTION_SETDBGFLAG:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(CTheScripts::DbgFlag ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(gbBigWhiteDebugLightSwitchedOn ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(gbBigWhiteDebugLightSwitchedOn ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_PEDROADGROUPS:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(gbShowPedRoadGroups ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(gbShowPedRoadGroups ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_CARROADGROUPS:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(gbShowCarRoadGroups ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(gbShowCarRoadGroups ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_COLLISIONPOLYS:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(gbShowCollisionPolys ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(gbShowCollisionPolys ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_SHOWCULL:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(gbShowCullZoneDebugStuff ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(gbShowCullZoneDebugStuff ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_SHOWHEADBOB:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(TheCamera.m_bHeadBob ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(TheCamera.m_bHeadBob ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_INVVERT:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_OFF" : "FEM_ON");
+				rightText = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_OFF" : "FEM_ON");
 				break;
-			case MENUACTION_SCREENRES: {
-				RwChar* res = _psGetVideoModeList()[m_nDisplayVideoMode];
-				wchar temp[32];
-				AsciiToUnicode(res, temp);
-				textToPrint[MENUCOLUMN_RIGHT] = temp;
+			case MENUACTION_SCREENRES:
+				AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp);
+				rightText = unicodeTemp;
 				break;
-			}
-			case MENUACTION_AUDIOHW: {
+			case MENUACTION_AUDIOHW:
 				if (m_nPrefsAudio3DProviderIndex == -1)
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_NAH");
+					rightText = TheText.Get("FEA_NAH");
 				else {
 					char *provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex);
 
@@ -773,25 +773,23 @@ void CMenuManager::Draw()
 					} else if (!strcmp(strupr(provider), "DIRECTSOUND3D SOFTWARE EMULATION")) {
 						strcpy(provider, "DSOUND3D SOFTWARE EMULATION");
 					}
-					wchar temp[64];
-					AsciiToUnicode(provider, temp);
-					textToPrint[MENUCOLUMN_RIGHT] = temp;
+					AsciiToUnicode(provider, unicodeTemp);
+					rightText = unicodeTemp;
 				}
 				break;
-			}
 			case MENUACTION_SPEAKERCONF: {
 				if (m_nPrefsAudio3DProviderIndex == -1)
-					textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_NAH");
+					rightText = TheText.Get("FEA_NAH");
 				else {
 					switch (m_PrefsSpeakers) {
 					case 0:
-						textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_2SP");
+						rightText = TheText.Get("FEA_2SP");
 						break;
 					case 1:
-						textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_EAR");
+						rightText = TheText.Get("FEA_EAR");
 						break;
 					case 2:
-						textToPrint[MENUCOLUMN_RIGHT] = TheText.Get("FEA_4SP");
+						rightText = TheText.Get("FEA_4SP");
 						break;
 					}
 				}
@@ -800,19 +798,19 @@ void CMenuManager::Draw()
 			case MENUACTION_CTRLMETHOD: {
 				switch (m_ControlMethod) {
 				case 0:
-					textToPrint[MENUCOLUMN_LEFT] = TheText.Get("FET_SCN");
+					leftText = TheText.Get("FET_SCN");
 					break;
 				case 1:
-					textToPrint[MENUCOLUMN_LEFT] = TheText.Get("FET_CCN");
+					leftText = TheText.Get("FET_CCN");
 					break;
 				}
 				break;
 			}
 			case MENUACTION_DYNAMICACOUSTIC:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF");
+				rightText = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF");
 				break;
 			case MENUACTION_MOUSESTEER:
-				textToPrint[MENUCOLUMN_RIGHT] = TheText.Get(m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON");
+				rightText = TheText.Get(m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON");
 				break;
 			}
 
@@ -885,8 +883,8 @@ void CMenuManager::Draw()
 
 				float itemY = MENU_Y(textLayer + nextItemY);
 				float itemX = MENU_X_LEFT_ALIGNED(textLayer + columnWidth);
-				CFont::PrintString(itemX, itemY, textToPrint[MENUCOLUMN_LEFT]);
-				if (textToPrint[MENUCOLUMN_RIGHT]) {
+				CFont::PrintString(itemX, itemY, leftText);
+				if (rightText) {
 					if (!CFont::Details.centre)
 						CFont::SetRightJustifyOn();
 					
@@ -894,7 +892,7 @@ void CMenuManager::Draw()
 						&& !m_bGameNotLoaded && textLayer == 1) {
 						CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255)));
 					}
-					CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, textToPrint[MENUCOLUMN_RIGHT]);
+					CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText);
 				}
 				if (i == m_nCurrOption && itemsAreSelectable) {
 					CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255)));
@@ -1017,7 +1015,7 @@ void CMenuManager::Draw()
 				}
 			}
 
-			nextYToUse += lineHeight * CFont::GetNumberLines(menuXYpadding, nextYToUse, textToPrint[MENUCOLUMN_LEFT]);
+			nextYToUse += lineHeight * CFont::GetNumberLines(menuXYpadding, nextYToUse, leftText);
 
 			// Radio icons.
 			// TO-DO: This is missing/broken
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index 32338933..18a324ed 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -340,14 +340,6 @@ enum eCheckHover
 	HOVEROPTION_42,
 };
 
-enum eMenuColumns
-{ 
-	MENUCOLUMN_LEFT,
-	MENUCOLUMN_CENTER,
-	MENUCOLUMN_RIGHT,
-	MENUCOLUMNS,
-};
-
 enum
 {
 	NUM_MENUROWS = 18,
diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp
index de98a2d6..357d67d7 100644
--- a/src/objects/Object.cpp
+++ b/src/objects/Object.cpp
@@ -55,6 +55,21 @@ CObject::CObject(int32 mi, bool createRW)
 	Init();
 }
 
+CObject::CObject(CDummyObject *dummy)
+{
+	SetModelIndexNoCreate(dummy->m_modelIndex);
+
+	if (dummy->m_rwObject)
+		AttachToRwObject(dummy->m_rwObject);
+	else
+		GetMatrix() = dummy->GetMatrix();
+
+	m_objectMatrix = dummy->GetMatrix();
+	dummy->DetachFromRwObject();
+	Init();
+	m_level = dummy->m_level;
+}
+
 CObject::~CObject(void)
 {
 	CRadar::ClearBlipForEntity(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(this));
@@ -109,14 +124,37 @@ CObject::RefModelInfo(int32 modelId)
 	CModelInfo::GetModelInfo(modelId)->AddRef();
 }
 
+bool
+CObject::CanBeDeleted(void)
+{
+	switch (ObjectCreatedBy) {
+		case GAME_OBJECT:
+			return true;
+		case MISSION_OBJECT:
+			return false;
+		case TEMP_OBJECT:
+			return true;
+		case CUTSCENE_OBJECT:
+			return false;
+		default:
+			return true;
+	}
+}
+
 class CObject_ : public CObject
 {
 public:
-	void dtor(void) { this->CObject::~CObject(); }
+	CObject *ctor(void) { return ::new (this) CObject(); }
+	CObject *ctor(int32 mi, bool createRW) { return ::new (this) CObject(mi, createRW); }
+	CObject *ctor(CDummyObject *dummy) { return ::new (this) CObject(dummy); }
+	void dtor(void) { CObject::~CObject(); }
 	void Render_(void) { CObject::Render(); }
 };
 
 STARTPATCHES
+	InjectHook(0x4BABD0, (CObject* (CObject::*)(void)) &CObject_::ctor, PATCH_JUMP);
+	InjectHook(0x4BACE0, (CObject* (CObject::*)(int32, bool)) &CObject_::ctor, PATCH_JUMP);
+	InjectHook(0x4BAD50, (CObject* (CObject::*)(CDummyObject*)) &CObject_::ctor, PATCH_JUMP);
 	InjectHook(0x4BAE00, &CObject_::dtor, PATCH_JUMP);
 	InjectHook(0x4BB1E0, &CObject_::Render_, PATCH_JUMP);
 ENDPATCHES
diff --git a/src/objects/Object.h b/src/objects/Object.h
index c07bb233..1c33b07f 100644
--- a/src/objects/Object.h
+++ b/src/objects/Object.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "Physical.h"
+#include "DummyObject.h"
 
 enum {
 	GAME_OBJECT = 1,
@@ -69,6 +70,7 @@ public:
 
 	CObject(void);
 	CObject(int32, bool);
+	CObject(CDummyObject*);
 	~CObject(void);
 
 	void ProcessControl(void);
@@ -80,6 +82,7 @@ public:
 	void ObjectDamage(float amount);
 	void RefModelInfo(int32 modelId);
 	void Init(void);
+	bool CanBeDeleted(void);
 
 	static void DeleteAllTempObjectInArea(CVector, float);
 };
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 1ea13cc2..3e9bfc51 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -1519,7 +1519,7 @@ CPed::BeingDraggedFromCar(void)
 #ifdef VC_PED_PORTS
 	if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
 		if (m_pMyVehicle) {
-			m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime);
+			m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f);
 		}
 	}
 #endif
@@ -2954,6 +2954,11 @@ CPed::QuitEnteringCar(void)
 		if (veh->m_nNumGettingIn != 0)
 			veh->m_nNumGettingIn--;
 
+#ifdef VC_PED_PORTS
+		if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+			RestorePreviousObjective();
+#endif
+
 		veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType);
 	}
 
@@ -2965,7 +2970,7 @@ CPed::QuitEnteringCar(void)
 		animAssoc = m_pVehicleAnim;
 		if (animAssoc) {
 			animAssoc->blendDelta = -4.0f;
-			animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+			animAssoc->flags |= ASSOC_DELETEFADEDOUT;
 			animAssoc = m_pVehicleAnim;
 			animAssoc->flags &= ~ASSOC_RUNNING;
 		}
@@ -4161,7 +4166,10 @@ CPed::ClearObjective(void)
 {
 	if (IsPedInControl() || m_nPedState == PED_DRIVING) {
 		m_objective = OBJECTIVE_NONE;
-
+#ifdef VC_PED_PORTS
+		m_pedInObjective = nil;
+		m_carInObjective = nil;
+#endif
 		if (m_nPedState == PED_DRIVING && m_pMyVehicle) {
 
 			if (m_pMyVehicle->pDriver != this) {
@@ -13603,7 +13611,10 @@ CPed::ProcessObjective(void)
 					if (InVehicle()) {
 						if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN
 							&& (m_nPedType != PEDTYPE_COP
-								|| m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < 0.000025f)) {
+#ifdef VC_PED_PORTS
+								|| m_pMyVehicle->IsBoat()
+#endif
+								|| m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) {
 							if (m_pMyVehicle->IsTrain())
 								SetExitTrain(m_pMyVehicle);
 #ifdef VC_PED_PORTS
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index a2dd5c38..6ffb65ba 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -17,6 +17,7 @@
 #include "VisibilityPlugins.h"
 #include "PedPlacement.h"
 #include "DummyObject.h"
+#include "Script.h"
 
 #define CREATION_DIST_MULT_TO_DIST 40.0f
 #define CREATION_RANGE 10.0f // Being added over the CREATION_DIST_MULT_TO_DIST.
@@ -56,10 +57,8 @@ CVector &CPopulation::RegenerationPoint_a = *(CVector*)0x8E2AA4;
 CVector &CPopulation::RegenerationPoint_b = *(CVector*)0x8E2A98;
 CVector &CPopulation::RegenerationForward = *(CVector*)0x8F1AD4;
 
-WRAPPER CPed *CPopulation::AddPedInCar(CVehicle *vehicle) { EAXJMP(0x4F5800); }
 WRAPPER void CPopulation::ManagePopulation(void) { EAXJMP(0x4F3B90); }
-WRAPPER void CPopulation::MoveCarsAndPedsOutOfAbandonedZones(void) { EAXJMP(0x4F5BE0); }
-WRAPPER void CPopulation::ConvertToRealObject(CDummyObject* obj) { EAXJMP(0x4F45A0); }
+WRAPPER bool CPopulation::TestSafeForRealObject(CDummyObject*) { EAXJMP(0x4F4700); }
 
 void
 CPopulation::Initialise()
@@ -470,13 +469,13 @@ CPopulation::PedCreationDistMultiplier()
 }
 
 CPed*
-CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors)
+CPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors)
 {
 	switch (pedType) {
 		case PEDTYPE_CIVMALE:
 		case PEDTYPE_CIVFEMALE:
 		{
-			CCivilianPed *ped = new CCivilianPed(pedType, mi);
+			CCivilianPed *ped = new CCivilianPed(pedType, miOrCopType);
 			ped->GetPosition() = coors;
 			ped->SetOrientation(0.0f, 0.0f, 0.0f);
 			CWorld::Add(ped);
@@ -490,7 +489,7 @@ CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors)
 		}
 		case PEDTYPE_COP:
 		{
-			CCopPed *ped = new CCopPed((eCopType)mi);
+			CCopPed *ped = new CCopPed((eCopType)miOrCopType);
 			ped->GetPosition() = coors;
 			ped->SetOrientation(0.0f, 0.0f, 0.0f);
 			CWorld::Add(ped);
@@ -506,7 +505,7 @@ CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors)
 		case PEDTYPE_GANG8:
 		case PEDTYPE_GANG9:
 		{
-			CCivilianPed *ped = new CCivilianPed(pedType, mi);
+			CCivilianPed *ped = new CCivilianPed(pedType, miOrCopType);
 			ped->GetPosition() = coors;
 			ped->SetOrientation(0.0f, 0.0f, 0.0f);
 			CWorld::Add(ped);
@@ -538,7 +537,7 @@ CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors)
 		case PEDTYPE_CRIMINAL:
 		case PEDTYPE_PROSTITUTE:
 		{
-			CCivilianPed *ped = new CCivilianPed(pedType, mi);
+			CCivilianPed *ped = new CCivilianPed(pedType, miOrCopType);
 			ped->GetPosition() = coors;
 			ped->SetOrientation(0.0f, 0.0f, 0.0f);
 			CWorld::Add(ped);
@@ -721,6 +720,292 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
 	}
 }
 
+CPed*
+CPopulation::AddPedInCar(CVehicle* car)
+{
+	int defaultModel = MI_MALE01;
+	bool imSureThatModelIsLoaded = true;
+	CVector coors = FindPlayerCoors();
+	CZoneInfo zoneInfo;
+	int pedType;
+
+	// May be eCopType, model index or non-sense(for medic), AddPed knows that by looking to ped type.
+	int preferredModel;
+
+	CTheZones::GetZoneInfoForTimeOfDay(&coors, &zoneInfo);
+	switch (car->m_modelIndex) {
+		case MI_FIRETRUCK:
+			preferredModel = 0;
+			pedType = PEDTYPE_FIREMAN;
+			break;
+		case MI_AMBULAN:
+			preferredModel = 0;
+			pedType = PEDTYPE_EMERGENCY;
+			break;
+		case MI_FBICAR:
+			preferredModel = COP_FBI;
+			pedType = PEDTYPE_COP;
+			break;
+		case MI_POLICE:
+			preferredModel = COP_STREET;
+			pedType = PEDTYPE_COP;
+			break;
+		case MI_ENFORCER:
+			preferredModel = COP_SWAT;
+			pedType = PEDTYPE_COP;
+			break;
+		case MI_RHINO:
+		case MI_BARRACKS:
+			preferredModel = COP_ARMY;
+			pedType = PEDTYPE_COP;
+			break;
+		case MI_TAXI:
+		case MI_CABBIE:
+		case MI_BORGNINE:
+			if (CGeneral::GetRandomTrueFalse()) {
+				pedType = PEDTYPE_CIVMALE;
+				preferredModel = MI_TAXI_D;
+				break;
+			}
+			defaultModel = MI_TAXI_D;
+
+			// fall through
+		default:
+			int gangOfPed = GANG_MAFIA;
+			imSureThatModelIsLoaded = false;
+
+			while (gangOfPed < NUM_GANGS && CGangs::GetGangInfo(gangOfPed)->m_nVehicleMI != car->m_modelIndex)
+				gangOfPed++;
+
+			if (gangOfPed < NUM_GANGS) {
+				pedType = gangOfPed + PEDTYPE_GANG1;
+				preferredModel = ChooseGangOccupation(gangOfPed);
+			} else if (gangOfPed == NUM_GANGS) {
+				CVehicleModelInfo *carModelInfo = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(car->m_modelIndex));
+				int i = 15;
+				for(; i >= 0; i--) {
+					// Should return random model each time
+					preferredModel = ChooseCivilianOccupation(zoneInfo.pedGroup);
+					if (preferredModel == -1)
+						preferredModel = defaultModel;
+
+					if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_carsCanDrive & (1 << carModelInfo->m_vehicleClass))
+						break;
+				}
+				if (i == -1)
+					preferredModel = defaultModel;
+
+				pedType = ((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_pedType;
+			}
+			break;
+	}
+	if (!imSureThatModelIsLoaded && !((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->GetRwObject()) {
+		preferredModel = defaultModel;
+		pedType = ((CPedModelInfo*)CModelInfo::GetModelInfo(defaultModel))->m_pedType;
+	}
+
+	CPed *newPed = CPopulation::AddPed((ePedType)pedType, preferredModel, car->GetPosition());
+	newPed->bUsesCollision = false;
+
+	// what??
+	if (pedType != PEDTYPE_COP) {
+		newPed->SetCurrentWeapon(WEAPONTYPE_COLT45);
+		newPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(newPed->GetWeapon()->m_eWeaponType)->m_nModelId);
+	}
+	/*
+	// Miami leftover
+	if (car->m_vehType == VEHICLE_TYPE_BIKE) {
+		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, *((CBike*)car + 308h), 100.0f);
+	} else */
+
+	// FIX: Make peds comfortable while driving car/boat
+#ifdef FIX_BUGS
+	if (car->IsBoat()) {
+		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+	} else if (car->IsVehicle() && ((CVehicle*)car)->bLowVehicle) {
+		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
+	} else
+#endif
+	{
+		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+	}
+	
+	newPed->StopNonPartialAnims();
+	return newPed;
+}
+
+void
+CPopulation::MoveCarsAndPedsOutOfAbandonedZones()
+{
+	eLevelName level;
+	int zone;
+	int frame = CTimer::GetFrameCounter() & 7;
+	if (frame == 1) {
+		int movedVehicleCount = 0;
+		int poolSize = CPools::GetVehiclePool()->GetSize();
+		for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
+
+			CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
+			if (veh && veh->m_nZoneLevel == LEVEL_NONE && veh->IsCar()) {
+
+				if(veh->m_status != STATUS_ABANDONED && veh->m_status != STATUS_WRECKED && veh->m_status != STATUS_PLAYER &&
+					veh->m_status != STATUS_PLAYER_REMOTE) {
+
+					CVector vehPos(veh->GetPosition());
+					CPopulation::FindCollisionZoneForCoors(&vehPos, &zone, &level);
+
+					// Level 0 is transition zones, and we don't wanna touch cars on transition zones.
+					if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && vehPos.z > -4.0f) {
+						if (veh->bIsLocked || !veh->CanBeDeleted()) {
+							switch (movedVehicleCount & 3) {
+								case 0:
+									veh->GetPosition() = RegenerationPoint_a;
+									break;
+								case 1:
+									veh->GetPosition() = RegenerationPoint_b;
+									break;
+								case 2:
+									veh->GetPosition() = CVector(RegenerationPoint_a.x, RegenerationPoint_b.y, RegenerationPoint_a.z);
+									break;
+								case 3:
+									veh->GetPosition() = CVector(RegenerationPoint_b.x, RegenerationPoint_a.y, RegenerationPoint_a.z);
+									break;
+								default:
+									break;
+							}
+							veh->GetPosition().z += (movedVehicleCount / 4) * 7.0f;
+							veh->GetForward() = RegenerationForward;
+							((CAutomobile*)veh)->PlaceOnRoadProperly();
+							CCarCtrl::JoinCarWithRoadSystem(veh);
+							CTheScripts::ClearSpaceForMissionEntity(veh->GetPosition(), veh);
+							++movedVehicleCount;
+						} else {
+							CWorld::Remove(veh);
+							delete veh;
+						}
+					}
+				}
+			}
+		}
+	} else if (frame == 5) {
+		int poolSize = CPools::GetPedPool()->GetSize();
+		for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
+
+			CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);
+			if (ped && ped->m_nZoneLevel == LEVEL_NONE && !ped->bInVehicle) {
+
+				CVector pedPos(ped->GetPosition());
+				CPopulation::FindCollisionZoneForCoors(&pedPos, &zone, &level);
+
+				// Level 0 is transition zones, and we don't wanna touch peds on transition zones.
+				if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && pedPos.z > -4.0f) {
+					if (ped->CanBeDeleted()) {
+						CWorld::Remove(ped);
+						delete ped;
+					} else if (ped->m_nPedType != PEDTYPE_PLAYER1 && ped->m_nPedType != PEDTYPE_PLAYER2) {
+						ped->GetPosition() = RegenerationPoint_a;
+
+						bool foundGround;
+						float groundZ = CWorld::FindGroundZFor3DCoord(ped->GetPosition().x, ped->GetPosition().y,
+							ped->GetPosition().z + 2.0f, &foundGround);
+
+						if (foundGround) {
+							ped->GetPosition().z = 1.0f + groundZ;
+							//ped->GetPosition().z += 0.0f;
+							CTheScripts::ClearSpaceForMissionEntity(ped->GetPosition(), ped);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+void
+CPopulation::ConvertAllObjectsToDummyObjects()
+{
+	int poolSize = CPools::GetObjectPool()->GetSize();
+	for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
+
+		CObject *obj = CPools::GetObjectPool()->GetSlot(poolIndex);
+
+		if (obj) {
+			if (obj->CanBeDeleted())
+				ConvertToDummyObject(obj);
+		}
+	}
+}
+
+void
+CPopulation::ConvertToRealObject(CDummyObject *dummy)
+{
+	if (!TestSafeForRealObject(dummy))
+		return;
+
+	CObject *obj = new CObject(dummy);
+	if (!obj)
+		return;
+
+	bool makeInvisible;
+	CWorld::Remove(dummy);
+	delete dummy;
+	CWorld::Add(obj);
+	int16 mi = obj->m_modelIndex;
+	if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 ||
+		mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8)
+		makeInvisible = true;
+	else
+		makeInvisible = false;
+
+	if (makeInvisible) {
+		obj->bIsVisible = false;
+	} else if (obj->m_modelIndex == MI_BUOY) {
+		obj->bIsStatic = false;
+		obj->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);
+		obj->m_flagD8 = true;
+		obj->AddToMovingList();
+	}
+}
+
+void
+CPopulation::ConvertToDummyObject(CObject *obj)
+{
+	CDummyObject *dummy = new CDummyObject(obj);
+	if (!dummy)
+		return;
+
+	dummy->GetMatrix() = obj->GetMatrix();
+	dummy->GetMatrix().UpdateRW();
+	dummy->UpdateRwFrame();
+
+	bool makeInvisible;
+	int16 mi = obj->m_modelIndex;
+	if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 ||
+		mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8)
+		makeInvisible = true;
+	else
+		makeInvisible = false;
+
+	if (makeInvisible) {
+		dummy->bIsVisible = false;
+	}
+
+	CWorld::Remove(obj);
+	delete obj;
+	CWorld::Add(dummy);
+}
+
+bool
+CPopulation::TestRoomForDummyObject(CObject *obj)
+{
+	int16 collidingObjs;
+	CWorld::FindObjectsKindaColliding(obj->GetPosition(),
+		CModelInfo::GetModelInfo(obj->m_modelIndex)->GetColModel()->boundingSphere.radius,
+		false, &collidingObjs, 2, nil, false, true, true, false, false);
+
+	return collidingObjs == 0;
+}
+
 STARTPATCHES
 	InjectHook(0x4F3770, &CPopulation::Initialise, PATCH_JUMP);
 	InjectHook(0x4F5780, &CPopulation::ChooseGangOccupation, PATCH_JUMP);
@@ -728,4 +1013,8 @@ STARTPATCHES
 	InjectHook(0x4F6010, &CPopulation::FindCollisionZoneForCoors, PATCH_JUMP);
 	InjectHook(0x4F6410, &CPopulation::PedCreationDistMultiplier, PATCH_JUMP);
 	InjectHook(0x4F5280, &CPopulation::AddPed, PATCH_JUMP);
+	InjectHook(0x4F4470, &CPopulation::ConvertToRealObject, PATCH_JUMP);
+	InjectHook(0x4F4690, &CPopulation::TestRoomForDummyObject, PATCH_JUMP);
+	InjectHook(0x4F45A0, &CPopulation::ConvertToDummyObject, PATCH_JUMP);
+	InjectHook(0x4F4410, &CPopulation::ConvertAllObjectsToDummyObjects, PATCH_JUMP);
 ENDPATCHES
\ No newline at end of file
diff --git a/src/peds/Population.h b/src/peds/Population.h
index f22926a0..152fb7ae 100644
--- a/src/peds/Population.h
+++ b/src/peds/Population.h
@@ -67,7 +67,7 @@ public:
 	static void LoadPedGroups();
 	static void UpdatePedCount(ePedType, bool);
 	static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool);
-	static CPed *AddPedInCar(CVehicle *vehicle);
+	static CPed *AddPedInCar(CVehicle *car);
 	static bool IsPointInSafeZone(CVector *coors);
 	static void RemovePed(CPed *ent);
 	static int32 ChooseCivilianOccupation(int32);
@@ -81,5 +81,9 @@ public:
 	static void AddToPopulation(float, float, float, float);
 	static void ManagePopulation(void);
 	static void MoveCarsAndPedsOutOfAbandonedZones(void);
-	static void ConvertToRealObject(CDummyObject* obj);
+	static void ConvertToRealObject(CDummyObject*);
+	static void ConvertToDummyObject(CObject*);
+	static void ConvertAllObjectsToDummyObjects(void);
+	static bool TestRoomForDummyObject(CObject*);
+	static bool TestSafeForRealObject(CDummyObject*);
 };

From ae523a09a7c12ff3c1fd9cb61e741cf09702b3fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?eray=20or=C3=A7unus?= <erayorcunus@gmail.com>
Date: Sun, 1 Mar 2020 04:43:30 +0300
Subject: [PATCH 2/3] fixes

---
 src/control/Script.cpp  |  8 ++++++++
 src/peds/Ped.cpp        | 23 +++++++++++++++++++++--
 src/peds/PlayerPed.cpp  |  6 +++++-
 src/peds/Population.cpp | 11 +++++------
 src/vehicles/Vehicle.h  |  4 +++-
 5 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 4ef3821e..5daf12f5 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -2815,7 +2815,11 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
 			pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
 		pVehicle->bEngineOn = true;
 		pPed->bUsesCollision = false;
+#ifdef FIX_BUGS
+		AnimationId anim = pVehicle->GetDriverAnim();
+#else
 		AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT;
+#endif
 		pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f);
 		pPed->StopNonPartialAnims();
 		pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition());
@@ -4009,7 +4013,11 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
 		pPed->SetPedState(PED_DRIVING);
 		pVehicle->m_status = STATUS_PHYSICS;
 		pPed->bUsesCollision = false;
+#ifdef FIX_BUGS
+		AnimationId anim = pVehicle->GetDriverAnim();
+#else
 		AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT;
+#endif
 		pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f);
 		pPed->StopNonPartialAnims();
 		pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition());
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 3e9bfc51..8803b5ec 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -237,7 +237,8 @@ static char PersonalityTypeText[][18] = {
 	"Geek Girl",
 	"Old Girl",
 	"Tough Girl",
-	"Tramp",
+	"Tramp Male",
+	"Tramp Female",
 	"Tourist",
 	"Prostitute",
 	"Criminal",
@@ -246,6 +247,8 @@ static char PersonalityTypeText[][18] = {
 	"Psycho",
 	"Steward",
 	"Sports Fan",
+	"Shopper",
+	"Old Shopper"
 };
 
 static char WaitStateText[][16] = {
@@ -16662,6 +16665,14 @@ CPed::WarpPedIntoCar(CVehicle *car)
 		car->bEngineOn = true;
 		DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
 	}
+
+#ifdef VC_PED_PORTS
+	RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
+
+	// VC uses AddInCarAnims but we don't have that
+	m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+	RemoveWeaponWhenEnteringVehicle();
+#else
 	if (car->IsBoat()) {
 		m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
 		CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
@@ -16675,6 +16686,8 @@ CPed::WarpPedIntoCar(CVehicle *car)
 		else
 			m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
 	}
+#endif
+
 	StopNonPartialAnims();
 	if (car->bIsBus)
 		bRenderPedInCar = false;
@@ -16904,11 +16917,17 @@ CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
 	m_vecOffsetSeek = doorOpenPos - GetPosition();
 	m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
 	if (car->IsBoat()) {
-		m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
 #ifdef VC_PED_PORTS
+		// VC checks for handling flag, but we can't do that
+		if(car->GetModelIndex() == MI_SPEEDER)
+			m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+		else
+			m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+
 		PedSetInCarCB(nil, this);
 		m_ped_flagI4 = true;
 #else
+		m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
 		m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);
 #endif
 		if (IsPlayer())
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 9d4adcef..b459ed84 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -79,7 +79,11 @@ void
 CPlayerPed::MakeObjectTargettable(int32 handle)
 {
 	for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
-		if (CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {
+		if (
+#ifdef FIX_BUGS
+			m_nTargettableObjects[i] == -1 ||
+#endif
+			CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {
 			m_nTargettableObjects[i] = handle;
 			return;
 		}
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index 6ffb65ba..6b15d8c7 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -820,15 +820,14 @@ CPopulation::AddPedInCar(CVehicle* car)
 
 	// FIX: Make peds comfortable while driving car/boat
 #ifdef FIX_BUGS
-	if (car->IsBoat()) {
-		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
-	} else if (car->IsVehicle() && ((CVehicle*)car)->bLowVehicle) {
-		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
-	} else
-#endif
+	{
+		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+	}
+#else
 	{
 		newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
 	}
+#endif
 	
 	newPed->StopNonPartialAnims();
 	return newPed;
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 7e99258c..bd8df694 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -3,6 +3,7 @@
 #include "Physical.h"
 #include "AutoPilot.h"
 #include "ModelIndices.h"
+#include "AnimManager.h"
 
 class CPed;
 class CFire;
@@ -269,7 +270,8 @@ 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; }
-	
+	AnimationId GetDriverAnim(void) { return IsCar() && bLowVehicle ? ANIM_CAR_LSIT : (IsBoat() && GetModelIndex() != MI_SPEEDER ? ANIM_DRIVE_BOAT : ANIM_CAR_SIT); }
+
 	static bool &bWheelsOnlyCheat;
 	static bool &bAllDodosCheat;
 	static bool &bCheat3;

From 5eccf44e7a4c7628beac2faaa87cbe9560133ff8 Mon Sep 17 00:00:00 2001
From: Nikolay Korolev <nickvnuk@gmail.com>
Date: Sun, 1 Mar 2020 17:42:47 +0300
Subject: [PATCH 3/3] review fixes

---
 src/control/Script.cpp | 267 +++++++++++++++++++++--------------------
 src/control/Script.h   |  67 +++++------
 2 files changed, 169 insertions(+), 165 deletions(-)

diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index acecc863..b8add76a 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -385,25 +385,30 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total)
 {
 	for (int16 i = 0; i < total; i++){
 		float tmp;
-		switch (Read1ByteFromScript(pIp))
+		uint16 varIndex;
+		switch (CTheScripts::Read1ByteFromScript(pIp))
 		{
 		case ARGUMENT_INT32:
-			ScriptParams[i] = Read4BytesFromScript(pIp);
+			ScriptParams[i] = CTheScripts::Read4BytesFromScript(pIp);
 			break;
 		case ARGUMENT_GLOBALVAR:
-			ScriptParams[i] = *((int32*)&CTheScripts::ScriptSpace[Read2BytesFromScript(pIp)]);
+			varIndex = CTheScripts::Read2BytesFromScript(pIp);
+			assert(varIndex >= 8 && varIndex < CTheScripts::GetSizeOfVariableSpace());
+			ScriptParams[i] = *((int32*)&CTheScripts::ScriptSpace[varIndex]);
 			break;
 		case ARGUMENT_LOCALVAR:
-			ScriptParams[i] = m_anLocalVariables[Read2BytesFromScript(pIp)];
+			varIndex = CTheScripts::Read2BytesFromScript(pIp);
+			assert(varIndex >= 0 && varIndex < ARRAY_SIZE(m_anLocalVariables));
+			ScriptParams[i] = m_anLocalVariables[varIndex];
 			break;
 		case ARGUMENT_INT8:
-			ScriptParams[i] = Read1ByteFromScript(pIp);
+			ScriptParams[i] = CTheScripts::Read1ByteFromScript(pIp);
 			break;
 		case ARGUMENT_INT16:
-			ScriptParams[i] = Read2BytesFromScript(pIp);
+			ScriptParams[i] = CTheScripts::Read2BytesFromScript(pIp);
 			break;
 		case ARGUMENT_FLOAT:
-			tmp = ReadFloatFromScript(pIp);
+			tmp = CTheScripts::ReadFloatFromScript(pIp);
 			ScriptParams[i] = *(int32*)&tmp;
 			break;
 		default:
@@ -417,20 +422,20 @@ int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
 {
 	uint32* pIp = &ip;
 	float tmp;
-	switch (Read1ByteFromScript(pIp))
+	switch (CTheScripts::Read1ByteFromScript(pIp))
 	{
 	case ARGUMENT_INT32:
-		return Read4BytesFromScript(pIp);
+		return CTheScripts::Read4BytesFromScript(pIp);
 	case ARGUMENT_GLOBALVAR:
-		return *((int32*)&CTheScripts::ScriptSpace[Read2BytesFromScript(pIp)]);
+		return *((int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(pIp)]);
 	case ARGUMENT_LOCALVAR:
-		return m_anLocalVariables[Read2BytesFromScript(pIp)];
+		return m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)];
 	case ARGUMENT_INT8:
-		return Read1ByteFromScript(pIp);
+		return CTheScripts::Read1ByteFromScript(pIp);
 	case ARGUMENT_INT16:
-		return Read2BytesFromScript(pIp);
+		return CTheScripts::Read2BytesFromScript(pIp);
 	case ARGUMENT_FLOAT:
-		tmp = ReadFloatFromScript(pIp);
+		tmp = CTheScripts::ReadFloatFromScript(pIp);
 		return *(int32*)&tmp;
 	default:
 		assert(0);
@@ -441,12 +446,12 @@ int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
 void CRunningScript::StoreParameters(uint32* pIp, int16 number)
 {
 	for (int16 i = 0; i < number; i++){
-		switch (Read1ByteFromScript(pIp)) {
+		switch (CTheScripts::Read1ByteFromScript(pIp)) {
 		case ARGUMENT_GLOBALVAR:
-			*(int32*)&CTheScripts::ScriptSpace[Read2BytesFromScript(pIp)] = ScriptParams[i];
+			*(int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(pIp)] = ScriptParams[i];
 			break;
 		case ARGUMENT_LOCALVAR:
-			m_anLocalVariables[Read2BytesFromScript(pIp)] = ScriptParams[i];
+			m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)] = ScriptParams[i];
 			break;
 		default:
 			assert(0);
@@ -456,14 +461,14 @@ void CRunningScript::StoreParameters(uint32* pIp, int16 number)
 
 int32 *CRunningScript::GetPointerToScriptVariable(uint32* pIp, int16 type)
 {
-	switch (Read1ByteFromScript(pIp))
+	switch (CTheScripts::Read1ByteFromScript(pIp))
 	{
 	case ARGUMENT_GLOBALVAR:
 		assert(type == VAR_GLOBAL);
-		return (int32*)&CTheScripts::ScriptSpace[Read2BytesFromScript(pIp)];
+		return (int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(pIp)];
 	case ARGUMENT_LOCALVAR:
 		assert(type == VAR_LOCAL);
-		return &m_anLocalVariables[Read2BytesFromScript(pIp)];
+		return &m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)];
 	default:
 		assert(0);
 	}
@@ -701,7 +706,7 @@ void CRunningScript::Process()
 int8 CRunningScript::ProcessOneCommand()
 {
 	++CTheScripts::CommandsExecuted;
-	int32 command = Read2BytesFromScript(&m_nIp);
+	int32 command = CTheScripts::Read2BytesFromScript(&m_nIp);
 	m_bNotFlag = (command & 0x8000);
 	command &= 0x7FFF;
 	if (command < 100)
@@ -1229,27 +1234,27 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
 		CollectParameters(&m_nIp, 1);
 		assert(ScriptParams[0] >= 0);
 		CRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]);
-		int8 type = Read1ByteFromScript(&m_nIp);
+		int8 type = CTheScripts::Read1ByteFromScript(&m_nIp);
 		float tmp;
-		for (int i = 0; type != ARGUMENT_END; type = Read1ByteFromScript(&m_nIp), i++) {
+		for (int i = 0; type != ARGUMENT_END; type = CTheScripts::Read1ByteFromScript(&m_nIp), i++) {
 			switch (type) {
 			case ARGUMENT_INT32:
-				pNew->m_anLocalVariables[i] = Read4BytesFromScript(&m_nIp);
+				pNew->m_anLocalVariables[i] = CTheScripts::Read4BytesFromScript(&m_nIp);
 				break;
 			case ARGUMENT_GLOBALVAR:
-				pNew->m_anLocalVariables[i] = *(int32*)&CTheScripts::ScriptSpace[Read2BytesFromScript(&m_nIp)];
+				pNew->m_anLocalVariables[i] = *(int32*)&CTheScripts::ScriptSpace[CTheScripts::Read2BytesFromScript(&m_nIp)];
 				break;
 			case ARGUMENT_LOCALVAR:
-				pNew->m_anLocalVariables[i] = m_anLocalVariables[Read2BytesFromScript(&m_nIp)];
+				pNew->m_anLocalVariables[i] = m_anLocalVariables[CTheScripts::Read2BytesFromScript(&m_nIp)];
 				break;
 			case ARGUMENT_INT8:
-				pNew->m_anLocalVariables[i] = Read1ByteFromScript(&m_nIp);
+				pNew->m_anLocalVariables[i] = CTheScripts::Read1ByteFromScript(&m_nIp);
 				break;
 			case ARGUMENT_INT16:
-				pNew->m_anLocalVariables[i] = Read2BytesFromScript(&m_nIp);
+				pNew->m_anLocalVariables[i] = CTheScripts::Read2BytesFromScript(&m_nIp);
 				break;
 			case ARGUMENT_FLOAT:
-				tmp = ReadFloatFromScript(&m_nIp);
+				tmp = CTheScripts::ReadFloatFromScript(&m_nIp);
 				pNew->m_anLocalVariables[i] = *(int32*)&tmp;
 				break;
 			default:
@@ -2671,7 +2676,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
 		CollectParameters(&m_nIp, 1);
 		CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
 		char label[12];
-		ReadTextLabelFromScript(&m_nIp, label);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
 		int zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label);
 		if (zoneToCheck != -1)
 			m_nIp += KEY_LENGTH_IN_SCRIPT; /* why only if zone != 1? */
@@ -2966,7 +2971,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 	}
 	case COMMAND_ADD_PAGER_MESSAGE:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 3);
 		CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]);
 		return 0;
@@ -2975,21 +2980,21 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 	{
 		assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
 		m_nIp++;
-		CUserDisplay::OnscnTimer.AddClock(Read2BytesFromScript(&m_nIp), nil);
+		CUserDisplay::OnscnTimer.AddClock(CTheScripts::Read2BytesFromScript(&m_nIp), nil);
 		return 0;
 	}
 	case COMMAND_CLEAR_ONSCREEN_TIMER:
 	{
 		assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
 		m_nIp++;
-		CUserDisplay::OnscnTimer.ClearClock(Read2BytesFromScript(&m_nIp));
+		CUserDisplay::OnscnTimer.ClearClock(CTheScripts::Read2BytesFromScript(&m_nIp));
 		return 0;
 	}
 	case COMMAND_DISPLAY_ONSCREEN_COUNTER:
 	{
 		assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
 		m_nIp++;
-		int32 counter = Read2BytesFromScript(&m_nIp);
+		int32 counter = CTheScripts::Read2BytesFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 1);
 		CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil);
 		return 0;
@@ -2998,13 +3003,13 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 	{
 		assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
 		m_nIp++;
-		CUserDisplay::OnscnTimer.ClearCounter(Read2BytesFromScript(&m_nIp));
+		CUserDisplay::OnscnTimer.ClearCounter(CTheScripts::Read2BytesFromScript(&m_nIp));
 		return 0;
 	}
 	case COMMAND_SET_ZONE_CAR_INFO:
 	{
 		char label[12];
-		ReadTextLabelFromScript(&m_nIp, label);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
 		m_nIp += KEY_LENGTH_IN_SCRIPT;
 		CollectParameters(&m_nIp, 16);
 		int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
@@ -3027,7 +3032,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
 		assert(pPed);
 		char label[12];
-		ReadTextLabelFromScript(&m_nIp, label);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
 		int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
 		if (zone != -1)
 			m_nIp += KEY_LENGTH_IN_SCRIPT;
@@ -3038,7 +3043,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 	case COMMAND_SET_CAR_DENSITY:
 	{
 		char label[12];
-		ReadTextLabelFromScript(&m_nIp, label);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
 		int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
 		m_nIp += 8;
 		CollectParameters(&m_nIp, 2);
@@ -3052,7 +3057,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 	case COMMAND_SET_PED_DENSITY:
 	{
 		char label[12];
-		ReadTextLabelFromScript(&m_nIp, label);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
 		int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
 		m_nIp += KEY_LENGTH_IN_SCRIPT;
 		CollectParameters(&m_nIp, 2);
@@ -3095,7 +3100,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 	case COMMAND_SET_ZONE_PED_INFO:
 	{
 		char label[12];
-		ReadTextLabelFromScript(&m_nIp, label);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
 		m_nIp += KEY_LENGTH_IN_SCRIPT;
 		CollectParameters(&m_nIp, 10);
 		int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
@@ -3387,11 +3392,11 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
 	case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE:
 	*/
 	case COMMAND_DECLARE_MISSION_FLAG:
-		CTheScripts::OnAMissionFlag = Read2BytesFromScript(&++m_nIp);
+		CTheScripts::OnAMissionFlag = CTheScripts::Read2BytesFromScript(&++m_nIp);
 		return 0;
 	case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:
 		CollectParameters(&m_nIp, 1);
-		CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = Read2BytesFromScript(&++m_nIp);
+		CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = CTheScripts::Read2BytesFromScript(&++m_nIp);
 		return 0;
 	case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT:
 		CollectParameters(&m_nIp, 2);
@@ -4201,21 +4206,21 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
 	}
 	case COMMAND_PRINT_WITH_NUMBER_BIG:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 3);
 		CMessages::AddBigMessageWithNumber(text, ScriptParams[1], ScriptParams[2] - 1, ScriptParams[0], -1, -1, -1, -1, -1);
 		return 0;
 	}
 	case COMMAND_PRINT_WITH_NUMBER:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 3);
 		CMessages::AddMessageWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);
 		return 0;
 	}
 	case COMMAND_PRINT_WITH_NUMBER_NOW:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 3);
 		CMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);
 		return 0;
@@ -4405,7 +4410,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
 	}
 	case COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 4);
 		CUserDisplay::Pager.AddMessageWithNumber(text, ScriptParams[0], -1, -1, -1, -1, -1,
 			ScriptParams[1], ScriptParams[2], ScriptParams[3]);
@@ -4413,7 +4418,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
 	}
 	case COMMAND_START_KILL_FRENZY:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		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],
@@ -4590,14 +4595,14 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
 	}
 	case COMMAND_PRINT_BIG_Q:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 2);
 		CMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1);
 		return 0;
 	}
 	case COMMAND_PRINT_WITH_NUMBER_BIG_Q:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 3);
 		CMessages::AddBigMessageWithNumberQ(text, ScriptParams[1], ScriptParams[2] - 1,
 			ScriptParams[0], -1, -1, -1, -1, -1);
@@ -5114,14 +5119,14 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
 	case COMMAND_SET_REPEATED_PHONE_MESSAGE:
 	{
 		CollectParameters(&m_nIp, 1);
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text, nil, nil, nil, nil, nil);
 		return 0;
 	}
 	case COMMAND_SET_PHONE_MESSAGE:
 	{
 		CollectParameters(&m_nIp, 1);
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text, nil, nil, nil, nil, nil);
 		return 0;
 	}
@@ -6191,105 +6196,105 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
 	}
 	case COMMAND_PRINT_WITH_2_NUMBERS:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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;
@@ -6485,7 +6490,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 	case COMMAND_SET_ZONE_GROUP:
 	{
 		char zone[KEY_LENGTH_IN_SCRIPT];
-		ReadTextLabelFromScript(&m_nIp, zone);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
 		m_nIp += KEY_LENGTH_IN_SCRIPT;
 		CollectParameters(&m_nIp, 2);
 		int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
@@ -6547,7 +6552,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 	case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE:
 	{
 		char zone[KEY_LENGTH_IN_SCRIPT];
-		ReadTextLabelFromScript(&m_nIp, zone);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
 		int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
 		if (zone_id != -1)
 			m_nIp += KEY_LENGTH_IN_SCRIPT;
@@ -6746,7 +6751,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 	case COMMAND_DISPLAY_TEXT:
 	{
 		CollectParameters(&m_nIp, 2);
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		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);
@@ -6991,7 +6996,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 		CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
 		assert(pPed);
 		char name[KEY_LENGTH_IN_SCRIPT];
-		ReadTextLabelFromScript(&m_nIp, name);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, name);
 		for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
 			name[i] = tolower(name[i]);
 		int mi = pPed->GetModelIndex();
@@ -7053,7 +7058,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 	{
 		CollectParameters(&m_nIp, 1);
 		char zone[KEY_LENGTH_IN_SCRIPT];
-		ReadTextLabelFromScript(&m_nIp, zone);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
 		int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
 		if (zone_id != -1)
 			m_nIp += KEY_LENGTH_IN_SCRIPT;
@@ -7234,7 +7239,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 	}
 	case COMMAND_START_KILL_FRENZY_HEADSHOT:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		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],
@@ -7288,35 +7293,35 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 	//case COMMAND_SET_AUDIO_STREAM:
 	case COMMAND_PRINT_WITH_2_NUMBERS_BIG:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
+		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;
@@ -7338,8 +7343,8 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 		return 0;
 	case COMMAND_PRINT_STRING_IN_STRING:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
-		wchar* string = GetTextByKeyFromScript(&m_nIp);
+		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;
@@ -7394,54 +7399,54 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
 	case COMMAND_SET_2_REPEATED_PHONE_MESSAGES:
 	{
 		CollectParameters(&m_nIp, 1);
-		wchar* text1 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text4 = GetTextByKeyFromScript(&m_nIp);
+		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 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text4 = GetTextByKeyFromScript(&m_nIp);
+		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;
 	}
@@ -7518,8 +7523,8 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
 	switch (command) {
 	case COMMAND_PRINT_STRING_IN_STRING_NOW:
 	{
-		wchar* source = GetTextByKeyFromScript(&m_nIp);
-		wchar* pstr = GetTextByKeyFromScript(&m_nIp);
+		wchar* source = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* pstr = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 2);
 		CMessages::AddMessageJumpQWithString(source, ScriptParams[0], ScriptParams[1], pstr);
 		return 0;
@@ -7528,46 +7533,46 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
 	case COMMAND_SET_5_REPEATED_PHONE_MESSAGES:
 	{
 		CollectParameters(&m_nIp, 1);
-		wchar* text1 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text4 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text5 = GetTextByKeyFromScript(&m_nIp);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, nil);
 		return 0;
 	}
 	case COMMAND_SET_5_PHONE_MESSAGES:
 	{
 		CollectParameters(&m_nIp, 1);
-		wchar* text1 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text4 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text5 = GetTextByKeyFromScript(&m_nIp);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, nil);
 		return 0;
 	}
 	case COMMAND_SET_6_REPEATED_PHONE_MESSAGES:
 	{
 		CollectParameters(&m_nIp, 1);
-		wchar* text1 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text4 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text5 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text6 = GetTextByKeyFromScript(&m_nIp);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, text6);
 		return 0;
 	}
 	case COMMAND_SET_6_PHONE_MESSAGES:
 	{
 		CollectParameters(&m_nIp, 1);
-		wchar* text1 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text2 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text3 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text4 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text5 = GetTextByKeyFromScript(&m_nIp);
-		wchar* text6 = GetTextByKeyFromScript(&m_nIp);
+		wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+		wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6);
 		return 0;
 	}
@@ -8071,7 +8076,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
 	case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING:
 	{
 		assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
-		int16 var = Read2BytesFromScript(&m_nIp);
+		int16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
 		wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
 		strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
 		m_nIp += KEY_LENGTH_IN_SCRIPT;
@@ -8081,7 +8086,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
 	case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING:
 	{
 		assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
-		int16 var = Read2BytesFromScript(&m_nIp);
+		int16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
 		CollectParameters(&m_nIp, 1);
 		wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
 		strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
@@ -8297,13 +8302,13 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
 	}
 	case COMMAND_CLEAR_THIS_PRINT:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CMessages::ClearThisPrint(text);
 		return 0;
 	}
 	case COMMAND_CLEAR_THIS_BIG_PRINT:
 	{
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CMessages::ClearThisBigPrint(text);
 		return 0;
 	}
@@ -8393,7 +8398,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
 			m_nIp += KEY_LENGTH_IN_SCRIPT;
 			return 0;
 		}
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CHud::SetHelpMessage(text, false);
 		return 0;
 	}
@@ -9134,7 +9139,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
 		CTimer::Update();
 		return 0;
 	case COMMAND_LOAD_SPLASH_SCREEN:
-		ReadTextLabelFromScript(&m_nIp, tmp);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
 		for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
 			tmp[i] = tolower(tmp[i]);
 		m_nIp += 8;
@@ -9236,7 +9241,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
 	}
 	case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME:
 	{
-		ReadTextLabelFromScript(&m_nIp, tmp);
+		CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
 		for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
 			tmp[i] = tolower(tmp[i]);
 		m_nIp += 8;
@@ -9254,7 +9259,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
 	case COMMAND_DISPLAY_TEXT_WITH_NUMBER:
 	{
 		CollectParameters(&m_nIp, 2);
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
 		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
 		CollectParameters(&m_nIp, 1);
@@ -9265,7 +9270,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
 	case COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS:
 	{
 		CollectParameters(&m_nIp, 2);
-		wchar* text = GetTextByKeyFromScript(&m_nIp);
+		wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
 		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];
 		CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];
 		CollectParameters(&m_nIp, 2);
@@ -9680,7 +9685,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
 
 int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index)
 {
-	if (ScriptSphereArray[index].m_Index >= 0xFFFE)
+	if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1)
 		ScriptSphereArray[index].m_Index = 1;
 	else
 		ScriptSphereArray[index].m_Index++;
diff --git a/src/control/Script.h b/src/control/Script.h
index 18d148bf..59054be3 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -292,11 +292,43 @@ public:
 	static bool IsDebugOn() { return DbgFlag; };
 	static void InvertDebugFlag() { DbgFlag = !DbgFlag; }
 
-	static int32* GetPointerToScriptVariable(int32 offset) { return (int32*)&ScriptSpace[offset]; }
+	static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; }
 
 	static void ResetCountdownToMakePlayerUnsafe() { CountdownToMakePlayerUnsafe = 0; }
 	static bool IsCountdownToMakePlayerUnsafeOn() { return CountdownToMakePlayerUnsafe != 0; }
 
+	static int32 Read4BytesFromScript(uint32* pIp) {
+		int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
+		*pIp += 4;
+		return retval;
+	}
+	static int16 Read2BytesFromScript(uint32* pIp) {
+		int16 retval = ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
+		*pIp += 2;
+		return retval;
+	}
+	static int8 Read1ByteFromScript(uint32* pIp) {
+		int8 retval = ScriptSpace[*pIp];
+		*pIp += 1;
+		return retval;
+	}
+	static float ReadFloatFromScript(uint32* pIp) {
+		return Read2BytesFromScript(pIp) / 16.0f;
+	}
+	static void ReadTextLabelFromScript(uint32* pIp, char* buf) {
+		strncpy(buf, (const char*)&CTheScripts::ScriptSpace[*pIp], KEY_LENGTH_IN_SCRIPT);
+	}
+	static wchar* GetTextByKeyFromScript(uint32* pIp) {
+		wchar* text = TheText.Get((const char*)&CTheScripts::ScriptSpace[*pIp]);
+		*pIp += KEY_LENGTH_IN_SCRIPT;
+		return text;
+	}
+	static int32 GetSizeOfVariableSpace()
+	{
+		uint32 tmp = 3;
+		return Read4BytesFromScript(&tmp);
+	}
+
 private:
 
 	static CRunningScript* StartNewScript(uint32);
@@ -387,39 +419,6 @@ public:
 		m_anLocalVariables[NUM_LOCAL_VARS + 1] += timeStep;
 	}
 
-	static int32 Read4BytesFromScript(uint32* pIp) {
-		int32 retval = 0;
-		for (int i = 0; i < 4; i++) {
-			retval |= CTheScripts::ScriptSpace[(*pIp)++] << (8 * i);
-		}
-		return retval;
-	}
-	static int16 Read2BytesFromScript(uint32* pIp) {
-		int16 retval = 0;
-		for (int i = 0; i < 2; i++) {
-			retval |= CTheScripts::ScriptSpace[(*pIp)++] << (8 * i);
-		}
-		return retval;
-	}
-	static int8 Read1ByteFromScript(uint32* pIp) {
-		int8 retval = 0;
-		for (int i = 0; i < 1; i++) {
-			retval |= CTheScripts::ScriptSpace[(*pIp)++] << (8 * i);
-		}
-		return retval;
-	}
-	static float ReadFloatFromScript(uint32* pIp) {
-		return Read2BytesFromScript(pIp) / 16.0f;
-	}
-	static void ReadTextLabelFromScript(uint32* pIp, char* buf) {
-		strncpy(buf, (const char*)&CTheScripts::ScriptSpace[*pIp], KEY_LENGTH_IN_SCRIPT);
-	}
-	static wchar* GetTextByKeyFromScript(uint32* pIp) {
-		wchar* text = TheText.Get((const char*)&CTheScripts::ScriptSpace[*pIp]);
-		*pIp += KEY_LENGTH_IN_SCRIPT;
-		return text;
-	}
-
 	void Init();
 	void Process();