summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/control/Script.cpp10
-rw-r--r--src/core/Frontend.cpp140
-rw-r--r--src/core/Frontend.h8
-rw-r--r--src/objects/Object.cpp40
-rw-r--r--src/objects/Object.h3
-rw-r--r--src/peds/Ped.cpp42
-rw-r--r--src/peds/PlayerPed.cpp6
-rw-r--r--src/peds/Population.cpp304
-rw-r--r--src/peds/Population.h8
-rw-r--r--src/vehicles/Vehicle.h4
10 files changed, 466 insertions, 99 deletions
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index dab68e5a..acecc863 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -2769,7 +2769,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());
@@ -3711,7 +3715,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--;
@@ -3963,7 +3967,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/core/Frontend.cpp b/src/core/Frontend.cpp
index 181ceb60..069a9caf 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::IsDebugOn() ? "FEM_ON" : "FEM_OFF");
+ rightText = TheText.Get(CTheScripts::IsDebugOn() ? "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..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] = {
@@ -1519,7 +1522,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 +2957,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 +2973,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 +4169,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 +13614,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
@@ -16651,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);
@@ -16664,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;
@@ -16893,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 a2dd5c38..6b15d8c7 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,291 @@ 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
+ {
+ 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;
+}
+
+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 +1012,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*);
};
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;