1
0
Fork 0
mirror of https://git.rip/DMCA_FUCKER/re3.git synced 2024-12-23 12:00:01 +00:00

Merge branch 'master' into garages_dev

This commit is contained in:
Nikolay Korolev 2020-04-10 21:17:00 +03:00
commit be260b49b1
94 changed files with 12517 additions and 10402 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**
@ -41,21 +35,16 @@ to reverse at the time, calling the original functions is acceptable.
cAudioManager - WIP cAudioManager - WIP
CBoat CBoat
CBulletInfo CBulletInfo
CExplosion
CMenuManager - WIP CMenuManager - WIP
CObject CObject
CPacManPickups CPacManPickups
CPad - only cheats
CPedPath CPedPath
CPools - save/loading CPools - save/loading
CRecordDataForChase CRecordDataForChase
CRecordDataForGame CRecordDataForGame
CRoadBlocks CRoadBlocks
CSkidmarks
CStats
CTrafficLights CTrafficLights
CWeapon CWeapon
CWeather
CWorld CWorld
GenericLoad GenericLoad
``` ```

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;

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

View file

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "DMAudio.h" #include "DMAudio.h"
#include "common.h" #include "common.h"

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

@ -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){

View file

@ -242,7 +242,7 @@ void CCarGenerator::Load(uint8 *&buffer)
void CTheCarGenerators::Process() void CTheCarGenerators::Process()
{ {
if (FindPlayerTrain() || CCutsceneMgr::IsRunning()) if (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing())
return; return;
if (++CTheCarGenerators::ProcessCounter == 4) if (++CTheCarGenerators::ProcessCounter == 4)
CTheCarGenerators::ProcessCounter = 0; CTheCarGenerators::ProcessCounter = 0;

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

@ -1,7 +1,7 @@
#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(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
@ -57,20 +57,20 @@ 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); // 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

@ -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");

File diff suppressed because it is too large Load diff

View file

@ -1,124 +1,124 @@
#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 class CPacManPickups
{ {
public: public:
static void Init(void); static void Init(void);
static void Update(void); static void Update(void);
static void GeneratePMPickUps(CVector, float, int16, uint8); static void GeneratePMPickUps(CVector, float, int16, uint8);
static void GeneratePMPickUpsForRace(int32); static void GeneratePMPickUpsForRace(int32);
static void GenerateOnePMPickUp(CVector); static void GenerateOnePMPickUp(CVector);
static void Render(void); static void Render(void);
static void DoCleanUpPacManStuff(void); static void DoCleanUpPacManStuff(void);
static void StartPacManRace(int32); static void StartPacManRace(int32);
static void StartPacManRecord(void); static void StartPacManRecord(void);
static uint32 QueryPowerPillsEatenInRace(void); static uint32 QueryPowerPillsEatenInRace(void);
static void ResetPowerPillsEatenInRace(void); static void ResetPowerPillsEatenInRace(void);
static void CleanUpPacManStuff(void); static void CleanUpPacManStuff(void);
static void StartPacManScramble(CVector, float, int16); static void StartPacManScramble(CVector, float, int16);
static uint32 QueryPowerPillsCarriedByPlayer(void); static uint32 QueryPowerPillsCarriedByPlayer(void);
static void ResetPowerPillsCarriedByPlayer(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

@ -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

@ -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);
@ -8442,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:
@ -11373,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
{ {
bool 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

@ -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;
@ -3269,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

@ -311,7 +311,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){

View file

@ -555,7 +555,7 @@ void CMenuManager::DoSettingsBeforeStartingAGame()
m_PrefsVsync = m_PrefsVsyncDisp; m_PrefsVsync = m_PrefsVsyncDisp;
DMAudio.Service(); DMAudio.Service();
m_bStartGameLoading = true; m_bWantToRestart = true;
ShutdownJustMenu(); ShutdownJustMenu();
UnloadTextures(); UnloadTextures();
@ -2819,7 +2819,7 @@ void CMenuManager::Process(void)
if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0) if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0)
return; return;
m_bStartGameLoading = false; m_bWantToRestart = false;
InitialiseChangedLanguageSettings(); InitialiseChangedLanguageSettings();
if (CPad::GetPad(0)->GetEscapeJustDown()) if (CPad::GetPad(0)->GetEscapeJustDown())
@ -2861,9 +2861,9 @@ void CMenuManager::Process(void)
if (m_PrefsVsyncDisp != m_PrefsVsync) if (m_PrefsVsyncDisp != m_PrefsVsync)
m_PrefsVsync = m_PrefsVsyncDisp; m_PrefsVsync = m_PrefsVsyncDisp;
DMAudio.Service(); DMAudio.Service();
m_bStartGameLoading = true; m_bWantToRestart = true;
RequestFrontEndShutDown(); RequestFrontEndShutDown();
m_bLoadingSavedGame = true; m_bWantToLoad = true;
b_FoundRecentSavedGameWantToLoad = true; b_FoundRecentSavedGameWantToLoad = true;
DMAudio.SetEffectsFadeVol(0); DMAudio.SetEffectsFadeVol(0);
DMAudio.SetMusicFadeVol(0); DMAudio.SetMusicFadeVol(0);
@ -2960,7 +2960,7 @@ void CMenuManager::Process(void)
m_bWaitingForNewKeyBind = false; m_bWaitingForNewKeyBind = false;
} }
if (!m_bStartGameLoading) { if (!m_bWantToRestart) {
if (m_bGameNotLoaded) if (m_bGameNotLoaded)
DMAudio.Service(); DMAudio.Service();
} }

View file

@ -464,7 +464,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;
@ -484,7 +484,7 @@ public:
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;
@ -550,10 +550,10 @@ public:
static int32 &sthWithButtons; static int32 &sthWithButtons;
static int32 &sthWithButtons2; static int32 &sthWithButtons2;
#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 #ifdef MENU_MAP
static bool bMenuMapActive; static bool bMenuMapActive;

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

@ -29,12 +29,17 @@
#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;
@ -50,29 +55,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
@ -89,7 +282,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;
@ -138,6 +331,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();
@ -165,13 +373,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;
@ -430,6 +638,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-- )
@ -672,7 +982,7 @@ void CPad::Update(int16 unk)
ProcessPCSpecificStuff(); ProcessPCSpecificStuff();
if ( ++iCurrHornHistory >= _TODOCONST(5) ) if ( ++iCurrHornHistory >= HORNHISTORY_SIZE )
iCurrHornHistory = 0; iCurrHornHistory = 0;
bHornHistory[iCurrHornHistory] = GetHorn(); bHornHistory[iCurrHornHistory] = GetHorn();
@ -689,7 +999,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');
@ -2092,7 +2402,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);

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

File diff suppressed because it is too large Load diff

View file

@ -56,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
@ -71,7 +71,7 @@ struct CBlip
uint16 m_eBlipDisplay; // eBlipDisplay uint16 m_eBlipDisplay; // eBlipDisplay
uint16 m_eRadarSprite; // 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)
@ -83,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;
@ -144,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);
@ -161,10 +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 ClipRadarTileCoords(int32 &x, int32 &y);
static bool IsPointInsideRadar(const CVector2D &);
static int LineRadarBoxCollision(CVector2D &, const CVector2D &, const CVector2D &);
static void CalculateCachedSinCos(); static void CalculateCachedSinCos();
}; };

View file

@ -347,13 +347,6 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)
return (nil); return (nil);
} }
WRAPPER void ReadVideoCardCapsFile(uint32&, uint32&, uint32&, uint32&) { EAXJMP(0x5926C0); }
WRAPPER bool CheckVideoCardCaps(void) { EAXJMP(0x592740); }
WRAPPER void WriteVideoCardCapsFile(void) { EAXJMP(0x5927D0); }
WRAPPER void ConvertingTexturesScreen(uint32, uint32, const char*) { EAXJMP(0x592880); }
WRAPPER void DealWithTxdWriteError(uint32, uint32, const char*) { EAXJMP(0x592BF0); }
WRAPPER bool CreateTxdImageForVideoCard() { EAXJMP(0x592C70); }
void CreateDebugFont() void CreateDebugFont()
{ {
; ;

View file

@ -3,10 +3,24 @@
#define DIRECTINPUT_VERSION 0x0800 #define DIRECTINPUT_VERSION 0x0800
#include <dinput.h> #include <dinput.h>
#pragma warning( pop ) #pragma warning( pop )
#define WITHWINDOWS
#include "common.h" #include "common.h"
#include "win.h" #include "win.h"
#include "patcher.h" #include "patcher.h"
#include "Timer.h" #include "Timer.h"
#ifdef GTA_PC
#include "FileMgr.h"
#include "Pad.h"
#include "main.h"
#include "Directory.h"
#include "Streaming.h"
#include "TxdStore.h"
#include "CdStream.h"
#include "Font.h"
#include "Sprite2d.h"
#include "Text.h"
#include "RwHelper.h"
#endif //GTA_PC
float &texLoadTime = *(float*)0x8F1B50; float &texLoadTime = *(float*)0x8F1B50;
int32 &texNumLoaded = *(int32*)0x8F252C; int32 &texNumLoaded = *(int32*)0x8F252C;
@ -132,9 +146,198 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)
return texDict; return texDict;
} }
#ifdef GTA_PC
WRAPPER RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags) { EAXJMP(0x59A350); }
void
ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8)
{
cap32 = UINT32_MAX;
cap24 = UINT32_MAX;
cap16 = UINT32_MAX;
cap8 = UINT32_MAX;
int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "rb");
if (file != 0) {
CFileMgr::Read(file, (char*)&cap32, 4);
CFileMgr::Read(file, (char*)&cap24, 4);
CFileMgr::Read(file, (char*)&cap16, 4);
CFileMgr::Read(file, (char*)&cap8, 4);
CFileMgr::CloseFile(file);
}
}
bool
CheckVideoCardCaps(void)
{
uint32 cap32 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT8888);
uint32 cap24 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT888);
uint32 cap16 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT1555);
uint32 cap8 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMATPAL8 | rwRASTERFORMAT8888);
uint32 fcap32, fcap24, fcap16, fcap8;
ReadVideoCardCapsFile(fcap32, fcap24, fcap16, fcap8);
return cap32 != fcap32 || cap24 != fcap24 || cap16 != fcap16 || cap8 != fcap8;
}
void
WriteVideoCardCapsFile(void)
{
uint32 cap32 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT8888);
uint32 cap24 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT888);
uint32 cap16 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT1555);
uint32 cap8 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMATPAL8 | rwRASTERFORMAT8888);
int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "wb");
if (file != 0) {
CFileMgr::Write(file, (char*)&cap32, 4);
CFileMgr::Write(file, (char*)&cap24, 4);
CFileMgr::Write(file, (char*)&cap16, 4);
CFileMgr::Write(file, (char*)&cap8, 4);
CFileMgr::CloseFile(file);
}
}
bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
void DoRWStuffEndOfFrame(void);
void
ConvertingTexturesScreen(uint32 num, uint32 count, const char *text)
{
HandleExit();
CSprite2d *splash = LoadSplash(nil);
if (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255))
return;
CSprite2d::SetRecipNearClip();
CSprite2d::InitPerFrame();
CFont::InitPerFrame();
DefinedState();
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), SCREEN_SCALE_FROM_RIGHT(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(64, 64, 64, 255));
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), (SCREEN_SCALE_FROM_RIGHT(200.0f) - SCREEN_SCALE_X(200.0f)) * ((float)num / (float)count) + SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(255, 217, 106, 255));
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(120.0f), SCREEN_SCALE_Y(150.0f), SCREEN_SCALE_FROM_RIGHT(120.0f), SCREEN_HEIGHT - SCREEN_SCALE_Y(220.0f)), CRGBA(50, 50, 50, 210));
CFont::SetBackgroundOff();
CFont::SetPropOn();
CFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.7f));
CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(170.0f));
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 217, 106, 255));
CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK);
CFont::PrintString(SCREEN_SCALE_X(170.0f), SCREEN_SCALE_Y(160.0f), TheText.Get(text));
CFont::DrawFonts();
DoRWStuffEndOfFrame();
}
void
DealWithTxdWriteError(uint32 num, uint32 count, const char *text)
{
while (!RsGlobal.quit) {
ConvertingTexturesScreen(num, count, text);
CPad::UpdatePads();
if (CPad::GetPad(0)->GetEscapeJustDown())
break;
}
RsGlobal.quit = false;
LoadingScreen(nil, nil, nil);
RsGlobal.quit = true;
}
bool
CreateTxdImageForVideoCard()
{
uint8 *buf = new uint8[CDSTREAM_SECTOR_SIZE];
CDirectory *pDir = new CDirectory(TXDSTORESIZE);
CDirectory::DirectoryInfo dirInfo;
CStreaming::FlushRequestList();
RwFileFunctions *filesys = RwOsGetFileInterface();
RwStream *img = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, "models\\txd.img");
if (img == nil) {
if (_dwOperatingSystemVersion == OS_WINNT || _dwOperatingSystemVersion == OS_WIN2000 || _dwOperatingSystemVersion == OS_WINXP) {
DealWithTxdWriteError(0, TXDSTORESIZE, "CVT_CRT");
delete []buf;
delete pDir;
}
return false;
}
int32 i;
for (i = 0; i < TXDSTORESIZE; i++) {
ConvertingTexturesScreen(i, TXDSTORESIZE, "CVT_MSG");
if (CTxdStore::GetSlot(i) != nil && CStreaming::IsObjectInCdImage(i + STREAM_OFFSET_TXD)) {
CStreaming::RequestTxd(i, STREAMFLAGS_KEEP_IN_MEMORY);
CStreaming::RequestModelStream(0);
CStreaming::FlushChannels();
char filename[64];
sprintf(filename, "%s.txd", CTxdStore::GetTxdName(i));
if (CTxdStore::GetSlot(i)->texDict) {
int32 pos = filesys->rwftell(img->Type.file.fpFile);
if (RwTexDictionaryStreamWrite(CTxdStore::GetSlot(i)->texDict, img) == nil) {
DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR");
RwStreamClose(img, nil);
delete []buf;
delete pDir;
CStreaming::RemoveTxd(i);
return false;
}
int32 size = filesys->rwftell(img->Type.file.fpFile) - pos;
int32 num = size % CDSTREAM_SECTOR_SIZE;
size /= CDSTREAM_SECTOR_SIZE;
if (num != 0) {
size++;
num = CDSTREAM_SECTOR_SIZE - num;
RwStreamWrite(img, buf, num);
}
dirInfo.offset = pos / CDSTREAM_SECTOR_SIZE;
dirInfo.size = size;
strncpy(dirInfo.name, filename, sizeof(dirInfo.name));
pDir->AddItem(dirInfo);
CStreaming::RemoveTxd(i);
}
CStreaming::FlushRequestList();
}
}
RwStreamClose(img, nil);
delete []buf;
if (!pDir->WriteDirFile("models\\txd.dir")) {
DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR");
delete pDir;
return false;
}
delete pDir;
WriteVideoCardCapsFile();
return true;
}
#endif // GTA_PC
STARTPATCHES STARTPATCHES
InjectHook(0x592380, RwTextureGtaStreamRead, PATCH_JUMP); InjectHook(0x592380, RwTextureGtaStreamRead, PATCH_JUMP);
InjectHook(0x5924A0, RwTexDictionaryGtaStreamRead, PATCH_JUMP); InjectHook(0x5924A0, RwTexDictionaryGtaStreamRead, PATCH_JUMP);
InjectHook(0x592550, RwTexDictionaryGtaStreamRead1, PATCH_JUMP); InjectHook(0x592550, RwTexDictionaryGtaStreamRead1, PATCH_JUMP);
InjectHook(0x592650, RwTexDictionaryGtaStreamRead2, PATCH_JUMP); InjectHook(0x592650, RwTexDictionaryGtaStreamRead2, PATCH_JUMP);
InjectHook(0x5926C0, ReadVideoCardCapsFile, PATCH_JUMP);
InjectHook(0x592740, CheckVideoCardCaps, PATCH_JUMP);
InjectHook(0x5927D0, WriteVideoCardCapsFile, PATCH_JUMP);
InjectHook(0x592880, ConvertingTexturesScreen, PATCH_JUMP);
InjectHook(0x592BF0, DealWithTxdWriteError, PATCH_JUMP);
InjectHook(0x592C70, CreateTxdImageForVideoCard, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View file

@ -1,14 +1,14 @@
#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;
@ -48,7 +48,7 @@ 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::ShotsMade = *(int32*)0x8E2BE8; int32& CStats::RoundsFiredByPlayer = *(int32*)0x8E2BE8;
int32& CStats::KgsOfExplosivesUsed = *(int32*)0x8F2510; int32& CStats::KgsOfExplosivesUsed = *(int32*)0x8F2510;
int32& CStats::InstantHitsFiredByPlayer = *(int32*)0x943070; int32& CStats::InstantHitsFiredByPlayer = *(int32*)0x943070;
int32& CStats::InstantHitsHitByPlayer = *(int32*)0x95CB8C; int32& CStats::InstantHitsHitByPlayer = *(int32*)0x95CB8C;
@ -62,7 +62,7 @@ void CStats::Init()
{ {
PeopleKilledByOthers = 0; PeopleKilledByOthers = 0;
PeopleKilledByPlayer = 0; PeopleKilledByPlayer = 0;
ShotsMade = 0; RoundsFiredByPlayer = 0;
CarsExploded = 0; CarsExploded = 0;
HelisDestroyed = 0; HelisDestroyed = 0;
ProgressMade = 0; ProgressMade = 0;
@ -200,6 +200,229 @@ void CStats::SetTotalNumberMissions(int32 total)
TotalNumberMissions = total; TotalNumberMissions = total;
} }
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 STARTPATCHES
InjectHook(0x48C5A3, CStats::Init, PATCH_JUMP); // CGame::ReInitGameObjectVariables 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 ENDPATCHES

View file

@ -11,9 +11,9 @@ public:
}; };
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;
@ -53,7 +53,7 @@ public:
static int32 &TimeTakenDefuseMission; static int32 &TimeTakenDefuseMission;
static int32 &TotalNumberKillFrenzies; static int32 &TotalNumberKillFrenzies;
static int32 &TotalNumberMissions; static int32 &TotalNumberMissions;
static int32 &ShotsMade; static int32 &RoundsFiredByPlayer;
static int32 &KgsOfExplosivesUsed; static int32 &KgsOfExplosivesUsed;
static int32 &InstantHitsFiredByPlayer; static int32 &InstantHitsFiredByPlayer;
static int32 &InstantHitsHitByPlayer; static int32 &InstantHitsHitByPlayer;
@ -64,24 +64,27 @@ public:
static int32(&HighestScores)[TOTAL_HIGHEST_SCORES]; static int32(&HighestScores)[TOTAL_HIGHEST_SCORES];
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 Init(void); static void LoadStats(uint8 *buf, uint32 size);
}; };

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

@ -84,12 +84,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 +107,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

@ -79,6 +79,7 @@ enum Config {
NUMPICKUPMESSAGES = 16, NUMPICKUPMESSAGES = 16,
NUMBULLETTRACES = 16, NUMBULLETTRACES = 16,
NUMMBLURSTREAKS = 4, NUMMBLURSTREAKS = 4,
NUMSKIDMARKS = 32,
NUMONSCREENTIMERENTRIES = 1, NUMONSCREENTIMERENTRIES = 1,
NUMRADARBLIPS = 32, NUMRADARBLIPS = 32,
@ -125,7 +126,9 @@ enum Config {
NUM_GARAGE_STORED_CARS = 6, NUM_GARAGE_STORED_CARS = 6,
NUM_CRANES = 8 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
@ -150,6 +153,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

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

@ -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

@ -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));
} }
} }
@ -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

@ -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

@ -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

@ -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

@ -707,7 +707,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 +758,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 +773,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 +861,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 +1058,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

@ -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

@ -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;
} }

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);

View file

@ -85,6 +85,7 @@ public:
static uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; } static uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; }
static uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; } static uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; }
static uint32 GetThreats(int type) { return ms_apPedType[type]->m_threats; } static uint32 GetThreats(int type) { return ms_apPedType[type]->m_threats; }
static void SetThreats(int type, uint32 threat) { ms_apPedType[type]->m_threats = threat; }
static void AddThreat(int type, int threat) { ms_apPedType[type]->m_threats |= threat; } static void AddThreat(int type, int threat) { ms_apPedType[type]->m_threats |= threat; }
static void RemoveThreat(int type, int threat) { ms_apPedType[type]->m_threats &= ~threat; } static void RemoveThreat(int type, int threat) { ms_apPedType[type]->m_threats &= ~threat; }
static bool IsThreat(int type, int threat) { return ms_apPedType[type]->m_threats & threat; } static bool IsThreat(int type, int threat) { return ms_apPedType[type]->m_threats & threat; }

File diff suppressed because it is too large Load diff

View file

@ -704,12 +704,15 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
if (i != 0) { if (i != 0) {
// Gang member // Gang member
newPed->SetLeader(gangLeader); newPed->SetLeader(gangLeader);
#ifndef FIX_BUGS
// seems to be a miami leftover (this code is not on PS2) but gang peds end up just being frozen
newPed->m_nPedState = PED_UNKNOWN; newPed->m_nPedState = PED_UNKNOWN;
gangLeader->m_nPedState = PED_UNKNOWN; gangLeader->m_nPedState = PED_UNKNOWN;
newPed->m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints( newPed->m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints(
gangLeader->GetPosition().x, gangLeader->GetPosition().y, gangLeader->GetPosition().x, gangLeader->GetPosition().y,
newPed->GetPosition().x, newPed->GetPosition().y); newPed->GetPosition().x, newPed->GetPosition().y);
newPed->m_fRotationDest = newPed->m_fRotationCur; newPed->m_fRotationDest = newPed->m_fRotationCur;
#endif
} else { } else {
gangLeader = newPed; gangLeader = newPed;
} }

View file

@ -87,7 +87,7 @@ CClouds::Render(void)
RwV3d pos = { 0.0f, -100.0f, 15.0f }; RwV3d pos = { 0.0f, -100.0f, 15.0f };
RwV3dAdd(&worldpos, &campos, &pos); RwV3dAdd(&worldpos, &campos, &pos);
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){ if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[2]->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2]));
if(CCoronas::bSmallMoon){ if(CCoronas::bSmallMoon){
szx *= 4.0f; szx *= 4.0f;
szy *= 4.0f; szy *= 4.0f;
@ -116,7 +116,7 @@ CClouds::Render(void)
static float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f }; static float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f };
static float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f }; static float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f };
int brightness = (1.0f - coverage) * starintens; int brightness = (1.0f - coverage) * starintens;
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
for(i = 0; i < 11; i++){ for(i = 0; i < 11; i++){
RwV3d pos = { 100.0f, 0.0f, 10.0f }; RwV3d pos = { 100.0f, 0.0f, 10.0f };
if(i >= 9) pos.x = -pos.x; if(i >= 9) pos.x = -pos.x;
@ -132,7 +132,7 @@ CClouds::Render(void)
CSprite::FlushSpriteBuffer(); CSprite::FlushSpriteBuffer();
// * // *
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
RwV3d pos = { 100.0f, 0.0f, 10.0f }; RwV3d pos = { 100.0f, 0.0f, 10.0f };
RwV3dAdd(&worldpos, &campos, &pos); RwV3dAdd(&worldpos, &campos, &pos);
worldpos.y -= 90.0f; worldpos.y -= 90.0f;
@ -156,7 +156,7 @@ CClouds::Render(void)
int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity; int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity;
for(int cloudtype = 0; cloudtype < 3; cloudtype++){ for(int cloudtype = 0; cloudtype < 3; cloudtype++){
for(i = cloudtype; i < 12; i += 3){ for(i = cloudtype; i < 12; i += 3){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[cloudtype]->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[cloudtype]));
RwV3d pos = { 800.0f*LowCloudsX[i], 800.0f*LowCloudsY[i], 60.0f*LowCloudsZ[i] }; RwV3d pos = { 800.0f*LowCloudsX[i], 800.0f*LowCloudsY[i], 60.0f*LowCloudsZ[i] };
worldpos.x = campos.x + pos.x; worldpos.x = campos.x + pos.x;
worldpos.y = campos.y + pos.y; worldpos.y = campos.y + pos.y;
@ -202,7 +202,7 @@ CClouds::Render(void)
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[4]->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[4]));
for(i = 0; i < 37; i++){ for(i = 0; i < 37; i++){
RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f }; RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };
worldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x; worldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x;
@ -244,7 +244,7 @@ CClouds::Render(void)
// Highlights // Highlights
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[3]->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[3]));
for(i = 0; i < 37; i++){ for(i = 0; i < 37; i++){
RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f }; RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };
@ -269,7 +269,7 @@ CClouds::Render(void)
static uint8 BowRed[6] = { 30, 30, 30, 10, 0, 15 }; static uint8 BowRed[6] = { 30, 30, 30, 10, 0, 15 };
static uint8 BowGreen[6] = { 0, 15, 30, 30, 0, 0 }; static uint8 BowGreen[6] = { 0, 15, 30, 30, 0, 0 };
static uint8 BowBlue[6] = { 0, 0, 0, 10, 30, 30 }; static uint8 BowBlue[6] = { 0, 0, 0, 10, 30, 30 };
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
for(i = 0; i < 6; i++){ for(i = 0; i < 6; i++){
RwV3d pos = { i*1.5f, 100.0f, 5.0f }; RwV3d pos = { i*1.5f, 100.0f, 5.0f };
RwV3dAdd(&worldpos, &campos, &pos); RwV3dAdd(&worldpos, &campos, &pos);

View file

@ -320,7 +320,7 @@ CCoronas::Render(void)
CSprite::RenderOneXLUSprite(spriteCoors.x, spriteCoors.y, spriteCoors.z, CSprite::RenderOneXLUSprite(spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * aCoronas[i].size * wscale, spritew * aCoronas[i].size * wscale,
spriteh * SCREEN_SCALE_AR2(aCoronas[i].size * fogscale * hscale), spriteh * aCoronas[i].size * fogscale * hscale,
CCoronas::aCoronas[i].red / fogscale, CCoronas::aCoronas[i].red / fogscale,
CCoronas::aCoronas[i].green / fogscale, CCoronas::aCoronas[i].green / fogscale,
CCoronas::aCoronas[i].blue / fogscale, CCoronas::aCoronas[i].blue / fogscale,
@ -331,7 +331,7 @@ CCoronas::Render(void)
CSprite::RenderOneXLUSprite_Rotate_Aspect( CSprite::RenderOneXLUSprite_Rotate_Aspect(
spriteCoors.x, spriteCoors.y, spriteCoors.z, spriteCoors.x, spriteCoors.y, spriteCoors.z,
spritew * aCoronas[i].size * fogscale, spritew * aCoronas[i].size * fogscale,
spriteh * SCREEN_SCALE_AR2(aCoronas[i].size * fogscale), spriteh * aCoronas[i].size * fogscale,
CCoronas::aCoronas[i].red / fogscale, CCoronas::aCoronas[i].red / fogscale,
CCoronas::aCoronas[i].green / fogscale, CCoronas::aCoronas[i].green / fogscale,
CCoronas::aCoronas[i].blue / fogscale, CCoronas::aCoronas[i].blue / fogscale,

View file

@ -755,14 +755,14 @@ void CTowerClock::Render()
&TempV[1], &TempV[1],
m_Position.x + Sin(angleMinute) * m_fScale * m_Size.x, m_Position.x + Sin(angleMinute) * m_fScale * m_Size.x,
m_Position.y + Sin(angleMinute) * m_fScale * m_Size.y, m_Position.y + Sin(angleMinute) * m_fScale * m_Size.y,
m_Position.z + Cos(angleMinute) * m_fScale; m_Position.z + Cos(angleMinute) * m_fScale
); );
RwIm3DVertexSetPos(&TempV[2], m_Position.x, m_Position.y, m_Position.z); RwIm3DVertexSetPos(&TempV[2], m_Position.x, m_Position.y, m_Position.z);
RwIm3DVertexSetPos( RwIm3DVertexSetPos(
&TempV[3], &TempV[3],
m_Position.x + Sin(angleHour) * 0.75f * m_fScale * m_Size.x, m_Position.x + Sin(angleHour) * 0.75f * m_fScale * m_Size.x,
m_Position.y + Sin(angleHour) * 0.75f * m_fScale * m_Size.y, m_Position.y + Sin(angleHour) * 0.75f * m_fScale * m_Size.y,
m_Position.z + Cos(angleHour) * 0.75f * m_fScale; m_Position.z + Cos(angleHour) * 0.75f * m_fScale
); );
LittleTest(); LittleTest();

File diff suppressed because it is too large Load diff

View file

@ -815,7 +815,7 @@ void CHud::Draw()
DrawScriptText DrawScriptText
*/ */
if (!CTimer::GetIsUserPaused()) { if (!CTimer::GetIsUserPaused()) {
CTextLine* IntroText = CTheScripts::IntroTextLines; intro_text_line* IntroText = CTheScripts::IntroTextLines;
for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++) { for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++) {
if (CTheScripts::IntroTextLines[i].m_Text[0] && CTheScripts::IntroTextLines[i].m_bTextBeforeFade) { if (CTheScripts::IntroTextLines[i].m_Text[0] && CTheScripts::IntroTextLines[i].m_bTextBeforeFade) {
@ -862,7 +862,7 @@ void CHud::Draw()
} }
} }
CScriptRectangle* IntroRect = CTheScripts::IntroRectangles; intro_script_rectangle* IntroRect = CTheScripts::IntroRectangles;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (CTheScripts::IntroRectangles[i].m_bIsUsed && CTheScripts::IntroRectangles[i].m_bBeforeFade) { if (CTheScripts::IntroRectangles[i].m_bIsUsed && CTheScripts::IntroRectangles[i].m_bBeforeFade) {

View file

@ -4,12 +4,13 @@
#include "Camera.h" #include "Camera.h"
#include "MBlur.h" #include "MBlur.h"
// Originally taken from RW example 'mblur'
RwRaster *&CMBlur::pFrontBuffer = *(RwRaster**)0x8E2C48; RwRaster *&CMBlur::pFrontBuffer = *(RwRaster**)0x8E2C48;
bool &CMBlur::ms_bJustInitialised = *(bool*)0x95CDAB; bool &CMBlur::ms_bJustInitialised = *(bool*)0x95CDAB;
bool &CMBlur::BlurOn = *(bool*)0x95CDAD; bool &CMBlur::BlurOn = *(bool*)0x95CDAD;
static RwIm2DVertex Vertex[4]; static RwIm2DVertex Vertex[4];
//static RwIm2DVertex *Vertex = (RwIm2DVertex*)0x62F780;
static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 }; static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
void void

View file

@ -1,169 +1,174 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "main.h" #include "main.h"
#include "PlayerSkin.h" #include "PlayerSkin.h"
#include "TxdStore.h" #include "TxdStore.h"
#include "rtbmp.h" #include "rtbmp.h"
#include "ClumpModelInfo.h" #include "ClumpModelInfo.h"
#include "VisibilityPlugins.h" #include "VisibilityPlugins.h"
#include "World.h" #include "World.h"
#include "PlayerInfo.h" #include "PlayerInfo.h"
#include "CdStream.h" #include "CdStream.h"
#include "FileMgr.h" #include "FileMgr.h"
#include "Directory.h" #include "Directory.h"
#include "RwHelper.h" #include "RwHelper.h"
#include "Timer.h" #include "Timer.h"
#include "Lights.h" #include "Lights.h"
int CPlayerSkin::m_txdSlot; RpClump *gpPlayerClump;
float gOldFov;
void
FindPlayerDff(uint32 &offset, uint32 &size) int CPlayerSkin::m_txdSlot;
{
int file; void
CDirectory::DirectoryInfo info; FindPlayerDff(uint32 &offset, uint32 &size)
{
file = CFileMgr::OpenFile("models\\gta3.dir", "rb"); int file;
CDirectory::DirectoryInfo info;
do {
if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo))) file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
return;
} while (strcasecmp("player.dff", info.name) != 0); do {
if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
offset = info.offset; return;
size = info.size; } while (strcasecmp("player.dff", info.name) != 0);
}
offset = info.offset;
void size = info.size;
LoadPlayerDff(void) }
{
RwStream *stream; void
RwMemory mem; LoadPlayerDff(void)
uint32 offset, size; {
uint8 *buffer; RwStream *stream;
bool streamWasAdded = false; RwMemory mem;
uint32 offset, size;
if (CdStreamGetNumImages() == 0) { uint8 *buffer;
CdStreamAddImage("models\\gta3.img"); bool streamWasAdded = false;
streamWasAdded = true;
} if (CdStreamGetNumImages() == 0) {
CdStreamAddImage("models\\gta3.img");
FindPlayerDff(offset, size); streamWasAdded = true;
buffer = (uint8*)RwMallocAlign(size << 11, 2048); }
CdStreamRead(0, buffer, offset, size);
CdStreamSync(0); FindPlayerDff(offset, size);
buffer = (uint8*)RwMallocAlign(size << 11, 2048);
mem.start = buffer; CdStreamRead(0, buffer, offset, size);
mem.length = size << 11; CdStreamSync(0);
stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
mem.start = buffer;
if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) mem.length = size << 11;
gpPlayerClump = RpClumpStreamRead(stream); stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
RwStreamClose(stream, &mem); if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
RwFreeAlign(buffer); gpPlayerClump = RpClumpStreamRead(stream);
if (streamWasAdded) RwStreamClose(stream, &mem);
CdStreamRemoveImages(); RwFreeAlign(buffer);
}
if (streamWasAdded)
void CdStreamRemoveImages();
CPlayerSkin::Initialise(void) }
{
m_txdSlot = CTxdStore::AddTxdSlot("skin"); void
CTxdStore::Create(m_txdSlot); CPlayerSkin::Initialise(void)
CTxdStore::AddRef(m_txdSlot); {
} m_txdSlot = CTxdStore::AddTxdSlot("skin");
CTxdStore::Create(m_txdSlot);
void CTxdStore::AddRef(m_txdSlot);
CPlayerSkin::Shutdown(void) }
{
CTxdStore::RemoveTxdSlot(m_txdSlot); void
} CPlayerSkin::Shutdown(void)
{
RwTexture * CTxdStore::RemoveTxdSlot(m_txdSlot);
CPlayerSkin::GetSkinTexture(const char *texName) }
{
RwTexture *tex; RwTexture *
RwRaster *raster; CPlayerSkin::GetSkinTexture(const char *texName)
int32 width, height, depth, format; {
RwTexture *tex;
CTxdStore::PushCurrentTxd(); RwRaster *raster;
CTxdStore::SetCurrentTxd(m_txdSlot); int32 width, height, depth, format;
tex = RwTextureRead(texName, NULL);
CTxdStore::PopCurrentTxd(); CTxdStore::PushCurrentTxd();
if (tex) return tex; CTxdStore::SetCurrentTxd(m_txdSlot);
tex = RwTextureRead(texName, NULL);
if (strcmp(DEFAULT_SKIN_NAME, texName) == 0) CTxdStore::PopCurrentTxd();
sprintf(gString, "models\\generic\\player.bmp"); if (tex != nil) return tex;
else
sprintf(gString, "skins\\%s.bmp", texName); if (strcmp(DEFAULT_SKIN_NAME, texName) == 0)
sprintf(gString, "models\\generic\\player.bmp");
if (RwImage *image = RtBMPImageRead(gString)) { else
RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format); sprintf(gString, "skins\\%s.bmp", texName);
raster = RwRasterCreate(width, height, depth, format);
RwRasterSetFromImage(raster, image); if (RwImage *image = RtBMPImageRead(gString)) {
RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
tex = RwTextureCreate(raster); raster = RwRasterCreate(width, height, depth, format);
RwTextureSetName(tex, texName); RwRasterSetFromImage(raster, image);
RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex); tex = RwTextureCreate(raster);
RwTextureSetName(tex, texName);
RwImageDestroy(image); #ifdef FIX_BUGS
} RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
return tex; #endif
} RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
void RwImageDestroy(image);
CPlayerSkin::BeginFrontendSkinEdit(void) }
{ return tex;
LoadPlayerDff(); }
RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
CWorld::Players[0].LoadPlayerSkin(); void
gOldFov = CDraw::GetFOV(); CPlayerSkin::BeginFrontendSkinEdit(void)
CDraw::SetFOV(30.0f); {
} LoadPlayerDff();
RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
void CWorld::Players[0].LoadPlayerSkin();
CPlayerSkin::EndFrontendSkinEdit(void) gOldFov = CDraw::GetFOV();
{ CDraw::SetFOV(30.0f);
RpClumpDestroy(gpPlayerClump); }
gpPlayerClump = NULL;
CDraw::SetFOV(gOldFov); void
} CPlayerSkin::EndFrontendSkinEdit(void)
{
void RpClumpDestroy(gpPlayerClump);
CPlayerSkin::RenderFrontendSkinEdit(void) gpPlayerClump = NULL;
{ CDraw::SetFOV(gOldFov);
static float rotation = 0.0f; }
RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
RwV3d pos = { 1.35f, 0.35f, 7.725f }; void
const RwV3d axis1 = { 1.0f, 0.0f, 0.0f }; CPlayerSkin::RenderFrontendSkinEdit(void)
const RwV3d axis2 = { 0.0f, 0.0f, 1.0f }; {
static uint32 LastFlash = 0; static float rotation = 0.0f;
RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
RwFrame *frame = RpClumpGetFrame(gpPlayerClump); const RwV3d pos = { 1.35f, 0.35f, 7.725f };
const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) { const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
rotation += 2.0f; static uint32 LastFlash = 0;
if (rotation > 360.0f)
rotation -= 360.0f; RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
} if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE); rotation += 2.0f;
RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT); if (rotation > 360.0f)
RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT); rotation -= 360.0f;
RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT); LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
RwFrameUpdateObjects(frame); }
SetAmbientColours(&AmbientColor); RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
RpClumpRender(gpPlayerClump); RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
} RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT);
RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT);
STARTPATCHES RwFrameUpdateObjects(frame);
InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP); SetAmbientColours(&AmbientColor);
InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP); RpClumpRender(gpPlayerClump);
InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP); }
InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP);
InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP); STARTPATCHES
InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP); InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP);
InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP);
InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP);
InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP);
InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP);
InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View file

@ -2,12 +2,6 @@
#define DEFAULT_SKIN_NAME "$$\"\"" #define DEFAULT_SKIN_NAME "$$\"\""
static RpClump *gpPlayerClump;// = *(RpClump**)0x660FF8;
static float gOldFov;// = *(float*)0x660FFC;
void LoadPlayerDff(void);
void FindPlayerDff(uint32 &offset, uint32 &size);
class CPlayerSkin class CPlayerSkin
{ {
static int m_txdSlot; static int m_txdSlot;

View file

@ -1,12 +1,247 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "main.h"
#include "TxdStore.h"
#include "Timer.h"
#include "Replay.h"
#include "Skidmarks.h" #include "Skidmarks.h"
WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); } CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS];
WRAPPER void CSkidmarks::Update() { EAXJMP(0x518200); }
WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); } RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6];
WRAPPER void CSkidmarks::RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy) { EAXJMP(0x5185C0); } RwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2];
RwTexture *gpSkidTex;
RwTexture *gpSkidBloodTex;
RwTexture *gpSkidMudTex;
WRAPPER void CSkidmarks::Init(void) { EAXJMP(0x517D70); } void
WRAPPER void CSkidmarks::Shutdown(void) { EAXJMP(0x518100); } CSkidmarks::Init(void)
{
int i, ix, slot;
CTxdStore::PushCurrentTxd();
slot = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slot);
gpSkidTex = RwTextureRead("particleskid", nil);
gpSkidBloodTex = RwTextureRead("particleskidblood", nil);
gpSkidMudTex = RwTextureRead("particleskidmud", nil);
CTxdStore::PopCurrentTxd();
for(i = 0; i < NUMSKIDMARKS; i++){
aSkidmarks[i].m_state = 0;
aSkidmarks[i].m_wasUpdated = false;
}
ix = 0;
for(i = 0; i < SKIDMARK_LENGTH; i++){
SkidmarkIndexList[i*6+0] = ix+0;
SkidmarkIndexList[i*6+1] = ix+2;
SkidmarkIndexList[i*6+2] = ix+1;
SkidmarkIndexList[i*6+3] = ix+1;
SkidmarkIndexList[i*6+4] = ix+2;
SkidmarkIndexList[i*6+5] = ix+3;
ix += 2;
}
for(i = 0; i < SKIDMARK_LENGTH; i++){
RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 0], 0.0f);
RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 0], i*5.01f);
RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 1], 1.0f);
RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 1], i*5.01f);
}
}
void
CSkidmarks::Shutdown(void)
{
RwTextureDestroy(gpSkidTex);
RwTextureDestroy(gpSkidBloodTex);
RwTextureDestroy(gpSkidMudTex);
}
void
CSkidmarks::Clear(void)
{
int i;
for(i = 0; i < NUMSKIDMARKS; i++){
aSkidmarks[i].m_state = 0;
aSkidmarks[i].m_wasUpdated = false;
}
}
void
CSkidmarks::Update(void)
{
int i;
uint32 t1 = CTimer::GetTimeInMilliseconds() + 2500;
uint32 t2 = CTimer::GetTimeInMilliseconds() + 5000;
uint32 t3 = CTimer::GetTimeInMilliseconds() + 10000;
uint32 t4 = CTimer::GetTimeInMilliseconds() + 20000;
for(i = 0; i < NUMSKIDMARKS; i++){
switch(aSkidmarks[i].m_state){
case 1:
if(!aSkidmarks[i].m_wasUpdated){
// Didn't continue this one last time, so finish it and set fade times
aSkidmarks[i].m_state = 2;
if(aSkidmarks[i].m_last < 4){
aSkidmarks[i].m_fadeStart = t1;
aSkidmarks[i].m_fadeEnd = t2;
}else if(aSkidmarks[i].m_last < 9){
aSkidmarks[i].m_fadeStart = t2;
aSkidmarks[i].m_fadeEnd = t3;
}else{
aSkidmarks[i].m_fadeStart = t3;
aSkidmarks[i].m_fadeEnd = t4;
}
}
break;
case 2:
if(CTimer::GetTimeInMilliseconds() > aSkidmarks[i].m_fadeEnd)
aSkidmarks[i].m_state = 0;
break;
}
aSkidmarks[i].m_wasUpdated = false;
}
}
void
CSkidmarks::Render(void)
{
int i, j;
RwTexture *lastTex = nil;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
for(i = 0; i < NUMSKIDMARKS; i++){
if(aSkidmarks[i].m_state == 0 || aSkidmarks[i].m_last < 1)
continue;
if(aSkidmarks[i].m_isBloody){
if(lastTex != gpSkidBloodTex){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidBloodTex));
lastTex = gpSkidBloodTex;
}
}else if(aSkidmarks[i].m_isMuddy){
if(lastTex != gpSkidMudTex){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidMudTex));
lastTex = gpSkidMudTex;
}
}else{
if(lastTex != gpSkidTex){
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex));
lastTex = gpSkidTex;
}
}
uint32 fade, alpha;
if(aSkidmarks[i].m_state == 1 || CTimer::GetTimeInMilliseconds() < aSkidmarks[i].m_fadeStart)
fade = 255;
else
fade = 255*(aSkidmarks[i].m_fadeEnd - CTimer::GetTimeInMilliseconds()) / (aSkidmarks[i].m_fadeEnd - aSkidmarks[i].m_fadeStart);
for(j = 0; j <= aSkidmarks[i].m_last; j++){
alpha = 128;
if(j == 0 || j == aSkidmarks[i].m_last && aSkidmarks[i].m_state == 2)
alpha = 0;
alpha = alpha*fade/256;
CVector p1 = aSkidmarks[i].m_pos[j] + aSkidmarks[i].m_side[j];
CVector p2 = aSkidmarks[i].m_pos[j] - aSkidmarks[i].m_side[j];
RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], 255, 255, 255, alpha);
RwIm3DVertexSetPos(&SkidmarkVertices[j*2+0], p1.x, p1.y, p1.z+0.1f);
RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], 255, 255, 255, alpha);
RwIm3DVertexSetPos(&SkidmarkVertices[j*2+1], p2.x, p2.y, p2.z+0.1f);
}
LittleTest();
if(RwIm3DTransform(SkidmarkVertices, 2*(aSkidmarks[i].m_last+1), nil, rwIM3D_VERTEXUV)){
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, SkidmarkIndexList, 6*aSkidmarks[i].m_last);
RwIm3DEnd();
}
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
}
void
CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody)
{
int i;
CVector2D fwd(fwdX, fwdY);
if(CReplay::IsPlayingBack())
return;
// Find a skidmark to continue
for(i = 0; i < NUMSKIDMARKS; i++)
if(aSkidmarks[i].m_state == 1 && aSkidmarks[i].m_id == id)
break;
if(i < NUMSKIDMARKS){
// Continue this one
if(aSkidmarks[i].m_isBloody != *isBloody){
// Blood-status changed, end this one
aSkidmarks[i].m_state = 2;
aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;
aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;
return;
}
aSkidmarks[i].m_wasUpdated = true;
if(CTimer::GetTimeInMilliseconds() - aSkidmarks[i].m_lastUpdate <= 100){
// Last update was recently, just change last coords
aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
return;
}
aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds();
if(aSkidmarks[i].m_last >= SKIDMARK_LENGTH-1){
// No space to continue, end it
aSkidmarks[i].m_state = 2;
aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;
aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;
*isBloody = false; // stpo blood marks at end
return;
}
aSkidmarks[i].m_last++;
aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
CVector2D dist = aSkidmarks[i].m_pos[aSkidmarks[i].m_last] - aSkidmarks[i].m_pos[aSkidmarks[i].m_last-1];
dist.Normalise();
CVector2D right(dist.y, -dist.x);
float turn = DotProduct2D(fwd, right);
turn = Abs(turn) + 1.0f;
aSkidmarks[i].m_side[aSkidmarks[i].m_last] = CVector(right.x, right.y, 0.0f) * turn * 0.125f;
if(aSkidmarks[i].m_last == 1)
aSkidmarks[i].m_side[0] = aSkidmarks[i].m_side[1];
if(aSkidmarks[i].m_last > 8)
*isBloody = false; // stop blood marks after 8
return;
}
// Start a new one
for(i = 0; i < NUMSKIDMARKS; i++)
if(aSkidmarks[i].m_state == 0)
break;
if(i < NUMSKIDMARKS){
// Found a free slot
aSkidmarks[i].m_state = 1;
aSkidmarks[i].m_id = id;
aSkidmarks[i].m_pos[0] = pos;
aSkidmarks[i].m_side[0] = CVector(0.0f, 0.0f, 0.0f);
aSkidmarks[i].m_wasUpdated = true;
aSkidmarks[i].m_last = 0;
aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds() - 1000;
aSkidmarks[i].m_isBloody = *isBloody;
aSkidmarks[i].m_isMuddy = *isMuddy;
}else
*isBloody = false; // stop blood marks if no space
}

View file

@ -1,12 +1,32 @@
#pragma once #pragma once
enum { SKIDMARK_LENGTH = 16 };
class CSkidmark
{
public:
uint8 m_state;
bool m_wasUpdated;
bool m_isBloody;
bool m_isMuddy;
uintptr m_id;
int16 m_last;
uint32 m_lastUpdate;;
uint32 m_fadeStart;
uint32 m_fadeEnd;
CVector m_pos[SKIDMARK_LENGTH];
CVector m_side[SKIDMARK_LENGTH];
};
class CSkidmarks class CSkidmarks
{ {
static CSkidmark aSkidmarks[NUMSKIDMARKS];
public: public:
static void Init(void);
static void Shutdown(void);
static void Clear(void); static void Clear(void);
static void Update(void); static void Update(void);
static void Render(void); static void Render(void);
static void RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy); static void RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody);
static void Init(void);
static void Shutdown(void);
}; };

View file

@ -22,10 +22,10 @@
#include "Shadows.h" #include "Shadows.h"
#include "main.h" #include "main.h"
RxObjSpace3DVertex StreakVertices[4]; RwIm3DVertex StreakVertices[4];
RwImVertexIndex StreakIndexList[12]; RwImVertexIndex StreakIndexList[12];
RxObjSpace3DVertex TraceVertices[6]; RwIm3DVertex TraceVertices[6];
RwImVertexIndex TraceIndexList[12]; RwImVertexIndex TraceIndexList[12];
@ -34,60 +34,60 @@ CSpecialFX::Init(void)
{ {
CBulletTraces::Init(); CBulletTraces::Init();
RwIm3DVertexSetU(&StreakVertices[0], 0.0f); RwIm3DVertexSetU(&StreakVertices[0], 0.0f);
RwIm3DVertexSetV(&StreakVertices[0], 0.0f); RwIm3DVertexSetV(&StreakVertices[0], 0.0f);
RwIm3DVertexSetU(&StreakVertices[1], 1.0f); RwIm3DVertexSetU(&StreakVertices[1], 1.0f);
RwIm3DVertexSetV(&StreakVertices[1], 0.0f); RwIm3DVertexSetV(&StreakVertices[1], 0.0f);
RwIm3DVertexSetU(&StreakVertices[2], 0.0f); RwIm3DVertexSetU(&StreakVertices[2], 0.0f);
RwIm3DVertexSetV(&StreakVertices[2], 0.0f); RwIm3DVertexSetV(&StreakVertices[2], 0.0f);
RwIm3DVertexSetU(&StreakVertices[3], 1.0f); RwIm3DVertexSetU(&StreakVertices[3], 1.0f);
RwIm3DVertexSetV(&StreakVertices[3], 0.0f); RwIm3DVertexSetV(&StreakVertices[3], 0.0f);
StreakIndexList[0] = 0; StreakIndexList[0] = 0;
StreakIndexList[1] = 1; StreakIndexList[1] = 1;
StreakIndexList[2] = 2; StreakIndexList[2] = 2;
StreakIndexList[3] = 1; StreakIndexList[3] = 1;
StreakIndexList[4] = 3; StreakIndexList[4] = 3;
StreakIndexList[5] = 2; StreakIndexList[5] = 2;
StreakIndexList[6] = 0; StreakIndexList[6] = 0;
StreakIndexList[7] = 2; StreakIndexList[7] = 2;
StreakIndexList[8] = 1; StreakIndexList[8] = 1;
StreakIndexList[9] = 1; StreakIndexList[9] = 1;
StreakIndexList[10] = 2; StreakIndexList[10] = 2;
StreakIndexList[11] = 3; StreakIndexList[11] = 3;
RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255); RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255);
RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255); RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255);
RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255); RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255);
RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255); RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255);
RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255); RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255);
RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255); RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255);
RwIm3DVertexSetU(&TraceVertices[0], 0.0); RwIm3DVertexSetU(&TraceVertices[0], 0.0);
RwIm3DVertexSetV(&TraceVertices[0], 0.0); RwIm3DVertexSetV(&TraceVertices[0], 0.0);
RwIm3DVertexSetU(&TraceVertices[1], 1.0); RwIm3DVertexSetU(&TraceVertices[1], 1.0);
RwIm3DVertexSetV(&TraceVertices[1], 0.0); RwIm3DVertexSetV(&TraceVertices[1], 0.0);
RwIm3DVertexSetU(&TraceVertices[2], 0.0); RwIm3DVertexSetU(&TraceVertices[2], 0.0);
RwIm3DVertexSetV(&TraceVertices[2], 0.5); RwIm3DVertexSetV(&TraceVertices[2], 0.5);
RwIm3DVertexSetU(&TraceVertices[3], 1.0); RwIm3DVertexSetU(&TraceVertices[3], 1.0);
RwIm3DVertexSetV(&TraceVertices[3], 0.5); RwIm3DVertexSetV(&TraceVertices[3], 0.5);
RwIm3DVertexSetU(&TraceVertices[4], 0.0); RwIm3DVertexSetU(&TraceVertices[4], 0.0);
RwIm3DVertexSetV(&TraceVertices[4], 1.0); RwIm3DVertexSetV(&TraceVertices[4], 1.0);
RwIm3DVertexSetU(&TraceVertices[5], 1.0); RwIm3DVertexSetU(&TraceVertices[5], 1.0);
RwIm3DVertexSetV(&TraceVertices[5], 1.0); RwIm3DVertexSetV(&TraceVertices[5], 1.0);
TraceIndexList[0] = 0;
TraceIndexList[1] = 2;
TraceIndexList[2] = 1;
TraceIndexList[3] = 1;
TraceIndexList[4] = 2;
TraceIndexList[5] = 3;
TraceIndexList[6] = 2;
TraceIndexList[7] = 4;
TraceIndexList[8] = 3;
TraceIndexList[9] = 3;
TraceIndexList[10] = 4;
TraceIndexList[11] = 5;
TraceIndexList[0] = 0;
TraceIndexList[1] = 2;
TraceIndexList[2] = 1;
TraceIndexList[3] = 1;
TraceIndexList[4] = 2;
TraceIndexList[5] = 3;
TraceIndexList[6] = 2;
TraceIndexList[7] = 4;
TraceIndexList[8] = 3;
TraceIndexList[9] = 3;
TraceIndexList[10] = 4;
TraceIndexList[11] = 5;
CMotionBlurStreaks::Init(); CMotionBlurStreaks::Init();
CBrightLights::Init(); CBrightLights::Init();
CShinyTexts::Init(); CShinyTexts::Init();
@ -112,13 +112,13 @@ LookForBatCB(RwObject *object, void *data)
void void
CSpecialFX::Update(void) CSpecialFX::Update(void)
{ {
CMotionBlurStreaks::Update(); CMotionBlurStreaks::Update();
CBulletTraces::Update(); CBulletTraces::Update();
if(FindPlayerPed() && if(FindPlayerPed() &&
FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT &&
FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING) FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING)
RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT));
} }
void void
@ -130,78 +130,78 @@ CSpecialFX::Shutdown(void)
void void
CSpecialFX::Render(void) CSpecialFX::Render(void)
{ {
CMotionBlurStreaks::Render(); CMotionBlurStreaks::Render();
CBulletTraces::Render(); CBulletTraces::Render();
CBrightLights::Render(); CBrightLights::Render();
CShinyTexts::Render(); CShinyTexts::Render();
CMoneyMessages::Render(); CMoneyMessages::Render();
C3dMarkers::Render(); C3dMarkers::Render();
} }
CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS]; CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS];
void void
CRegisteredMotionBlurStreak::Update(void) CRegisteredMotionBlurStreak::Update(void)
{ {
int i; int i;
bool wasUpdated; bool wasUpdated;
bool lastWasUpdated = false; bool lastWasUpdated = false;
for(i = 2; i > 0; i--){ for(i = 2; i > 0; i--){
m_pos1[i] = m_pos1[i-1]; m_pos1[i] = m_pos1[i-1];
m_pos2[i] = m_pos2[i-1]; m_pos2[i] = m_pos2[i-1];
m_isValid[i] = m_isValid[i-1]; m_isValid[i] = m_isValid[i-1];
wasUpdated = true; wasUpdated = true;
if(!lastWasUpdated && !m_isValid[i]) if(!lastWasUpdated && !m_isValid[i])
wasUpdated = false; wasUpdated = false;
lastWasUpdated = wasUpdated; lastWasUpdated = wasUpdated;
} }
m_isValid[0] = false; m_isValid[0] = false;
if(!wasUpdated) if(!wasUpdated)
m_id = 0; m_id = 0;
} }
void void
CRegisteredMotionBlurStreak::Render(void) CRegisteredMotionBlurStreak::Render(void)
{ {
int i; int i;
int a1, a2; int a1, a2;
for(i = 0; i < 2; i++) for(i = 0; i < 2; i++)
if(m_isValid[i] && m_isValid[i+1]){ if(m_isValid[i] && m_isValid[i+1]){
a1 = (255/3)*(3-i)/3; a1 = (255/3)*(3-i)/3;
RwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1); RwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1);
RwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1); RwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1);
a2 = (255/3)*(3-(i+1))/3; a2 = (255/3)*(3-(i+1))/3;
RwIm3DVertexSetRGBA(&StreakVertices[2], m_red, m_green, m_blue, a2); RwIm3DVertexSetRGBA(&StreakVertices[2], m_red, m_green, m_blue, a2);
RwIm3DVertexSetRGBA(&StreakVertices[3], m_red, m_green, m_blue, a2); RwIm3DVertexSetRGBA(&StreakVertices[3], m_red, m_green, m_blue, a2);
RwIm3DVertexSetPos(&StreakVertices[0], m_pos1[i].x, m_pos1[i].y, m_pos1[i].z); RwIm3DVertexSetPos(&StreakVertices[0], m_pos1[i].x, m_pos1[i].y, m_pos1[i].z);
RwIm3DVertexSetPos(&StreakVertices[1], m_pos2[i].x, m_pos2[i].y, m_pos2[i].z); RwIm3DVertexSetPos(&StreakVertices[1], m_pos2[i].x, m_pos2[i].y, m_pos2[i].z);
RwIm3DVertexSetPos(&StreakVertices[2], m_pos1[i+1].x, m_pos1[i+1].y, m_pos1[i+1].z); RwIm3DVertexSetPos(&StreakVertices[2], m_pos1[i+1].x, m_pos1[i+1].y, m_pos1[i+1].z);
RwIm3DVertexSetPos(&StreakVertices[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z); RwIm3DVertexSetPos(&StreakVertices[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z);
LittleTest(); LittleTest();
if(RwIm3DTransform(StreakVertices, 4, nil, rwIM3D_VERTEXUV)){ if(RwIm3DTransform(StreakVertices, 4, nil, rwIM3D_VERTEXUV)){
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, StreakIndexList, 12); RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, StreakIndexList, 12);
RwIm3DEnd(); RwIm3DEnd();
} }
} }
} }
void
CMotionBlurStreaks::Init(void)
{
int i;
for(i = 0; i < NUMMBLURSTREAKS; i++)
aStreaks[i].m_id = 0;
}
void
CMotionBlurStreaks::Update(void)
{
int i;
for(i = 0; i < NUMMBLURSTREAKS; i++)
if(aStreaks[i].m_id)
aStreaks[i].Update();
}
void
CMotionBlurStreaks::Init(void)
{
int i;
for(i = 0; i < NUMMBLURSTREAKS; i++)
aStreaks[i].m_id = 0;
}
void
CMotionBlurStreaks::Update(void)
{
int i;
for(i = 0; i < NUMMBLURSTREAKS; i++)
if(aStreaks[i].m_id)
aStreaks[i].Update();
}
void void
CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2)
{ {
@ -234,32 +234,32 @@ CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVecto
aStreaks[i].m_isValid[2] = false; aStreaks[i].m_isValid[2] = false;
} }
void void
CMotionBlurStreaks::Render(void) CMotionBlurStreaks::Render(void)
{ {
bool setRenderStates = false; bool setRenderStates = false;
int i; int i;
for(i = 0; i < NUMMBLURSTREAKS; i++) for(i = 0; i < NUMMBLURSTREAKS; i++)
if(aStreaks[i].m_id){ if(aStreaks[i].m_id){
if(!setRenderStates){ if(!setRenderStates){
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGCOLOR, RwRenderStateSet(rwRENDERSTATEFOGCOLOR,
(void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255)); (void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
setRenderStates = true; setRenderStates = true;
} }
aStreaks[i].Render(); aStreaks[i].Render();
} }
if(setRenderStates){ if(setRenderStates){
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
} }
} }
CBulletTrace CBulletTraces::aTraces[NUMBULLETTRACES]; CBulletTrace CBulletTraces::aTraces[NUMBULLETTRACES];
@ -291,10 +291,10 @@ void CBulletTraces::Render(void)
for (int i = 0; i < NUMBULLETTRACES; i++) { for (int i = 0; i < NUMBULLETTRACES; i++) {
if (!aTraces[i].m_bInUse) if (!aTraces[i].m_bInUse)
continue; continue;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)2); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpShadowExplosionTex->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpShadowExplosionTex));
CVector inf = aTraces[i].m_vecCurrentPos; CVector inf = aTraces[i].m_vecCurrentPos;
CVector sup = aTraces[i].m_vecTargetPos; CVector sup = aTraces[i].m_vecTargetPos;
CVector center = (inf + sup) / 2; CVector center = (inf + sup) / 2;
@ -316,9 +316,9 @@ void CBulletTraces::Render(void)
RwIm3DEnd(); RwIm3DEnd();
} }
} }
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
} }
void CBulletTraces::Update(void) void CBulletTraces::Update(void)
@ -414,8 +414,7 @@ C3dMarker::Render()
{ {
if (m_pAtomic == nil) return; if (m_pAtomic == nil) return;
RwRGBA *color = RpMaterialGetColor(m_pMaterial); RpMaterialSetColor(m_pMaterial, &m_Color);
*color = m_Color;
m_Matrix.UpdateRW(); m_Matrix.UpdateRW();
@ -643,13 +642,13 @@ C3dMarkers::Update()
int CBrightLights::NumBrightLights; int CBrightLights::NumBrightLights;
CBrightLight CBrightLights::aBrightLights[NUMBRIGHTLIGHTS]; CBrightLight CBrightLights::aBrightLights[NUMBRIGHTLIGHTS];
void void
CBrightLights::Init(void) CBrightLights::Init(void)
{ {
NumBrightLights = 0; NumBrightLights = 0;
} }
void void
CBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front, CBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front,
uint8 type, uint8 red, uint8 green, uint8 blue) uint8 type, uint8 red, uint8 green, uint8 blue)
@ -661,13 +660,13 @@ CBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front,
if(aBrightLights[NumBrightLights].m_camDist > BRIGHTLIGHTS_MAX_DIST) if(aBrightLights[NumBrightLights].m_camDist > BRIGHTLIGHTS_MAX_DIST)
return; return;
aBrightLights[NumBrightLights].m_pos = pos; aBrightLights[NumBrightLights].m_pos = pos;
aBrightLights[NumBrightLights].m_up = up; aBrightLights[NumBrightLights].m_up = up;
aBrightLights[NumBrightLights].m_side = side; aBrightLights[NumBrightLights].m_side = side;
aBrightLights[NumBrightLights].m_front = front; aBrightLights[NumBrightLights].m_front = front;
aBrightLights[NumBrightLights].m_type = type; aBrightLights[NumBrightLights].m_type = type;
aBrightLights[NumBrightLights].m_red = red; aBrightLights[NumBrightLights].m_red = red;
aBrightLights[NumBrightLights].m_green = green; aBrightLights[NumBrightLights].m_green = green;
aBrightLights[NumBrightLights].m_blue = blue; aBrightLights[NumBrightLights].m_blue = blue;
NumBrightLights++; NumBrightLights++;
@ -696,22 +695,22 @@ static RwImVertexIndex CubeIndices[12*3] = {
6, 0, 4, 6, 2, 0, 6, 5, 7, 6, 4, 5 6, 0, 4, 6, 2, 0, 6, 5, 7, 6, 4, 5
}; };
void void
CBrightLights::Render(void) CBrightLights::Render(void)
{ {
int i, j; int i, j;
CVector pos; CVector pos;
if(NumBrightLights == 0) if(NumBrightLights == 0)
return; return;
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
for(i = 0; i < NumBrightLights; i++){ for(i = 0; i < NumBrightLights; i++){
if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40) if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40)
RenderOutGeometryBuffer(); RenderOutGeometryBuffer();
@ -753,14 +752,14 @@ CBrightLights::Render(void)
a = 255; a = 255;
else else
a = 255*(1.0f - (aBrightLights[i].m_camDist-BRIGHTLIGHTS_FADE_DIST)/(BRIGHTLIGHTS_MAX_DIST-BRIGHTLIGHTS_FADE_DIST)); a = 255*(1.0f - (aBrightLights[i].m_camDist-BRIGHTLIGHTS_FADE_DIST)/(BRIGHTLIGHTS_MAX_DIST-BRIGHTLIGHTS_FADE_DIST));
// fade car lights down to 31 as they come near // fade car lights down to 31 as they come near
if(aBrightLights[i].m_type >= BRIGHTLIGHT_FRONT_LONG && aBrightLights[i].m_type <= BRIGHTLIGHT_REAR_TALL){ if(aBrightLights[i].m_type >= BRIGHTLIGHT_FRONT_LONG && aBrightLights[i].m_type <= BRIGHTLIGHT_REAR_TALL){
if(aBrightLights[i].m_camDist < CARLIGHTS_FADE_DIST) if(aBrightLights[i].m_camDist < CARLIGHTS_FADE_DIST)
a = 31; a = 31;
else if(aBrightLights[i].m_camDist < CARLIGHTS_MAX_DIST) else if(aBrightLights[i].m_camDist < CARLIGHTS_MAX_DIST)
a = 31 + (255-31)*((aBrightLights[i].m_camDist-CARLIGHTS_FADE_DIST)/(CARLIGHTS_MAX_DIST-CARLIGHTS_FADE_DIST)); a = 31 + (255-31)*((aBrightLights[i].m_camDist-CARLIGHTS_FADE_DIST)/(CARLIGHTS_MAX_DIST-CARLIGHTS_FADE_DIST));
} }
switch(aBrightLights[i].m_type){ switch(aBrightLights[i].m_type){
case BRIGHTLIGHT_TRAFFIC_GREEN: case BRIGHTLIGHT_TRAFFIC_GREEN:
case BRIGHTLIGHT_TRAFFIC_YELLOW: case BRIGHTLIGHT_TRAFFIC_YELLOW:
@ -793,7 +792,7 @@ CBrightLights::Render(void)
TempBufferVerticesStored += 8; TempBufferVerticesStored += 8;
TempBufferIndicesStored += 12*3; TempBufferIndicesStored += 12*3;
break; break;
case BRIGHTLIGHT_FRONT_SMALL: case BRIGHTLIGHT_FRONT_SMALL:
case BRIGHTLIGHT_REAR_SMALL: case BRIGHTLIGHT_REAR_SMALL:
for(j = 0; j < 8; j++){ for(j = 0; j < 8; j++){
@ -809,7 +808,7 @@ CBrightLights::Render(void)
TempBufferVerticesStored += 8; TempBufferVerticesStored += 8;
TempBufferIndicesStored += 12*3; TempBufferIndicesStored += 12*3;
break; break;
case BRIGHTLIGHT_FRONT_TALL: case BRIGHTLIGHT_FRONT_TALL:
case BRIGHTLIGHT_REAR_TALL: case BRIGHTLIGHT_REAR_TALL:
for(j = 0; j < 8; j++){ for(j = 0; j < 8; j++){
@ -840,17 +839,17 @@ CBrightLights::Render(void)
TempBufferIndicesStored += 4*3; TempBufferIndicesStored += 4*3;
break; break;
} }
} }
RenderOutGeometryBuffer(); RenderOutGeometryBuffer();
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
NumBrightLights = 0; NumBrightLights = 0;
} }
void void
CBrightLights::RenderOutGeometryBuffer(void) CBrightLights::RenderOutGeometryBuffer(void)
{ {
if(TempBufferIndicesStored != 0){ if(TempBufferIndicesStored != 0){
LittleTest(); LittleTest();
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){ if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
@ -864,13 +863,13 @@ CBrightLights::RenderOutGeometryBuffer(void)
int CShinyTexts::NumShinyTexts; int CShinyTexts::NumShinyTexts;
CShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS]; CShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS];
void void
CShinyTexts::Init(void) CShinyTexts::Init(void)
{ {
NumShinyTexts = 0; NumShinyTexts = 0;
} }
void void
CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3, CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,
@ -910,20 +909,20 @@ CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
NumShinyTexts++; NumShinyTexts++;
} }
void void
CShinyTexts::Render(void) CShinyTexts::Render(void)
{ {
int i, ix, v; int i, ix, v;
RwTexture *lastTex = nil; RwTexture *lastTex = nil;
if(NumShinyTexts == 0) if(NumShinyTexts == 0)
return; return;
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
TempBufferVerticesStored = 0; TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0; TempBufferIndicesStored = 0;
@ -984,15 +983,15 @@ CShinyTexts::Render(void)
RenderOutGeometryBuffer(); RenderOutGeometryBuffer();
NumShinyTexts = 0; NumShinyTexts = 0;
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
} }
void void
CShinyTexts::RenderOutGeometryBuffer(void) CShinyTexts::RenderOutGeometryBuffer(void)
{ {
if(TempBufferIndicesStored != 0){ if(TempBufferIndicesStored != 0){
LittleTest(); LittleTest();
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){ if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
@ -1002,8 +1001,8 @@ CShinyTexts::RenderOutGeometryBuffer(void)
TempBufferVerticesStored = 0; TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0; TempBufferIndicesStored = 0;
} }
} }
#define MONEY_MESSAGE_LIFETIME_MS 2000 #define MONEY_MESSAGE_LIFETIME_MS 2000

View file

@ -12,26 +12,26 @@ public:
class CRegisteredMotionBlurStreak class CRegisteredMotionBlurStreak
{ {
public: public:
uintptr m_id; uintptr m_id;
uint8 m_red; uint8 m_red;
uint8 m_green; uint8 m_green;
uint8 m_blue; uint8 m_blue;
CVector m_pos1[3]; CVector m_pos1[3];
CVector m_pos2[3]; CVector m_pos2[3];
bool m_isValid[3]; bool m_isValid[3];
void Update(void); void Update(void);
void Render(void); void Render(void);
}; };
class CMotionBlurStreaks class CMotionBlurStreaks
{ {
static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS]; static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS];
public: public:
static void Init(void); static void Init(void);
static void Update(void); static void Update(void);
static void RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2); static void RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2);
static void Render(void); static void Render(void);
}; };
struct CBulletTrace struct CBulletTrace
@ -133,18 +133,18 @@ enum
BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG, BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG,
}; };
class CBrightLight class CBrightLight
{ {
public: public:
CVector m_pos; CVector m_pos;
CVector m_up; CVector m_up;
CVector m_side; CVector m_side;
CVector m_front; CVector m_front;
float m_camDist; float m_camDist;
uint8 m_type; uint8 m_type;
uint8 m_red; uint8 m_red;
uint8 m_green; uint8 m_green;
uint8 m_blue; uint8 m_blue;
}; };
class CBrightLights class CBrightLights
@ -152,11 +152,11 @@ class CBrightLights
static int NumBrightLights; static int NumBrightLights;
static CBrightLight aBrightLights[NUMBRIGHTLIGHTS]; static CBrightLight aBrightLights[NUMBRIGHTLIGHTS];
public: public:
static void Init(void); static void Init(void);
static void RegisterOne(CVector pos, CVector up, CVector side, CVector front, static void RegisterOne(CVector pos, CVector up, CVector side, CVector front,
uint8 type, uint8 red = 0, uint8 green = 0, uint8 blue = 0); uint8 type, uint8 red = 0, uint8 green = 0, uint8 blue = 0);
static void Render(void); static void Render(void);
static void RenderOutGeometryBuffer(void); static void RenderOutGeometryBuffer(void);
}; };
@ -169,12 +169,12 @@ enum
class CShinyText class CShinyText
{ {
public: public:
CVector m_verts[4]; CVector m_verts[4];
CVector2D m_texCoords[4]; CVector2D m_texCoords[4];
float m_camDist; float m_camDist;
uint8 m_type; uint8 m_type;
uint8 m_red; uint8 m_red;
uint8 m_green; uint8 m_green;
uint8 m_blue; uint8 m_blue;
}; };
@ -183,12 +183,12 @@ class CShinyTexts
static int NumShinyTexts; static int NumShinyTexts;
static CShinyText aShinyTexts[NUMSHINYTEXTS]; static CShinyText aShinyTexts[NUMSHINYTEXTS];
public: public:
static void Init(void); static void Init(void);
static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3, static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,
uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist);
static void Render(void); static void Render(void);
static void RenderOutGeometryBuffer(void); static void RenderOutGeometryBuffer(void);
}; };
class CMoneyMessage class CMoneyMessage

View file

@ -30,10 +30,12 @@ CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh,
out->x *= SCREEN_WIDTH * recip; out->x *= SCREEN_WIDTH * recip;
out->y *= SCREEN_HEIGHT * recip; out->y *= SCREEN_HEIGHT * recip;
// What is this? size? // What is this? size?
*outw = 70.0f/CDraw::GetFOV(); *outw = 70.0f/CDraw::GetFOV() * SCREEN_WIDTH * recip;
*outh = 70.0f/CDraw::GetFOV(); #ifdef ASPECT_RATIO_SCALE
*outw *= SCREEN_WIDTH * recip; *outh = 70.0f/CDraw::GetFOV() / (DEFAULT_ASPECT_RATIO / SCREEN_ASPECT_RATIO) * SCREEN_HEIGHT * recip;
*outh *= SCREEN_HEIGHT * recip; #else
*outh = 70.0f/CDraw::GetFOV() * SCREEN_HEIGHT * recip;
#endif
return true; return true;
} }
@ -432,6 +434,7 @@ void
CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{ {
float screenz, recipz; float screenz, recipz;
float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = m_f2DNearScreenZ; screenz = m_f2DNearScreenZ;
recipz = m_fRecipNearClipPlane; recipz = m_fRecipNearClipPlane;
@ -496,6 +499,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, float x1, float y1, float x2, float
const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{ {
float screenz, recipz; float screenz, recipz;
float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = m_f2DNearScreenZ; screenz = m_f2DNearScreenZ;
recipz = m_fRecipNearClipPlane; recipz = m_fRecipNearClipPlane;

View file

@ -267,6 +267,7 @@ CSprite2d::SetVertices(float x1, float y1, float x2, float y2, float x3, float y
const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3) const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{ {
float screenz, recipz; float screenz, recipz;
float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = RwIm2DGetNearScreenZ(); screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip; recipz = RecipNearClip;
@ -312,10 +313,11 @@ void
CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col) CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col)
{ {
int i; int i;
float screenz, recipz; float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ(); screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip; recipz = RecipNearClip;
z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
for(i = 0; i < n; i++){ for(i = 0; i < n; i++){
@ -334,10 +336,11 @@ void
CSprite2d::SetMaskVertices(int n, float *positions) CSprite2d::SetMaskVertices(int n, float *positions)
{ {
int i; int i;
float screenz, recipz; float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ(); screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip; recipz = RecipNearClip;
z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
for(i = 0; i < n; i++){ for(i = 0; i < n; i++){
RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]); RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);
@ -345,7 +348,7 @@ CSprite2d::SetMaskVertices(int n, float *positions)
RwIm2DVertexSetScreenZ(&maVertices[i], screenz); RwIm2DVertexSetScreenZ(&maVertices[i], screenz);
RwIm2DVertexSetCameraZ(&maVertices[i], z); RwIm2DVertexSetCameraZ(&maVertices[i], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz); RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[i], 0, 0, 0, 0); RwIm2DVertexSetIntRGBA(&maVertices[i], 255, 255, 255, 255); // 0, 0, 0, 0 on PC
} }
} }
@ -353,10 +356,11 @@ void
CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2) float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
{ {
float screenz, recipz; float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ(); screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip; recipz = RecipNearClip;
z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
RwIm2DVertexSetScreenX(&verts[0], r.left); RwIm2DVertexSetScreenX(&verts[0], r.left);
RwIm2DVertexSetScreenY(&verts[0], r.top); RwIm2DVertexSetScreenY(&verts[0], r.top);
@ -459,15 +463,15 @@ CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C
void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color) void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color)
{ {
SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color); SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4); RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
} }

41
src/render/TexList.cpp Normal file
View file

@ -0,0 +1,41 @@
#include "common.h"
#include "TexList.h"
#include "rtbmp.h"
#include "FileMgr.h"
bool CTexList::ms_nTexUsed[MAX_TEXUSED];
void
CTexList::Initialise()
{}
void
CTexList::Shutdown()
{}
RwTexture *
CTexList::SetTexture(int32 slot, char *name)
{
return nil;
}
int32
CTexList::GetFirstFreeTexture()
{
for (int32 i = 0; i < MAX_TEXUSED; i++)
if (!ms_nTexUsed[i])
return i;
return -1;
}
RwTexture *
CTexList::LoadFileNameTexture(char *name)
{
return SetTexture(GetFirstFreeTexture(), name);
}
void
CTexList::LoadGlobalTextureList()
{
CFileMgr::SetDir("TEXTURES");
}

14
src/render/TexList.h Normal file
View file

@ -0,0 +1,14 @@
#pragma once
class CTexList
{
enum { MAX_TEXUSED = 400, };
static bool ms_nTexUsed[MAX_TEXUSED];
public:
static void Initialise();
static void Shutdown();
static RwTexture *SetTexture(int32 slot, char *name);
static int32 GetFirstFreeTexture();
static RwTexture *LoadFileNameTexture(char *name);
static void LoadGlobalTextureList();
};

View file

@ -117,7 +117,7 @@ CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera)
RpMaterial* RpMaterial*
SetAlphaCB(RpMaterial *material, void *data) SetAlphaCB(RpMaterial *material, void *data)
{ {
material->color.alpha = (uint8)(uint32)data; ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uint32)data;
return material; return material;
} }

View file

@ -83,7 +83,7 @@ CWeaponEffects::Render(void)
{ {
float recipz = 1.0f / pos.z; float recipz = 1.0f / pos.z;
CSprite::RenderOneXLUSprite(pos.x, pos.y, pos.z, CSprite::RenderOneXLUSprite(pos.x, pos.y, pos.z,
gCrossHair.m_fSize * w, gCrossHair.m_fSize * SCREEN_SCALE_AR2(h), gCrossHair.m_fSize * w, gCrossHair.m_fSize * h,
gCrossHair.m_nRed, gCrossHair.m_nGreen, gCrossHair.m_nBlue, 255, gCrossHair.m_nRed, gCrossHair.m_nGreen, gCrossHair.m_nBlue, 255,
recipz, 255); recipz, 255);
} }

View file

@ -71,8 +71,8 @@ const int16 WeatherTypesList[] = {
const float Windiness[] = { const float Windiness[] = {
0.0f, // WEATHER_SUNNY 0.0f, // WEATHER_SUNNY
0.7f, // WEATHER_RAINY 0.7f, // WEATHER_CLOUDY
1.0f, // WEATHER_CLOUDY 1.0f, // WEATHER_RAINY
0.5f // WEATHER_FOGGY 0.5f // WEATHER_FOGGY
}; };
@ -106,7 +106,7 @@ void CWeather::Init(void)
{ {
NewWeatherType = WEATHER_SUNNY; NewWeatherType = WEATHER_SUNNY;
bScriptsForceRain = false; bScriptsForceRain = false;
OldWeatherType = WEATHER_RAINY; OldWeatherType = WEATHER_CLOUDY;
Stored_StateStored = false; Stored_StateStored = false;
InterpolationValue = 0.0f; InterpolationValue = 0.0f;
WhenToPlayLightningSound = 0; WhenToPlayLightningSound = 0;
@ -475,7 +475,7 @@ void CWeather::RenderRainStreaks(void)
// 1/16 probability // 1/16 probability
Streaks[i].direction = CVector(4.0f, 4.0f, -4.0f); Streaks[i].direction = CVector(4.0f, 4.0f, -4.0f);
Streaks[i].position = 6.0f * TheCamera.GetForward() + TheCamera.GetPosition() + CVector(-1.8f * Streaks[i].direction.x, -1.8f * Streaks[i].direction.y, 8.0f); Streaks[i].position = 6.0f * TheCamera.GetForward() + TheCamera.GetPosition() + CVector(-1.8f * Streaks[i].direction.x, -1.8f * Streaks[i].direction.y, 8.0f);
if (!CCutsceneMgr::IsCutsceneProcessing()) { if (!CCutsceneMgr::IsRunning()) {
Streaks[i].position.x += 2.0f * FindPlayerSpeed().x * 60.0f; Streaks[i].position.x += 2.0f * FindPlayerSpeed().x * 60.0f;
Streaks[i].position.y += 2.0f * FindPlayerSpeed().y * 60.0f; Streaks[i].position.y += 2.0f * FindPlayerSpeed().y * 60.0f;
} }

View file

@ -1,18 +1,18 @@
#pragma once #pragma once
class CDate class CDate
{ {
public: public:
int m_nSecond; int m_nSecond;
int m_nMinute; int m_nMinute;
int m_nHour; int m_nHour;
int m_nDay; int m_nDay;
int m_nMonth; int m_nMonth;
int m_nYear; int m_nYear;
CDate(); CDate();
bool operator>(const CDate &right); bool operator>(const CDate &right);
bool operator<(const CDate &right); bool operator<(const CDate &right);
bool operator==(const CDate &right); bool operator==(const CDate &right);
void PopulateDateFields(int8 &second, int8 &minute, int8 &hour, int8 &day, int8 &month, int16 year); void PopulateDateFields(int8 &second, int8 &minute, int8 &hour, int8 &day, int8 &month, int16 year);
}; };

View file

@ -48,6 +48,13 @@ char SaveFileNameJustSaved[260];
int (&Slots)[SLOT_COUNT+1] = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C; int (&Slots)[SLOT_COUNT+1] = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C;
CDate &CompileDateAndTime = *(CDate*)0x72BCB8; CDate &CompileDateAndTime = *(CDate*)0x72BCB8;
bool &b_FoundRecentSavedGameWantToLoad = *(bool*)0x95CDA8;
bool &JustLoadedDontFadeInYet = *(bool*)0x95CDB4;
bool &StillToFadeOut = *(bool*)0x95CD99;
uint32 &TimeStartedCountingForFade = *(uint32*)0x9430EC;
uint32 &TimeToStayFadedBeforeFadeOut = *(uint32*)0x611564;
#define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to)); #define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to));
#define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from)); #define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from));

View file

@ -1,37 +1,43 @@
#pragma once #pragma once
#include "PCSave.h" #include "PCSave.h"
#define SLOT_COUNT (8) #define SLOT_COUNT (8)
bool GenericSave(int file); bool GenericSave(int file);
bool GenericLoad(); bool GenericLoad();
bool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size); bool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size);
bool ReadDataFromFile(int32 file, uint8 *buf, uint32 size); bool ReadDataFromFile(int32 file, uint8 *buf, uint32 size);
bool CloseFile(int32 file); bool CloseFile(int32 file);
void DoGameSpecificStuffAfterSucessLoad(); void DoGameSpecificStuffAfterSucessLoad();
bool CheckSlotDataValid(int32 slot); bool CheckSlotDataValid(int32 slot);
void MakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize); void MakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize);
void CopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size); void CopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size);
void DoGameSpecificStuffBeforeSave(); void DoGameSpecificStuffBeforeSave();
void MakeValidSaveName(int32 slot); void MakeValidSaveName(int32 slot);
wchar *GetSavedGameDateAndTime(int32 slot); wchar *GetSavedGameDateAndTime(int32 slot);
wchar *GetNameOfSavedGame(int32 slot); wchar *GetNameOfSavedGame(int32 slot);
bool CheckDataNotCorrupt(int32 slot, char *name); bool CheckDataNotCorrupt(int32 slot, char *name);
bool RestoreForStartLoad(); bool RestoreForStartLoad();
int align4bytes(int32 size); int align4bytes(int32 size);
extern class CDate& CompileDateAndTime; extern class CDate& CompileDateAndTime;
extern char (&DefaultPCSaveFileName)[260]; extern char (&DefaultPCSaveFileName)[260];
extern char (&ValidSaveName)[260]; extern char (&ValidSaveName)[260];
extern char (&LoadFileName)[256]; extern char (&LoadFileName)[256];
extern wchar (&SlotFileName)[SLOT_COUNT][260]; extern wchar (&SlotFileName)[SLOT_COUNT][260];
extern wchar (&SlotSaveDate)[SLOT_COUNT][70]; extern wchar (&SlotSaveDate)[SLOT_COUNT][70];
extern int &CheckSum; extern int &CheckSum;
extern enum eLevelName &m_LevelToLoad; extern enum eLevelName &m_LevelToLoad;
extern int (&Slots)[SLOT_COUNT+1]; extern int (&Slots)[SLOT_COUNT+1];
extern char SaveFileNameJustSaved[260]; // 8F2570 extern bool &b_FoundRecentSavedGameWantToLoad;
extern bool &JustLoadedDontFadeInYet;
extern bool &StillToFadeOut;
extern uint32 &TimeStartedCountingForFade;
extern uint32 &TimeToStayFadedBeforeFadeOut;
extern char SaveFileNameJustSaved[260]; // 8F2570
const char TopLineEmptyFile[] = "THIS FILE IS NOT VALID YET"; const char TopLineEmptyFile[] = "THIS FILE IS NOT VALID YET";

View file

@ -1927,7 +1927,7 @@ _WinMain(HINSTANCE instance,
* Enter the message processing loop... * Enter the message processing loop...
*/ */
while( !RsGlobal.quit && !FrontEndMenuManager.m_bStartGameLoading ) while( !RsGlobal.quit && !FrontEndMenuManager.m_bWantToRestart )
{ {
if( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) ) if( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) )
{ {
@ -2059,13 +2059,13 @@ _WinMain(HINSTANCE instance,
if (wp.showCmd != SW_SHOWMINIMIZED) if (wp.showCmd != SW_SHOWMINIMIZED)
RsEventHandler(rsFRONTENDIDLE, nil); RsEventHandler(rsFRONTENDIDLE, nil);
if ( !FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bLoadingSavedGame ) if ( !FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bWantToLoad )
{ {
gGameState = GS_INIT_PLAYING_GAME; gGameState = GS_INIT_PLAYING_GAME;
TRACE("gGameState = GS_INIT_PLAYING_GAME;"); TRACE("gGameState = GS_INIT_PLAYING_GAME;");
} }
if ( FrontEndMenuManager.m_bLoadingSavedGame ) if ( FrontEndMenuManager.m_bWantToLoad )
{ {
InitialiseGame(); InitialiseGame();
FrontEndMenuManager.m_bGameNotLoaded = false; FrontEndMenuManager.m_bGameNotLoaded = false;
@ -2128,7 +2128,7 @@ _WinMain(HINSTANCE instance,
RwInitialised = FALSE; RwInitialised = FALSE;
FrontEndMenuManager.UnloadTextures(); FrontEndMenuManager.UnloadTextures();
if ( !FrontEndMenuManager.m_bStartGameLoading ) if ( !FrontEndMenuManager.m_bWantToRestart )
break; break;
CPad::ResetCheats(); CPad::ResetCheats();
@ -2138,13 +2138,13 @@ _WinMain(HINSTANCE instance,
CTimer::Stop(); CTimer::Stop();
if ( FrontEndMenuManager.m_bLoadingSavedGame ) if ( FrontEndMenuManager.m_bWantToLoad )
{ {
CGame::ShutDownForRestart(); CGame::ShutDownForRestart();
CGame::InitialiseWhenRestarting(); CGame::InitialiseWhenRestarting();
DMAudio.ChangeMusicMode(MUSICMODE_GAME); DMAudio.ChangeMusicMode(MUSICMODE_GAME);
LoadSplash(GetLevelSplashScreen(CGame::currLevel)); LoadSplash(GetLevelSplashScreen(CGame::currLevel));
FrontEndMenuManager.m_bLoadingSavedGame = false; FrontEndMenuManager.m_bWantToLoad = false;
} }
else else
{ {
@ -2168,7 +2168,7 @@ _WinMain(HINSTANCE instance,
} }
FrontEndMenuManager.m_bFirstTime = false; FrontEndMenuManager.m_bFirstTime = false;
FrontEndMenuManager.m_bStartGameLoading = false; FrontEndMenuManager.m_bWantToRestart = false;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,194 +1,194 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "Pager.h" #include "Pager.h"
#include "Timer.h" #include "Timer.h"
#include "Messages.h" #include "Messages.h"
#include "Hud.h" #include "Hud.h"
#include "Camera.h" #include "Camera.h"
void void
CPager::Init() CPager::Init()
{ {
ClearMessages(); ClearMessages();
m_nNumDisplayLetters = 8; m_nNumDisplayLetters = 8;
} }
void void
CPager::Process() CPager::Process()
{ {
if (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) { if (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) {
m_messages[0].m_pText = nil; m_messages[0].m_pText = nil;
uint16 i = 0; uint16 i = 0;
while (i < NUMPAGERMESSAGES-1) { while (i < NUMPAGERMESSAGES-1) {
if (m_messages[i + 1].m_pText == nil) break; if (m_messages[i + 1].m_pText == nil) break;
m_messages[i] = m_messages[i + 1]; m_messages[i] = m_messages[i + 1];
i++; i++;
} }
m_messages[i].m_pText = nil; m_messages[i].m_pText = nil;
if (m_messages[0].m_pText != nil) if (m_messages[0].m_pText != nil)
CMessages::AddToPreviousBriefArray( CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText, m_messages[0].m_pText,
m_messages[0].m_nNumber[0], m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1], m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2], m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3], m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4], m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5], m_messages[0].m_nNumber[5],
0); 0);
} }
Display(); Display();
if (m_messages[0].m_pText != nil) { if (m_messages[0].m_pText != nil) {
if (TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud || CHud::m_BigMessage[0][0] || CHud::m_BigMessage[2][0]) { if (TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud || CHud::m_BigMessage[0][0] || CHud::m_BigMessage[2][0]) {
RestartCurrentMessage(); RestartCurrentMessage();
} else { } else {
if (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) { if (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) {
m_messages[0].m_nCurrentPosition++; m_messages[0].m_nCurrentPosition++;
m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs; m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
} }
} }
} }
} }
void void
CPager::Display() CPager::Display()
{ {
wchar outstr1[256]; wchar outstr1[256];
wchar outstr2[260]; wchar outstr2[260];
wchar *pText = m_messages[0].m_pText; wchar *pText = m_messages[0].m_pText;
uint16 i = 0; uint16 i = 0;
if (pText != nil) { if (pText != nil) {
CMessages::InsertNumberInString( CMessages::InsertNumberInString(
pText, pText,
m_messages[0].m_nNumber[0], m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1], m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2], m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3], m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4], m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5], m_messages[0].m_nNumber[5],
outstr1); outstr1);
for (; i < m_nNumDisplayLetters; i++) { for (; i < m_nNumDisplayLetters; i++) {
int pos = m_messages[0].m_nCurrentPosition + i; int pos = m_messages[0].m_nCurrentPosition + i;
if (pos >= 0) { if (pos >= 0) {
if (!outstr1[pos]) break; if (!outstr1[pos]) break;
outstr2[i] = outstr1[pos]; outstr2[i] = outstr1[pos];
} else { } else {
outstr2[i] = ' '; outstr2[i] = ' ';
} }
} }
} }
outstr2[i] = '\0'; outstr2[i] = '\0';
CHud::SetPagerMessage(outstr2); CHud::SetPagerMessage(outstr2);
} }
void void
CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5) CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5)
{ {
uint16 size = CMessages::GetWideStringLength(str); uint16 size = CMessages::GetWideStringLength(str);
for (int32 i = 0; i < NUMPAGERMESSAGES; i++) { for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
if (m_messages[i].m_pText) { if (m_messages[i].m_pText) {
if (m_messages[i].m_nPriority >= priority) if (m_messages[i].m_nPriority >= priority)
continue; continue;
for (int j = NUMPAGERMESSAGES-1; j > i; j--) for (int j = NUMPAGERMESSAGES-1; j > i; j--)
m_messages[j] = m_messages[j-1]; m_messages[j] = m_messages[j-1];
} }
m_messages[i].m_pText = str; m_messages[i].m_pText = str;
m_messages[i].m_nSpeedMs = speed; m_messages[i].m_nSpeedMs = speed;
m_messages[i].m_nPriority = priority; m_messages[i].m_nPriority = priority;
m_messages[i].field_10 = a5; m_messages[i].field_10 = a5;
m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10); m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed; m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
m_messages[i].m_nStringLength = size; m_messages[i].m_nStringLength = size;
m_messages[i].m_nNumber[0] = -1; m_messages[i].m_nNumber[0] = -1;
m_messages[i].m_nNumber[1] = -1; m_messages[i].m_nNumber[1] = -1;
m_messages[i].m_nNumber[2] = -1; m_messages[i].m_nNumber[2] = -1;
m_messages[i].m_nNumber[3] = -1; m_messages[i].m_nNumber[3] = -1;
m_messages[i].m_nNumber[4] = -1; m_messages[i].m_nNumber[4] = -1;
m_messages[i].m_nNumber[5] = -1; m_messages[i].m_nNumber[5] = -1;
if (i == 0) if (i == 0)
CMessages::AddToPreviousBriefArray( CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText, m_messages[0].m_pText,
m_messages[0].m_nNumber[0], m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1], m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2], m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3], m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4], m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5], m_messages[0].m_nNumber[5],
nil); nil);
return; return;
} }
} }
void void
CPager::AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11) CPager::AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11)
{ {
wchar nstr[520]; wchar nstr[520];
CMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr); CMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr);
uint16 size = CMessages::GetWideStringLength(nstr); uint16 size = CMessages::GetWideStringLength(nstr);
for (int32 i = 0; i < NUMPAGERMESSAGES; i++) { for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
if (m_messages[i].m_pText) { if (m_messages[i].m_pText) {
if (m_messages[i].m_nPriority >= priority) if (m_messages[i].m_nPriority >= priority)
continue; continue;
for (int j = NUMPAGERMESSAGES-1; j > i; j--) for (int j = NUMPAGERMESSAGES-1; j > i; j--)
m_messages[j] = m_messages[j - 1]; m_messages[j] = m_messages[j - 1];
} }
m_messages[i].m_pText = str; m_messages[i].m_pText = str;
m_messages[i].m_nSpeedMs = speed; m_messages[i].m_nSpeedMs = speed;
m_messages[i].m_nPriority = priority; m_messages[i].m_nPriority = priority;
m_messages[i].field_10 = a11; m_messages[i].field_10 = a11;
m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10); m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed; m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
m_messages[i].m_nStringLength = size; m_messages[i].m_nStringLength = size;
m_messages[i].m_nNumber[0] = n1; m_messages[i].m_nNumber[0] = n1;
m_messages[i].m_nNumber[1] = n2; m_messages[i].m_nNumber[1] = n2;
m_messages[i].m_nNumber[2] = n3; m_messages[i].m_nNumber[2] = n3;
m_messages[i].m_nNumber[3] = n4; m_messages[i].m_nNumber[3] = n4;
m_messages[i].m_nNumber[4] = n5; m_messages[i].m_nNumber[4] = n5;
m_messages[i].m_nNumber[5] = n6; m_messages[i].m_nNumber[5] = n6;
if (i == 0) if (i == 0)
CMessages::AddToPreviousBriefArray( CMessages::AddToPreviousBriefArray(
m_messages[0].m_pText, m_messages[0].m_pText,
m_messages[0].m_nNumber[0], m_messages[0].m_nNumber[0],
m_messages[0].m_nNumber[1], m_messages[0].m_nNumber[1],
m_messages[0].m_nNumber[2], m_messages[0].m_nNumber[2],
m_messages[0].m_nNumber[3], m_messages[0].m_nNumber[3],
m_messages[0].m_nNumber[4], m_messages[0].m_nNumber[4],
m_messages[0].m_nNumber[5], m_messages[0].m_nNumber[5],
nil); nil);
return; return;
} }
} }
void void
CPager::ClearMessages() CPager::ClearMessages()
{ {
for (int32 i = 0; i < NUMPAGERMESSAGES; i++) for (int32 i = 0; i < NUMPAGERMESSAGES; i++)
m_messages[i].m_pText = nil; m_messages[i].m_pText = nil;
} }
void void
CPager::RestartCurrentMessage() CPager::RestartCurrentMessage()
{ {
if (m_messages[0].m_pText != nil) { if (m_messages[0].m_pText != nil) {
m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10); m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs; m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
} }
} }
STARTPATCHES STARTPATCHES
InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP); InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP);
InjectHook(0x52B740, &CPager::Process, PATCH_JUMP); InjectHook(0x52B740, &CPager::Process, PATCH_JUMP);
InjectHook(0x52B890, &CPager::Display, PATCH_JUMP); InjectHook(0x52B890, &CPager::Display, PATCH_JUMP);
InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP); InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP);
InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP); InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP);
InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP); InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP);
InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP); InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View file

@ -1,28 +1,28 @@
#pragma once #pragma once
struct PagerMessage { struct PagerMessage {
wchar *m_pText; wchar *m_pText;
uint16 m_nSpeedMs; uint16 m_nSpeedMs;
int16 m_nCurrentPosition; int16 m_nCurrentPosition;
uint16 m_nStringLength; uint16 m_nStringLength;
uint16 m_nPriority; uint16 m_nPriority;
uint32 m_nTimeToChangePosition; uint32 m_nTimeToChangePosition;
int16 field_10; int16 field_10;
int32 m_nNumber[6]; int32 m_nNumber[6];
}; };
#define NUMPAGERMESSAGES 8 #define NUMPAGERMESSAGES 8
class CPager class CPager
{ {
int16 m_nNumDisplayLetters; int16 m_nNumDisplayLetters;
PagerMessage m_messages[NUMPAGERMESSAGES]; PagerMessage m_messages[NUMPAGERMESSAGES];
public: public:
void Init(); void Init();
void Process(); void Process();
void Display(); void Display();
void AddMessage(wchar*, uint16, uint16, uint16); void AddMessage(wchar*, uint16, uint16, uint16);
void AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11); void AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11);
void ClearMessages(); void ClearMessages();
void RestartCurrentMessage(); void RestartCurrentMessage();
}; };

View file

@ -1,324 +1,324 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "FileMgr.h" #include "FileMgr.h"
#include "Frontend.h" #include "Frontend.h"
#include "Messages.h" #include "Messages.h"
#include "Text.h" #include "Text.h"
static wchar WideErrorString[25]; static wchar WideErrorString[25];
CText &TheText = *(CText*)0x941520; CText &TheText = *(CText*)0x941520;
CText::CText(void) CText::CText(void)
{ {
encoding = 'e'; encoding = 'e';
memset(WideErrorString, 0, sizeof(WideErrorString)); memset(WideErrorString, 0, sizeof(WideErrorString));
} }
void void
CText::Load(void) CText::Load(void)
{ {
uint8 *filedata; uint8 *filedata;
char filename[32], type[4]; char filename[32], type[4];
int length; int length;
int offset, sectlen; int offset, sectlen;
Unload(); Unload();
filedata = new uint8[0x40000]; filedata = new uint8[0x40000];
CFileMgr::SetDir("TEXT"); CFileMgr::SetDir("TEXT");
switch(CMenuManager::m_PrefsLanguage){ switch(CMenuManager::m_PrefsLanguage){
case LANGUAGE_AMERICAN: case LANGUAGE_AMERICAN:
sprintf(filename, "AMERICAN.GXT"); sprintf(filename, "AMERICAN.GXT");
break; break;
case LANGUAGE_FRENCH: case LANGUAGE_FRENCH:
sprintf(filename, "FRENCH.GXT"); sprintf(filename, "FRENCH.GXT");
break; break;
case LANGUAGE_GERMAN: case LANGUAGE_GERMAN:
sprintf(filename, "GERMAN.GXT"); sprintf(filename, "GERMAN.GXT");
break; break;
case LANGUAGE_ITALIAN: case LANGUAGE_ITALIAN:
sprintf(filename, "ITALIAN.GXT"); sprintf(filename, "ITALIAN.GXT");
break; break;
case LANGUAGE_SPANISH: case LANGUAGE_SPANISH:
sprintf(filename, "SPANISH.GXT"); sprintf(filename, "SPANISH.GXT");
break; break;
#ifdef MORE_LANGUAGES #ifdef MORE_LANGUAGES
case LANGUAGE_RUSSIAN: case LANGUAGE_RUSSIAN:
sprintf(filename, "RUSSIAN.GXT"); sprintf(filename, "RUSSIAN.GXT");
break; break;
#endif #endif
} }
length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb"); length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
CFileMgr::SetDir(""); CFileMgr::SetDir("");
offset = 0; offset = 0;
while(offset < length){ while(offset < length){
type[0] = filedata[offset++]; type[0] = filedata[offset++];
type[1] = filedata[offset++]; type[1] = filedata[offset++];
type[2] = filedata[offset++]; type[2] = filedata[offset++];
type[3] = filedata[offset++]; type[3] = filedata[offset++];
sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 | sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
(int)filedata[offset+1]<<8 | (int)filedata[offset+0]; (int)filedata[offset+1]<<8 | (int)filedata[offset+0];
offset += 4; offset += 4;
if(sectlen != 0){ if(sectlen != 0){
if(strncmp(type, "TKEY", 4) == 0) if(strncmp(type, "TKEY", 4) == 0)
keyArray.Load(sectlen, filedata, &offset); keyArray.Load(sectlen, filedata, &offset);
else if(strncmp(type, "TDAT", 4) == 0) else if(strncmp(type, "TDAT", 4) == 0)
data.Load(sectlen, filedata, &offset); data.Load(sectlen, filedata, &offset);
else else
offset += sectlen; offset += sectlen;
} }
} }
keyArray.Update(data.chars); keyArray.Update(data.chars);
delete[] filedata; delete[] filedata;
} }
void void
CText::Unload(void) CText::Unload(void)
{ {
CMessages::ClearAllMessagesDisplayedByGame(); CMessages::ClearAllMessagesDisplayedByGame();
data.Unload(); data.Unload();
keyArray.Unload(); keyArray.Unload();
} }
wchar* wchar*
CText::Get(const char *key) CText::Get(const char *key)
{ {
return keyArray.Search(key); return keyArray.Search(key);
} }
wchar UpperCaseTable[128] = { wchar UpperCaseTable[128] = {
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182, 149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182,
183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
249, 250, 251, 252, 253, 254, 255 249, 250, 251, 252, 253, 254, 255
}; };
wchar FrenchUpperCaseTable[128] = { wchar FrenchUpperCaseTable[128] = {
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 65, 65, 65, 65, 132, 133, 69, 69, 69, 69, 73, 73, 150, 65, 65, 65, 65, 132, 133, 69, 69, 69, 69, 73, 73,
73, 73, 79, 79, 79, 79, 85, 85, 85, 85, 173, 173, 175, 73, 73, 79, 79, 79, 79, 85, 85, 85, 85, 173, 173, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255 253, 254, 255
}; };
wchar wchar
CText::GetUpperCase(wchar c) CText::GetUpperCase(wchar c)
{ {
switch (encoding) switch (encoding)
{ {
case 'e': case 'e':
if (c >= 'a' && c <= 'z') if (c >= 'a' && c <= 'z')
return c - 32; return c - 32;
break; break;
case 'f': case 'f':
if (c >= 'a' && c <= 'z') if (c >= 'a' && c <= 'z')
return c - 32; return c - 32;
if (c >= 128 && c <= 255) if (c >= 128 && c <= 255)
return FrenchUpperCaseTable[c-128]; return FrenchUpperCaseTable[c-128];
break; break;
case 'g': case 'g':
case 'i': case 'i':
case 's': case 's':
if (c >= 'a' && c <= 'z') if (c >= 'a' && c <= 'z')
return c - 32; return c - 32;
if (c >= 128 && c <= 255) if (c >= 128 && c <= 255)
return UpperCaseTable[c-128]; return UpperCaseTable[c-128];
break; break;
default: default:
break; break;
} }
return c; return c;
} }
void void
CText::UpperCase(wchar *s) CText::UpperCase(wchar *s)
{ {
while(*s){ while(*s){
*s = GetUpperCase(*s); *s = GetUpperCase(*s);
s++; s++;
} }
} }
void void
CKeyArray::Load(uint32 length, uint8 *data, int *offset) CKeyArray::Load(uint32 length, uint8 *data, int *offset)
{ {
uint32 i; uint32 i;
uint8 *rawbytes; uint8 *rawbytes;
numEntries = length / sizeof(CKeyEntry); numEntries = length / sizeof(CKeyEntry);
entries = new CKeyEntry[numEntries]; entries = new CKeyEntry[numEntries];
rawbytes = (uint8*)entries; rawbytes = (uint8*)entries;
for(i = 0; i < length; i++) for(i = 0; i < length; i++)
rawbytes[i] = data[(*offset)++]; rawbytes[i] = data[(*offset)++];
} }
void void
CKeyArray::Unload(void) CKeyArray::Unload(void)
{ {
delete[] entries; delete[] entries;
entries = nil; entries = nil;
numEntries = 0; numEntries = 0;
} }
void void
CKeyArray::Update(wchar *chars) CKeyArray::Update(wchar *chars)
{ {
int i; int i;
for(i = 0; i < numEntries; i++) for(i = 0; i < numEntries; i++)
entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value); entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value);
} }
CKeyEntry* CKeyEntry*
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high) CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
{ {
int mid; int mid;
int diff; int diff;
if(low > high) if(low > high)
return nil; return nil;
mid = (low + high)/2; mid = (low + high)/2;
diff = strcmp(key, entries[mid].key); diff = strcmp(key, entries[mid].key);
if(diff == 0) if(diff == 0)
return &entries[mid]; return &entries[mid];
if(diff < 0) if(diff < 0)
return BinarySearch(key, entries, low, mid-1); return BinarySearch(key, entries, low, mid-1);
if(diff > 0) if(diff > 0)
return BinarySearch(key, entries, mid+1, high); return BinarySearch(key, entries, mid+1, high);
return nil; return nil;
} }
wchar* wchar*
CKeyArray::Search(const char *key) CKeyArray::Search(const char *key)
{ {
CKeyEntry *found; CKeyEntry *found;
char errstr[25]; char errstr[25];
int i; int i;
found = BinarySearch(key, entries, 0, numEntries-1); found = BinarySearch(key, entries, 0, numEntries-1);
if(found) if(found)
return found->value; return found->value;
sprintf(errstr, "%s missing", key); sprintf(errstr, "%s missing", key);
for(i = 0; i < 25; i++) for(i = 0; i < 25; i++)
WideErrorString[i] = errstr[i]; WideErrorString[i] = errstr[i];
return WideErrorString; return WideErrorString;
} }
void void
CData::Load(uint32 length, uint8 *data, int *offset) CData::Load(uint32 length, uint8 *data, int *offset)
{ {
uint32 i; uint32 i;
uint8 *rawbytes; uint8 *rawbytes;
numChars = length / sizeof(wchar); numChars = length / sizeof(wchar);
chars = new wchar[numChars]; chars = new wchar[numChars];
rawbytes = (uint8*)chars; rawbytes = (uint8*)chars;
for(i = 0; i < length; i++) for(i = 0; i < length; i++)
rawbytes[i] = data[(*offset)++]; rawbytes[i] = data[(*offset)++];
} }
void void
CData::Unload(void) CData::Unload(void)
{ {
delete[] chars; delete[] chars;
chars = nil; chars = nil;
numChars = 0; numChars = 0;
} }
void void
AsciiToUnicode(const char *src, wchar *dst) AsciiToUnicode(const char *src, wchar *dst)
{ {
while((*dst++ = *src++) != '\0'); while((*dst++ = *src++) != '\0');
} }
char* char*
UnicodeToAscii(wchar *src) UnicodeToAscii(wchar *src)
{ {
static char aStr[256]; static char aStr[256];
int len; int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++) for(len = 0; *src != '\0' && len < 256-1; len++, src++)
if(*src < 128) if(*src < 128)
aStr[len] = *src; aStr[len] = *src;
else else
aStr[len] = '#'; aStr[len] = '#';
aStr[len] = '\0'; aStr[len] = '\0';
return aStr; return aStr;
} }
char* char*
UnicodeToAsciiForSaveLoad(wchar *src) UnicodeToAsciiForSaveLoad(wchar *src)
{ {
static char aStr[256]; static char aStr[256];
int len; int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++) for(len = 0; *src != '\0' && len < 256-1; len++, src++)
if(*src < 256) if(*src < 256)
aStr[len] = *src; aStr[len] = *src;
else else
aStr[len] = '#'; aStr[len] = '#';
aStr[len] = '\0'; aStr[len] = '\0';
return aStr; return aStr;
} }
void void
UnicodeStrcpy(wchar *dst, const wchar *src) UnicodeStrcpy(wchar *dst, const wchar *src)
{ {
while((*dst++ = *src++) != '\0'); while((*dst++ = *src++) != '\0');
} }
int int
UnicodeStrlen(const wchar *str) UnicodeStrlen(const wchar *str)
{ {
int len; int len;
for(len = 0; *str != '\0'; len++, str++); for(len = 0; *str != '\0'; len++, str++);
return len; return len;
} }
void void
TextCopy(wchar *dst, const wchar *src) TextCopy(wchar *dst, const wchar *src)
{ {
while((*dst++ = *src++) != '\0'); while((*dst++ = *src++) != '\0');
} }
STARTPATCHES STARTPATCHES
InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP); InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
InjectHook(0x52C580, &CText::Unload, PATCH_JUMP); InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP); InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP); InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP);
InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP); InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP);
InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP); InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP); InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP); InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP); InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP); InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
InjectHook(0x52C120, &CData::Load, PATCH_JUMP); InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
InjectHook(0x52C200, &CData::Unload, PATCH_JUMP); InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View file

@ -182,17 +182,17 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_weaponDoorTimerRight = m_weaponDoorTimerLeft; m_weaponDoorTimerRight = m_weaponDoorTimerLeft;
if(GetModelIndex() == MI_DODO){ if(GetModelIndex() == MI_DODO){
RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0); RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
CMatrix mat1; CMatrix mat1;
mat1.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF])); mat1.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
CMatrix mat2(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF])); CMatrix mat2(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
mat1.GetPosition() += CVector(mat2.GetPosition().x + 0.1f, 0.0f, mat2.GetPosition().z); mat1.GetPosition() += CVector(mat2.GetPosition().x + 0.1f, 0.0f, mat2.GetPosition().z);
mat1.UpdateRW(); mat1.UpdateRW();
}else if(GetModelIndex() == MI_MIAMI_SPARROW || GetModelIndex() == MI_MIAMI_RCRAIDER){ }else if(GetModelIndex() == MI_MIAMI_SPARROW || GetModelIndex() == MI_MIAMI_RCRAIDER){
RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0); RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0); RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);
RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0); RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0); RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
}else if(GetModelIndex() == MI_RHINO){ }else if(GetModelIndex() == MI_RHINO){
bExplosionProof = true; bExplosionProof = true;
bBulletProof = true; bBulletProof = true;

15
src/vehicles/Bike.h Normal file
View file

@ -0,0 +1,15 @@
#pragma once
// some miami bike leftovers
enum eBikeNodes {
BIKE_NODE_NONE,
BIKE_CHASSIS,
BIKE_FORKS_FRONT,
BIKE_FORKS_REAR,
BIKE_WHEEL_FRONT,
BIKE_WHEEL_REAR,
BIKE_MUDGUARD,
BIKE_HANDLEBARS,
BIKE_NUM_NODES
};

View file

@ -94,7 +94,7 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos)
pos = *RwMatrixGetPos(RwFrameGetLTM(m_aBoatNodes[component])); pos = *RwMatrixGetPos(RwFrameGetLTM(m_aBoatNodes[component]));
} }
RxObjSpace3DVertex KeepWaterOutVertices[4]; RwIm3DVertex KeepWaterOutVertices[4];
RwImVertexIndex KeepWaterOutIndices[6]; RwImVertexIndex KeepWaterOutIndices[6];
void void
@ -103,7 +103,7 @@ CBoat::Render()
CMatrix matrix; CMatrix matrix;
if (m_aBoatNodes[1] != nil) { if (m_aBoatNodes[1] != nil) {
matrix.Attach(&m_aBoatNodes[1]->modelling); matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[1]));
CVector pos = matrix.GetPosition(); CVector pos = matrix.GetPosition();
matrix.SetRotateZ(m_fMovingHiRotation); matrix.SetRotateZ(m_fMovingHiRotation);
@ -111,7 +111,7 @@ CBoat::Render()
matrix.UpdateRW(); matrix.UpdateRW();
if (CVehicle::bWheelsOnlyCheat) { if (CVehicle::bWheelsOnlyCheat) {
RpAtomicRenderMacro((RpAtomic*)GetFirstObject(m_aBoatNodes[1])); RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[1]));
} }
} }
m_fMovingHiRotation += 0.05f; m_fMovingHiRotation += 0.05f;
@ -130,47 +130,23 @@ CBoat::Render()
KeepWaterOutIndices[5] = 3; KeepWaterOutIndices[5] = 3;
switch (GetModelIndex()) { switch (GetModelIndex()) {
case MI_SPEEDER: case MI_SPEEDER:
KeepWaterOutVertices[0].objVertex.x = -1.15f; RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.15f, 3.61f, 1.03f);
KeepWaterOutVertices[0].objVertex.y = 3.61f; RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.15f, 3.61f, 1.03f);
KeepWaterOutVertices[0].objVertex.z = 1.03f; RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.15f, 0.06f, 1.03f);
KeepWaterOutVertices[1].objVertex.x = 1.15f; RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.15f, 0.06f, 1.03f);
KeepWaterOutVertices[1].objVertex.y = 3.61f;
KeepWaterOutVertices[1].objVertex.z = 1.03f;
KeepWaterOutVertices[2].objVertex.x = -1.15f;
KeepWaterOutVertices[2].objVertex.y = 0.06f;
KeepWaterOutVertices[2].objVertex.z = 1.03f;
KeepWaterOutVertices[3].objVertex.x = 1.15f;
KeepWaterOutVertices[3].objVertex.y = 0.06f;
KeepWaterOutVertices[3].objVertex.z = 1.03f;
break; break;
case MI_REEFER: case MI_REEFER:
KeepWaterOutVertices[2].objVertex.x = -1.9f; RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.9f, 2.83f, 1.0f);
KeepWaterOutVertices[2].objVertex.y = 2.83f; RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.9f, 2.83f, 1.0f);
KeepWaterOutVertices[2].objVertex.z = 1.0f; RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.66f, -4.48f, 0.83f);
KeepWaterOutVertices[3].objVertex.x = 1.9f; RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.66f, -4.48f, 0.83f);
KeepWaterOutVertices[3].objVertex.y = 2.83f;
KeepWaterOutVertices[3].objVertex.z = 1.0f;
KeepWaterOutVertices[0].objVertex.x = -1.66f;
KeepWaterOutVertices[0].objVertex.y = -4.48f;
KeepWaterOutVertices[0].objVertex.z = 0.83f;
KeepWaterOutVertices[1].objVertex.x = 1.66f;
KeepWaterOutVertices[1].objVertex.y = -4.48f;
KeepWaterOutVertices[1].objVertex.z = 0.83f;
break; break;
case MI_PREDATOR: case MI_PREDATOR:
default: default:
KeepWaterOutVertices[0].objVertex.x = -1.45f; RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.45f, 1.9f, 0.96f);
KeepWaterOutVertices[0].objVertex.y = 1.9f; RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.45f, 1.9f, 0.96f);
KeepWaterOutVertices[0].objVertex.z = 0.96f; RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.45f, -3.75f, 0.96f);
KeepWaterOutVertices[1].objVertex.x = 1.45f; RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.45f, -3.75f, 0.96f);
KeepWaterOutVertices[1].objVertex.y = 1.9f;
KeepWaterOutVertices[1].objVertex.z = 0.96f;
KeepWaterOutVertices[2].objVertex.x = -1.45f;
KeepWaterOutVertices[2].objVertex.y = -3.75f;
KeepWaterOutVertices[2].objVertex.z = 0.96f;
KeepWaterOutVertices[3].objVertex.x = 1.45f;
KeepWaterOutVertices[3].objVertex.y = -3.75f;
KeepWaterOutVertices[3].objVertex.z = 0.96f;
break; break;
} }
KeepWaterOutVertices[0].u = 0.0f; KeepWaterOutVertices[0].u = 0.0f;

View file

@ -238,6 +238,7 @@ public:
bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; } bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; }
bool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; } bool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; }
bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; } bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; }
bool IsBike(void) { return m_vehType == VEHICLE_TYPE_BIKE; }
void FlyingControl(eFlightModel flightModel); void FlyingControl(eFlightModel flightModel);
void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,

View file

@ -1,11 +1,29 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "Automobile.h"
#include "Bike.h"
#include "Camera.h"
#include "Coronas.h"
#include "DMAudio.h" #include "DMAudio.h"
#include "Entity.h"
#include "EventList.h"
#include "Explosion.h" #include "Explosion.h"
#include "General.h"
#include "Fire.h"
#include "Pad.h"
#include "Particle.h"
#include "PointLights.h"
#include "Shadows.h"
#include "Timer.h"
#include "Vehicle.h"
#include "WaterLevel.h"
#include "World.h"
CExplosion(&gaExplosion)[48] = *(CExplosion(*)[48])*(uintptr*)0x64E208; CExplosion(&gaExplosion)[NUM_EXPLOSIONS] = *(CExplosion(*)[NUM_EXPLOSIONS])*(uintptr*)0x64E208;
WRAPPER void CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32) { EAXJMP(0x5591C0); } // these two were not initialised in original code, I'm really not sure what were they meant to be
RwRGBA colMedExpl = { 0, 0, 0, 0 };
RwRGBA colUpdate = { 0, 0, 0, 0 };
int AudioHandle = AEHANDLE_NONE; int AudioHandle = AEHANDLE_NONE;
@ -15,26 +33,25 @@ CExplosion::Initialise()
debug("Initialising CExplosion...\n"); debug("Initialising CExplosion...\n");
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) { for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
gaExplosion[i].m_ExplosionType = EXPLOSION_GRENADE; gaExplosion[i].m_ExplosionType = EXPLOSION_GRENADE;
gaExplosion[i].m_vecPosition.x = 0.0f; gaExplosion[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
gaExplosion[i].m_vecPosition.y = 0.0f;
gaExplosion[i].m_vecPosition.z = 0.0f;
gaExplosion[i].m_fRadius = 1.0f; gaExplosion[i].m_fRadius = 1.0f;
gaExplosion[i].m_fPropagationRate = 0.0f; gaExplosion[i].m_fPropagationRate = 0.0f;
gaExplosion[i].field_38 = 0; gaExplosion[i].m_fZshift = 0.0f;
gaExplosion[i].m_pCreatorEntity = nil; gaExplosion[i].m_pCreatorEntity = nil;
gaExplosion[i].m_pVictimEntity = nil; gaExplosion[i].m_pVictimEntity = nil;
gaExplosion[i].m_fStopTime = 0.0f; gaExplosion[i].m_fStopTime = 0.0f;
gaExplosion[i].m_bActive = false; gaExplosion[i].m_nIteration = 0;
gaExplosion[i].m_nStartTime = 0; gaExplosion[i].m_fStartTime = 0.0f;
gaExplosion[i].field_34 = 0; gaExplosion[i].m_bIsBoat = false;
} }
AudioHandle = DMAudio.CreateEntity(AUDIOTYPE_EXPLOSION, (void*)1); AudioHandle = DMAudio.CreateEntity(AUDIOTYPE_EXPLOSION, (void*)1);
if (AudioHandle >= 0) if (AudioHandle >= 0)
DMAudio.SetEntityStatus(AudioHandle, 1); DMAudio.SetEntityStatus(AudioHandle, true);
debug("CExplosion ready\n"); debug("CExplosion ready\n");
} }
void CExplosion::Shutdown() void
CExplosion::Shutdown()
{ {
debug("Shutting down CExplosion...\n"); debug("Shutting down CExplosion...\n");
if (AudioHandle >= 0) { if (AudioHandle >= 0) {
@ -44,27 +61,16 @@ void CExplosion::Shutdown()
debug("CExplosion shut down\n"); debug("CExplosion shut down\n");
} }
void
CExplosion::RemoveAllExplosionsInArea(CVector pos, float radius)
{
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
if (gaExplosion[i].m_bActive) {
if ((pos - gaExplosion[i].m_vecPosition).MagnitudeSqr() < SQR(radius))
gaExplosion[i].m_bActive = false;
}
}
}
int8 int8
CExplosion::GetExplosionActiveCounter(uint8 id) CExplosion::GetExplosionActiveCounter(uint8 id)
{ {
return gaExplosion[id].m_bActiveCounter; return gaExplosion[id].m_nActiveCounter;
} }
CVector * void
CExplosion::GetExplosionPosition(uint8 id) CExplosion::ResetExplosionActiveCounter(uint8 id)
{ {
return &gaExplosion[id].m_vecPosition; gaExplosion[id].m_nActiveCounter = 0;
} }
uint8 uint8
@ -73,18 +79,363 @@ CExplosion::GetExplosionType(uint8 id)
return gaExplosion[id].m_ExplosionType; return gaExplosion[id].m_ExplosionType;
} }
void CVector *
CExplosion::ResetExplosionActiveCounter(uint8 id) CExplosion::GetExplosionPosition(uint8 id)
{ {
gaExplosion[id].m_bActiveCounter = 0; return &gaExplosion[id].m_vecPosition;
} }
bool bool
CExplosion::TestForExplosionInArea(eExplosionType a1, float x1, float x2, float y1, float y2, float z1, float z2) CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime)
{
CVector pPosn;
CVector posGround;
RwRGBA colorMedium = colMedExpl;
bool bDontExplode = false;
const RwRGBA color = { 160, 160, 160, 255 };
pPosn = pos;
pPosn.z += 5.0f;
#ifdef FIX_BUGS
CShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 30000, 1.0f);
#else
// last two arguments are swapped resulting in no shadow
CShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 1, 30000.0f);
#endif
int n = 0;
while (gaExplosion[n].m_nIteration != 0 && n < ARRAY_SIZE(gaExplosion))
n++;
if (n == ARRAY_SIZE(gaExplosion))
return false;
CExplosion &explosion = gaExplosion[n];
explosion.m_ExplosionType = type;
explosion.m_vecPosition = pos;
explosion.m_fRadius = 1.0f;
explosion.m_fZshift = 0.0f;
explosion.m_pCreatorEntity = culprit;
if (culprit != nil)
culprit->RegisterReference(&explosion.m_pCreatorEntity);
explosion.m_pVictimEntity = explodingEntity;
if (explodingEntity != nil)
explodingEntity->RegisterReference(&explosion.m_pVictimEntity);
explosion.m_nIteration = 1;
explosion.m_nActiveCounter = 1;
explosion.m_bIsBoat = false;
explosion.m_nParticlesExpireTime = lifetime != 0 ? CTimer::GetTimeInMilliseconds() + lifetime : 0;
switch (type)
{
case EXPLOSION_GRENADE:
explosion.m_fRadius = 9.0f;
explosion.m_fPower = 300.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
explosion.m_fPropagationRate = 0.5f;
posGround = pos;
posGround.z = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, nil);
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
if (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f)
CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
break;
case EXPLOSION_MOLOTOV:
{
explosion.m_fRadius = 6.0f;
explosion.m_fPower = 0.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 3000;
explosion.m_fPropagationRate = 0.5f;
posGround = pos;
bool found;
posGround.z = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, &found);
if (found) {
float waterLevel;
if (CWaterLevel::GetWaterLevelNoWaves(posGround.x, posGround.y, posGround.z, &waterLevel)
&& posGround.z < waterLevel
&& waterLevel - 6.0f < posGround.z) // some subway/tunnels check?
bDontExplode = true;
else
gFireManager.StartFire(posGround, 1.8f, false);
}
else
bDontExplode = true;
break;
}
case EXPLOSION_ROCKET:
explosion.m_fRadius = 10.0f;
explosion.m_fPower = 300.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
explosion.m_fPropagationRate = 0.5f;
CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 250);
if (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f)
CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
break;
case EXPLOSION_CAR:
case EXPLOSION_CAR_QUICK:
explosion.m_fRadius = 9.0f;
explosion.m_fPower = 300.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 4250;
explosion.m_fPropagationRate = 0.5f;
explosion.m_fStartTime = CTimer::GetTimeInMilliseconds();
if (explosion.m_pVictimEntity != nil) {
if (explosion.m_pVictimEntity->IsVehicle() && ((CVehicle*)explosion.m_pVictimEntity)->IsBoat())
explosion.m_bIsBoat = true;
CEventList::RegisterEvent(EVENT_EXPLOSION, EVENT_ENTITY_VEHICLE, explosion.m_pVictimEntity, nil, 1000);
} else
CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);
if (explosion.m_pVictimEntity != nil && !explosion.m_bIsBoat) {
int rn = (CGeneral::GetRandomNumber() & 1) + 2;
for (int i = 0; i < rn; i++) {
CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, 3.5f, colMedExpl);
CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
}
CVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;
int32 component = CAR_WING_LR;
// miami leftover
if (veh->IsBike())
component = BIKE_FORKS_REAR;
if (veh->IsComponentPresent(component)) {
CVector componentPos;
veh->GetComponentWorldPosition(component, componentPos);
rn = (CGeneral::GetRandomNumber() & 1) + 1;
for (int i = 0; i < rn; i++)
CParticle::AddJetExplosion(componentPos, 1.4f, 0.0f);
}
}
break;
case EXPLOSION_HELI:
explosion.m_fRadius = 6.0f;
explosion.m_fPower = 300.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
explosion.m_fPropagationRate = 0.5f;
explosion.m_fStartTime = CTimer::GetTimeInMilliseconds();
for (int i = 0; i < 10; i++) {
CVector randpos;
uint8 x, y, z;
x = CGeneral::GetRandomNumber();
y = CGeneral::GetRandomNumber();
z = CGeneral::GetRandomNumber();
randpos = pos + CVector(x - 128, y - 128, z - 128) / 20.0f;
CParticle::AddParticle(PARTICLE_EXPLOSION_MFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 2.5f, color);
x = CGeneral::GetRandomNumber();
y = CGeneral::GetRandomNumber();
z = CGeneral::GetRandomNumber();
randpos = pos + CVector(x - 128, y - 128, z - 128) / 20.0f;
CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 5.0f, color);
x = CGeneral::GetRandomNumber();
y = CGeneral::GetRandomNumber();
z = CGeneral::GetRandomNumber();
randpos = pos + CVector(x - 128, y - 128, z - 128) / 20.0f;
CParticle::AddJetExplosion(randpos, 1.4f, 3.0f);
}
CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);
break;
case EXPLOSION_MINE:
explosion.m_fRadius = 10.0f;
explosion.m_fPower = 150.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
explosion.m_fPropagationRate = 0.5f;
posGround = pos;
//posGround.z =
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
break;
case EXPLOSION_BARREL:
explosion.m_fRadius = 7.0f;
explosion.m_fPower = 150.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
explosion.m_fPropagationRate = 0.5f;
for (int i = 0; i < 6; i++) {
CVector randpos;
uint8 x, y, z;
x = CGeneral::GetRandomNumber();
y = CGeneral::GetRandomNumber();
z = CGeneral::GetRandomNumber();
randpos = CVector(x - 128, y - 128, z - 128);
randpos.x /= 50.0f;
randpos.y /= 50.0f;
randpos.z /= 25.0f;
randpos += pos;
CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colorMedium);
}
posGround = pos;
//posGround.z =
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
break;
case EXPLOSION_TANK_GRENADE:
explosion.m_fRadius = 10.0f;
explosion.m_fPower = 150.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
explosion.m_fPropagationRate = 0.5f;
posGround = pos;
//posGround.z =
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
break;
case EXPLOSION_HELI_BOMB:
explosion.m_fRadius = 8.0f;
explosion.m_fPower = 50.0f;
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
explosion.m_fPropagationRate = 0.5f;
posGround = pos;
//posGround.z =
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
break;
}
if (bDontExplode) {
explosion.m_nIteration = 0;
return false;
}
if (explosion.m_fPower != 0.0f && explosion.m_nParticlesExpireTime == 0)
CWorld::TriggerExplosion(pos, explosion.m_fRadius, explosion.m_fPower, culprit, (type == EXPLOSION_ROCKET || type == EXPLOSION_CAR_QUICK || type == EXPLOSION_MINE || type == EXPLOSION_BARREL || type == EXPLOSION_TANK_GRENADE || type == EXPLOSION_HELI_BOMB));
TheCamera.CamShake(0.6f, pos.x, pos.y, pos.z);
CPad::GetPad(0)->StartShake_Distance(300, 128, pos.x, pos.y, pos.z);
return true;
}
void
CExplosion::Update()
{
RwRGBA color = colUpdate;
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
CExplosion &explosion = gaExplosion[i];
if (explosion.m_nIteration == 0) continue;
if (explosion.m_nParticlesExpireTime != 0) {
if (CTimer::GetTimeInMilliseconds() > explosion.m_nParticlesExpireTime) {
explosion.m_nParticlesExpireTime = 0;
if (explosion.m_fPower != 0.0f)
CWorld::TriggerExplosion(explosion.m_vecPosition, explosion.m_fRadius, explosion.m_fPower, explosion.m_pCreatorEntity, (explosion.m_ExplosionType == EXPLOSION_ROCKET || explosion.m_ExplosionType == EXPLOSION_CAR_QUICK || explosion.m_ExplosionType == EXPLOSION_MINE || explosion.m_ExplosionType == EXPLOSION_BARREL || explosion.m_ExplosionType == EXPLOSION_TANK_GRENADE || explosion.m_ExplosionType == EXPLOSION_HELI_BOMB));
}
} else {
explosion.m_fRadius += explosion.m_fPropagationRate * CTimer::GetTimeStep();
int32 someTime = explosion.m_fStopTime - CTimer::GetTimeInMilliseconds();
switch (explosion.m_ExplosionType)
{
case EXPLOSION_GRENADE:
case EXPLOSION_ROCKET:
case EXPLOSION_HELI:
case EXPLOSION_MINE:
case EXPLOSION_BARREL:
if (CTimer::GetFrameCounter() & 1) {
CPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 20.0f, 1.0f, 1.0f, 0.5f, CPointLights::FOG_NONE, true);
CCoronas::RegisterCorona((uintptr)&explosion, 255, 255, 200, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
} else
CCoronas::RegisterCorona((uintptr)&explosion, 128, 128, 100, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
CCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 30, 25, 255, explosion.m_vecPosition, explosion.m_fRadius, 120.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
break;
case EXPLOSION_MOLOTOV:
CWorld::SetPedsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);
CWorld::SetCarsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);
if (explosion.m_nIteration < 10) {
if (explosion.m_nIteration == 1) {
CVector point1 = explosion.m_vecPosition;
point1.z += 5.0f;
CColPoint colPoint;
CEntity *pEntity;
CWorld::ProcessVerticalLine(point1, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil);
explosion.m_fZshift = colPoint.point.z;
}
float ff = ((float)explosion.m_nIteration * 0.55f);
for (int i = 0; i < 5 * ff; i++) {
float angle = CGeneral::GetRandomNumber() / 256.0f * 6.28f;
CVector pos = explosion.m_vecPosition;
pos.x += ff * Sin(angle);
pos.y += ff * Cos(angle);
pos.z += 5.0f; // what is the point of this?
pos.z = explosion.m_fZshift + 0.5f;
CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));
}
}
break;
case EXPLOSION_CAR:
case EXPLOSION_CAR_QUICK:
if (someTime >= 3500) {
if (explosion.m_pVictimEntity != nil && !explosion.m_bIsBoat) {
if ((CGeneral::GetRandomNumber() & 0xF) == 0) {
CVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;
uint8 component = CAR_WING_LR;
// miami leftover
if (veh->IsBike())
component = BIKE_FORKS_REAR;
if (veh->IsComponentPresent(component)) {
CVector componentPos;
veh->GetComponentWorldPosition(component, componentPos);
CParticle::AddJetExplosion(componentPos, 1.5f, 0.0f);
}
}
if (CTimer::GetTimeInMilliseconds() > explosion.m_fStartTime) {
explosion.m_fStartTime = CTimer::GetTimeInMilliseconds() + 125 + (CGeneral::GetRandomNumber() & 0x7F);
CVector pos = explosion.m_pVictimEntity->GetPosition();
for (int i = 0; i < (CGeneral::GetRandomNumber() & 1) + 1; i++) {
CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 3.5f, color);
CParticle::AddParticle(PARTICLE_EXPLOSION_LARGE, pos, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
}
}
}
if (CTimer::GetFrameCounter() & 1) {
CPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 15.0f, 1.0f, 0.0f, 0.0f, CPointLights::FOG_NONE, true);
CCoronas::RegisterCorona((uintptr)&explosion, 200, 100, 0, 255, explosion.m_vecPosition, 6.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
} else
CCoronas::RegisterCorona((uintptr)&explosion, 128, 0, 0, 255, explosion.m_vecPosition, 8.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
CCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 15, 0, 255, explosion.m_vecPosition, explosion.m_fRadius, 80.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
} else if (explosion.m_nIteration & 1) {
if (explosion.m_pVictimEntity != nil)
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, CGeneral::GetRandomNumberInRange(0.5f, 0.8f), color);
CVector pos = explosion.m_vecPosition;
pos.z += 1.0f;
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, pos, CVector(0.0f, 0.0f, 0.11f), nil, CGeneral::GetRandomNumberInRange(0.5f, 2.0f), color);
}
break;
case EXPLOSION_TANK_GRENADE:
case EXPLOSION_HELI_BOMB:
if (explosion.m_nIteration < 5) {
float ff = ((float)explosion.m_nIteration * 0.65f);
for (int i = 0; i < 10 * ff; i++) {
uint8 x = CGeneral::GetRandomNumber(), y = CGeneral::GetRandomNumber(), z = CGeneral::GetRandomNumber();
CVector pos(x - 128, y - 128, (z % 128) + 1);
pos.Normalise();
pos *= ff / 5.0f;
pos += explosion.m_vecPosition;
pos.z += 0.5f;
CParticle::AddParticle(PARTICLE_EXPLOSION_LARGE, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));
}
}
break;
}
if (someTime > 0)
explosion.m_nIteration++;
else
explosion.m_nIteration = 0;
}
}
}
bool
CExplosion::TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2)
{ {
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) { for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
if (gaExplosion[i].m_bActive) { if (gaExplosion[i].m_nIteration != 0) {
if (a1 == gaExplosion[i].m_ExplosionType) { if (type == gaExplosion[i].m_ExplosionType) {
if (gaExplosion[i].m_vecPosition.x >= x1 && gaExplosion[i].m_vecPosition.x <= x2) { if (gaExplosion[i].m_vecPosition.x >= x1 && gaExplosion[i].m_vecPosition.x <= x2) {
if (gaExplosion[i].m_vecPosition.y >= y1 && gaExplosion[i].m_vecPosition.y <= y2) { if (gaExplosion[i].m_vecPosition.y >= y1 && gaExplosion[i].m_vecPosition.y <= y2) {
if (gaExplosion[i].m_vecPosition.z >= z1 && gaExplosion[i].m_vecPosition.z <= z2) if (gaExplosion[i].m_vecPosition.z >= z1 && gaExplosion[i].m_vecPosition.z <= z2)
@ -97,13 +448,26 @@ CExplosion::TestForExplosionInArea(eExplosionType a1, float x1, float x2, float
return false; return false;
} }
void
CExplosion::RemoveAllExplosionsInArea(CVector pos, float radius)
{
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
if (gaExplosion[i].m_nIteration != 0) {
if ((pos - gaExplosion[i].m_vecPosition).MagnitudeSqr() < SQR(radius))
gaExplosion[i].m_nIteration = 0;
}
}
}
STARTPATCHES STARTPATCHES
InjectHook(0x559030, &CExplosion::Initialise, PATCH_JUMP); InjectHook(0x559030, &CExplosion::Initialise, PATCH_JUMP);
InjectHook(0x559100, &CExplosion::Shutdown, PATCH_JUMP); InjectHook(0x559100, &CExplosion::Shutdown, PATCH_JUMP);
InjectHook(0x55AD40, &CExplosion::RemoveAllExplosionsInArea, PATCH_JUMP);
InjectHook(0x559140, &CExplosion::GetExplosionActiveCounter, PATCH_JUMP); InjectHook(0x559140, &CExplosion::GetExplosionActiveCounter, PATCH_JUMP);
InjectHook(0x5591A0, &CExplosion::GetExplosionPosition, PATCH_JUMP);
InjectHook(0x559180, &CExplosion::GetExplosionType, PATCH_JUMP);
InjectHook(0x559160, &CExplosion::ResetExplosionActiveCounter, PATCH_JUMP); InjectHook(0x559160, &CExplosion::ResetExplosionActiveCounter, PATCH_JUMP);
InjectHook(0x559180, &CExplosion::GetExplosionType, PATCH_JUMP);
InjectHook(0x5591A0, &CExplosion::GetExplosionPosition, PATCH_JUMP);
InjectHook(0x5591C0, &CExplosion::AddExplosion, PATCH_JUMP);
InjectHook(0x55A0C0, &CExplosion::Update, PATCH_JUMP);
InjectHook(0x55AC80, &CExplosion::TestForExplosionInArea, PATCH_JUMP); InjectHook(0x55AC80, &CExplosion::TestForExplosionInArea, PATCH_JUMP);
InjectHook(0x55AD40, &CExplosion::RemoveAllExplosionsInArea, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View file

@ -26,25 +26,24 @@ class CExplosion
CEntity *m_pCreatorEntity; CEntity *m_pCreatorEntity;
CEntity *m_pVictimEntity; CEntity *m_pVictimEntity;
float m_fStopTime; float m_fStopTime;
bool m_bActive; uint8 m_nIteration;
int8 m_bActiveCounter; uint8 m_nActiveCounter;
int32 m_nStartTime; float m_fStartTime;
uint32 m_nParticlesExpireTime; uint32 m_nParticlesExpireTime;
float m_fPower; float m_fPower;
int32 field_34; bool m_bIsBoat;
int32 field_38; float m_fZshift;
public: public:
static void Initialise(); static void Initialise();
static void Shutdown(); static void Shutdown();
static void AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type,
const CVector &pos, uint32);
static int8 GetExplosionActiveCounter(uint8 id); static int8 GetExplosionActiveCounter(uint8 id);
static CVector *GetExplosionPosition(uint8 id);
static uint8 GetExplosionType(uint8 id);
static void ResetExplosionActiveCounter(uint8 id); static void ResetExplosionActiveCounter(uint8 id);
static void RemoveAllExplosionsInArea(CVector, float); static uint8 GetExplosionType(uint8 id);
static bool TestForExplosionInArea(eExplosionType, float, float, float, float, float, float); static CVector *GetExplosionPosition(uint8 id);
static bool AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime);
static void Update();
static bool TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2);
static void RemoveAllExplosionsInArea(CVector pos, float radius);
}; };
extern CExplosion (&gaExplosion)[48]; extern CExplosion (&gaExplosion)[NUM_EXPLOSIONS];

View file

@ -1,32 +1,32 @@
#pragma once #pragma once
class CEntity; class CEntity;
class CObject; class CObject;
class CProjectile; class CProjectile;
enum eWeaponType; enum eWeaponType;
class CProjectileInfo class CProjectileInfo
{ {
public: public:
eWeaponType m_eWeaponType; eWeaponType m_eWeaponType;
CEntity* m_pSource; CEntity* m_pSource;
uint32 m_nExplosionTime; uint32 m_nExplosionTime;
bool m_bInUse; bool m_bInUse;
CVector m_vecPos; CVector m_vecPos;
public: public:
static CProjectileInfo* GetProjectileInfo(int32 id); static CProjectileInfo* GetProjectileInfo(int32 id);
static CProjectile* (&ms_apProjectile)[NUM_PROJECTILES]; static CProjectile* (&ms_apProjectile)[NUM_PROJECTILES];
static void Initialise(); static void Initialise();
static void Shutdown(); static void Shutdown();
static bool AddProjectile(CEntity *ped, eWeaponType weapon, CVector pos, float speed); static bool AddProjectile(CEntity *ped, eWeaponType weapon, CVector pos, float speed);
static void RemoveProjectile(CProjectileInfo *info, CProjectile *projectile); static void RemoveProjectile(CProjectileInfo *info, CProjectile *projectile);
static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos); static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);
static bool RemoveIfThisIsAProjectile(CObject *pObject); static bool RemoveIfThisIsAProjectile(CObject *pObject);
static void RemoveAllProjectiles(); static void RemoveAllProjectiles();
static void Update(); static void Update();
static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove); static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
}; };
extern CProjectileInfo (&gaProjectileInfo)[NUM_PROJECTILES]; extern CProjectileInfo (&gaProjectileInfo)[NUM_PROJECTILES];