summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2020-06-01 10:44:33 +0200
committerGitHub <noreply@github.com>2020-06-01 10:44:33 +0200
commit6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0 (patch)
tree5f09d5f4358b1518262068d65ac713993b2cf437
parentMerge branch 'miami' of https://github.com/GTAmodding/re3 into miami (diff)
parentfix (diff)
downloadre3-6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0.tar
re3-6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0.tar.gz
re3-6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0.tar.bz2
re3-6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0.tar.lz
re3-6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0.tar.xz
re3-6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0.tar.zst
re3-6d3e54369ce9ac826ab7c74da4be1c15d3ff3df0.zip
-rw-r--r--src/audio/sampman.h4
-rw-r--r--src/audio/sampman_miles.cpp11
-rw-r--r--src/audio/sampman_null.cpp4
-rw-r--r--src/audio/sampman_oal.cpp12
-rw-r--r--src/control/CarCtrl.h2
-rw-r--r--src/control/Darkel.cpp3
-rw-r--r--src/control/GameLogic.cpp324
-rw-r--r--src/control/GameLogic.h38
-rw-r--r--src/control/PathFind.h6
-rw-r--r--src/control/RoadBlocks.cpp242
-rw-r--r--src/control/RoadBlocks.h18
-rw-r--r--src/control/Script.cpp48
-rw-r--r--src/core/Camera.cpp2
-rw-r--r--src/core/Fire.cpp13
-rw-r--r--src/core/Game.cpp1
-rw-r--r--src/core/Pad.h9
-rw-r--r--src/core/PlayerInfo.cpp2
-rw-r--r--src/core/PlayerInfo.h9
-rw-r--r--src/core/User.cpp4
-rw-r--r--src/core/config.h5
-rw-r--r--src/math/Matrix.h8
-rw-r--r--src/peds/Ped.cpp36
-rw-r--r--src/peds/Ped.h2
-rw-r--r--src/render/Particle.h2
-rw-r--r--src/save/GenericGameStorage.cpp4
25 files changed, 662 insertions, 147 deletions
diff --git a/src/audio/sampman.h b/src/audio/sampman.h
index 655efb5c..b539854c 100644
--- a/src/audio/sampman.h
+++ b/src/audio/sampman.h
@@ -126,10 +126,10 @@ public:
void StartChannel (uint32 nChannel);
void StopChannel (uint32 nChannel);
- void PreloadStreamedFile (uint8 nFile, uint8 nStream);
+ void PreloadStreamedFile (uint32 nFile, uint8 nStream);
void PauseStream (uint8 nPauseFlag, uint8 nStream);
void StartPreloadedStreamedFile (uint8 nStream);
- bool StartStreamedFile (uint8 nFile, uint32 nPos, uint8 nStream);
+ bool StartStreamedFile (uint32 nFile, uint32 nPos, uint8 nStream);
void StopStreamedFile (uint8 nStream);
int32 GetStreamedFilePosition (uint8 nStream);
void SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream);
diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp
index 63e89cac..5893ea64 100644
--- a/src/audio/sampman_miles.cpp
+++ b/src/audio/sampman_miles.cpp
@@ -2030,7 +2030,7 @@ cSampleManager::StopChannel(uint32 nChannel)
}
void
-cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream)
+cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
{
if ( m_bInitialised )
{
@@ -2081,7 +2081,7 @@ cSampleManager::StartPreloadedStreamedFile(uint8 nStream)
}
bool
-cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream)
+cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
{
uint32 position = nPos;
char filename[MAX_PATH];
@@ -2287,7 +2287,12 @@ cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffect
if ( mp3Stream[nStream] )
{
if ( nEffectFlag )
- AIL_set_stream_volume(mp3Stream[nStream], m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14);
+ {
+ if ( nStream == 1 ) // TODO(MIAMI): || nStream == 2 when we have second mission channel?
+ AIL_set_stream_volume(mp3Stream[nStream], 128*vol*m_nEffectsVolume >> 14);
+ else
+ AIL_set_stream_volume(mp3Stream[nStream], m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14);
+ }
else
AIL_set_stream_volume(mp3Stream[nStream], m_nMusicFadeVolume*vol*m_nMusicVolume >> 14);
diff --git a/src/audio/sampman_null.cpp b/src/audio/sampman_null.cpp
index 6ec8a521..3638e6fb 100644
--- a/src/audio/sampman_null.cpp
+++ b/src/audio/sampman_null.cpp
@@ -297,7 +297,7 @@ cSampleManager::StopChannel(uint32 nChannel)
}
void
-cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream)
+cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
{
ASSERT( nStream < MAX_STREAMS );
}
@@ -315,7 +315,7 @@ cSampleManager::StartPreloadedStreamedFile(uint8 nStream)
}
bool
-cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream)
+cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
{
ASSERT( nStream < MAX_STREAMS );
diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp
index 5092a4b1..de55c2ed 100644
--- a/src/audio/sampman_oal.cpp
+++ b/src/audio/sampman_oal.cpp
@@ -1168,7 +1168,7 @@ cSampleManager::StopChannel(uint32 nChannel)
}
void
-cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream)
+cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
{
char filename[256];
@@ -1226,7 +1226,7 @@ cSampleManager::StartPreloadedStreamedFile(uint8 nStream)
}
bool
-cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream)
+cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
{
char filename[256];
@@ -1317,8 +1317,12 @@ cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffect
if ( stream )
{
- if ( nEffectFlag )
- stream->SetVolume(m_nEffectsFadeVolume*nVolume*m_nEffectsVolume >> 14);
+ if ( nEffectFlag ) {
+ if ( nStream == 1 ) // TODO(MIAMI): || nStream == 2 when we have second mission channel?
+ stream->SetVolume(128*nVolume*m_nEffectsVolume >> 14);
+ else
+ stream->SetVolume(m_nEffectsFadeVolume*nVolume*m_nEffectsVolume >> 14);
+ }
else
stream->SetVolume(m_nMusicFadeVolume*nVolume*m_nMusicVolume >> 14);
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index ed63a0e2..6b4e94ee 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -16,8 +16,6 @@ enum{
MAX_CAR_MODELS_IN_ARRAY = 25,
};
-#define LANE_WIDTH 5.0f
-
#ifdef FIX_BUGS
#define FIX_PATHFIND_BUG
#endif
diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp
index cfd58340..b6489ef2 100644
--- a/src/control/Darkel.cpp
+++ b/src/control/Darkel.cpp
@@ -13,6 +13,7 @@
#include "Font.h"
#include "Text.h"
#include "Vehicle.h"
+#include "GameLogic.h"
#define FRENZY_ANY_PED -1
#define FRENZY_ANY_CAR -2
@@ -246,6 +247,8 @@ CDarkel::ResetOnPlayerDeath()
void
CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot)
{
+ CGameLogic::ClearShortCut();
+ CGameLogic::RemoveShortCutDropOffPointForMission();
eWeaponType fixedWeapon;
if (weaponType == WEAPONTYPE_UZI_DRIVEBY)
fixedWeapon = WEAPONTYPE_UZI;
diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp
index abb5c5f3..6cfaa042 100644
--- a/src/control/GameLogic.cpp
+++ b/src/control/GameLogic.cpp
@@ -19,13 +19,42 @@
#include "Fire.h"
#include "Script.h"
#include "Garages.h"
+#include "Population.h"
+#include "General.h"
+#include "DMAudio.h"
+#include "Radar.h"
+#include "Pools.h"
+#include "Hud.h"
+#include "Particle.h"
+#include "ColStore.h"
+#include "Automobile.h"
uint8 CGameLogic::ActivePlayers;
+uint8 CGameLogic::ShortCutState;
+CAutomobile* CGameLogic::pShortCutTaxi;
+uint32 CGameLogic::NumAfterDeathStartPoints;
+CVector CGameLogic::ShortCutStart;
+float CGameLogic::ShortCutStartOrientation;
+CVector CGameLogic::ShortCutDestination;
+float CGameLogic::ShortCutDestinationOrientation;
+uint32 CGameLogic::ShortCutTimer;
+CVector CGameLogic::AfterDeathStartPoints[NUM_SHORTCUT_START_POINTS];
+float CGameLogic::AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS];
+CVector CGameLogic::ShortCutDropOffForMission;
+float CGameLogic::ShortCutDropOffOrientationForMission;
+bool CGameLogic::MissionDropOffReadyToBeUsed;
+
+//--MIAMI: file done except TODO
+
+#define SHORTCUT_TAXI_COST (9)
void
CGameLogic::InitAtStartOfGame()
{
ActivePlayers = 1;
+ ShortCutState = SHORTCUT_NONE;
+ pShortCutTaxi = nil;
+ NumAfterDeathStartPoints = 0;
}
void
@@ -58,7 +87,10 @@ CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
CStreaming::DeleteRwObjectsAfterDeath(pos);
CStreaming::RemoveUnusedModelsInLoadedList();
CGame::DrasticTidyUpMemory(true);
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed->Undress("player");
+ CStreaming::LoadSceneCollision(pos);
CStreaming::LoadScene(pos);
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed->Dress();
CTimer::Update();
}
@@ -70,7 +102,9 @@ CGameLogic::Update()
if (CCutsceneMgr::IsCutsceneProcessing()) return;
+ UpdateShortCut();
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
+
switch (pPlayerInfo.m_WBState) {
case WBSTATE_PLAYING:
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
@@ -93,7 +127,7 @@ CGameLogic::Update()
if (pPlayerInfo.m_bGetOutOfHospitalFree) {
pPlayerInfo.m_bGetOutOfHospitalFree = false;
} else {
- pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - 1000);
+ pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - 100);
pPlayerInfo.m_pPed->ClearWeapons();
}
@@ -117,17 +151,20 @@ CGameLogic::Update()
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ AfterDeathArrestSetUpShortCutTaxi();
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
+ CPopulation::m_CountDownToPedsAtStart = 10;
+ CCarCtrl::CountDownToCarsAtStart = 10;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextDeath) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextDeath = true;
+ } else
+ CRestart::bFadeInAfterNextDeath = true;
}
break;
case WBSTATE_BUSTED:
@@ -135,7 +172,30 @@ CGameLogic::Update()
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
+
+ if (!CTheScripts::IsPlayerOnAMission() && pPlayerInfo.m_nBustedAudioStatus == 0) {
+ if (CGeneral::GetRandomNumberInRange(0, 4) == 0)
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE;
+ else {
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_LOADING;
+ char name[12];
+ sprintf(name, pPlayerInfo.m_nCurrentBustedAudio >= 10 ? "bust_%d" : "bust_0%d", pPlayerInfo.m_nCurrentBustedAudio);
+ DMAudio.ClearMissionAudio(); // TODO(MIAMI): argument is 0
+ DMAudio.PreloadMissionAudio(name); // TODO(MIAMI): argument is 0
+ pPlayerInfo.m_nCurrentBustedAudio = pPlayerInfo.m_nCurrentBustedAudio % 28 + 1; // enum? const? TODO
+ }
+ }
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 4000 &&
+ pPlayerInfo.m_nBustedAudioStatus == BUSTEDAUDIO_LOADING &&
+ DMAudio.GetMissionAudioLoadingStatus() == 1) { // TODO: argument is 0
+ DMAudio.PlayLoadedMissionAudio(); // TODO: argument is 0
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE;
+ }
+
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
+#ifdef FIX_BUGS
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_NONE;
+#endif
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
int takeMoney;
@@ -188,18 +248,21 @@ CGameLogic::Update()
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ AfterDeathArrestSetUpShortCutTaxi();
pPlayerInfo.m_pPed->ClearWeapons();
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
+ CPopulation::m_CountDownToPedsAtStart = 10;
+ CCarCtrl::CountDownToCarsAtStart = 10;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextArrest) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextArrest = true;
+ } else
+ CRestart::bFadeInAfterNextArrest = true;
}
break;
case WBSTATE_FAILED_CRITICAL_MISSION:
@@ -233,7 +296,8 @@ CGameLogic::Update()
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
+ CPopulation::m_CountDownToPedsAtStart = 10;
+ CCarCtrl::CountDownToCarsAtStart = 10;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
@@ -247,11 +311,14 @@ CGameLogic::Update()
void
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
{
- pPlayerPed->m_fHealth = 100.0f;
+ ClearShortCut();
+ CPlayerInfo* pPlayerInfo = pPlayerPed->GetPlayerInfoForThisPlayerPed();
+ pPlayerPed->m_fHealth = pPlayerInfo->m_nMaxHealth;
pPlayerPed->m_fArmour = 0.0f;
pPlayerPed->bIsVisible = true;
pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
pPlayerPed->bDoBloodyFootprints = false;
+ //TODO(MIAMI): clear drunk stuff
pPlayerPed->ClearAdrenaline();
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
if (pPlayerPed->m_pFire)
@@ -260,27 +327,258 @@ CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector
pPlayerPed->m_pMyVehicle = nil;
pPlayerPed->m_pVehicleAnim = nil;
pPlayerPed->m_pWanted->Reset();
+ pPlayerPed->bCancelEnteringCar = false;
pPlayerPed->RestartNonPartialAnims();
- pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
+ pPlayerInfo->MakePlayerSafe(false);
pPlayerPed->bRemoveFromWorld = false;
pPlayerPed->ClearWeaponTarget();
pPlayerPed->SetInitialState();
CCarCtrl::ClearInterestingVehicleList();
-
- pos.z += 1.0f;
- pPlayerPed->Teleport(pos);
- pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
-
+ pPlayerPed->Teleport(pos + CVector(0.0f, 0.0f, 1.0f));
+ pPlayerPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
pPlayerPed->m_fRotationCur = DEGTORAD(angle);
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
pPlayerPed->RestoreHeadingRate();
+ CGame::currArea = AREA_MAIN_MAP;
+ //CStreaming::RemoveBuildingsNotInArea(0); // TODO(MIAMI)
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
+ TheCamera.Restore();
CReferences::RemoveReferencesToPlayer();
CGarages::PlayerArrestedOrDied();
CStats::CheckPointReachedUnsuccessfully();
CWorld::Remove(pPlayerPed);
CWorld::Add(pPlayerPed);
+ //CHud::ResetWastedText() // TODO(MIAMI)
+ CStreaming::StreamZoneModels(pos);
+ clearWaterDrop = true;
+}
+
+void
+CGameLogic::ClearShortCut()
+{
+ if (pShortCutTaxi) {
+ if (pShortCutTaxi->VehicleCreatedBy == MISSION_VEHICLE) {
+ pShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE;
+ --CCarCtrl::NumMissionCars;
+ ++CCarCtrl::NumRandomCars;
+ }
+ CRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi));
+ pShortCutTaxi = nil;
+ }
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);
+}
+
+void
+CGameLogic::SetUpShortCut(CVector vStartPos, float fStartAngle, CVector vEndPos, float fEndAngle)
+{
+ ClearShortCut();
+ ShortCutState = SHORTCUT_INIT;
+ ShortCutStart = vStartPos;
+ ShortCutStartOrientation = fStartAngle;
+ ShortCutDestination = vEndPos;
+ ShortCutDestinationOrientation = fEndAngle;
+ CStreaming::RequestModel(MI_KAUFMAN, 0);
+}
+
+void
+CGameLogic::AbandonShortCutIfTaxiHasBeenMessedWith()
+{
+ if (!pShortCutTaxi)
+ return;
+ if (pShortCutTaxi->pDriver == nil ||
+ pShortCutTaxi->pDriver->DyingOrDead() ||
+ pShortCutTaxi->pDriver->GetPedState() == PED_DRAG_FROM_CAR ||
+ pShortCutTaxi->pDriver->GetPedState() == PED_ON_FIRE ||
+ pShortCutTaxi->pDriver->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE ||
+ pShortCutTaxi->m_fHealth < 250.0f ||
+ pShortCutTaxi->bRenderScorched)
+ ClearShortCut();
+}
+
+void
+CGameLogic::AbandonShortCutIfPlayerMilesAway()
+{
+ if (!pShortCutTaxi)
+ return;
+ if ((FindPlayerCoors() - pShortCutTaxi->GetPosition()).Magnitude() > 120.0f)
+ ClearShortCut();
+}
+
+void
+CGameLogic::UpdateShortCut()
+{
+ switch (ShortCutState) {
+ case SHORTCUT_INIT:
+ if (!CStreaming::HasModelLoaded(MI_KAUFMAN)) {
+ CStreaming::RequestModel(MI_KAUFMAN, 0);
+ return;
+ }
+ pShortCutTaxi = new CAutomobile(MI_KAUFMAN, RANDOM_VEHICLE);
+ if (!pShortCutTaxi)
+ return;
+ pShortCutTaxi->SetPosition(ShortCutStart);
+ pShortCutTaxi->SetHeading(DEGTORAD(ShortCutStartOrientation));
+ pShortCutTaxi->PlaceOnRoadProperly();
+ pShortCutTaxi->SetStatus(STATUS_PHYSICS);
+ pShortCutTaxi->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
+ pShortCutTaxi->AutoPilot.m_nCruiseSpeed = 0;
+ pShortCutTaxi->SetUpDriver();
+ pShortCutTaxi->VehicleCreatedBy = MISSION_VEHICLE;
+ ++CCarCtrl::NumMissionCars;
+ --CCarCtrl::NumRandomCars;
+ CTheScripts::ClearSpaceForMissionEntity(ShortCutStart, pShortCutTaxi);
+ CWorld::Add(pShortCutTaxi);
+ CRadar::SetEntityBlip(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi), 0, BLIP_DISPLAY_MARKER_ONLY);
+ ShortCutState = SHORTCUT_IDLE;
+ break;
+ case SHORTCUT_IDLE:
+ if (FindPlayerPed()->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && FindPlayerPed()->m_carInObjective == pShortCutTaxi) {
+ CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);
+ FindPlayerPed()->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pShortCutTaxi);
+ ShortCutState = SHORTCUT_GETTING_IN;
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ AbandonShortCutIfPlayerMilesAway();
+ break;
+ case SHORTCUT_GETTING_IN:
+ if (pShortCutTaxi->pPassengers[0] == FindPlayerPed() ||
+ pShortCutTaxi->pPassengers[1] == FindPlayerPed() ||
+ pShortCutTaxi->pPassengers[2] == FindPlayerPed()) {
+ pShortCutTaxi->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pShortCutTaxi->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2500;
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(2.5f, 0);
+ ShortCutState = SHORTCUT_TRANSITION;
+ ShortCutTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ CMessages::AddBigMessage(TheText.Get("TAXI"), 4500, 1);
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ break;
+ case SHORTCUT_TRANSITION:
+ if (CTimer::GetTimeInMilliseconds() > ShortCutTimer) {
+ CTimer::Suspend();
+ CColStore::RequestCollision(ShortCutDestination);
+ CStreaming::LoadSceneCollision(ShortCutDestination);
+ CStreaming::LoadScene(ShortCutDestination);
+ CTheScripts::ClearSpaceForMissionEntity(ShortCutDestination, pShortCutTaxi);
+ pShortCutTaxi->Teleport(ShortCutDestination);
+ pShortCutTaxi->SetHeading(DEGTORAD(ShortCutDestinationOrientation));
+ pShortCutTaxi->PlaceOnRoadProperly();
+ pShortCutTaxi->SetMoveSpeed(pShortCutTaxi->GetForward() * 0.4f);
+ ShortCutTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(1.0f, 1);
+ ShortCutState = SHORTCUT_ARRIVING;
+ CTimer::Resume();
+ }
+ break;
+ case SHORTCUT_ARRIVING:
+ if (CTimer::GetTimeInMilliseconds() > ShortCutTimer) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - SHORTCUT_TAXI_COST);
+ FindPlayerPed()->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pShortCutTaxi);
+ FindPlayerPed()->m_carInObjective = pShortCutTaxi;
+ ShortCutState = SHORTCUT_GETTING_OUT;
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ break;
+ case SHORTCUT_GETTING_OUT:
+ if (pShortCutTaxi->pPassengers[0] != FindPlayerPed() &&
+ pShortCutTaxi->pPassengers[1] != FindPlayerPed() &&
+ pShortCutTaxi->pPassengers[2] != FindPlayerPed()) {
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);
+ pShortCutTaxi->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pShortCutTaxi->AutoPilot.m_nCruiseSpeed = 18;
+ CCarCtrl::JoinCarWithRoadSystem(pShortCutTaxi);
+ pShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE;
+ ++CCarCtrl::NumRandomCars;
+ --CCarCtrl::NumMissionCars;
+ CRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi));
+ ShortCutState = SHORTCUT_NONE;
+ pShortCutTaxi = nil;
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ break;
+ }
+}
+
+void
+CGameLogic::AddShortCutPointAfterDeath(CVector point, float angle)
+{
+ if (NumAfterDeathStartPoints >= NUM_SHORTCUT_START_POINTS)
+ return;
+ AfterDeathStartPoints[NumAfterDeathStartPoints] = point;
+ AfterDeathStartPointOrientation[NumAfterDeathStartPoints] = angle;
+ NumAfterDeathStartPoints++;
+}
+
+void
+CGameLogic::AddShortCutDropOffPointForMission(CVector point, float angle)
+{
+ ShortCutDropOffForMission = point;
+ ShortCutDropOffOrientationForMission = angle;
+ MissionDropOffReadyToBeUsed = true;
+}
+
+void
+CGameLogic::RemoveShortCutDropOffPointForMission()
+{
+ MissionDropOffReadyToBeUsed = false;
+}
+
+void
+CGameLogic::AfterDeathArrestSetUpShortCutTaxi()
+{
+ if (!MissionDropOffReadyToBeUsed)
+ return;
+ int nClosestPoint = -1;
+ float fDistanceToPoint = 999999.9f;
+ for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {
+ float dist = (AfterDeathStartPoints[i] - FindPlayerCoors()).Magnitude();
+ if (dist < fDistanceToPoint) {
+ fDistanceToPoint = dist;
+ nClosestPoint = i;
+ }
+ }
+ if (fDistanceToPoint < 100.0f)
+ SetUpShortCut(AfterDeathStartPoints[nClosestPoint],
+ AfterDeathStartPointOrientation[nClosestPoint],
+ ShortCutDropOffForMission,
+ ShortCutDropOffOrientationForMission);
+ MissionDropOffReadyToBeUsed = false;
+}
+
+void
+CGameLogic::Save(uint8* buf, uint32* size)
+{
+INITSAVEBUF
+ WriteSaveBuf(buf, NumAfterDeathStartPoints);
+ *size += sizeof(NumAfterDeathStartPoints);
+ for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {
+ WriteSaveBuf(buf, AfterDeathStartPoints[i].x);
+ *size += sizeof(AfterDeathStartPoints[i].x);
+ WriteSaveBuf(buf, AfterDeathStartPoints[i].y);
+ *size += sizeof(AfterDeathStartPoints[i].y);
+ WriteSaveBuf(buf, AfterDeathStartPoints[i].z);
+ *size += sizeof(AfterDeathStartPoints[i].z);
+ WriteSaveBuf(buf, AfterDeathStartPointOrientation[i]);
+ *size += sizeof(AfterDeathStartPointOrientation[i]);
+ }
+VALIDATESAVEBUF(*size)
+}
+
+void
+CGameLogic::Load(uint8* buf, uint32 size)
+{
+INITSAVEBUF
+ NumAfterDeathStartPoints = ReadSaveBuf<uint32>(buf);
+ for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {
+ AfterDeathStartPoints[i].x = ReadSaveBuf<float>(buf);
+ AfterDeathStartPoints[i].y = ReadSaveBuf<float>(buf);
+ AfterDeathStartPoints[i].z = ReadSaveBuf<float>(buf);
+ AfterDeathStartPointOrientation[i] = ReadSaveBuf<float>(buf);
+ }
+VALIDATESAVEBUF(size)
}
diff --git a/src/control/GameLogic.h b/src/control/GameLogic.h
index 43e244a3..9b774cc7 100644
--- a/src/control/GameLogic.h
+++ b/src/control/GameLogic.h
@@ -1,13 +1,51 @@
#pragma once
+class CAutomobile;
+
class CGameLogic
{
public:
+ enum {
+ SHORTCUT_NONE = 0,
+ SHORTCUT_INIT,
+ SHORTCUT_IDLE,
+ SHORTCUT_GETTING_IN,
+ SHORTCUT_TRANSITION,
+ SHORTCUT_ARRIVING,
+ SHORTCUT_GETTING_OUT
+ };
+
static void InitAtStartOfGame();
static void PassTime(uint32 time);
static void SortOutStreamingAndMemory(const CVector &pos);
static void Update();
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
+ static void ClearShortCut();
+ static void SetUpShortCut(CVector, float, CVector, float);
+ static void AbandonShortCutIfTaxiHasBeenMessedWith();
+ static void AbandonShortCutIfPlayerMilesAway();
+ static void UpdateShortCut();
+ static void AddShortCutPointAfterDeath(CVector, float);
+ static void AddShortCutDropOffPointForMission(CVector, float);
+ static void RemoveShortCutDropOffPointForMission();
+ static void AfterDeathArrestSetUpShortCutTaxi();
+
+ static void Save(uint8*, uint32*);
+ static void Load(uint8*, uint32);
+
static uint8 ActivePlayers;
+ static uint8 ShortCutState;
+ static CAutomobile* pShortCutTaxi;
+ static uint32 NumAfterDeathStartPoints;
+ static CVector ShortCutStart;
+ static float ShortCutStartOrientation;
+ static CVector ShortCutDestination;
+ static float ShortCutDestinationOrientation;
+ static uint32 ShortCutTimer;
+ static CVector AfterDeathStartPoints[NUM_SHORTCUT_START_POINTS];
+ static float AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS];
+ static CVector ShortCutDropOffForMission;
+ static float ShortCutDropOffOrientationForMission;
+ static bool MissionDropOffReadyToBeUsed;
}; \ No newline at end of file
diff --git a/src/control/PathFind.h b/src/control/PathFind.h
index 7abc455a..e481f4c6 100644
--- a/src/control/PathFind.h
+++ b/src/control/PathFind.h
@@ -5,6 +5,8 @@
class CVehicle;
class CPtrList;
+#define LANE_WIDTH 5.0f
+
enum
{
NodeTypeExtern = 1,
@@ -85,6 +87,8 @@ struct CPathNode
float GetX(void) { return x/8.0f; }
float GetY(void) { return y/8.0f; }
float GetZ(void) { return z/8.0f; }
+ bool HasDivider(void) { return width != 0; }
+ float GetDividerWidth(void) { return width/(2*8.0f); }
CPathNode *GetPrev(void);
CPathNode *GetNext(void);
void SetPrev(CPathNode *node);
@@ -120,7 +124,7 @@ struct CCarPathLink
float GetY(void) { return y/8.0f; }
float GetDirX(void) { return dirX/100.0f; }
float GetDirY(void) { return dirY/100.0f; }
- float GetLaneOffset(void) { return width/80.0f; }
+ float GetLaneOffset(void) { return width/(2*8.0f*LANE_WIDTH); }
float OneWayLaneOffset()
{
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index a26e19f5..5d466be2 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -14,14 +14,18 @@
#include "Camera.h"
#include "CarCtrl.h"
#include "General.h"
+#include "Object.h"
+
+//--MIAMI: file done
#define ROADBLOCKDIST (90.0f)
+#define ROADBLOCK_OBJECT_WIDTH (4.0f)
int16 CRoadBlocks::NumRoadBlocks;
int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS];
bool CRoadBlocks::InOrOut[NUMROADBLOCKS];
+CScriptRoadblock CRoadBlocks::aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS];
-//--MIAMI: TODO
void
CRoadBlocks::Init(void)
{
@@ -43,7 +47,7 @@ CRoadBlocks::Init(void)
}
}
- // TODO(MIAMI): script roadblocks
+ ClearScriptRoadBlocks();
}
void
@@ -83,14 +87,11 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45);
CPedPlacement::FindZCoorForPed(&posForZ);
pCopPed->SetPosition(posForZ);
- CVector vecSavedPos = pCopPed->GetPosition();
- pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI);
- pCopPed->m_matrix.GetPosition() += vecSavedPos;
+ pCopPed->SetOrientation(0.0f, 0.0f, -HALFPI);
pCopPed->m_bIsDisabledCop = true;
pCopPed->SetIdle();
pCopPed->bKindaStayInSamePlace = true;
pCopPed->bNotAllowedToDuck = false;
-// pCopPed->m_nRoadblockNode = roadBlockNode;
pCopPed->bCrouchWhenShooting = roadBlockType != 2;
if (pEntityToAttack) {
pCopPed->m_pPointGunAt = pEntityToAttack;
@@ -105,99 +106,178 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
}
}
-//--MIAMI: TODO: implement this
void
CRoadBlocks::GenerateRoadBlocks(void)
{
- CMatrix offsetMatrix;
+ CMatrix tmp1, tmp2;
+ static int16 unk;
uint32 frame = CTimer::GetFrameCounter() & 0xF;
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) {
- CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[nRoadblockNode].GetPosition();
+ int16 node = RoadBlockNodes[nRoadblockNode];
+ CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[node].GetPosition();
if (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST &&
vecDistance.y > -ROADBLOCKDIST && vecDistance.y < ROADBLOCKDIST &&
vecDistance.Magnitude() < ROADBLOCKDIST) {
if (!InOrOut[nRoadblockNode]) {
InOrOut[nRoadblockNode] = true;
if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
-#ifndef MIAMI
- CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
- float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
- int32 vehicleId = MI_POLICE;
- if (pPlayerWanted->AreArmyRequired())
- vehicleId = MI_BARRACKS;
- else if (pPlayerWanted->AreFbiRequired())
- vehicleId = MI_FBICAR;
- else if (pPlayerWanted->AreSwatRequired())
- vehicleId = MI_ENFORCER;
- if (!CStreaming::HasModelLoaded(vehicleId))
- vehicleId = MI_POLICE;
- CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel();
- float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;
- int16 radius = (int16)(fMapObjectRadius / fModelRadius);
- if (radius > 0 && radius < 6) {
- CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->GetPosition();
- float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->GetForward());
- float fOffset = 0.5f * fModelRadius * (float)(radius - 1);
- for (int16 i = 0; i < radius; i++) {
- uint8 nRoadblockType = fDotProduct < 0.0f;
- if (CGeneral::GetRandomNumber() & 1) {
- offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI);
- }
- else {
- nRoadblockType = !nRoadblockType;
- offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI);
- }
- if (ThePaths.m_objectFlags[RoadBlockObjects[nRoadblockNode]] & ObjectEastWest)
- offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f);
- else
- offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f);
- CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix;
- float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f;
- int16 colliding = 0;
- CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);
- if (!colliding) {
- CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);
- pVehicle->SetStatus(STATUS_ABANDONED);
- // pVehicle->GetHeightAboveRoad(); // called but return value is ignored?
- vehicleMatrix.GetPosition().z += fModelRadius - 0.6f;
- pVehicle->m_matrix = vehicleMatrix;
- pVehicle->PlaceOnRoadProperly();
- pVehicle->bIsStatic = false;
- pVehicle->m_matrix.UpdateRW();
- pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->bIsLocked = false;
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
- pVehicle->AutoPilot.m_nCurrentLane = 0;
- pVehicle->AutoPilot.m_nNextLane = 0;
- pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f;
- pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f;
- pVehicle->bExtendedRange = true;
- if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1)
- pVehicle->m_bSirenOrAlarm = true;
- if (pVehicle->GetForward().z > 0.94f) {
- CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
- CWorld::Add(pVehicle);
- pVehicle->bCreateRoadBlockPeds = true;
- pVehicle->m_nRoadblockType = nRoadblockType;
- pVehicle->m_nRoadblockNode = nRoadblockNode;
- }
- else {
- delete pVehicle;
- }
- }
- }
+ CCarPathLink* pLink1 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink]];
+ CCarPathLink* pLink2 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink + 1]];
+ int lanes = Min(pLink1->numRightLanes + pLink1->numLeftLanes, pLink2->numLeftLanes + pLink2->numRightLanes);
+ float length = LANE_WIDTH * (lanes + 1);
+ CVector forward(pLink2->GetY() - pLink1->GetY(), -(pLink2->GetX() - pLink1->GetX()), 0.0f);
+ forward.Normalise();
+ if (ThePaths.m_pathNodes[node].HasDivider()) {
+ CreateRoadBlockBetween2Points(
+ ThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f + ThePaths.m_pathNodes[node].GetDividerWidth()) * forward,
+ ThePaths.m_pathNodes[node].GetPosition() + ThePaths.m_pathNodes[node].GetDividerWidth() * forward);
+ CreateRoadBlockBetween2Points(
+ ThePaths.m_pathNodes[node].GetPosition() - ThePaths.m_pathNodes[node].GetDividerWidth() * forward,
+ ThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f + ThePaths.m_pathNodes[node].GetDividerWidth()) * forward);
+ }
+ else {
+ CreateRoadBlockBetween2Points(
+ ThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f) * forward,
+ ThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f) * forward);
}
-#endif
}
}
- } else {
+ }
+ else {
InOrOut[nRoadblockNode] = false;
}
}
+ int i = CTimer::GetFrameCounter() & 0xF;
+ if (!aScriptRoadBlocks[i].m_bInUse)
+ return;
+ if ((aScriptRoadBlocks[i].GetPosition() - FindPlayerCoors()).Magnitude() < 100.0f) {
+ CreateRoadBlockBetween2Points(aScriptRoadBlocks[i].m_vInf, aScriptRoadBlocks[i].m_vSup);
+ aScriptRoadBlocks[i].m_bInUse = false;
+ }
+}
- // TODO(MIAMI): script roadblocks
+void
+CRoadBlocks::ClearScriptRoadBlocks(void)
+{
+ for (int i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++)
+ aScriptRoadBlocks[i].m_bInUse = false;
+}
+
+void
+CRoadBlocks::RegisterScriptRoadBlock(CVector vInf, CVector vSup)
+{
+ int32 i;
+ for (i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++) {
+ if (!aScriptRoadBlocks[i].m_bInUse)
+ break;
+ }
+ if (i == NUM_SCRIPT_ROADBLOCKS)
+ return;
+ aScriptRoadBlocks[i].m_bInUse = true;
+ aScriptRoadBlocks[i].m_vInf = vInf;
+ aScriptRoadBlocks[i].m_vSup = vSup;
+}
+
+void
+CRoadBlocks::CreateRoadBlockBetween2Points(CVector point1, CVector point2)
+{
+ CMatrix tmp;
+ CVector forward = (point2 - point1);
+ float distBetween = forward.Magnitude();
+ CVector pos = (point1 + point2) / 2;
+ CVector right(forward.y, -forward.x, 0.0f);
+ forward.Normalise();
+ right.Normalise();
+ if (DotProduct(FindPlayerCoors() - pos, right) < 0.0f) {
+ right *= -1.0f;
+ }
+ int32 vehicleId = MI_POLICE;
+ if (FindPlayerPed()->m_pWanted->AreArmyRequired())
+ vehicleId = MI_BARRACKS;
+ else if (FindPlayerPed()->m_pWanted->AreFbiRequired())
+ vehicleId = MI_FBICAR;
+ else if (FindPlayerPed()->m_pWanted->AreSwatRequired())
+ vehicleId = MI_ENFORCER;
+ if (!CStreaming::HasModelLoaded(vehicleId))
+ vehicleId = MI_POLICE;
+ CColModel* pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel();
+ float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;
+ int16 numRoadblockVehicles = Min(6, (int16)(distBetween / fModelRadius));
+ for (int16 i = 0; i < numRoadblockVehicles; i++) {
+ float offset = fModelRadius * (i - numRoadblockVehicles / 2);
+ tmp.SetTranslate(0.0f, 0.0f, 0.0f);
+ tmp.GetRight() = CVector(forward.y, -forward.x, 0.0f);
+ tmp.GetForward() = forward;
+ tmp.GetUp() = CVector(0.0f, 0.0f, 1.0f);
+ tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f);
+ if (CGeneral::GetRandomNumber() & 1)
+ tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + 3.1416f);
+ tmp.SetTranslateOnly(offset * forward + pos);
+ tmp.GetPosition().z += 0.6f;
+ float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f;
+ int16 colliding = 0;
+ CWorld::FindObjectsKindaColliding(tmp.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);
+ if (!colliding) {
+ CAutomobile* pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);
+ pVehicle->SetStatus(STATUS_ABANDONED);
+ // pVehicle->GetHeightAboveRoad(); // called but return value is ignored?
+ tmp.GetPosition().z += fModelRadius - 0.6f;
+ pVehicle->m_matrix = tmp;
+ pVehicle->PlaceOnRoadProperly();
+ pVehicle->bIsStatic = false;
+ pVehicle->m_matrix.UpdateRW();
+ pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+ CCarCtrl::JoinCarWithRoadSystem(pVehicle);
+ pVehicle->bIsLocked = false;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0;
+ pVehicle->AutoPilot.m_nCruiseSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0;
+ pVehicle->bExtendedRange = true;
+ if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1)
+ pVehicle->m_bSirenOrAlarm = true;
+ if (pVehicle->GetUp().z > 0.94f) {
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
+ CWorld::Add(pVehicle);
+ pVehicle->bCreateRoadBlockPeds = true;
+ pVehicle->m_nRoadblockType = DotProduct(pVehicle->GetRight(), pVehicle->GetPosition() - FindPlayerCoors()) >= 0.0f;
+ pVehicle->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 7000;
+ }
+ else {
+ delete pVehicle;
+ }
+ }
+ }
+ int numBarriers = distBetween / ROADBLOCK_OBJECT_WIDTH;
+ CStreaming::RequestModel(MI_ROADWORKBARRIER1, STREAMFLAGS_DONT_REMOVE);
+ if (!CStreaming::HasModelLoaded(MI_ROADWORKBARRIER1))
+ return;
+ for (int i = 0; i < numBarriers; i++) {
+ float offset = ROADBLOCK_OBJECT_WIDTH * (i - numBarriers / 2);
+ tmp.SetTranslate(0.0f, 0.0f, 0.0f);
+ tmp.GetRight() = CVector(forward.y, -forward.x, 0.0f);
+ tmp.GetForward() = forward;
+ tmp.GetUp() = CVector(0.0f, 0.0f, 1.0f);
+ tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f);
+ tmp.SetTranslateOnly(5.0f * right + offset * forward + pos);
+ tmp.GetPosition().x += (CGeneral::GetRandomNumber() & 0xF) * 0.1f;
+ tmp.GetPosition().y += (CGeneral::GetRandomNumber() & 0xF) * 0.1f;
+ bool found;
+ tmp.GetPosition().z = CWorld::FindGroundZFor3DCoord(tmp.GetPosition().x, tmp.GetPosition().y, tmp.GetPosition().z + 2.0f, &found);
+ if (!found)
+ continue;
+ int16 colliding = 0;
+ CBaseModelInfo* pMI = CModelInfo::GetModelInfo(MI_ROADWORKBARRIER1);
+ tmp.GetPosition().z -= pMI->GetColModel()->boundingBox.min.z;
+ CWorld::FindObjectsKindaColliding(tmp.GetPosition(), pMI->GetColModel()->boundingSphere.radius, 0, &colliding, 2, nil, false, true, true, false, false);
+ if (colliding == 0) {
+ CObject* pObject = new CObject(MI_ROADWORKBARRIER1, true);
+ pObject->GetMatrix() = tmp;
+ pObject->ObjectCreatedBy = TEMP_OBJECT;
+ pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 600000;
+ CWorld::Add(pObject);
+ }
+ }
}
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index c8469ba5..ef614950 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -3,18 +3,28 @@
class CVehicle;
+class CScriptRoadblock
+{
+public:
+ CVector m_vInf;
+ CVector m_vSup;
+ bool m_bInUse;
+ CVector GetPosition() { return (m_vInf + m_vSup) / 2; }
+};
+
class CRoadBlocks
{
public:
static int16 NumRoadBlocks;
-#ifndef MIAMI
- static int16 RoadBlockObjects[NUMROADBLOCKS];
-#else
static int16 RoadBlockNodes[NUMROADBLOCKS];
-#endif
static bool InOrOut[NUMROADBLOCKS];
+ static CScriptRoadblock aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS];
static void Init(void);
static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType);
static void GenerateRoadBlocks(void);
+
+ static void CreateRoadBlockBetween2Points(CVector, CVector);
+ static void RegisterScriptRoadBlock(CVector, CVector);
+ static void ClearScriptRoadBlocks();
};
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index f3583cbe..bfc778ba 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -26,6 +26,7 @@
#include "Fire.h"
#include "Frontend.h"
#include "Gangs.h"
+#include "GameLogic.h"
#include "Garages.h"
#include "General.h"
#include "HandlingMgr.h"
@@ -272,7 +273,7 @@ void CMissionCleanup::Process()
CPed::nThreatReactionRangeMultiplier = 1;
CPed::nEnterCarRangeMultiplier = 1;
FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f;
- //CRoadBlocks::ClearScriptRoadblocks() // TODO(MIAMI)
+ CRoadBlocks::ClearScriptRoadBlocks();
CRouteNode::Initialise();
if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
TheCamera.Restore();
@@ -300,7 +301,7 @@ void CMissionCleanup::Process()
//DMAudio::ShutUpPlayerTalking(0);
CVehicle::bDisableRemoteDetonation = false;
CVehicle::bDisableRemoteDetonationOnContact = false;
- //CGameLogic::ClearShortCut(); // TODO(MIAMI)
+ CGameLogic::ClearShortCut();
CTheScripts::RiotIntensity = 0;
CTheScripts::StoreVehicleIndex = -1;
CTheScripts::StoreVehicleWasRandom = true;
@@ -6506,7 +6507,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
++CStats::MissionsPassed;
CStats::CheckPointReachedSuccessfully();
CTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds();
- //CGameLogic::RemoveShortCutDropOffPointForMission() // TODO(MIAMI)
+ CGameLogic::RemoveShortCutDropOffPointForMission();
return 0;
}
case COMMAND_SET_CHAR_RUNNING:
@@ -7153,13 +7154,8 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CTheScripts::ReadTextLabelFromScript(&m_nIp, name);
for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
name[i] = tolower(name[i]);
- int mi = pPed->GetModelIndex();
- pPed->DeleteRwObject();
- if (pPed->IsPlayer())
- mi = 0;
- CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CWorld::Remove(pPed);
+ pPed->Undress(name);
return 0;
}
case COMMAND_DRESS_CHAR:
@@ -7167,10 +7163,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
assert(pPed);
- int mi = pPed->GetModelIndex();
- pPed->m_modelIndex = -1;
- pPed->SetModelIndex(mi);
- CWorld::Add(pPed);
+ pPed->Dress();
return 0;
}
/*
@@ -9045,7 +9038,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pMissionScript->m_bIsMissionScript = true;
pMissionScript->m_bMissionFlag = true;
CTheScripts::bAlreadyRunningAMissionScript = true;
- //CGameLogic::ClearShortcut(); // TODO(MIAMI)
+ CGameLogic::ClearShortCut();
return 0;
}
case COMMAND_SET_OBJECT_DRAW_LAST:
@@ -10533,12 +10526,12 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
case COMMAND_CREATE_SCRIPT_ROADBLOCK:
{
CollectParameters(&m_nIp, 6);
- debug("CREATE_SCRIPT_ROADBLOCK not implemented\n"); // TODO(MIAMI)
+ CRoadBlocks::RegisterScriptRoadBlock(*(CVector*)&ScriptParams[0], *(CVector*)&ScriptParams[3]);
return 0;
}
case COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS:
{
- debug("CLEAR_ALL_SCRIPT_ROADBLOCKS not implemented\n"); // TODO(MIAMI)
+ CRoadBlocks::ClearScriptRoadBlocks();
return 0;
}
case COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR:
@@ -11440,11 +11433,13 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command)
case COMMAND_SET_UP_TAXI_SHORTCUT:
{
CollectParameters(&m_nIp, 8);
- debug("SET_UP_TAXI_SHORTCUT is not implemented\n"); // TODO(MIAMI)
+ CGameLogic::SetUpShortCut(
+ *(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3],
+ *(CVector*)&ScriptParams[4], *(float*)&ScriptParams[7]);
return 0;
}
case COMMAND_CLEAR_TAXI_SHORTCUT:
- debug("CLEAR_TAXI_SHORTCUT is not implemented\n"); // TODO(MIAMI)
+ CGameLogic::ClearShortCut();
return 0;
//case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT:
//case COMMAND_GET_CLOSEST_WATER_NODE:
@@ -11910,13 +11905,13 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command)
case COMMAND_SET_SHORTCUT_PICKUP_POINT:
{
CollectParameters(&m_nIp, 4);
- debug("SET_SHORTCUT_PICKUP_POINT not implemented, skipping\n");
+ CGameLogic::AddShortCutPointAfterDeath(*(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3]);
return 0;
}
case COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION:
{
CollectParameters(&m_nIp, 4);
- debug("SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION not implemented, skipping");
+ CGameLogic::AddShortCutDropOffPointForMission(*(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3]);
return 0;
}
case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA:
@@ -11948,16 +11943,14 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command)
++CStats::MissionsPassed;
CStats::CheckPointReachedSuccessfully();
CTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds();
- // CGameLogic::RemoveShortCutDropOffPointForMission(); // TODO(MIAMI)
+ CGameLogic::RemoveShortCutDropOffPointForMission();
+ return 0;
case COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI:
{
CollectParameters(&m_nIp, 1);
- static bool bShowed = false;
- if (!bShowed) {
- debug("IS_PLAYER_IN_SHORTCUT_TAXI not implemented, default to FALSE\n");
- bShowed = true;
- }
- UpdateCompareFlag(false);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle && pPed->m_pMyVehicle == CGameLogic::pShortCutTaxi);
return 0;
}
case COMMAND_IS_CHAR_DUCKING:
@@ -11980,6 +11973,7 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command)
return 0;
case COMMAND_IS_AUSTRALIAN_GAME:
UpdateCompareFlag(false); // should we make some check?
+ return 0;
case COMMAND_DISARM_CAR_BOMB:
{
CollectParameters(&m_nIp, 1);
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index b65b60f3..d9cc5c32 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -3123,7 +3123,7 @@ CCamera::Fade(float timeout, int16 direction)
void
CCamera::SetFadeColour(uint8 r, uint8 g, uint8 b)
{
- m_FadeTargetIsSplashScreen = r == 0 && g == 0 && b == 0;
+ m_FadeTargetIsSplashScreen = r == 2 && g == 2 && b == 2;
CDraw::FadeRed = r;
CDraw::FadeGreen = g;
CDraw::FadeBlue = b;
diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp
index 933c73da..3752f1ba 100644
--- a/src/core/Fire.cpp
+++ b/src/core/Fire.cpp
@@ -15,6 +15,7 @@
#include "DamageManager.h"
#include "Ped.h"
#include "Fire.h"
+#include "GameLogic.h"
CFireManager gFireManager;
@@ -59,6 +60,12 @@ CFire::ProcessFire(void)
Extinguish();
return;
}
+#if defined GTAVC_JP_PATCH && !defined FIX_BUGS
+ if (m_pEntity == CGameLogic::pShortCutTaxi && CGameLogic::ShortCutState == CGameLogic::SHORTCUT_TRANSITION) {
+ Extinguish();
+ return;
+ }
+#endif
if (ped->m_nMoveState != PEDMOVE_RUN)
m_vecPos.z -= 1.0f;
if (ped->bInVehicle && ped->m_pMyVehicle) {
@@ -84,6 +91,12 @@ CFire::ProcessFire(void)
Extinguish();
return;
}
+#ifdef FIX_BUGS
+ if (m_pEntity == CGameLogic::pShortCutTaxi && CGameLogic::ShortCutState == CGameLogic::SHORTCUT_TRANSITION) {
+ Extinguish();
+ return;
+ }
+#endif
if (!m_bIsScriptFire) {
fDamageVehicle = 1.2f * CTimer::GetTimeStep();
veh->InflictDamage((CVehicle *)m_pSource, WEAPONTYPE_FLAMETHROWER, fDamageVehicle);
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index 9a1c00a7..f401ca3f 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -523,6 +523,7 @@ void CGame::ShutDownForRestart(void)
CTheScripts::UndoBuildingSwaps();
CTheScripts::UndoEntityInvisibilitySettings();
CWorld::ClearForRestart();
+ CGameLogic::ClearShortCut();
CTimer::Shutdown();
CStreaming::FlushRequestList();
CStreaming::DeleteAllRwObjects();
diff --git a/src/core/Pad.h b/src/core/Pad.h
index 46ed9b39..a1461575 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -10,6 +10,7 @@ enum {
PLAYERCONTROL_DISABLED_20 = 32, // used on CPlayerInfo::MakePlayerSafe
PLAYERCONTROL_DISABLED_40 = 64, // used on phone calls
PLAYERCONTROL_DISABLED_80 = 128,// used on cutscenes
+ PLAYERCONTROL_SHORTCUT_TAXI = 256,
};
class CControllerState
@@ -150,10 +151,10 @@ public:
int16 Phase;
int16 Mode;
int16 ShakeDur;
+ uint16 DisablePlayerControls;
uint8 ShakeFreq;
bool bHornHistory[HORNHISTORY_SIZE];
uint8 iCurrHornHistory;
- uint8 DisablePlayerControls;
int8 bApplyBrakes;
char CheatString[12];
int32 LastTimeTouched;
@@ -449,9 +450,9 @@ public:
int16 GetRightStickY(void) { return NewState.RightStickY; }
bool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; }
- void SetDisablePlayerControls(uint8 who) { DisablePlayerControls |= who; }
- void SetEnablePlayerControls(uint8 who) { DisablePlayerControls &= ~who; }
- bool IsPlayerControlsDisabledBy(uint8 who) { return DisablePlayerControls & who; }
+ void SetDisablePlayerControls(uint16 who) { DisablePlayerControls |= who; }
+ void SetEnablePlayerControls(uint16 who) { DisablePlayerControls &= ~who; }
+ bool IsPlayerControlsDisabledBy(uint16 who) { return DisablePlayerControls & who; }
};
VALIDATE_SIZE(CPad, 0xFC);
diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp
index 675fafb3..08c8ac36 100644
--- a/src/core/PlayerInfo.cpp
+++ b/src/core/PlayerInfo.cpp
@@ -146,6 +146,8 @@ CPlayerInfo::Clear(void)
m_bDriveByAllowed = true;
m_nPreviousTimeRewardedForExplosion = 0;
m_nExplosionsSinceLastReward = 0;
+ m_nCurrentBustedAudio = 1;
+ m_nBustedAudioStatus = BUSTEDAUDIO_NONE;
}
void
diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h
index e2e874e6..dfe6a53e 100644
--- a/src/core/PlayerInfo.h
+++ b/src/core/PlayerInfo.h
@@ -10,6 +10,13 @@ enum eWastedBustedState
WBSTATE_FAILED_CRITICAL_MISSION,
};
+enum eBustedAudioState : uint8
+{
+ BUSTEDAUDIO_NONE,
+ BUSTEDAUDIO_LOADING,
+ BUSTEDAUDIO_DONE
+};
+
class CEntity;
class CPed;
class CVehicle;
@@ -60,6 +67,8 @@ public:
bool m_bGetOutOfJailFree;
bool m_bGetOutOfHospitalFree;
bool m_bDriveByAllowed;
+ eBustedAudioState m_nBustedAudioStatus;
+ int16 m_nCurrentBustedAudio;
char m_aSkinName[32];
RwTexture *m_pSkinTexture;
diff --git a/src/core/User.cpp b/src/core/User.cpp
index 716d6393..56e37ac4 100644
--- a/src/core/User.cpp
+++ b/src/core/User.cpp
@@ -1,6 +1,6 @@
#include "common.h"
-
+#include "GameLogic.h"
#include "Hud.h"
#include "PlayerPed.h"
#include "Replay.h"
@@ -99,7 +99,7 @@ void
CCurrentVehicle::Display()
{
wchar *text = nil;
- if (m_pCurrentVehicle != nil)
+ if (m_pCurrentVehicle != nil && m_pCurrentVehicle != CGameLogic::pShortCutTaxi)
text = TheText.Get(((CVehicleModelInfo*)CModelInfo::GetModelInfo(m_pCurrentVehicle->GetModelIndex()))->m_gameName);
CHud::SetVehicleName(text);
}
diff --git a/src/core/config.h b/src/core/config.h
index c90d3cbf..6744e888 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -115,6 +115,7 @@ enum Config {
NUMSHOTINFOS = 100,
NUMROADBLOCKS = 300,
+ NUM_SCRIPT_ROADBLOCKS = 16,
NUMVISIBLEENTITIES = 2000,
NUMINVISIBLEENTITIES = 150,
@@ -136,7 +137,8 @@ enum Config {
NUM_EXPLOSIONS = 48,
- NUM_SETPIECES = 96
+ NUM_SETPIECES = 96,
+ NUM_SHORTCUT_START_POINTS = 16
};
// We'll use this once we're ready to become independent of the game
@@ -166,6 +168,7 @@ enum Config {
#elif defined GTA_PC
# define GTA3_1_1_PATCH
//# define GTA3_STEAM_PATCH
+//# define GTAVC_JP_PATCH
# ifdef GTA_PS2_STUFF
# define USE_PS2_RAND
# define RANDOMSPLASH // use random splash as on PS2
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
index 1d26cc20..9979e701 100644
--- a/src/math/Matrix.h
+++ b/src/math/Matrix.h
@@ -255,6 +255,14 @@ public:
m_matrix.at.y = 0.0f;
m_matrix.at.z = 1.0f;
}
+ void SetTranslateOnly(float x, float y, float z) {
+ m_matrix.pos.x = x;
+ m_matrix.pos.y = y;
+ m_matrix.pos.z = z;
+ }
+ void SetTranslateOnly(const CVector& pos) {
+ SetTranslateOnly(pos.x, pos.y, pos.z);
+ }
};
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 687f9da1..406ac23f 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -60,6 +60,7 @@
#include "Streaming.h"
#include "PedAttractor.h"
#include "Debug.h"
+#include "GameLogic.h"
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
@@ -16228,6 +16229,12 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
return;
}
if (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) {
+#if defined GTAVC_JP_PATCH || defined FIX_BUGS
+ if (veh->pDriver == this && !IsPlayer() && veh == CGameLogic::pShortCutTaxi) {
+ m_objective = OBJECTIVE_NONE;
+ return;
+ }
+#endif
// Again, unused...
// CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
bool thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil);
@@ -18666,6 +18673,35 @@ CPed::CanBeDamagedByThisGangMember(CPed* who)
return m_gangFlags & (1 << (uint8)(who->m_nPedType - PEDTYPE_GANG1));
}
+void
+CPed::Undress(const char* name)
+{
+ int mi = GetModelIndex();
+ CAnimBlendAssociation* pAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_OUT);
+ //if (pAnim)
+ // FinishTalkingOnMobileCB(pAnim, this); // TODO(MIAMI)
+ DeleteRwObject();
+ if (m_nPedType == PEDTYPE_PLAYER1)
+ mi = MI_PLAYER;
+ CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
+ CWorld::Remove(this);
+}
+
+void
+CPed::Dress(void)
+{
+ int mi = GetModelIndex();
+ m_modelIndex = -1;
+ SetModelIndex(mi);
+ m_nPedState = PED_IDLE;
+ m_nLastPedState = PED_NONE;
+ m_objective = OBJECTIVE_NONE;
+ m_prevObjective = OBJECTIVE_NONE;
+ m_nWaitState = WAITSTATE_FALSE;
+ CWorld::Add(this);
+ m_headingRate = m_pedStats->m_headingChangeRate;
+}
+
bool
IsPedPointerValid_NotInWorld(CPed* pPed)
{
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 155e6cea..bbc5334b 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -916,6 +916,8 @@ public:
void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int);
void ClearWaitState(void);
+ void Undress(const char*);
+ void Dress(void);
bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; }
CWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; }
diff --git a/src/render/Particle.h b/src/render/Particle.h
index d254ef65..f2c3a459 100644
--- a/src/render/Particle.h
+++ b/src/render/Particle.h
@@ -97,4 +97,6 @@ public:
static void HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos);
};
+extern bool clearWaterDrop;
+
VALIDATE_SIZE(CParticle, 0x58);
diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp
index 839ad8b9..8ae3ffed 100644
--- a/src/save/GenericGameStorage.cpp
+++ b/src/save/GenericGameStorage.cpp
@@ -84,6 +84,7 @@ do {\
#define WriteSaveDataBlock(save_func)\
do {\
+ size = 0;\
buf = work_buff;\
reserved = 0;\
MakeSpaceForSizeInBufferPointer(presize, buf, postsize);\
@@ -192,6 +193,7 @@ GenericSave(int file)
// Save the rest
WriteSaveDataBlock(CPools::SavePedPool);
WriteSaveDataBlock(CGarages::Save);
+ WriteSaveDataBlock(CGameLogic::Save);
WriteSaveDataBlock(CPools::SaveVehiclePool);
WriteSaveDataBlock(CPools::SaveObjectPool);
WriteSaveDataBlock(ThePaths.Save);
@@ -306,6 +308,8 @@ GenericLoad()
LoadSaveDataBlock();
ReadDataFromBlock("Loading Garages \n", CGarages::Load);
LoadSaveDataBlock();
+ ReadDataFromBlock("Loading GameLogic \n", CGameLogic::Load);
+ LoadSaveDataBlock();
ReadDataFromBlock("Loading Vehicles \n", CPools::LoadVehiclePool);
LoadSaveDataBlock();
CProjectileInfo::RemoveAllProjectiles();