Merge branch 'master' into MoreLanguages

# Conflicts:
#	src/core/Frontend.cpp
#	src/render/Font.cpp
#	src/render/Hud.cpp
#	src/render/Hud.h
#	src/text/Messages.cpp
#	src/text/Text.cpp
This commit is contained in:
Sergeanur 2020-04-15 00:10:50 +03:00
commit e373d0526e
161 changed files with 26998 additions and 12336 deletions

View File

@ -16,12 +16,6 @@ such that we have a working game at all times.
- Since re3 is a DLL that works with original GTA III for now, you need Simple DLL Loader. You can get it [here](https://github.com/aap/simpledllloader). - Since re3 is a DLL that works with original GTA III for now, you need Simple DLL Loader. You can get it [here](https://github.com/aap/simpledllloader).
- Build re3 or download it from one of the above links (Debug or Release). - Build re3 or download it from one of the above links (Debug or Release).
- Make sure you included the re3 in `plugins.cfg` or `dlls.cfg`. - Make sure you included the re3 in `plugins.cfg` or `dlls.cfg`.
- re3 starts the script `main_freeroam.scm` that comes along with it by default, so you should copy it to from `gamefiles/` to your game's `data/` directory.
![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice**
If you want to load original script/story, press and hold G while game is loading.
This includes both starting new game and loading save game.
![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice if you will build it** ![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice if you will build it**
@ -38,35 +32,19 @@ to reverse at the time, calling the original functions is acceptable.
### Unreversed / incomplete classes (at least the ones we know) ### Unreversed / incomplete classes (at least the ones we know)
``` ```
cAudioManager - WIP
CBoat
CBrightLights
CBulletInfo CBulletInfo
CCrane
CCranes
CCullZone
CCullZones
CExplosion
CFallingGlassPane
CGlass
CMenuManager - WIP
CMotionBlurStreaks
CObject
CPacManPickups
CPedPath CPedPath
CRecordDataForChase
CRoadBlocks
CRubbish
CSceneEdit
CSkidmarks
CSpecialFX
CStats
CTrafficLights
CWeapon CWeapon
CWeather
CWorld CWorld
``` ```
The following classes have only unused or practically unused code left:
```
CCullZone - only mobile stuff
CCullZones - only mobile stuff
CSceneEdit
```
### Coding style ### Coding style
I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style), I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style),

BIN
gamefiles/menu.txd Normal file

Binary file not shown.

View File

@ -1,5 +1,5 @@
workspace "re3" workspace "re3"
configurations { "Debug", "Release", "ReleaseFH" } configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW" }
location "build" location "build"
files { "src/*.*" } files { "src/*.*" }
@ -13,6 +13,7 @@ workspace "re3"
files { "src/objects/*.*" } files { "src/objects/*.*" }
files { "src/peds/*.*" } files { "src/peds/*.*" }
files { "src/render/*.*" } files { "src/render/*.*" }
files { "src/rw/*.*" }
files { "src/save/*.*" } files { "src/save/*.*" }
files { "src/skel/*.*" } files { "src/skel/*.*" }
files { "src/skel/win/*.*" } files { "src/skel/win/*.*" }
@ -32,6 +33,7 @@ workspace "re3"
includedirs { "src/objects" } includedirs { "src/objects" }
includedirs { "src/peds" } includedirs { "src/peds" }
includedirs { "src/render" } includedirs { "src/render" }
includedirs { "src/rw" }
includedirs { "src/save/" } includedirs { "src/save/" }
includedirs { "src/skel/" } includedirs { "src/skel/" }
includedirs { "src/skel/win" } includedirs { "src/skel/win" }
@ -47,6 +49,12 @@ workspace "re3"
libdirs { "dxsdk/lib" } libdirs { "dxsdk/lib" }
libdirs { "milessdk/lib" } libdirs { "milessdk/lib" }
filter "configurations:DebugRW or configurations:ReleaseRW"
defines { "RWLIBS" }
libdirs { "rwsdk/lib/d3d8/release" }
links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp" }
filter {}
pbcommands = { pbcommands = {
"setlocal EnableDelayedExpansion", "setlocal EnableDelayedExpansion",
@ -102,3 +110,15 @@ project "re3"
staticruntime "on" staticruntime "on"
targetextension ".asi" targetextension ".asi"
setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "scripts/") setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "scripts/")
filter "configurations:DebugRW"
defines { "DEBUG" }
staticruntime "on"
symbols "On"
setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/")
filter "configurations:ReleaseRW"
defines { "NDEBUG" }
optimize "On"
staticruntime "on"
setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/")

View File

@ -134,8 +134,8 @@ uint32 &CCutsceneMgr::ms_cutsceneLoadStatus = *(uint32*)0x95CB40;
RpAtomic * RpAtomic *
CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data) CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data)
{ {
float radius = RpAtomicGetBoundingSphereMacro(atomic)->radius; float radius = RpAtomicGetBoundingSphere(atomic)->radius;
RwV3d center = RpAtomicGetBoundingSphereMacro(atomic)->center; RwV3d center = RpAtomicGetBoundingSphere(atomic)->center;
for (RwFrame *frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame)) for (RwFrame *frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame))
RwV3dTransformPoints(&center, &center, 1, RwFrameGetMatrix(frame)); RwV3dTransformPoints(&center, &center, 1, RwFrameGetMatrix(frame));
@ -326,7 +326,7 @@ CCutsceneMgr::CreateCutsceneObject(int modelId)
pModelInfo->SetColModel(pColModel); pModelInfo->SetColModel(pColModel);
clump = (RpClump*)pModelInfo->GetRwObject(); clump = (RpClump*)pModelInfo->GetRwObject();
assert(RwObjectGetType(clump) == rpCLUMP); assert(RwObjectGetType((RwObject*)clump) == rpCLUMP);
RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius); RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius);
pColModel->boundingSphere.radius = radius; pColModel->boundingSphere.radius = radius;
@ -352,6 +352,7 @@ CCutsceneMgr::DeleteCutsceneData(void)
CWorld::Remove(ms_pCutsceneObjects[ms_numCutsceneObjs]); CWorld::Remove(ms_pCutsceneObjects[ms_numCutsceneObjs]);
ms_pCutsceneObjects[ms_numCutsceneObjs]->DeleteRwObject(); ms_pCutsceneObjects[ms_numCutsceneObjs]->DeleteRwObject();
delete ms_pCutsceneObjects[ms_numCutsceneObjs]; delete ms_pCutsceneObjects[ms_numCutsceneObjs];
ms_pCutsceneObjects[ms_numCutsceneObjs] = nil;
} }
ms_numCutsceneObjs = 0; ms_numCutsceneObjs = 0;
@ -409,7 +410,7 @@ CCutsceneMgr::Update(void)
if (!ms_running) return; if (!ms_running) return;
ms_cutsceneTimer += CTimer::GetTimeStepNonClipped() * 0.02f; ms_cutsceneTimer += CTimer::GetTimeStepNonClippedInSeconds();
if (CGeneral::faststricmp(ms_cutsceneName, "end") && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FLYBY && ms_cutsceneLoadStatus == CUTSCENE_LOADING_0) { if (CGeneral::faststricmp(ms_cutsceneName, "end") && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FLYBY && ms_cutsceneLoadStatus == CUTSCENE_LOADING_0) {
if (CPad::GetPad(0)->GetCrossJustDown() if (CPad::GetPad(0)->GetCrossJustDown()
|| (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown()) || (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown())

View File

@ -26,7 +26,7 @@ public:
static CDirectory *&ms_pCutsceneDir; static CDirectory *&ms_pCutsceneDir;
static uint32 &ms_cutsceneLoadStatus; static uint32 &ms_cutsceneLoadStatus;
static void SetRunning(bool running) { ms_running = running; } static void StartCutsceneProcessing() { ms_cutsceneProcessing = true; }
static bool IsRunning(void) { return ms_running; } static bool IsRunning(void) { return ms_running; }
static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; } static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; }
static bool UseLodMultiplier(void) { return ms_useLodMultiplier; } static bool UseLodMultiplier(void) { return ms_useLodMultiplier; }

View File

@ -1,403 +1,419 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "DMAudio.h" #include "DMAudio.h"
#include "Entity.h" #include "Entity.h"
#include "AudioCollision.h" #include "AudioCollision.h"
#include "AudioManager.h" #include "AudioManager.h"
#include "AudioSamples.h" #include "AudioSamples.h"
#include "SurfaceTable.h" #include "SurfaceTable.h"
#include "sampman.h" #include "sampman.h"
const int CollisionSoundIntensity = 60; const int CollisionSoundIntensity = 60;
void cAudioCollisionManager::cAudioCollisionManager()
cAudioCollisionManager::AddCollisionToRequestedQueue() {
{ m_sQueue.m_pEntity1 = nil;
int32 collisionsIndex; m_sQueue.m_pEntity2 = nil;
int32 i; m_sQueue.m_bSurface1 = SURFACE_DEFAULT;
m_sQueue.m_bSurface2 = SURFACE_DEFAULT;
m_sQueue.m_fIntensity2 = 0.0f;
if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS) m_sQueue.m_fIntensity1 = 0.0f;
collisionsIndex = m_bCollisionsInQueue++; m_sQueue.m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
else {
collisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1]; for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
if (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return; m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
}
m_bCollisionsInQueue = 0;
m_asCollisions1[collisionsIndex] = m_sQueue; }
i = 0; void
if(collisionsIndex) { cAudioCollisionManager::AddCollisionToRequestedQueue()
while(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) { {
if(++i >= collisionsIndex) { int32 collisionsIndex;
m_bIndicesTable[i] = collisionsIndex; int32 i;
return;
}
} if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)
memmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i); collisionsIndex = m_bCollisionsInQueue++;
} else {
m_bIndicesTable[i] = collisionsIndex; collisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1];
} if (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return;
}
float
cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const m_asCollisions1[collisionsIndex] = m_sQueue;
{
return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f); i = 0;
} if(collisionsIndex) {
while(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) {
float if(++i >= collisionsIndex) {
cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const m_bIndicesTable[i] = collisionsIndex;
{ return;
float result; }
}
switch(a) { memmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i);
case SURFACE_DEFAULT: }
case SURFACE_TARMAC: m_bIndicesTable[i] = collisionsIndex;
case SURFACE_PAVEMENT: }
case SURFACE_STONE:
case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break; float
case SURFACE_GRASS: cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const
case SURFACE_LOOSE30: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; {
case SURFACE_DIRT: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
case SURFACE_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; }
case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; float
case SURFACE_SCAFFOLD: cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const
case SURFACE_STEEL: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break; {
case SURFACE_METAL_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break; float result;
case SURFACE_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
case SURFACE_METAL_POLE: switch(a) {
case SURFACE_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; case SURFACE_DEFAULT:
case SURFACE_STREET_LIGHT: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; case SURFACE_TARMAC:
case SURFACE_METAL14: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break; case SURFACE_PAVEMENT:
case SURFACE_METAL15: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break; case SURFACE_STONE:
case SURFACE_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;
case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break; case SURFACE_GRASS:
case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; case SURFACE_LOOSE30: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_PUDDLE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; case SURFACE_DIRT: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_WOOD: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break; case SURFACE_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
case SURFACE_WOOD_BOX: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break; case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
case SURFACE_WOOD_PLANK: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break; case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
case SURFACE_TIRE: case SURFACE_SCAFFOLD:
case SURFACE_RUBBER29: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; case SURFACE_STEEL: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break;
case SURFACE_HARD24: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break; case SURFACE_METAL_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break;
case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break; case SURFACE_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break; case SURFACE_METAL_POLE:
case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break; case SURFACE_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
default: result = 0.f; break; case SURFACE_STREET_LIGHT: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
} case SURFACE_METAL14: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break;
case SURFACE_METAL15: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break;
return result; case SURFACE_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
} case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;
case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
float case SURFACE_PUDDLE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const case SURFACE_WOOD: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break;
{ case SURFACE_WOOD_BOX: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break;
float e; case SURFACE_WOOD_PLANK: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break;
e = a; case SURFACE_TIRE:
if(a <= b) return 0.0f; case SURFACE_RUBBER29: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
if(c <= a) e = c; case SURFACE_HARD24: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break;
return (e - b) / d; case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;
} case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;
case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;
uint32 default: result = 0.f; break;
cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision) }
{
uint8 surface1 = audioCollision->m_bSurface1; return result;
uint8 surface2 = audioCollision->m_bSurface2; }
int32 vol;
float ratio; float
cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const
if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE || {
surface2 == SURFACE_HEDGE) { float e;
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f); e = a;
m_sQueueSample.m_nSampleIndex = SFX_RAIN; if(a <= b) return 0.0f;
m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000; if(c <= a) e = c;
vol = 50.f * ratio; return (e - b) / d;
} else { }
if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f); uint32
m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision)
m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000; {
vol = 30.f * ratio; uint8 surface1 = audioCollision->m_bSurface1;
uint8 surface2 = audioCollision->m_bSurface2;
} else { int32 vol;
if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK || float ratio;
surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f); if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID; surface2 == SURFACE_HEDGE) {
m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000; ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
vol = 50.f * ratio; m_sQueueSample.m_nSampleIndex = SFX_RAIN;
} else { m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { return 0; } vol = 50.f * ratio;
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f); } else {
m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1; if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) {
m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000; ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
vol = 40.f * ratio; m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
} m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
} vol = 30.f * ratio;
}
if(audioCollision->m_nBaseVolume < 2) vol = audioCollision->m_nBaseVolume * vol / 2; } else {
return vol; if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK ||
} surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) {
ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
void m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
cAudioManager::SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter) m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
{ vol = 50.f * ratio;
if(col->m_fIntensity2 > 0.0016f) { } else {
uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col); if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { return 0; }
if(emittingVol) { ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance); m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
m_sQueueSample.m_bVolume = m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance); vol = 40.f * ratio;
if(m_sQueueSample.m_bVolume) { }
m_sQueueSample.m_counter = counter; }
m_sQueueSample.m_vecPos = col->m_vecPosition; }
m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN; if(audioCollision->m_nBaseVolume < 2) vol = audioCollision->m_nBaseVolume * vol / 2;
m_sQueueSample.m_bIsDistant = false; return vol;
m_sQueueSample.field_16 = 7; }
m_sQueueSample.m_nLoopCount = 0;
m_sQueueSample.m_bEmittingVolume = emittingVol; void
m_sQueueSample.m_nLoopStart = cAudioManager::SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter)
SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); {
m_sQueueSample.m_nLoopEnd = if(col->m_fIntensity2 > 0.0016f) {
SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
m_sQueueSample.field_48 = 4.0f; if(emittingVol) {
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity; m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
m_sQueueSample.field_56 = 0; m_sQueueSample.m_bVolume =
m_sQueueSample.field_76 = 5; ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
m_sQueueSample.m_bReverbFlag = true; if(m_sQueueSample.m_bVolume) {
m_sQueueSample.m_bRequireReflection = false; m_sQueueSample.m_nCounter = counter;
AddSampleToRequestedQueue(); m_sQueueSample.m_vecPos = col->m_vecPosition;
} m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
} m_sQueueSample.m_bIs2D = false;
} m_sQueueSample.m_nReleasingVolumeModificator = 7;
} m_sQueueSample.m_nLoopCount = 0;
m_sQueueSample.m_bEmittingVolume = emittingVol;
void m_sQueueSample.m_nLoopStart =
cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col) SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
{ m_sQueueSample.m_nLoopEnd =
static const int32 gOneShotCol[] = { SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
SFX_COL_TARMAC_1, SFX_COL_TARMAC_1, SFX_COL_GRASS_1, m_sQueueSample.m_fSpeedMultiplier = 4.0f;
SFX_COL_GRAVEL_1, SFX_COL_MUD_1, SFX_COL_TARMAC_1, m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
SFX_COL_CAR_1, SFX_COL_GRASS_1, SFX_COL_SCAFFOLD_POLE_1, m_sQueueSample.m_bReleasingSoundFlag = false;
SFX_COL_GARAGE_DOOR_1, SFX_COL_CAR_PANEL_1, SFX_COL_THICK_METAL_PLATE_1, m_sQueueSample.m_nReleasingVolumeDivider = 5;
SFX_COL_SCAFFOLD_POLE_1, SFX_COL_LAMP_POST_1, SFX_COL_HYDRANT_1, m_sQueueSample.m_bReverbFlag = true;
SFX_COL_HYDRANT_1, SFX_COL_METAL_CHAIN_FENCE_1, SFX_COL_PED_1, m_sQueueSample.m_bRequireReflection = false;
SFX_COL_SAND_1, SFX_SPLASH_1, SFX_COL_WOOD_CRATES_1, AddSampleToRequestedQueue();
SFX_COL_WOOD_BENCH_1, SFX_COL_WOOD_SOLID_1, SFX_COL_GRASS_1, }
SFX_COL_GRASS_1, SFX_COL_VEG_1, SFX_COL_TARMAC_1, }
SFX_COL_CONTAINER_1, SFX_COL_NEWS_VENDOR_1, SFX_TYRE_BUMP, }
SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, SFX_COL_GATE}; }
int16 s1; void
int16 s2; cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col)
{
int32 emittingVol; static const int32 gOneShotCol[] = {
float ratio; SFX_COL_TARMAC_1, SFX_COL_TARMAC_1, SFX_COL_GRASS_1,
SFX_COL_GRAVEL_1, SFX_COL_MUD_1, SFX_COL_TARMAC_1,
static uint16 counter = 28; SFX_COL_CAR_1, SFX_COL_GRASS_1, SFX_COL_SCAFFOLD_POLE_1,
SFX_COL_GARAGE_DOOR_1, SFX_COL_CAR_PANEL_1, SFX_COL_THICK_METAL_PLATE_1,
for(int32 i = 0; i < 2; i++) { SFX_COL_SCAFFOLD_POLE_1, SFX_COL_LAMP_POST_1, SFX_COL_HYDRANT_1,
if(i) { SFX_COL_HYDRANT_1, SFX_COL_METAL_CHAIN_FENCE_1, SFX_COL_PED_1,
s1 = col->m_bSurface2; SFX_COL_SAND_1, SFX_SPLASH_1, SFX_COL_WOOD_CRATES_1,
s2 = col->m_bSurface1; SFX_COL_WOOD_BENCH_1, SFX_COL_WOOD_SOLID_1, SFX_COL_GRASS_1,
} else { SFX_COL_GRASS_1, SFX_COL_VEG_1, SFX_COL_TARMAC_1,
s1 = col->m_bSurface1; SFX_COL_CONTAINER_1, SFX_COL_NEWS_VENDOR_1, SFX_TYRE_BUMP,
s2 = col->m_bSurface2; SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, SFX_COL_GATE};
}
ratio = GetCollisionOneShotRatio(s1, col->m_fIntensity1); int16 s1;
if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio; int16 s2;
if(s1 == SURFACE_METAL6 && ratio < 0.6f) {
s1 = SURFACE_BILLBOARD; int32 emittingVol;
ratio = min(1.f, 2.f * ratio); float ratio;
}
emittingVol = 40.f * ratio; static uint16 counter = 28;
if(emittingVol) {
m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance); for(int32 i = 0; i < 2; i++) {
m_sQueueSample.m_bVolume = if(i) {
ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance); s1 = col->m_bSurface2;
if(m_sQueueSample.m_bVolume) { s2 = col->m_bSurface1;
m_sQueueSample.m_nSampleIndex = gOneShotCol[s1]; } else {
switch(m_sQueueSample.m_nSampleIndex) { s1 = col->m_bSurface1;
case SFX_COL_TARMAC_1: s2 = col->m_bSurface2;
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5; }
break; ratio = GetCollisionOneShotRatio(s1, col->m_fIntensity1);
case SFX_COL_CAR_PANEL_1: if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio;
m_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6; if(s1 == SURFACE_METAL6 && ratio < 0.6f) {
break; s1 = SURFACE_BILLBOARD;
case SFX_COL_LAMP_POST_1: ratio = min(1.f, 2.f * ratio);
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2; }
break; emittingVol = 40.f * ratio;
case SFX_COL_METAL_CHAIN_FENCE_1: if(emittingVol) {
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4; m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
break; m_sQueueSample.m_bVolume =
case SFX_COL_PED_1: ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 5; if(m_sQueueSample.m_bVolume) {
break; m_sQueueSample.m_nSampleIndex = gOneShotCol[s1];
case SFX_COL_WOOD_CRATES_1: switch(m_sQueueSample.m_nSampleIndex) {
m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4; case SFX_COL_TARMAC_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5;
case SFX_COL_WOOD_BENCH_1: break;
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4; case SFX_COL_CAR_PANEL_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6;
case SFX_COL_VEG_1: break;
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5; case SFX_COL_LAMP_POST_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2;
case SFX_COL_NEWS_VENDOR_1: break;
m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3; case SFX_COL_METAL_CHAIN_FENCE_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4;
case SFX_COL_CAR_1: break;
m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5; case SFX_COL_PED_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 5;
case SFX_COL_CARDBOARD_1: break;
m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2; case SFX_COL_WOOD_CRATES_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4;
default: break; break;
} case SFX_COL_WOOD_BENCH_1:
switch(s1) { m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4;
case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break; break;
case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break; case SFX_COL_VEG_1:
case SURFACE_PUDDLE: m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5;
m_sQueueSample.m_nFrequency = break;
2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); case SFX_COL_NEWS_VENDOR_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3;
case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break; break;
case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break; case SFX_COL_CAR_1:
default: m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5;
m_sQueueSample.m_nFrequency = break;
SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); case SFX_COL_CARDBOARD_1:
break; m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2;
} break;
m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); default: break;
m_sQueueSample.m_counter = counter++; }
if(counter >= 255) counter = 28; switch(s1) {
m_sQueueSample.m_vecPos = col->m_vecPosition; case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break;
m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN; case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break;
m_sQueueSample.m_bIsDistant = false; case SURFACE_PUDDLE:
m_sQueueSample.field_16 = 11; m_sQueueSample.m_nFrequency =
m_sQueueSample.m_nLoopCount = 1; 2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_bEmittingVolume = emittingVol; break;
m_sQueueSample.m_nLoopStart = 0; case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break;
m_sQueueSample.m_nLoopEnd = -1; case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break;
m_sQueueSample.field_48 = 4.0f; default:
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity; m_sQueueSample.m_nFrequency =
m_sQueueSample.field_56 = 1; SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.m_bReverbFlag = true; break;
m_sQueueSample.m_bRequireReflection = false; }
AddSampleToRequestedQueue(); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
} m_sQueueSample.m_nCounter = counter++;
} if(counter >= 255) counter = 28;
} m_sQueueSample.m_vecPos = col->m_vecPosition;
} m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
m_sQueueSample.m_bIs2D = false;
void m_sQueueSample.m_nReleasingVolumeModificator = 11;
cAudioManager::ServiceCollisions() m_sQueueSample.m_nLoopCount = 1;
{ m_sQueueSample.m_bEmittingVolume = emittingVol;
int i, j; m_sQueueSample.m_nLoopStart = 0;
bool someArr1[NUMAUDIOCOLLISIONS]; m_sQueueSample.m_nLoopEnd = -1;
bool someArr2[NUMAUDIOCOLLISIONS]; m_sQueueSample.m_fSpeedMultiplier = 4.0f;
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
m_sQueueSample.m_nEntityIndex = m_nCollisionEntity; m_sQueueSample.m_bReleasingSoundFlag = true;
m_sQueueSample.m_bReverbFlag = true;
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++) m_sQueueSample.m_bRequireReflection = false;
someArr1[i] = someArr2[i] = false; AddSampleToRequestedQueue();
}
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) { }
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) { }
int index = m_sCollisionManager.m_bIndicesTable[i]; }
if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
&& (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2) void
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1) cAudioManager::ServiceCollisions()
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2) {
) { int i, j;
someArr1[index] = true; bool someArr1[NUMAUDIOCOLLISIONS];
someArr2[j] = true; bool someArr2[NUMAUDIOCOLLISIONS];
m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j); m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
break;
} for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
} someArr1[i] = someArr2[i] = false;
}
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
for (i = 0; i < NUMAUDIOCOLLISIONS; i++) { for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
if (!someArr2[i]) { int index = m_sCollisionManager.m_bIndicesTable[i];
m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil; if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil; && (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = SURFACE_DEFAULT; && (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1)
m_sCollisionManager.m_asCollisions2[i].m_bSurface2 = SURFACE_DEFAULT; && (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2)
m_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f; ) {
m_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f; someArr1[index] = true;
m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f); someArr2[j] = true;
m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f; m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
} SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
} break;
}
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) { }
int index = m_sCollisionManager.m_bIndicesTable[i]; }
if (!someArr1[index]) {
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) { for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
if (someArr2[j]) { if (!someArr2[i]) {
m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1; m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1; m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
m_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2; m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = SURFACE_DEFAULT;
m_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1; m_sCollisionManager.m_asCollisions2[i].m_bSurface2 = SURFACE_DEFAULT;
m_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2; m_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f;
break; m_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f;
} m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
} m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
SetUpOneShotCollisionSound(&m_sCollisionManager.m_asCollisions1[index]); }
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j); }
}
} for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
int index = m_sCollisionManager.m_bIndicesTable[i];
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++) if (!someArr1[index]) {
m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS; for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
m_sCollisionManager.m_bCollisionsInQueue = 0; if (someArr2[j]) {
} m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
void m_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2;
cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, m_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1;
float velocity) m_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
{ break;
float distSquared; }
CVector v1; }
CVector v2; SetUpOneShotCollisionSound(&m_sCollisionManager.m_asCollisions1[index]);
SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bUserPause || }
(velocity < 0.0016f && collisionPower < 0.01f)) }
return;
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
if(entity1->IsBuilding()) { m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
v1 = v2 = entity2->GetPosition(); m_sCollisionManager.m_bCollisionsInQueue = 0;
} else if(entity2->IsBuilding()) { }
v1 = v2 = entity1->GetPosition();
} else { void
v1 = entity1->GetPosition(); cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
v2 = entity2->GetPosition(); float velocity)
} {
CVector pos = (v1 + v2) * 0.5f; float distSquared;
distSquared = GetDistanceSquared(&pos); CVector v1;
if(distSquared < SQR(CollisionSoundIntensity)) { CVector v2;
m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
m_sCollisionManager.m_sQueue.m_pEntity2 = entity2; if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bUserPause ||
m_sCollisionManager.m_sQueue.m_bSurface1 = surface1; (velocity < 0.0016f && collisionPower < 0.01f))
m_sCollisionManager.m_sQueue.m_bSurface2 = surface2; return;
m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity; if(entity1->IsBuilding()) {
m_sCollisionManager.m_sQueue.m_vecPosition = pos; v1 = v2 = entity2->GetPosition();
m_sCollisionManager.m_sQueue.m_fDistance = distSquared; } else if(entity2->IsBuilding()) {
m_sCollisionManager.AddCollisionToRequestedQueue(); v1 = v2 = entity1->GetPosition();
} } else {
} v1 = entity1->GetPosition();
v2 = entity2->GetPosition();
STARTPATCHES }
InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP); CVector pos = (v1 + v2) * 0.5f;
InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP); distSquared = GetDistanceSquared(&pos);
InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP); if(distSquared < SQR(CollisionSoundIntensity)) {
InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP); m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP); m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP); m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP); m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP); m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
ENDPATCHES m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
m_sCollisionManager.m_sQueue.m_vecPosition = pos;
m_sCollisionManager.m_sQueue.m_fDistance = distSquared;
m_sCollisionManager.AddCollisionToRequestedQueue();
}
}
STARTPATCHES
InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP);
InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP);
InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP);
InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP);
InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP);
InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP);
InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP);
InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP);
ENDPATCHES

View File

@ -1,36 +1,36 @@
#pragma once #pragma once
#define NUMAUDIOCOLLISIONS 10 #define NUMAUDIOCOLLISIONS 10
class cAudioCollision class cAudioCollision
{ {
public: public:
CEntity *m_pEntity1; CEntity *m_pEntity1;
CEntity *m_pEntity2; CEntity *m_pEntity2;
uint8 m_bSurface1; uint8 m_bSurface1;
uint8 m_bSurface2; uint8 m_bSurface2;
float m_fIntensity1; float m_fIntensity1;
float m_fIntensity2; float m_fIntensity2;
CVector m_vecPosition; CVector m_vecPosition;
float m_fDistance; float m_fDistance;
int32 m_nBaseVolume; int32 m_nBaseVolume;
// no methods // no methods
}; };
static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error"); static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error");
class cAudioCollisionManager class cAudioCollisionManager
{ {
public: public:
cAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS]; cAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS];
cAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS]; cAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS];
uint8 m_bIndicesTable[NUMAUDIOCOLLISIONS]; uint8 m_bIndicesTable[NUMAUDIOCOLLISIONS];
uint8 m_bCollisionsInQueue; uint8 m_bCollisionsInQueue;
cAudioCollision m_sQueue; cAudioCollision m_sQueue;
// reversed all methods cAudioCollisionManager();
void AddCollisionToRequestedQueue(); /// ok void AddCollisionToRequestedQueue();
}; };
static_assert(sizeof(cAudioCollisionManager) == 852, "cAudioCollisionManager: error"); static_assert(sizeof(cAudioCollisionManager) == 852, "cAudioCollisionManager: error");

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,14 @@
#pragma once #pragma once
#include "DMAudio.h"
#include "common.h" #include "common.h"
#include "config.h" #include "config.h"
#include "DMAudio.h"
#include "AudioCollision.h" #include "AudioCollision.h"
#include "PoliceRadio.h" #include "PoliceRadio.h"
enum eScriptSounds : int16 enum eScriptSounds : int16 {
{
SCRIPT_SOUND_0 = 0, SCRIPT_SOUND_0 = 0,
SCRIPT_SOUND_1 = 1, SCRIPT_SOUND_1 = 1,
SCRIPT_SOUND_2 = 2, SCRIPT_SOUND_2 = 2,
@ -138,47 +139,47 @@ class tSound
{ {
public: public:
int32 m_nEntityIndex; int32 m_nEntityIndex;
int32 m_counter; int32 m_nCounter;
int32 m_nSampleIndex; int32 m_nSampleIndex;
uint8 m_bBankIndex; uint8 m_bBankIndex;
bool m_bIsDistant; bool m_bIs2D;
uint8 field_14; uint8 field_14; // unused
uint8 field_15; uint8 field_15; // unused
int32 field_16; int32 m_nReleasingVolumeModificator;
int32 m_nFrequency; int32 m_nFrequency;
uint8 m_bVolume; uint8 m_bVolume;
uint8 field_25; uint8 field_25; // unused
uint8 field_26; uint8 field_26; // unused
uint8 field_27; uint8 field_27; // unused
float m_fDistance; float m_fDistance;
int32 m_nLoopCount; int32 m_nLoopCount;
int32 m_nLoopStart; int32 m_nLoopStart;
int32 m_nLoopEnd; int32 m_nLoopEnd;
uint8 m_bEmittingVolume; uint8 m_bEmittingVolume;
uint8 field_45; uint8 field_45; // unused
uint8 field_46; uint8 field_46; // unused
uint8 field_47; uint8 field_47; // unused
float field_48; float m_fSpeedMultiplier;
float m_fSoundIntensity; float m_fSoundIntensity;
uint8 field_56; bool m_bReleasingSoundFlag;
uint8 field_57; uint8 field_57; // unused
uint8 field_58; uint8 field_58; // unused
uint8 field_59; uint8 field_59; // unused
CVector m_vecPos; CVector m_vecPos;
bool m_bReverbFlag; bool m_bReverbFlag;
uint8 m_bLoopsRemaining; uint8 m_bLoopsRemaining;
bool m_bRequireReflection; bool m_bRequireReflection; // Used for oneshots
uint8 m_bOffset; uint8 m_bOffset;
int32 field_76; int32 m_nReleasingVolumeDivider;
uint8 m_bIsProcessed; bool m_bIsProcessed;
uint8 m_bLoopEnded; bool m_bLoopEnded;
uint8 field_82; uint8 field_82; // unused
uint8 field_83; uint8 field_83; // unused
int32 calculatedVolume; int32 m_nCalculatedVolume;
int8 field_88; int8 m_nVolumeChange;
uint8 field_89; uint8 field_89; // unused
uint8 field_90; uint8 field_90; // unused
uint8 field_91; uint8 field_91; // unused
// no methods // no methods
}; };
@ -196,7 +197,7 @@ public:
bool m_bIsUsed; bool m_bIsUsed;
uint8 m_bStatus; uint8 m_bStatus;
int16 m_awAudioEvent[NUM_AUDIOENTITY_EVENTS]; int16 m_awAudioEvent[NUM_AUDIOENTITY_EVENTS];
uint8 gap_18[2]; //uint8 gap_18[2];
float m_afVolume[NUM_AUDIOENTITY_EVENTS]; float m_afVolume[NUM_AUDIOENTITY_EVENTS];
uint8 m_AudioEvents; uint8 m_AudioEvents;
uint8 field_25[3]; uint8 field_25[3];
@ -210,12 +211,11 @@ class tPedComment
{ {
public: public:
int32 m_nSampleIndex; int32 m_nSampleIndex;
int32 m_entityIndex; int32 m_nEntityIndex;
CVector m_vecPos; CVector m_vecPos;
float m_fDistance; float m_fDistance;
uint8 m_bVolume; uint8 m_bVolume;
int8 field_25; // allocated time? int8 m_nProcess;
uint8 gap_26[2];
// no methods // no methods
}; };
@ -226,14 +226,13 @@ class cPedComments
{ {
public: public:
tPedComment m_asPedComments[NUM_PED_COMMENTS_BANKS][NUM_PED_COMMENTS_SLOTS]; tPedComment m_asPedComments[NUM_PED_COMMENTS_BANKS][NUM_PED_COMMENTS_SLOTS];
uint8 indexMap[NUM_PED_COMMENTS_BANKS][NUM_PED_COMMENTS_SLOTS]; uint8 m_nIndexMap[NUM_PED_COMMENTS_BANKS][NUM_PED_COMMENTS_SLOTS];
uint8 nrOfCommentsInBank[NUM_PED_COMMENTS_BANKS]; uint8 m_nCommentsInBank[NUM_PED_COMMENTS_BANKS];
uint8 activeBank; uint8 m_nActiveBank;
uint8 gap_1163[1];
// reversed all methods cPedComments();
void Add(tPedComment *com); /// ok void Add(tPedComment *com);
void Process(); /// ok void Process();
}; };
static_assert(sizeof(cPedComments) == 1164, "cPedComments: error"); static_assert(sizeof(cPedComments) == 1164, "cPedComments: error");
@ -244,23 +243,35 @@ class cMissionAudio
{ {
public: public:
CVector m_vecPos; CVector m_vecPos;
uint8 field_12; bool m_bPredefinedProperties;
uint8 gap_13[3]; //uint8 gap_13[3];
int m_nSampleIndex; int m_nSampleIndex;
uint8 m_bLoadingStatus; uint8 m_bLoadingStatus;
uint8 m_bPlayStatus; uint8 m_bPlayStatus;
uint8 field_22; uint8 field_22; // todo find a name
uint8 field_23; uint8 field_23; // unused
int field_24; int32 m_nMissionAudioCounter;
bool m_bIsPlayed; bool m_bIsPlayed;
uint8 field_29; uint8 field_29; // unused
uint8 field_30; uint8 field_30; // unused
uint8 field_31; uint8 field_31; // unused
// no methods // no methods
}; };
static_assert(sizeof(cMissionAudio) == 32, "cMissionAudio: error"); static_assert(sizeof(cMissionAudio) == 32, "cMissionAudio: error");
// name made up
class cAudioScriptObjectManager
{
public:
int32 m_anScriptObjectEntityIndices[NUM_SCRIPT_MAX_ENTITIES];
int32 m_nScriptObjectEntityTotal;
cAudioScriptObjectManager() { m_nScriptObjectEntityTotal = 0; }
~cAudioScriptObjectManager() { m_nScriptObjectEntityTotal = 0; }
};
class cVehicleParams; class cVehicleParams;
class CPlane; class CPlane;
class CVehicle; class CVehicle;
@ -289,22 +300,22 @@ class cAudioManager
{ {
public: public:
bool m_bIsInitialised; bool m_bIsInitialised;
uint8 field_1; uint8 field_1; // unused
uint8 field_2; bool m_bFifthFrameFlag;
uint8 m_bActiveSamples; uint8 m_bActiveSamples;
uint8 field_4; uint8 field_4; // unused
bool m_bDynamicAcousticModelingStatus; bool m_bDynamicAcousticModelingStatus;
uint8 field_6; uint8 field_6; // unused
uint8 field_7; uint8 field_7; // unused
float speedOfSound; float m_fSpeedOfSound;
bool m_bTimerJustReset; bool m_bTimerJustReset;
uint8 field_13; uint8 field_13; // unused
uint8 field_14; uint8 field_14; // unused
uint8 field_15; uint8 field_15; // unused
int32 m_nTimer; int32 m_nTimer;
tSound m_sQueueSample; tSound m_sQueueSample;
bool m_bActiveSampleQueue; bool m_bActiveSampleQueue;
uint8 gap_109[3]; uint8 gap_109[3]; // unused
tSound m_asSamples[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS]; tSound m_asSamples[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS];
uint8 m_abSampleQueueIndexTable[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS]; uint8 m_abSampleQueueIndexTable[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS];
uint8 m_bSampleRequestQueuesStatus[NUM_SOUNDS_SAMPLES_BANKS]; uint8 m_bSampleRequestQueuesStatus[NUM_SOUNDS_SAMPLES_BANKS];
@ -314,8 +325,7 @@ public:
int32 m_nAudioEntitiesTotal; int32 m_nAudioEntitiesTotal;
CVector m_avecReflectionsPos[NUM_AUDIO_REFLECTIONS]; CVector m_avecReflectionsPos[NUM_AUDIO_REFLECTIONS];
float m_afReflectionsDistances[NUM_AUDIO_REFLECTIONS]; float m_afReflectionsDistances[NUM_AUDIO_REFLECTIONS];
int32 m_anScriptObjectEntityIndices[NUM_SCRIPT_MAX_ENTITIES]; cAudioScriptObjectManager m_sAudioScriptObjectManager;
int32 m_nScriptObjectEntityTotal;
cPedComments m_sPedComments; cPedComments m_sPedComments;
int32 m_nFireAudioEntity; int32 m_nFireAudioEntity;
int32 m_nWaterCannonEntity; int32 m_nWaterCannonEntity;
@ -328,12 +338,15 @@ public:
int32 m_nBridgeEntity; int32 m_nBridgeEntity;
cMissionAudio m_sMissionAudio; cMissionAudio m_sMissionAudio;
int32 m_anRandomTable[5]; int32 m_anRandomTable[5];
uint8 field_19192; uint8 m_bTimeSpent;
uint8 m_bUserPause; uint8 m_bUserPause;
uint8 m_bPreviousUserPause; uint8 m_bPreviousUserPause;
uint8 field_19195; // time? uint8 field_19195; // unused
uint32 m_FrameCounter; uint32 m_FrameCounter;
cAudioManager();
~cAudioManager();
// getters // getters
uint32 GetFrameCounter() const { return m_FrameCounter; } uint32 GetFrameCounter() const { return m_FrameCounter; }
float GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; } float GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; }
@ -341,29 +354,29 @@ public:
bool IsMissionAudioPlaying() const { return m_sMissionAudio.m_bPlayStatus == 1; } bool IsMissionAudioPlaying() const { return m_sMissionAudio.m_bPlayStatus == 1; }
// "Should" be in alphabetic order, except "getXTalkSfx" // "Should" be in alphabetic order, except "getXTalkSfx"
void AddDetailsToRequestedOrderList(uint8 sample); /// ok (check once more) void AddDetailsToRequestedOrderList(uint8 sample);
void AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 unk1, void AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 unk1,
uint8 counter, bool notLooping); /// ok uint8 counter, bool notLooping);
void AddReflectionsToRequestedQueue(); /// ok (check value) void AddReflectionsToRequestedQueue();
void AddReleasingSounds(); /// ok (check) void AddReleasingSounds();
void AddSampleToRequestedQueue(); /// ok void AddSampleToRequestedQueue();
void AgeCrimes(); /// ok void AgeCrimes();
void CalculateDistance(bool &condition, float dist); /// ok void CalculateDistance(bool &condition, float dist);
bool CheckForAnAudioFileOnCD() const; /// ok bool CheckForAnAudioFileOnCD() const;
void ClearActiveSamples(); /// ok void ClearActiveSamples();
void ClearMissionAudio(); /// ok void ClearMissionAudio();
void ClearRequestedQueue(); /// ok void ClearRequestedQueue();
int32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, int32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2,
float speedMultiplier) const; /// ok float speedMultiplier) const;
int32 ComputePan(float, CVector *); /// ok int32 ComputePan(float, CVector *);
uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const; /// ok uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const;
int32 CreateEntity(int32 type, void *entity); /// ok int32 CreateEntity(int32 type, void *entity);
void DestroyAllGameCreatedEntities(); /// ok void DestroyAllGameCreatedEntities();
void DestroyEntity(int32 id); /// ok void DestroyEntity(int32 id);
void DoJumboVolOffset() const; /// ok void DoJumboVolOffset() const;
void DoPoliceRadioCrackle(); /// ok void DoPoliceRadioCrackle();
// functions returning talk sfx, // functions returning talk sfx,
// order from GetPedCommentSfx // order from GetPedCommentSfx
@ -445,154 +458,151 @@ public:
uint32 GetGenericFemaleTalkSfx(int16 sound); uint32 GetGenericFemaleTalkSfx(int16 sound);
// end of functions returning talk sfx // end of functions returning talk sfx
void GenerateIntegerRandomNumberTable(); /// ok void GenerateIntegerRandomNumberTable();
char *Get3DProviderName(uint8 id) const; char *Get3DProviderName(uint8 id) const;
uint8 GetCDAudioDriveLetter() const; uint8 GetCDAudioDriveLetter() const;
int8 GetCurrent3DProviderIndex() const; /// ok int8 GetCurrent3DProviderIndex() const;
float GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const; // not used float GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const; // not used
float GetCollisionOneShotRatio(int32 a, float b) const; /// ok float GetCollisionOneShotRatio(int32 a, float b) const;
float GetCollisionRatio(float a, float b, float c, float d) const; /// ok float GetCollisionRatio(float a, float b, float c, float d) const;
float GetDistanceSquared(CVector *v) const; /// ok float GetDistanceSquared(CVector *v) const;
int32 GetJumboTaxiFreq() const; /// ok int32 GetJumboTaxiFreq() const;
bool GetMissionAudioLoadingStatus() const; /// ok bool GetMissionAudioLoadingStatus() const;
int8 GetMissionScriptPoliceAudioPlayingStatus() const; /// ok int8 GetMissionScriptPoliceAudioPlayingStatus() const;
uint8 GetNum3DProvidersAvailable() const; uint8 GetNum3DProvidersAvailable() const;
int32 GetPedCommentSfx(CPed *ped, int32 sound); int32 GetPedCommentSfx(CPed *ped, int32 sound);
void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const; void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const;
float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile,
cTransmission *transmission, cTransmission *transmission, float velocityChange);
float velocityChange); /// ok
float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile,
cTransmission *transmission, cTransmission *transmission, float velocityChange);
float velocityChange); /// ok
bool HasAirBrakes(int32 model) const; /// ok bool HasAirBrakes(int32 model) const;
void Initialise(); /// ok void Initialise();
void InitialisePoliceRadio(); /// ok void InitialisePoliceRadio();
void InitialisePoliceRadioZones(); /// ok void InitialisePoliceRadioZones();
void InterrogateAudioEntities(); /// ok void InterrogateAudioEntities();
bool IsAudioInitialised() const; /// ok bool IsAudioInitialised() const;
bool IsMissionAudioSampleFinished(); /// ok bool IsMissionAudioSampleFinished();
bool IsMP3RadioChannelAvailable() const; bool IsMP3RadioChannelAvailable() const;
bool MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; /// ok bool MissionScriptAudioUsesPoliceChannel(int32 soundMission) const;
void PlayLoadedMissionAudio(); /// ok void PlayLoadedMissionAudio();
void PlayOneShot(int32 index, int16 sound, float vol); /// ok void PlayOneShot(int32 index, int16 sound, float vol);
void PlaySuspectLastSeen(float x, float y, float z); /// ok void PlaySuspectLastSeen(float x, float y, float z);
void PlayerJustGotInCar() const; /// ok void PlayerJustGotInCar() const;
void PlayerJustLeftCar() const; /// ok void PlayerJustLeftCar() const;
void PostInitialiseGameSpecificSetup(); /// ok void PostInitialiseGameSpecificSetup();
void PostTerminateGameSpecificShutdown(); /// ok void PostTerminateGameSpecificShutdown();
void PreInitialiseGameSpecificSetup() const; /// ok void PreInitialiseGameSpecificSetup() const;
void PreloadMissionAudio(const char *name); /// ok void PreloadMissionAudio(const char *name);
void PreTerminateGameSpecificShutdown(); /// ok void PreTerminateGameSpecificShutdown();
/// processX - main logic of adding new sounds /// processX - main logic of adding new sounds
void ProcessActiveQueues(); /// ok void ProcessActiveQueues();
bool ProcessAirBrakes(cVehicleParams *params); /// ok bool ProcessAirBrakes(cVehicleParams *params);
void ProcessAirportScriptObject(uint8 sound); /// ok void ProcessAirportScriptObject(uint8 sound);
bool ProcessBoatEngine(cVehicleParams *params); /// ok bool ProcessBoatEngine(cVehicleParams *params);
bool ProcessBoatMovingOverWater(cVehicleParams *params); /// ok bool ProcessBoatMovingOverWater(cVehicleParams *params);
void ProcessBridge(); /// ok void ProcessBridge();
void ProcessBridgeMotor(); /// ok void ProcessBridgeMotor();
void ProcessBridgeOneShots(); /// ok void ProcessBridgeOneShots();
void ProcessBridgeWarning(); /// ok void ProcessBridgeWarning();
bool ProcessCarBombTick(cVehicleParams *params); /// ok bool ProcessCarBombTick(cVehicleParams *params);
void ProcessCesna(cVehicleParams *params); /// ok void ProcessCesna(cVehicleParams *params);
void ProcessCinemaScriptObject(uint8 sound); /// ok void ProcessCinemaScriptObject(uint8 sound);
void ProcessCrane(); /// ok void ProcessCrane();
void ProcessDocksScriptObject(uint8 sound); /// ok void ProcessDocksScriptObject(uint8 sound);
bool ProcessEngineDamage(cVehicleParams *params); /// ok bool ProcessEngineDamage(cVehicleParams *params);
void ProcessEntity(int32 sound); /// ok void ProcessEntity(int32 sound);
void ProcessExplosions(int32 explosion); /// ok void ProcessExplosions(int32 explosion);
void ProcessFireHydrant(); /// ok void ProcessFireHydrant();
void ProcessFires(int32 entity); /// ok void ProcessFires(int32 entity);
void ProcessFrontEnd(); /// ok void ProcessFrontEnd();
void ProcessGarages(); /// ok void ProcessGarages();
bool ProcessHelicopter(cVehicleParams *params); /// ok bool ProcessHelicopter(cVehicleParams *params);
void ProcessHomeScriptObject(uint8 sound); /// ok void ProcessHomeScriptObject(uint8 sound);
void ProcessJumbo(cVehicleParams *); /// ok void ProcessJumbo(cVehicleParams *);
void ProcessJumboAccel(CPlane *plane); /// ok void ProcessJumboAccel(CPlane *plane);
void ProcessJumboDecel(CPlane *plane); /// ok void ProcessJumboDecel(CPlane *plane);
void ProcessJumboFlying(); /// ok void ProcessJumboFlying();
void ProcessJumboLanding(CPlane *plane); /// ok void ProcessJumboLanding(CPlane *plane);
void ProcessJumboTakeOff(CPlane *plane); /// ok void ProcessJumboTakeOff(CPlane *plane);
void ProcessJumboTaxi(); /// ok void ProcessJumboTaxi();
void ProcessLaunderetteScriptObject(uint8 sound); /// ok void ProcessLaunderetteScriptObject(uint8 sound);
void ProcessLoopingScriptObject(uint8 sound); /// ok void ProcessLoopingScriptObject(uint8 sound);
void ProcessMissionAudio(); /// ok void ProcessMissionAudio();
void ProcessModelCarEngine(cVehicleParams *params); /// ok void ProcessModelCarEngine(cVehicleParams *params);
void ProcessOneShotScriptObject(uint8 sound); /// ok void ProcessOneShotScriptObject(uint8 sound);
void ProcessPed(CPhysical *ped); /// ok void ProcessPed(CPhysical *ped);
void ProcessPedHeadphones(cPedParams *params); /// ok void ProcessPedHeadphones(cPedParams *params);
void ProcessPedOneShots(cPedParams *params); // todo later (weird) void ProcessPedOneShots(cPedParams *params);
void ProcessPhysical(int32 id); /// ok void ProcessPhysical(int32 id);
void ProcessPlane(cVehicleParams *params); /// ok void ProcessPlane(cVehicleParams *params);
void ProcessPlayersVehicleEngine(cVehicleParams *params, void ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile);
CAutomobile *automobile); /// ok void ProcessPoliceCellBeatingScriptObject(uint8 sound);
void ProcessPoliceCellBeatingScriptObject(uint8 sound); /// ok void ProcessPornCinema(uint8 sound);
void ProcessPornCinema(uint8 sound); /// ok void ProcessProjectiles();
void ProcessProjectiles(); /// ok void ProcessRainOnVehicle(cVehicleParams *params);
void ProcessRainOnVehicle(cVehicleParams *params); /// ok void ProcessReverb() const;
void ProcessReverb() const; /// ok bool ProcessReverseGear(cVehicleParams *params);
bool ProcessReverseGear(cVehicleParams *params); /// ok void ProcessSawMillScriptObject(uint8 sound);
void ProcessSawMillScriptObject(uint8 sound); /// ok void ProcessScriptObject(int32 id);
void ProcessScriptObject(int32 id); /// ok void ProcessShopScriptObject(uint8 sound);
void ProcessShopScriptObject(uint8 sound); /// ok void ProcessSpecial();
void ProcessSpecial(); /// ok bool ProcessTrainNoise(cVehicleParams *params);
bool ProcessTrainNoise(cVehicleParams *params); /// ok void ProcessVehicle(CVehicle *vehicle);
void ProcessVehicle(CVehicle *vehicle); /// ok bool ProcessVehicleDoors(cVehicleParams *params);
bool ProcessVehicleDoors(cVehicleParams *params); /// ok void ProcessVehicleEngine(cVehicleParams *params);
void ProcessVehicleEngine(cVehicleParams *params); /// ok void ProcessVehicleHorn(cVehicleParams *params);
void ProcessVehicleHorn(cVehicleParams *params); /// ok void ProcessVehicleOneShots(cVehicleParams *params);
void ProcessVehicleOneShots(void *); // todo bool ProcessVehicleReverseWarning(cVehicleParams *params);
bool ProcessVehicleReverseWarning(cVehicleParams *params); /// ok bool ProcessVehicleRoadNoise(cVehicleParams *params);
bool ProcessVehicleRoadNoise(cVehicleParams *params); /// ok void ProcessVehicleSirenOrAlarm(cVehicleParams *params);
void ProcessVehicleSirenOrAlarm(cVehicleParams *params); /// ok void ProcessVehicleSkidding(cVehicleParams *params);
void ProcessVehicleSkidding(cVehicleParams *params); /// ok void ProcessWaterCannon(int32);
void ProcessWaterCannon(int32); /// ok void ProcessWeather(int32 id);
void ProcessWeather(int32 id); /// ok bool ProcessWetRoadNoise(cVehicleParams *params);
bool ProcessWetRoadNoise(cVehicleParams *params); /// ok void ProcessWorkShopScriptObject(uint8 sound);
void ProcessWorkShopScriptObject(uint8 sound); /// ok
int32 RandomDisplacement(uint32 seed) const; int32 RandomDisplacement(uint32 seed) const;
void ReacquireDigitalHandle() const; void ReacquireDigitalHandle() const;
void ReleaseDigitalHandle() const; void ReleaseDigitalHandle() const;
void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2,
float intensity2); /// ok float collisionPower, float intensity2);
void ReportCrime(int32 crime, const CVector *pos); /// ok void ReportCrime(int32 crime, const CVector *pos);
void ResetAudioLogicTimers(uint32 timer); /// ok void ResetAudioLogicTimers(uint32 timer);
void ResetPoliceRadio(); /// ok void ResetPoliceRadio();
void ResetTimers(uint32 time); /// ok void ResetTimers(uint32 time);
void Service(); /// ok void Service();
void ServiceCollisions(); /// ok void ServiceCollisions();
void ServicePoliceRadio(); /// ok void ServicePoliceRadio();
void ServicePoliceRadioChannel(int32 wantedLevel); /// ok void ServicePoliceRadioChannel(int32 wantedLevel);
void ServiceSoundEffects(); /// ok void ServiceSoundEffects();
int8 SetCurrent3DProvider(uint8 which); /// ok int8 SetCurrent3DProvider(uint8 which);
void SetDynamicAcousticModelingStatus(bool status); void SetDynamicAcousticModelingStatus(bool status);
void SetEffectsFadeVolume(uint8 volume) const; void SetEffectsFadeVolume(uint8 volume) const;
void SetEffectsMasterVolume(uint8 volume) const; void SetEffectsMasterVolume(uint8 volume) const;
void SetEntityStatus(int32 id, uint8 status); void SetEntityStatus(int32 id, uint8 status);
uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision); /// ok uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision);
void SetMissionAudioLocation(float x, float y, float z); void SetMissionAudioLocation(float x, float y, float z);
void SetMissionScriptPoliceAudio(int32 sfx) const; void SetMissionScriptPoliceAudio(int32 sfx) const;
void SetMonoMode(uint8); // todo (mobile) void SetMonoMode(uint8); // todo (mobile)
void SetMusicFadeVolume(uint8 volume) const; void SetMusicFadeVolume(uint8 volume) const;
void SetMusicMasterVolume(uint8 volume) const; void SetMusicMasterVolume(uint8 volume) const;
void SetSpeakerConfig(int32 conf) const; void SetSpeakerConfig(int32 conf) const;
void SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter); /// ok void SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter);
void SetUpOneShotCollisionSound(cAudioCollision *col); /// ok void SetUpOneShotCollisionSound(cAudioCollision *col);
bool SetupCrimeReport(); /// ok bool SetupCrimeReport();
bool SetupJumboEngineSound(uint8 vol, int32 freq); /// ok bool SetupJumboEngineSound(uint8 vol, int32 freq);
bool SetupJumboFlySound(uint8 emittingVol); /// ok bool SetupJumboFlySound(uint8 emittingVol);
bool SetupJumboRumbleSound(uint8 emittingVol); /// ok bool SetupJumboRumbleSound(uint8 emittingVol);
bool SetupJumboTaxiSound(uint8 vol); /// ok bool SetupJumboTaxiSound(uint8 vol);
bool SetupJumboWhineSound(uint8 emittingVol, int32 freq); /// ok bool SetupJumboWhineSound(uint8 emittingVol, int32 freq);
void SetupPedComments(cPedParams *params, uint32 sound); /// ok void SetupPedComments(cPedParams *params, uint32 sound);
void SetupSuspectLastSeenReport(); /// ok void SetupSuspectLastSeenReport();
void Terminate(); void Terminate();
void TranslateEntity(CVector *v1, CVector *v2) const; void TranslateEntity(CVector *v1, CVector *v2) const;
@ -604,11 +614,10 @@ public:
bool UsesSirenSwitching(int32 model) const; bool UsesSirenSwitching(int32 model) const;
// only used in pc // only used in pc
void AdjustSamplesVolume(); /// ok void AdjustSamplesVolume();
uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist);
float dist); /// ok
}; };
static_assert(sizeof(cAudioManager) == 19220, "cAudioManager: error"); static_assert(sizeof(cAudioManager) == 19220, "cAudioManager: error");
extern cAudioManager &AudioManager; extern cAudioManager AudioManager;

View File

@ -61,7 +61,7 @@ cAudioScriptObject::SaveAllAudioScriptObjects(uint8 *buf, uint32 *size)
INITSAVEBUF INITSAVEBUF
int32 pool_size = CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces(); int32 pool_size = CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces();
*size = SAVE_HEADER_SIZE + pool_size * (sizeof(cAudioScriptObject) + sizeof(int32)); *size = SAVE_HEADER_SIZE + sizeof(int32) + pool_size * (sizeof(cAudioScriptObject) + sizeof(int32));
WriteSaveHeader(buf, 'A', 'U', 'D', '\0', *size - SAVE_HEADER_SIZE); WriteSaveHeader(buf, 'A', 'U', 'D', '\0', *size - SAVE_HEADER_SIZE);
WriteSaveBuf(buf, pool_size); WriteSaveBuf(buf, pool_size);

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +1,46 @@
#pragma once #pragma once
#include "Wanted.h" #include "Wanted.h"
struct cAMCrime { struct cAMCrime {
int32 type; int32 type;
CVector position; CVector position;
uint16 timer; uint16 timer;
cAMCrime() cAMCrime()
{ {
type = CRIME_NONE; type = CRIME_NONE;
position = CVector(0.0f, 0.0f, 0.0f); position = CVector(0.0f, 0.0f, 0.0f);
timer = 0; timer = 0;
} }
}; };
static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error "); static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error ");
class cPoliceRadioQueue class cPoliceRadioQueue
{ {
public: public:
int32 crimesSamples[60]; int32 crimesSamples[60];
uint8 policeChannelTimer; uint8 policeChannelTimer;
uint8 policeChannelTimerSeconds; uint8 policeChannelTimerSeconds;
uint8 policeChannelCounterSeconds; uint8 policeChannelCounterSeconds;
cAMCrime crimes[10]; cAMCrime crimes[10];
cPoliceRadioQueue() cPoliceRadioQueue()
{ {
policeChannelTimerSeconds = 0; policeChannelTimerSeconds = 0;
policeChannelCounterSeconds = 0; policeChannelCounterSeconds = 0;
policeChannelTimer = 0; policeChannelTimer = 0;
} }
void Add(uint32 sample) void Add(uint32 sample)
{ {
if (policeChannelTimer != 60) { if (policeChannelTimer != 60) {
crimesSamples[policeChannelTimerSeconds] = sample; crimesSamples[policeChannelTimerSeconds] = sample;
policeChannelTimer++; policeChannelTimer++;
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60; policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
} }
} }
}; };
static_assert(sizeof(cPoliceRadioQueue) == 444, "cPoliceRadioQueue: error "); static_assert(sizeof(cPoliceRadioQueue) == 444, "cPoliceRadioQueue: error ");

View File

@ -12,17 +12,17 @@ void CAutoPilot::ModifySpeed(float speed)
float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve; float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo];
float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dirX; float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.x;
float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dirY; float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.y;
float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dirX; float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.x;
float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dirY; float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.y;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->pos.x + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->posY - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->pos.y - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,

View File

@ -90,7 +90,7 @@ uint32 (&aCarsToKeepTime)[MAX_CARS_TO_KEEP] = *(uint32(*)[MAX_CARS_TO_KEEP])*(ui
void void
CCarCtrl::GenerateRandomCars() CCarCtrl::GenerateRandomCars()
{ {
if (CCutsceneMgr::IsCutsceneProcessing()) if (CCutsceneMgr::IsRunning())
return; return;
if (NumRandomCars < 30){ if (NumRandomCars < 30){
if (CountDownToCarsAtStart == 0){ if (CountDownToCarsAtStart == 0){
@ -393,25 +393,25 @@ CCarCtrl::GenerateOneRandomCar()
pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f); pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f);
pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f); pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f);
float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dirX; float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.x;
float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dirY; float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.y;
float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirX; float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.x;
float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirY; float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.y;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo];
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->pos.x + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->posY - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->pos.y - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurrentLink->dirX * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurrentLink->dir.x * pCar->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurrentLink->dirY * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurrentLink->dir.y * pCar->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pCar->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pCar->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pCar->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pCar->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -763,17 +763,17 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
return; return;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
float currentPathLinkForwardX = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float currentPathLinkForwardX = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float currentPathLinkForwardY = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float currentPathLinkForwardY = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f); CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f); CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
@ -1553,8 +1553,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nNextDirection = -1; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
if (lanesOnNextNode >= 0){ if (lanesOnNextNode >= 0){
if ((CGeneral::GetRandomNumber() & 0x600) == 0){ if ((CGeneral::GetRandomNumber() & 0x600) == 0){
/* 25% chance vehicle will try to switch lane */ /* 25% chance vehicle will try to switch lane */
@ -1574,17 +1574,17 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH),
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -1725,10 +1725,10 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
pVehicle->AutoPilot.m_nNextDirection = -1; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY; float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y;
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY; float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y;
if (lanesOnNextNode >= 0) { if (lanesOnNextNode >= 0) {
CVector2D dist = pNextPathNode->pos - pCurNode->pos; CVector2D dist = pNextPathNode->pos - pCurNode->pos;
if (dist.MagnitudeSqr() >= SQR(7.0f)){ if (dist.MagnitudeSqr() >= SQR(7.0f)){
@ -1755,17 +1755,17 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -1814,10 +1814,10 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nNextDirection = -1; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY; float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y;
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY; float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y;
if (lanesOnNextNode >= 0) { if (lanesOnNextNode >= 0) {
CVector2D dist = pNextPathNode->pos - pCurNode->pos; CVector2D dist = pNextPathNode->pos - pCurNode->pos;
if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) { if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) {
@ -1835,17 +1835,17 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -2192,16 +2192,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
forward.Normalise(); forward.Normalise();
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
CVector2D currentPathLinkForward(pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection, CVector2D currentPathLinkForward(pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection,
pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection); pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection);
float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
CVector2D positionOnCurrentLinkIncludingLane( CVector2D positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
CVector2D positionOnNextLinkIncludingLane( CVector2D positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX); pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX);
CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane; CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane;
float scalarDistanceToNextNode = distanceToNextNode.Magnitude(); float scalarDistanceToNextNode = distanceToNextNode.Magnitude();
CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane; CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane;
@ -2230,16 +2230,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
} }
pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
scalarDistanceToNextNode = CVector2D( scalarDistanceToNextNode = CVector2D(
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude();
pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
currentPathLinkForward.x = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; currentPathLinkForward.x = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
currentPathLinkForward.y = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; currentPathLinkForward.y = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
} }
positionOnCurrentLinkIncludingLane.x = pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; positionOnCurrentLinkIncludingLane.x = pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y;
positionOnCurrentLinkIncludingLane.y = pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; positionOnCurrentLinkIncludingLane.y = pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x;
CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f; CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f;
if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){ if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){
projectedPosition.x = positionOnCurrentLinkIncludingLane.x; projectedPosition.x = positionOnCurrentLinkIncludingLane.x;
@ -2281,8 +2281,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
CCarAI::CarHasReasonToStop(pVehicle); CCarAI::CarHasReasonToStop(pVehicle);
speedStyleMultiplier = 0.0f; speedStyleMultiplier = 0.0f;
} }
CVector2D trajectory(pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, CVector2D trajectory(pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
trajectory -= pVehicle->GetPosition(); trajectory -= pVehicle->GetPosition();
float speedAngleMultiplier = FindSpeedMultiplier( float speedAngleMultiplier = FindSpeedMultiplier(
CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward, CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward,

View File

@ -1,14 +0,0 @@
#include "common.h"
#include "patcher.h"
#include "Cranes.h"
WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); }
WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); }
WRAPPER bool CCranes::IsThisCarPickedUp(float, float, CVehicle*) { EAXJMP(0x543940); }
WRAPPER bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() { EAXJMP(0x544BE0); }
WRAPPER void CCranes::ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float) { EAXJMP(0x543650); }
WRAPPER void CCranes::DeActivateCrane(float, float) { EAXJMP(0x543890); }
WRAPPER void CCranes::InitCranes(void) { EAXJMP(0x543360); }
WRAPPER void CCranes::UpdateCranes(void) { EAXJMP(0x5439E0); }
WRAPPER void CCranes::Save(uint8*, uint32*) { EAXJMP(0x545210); }
WRAPPER void CranesLoad(uint8*, uint32) { EAXJMP(0x5454d0); }

View File

@ -1,61 +0,0 @@
#pragma once
#include "common.h"
class CVehicle;
class CEntity;
class CObject;
class CCrane
{
public:
CEntity *m_pObject;
CObject *m_pMagnet;
int m_nAudioEntity;
float m_fPickupX1;
float m_fPickupX2;
float m_fPickupY1;
float m_fPickupY2;
CVector m_vecDropoffTarget;
float m_fDropoffHeading;
float m_fPickupAngle;
float m_fDropoffAngle;
float m_fPickupDistance;
float m_fDropoffDistance;
float m_fAngle;
float m_fDistance;
float m_fHeight;
float m_fHookOffset;
float m_fHookHeight;
CVector m_vecHookInitPos;
CVector m_vecHookCurPos;
float m_fHookVelocityX;
float m_fHookVelocityY;
CVehicle *m_pVehiclePickedUp;
int m_nUpdateTimer;
char m_bCraneActive;
char m_bCraneStatus;
char m_bVehiclesCollected;
char m_bIsCrusher;
char m_bIsMilitaryCrane;
char field_125;
char m_bNotMilitaryCrane;
char gap_127[1];
};
static_assert(sizeof(CCrane) == 128, "CCrane: error");
class CCranes
{
public:
static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*);
static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*);
static bool IsThisCarPickedUp(float, float, CVehicle*);
static bool HaveAllCarsBeenCollectedByMilitaryCrane();
static void ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float);
static void DeActivateCrane(float, float);
static void InitCranes(void);
static void UpdateCranes(void);
static void Save(uint8*, uint32*);
};
void CranesLoad(uint8*, uint32); // is this really outside CCranes?

View File

@ -1,294 +1,294 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "GameLogic.h" #include "GameLogic.h"
#include "Clock.h" #include "Clock.h"
#include "Stats.h" #include "Stats.h"
#include "Pickups.h" #include "Pickups.h"
#include "Timer.h" #include "Timer.h"
#include "Streaming.h" #include "Streaming.h"
#include "CutsceneMgr.h" #include "CutsceneMgr.h"
#include "World.h" #include "World.h"
#include "PlayerPed.h" #include "PlayerPed.h"
#include "Wanted.h" #include "Wanted.h"
#include "Camera.h" #include "Camera.h"
#include "Messages.h" #include "Messages.h"
#include "CarCtrl.h" #include "CarCtrl.h"
#include "Restart.h" #include "Restart.h"
#include "Pad.h" #include "Pad.h"
#include "References.h" #include "References.h"
#include "Fire.h" #include "Fire.h"
#include "Script.h" #include "Script.h"
#include "Garages.h" #include "Garages.h"
uint8 CGameLogic::ActivePlayers; // 0x95CD5E uint8 CGameLogic::ActivePlayers; // 0x95CD5E
void void
CGameLogic::InitAtStartOfGame() CGameLogic::InitAtStartOfGame()
{ {
ActivePlayers = 1; ActivePlayers = 1;
} }
void void
CGameLogic::PassTime(uint32 time) CGameLogic::PassTime(uint32 time)
{ {
int32 minutes, hours, days; int32 minutes, hours, days;
minutes = time + CClock::GetMinutes(); minutes = time + CClock::GetMinutes();
hours = CClock::GetHours(); hours = CClock::GetHours();
for (; minutes >= 60; minutes -= 60) for (; minutes >= 60; minutes -= 60)
hours++; hours++;
if (hours > 23) { if (hours > 23) {
days = CStats::DaysPassed; days = CStats::DaysPassed;
for (; hours >= 24; hours -= 24) for (; hours >= 24; hours -= 24)
days++; days++;
CStats::DaysPassed = days; CStats::DaysPassed = days;
} }
CClock::SetGameClock(hours, minutes); CClock::SetGameClock(hours, minutes);
CPickups::PassTime(time * 1000); CPickups::PassTime(time * 1000);
} }
void void
CGameLogic::SortOutStreamingAndMemory(const CVector &pos) CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
{ {
CTimer::Stop(); CTimer::Stop();
CStreaming::FlushRequestList(); CStreaming::FlushRequestList();
CStreaming::DeleteRwObjectsAfterDeath(pos); CStreaming::DeleteRwObjectsAfterDeath(pos);
CStreaming::RemoveUnusedModelsInLoadedList(); CStreaming::RemoveUnusedModelsInLoadedList();
CGame::DrasticTidyUpMemory(true); CGame::DrasticTidyUpMemory(true);
CStreaming::LoadScene(pos); CStreaming::LoadScene(pos);
CTimer::Update(); CTimer::Update();
} }
void void
CGameLogic::Update() CGameLogic::Update()
{ {
CVector vecRestartPos; CVector vecRestartPos;
float fRestartFloat; float fRestartFloat;
if (CCutsceneMgr::IsCutsceneProcessing()) return; if (CCutsceneMgr::IsCutsceneProcessing()) return;
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus]; CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
switch (pPlayerInfo.m_WBState) { switch (pPlayerInfo.m_WBState) {
case WBSTATE_PLAYING: case WBSTATE_PLAYING:
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) { if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
pPlayerInfo.m_pPed->ClearAdrenaline(); pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.KillPlayer(); pPlayerInfo.KillPlayer();
} }
if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) { if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
pPlayerInfo.m_pPed->ClearAdrenaline(); pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.ArrestPlayer(); pPlayerInfo.ArrestPlayer();
} }
break; break;
case WBSTATE_WASTED: case WBSTATE_WASTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(200, 200, 200); TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(2.0f, FADE_OUT); TheCamera.Fade(2.0f, FADE_OUT);
} }
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING; pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_bGetOutOfHospitalFree) { if (pPlayerInfo.m_bGetOutOfHospitalFree) {
pPlayerInfo.m_bGetOutOfHospitalFree = false; pPlayerInfo.m_bGetOutOfHospitalFree = false;
} else { } else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000); pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
pPlayerInfo.m_pPed->ClearWeapons(); pPlayerInfo.m_pPed->ClearWeapons();
} }
if (pPlayerInfo.m_pPed->bInVehicle) { if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) { if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil; pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED) if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED; pVehicle->m_status = STATUS_ABANDONED;
} else } else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed); pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
} }
} }
CEventList::Initialise(); CEventList::Initialise();
CMessages::ClearMessages(); CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList(); CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_NONE; CRestart::OverrideHospitalLevel = LEVEL_NONE;
CRestart::OverridePoliceStationLevel = LEVEL_NONE; CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720); PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos()); SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f; TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0); CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer(); CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2; CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextDeath) { if (CRestart::bFadeInAfterNextDeath) {
TheCamera.SetFadeColour(200, 200, 200); TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(4.0f, FADE_IN); TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextDeath = true; } else CRestart::bFadeInAfterNextDeath = true;
} }
break; break;
case WBSTATE_BUSTED: case WBSTATE_BUSTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(0, 0, 0); TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT); TheCamera.Fade(2.0f, FADE_OUT);
} }
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING; pPlayerInfo.m_WBState = WBSTATE_PLAYING;
int takeMoney; int takeMoney;
switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) { switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
case 0: case 0:
case 1: case 1:
takeMoney = 100; takeMoney = 100;
break; break;
case 2: case 2:
takeMoney = 200; takeMoney = 200;
break; break;
case 3: case 3:
takeMoney = 400; takeMoney = 400;
break; break;
case 4: case 4:
takeMoney = 600; takeMoney = 600;
break; break;
case 5: case 5:
takeMoney = 900; takeMoney = 900;
break; break;
case 6: case 6:
takeMoney = 1500; takeMoney = 1500;
break; break;
} }
if (pPlayerInfo.m_bGetOutOfJailFree) { if (pPlayerInfo.m_bGetOutOfJailFree) {
pPlayerInfo.m_bGetOutOfJailFree = false; pPlayerInfo.m_bGetOutOfJailFree = false;
} else { } else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney); pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
pPlayerInfo.m_pPed->ClearWeapons(); pPlayerInfo.m_pPed->ClearWeapons();
} }
if (pPlayerInfo.m_pPed->bInVehicle) { if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) { if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil; pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED) if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED; pVehicle->m_status = STATUS_ABANDONED;
} }
else else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed); pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
} }
} }
CEventList::Initialise(); CEventList::Initialise();
CMessages::ClearMessages(); CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList(); CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_NONE; CRestart::OverrideHospitalLevel = LEVEL_NONE;
CRestart::OverridePoliceStationLevel = LEVEL_NONE; CRestart::OverridePoliceStationLevel = LEVEL_NONE;
PassTime(720); PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
pPlayerInfo.m_pPed->ClearWeapons(); pPlayerInfo.m_pPed->ClearWeapons();
SortOutStreamingAndMemory(pPlayerInfo.GetPos()); SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f; TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0); CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer(); CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2; CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextArrest) { if (CRestart::bFadeInAfterNextArrest) {
TheCamera.SetFadeColour(0, 0, 0); TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN); TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextArrest = true; } else CRestart::bFadeInAfterNextArrest = true;
} }
break; break;
case WBSTATE_FAILED_CRITICAL_MISSION: case WBSTATE_FAILED_CRITICAL_MISSION:
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) { if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
TheCamera.SetFadeColour(0, 0, 0); TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT); TheCamera.Fade(2.0f, FADE_OUT);
} }
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING; pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_pPed->bInVehicle) { if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) { if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil; pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED) if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED; pVehicle->m_status = STATUS_ABANDONED;
} else } else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed); pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
} }
} }
CEventList::Initialise(); CEventList::Initialise();
CMessages::ClearMessages(); CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList(); CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverridePoliceStationLevel = LEVEL_NONE; CRestart::OverridePoliceStationLevel = LEVEL_NONE;
CRestart::OverrideHospitalLevel = LEVEL_NONE; CRestart::OverrideHospitalLevel = LEVEL_NONE;
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos()); SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f; TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0); CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer(); CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2; CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
TheCamera.SetFadeColour(0, 0, 0); TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN); TheCamera.Fade(4.0f, FADE_IN);
} }
break; break;
case 4: case 4:
return; return;
} }
} }
void void
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle) CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
{ {
pPlayerPed->m_fHealth = 100.0f; pPlayerPed->m_fHealth = 100.0f;
pPlayerPed->m_fArmour = 0.0f; pPlayerPed->m_fArmour = 0.0f;
pPlayerPed->bIsVisible = true; pPlayerPed->bIsVisible = true;
pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0; pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
pPlayerPed->bDoBloodyFootprints = false; pPlayerPed->bDoBloodyFootprints = false;
pPlayerPed->ClearAdrenaline(); pPlayerPed->ClearAdrenaline();
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina; pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
if (pPlayerPed->m_pFire) if (pPlayerPed->m_pFire)
pPlayerPed->m_pFire->Extinguish(); pPlayerPed->m_pFire->Extinguish();
pPlayerPed->bInVehicle = false; pPlayerPed->bInVehicle = false;
pPlayerPed->m_pMyVehicle = nil; pPlayerPed->m_pMyVehicle = nil;
pPlayerPed->m_pVehicleAnim = nil; pPlayerPed->m_pVehicleAnim = nil;
pPlayerPed->m_pWanted->Reset(); pPlayerPed->m_pWanted->Reset();
pPlayerPed->RestartNonPartialAnims(); pPlayerPed->RestartNonPartialAnims();
pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false); pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
pPlayerPed->bRemoveFromWorld = false; pPlayerPed->bRemoveFromWorld = false;
pPlayerPed->ClearWeaponTarget(); pPlayerPed->ClearWeaponTarget();
pPlayerPed->SetInitialState(); pPlayerPed->SetInitialState();
CCarCtrl::ClearInterestingVehicleList(); CCarCtrl::ClearInterestingVehicleList();
pos.z += 1.0f; pos.z += 1.0f;
pPlayerPed->Teleport(pos); pPlayerPed->Teleport(pos);
pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f)); pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
pPlayerPed->m_fRotationCur = DEGTORAD(angle); pPlayerPed->m_fRotationCur = DEGTORAD(angle);
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur; pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur); pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed); CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1); CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
pPlayerPed->RestoreHeadingRate(); pPlayerPed->RestoreHeadingRate();
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString(); TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
CReferences::RemoveReferencesToPlayer(); CReferences::RemoveReferencesToPlayer();
CGarages::PlayerArrestedOrDied(); CGarages::PlayerArrestedOrDied();
CStats::CheckPointReachedUnsuccessfully(); CStats::CheckPointReachedUnsuccessfully();
CWorld::Remove(pPlayerPed); CWorld::Remove(pPlayerPed);
CWorld::Add(pPlayerPed); CWorld::Add(pPlayerPed);
} }
STARTPATCHES STARTPATCHES
InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP); InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP);
InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP); InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP);
InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP); InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP);
InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP); InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP);
InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP); InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -1,13 +1,13 @@
#pragma once #pragma once
class CGameLogic class CGameLogic
{ {
public: public:
static void InitAtStartOfGame(); static void InitAtStartOfGame();
static void PassTime(uint32 time); static void PassTime(uint32 time);
static void SortOutStreamingAndMemory(const CVector &pos); static void SortOutStreamingAndMemory(const CVector &pos);
static void Update(); static void Update();
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle); static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
static uint8 ActivePlayers; static uint8 ActivePlayers;
}; };

View File

@ -126,7 +126,6 @@ uint32& CGarages::MessageEndTime = *(uint32*)0x8F597C;
uint32& CGarages::NumGarages = *(uint32*)0x8F29F4; uint32& CGarages::NumGarages = *(uint32*)0x8F29F4;
bool& CGarages::PlayerInGarage = *(bool*)0x95CD83; bool& CGarages::PlayerInGarage = *(bool*)0x95CD83;
int32& CGarages::PoliceCarsCollected = *(int32*)0x941444; int32& CGarages::PoliceCarsCollected = *(int32*)0x941444;
uint32& CGarages::GarageToBeTidied = *(uint32*)0x623570;
CStoredCar(&CGarages::aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA210; CStoredCar(&CGarages::aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA210;
CStoredCar(&CGarages::aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA300; CStoredCar(&CGarages::aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA300;
CStoredCar(&CGarages::aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA3F0; CStoredCar(&CGarages::aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA3F0;
@ -322,6 +321,9 @@ void CGarage::Update()
} }
} }
} }
break;
default:
break;
} }
} }
if (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED) if (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED)
@ -408,11 +410,11 @@ void CGarage::Update()
if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) { if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
uint8 colour1, colour2; uint8 colour1, colour2;
uint16 attempt; uint16 attempt;
((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2); FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
for (attempt = 0; attempt < 10; attempt++) { for (attempt = 0; attempt < 10; attempt++) {
if (colour1 != FindPlayerVehicle()->m_currentColour1 || colour2 != FindPlayerVehicle()->m_currentColour2) if (colour1 != FindPlayerVehicle()->m_currentColour1 || colour2 != FindPlayerVehicle()->m_currentColour2)
break; break;
((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2); FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
} }
bChangedColour = (attempt < 10); bChangedColour = (attempt < 10);
FindPlayerVehicle()->m_currentColour1 = colour1; FindPlayerVehicle()->m_currentColour1 = colour1;
@ -490,7 +492,7 @@ void CGarage::Update()
break; break;
} }
if (!CGarages::BombsAreFree && CWorld::Players[CWorld::PlayerInFocus].m_nMoney < BOMB_PRICE) { if (!CGarages::BombsAreFree && CWorld::Players[CWorld::PlayerInFocus].m_nMoney < BOMB_PRICE) {
CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each" CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each" - weird that the price is hardcoded in message
m_eGarageState = GS_OPENEDCONTAINSCAR; m_eGarageState = GS_OPENEDCONTAINSCAR;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1); DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1);
break; break;
@ -524,7 +526,7 @@ void CGarage::Update()
((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed(); ((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
if (m_eGarageType == GARAGE_BOMBSHOP3) if (m_eGarageType == GARAGE_BOMBSHOP3)
CGarages::GivePlayerDetonator(); CGarages::GivePlayerDetonator();
CStats::KgOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB; CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
} }
switch (m_eGarageType) { switch (m_eGarageType) {
case GARAGE_BOMBSHOP1: case GARAGE_BOMBSHOP1:
@ -1184,7 +1186,7 @@ bool CGarage::IsEntityEntirelyInside(CEntity * pEntity)
if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 || if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 ||
pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2) pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2)
return false; return false;
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -1201,7 +1203,7 @@ bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin || pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin ||
pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin) pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin)
return false; return false;
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -1218,7 +1220,7 @@ bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin && if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin &&
pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin) pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin)
return false; return false;
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -1250,7 +1252,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 || pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 ||
pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2) pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2)
return false; return false;
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
radius = pColModel->spheres[i].radius; radius = pColModel->spheres[i].radius;
@ -1264,7 +1266,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin) bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
{ {
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -1285,7 +1287,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
continue; continue;
if (!IsEntityTouching3D(pVehicle)) if (!IsEntityTouching3D(pVehicle))
continue; continue;
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel(); CColModel* pColModel = pVehicle->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center; CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -1307,7 +1309,7 @@ bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)
continue; continue;
if (!IsEntityTouching3D(pPed)) if (!IsEntityTouching3D(pPed))
continue; continue;
CColModel* pColModel = CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetColModel(); CColModel* pColModel = pException->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center; CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -1329,7 +1331,7 @@ bool CGarage::IsAnyCarBlockingDoor()
continue; continue;
if (!IsEntityTouching3D(pVehicle)) if (!IsEntityTouching3D(pVehicle))
continue; continue;
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel(); CColModel* pColModel = pVehicle->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center; CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -1677,7 +1679,7 @@ float CGarage::CalcDistToGarageRectangleSquared(float X, float Y)
else else
distX = 0.0f; distX = 0.0f;
if (Y < m_fY1) if (Y < m_fY1)
distY = m_fY1 - X; distY = m_fY1 - Y;
else if (Y > m_fY2) else if (Y > m_fY2)
distY = Y - m_fY2; distY = Y - m_fY2;
else else
@ -1698,8 +1700,8 @@ float CGarage::CalcSmallestDistToGarageDoorSquared(float X, float Y)
void CGarage::FindDoorsEntities() void CGarage::FindDoorsEntities()
{ {
m_pDoor1 = false; m_pDoor1 = nil;
m_pDoor2 = false; m_pDoor2 = nil;
int xstart = max(0, CWorld::GetSectorIndexX(m_fX1)); int xstart = max(0, CWorld::GetSectorIndexX(m_fX1));
int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2)); int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2));
int ystart = max(0, CWorld::GetSectorIndexY(m_fY1)); int ystart = max(0, CWorld::GetSectorIndexY(m_fY1));
@ -1992,7 +1994,7 @@ void CGarage::TidyUpGarageClose()
continue; continue;
bool bRemove = false; bool bRemove = false;
if (m_eGarageState != GS_FULLYCLOSED) { if (m_eGarageState != GS_FULLYCLOSED) {
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel(); CColModel* pColModel = pVehicle->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center; CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius; float radius = pColModel->spheres[i].radius;
@ -2106,7 +2108,7 @@ void CGarages::CloseHideOutGaragesBeforeSave()
aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE) aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE)
continue; continue;
if (aGarages[i].m_eGarageState != GS_FULLYCLOSED && if (aGarages[i].m_eGarageState != GS_FULLYCLOSED &&
aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor()) { (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) {
aGarages[i].m_eGarageState = GS_FULLYCLOSED; aGarages[i].m_eGarageState = GS_FULLYCLOSED;
switch (aGarages[i].m_eGarageType) { switch (aGarages[i].m_eGarageType) {
case GARAGE_HIDEOUT_ONE: case GARAGE_HIDEOUT_ONE:
@ -2227,6 +2229,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
void CGarages::Save(uint8 * buf, uint32 * size) void CGarages::Save(uint8 * buf, uint32 * size)
{ {
#ifdef FIX_GARAGE_SIZE #ifdef FIX_GARAGE_SIZE
INITSAVEBUF
*size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); *size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
#else #else
* size = 5484; * size = 5484;
@ -2248,6 +2251,9 @@ void CGarages::Save(uint8 * buf, uint32 * size)
} }
for (int i = 0; i < NUM_GARAGES; i++) for (int i = 0; i < NUM_GARAGES; i++)
WriteSaveBuf(buf, aGarages[i]); WriteSaveBuf(buf, aGarages[i]);
#ifdef FIX_GARAGE_SIZE
VALIDATESAVEBUF(*size);
#endif
} }
CStoredCar::CStoredCar(const CStoredCar & other) CStoredCar::CStoredCar(const CStoredCar & other)
@ -2271,6 +2277,7 @@ CStoredCar::CStoredCar(const CStoredCar & other)
void CGarages::Load(uint8* buf, uint32 size) void CGarages::Load(uint8* buf, uint32 size)
{ {
#ifdef FIX_GARAGE_SIZE #ifdef FIX_GARAGE_SIZE
INITSAVEBUF
assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
#else #else
assert(size == 5484); assert(size == 5484);
@ -2303,6 +2310,9 @@ void CGarages::Load(uint8* buf, uint32 size)
else else
aGarages[i].UpdateDoorsHeight(); aGarages[i].UpdateDoorsHeight();
} }
#ifdef FIX_GARAGE_SIZE
VALIDATESAVEBUF(size);
#endif
} }
bool bool
@ -2345,8 +2355,7 @@ CGarages::IsModelIndexADoor(uint32 id)
STARTPATCHES STARTPATCHES
InjectHook(0x426B20, CGarages::TriggerMessage, PATCH_JUMP); // CCrane::Update, CCrane::FindCarInSectorList
InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl
InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl
InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad
ENDPATCHES ENDPATCHES

View File

@ -194,7 +194,6 @@ class CGarages
static uint32 &NumGarages; static uint32 &NumGarages;
static bool &PlayerInGarage; static bool &PlayerInGarage;
static int32 &PoliceCarsCollected; static int32 &PoliceCarsCollected;
static uint32 &GarageToBeTidied;
static CGarage(&aGarages)[NUM_GARAGES]; static CGarage(&aGarages)[NUM_GARAGES];
static CStoredCar(&aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS]; static CStoredCar(&aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS];
static CStoredCar(&aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS]; static CStoredCar(&aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS];

View File

@ -1,49 +1,49 @@
#pragma once #pragma once
enum enum
{ {
COUNTER_DISPLAY_NUMBER, COUNTER_DISPLAY_NUMBER,
COUNTER_DISPLAY_BAR, COUNTER_DISPLAY_BAR,
}; };
class COnscreenTimerEntry class COnscreenTimerEntry
{ {
public: public:
uint32 m_nTimerOffset; uint32 m_nTimerOffset;
uint32 m_nCounterOffset; uint32 m_nCounterOffset;
char m_aTimerText[10]; char m_aTimerText[10];
char m_aCounterText[10]; char m_aCounterText[10];
uint16 m_nType; uint16 m_nType;
char m_bCounterBuffer[42]; char m_bCounterBuffer[42];
char m_bTimerBuffer[42]; char m_bTimerBuffer[42];
bool m_bTimerProcessed; bool m_bTimerProcessed;
bool m_bCounterProcessed; bool m_bCounterProcessed;
void Process(); void Process();
bool ProcessForDisplay(); bool ProcessForDisplay();
void ProcessForDisplayClock(); void ProcessForDisplayClock();
void ProcessForDisplayCounter(); void ProcessForDisplayCounter();
}; };
static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error"); static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
class COnscreenTimer class COnscreenTimer
{ {
public: public:
COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES]; COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
bool m_bProcessed; bool m_bProcessed;
bool m_bDisabled; bool m_bDisabled;
void Init(); void Init();
void Process(); void Process();
void ProcessForDisplay(); void ProcessForDisplay();
void ClearCounter(uint32 offset); void ClearCounter(uint32 offset);
void ClearClock(uint32 offset); void ClearClock(uint32 offset);
void AddCounter(uint32 offset, uint16 type, char* text); void AddCounter(uint32 offset, uint16 type, char* text);
void AddClock(uint32 offset, char* text); void AddClock(uint32 offset, char* text);
}; };
static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error"); static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error");

View File

@ -5,8 +5,13 @@
#include "Camera.h" #include "Camera.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "World.h" #include "World.h"
#include "Lines.h" // for debug
#include "PathFind.h" #include "PathFind.h"
bool gbShowPedPaths;
bool gbShowCarPaths;
bool gbShowCarPathsLinks;
CPathFind &ThePaths = *(CPathFind*)0x8F6754; CPathFind &ThePaths = *(CPathFind*)0x8F6754;
WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); } WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); }
@ -466,20 +471,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// IMPROVE: use a goto here // IMPROVE: use a goto here
// Find existing car path link // Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){ for(k = 0; k < m_numCarPathLinks; k++){
if(m_carPathLinks[k].dirX == tempnodes[j].dirX && if(m_carPathLinks[k].dir.x == tempnodes[j].dirX &&
m_carPathLinks[k].dirY == tempnodes[j].dirY && m_carPathLinks[k].dir.y == tempnodes[j].dirY &&
m_carPathLinks[k].posX == tempnodes[j].pos.x && m_carPathLinks[k].pos.x == tempnodes[j].pos.x &&
m_carPathLinks[k].posY == tempnodes[j].pos.y){ m_carPathLinks[k].pos.y == tempnodes[j].pos.y){
m_carPathConnections[m_numConnections] = k; m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks; k = m_numCarPathLinks;
} }
} }
// k is m_numCarPathLinks+1 if we found one // k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){ if(k == m_numCarPathLinks){
m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX; m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX;
m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY; m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY;
m_carPathLinks[m_numCarPathLinks].posX = tempnodes[j].pos.x; m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x;
m_carPathLinks[m_numCarPathLinks].posY = tempnodes[j].pos.y; m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes; m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes;
m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes; m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes;
@ -529,20 +534,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// IMPROVE: use a goto here // IMPROVE: use a goto here
// Find existing car path link // Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){ for(k = 0; k < m_numCarPathLinks; k++){
if(m_carPathLinks[k].dirX == dx && if(m_carPathLinks[k].dir.x == dx &&
m_carPathLinks[k].dirY == dy && m_carPathLinks[k].dir.y == dy &&
m_carPathLinks[k].posX == posx && m_carPathLinks[k].pos.x == posx &&
m_carPathLinks[k].posY == posy){ m_carPathLinks[k].pos.y == posy){
m_carPathConnections[m_numConnections] = k; m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks; k = m_numCarPathLinks;
} }
} }
// k is m_numCarPathLinks+1 if we found one // k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){ if(k == m_numCarPathLinks){
m_carPathLinks[m_numCarPathLinks].dirX = dx; m_carPathLinks[m_numCarPathLinks].dir.x = dx;
m_carPathLinks[m_numCarPathLinks].dirY = dy; m_carPathLinks[m_numCarPathLinks].dir.y = dy;
m_carPathLinks[m_numCarPathLinks].posX = posx; m_carPathLinks[m_numCarPathLinks].pos.x = posx;
m_carPathLinks[m_numCarPathLinks].posY = posy; m_carPathLinks[m_numCarPathLinks].pos.y = posy;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1; m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1;
m_carPathLinks[m_numCarPathLinks].numRightLanes = -1; m_carPathLinks[m_numCarPathLinks].numRightLanes = -1;
@ -760,8 +765,8 @@ CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool ena
{ {
int i; int i;
for(i = 0; i < m_numCarPathLinks; i++) for(i = 0; i < m_numCarPathLinks; i++)
if(x1 < m_carPathLinks[i].posX && m_carPathLinks[i].posX < x2 && if(x1 < m_carPathLinks[i].pos.x && m_carPathLinks[i].pos.x < x2 &&
y1 < m_carPathLinks[i].posY && m_carPathLinks[i].posY < y2) y1 < m_carPathLinks[i].pos.y && m_carPathLinks[i].pos.y < y2)
m_carPathLinks[i].bBridgeLights = enable; m_carPathLinks[i].bBridgeLights = enable;
} }
@ -1444,6 +1449,132 @@ CPathFind::Load(uint8 *buf, uint32 size)
m_pathNodes[i].bBetweenLevels = false; m_pathNodes[i].bBetweenLevels = false;
} }
void
CPathFind::DisplayPathData(void)
{
// Not the function from mobm_carPathLinksile but my own!
int i, j, k;
// Draw 50 units around camera
CVector pos = TheCamera.GetPosition();
const float maxDist = 50.0f;
// Render car path nodes
if(gbShowCarPaths)
for(i = 0; i < m_numCarPathNodes; i++){
if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist))
continue;
CVector n1 = m_pathNodes[i].pos;
n1.z += 0.3f;
// Draw node itself
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n1.x, n1.y, n1.z + 1.0f,
0xFFFFFFFF, 0xFFFFFFFF);
for(j = 0; j < m_pathNodes[i].numLinks; j++){
k = m_connections[m_pathNodes[i].firstLink + j];
CVector n2 = m_pathNodes[k].pos;
n2.z += 0.3f;
// Draw links to neighbours
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n2.x, n2.y, n2.z,
0xFFFFFFFF, 0xFFFFFFFF);
}
}
// Render car path nodes
if(gbShowCarPathsLinks)
for(i = 0; i < m_numCarPathLinks; i++){
CVector2D n1_2d = m_carPathLinks[i].pos;
if((n1_2d - pos).MagnitudeSqr() > SQR(maxDist))
continue;
int ni = m_carPathLinks[i].pathNodeIndex;
CVector pn1 = m_pathNodes[ni].pos;
pn1.z += 0.3f;
CVector n1(n1_2d.x, n1_2d.y, pn1.z);
n1.z += 0.3f;
// Draw car node itself
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n1.x, n1.y, n1.z + 1.0f,
0xFFFFFFFF, 0xFFFFFFFF);
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z + 0.5f,
n1.x+m_carPathLinks[i].dir.x, n1.y+m_carPathLinks[i].dir.y, n1.z + 0.5f,
0xFFFFFFFF, 0xFFFFFFFF);
// Draw connection to car path node
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
pn1.x, pn1.y, pn1.z,
0xFF0000FF, 0xFFFFFFFF);
// traffic light type
uint32 col = 0xFF;
if((m_carPathLinks[i].trafficLightType&0x7F) == 1)
col += 0xFF000000;
if((m_carPathLinks[i].trafficLightType&0x7F) == 2)
col += 0x00FF0000;
if(m_carPathLinks[i].trafficLightType & 0x80)
col += 0x0000FF00;
CLines::RenderLineWithClipping(n1.x+0.2f, n1.y, n1.z,
n1.x+0.2f, n1.y, n1.z + 1.0f,
col, col);
for(j = 0; j < m_pathNodes[ni].numLinks; j++){
k = m_carPathConnections[m_pathNodes[ni].firstLink + j];
CVector2D n2_2d = m_carPathLinks[k].pos;
int nk = m_carPathLinks[k].pathNodeIndex;
CVector pn2 = m_pathNodes[nk].pos;
pn2.z += 0.3f;
CVector n2(n2_2d.x, n2_2d.y, pn2.z);
n2.z += 0.3f;
// Draw links to neighbours
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n2.x, n2.y, n2.z,
0xFF00FFFF, 0xFF00FFFF);
}
}
// Render ped path nodes
if(gbShowPedPaths)
for(i = m_numCarPathNodes; i < m_numPathNodes; i++){
if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist))
continue;
CVector n1 = m_pathNodes[i].pos;
n1.z += 0.3f;
// Draw node itself
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n1.x, n1.y, n1.z + 1.0f,
0xFFFFFFFF, 0xFFFFFFFF);
for(j = 0; j < m_pathNodes[i].numLinks; j++){
k = m_connections[m_pathNodes[i].firstLink + j];
CVector n2 = m_pathNodes[k].pos;
n2.z += 0.3f;
// Draw links to neighbours
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n2.x, n2.y, n2.z,
0xFFFFFFFF, 0xFFFFFFFF);
// Draw connection flags
CVector mid = (n1+n2)/2.0f;
uint32 col = 0xFF;
if(m_connectionFlags[m_pathNodes[i].firstLink + j].bCrossesRoad)
col += 0x00FF0000;
if(m_connectionFlags[m_pathNodes[i].firstLink + j].bTrafficLight)
col += 0xFF000000;
CLines::RenderLineWithClipping(mid.x, mid.y, mid.z,
mid.x, mid.y, mid.z + 1.0f,
col, col);
}
}
}
STARTPATCHES STARTPATCHES
InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP); InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP);
InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP); InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP);

View File

@ -84,10 +84,8 @@ union CConnectionFlags
struct CCarPathLink struct CCarPathLink
{ {
float posX; CVector2D pos;
float posY; CVector2D dir;
float dirX;
float dirY;
int16 pathNodeIndex; int16 pathNodeIndex;
int8 numLeftLanes; int8 numLeftLanes;
int8 numRightLanes; int8 numRightLanes;
@ -208,7 +206,13 @@ public:
bool TestCoorsCloseness(CVector target, uint8 type, CVector start); bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
void Save(uint8 *buf, uint32 *size); void Save(uint8 *buf, uint32 *size);
void Load(uint8 *buf, uint32 size); void Load(uint8 *buf, uint32 size);
void DisplayPathData(void);
}; };
static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error"); static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error");
extern CPathFind &ThePaths; extern CPathFind &ThePaths;
extern bool gbShowPedPaths;
extern bool gbShowCarPaths;
extern bool gbShowCarPathsLinks;

File diff suppressed because it is too large Load Diff

View File

@ -1,124 +1,147 @@
#pragma once #pragma once
#include "Weapon.h" #include "Weapon.h"
enum ePickupType : uint8 enum ePickupType : uint8
{ {
PICKUP_NONE = 0, PICKUP_NONE = 0,
PICKUP_IN_SHOP, PICKUP_IN_SHOP,
PICKUP_ON_STREET, PICKUP_ON_STREET,
PICKUP_ONCE, PICKUP_ONCE,
PICKUP_ONCE_TIMEOUT, PICKUP_ONCE_TIMEOUT,
PICKUP_COLLECTABLE1, PICKUP_COLLECTABLE1,
PICKUP_IN_SHOP_OUT_OF_STOCK, PICKUP_IN_SHOP_OUT_OF_STOCK,
PICKUP_MONEY, PICKUP_MONEY,
PICKUP_MINE_INACTIVE, PICKUP_MINE_INACTIVE,
PICKUP_MINE_ARMED, PICKUP_MINE_ARMED,
PICKUP_NAUTICAL_MINE_INACTIVE, PICKUP_NAUTICAL_MINE_INACTIVE,
PICKUP_NAUTICAL_MINE_ARMED, PICKUP_NAUTICAL_MINE_ARMED,
PICKUP_FLOATINGPACKAGE, PICKUP_FLOATINGPACKAGE,
PICKUP_FLOATINGPACKAGE_FLOATING, PICKUP_FLOATINGPACKAGE_FLOATING,
PICKUP_ON_STREET_SLOW, PICKUP_ON_STREET_SLOW,
PICKUP_NUMOFTYPES PICKUP_NUMOFTYPES
}; };
class CEntity; class CEntity;
class CObject; class CObject;
class CVehicle; class CVehicle;
class CPlayerPed; class CPlayerPed;
class CPickup class CPickup
{ {
public: public:
ePickupType m_eType; ePickupType m_eType;
bool m_bRemoved; bool m_bRemoved;
uint16 m_nQuantity; uint16 m_nQuantity;
CObject *m_pObject; CObject *m_pObject;
uint32 m_nTimer; uint32 m_nTimer;
int16 m_eModelIndex; int16 m_eModelIndex;
uint16 m_nIndex; uint16 m_nIndex;
CVector m_vecPos; CVector m_vecPos;
CObject *GiveUsAPickUpObject(int32 handle); CObject *GiveUsAPickUpObject(int32 handle);
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId); bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
private: private:
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; } bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
inline bool CanBePickedUp(CPlayerPed *player); inline bool CanBePickedUp(CPlayerPed *player);
void RemoveKeepType(); void RemoveKeepType();
void Remove(); void Remove();
}; };
static_assert(sizeof(CPickup) == 0x1C, "CPickup: error"); static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
struct tPickupMessage struct tPickupMessage
{ {
CVector2D m_pos; CVector2D m_pos;
eWeaponType m_weaponType; eWeaponType m_weaponType;
CVector2D m_dist; CVector2D m_dist;
CRGBA m_color; CRGBA m_color;
uint8 m_bOutOfStock : 1; uint8 m_bOutOfStock : 1;
uint8 m_quantity; uint8 m_quantity;
}; };
class CPickups class CPickups
{ {
static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS]; static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
static int16 CollectedPickUpIndex; static int16 CollectedPickUpIndex;
static int16 NumMessages; static int16 NumMessages;
static tPickupMessage aMessages[NUMPICKUPMESSAGES]; static tPickupMessage aMessages[NUMPICKUPMESSAGES];
public: public:
static void Init(); static void Init();
static void Update(); static void Update();
static void RenderPickUpText(); static void RenderPickUpText();
static void DoCollectableEffects(CEntity *ent); static void DoCollectableEffects(CEntity *ent);
static void DoMoneyEffects(CEntity *ent); static void DoMoneyEffects(CEntity *ent);
static void DoMineEffects(CEntity *ent); static void DoMineEffects(CEntity *ent);
static void DoPickUpEffects(CEntity *ent); static void DoPickUpEffects(CEntity *ent);
static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity); static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity); static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
static void RemovePickUp(int32 pickupIndex); static void RemovePickUp(int32 pickupIndex);
static void RemoveAllFloatingPickups(); static void RemoveAllFloatingPickups();
static void AddToCollectedPickupsArray(int32 index); static void AddToCollectedPickupsArray(int32 index);
static bool IsPickUpPickedUp(int32 pickupId); static bool IsPickUpPickedUp(int32 pickupId);
static int32 ModelForWeapon(eWeaponType weaponType); static int32 ModelForWeapon(eWeaponType weaponType);
static enum eWeaponType WeaponForModel(int32 model); static enum eWeaponType WeaponForModel(int32 model);
static int32 FindColourIndexForWeaponMI(int32 model); static int32 FindColourIndexForWeaponMI(int32 model);
static int32 GetActualPickupIndex(int32 index); static int32 GetActualPickupIndex(int32 index);
static int32 GetNewUniquePickupIndex(int32 slot); static int32 GetNewUniquePickupIndex(int32 slot);
static void PassTime(uint32 time); static void PassTime(uint32 time);
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex); static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
static void Load(uint8 *buf, uint32 size); static void Load(uint8 *buf, uint32 size);
static void Save(uint8 *buf, uint32 *size); static void Save(uint8 *buf, uint32 *size);
static CPickup(&aPickUps)[NUMPICKUPS]; static CPickup(&aPickUps)[NUMPICKUPS];
// unused // unused
static bool &bPickUpcamActivated; static bool &bPickUpcamActivated;
static CVehicle *&pPlayerVehicle; static CVehicle *&pPlayerVehicle;
static CVector &StaticCamCoors; static CVector &StaticCamCoors;
static uint32 &StaticCamStartTime; static uint32 &StaticCamStartTime;
}; };
extern uint16 AmmoForWeapon[20]; extern uint16 AmmoForWeapon[20];
extern uint16 AmmoForWeapon_OnStreet[20]; extern uint16 AmmoForWeapon_OnStreet[20];
extern uint16 CostOfWeapon[20]; extern uint16 CostOfWeapon[20];
class CPacManPickups enum ePacmanPickupType
{ {
public: PACMAN_NONE,
static void Init(void); PACMAN_SCRAMBLE,
static void Update(void); PACMAN_RACE,
static void GeneratePMPickUps(CVector, float, int16, uint8); };
static void GeneratePMPickUpsForRace(int32);
static void GenerateOnePMPickUp(CVector); class CPacManPickup
static void Render(void); {
static void DoCleanUpPacManStuff(void); public:
static void StartPacManRace(int32); CVector m_vecPosn;
static void StartPacManRecord(void); CObject *m_pObject;
static uint32 QueryPowerPillsEatenInRace(void); uint8 m_eType;
static void ResetPowerPillsEatenInRace(void);
static void CleanUpPacManStuff(void); void Update();
static void StartPacManScramble(CVector, float, int16); };
static uint32 QueryPowerPillsCarriedByPlayer(void);
static void ResetPowerPillsCarriedByPlayer(void); class CPacManPickups
{
}; friend CPacManPickup;
static CPacManPickup aPMPickUps[NUMPACMANPICKUPS];
static CVector LastPickUpCoors;
static int PillsEatenInRace;
static bool bPMActive;
public:
static void Init(void);
static void Update(void);
static void GeneratePMPickUps(CVector, float, int16, uint8);
static void GeneratePMPickUpsForRace(int32);
static void GenerateOnePMPickUp(CVector);
static void Render(void);
static void StartPacManRace(int32);
static void StartPacManRecord(void);
static uint32 QueryPowerPillsEatenInRace(void);
static void ResetPowerPillsEatenInRace(void);
static void ClearPMPickUps(void);
static void CleanUpPacManStuff(void);
static void StartPacManScramble(CVector, float, int16);
static uint32 QueryPowerPillsCarriedByPlayer(void);
static void ResetPowerPillsCarriedByPlayer(void);
};

View File

@ -1,22 +1,22 @@
#include "common.h" #include "common.h"
#include "PowerPoints.h" #include "PowerPoints.h"
// Some cut beta feature // Some cut beta feature
void CPowerPoint::Update() void CPowerPoint::Update()
{} {}
void CPowerPoints::Init() void CPowerPoints::Init()
{} {}
void CPowerPoints::Update() void CPowerPoints::Update()
{} {}
void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8) void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
{} {}
void CPowerPoints::Save(uint8**, uint32*) void CPowerPoints::Save(uint8**, uint32*)
{} {}
void CPowerPoints::Load(uint8*, uint32) void CPowerPoints::Load(uint8*, uint32)
{} {}

View File

@ -1,26 +1,26 @@
#pragma once #pragma once
enum enum
{ {
POWERPOINT_NONE = 0, POWERPOINT_NONE = 0,
POWERPOINT_HEALTH, POWERPOINT_HEALTH,
POWERPOINT_HIDEOUT_INDUSTRIAL, POWERPOINT_HIDEOUT_INDUSTRIAL,
POWERPOINT_HIDEOUT_COMMERCIAL, POWERPOINT_HIDEOUT_COMMERCIAL,
POWERPOINT_HIDEOUT_SUBURBAN POWERPOINT_HIDEOUT_SUBURBAN
}; };
class CPowerPoint class CPowerPoint
{ {
public: public:
void Update(); void Update();
}; };
class CPowerPoints class CPowerPoints
{ {
public: public:
static void Init(); static void Init();
static void Update(); static void Update();
static void GenerateNewOne(float, float, float, float, float, float, uint8); static void GenerateNewOne(float, float, float, float, float, float, uint8);
static void Save(uint8**, uint32*); static void Save(uint8**, uint32*);
static void Load(uint8*, uint32); static void Load(uint8*, uint32);
}; };

View File

@ -2,18 +2,522 @@
#include "patcher.h" #include "patcher.h"
#include "Record.h" #include "Record.h"
#include "FileMgr.h"
#include "Pad.h"
#include "Pools.h"
#include "Streaming.h"
#include "Timer.h"
#include "VehicleModelInfo.h"
#include "World.h"
uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24; uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24;
uint8*& CRecordDataForGame::pDataBuffer = *(uint8**)0x8F1B70;
uint8*& CRecordDataForGame::pDataBufferPointer = *(uint8**)0x8F1AB0;
int& CRecordDataForGame::FId = *(int*)0x885BA4;
tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0;
uint8 &CRecordDataForChase::Status = *(uint8*)0x95CDCE; #define MEMORY_FOR_GAME_RECORD (150000)
WRAPPER void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4341F0); } void CRecordDataForGame::Init(void)
WRAPPER void CRecordDataForGame::Init(void) { EAXJMP(0x4340F0); } {
RecordingState = STATE_NONE;
delete[] pDataBuffer;
pDataBufferPointer = nil;
pDataBuffer = nil;
#ifndef GTA_PS2 // this stuff is not present on PS2
FId = CFileMgr::OpenFile("playback.dat", "r");
if (FId <= 0) {
if ((FId = CFileMgr::OpenFile("record.dat", "r")) <= 0)
RecordingState = STATE_NONE;
else {
CFileMgr::CloseFile(FId);
FId = CFileMgr::OpenFileForWriting("record.dat");
RecordingState = STATE_RECORD;
}
}
else {
RecordingState = STATE_PLAYBACK;
}
if (RecordingState == STATE_PLAYBACK) {
pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
pDataBuffer = pDataBufferPointer;
pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
CFileMgr::CloseFile(FId);
}
#else
RecordingState = STATE_NONE; // second time to make sure
#endif
}
void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
{
switch (RecordingState) {
case STATE_RECORD:
{
pDataBufferForFrame.m_fTimeStep = CTimer::GetTimeStep();
pDataBufferForFrame.m_nTimeInMilliseconds = CTimer::GetTimeInMilliseconds();
pDataBufferForFrame.m_nSizeOfPads[0] = 0;
pDataBufferForFrame.m_nSizeOfPads[1] = 0;
pDataBufferForFrame.m_nChecksum = CalcGameChecksum();
uint8* pController1 = PackCurrentPadValues(pDataBufferForFrame.m_ControllerBuffer, &CPad::GetPad(0)->OldState, &CPad::GetPad(0)->NewState);
pDataBufferForFrame.m_nSizeOfPads[0] = (pController1 - pDataBufferForFrame.m_ControllerBuffer) / 2;
uint8* pController2 = PackCurrentPadValues(pController1, &CPad::GetPad(1)->OldState, &CPad::GetPad(1)->NewState);
pDataBufferForFrame.m_nSizeOfPads[1] = (pController2 - pController1) / 2;
uint8* pEndPtr = pController2;
if ((pDataBufferForFrame.m_nSizeOfPads[0] + pDataBufferForFrame.m_nSizeOfPads[1]) & 1)
pEndPtr += 2;
CFileMgr::Write(FId, (char*)&pDataBufferForFrame, pEndPtr - (uint8*)&pDataBufferForFrame);
break;
}
case STATE_PLAYBACK:
if (pDataBufferPointer[8] == (uint8)-1)
CPad::GetPad(0)->NewState.Clear();
else {
tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
CTimer::SetTimeInMilliseconds(pData->m_nTimeInMilliseconds);
CTimer::SetTimeStep(pData->m_fTimeStep);
uint8 size1 = pData->m_nSizeOfPads[0];
uint8 size2 = pData->m_nSizeOfPads[1];
pDataBufferPointer = (uint8*)&pData->m_ControllerBuffer;
pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size1, &CPad::GetPad(0)->NewState);
pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size2, &CPad::GetPad(1)->NewState);
if ((size1 + size2) & 1)
pDataBufferPointer += 2;
if (pData->m_nChecksum != CalcGameChecksum())
printf("Playback out of sync\n");
}
}
}
#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
do { \
if (os->field != ns->field){ \
*buf++ = id; \
*buf++ = ns->field; \
} \
} while (0);
uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os, CControllerState* ns)
{
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickX, 2);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder1, 6);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder2, 7);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadUp, 8);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadDown, 9);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadLeft, 10);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadRight, 11);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Start, 12);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Select, 13);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Square, 14);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Triangle, 15);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Cross, 16);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Circle, 17);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShock, 18);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShock, 19);
return buf;
}
#undef PROCESS_BUTTON_STATE_STORE
#define PROCESS_BUTTON_STATE_RESTORE(buf, state, field, id) case id: state->field = *buf++; break;
uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CControllerState* state)
{
for (uint8 i = 0; i < total; i++) {
switch (*buf++) {
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickX, 2);
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5);
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder1, 6);
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder2, 7);
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadUp, 8);
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadDown, 9);
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadLeft, 10);
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadRight, 11);
PROCESS_BUTTON_STATE_RESTORE(buf, state, Start, 12);
PROCESS_BUTTON_STATE_RESTORE(buf, state, Select, 13);
PROCESS_BUTTON_STATE_RESTORE(buf, state, Square, 14);
PROCESS_BUTTON_STATE_RESTORE(buf, state, Triangle, 15);
PROCESS_BUTTON_STATE_RESTORE(buf, state, Cross, 16);
PROCESS_BUTTON_STATE_RESTORE(buf, state, Circle, 17);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShock, 18);
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShock, 19);
}
}
return buf;
}
#undef PROCESS_BUTTON_STATE_RESTORE
uint16 CRecordDataForGame::CalcGameChecksum(void)
{
uint32 checksum = 0;
int i = CPools::GetPedPool()->GetSize();
while (i--) {
CPed* pPed = CPools::GetPedPool()->GetSlot(i);
if (!pPed)
continue;
checksum ^= pPed->GetModelIndex() ^ *(uint32*)&pPed->GetPosition().z ^ *(uint32*)&pPed->GetPosition().y ^ *(uint32*)&pPed->GetPosition().x;
}
i = CPools::GetVehiclePool()->GetSize();
while (i--) {
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
checksum ^= pVehicle->GetModelIndex() ^ *(uint32*)&pVehicle->GetPosition().z ^ *(uint32*)&pVehicle->GetPosition().y ^ *(uint32*)&pVehicle->GetPosition().x;
}
return checksum ^ checksum >> 16;
}
uint8& CRecordDataForChase::Status = *(uint8*)0x95CDCE;
int& CRecordDataForChase::PositionChanges = *(int*)0x8F59C8;
uint8& CRecordDataForChase::CurrentCar = *(uint8*)0x95CDC9;
CAutomobile* (&CRecordDataForChase::pChaseCars)[NUM_CHASE_CARS] = *(CAutomobile * (*)[NUM_CHASE_CARS])*(uintptr*)0x6F46A8;
uint32& CRecordDataForChase::AnimStartTime = *(uint32*)0x8F1AEC;
float& CRecordDataForChase::AnimTime = *(float*)0x880F88;
CCarStateEachFrame* (&CRecordDataForChase::pBaseMemForCar)[NUM_CHASE_CARS] = *(CCarStateEachFrame * (*)[NUM_CHASE_CARS])*(uintptr*)0x70EA18;
float& CRecordDataForChase::TimeMultiplier = *(float*)0x8E2A94;
int& CRecordDataForChase::FId2 = *(int*)0x8E2C18;
#define CHASE_SCENE_LENGTH_IN_SECONDS (80)
#define CHASE_SCENE_FRAMES_PER_SECOND (15) // skipping every second frame
#define CHASE_SCENE_FRAMES_IN_RECORDING (CHASE_SCENE_LENGTH_IN_SECONDS * CHASE_SCENE_FRAMES_PER_SECOND)
#define CHASE_SCENE_LENGTH_IN_FRAMES (CHASE_SCENE_FRAMES_IN_RECORDING * 2)
void CRecordDataForChase::Init(void)
{
Status = STATE_NONE;
PositionChanges = 0;
CurrentCar = 0;
for (int i = 0; i < NUM_CHASE_CARS; i++)
pChaseCars[i] = nil;
AnimStartTime = 0;
}
void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void)
{
switch (Status) {
case STATE_NONE:
return;
case STATE_RECORD:
{
if ((CTimer::GetFrameCounter() & 1) == 0)
StoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2]);
if (CTimer::GetFrameCounter() < CHASE_SCENE_LENGTH_IN_FRAMES * 2)
return;
CFileMgr::SetDir("data\\paths");
sprintf(gString, "chase%d.dat", CurrentCar);
int fid = CFileMgr::OpenFileForWriting(gString);
uint32 fs = CHASE_SCENE_LENGTH_IN_FRAMES * sizeof(CCarStateEachFrame);
printf("FileSize:%d\n", fs);
CFileMgr::Write(fid, (char*)pBaseMemForCar[CurrentCar], fs);
CFileMgr::CloseFile(fid);
CFileMgr::SetDir("");
sprintf(gString, "car%d.max", CurrentCar);
int fid2 = CFileMgr::OpenFileForWriting(gString);
for (int i = 0; i < CHASE_SCENE_FRAMES_IN_RECORDING; i++) {
// WTF? Was it ever used?
#ifdef FIX_BUGS
CCarStateEachFrame* pState = pBaseMemForCar[CurrentCar];
#else
CCarStateEachFrame* pState = (CCarStateEachFrame*)pChaseCars[CurrentCar];
#endif
CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
CVector up = CrossProduct(right, forward);
sprintf(gString, "%f %f %f\n", pState->pos.x, pState->pos.y, pState->pos.z);
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
sprintf(gString, "%f %f %f\n", right.x, right.y, right.z);
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
sprintf(gString, "%f %f %f\n", forward.x, forward.y, forward.z);
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
sprintf(gString, "%f %f %f\n", up.x, up.y, up.z);
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
}
CFileMgr::CloseFile(fid2);
}
case STATE_PLAYBACK:
case STATE_PLAYBACK_BEFORE_RECORDING:
case STATE_PLAYBACK_INIT:
break;
}
}
struct tCoors {
CVector pos;
float angle;
};
// I guess developer was filling this with actual data before running the game
tCoors NewCoorsForRecordedCars[7];
void CRecordDataForChase::SaveOrRetrieveCarPositions(void)
{
switch (Status) {
case STATE_NONE:
return;
case STATE_RECORD:
case STATE_PLAYBACK_BEFORE_RECORDING:
for (int i = 0; i < NUM_CHASE_CARS; i++) {
if (i != CurrentCar && CTimer::GetFrameCounter()) {
RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CTimer::GetFrameCounter() / 2], false);
pChaseCars[i]->GetMatrix().UpdateRW();
pChaseCars[i]->UpdateRwFrame();
}
}
if (Status == STATE_PLAYBACK_BEFORE_RECORDING && CTimer::GetFrameCounter()) {
RestoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2], false);
pChaseCars[CurrentCar]->GetMatrix().UpdateRW();
pChaseCars[CurrentCar]->UpdateRwFrame();
}
if (CPad::GetPad(0)->GetLeftShockJustDown() && CPad::GetPad(0)->GetRightShockJustDown()) {
if (!CPad::GetPad(0)->GetRightShockJustDown()) {
pChaseCars[CurrentCar]->GetPosition() = NewCoorsForRecordedCars[PositionChanges].pos;
pChaseCars[CurrentCar]->SetMoveSpeed(0.0f, 0.0f, 0.0f);
pChaseCars[CurrentCar]->GetMatrix().SetRotateZOnly(DEGTORAD(NewCoorsForRecordedCars[PositionChanges].angle));
++PositionChanges;
}
if (Status == STATE_PLAYBACK_BEFORE_RECORDING) {
Status = STATE_RECORD;
pChaseCars[CurrentCar]->m_status = STATUS_PLAYER;
}
}
break;
case STATE_PLAYBACK_INIT:
Status = STATE_PLAYBACK;
break;
case STATE_PLAYBACK:
{
TimeMultiplier += CTimer::GetTimeStepNonClippedInSeconds();
float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier);
for (int i = 0; i < NUM_CHASE_CARS; i++) {
if (!pBaseMemForCar[i])
continue;
if (!pChaseCars[i])
continue;
if (EndOfFrameTime < CHASE_SCENE_FRAMES_IN_RECORDING - 1) {
int FlooredEOFTime = EndOfFrameTime;
RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][FlooredEOFTime], false);
CMatrix tmp;
float dp = EndOfFrameTime - FlooredEOFTime;
RestoreInfoForMatrix(tmp, &pBaseMemForCar[i][FlooredEOFTime + 1]);
pChaseCars[i]->GetRight() += (tmp.GetRight() - pChaseCars[i]->GetRight()) * dp;
pChaseCars[i]->GetForward() += (tmp.GetForward() - pChaseCars[i]->GetForward()) * dp;
pChaseCars[i]->GetUp() += (tmp.GetUp() - pChaseCars[i]->GetUp()) * dp;
pChaseCars[i]->GetPosition() += (tmp.GetPosition() - pChaseCars[i]->GetPosition()) * dp;
}
else{
RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CHASE_SCENE_FRAMES_IN_RECORDING - 1], true);
if (i == 0)
pChaseCars[i]->GetPosition().z += 0.2f;
}
pChaseCars[i]->GetMatrix().UpdateRW();
pChaseCars[i]->UpdateRwFrame();
pChaseCars[i]->RemoveAndAdd();
}
break;
}
}
}
void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState)
{
pState->rightX = INT8_MAX * pCar->GetRight().x;
pState->rightY = INT8_MAX * pCar->GetRight().y;
pState->rightZ = INT8_MAX * pCar->GetRight().z;
pState->forwardX = INT8_MAX * pCar->GetForward().x;
pState->forwardY = INT8_MAX * pCar->GetForward().y;
pState->forwardZ = INT8_MAX * pCar->GetForward().z;
pState->pos = pCar->GetPosition();
pState->velX = 0.5f * INT16_MAX * pCar->GetMoveSpeed().x;
pState->velY = 0.5f * INT16_MAX * pCar->GetMoveSpeed().y;
pState->velZ = 0.5f * INT16_MAX * pCar->GetMoveSpeed().z;
pState->wheel = 20 * pCar->m_fSteerAngle;
pState->gas = 100 * pCar->m_fGasPedal;
pState->brake = 100 * pCar->m_fBrakePedal;
pState->handbrake = pCar->bIsHandbrakeOn;
}
void CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState)
{
matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
matrix.GetUp() = CrossProduct(matrix.GetRight(), matrix.GetForward());
matrix.GetPosition() = pState->pos;
}
void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState, bool stop)
{
CVector oldPos = pCar->GetPosition();
RestoreInfoForMatrix(pCar->GetMatrix(), pState);
pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) / INT16_MAX / 0.5f);
pCar->SetTurnSpeed(0.0f, 0.0f, 0.0f);
pCar->m_fSteerAngle = pState->wheel / 20.0f;
pCar->m_fGasPedal = pState->gas / 100.0f;
pCar->m_fBrakePedal = pState->brake / 100.0f;
pCar->bIsHandbrakeOn = pState->handbrake;
if ((oldPos - pCar->GetPosition()).Magnitude() > 15.0f) {
if (pCar == pChaseCars[14]) {
pCar->m_currentColour1 = 58;
pCar->m_currentColour2 = 1;
}
else
pCar->GetModelInfo()->ChooseVehicleColour(pCar->m_currentColour1, pCar->m_currentColour2);
}
pCar->m_fHealth = min(pCar->m_fHealth, 500.0f);
if (stop) {
pCar->m_fGasPedal = 0.0f;
pCar->m_fBrakePedal = 0.0f;
pCar->SetMoveSpeed(0.0f, 0.0f, 0.0f);
pCar->bIsHandbrakeOn = false;
}
}
void CRecordDataForChase::ProcessControlCars(void)
{
if (Status != STATE_PLAYBACK)
return;
for (int i = 0; i < NUM_CHASE_CARS; i++) {
if (pChaseCars[i])
pChaseCars[i]->ProcessControl();
}
}
#if (defined(GTA_PS2) || defined(FIX_BUGS))
bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad)
{
// may be wrong
if (Status == STATE_NONE || Status == STATE_PLAYBACK)
return false;
return pad != 0;
}
#endif
void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2)
{
CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
CStreaming::LoadAllRequestedModels(false);
if (!CStreaming::HasModelLoaded(mi))
return;
CAutomobile* pCar = new CAutomobile(mi, MISSION_VEHICLE);
pCar->GetPosition() = pos;
pCar->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER;
pCar->GetMatrix().SetRotateZOnly(DEGTORAD(angle));
pCar->pDriver = nil;
pCar->m_currentColour1 = colour1;
pCar->m_currentColour2 = colour2;
CWorld::Add(pCar);
*ppCar = pCar;
}
void RemoveUnusedCollision(void)
{
static const char* dontDeleteArray[] = {
"rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22",
"road_broadway02", "road_broadway01", "com_21way5", "com_21way50",
"cm1waycrosscom", "com_21way20", "com_21way10", "road_broadway04",
"com_rvroads52", "com_roadsrv", "com_roadkb23", "com_roadkb22"
};
for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_NONE;
CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE);
for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL;
}
void CRecordDataForChase::StartChaseScene(float startTime)
{
char filename[28];
SetUpCarsForChaseScene();
Status = STATE_PLAYBACK;
AnimTime = startTime;
AnimStartTime = CTimer::GetTimeInMilliseconds();
RemoveUnusedCollision();
CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
CGame::TidyUpMemory(true, true);
CStreaming::ImGonnaUseStreamingMemory();
CFileMgr::SetDir("data\\paths");
for (int i = 0; i < NUM_CHASE_CARS; i++) {
if (!pChaseCars[i]) {
pBaseMemForCar[i] = nil;
continue;
}
sprintf(filename, "chase%d.dat", i);
FId2 = CFileMgr::OpenFile(filename, "rb");
if (FId2 <= 0) {
pBaseMemForCar[i] = nil;
continue;
}
pBaseMemForCar[i] = new CCarStateEachFrame[CHASE_SCENE_FRAMES_IN_RECORDING];
for (int j = 0; j < CHASE_SCENE_FRAMES_IN_RECORDING; j++) {
CFileMgr::Read(FId2, (char*)&pBaseMemForCar[i][j], sizeof(CCarStateEachFrame));
CFileMgr::Seek(FId2, sizeof(CCarStateEachFrame), 1);
}
CFileMgr::CloseFile(FId2);
}
CFileMgr::SetDir("");
CStreaming::IHaveUsedStreamingMemory();
TimeMultiplier = 0.0f;
}
void CRecordDataForChase::CleanUpChaseScene(void)
{
if (Status != STATE_PLAYBACK_INIT && Status != STATE_PLAYBACK)
return;
Status = STATE_NONE;
CleanUpCarsForChaseScene();
for (int i = 0; i < NUM_CHASE_CARS; i++) {
if (pBaseMemForCar[i]) {
delete[] pBaseMemForCar[i];
pBaseMemForCar[i] = nil;
}
}
}
void CRecordDataForChase::SetUpCarsForChaseScene(void)
{
GiveUsACar(MI_POLICE, CVector(273.54221f, -1167.1907f, 24.880601f), 63.0f, &pChaseCars[0], 2, 1);
GiveUsACar(MI_ENFORCER, CVector(231.1783f, -1388.8322f, 25.978201f), 90.0f, &pChaseCars[1], 2, 1);
GiveUsACar(MI_TAXI, CVector(184.3156f, -1473.251f, 25.978201f), 0.0f, &pChaseCars[4], 6, 6);
GiveUsACar(MI_CHEETAH, CVector(173.8868f, -1377.6514f, 25.978201f), 0.0f, &pChaseCars[6], 4, 5);
GiveUsACar(MI_STINGER, CVector(102.5946f, -943.93628f, 25.9781f), 270.0f, &pChaseCars[7], 53, 53);
GiveUsACar(MI_CHEETAH, CVector(-177.7157f, -862.18652f, 25.978201f), 155.0f, &pChaseCars[10], 41, 1);
GiveUsACar(MI_STINGER, CVector(-170.56979f, -889.02362f, 25.978201f), 154.0f, &pChaseCars[11], 10, 10);
GiveUsACar(MI_KURUMA, CVector(402.60809f, -917.49628f, 37.381001f), 90.0f, &pChaseCars[14], 34, 1);
GiveUsACar(MI_TAXI, CVector(-33.496201f, -938.4563f, 25.9781f), 266.0f, &pChaseCars[16], 6, 6);
GiveUsACar(MI_KURUMA, CVector(49.363098f, -987.60498f, 25.9781f), 0.0f, &pChaseCars[18], 51, 1);
GiveUsACar(MI_TAXI, CVector(179.0049f, -1154.6686f, 25.9781f), 0.0f, &pChaseCars[19], 6, 76);
GiveUsACar(MI_RUMPO, CVector(-28.9762f, -1031.3367f, 25.990601f), 242.0f, &pChaseCars[2], 1, 75);
GiveUsACar(MI_PATRIOT, CVector(114.1564f, -796.69379f, 24.978201f), 180.0f, &pChaseCars[3], 0, 0);
}
void CRecordDataForChase::CleanUpCarsForChaseScene(void)
{
for (int i = 0; i < NUM_CHASE_CARS; i++)
RemoveCarFromChase(i);
}
void CRecordDataForChase::RemoveCarFromChase(int32 i)
{
if (!pChaseCars[i])
return;
CWorld::Remove(pChaseCars[i]);
delete pChaseCars[i];
pChaseCars[i] = nil;
}
CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i)
{
CVehicle* pVehicle = pChaseCars[i];
pChaseCars[i] = nil;
pVehicle->m_status = STATUS_PHYSICS;
return pVehicle;
}
WRAPPER void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4347F0); }
WRAPPER void CRecordDataForChase::ProcessControlCars(void) { EAXJMP(0x435540); }
WRAPPER void CRecordDataForChase::SaveOrRetrieveCarPositions(void) { EAXJMP(0x434B20); }
WRAPPER void CRecordDataForChase::StartChaseScene(float) { EAXJMP(0x435690); }
WRAPPER void CRecordDataForChase::CleanUpChaseScene() { EAXJMP(0x4357C0); }
WRAPPER void CRecordDataForChase::RemoveCarFromChase(int32) { EAXJMP(0x435BC0); }
WRAPPER CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32) { EAXJMP(0x435C00); }
WRAPPER void CRecordDataForChase::Init(void) { EAXJMP(0x434780); }

View File

@ -1,34 +1,106 @@
#pragma once #pragma once
class CAutomobile;
class CVehicle; class CVehicle;
class CControllerState;
enum { class CCarStateEachFrame
RECORDSTATE_0, {
RECORDSTATE_1, public:
RECORDSTATE_2, int16 velX;
int16 velY;
int16 velZ;
int8 rightX;
int8 rightY;
int8 rightZ;
int8 forwardX;
int8 forwardY;
int8 forwardZ;
int8 wheel;
uint8 gas;
uint8 brake;
bool handbrake;
CVector pos;
}; };
extern char* gString;
class CRecordDataForChase class CRecordDataForChase
{ {
public: enum {
NUM_CHASE_CARS = 20
};
enum {
STATE_NONE = 0,
STATE_RECORD = 1,
STATE_PLAYBACK_INIT = 2,
STATE_PLAYBACK = 3,
STATE_PLAYBACK_BEFORE_RECORDING = 4
};
static uint8 &Status; static uint8 &Status;
static int &PositionChanges;
static uint8 &CurrentCar;
static CAutomobile*(&pChaseCars)[NUM_CHASE_CARS];
static float &AnimTime;
static uint32 &AnimStartTime;
static CCarStateEachFrame* (&pBaseMemForCar)[NUM_CHASE_CARS];
static float &TimeMultiplier;
static int &FId2;
public:
static bool IsRecording(void) { return Status == STATE_RECORD; }
static void Init(void);
static void SaveOrRetrieveDataForThisFrame(void); static void SaveOrRetrieveDataForThisFrame(void);
static void ProcessControlCars(void);
static void SaveOrRetrieveCarPositions(void); static void SaveOrRetrieveCarPositions(void);
static void StoreInfoForCar(CAutomobile*, CCarStateEachFrame*);
static void RestoreInfoForMatrix(CMatrix&, CCarStateEachFrame*);
static void RestoreInfoForCar(CAutomobile*, CCarStateEachFrame*, bool);
static void ProcessControlCars(void);
#if (defined(GTA_PS2) || defined(FIX_BUGS))
static bool ShouldThisPadBeLeftAlone(uint8 pad);
#endif
static void GiveUsACar(int32, CVector, float, CAutomobile**, uint8, uint8);
static void StartChaseScene(float); static void StartChaseScene(float);
static void CleanUpChaseScene(); static void CleanUpChaseScene(void);
static void SetUpCarsForChaseScene(void);
static void CleanUpCarsForChaseScene(void);
static void RemoveCarFromChase(int32); static void RemoveCarFromChase(int32);
static CVehicle* TurnChaseCarIntoScriptCar(int32); static CVehicle* TurnChaseCarIntoScriptCar(int32);
static void Init(void);
}; };
struct tGameBuffer
{
float m_fTimeStep;
uint32 m_nTimeInMilliseconds;
uint8 m_nSizeOfPads[2];
uint16 m_nChecksum;
uint8 m_ControllerBuffer[116];
};
class CRecordDataForGame class CRecordDataForGame
{ {
enum {
STATE_NONE = 0,
STATE_RECORD = 1,
STATE_PLAYBACK = 2,
};
static uint16& RecordingState;
static uint8* &pDataBuffer;
static uint8* &pDataBufferPointer;
static int &FId;
static tGameBuffer &pDataBufferForFrame;
public: public:
static uint16 &RecordingState; static bool IsRecording() { return RecordingState == STATE_RECORD; }
static bool IsPlayingBack() { return RecordingState == STATE_PLAYBACK; }
static void SaveOrRetrieveDataForThisFrame(void); static void SaveOrRetrieveDataForThisFrame(void);
static void Init(void); static void Init(void);
private:
static uint16 CalcGameChecksum(void);
static uint8* PackCurrentPadValues(uint8*, CControllerState*, CControllerState*);
static uint8* UnPackCurrentPadValues(uint8*, uint8, CControllerState*);
}; };

View File

@ -1107,7 +1107,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca
CStreaming::LoadScene(ff_coord); CStreaming::LoadScene(ff_coord);
} }
if (cam_mode == REPLAYCAMMODE_ASSTORED) if (cam_mode == REPLAYCAMMODE_ASSTORED)
TheCamera.CarZoomIndicator = 5.0f; TheCamera.CarZoomIndicator = CAM_ZOOM_CINEMATIC;
} }
void CReplay::StoreStuffInMem(void) void CReplay::StoreStuffInMem(void)
@ -1129,8 +1129,8 @@ void CReplay::StoreStuffInMem(void)
pEmptyReferences = CReferences::pEmptyList; pEmptyReferences = CReferences::pEmptyList;
pStoredCam = new uint8[sizeof(CCamera)]; pStoredCam = new uint8[sizeof(CCamera)];
memcpy(pStoredCam, &TheCamera, sizeof(CCamera)); memcpy(pStoredCam, &TheCamera, sizeof(CCamera));
pRadarBlips = new uint8[sizeof(CBlip) * NUMRADARBLIPS]; pRadarBlips = new uint8[sizeof(sRadarTrace) * NUMRADARBLIPS];
memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(CBlip)); memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(sRadarTrace));
PlayerWanted = *FindPlayerPed()->m_pWanted; PlayerWanted = *FindPlayerPed()->m_pWanted;
PlayerInfo = CWorld::Players[0]; PlayerInfo = CWorld::Players[0];
Time1 = CTimer::GetTimeInMilliseconds(); Time1 = CTimer::GetTimeInMilliseconds();
@ -1179,7 +1179,7 @@ void CReplay::RestoreStuffFromMem(void)
memcpy(&TheCamera, pStoredCam, sizeof(CCamera)); memcpy(&TheCamera, pStoredCam, sizeof(CCamera));
delete[] pStoredCam; delete[] pStoredCam;
pStoredCam = nil; pStoredCam = nil;
memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMRADARBLIPS); memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(sRadarTrace) * NUMRADARBLIPS);
delete[] pRadarBlips; delete[] pRadarBlips;
pRadarBlips = nil; pRadarBlips = nil;
FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted);

View File

@ -21,234 +21,234 @@ CVector(&CRestart::PoliceRestartPoints)[NUM_RESTART_POINTS] = *(CVector(*)[NUM_R
float(&CRestart::PoliceRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D20; float(&CRestart::PoliceRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D20;
uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44; uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44;
void void
CRestart::Initialise() CRestart::Initialise()
{ {
OverridePoliceStationLevel = LEVEL_NONE; OverridePoliceStationLevel = LEVEL_NONE;
OverrideHospitalLevel = LEVEL_NONE; OverrideHospitalLevel = LEVEL_NONE;
bFadeInAfterNextArrest = true; bFadeInAfterNextArrest = true;
bFadeInAfterNextDeath = true; bFadeInAfterNextDeath = true;
OverrideHeading = 0.0f; OverrideHeading = 0.0f;
OverridePosition = CVector(0.0f, 0.0f, 0.0f); OverridePosition = CVector(0.0f, 0.0f, 0.0f);
bOverrideRestart = false; bOverrideRestart = false;
NumberOfPoliceRestarts = 0; NumberOfPoliceRestarts = 0;
NumberOfHospitalRestarts = 0; NumberOfHospitalRestarts = 0;
for (int i = 0; i < NUM_RESTART_POINTS; i++) { for (int i = 0; i < NUM_RESTART_POINTS; i++) {
HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
HospitalRestartHeadings[i] = 0.0f; HospitalRestartHeadings[i] = 0.0f;
PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
PoliceRestartHeadings[i] = 0.0f; PoliceRestartHeadings[i] = 0.0f;
} }
} }
void void
CRestart::AddHospitalRestartPoint(const CVector &pos, float heading) CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
{ {
HospitalRestartPoints[NumberOfHospitalRestarts] = pos; HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading; HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
} }
void void
CRestart::AddPoliceRestartPoint(const CVector &pos, float heading) CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
{ {
PoliceRestartPoints[NumberOfPoliceRestarts] = pos; PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading; PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
} }
void void
CRestart::OverrideNextRestart(const CVector &pos, float heading) CRestart::OverrideNextRestart(const CVector &pos, float heading)
{ {
bOverrideRestart = true; bOverrideRestart = true;
OverridePosition = pos; OverridePosition = pos;
OverrideHeading = heading; OverrideHeading = heading;
} }
void void
CRestart::CancelOverrideRestart() CRestart::CancelOverrideRestart()
{ {
bOverrideRestart = false; bOverrideRestart = false;
} }
void void
CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
{ {
if (bOverrideRestart) { if (bOverrideRestart) {
*outPos = OverridePosition; *outPos = OverridePosition;
*outHeading = OverrideHeading; *outHeading = OverrideHeading;
CancelOverrideRestart(); CancelOverrideRestart();
return; return;
} }
eLevelName curlevel = CTheZones::FindZoneForPoint(pos); eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f; float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS; int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level // find closest point on this level
for (int i = 0; i < NumberOfHospitalRestarts; i++) { for (int i = 0; i < NumberOfHospitalRestarts; i++) {
if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) { if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) { if (fMinDist >= dist) {
fMinDist = dist; fMinDist = dist;
closestPoint = i; closestPoint = i;
} }
} }
} }
// if we didn't find anything, find closest point on any level // if we didn't find anything, find closest point on any level
if (closestPoint == NUM_RESTART_POINTS) { if (closestPoint == NUM_RESTART_POINTS) {
for (int i = 0; i < NumberOfHospitalRestarts; i++) { for (int i = 0; i < NumberOfHospitalRestarts; i++) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) { if (fMinDist >= dist) {
fMinDist = dist; fMinDist = dist;
closestPoint = i; closestPoint = i;
} }
} }
} }
// if we still didn't find anything, find closest path node // if we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) { if (closestPoint == NUM_RESTART_POINTS) {
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
*outHeading = 0.0f; *outHeading = 0.0f;
printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z); printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);
} else { } else {
*outPos = HospitalRestartPoints[closestPoint]; *outPos = HospitalRestartPoints[closestPoint];
*outHeading = HospitalRestartHeadings[closestPoint]; *outHeading = HospitalRestartHeadings[closestPoint];
} }
} }
void void
CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
{ {
if (bOverrideRestart) { if (bOverrideRestart) {
*outPos = OverridePosition; *outPos = OverridePosition;
*outHeading = OverrideHeading; *outHeading = OverrideHeading;
CancelOverrideRestart(); CancelOverrideRestart();
return; return;
} }
eLevelName curlevel = CTheZones::FindZoneForPoint(pos); eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f; float fMinDist = 16000000.0f;
int closestPoint = NUM_RESTART_POINTS; int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level // find closest point on this level
for (int i = 0; i < NumberOfPoliceRestarts; i++) { for (int i = 0; i < NumberOfPoliceRestarts; i++) {
if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) { if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) { if (fMinDist >= dist) {
fMinDist = dist; fMinDist = dist;
closestPoint = i; closestPoint = i;
} }
} }
} }
// if we didn't find anything, find closest point on any level // if we didn't find anything, find closest point on any level
if (closestPoint == NUM_RESTART_POINTS) { if (closestPoint == NUM_RESTART_POINTS) {
for (int i = 0; i < NumberOfPoliceRestarts; i++) { for (int i = 0; i < NumberOfPoliceRestarts; i++) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) { if (fMinDist >= dist) {
fMinDist = dist; fMinDist = dist;
closestPoint = i; closestPoint = i;
} }
} }
} }
// if we still didn't find anything, find closest path node // if we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) { if (closestPoint == NUM_RESTART_POINTS) {
printf("Couldn't find a police restart zone near the player\n"); printf("Couldn't find a police restart zone near the player\n");
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
*outHeading = 0.0f; *outHeading = 0.0f;
} else { } else {
*outPos = PoliceRestartPoints[closestPoint]; *outPos = PoliceRestartPoints[closestPoint];
*outHeading = PoliceRestartHeadings[closestPoint]; *outHeading = PoliceRestartHeadings[closestPoint];
} }
} }
void void
CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size) CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
{ {
Initialise(); Initialise();
INITSAVEBUF INITSAVEBUF
CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE); CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_RESTART_POINTS; i++) { for (int i = 0; i < NUM_RESTART_POINTS; i++) {
HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf); HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf); HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
} }
for (int i = 0; i < NUM_RESTART_POINTS; i++) { for (int i = 0; i < NUM_RESTART_POINTS; i++) {
PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf); PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf); PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
} }
NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf); NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf); NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
bOverrideRestart = ReadSaveBuf<bool>(buf); bOverrideRestart = ReadSaveBuf<bool>(buf);
// skip something unused // skip something unused
ReadSaveBuf<uint8>(buf); ReadSaveBuf<uint8>(buf);
ReadSaveBuf<uint16>(buf); ReadSaveBuf<uint16>(buf);
OverridePosition = ReadSaveBuf<CVector>(buf); OverridePosition = ReadSaveBuf<CVector>(buf);
OverrideHeading = ReadSaveBuf<float>(buf); OverrideHeading = ReadSaveBuf<float>(buf);
bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf); bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf); bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
OverrideHospitalLevel = ReadSaveBuf<uint8>(buf); OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf); OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
VALIDATESAVEBUF(size); VALIDATESAVEBUF(size);
} }
void void
CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size) CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
{ {
*size = SAVE_HEADER_SIZE *size = SAVE_HEADER_SIZE
+ sizeof(HospitalRestartPoints) + sizeof(HospitalRestartPoints)
+ sizeof(HospitalRestartHeadings) + sizeof(HospitalRestartHeadings)
+ sizeof(PoliceRestartPoints) + sizeof(PoliceRestartPoints)
+ sizeof(PoliceRestartHeadings) + sizeof(PoliceRestartHeadings)
+ sizeof(NumberOfHospitalRestarts) + sizeof(NumberOfHospitalRestarts)
+ sizeof(NumberOfPoliceRestarts) + sizeof(NumberOfPoliceRestarts)
+ sizeof(bOverrideRestart) + sizeof(bOverrideRestart)
+ sizeof(uint8) + sizeof(uint8)
+ sizeof(uint16) + sizeof(uint16)
+ sizeof(OverridePosition) + sizeof(OverridePosition)
+ sizeof(OverrideHeading) + sizeof(OverrideHeading)
+ sizeof(bFadeInAfterNextDeath) + sizeof(bFadeInAfterNextDeath)
+ sizeof(bFadeInAfterNextArrest) + sizeof(bFadeInAfterNextArrest)
+ sizeof(OverrideHospitalLevel) + sizeof(OverrideHospitalLevel)
+ sizeof(OverridePoliceStationLevel); // == 292 + sizeof(OverridePoliceStationLevel); // == 292
INITSAVEBUF INITSAVEBUF
WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE); WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_RESTART_POINTS; i++) { for (int i = 0; i < NUM_RESTART_POINTS; i++) {
WriteSaveBuf(buf, HospitalRestartPoints[i]); WriteSaveBuf(buf, HospitalRestartPoints[i]);
WriteSaveBuf(buf, HospitalRestartHeadings[i]); WriteSaveBuf(buf, HospitalRestartHeadings[i]);
} }
for (int i = 0; i < NUM_RESTART_POINTS; i++) { for (int i = 0; i < NUM_RESTART_POINTS; i++) {
WriteSaveBuf(buf, PoliceRestartPoints[i]); WriteSaveBuf(buf, PoliceRestartPoints[i]);
WriteSaveBuf(buf, PoliceRestartHeadings[i]); WriteSaveBuf(buf, PoliceRestartHeadings[i]);
} }
WriteSaveBuf(buf, NumberOfHospitalRestarts); WriteSaveBuf(buf, NumberOfHospitalRestarts);
WriteSaveBuf(buf, NumberOfPoliceRestarts); WriteSaveBuf(buf, NumberOfPoliceRestarts);
WriteSaveBuf(buf, bOverrideRestart); WriteSaveBuf(buf, bOverrideRestart);
WriteSaveBuf(buf, (uint8)0); WriteSaveBuf(buf, (uint8)0);
WriteSaveBuf(buf, (uint16)0); WriteSaveBuf(buf, (uint16)0);
WriteSaveBuf(buf, OverridePosition); WriteSaveBuf(buf, OverridePosition);
WriteSaveBuf(buf, OverrideHeading); WriteSaveBuf(buf, OverrideHeading);
WriteSaveBuf(buf, bFadeInAfterNextDeath); WriteSaveBuf(buf, bFadeInAfterNextDeath);
WriteSaveBuf(buf, bFadeInAfterNextArrest); WriteSaveBuf(buf, bFadeInAfterNextArrest);
WriteSaveBuf(buf, OverrideHospitalLevel); WriteSaveBuf(buf, OverrideHospitalLevel);
WriteSaveBuf(buf, OverridePoliceStationLevel); WriteSaveBuf(buf, OverridePoliceStationLevel);
VALIDATESAVEBUF(*size); VALIDATESAVEBUF(*size);
} }
STARTPATCHES STARTPATCHES
InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP); InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP);
InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP); InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP);
@ -258,5 +258,5 @@ STARTPATCHES
InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP); InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP);
InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP); InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP);
InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP); InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP);
InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP); InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -2,36 +2,202 @@
#include "patcher.h" #include "patcher.h"
#include "RoadBlocks.h" #include "RoadBlocks.h"
#include "PathFind.h" #include "PathFind.h"
#include "ModelIndices.h"
#include "Streaming.h"
#include "World.h"
#include "PedPlacement.h"
#include "Automobile.h"
#include "CopPed.h"
#include "VisibilityPlugins.h"
#include "PlayerPed.h"
#include "Wanted.h"
#include "Camera.h"
#include "CarCtrl.h"
#include "General.h"
int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34; int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34;
int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8; int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8;
bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810; bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810;
WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); }
WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); }
void void
CRoadBlocks::Init(void) CRoadBlocks::Init(void)
{ {
NumRoadBlocks = 0; NumRoadBlocks = 0;
for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
if (NumRoadBlocks < 600) { if (NumRoadBlocks < NUMROADBLOCKS) {
InOrOut[NumRoadBlocks] = true; InOrOut[NumRoadBlocks] = true;
RoadBlockObjects[NumRoadBlocks] = objId; RoadBlockObjects[NumRoadBlocks] = objId;
NumRoadBlocks++; NumRoadBlocks++;
} else { } else {
#ifndef MASTER #ifndef MASTER
printf("Not enough room for the potential roadblocks\n"); printf("Not enough room for the potential roadblocks\n");
#endif #endif
// FIX: Don't iterate loop after NUMROADBLOCKS // FIX: Don't iterate loop after NUMROADBLOCKS
return; return;
} }
} }
} }
} }
void
CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode)
{
static const CVector vecRoadBlockOffets[6] = { {-1.5, 1.8f, 0.0f}, {-1.5f, -1.8f, 0.0f}, {1.5f, 1.8f, 0.0f},
{1.5f, -1.8f, 0.0f}, {-1.5f, 0.0f, 0.0f}, {1.5, 0.0, 0.0} };
CEntity* pEntityToAttack = (CEntity*)FindPlayerVehicle();
if (!pEntityToAttack)
pEntityToAttack = (CEntity*)FindPlayerPed();
CColModel* pPoliceColModel = CModelInfo::GetModelInfo(MI_POLICE)->GetColModel();
float fRadius = pVehicle->GetBoundRadius() / pPoliceColModel->boundingSphere.radius;
for (int32 i = 0; i < 2; i++) {
const int32 roadBlockIndex = i + 2 * roadBlockType;
CVector posForZ = pVehicle->m_matrix * (fRadius * vecRoadBlockOffets[roadBlockIndex]);
int32 modelInfoId = MI_COP;
eCopType copType = COP_STREET;
switch (pVehicle->GetModelIndex())
{
case MI_FBICAR:
modelInfoId = MI_FBI;
copType = COP_FBI;
break;
case MI_ENFORCER:
modelInfoId = MI_SWAT;
copType = COP_SWAT;
break;
case MI_BARRACKS:
modelInfoId = MI_ARMY;
copType = COP_ARMY;
break;
}
if (!CStreaming::HasModelLoaded(modelInfoId))
copType = COP_STREET;
CCopPed* pCopPed = new CCopPed(copType);
if (copType == COP_STREET)
pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45);
CPedPlacement::FindZCoorForPed(&posForZ);
pCopPed->m_matrix.GetPosition() = posForZ;
CVector vecSavedPos = pCopPed->m_matrix.GetPosition();
pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI);
pCopPed->m_matrix.GetPosition() += vecSavedPos;
pCopPed->m_bIsDisabledCop = true;
pCopPed->SetIdle();
pCopPed->bKindaStayInSamePlace = true;
pCopPed->bNotAllowedToDuck = false;
pCopPed->m_wRoadblockNode = roadBlockNode;
pCopPed->bCrouchWhenShooting = roadBlockType != 2;
if (pEntityToAttack) {
pCopPed->m_pPointGunAt = pEntityToAttack;
pEntityToAttack->RegisterReference(&pCopPed->m_pPointGunAt);
pCopPed->SetAttack(pEntityToAttack);
}
pCopPed->m_pMyVehicle = pVehicle;
pVehicle->RegisterReference((CEntity**)&pCopPed->m_pMyVehicle);
pCopPed->bCullExtraFarAway = true;
CVisibilityPlugins::SetClumpAlpha(pCopPed->GetClump(), 0);
CWorld::Add(pCopPed);
}
}
void
CRoadBlocks::GenerateRoadBlocks(void)
{
CMatrix offsetMatrix;
uint32 frame = CTimer::GetFrameCounter() & 0xF;
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks;
if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks)
numRoadBlocks = maxRoadBlocks;
for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) {
CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]];
CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
if (vecDistance.x > -80.0f && vecDistance.x < 80.0f &&
vecDistance.y > -80.0f && vecDistance.y < 80.0f &&
vecDistance.Magnitude() < 80.0f) {
if (!CRoadBlocks::InOrOut[nRoadblockNode]) {
CRoadBlocks::InOrOut[nRoadblockNode] = true;
if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
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->m_matrix.GetPosition();
float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->m_matrix.GetUp());
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[CRoadBlocks::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->m_status = 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->m_matrix.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;
}
}
}
}
}
}
} else {
CRoadBlocks::InOrOut[nRoadblockNode] = false;
}
}
}
STARTPATCHES STARTPATCHES
InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP); InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP);
InjectHook(0x4376A0, &CRoadBlocks::GenerateRoadBlockCopsForCar, PATCH_JUMP);
InjectHook(0x436FA0, &CRoadBlocks::GenerateRoadBlocks, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -11,6 +11,6 @@ public:
static bool (&InOrOut)[NUMROADBLOCKS]; static bool (&InOrOut)[NUMROADBLOCKS];
static void Init(void); static void Init(void);
static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16); static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode);
static void GenerateRoadBlocks(void); static void GenerateRoadBlocks(void);
}; };

View File

@ -91,10 +91,10 @@ uint8 (&CTheScripts::ScriptSpace)[SIZE_SCRIPT_SPACE] = *(uint8(*)[SIZE_SCRIPT_SP
CRunningScript(&CTheScripts::ScriptsArray)[MAX_NUM_SCRIPTS] = *(CRunningScript(*)[MAX_NUM_SCRIPTS])*(uintptr*)0x6F5C08; CRunningScript(&CTheScripts::ScriptsArray)[MAX_NUM_SCRIPTS] = *(CRunningScript(*)[MAX_NUM_SCRIPTS])*(uintptr*)0x6F5C08;
int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200; int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200;
int32(&CTheScripts::OnAMissionForContactFlag)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x8622F0; int32(&CTheScripts::OnAMissionForContactFlag)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x8622F0;
CTextLine (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(CTextLine (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68; intro_text_line (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(intro_text_line (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68;
CScriptRectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(CScriptRectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108; intro_script_rectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(intro_script_rectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108;
CSprite2d (&CTheScripts::ScriptSprites)[MAX_NUM_SCRIPT_SRPITES] = *(CSprite2d(*)[MAX_NUM_SCRIPT_SRPITES])*(uintptr*)0x72B090; CSprite2d (&CTheScripts::ScriptSprites)[MAX_NUM_SCRIPT_SRPITES] = *(CSprite2d(*)[MAX_NUM_SCRIPT_SRPITES])*(uintptr*)0x72B090;
CScriptSphere(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(CScriptSphere(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60; script_sphere_struct(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(script_sphere_struct(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60;
tCollectiveData(&CTheScripts::CollectiveArray)[MAX_NUM_COLLECTIVES] = *(tCollectiveData(*)[MAX_NUM_COLLECTIVES])*(uintptr*)0x6FA008; tCollectiveData(&CTheScripts::CollectiveArray)[MAX_NUM_COLLECTIVES] = *(tCollectiveData(*)[MAX_NUM_COLLECTIVES])*(uintptr*)0x6FA008;
tUsedObject(&CTheScripts::UsedObjectArray)[MAX_NUM_USED_OBJECTS] = *(tUsedObject(*)[MAX_NUM_USED_OBJECTS])*(uintptr*)0x6E69C8; tUsedObject(&CTheScripts::UsedObjectArray)[MAX_NUM_USED_OBJECTS] = *(tUsedObject(*)[MAX_NUM_USED_OBJECTS])*(uintptr*)0x6E69C8;
int32(&CTheScripts::MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS] = *(int32(*)[MAX_NUM_MISSION_SCRIPTS])*(uintptr*)0x6F0558; int32(&CTheScripts::MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS] = *(int32(*)[MAX_NUM_MISSION_SCRIPTS])*(uintptr*)0x6F0558;
@ -313,7 +313,7 @@ bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)
return false; return false;
} }
void CStuckCarCheckEntry::Reset() void stuck_car_data::Reset()
{ {
m_nVehicleIndex = -1; m_nVehicleIndex = -1;
m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f); m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);
@ -2229,6 +2229,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
if (pos.z <= -100) if (pos.z <= -100)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
UpdateCompareFlag(TheCamera.IsSphereVisible(pos, *(float*)&ScriptParams[3])); UpdateCompareFlag(TheCamera.IsSphereVisible(pos, *(float*)&ScriptParams[3]));
return 0;
} }
case COMMAND_DEBUG_ON: case COMMAND_DEBUG_ON:
CTheScripts::DbgFlag = true; CTheScripts::DbgFlag = true;
@ -7116,7 +7117,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
case COMMAND_CLOSE_GARAGE: case COMMAND_CLOSE_GARAGE:
{ {
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
CGarages::CloseGarage(ScriptParams[1]); CGarages::CloseGarage(ScriptParams[0]);
return 0; return 0;
} }
case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD: case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:
@ -7657,13 +7658,13 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
assert(pObject); assert(pObject);
if (ScriptParams[1]) { if (ScriptParams[1]) {
if (pObject->bIsStatic) { if (pObject->bIsStatic) {
pObject->bIsStatic = true; pObject->bIsStatic = false;
pObject->AddToMovingList(); pObject->AddToMovingList();
} }
} }
else { else {
if (!pObject->bIsStatic) { if (!pObject->bIsStatic) {
pObject->bIsStatic = false; pObject->bIsStatic = true;
pObject->RemoveFromMovingList(); pObject->RemoveFromMovingList();
} }
} }
@ -8441,7 +8442,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
CPad::GetPad(ScriptParams[0])->DisablePlayerControls |= PLAYERCONTROL_DISABLED_80; CPad::GetPad(ScriptParams[0])->DisablePlayerControls |= PLAYERCONTROL_DISABLED_80;
pPlayerInfo->MakePlayerSafe(true); pPlayerInfo->MakePlayerSafe(true);
CCutsceneMgr::SetRunning(true); CCutsceneMgr::StartCutsceneProcessing();
return 0; return 0;
} }
case COMMAND_USE_TEXT_COMMANDS: case COMMAND_USE_TEXT_COMMANDS:
@ -9140,7 +9141,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
assert(pVehicle); assert(pVehicle);
assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
CAutomobile* pCar = (CAutomobile*)pVehicle; CAutomobile* pCar = (CAutomobile*)pVehicle;
pCar->bTakeLessDamage = ScriptParams[1]; pCar->bMoreResistantToDamage = ScriptParams[1];
return 0; return 0;
} }
case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER: case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER:
@ -9152,6 +9153,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
return 0; return 0;
} }
case COMMAND_LOAD_END_OF_GAME_TUNE: case COMMAND_LOAD_END_OF_GAME_TUNE:
DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);
printf("Start preload end of game audio\n"); printf("Start preload end of game audio\n");
DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED); DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED);
printf("End preload end of game audio\n"); printf("End preload end of game audio\n");
@ -11037,6 +11039,7 @@ void CRunningScript::DoDeatharrestCheck()
int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact]; int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact];
if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) { if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) {
messageId += CTheScripts::BaseBriefIdForContact[contact]; messageId += CTheScripts::BaseBriefIdForContact[contact];
found = true;
} }
} }
if (!found) if (!found)
@ -11331,6 +11334,7 @@ INITSAVEBUF
break; break;
case 4: case 4:
InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1); InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1);
break;
default: default:
assert(false); assert(false);
} }
@ -11369,15 +11373,15 @@ void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntit
continue; continue;
CEntity* pFound = aEntities[i]; CEntity* pFound = aEntities[i];
int cols; int cols;
if (CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel()->numLines <= 0) if (pEntity->GetColModel()->numLines <= 0)
cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(), cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, nil, nil); pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil);
else { else {
float lines[4]; float lines[4];
lines[0] = lines[1] = lines[2] = lines[3] = 1.0f; lines[0] = lines[1] = lines[2] = lines[3] = 1.0f;
CColPoint tmp; CColPoint tmp[4];
cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(), cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, &tmp, lines); pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines);
} }
if (cols <= 0) if (cols <= 0)
continue; continue;

View File

@ -15,22 +15,25 @@ class CRunningScript;
#define KEY_LENGTH_IN_SCRIPT 8 #define KEY_LENGTH_IN_SCRIPT 8
struct CScriptRectangle struct intro_script_rectangle
{ {
int8 m_bIsUsed; bool m_bIsUsed;
bool m_bBeforeFade; bool m_bBeforeFade;
int16 m_nTextureId; int16 m_nTextureId;
CRect m_sRect; CRect m_sRect;
CRGBA m_sColor; CRGBA m_sColor;
intro_script_rectangle() { }
~intro_script_rectangle() { }
}; };
static_assert(sizeof(CScriptRectangle) == 0x18, "Script.h: error"); static_assert(sizeof(intro_script_rectangle) == 0x18, "Script.h: error");
enum { enum {
SCRIPT_TEXT_MAX_LENGTH = 500 SCRIPT_TEXT_MAX_LENGTH = 500
}; };
struct CTextLine struct intro_text_line
{ {
float m_fScaleX; float m_fScaleX;
float m_fScaleY; float m_fScaleY;
@ -50,6 +53,9 @@ struct CTextLine
float m_fAtY; float m_fAtY;
wchar m_Text[SCRIPT_TEXT_MAX_LENGTH]; wchar m_Text[SCRIPT_TEXT_MAX_LENGTH];
intro_text_line() { }
~intro_text_line() { }
void Reset() void Reset()
{ {
m_fScaleX = 0.48f; m_fScaleX = 0.48f;
@ -72,15 +78,17 @@ struct CTextLine
} }
}; };
static_assert(sizeof(CTextLine) == 0x414, "Script.h: error"); static_assert(sizeof(intro_text_line) == 0x414, "Script.h: error");
struct CScriptSphere struct script_sphere_struct
{ {
bool m_bInUse; bool m_bInUse;
uint16 m_Index; uint16 m_Index;
uint32 m_Id; uint32 m_Id;
CVector m_vecCenter; CVector m_vecCenter;
float m_fRadius; float m_fRadius;
script_sphere_struct() { }
}; };
struct CStoredLine struct CStoredLine
@ -145,7 +153,7 @@ public:
bool HasCarBeenUpsideDownForAWhile(int32); bool HasCarBeenUpsideDownForAWhile(int32);
}; };
struct CStuckCarCheckEntry struct stuck_car_data
{ {
int32 m_nVehicleIndex; int32 m_nVehicleIndex;
CVector m_vecPos; CVector m_vecPos;
@ -154,12 +162,13 @@ struct CStuckCarCheckEntry
uint32 m_nStuckTime; uint32 m_nStuckTime;
bool m_bStuck; bool m_bStuck;
stuck_car_data() { }
inline void Reset(); inline void Reset();
}; };
class CStuckCarCheck class CStuckCarCheck
{ {
CStuckCarCheckEntry m_sCars[MAX_STUCK_CAR_CHECKS]; stuck_car_data m_sCars[MAX_STUCK_CAR_CHECKS];
public: public:
void Init(); void Init();
@ -235,10 +244,10 @@ class CTheScripts
static CRunningScript(&ScriptsArray)[MAX_NUM_SCRIPTS]; static CRunningScript(&ScriptsArray)[MAX_NUM_SCRIPTS];
static int32(&BaseBriefIdForContact)[MAX_NUM_CONTACTS]; static int32(&BaseBriefIdForContact)[MAX_NUM_CONTACTS];
static int32(&OnAMissionForContactFlag)[MAX_NUM_CONTACTS]; static int32(&OnAMissionForContactFlag)[MAX_NUM_CONTACTS];
static CTextLine(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES]; static intro_text_line(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES];
static CScriptRectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES]; static intro_script_rectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES];
static CSprite2d(&ScriptSprites)[MAX_NUM_SCRIPT_SRPITES]; static CSprite2d(&ScriptSprites)[MAX_NUM_SCRIPT_SRPITES];
static CScriptSphere(&ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES]; static script_sphere_struct(&ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES];
static tCollectiveData(&CollectiveArray)[MAX_NUM_COLLECTIVES]; static tCollectiveData(&CollectiveArray)[MAX_NUM_COLLECTIVES];
static tUsedObject(&UsedObjectArray)[MAX_NUM_USED_OBJECTS]; static tUsedObject(&UsedObjectArray)[MAX_NUM_USED_OBJECTS];
static int32(&MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS]; static int32(&MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS];

View File

@ -1,23 +1,335 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "TrafficLights.h" #include "General.h"
#include "Camera.h"
#include "World.h"
#include "PathFind.h"
#include "Timer.h" #include "Timer.h"
#include "Clock.h"
#include "Weather.h"
#include "Timecycle.h"
#include "Pointlights.h"
#include "Shadows.h"
#include "Coronas.h"
#include "SpecialFX.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "TrafficLights.h"
WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); } // TODO: figure out the meaning of this
WRAPPER void CTrafficLights::ScanForLightsOnMap(void) { EAXJMP(0x454F40); } enum { SOME_FLAG = 0x80 };
WRAPPER bool CTrafficLights::ShouldCarStopForLight(CVehicle*, bool) { EAXJMP(0x455350); }
WRAPPER bool CTrafficLights::ShouldCarStopForBridge(CVehicle*) { EAXJMP(0x456460); } void
CTrafficLights::DisplayActualLight(CEntity *ent)
{
if(ent->GetUp().z < 0.96f || ent->bRenderDamaged)
return;
int phase;
if(FindTrafficLightType(ent) == 1)
phase = LightForCars1();
else
phase = LightForCars2();
int i;
CBaseModelInfo *mi = CModelInfo::GetModelInfo(ent->GetModelIndex());
float x = mi->Get2dEffect(0)->pos.x;
float yMin = mi->Get2dEffect(0)->pos.y;
float yMax = mi->Get2dEffect(0)->pos.y;
float zMin = mi->Get2dEffect(0)->pos.z;
float zMax = mi->Get2dEffect(0)->pos.z;
for(i = 1; i < 6; i++){
assert(mi->Get2dEffect(i));
yMin = min(yMin, mi->Get2dEffect(i)->pos.y);
yMax = max(yMax, mi->Get2dEffect(i)->pos.y);
zMin = min(zMin, mi->Get2dEffect(i)->pos.z);
zMax = max(zMax, mi->Get2dEffect(i)->pos.z);
}
CVector pos1, pos2;
uint8 r, g;
int id;
switch(phase){
case CAR_LIGHTS_GREEN:
r = 0;
g = 255;
pos1 = ent->GetMatrix() * CVector(x, yMax, zMin);
pos2 = ent->GetMatrix() * CVector(x, yMin, zMin);
id = 0;
break;
case CAR_LIGHTS_YELLOW:
r = 255;
g = 128;
pos1 = ent->GetMatrix() * CVector(x, yMax, (zMin+zMax)/2.0f);
pos2 = ent->GetMatrix() * CVector(x, yMin, (zMin+zMax)/2.0f);
id = 1;
break;
case CAR_LIGHTS_RED:
default:
r = 255;
g = 0;
pos1 = ent->GetMatrix() * CVector(x, yMax, zMax);
pos2 = ent->GetMatrix() * CVector(x, yMin, zMax);
id = 2;
break;
}
if(CClock::GetHours() > 19 || CClock::GetHours() < 6 || CWeather::Foggyness > 0.05f)
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,
r/255.0f, g/255.0f, 0/255.0f, CPointLights::FOG_NORMAL, true);
CShadows::StoreStaticShadow((uintptr)ent,
SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,
8.0f, 0.0f, 0.0f, -8.0f, 128,
r*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
g*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
0*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
12.0f, 1.0f, 40.0f, false, 0.0f);
if(DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)
CCoronas::RegisterCorona((uintptr)ent + id,
r*CTimeCycle::GetSpriteBrightness()*0.7f,
g*CTimeCycle::GetSpriteBrightness()*0.7f,
0*CTimeCycle::GetSpriteBrightness()*0.7f,
255,
pos1, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
else
CCoronas::RegisterCorona((uintptr)ent + id + 3,
r*CTimeCycle::GetSpriteBrightness()*0.7f,
g*CTimeCycle::GetSpriteBrightness()*0.7f,
0*CTimeCycle::GetSpriteBrightness()*0.7f,
255,
pos2, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
CBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
static const float top = -0.127f;
static const float bot = -0.539f;
static const float mid = bot + (top-bot)/3.0f;
static const float left = 1.256f;
static const float right = 0.706f;
phase = CTrafficLights::LightForPeds();
if(phase == PED_LIGHTS_DONT_WALK){
CVector p0(2.7f, right, top);
CVector p1(2.7f, left, top);
CVector p2(2.7f, right, mid);
CVector p3(2.7f, left, mid);
CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
SHINYTEXT_WALK, 255, 0, 0, 60.0f);
}else if(phase == PED_LIGHTS_WALK || CTimer::GetTimeInMilliseconds() & 0x100){
CVector p0(2.7f, right, mid);
CVector p1(2.7f, left, mid);
CVector p2(2.7f, right, bot);
CVector p3(2.7f, left, bot);
CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
SHINYTEXT_WALK, 255, 255, 255, 60.0f);
}
}
void
CTrafficLights::ScanForLightsOnMap(void)
{
int x, y;
int i, j, l;
CPtrNode *node;
for(x = 0; x < NUMSECTORS_X; x++)
for(y = 0; y < NUMSECTORS_Y; y++){
CPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES];
for(node = list.first; node; node = node->next){
CEntity *light = (CEntity*)node->item;
if(light->GetModelIndex() != MI_TRAFFICLIGHTS)
continue;
// Check cars
for(i = 0; i < ThePaths.m_numCarPathLinks; i++){
CVector2D dist = ThePaths.m_carPathLinks[i].pos - light->GetPosition();
float dotY = Abs(DotProduct2D(dist, light->GetForward())); // forward is direction of car light
float dotX = DotProduct2D(dist, light->GetRight()); // towards base of light
// it has to be on the correct side of the node and also not very far away
if(dotX < 0.0f && dotX > -15.0f && dotY < 3.0f){
float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].pos.z -
light->GetPosition().z;
if(dz < 15.0f){
ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light);
// Find two neighbour nodes of this one
int n1 = -1;
int n2 = -1;
for(j = 0; j < ThePaths.m_numPathNodes; j++)
for(l = 0; l < ThePaths.m_pathNodes[j].numLinks; l++)
if(ThePaths.m_carPathConnections[ThePaths.m_pathNodes[j].firstLink + l] == i){
if(n1 == -1)
n1 = j;
else
n2 = j;
}
// What's going on here?
if(ThePaths.m_pathNodes[n1].numLinks <= ThePaths.m_pathNodes[n2].numLinks)
n1 = n2;
if(ThePaths.m_carPathLinks[i].pathNodeIndex != n1)
ThePaths.m_carPathLinks[i].trafficLightType |= SOME_FLAG;
}
}
}
// Check peds
for(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){
float dist1, dist2;
dist1 = Abs(ThePaths.m_pathNodes[i].pos.x - light->GetPosition().x) +
Abs(ThePaths.m_pathNodes[i].pos.y - light->GetPosition().y);
if(dist1 < 50.0f){
for(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){
j = ThePaths.m_pathNodes[i].firstLink + l;
if(ThePaths.m_connectionFlags[j].bCrossesRoad){
dist2 = Abs(ThePaths.m_pathNodes[j].pos.x - light->GetPosition().x) +
Abs(ThePaths.m_pathNodes[j].pos.y - light->GetPosition().y);
if(dist1 < 15.0f || dist2 < 15.0f)
ThePaths.m_connectionFlags[j].bTrafficLight = true;
}
}
}
}
}
}
}
bool
CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
{
int node, type;
node = vehicle->AutoPilot.m_nNextPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
if(type){
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nNextRouteNode) &&
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nNextRouteNode))
if(alwaysStop ||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos,
ThePaths.m_carPathLinks[node].dir);
if(vehicle->AutoPilot.m_nNextDirection == -1){
if(dist > 0.0f && dist < 8.0f)
return true;
}else{
if(dist < 0.0f && dist > -8.0f)
return true;
}
}
}
node = vehicle->AutoPilot.m_nCurrentPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
if(type){
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nCurrentRouteNode) &&
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nCurrentRouteNode))
if(alwaysStop ||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos,
ThePaths.m_carPathLinks[node].dir);
if(vehicle->AutoPilot.m_nCurrentDirection == -1){
if(dist > 0.0f && dist < 8.0f)
return true;
}else{
if(dist < 0.0f && dist > -8.0f)
return true;
}
}
}
if(vehicle->m_status == STATUS_PHYSICS){
node = vehicle->AutoPilot.m_nPreviousPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
if(type){
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nPrevRouteNode) &&
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nPrevRouteNode))
if(alwaysStop ||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos,
ThePaths.m_carPathLinks[node].dir);
if(vehicle->AutoPilot.m_nPreviousDirection == -1){
if(dist > 0.0f && dist < 6.0f)
return true;
}else{
if(dist < 0.0f && dist > -6.0f)
return true;
}
}
}
}
return false;
}
bool
CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle)
{
return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights &&
!ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights;
}
int
CTrafficLights::FindTrafficLightType(CEntity *light)
{
float orientation = RADTODEG(CGeneral::GetATanOfXY(light->GetForward().x, light->GetForward().y));
if((orientation > 60.0f && orientation < 60.0f + 90.0f) ||
(orientation > 240.0f && orientation < 240.0f + 90.0f))
return 1;
return 2;
}
uint8 uint8
CTrafficLights::LightForPeds(void) CTrafficLights::LightForPeds(void)
{ {
uint32 period = CTimer::GetTimeInMilliseconds() & 0x3FFF; // Equals to % 16384 uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if (period >= 15384) if(period < 12000)
return PED_LIGHTS_WALK_BLINK; return PED_LIGHTS_DONT_WALK;
else if (period >= 12000) else if(period < 16384 - 1000)
return PED_LIGHTS_WALK; return PED_LIGHTS_WALK;
else else
return PED_LIGHTS_DONT_WALK; return PED_LIGHTS_WALK_BLINK;
} }
uint8
CTrafficLights::LightForCars1(void)
{
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if(period < 5000)
return CAR_LIGHTS_GREEN;
else if(period < 5000 + 1000)
return CAR_LIGHTS_YELLOW;
else
return CAR_LIGHTS_RED;
}
uint8
CTrafficLights::LightForCars2(void)
{
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if(period < 6000)
return CAR_LIGHTS_RED;
else if(period < 12000 - 1000)
return CAR_LIGHTS_GREEN;
else if(period < 12000)
return CAR_LIGHTS_YELLOW;
else
return CAR_LIGHTS_RED;
}
STARTPATCHES
InjectHook(0x455760, &CTrafficLights::LightForCars1, PATCH_JUMP);
InjectHook(0x455790, &CTrafficLights::LightForCars2, PATCH_JUMP);
InjectHook(0x4557D0, &CTrafficLights::LightForPeds, PATCH_JUMP);
ENDPATCHES

View File

@ -7,6 +7,10 @@ enum {
PED_LIGHTS_WALK, PED_LIGHTS_WALK,
PED_LIGHTS_WALK_BLINK, PED_LIGHTS_WALK_BLINK,
PED_LIGHTS_DONT_WALK, PED_LIGHTS_DONT_WALK,
CAR_LIGHTS_GREEN = 0,
CAR_LIGHTS_YELLOW,
CAR_LIGHTS_RED
}; };
class CTrafficLights class CTrafficLights
@ -14,7 +18,10 @@ class CTrafficLights
public: public:
static void DisplayActualLight(CEntity *ent); static void DisplayActualLight(CEntity *ent);
static void ScanForLightsOnMap(void); static void ScanForLightsOnMap(void);
static int FindTrafficLightType(CEntity *light);
static uint8 LightForPeds(void); static uint8 LightForPeds(void);
static uint8 LightForCars1(void);
static uint8 LightForCars2(void);
static bool ShouldCarStopForLight(CVehicle*, bool); static bool ShouldCarStopForLight(CVehicle*, bool);
static bool ShouldCarStopForBridge(CVehicle*); static bool ShouldCarStopForBridge(CVehicle*);
}; };

View File

@ -3511,7 +3511,7 @@ CCam::Process_FlyBy(const CVector&, float, float, float)
Up = CVector(0.0f, 0.0f, 1.0f); Up = CVector(0.0f, 0.0f, 1.0f);
if(TheCamera.m_bStartingSpline) if(TheCamera.m_bStartingSpline)
m_fTimeElapsedFloat += CTimer::GetTimeStepInMilliseconds(); m_fTimeElapsedFloat += CTimer::GetTimeStepNonClippedInMilliseconds();
else{ else{
m_fTimeElapsedFloat = 0.0f; m_fTimeElapsedFloat = 0.0f;
m_uiFinishTime = MS(TheCamera.m_arrPathArray[2].m_arr_PathData[10*((int)TheCamera.m_arrPathArray[2].m_arr_PathData[0]-1) + 1]); m_uiFinishTime = MS(TheCamera.m_arrPathArray[2].m_arr_PathData[10*((int)TheCamera.m_arrPathArray[2].m_arr_PathData[0]-1) + 1]);
@ -4672,15 +4672,15 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation,
else { else {
switch ((int)TheCamera.CarZoomIndicator) { switch ((int)TheCamera.CarZoomIndicator) {
// near // near
case 1: case CAM_ZOOM_1:
zoomModeAlphaOffset = ZmOneAlphaOffsetLCS[alphaArrPos]; zoomModeAlphaOffset = ZmOneAlphaOffsetLCS[alphaArrPos];
break; break;
// mid // mid
case 2: case CAM_ZOOM_2:
zoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos]; zoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos];
break; break;
// far // far
case 3: case CAM_ZOOM_3:
zoomModeAlphaOffset = ZmThreeAlphaOffsetLCS[alphaArrPos]; zoomModeAlphaOffset = ZmThreeAlphaOffsetLCS[alphaArrPos];
break; break;
default: default:
@ -4705,14 +4705,12 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation,
} }
} else { } else {
// 0.6f = fTestShiftHeliCamTarget // 0.6f = fTestShiftHeliCamTarget
TargetCoors.x += 0.6f * car->GetUp().x * colMaxZ; TargetCoors += 0.6f * car->GetUp() * colMaxZ;
TargetCoors.y += 0.6f * car->GetUp().y * colMaxZ;
TargetCoors.z += 0.6f * car->GetUp().z * colMaxZ;
} }
float minDistForVehType = CARCAM_SET[camSetArrPos][4]; float minDistForVehType = CARCAM_SET[camSetArrPos][4];
if ((int)TheCamera.CarZoomIndicator == 1 && (camSetArrPos < 2 || camSetArrPos == 7)) { if (TheCamera.CarZoomIndicator == CAM_ZOOM_1 && (camSetArrPos < 2 || camSetArrPos == 7)) {
minDistForVehType = minDistForVehType * 0.65f; minDistForVehType = minDistForVehType * 0.65f;
} }
@ -4904,8 +4902,8 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation,
// yMovement = 0.0; // yMovement = 0.0;
if (!nextDirectionIsForward) { if (!nextDirectionIsForward) {
yMovement = 0.0; yMovement = 0.0f;
xMovement = 0.0; xMovement = 0.0f;
} }
if (camSetArrPos == 0 || camSetArrPos == 7) { if (camSetArrPos == 0 || camSetArrPos == 7) {

View File

@ -124,8 +124,8 @@ CCamera::Init(void)
m_WideScreenOn = false; m_WideScreenOn = false;
m_fFOV_Wide_Screen = 0.0f; m_fFOV_Wide_Screen = 0.0f;
m_bRestoreByJumpCut = false; m_bRestoreByJumpCut = false;
CarZoomIndicator = 2.0f; CarZoomIndicator = CAM_ZOOM_2;
PedZoomIndicator = 2.0f; PedZoomIndicator = CAM_ZOOM_2;
CarZoomValueSmooth = 0.0f; CarZoomValueSmooth = 0.0f;
m_fPedZoomValueSmooth = 0.0f; m_fPedZoomValueSmooth = 0.0f;
pTargetEntity = nil; pTargetEntity = nil;
@ -142,7 +142,7 @@ CCamera::Init(void)
PlayerExhaustion = 1.0f; PlayerExhaustion = 1.0f;
DebugCamMode = CCam::MODE_NONE; DebugCamMode = CCam::MODE_NONE;
m_PedOrientForBehindOrInFront = 0.0f; m_PedOrientForBehindOrInFront = 0.0f;
if(!FrontEndMenuManager.m_bStartGameLoading){ if(!FrontEndMenuManager.m_bWantToRestart){
m_bFading = false; m_bFading = false;
CDraw::FadeValue = 0; CDraw::FadeValue = 0;
m_fFLOATingFade = 0.0f; m_fFLOATingFade = 0.0f;
@ -151,7 +151,7 @@ CCamera::Init(void)
m_fFLOATingFadeMusic = 0.0f; m_fFLOATingFadeMusic = 0.0f;
} }
m_bMoveCamToAvoidGeom = false; m_bMoveCamToAvoidGeom = false;
if(FrontEndMenuManager.m_bStartGameLoading) if(FrontEndMenuManager.m_bWantToRestart)
m_bMoveCamToAvoidGeom = true; m_bMoveCamToAvoidGeom = true;
m_bStartingSpline = false; m_bStartingSpline = false;
m_iTypeOfSwitch = INTERPOLATION; m_iTypeOfSwitch = INTERPOLATION;
@ -623,11 +623,11 @@ CCamera::CamControl(void)
if(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() && if(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() &&
(m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
!m_WideScreenOn) !m_WideScreenOn)
CarZoomIndicator -= 1.0f; CarZoomIndicator--;
if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() && if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() &&
(m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
!m_WideScreenOn) !m_WideScreenOn)
CarZoomIndicator += 1.0f; CarZoomIndicator++;
if(!m_bFailedCullZoneTestPreviously){ if(!m_bFailedCullZoneTestPreviously){
if(CarZoomIndicator < CAM_ZOOM_1STPRS) CarZoomIndicator = CAM_ZOOM_CINEMATIC; if(CarZoomIndicator < CAM_ZOOM_1STPRS) CarZoomIndicator = CAM_ZOOM_CINEMATIC;
else if(CarZoomIndicator > CAM_ZOOM_CINEMATIC) CarZoomIndicator = CAM_ZOOM_1STPRS; else if(CarZoomIndicator > CAM_ZOOM_CINEMATIC) CarZoomIndicator = CAM_ZOOM_1STPRS;
@ -727,12 +727,24 @@ CCamera::CamControl(void)
if(CarZoomIndicator == CAM_ZOOM_1STPRS && !m_bPlayerIsInGarage){ if(CarZoomIndicator == CAM_ZOOM_1STPRS && !m_bPlayerIsInGarage){
CarZoomValue = 0.0f; CarZoomValue = 0.0f;
ReqMode = CCam::MODE_1STPERSON; ReqMode = CCam::MODE_1STPERSON;
}else if(CarZoomIndicator == CAM_ZOOM_1) }
CarZoomValue = 0.05f; #ifdef FREE_CAM
else if (bFreeCam) {
if (CarZoomIndicator == CAM_ZOOM_1)
CarZoomValue = ((CVehicle*)pTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_1 : FREE_CAR_ZOOM_VALUE_1;
else if (CarZoomIndicator == CAM_ZOOM_2)
CarZoomValue = ((CVehicle*)pTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_2 : FREE_CAR_ZOOM_VALUE_2;
else if (CarZoomIndicator == CAM_ZOOM_3)
CarZoomValue = ((CVehicle*)pTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_3 : FREE_CAR_ZOOM_VALUE_3;
}
#endif
else if(CarZoomIndicator == CAM_ZOOM_1)
CarZoomValue = DEFAULT_CAR_ZOOM_VALUE_1;
else if(CarZoomIndicator == CAM_ZOOM_2) else if(CarZoomIndicator == CAM_ZOOM_2)
CarZoomValue = 1.9f; CarZoomValue = DEFAULT_CAR_ZOOM_VALUE_2;
else if(CarZoomIndicator == CAM_ZOOM_3) else if(CarZoomIndicator == CAM_ZOOM_3)
CarZoomValue = 3.9f; CarZoomValue = DEFAULT_CAR_ZOOM_VALUE_3;
if(CarZoomIndicator == CAM_ZOOM_TOPDOWN && !m_bPlayerIsInGarage){ if(CarZoomIndicator == CAM_ZOOM_TOPDOWN && !m_bPlayerIsInGarage){
CarZoomValue = 1.0f; CarZoomValue = 1.0f;
ReqMode = CCam::MODE_TOPDOWN; ReqMode = CCam::MODE_TOPDOWN;
@ -800,7 +812,7 @@ CCamera::CamControl(void)
else else
PedZoomIndicator = CAM_ZOOM_TOPDOWN; PedZoomIndicator = CAM_ZOOM_TOPDOWN;
}else }else
PedZoomIndicator -= 1.0f; PedZoomIndicator--;
} }
if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() && if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() &&
(m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
@ -811,7 +823,7 @@ CCamera::CamControl(void)
else else
PedZoomIndicator = CAM_ZOOM_TOPDOWN; PedZoomIndicator = CAM_ZOOM_TOPDOWN;
}else }else
PedZoomIndicator += 1.0f; PedZoomIndicator++;
} }
// disabled obbe's cam here // disabled obbe's cam here
if(PedZoomIndicator < CAM_ZOOM_1) PedZoomIndicator = CAM_ZOOM_TOPDOWN; if(PedZoomIndicator < CAM_ZOOM_1) PedZoomIndicator = CAM_ZOOM_TOPDOWN;
@ -1211,7 +1223,7 @@ CCamera::CamControl(void)
ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT || ReqMode == CCam::MODE_HELICANNON_1STPERSON || ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT || ReqMode == CCam::MODE_HELICANNON_1STPERSON ||
WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT || WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT ||
m_bJustCameOutOfGarage || m_bPlayerIsInGarage) m_bJustCameOutOfGarage || m_bPlayerIsInGarage)
canUseObbeCam = false; canUseObbeCam = false;
if(m_bObbeCinematicPedCamOn && canUseObbeCam) if(m_bObbeCinematicPedCamOn && canUseObbeCam)
@ -1512,7 +1524,7 @@ CCamera::UpdateTargetEntity(void)
cantOpen = false; cantOpen = false;
if(PLAYER->GetPedState() == PED_ENTER_CAR && !cantOpen){ if(PLAYER->GetPedState() == PED_ENTER_CAR && !cantOpen){
if(!enteringCar && CarZoomIndicator != 0.0f){ if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS){
pTargetEntity = PLAYER->m_pMyVehicle; pTargetEntity = PLAYER->m_pMyVehicle;
if(PLAYER->m_pMyVehicle == nil) if(PLAYER->m_pMyVehicle == nil)
pTargetEntity = PLAYER; pTargetEntity = PLAYER;
@ -1520,7 +1532,7 @@ CCamera::UpdateTargetEntity(void)
} }
if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){ if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){
if(!enteringCar && CarZoomIndicator != 0.0f) if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS)
#ifdef GTA_PS2_STUFF #ifdef GTA_PS2_STUFF
// dunno if this has any amazing effects // dunno if this has any amazing effects
{ {
@ -1537,7 +1549,7 @@ CCamera::UpdateTargetEntity(void)
pTargetEntity = FindPlayerPed(); pTargetEntity = FindPlayerPed();
if(PLAYER->GetPedState() == PED_DRAG_FROM_CAR) if(PLAYER->GetPedState() == PED_DRAG_FROM_CAR)
pTargetEntity = FindPlayerPed(); pTargetEntity = FindPlayerPed();
if(pTargetEntity->IsVehicle() && CarZoomIndicator != 0.0f && FindPlayerPed()->GetPedState() == PED_ARRESTED) if(pTargetEntity->IsVehicle() && CarZoomIndicator != CAM_ZOOM_1STPRS && FindPlayerPed()->GetPedState() == PED_ARRESTED)
pTargetEntity = FindPlayerPed(); pTargetEntity = FindPlayerPed();
} }
} }
@ -2956,11 +2968,23 @@ CCamera::SetZoomValueFollowPedScript(int16 dist)
void void
CCamera::SetZoomValueCamStringScript(int16 dist) CCamera::SetZoomValueCamStringScript(int16 dist)
{ {
switch (dist) { #ifdef FREE_CAM
case 0: m_fCarZoomValueScript = 0.05f; break; if (bFreeCam) {
case 1: m_fCarZoomValueScript = 1.9f; break; switch (dist) {
case 2: m_fCarZoomValueScript = 3.9f; break; case 0: m_fCarZoomValueScript = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_1 : FREE_CAR_ZOOM_VALUE_1; break;
default: m_fCarZoomValueScript = m_fCarZoomValueScript; break; case 1: m_fCarZoomValueScript = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_2 : FREE_CAR_ZOOM_VALUE_2; break;
case 2: m_fCarZoomValueScript = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_3 : FREE_CAR_ZOOM_VALUE_3; break;
default: m_fCarZoomValueScript = m_fCarZoomValueScript; break;
}
} else
#endif
{
switch (dist) {
case 0: m_fCarZoomValueScript = DEFAULT_CAR_ZOOM_VALUE_1; break;
case 1: m_fCarZoomValueScript = DEFAULT_CAR_ZOOM_VALUE_2; break;
case 2: m_fCarZoomValueScript = DEFAULT_CAR_ZOOM_VALUE_3; break;
default: m_fCarZoomValueScript = m_fCarZoomValueScript; break;
}
} }
m_bUseScriptZoomValueCar = true; m_bUseScriptZoomValueCar = true;
@ -3245,7 +3269,7 @@ void
CCamera::SetRwCamera(RwCamera *cam) CCamera::SetRwCamera(RwCamera *cam)
{ {
m_pRwCamera = cam; m_pRwCamera = cam;
m_viewMatrix.Attach(&m_pRwCamera->viewMatrix, false); m_viewMatrix.Attach(RwCameraGetViewMatrix(m_pRwCamera), false);
CMBlur::MotionBlurOpen(m_pRwCamera); CMBlur::MotionBlurOpen(m_pRwCamera);
} }

View File

@ -16,12 +16,29 @@ enum
}; };
#define DEFAULT_NEAR (0.9f) #define DEFAULT_NEAR (0.9f)
#define CAM_ZOOM_1STPRS (0.0f) enum
#define CAM_ZOOM_1 (1.0f) {
#define CAM_ZOOM_2 (2.0f) CAM_ZOOM_1STPRS,
#define CAM_ZOOM_3 (3.0f) CAM_ZOOM_1,
#define CAM_ZOOM_TOPDOWN (4.0f) CAM_ZOOM_2,
#define CAM_ZOOM_CINEMATIC (5.0f) CAM_ZOOM_3,
CAM_ZOOM_TOPDOWN,
CAM_ZOOM_CINEMATIC,
};
#ifdef FREE_CAM // LCS values
#define FREE_CAR_ZOOM_VALUE_1 (-1.0f)
#define FREE_CAR_ZOOM_VALUE_2 (2.0f)
#define FREE_CAR_ZOOM_VALUE_3 (6.0f)
#define FREE_BOAT_ZOOM_VALUE_1 (-2.41f)
#define FREE_BOAT_ZOOM_VALUE_2 (6.49f)
#define FREE_BOAT_ZOOM_VALUE_3 (15.0f)
#endif
#define DEFAULT_CAR_ZOOM_VALUE_1 (0.05f)
#define DEFAULT_CAR_ZOOM_VALUE_2 (1.9f)
#define DEFAULT_CAR_ZOOM_VALUE_3 (3.9f)
class CCam class CCam
{ {
@ -398,7 +415,11 @@ uint32 unknown; // some counter having to do with music
float CamFrontXNorm; float CamFrontXNorm;
float CamFrontYNorm; float CamFrontYNorm;
#if 0 // TODO: FIX_BUGS once GenericLoad is done
int32 CarZoomIndicator;
#else
float CarZoomIndicator; float CarZoomIndicator;
#endif
float CarZoomValue; float CarZoomValue;
float CarZoomValueSmooth; float CarZoomValueSmooth;
@ -434,7 +455,11 @@ uint32 unknown; // some counter having to do with music
float m_ScreenReductionSpeed; float m_ScreenReductionSpeed;
float m_AlphaForPlayerAnim1rstPerson; float m_AlphaForPlayerAnim1rstPerson;
float Orientation; float Orientation;
#if 0 // TODO: FIX_BUGS once GenericLoad is done
int32 PedZoomIndicator;
#else
float PedZoomIndicator; float PedZoomIndicator;
#endif
float PlayerExhaustion; float PlayerExhaustion;
float SoundDistUp, SoundDistLeft, SoundDistRight; float SoundDistUp, SoundDistLeft, SoundDistRight;
float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead; float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead;

View File

@ -34,8 +34,6 @@ enum Direction
eLevelName &CCollision::ms_collisionInMemory = *(eLevelName*)0x8F6250; eLevelName &CCollision::ms_collisionInMemory = *(eLevelName*)0x8F6250;
CLinkList<CColModel*> &CCollision::ms_colModelCache = *(CLinkList<CColModel*>*)0x95CB58; CLinkList<CColModel*> &CCollision::ms_colModelCache = *(CLinkList<CColModel*>*)0x95CB58;
WRAPPER bool CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly) { EAXJMP(0x4105A0); }
void void
CCollision::Init(void) CCollision::Init(void)
{ {
@ -926,6 +924,87 @@ CCollision::ProcessVerticalLineTriangle(const CColLine &line,
return true; return true;
} }
bool
CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly)
{
float t;
if(!poly->valid)
return false;
// maybe inlined?
CColTriangle tri;
tri.a = 0;
tri.b = 1;
tri.c = 2;
CColTrianglePlane plane;
plane.Set(poly->verts, tri);
const CVector &va = poly->verts[tri.a];
const CVector &vb = poly->verts[tri.b];
const CVector &vc = poly->verts[tri.c];
CVector p0 = pos;
CVector p1(pos.x, pos.y, z);
// The rest is pretty much CCollision::ProcessLineTriangle
// if points are on the same side, no collision
if(plane.CalcPoint(p0) * plane.CalcPoint(p1) > 0.0f)
return poly->valid = false;
// intersection parameter on line
t = -plane.CalcPoint(p0) / DotProduct(p1 - p0, plane.normal);
// find point of intersection
CVector p = p0 + (p1-p0)*t;
CVector2D vec1, vec2, vec3, vect;
switch(plane.dir){
case DIR_X_POS:
vec1.x = va.y; vec1.y = va.z;
vec2.x = vc.y; vec2.y = vc.z;
vec3.x = vb.y; vec3.y = vb.z;
vect.x = p.y; vect.y = p.z;
break;
case DIR_X_NEG:
vec1.x = va.y; vec1.y = va.z;
vec2.x = vb.y; vec2.y = vb.z;
vec3.x = vc.y; vec3.y = vc.z;
vect.x = p.y; vect.y = p.z;
break;
case DIR_Y_POS:
vec1.x = va.z; vec1.y = va.x;
vec2.x = vc.z; vec2.y = vc.x;
vec3.x = vb.z; vec3.y = vb.x;
vect.x = p.z; vect.y = p.x;
break;
case DIR_Y_NEG:
vec1.x = va.z; vec1.y = va.x;
vec2.x = vb.z; vec2.y = vb.x;
vec3.x = vc.z; vec3.y = vc.x;
vect.x = p.z; vect.y = p.x;
break;
case DIR_Z_POS:
vec1.x = va.x; vec1.y = va.y;
vec2.x = vc.x; vec2.y = vc.y;
vec3.x = vb.x; vec3.y = vb.y;
vect.x = p.x; vect.y = p.y;
break;
case DIR_Z_NEG:
vec1.x = va.x; vec1.y = va.y;
vec2.x = vb.x; vec2.y = vb.y;
vec3.x = vc.x; vec3.y = vc.y;
vect.x = p.x; vect.y = p.y;
break;
default:
assert(0);
}
if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return poly->valid = false;
if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return poly->valid = false;
if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return poly->valid = false;
point.point = p;
return poly->valid = true;
}
bool bool
CCollision::ProcessLineTriangle(const CColLine &line , CCollision::ProcessLineTriangle(const CColLine &line ,
const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,

View File

@ -144,7 +144,6 @@ public:
static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough); static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough);
static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly); static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly);
static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists); static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
// TODO:
static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly); static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point); static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);

View File

@ -24,7 +24,7 @@ CDebug::DebugAddText(const char *str)
{ {
int32 i = 0; int32 i = 0;
if (*str != '\0') { if (*str != '\0') {
while (i < MAX_STR_LEN) { while (i < MAX_STR_LEN - 1) {
ms_aTextBuffer[ms_nCurrentTextLine][i++] = *(str++); ms_aTextBuffer[ms_nCurrentTextLine][i++] = *(str++);
if (*str == '\0') if (*str == '\0')
break; break;

View File

@ -25,8 +25,6 @@
#include "CdStream.h" #include "CdStream.h"
#include "FileLoader.h" #include "FileLoader.h"
WRAPPER void CFileLoader::ReloadPaths(const char *filename) { EAXJMP(0x476DB0); }
char CFileLoader::ms_line[256]; char CFileLoader::ms_line[256];
const char* const char*
@ -311,7 +309,7 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)
int n; int n;
RpClump *clump = (RpClump*)data; RpClump *clump = (RpClump*)data;
nodename = GetFrameNodeName(RpClumpGetFrame(atomic)); nodename = GetFrameNodeName(RpAtomicGetFrame(atomic));
GetNameAndLOD(nodename, name, &n); GetNameAndLOD(nodename, name, &n);
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, nil); mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, nil);
if(mi){ if(mi){
@ -1198,6 +1196,165 @@ CFileLoader::LoadMapZones(const char *filename)
debug("Finished loading IPL\n"); debug("Finished loading IPL\n");
} }
void
CFileLoader::ReloadPaths(const char *filename)
{
enum {
NONE,
PATH,
};
char *line;
int section = NONE;
int id, pathType, pathIndex = -1;
char pathTypeStr[20];
debug("Reloading paths from %s...\n", filename);
int fd = CFileMgr::OpenFile(filename, "r");
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
if (*line == '\0' || *line == '#')
continue;
if (section == NONE) {
if (strncmp(line, "path", 4) == 0) {
section = PATH;
ThePaths.AllocatePathFindInfoMem(4500);
}
} else if (strncmp(line, "end", 3) == 0) {
section = NONE;
} else {
switch (section) {
case PATH:
if (pathIndex == -1) {
id = LoadPathHeader(line, pathTypeStr);
if (strncmp(pathTypeStr, "ped", 4) == 0)
pathType = 1;
else if (strncmp(pathTypeStr, "car", 4) == 0)
pathType = 0;
pathIndex = 0;
} else {
if (pathType == 1)
LoadPedPathNode(line, id, pathIndex);
else if (pathType == 0)
LoadCarPathNode(line, id, pathIndex);
pathIndex++;
if (pathIndex == 12)
pathIndex = -1;
}
break;
default:
break;
}
}
}
CFileMgr::CloseFile(fd);
}
void
CFileLoader::ReloadObjectTypes(const char *filename)
{
enum {
NONE,
OBJS,
TOBJ,
TWODFX
};
char *line;
int section = NONE;
CModelInfo::ReInit2dEffects();
debug("Reloading object types from %s...\n", filename);
CFileMgr::ChangeDir("\\DATA\\MAPS\\");
int fd = CFileMgr::OpenFile(filename, "r");
CFileMgr::ChangeDir("\\");
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
if (*line == '\0' || *line == '#')
continue;
if (section == NONE) {
if (strncmp(line, "objs", 4) == 0) section = OBJS;
else if (strncmp(line, "tobj", 4) == 0) section = TOBJ;
else if (strncmp(line, "2dfx", 4) == 0) section = TWODFX;
} else if (strncmp(line, "end", 3) == 0) {
section = NONE;
} else {
switch (section) {
case OBJS:
case TOBJ:
ReloadObject(line);
break;
case TWODFX:
Load2dEffect(line);
break;
default:
break;
}
}
}
CFileMgr::CloseFile(fd);
}
void
CFileLoader::ReloadObject(const char *line)
{
int id, numObjs;
char model[24], txd[24];
float dist[3];
uint32 flags;
CSimpleModelInfo *mi;
if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4)
return;
switch(numObjs){
case 1:
sscanf(line, "%d %s %s %d %f %d",
&id, model, txd, &numObjs, &dist[0], &flags);
break;
case 2:
sscanf(line, "%d %s %s %d %f %f %d",
&id, model, txd, &numObjs, &dist[0], &dist[1], &flags);
break;
case 3:
sscanf(line, "%d %s %s %d %f %f %f %d",
&id, model, txd, &numObjs, &dist[0], &dist[1], &dist[2], &flags);
break;
}
mi = (CSimpleModelInfo*) CModelInfo::GetModelInfo(id);
if (
#ifdef FIX_BUGS
mi &&
#endif
mi->m_type == MITYPE_SIMPLE && !strcmp(mi->GetName(), model) && mi->m_numAtomics == numObjs) {
mi->SetLodDistances(dist);
SetModelInfoFlags(mi, flags);
} else {
printf("Can't reload %s\n", model);
}
}
// unused mobile function - crashes
void
CFileLoader::ReLoadScene(const char *filename)
{
char *line;
CFileMgr::ChangeDir("\\DATA\\");
int fd = CFileMgr::OpenFile(filename, "r");
CFileMgr::ChangeDir("\\");
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
if (*line == '#')
continue;
if (strncmp(line, "EXIT", 9) == 0) // BUG: 9?
break;
if (strncmp(line, "IDE", 3) == 0) {
LoadObjectTypes(line + 4);
}
}
CFileMgr::CloseFile(fd);
}
STARTPATCHES STARTPATCHES
InjectHook(0x476290, CFileLoader::LoadLevel, PATCH_JUMP); InjectHook(0x476290, CFileLoader::LoadLevel, PATCH_JUMP);
@ -1233,4 +1390,8 @@ STARTPATCHES
InjectHook(0x478A90, CFileLoader::LoadCullZone, PATCH_JUMP); InjectHook(0x478A90, CFileLoader::LoadCullZone, PATCH_JUMP);
InjectHook(0x478550, CFileLoader::LoadMapZones, PATCH_JUMP); InjectHook(0x478550, CFileLoader::LoadMapZones, PATCH_JUMP);
InjectHook(0x476DB0, CFileLoader::ReloadPaths, PATCH_JUMP);
InjectHook(0x476F30, CFileLoader::ReloadObjectTypes, PATCH_JUMP);
InjectHook(0x4772B0, CFileLoader::ReloadObject, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -43,4 +43,7 @@ public:
static void LoadMapZones(const char *filename); static void LoadMapZones(const char *filename);
static void ReloadPaths(const char *filename); static void ReloadPaths(const char *filename);
static void ReloadObjectTypes(const char *filename);
static void ReloadObject(const char *line);
static void ReLoadScene(const char *filename); // unused mobile function
}; };

File diff suppressed because it is too large Load Diff

712
src/core/FrontEndControls.h Normal file
View File

@ -0,0 +1,712 @@
#pragma once
enum {
NUM_MULTICHOICE_OPTIONS = 16,
// 50 actual lines and 15 for spacing
NUM_LINELISTER_LINES = 50,
NUM_LINELISTER_LINES_TOTAL = NUM_LINELISTER_LINES + 15,
NUM_PAGE_WIDGETS = 10,
};
class CPlaceableText
{
public:
CVector2D m_position;
CRGBA m_color;
wchar *m_text;
CPlaceableText(void)
: m_position(0.0f, 0.0f), m_color(255, 255, 255, 255) {}
void SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }
void SetColor(const CRGBA &color) { m_color = color; }
CRGBA GetColor(void) { return m_color; }
void SetAlpha(uint8 alpha) { m_color.alpha = alpha; }
};
// No trace of this in the game but it makes the other classes simpler
class CPlaceableTextTwoLines
{
public:
CPlaceableText m_line1;
CPlaceableText m_line2;
void SetColor(const CRGBA &color) { m_line1.SetColor(color); m_line2.SetColor(color); }
void SetAlpha(uint8 alpha) { m_line1.SetAlpha(alpha); m_line2.SetAlpha(alpha); }
};
// No trace of this in the game but it makes the other classes simpler
class CShadowInfo
{
public:
bool m_bRightJustify;
bool m_bDropShadow;
CRGBA m_shadowColor;
CVector2D m_shadowOffset;
CShadowInfo(void)
: m_bRightJustify(false), m_bDropShadow(false),
m_shadowColor(255, 255, 255, 255),
m_shadowOffset(-1.0f, -1.0f) {}
CRGBA GetShadowColor(void) { return m_shadowColor; }
void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset){
m_bDropShadow = bDropShadows;
m_shadowColor = shadowColor;
m_shadowOffset = shadowOffset;
}
};
// No trace of this in the game but it makes the other classes simpler
class CSelectable
{
public:
bool m_bSelected;
CRGBA m_selectedColor;
CSelectable(void) : m_bSelected(false) {}
CRGBA GetSelectedColor(void) { return m_selectedColor; }
};
class CPlaceableShText : public CPlaceableText, public CShadowInfo
{
public:
using CPlaceableText::SetPosition;
void SetPosition(float x, float y, bool bRightJustify) { SetPosition(x, y); m_bRightJustify = bRightJustify; }
void SetAlpha(uint8 alpha) { m_shadowColor.alpha = alpha; CPlaceableText::SetAlpha(alpha); }
void Draw(float x, float y);
void Draw(const CRGBA &color, float x, float y);
// unused arguments it seems
void DrawShWrap(float x, float y, float wrapX, float wrapY) { Draw(x, y); }
};
class CPlaceableShTextTwoLines : public CPlaceableTextTwoLines, public CShadowInfo
{
public:
void SetAlpha(uint8 alpha) { m_shadowColor.alpha = alpha; CPlaceableTextTwoLines::SetAlpha(alpha); }
void Draw(float x, float y);
void Draw(const CRGBA &color, float x, float y);
};
class CPlaceableShOption : public CPlaceableShText, public CSelectable
{
public:
void SetColors(const CRGBA &normal, const CRGBA &selection) { CPlaceableShText::SetColor(normal); m_selectedColor = selection; }
void SetAlpha(uint8 alpha) { m_selectedColor.alpha = alpha; CPlaceableShText::SetAlpha(alpha); }
using CPlaceableShText::Draw;
void Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight);
};
class CPlaceableShOptionTwoLines : public CPlaceableShTextTwoLines, public CSelectable
{
public:
void SetColors(const CRGBA &normal, const CRGBA &selection) { CPlaceableShTextTwoLines::SetColor(normal); m_selectedColor = selection; }
void SetAlpha(uint8 alpha) { m_selectedColor.alpha = alpha; CPlaceableShTextTwoLines::SetAlpha(alpha); }
using CPlaceableShTextTwoLines::Draw;
void Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight);
};
class CPlaceableSprite
{
public:
CSprite2d *m_pSprite;
CVector2D m_position;
CVector2D m_size;
CRGBA m_color;
CPlaceableSprite(void)
: m_pSprite(nil), m_position(0.0f, 0.0f),
m_size(0.0f, 0.0f), m_color(255, 255, 255, 255) {}
void SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }
void SetAlpha(uint8 alpha) { m_color.alpha = alpha; }
void Draw(float x, float y);
void Draw(const CRGBA &color, float x, float y);
};
class CPlaceableShSprite
{
public:
CPlaceableSprite m_sprite;
CPlaceableSprite m_shadow;
bool m_bDropShadow;
CPlaceableShSprite(void) : m_bDropShadow(false) {}
void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset){
m_bDropShadow = bDropShadows;
m_shadow.m_color = shadowColor;
m_shadow.m_position = shadowOffset;
}
void SetAlpha(uint8 alpha) { m_sprite.SetAlpha(alpha); m_shadow.SetAlpha(alpha); }
void Draw(float x, float y);
};
class CMenuBase
{
public:
CVector2D m_position;
bool m_bTwoState;
CMenuBase(void)
: m_position(0.0f, 0.0f), m_bTwoState(false) {}
void SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y) = 0;
virtual void DrawNormal(float x, float y) = 0;
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y) = 0;
virtual void SetAlpha(uint8 alpha) = 0;
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset) = 0;
virtual bool GoNext(void) = 0;
virtual bool GoPrev(void) = 0;
virtual bool GoDown(void) = 0;
virtual bool GoUp(void) = 0;
virtual bool GoDownStill(void) = 0;
virtual bool GoUpStill(void) = 0;
virtual bool GoLeft(void) = 0;
virtual bool GoRight(void) = 0;
virtual bool GoLeftStill(void) = 0;
virtual bool GoRightStill(void) = 0;
virtual bool GoFirst(void) = 0;
virtual bool GoLast(void) = 0;
virtual void SelectCurrentOptionUnderCursor(void) = 0;
virtual void SelectDefaultCancelAction(void) = 0;
virtual void ActivateMenu(bool first) = 0;
virtual void DeactivateMenu(void) = 0;
virtual int GetMenuSelection(void) = 0;
virtual void SetMenuSelection(int selection) = 0;
};
class CMenuDummy : public CMenuBase
{
public:
bool m_bActive;
virtual void Draw(const CRGBA &, const CRGBA &, float x, float y) {}
virtual void DrawNormal(float x, float y) {}
virtual void DrawHighlighted(const CRGBA &, float x, float y) {}
virtual void SetAlpha(uint8 alpha) {}
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset) {}
virtual bool GoNext(void) { DeactivateMenu(); return false; }
virtual bool GoPrev(void) { DeactivateMenu(); return false; }
virtual bool GoDown(void) { return GoNext(); }
virtual bool GoUp(void) { return GoPrev(); }
virtual bool GoDownStill(void) { return false; }
virtual bool GoUpStill(void) { return false; }
virtual bool GoLeft(void) { return true; }
virtual bool GoRight(void) { return true; }
virtual bool GoLeftStill(void) { return true; }
virtual bool GoRightStill(void) { return true; }
virtual bool GoFirst(void) { ActivateMenu(true); return true; }
virtual bool GoLast(void) { ActivateMenu(true); return true; }
virtual void SelectCurrentOptionUnderCursor(void) {}
virtual void SelectDefaultCancelAction(void) {}
virtual void ActivateMenu(bool first) { m_bActive = true; }
virtual void DeactivateMenu(void) { m_bActive = false; }
virtual int GetMenuSelection(void) { return -1; }
virtual void SetMenuSelection(int) {}
};
class CMenuPictureAndText : public CMenuBase
{
public:
int m_numSprites;
CPlaceableShSprite m_sprites[5];
int m_numTexts;
CPlaceableShText m_texts[20];
CVector2D m_oldTextScale;
CVector2D m_textScale;
bool m_bSetTextScale;
float m_wrapX;
float m_oldWrapx;
bool m_bWrap;
// missing some?
CMenuPictureAndText(void)
: m_numSprites(0), m_numTexts(0),
m_bSetTextScale(false), m_bWrap(false) {}
void SetNewOldShadowWrapX(bool bWrapX, float newWrapX, float oldWrapX);
void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale);
void SetTextsColor(const CRGBA &color);
void AddText(wchar *text, float positionX, float positionY, const CRGBA &color, bool bRightJustify);
void AddPicture(CSprite2d *sprite, CSprite2d *shadow, float positionX, float positionY, float width, float height, const CRGBA &color);
void AddPicture(CSprite2d *sprite, float positionX, float positionY, float width, float height, const CRGBA &color);
virtual void Draw(const CRGBA &, const CRGBA &, float x, float y);
virtual void DrawNormal(float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
virtual void DrawHighlighted(const CRGBA &, float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
virtual void SetAlpha(uint8 alpha);
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
virtual bool GoNext(void) { return false; }
virtual bool GoPrev(void) { return false; }
virtual bool GoDown(void) { return GoNext(); }
virtual bool GoUp(void) { return GoPrev(); }
virtual bool GoDownStill(void) { return false; }
virtual bool GoUpStill(void) { return false; }
virtual bool GoLeft(void) { return true; }
virtual bool GoRight(void) { return true; }
virtual bool GoLeftStill(void) { return true; }
virtual bool GoRightStill(void) { return true; }
virtual bool GoFirst(void) { return false; }
virtual bool GoLast(void) { return false; }
virtual void SelectCurrentOptionUnderCursor(void) {}
virtual void SelectDefaultCancelAction(void) {}
virtual void ActivateMenu(bool first) {}
virtual void DeactivateMenu(void) {}
virtual int GetMenuSelection(void) { return -1; }
virtual void SetMenuSelection(int) {}
};
class CMenuMultiChoice : public CMenuBase
{
public:
int m_numOptions;
CPlaceableShText m_title;
CPlaceableShOption m_options[NUM_MULTICHOICE_OPTIONS];
int m_cursor;
CVector2D m_oldTextScale;
CVector2D m_textScale;
bool m_bSetTextScale;
bool m_bSetTitleTextScale;
CMenuMultiChoice(void)
: m_numOptions(0), m_cursor(-1),
m_bSetTextScale(false), m_bSetTitleTextScale(false) {}
void AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify);
CPlaceableShOption *AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify);
void SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected);
void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual void DrawNormal(float x, float y);
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
virtual void SetAlpha(uint8 alpha);
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
virtual bool GoNext(void);
virtual bool GoPrev(void);
virtual bool GoDown(void) { return GoNext(); }
virtual bool GoUp(void) { return GoPrev(); }
virtual bool GoDownStill(void) { return false; }
virtual bool GoUpStill(void) { return false; }
virtual bool GoLeft(void) { return GoPrev(); }
virtual bool GoRight(void) { return GoNext(); }
virtual bool GoLeftStill(void) { return true; }
virtual bool GoRightStill(void) { return true; }
virtual bool GoFirst(void) { m_cursor = 0; return true; }
virtual bool GoLast(void) { m_cursor = m_numOptions-1; return true; }
virtual void SelectCurrentOptionUnderCursor(void);
virtual void SelectDefaultCancelAction(void) {}
virtual void ActivateMenu(bool first) { m_cursor = first ? 0 : m_numOptions-1; }
virtual void DeactivateMenu(void) { m_cursor = -1; }
virtual int GetMenuSelection(void);
virtual void SetMenuSelection(int selection);
};
class CMenuMultiChoiceTriggered : public CMenuMultiChoice
{
public:
typedef void (*Trigger)(CMenuMultiChoiceTriggered *);
Trigger m_triggers[NUM_MULTICHOICE_OPTIONS];
Trigger m_defaultCancel;
CMenuMultiChoiceTriggered(void) { Initialise(); }
void Initialise(void);
CPlaceableShOption *AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify);
virtual void SelectCurrentOptionUnderCursor(void);
virtual void SelectDefaultCancelAction(void);
};
class CMenuMultiChoiceTriggeredAlways : public CMenuMultiChoiceTriggered
{
public:
Trigger m_alwaysNormalTrigger;
Trigger m_alwaysHighlightTrigger;
Trigger m_alwaysTrigger;
CMenuMultiChoiceTriggeredAlways(void)
: m_alwaysNormalTrigger(nil), m_alwaysHighlightTrigger(nil), m_alwaysTrigger(nil) {}
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual void DrawNormal(float x, float y);
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
};
class CMenuMultiChoicePictured : public CMenuMultiChoice
{
public:
CPlaceableSprite m_sprites[NUM_MULTICHOICE_OPTIONS];
bool m_bHasSprite[NUM_MULTICHOICE_OPTIONS];
CMenuMultiChoicePictured(void) { Initialise(); }
void Initialise(void);
using CMenuMultiChoice::AddOption;
CPlaceableShOption *AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, bool bSelected);
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual void DrawNormal(float x, float y);
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
virtual void SetAlpha(uint8 alpha);
// unnecessary - same as base class
// virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
};
class CMenuMultiChoicePicturedTriggered : public CMenuMultiChoicePictured
{
public:
typedef void (*Trigger)(CMenuMultiChoicePicturedTriggered *);
Trigger m_triggers[NUM_MULTICHOICE_OPTIONS];
Trigger m_defaultCancel;
CMenuMultiChoicePicturedTriggered(void) { Initialise(); }
void Initialise(void);
using CMenuMultiChoicePictured::AddOption;
CPlaceableShOption *AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected);
virtual void SelectCurrentOptionUnderCursor(void);
virtual void SelectDefaultCancelAction(void);
};
struct FEC_MOVETAB
{
int8 right;
int8 left;
int8 down;
int8 up;
};
class CMenuMultiChoicePicturedTriggeredAnyMove : public CMenuMultiChoicePicturedTriggered
{
public:
FEC_MOVETAB m_moveTab[NUM_MULTICHOICE_OPTIONS];
CMenuMultiChoicePicturedTriggeredAnyMove(void) { Initialise(); }
void Initialise(void);
using CMenuMultiChoicePicturedTriggered::AddOption;
CPlaceableShOption *AddOption(CSprite2d *sprite, FEC_MOVETAB *moveTab, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected);
virtual bool GoDown(void);
virtual bool GoUp(void);
virtual bool GoLeft(void);
virtual bool GoRight(void);
};
// copy of CMenuMultiChoice pretty much except for m_options type
class CMenuMultiChoiceTwoLines : public CMenuBase
{
public:
int m_numOptions;
CPlaceableShText m_title;
CPlaceableShOptionTwoLines m_options[NUM_MULTICHOICE_OPTIONS];
int m_cursor;
CVector2D m_oldTextScale;
CVector2D m_textScale;
bool m_bSetTextScale;
bool m_bSetTitleTextScale;
CMenuMultiChoiceTwoLines(void)
: m_numOptions(0), m_cursor(-1),
m_bSetTextScale(false), m_bSetTitleTextScale(false) {}
void AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify);
CPlaceableShOptionTwoLines *AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify);
CPlaceableShOptionTwoLines *AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, bool bSelected, bool bRightJustify);
void SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected);
void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual void DrawNormal(float x, float y);
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
virtual void SetAlpha(uint8 alpha);
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
virtual bool GoNext(void);
virtual bool GoPrev(void);
virtual bool GoDown(void) { return GoNext(); }
virtual bool GoUp(void) { return GoPrev(); }
virtual bool GoDownStill(void) { return true; }
virtual bool GoUpStill(void) { return true; }
virtual bool GoLeft(void) { return GoPrev(); }
virtual bool GoRight(void) { return GoNext(); }
virtual bool GoLeftStill(void) { return true; }
virtual bool GoRightStill(void) { return true; }
virtual bool GoFirst(void) { m_cursor = 0; return true; }
virtual bool GoLast(void) { m_cursor = m_numOptions-1; return true; }
virtual void SelectCurrentOptionUnderCursor(void);
virtual void SelectDefaultCancelAction(void) {}
virtual void ActivateMenu(bool first) { m_cursor = first ? 0 : m_numOptions-1; }
virtual void DeactivateMenu(void) { m_cursor = -1; }
virtual int GetMenuSelection(void);
virtual void SetMenuSelection(int selection);
};
// copy of CMenuMultiChoiceTriggered except for m_options
class CMenuMultiChoiceTwoLinesTriggered : public CMenuMultiChoiceTwoLines
{
public:
typedef void (*Trigger)(CMenuMultiChoiceTwoLinesTriggered *);
Trigger m_triggers[NUM_MULTICHOICE_OPTIONS];
Trigger m_defaultCancel;
CMenuMultiChoiceTwoLinesTriggered(void) { Initialise(); }
void Initialise(void);
CPlaceableShOptionTwoLines *AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify);
CPlaceableShOptionTwoLines *AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, Trigger trigger, bool bSelected, bool bRightJustify);
virtual void SelectCurrentOptionUnderCursor(void);
virtual void SelectDefaultCancelAction(void);
};
class CMenuOnOff : public CMenuBase
{
public:
CPlaceableShOption m_title;
CPlaceableShText m_options[2];
bool m_bActive;
bool m_bSetTextScale;
bool m_bSetTitleTextScale;
CVector2D m_textScale;
CVector2D m_oldTextScale;
int m_type; // 0: on/off 1: yes/no
void SetColors(const CRGBA &title, const CRGBA &options);
void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);
void SetOptionPosition(float x, float y, bool bRightJustify);
void AddTitle(wchar *text, bool bSelected, float positionX, float positionY, bool bRightJustify);
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual void DrawNormal(float x, float y);
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
virtual void SetAlpha(uint8 alpha);
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
virtual bool GoNext(void) { DeactivateMenu(); return false; }
virtual bool GoPrev(void) { DeactivateMenu(); return false; }
virtual bool GoDown(void) { return GoNext(); }
virtual bool GoUp(void) { return GoPrev(); }
virtual bool GoDownStill(void) { return false; }
virtual bool GoUpStill(void) { return false; }
virtual bool GoLeft(void) { SelectCurrentOptionUnderCursor(); return true; }
virtual bool GoRight(void) { SelectCurrentOptionUnderCursor(); return true; }
virtual bool GoLeftStill(void) { return true; }
virtual bool GoRightStill(void) { return true; }
virtual bool GoFirst(void) { ActivateMenu(true); return true; }
virtual bool GoLast(void) { ActivateMenu(true); return true; }
virtual void SelectCurrentOptionUnderCursor(void) { m_title.m_bSelected ^= 1; }
virtual void SelectDefaultCancelAction(void) {}
virtual void ActivateMenu(bool first) { m_bActive = true; }
virtual void DeactivateMenu(void) { m_bActive = false; }
virtual int GetMenuSelection(void) { return m_title.m_bSelected; }
virtual void SetMenuSelection(int selection) { m_title.m_bSelected = selection; }
};
class CMenuOnOffTriggered : public CMenuOnOff
{
public:
typedef void (*Trigger)(CMenuOnOffTriggered *);
Trigger m_trigger;
void SetOptionPosition(float x, float y, Trigger trigger, bool bRightJustify);
virtual void SelectCurrentOptionUnderCursor(void);
};
class CMenuSlider : public CMenuBase
{
public:
CPlaceableShText m_title;
CPlaceableShText m_box; // not really a text
CRGBA m_colors[2]; // left and right
CVector2D m_size[2]; // left and right
int m_value;
CPlaceableShText m_percentageText;
bool m_bDrawPercentage;
// char field_8D;
// char field_8E;
// char field_8F;
uint8 m_someAlpha;
// char field_91;
// char field_92;
// char field_93;
bool m_bActive;
int m_style;
static char Buf8[8];
static wchar Buf16[8];
CMenuSlider(void)
: m_value(0), m_bDrawPercentage(false), m_bActive(false), m_style(0) {}
void SetColors(const CRGBA &title, const CRGBA &percentage, const CRGBA &left, const CRGBA &right);
void DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &selCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor);
void DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor);
void AddTickBox(float positionX, float positionY, float width, float heigthLeft, float heightRight);
void AddTitle(wchar *text, float positionX, float positionY);
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual void DrawNormal(float x, float y);
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
virtual void SetAlpha(uint8 alpha);
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
virtual bool GoNext(void) { DeactivateMenu(); return false; }
virtual bool GoPrev(void) { DeactivateMenu(); return false; }
virtual bool GoDown(void) { return GoNext(); }
virtual bool GoUp(void) { return GoPrev(); }
virtual bool GoDownStill(void) { return false; }
virtual bool GoUpStill(void) { return false; }
virtual bool GoLeft(void) { if(m_value < 0) m_value = 0; return true; }
virtual bool GoRight(void) { if(m_value > 1000) m_value = 1000; return true; }
virtual bool GoLeftStill(void) { m_value -= 8; if(m_value < 0) m_value = 0; return true; }
virtual bool GoRightStill(void) { m_value += 8; if(m_value > 1000) m_value = 1000; return true; }
virtual bool GoFirst(void) { ActivateMenu(true); return true; }
virtual bool GoLast(void) { ActivateMenu(true); return true; }
virtual void SelectCurrentOptionUnderCursor(void) {}
virtual void SelectDefaultCancelAction(void) {}
virtual void ActivateMenu(bool first) { m_bActive = true; }
virtual void DeactivateMenu(void) { m_bActive = false; }
virtual int GetMenuSelection(void) { return m_value/10; }
virtual void SetMenuSelection(int selection) { m_value = selection*10; }
};
class CMenuSliderTriggered : public CMenuSlider
{
public:
typedef void (*Trigger)(CMenuSliderTriggered *);
Trigger m_trigger;
Trigger m_alwaysTrigger;
CMenuSliderTriggered(void)
: m_trigger(nil), m_alwaysTrigger(nil) {}
void AddTickBox(float positionX, float positionY, float width, float heigthLeft, float heightRight, Trigger trigger, Trigger alwaysTrigger);
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual bool GoLeft(void);
virtual bool GoRight(void);
virtual bool GoLeftStill(void);
virtual bool GoRightStill(void);
};
class CMenuLineLister : public CMenuBase
{
public:
float m_width;
float m_height;
int m_numLines;
CPlaceableShText m_linesLeft[NUM_LINELISTER_LINES_TOTAL];
CPlaceableShText m_linesRight[NUM_LINELISTER_LINES_TOTAL];
uint8 m_lineAlphas[NUM_LINELISTER_LINES_TOTAL];
int8 m_lineFade[NUM_LINELISTER_LINES_TOTAL];
float m_scrollPosition;
float m_scrollSpeed;
int field_10E8;
float m_lineSpacing;
CMenuLineLister(void);
void SetLinesColor(const CRGBA &color);
void ResetNumberOfTextLines(void);
bool AddTextLine(wchar *left, wchar *right);
CPlaceableShText *GetLeftLine(int i) { return &m_linesLeft[(i%NUM_LINELISTER_LINES) + 15]; };
CPlaceableShText *GetRightLine(int i) { return &m_linesRight[(i%NUM_LINELISTER_LINES) + 15]; };
virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
virtual void DrawNormal(float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
virtual void SetAlpha(uint8 alpha);
virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
virtual bool GoNext(void) { return false; }
virtual bool GoPrev(void) { return false; }
virtual bool GoDown(void) { return GoNext(); }
virtual bool GoUp(void) { return GoPrev(); }
virtual bool GoDownStill(void) { m_scrollSpeed = 0.0f; return true; }
virtual bool GoUpStill(void) { m_scrollSpeed *= 6.0f; return true; }
virtual bool GoLeft(void) { return true; }
virtual bool GoRight(void) { return true; }
virtual bool GoLeftStill(void) { return true; }
virtual bool GoRightStill(void) { return true; }
virtual bool GoFirst(void) { return true; }
virtual bool GoLast(void) { return true; }
virtual void SelectCurrentOptionUnderCursor(void) {}
virtual void SelectDefaultCancelAction(void) {}
virtual void ActivateMenu(bool first) {}
virtual void DeactivateMenu(void) {}
virtual int GetMenuSelection(void) { return -1; }
virtual void SetMenuSelection(int selection) {}
};
class CMenuPage
{
public:
CMenuBase *m_controls[NUM_PAGE_WIDGETS];
int m_numControls;
CMenuBase *m_pCurrentControl;
int m_cursor;
CMenuPage(void) { Initialise(); }
void Initialise(void);
bool AddMenu(CMenuBase *widget);
bool IsActiveMenuTwoState(void);
void ActiveMenuTwoState_SelectNextPosition(void);
void Draw(const CRGBA &,const CRGBA &, float, float);
void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
void DrawNormal(float x, float y);
void ActivatePage(void);
void SetAlpha(uint8 alpha);
void SetShadows(bool, const CRGBA &, const CVector2D &);
void GoPrev(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoPrev()) m_pCurrentControl->GoLast(); } }
void GoNext(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoNext()) m_pCurrentControl->GoFirst(); } }
void GoLeft(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoLeft()) m_pCurrentControl->GoLast(); } }
void GoRight(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoRight()) m_pCurrentControl->GoFirst(); } }
void GoUp(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoUp()) m_pCurrentControl->GoLast(); } }
void GoDown(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoDown()) m_pCurrentControl->GoFirst(); } }
void GoLeftStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoLeftStill(); }
void GoRightStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoRightStill(); }
void GoUpStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoUpStill(); }
void GoDownStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoDownStill(); }
void SelectDefaultCancelAction(void) { if(m_pCurrentControl) m_pCurrentControl->SelectDefaultCancelAction(); }
void SelectCurrentOptionUnderCursor(void) { if(m_pCurrentControl) m_pCurrentControl->SelectCurrentOptionUnderCursor(); }
virtual void GoUpMenuOnPage(void);
virtual void GoDownMenuOnPage(void);
virtual void GoLeftMenuOnPage(void);
virtual void GoRightMenuOnPage(void);
};
class CMenuPageAnyMove : public CMenuPage
{
public:
FEC_MOVETAB m_moveTab[NUM_PAGE_WIDGETS];
CMenuPageAnyMove(void) { Initialise(); }
void Initialise(void);
using CMenuPage::AddMenu;
bool AddMenu(CMenuBase *widget, FEC_MOVETAB *moveTab);
virtual void GoUpMenuOnPage(void);
virtual void GoDownMenuOnPage(void);
virtual void GoLeftMenuOnPage(void);
virtual void GoRightMenuOnPage(void);
};

File diff suppressed because it is too large Load Diff

View File

@ -7,27 +7,10 @@
#define MENUHEADER_WIDTH 0.84f #define MENUHEADER_WIDTH 0.84f
#define MENUHEADER_HEIGHT 1.6f #define MENUHEADER_HEIGHT 1.6f
#define MENUACTION_X_MARGIN 40.0f #define MENU_X_MARGIN 40.0f
#define MENUACTION_POS_Y 60.0f #define MENUACTION_POS_Y 60.0f
#define MENUACTION_WIDTH 0.405f #define MENUACTION_WIDTH 38.0f
#define MENUACTION_HEIGHT 0.63f #define MENUACTION_SCALE_MULT 0.9f
#define MENUCOLUMN_POS_X MENUHEADER_POS_X + 16.0f
#define MENUCOLUMN_MAX_Y 149.0f
#define MENUCOLUMN_MID_Y 100.0f
#define MENUCOLUMN_MIN_Y 110.0f
#define MENUCOLUMN_PAUSE_Y 25.0f
#define MENUCOLUMN_START_Y 9.0f
#define MENUCOLUMN_FEDS 139.0f
#define MENUCOLUMN_SAVE_X 121.0f
#define MENUCOLUMN_SAVE_Y 111.0f
#define MENUCOLUMN_SPACING_MAX 24.0f
#define MENUCOLUMN_SPACING_MIN 20.0f
#define MENUSELECT_BOX_MAX 20.5f
#define MENUSELECT_BOX_MIN 17.0f
#ifndef ASPECT_RATIO_SCALE #ifndef ASPECT_RATIO_SCALE
#define MENURADIO_ICON_X 31.5f #define MENURADIO_ICON_X 31.5f
@ -38,12 +21,63 @@
#define MENURADIO_ICON_W 60.0f #define MENURADIO_ICON_W 60.0f
#define MENURADIO_ICON_H 60.0f #define MENURADIO_ICON_H 60.0f
#define MENUDROP_COLOR_A 150
#define MENUDROP_COLOR_SIZE -1
#define MENUSLIDER_X 256.0f #define MENUSLIDER_X 256.0f
#define MENUSLIDER_UNK 256.0f #define MENUSLIDER_UNK 256.0f
#define BIGTEXT_X_SCALE 0.75f
#define BIGTEXT_Y_SCALE 0.9f
#define MEDIUMTEXT_X_SCALE 0.55f
#define MEDIUMTEXT_Y_SCALE 0.8f
#define SMALLTEXT_X_SCALE 0.45f
#define SMALLTEXT_Y_SCALE 0.7f
#define SMALLESTTEXT_X_SCALE 0.4f
#define SMALLESTTEXT_Y_SCALE 0.6f
#define PLAYERSETUP_LIST_TOP 28.0f
#define PLAYERSETUP_LIST_BOTTOM 125.0f
#define PLAYERSETUP_LIST_LEFT 200.0f
#define PLAYERSETUP_LIST_RIGHT 36.0f
#ifdef FIX_BUGS // See the scrollbar button drawing code
#define PLAYERSETUP_SCROLLBAR_WIDTH 19.0f
#else
#define PLAYERSETUP_SCROLLBAR_WIDTH 16.0f
#endif
#define PLAYERSETUP_SCROLLBUTTON_HEIGHT 17.0f
#define PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION 64
#define PLAYERSETUP_ROW_TEXT_X_SCALE 0.4f
#define PLAYERSETUP_ROW_TEXT_Y_SCALE 0.6f
#define PLAYERSETUP_SKIN_COLUMN_LEFT 220.0f
#define PLAYERSETUP_DATE_COLUMN_RIGHT 56.0f
#define PLAYERSETUP_LIST_BODY_TOP 47
#define PLAYERSETUP_ROW_HEIGHT 9
#define STATS_SLIDE_Y_PER_SECOND 30.0f
#define STATS_ROW_HEIGHT 20.0f
#define STATS_ROW_X_MARGIN 50.0f
#define STATS_BOTTOM_MARGIN 135.0f
#define STATS_TOP_MARGIN 40.0f
#define STATS_TOP_DIMMING_AREA_LENGTH (93.0f - STATS_TOP_MARGIN)
#define STATS_BOTTOM_DIMMING_AREA_LENGTH 55.0f
#define STATS_PUT_BACK_TO_BOTTOM_Y 50.0f
#define STATS_RATING_X 24.0f
#define STATS_RATING_Y 20.0f
#define CONTSETUP_STANDARD_ROW_HEIGHT 10.7f
#define CONTSETUP_CLASSIC_ROW_HEIGHT 9.0f
#define CONTSETUP_BOUND_HIGHLIGHT_HEIGHT 10
#define CONTSETUP_BOUND_COLUMN_WIDTH 190.0f
#define CONTSETUP_LIST_HEADER_HEIGHT 20.0f
#define CONTSETUP_LIST_TOP 28.0f
#define CONTSETUP_LIST_RIGHT 18.0f
#define CONTSETUP_LIST_BOTTOM 120.0f
#define CONTSETUP_LIST_LEFT 18.0f
#define CONTSETUP_COLUMN_1_X 40.0f
#define CONTSETUP_COLUMN_2_X 210.0f
#define CONTSETUP_COLUMN_3_X (CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH + 10.0f)
#define CONTSETUP_BACK_RIGHT 35.0f
#define CONTSETUP_BACK_BOTTOM 122.0f
#define CONTSETUP_BACK_HEIGHT 25.0f
enum eLanguages enum eLanguages
{ {
LANGUAGE_AMERICAN, LANGUAGE_AMERICAN,
@ -87,6 +121,8 @@ enum eFrontendSprites
FE_RADIO7, FE_RADIO7,
FE_RADIO8, FE_RADIO8,
FE_RADIO9, FE_RADIO9,
NUM_FE_SPRITES
}; };
enum eMenuSprites enum eMenuSprites
@ -110,6 +146,8 @@ enum eMenuSprites
MENUSPRITE_UPOFF, MENUSPRITE_UPOFF,
MENUSPRITE_UPON, MENUSPRITE_UPON,
MENUSPRITE_GTA3LOGO, MENUSPRITE_GTA3LOGO,
MENUSPRITE_UNUSED,
NUM_MENU_SPRITES
}; };
enum eSaveSlot enum eSaveSlot
@ -127,6 +165,22 @@ enum eSaveSlot
SAVESLOT_LABEL = 36 SAVESLOT_LABEL = 36
}; };
#ifdef MENU_MAP
enum MapSprites
{
MAPMID1,
MAPMID2,
MAPMID3,
MAPBOT1,
MAPBOT2,
MAPBOT3,
MAPTOP1,
MAPTOP2,
MAPTOP3,
NUM_MAP_SPRITES
};
#endif
enum eMenuScreen enum eMenuScreen
{ {
MENUPAGE_DISABLED = -1, MENUPAGE_DISABLED = -1,
@ -143,19 +197,19 @@ enum eMenuScreen
MENUPAGE_NEW_GAME_RELOAD = 10, MENUPAGE_NEW_GAME_RELOAD = 10,
MENUPAGE_LOAD_SLOT_CONFIRM = 11, MENUPAGE_LOAD_SLOT_CONFIRM = 11,
MENUPAGE_DELETE_SLOT_CONFIRM = 12, MENUPAGE_DELETE_SLOT_CONFIRM = 12,
MENUPAGE_13 = 13, MENUPAGE_NO_MEMORY_CARD = 13, // hud adjustment page in mobile
MENUPAGE_LOADING_IN_PROGRESS = 14, MENUPAGE_LOADING_IN_PROGRESS = 14,
MENUPAGE_DELETING_IN_PROGRESS = 15, MENUPAGE_DELETING_IN_PROGRESS = 15,
MENUPAGE_16 = 16, MENUPAGE_PS2_LOAD_FAILED = 16,
MENUPAGE_DELETE_FAILED = 17, MENUPAGE_DELETE_FAILED = 17,
MENUPAGE_DEBUG_MENU = 18, MENUPAGE_DEBUG_MENU = 18,
MENUPAGE_MEMORY_CARD_1 = 19, MENUPAGE_MEMORY_CARD_DEBUG = 19,
MENUPAGE_MEMORY_CARD_2 = 20, MENUPAGE_MEMORY_CARD_TEST = 20,
MENUPAGE_MULTIPLAYER_MAIN = 21, MENUPAGE_MULTIPLAYER_MAIN = 21,
MENUPAGE_SAVE_FAILED_1 = 22, MENUPAGE_PS2_SAVE_FAILED = 22,
MENUPAGE_SAVE_FAILED_2 = 23, MENUPAGE_PS2_SAVE_FAILED_2 = 23,
MENUPAGE_SAVE = 24, MENUPAGE_SAVE = 24,
MENUPAGE_NO_MEMORY_CARD = 25, MENUPAGE_NO_MEMORY_CARD_2 = 25,
MENUPAGE_CHOOSE_SAVE_SLOT = 26, MENUPAGE_CHOOSE_SAVE_SLOT = 26,
MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27, MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27,
MENUPAGE_MULTIPLAYER_MAP = 28, MENUPAGE_MULTIPLAYER_MAP = 28,
@ -187,8 +241,11 @@ enum eMenuScreen
MENUPAGE_SKIN_SELECT = 54, MENUPAGE_SKIN_SELECT = 54,
MENUPAGE_KEYBOARD_CONTROLS = 55, MENUPAGE_KEYBOARD_CONTROLS = 55,
MENUPAGE_MOUSE_CONTROLS = 56, MENUPAGE_MOUSE_CONTROLS = 56,
MENUPAGE_57 = 57, MENUPAGE_57 = 57, // mission failed, wanna restart page in mobile
MENUPAGE_58 = 58, MENUPAGE_58 = 58,
#ifdef MENU_MAP
MENUPAGE_MAP = 59,
#endif
MENUPAGES MENUPAGES
}; };
@ -322,7 +379,7 @@ enum eCheckHover
HOVEROPTION_6, HOVEROPTION_6,
HOVEROPTION_7, HOVEROPTION_7,
HOVEROPTION_8, HOVEROPTION_8,
HOVEROPTION_BACK, // used in controller setup HOVEROPTION_BACK, // also layer in controller setup and skin menu
HOVEROPTION_10, HOVEROPTION_10,
HOVEROPTION_11, HOVEROPTION_11,
HOVEROPTION_OVER_SCROLL_UP, HOVEROPTION_OVER_SCROLL_UP,
@ -332,9 +389,9 @@ enum eCheckHover
HOVEROPTION_HOLDING_SCROLLBAR, HOVEROPTION_HOLDING_SCROLLBAR,
HOVEROPTION_PAGEUP, HOVEROPTION_PAGEUP,
HOVEROPTION_PAGEDOWN, HOVEROPTION_PAGEDOWN,
HOVEROPTION_19, HOVEROPTION_LIST, // also layer in controller setup and skin menu
HOVEROPTION_20, HOVEROPTION_SKIN,
HOVEROPTION_CHANGESKIN, HOVEROPTION_USESKIN, // also layer in controller setup and skin menu
HOVEROPTION_RADIO_0, HOVEROPTION_RADIO_0,
HOVEROPTION_RADIO_1, HOVEROPTION_RADIO_1,
HOVEROPTION_RADIO_2, HOVEROPTION_RADIO_2,
@ -369,13 +426,20 @@ enum eControlMethod
CONTROL_CLASSIC, CONTROL_CLASSIC,
}; };
// Why??
enum ControllerSetupColumn
{
CONTSETUP_PED_COLUMN = 0,
CONTSETUP_VEHICLE_COLUMN = 14,
};
struct tSkinInfo struct tSkinInfo
{ {
int32 field_0; int32 skinId;
char skinName[256]; char skinNameDisplayed[256];
char currSkinName[256]; char skinNameOriginal[256];
char date[256]; char date[256];
tSkinInfo *field_304; tSkinInfo *nextSkin;
}; };
struct BottomBarOption struct BottomBarOption
@ -387,7 +451,7 @@ struct BottomBarOption
struct CMenuScreen struct CMenuScreen
{ {
char m_ScreenName[8]; char m_ScreenName[8];
int32 unk; int32 unk; // 2 on MENUPAGE_MULTIPLAYER_START, 1 on everywhere else
int32 m_PreviousPage[2]; // eMenuScreen int32 m_PreviousPage[2]; // eMenuScreen
int32 m_ParentEntry[2]; // row int32 m_ParentEntry[2]; // row
@ -413,7 +477,7 @@ public:
bool m_bMenuActive; bool m_bMenuActive;
bool m_bMenuStateChanged; bool m_bMenuStateChanged;
bool m_bWaitingForNewKeyBind; bool m_bWaitingForNewKeyBind;
bool m_bStartGameLoading; bool m_bWantToRestart;
bool m_bFirstTime; bool m_bFirstTime;
bool m_bGameNotLoaded; bool m_bGameNotLoaded;
int32 m_nMousePosX; int32 m_nMousePosX;
@ -421,24 +485,24 @@ public:
int32 m_nMouseTempPosX; int32 m_nMouseTempPosX;
int32 m_nMouseTempPosY; int32 m_nMouseTempPosY;
bool m_bShowMouse; bool m_bShowMouse;
tSkinInfo m_sSkin; tSkinInfo m_pSkinListHead;
tSkinInfo *m_pSelectedSkin; tSkinInfo *m_pSelectedSkin;
int32 m_nFirstVisibleRowOnList; int32 m_nFirstVisibleRowOnList;
float m_nCurListItemY; float m_nScrollbarTopMargin;
int32 m_nTotalListRow; int32 m_nTotalListRow;
int32 m_nSkinsTotal; int32 m_nSkinsTotal;
char _unk0[4]; char _unk0[4];
int32 m_nSelectedListRow; int32 m_nSelectedListRow;
bool m_bSkinsFound; bool m_bSkinsEnumerated;
bool m_bQuitGameNoCD; bool m_bQuitGameNoCD;
bool m_bRenderGameInMenu; bool m_bRenderGameInMenu;
bool m_bSaveMenuActive; bool m_bSaveMenuActive;
bool m_bLoadingSavedGame; bool m_bWantToLoad;
char field_455; char field_455;
bool m_bStartWaitingForKeyBind; bool m_bStartWaitingForKeyBind;
bool m_bSpritesLoaded; bool m_bSpritesLoaded;
CSprite2d m_aFrontEndSprites[28]; CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES];
CSprite2d m_aMenuSprites[20]; CSprite2d m_aMenuSprites[NUM_MENU_SPRITES];
int32 field_518; int32 field_518;
int32 m_nMenuFadeAlpha; int32 m_nMenuFadeAlpha;
bool m_bPressedPgUpOnList; bool m_bPressedPgUpOnList;
@ -448,10 +512,10 @@ public:
bool m_bPressedScrollButton; bool m_bPressedScrollButton;
int32 m_CurrCntrlAction; int32 m_CurrCntrlAction;
char _unk1[4]; char _unk1[4];
int32 field_530; int32 m_nSelectedContSetupColumn;
bool m_bKeyIsOK; bool m_bKeyIsOK;
bool field_535; bool field_535;
int8 m_nCurrExLayer; // TODO: What's that? int8 m_nCurrExLayer;
int32 m_nHelperTextAlpha; int32 m_nHelperTextAlpha;
int32 m_nMouseOldPosX; int32 m_nMouseOldPosX;
int32 m_nMouseOldPosY; int32 m_nMouseOldPosY;
@ -468,47 +532,58 @@ public:
bool GetIsMenuActive() {return !!m_bMenuActive;} bool GetIsMenuActive() {return !!m_bMenuActive;}
public: public:
static int32 &OS_Language; static int32 OS_Language;
static int8 &m_PrefsUseVibration; static int8 m_PrefsUseVibration;
static int8 &m_DisplayControllerOnFoot; static int8 m_DisplayControllerOnFoot;
static int8 &m_PrefsUseWideScreen; static int8 m_PrefsUseWideScreen;
static int8 &m_PrefsRadioStation; static int8 m_PrefsRadioStation;
static int8 &m_PrefsVsync; static int8 m_PrefsVsync;
static int8 &m_PrefsVsyncDisp; static int8 m_PrefsVsyncDisp;
static int8 &m_PrefsFrameLimiter; static int8 m_PrefsFrameLimiter;
static int8 &m_PrefsShowSubtitles; static int8 m_PrefsShowSubtitles;
static int8 &m_PrefsSpeakers; static int8 m_PrefsSpeakers;
static int32 &m_ControlMethod; static int32 m_ControlMethod;
static int8 &m_PrefsDMA; static int8 m_PrefsDMA;
static int32 &m_PrefsLanguage; static int32 m_PrefsLanguage;
static int32 &m_PrefsBrightness; static int32 m_PrefsBrightness;
static float &m_PrefsLOD; static float m_PrefsLOD;
static int8 &m_bFrontEnd_ReloadObrTxtGxt; static int8 m_bFrontEnd_ReloadObrTxtGxt;
static int32 &m_PrefsMusicVolume; static int32 m_PrefsMusicVolume;
static int32 &m_PrefsSfxVolume; static int32 m_PrefsSfxVolume;
static char *m_PrefsSkinFile; static char m_PrefsSkinFile[256];
static int32 &m_KeyPressedCode; static int32 m_KeyPressedCode;
static bool &m_bStartUpFrontEndRequested; static bool m_bStartUpFrontEndRequested;
static bool &m_bShutDownFrontEndRequested; static bool m_bShutDownFrontEndRequested;
static bool &m_PrefsAllowNastyGame; static bool m_PrefsAllowNastyGame;
static float &menuXYpadding; static uint8 m_PrefsStereoMono;
static float &actionTextScaleX; static int32 m_SelectedMap;
static float &actionTextScaleY; static int32 m_SelectedGameType;
static int32 &sthWithButtons; static uint8 m_PrefsPlayerRed;
static int32 &sthWithButtons2; static uint8 m_PrefsPlayerGreen;
static uint8 m_PrefsPlayerBlue;
#ifndef MASTER #ifndef MASTER
static bool m_PrefsMarketing; static bool m_PrefsMarketing;
static bool m_PrefsDisableTutorials; static bool m_PrefsDisableTutorials;
#endif // !MASTER #endif // !MASTER
#ifdef MENU_MAP
static bool bMenuMapActive;
static bool bMapMouseShownOnce;
static bool bMapLoaded;
static float fMapSize;
static float fMapCenterY;
static float fMapCenterX;
static CSprite2d m_aMapSprites[NUM_MAP_SPRITES];
void PrintMap();
#endif
public: public:
static void BuildStatLine(char *text, void *stat, uint8 aFloat, void *stat2); static void BuildStatLine(char *text, void *stat, bool itsFloat, void *stat2);
static void CentreMousePointer(); static void CentreMousePointer();
int CheckCodesForControls(int32); void CheckCodesForControls(int);
bool CheckHover(int x1, int x2, int y1, int y2); bool CheckHover(int x1, int x2, int y1, int y2);
void CheckSliderMovement(int); void CheckSliderMovement(int);
int CostructStatLine(int); int CostructStatLine(int);
@ -516,7 +591,7 @@ public:
int DisplaySlider(float, float, float, float, float, float); int DisplaySlider(float, float, float, float, float, float);
void DoSettingsBeforeStartingAGame(); void DoSettingsBeforeStartingAGame();
void Draw(); void Draw();
void DrawControllerBound(int, int, int, uint8); void DrawControllerBound(int32, int32, int32, int8);
void DrawControllerScreenExtraText(int, int, int); void DrawControllerScreenExtraText(int, int, int);
void DrawControllerSetupScreen(); void DrawControllerSetupScreen();
void DrawFrontEnd(); void DrawFrontEnd();
@ -526,13 +601,13 @@ public:
#endif #endif
void DrawPlayerSetupScreen(); void DrawPlayerSetupScreen();
int FadeIn(int alpha); int FadeIn(int alpha);
void FilterOutColorMarkersFromString(uint16, CRGBA &); void FilterOutColorMarkersFromString(wchar*, CRGBA &);
int GetStartOptionsCntrlConfigScreens(); int GetStartOptionsCntrlConfigScreens();
static void InitialiseChangedLanguageSettings(); static void InitialiseChangedLanguageSettings();
void LoadAllTextures(); void LoadAllTextures();
void LoadSettings(); void LoadSettings();
static void MessageScreen(char *); void MessageScreen(const char *);
static void PickNewPlayerColour(); void PickNewPlayerColour();
void PrintBriefs(); void PrintBriefs();
static void PrintErrorMessage(); static void PrintErrorMessage();
void PrintStats(); void PrintStats();
@ -552,6 +627,8 @@ public:
void UnloadTextures(); void UnloadTextures();
void WaitForUserCD(); void WaitForUserCD();
void PrintController(); void PrintController();
int GetNumOptionsCntrlConfigScreens();
int ConstructStatLine(int);
// New (not in function or inlined in the game) // New (not in function or inlined in the game)
void ThingsToDoBeforeLeavingPage(); void ThingsToDoBeforeLeavingPage();
@ -565,4 +642,4 @@ public:
static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error"); static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error");
extern CMenuManager &FrontEndMenuManager; extern CMenuManager FrontEndMenuManager;

View File

@ -89,8 +89,6 @@
#define DEFAULT_VIEWWINDOW (0.7f)
eLevelName &CGame::currLevel = *(eLevelName*)0x941514; eLevelName &CGame::currLevel = *(eLevelName*)0x941514;
bool &CGame::bDemoMode = *(bool*)0x5F4DD0; bool &CGame::bDemoMode = *(bool*)0x5F4DD0;
bool &CGame::nastyGame = *(bool*)0x5F4DD4; bool &CGame::nastyGame = *(bool*)0x5F4DD4;
@ -492,7 +490,7 @@ void CGame::ReInitGameObjectVariables(void)
CParticle::ReloadConfig(); CParticle::ReloadConfig();
CCullZones::ResolveVisibilities(); CCullZones::ResolveVisibilities();
if ( !FrontEndMenuManager.m_bLoadingSavedGame ) if ( !FrontEndMenuManager.m_bWantToLoad )
{ {
CCranes::InitCranes(); CCranes::InitCranes();
CTheScripts::StartTestScript(); CTheScripts::StartTestScript();
@ -566,7 +564,7 @@ void CGame::InitialiseWhenRestarting(void)
TheCamera.Init(); TheCamera.Init();
if ( FrontEndMenuManager.m_bLoadingSavedGame == true ) if ( FrontEndMenuManager.m_bWantToLoad == true )
{ {
RestoreForStartLoad(); RestoreForStartLoad();
CStreaming::LoadScene(TheCamera.GetPosition()); CStreaming::LoadScene(TheCamera.GetPosition());
@ -574,7 +572,7 @@ void CGame::InitialiseWhenRestarting(void)
ReInitGameObjectVariables(); ReInitGameObjectVariables();
if ( FrontEndMenuManager.m_bLoadingSavedGame == true ) if ( FrontEndMenuManager.m_bWantToLoad == true )
{ {
if ( GenericLoad() == true ) if ( GenericLoad() == true )
{ {
@ -593,7 +591,7 @@ void CGame::InitialiseWhenRestarting(void)
ShutDownForRestart(); ShutDownForRestart();
CTimer::Stop(); CTimer::Stop();
CTimer::Initialise(); CTimer::Initialise();
FrontEndMenuManager.m_bLoadingSavedGame = false; FrontEndMenuManager.m_bWantToLoad = false;
ReInitGameObjectVariables(); ReInitGameObjectVariables();
currLevel = LEVEL_INDUSTRIAL; currLevel = LEVEL_INDUSTRIAL;
CCollision::SortOutCollisionAfterLoad(); CCollision::SortOutCollisionAfterLoad();
@ -609,6 +607,9 @@ extern void (*DebugMenuProcess)(void);
void CGame::Process(void) void CGame::Process(void)
{ {
CPad::UpdatePads(); CPad::UpdatePads();
#ifdef GTA_PS2
ProcessTidyUpMemory();
#endif
TheCamera.SetMotionBlurAlpha(0); TheCamera.SetMotionBlurAlpha(0);
if (TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_SNIPER || TheCamera.m_BlurType == MBLUR_NORMAL) if (TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_SNIPER || TheCamera.m_BlurType == MBLUR_NORMAL)
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
@ -695,6 +696,13 @@ void CGame::TidyUpMemory(bool, bool)
#endif #endif
} }
void CGame::ProcessTidyUpMemory(void)
{
#ifdef PS2
// meow
#endif
}
STARTPATCHES STARTPATCHES
InjectHook(0x48BB80, CGame::InitialiseOnceBeforeRW, PATCH_JUMP); InjectHook(0x48BB80, CGame::InitialiseOnceBeforeRW, PATCH_JUMP);
InjectHook(0x48BBA0, CGame::InitialiseRenderWare, PATCH_JUMP); InjectHook(0x48BBA0, CGame::InitialiseRenderWare, PATCH_JUMP);

View File

@ -39,4 +39,5 @@ public:
// NB: these do something on PS2 // NB: these do something on PS2
static void TidyUpMemory(bool, bool); static void TidyUpMemory(bool, bool);
static void DrasticTidyUpMemory(bool); static void DrasticTidyUpMemory(bool);
static void ProcessTidyUpMemory(void);
}; };

View File

@ -1,18 +1,22 @@
#pragma once #pragma once
// There are some missing/wrong entries in here. // TODO: There are some missing/wrong entries in here.
const CMenuScreen aScreens[] = { const CMenuScreen aScreens[] = {
// MENUPAGE_NONE = 0 // MENUPAGE_NONE = 0
{ "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, }, { "", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, },
// MENUPAGE_STATS = 1 - Both PrintStats and Draw were printing the page name, so deleted the string Draw looked for. // MENUPAGE_STATS = 1
{ ""/*"FET_STA"*/, MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2, #ifdef MENU_MAP
{ "FET_STA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 3,
#else
{ "FET_STA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2,
#endif
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_NEW_GAME = 2 // MENUPAGE_NEW_GAME = 2
{ "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, 0, 1, { "FET_SGA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 0, 1,
MENUACTION_CHANGEMENU, "FES_SNG", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, MENUACTION_CHANGEMENU, "FES_SNG", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD,
MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT,
MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
@ -20,12 +24,16 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_BRIEFS = 3 // MENUPAGE_BRIEFS = 3
{ "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, 6, 3, #ifdef MENU_MAP
{ "FET_BRE", 1, MENUPAGE_NONE, MENUPAGE_NONE, 6, 4,
#else
{ "FET_BRE", 1, MENUPAGE_NONE, MENUPAGE_NONE, 6, 3,
#endif
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENU_CONTROLLER_SETTINGS = 4 // MENU_CONTROLLER_SETTINGS = 4
{ "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0, { "FET_CON", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0,
MENUACTION_CTRLCONFIG, "FEC_CCF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, MENUACTION_CTRLCONFIG, "FEC_CCF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS,
MENUACTION_CTRLDISPLAY, "FEC_CDP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, MENUACTION_CTRLDISPLAY, "FEC_CDP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS,
MENUACTION_CTRLVIBRATION, "FEC_VIB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, MENUACTION_CTRLVIBRATION, "FEC_VIB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS,
@ -33,7 +41,7 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_SOUND_SETTINGS = 5 // MENUPAGE_SOUND_SETTINGS = 5
{ "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 1, 1, { "FET_AUD", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 1, 1,
MENUACTION_MUSICVOLUME, "FEA_MUS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, MENUACTION_MUSICVOLUME, "FEA_MUS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
MENUACTION_SFXVOLUME, "FEA_SFX", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, MENUACTION_SFXVOLUME, "FEA_SFX", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
MENUACTION_AUDIOHW, "FEA_3DH", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, MENUACTION_AUDIOHW, "FEA_3DH", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
@ -45,7 +53,7 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_GRAPHICS_SETTINGS = 6 // MENUPAGE_GRAPHICS_SETTINGS = 6
{ "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 2, 2, { "FET_DIS", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 2, 2,
MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
@ -59,7 +67,7 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_LANGUAGE_SETTINGS = 7 // MENUPAGE_LANGUAGE_SETTINGS = 7
{ "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 3, 3, { "FET_LAN", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 3, 3,
MENUACTION_LANG_ENG, "FEL_ENG", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_ENG, "FEL_ENG", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_LANG_FRE, "FEL_FRE", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_FRE, "FEL_FRE", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_NONE,
@ -73,7 +81,7 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_CHOOSE_LOAD_SLOT = 8 // MENUPAGE_CHOOSE_LOAD_SLOT = 8
{ "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 1, 1, { "FET_LG", 1, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 1, 1,
MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM, MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM,
MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM, MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM,
@ -86,7 +94,7 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_CHOOSE_DELETE_SLOT = 9 // MENUPAGE_CHOOSE_DELETE_SLOT = 9
{ "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 2, 2, { "FET_DG", 1, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 2, 2,
MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM, MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM,
MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM, MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM,
@ -99,104 +107,123 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_NEW_GAME_RELOAD = 10 // MENUPAGE_NEW_GAME_RELOAD = 10
{ "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 0, 0, { "FET_NG", 1, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 0, 0,
MENUACTION_LABEL, "FESZ_QR", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FESZ_QR", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NEW_GAME, MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
MENUACTION_NEWGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, MENUACTION_NEWGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD,
}, },
// MENUPAGE_LOAD_SLOT_CONFIRM = 11 // MENUPAGE_LOAD_SLOT_CONFIRM = 11
{ "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, 0, 0, { "FET_LG", 1, MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, 0, 0,
MENUACTION_LABEL, "FESZ_QL", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FESZ_QL", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT,
MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS, MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS,
}, },
// MENUPAGE_DELETE_SLOT_CONFIRM = 12 // MENUPAGE_DELETE_SLOT_CONFIRM = 12
{ "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, { "FET_DG", 1, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0,
MENUACTION_LABEL, "FESZ_QD", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FESZ_QD", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_DELETING, MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_DELETING,
}, },
// MENUPAGE_13 = 13 // MENUPAGE_NO_MEMORY_CARD = 13
{ "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FES_NOC", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
// hud adjustment page in mobile
}, },
// MENUPAGE_LOADING_IN_PROGRESS = 14 // MENUPAGE_LOADING_IN_PROGRESS = 14
{ "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_LG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_LABEL, "FED_LDW", SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM, MENUACTION_LABEL, "FED_LDW", SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM,
}, },
// MENUPAGE_DELETING_IN_PROGRESS = 15 // MENUPAGE_DELETING_IN_PROGRESS = 15
{ "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_DG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_LABEL, "FEDL_WR", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FEDL_WR", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_16 = 16 // MENUPAGE_PS2_LOAD_FAILED = 16
{ "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_LG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_LABEL, "FES_LOE", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FES_LOE", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_DELETE_FAILED = 17 // MENUPAGE_DELETE_FAILED = 17
{ "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_DG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_LABEL, "FES_DEE", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FES_DEE", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
}, },
// MENUPAGE_DEBUG_MENU = 18 // MENUPAGE_DEBUG_MENU = 18
{ "FED_DBG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FED_DBG", 1, MENUPAGE_NONE, MENUPAGE_NONE, 4, 0,
MENUACTION_RELOADIDE, "FED_RID", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_RELOADIPL, "FED_RIP", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_SETDBGFLAG, "FED_DFL", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_PEDROADGROUPS, "FED_SPR", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CARROADGROUPS, "FED_SCR", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_COLLISIONPOLYS, "FED_SCP", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_PARSEHEAP, "FED_PAH", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_SHOWCULL, "FED_SCZ", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_DEBUGSTREAM, "FED_DSR", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_MEMORY_CARD_1 = 19 // MENUPAGE_MEMORY_CARD_DEBUG = 19
{ "FEM_MCM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FEM_MCM", 1, MENUPAGE_NONE, MENUPAGE_NONE, 7, 0,
MENUACTION_REGMEMCARD1, "FEM_RMC", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_TESTFORMATMEMCARD1, "FEM_TFM", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_TESTUNFORMATMEMCARD1, "FEM_TUM", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CREATEROOTDIR, "FEM_CRD", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CREATELOADICONS, "FEM_CLI", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_FILLWITHGUFF, "FEM_FFF", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_SAVEONLYTHEGAME, "FEM_SOG", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_SAVEGAME, "FEM_STG", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_SAVEGAMEUNDERGTA, "FEM_STS", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CREATECOPYPROTECTED, "FEM_CPD", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_MEMORY_CARD_2 = 20 // MENUPAGE_MEMORY_CARD_TEST = 20
{ "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FEM_MC2", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_MULTIPLAYER_MAIN = 21 // MENUPAGE_MULTIPLAYER_MAIN = 21
{ "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_MP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_SAVE_FAILED_1 = 22 // MENUPAGE_PS2_SAVE_FAILED = 22
{ "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "MCDNSP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_SAVE_FAILED_2 = 23 // MENUPAGE_PS2_SAVE_FAILED_2 = 23
{ "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "MCGNSP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// Unused in PC but anyway // Unused in PC but anyway
// MENUPAGE_SAVE = 24 // MENUPAGE_SAVE = 24
#ifdef PS2_SAVE_DIALOG #ifdef PS2_SAVE_DIALOG
{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_CHANGEMENU, "FESZ_SA", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, MENUACTION_CHANGEMENU, "FESZ_SA", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
#else #else
{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_LABEL, "FES_SCG", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FES_SCG", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
#endif #endif
// MENUPAGE_NO_MEMORY_CARD = 25 // MENUPAGE_NO_MEMORY_CARD_2 = 25
{ "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FES_NOC", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_CHOOSE_SAVE_SLOT = 26 // MENUPAGE_CHOOSE_SAVE_SLOT = 26
{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM, MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
@ -209,59 +236,58 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27 // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0,
MENUACTION_LABEL, "FESZ_QO", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FESZ_QO", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS, MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS,
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
}, },
// MENUPAGE_MULTIPLAYER_MAP = 28 // MENUPAGE_MULTIPLAYER_MAP = 28
{ "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_MAP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_MULTIPLAYER_CONNECTION = 29 // MENUPAGE_MULTIPLAYER_CONNECTION = 29
{ "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_CON", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_MULTIPLAYER_FIND_GAME = 30 // MENUPAGE_MULTIPLAYER_FIND_GAME = 30
{ "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_FG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_MULTIPLAYER_MODE = 31 // MENUPAGE_MULTIPLAYER_MODE = 31
{ "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_GT", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_MULTIPLAYER_CREATE = 32 // MENUPAGE_MULTIPLAYER_CREATE = 32
{ "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_HG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_MULTIPLAYER_START = 33 // MENUPAGE_MULTIPLAYER_START = 33
{ "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FEN_STA", 2, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_SKIN_SELECT_OLD = 34 // MENUPAGE_SKIN_SELECT_OLD = 34
{ "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_PS", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_CONTROLLER_PC = 35 // MENUPAGE_CONTROLLER_PC = 35
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0, { "FET_CTL", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0,
MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
MENUACTION_CHANGEMENU, "FET_RDK", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, MENUACTION_CHANGEMENU, "FET_RDK", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS,
MENUACTION_CHANGEMENU, "FET_AMS", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, MENUACTION_CHANGEMENU, "FET_AMS", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_CONTROLLER_PC_OLD1 = 36 // MENUPAGE_CONTROLLER_PC_OLD1 = 36
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 0, 0, { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 0, 0,
MENUACTION_GETKEY, "FEC_PLB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, MENUACTION_GETKEY, "FEC_PLB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1,
MENUACTION_GETKEY, "FEC_CWL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, MENUACTION_GETKEY, "FEC_CWL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1,
MENUACTION_GETKEY, "FEC_CWR", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, MENUACTION_GETKEY, "FEC_CWR", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1,
@ -275,12 +301,12 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_CONTROLLER_PC_OLD2 = 37 // MENUPAGE_CONTROLLER_PC_OLD2 = 37
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 1, 1, { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 1, 1,
}, },
// MENUPAGE_CONTROLLER_PC_OLD3 = 38 // MENUPAGE_CONTROLLER_PC_OLD3 = 38
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 2, 2, { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 2, 2,
MENUACTION_GETKEY, "FEC_LUP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, MENUACTION_GETKEY, "FEC_LUP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3,
MENUACTION_GETKEY, "FEC_LDN", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, MENUACTION_GETKEY, "FEC_LDN", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3,
MENUACTION_GETKEY, "FEC_SMS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, MENUACTION_GETKEY, "FEC_SMS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3,
@ -289,17 +315,25 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_CONTROLLER_PC_OLD4 = 39 // MENUPAGE_CONTROLLER_PC_OLD4 = 39
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 3, 3, { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 3, 3,
}, },
// MENUPAGE_CONTROLLER_DEBUG = 40 // MENUPAGE_CONTROLLER_DEBUG = 40
{ "FEC_DBG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FEC_DBG", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 3, 3,
MENUACTION_GETKEY, "FEC_TGD", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG,
MENUACTION_GETKEY, "FEC_TDO", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG,
MENUACTION_GETKEY, "FEC_TSS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG,
MENUACTION_GETKEY, "FEC_SMS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG,
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_OPTIONS = 41 // MENUPAGE_OPTIONS = 41
{ "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, 1, 4, #ifdef MENU_MAP
{ "FET_OPT", 1, MENUPAGE_NONE, MENUPAGE_NONE, 1, 5,
#else
{ "FET_OPT", 1, MENUPAGE_NONE, MENUPAGE_NONE, 1, 4,
#endif
MENUACTION_CHANGEMENU, "FET_CTL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, MENUACTION_CHANGEMENU, "FET_CTL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
MENUACTION_LOADRADIO, "FET_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, MENUACTION_LOADRADIO, "FET_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
MENUACTION_CHANGEMENU, "FET_DIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, MENUACTION_CHANGEMENU, "FET_DIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
@ -309,67 +343,74 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_EXIT = 42 // MENUPAGE_EXIT = 42
{ "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, 2, 5, #ifdef MENU_MAP
{ "FET_QG", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 6,
#else
{ "FET_QG", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 5,
#endif
MENUACTION_LABEL, "FEQ_SRE", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FEQ_SRE", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CANCELGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CANCELGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_SAVING_IN_PROGRESS = 43 // MENUPAGE_SAVING_IN_PROGRESS = 43
{ "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, { "", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0,
MENUACTION_LABEL, "FES_WAR", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FES_WAR", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_SAVE_SUCCESSFUL = 44 // MENUPAGE_SAVE_SUCCESSFUL = 44
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0,
MENUACTION_LABEL, "FES_SSC", SAVESLOT_LABEL, MENUPAGE_NONE, MENUACTION_LABEL, "FES_SSC", SAVESLOT_LABEL, MENUPAGE_NONE,
MENUACTION_RESUME_FROM_SAVEZONE, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, MENUACTION_RESUME_FROM_SAVEZONE, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
}, },
// MENUPAGE_DELETING = 45 // MENUPAGE_DELETING = 45
{ "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, { "FET_DG", 1, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0,
MENUACTION_LABEL, "FED_DLW", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FED_DLW", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_DELETE_SUCCESS = 46 // MENUPAGE_DELETE_SUCCESS = 46
{ "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, { "FET_DG", 1, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0,
MENUACTION_LABEL, "DEL_FNM", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "DEL_FNM", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
}, },
// MENUPAGE_SAVE_FAILED = 47 // MENUPAGE_SAVE_FAILED = 47
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0,
MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
}, },
// MENUPAGE_LOAD_FAILED = 48 // MENUPAGE_LOAD_FAILED = 48
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0,
MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_LOAD_FAILED_2 = 49 // MENUPAGE_LOAD_FAILED_2 = 49
{ "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, { "FET_LG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0,
MENUACTION_LABEL, "FEC_LUN", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LABEL, "FEC_LUN", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT,
}, },
// MENUPAGE_FILTER_GAME = 50 // MENUPAGE_FILTER_GAME = 50
{ "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FIL_FLT", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
}, },
// MENUPAGE_START_MENU = 51 // MENUPAGE_START_MENU = 51
{ "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FEM_MM", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS,
MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT, MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT,
}, },
// MENUPAGE_PAUSE_MENU = 52 // MENUPAGE_PAUSE_MENU = 52
{ "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FET_PAU", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
#ifdef MENU_MAP
MENUACTION_CHANGEMENU, "FEG_MAP", SAVESLOT_NONE, MENUPAGE_MAP,
#endif
MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS, MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS,
MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS, MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS,
MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS,
@ -377,22 +418,24 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_CHOOSE_MODE = 53 // MENUPAGE_CHOOSE_MODE = 53
{ "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "FEN_STA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 0, 1,
MENUACTION_CHANGEMENU, "FET_SP", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
MENUACTION_INITMP, "FET_MP", SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN,
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
}, },
// MENUPAGE_SKIN_SELECT = 54 // MENUPAGE_SKIN_SELECT = 54
{ "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 4, 4, { "FET_PSU", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 4, 4,
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN,
}, },
// MENUPAGE_KEYBOARD_CONTROLS = 55 // MENUPAGE_KEYBOARD_CONTROLS = 55
{ "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 1, 1, { "FET_STI", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 1, 1,
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
}, },
// MENUPAGE_MOUSE_CONTROLS = 56 // MENUPAGE_MOUSE_CONTROLS = 56
{ "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 2, 2, { "FET_MTI", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 2, 2,
MENUACTION_MOUSESENS, "FEC_MSH", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, MENUACTION_MOUSESENS, "FEC_MSH", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
MENUACTION_INVVERT, "FEC_IVV", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, MENUACTION_INVVERT, "FEC_IVV", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
MENUACTION_MOUSESTEER, "FET_MST", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, MENUACTION_MOUSESTEER, "FET_MST", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
@ -400,12 +443,18 @@ const CMenuScreen aScreens[] = {
}, },
// MENUPAGE_57 = 57 // MENUPAGE_57 = 57
{ "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0,
// mission failed, wanna restart page in mobile
}, },
// MENUPAGE_58 = 58 // MENUPAGE_58 = 58
{ "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0,
}, },
#ifdef MENU_MAP
// MENUPAGE_MAP = 59
{ "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2,
},
#endif
}; };

View File

@ -21,19 +21,26 @@
#include "Hud.h" #include "Hud.h"
#include "Text.h" #include "Text.h"
#include "Timer.h" #include "Timer.h"
#include "Record.h"
#include "World.h" #include "World.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "Ped.h" #include "Ped.h"
#include "Population.h" #include "Population.h"
#include "Record.h"
#include "Replay.h" #include "Replay.h"
#include "Weather.h" #include "Weather.h"
#include "win.h" #include "win.h"
#include "Streaming.h"
#include "PathFind.h"
#include "Wanted.h"
#include "General.h"
CPad *Pads = (CPad*)0x6F0360; // [2] CPad *Pads = (CPad*)0x6F0360; // [2]
CMousePointerStateHelper &MousePointerStateHelper = *(CMousePointerStateHelper*)0x95CC8C; CMousePointerStateHelper &MousePointerStateHelper = *(CMousePointerStateHelper*)0x95CC8C;
bool &CPad::bDisplayNoControllerMessage = *(bool *)0x95CD52; bool &CPad::bDisplayNoControllerMessage = *(bool *)0x95CD52;
bool &CPad::bObsoleteControllerMessage = *(bool *)0x95CDB8; bool &CPad::bObsoleteControllerMessage = *(bool *)0x95CDB8;
bool CPad::bOldDisplayNoControllerMessage;
bool &CPad::m_bMapPadOneToPadTwo = *(bool *)0x95CD48; bool &CPad::m_bMapPadOneToPadTwo = *(bool *)0x95CD48;
CKeyboardState &CPad::OldKeyState = *(CKeyboardState*)0x6F1E70; CKeyboardState &CPad::OldKeyState = *(CKeyboardState*)0x6F1E70;
@ -49,29 +56,217 @@ CMouseControllerState &CPad::PCTempMouseControllerState = *(CMouseControllerStat
_TODO("gbFastTime"); _TODO("gbFastTime");
extern bool &gbFastTime; extern bool &gbFastTime;
WRAPPER void WeaponCheat() { EAXJMP(0x490D90); } void WeaponCheat()
WRAPPER void HealthCheat() { EAXJMP(0x490E70); } {
WRAPPER void TankCheat() { EAXJMP(0x490EE0); } CHud::SetHelpMessage(TheText.Get("CHEAT2"), true);
WRAPPER void BlowUpCarsCheat() { EAXJMP(0x491040); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 0);
WRAPPER void ChangePlayerCheat() { EAXJMP(0x4910B0); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100);
WRAPPER void MayhemCheat() { EAXJMP(0x4911C0); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_UZI, 100);
WRAPPER void EverybodyAttacksPlayerCheat() { EAXJMP(0x491270); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 20);
WRAPPER void WeaponsForAllCheat() { EAXJMP(0x491370); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_AK47, 200);
WRAPPER void FastTimeCheat() { EAXJMP(0x4913A0); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_M16, 200);
WRAPPER void SlowTimeCheat() { EAXJMP(0x4913F0); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 5);
WRAPPER void MoneyCheat() { EAXJMP(0x491430); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5);
WRAPPER void ArmourCheat() { EAXJMP(0x491460); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 5);
WRAPPER void WantedLevelUpCheat() { EAXJMP(0x491490); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 5);
WRAPPER void WantedLevelDownCheat() { EAXJMP(0x4914F0); } FindPlayerPed()->GiveWeapon(WEAPONTYPE_FLAMETHROWER, 200);
WRAPPER void SunnyWeatherCheat() { EAXJMP(0x491520); } }
WRAPPER void CloudyWeatherCheat() { EAXJMP(0x491550); }
WRAPPER void RainyWeatherCheat() { EAXJMP(0x491580); } void HealthCheat()
WRAPPER void FoggyWeatherCheat() { EAXJMP(0x4915B0); } {
WRAPPER void FastWeatherCheat() { EAXJMP(0x4915E0); } CHud::SetHelpMessage(TheText.Get("CHEAT3"), true);
WRAPPER void OnlyRenderWheelsCheat() { EAXJMP(0x491610); } FindPlayerPed()->m_fHealth = 100.0f;
WRAPPER void ChittyChittyBangBangCheat() { EAXJMP(0x491640); } if (FindPlayerVehicle()) {
WRAPPER void StrongGripCheat() { EAXJMP(0x491670); } FindPlayerVehicle()->m_fHealth = 1000.0f;
WRAPPER void NastyLimbsCheat() { EAXJMP(0x4916A0); } if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR)
((CAutomobile*)FindPlayerVehicle())->Damage.SetEngineStatus(0);
}
}
void TankCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
CStreaming::RequestModel(MI_RHINO, 0);
CStreaming::LoadAllRequestedModels(false);
if (CStreaming::ms_aInfoForModel[MI_RHINO].m_loadState == STREAMSTATE_LOADED) {
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f);
if (node < 0) return;
#ifdef FIX_BUGS
CAutomobile* tank = new CAutomobile(MI_RHINO, RANDOM_VEHICLE);
#else
CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE);
#endif
if (tank != nil) {
CVector pos = ThePaths.m_pathNodes[node].pos;
pos.z += 4.0f;
tank->GetPosition() = pos;
tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f));
tank->m_status = STATUS_ABANDONED;
tank->m_nDoorLock = CARLOCK_UNLOCKED;
CWorld::Add(tank);
}
}
}
void BlowUpCarsCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
int i = CPools::GetVehiclePool()->GetSize();
while (i-- > 0) {
if (CVehicle *veh = CPools::GetVehiclePool()->GetSlot(i))
veh->BlowUpCar(nil);
}
}
void ChangePlayerCheat()
{
int modelId;
if (FindPlayerPed()->IsPedInControl() && CModelInfo::GetModelInfo("player", nil)) {
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
CPlayerPed *ped = FindPlayerPed();
AssocGroupId AnimGrp = ped->m_animGroup;
do
{
do
modelId = CGeneral::GetRandomNumberInRange(0, MI_CAS_WOM+1);
while (!CModelInfo::GetModelInfo(modelId));
} while (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL04 || modelId == MI_TAXI_D);
uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags;
ped->DeleteRwObject();
CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE);
CStreaming::LoadAllRequestedModels(false);
ped->m_modelIndex = -1;
ped->SetModelIndex(modelId);
ped->m_animGroup = AnimGrp;
if (modelId != MI_PLAYER) {
if (!(flags & STREAMFLAGS_DONT_REMOVE))
CStreaming::SetModelIsDeletable(modelId);
}
}
}
void MayhemCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
for (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)
CPedType::SetThreats(i, PED_FLAG_PLAYER1 | PED_FLAG_PLAYER2 | PED_FLAG_PLAYER3 | PED_FLAG_PLAYER4 |
PED_FLAG_CIVMALE | PED_FLAG_CIVFEMALE | PED_FLAG_COP | PED_FLAG_GANG1 |
PED_FLAG_GANG2 | PED_FLAG_GANG3 | PED_FLAG_GANG4 | PED_FLAG_GANG5 |
PED_FLAG_GANG6 | PED_FLAG_GANG7 | PED_FLAG_GANG8 | PED_FLAG_GANG9 |
PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL );
}
void EverybodyAttacksPlayerCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
for (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)
CPedType::AddThreat(i, PED_FLAG_PLAYER1);
}
void WeaponsForAllCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
CPopulation::ms_bGivePedsWeapons = !CPopulation::ms_bGivePedsWeapons;
}
void FastTimeCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
if (CTimer::GetTimeScale() < 4.0f)
CTimer::SetTimeScale(CTimer::GetTimeScale() * 2.0f);
}
void SlowTimeCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
if (CTimer::GetTimeScale() > 0.25f)
CTimer::SetTimeScale(CTimer::GetTimeScale() * 0.5f);
}
void MoneyCheat()
{
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250000;
CHud::SetHelpMessage(TheText.Get("CHEAT6"), true);
}
void ArmourCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT4"), true);
FindPlayerPed()->m_fArmour = 100.0f;
}
void WantedLevelUpCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT5"), true);
FindPlayerPed()->SetWantedLevel(min(FindPlayerPed()->m_pWanted->m_nWantedLevel + 2, 6));
}
void WantedLevelDownCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT5"), true);
FindPlayerPed()->SetWantedLevel(0);
}
void SunnyWeatherCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
CWeather::ForceWeatherNow(WEATHER_SUNNY);
}
void CloudyWeatherCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
CWeather::ForceWeatherNow(WEATHER_CLOUDY);
}
void RainyWeatherCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
CWeather::ForceWeatherNow(WEATHER_RAINY);
}
void FoggyWeatherCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
CWeather::ForceWeatherNow(WEATHER_FOGGY);
}
void FastWeatherCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
gbFastTime = !gbFastTime;
}
void OnlyRenderWheelsCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
CVehicle::bWheelsOnlyCheat = !CVehicle::bWheelsOnlyCheat;
}
void ChittyChittyBangBangCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
CVehicle::bAllDodosCheat = !CVehicle::bAllDodosCheat;
}
void StrongGripCheat()
{
CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
CVehicle::bCheat3 = !CVehicle::bCheat3;
}
void NastyLimbsCheat()
{
CPed::bNastyLimbsCheat = !CPed::bNastyLimbsCheat;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifdef KANGAROO_CHEAT #ifdef KANGAROO_CHEAT
@ -88,7 +283,7 @@ void KangarooCheat()
string = TheText.Get("CHEAT1"); string = TheText.Get("CHEAT1");
m_fMass = 15.0f; m_fMass = 15.0f;
} }
CHud::SetHelpMessage(string, 1); CHud::SetHelpMessage(string, true);
playerPed->m_ped_flagI80 = !playerPed->m_ped_flagI80; playerPed->m_ped_flagI80 = !playerPed->m_ped_flagI80;
playerPed->m_fMass = m_fMass; playerPed->m_fMass = m_fMass;
@ -137,6 +332,21 @@ void CKeyboardState::Clear()
LWIN = RWIN = APPS = 0; LWIN = RWIN = APPS = 0;
} }
#ifdef GTA_PS2_STUFF
void CPad::Initialise(void)
{
for (int i = 0; i < MAX_PADS; i++)
{
CPad::GetPad(i)->Clear(true);
CPad::GetPad(i)->Mode = 0;
}
bObsoleteControllerMessage = false;
bOldDisplayNoControllerMessage = false;
bDisplayNoControllerMessage = false;
}
#endif
void CPad::Clear(bool bResetPlayerControls) void CPad::Clear(bool bResetPlayerControls)
{ {
NewState.Clear(); NewState.Clear();
@ -164,13 +374,13 @@ void CPad::Clear(bool bResetPlayerControls)
bApplyBrakes = false; bApplyBrakes = false;
for ( int32 i = 0; i < _TODOCONST(5); i++ ) for ( int32 i = 0; i < HORNHISTORY_SIZE; i++ )
bHornHistory[i] = false; bHornHistory[i] = false;
iCurrHornHistory = 0; iCurrHornHistory = 0;
for ( int32 i = 0; i < _TODOCONST(12); i++ ) for ( int32 i = 0; i < ARRAY_SIZE(CheatString); i++ )
_unk[i] = ' '; CheatString[i] = ' ';
LastTimeTouched = CTimer::GetTimeInMilliseconds(); LastTimeTouched = CTimer::GetTimeInMilliseconds();
AverageWeapon = 0; AverageWeapon = 0;
@ -429,6 +639,108 @@ void CPad::StartShake_Train(float fX, float fY)
} }
} }
#ifdef GTA_PS2_STUFF
void CPad::AddToCheatString(char c)
{
for ( int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i-- )
CheatString[i + 1] = CheatString[i];
#define _CHEATCMP(str) strncmp(str, CheatString, sizeof(str)-1)
// "4414LDRULDRU" - R2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
if ( !_CHEATCMP("URDLURDL4144") )
WeaponCheat();
// "4411LDRULDRU" - R2 R2 L1 L1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
else if ( !_CHEATCMP("URDLURDL1144") )
MoneyCheat();
// "4412LDRULDRU" - R2 R2 L1 L2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
else if ( !_CHEATCMP("URDLURDL2144") )
ArmourCheat();
// "4413LDRULDRU" - R2 R2 L1 R1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
else if ( !_CHEATCMP("URDLURDL3144") )
HealthCheat();
// "4414LRLRLR" - R2 R2 L1 R2 LEFT RIGHT LEFT RIGHT LEFT RIGHT
else if ( !_CHEATCMP("RLRLRL4144") )
WantedLevelUpCheat();
// "4414UDUDUD" - R2 R2 L1 R2 UP DOWN UP DOWN UP DOWN
else if ( !_CHEATCMP("DUDUDU4144") )
WantedLevelDownCheat();
// "1234432T" - L1 L2 R1 R2 R2 R1 L2 TRIANGLE
else if ( !_CHEATCMP("T2344321") )
SunnyWeatherCheat();
// "1234432S" - L1 L2 R1 R2 R2 R1 L2 SQUARE
else if ( !_CHEATCMP("S2344321") )
CloudyWeatherCheat();
// "1234432C" - L1 L2 R1 R2 R2 R1 L2 CIRCLE
else if ( !_CHEATCMP("C2344321") )
RainyWeatherCheat();
// "1234432X" - L1 L2 R1 R2 R2 R1 L2 CROSS
else if ( !_CHEATCMP("X2344321") )
FoggyWeatherCheat();
// "CCCCCC321TCT" - CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE R1 L2 L1 TRIANGLE CIRCLE TRIANGLE
else if ( !_CHEATCMP("TCT123CCCCCC") )
TankCheat();
// "CCCSSSSS1TCT" - CIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE
else if ( !_CHEATCMP("TCT1SSSSSCCC") )
FastWeatherCheat();
// "241324TSCT21" - L2 R2 L1 R1 L2 R2 TRIANGLE SQUARE CIRCLE TRIANGLE L2 L1
else if ( !_CHEATCMP("12TCST423142") )
BlowUpCarsCheat();
// "RDLU12ULDR" - RIGHT DOWN LEFT UP L1 L2 UP LEFT DOWN RIGHT
else if ( !_CHEATCMP("RDLU21ULDR") )
ChangePlayerCheat();
// "DULUX3421" - DOWN UP LEFT UP CROSS R1 R2 L2 L1
else if ( !_CHEATCMP("1243XULUD") )
MayhemCheat();
// "DULUX3412" - DOWN UP LEFT UP CROSS R1 R2 L1 L2
else if ( !_CHEATCMP("2143XULUD") )
EverybodyAttacksPlayerCheat();
// "43TX21UD" - R2 R1 TRIANGLE CROSS L2 L1 UP DOWN
else if ( !_CHEATCMP("DU12XT34") )
WeaponsForAllCheat();
// "TURDS12" - TRIANGLE UP RIGHT DOWN SQUARE L1 L2
else if ( !_CHEATCMP("21SDRUT") )
FastTimeCheat();
// "TURDS34" - TRIANGLE UP RIGHT DOWN SQUARE R1 R2
else if ( !_CHEATCMP("43SDRUT") )
SlowTimeCheat();
// "11S4T1T" - L1 L1 SQUARE R2 TRIANGLE L1 TRIANGLE
else if ( !_CHEATCMP("T1T4S11") )
OnlyRenderWheelsCheat();
// "R4C32D13" - RIGHT R2 CIRCLE R1 L2 DOWN L1 R1
else if ( !_CHEATCMP("31D23C4R") )
ChittyChittyBangBangCheat();
// "3141L33T" - R1 L1 R2 L1 LEFT R1 R1 TRIANGLE
else if ( !_CHEATCMP("T33L1413") )
StrongGripCheat();
// "S1CD13TR1X" - SQUARE L1 CIRCLE DOWN L1 R1 TRIANGLE RIGHT L1 CROSS
else if ( !_CHEATCMP("X1RT31DC1S") )
NastyLimbsCheat();
#undef _CHEATCMP
}
#endif
void CPad::AddToPCCheatString(char c) void CPad::AddToPCCheatString(char c)
{ {
for ( int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i-- ) for ( int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i-- )
@ -657,16 +969,21 @@ void CPad::Update(int16 unk)
{ {
OldState = NewState; OldState = NewState;
NewState = ReconcileTwoControllersInput(PCTempKeyState, PCTempJoyState); #if (defined GTA_PS2 || defined FIX_BUGS)
NewState = ReconcileTwoControllersInput(PCTempMouseState, NewState); if (!CRecordDataForGame::IsPlayingBack() && !CRecordDataForChase::ShouldThisPadBeLeftAlone(unk))
#endif
{
NewState = ReconcileTwoControllersInput(PCTempKeyState, PCTempJoyState);
NewState = ReconcileTwoControllersInput(PCTempMouseState, NewState);
}
PCTempJoyState.Clear(); PCTempJoyState.Clear();
PCTempKeyState.Clear(); PCTempKeyState.Clear();
PCTempMouseState.Clear(); PCTempMouseState.Clear();
ProcessPCSpecificStuff(); ProcessPCSpecificStuff();
if ( ++iCurrHornHistory >= _TODOCONST(5) ) if ( ++iCurrHornHistory >= HORNHISTORY_SIZE )
iCurrHornHistory = 0; iCurrHornHistory = 0;
bHornHistory[iCurrHornHistory] = GetHorn(); bHornHistory[iCurrHornHistory] = GetHorn();
@ -683,7 +1000,7 @@ void CPad::DoCheats(void)
void CPad::DoCheats(int16 unk) void CPad::DoCheats(int16 unk)
{ {
#ifdef PS2 #ifdef GTA_PS2_STUFF
if ( GetTriangleJustDown() ) if ( GetTriangleJustDown() )
AddToCheatString('T'); AddToCheatString('T');
@ -2086,7 +2403,31 @@ int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize)
return pRsKeys; return pRsKeys;
} }
STARTPATCHES STARTPATCHES
InjectHook(0x490D90, &WeaponCheat, PATCH_JUMP);
InjectHook(0x490E70, &HealthCheat, PATCH_JUMP);
InjectHook(0x490EE0, &TankCheat, PATCH_JUMP);
InjectHook(0x491040, &BlowUpCarsCheat, PATCH_JUMP);
InjectHook(0x4910B0, &ChangePlayerCheat, PATCH_JUMP);
InjectHook(0x4911C0, &MayhemCheat, PATCH_JUMP);
InjectHook(0x491270, &EverybodyAttacksPlayerCheat, PATCH_JUMP);
InjectHook(0x491370, &WeaponsForAllCheat, PATCH_JUMP);
InjectHook(0x4913A0, &FastTimeCheat, PATCH_JUMP);
InjectHook(0x4913F0, &SlowTimeCheat, PATCH_JUMP);
InjectHook(0x491430, &MoneyCheat, PATCH_JUMP);
InjectHook(0x491460, &ArmourCheat, PATCH_JUMP);
InjectHook(0x491490, &WantedLevelUpCheat, PATCH_JUMP);
InjectHook(0x4914F0, &WantedLevelDownCheat, PATCH_JUMP);
InjectHook(0x491520, &SunnyWeatherCheat, PATCH_JUMP);
InjectHook(0x491550, &CloudyWeatherCheat, PATCH_JUMP);
InjectHook(0x491580, &RainyWeatherCheat, PATCH_JUMP);
InjectHook(0x4915B0, &FoggyWeatherCheat, PATCH_JUMP);
InjectHook(0x4915E0, &FastWeatherCheat, PATCH_JUMP);
InjectHook(0x491610, &OnlyRenderWheelsCheat, PATCH_JUMP);
InjectHook(0x491640, &ChittyChittyBangBangCheat, PATCH_JUMP);
InjectHook(0x491670, &StrongGripCheat, PATCH_JUMP);
InjectHook(0x4916A0, &NastyLimbsCheat, PATCH_JUMP);
InjectHook(0x4916C0, &CControllerState::Clear, PATCH_JUMP); InjectHook(0x4916C0, &CControllerState::Clear, PATCH_JUMP);
InjectHook(0x491760, &CKeyboardState::Clear, PATCH_JUMP); InjectHook(0x491760, &CKeyboardState::Clear, PATCH_JUMP);
InjectHook(0x491A10, &CPad::Clear, PATCH_JUMP); InjectHook(0x491A10, &CPad::Clear, PATCH_JUMP);

View File

@ -136,6 +136,10 @@ enum
class CPad class CPad
{ {
public: public:
enum
{
HORNHISTORY_SIZE = 5,
};
CControllerState NewState; CControllerState NewState;
CControllerState OldState; CControllerState OldState;
CControllerState PCTempKeyState; CControllerState PCTempKeyState;
@ -146,11 +150,11 @@ public:
int16 Mode; int16 Mode;
int16 ShakeDur; int16 ShakeDur;
uint8 ShakeFreq; uint8 ShakeFreq;
bool bHornHistory[5]; bool bHornHistory[HORNHISTORY_SIZE];
uint8 iCurrHornHistory; uint8 iCurrHornHistory;
uint8 DisablePlayerControls; uint8 DisablePlayerControls;
int8 bApplyBrakes; int8 bApplyBrakes;
char _unk[12]; //int32 unk[3]; char CheatString[12];
char _pad0[3]; char _pad0[3];
int32 LastTimeTouched; int32 LastTimeTouched;
int32 AverageWeapon; int32 AverageWeapon;
@ -161,6 +165,7 @@ public:
static bool &bDisplayNoControllerMessage; static bool &bDisplayNoControllerMessage;
static bool &bObsoleteControllerMessage; static bool &bObsoleteControllerMessage;
static bool bOldDisplayNoControllerMessage;
static bool &m_bMapPadOneToPadTwo; static bool &m_bMapPadOneToPadTwo;
static CKeyboardState &OldKeyState; static CKeyboardState &OldKeyState;
@ -172,8 +177,9 @@ public:
static CMouseControllerState &PCTempMouseControllerState; static CMouseControllerState &PCTempMouseControllerState;
#ifdef GTA_PS2_STUFF
static void Initialise(void);
#endif
void Clear(bool bResetPlayerControls); void Clear(bool bResetPlayerControls);
void ClearMouseHistory(); void ClearMouseHistory();
void UpdateMouse(); void UpdateMouse();
@ -181,6 +187,9 @@ public:
void StartShake(int16 nDur, uint8 nFreq); void StartShake(int16 nDur, uint8 nFreq);
void StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fz); void StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fz);
void StartShake_Train(float fX, float fY); void StartShake_Train(float fX, float fY);
#ifdef GTA_PS2_STUFF
void AddToCheatString(char c);
#endif
void AddToPCCheatString(char c); void AddToPCCheatString(char c);
static void UpdatePads(void); static void UpdatePads(void);
@ -409,6 +418,7 @@ public:
bool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); } bool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); }
bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); } bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); }
bool GetTriangleJustUp() { return !!(!NewState.Triangle && OldState.Triangle); }
bool GetCrossJustUp() { return !!(!NewState.Cross && OldState.Cross); } bool GetCrossJustUp() { return !!(!NewState.Cross && OldState.Cross); }
bool GetSquareJustUp() { return !!(!NewState.Square && OldState.Square); } bool GetSquareJustUp() { return !!(!NewState.Square && OldState.Square); }
bool GetDPadUpJustUp() { return !!(!NewState.DPadUp && OldState.DPadUp); } bool GetDPadUpJustUp() { return !!(!NewState.DPadUp && OldState.DPadUp); }

View File

@ -48,45 +48,45 @@ CPlayerInfo::GetPos()
void void
CPlayerInfo::LoadPlayerSkin() CPlayerInfo::LoadPlayerSkin()
{ {
DeletePlayerSkin(); DeletePlayerSkin();
m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName); m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName);
if (!m_pSkinTexture) if (!m_pSkinTexture)
m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME); m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME);
} }
void void
CPlayerInfo::DeletePlayerSkin() CPlayerInfo::DeletePlayerSkin()
{ {
if (m_pSkinTexture) { if (m_pSkinTexture) {
RwTextureDestroy(m_pSkinTexture); RwTextureDestroy(m_pSkinTexture);
m_pSkinTexture = nil; m_pSkinTexture = nil;
} }
} }
void void
CPlayerInfo::KillPlayer() CPlayerInfo::KillPlayer()
{ {
if (m_WBState != WBSTATE_PLAYING) return; if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_WASTED; m_WBState = WBSTATE_WASTED;
m_nWBTime = CTimer::GetTimeInMilliseconds(); m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath(); CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2); CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2);
CStats::TimesDied++; CStats::TimesDied++;
} }
void void
CPlayerInfo::ArrestPlayer() CPlayerInfo::ArrestPlayer()
{ {
if (m_WBState != WBSTATE_PLAYING) return; if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_BUSTED; m_WBState = WBSTATE_BUSTED;
m_nWBTime = CTimer::GetTimeInMilliseconds(); m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath(); CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2); CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2);
CStats::TimesArrested++; CStats::TimesArrested++;
} }
bool bool
@ -105,102 +105,102 @@ CPlayerInfo::PlayerFailedCriticalMission()
CDarkel::ResetOnPlayerDeath(); CDarkel::ResetOnPlayerDeath();
} }
void void
CPlayerInfo::Clear(void) CPlayerInfo::Clear(void)
{ {
m_pPed = nil; m_pPed = nil;
m_pRemoteVehicle = nil; m_pRemoteVehicle = nil;
if (m_pVehicleEx) { if (m_pVehicleEx) {
m_pVehicleEx->bUsingSpecialColModel = false; m_pVehicleEx->bUsingSpecialColModel = false;
m_pVehicleEx = nil; m_pVehicleEx = nil;
} }
m_nVisibleMoney = 0; m_nVisibleMoney = 0;
m_nMoney = m_nVisibleMoney; m_nMoney = m_nVisibleMoney;
m_WBState = WBSTATE_PLAYING; m_WBState = WBSTATE_PLAYING;
m_nWBTime = 0; m_nWBTime = 0;
m_nTrafficMultiplier = 0; m_nTrafficMultiplier = 0;
m_fRoadDensity = 1.0f; m_fRoadDensity = 1.0f;
m_bInRemoteMode = false; m_bInRemoteMode = false;
m_bUnusedTaxiThing = false; m_bUnusedTaxiThing = false;
m_nUnusedTaxiTimer = 0; m_nUnusedTaxiTimer = 0;
m_nCollectedPackages = 0; m_nCollectedPackages = 0;
m_nTotalPackages = 3; m_nTotalPackages = 3;
m_nTimeLastHealthLoss = 0; m_nTimeLastHealthLoss = 0;
m_nTimeLastArmourLoss = 0; m_nTimeLastArmourLoss = 0;
m_nNextSexFrequencyUpdateTime = 0; m_nNextSexFrequencyUpdateTime = 0;
m_nNextSexMoneyUpdateTime = 0; m_nNextSexMoneyUpdateTime = 0;
m_nSexFrequency = 0; m_nSexFrequency = 0;
m_pHooker = nil; m_pHooker = nil;
m_nTimeTankShotGun = 0; m_nTimeTankShotGun = 0;
field_248 = 0; field_248 = 0;
m_nUpsideDownCounter = 0; m_nUpsideDownCounter = 0;
m_bInfiniteSprint = false; m_bInfiniteSprint = false;
m_bFastReload = false; m_bFastReload = false;
m_bGetOutOfJailFree = false; m_bGetOutOfJailFree = false;
m_bGetOutOfHospitalFree = false; m_bGetOutOfHospitalFree = false;
m_nPreviousTimeRewardedForExplosion = 0; m_nPreviousTimeRewardedForExplosion = 0;
m_nExplosionsSinceLastReward = 0; m_nExplosionsSinceLastReward = 0;
} }
void void
CPlayerInfo::BlowUpRCBuggy(void) CPlayerInfo::BlowUpRCBuggy(void)
{ {
if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld) if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld)
return; return;
CRemote::TakeRemoteControlledCarFromPlayer(); CRemote::TakeRemoteControlledCarFromPlayer();
m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); m_pRemoteVehicle->BlowUpCar(FindPlayerPed());
}
void
CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car)
{
if (!car || car == m_pPed->m_pMyVehicle) {
if (m_pPed->EnteringCar())
m_pPed->QuitEnteringCar();
}
if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
m_pPed->ClearObjective();
} }
void void
CPlayerInfo::MakePlayerSafe(bool toggle) CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car)
{ {
if (toggle) { if (!car || car == m_pPed->m_pMyVehicle) {
CTheScripts::ResetCountdownToMakePlayerUnsafe(); if (m_pPed->EnteringCar())
m_pPed->m_pWanted->m_bIgnoredByEveryone = true; m_pPed->QuitEnteringCar();
CWorld::StopAllLawEnforcersInTheirTracks(); }
CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20; if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
CPad::StopPadsShaking(); m_pPed->ClearObjective();
m_pPed->bBulletProof = true; }
m_pPed->bFireProof = true;
m_pPed->bCollisionProof = true; void
m_pPed->bMeleeProof = true; CPlayerInfo::MakePlayerSafe(bool toggle)
m_pPed->bOnlyDamagedByPlayer = true; {
m_pPed->bExplosionProof = true; if (toggle) {
m_pPed->m_bCanBeDamaged = false; CTheScripts::ResetCountdownToMakePlayerUnsafe();
((CPlayerPed*)m_pPed)->ClearAdrenaline(); m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
CancelPlayerEnteringCars(false); CWorld::StopAllLawEnforcersInTheirTracks();
gFireManager.ExtinguishPoint(GetPos(), 4000.0f); CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f); CPad::StopPadsShaking();
CProjectileInfo::RemoveAllProjectiles(); m_pPed->bBulletProof = true;
CWorld::SetAllCarsCanBeDamaged(false); m_pPed->bFireProof = true;
CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f); m_pPed->bCollisionProof = true;
CReplay::DisableReplays(); m_pPed->bMeleeProof = true;
m_pPed->bOnlyDamagedByPlayer = true;
} else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) { m_pPed->bExplosionProof = true;
m_pPed->m_pWanted->m_bIgnoredByEveryone = false; m_pPed->m_bCanBeDamaged = false;
CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20; ((CPlayerPed*)m_pPed)->ClearAdrenaline();
m_pPed->bBulletProof = false; CancelPlayerEnteringCars(false);
m_pPed->bFireProof = false; gFireManager.ExtinguishPoint(GetPos(), 4000.0f);
m_pPed->bCollisionProof = false; CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f);
m_pPed->bMeleeProof = false; CProjectileInfo::RemoveAllProjectiles();
m_pPed->bOnlyDamagedByPlayer = false; CWorld::SetAllCarsCanBeDamaged(false);
m_pPed->bExplosionProof = false; CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
m_pPed->m_bCanBeDamaged = true; CReplay::DisableReplays();
CWorld::SetAllCarsCanBeDamaged(true);
CReplay::EnableReplays(); } else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) {
} m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20;
m_pPed->bBulletProof = false;
m_pPed->bFireProof = false;
m_pPed->bCollisionProof = false;
m_pPed->bMeleeProof = false;
m_pPed->bOnlyDamagedByPlayer = false;
m_pPed->bExplosionProof = false;
m_pPed->m_bCanBeDamaged = true;
CWorld::SetAllCarsCanBeDamaged(true);
CReplay::EnableReplays();
}
} }
bool bool
@ -216,347 +216,347 @@ CPlayerInfo::IsRestartingAfterArrest()
} }
// lastCloseness is passed to other calls of this function // lastCloseness is passed to other calls of this function
void void
CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput) CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput)
{ {
// This dist used for determining the angle to face // This dist used for determining the angle to face
CVector2D dist(carToTest->GetPosition() - player->GetPosition()); CVector2D dist(carToTest->GetPosition() - player->GetPosition());
float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y); float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y);
while (neededTurn >= PI) { while (neededTurn >= PI) {
neededTurn -= 2 * PI; neededTurn -= 2 * PI;
} }
while (neededTurn < -PI) { while (neededTurn < -PI) {
neededTurn += 2 * PI; neededTurn += 2 * PI;
} }
// This dist used for evaluating cars' distances, weird... // This dist used for evaluating cars' distances, weird...
// Accounts inverted needed turn (or needed turn in long way) and car dist. // Accounts inverted needed turn (or needed turn in long way) and car dist.
float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist); float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist);
if (closeness > *lastCloseness) { if (closeness > *lastCloseness) {
*lastCloseness = closeness; *lastCloseness = closeness;
*closestCarOutput = (CVehicle*)carToTest; *closestCarOutput = (CVehicle*)carToTest;
} }
} }
// There is something unfinished in here... Sadly all IDBs we have have it unfinished. // There is something unfinished in here... Sadly all IDBs we have have it unfinished.
void void
CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar) CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar)
{ {
if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000) if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000)
++m_nExplosionsSinceLastReward; ++m_nExplosionsSinceLastReward;
else else
m_nExplosionsSinceLastReward = 1; m_nExplosionsSinceLastReward = 1;
m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds(); m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds();
int award = wreckedCar->pHandling->nMonetaryValue * 0.002f; int award = wreckedCar->pHandling->nMonetaryValue * 0.002f;
sprintf(gString, "$%d", award); sprintf(gString, "$%d", award);
#ifdef MONEY_MESSAGES #ifdef MONEY_MESSAGES
// This line is a leftover from PS2, I don't know what it was meant to be. // This line is a leftover from PS2, I don't know what it was meant to be.
// CVector sth(TheCamera.GetPosition() * 4.0f); // CVector sth(TheCamera.GetPosition() * 4.0f);
CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f); CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f);
#endif #endif
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
for (int i = m_nExplosionsSinceLastReward; i > 1; --i) { for (int i = m_nExplosionsSinceLastReward; i > 1; --i) {
CGeneral::GetRandomNumber(); CGeneral::GetRandomNumber();
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
} }
} }
void void
CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size) CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size)
{ {
// Interesting // Interesting
*size = sizeof(CPlayerInfo); *size = sizeof(CPlayerInfo);
INITSAVEBUF INITSAVEBUF
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);
for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) { for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i]); WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i]);
} }
// Save struct is different // Save struct is different
// VALIDATESAVEBUF(*size) // VALIDATESAVEBUF(*size)
} }
void void
CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size) CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size)
{ {
INITSAVEBUF INITSAVEBUF
CWorld::Players[CWorld::PlayerInFocus].m_nMoney = ReadSaveBuf<uint32>(buf); CWorld::Players[CWorld::PlayerInFocus].m_nMoney = ReadSaveBuf<uint32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf<int8>(buf); CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf<int8>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf<uint32>(buf); CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf<uint32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf<int16>(buf); CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf<int16>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf<float>(buf); CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf<float>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = ReadSaveBuf<int32>(buf); CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages = ReadSaveBuf<int32>(buf); CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ReadSaveBuf<int32>(buf); CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ReadSaveBuf<int32>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint = ReadSaveBuf<bool>(buf); CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bFastReload = ReadSaveBuf<bool>(buf); CWorld::Players[CWorld::PlayerInFocus].m_bFastReload = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree = ReadSaveBuf<bool>(buf); CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree = ReadSaveBuf<bool>(buf);
CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree = ReadSaveBuf<bool>(buf); CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree = ReadSaveBuf<bool>(buf);
for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) { for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf<char>(buf); CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf<char>(buf);
} }
// Save struct is different // Save struct is different
// VALIDATESAVEBUF(size) // VALIDATESAVEBUF(size)
} }
void void
CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput) CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput)
{ {
for (CPtrNode* node = carList.first; node; node = node->next) { for (CPtrNode* node = carList.first; node; node = node->next) {
CVehicle *car = (CVehicle*)node->item; CVehicle *car = (CVehicle*)node->item;
if(car->m_scanCode != CWorld::GetCurrentScanCode()) { if(car->m_scanCode != CWorld::GetCurrentScanCode()) {
if (!car->bUsesCollision || !car->IsVehicle()) if (!car->bUsesCollision || !car->IsVehicle())
continue; continue;
car->m_scanCode = CWorld::GetCurrentScanCode(); car->m_scanCode = CWorld::GetCurrentScanCode();
if (car->m_status != STATUS_WRECKED && car->m_status != STATUS_TRAIN_MOVING if (car->m_status != STATUS_WRECKED && car->m_status != STATUS_TRAIN_MOVING
&& (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) { && (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) {
CVector carCentre = car->GetBoundCentre(); CVector carCentre = car->GetBoundCentre();
if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) { if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) {
float dist = (ped->GetPosition() - carCentre).Magnitude2D(); float dist = (ped->GetPosition() - carCentre).Magnitude2D();
if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) { if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput); EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput);
} }
} }
} }
} }
} }
} }
void void
CPlayerInfo::Process(void) CPlayerInfo::Process(void)
{ {
// Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode. // Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode.
bool startTaxiTimer = true; bool startTaxiTimer = true;
if (m_bUnusedTaxiThing && m_pPed->bInVehicle) { if (m_bUnusedTaxiThing && m_pPed->bInVehicle) {
CVehicle *veh = m_pPed->m_pMyVehicle; CVehicle *veh = m_pPed->m_pMyVehicle;
if ((veh->m_modelIndex == MI_TAXI || veh->m_modelIndex == MI_CABBIE || veh->m_modelIndex == MI_BORGNINE) if ((veh->m_modelIndex == MI_TAXI || veh->m_modelIndex == MI_CABBIE || veh->m_modelIndex == MI_BORGNINE)
&& veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) { && veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) {
for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) { for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) {
timePassed -= 1000; timePassed -= 1000;
++m_nMoney; ++m_nMoney;
} }
startTaxiTimer = false; startTaxiTimer = false;
} }
} }
if (startTaxiTimer) if (startTaxiTimer)
m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds(); m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
// The effect that makes money counter does while earning/losing money // The effect that makes money counter does while earning/losing money
if (m_nVisibleMoney != m_nMoney) { if (m_nVisibleMoney != m_nMoney) {
int diff = m_nMoney - m_nVisibleMoney; int diff = m_nMoney - m_nVisibleMoney;
int diffAbs = Abs(diff); int diffAbs = Abs(diff);
int changeBy; int changeBy;
if (diffAbs > 100000) if (diffAbs > 100000)
changeBy = 12345; changeBy = 12345;
else if (diffAbs > 10000) else if (diffAbs > 10000)
changeBy = 1234; changeBy = 1234;
else if (diffAbs > 1000) else if (diffAbs > 1000)
changeBy = 123; changeBy = 123;
else if (diffAbs > 50) else if (diffAbs > 50)
changeBy = 42; changeBy = 42;
else else
changeBy = 1; changeBy = 1;
if (diff < 0) if (diff < 0)
m_nVisibleMoney -= changeBy; m_nVisibleMoney -= changeBy;
else else
m_nVisibleMoney += changeBy; m_nVisibleMoney += changeBy;
} }
if (!(CTimer::GetFrameCounter() & 15)) { if (!(CTimer::GetFrameCounter() & 15)) {
CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition(); CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition();
m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y); m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y);
} }
m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f); m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f);
// Because vehicle enter/exit use same key binding. // Because vehicle enter/exit use same key binding.
bool enterOrExitVeh; bool enterOrExitVeh;
if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle) if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle)
enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown(); enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown();
else else
enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle(); enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle();
if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_ODE) { if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_ODE) {
if (m_pPed->bInVehicle) { if (m_pPed->bInVehicle) {
if (!m_pRemoteVehicle) { if (!m_pRemoteVehicle) {
CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity; CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity;
if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->m_modelIndex)) { if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->m_modelIndex)) {
CVehicle *veh = m_pPed->m_pMyVehicle; CVehicle *veh = m_pPed->m_pMyVehicle;
if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
// This condition will always return true, else block was probably WIP Miami code. // This condition will always return true, else block was probably WIP Miami code.
if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
if (veh->m_status != STATUS_WRECKED && veh->m_status != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) { if (veh->m_status != STATUS_WRECKED && veh->m_status != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) {
if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) { if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) {
m_pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); m_pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh);
} }
} }
} else { } else {
CVector sth = 0.7f * veh->GetRight() + veh->GetPosition(); CVector sth = 0.7f * veh->GetRight() + veh->GetPosition();
bool found = false; bool found = false;
float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found); float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found);
if (found) if (found)
sth.z = 1.0f + groundZ; sth.z = 1.0f + groundZ;
m_pPed->m_nPedState = PED_IDLE; m_pPed->m_nPedState = PED_IDLE;
m_pPed->SetMoveState(PEDMOVE_STILL); m_pPed->SetMoveState(PEDMOVE_STILL);
CPed::PedSetOutCarCB(0, m_pPed); CPed::PedSetOutCarCB(0, m_pPed);
CAnimManager::BlendAnimation(m_pPed->GetClump(), m_pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f); CAnimManager::BlendAnimation(m_pPed->GetClump(), m_pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f);
CAnimManager::BlendAnimation(m_pPed->GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND, 100.0f); CAnimManager::BlendAnimation(m_pPed->GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND, 100.0f);
m_pPed->GetPosition() = sth; m_pPed->GetPosition() = sth;
m_pPed->SetMoveState(PEDMOVE_STILL); m_pPed->SetMoveState(PEDMOVE_STILL);
m_pPed->m_vecMoveSpeed = veh->m_vecMoveSpeed; m_pPed->m_vecMoveSpeed = veh->m_vecMoveSpeed;
} }
} else { } else {
// The code in here was under CPed::SetExitBoat in VC, did the same for here. // The code in here was under CPed::SetExitBoat in VC, did the same for here.
m_pPed->SetExitBoat(veh); m_pPed->SetExitBoat(veh);
m_pPed->bTryingToReachDryLand = true; m_pPed->bTryingToReachDryLand = true;
} }
} }
} }
} else { } else {
// Enter vehicle // Enter vehicle
if (CPad::GetPad(0)->ExitVehicleJustDown()) { if (CPad::GetPad(0)->ExitVehicleJustDown()) {
bool weAreOnBoat = false; bool weAreOnBoat = false;
float lastCloseness = 0.0f; float lastCloseness = 0.0f;
CVehicle *carBelow = nil; CVehicle *carBelow = nil;
CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface; CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface;
if (surfaceBelow && surfaceBelow->IsVehicle()) { if (surfaceBelow && surfaceBelow->IsVehicle()) {
carBelow = (CVehicle*)surfaceBelow; carBelow = (CVehicle*)surfaceBelow;
if (carBelow->IsBoat()) { if (carBelow->IsBoat()) {
weAreOnBoat = true; weAreOnBoat = true;
m_pPed->bOnBoat = true; m_pPed->bOnBoat = true;
#ifdef VC_PED_PORTS #ifdef VC_PED_PORTS
if (carBelow->m_status != STATUS_WRECKED && carBelow->GetUp().z > 0.3f) if (carBelow->m_status != STATUS_WRECKED && carBelow->GetUp().z > 0.3f)
#else #else
if (carBelow->m_status != STATUS_WRECKED) if (carBelow->m_status != STATUS_WRECKED)
#endif #endif
m_pPed->SetSeekBoatPosition(carBelow); m_pPed->SetSeekBoatPosition(carBelow);
} }
} }
// Find closest car // Find closest car
if (!weAreOnBoat) { if (!weAreOnBoat) {
float minX = m_pPed->GetPosition().x - 10.0f; float minX = m_pPed->GetPosition().x - 10.0f;
float maxX = 10.0f + m_pPed->GetPosition().x; float maxX = 10.0f + m_pPed->GetPosition().x;
float minY = m_pPed->GetPosition().y - 10.0f; float minY = m_pPed->GetPosition().y - 10.0f;
float maxY = 10.0f + m_pPed->GetPosition().y; float maxY = 10.0f + m_pPed->GetPosition().y;
int minXSector = CWorld::GetSectorIndexX(minX); int minXSector = CWorld::GetSectorIndexX(minX);
if (minXSector < 0) minXSector = 0; if (minXSector < 0) minXSector = 0;
int minYSector = CWorld::GetSectorIndexY(minY); int minYSector = CWorld::GetSectorIndexY(minY);
if (minYSector < 0) minYSector = 0; if (minYSector < 0) minYSector = 0;
int maxXSector = CWorld::GetSectorIndexX(maxX); int maxXSector = CWorld::GetSectorIndexX(maxX);
if (maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1; if (maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1;
int maxYSector = CWorld::GetSectorIndexY(maxY); int maxYSector = CWorld::GetSectorIndexY(maxY);
if (maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1; if (maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1;
CWorld::AdvanceCurrentScanCode(); CWorld::AdvanceCurrentScanCode();
for (int curY = minYSector; curY <= maxYSector; curY++) { for (int curY = minYSector; curY <= maxYSector; curY++) {
for (int curX = minXSector; curX <= maxXSector; curX++) { for (int curX = minXSector; curX <= maxXSector; curX++) {
CSector *sector = CWorld::GetSector(curX, curY); CSector *sector = CWorld::GetSector(curX, curY);
FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed, FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed,
minX, minY, maxX, maxY, &lastCloseness, &carBelow); minX, minY, maxX, maxY, &lastCloseness, &carBelow);
FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed, FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed,
minX, minY, maxX, maxY, &lastCloseness, &carBelow); minX, minY, maxX, maxY, &lastCloseness, &carBelow);
} }
} }
} }
// carBelow is now closest vehicle // carBelow is now closest vehicle
if (carBelow && !weAreOnBoat) { if (carBelow && !weAreOnBoat) {
if (carBelow->m_status == STATUS_TRAIN_NOT_MOVING) { if (carBelow->m_status == STATUS_TRAIN_NOT_MOVING) {
m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, carBelow); m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, carBelow);
} else if (carBelow->IsBoat()) { } else if (carBelow->IsBoat()) {
if (!carBelow->pDriver) { if (!carBelow->pDriver) {
m_pPed->m_vehEnterType = 0; m_pPed->m_vehEnterType = 0;
m_pPed->SetEnterCar(carBelow, m_pPed->m_vehEnterType); m_pPed->SetEnterCar(carBelow, m_pPed->m_vehEnterType);
} }
} else { } else {
m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carBelow); m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carBelow);
} }
} }
} }
} }
} }
if (m_bInRemoteMode) { if (m_bInRemoteMode) {
uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar; uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar;
if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) { if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) {
TheCamera.SetFadeColour(0, 0, 0); TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(1.0f, 0); TheCamera.Fade(1.0f, 0);
} }
if (timeWithoutRemoteCar > 2000) { if (timeWithoutRemoteCar > 2000) {
if (m_WBState == WBSTATE_PLAYING) { if (m_WBState == WBSTATE_PLAYING) {
TheCamera.RestoreWithJumpCut(); TheCamera.RestoreWithJumpCut();
TheCamera.SetFadeColour(0, 0, 0); TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(1.0f, 1); TheCamera.Fade(1.0f, 1);
TheCamera.Process(); TheCamera.Process();
CTimer::Stop(); CTimer::Stop();
CCullZones::ForceCullZoneCoors(TheCamera.GetPosition()); CCullZones::ForceCullZoneCoors(TheCamera.GetPosition());
CRenderer::RequestObjectsInFrustum(); CRenderer::RequestObjectsInFrustum();
CStreaming::LoadAllRequestedModels(false); CStreaming::LoadAllRequestedModels(false);
CTimer::Update(); CTimer::Update();
} }
m_bInRemoteMode = false; m_bInRemoteMode = false;
CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil; CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil;
if (FindPlayerVehicle()) { if (FindPlayerVehicle()) {
FindPlayerVehicle()->m_status = STATUS_PLAYER; FindPlayerVehicle()->m_status = STATUS_PLAYER;
} }
} }
} }
if (!(CTimer::GetFrameCounter() & 31)) { if (!(CTimer::GetFrameCounter() & 31)) {
CVehicle *veh = FindPlayerVehicle(); CVehicle *veh = FindPlayerVehicle();
if (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f if (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f
&& veh->m_vecMoveSpeed.Magnitude() < 0.05f && veh->IsCar() && !veh->bIsInWater) { && veh->m_vecMoveSpeed.Magnitude() < 0.05f && veh->IsCar() && !veh->bIsInWater) {
if (veh->GetUp().z < -0.5f) { if (veh->GetUp().z < -0.5f) {
m_nUpsideDownCounter += 2; m_nUpsideDownCounter += 2;
} else { } else {
m_nUpsideDownCounter++; m_nUpsideDownCounter++;
} }
} else { } else {
m_nUpsideDownCounter = 0; m_nUpsideDownCounter = 0;
} }
if (m_nUpsideDownCounter > 6 && veh->bCanBeDamaged) { if (m_nUpsideDownCounter > 6 && veh->bCanBeDamaged) {
veh->m_fHealth = 249.0f < veh->m_fHealth ? 249.0f : veh->m_fHealth; veh->m_fHealth = 249.0f < veh->m_fHealth ? 249.0f : veh->m_fHealth;
if (veh->IsCar()) { if (veh->IsCar()) {
CAutomobile* car = (CAutomobile*)veh; CAutomobile* car = (CAutomobile*)veh;
car->Damage.SetEngineStatus(225); car->Damage.SetEngineStatus(225);
car->m_pSetOnFireEntity = nil; car->m_pSetOnFireEntity = nil;
} }
} }
} }
if (FindPlayerVehicle()) { if (FindPlayerVehicle()) {
CVehicle *veh = FindPlayerVehicle(); CVehicle *veh = FindPlayerVehicle();
veh->m_nZoneLevel = -1; veh->m_nZoneLevel = -1;
for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) { for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {
if (veh->pPassengers[i]) if (veh->pPassengers[i])
veh->pPassengers[i]->m_nZoneLevel = 0; veh->pPassengers[i]->m_nZoneLevel = 0;
} }
CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled; CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled;
} else { } else {
CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled; CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled;
} }
} }
STARTPATCHES STARTPATCHES

View File

@ -1,8 +1,14 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "Pools.h" #include "Pools.h"
#include "World.h"
#include "Boat.h"
#include "CarCtrl.h"
#include "Population.h"
#include "ProjectileInfo.h" #include "ProjectileInfo.h"
#include "Streaming.h"
#include "Wanted.h"
#include "World.h"
CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044; CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044;
CEntryInfoNodePool *&CPools::ms_pEntryInfoNodePool = *(CEntryInfoNodePool**)0x941448; CEntryInfoNodePool *&CPools::ms_pEntryInfoNodePool = *(CEntryInfoNodePool**)0x941448;
@ -14,13 +20,6 @@ CObjectPool *&CPools::ms_pObjectPool = *(CObjectPool**)0x880E28;
CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18; CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18;
CAudioScriptObjectPool *&CPools::ms_pAudioScriptObjectPool = *(CAudioScriptObjectPool**)0x8F1B6C; CAudioScriptObjectPool *&CPools::ms_pAudioScriptObjectPool = *(CAudioScriptObjectPool**)0x8F1B6C;
WRAPPER void CPools::LoadObjectPool(uint8* buf, uint32 size) { EAXJMP(0x4a2550); }
WRAPPER void CPools::LoadPedPool(uint8* buf, uint32 size) { EAXJMP(0x4a2b50); }
WRAPPER void CPools::LoadVehiclePool(uint8* buf, uint32 size) { EAXJMP(0x4a1b40); }
WRAPPER void CPools::SaveObjectPool(uint8* buf, uint32 *size) { EAXJMP(0x4a22d0); }
WRAPPER void CPools::SavePedPool(uint8* buf, uint32 *size) { EAXJMP(0x4a29b0); }
WRAPPER void CPools::SaveVehiclePool(uint8* buf, uint32 *size) { EAXJMP(0x4a2080); }
void void
CPools::Initialise(void) CPools::Initialise(void)
{ {
@ -99,6 +98,333 @@ CPools::MakeSureSlotInObjectPoolIsEmpty(int32 slot)
} }
} }
void CPools::LoadVehiclePool(uint8* buf, uint32 size)
{
INITSAVEBUF
int nNumCars = ReadSaveBuf<int>(buf);
int nNumBoats = ReadSaveBuf<int>(buf);
for (int i = 0; i < nNumCars + nNumBoats; i++) {
uint32 type = ReadSaveBuf<uint32>(buf);
int16 model = ReadSaveBuf<int16>(buf);
CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY);
CStreaming::LoadAllRequestedModels(false);
int32 slot = ReadSaveBuf<int32>(buf);
CVehicle* pVehicle;
char* vbuf = new char[max(sizeof(CAutomobile), sizeof(CBoat))];
if (type == VEHICLE_TYPE_BOAT) {
memcpy(vbuf, buf, sizeof(CBoat));
SkipSaveBuf(buf, sizeof(CBoat));
CBoat* pBoat = new(slot) CBoat(model, RANDOM_VEHICLE);
pVehicle = pBoat;
--CCarCtrl::NumRandomCars; // why?
}
else if (type == VEHICLE_TYPE_CAR) {
memcpy(vbuf, buf, sizeof(CAutomobile));
SkipSaveBuf(buf, sizeof(CAutomobile));
CStreaming::RequestModel(model, 0); // is it needed?
CStreaming::LoadAllRequestedModels(false);
CAutomobile* pAutomobile = new(slot) CAutomobile(model, RANDOM_VEHICLE);
pVehicle = pAutomobile;
CCarCtrl::NumRandomCars--; // why?
pAutomobile->Damage = ((CAutomobile*)vbuf)->Damage;
pAutomobile->SetupDamageAfterLoad();
}
else
assert(0);
CVehicle* pBufferVehicle = (CVehicle*)vbuf;
pVehicle->GetMatrix() = pBufferVehicle->GetMatrix();
pVehicle->VehicleCreatedBy = pBufferVehicle->VehicleCreatedBy;
pVehicle->m_currentColour1 = pBufferVehicle->m_currentColour1;
pVehicle->m_currentColour2 = pBufferVehicle->m_currentColour2;
pVehicle->m_nAlarmState = pBufferVehicle->m_nAlarmState;
pVehicle->m_nNumMaxPassengers = pBufferVehicle->m_nNumMaxPassengers;
pVehicle->field_1D0[0] = pBufferVehicle->field_1D0[0];
pVehicle->field_1D0[1] = pBufferVehicle->field_1D0[1];
pVehicle->field_1D0[2] = pBufferVehicle->field_1D0[2];
pVehicle->field_1D0[3] = pBufferVehicle->field_1D0[3];
pVehicle->m_fSteerAngle = pBufferVehicle->m_fSteerAngle;
pVehicle->m_fGasPedal = pBufferVehicle->m_fGasPedal;
pVehicle->m_fBrakePedal = pBufferVehicle->m_fBrakePedal;
pVehicle->bIsLawEnforcer = pBufferVehicle->bIsLawEnforcer;
pVehicle->bIsLocked = pBufferVehicle->bIsLocked;
pVehicle->bEngineOn = pBufferVehicle->bEngineOn;
pVehicle->bIsHandbrakeOn = pBufferVehicle->bIsHandbrakeOn;
pVehicle->bLightsOn = pBufferVehicle->bLightsOn;
pVehicle->bFreebies = pBufferVehicle->bFreebies;
pVehicle->m_fHealth = pBufferVehicle->m_fHealth;
pVehicle->m_nCurrentGear = pBufferVehicle->m_nCurrentGear;
pVehicle->m_fChangeGearTime = pBufferVehicle->m_fChangeGearTime;
pVehicle->m_nTimeOfDeath = pBufferVehicle->m_nTimeOfDeath;
#ifdef FIX_BUGS //must be copypaste
pVehicle->m_nBombTimer = pBufferVehicle->m_nBombTimer;
#else
pVehicle->m_nTimeOfDeath = pBufferVehicle->m_nTimeOfDeath;
#endif
pVehicle->m_nDoorLock = pBufferVehicle->m_nDoorLock;
pVehicle->m_status = pBufferVehicle->m_status;
pVehicle->m_type = pBufferVehicle->m_type;
(pVehicle->GetAddressOfEntityProperties())[0] = (pBufferVehicle->GetAddressOfEntityProperties())[0];
(pVehicle->GetAddressOfEntityProperties())[1] = (pBufferVehicle->GetAddressOfEntityProperties())[1];
pVehicle->AutoPilot = pBufferVehicle->AutoPilot;
CWorld::Add(pVehicle);
delete[] vbuf;
}
VALIDATESAVEBUF(size)
}
void CPools::SaveVehiclePool(uint8* buf, uint32* size)
{
INITSAVEBUF
int nNumCars = 0;
int nNumBoats = 0;
int nPoolSize = GetVehiclePool()->GetSize();
for (int i = 0; i < nPoolSize; i++) {
CVehicle* pVehicle = GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
bool bHasPassenger = false;
for (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {
if (pVehicle->pPassengers[i])
bHasPassenger = true;
}
if (!pVehicle->pDriver && !bHasPassenger) {
if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE)
++nNumCars;
if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE)
++nNumBoats;
}
}
*size = nNumCars * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + sizeof(CAutomobile)) + sizeof(int) +
nNumBoats * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + sizeof(CBoat)) + sizeof(int);
WriteSaveBuf(buf, nNumCars);
WriteSaveBuf(buf, nNumBoats);
for (int i = 0; i < nPoolSize; i++) {
CVehicle* pVehicle = GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
bool bHasPassenger = false;
for (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {
if (pVehicle->pPassengers[j])
bHasPassenger = true;
}
if (!pVehicle->pDriver && !bHasPassenger) {
if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
WriteSaveBuf(buf, (uint32)pVehicle->m_vehType);
WriteSaveBuf(buf, pVehicle->m_modelIndex);
WriteSaveBuf(buf, GetVehicleRef(pVehicle));
memcpy(buf, pVehicle, sizeof(CAutomobile));
SkipSaveBuf(buf, sizeof(CAutomobile));
}
if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
WriteSaveBuf(buf, (uint32)pVehicle->m_vehType);
WriteSaveBuf(buf, pVehicle->m_modelIndex);
WriteSaveBuf(buf, GetVehicleRef(pVehicle));
memcpy(buf, pVehicle, sizeof(CBoat));
SkipSaveBuf(buf, sizeof(CBoat));
}
}
}
VALIDATESAVEBUF(*size)
}
void CPools::SaveObjectPool(uint8* buf, uint32* size)
{
INITSAVEBUF
CProjectileInfo::RemoveAllProjectiles();
CObject::DeleteAllTempObjects();
int nObjects = 0;
int nPoolSize = GetObjectPool()->GetSize();
for (int i = 0; i < nPoolSize; i++) {
CObject* pObject = GetObjectPool()->GetSlot(i);
if (!pObject)
continue;
if (pObject->ObjectCreatedBy == MISSION_OBJECT)
++nObjects;
}
*size = nObjects * (sizeof(int16) + sizeof(int) + sizeof(CCompressedMatrixNotAligned) + sizeof(uint32) +
sizeof(float) + sizeof(CCompressedMatrixNotAligned) + sizeof(uint32) + sizeof(int8) + 7 * sizeof(bool) + sizeof(float) +
sizeof(int8) + sizeof(int8) + sizeof(uint32) + 2 * sizeof(uint32)) + sizeof(int);
WriteSaveBuf(buf, nObjects);
for (int i = 0; i < nPoolSize; i++) {
CObject* pObject = GetObjectPool()->GetSlot(i);
if (!pObject)
continue;
if (pObject->ObjectCreatedBy == MISSION_OBJECT) {
bool bIsPickup = pObject->bIsPickup;
bool bFlag2 = pObject->m_obj_flag2;
bool bOutOfStock = pObject->bOutOfStock;
bool bGlassCracked = pObject->bGlassCracked;
bool bGlassBroken = pObject->bGlassBroken;
bool bHasBeenDamaged = pObject->bHasBeenDamaged;
bool bUseVehicleColours = pObject->bUseVehicleColours;
CCompressedMatrixNotAligned tmp;
WriteSaveBuf(buf, pObject->m_modelIndex);
WriteSaveBuf(buf, GetObjectRef(pObject));
tmp.CompressFromFullMatrix(pObject->GetMatrix());
WriteSaveBuf(buf, tmp);
WriteSaveBuf(buf, (uint32)0); // game writes ununitialized data here
WriteSaveBuf(buf, pObject->m_fUprootLimit);
tmp.CompressFromFullMatrix(pObject->m_objectMatrix);
WriteSaveBuf(buf, tmp);
WriteSaveBuf(buf, (uint32)0); // same
WriteSaveBuf(buf, pObject->ObjectCreatedBy);
WriteSaveBuf(buf, bIsPickup);
WriteSaveBuf(buf, bFlag2);
WriteSaveBuf(buf, bOutOfStock);
WriteSaveBuf(buf, bGlassCracked);
WriteSaveBuf(buf, bGlassBroken);
WriteSaveBuf(buf, bHasBeenDamaged);
WriteSaveBuf(buf, bUseVehicleColours);
WriteSaveBuf(buf, pObject->m_fCollisionDamageMultiplier);
WriteSaveBuf(buf, pObject->m_nCollisionDamageEffect);
WriteSaveBuf(buf, pObject->m_nSpecialCollisionResponseCases);
WriteSaveBuf(buf, pObject->m_nEndOfLifeTime);
WriteSaveBuf(buf, (pObject->GetAddressOfEntityProperties())[0]);
WriteSaveBuf(buf, (pObject->GetAddressOfEntityProperties())[1]);
}
}
VALIDATESAVEBUF(*size)
}
void CPools::LoadObjectPool(uint8* buf, uint32 size)
{
INITSAVEBUF
int nObjects = ReadSaveBuf<int>(buf);
for (int i = 0; i < nObjects; i++) {
int16 mi = ReadSaveBuf<int16>(buf);
int ref = ReadSaveBuf<int>(buf);
char* obuf = new char[sizeof(CObject)];
CObject* pBufferObject = (CObject*)obuf;
CCompressedMatrixNotAligned tmp;
tmp = ReadSaveBuf<CCompressedMatrixNotAligned>(buf);
tmp.DecompressIntoFullMatrix(pBufferObject->GetMatrix());
ReadSaveBuf<uint32>(buf);
pBufferObject->m_fUprootLimit = ReadSaveBuf<float>(buf);
tmp = ReadSaveBuf<CCompressedMatrixNotAligned>(buf);
tmp.DecompressIntoFullMatrix(pBufferObject->m_objectMatrix);
ReadSaveBuf<uint32>(buf);
pBufferObject->ObjectCreatedBy = ReadSaveBuf<int8>(buf);
pBufferObject->bIsPickup = ReadSaveBuf<bool>(buf);
pBufferObject->m_flagE2 = ReadSaveBuf<bool>(buf);
pBufferObject->bOutOfStock = ReadSaveBuf<bool>(buf);
pBufferObject->bGlassCracked = ReadSaveBuf<bool>(buf);
pBufferObject->bGlassBroken = ReadSaveBuf<bool>(buf);
pBufferObject->bHasBeenDamaged = ReadSaveBuf<bool>(buf);
pBufferObject->bUseVehicleColours = ReadSaveBuf<bool>(buf);
pBufferObject->m_fCollisionDamageMultiplier = ReadSaveBuf<float>(buf);
pBufferObject->m_nCollisionDamageEffect = ReadSaveBuf<uint8>(buf);
pBufferObject->m_nSpecialCollisionResponseCases = ReadSaveBuf<uint8>(buf);
pBufferObject->m_nEndOfLifeTime = ReadSaveBuf<uint32>(buf);
(pBufferObject->GetAddressOfEntityProperties())[0] = ReadSaveBuf<uint32>(buf);
(pBufferObject->GetAddressOfEntityProperties())[1] = ReadSaveBuf<uint32>(buf);
if (GetObjectPool()->GetSlot(ref >> 8))
CPopulation::ConvertToDummyObject(GetObjectPool()->GetSlot(ref >> 8));
CObject* pObject = new(ref) CObject(mi, false);
pObject->GetMatrix() = pBufferObject->GetMatrix();
pObject->m_fUprootLimit = pBufferObject->m_fUprootLimit;
pObject->m_objectMatrix = pBufferObject->m_objectMatrix;
pObject->ObjectCreatedBy = pBufferObject->ObjectCreatedBy;
pObject->bIsPickup = pBufferObject->bIsPickup;
pObject->m_flagE2 = pBufferObject->m_flagE2;
pObject->bOutOfStock = pBufferObject->bOutOfStock;
pObject->bGlassCracked = pBufferObject->bGlassCracked;
pObject->bGlassBroken = pBufferObject->bGlassBroken;
pObject->bHasBeenDamaged = pBufferObject->bHasBeenDamaged;
pObject->bUseVehicleColours = pBufferObject->bUseVehicleColours;
pObject->m_fCollisionDamageMultiplier = pBufferObject->m_fCollisionDamageMultiplier;
pObject->m_nCollisionDamageEffect = pBufferObject->m_nCollisionDamageEffect;
pObject->m_nSpecialCollisionResponseCases = pBufferObject->m_nSpecialCollisionResponseCases;
pObject->m_nEndOfLifeTime = pBufferObject->m_nEndOfLifeTime;
(pObject->GetAddressOfEntityProperties())[0] = (pBufferObject->GetAddressOfEntityProperties())[0];
(pObject->GetAddressOfEntityProperties())[1] = (pBufferObject->GetAddressOfEntityProperties())[1];
pObject->bHasCollided = false;
CWorld::Add(pObject);
delete[] obuf;
}
VALIDATESAVEBUF(size)
}
void CPools::SavePedPool(uint8* buf, uint32* size)
{
INITSAVEBUF
int nNumPeds = 0;
int nPoolSize = GetPedPool()->GetSize();
for (int i = 0; i < nPoolSize; i++) {
CPed* pPed = GetPedPool()->GetSlot(i);
if (!pPed)
continue;
if (!pPed->bInVehicle && pPed->m_nPedType == PEDTYPE_PLAYER1)
nNumPeds++;
}
*size = sizeof(int) + nNumPeds * (sizeof(uint32) + sizeof(int16) + sizeof(int) + sizeof(CPlayerPed) +
sizeof(CWanted::MaximumWantedLevel) + sizeof(CWanted::nMaximumWantedLevel) + MAX_MODEL_NAME);
WriteSaveBuf(buf, nNumPeds);
for (int i = 0; i < nPoolSize; i++) {
CPed* pPed = GetPedPool()->GetSlot(i);
if (!pPed)
continue;
if (!pPed->bInVehicle && pPed->m_nPedType == PEDTYPE_PLAYER1) {
WriteSaveBuf(buf, pPed->m_nPedType);
WriteSaveBuf(buf, pPed->m_modelIndex);
WriteSaveBuf(buf, GetPedRef(pPed));
memcpy(buf, pPed, sizeof(CPlayerPed));
SkipSaveBuf(buf, sizeof(CPlayerPed));
WriteSaveBuf(buf, CWanted::MaximumWantedLevel);
WriteSaveBuf(buf, CWanted::nMaximumWantedLevel);
memcpy(buf, CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetName(), MAX_MODEL_NAME);
SkipSaveBuf(buf, MAX_MODEL_NAME);
}
}
VALIDATESAVEBUF(*size);
}
void CPools::LoadPedPool(uint8* buf, uint32 size)
{
INITSAVEBUF
int nPeds = ReadSaveBuf<int>(buf);
for (int i = 0; i < nPeds; i++) {
uint32 pedtype = ReadSaveBuf<uint32>(buf);
int16 model = ReadSaveBuf<int16>(buf);
int ref = ReadSaveBuf<int>(buf);
char* pbuf = new char[sizeof(CPlayerPed)];
CPlayerPed* pBufferPlayer = (CPlayerPed*)pbuf;
CPed* pPed;
char name[MAX_MODEL_NAME];
// the code implies that there was idea to load non-player ped
if (pedtype == PEDTYPE_PLAYER1) { // always true
memcpy(pbuf, buf, sizeof(CPlayerPed));
SkipSaveBuf(buf, sizeof(CPlayerPed));
CWanted::MaximumWantedLevel = ReadSaveBuf<int32>(buf);
CWanted::nMaximumWantedLevel = ReadSaveBuf<int32>(buf);
memcpy(name, buf, MAX_MODEL_NAME);
SkipSaveBuf(buf, MAX_MODEL_NAME);
}
CStreaming::RequestSpecialModel(model, name, STREAMFLAGS_DONT_REMOVE);
CStreaming::LoadAllRequestedModels(false);
if (pedtype == PEDTYPE_PLAYER1) {
CPlayerPed* pPlayerPed = new(ref) CPlayerPed();
for (int i = 0; i < ARRAY_SIZE(pPlayerPed->m_nTargettableObjects); i++)
pPlayerPed->m_nTargettableObjects[i] = pBufferPlayer->m_nTargettableObjects[i];
pPlayerPed->m_fMaxStamina = pBufferPlayer->m_fMaxStamina;
pPed = pPlayerPed;
}
pPed->GetPosition() = pBufferPlayer->GetPosition();
pPed->m_fHealth = pBufferPlayer->m_fHealth;
pPed->m_fArmour = pBufferPlayer->m_fArmour;
pPed->CharCreatedBy = pBufferPlayer->CharCreatedBy;
pPed->m_currentWeapon = 0;
pPed->m_maxWeaponTypeAllowed = pBufferPlayer->m_maxWeaponTypeAllowed;
for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++)
pPed->m_weapons[i] = pBufferPlayer->m_weapons[i];
if (pedtype == PEDTYPE_PLAYER1) {
pPed->m_wepAccuracy = 100;
CWorld::Players[0].m_pPed = (CPlayerPed*)pPed;
}
CWorld::Add(pPed);
delete[] pbuf;
}
VALIDATESAVEBUF(size)
}
STARTPATCHES STARTPATCHES
InjectHook(0x4A1770, CPools::Initialise, PATCH_JUMP); InjectHook(0x4A1770, CPools::Initialise, PATCH_JUMP);
@ -111,4 +437,7 @@ STARTPATCHES
InjectHook(0x4A1B00, CPools::GetObjectRef, PATCH_JUMP); InjectHook(0x4A1B00, CPools::GetObjectRef, PATCH_JUMP);
InjectHook(0x4A1B20, CPools::GetObject, PATCH_JUMP); InjectHook(0x4A1B20, CPools::GetObject, PATCH_JUMP);
InjectHook(0x4A2DB0, CPools::MakeSureSlotInObjectPoolIsEmpty, PATCH_JUMP); InjectHook(0x4A2DB0, CPools::MakeSureSlotInObjectPoolIsEmpty, PATCH_JUMP);
InjectHook(0x4A1B40, CPools::LoadVehiclePool, PATCH_JUMP);
InjectHook(0x4A2550, CPools::LoadObjectPool, PATCH_JUMP);
InjectHook(0x4A2B50, CPools::LoadPedPool, PATCH_JUMP);
ENDPATCHES ENDPATCHES

71
src/core/Profile.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "common.h"
#include "Profile.h"
#ifndef MASTER
float CProfile::ms_afStartTime[NUM_PROFILES];
float CProfile::ms_afCumulativeTime[NUM_PROFILES];
float CProfile::ms_afEndTime[NUM_PROFILES];
float CProfile::ms_afMaxEndTime[NUM_PROFILES];
float CProfile::ms_afMaxCumulativeTime[NUM_PROFILES];
char *CProfile::ms_pProfileString[NUM_PROFILES];
RwRGBA CProfile::ms_aBarColours[NUM_PROFILES];
void CProfile::Initialise()
{
ms_afMaxEndTime[PROFILE_FRAME_RATE] = 0.0f;
ms_afMaxEndTime[PROFILE_PHYSICS] = 0.0f;
ms_afMaxEndTime[PROFILE_COLLISION] = 0.0f;
ms_afMaxEndTime[PROFILE_PED_AI] = 0.0f;
ms_afMaxEndTime[PROFILE_PROCESSING_TIME] = 0.0f;
ms_afMaxEndTime[PROFILE_RENDERING_TIME] = 0.0f;
ms_afMaxEndTime[PROFILE_TOTAL] = 0.0f;
ms_pProfileString[PROFILE_FRAME_RATE] = "Frame rate";
ms_pProfileString[PROFILE_PHYSICS] = "Physics";
ms_pProfileString[PROFILE_COLLISION] = "Collision";
ms_pProfileString[PROFILE_PED_AI] = "Ped AI";
ms_pProfileString[PROFILE_PROCESSING_TIME] = "Processing time";
ms_pProfileString[PROFILE_RENDERING_TIME] = "Rendering time";
ms_pProfileString[PROFILE_TOTAL] = "Total";
ms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = 0.0f;
ms_afMaxCumulativeTime[PROFILE_PHYSICS] = 0.0f;
ms_afMaxCumulativeTime[PROFILE_COLLISION] = 0.0f;
ms_afMaxCumulativeTime[PROFILE_PED_AI] = 0.0f;
ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = 0.0f;
ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = 0.0f;
ms_afMaxCumulativeTime[PROFILE_TOTAL] = 0.0f;
ms_aBarColours[PROFILE_PHYSICS] = { 0, 127, 255, 255 };
ms_aBarColours[PROFILE_COLLISION] = { 0, 255, 255, 255 };
ms_aBarColours[PROFILE_PED_AI] = { 255, 0, 0, 255 };
ms_aBarColours[PROFILE_PROCESSING_TIME] = { 0, 255, 0, 255 };
ms_aBarColours[PROFILE_RENDERING_TIME] = { 0, 0, 255, 255 };
ms_aBarColours[PROFILE_TOTAL] = { 255, 255, 255, 255 };
}
void CProfile::SuspendProfile(eProfile profile)
{
ms_afEndTime[profile] = -ms_afStartTime[profile];
ms_afCumulativeTime[profile] -= ms_afStartTime[profile];
}
void CProfile::ShowResults()
{
ms_afMaxEndTime[PROFILE_FRAME_RATE] = max(ms_afMaxEndTime[PROFILE_FRAME_RATE], ms_afEndTime[PROFILE_FRAME_RATE]);
ms_afMaxEndTime[PROFILE_PHYSICS] = max(ms_afMaxEndTime[PROFILE_PHYSICS], ms_afEndTime[PROFILE_PHYSICS]);
ms_afMaxEndTime[PROFILE_COLLISION] = max(ms_afMaxEndTime[PROFILE_COLLISION], ms_afEndTime[PROFILE_COLLISION]);
ms_afMaxEndTime[PROFILE_PED_AI] = max(ms_afMaxEndTime[PROFILE_PED_AI], ms_afEndTime[PROFILE_PED_AI]);
ms_afMaxEndTime[PROFILE_PROCESSING_TIME] = max(ms_afMaxEndTime[PROFILE_PROCESSING_TIME], ms_afEndTime[PROFILE_PROCESSING_TIME]);
ms_afMaxEndTime[PROFILE_RENDERING_TIME] = max(ms_afMaxEndTime[PROFILE_RENDERING_TIME], ms_afEndTime[PROFILE_RENDERING_TIME]);
ms_afMaxEndTime[PROFILE_TOTAL] = max(ms_afMaxEndTime[PROFILE_TOTAL], ms_afEndTime[PROFILE_TOTAL]);
ms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = max(ms_afMaxCumulativeTime[PROFILE_FRAME_RATE], ms_afCumulativeTime[PROFILE_FRAME_RATE]);
ms_afMaxCumulativeTime[PROFILE_PHYSICS] = max(ms_afMaxCumulativeTime[PROFILE_PHYSICS], ms_afCumulativeTime[PROFILE_PHYSICS]);
ms_afMaxCumulativeTime[PROFILE_COLLISION] = max(ms_afMaxCumulativeTime[PROFILE_COLLISION], ms_afCumulativeTime[PROFILE_COLLISION]);
ms_afMaxCumulativeTime[PROFILE_PED_AI] = max(ms_afMaxCumulativeTime[PROFILE_PED_AI], ms_afCumulativeTime[PROFILE_PED_AI]);
ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = max(ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME], ms_afCumulativeTime[PROFILE_PROCESSING_TIME]);
ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = max(ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME], ms_afCumulativeTime[PROFILE_RENDERING_TIME]);
ms_afMaxCumulativeTime[PROFILE_TOTAL] = max(ms_afMaxCumulativeTime[PROFILE_TOTAL], ms_afCumulativeTime[PROFILE_TOTAL]);
}
#endif

28
src/core/Profile.h Normal file
View File

@ -0,0 +1,28 @@
#pragma once
enum eProfile
{
PROFILE_FRAME_RATE,
PROFILE_PHYSICS,
PROFILE_COLLISION,
PROFILE_PED_AI,
PROFILE_PROCESSING_TIME,
PROFILE_RENDERING_TIME,
PROFILE_TOTAL,
NUM_PROFILES,
};
class CProfile
{
static float ms_afStartTime[NUM_PROFILES];
static float ms_afCumulativeTime[NUM_PROFILES];
static float ms_afEndTime[NUM_PROFILES];
static float ms_afMaxEndTime[NUM_PROFILES];
static float ms_afMaxCumulativeTime[NUM_PROFILES];
static char *ms_pProfileString[NUM_PROFILES];
static RwRGBA ms_aBarColours[NUM_PROFILES];
public:
static void Initialise();
static void SuspendProfile(eProfile profile);
static void ShowResults();
};

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,10 @@ enum eBlipDisplay
enum eRadarSprite enum eRadarSprite
{ {
#ifdef MENU_MAP
RADAR_SPRITE_ENTITY_BLIP = -2,
RADAR_SPRITE_COORD_BLIP = -1,
#endif
RADAR_SPRITE_NONE = 0, RADAR_SPRITE_NONE = 0,
RADAR_SPRITE_ASUKA = 1, RADAR_SPRITE_ASUKA = 1,
RADAR_SPRITE_BOMB = 2, RADAR_SPRITE_BOMB = 2,
@ -52,7 +56,7 @@ enum
BLIP_MODE_SQUARE, BLIP_MODE_SQUARE,
}; };
struct CBlip struct sRadarTrace
{ {
uint32 m_nColor; uint32 m_nColor;
uint32 m_eBlipType; // eBlipType uint32 m_eBlipType; // eBlipType
@ -65,9 +69,9 @@ struct CBlip
float m_Radius; float m_Radius;
int16 m_wScale; int16 m_wScale;
uint16 m_eBlipDisplay; // eBlipDisplay uint16 m_eBlipDisplay; // eBlipDisplay
uint16 m_IconID; // eRadarSprite uint16 m_eRadarSprite; // eRadarSprite
}; };
static_assert(sizeof(CBlip) == 0x30, "CBlip: error"); static_assert(sizeof(sRadarTrace) == 0x30, "sRadarTrace: error");
// Values for screen space // Values for screen space
#define RADAR_LEFT (40.0f) #define RADAR_LEFT (40.0f)
@ -79,7 +83,7 @@ class CRadar
{ {
public: public:
static float &m_radarRange; static float &m_radarRange;
static CBlip (&ms_RadarTrace)[NUMRADARBLIPS]; static sRadarTrace (&ms_RadarTrace)[NUMRADARBLIPS];
static CSprite2d AsukaSprite; static CSprite2d AsukaSprite;
static CSprite2d BombSprite; static CSprite2d BombSprite;
static CSprite2d CatSprite; static CSprite2d CatSprite;
@ -101,8 +105,20 @@ public:
static CSprite2d TonySprite; static CSprite2d TonySprite;
static CSprite2d WeaponSprite; static CSprite2d WeaponSprite;
static CSprite2d *RadarSprites[21]; static CSprite2d *RadarSprites[21];
static float cachedCos;
static float cachedSin;
#ifdef MENU_MAP
#define NUM_MAP_LEGENDS 75
static CRGBA ArrowBlipColour1;
static CRGBA ArrowBlipColour2;
static uint16 MapLegendList[NUM_MAP_LEGENDS];
static uint16 MapLegendCounter;
static int TargetMarkerId;
public: static void InitFrontEndMap();
static void DrawYouAreHereSprite(float, float);
static void ToggleTargetMarker(float, float);
#endif
static uint8 CalculateBlipAlpha(float dist); static uint8 CalculateBlipAlpha(float dist);
static void ChangeBlipBrightness(int32 i, int32 bright); static void ChangeBlipBrightness(int32 i, int32 bright);
static void ChangeBlipColour(int32 i, int32); static void ChangeBlipColour(int32 i, int32);
@ -128,7 +144,6 @@ public:
static void LoadAllRadarBlips(uint8 *buf, uint32 size); static void LoadAllRadarBlips(uint8 *buf, uint32 size);
static void LoadTextures(); static void LoadTextures();
static void RemoveRadarSections(); static void RemoveRadarSections();
static void RequestMapSection(int32 x, int32 y);
static void SaveAllRadarBlips(uint8*, uint32*); static void SaveAllRadarBlips(uint8*, uint32*);
static void SetBlipSprite(int32 i, int32 icon); static void SetBlipSprite(int32 i, int32 icon);
static int32 SetCoordBlip(eBlipType type, CVector pos, int32, eBlipDisplay); static int32 SetCoordBlip(eBlipType type, CVector pos, int32, eBlipDisplay);
@ -145,9 +160,6 @@ public:
static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in); static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in);
static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in); static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in);
// no in CRadar in the game: // no in CRadar in the game:
static void GetTextureCorners(int32 x, int32 y, CVector2D *out); static void CalculateCachedSinCos();
static void ClipRadarTileCoords(int32 &x, int32 &y);
static bool IsPointInsideRadar(const CVector2D &);
static int LineRadarBoxCollision(CVector2D &, const CVector2D &, const CVector2D &);
}; };

View File

@ -1,140 +0,0 @@
#pragma warning( push )
#pragma warning( disable : 4005)
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#pragma warning( pop )
#include "common.h"
#include "win.h"
#include "patcher.h"
#include "Timer.h"
float &texLoadTime = *(float*)0x8F1B50;
int32 &texNumLoaded = *(int32*)0x8F252C;
RwTexture*
RwTextureGtaStreamRead(RwStream *stream)
{
RwUInt32 size, version;
RwTexture *tex;
if(!RwStreamFindChunk(stream, rwID_TEXTURENATIVE, &size, &version))
return nil;
float preloadTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();
if(!RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, &tex, size)))
return nil;
if (gGameState == GS_INIT_PLAYING_GAME) {
texLoadTime = (texNumLoaded * texLoadTime + (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond() - preloadTime) / (float)(texNumLoaded+1);
texNumLoaded++;
}
return tex;
}
RwTexture*
destroyTexture(RwTexture *texture, void *data)
{
RwTextureDestroy(texture);
return texture;
}
RwTexDictionary*
RwTexDictionaryGtaStreamRead(RwStream *stream)
{
RwUInt32 size, version;
RwInt32 numTextures;
RwTexDictionary *texDict;
RwTexture *tex;
if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))
return nil;
assert(size == 4);
if(RwStreamRead(stream, &numTextures, size) != size)
return nil;
texDict = RwTexDictionaryCreate();
if(texDict == nil)
return nil;
while(numTextures--){
tex = RwTextureGtaStreamRead(stream);
if(tex == nil){
RwTexDictionaryForAllTextures(texDict, destroyTexture, nil);
RwTexDictionaryDestroy(texDict);
return nil;
}
RwTexDictionaryAddTexture(texDict, tex);
}
return texDict;
}
static int32 numberTextures = -1;
static int32 streamPosition;
RwTexDictionary*
RwTexDictionaryGtaStreamRead1(RwStream *stream)
{
RwUInt32 size, version;
RwInt32 numTextures;
RwTexDictionary *texDict;
RwTexture *tex;
numberTextures = 0;
if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))
return nil;
assert(size == 4);
if(RwStreamRead(stream, &numTextures, size) != size)
return nil;
texDict = RwTexDictionaryCreate();
if(texDict == nil)
return nil;
numberTextures = numTextures/2;
while(numTextures > numberTextures){
numTextures--;
tex = RwTextureGtaStreamRead(stream);
if(tex == nil){
RwTexDictionaryForAllTextures(texDict, destroyTexture, nil);
RwTexDictionaryDestroy(texDict);
return nil;
}
RwTexDictionaryAddTexture(texDict, tex);
}
numberTextures = numTextures;
streamPosition = stream->Type.memory.position;
return texDict;
}
RwTexDictionary*
RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)
{
RwTexture *tex;
RwStreamSkip(stream, streamPosition - stream->Type.memory.position);
while(numberTextures--){
tex = RwTextureGtaStreamRead(stream);
if(tex == nil){
RwTexDictionaryForAllTextures(texDict, destroyTexture, nil);
RwTexDictionaryDestroy(texDict);
return nil;
}
RwTexDictionaryAddTexture(texDict, tex);
}
return texDict;
}
STARTPATCHES
InjectHook(0x592380, RwTextureGtaStreamRead, PATCH_JUMP);
InjectHook(0x5924A0, RwTexDictionaryGtaStreamRead, PATCH_JUMP);
InjectHook(0x592550, RwTexDictionaryGtaStreamRead1, PATCH_JUMP);
InjectHook(0x592650, RwTexDictionaryGtaStreamRead2, PATCH_JUMP);
ENDPATCHES

View File

@ -1,18 +1,18 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "Stats.h" #include "Stats.h"
#include "Text.h"
WRAPPER void CStats::SaveStats(uint8 *buf, uint32 *size) { EAXJMP(0x4ab3e0); } #include "World.h"
int32 &CStats::DaysPassed = *(int32*)0x8F2BB8; int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
int32 &CStats::HeadsPopped = *(int32*)0x8F647C; int32 &CStats::HeadsPopped = *(int32*)0x8F647C;
bool& CStats::CommercialPassed = *(bool*)0x8F4334; int32& CStats::CommercialPassed = *(int32*)0x8F4334;
bool& CStats::IndustrialPassed = *(bool*)0x8E2A68; int32& CStats::IndustrialPassed = *(int32*)0x8E2A68;
bool& CStats::SuburbanPassed = *(bool*)0x8F2740; int32& CStats::SuburbanPassed = *(int32*)0x8F2740;
int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C; int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50; int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64; int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64;
int32 *CStats::PedsKilledOfThisType = (int32*)0x880DBC; int32(&CStats::PedsKilledOfThisType)[NUM_PEDTYPES] = *(int32(*)[NUM_PEDTYPES]) * (uintptr*)0x880DBC;
int32 &CStats::TimesDied = *(int32*)0x8E2BDC; int32 &CStats::TimesDied = *(int32*)0x8E2BDC;
int32 &CStats::TimesArrested = *(int32*)0x8E2BEC; int32 &CStats::TimesArrested = *(int32*)0x8E2BEC;
int32 &CStats::KillsSinceLastCheckpoint = *(int32*)0x8F2C8C; int32 &CStats::KillsSinceLastCheckpoint = *(int32*)0x8F2C8C;
@ -48,11 +48,73 @@ int32& CStats::LongestFlightInDodo = *(int32*)0x8F5FE4;
int32& CStats::TimeTakenDefuseMission = *(int32*)0x880E24; int32& CStats::TimeTakenDefuseMission = *(int32*)0x880E24;
int32& CStats::TotalNumberKillFrenzies = *(int32*)0x8E2884; int32& CStats::TotalNumberKillFrenzies = *(int32*)0x8E2884;
int32& CStats::TotalNumberMissions = *(int32*)0x8E2820; int32& CStats::TotalNumberMissions = *(int32*)0x8E2820;
int32& CStats::KgOfExplosivesUsed = *(int32*)0x8F2510; int32& CStats::RoundsFiredByPlayer = *(int32*)0x8E2BE8;
int32& CStats::KgsOfExplosivesUsed = *(int32*)0x8F2510;
int32& CStats::InstantHitsFiredByPlayer = *(int32*)0x943070;
int32& CStats::InstantHitsHitByPlayer = *(int32*)0x95CB8C;
int32& CStats::BestTimeBombDefusal = *(int32*)0x880E24;
int32& CStats::mmRain = *(int32*)0x8F2C98;
int32& CStats::CarsCrushed = *(int32*)0x943050; int32& CStats::CarsCrushed = *(int32*)0x943050;
int32(&CStats::FastestTimes)[CStats::TOTAL_FASTEST_TIMES] = *(int32(*)[CStats::TOTAL_FASTEST_TIMES])*(uintptr*)0x6E9128; int32(&CStats::FastestTimes)[CStats::TOTAL_FASTEST_TIMES] = *(int32(*)[CStats::TOTAL_FASTEST_TIMES])*(uintptr*)0x6E9128;
int32(&CStats::HighestScores)[CStats::TOTAL_HIGHEST_SCORES] = *(int32(*)[CStats::TOTAL_HIGHEST_SCORES]) * (uintptr*)0x8622B0; int32(&CStats::HighestScores)[CStats::TOTAL_HIGHEST_SCORES] = *(int32(*)[CStats::TOTAL_HIGHEST_SCORES]) * (uintptr*)0x8622B0;
void CStats::Init()
{
PeopleKilledByOthers = 0;
PeopleKilledByPlayer = 0;
RoundsFiredByPlayer = 0;
CarsExploded = 0;
HelisDestroyed = 0;
ProgressMade = 0;
KgsOfExplosivesUsed = 0;
InstantHitsFiredByPlayer = 0;
InstantHitsHitByPlayer = 0;
CarsCrushed = 0;
HeadsPopped = 0;
TimesArrested = 0;
TimesDied = 0;
DaysPassed = 0;
NumberOfUniqueJumpsFound = 0;
mmRain = 0;
MaximumJumpFlips = 0;
MaximumJumpSpins = 0;
MaximumJumpDistance = 0;
MaximumJumpHeight = 0;
BestStuntJump = 0;
TotalNumberOfUniqueJumps = 0;
Record4x4One = 0;
LongestFlightInDodo = 0;
Record4x4Two = 0;
PassengersDroppedOffWithTaxi = 0;
Record4x4Three = 0;
MoneyMadeWithTaxi = 0;
Record4x4Mayhem = 0;
LivesSavedWithAmbulance = 0;
ElBurroTime = 0;
CriminalsCaught = 0;
MissionsGiven = 0;
HighestLevelAmbulanceMission = 0;
MissionsPassed = 0;
FiresExtinguished = 0;
DistanceTravelledOnFoot = 0;
TimeTakenDefuseMission = 0;
NumberKillFrenziesPassed = 0;
DistanceTravelledInVehicle = 0;
TotalNumberKillFrenzies = 0;
TotalNumberMissions = 0;
KillsSinceLastCheckpoint = 0;
TotalLegitimateKills = 0;
for (int i = 0; i < TOTAL_FASTEST_TIMES; i++)
FastestTimes[i] = 0;
for (int i = 0; i < TOTAL_HIGHEST_SCORES; i++)
HighestScores[i] = 0;
for (int i = 0; i < NUM_PEDTYPES; i++)
PedsKilledOfThisType[i] = 0;
IndustrialPassed = 0;
CommercialPassed = 0;
SuburbanPassed = 0;
}
void CStats::RegisterFastestTime(int32 index, int32 time) void CStats::RegisterFastestTime(int32 index, int32 time)
{ {
assert(index >= 0 && index < TOTAL_FASTEST_TIMES); assert(index >= 0 && index < TOTAL_FASTEST_TIMES);
@ -138,4 +200,229 @@ void CStats::SetTotalNumberMissions(int32 total)
TotalNumberMissions = total; TotalNumberMissions = total;
} }
WRAPPER void CStats::Init() { EAXJMP(0x4AAC60); } wchar *CStats::FindCriminalRatingString()
{
int rating = FindCriminalRatingNumber();
if (rating < 10) return TheText.Get("RATNG1");
if (rating < 25) return TheText.Get("RATNG2");
if (rating < 70) return TheText.Get("RATNG3");
if (rating < 150) return TheText.Get("RATNG4");
if (rating < 250) return TheText.Get("RATNG5");
if (rating < 450) return TheText.Get("RATNG6");
if (rating < 700) return TheText.Get("RATNG7");
if (rating < 1000) return TheText.Get("RATNG8");
if (rating < 1400) return TheText.Get("RATNG9");
if (rating < 1900) return TheText.Get("RATNG10");
if (rating < 2500) return TheText.Get("RATNG11");
if (rating < 3200) return TheText.Get("RATNG12");
if (rating < 4000) return TheText.Get("RATNG13");
if (rating < 5000) return TheText.Get("RATNG14");
return TheText.Get("RATNG15");
}
int32 CStats::FindCriminalRatingNumber()
{
int32 rating;
rating = FiresExtinguished + 10 * HighestLevelAmbulanceMission + CriminalsCaught + LivesSavedWithAmbulance
+ 30 * HelisDestroyed + TotalLegitimateKills - 3 * TimesArrested - 3 * TimesDied
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney / 5000;
if (rating <= 0) rating = 0;
if (InstantHitsFiredByPlayer > 100)
rating += (float)CStats::InstantHitsHitByPlayer / (float)CStats::InstantHitsFiredByPlayer * 500.0f;
if (TotalProgressInGame)
rating += (float)CStats::ProgressMade / (float)CStats::TotalProgressInGame * 1000.0f;
if (!IndustrialPassed && rating >= 3521)
rating = 3521;
if (!CommercialPassed && rating >= 4552)
rating = 4552;
return rating;
}
void CStats::SaveStats(uint8 *buf, uint32 *size)
{
CheckPointReachedSuccessfully();
uint8 *buf_start = buf;
*size = sizeof(PeopleKilledByPlayer) +
sizeof(PeopleKilledByOthers) +
sizeof(CarsExploded) +
sizeof(RoundsFiredByPlayer) +
sizeof(PedsKilledOfThisType) +
sizeof(HelisDestroyed) +
sizeof(ProgressMade) +
sizeof(TotalProgressInGame) +
sizeof(KgsOfExplosivesUsed) +
sizeof(InstantHitsFiredByPlayer) +
sizeof(InstantHitsHitByPlayer) +
sizeof(CarsCrushed) +
sizeof(HeadsPopped) +
sizeof(TimesArrested) +
sizeof(TimesDied) +
sizeof(DaysPassed) +
sizeof(mmRain) +
sizeof(MaximumJumpDistance) +
sizeof(MaximumJumpHeight) +
sizeof(MaximumJumpFlips) +
sizeof(MaximumJumpSpins) +
sizeof(BestStuntJump) +
sizeof(NumberOfUniqueJumpsFound) +
sizeof(TotalNumberOfUniqueJumps) +
sizeof(MissionsGiven) +
sizeof(MissionsPassed) +
sizeof(PassengersDroppedOffWithTaxi) +
sizeof(MoneyMadeWithTaxi) +
sizeof(IndustrialPassed) +
sizeof(CommercialPassed) +
sizeof(SuburbanPassed) +
sizeof(ElBurroTime) +
sizeof(DistanceTravelledOnFoot) +
sizeof(DistanceTravelledInVehicle) +
sizeof(Record4x4One) +
sizeof(Record4x4Two) +
sizeof(Record4x4Three) +
sizeof(Record4x4Mayhem) +
sizeof(LivesSavedWithAmbulance) +
sizeof(CriminalsCaught) +
sizeof(HighestLevelAmbulanceMission) +
sizeof(FiresExtinguished) +
sizeof(LongestFlightInDodo) +
sizeof(TimeTakenDefuseMission) +
sizeof(NumberKillFrenziesPassed) +
sizeof(TotalNumberKillFrenzies) +
sizeof(TotalNumberMissions) +
sizeof(FastestTimes) +
sizeof(HighestScores) +
sizeof(KillsSinceLastCheckpoint) +
sizeof(TotalLegitimateKills) +
sizeof(LastMissionPassedName);
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data);
CopyToBuf(buf, PeopleKilledByPlayer);
CopyToBuf(buf, PeopleKilledByOthers);
CopyToBuf(buf, CarsExploded);
CopyToBuf(buf, RoundsFiredByPlayer);
CopyToBuf(buf, PedsKilledOfThisType);
CopyToBuf(buf, HelisDestroyed);
CopyToBuf(buf, ProgressMade);
CopyToBuf(buf, TotalProgressInGame);
CopyToBuf(buf, KgsOfExplosivesUsed);
CopyToBuf(buf, InstantHitsFiredByPlayer);
CopyToBuf(buf, InstantHitsHitByPlayer);
CopyToBuf(buf, CarsCrushed);
CopyToBuf(buf, HeadsPopped);
CopyToBuf(buf, TimesArrested);
CopyToBuf(buf, TimesDied);
CopyToBuf(buf, DaysPassed);
CopyToBuf(buf, mmRain);
CopyToBuf(buf, MaximumJumpDistance);
CopyToBuf(buf, MaximumJumpHeight);
CopyToBuf(buf, MaximumJumpFlips);
CopyToBuf(buf, MaximumJumpSpins);
CopyToBuf(buf, BestStuntJump);
CopyToBuf(buf, NumberOfUniqueJumpsFound);
CopyToBuf(buf, TotalNumberOfUniqueJumps);
CopyToBuf(buf, MissionsGiven);
CopyToBuf(buf, MissionsPassed);
CopyToBuf(buf, PassengersDroppedOffWithTaxi);
CopyToBuf(buf, MoneyMadeWithTaxi);
CopyToBuf(buf, IndustrialPassed);
CopyToBuf(buf, CommercialPassed);
CopyToBuf(buf, SuburbanPassed);
CopyToBuf(buf, ElBurroTime);
CopyToBuf(buf, DistanceTravelledOnFoot);
CopyToBuf(buf, DistanceTravelledInVehicle);
CopyToBuf(buf, Record4x4One);
CopyToBuf(buf, Record4x4Two);
CopyToBuf(buf, Record4x4Three);
CopyToBuf(buf, Record4x4Mayhem);
CopyToBuf(buf, LivesSavedWithAmbulance);
CopyToBuf(buf, CriminalsCaught);
CopyToBuf(buf, HighestLevelAmbulanceMission);
CopyToBuf(buf, FiresExtinguished);
CopyToBuf(buf, LongestFlightInDodo);
CopyToBuf(buf, TimeTakenDefuseMission);
CopyToBuf(buf, NumberKillFrenziesPassed);
CopyToBuf(buf, TotalNumberKillFrenzies);
CopyToBuf(buf, TotalNumberMissions);
CopyToBuf(buf, FastestTimes);
CopyToBuf(buf, HighestScores);
CopyToBuf(buf, KillsSinceLastCheckpoint);
CopyToBuf(buf, TotalLegitimateKills);
CopyToBuf(buf, LastMissionPassedName);
assert(buf - buf_start == *size);
#undef CopyToBuf
}
void CStats::LoadStats(uint8 *buf, uint32 size)
{
uint8* buf_start = buf;
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); buf += sizeof(data);
CopyFromBuf(buf, PeopleKilledByPlayer);
CopyFromBuf(buf, PeopleKilledByOthers);
CopyFromBuf(buf, CarsExploded);
CopyFromBuf(buf, RoundsFiredByPlayer);
CopyFromBuf(buf, PedsKilledOfThisType);
CopyFromBuf(buf, HelisDestroyed);
CopyFromBuf(buf, ProgressMade);
CopyFromBuf(buf, TotalProgressInGame);
CopyFromBuf(buf, KgsOfExplosivesUsed);
CopyFromBuf(buf, InstantHitsFiredByPlayer);
CopyFromBuf(buf, InstantHitsHitByPlayer);
CopyFromBuf(buf, CarsCrushed);
CopyFromBuf(buf, HeadsPopped);
CopyFromBuf(buf, TimesArrested);
CopyFromBuf(buf, TimesDied);
CopyFromBuf(buf, DaysPassed);
CopyFromBuf(buf, mmRain);
CopyFromBuf(buf, MaximumJumpDistance);
CopyFromBuf(buf, MaximumJumpHeight);
CopyFromBuf(buf, MaximumJumpFlips);
CopyFromBuf(buf, MaximumJumpSpins);
CopyFromBuf(buf, BestStuntJump);
CopyFromBuf(buf, NumberOfUniqueJumpsFound);
CopyFromBuf(buf, TotalNumberOfUniqueJumps);
CopyFromBuf(buf, MissionsGiven);
CopyFromBuf(buf, MissionsPassed);
CopyFromBuf(buf, PassengersDroppedOffWithTaxi);
CopyFromBuf(buf, MoneyMadeWithTaxi);
CopyFromBuf(buf, IndustrialPassed);
CopyFromBuf(buf, CommercialPassed);
CopyFromBuf(buf, SuburbanPassed);
CopyFromBuf(buf, ElBurroTime);
CopyFromBuf(buf, DistanceTravelledOnFoot);
CopyFromBuf(buf, DistanceTravelledInVehicle);
CopyFromBuf(buf, Record4x4One);
CopyFromBuf(buf, Record4x4Two);
CopyFromBuf(buf, Record4x4Three);
CopyFromBuf(buf, Record4x4Mayhem);
CopyFromBuf(buf, LivesSavedWithAmbulance);
CopyFromBuf(buf, CriminalsCaught);
CopyFromBuf(buf, HighestLevelAmbulanceMission);
CopyFromBuf(buf, FiresExtinguished);
CopyFromBuf(buf, LongestFlightInDodo);
CopyFromBuf(buf, TimeTakenDefuseMission);
CopyFromBuf(buf, NumberKillFrenziesPassed);
CopyFromBuf(buf, TotalNumberKillFrenzies);
CopyFromBuf(buf, TotalNumberMissions);
CopyFromBuf(buf, FastestTimes);
CopyFromBuf(buf, HighestScores);
CopyFromBuf(buf, KillsSinceLastCheckpoint);
CopyFromBuf(buf, TotalLegitimateKills);
CopyFromBuf(buf, LastMissionPassedName);
assert(buf - buf_start == size);
#undef CopyFromBuf
}
STARTPATCHES
InjectHook(0x48C5A3, CStats::Init, PATCH_JUMP); // CGame::ReInitGameObjectVariables
InjectHook(0x4AB3E0, CStats::SaveStats, PATCH_JUMP);
InjectHook(0x4AB670, CStats::LoadStats, PATCH_JUMP);
InjectHook(0x4AB090, CStats::FindCriminalRatingString, PATCH_JUMP);
InjectHook(0x4AB2A0, CStats::FindCriminalRatingNumber, PATCH_JUMP);
ENDPATCHES

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "PedType.h"
class CStats class CStats
{ {
public: public:
@ -8,14 +10,14 @@ public:
TOTAL_HIGHEST_SCORES = 16 TOTAL_HIGHEST_SCORES = 16
}; };
static int32 &DaysPassed; static int32 &DaysPassed;
static int32 &HeadsPopped; static int32 &HeadsPopped;
static bool& CommercialPassed; static int32& CommercialPassed;
static bool& IndustrialPassed; static int32& IndustrialPassed;
static bool& SuburbanPassed; static int32& SuburbanPassed;
static int32 &NumberKillFrenziesPassed; static int32 &NumberKillFrenziesPassed;
static int32 &PeopleKilledByOthers; static int32 &PeopleKilledByOthers;
static int32 &HelisDestroyed; static int32 &HelisDestroyed;
static int32 *PedsKilledOfThisType; //[NUM_PEDTYPES] static int32(&PedsKilledOfThisType)[ePedType::NUM_PEDTYPES];
static int32 &TimesDied; static int32 &TimesDied;
static int32 &TimesArrested; static int32 &TimesArrested;
static int32 &KillsSinceLastCheckpoint; static int32 &KillsSinceLastCheckpoint;
@ -50,32 +52,39 @@ public:
static int32 &LongestFlightInDodo; static int32 &LongestFlightInDodo;
static int32 &TimeTakenDefuseMission; static int32 &TimeTakenDefuseMission;
static int32 &TotalNumberKillFrenzies; static int32 &TotalNumberKillFrenzies;
static int32 &TotalNumberMissions; static int32 &TotalNumberMissions;
static int32 &RoundsFiredByPlayer;
static int32 &KgsOfExplosivesUsed;
static int32 &InstantHitsFiredByPlayer;
static int32 &InstantHitsHitByPlayer;
static int32 &BestTimeBombDefusal;
static int32 &mmRain;
static int32 &CarsCrushed;
static int32(&FastestTimes)[TOTAL_FASTEST_TIMES]; static int32(&FastestTimes)[TOTAL_FASTEST_TIMES];
static int32(&HighestScores)[TOTAL_HIGHEST_SCORES]; static int32(&HighestScores)[TOTAL_HIGHEST_SCORES];
static int32 &KgOfExplosivesUsed;
static int32 &CarsCrushed;
public: public:
static void Init(void);
static void RegisterFastestTime(int32, int32); static void RegisterFastestTime(int32, int32);
static void RegisterHighestScore(int32, int32); static void RegisterHighestScore(int32, int32);
static void AnotherKillFrenzyPassed(); static void RegisterElBurroTime(int32);
static void AnotherLifeSavedWithAmbulance();
static void AnotherCriminalCaught();
static void RegisterLevelAmbulanceMission(int32);
static void AnotherFireExtinguished();
static void Register4x4OneTime(int32); static void Register4x4OneTime(int32);
static void Register4x4TwoTime(int32); static void Register4x4TwoTime(int32);
static void Register4x4ThreeTime(int32); static void Register4x4ThreeTime(int32);
static void Register4x4MayhemTime(int32); static void Register4x4MayhemTime(int32);
static void AnotherLifeSavedWithAmbulance();
static void AnotherCriminalCaught();
static void RegisterLevelAmbulanceMission(int32);
static void AnotherFireExtinguished();
static wchar *FindCriminalRatingString();
static void RegisterLongestFlightInDodo(int32); static void RegisterLongestFlightInDodo(int32);
static void RegisterTimeTakenDefuseMission(int32); static void RegisterTimeTakenDefuseMission(int32);
static void AnotherKillFrenzyPassed();
static void SetTotalNumberKillFrenzies(int32); static void SetTotalNumberKillFrenzies(int32);
static void SetTotalNumberMissions(int32); static void SetTotalNumberMissions(int32);
static void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; };
static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; }; static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; };
static void RegisterElBurroTime(int32); static void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; };
static int32 FindCriminalRatingNumber();
static void SaveStats(uint8 *buf, uint32 *size); static void SaveStats(uint8 *buf, uint32 *size);
static void LoadStats(uint8 *buf, uint32 size);
static void Init(void);
}; };

View File

@ -1247,8 +1247,8 @@ CStreaming::StreamVehiclesAndPeds(void)
static int timeBeforeNextLoad = 0; static int timeBeforeNextLoad = 0;
static int modelQualityClass = 0; static int modelQualityClass = 0;
if(CRecordDataForGame::RecordingState == RECORDSTATE_1 || if(CRecordDataForGame::IsRecording() ||
CRecordDataForGame::RecordingState == RECORDSTATE_2) CRecordDataForGame::IsPlayingBack())
return; return;
if(FindPlayerPed()->m_pWanted->AreSwatRequired()){ if(FindPlayerPed()->m_pWanted->AreSwatRequired()){

View File

@ -34,6 +34,10 @@ LARGE_INTEGER &perfSuspendCounter = *(LARGE_INTEGER*)0x62A318;
//UInt32 suspendDepth; //UInt32 suspendDepth;
uint32 &suspendDepth = *(uint32*)0x62A320; uint32 &suspendDepth = *(uint32*)0x62A320;
#ifdef FIX_BUGS
double frameTime;
#endif
void CTimer::Initialise(void) void CTimer::Initialise(void)
{ {
debug("Initialising CTimer...\n"); debug("Initialising CTimer...\n");
@ -90,17 +94,21 @@ void CTimer::Update(void)
float updInCyclesScaled = updInCycles * ms_fTimeScale; float updInCyclesScaled = updInCycles * ms_fTimeScale;
double upd = updInCyclesScaled / (double)_nCyclesPerMS; // We need that real frame time to fix transparent menu bug.
#ifndef FIX_BUGS
double
#endif
frameTime = updInCyclesScaled / (double)_nCyclesPerMS;
m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + upd; m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime;
if ( GetIsPaused() ) if ( GetIsPaused() )
ms_fTimeStep = 0.0f; ms_fTimeStep = 0.0f;
else else
{ {
m_snTimeInMilliseconds = m_snTimeInMilliseconds + upd; m_snTimeInMilliseconds = m_snTimeInMilliseconds + frameTime;
m_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + upd; m_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + frameTime;
ms_fTimeStep = updInCyclesScaled / (double)_nCyclesPerMS / 20.0f; ms_fTimeStep = frameTime / 1000.0f * 50.0f;
} }
} }
else else
@ -109,19 +117,23 @@ void CTimer::Update(void)
uint32 updInMs = timer - oldPcTimer; uint32 updInMs = timer - oldPcTimer;
double upd = (double)updInMs * ms_fTimeScale; // We need that real frame time to fix transparent menu bug.
#ifndef FIX_BUGS
double
#endif
frameTime = (double)updInMs * ms_fTimeScale;
oldPcTimer = timer; oldPcTimer = timer;
m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + upd; m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime;
if ( GetIsPaused() ) if ( GetIsPaused() )
ms_fTimeStep = 0.0f; ms_fTimeStep = 0.0f;
else else
{ {
m_snTimeInMilliseconds = m_snTimeInMilliseconds + upd; m_snTimeInMilliseconds = m_snTimeInMilliseconds + frameTime;
m_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + upd; m_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + frameTime;
ms_fTimeStep = upd / 1000.0f * 50.0f; ms_fTimeStep = frameTime / 1000.0f * 50.0f;
} }
} }
@ -130,7 +142,7 @@ void CTimer::Update(void)
ms_fTimeStepNonClipped = ms_fTimeStep; ms_fTimeStepNonClipped = ms_fTimeStep;
if ( CRecordDataForGame::RecordingState != RECORDSTATE_2 ) if ( !CRecordDataForGame::IsPlayingBack() )
{ {
ms_fTimeStep = min(3.0f, ms_fTimeStep); ms_fTimeStep = min(3.0f, ms_fTimeStep);
@ -138,7 +150,7 @@ void CTimer::Update(void)
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60; m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60;
} }
if ( CRecordDataForChase::Status == RECORDSTATE_1 ) if ( CRecordDataForChase::IsRecording() )
{ {
ms_fTimeStep = 1.0f; ms_fTimeStep = 1.0f;
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 16; m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 16;

View File

@ -21,6 +21,7 @@ public:
static float GetTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; } static float GetTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; }
static const float &GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; } static const float &GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; }
static float GetTimeStepNonClippedInSeconds(void) { return ms_fTimeStepNonClipped / 50.0f; } static float GetTimeStepNonClippedInSeconds(void) { return ms_fTimeStepNonClipped / 50.0f; }
static float GetTimeStepNonClippedInMilliseconds(void) { return ms_fTimeStepNonClipped / 50.0f * 1000.0f; }
static void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; } static void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; }
static const uint32 &GetFrameCounter(void) { return m_FrameCounter; } static const uint32 &GetFrameCounter(void) { return m_FrameCounter; }
static void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; } static void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; }
@ -52,4 +53,11 @@ public:
static void Stop(void); static void Stop(void);
static void StartUserPause(void); static void StartUserPause(void);
static void EndUserPause(void); static void EndUserPause(void);
friend bool GenericLoad(void);
friend bool GenericSave(int file);
}; };
#ifdef FIX_BUGS
extern double frameTime;
#endif

View File

@ -56,6 +56,8 @@ WRAPPER void CWorld::FindMissionEntitiesIntersectingCube(const CVector&, const C
WRAPPER void CWorld::ClearCarsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B50E0); } WRAPPER void CWorld::ClearCarsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B50E0); }
WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); } WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); }
WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); } WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); }
WRAPPER void CWorld::TriggerExplosion(const CVector& a1, float a2, float a3, CEntity *a4, bool a5) { EAXJMP(0x4B1140); }
WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); }
void void
CWorld::Initialise() CWorld::Initialise()

View File

@ -132,6 +132,7 @@ public:
static void SetAllCarsCanBeDamaged(bool); static void SetAllCarsCanBeDamaged(bool);
static void ExtinguishAllCarFiresInArea(CVector, float); static void ExtinguishAllCarFiresInArea(CVector, float);
static void SetCarsOnFire(float, float, float, float, CEntity*); static void SetCarsOnFire(float, float, float, float, CEntity*);
static void SetPedsOnFire(float, float, float, float, CEntity*);
static void Initialise(); static void Initialise();
static void AddParticles(); static void AddParticles();
@ -140,6 +141,7 @@ public:
static void RepositionCertainDynamicObjects(); static void RepositionCertainDynamicObjects();
static void RemoveStaticObjects(); static void RemoveStaticObjects();
static void Process(); static void Process();
static void TriggerExplosion(const CVector &, float, float, CEntity*, bool);
}; };
extern CColPoint *gaTempSphereColPoints; extern CColPoint *gaTempSphereColPoints;

View File

@ -74,9 +74,11 @@ inline uint32 ldb(uint32 p, uint32 s, uint32 w)
} }
#ifndef RWLIBS
// little hack // little hack
extern void **rwengine; extern void **rwengine;
#define RwEngineInstance (*rwengine) #define RwEngineInstance (*rwengine)
#endif
#include "skeleton.h" #include "skeleton.h"
#include "Draw.h" #include "Draw.h"
@ -84,12 +86,14 @@ extern void **rwengine;
#define DEFAULT_SCREEN_WIDTH (640) #define DEFAULT_SCREEN_WIDTH (640)
#define DEFAULT_SCREEN_HEIGHT (448) #define DEFAULT_SCREEN_HEIGHT (448)
#define DEFAULT_ASPECT_RATIO (4.0f/3.0f) #define DEFAULT_ASPECT_RATIO (4.0f/3.0f)
#define DEFAULT_VIEWWINDOW (0.7f)
// game uses maximumWidth/Height, but this probably won't work // game uses maximumWidth/Height, but this probably won't work
// with RW windowed mode // with RW windowed mode
#define SCREEN_WIDTH ((float)RsGlobal.width) #define SCREEN_WIDTH ((float)RsGlobal.width)
#define SCREEN_HEIGHT ((float)RsGlobal.height) #define SCREEN_HEIGHT ((float)RsGlobal.height)
#define SCREEN_ASPECT_RATIO (CDraw::GetAspectRatio()) #define SCREEN_ASPECT_RATIO (CDraw::GetAspectRatio())
#define SCREEN_VIEWWINDOW (Tan(DEGTORAD(CDraw::GetFOV() * 0.5f)))
// This scales from PS2 pixel coordinates to the real resolution // This scales from PS2 pixel coordinates to the real resolution
#define SCREEN_STRETCH_X(a) ((a) * (float) SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH) #define SCREEN_STRETCH_X(a) ((a) * (float) SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH)
@ -105,10 +109,8 @@ extern void **rwengine;
#ifdef ASPECT_RATIO_SCALE #ifdef ASPECT_RATIO_SCALE
#define SCREEN_SCALE_AR(a) ((a) * DEFAULT_ASPECT_RATIO / SCREEN_ASPECT_RATIO) #define SCREEN_SCALE_AR(a) ((a) * DEFAULT_ASPECT_RATIO / SCREEN_ASPECT_RATIO)
#define SCREEN_SCALE_AR2(a) ((a) / (DEFAULT_ASPECT_RATIO / SCREEN_ASPECT_RATIO))
#else #else
#define SCREEN_SCALE_AR(a) (a) #define SCREEN_SCALE_AR(a) (a)
#define SCREEN_SCALE_AR2(a) (a)
#endif #endif
#include "maths.h" #include "maths.h"

View File

@ -73,9 +73,13 @@ enum Config {
NUMCORONAS = 56, NUMCORONAS = 56,
NUMPOINTLIGHTS = 32, NUMPOINTLIGHTS = 32,
NUM3DMARKERS = 32, NUM3DMARKERS = 32,
NUMBRIGHTLIGHTS = 32,
NUMSHINYTEXTS = 32,
NUMMONEYMESSAGES = 16, NUMMONEYMESSAGES = 16,
NUMPICKUPMESSAGES = 16, NUMPICKUPMESSAGES = 16,
NUMBULLETTRACES = 16, NUMBULLETTRACES = 16,
NUMMBLURSTREAKS = 4,
NUMSKIDMARKS = 32,
NUMONSCREENTIMERENTRIES = 1, NUMONSCREENTIMERENTRIES = 1,
NUMRADARBLIPS = 32, NUMRADARBLIPS = 32,
@ -83,6 +87,7 @@ enum Config {
NUMSCRIPTEDPICKUPS = 16, NUMSCRIPTEDPICKUPS = 16,
NUMPICKUPS = NUMGENERALPICKUPS + NUMSCRIPTEDPICKUPS, NUMPICKUPS = NUMGENERALPICKUPS + NUMSCRIPTEDPICKUPS,
NUMCOLLECTEDPICKUPS = 20, NUMCOLLECTEDPICKUPS = 20,
NUMPACMANPICKUPS = 256,
NUMEVENTS = 64, NUMEVENTS = 64,
NUM_CARGENS = 160, NUM_CARGENS = 160,
@ -120,7 +125,11 @@ enum Config {
NUM_AUDIO_REFLECTIONS = 5, NUM_AUDIO_REFLECTIONS = 5,
NUM_SCRIPT_MAX_ENTITIES = 40, NUM_SCRIPT_MAX_ENTITIES = 40,
NUM_GARAGE_STORED_CARS = 6 NUM_GARAGE_STORED_CARS = 6,
NUM_CRANES = 8,
NUM_EXPLOSIONS = 48,
}; };
// We'll use this once we're ready to become independent of the game // We'll use this once we're ready to become independent of the game
@ -145,6 +154,7 @@ enum Config {
//#define MASTER //#define MASTER
#if defined GTA_PS2 #if defined GTA_PS2
# define GTA_PS2_STUFF
# define RANDOMSPLASH # define RANDOMSPLASH
#elif defined GTA_PC #elif defined GTA_PC
# define GTA3_1_1_PATCH # define GTA3_1_1_PATCH
@ -183,13 +193,17 @@ enum Config {
// Pad // Pad
#define XINPUT #define XINPUT
#define KANGAROO_CHEAT #define KANGAROO_CHEAT
#define REGISTER_START_BUTTON // currently only in menu sadly. resumes the game #define REGISTER_START_BUTTON
// Hud, frontend and radar // Hud, frontend and radar
#define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios
#define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC #define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC
#define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box #define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box
// #define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc. // #define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc.
#define MENU_MAP // VC-like menu map. Make sure you have new menu.txd
#define SCROLLABLE_STATS_PAGE // only draggable by mouse atm
#define TRIANGLE_BACK_BUTTON
// #define CIRCLE_BACK_BUTTON
// Script // Script
#define USE_DEBUG_SCRIPT_LOADER // makes game load main_freeroam.scm by default #define USE_DEBUG_SCRIPT_LOADER // makes game load main_freeroam.scm by default

File diff suppressed because it is too large Load Diff

View File

@ -1,119 +1,119 @@
#include "common.h" #include "common.h"
#include "Debug.h" #include "Debug.h"
#include "obrstr.h" #include "obrstr.h"
char obrstr[128]; char obrstr[128];
char obrstr2[128]; char obrstr2[128];
void ObrInt(int32 n1) void ObrInt(int32 n1)
{ {
IntToStr(n1, obrstr); IntToStr(n1, obrstr);
CDebug::DebugAddText(obrstr); CDebug::DebugAddText(obrstr);
} }
void ObrInt2(int32 n1, int32 n2) void ObrInt2(int32 n1, int32 n2)
{ {
IntToStr(n1, obrstr); IntToStr(n1, obrstr);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n2, obrstr2); IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr); CDebug::DebugAddText(obrstr);
} }
void ObrInt3(int32 n1, int32 n2, int32 n3) void ObrInt3(int32 n1, int32 n2, int32 n3)
{ {
IntToStr(n1, obrstr); IntToStr(n1, obrstr);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n2, obrstr2); IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n3, obrstr2); IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr); CDebug::DebugAddText(obrstr);
} }
void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4) void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4)
{ {
IntToStr(n1, obrstr); IntToStr(n1, obrstr);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n2, obrstr2); IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n3, obrstr2); IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n4, obrstr2); IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr); CDebug::DebugAddText(obrstr);
} }
void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5) void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5)
{ {
IntToStr(n1, obrstr); IntToStr(n1, obrstr);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n2, obrstr2); IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n3, obrstr2); IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n4, obrstr2); IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n5, obrstr2); IntToStr(n5, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr); CDebug::DebugAddText(obrstr);
} }
void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6) void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
{ {
IntToStr(n1, obrstr); IntToStr(n1, obrstr);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n2, obrstr2); IntToStr(n2, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n3, obrstr2); IntToStr(n3, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n4, obrstr2); IntToStr(n4, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n5, obrstr2); IntToStr(n5, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
strcat(obrstr, " "); strcat(obrstr, " ");
IntToStr(n6, obrstr2); IntToStr(n6, obrstr2);
strcat(obrstr, obrstr2); strcat(obrstr, obrstr2);
CDebug::DebugAddText(obrstr); CDebug::DebugAddText(obrstr);
} }
void IntToStr(int32 inNum, char *outStr) void IntToStr(int32 inNum, char *outStr)
{ {
bool isNeg = inNum < 0; bool isNeg = inNum < 0;
if (isNeg) { if (isNeg) {
inNum = -inNum; inNum = -inNum;
*outStr = '-'; *outStr = '-';
} }
int16 digits = 1; int16 digits = 1;
if (inNum > 9) { if (inNum > 9) {
int32 _inNum = inNum; int32 _inNum = inNum;
do { do {
digits++; digits++;
_inNum /= 10; _inNum /= 10;
} while (_inNum > 9); } while (_inNum > 9);
} }
int32 strSize = digits; int32 strSize = digits;
if (isNeg) if (isNeg)
strSize++; strSize++;
char *pStr = &outStr[strSize]; char *pStr = &outStr[strSize];
int32 i = 0; int32 i = 0;
do { do {
*(pStr-- - 1) = (inNum % 10) + '0'; *(pStr-- - 1) = (inNum % 10) + '0';
inNum /= 10; inNum /= 10;
} while (++i < strSize); } while (++i < strSize);
outStr[strSize] = '\0'; outStr[strSize] = '\0';
} }

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
void ObrInt(int32 n1); void ObrInt(int32 n1);
void ObrInt2(int32 n1, int32 n2); void ObrInt2(int32 n1, int32 n2);
void ObrInt3(int32 n1, int32 n2, int32 n3); void ObrInt3(int32 n1, int32 n2, int32 n3);
void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4); void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4);
void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5); void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5);
void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6); void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
void IntToStr(int32 inNum, char *outStr); void IntToStr(int32 inNum, char *outStr);

View File

@ -21,10 +21,15 @@
#include "Particle.h" #include "Particle.h"
#include "Console.h" #include "Console.h"
#include "Debug.h" #include "Debug.h"
#include "Hud.h"
#include <list> #include <list>
#ifndef RWLIBS
void **rwengine = *(void***)0x5A10E1; void **rwengine = *(void***)0x5A10E1;
#else
extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list _ArgList);
#endif
DebugMenuAPI gDebugMenuAPI; DebugMenuAPI gDebugMenuAPI;
@ -144,19 +149,6 @@ SpawnCar(int id)
} }
} }
static void
LetThemFollowYou(void) {
CPed *player = (CPed*) FindPlayerPed();
for (int i = 0; i < player->m_numNearPeds; i++) {
CPed *nearPed = player->m_nearPeds[i];
if (nearPed && !nearPed->IsPlayer()) {
nearPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, (void*)player);
nearPed->m_pedFormation = (eFormation)(1 + (rand() & 7));
nearPed->bScriptObjectiveCompleted = false;
}
}
}
static void static void
FixCar(void) FixCar(void)
{ {
@ -337,7 +329,9 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Spawn", "Spawn Dodo", [](){ SpawnCar(MI_DODO); }); DebugMenuAddCmd("Spawn", "Spawn Dodo", [](){ SpawnCar(MI_DODO); });
DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); }); DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); });
DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); }); DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); });
DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); });
DebugMenuAddVarBool8("Debug", "Draw hud", (int8*)&CHud::m_Wants_To_Draw_Hud, nil);
DebugMenuAddVar("Debug", "Engine Status", &engineStatus, nil, 1, 0, 226, nil); DebugMenuAddVar("Debug", "Engine Status", &engineStatus, nil, 1, 0, 226, nil);
DebugMenuAddCmd("Debug", "Set Engine Status", SetEngineStatus); DebugMenuAddCmd("Debug", "Set Engine Status", SetEngineStatus);
DebugMenuAddCmd("Debug", "Fix Car", FixCar); DebugMenuAddCmd("Debug", "Fix Car", FixCar);
@ -350,6 +344,9 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway);
DebugMenuAddVarBool8("Debug", "Script Heli On", (int8*)0x95CD43, nil); DebugMenuAddVarBool8("Debug", "Script Heli On", (int8*)0x95CD43, nil);
DebugMenuAddVarBool8("Debug", "Show Ped Paths", (int8*)&gbShowPedPaths, nil);
DebugMenuAddVarBool8("Debug", "Show Car Paths", (int8*)&gbShowCarPaths, nil);
DebugMenuAddVarBool8("Debug", "Show Car Path Links", (int8*)&gbShowCarPathsLinks, nil);
DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil); DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil);
DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil); DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil);
DebugMenuAddVarBool8("Debug", "Show Collision Lines", (int8*)&gbShowCollisionLines, nil); DebugMenuAddVarBool8("Debug", "Show Collision Lines", (int8*)&gbShowCollisionLines, nil);
@ -359,8 +356,6 @@ DebugMenuPopulate(void)
DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil); DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil);
DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil); DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil);
DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil);
DebugMenuAddCmd("Debug", "Make peds follow you in formation", LetThemFollowYou);
#ifdef TOGGLEABLE_BETA_FEATURES #ifdef TOGGLEABLE_BETA_FEATURES
DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil); DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil);
DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil); DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil);
@ -458,7 +453,7 @@ void re3_debug(const char *format, ...)
vsprintf_s(re3_buff, re3_buffsize, format, va); vsprintf_s(re3_buff, re3_buffsize, format, va);
va_end(va); va_end(va);
// printf("%s", re3_buff); printf("%s", re3_buff);
CDebug::DebugAddText(re3_buff); CDebug::DebugAddText(re3_buff);
} }

View File

@ -1,121 +1,121 @@
#ifndef MASTER #ifndef MASTER
#include "common.h" #include "common.h"
#include "Font.h" #include "Font.h"
#include "Frontend.h" #include "Frontend.h"
#include "Timer.h" #include "Timer.h"
#include "Text.h" #include "Text.h"
#define MAX_TIMERS (50) #define MAX_TIMERS (50)
#define MAX_MS_COLLECTED (40) #define MAX_MS_COLLECTED (40)
// enables frame time output // enables frame time output
#define FRAMETIME #define FRAMETIME
struct sTimeBar struct sTimeBar
{ {
char name[20]; char name[20];
float startTime; float startTime;
float endTime; float endTime;
int32 unk; int32 unk;
}; };
struct struct
{ {
sTimeBar Timers[MAX_TIMERS]; sTimeBar Timers[MAX_TIMERS];
uint32 count; uint32 count;
} TimerBar; } TimerBar;
float MaxTimes[MAX_TIMERS]; float MaxTimes[MAX_TIMERS];
float MaxFrameTime; float MaxFrameTime;
uint32 curMS; uint32 curMS;
uint32 msCollected[MAX_MS_COLLECTED]; uint32 msCollected[MAX_MS_COLLECTED];
#ifdef FRAMETIME #ifdef FRAMETIME
float FrameInitTime; float FrameInitTime;
#endif #endif
void tbInit() void tbInit()
{ {
TimerBar.count = 0; TimerBar.count = 0;
uint32 i = CTimer::GetFrameCounter() & 0x7F; uint32 i = CTimer::GetFrameCounter() & 0x7F;
if (i == 0) { if (i == 0) {
do do
MaxTimes[i++] = 0.0f; MaxTimes[i++] = 0.0f;
while (i != MAX_TIMERS); while (i != MAX_TIMERS);
#ifdef FRAMETIME #ifdef FRAMETIME
MaxFrameTime = 0.0f; MaxFrameTime = 0.0f;
#endif #endif
} }
#ifdef FRAMETIME #ifdef FRAMETIME
FrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame(); FrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif #endif
} }
void tbStartTimer(int32 unk, char *name) void tbStartTimer(int32 unk, char *name)
{ {
strcpy(TimerBar.Timers[TimerBar.count].name, name); strcpy(TimerBar.Timers[TimerBar.count].name, name);
TimerBar.Timers[TimerBar.count].unk = unk; TimerBar.Timers[TimerBar.count].unk = unk;
TimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame(); TimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
TimerBar.count++; TimerBar.count++;
} }
void tbEndTimer(char* name) void tbEndTimer(char* name)
{ {
uint32 n = 1500; uint32 n = 1500;
for (uint32 i = 0; i < TimerBar.count; i++) { for (uint32 i = 0; i < TimerBar.count; i++) {
if (strcmp(name, TimerBar.Timers[i].name) == 0) if (strcmp(name, TimerBar.Timers[i].name) == 0)
n = i; n = i;
} }
assert(n != 1500); assert(n != 1500);
TimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame(); TimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
} }
float Diag_GetFPS() float Diag_GetFPS()
{ {
return 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]); return 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]);
} }
void tbDisplay() void tbDisplay()
{ {
char temp[200]; char temp[200];
wchar wtemp[200]; wchar wtemp[200];
#ifdef FRAMETIME #ifdef FRAMETIME
float FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame(); float FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif #endif
msCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer(); msCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer();
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128)); CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
CFont::SetScale(0.48f, 1.12f); CFont::SetScale(0.48f, 1.12f);
CFont::SetCentreOff(); CFont::SetCentreOff();
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetWrapx(640.0f); CFont::SetWrapx(640.0f);
CFont::SetRightJustifyOff(); CFont::SetRightJustifyOff();
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
sprintf(temp, "FPS: %.2f", Diag_GetFPS()); sprintf(temp, "FPS: %.2f", Diag_GetFPS());
AsciiToUnicode(temp, wtemp); AsciiToUnicode(temp, wtemp);
CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetColor(CRGBA(255, 255, 255, 255));
if (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) { if (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) {
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp); CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp);
#ifndef FINAL #ifndef FINAL
// Timers output (my own implementation) // Timers output (my own implementation)
for (uint32 i = 0; i < TimerBar.count; i++) { for (uint32 i = 0; i < TimerBar.count; i++) {
MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime); MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime);
sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]); sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]);
AsciiToUnicode(temp, wtemp); AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp); CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp);
} }
#ifdef FRAMETIME #ifdef FRAMETIME
MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime); MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime);
sprintf(temp, "Frame Time: %.2f", MaxFrameTime); sprintf(temp, "Frame Time: %.2f", MaxFrameTime);
AsciiToUnicode(temp, wtemp); AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp); CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp);
#endif // FRAMETIME #endif // FRAMETIME
#endif // !FINAL #endif // !FINAL
} }
} }
#endif // !MASTER #endif // !MASTER

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
void tbInit(); void tbInit();
void tbStartTimer(int32, char*); void tbStartTimer(int32, char*);
void tbEndTimer(char*); void tbEndTimer(char*);
void tbDisplay(); void tbDisplay();

View File

@ -62,11 +62,11 @@ CEntity::CEntity(void)
bRemoveFromWorld = false; bRemoveFromWorld = false;
bHasHitWall = false; bHasHitWall = false;
bImBeingRendered = false; bImBeingRendered = false;
m_flagD8 = false; bTouchingWater = false;
bIsSubway = false; bIsSubway = false;
bDrawLast = false; bDrawLast = false;
bNoBrightHeadLights = false; bNoBrightHeadLights = false;
m_flagD80 = false; bDoNotRender = false;
bDistanceFade = false; bDistanceFade = false;
m_flagE2 = false; m_flagE2 = false;
@ -275,9 +275,9 @@ CEntity::CreateRwObject(void)
if(IsBuilding()) if(IsBuilding())
gBuildings++; gBuildings++;
if(RwObjectGetType(m_rwObject) == rpATOMIC) if(RwObjectGetType(m_rwObject) == rpATOMIC)
m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(m_rwObject)), false); m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP) else if(RwObjectGetType(m_rwObject) == rpCLUMP)
m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame(m_rwObject)), false); m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
mi->AddRef(); mi->AddRef();
} }
} }
@ -290,7 +290,7 @@ CEntity::DeleteRwObject(void)
m_matrix.Detach(); m_matrix.Detach();
if(m_rwObject){ if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC){ if(RwObjectGetType(m_rwObject) == rpATOMIC){
f = RpAtomicGetFrame(m_rwObject); f = RpAtomicGetFrame((RpAtomic*)m_rwObject);
RpAtomicDestroy((RpAtomic*)m_rwObject); RpAtomicDestroy((RpAtomic*)m_rwObject);
RwFrameDestroy(f); RwFrameDestroy(f);
}else if(RwObjectGetType(m_rwObject) == rpCLUMP) }else if(RwObjectGetType(m_rwObject) == rpCLUMP)
@ -307,9 +307,9 @@ CEntity::UpdateRwFrame(void)
{ {
if(m_rwObject){ if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC) if(RwObjectGetType(m_rwObject) == rpATOMIC)
RwFrameUpdateObjects(RpAtomicGetFrame(m_rwObject)); RwFrameUpdateObjects(RpAtomicGetFrame((RpAtomic*)m_rwObject));
else if(RwObjectGetType(m_rwObject) == rpCLUMP) else if(RwObjectGetType(m_rwObject) == rpCLUMP)
RwFrameUpdateObjects(RpClumpGetFrame(m_rwObject)); RwFrameUpdateObjects(RpClumpGetFrame((RpClump*)m_rwObject));
} }
} }
@ -394,13 +394,13 @@ CEntity::PreRender(void)
}else if(GetModelIndex() == MI_GRENADE){ }else if(GetModelIndex() == MI_GRENADE){
CMotionBlurStreaks::RegisterStreak((uintptr)this, CMotionBlurStreaks::RegisterStreak((uintptr)this,
100, 100, 100, 100, 100, 100,
TheCamera.GetPosition() - 0.07f*TheCamera.GetRight(), GetPosition() - 0.07f*TheCamera.GetRight(),
TheCamera.GetPosition() + 0.07f*TheCamera.GetRight()); GetPosition() + 0.07f*TheCamera.GetRight());
}else if(GetModelIndex() == MI_MOLOTOV){ }else if(GetModelIndex() == MI_MOLOTOV){
CMotionBlurStreaks::RegisterStreak((uintptr)this, CMotionBlurStreaks::RegisterStreak((uintptr)this,
0, 100, 0, 0, 100, 0,
TheCamera.GetPosition() - 0.07f*TheCamera.GetRight(), GetPosition() - 0.07f*TheCamera.GetRight(),
TheCamera.GetPosition() + 0.07f*TheCamera.GetRight()); GetPosition() + 0.07f*TheCamera.GetRight());
} }
}else if(GetModelIndex() == MI_MISSILE){ }else if(GetModelIndex() == MI_MISSILE){
CVector pos = GetPosition(); CVector pos = GetPosition();
@ -482,9 +482,9 @@ CEntity::AttachToRwObject(RwObject *obj)
m_rwObject = obj; m_rwObject = obj;
if(m_rwObject){ if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC) if(RwObjectGetType(m_rwObject) == rpATOMIC)
m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame(m_rwObject)), false); m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP) else if(RwObjectGetType(m_rwObject) == rpCLUMP)
m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame(m_rwObject)), false); m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
CModelInfo::GetModelInfo(m_modelIndex)->AddRef(); CModelInfo::GetModelInfo(m_modelIndex)->AddRef();
} }
} }

View File

@ -73,11 +73,11 @@ public:
uint32 bRemoveFromWorld : 1; uint32 bRemoveFromWorld : 1;
uint32 bHasHitWall : 1; uint32 bHasHitWall : 1;
uint32 bImBeingRendered : 1; uint32 bImBeingRendered : 1;
uint32 m_flagD8 : 1; // used by cBuoyancy::ProcessBuoyancy uint32 bTouchingWater : 1; // used by cBuoyancy::ProcessBuoyancy
uint32 bIsSubway : 1; // set when subway, but maybe different meaning? uint32 bIsSubway : 1; // set when subway, but maybe different meaning?
uint32 bDrawLast : 1; uint32 bDrawLast : 1;
uint32 bNoBrightHeadLights : 1; uint32 bNoBrightHeadLights : 1;
uint32 m_flagD80 : 1; // CObject visibility? uint32 bDoNotRender : 1;
// flagsE // flagsE
uint32 bDistanceFade : 1; uint32 bDistanceFade : 1;
@ -90,6 +90,7 @@ public:
CReference *m_pFirstReference; CReference *m_pFirstReference;
CColModel *GetColModel(void) { return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); } CColModel *GetColModel(void) { return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); }
uint32* GetAddressOfEntityProperties() { /* AWFUL */ return (uint32*)((char*)&m_rwObject + sizeof(m_rwObject)); }
CEntity(void); CEntity(void);
~CEntity(void); ~CEntity(void);

View File

@ -21,7 +21,7 @@ CPhysical::CPhysical(void)
{ {
int i; int i;
fForceMultiplier = 1.0f; m_fForceMultiplier = 1.0f;
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f); m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);

View File

@ -29,7 +29,7 @@ public:
CVector m_vecTurnSpeedAvg; CVector m_vecTurnSpeedAvg;
float m_fMass; float m_fMass;
float m_fTurnMass; // moment of inertia float m_fTurnMass; // moment of inertia
float fForceMultiplier; float m_fForceMultiplier;
float m_fAirResistance; float m_fAirResistance;
float m_fElasticity; float m_fElasticity;
float m_fBuoyancy; float m_fBuoyancy;

View File

@ -1,12 +1,12 @@
#pragma once #pragma once
#include "Entity.h" #include "Entity.h"
class CSolid : public CEntity class CSolid : public CEntity
{ {
public: public:
CSolid(void) { CSolid(void) {
m_type = ENTITY_TYPE_BUILDING; m_type = ENTITY_TYPE_BUILDING;
bUsesCollision = true; bUsesCollision = true;
} }
}; };

View File

@ -243,6 +243,17 @@ public:
m_matrix.pos.y = 0.0f; m_matrix.pos.y = 0.0f;
m_matrix.pos.z = 0.0f; m_matrix.pos.z = 0.0f;
} }
void ResetOrientation(void) {
m_matrix.right.x = 1.0f;
m_matrix.right.y = 0.0f;
m_matrix.right.z = 0.0f;
m_matrix.up.x = 0.0f;
m_matrix.up.y = 1.0f;
m_matrix.up.z = 0.0f;
m_matrix.at.x = 0.0f;
m_matrix.at.y = 0.0f;
m_matrix.at.z = 1.0f;
}
}; };

View File

@ -83,7 +83,7 @@ public:
return x == right.x && y == right.y && z == right.z; return x == right.x && y == right.y && z == right.z;
} }
bool IsZero(void) { return x == 0.0f && y == 0.0f && z == 0.0f; } bool IsZero(void) const { return x == 0.0f && y == 0.0f && z == 0.0f; }
}; };
inline CVector operator+(const CVector &left, const CVector &right) inline CVector operator+(const CVector &left, const CVector &right)

View File

@ -2,6 +2,8 @@
#include "Collision.h" #include "Collision.h"
#define MAX_MODEL_NAME (24)
enum ModeInfoType : uint8 enum ModeInfoType : uint8
{ {
MITYPE_NA = 0, MITYPE_NA = 0,
@ -21,7 +23,7 @@ class CBaseModelInfo
{ {
protected: protected:
// TODO?: make more things protected // TODO?: make more things protected
char m_name[24]; char m_name[MAX_MODEL_NAME];
CColModel *m_colModel; CColModel *m_colModel;
C2dEffect *m_twodEffects; C2dEffect *m_twodEffects;
int16 m_objectId; int16 m_objectId;

View File

@ -1,14 +1,14 @@
#pragma once #pragma once
#include "ClumpModelInfo.h" #include "ClumpModelInfo.h"
class CMloModelInfo : public CClumpModelInfo class CMloModelInfo : public CClumpModelInfo
{ {
public: public:
float field_34; // draw distance? float field_34; // draw distance?
int firstInstance; int firstInstance;
int lastInstance; int lastInstance;
public: public:
CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {} CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {}
void ConstructClump(); void ConstructClump();
}; };

View File

@ -234,12 +234,6 @@ CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level)
} }
} }
CStore<CInstance, MLOINSTANCESIZE>&
CModelInfo::GetMloInstanceStore()
{
return CModelInfo::ms_mloInstanceStore;
}
void void
CModelInfo::ConstructMloClumps() CModelInfo::ConstructMloClumps()
{ {
@ -247,6 +241,17 @@ CModelInfo::ConstructMloClumps()
ms_mloModelStore.store[i].ConstructClump(); ms_mloModelStore.store[i].ConstructClump();
} }
void
CModelInfo::ReInit2dEffects()
{
ms_2dEffectStore.clear();
for (int i = 0; i < MODELINFOSIZE; i++) {
if (ms_modelInfoPtrs[i])
ms_modelInfoPtrs[i]->Init2dEffects();
}
}
STARTPATCHES STARTPATCHES
InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP); InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP);
InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP); InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP);

View File

@ -36,7 +36,7 @@ public:
static CVehicleModelInfo *AddVehicleModel(int id); static CVehicleModelInfo *AddVehicleModel(int id);
static CStore<C2dEffect, TWODFXSIZE> &Get2dEffectStore(void) { return ms_2dEffectStore; } static CStore<C2dEffect, TWODFXSIZE> &Get2dEffectStore(void) { return ms_2dEffectStore; }
static CStore<CInstance, MLOINSTANCESIZE> &GetMloInstanceStore(); static CStore<CInstance, MLOINSTANCESIZE> &GetMloInstanceStore(void) { return ms_mloInstanceStore; }
static CBaseModelInfo *GetModelInfo(const char *name, int *id); static CBaseModelInfo *GetModelInfo(const char *name, int *id);
static CBaseModelInfo *GetModelInfo(int id){ static CBaseModelInfo *GetModelInfo(int id){
@ -47,4 +47,5 @@ public:
static bool IsBikeModel(int32 id); static bool IsBikeModel(int32 id);
static void RemoveColModelsFromOtherLevels(eLevelName level); static void RemoveColModelsFromOtherLevels(eLevelName level);
static void ConstructMloClumps(); static void ConstructMloClumps();
static void ReInit2dEffects();
}; };

View File

@ -216,7 +216,7 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame)
RwMatrixCopy(mat, RwFrameGetMatrix(f)); RwMatrixCopy(mat, RwFrameGetMatrix(f));
for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) { for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) {
RwMatrixTransform(mat, &f->modelling, rwCOMBINEPOSTCONCAT); RwMatrixTransform(mat, RwFrameGetMatrix(f), rwCOMBINEPOSTCONCAT);
if (RwFrameGetParent(f) == frame) if (RwFrameGetParent(f) == frame)
break; break;
} }

View File

@ -12,6 +12,7 @@
#include "World.h" #include "World.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "Automobile.h" #include "Automobile.h"
#include "Boat.h"
#include "Train.h" #include "Train.h"
#include "Plane.h" #include "Plane.h"
#include "Heli.h" #include "Heli.h"
@ -80,9 +81,9 @@ RwObjectNameIdAssocation carIds[] = {
}; };
RwObjectNameIdAssocation boatIds[] = { RwObjectNameIdAssocation boatIds[] = {
{ "boat_moving_hi", 1, VEHICLE_FLAG_COLLAPSE }, { "boat_moving_hi", BOAT_MOVING, VEHICLE_FLAG_COLLAPSE },
{ "boat_rudder_hi", 3, VEHICLE_FLAG_COLLAPSE }, { "boat_rudder_hi", BOAT_RUDDER, VEHICLE_FLAG_COLLAPSE },
{ "windscreen", 2, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE }, { "windscreen", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE },
{ "ped_frontseat", BOAT_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, { "ped_frontseat", BOAT_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
{ nil, 0, 0 } { nil, 0, 0 }
}; };
@ -707,7 +708,7 @@ RpMaterial*
CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial *material, void *data) CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial *material, void *data)
{ {
static RwRGBA white = { 255, 255, 255, 255 }; static RwRGBA white = { 255, 255, 255, 255 };
RwRGBA *col; const RwRGBA *col;
editableMatCBData *cbdata; editableMatCBData *cbdata;
cbdata = (editableMatCBData*)data; cbdata = (editableMatCBData*)data;
@ -758,8 +759,8 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
col = ms_vehicleColourTable[c1]; col = ms_vehicleColourTable[c1];
coltex = ms_colourTextureTable[c1]; coltex = ms_colourTextureTable[c1];
for(matp = m_materials1; *matp; matp++){ for(matp = m_materials1; *matp; matp++){
if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){ if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
colp = RpMaterialGetColor(*matp); colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
colp->red = col.red; colp->red = col.red;
colp->green = col.green; colp->green = col.green;
colp->blue = col.blue; colp->blue = col.blue;
@ -773,8 +774,8 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
col = ms_vehicleColourTable[c2]; col = ms_vehicleColourTable[c2];
coltex = ms_colourTextureTable[c2]; coltex = ms_colourTextureTable[c2];
for(matp = m_materials2; *matp; matp++){ for(matp = m_materials2; *matp; matp++){
if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){ if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
colp = RpMaterialGetColor(*matp); colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
colp->red = col.red; colp->red = col.red;
colp->green = col.green; colp->green = col.green;
colp->blue = col.blue; colp->blue = col.blue;
@ -861,7 +862,7 @@ CreateCarColourTexture(uint8 r, uint8 g, uint8 b)
RwImageDestroy(img); RwImageDestroy(img);
RwFree(pixels); RwFree(pixels);
tex = RwTextureCreate(ras); tex = RwTextureCreate(ras);
tex->name[0] = '@'; RwTextureGetName(tex)[0] = '@';
return tex; return tex;
} }
@ -1058,7 +1059,7 @@ CVehicleModelInfo::LoadEnvironmentMaps(void)
} }
if(gpWhiteTexture == nil){ if(gpWhiteTexture == nil){
gpWhiteTexture = RwTextureRead("white", nil); gpWhiteTexture = RwTextureRead("white", nil);
gpWhiteTexture->name[0] = '@'; RwTextureGetName(gpWhiteTexture)[0] = '@';
RwTextureSetFilterMode(gpWhiteTexture, rwFILTERLINEAR); RwTextureSetFilterMode(gpWhiteTexture, rwFILTERLINEAR);
} }
CTxdStore::PopCurrentTxd(); CTxdStore::PopCurrentTxd();

View File

@ -1,12 +1,12 @@
#pragma once #pragma once
#include "ClumpModelInfo.h" #include "ClumpModelInfo.h"
class CXtraCompsModelInfo : public CClumpModelInfo class CXtraCompsModelInfo : public CClumpModelInfo
{ {
int field_34; int field_34;
public: public:
CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; } CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; }
void SetClump(RpClump*) {}; void SetClump(RpClump*) {};
void Shutdown(void) {}; void Shutdown(void) {};
}; };

View File

@ -20,7 +20,7 @@ CCutsceneHead::CCutsceneHead(CObject *obj)
m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame; m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame;
atm = (RpAtomic*)GetFirstObject(m_pHeadNode); atm = (RpAtomic*)GetFirstObject(m_pHeadNode);
if(atm){ if(atm){
assert(RwObjectGetType(atm) == rpATOMIC); assert(RwObjectGetType((RwObject*)atm) == rpATOMIC);
RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER); RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER);
} }
} }

View File

@ -6,12 +6,11 @@
#include "Radar.h" #include "Radar.h"
#include "Object.h" #include "Object.h"
#include "DummyObject.h" #include "DummyObject.h"
#include "Particle.h"
WRAPPER void CObject::ObjectDamage(float amount) { EAXJMP(0x4BB240); } #include "General.h"
WRAPPER void CObject::DeleteAllTempObjectInArea(CVector, float) { EAXJMP(0x4BBED0); } #include "ObjectData.h"
WRAPPER void CObject::Init(void) { EAXJMP(0x4BAEC0); } #include "World.h"
WRAPPER void CObject::ProcessControl(void) { EAXJMP(0x4BB040); } #include "Floater.h"
WRAPPER void CObject::Teleport(CVector) { EAXJMP(0x4BBDA0); }
int16 &CObject::nNoTempObjects = *(int16*)0x95CCA2; int16 &CObject::nNoTempObjects = *(int16*)0x95CCA2;
int16 &CObject::nBodyCastHealth = *(int16*)0x5F7D4C; // 1000 int16 &CObject::nBodyCastHealth = *(int16*)0x5F7D4C; // 1000
@ -28,13 +27,13 @@ CObject::CObject(void)
m_nCollisionDamageEffect = 0; m_nCollisionDamageEffect = 0;
m_nSpecialCollisionResponseCases = COLLRESPONSE_NONE; m_nSpecialCollisionResponseCases = COLLRESPONSE_NONE;
m_bCameraToAvoidThisObject = false; m_bCameraToAvoidThisObject = false;
ObjectCreatedBy = 0; ObjectCreatedBy = UNKNOWN_OBJECT;
m_nEndOfLifeTime = 0; m_nEndOfLifeTime = 0;
// m_nRefModelIndex = -1; // duplicate // m_nRefModelIndex = -1; // duplicate
// bUseVehicleColours = false; // duplicate // bUseVehicleColours = false; // duplicate
m_colour2 = 0; m_colour2 = 0;
m_colour1 = m_colour2; m_colour1 = m_colour2;
field_172 = 0; m_nBonusValue = 0;
bIsPickup = false; bIsPickup = false;
m_obj_flag2 = false; m_obj_flag2 = false;
bOutOfStock = false; bOutOfStock = false;
@ -82,10 +81,46 @@ CObject::~CObject(void)
nNoTempObjects--; nNoTempObjects--;
} }
void
CObject::ProcessControl(void)
{
CVector point, impulse;
if (m_nCollisionDamageEffect)
ObjectDamage(m_fDamageImpulse);
CPhysical::ProcessControl();
if (mod_Buoyancy.ProcessBuoyancy(this, m_fBuoyancy, &point, &impulse)) {
bIsInWater = true;
bIsStatic = false;
ApplyMoveForce(impulse);
ApplyTurnForce(impulse, point);
float fTimeStep = Pow(0.97f, CTimer::GetTimeStep());
m_vecMoveSpeed *= fTimeStep;
m_vecTurnSpeed *= fTimeStep;
}
if ((m_modelIndex == MI_EXPLODINGBARREL || m_modelIndex == MI_PETROLPUMP) && bHasBeenDamaged && bIsVisible
&& (CGeneral::GetRandomNumber() & 0x1F) == 10) {
bExplosionProof = true;
bIsVisible = false;
bUsesCollision = false;
bAffectedByGravity = false;
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
}
}
void
CObject::Teleport(CVector vecPos)
{
CWorld::Remove(this);
m_matrix.GetPosition() = vecPos;
m_matrix.UpdateRW();
UpdateRwFrame();
CWorld::Add(this);
}
void void
CObject::Render(void) CObject::Render(void)
{ {
if(m_flagD80) if(bDoNotRender)
return; return;
if(m_nRefModelIndex != -1 && ObjectCreatedBy == TEMP_OBJECT && bUseVehicleColours){ if(m_nRefModelIndex != -1 && ObjectCreatedBy == TEMP_OBJECT && bUseVehicleColours){
@ -117,6 +152,152 @@ CObject::RemoveLighting(bool reset)
WorldReplaceScorchedLightsWithNormal(Scene.world); WorldReplaceScorchedLightsWithNormal(Scene.world);
} }
void
CObject::ObjectDamage(float amount)
{
if (!m_nCollisionDamageEffect || !bUsesCollision)
return;
static int8 nFrameGen = 0;
bool bBodyCastDamageEffect = false;
if (m_modelIndex == MI_BODYCAST){
if (amount > 50.0f)
nBodyCastHealth = (int16)(nBodyCastHealth - 0.5f * amount);
if (nBodyCastHealth < 0)
nBodyCastHealth = 0;
if (nBodyCastHealth < 200)
bBodyCastDamageEffect = true;
amount = 0.0f;
}
if ((amount * m_fCollisionDamageMultiplier > 150.0f || bBodyCastDamageEffect) && m_nCollisionDamageEffect) {
const CVector& vecPos = m_matrix.GetPosition();
const float fDirectionZ = 0.0002f * amount;
switch (m_nCollisionDamageEffect)
{
case COLDAMAGE_EFFECT_CHANGE_MODEL:
bRenderDamaged = true;
break;
case COLDAMAGE_EFFECT_SPLIT_MODEL:
break;
case COLDAMAGE_EFFECT_SMASH_COMPLETELY:
bIsVisible = false;
bUsesCollision = false;
bIsStatic = true;
bExplosionProof = true;
SetMoveSpeed(0.0f, 0.0f, 0.0f);
SetTurnSpeed(0.0f, 0.0f, 0.0f);
break;
case COLDAMAGE_EFFECT_CHANGE_THEN_SMASH:
if (!bRenderDamaged) {
bRenderDamaged = true;
}
else {
bIsVisible = false;
bUsesCollision = false;
bIsStatic = true;
bExplosionProof = true;
SetMoveSpeed(0.0f, 0.0f, 0.0f);
SetTurnSpeed(0.0f, 0.0f, 0.0f);
}
break;
case COLDAMAGE_EFFECT_SMASH_CARDBOX_COMPLETELY: {
bIsVisible = false;
bUsesCollision = false;
bIsStatic = true;
bExplosionProof = true;
SetMoveSpeed(0.0f, 0.0f, 0.0f);
SetTurnSpeed(0.0f, 0.0f, 0.0f);
const RwRGBA color = { 96, 48, 0, 255 };
for (int32 i = 0; i < 25; i++) {
CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ);
++nFrameGen;
int32 currentFrame = nFrameGen & 3;
float fRandom = CGeneral::GetRandomNumberInRange(0.01f, 1.0f);
RwRGBA randomColor = { color.red * fRandom, color.green * fRandom , color.blue, color.alpha };
float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f);
int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80);
CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0);
}
PlayOneShotScriptObject(_SCRSOUND_CARDBOARD_BOX_SMASH, vecPos);
break;
}
case COLDAMAGE_EFFECT_SMASH_WOODENBOX_COMPLETELY: {
bIsVisible = false;
bUsesCollision = false;
bIsStatic = true;
bExplosionProof = true;
SetMoveSpeed(0.0f, 0.0f, 0.0f);
SetTurnSpeed(0.0f, 0.0f, 0.0f);
const RwRGBA color = { 128, 128, 128, 255 };
for (int32 i = 0; i < 45; i++) {
CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ);
++nFrameGen;
int32 currentFrame = nFrameGen & 3;
float fRandom = CGeneral::GetRandomNumberInRange(0.5f, 0.5f);
RwRGBA randomColor = { color.red * fRandom, color.green * fRandom , color.blue * fRandom, color.alpha };
float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f);
int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80);
CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0);
}
PlayOneShotScriptObject(_SCRSOUND_WOODEN_BOX_SMASH, vecPos);
break;
}
case COLDAMAGE_EFFECT_SMASH_TRAFFICCONE_COMPLETELY: {
bIsVisible = false;
bUsesCollision = false;
bIsStatic = true;
bExplosionProof = true;
SetMoveSpeed(0.0f, 0.0f, 0.0f);
SetTurnSpeed(0.0f, 0.0f, 0.0f);
const RwRGBA color1 = { 200, 0, 0, 255 };
const RwRGBA color2 = { 200, 200, 200, 255 };
for (int32 i = 0; i < 10; i++) {
CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ);
++nFrameGen;
int32 currentFrame = nFrameGen & 3;
RwRGBA color = color2;
if (nFrameGen & 1)
color = color1;
float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f);
int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80);
CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0);
}
PlayOneShotScriptObject(_SCRSOUND_TYRE_BUMP, vecPos);
break;
}
case COLDAMAGE_EFFECT_SMASH_BARPOST_COMPLETELY: {
bIsVisible = false;
bUsesCollision = false;
bIsStatic = true;
bExplosionProof = true;
SetMoveSpeed(0.0f, 0.0f, 0.0f);
SetTurnSpeed(0.0f, 0.0f, 0.0f);
const RwRGBA color1 = { 200, 0, 0, 255 };
const RwRGBA color2 = { 200, 200, 200, 255 };
for (int32 i = 0; i < 32; i++) {
CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(-0.35f, 0.7f),
CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ);
++nFrameGen;
int32 currentFrame = nFrameGen & 3;
RwRGBA color = color2;
if (nFrameGen & 1)
color = color1;
float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f);
int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80);
CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0);
}
PlayOneShotScriptObject(_SCRSOUND_COL_CAR, vecPos);
break;
}
}
}
}
void void
CObject::RefModelInfo(int32 modelId) CObject::RefModelInfo(int32 modelId)
@ -125,6 +306,39 @@ CObject::RefModelInfo(int32 modelId)
CModelInfo::GetModelInfo(modelId)->AddRef(); CModelInfo::GetModelInfo(modelId)->AddRef();
} }
void
CObject::Init(void)
{
m_type = ENTITY_TYPE_OBJECT;;
CObjectData::SetObjectData(m_modelIndex, *this);
m_nEndOfLifeTime = 0;
ObjectCreatedBy = GAME_OBJECT;
bIsStatic = true;
bIsPickup = false;
m_obj_flag2 = false;
bOutOfStock = false;
bGlassCracked = false;
bGlassBroken = false;
bHasBeenDamaged = false;
bUseVehicleColours = false;
m_nRefModelIndex = -1;
m_colour1 = 0;
m_colour2 = 0;
m_nBonusValue = 0;
m_pCollidingEntity = nil;
CColPoint point;
CEntity* outEntity = nil;
const CVector& vecPos = m_matrix.GetPosition();
if (CWorld::ProcessVerticalLine(vecPos, vecPos.z - 10.0f, point, outEntity, true, false, false, false, false, false, nil))
m_pCurSurface = outEntity;
else
m_pCurSurface = nil;
if (m_modelIndex == MI_BODYCAST)
nBodyCastHealth = 1000;
else if (m_modelIndex == MI_BUOY)
bTouchingWater = true;
}
bool bool
CObject::CanBeDeleted(void) CObject::CanBeDeleted(void)
{ {
@ -142,6 +356,45 @@ CObject::CanBeDeleted(void)
} }
} }
void
CObject::DeleteAllMissionObjects()
{
CObjectPool* objectPool = CPools::GetObjectPool();
for (int32 i = 0; i < objectPool->GetSize(); i++) {
CObject* pObject = objectPool->GetSlot(i);
if (pObject && pObject->ObjectCreatedBy == MISSION_OBJECT) {
CWorld::Remove(pObject);
delete pObject;
}
}
}
void
CObject::DeleteAllTempObjects()
{
CObjectPool* objectPool = CPools::GetObjectPool();
for (int32 i = 0; i < objectPool->GetSize(); i++) {
CObject* pObject = objectPool->GetSlot(i);
if (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT) {
CWorld::Remove(pObject);
delete pObject;
}
}
}
void
CObject::DeleteAllTempObjectInArea(CVector point, float fRadius)
{
CObjectPool *objectPool = CPools::GetObjectPool();
for (int32 i = 0; i < objectPool->GetSize(); i++) {
CObject *pObject = objectPool->GetSlot(i);
if (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT && fRadius * fRadius > pObject->GetPosition().MagnitudeSqr()) {
CWorld::Remove(pObject);
delete pObject;
}
}
}
#include <new> #include <new>
class CObject_ : public CObject class CObject_ : public CObject
@ -152,6 +405,9 @@ public:
CObject *ctor(CDummyObject *dummy) { return ::new (this) CObject(dummy); } CObject *ctor(CDummyObject *dummy) { return ::new (this) CObject(dummy); }
void dtor(void) { CObject::~CObject(); } void dtor(void) { CObject::~CObject(); }
void Render_(void) { CObject::Render(); } void Render_(void) { CObject::Render(); }
void ProcessControl_(void) { CObject::ProcessControl(); }
bool SetupLighting_(void) { return CObject::SetupLighting(); }
void RemoveLighting_(bool reset) { CObject::RemoveLighting(reset); }
}; };
STARTPATCHES STARTPATCHES
@ -159,5 +415,16 @@ STARTPATCHES
InjectHook(0x4BACE0, (CObject* (CObject::*)(int32, bool)) &CObject_::ctor, PATCH_JUMP); InjectHook(0x4BACE0, (CObject* (CObject::*)(int32, bool)) &CObject_::ctor, PATCH_JUMP);
InjectHook(0x4BAD50, (CObject* (CObject::*)(CDummyObject*)) &CObject_::ctor, PATCH_JUMP); InjectHook(0x4BAD50, (CObject* (CObject::*)(CDummyObject*)) &CObject_::ctor, PATCH_JUMP);
InjectHook(0x4BAE00, &CObject_::dtor, PATCH_JUMP); InjectHook(0x4BAE00, &CObject_::dtor, PATCH_JUMP);
InjectHook(0x4BB040, &CObject_::ProcessControl_, PATCH_JUMP);
InjectHook(0x4BBDA0, &CObject::Teleport, PATCH_JUMP);
InjectHook(0x4BB1E0, &CObject_::Render_, PATCH_JUMP); InjectHook(0x4BB1E0, &CObject_::Render_, PATCH_JUMP);
InjectHook(0x4A7C90, &CObject_::SetupLighting_, PATCH_JUMP);
InjectHook(0x4A7CD0, &CObject_::RemoveLighting_, PATCH_JUMP);
InjectHook(0x4BB240, &CObject::ObjectDamage, PATCH_JUMP);
InjectHook(0x4BBD80, &CObject::RefModelInfo, PATCH_JUMP);
InjectHook(0x4BAEC0, &CObject::Init, PATCH_JUMP);
InjectHook(0x4BB010, &CObject::CanBeDeleted, PATCH_JUMP);
InjectHook(0x4BBE60, &CObject::DeleteAllMissionObjects, PATCH_JUMP);
InjectHook(0x4BBDF0, &CObject::DeleteAllTempObjects, PATCH_JUMP);
InjectHook(0x4BBED0, &CObject::DeleteAllTempObjectInArea, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -3,12 +3,25 @@
#include "Physical.h" #include "Physical.h"
enum { enum {
UNKNOWN_OBJECT = 0,
GAME_OBJECT = 1, GAME_OBJECT = 1,
MISSION_OBJECT = 2, MISSION_OBJECT = 2,
TEMP_OBJECT = 3, TEMP_OBJECT = 3,
CUTSCENE_OBJECT = 4, CUTSCENE_OBJECT = 4,
}; };
enum {
COLDAMAGE_EFFECT_NONE = 0,
COLDAMAGE_EFFECT_CHANGE_MODEL = 1,
COLDAMAGE_EFFECT_SPLIT_MODEL = 2,
COLDAMAGE_EFFECT_SMASH_COMPLETELY = 3,
COLDAMAGE_EFFECT_CHANGE_THEN_SMASH = 4,
COLDAMAGE_EFFECT_SMASH_CARDBOX_COMPLETELY = 50,
COLDAMAGE_EFFECT_SMASH_WOODENBOX_COMPLETELY = 60,
COLDAMAGE_EFFECT_SMASH_TRAFFICCONE_COMPLETELY = 70,
COLDAMAGE_EFFECT_SMASH_BARPOST_COMPLETELY = 80,
};
enum { enum {
COLLRESPONSE_NONE, COLLRESPONSE_NONE,
COLLRESPONSE_CHANGE_MODEL, COLLRESPONSE_CHANGE_MODEL,
@ -41,21 +54,21 @@ public:
int8 bHasBeenDamaged : 1; int8 bHasBeenDamaged : 1;
int8 bUseVehicleColours : 1; int8 bUseVehicleColours : 1;
int8 m_obj_flag80 : 1; int8 m_obj_flag80 : 1;
int8 field_172; // car for a bonus pickup? int8 m_nBonusValue;
int8 field_173; int8 field_173;
float m_fCollisionDamageMultiplier; float m_fCollisionDamageMultiplier;
uint8 m_nCollisionDamageEffect; uint8 m_nCollisionDamageEffect;
uint8 m_nSpecialCollisionResponseCases; uint8 m_nSpecialCollisionResponseCases;
bool m_bCameraToAvoidThisObject; bool m_bCameraToAvoidThisObject;
int8 field_17B; int8 field_17B;
int8 field_17C; int8 field_17C;
int8 field_17D; int8 field_17D;
int8 field_17E; int8 field_17E;
int8 field_17F; int8 field_17F;
uint32 m_nEndOfLifeTime; uint32 m_nEndOfLifeTime;
int16 m_nRefModelIndex; int16 m_nRefModelIndex;
int8 field_186; int8 field_186;
int8 field_187; int8 field_187;
CEntity *m_pCurSurface; CEntity *m_pCurSurface;
CEntity *m_pCollidingEntity; CEntity *m_pCollidingEntity;
int8 m_colour1, m_colour2; int8 m_colour1, m_colour2;
@ -74,7 +87,7 @@ public:
~CObject(void); ~CObject(void);
void ProcessControl(void); void ProcessControl(void);
void Teleport(CVector); void Teleport(CVector vecPos);
void Render(void); void Render(void);
bool SetupLighting(void); bool SetupLighting(void);
void RemoveLighting(bool reset); void RemoveLighting(bool reset);
@ -84,6 +97,8 @@ public:
void Init(void); void Init(void);
bool CanBeDeleted(void); bool CanBeDeleted(void);
static void DeleteAllTempObjectInArea(CVector, float); static void DeleteAllMissionObjects();
static void DeleteAllTempObjects();
static void DeleteAllTempObjectInArea(CVector point, float fRadius);
}; };
static_assert(sizeof(CObject) == 0x198, "CObject: error"); static_assert(sizeof(CObject) == 0x198, "CObject: error");

View File

@ -154,7 +154,7 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe
pobj->m_nRemoveTimer = 0; pobj->m_nRemoveTimer = 0;
if ( color.alpha != 0 ) if ( color.alpha != 0 )
RwRGBAAssign(&pobj->m_Color, &color); pobj->m_Color = color;
else else
pobj->m_Color.alpha = 0; pobj->m_Color.alpha = 0;

View File

@ -28,10 +28,8 @@ CCivilianPed::CivilianAI(void)
return; return;
if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
if (m_pedInObjective) { if (m_pedInObjective && m_pedInObjective->IsPlayer())
if (m_pedInObjective->IsPlayer()) return;
return;
}
} }
if (CTimer::GetTimeInMilliseconds() <= m_lookTimer) if (CTimer::GetTimeInMilliseconds() <= m_lookTimer)
return; return;
@ -75,7 +73,7 @@ CCivilianPed::CivilianAI(void)
} else { } else {
SetMoveState(PEDMOVE_WALK); SetMoveState(PEDMOVE_WALK);
} }
} else if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops) { } else if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {
SetFindPathAndFlee(m_threatEntity, 5000); SetFindPathAndFlee(m_threatEntity, 5000);
if (threatDistSqr < sq(10.0f)) { if (threatDistSqr < sq(10.0f)) {
SetMoveState(PEDMOVE_RUN); SetMoveState(PEDMOVE_RUN);
@ -170,8 +168,8 @@ CCivilianPed::CivilianAI(void)
if (m_threatEntity && m_threatEntity->IsPed()) { if (m_threatEntity && m_threatEntity->IsPed()) {
CPed *threatPed = (CPed*)m_threatEntity; CPed *threatPed = (CPed*)m_threatEntity;
if (m_pedStats->m_fear <= 100 - threatPed->m_pedStats->m_temper && threatPed->m_nPedType != PEDTYPE_COP) { if (m_pedStats->m_fear <= 100 - threatPed->m_pedStats->m_temper && threatPed->m_nPedType != PEDTYPE_COP) {
if (threatPed->GetWeapon()->IsTypeMelee() || !GetWeapon()->IsTypeMelee()) { if (threatPed->GetWeapon(m_currentWeapon).IsTypeMelee() || !GetWeapon()->IsTypeMelee()) {
if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops) { if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {
if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
SetFindPathAndFlee(m_threatEntity, 10000); SetFindPathAndFlee(m_threatEntity, 10000);
} }

View File

@ -1,10 +1,9 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "ModelIndices.h" #include "ModelIndices.h"
#include "Gangs.h" #include "Gangs.h"
#include "Weapon.h" #include "Weapon.h"
//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
CGangInfo CGangs::Gang[NUM_GANGS]; CGangInfo CGangs::Gang[NUM_GANGS];
CGangInfo::CGangInfo() : CGangInfo::CGangInfo() :
@ -57,20 +56,19 @@ void CGangs::SaveAllGangData(uint8 *buf, uint32 *size)
{ {
INITSAVEBUF INITSAVEBUF
*size = SAVE_HEADER_SIZE + sizeof(Gang); *size = SAVE_HEADER_SIZE + sizeof(Gang);
WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE); WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_GANGS; i++) for (int i = 0; i < NUM_GANGS; i++)
WriteSaveBuf(buf, Gang[i]); WriteSaveBuf(buf, Gang[i]);
VALIDATESAVEBUF(*size); VALIDATESAVEBUF(*size);
} }
void CGangs::LoadAllGangData(uint8 *buf, uint32 size) void CGangs::LoadAllGangData(uint8 *buf, uint32 size)
{ {
Initialise(); Initialise();
INITSAVEBUF INITSAVEBUF
// original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE); CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_GANGS; i++) for (int i = 0; i < NUM_GANGS; i++)

View File

@ -676,7 +676,7 @@ RemoveAllModelCB(RwObject *object, void *data)
{ {
RpAtomic *atomic = (RpAtomic*)object; RpAtomic *atomic = (RpAtomic*)object;
if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) { if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {
RpClumpRemoveAtomic(atomic->clump, atomic); RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);
RpAtomicDestroy(atomic); RpAtomicDestroy(atomic);
} }
return object; return object;
@ -902,7 +902,7 @@ static RwObject*
SetPedAtomicVisibilityCB(RwObject* object, void* data) SetPedAtomicVisibilityCB(RwObject* object, void* data)
{ {
if (data == nil) if (data == nil)
RpAtomicSetFlags(object, 0); RpAtomicSetFlags((RpAtomic*)object, 0);
return object; return object;
} }
@ -2733,7 +2733,6 @@ CPed::SetObjective(eObjective newObj, void *entity)
} }
#ifdef VC_PED_PORTS #ifdef VC_PED_PORTS
SetObjectiveTimer(0);
ClearPointGunAt(); ClearPointGunAt();
#endif #endif
bObjectiveCompleted = false; bObjectiveCompleted = false;
@ -15027,7 +15026,7 @@ CPed::ProcessBuoyancy(void)
#endif #endif
if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) { if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
m_flagD8 = true; bTouchingWater = true;
CEntity *entity; CEntity *entity;
CColPoint point; CColPoint point;
if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, false) if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, false)
@ -15093,7 +15092,7 @@ CPed::ProcessBuoyancy(void)
} else } else
return; return;
} else } else
m_flagD8 = false; bTouchingWater = false;
if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) { if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) {
CVector pos = GetPosition(); CVector pos = GetPosition();

View File

@ -340,7 +340,7 @@ CPedIK::RestoreLookAt(void)
} }
void void
CPedIK::ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch) CPedIK::ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch)
{ {
float f = clamp(DotProduct(mat->up, CVector(0.0f, 1.0f, 0.0f)), -1.0f, 1.0f); float f = clamp(DotProduct(mat->up, CVector(0.0f, 1.0f, 0.0f)), -1.0f, 1.0f);
*yaw = Acos(f); *yaw = Acos(f);
@ -352,7 +352,7 @@ CPedIK::ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch)
} }
void void
CPedIK::ExtractYawAndPitchLocal(RwMatrixTag *mat, float *yaw, float *pitch) CPedIK::ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch)
{ {
float f = clamp(DotProduct(mat->at, CVector(0.0f, 0.0f, 1.0f)), -1.0f, 1.0f); float f = clamp(DotProduct(mat->at, CVector(0.0f, 0.0f, 1.0f)), -1.0f, 1.0f);
*yaw = Acos(f); *yaw = Acos(f);

View File

@ -54,8 +54,8 @@ public:
void GetComponentPosition(RwV3d *pos, uint32 node); void GetComponentPosition(RwV3d *pos, uint32 node);
static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination); static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination);
void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll); void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);
void ExtractYawAndPitchLocal(RwMatrixTag *mat, float *yaw, float *pitch); void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch);
void ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch); void ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch);
LimbMoveStatus MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo); LimbMoveStatus MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo);
bool RestoreGunPosn(void); bool RestoreGunPosn(void);
bool LookInDirection(float phi, float theta); bool LookInDirection(float phi, float theta);

Some files were not shown because too many files have changed in this diff Show More