summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/animation/CutsceneMgr.cpp (renamed from src/core/CutsceneMgr.cpp)7
-rw-r--r--src/animation/CutsceneMgr.h (renamed from src/core/CutsceneMgr.h)2
-rw-r--r--src/audio/AudioCollision.cpp806
-rw-r--r--src/audio/AudioCollision.h70
-rw-r--r--src/audio/AudioManager.h2
-rw-r--r--src/audio/PoliceRadio.cpp1578
-rw-r--r--src/audio/PoliceRadio.h90
-rw-r--r--src/control/CarCtrl.cpp2
-rw-r--r--src/control/CarGen.cpp2
-rw-r--r--src/control/GameLogic.cpp572
-rw-r--r--src/control/GameLogic.h24
-rw-r--r--src/control/Gangs.cpp18
-rw-r--r--src/control/OnscreenTimer.h96
-rw-r--r--src/control/Pickups.cpp2098
-rw-r--r--src/control/Pickups.h248
-rw-r--r--src/control/PowerPoints.cpp42
-rw-r--r--src/control/PowerPoints.h50
-rw-r--r--src/control/Replay.cpp6
-rw-r--r--src/control/Restart.cpp434
-rw-r--r--src/control/Script.cpp22
-rw-r--r--src/control/Script.h29
-rw-r--r--src/core/Camera.cpp6
-rw-r--r--src/core/FileLoader.cpp2
-rw-r--r--src/core/Frontend.cpp10
-rw-r--r--src/core/Frontend.h12
-rw-r--r--src/core/Game.cpp20
-rw-r--r--src/core/Game.h1
-rw-r--r--src/core/Pad.cpp394
-rw-r--r--src/core/Pad.h17
-rw-r--r--src/core/PlayerInfo.cpp900
-rw-r--r--src/core/Radar.cpp3006
-rw-r--r--src/core/Radar.h13
-rw-r--r--src/core/RwHelper.cpp7
-rw-r--r--src/core/RwTexRead.cpp203
-rw-r--r--src/core/Stats.cpp237
-rw-r--r--src/core/Stats.h27
-rw-r--r--src/core/World.cpp2
-rw-r--r--src/core/World.h2
-rw-r--r--src/core/common.h4
-rw-r--r--src/core/config.h6
-rw-r--r--src/core/main.cpp1928
-rw-r--r--src/core/obrstr.cpp236
-rw-r--r--src/core/obrstr.h16
-rw-r--r--src/core/timebars.cpp240
-rw-r--r--src/core/timebars.h10
-rw-r--r--src/entities/Entity.cpp14
-rw-r--r--src/entities/Solid.h22
-rw-r--r--src/modelinfo/MloModelInfo.h26
-rw-r--r--src/modelinfo/PedModelInfo.cpp2
-rw-r--r--src/modelinfo/VehicleModelInfo.cpp14
-rw-r--r--src/modelinfo/XtraCompsModelInfo.h22
-rw-r--r--src/objects/CutsceneHead.cpp2
-rw-r--r--src/objects/ParticleObject.cpp2
-rw-r--r--src/peds/Ped.cpp4
-rw-r--r--src/peds/PedIK.cpp4
-rw-r--r--src/peds/PedIK.h4
-rw-r--r--src/peds/PedType.h1
-rw-r--r--src/peds/PlayerPed.cpp3070
-rw-r--r--src/peds/Population.cpp3
-rw-r--r--src/render/Clouds.cpp14
-rw-r--r--src/render/Coronas.cpp4
-rw-r--r--src/render/Fluff.cpp4
-rw-r--r--src/render/Font.cpp1272
-rw-r--r--src/render/Hud.cpp4
-rw-r--r--src/render/MBlur.cpp3
-rw-r--r--src/render/PlayerSkin.cpp (renamed from src/core/PlayerSkin.cpp)341
-rw-r--r--src/render/PlayerSkin.h (renamed from src/core/PlayerSkin.h)6
-rw-r--r--src/render/Skidmarks.cpp247
-rw-r--r--src/render/Skidmarks.h26
-rw-r--r--src/render/SpecialFX.cpp465
-rw-r--r--src/render/SpecialFX.h70
-rw-r--r--src/render/Sprite.cpp12
-rw-r--r--src/render/Sprite2d.cpp30
-rw-r--r--src/render/TexList.cpp41
-rw-r--r--src/render/TexList.h14
-rw-r--r--src/render/VisibilityPlugins.cpp2
-rw-r--r--src/render/WeaponEffects.cpp2
-rw-r--r--src/render/Weather.cpp8
-rw-r--r--src/save/Date.h34
-rw-r--r--src/save/GenericGameStorage.cpp7
-rw-r--r--src/save/GenericGameStorage.h78
-rw-r--r--src/skel/win/win.cpp14
-rw-r--r--src/text/Messages.cpp1670
-rw-r--r--src/text/Pager.cpp386
-rw-r--r--src/text/Pager.h54
-rw-r--r--src/text/Text.cpp648
-rw-r--r--src/vehicles/Automobile.cpp10
-rw-r--r--src/vehicles/Bike.h15
-rw-r--r--src/vehicles/Boat.cpp54
-rw-r--r--src/vehicles/Vehicle.h1
-rw-r--r--src/weapons/Explosion.cpp428
-rw-r--r--src/weapons/Explosion.h25
-rw-r--r--src/weapons/ProjectileInfo.h62
93 files changed, 12432 insertions, 10306 deletions
diff --git a/src/core/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp
index 283f34b8..0e35599b 100644
--- a/src/core/CutsceneMgr.cpp
+++ b/src/animation/CutsceneMgr.cpp
@@ -134,8 +134,8 @@ uint32 &CCutsceneMgr::ms_cutsceneLoadStatus = *(uint32*)0x95CB40;
RpAtomic *
CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data)
{
- float radius = RpAtomicGetBoundingSphereMacro(atomic)->radius;
- RwV3d center = RpAtomicGetBoundingSphereMacro(atomic)->center;
+ float radius = RpAtomicGetBoundingSphere(atomic)->radius;
+ RwV3d center = RpAtomicGetBoundingSphere(atomic)->center;
for (RwFrame *frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame))
RwV3dTransformPoints(&center, &center, 1, RwFrameGetMatrix(frame));
@@ -326,7 +326,7 @@ CCutsceneMgr::CreateCutsceneObject(int modelId)
pModelInfo->SetColModel(pColModel);
clump = (RpClump*)pModelInfo->GetRwObject();
- assert(RwObjectGetType(clump) == rpCLUMP);
+ assert(RwObjectGetType((RwObject*)clump) == rpCLUMP);
RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius);
pColModel->boundingSphere.radius = radius;
@@ -352,6 +352,7 @@ CCutsceneMgr::DeleteCutsceneData(void)
CWorld::Remove(ms_pCutsceneObjects[ms_numCutsceneObjs]);
ms_pCutsceneObjects[ms_numCutsceneObjs]->DeleteRwObject();
delete ms_pCutsceneObjects[ms_numCutsceneObjs];
+ ms_pCutsceneObjects[ms_numCutsceneObjs] = nil;
}
ms_numCutsceneObjs = 0;
diff --git a/src/core/CutsceneMgr.h b/src/animation/CutsceneMgr.h
index 7b809964..3c915eea 100644
--- a/src/core/CutsceneMgr.h
+++ b/src/animation/CutsceneMgr.h
@@ -26,7 +26,7 @@ public:
static CDirectory *&ms_pCutsceneDir;
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 IsCutsceneProcessing(void) { return ms_cutsceneProcessing; }
static bool UseLodMultiplier(void) { return ms_useLodMultiplier; }
diff --git a/src/audio/AudioCollision.cpp b/src/audio/AudioCollision.cpp
index 608b1a8d..4039bd75 100644
--- a/src/audio/AudioCollision.cpp
+++ b/src/audio/AudioCollision.cpp
@@ -1,403 +1,403 @@
-#include "common.h"
-#include "patcher.h"
-#include "DMAudio.h"
-#include "Entity.h"
-#include "AudioCollision.h"
-#include "AudioManager.h"
-#include "AudioSamples.h"
-#include "SurfaceTable.h"
-#include "sampman.h"
-
-const int CollisionSoundIntensity = 60;
-
-void
-cAudioCollisionManager::AddCollisionToRequestedQueue()
-{
- int32 collisionsIndex;
- int32 i;
-
-
- if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)
- collisionsIndex = m_bCollisionsInQueue++;
- else {
- collisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1];
- if (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return;
- }
-
- m_asCollisions1[collisionsIndex] = m_sQueue;
-
- i = 0;
- if(collisionsIndex) {
- while(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) {
- if(++i >= collisionsIndex) {
- m_bIndicesTable[i] = collisionsIndex;
- return;
- }
- }
- memmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i);
- }
- m_bIndicesTable[i] = collisionsIndex;
-}
-
-float
-cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const
-{
- return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
-}
-
-float
-cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const
-{
- float result;
-
- switch(a) {
- case SURFACE_DEFAULT:
- case SURFACE_TARMAC:
- case SURFACE_PAVEMENT:
- case SURFACE_STONE:
- case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;
- case SURFACE_GRASS:
- 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_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
- case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
- case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
- case SURFACE_SCAFFOLD:
- 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_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
- case SURFACE_METAL_POLE:
- 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_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_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
- case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;
- case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
- 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_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_TIRE:
- 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_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;
- case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;
- case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;
- default: result = 0.f; break;
- }
-
- return result;
-}
-
-float
-cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const
-{
- float e;
- e = a;
- if(a <= b) return 0.0f;
- if(c <= a) e = c;
- return (e - b) / d;
-}
-
-uint32
-cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision)
-{
- uint8 surface1 = audioCollision->m_bSurface1;
- uint8 surface2 = audioCollision->m_bSurface2;
- int32 vol;
- float ratio;
-
- if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
- surface2 == SURFACE_HEDGE) {
- ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
- m_sQueueSample.m_nSampleIndex = SFX_RAIN;
- m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
- vol = 50.f * ratio;
- } else {
- if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) {
- ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
- m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
- m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
- vol = 30.f * ratio;
-
- } else {
- if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK ||
- surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) {
- ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
- m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
- m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
- vol = 50.f * ratio;
- } else {
- if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { return 0; }
- ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
- m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
- m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
- vol = 40.f * ratio;
- }
- }
- }
- if(audioCollision->m_nBaseVolume < 2) vol = audioCollision->m_nBaseVolume * vol / 2;
- return vol;
-}
-
-void
-cAudioManager::SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter)
-{
- if(col->m_fIntensity2 > 0.0016f) {
- uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
- if(emittingVol) {
- m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
- m_sQueueSample.m_bVolume =
- ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
- if(m_sQueueSample.m_bVolume) {
- m_sQueueSample.m_counter = counter;
- m_sQueueSample.m_vecPos = col->m_vecPosition;
- m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_nReleasingVolumeModificator = 7;
- m_sQueueSample.m_nLoopCount = 0;
- m_sQueueSample.m_bEmittingVolume = emittingVol;
- m_sQueueSample.m_nLoopStart =
- SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
- m_sQueueSample.m_nLoopEnd =
- SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
- m_sQueueSample.m_fSpeedMultiplier = 4.0f;
- m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
- m_sQueueSample.m_bReleasingSoundFlag = 0;
- m_sQueueSample.m_nReleasingVolumeDivider = 5;
- m_sQueueSample.m_bReverbFlag = true;
- m_sQueueSample.m_bRequireReflection = false;
- AddSampleToRequestedQueue();
- }
- }
- }
-}
-
-void
-cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col)
-{
- static const int32 gOneShotCol[] = {
- 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_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_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_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_GRASS_1, SFX_COL_VEG_1, SFX_COL_TARMAC_1,
- SFX_COL_CONTAINER_1, SFX_COL_NEWS_VENDOR_1, SFX_TYRE_BUMP,
- SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, SFX_COL_GATE};
-
- int16 s1;
- int16 s2;
-
- int32 emittingVol;
- float ratio;
-
- static uint16 counter = 28;
-
- for(int32 i = 0; i < 2; i++) {
- if(i) {
- s1 = col->m_bSurface2;
- s2 = col->m_bSurface1;
- } else {
- s1 = col->m_bSurface1;
- s2 = col->m_bSurface2;
- }
- ratio = GetCollisionOneShotRatio(s1, col->m_fIntensity1);
- if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio;
- if(s1 == SURFACE_METAL6 && ratio < 0.6f) {
- s1 = SURFACE_BILLBOARD;
- ratio = min(1.f, 2.f * ratio);
- }
- emittingVol = 40.f * ratio;
- if(emittingVol) {
- m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
- m_sQueueSample.m_bVolume =
- ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
- if(m_sQueueSample.m_bVolume) {
- m_sQueueSample.m_nSampleIndex = gOneShotCol[s1];
- switch(m_sQueueSample.m_nSampleIndex) {
- case SFX_COL_TARMAC_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5;
- break;
- case SFX_COL_CAR_PANEL_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6;
- break;
- case SFX_COL_LAMP_POST_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2;
- break;
- case SFX_COL_METAL_CHAIN_FENCE_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4;
- break;
- case SFX_COL_PED_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 5;
- break;
- case SFX_COL_WOOD_CRATES_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4;
- break;
- case SFX_COL_WOOD_BENCH_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4;
- break;
- case SFX_COL_VEG_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5;
- break;
- case SFX_COL_NEWS_VENDOR_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3;
- break;
- case SFX_COL_CAR_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5;
- break;
- case SFX_COL_CARDBOARD_1:
- m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2;
- break;
- default: break;
- }
- switch(s1) {
- case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break;
- case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break;
- case SURFACE_PUDDLE:
- m_sQueueSample.m_nFrequency =
- 2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
- break;
- case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break;
- case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break;
- default:
- m_sQueueSample.m_nFrequency =
- SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
- break;
- }
- m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
- m_sQueueSample.m_counter = counter++;
- if(counter >= 255) counter = 28;
- m_sQueueSample.m_vecPos = col->m_vecPosition;
- m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_nReleasingVolumeModificator = 11;
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_bEmittingVolume = emittingVol;
- m_sQueueSample.m_nLoopStart = 0;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_fSpeedMultiplier = 4.0f;
- m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
- m_sQueueSample.m_bReleasingSoundFlag = 1;
- m_sQueueSample.m_bReverbFlag = true;
- m_sQueueSample.m_bRequireReflection = false;
- AddSampleToRequestedQueue();
- }
- }
- }
-}
-
-void
-cAudioManager::ServiceCollisions()
-{
- int i, j;
- bool someArr1[NUMAUDIOCOLLISIONS];
- bool someArr2[NUMAUDIOCOLLISIONS];
-
- m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
-
- for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
- someArr1[i] = someArr2[i] = false;
-
- for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
- for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
- int index = m_sCollisionManager.m_bIndicesTable[i];
- if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
- && (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
- && (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)
- ) {
- someArr1[index] = true;
- someArr2[j] = true;
- m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
- SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
- break;
- }
- }
- }
-
- for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
- if (!someArr2[i]) {
- m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
- m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
- m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = 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_fIntensity1 = 0.0f;
- m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
- m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
- }
- }
-
- for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
- int index = m_sCollisionManager.m_bIndicesTable[i];
- if (!someArr1[index]) {
- for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
- if (someArr2[j]) {
- m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
- m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
- 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_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
- break;
- }
- }
- SetUpOneShotCollisionSound(&m_sCollisionManager.m_asCollisions1[index]);
- SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
- }
- }
-
- for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
- m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
- m_sCollisionManager.m_bCollisionsInQueue = 0;
-}
-
-void
-cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
- float velocity)
-{
- float distSquared;
- CVector v1;
- CVector v2;
-
- if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bUserPause ||
- (velocity < 0.0016f && collisionPower < 0.01f))
- return;
-
- if(entity1->IsBuilding()) {
- v1 = v2 = entity2->GetPosition();
- } else if(entity2->IsBuilding()) {
- v1 = v2 = entity1->GetPosition();
- } else {
- v1 = entity1->GetPosition();
- v2 = entity2->GetPosition();
- }
- CVector pos = (v1 + v2) * 0.5f;
- distSquared = GetDistanceSquared(&pos);
- if(distSquared < SQR(CollisionSoundIntensity)) {
- m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
- m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
- m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
- m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
- m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
- m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
- m_sCollisionManager.m_sQueue.m_vecPosition = pos;
- m_sCollisionManager.m_sQueue.m_fDistance = distSquared;
- m_sCollisionManager.AddCollisionToRequestedQueue();
- }
-}
-
-STARTPATCHES
-InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP);
-InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP);
-InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP);
-InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP);
-InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP);
-InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP);
-InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP);
-InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP);
-ENDPATCHES
+#include "common.h"
+#include "patcher.h"
+#include "DMAudio.h"
+#include "Entity.h"
+#include "AudioCollision.h"
+#include "AudioManager.h"
+#include "AudioSamples.h"
+#include "SurfaceTable.h"
+#include "sampman.h"
+
+const int CollisionSoundIntensity = 60;
+
+void
+cAudioCollisionManager::AddCollisionToRequestedQueue()
+{
+ int32 collisionsIndex;
+ int32 i;
+
+
+ if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)
+ collisionsIndex = m_bCollisionsInQueue++;
+ else {
+ collisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1];
+ if (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return;
+ }
+
+ m_asCollisions1[collisionsIndex] = m_sQueue;
+
+ i = 0;
+ if(collisionsIndex) {
+ while(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) {
+ if(++i >= collisionsIndex) {
+ m_bIndicesTable[i] = collisionsIndex;
+ return;
+ }
+ }
+ memmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i);
+ }
+ m_bIndicesTable[i] = collisionsIndex;
+}
+
+float
+cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const
+{
+ return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
+}
+
+float
+cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const
+{
+ float result;
+
+ switch(a) {
+ case SURFACE_DEFAULT:
+ case SURFACE_TARMAC:
+ case SURFACE_PAVEMENT:
+ case SURFACE_STONE:
+ case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;
+ case SURFACE_GRASS:
+ 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_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
+ case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
+ case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
+ case SURFACE_SCAFFOLD:
+ 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_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
+ case SURFACE_METAL_POLE:
+ 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_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_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
+ case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;
+ case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
+ 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_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_TIRE:
+ 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_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;
+ case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;
+ case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;
+ default: result = 0.f; break;
+ }
+
+ return result;
+}
+
+float
+cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const
+{
+ float e;
+ e = a;
+ if(a <= b) return 0.0f;
+ if(c <= a) e = c;
+ return (e - b) / d;
+}
+
+uint32
+cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(cAudioCollision *audioCollision)
+{
+ uint8 surface1 = audioCollision->m_bSurface1;
+ uint8 surface2 = audioCollision->m_bSurface2;
+ int32 vol;
+ float ratio;
+
+ if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
+ surface2 == SURFACE_HEDGE) {
+ ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
+ m_sQueueSample.m_nSampleIndex = SFX_RAIN;
+ m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
+ vol = 50.f * ratio;
+ } else {
+ if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) {
+ ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
+ m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
+ m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
+ vol = 30.f * ratio;
+
+ } else {
+ if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK ||
+ surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) {
+ ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
+ m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
+ m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
+ vol = 50.f * ratio;
+ } else {
+ if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { return 0; }
+ ratio = GetCollisionRatio(audioCollision->m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
+ m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
+ m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
+ vol = 40.f * ratio;
+ }
+ }
+ }
+ if(audioCollision->m_nBaseVolume < 2) vol = audioCollision->m_nBaseVolume * vol / 2;
+ return vol;
+}
+
+void
+cAudioManager::SetUpLoopingCollisionSound(cAudioCollision *col, uint8 counter)
+{
+ if(col->m_fIntensity2 > 0.0016f) {
+ uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
+ if(emittingVol) {
+ m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
+ m_sQueueSample.m_bVolume =
+ ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
+ if(m_sQueueSample.m_bVolume) {
+ m_sQueueSample.m_counter = counter;
+ m_sQueueSample.m_vecPos = col->m_vecPosition;
+ m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
+ m_sQueueSample.m_bIs2D = false;
+ m_sQueueSample.m_nReleasingVolumeModificator = 7;
+ m_sQueueSample.m_nLoopCount = 0;
+ m_sQueueSample.m_bEmittingVolume = emittingVol;
+ m_sQueueSample.m_nLoopStart =
+ SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
+ m_sQueueSample.m_nLoopEnd =
+ SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
+ m_sQueueSample.m_fSpeedMultiplier = 4.0f;
+ m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
+ m_sQueueSample.m_bReleasingSoundFlag = 0;
+ m_sQueueSample.m_nReleasingVolumeDivider = 5;
+ m_sQueueSample.m_bReverbFlag = true;
+ m_sQueueSample.m_bRequireReflection = false;
+ AddSampleToRequestedQueue();
+ }
+ }
+ }
+}
+
+void
+cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col)
+{
+ static const int32 gOneShotCol[] = {
+ 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_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_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_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_GRASS_1, SFX_COL_VEG_1, SFX_COL_TARMAC_1,
+ SFX_COL_CONTAINER_1, SFX_COL_NEWS_VENDOR_1, SFX_TYRE_BUMP,
+ SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, SFX_COL_GATE};
+
+ int16 s1;
+ int16 s2;
+
+ int32 emittingVol;
+ float ratio;
+
+ static uint16 counter = 28;
+
+ for(int32 i = 0; i < 2; i++) {
+ if(i) {
+ s1 = col->m_bSurface2;
+ s2 = col->m_bSurface1;
+ } else {
+ s1 = col->m_bSurface1;
+ s2 = col->m_bSurface2;
+ }
+ ratio = GetCollisionOneShotRatio(s1, col->m_fIntensity1);
+ if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio;
+ if(s1 == SURFACE_METAL6 && ratio < 0.6f) {
+ s1 = SURFACE_BILLBOARD;
+ ratio = min(1.f, 2.f * ratio);
+ }
+ emittingVol = 40.f * ratio;
+ if(emittingVol) {
+ m_sQueueSample.m_fDistance = Sqrt(col->m_fDistance);
+ m_sQueueSample.m_bVolume =
+ ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
+ if(m_sQueueSample.m_bVolume) {
+ m_sQueueSample.m_nSampleIndex = gOneShotCol[s1];
+ switch(m_sQueueSample.m_nSampleIndex) {
+ case SFX_COL_TARMAC_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5;
+ break;
+ case SFX_COL_CAR_PANEL_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6;
+ break;
+ case SFX_COL_LAMP_POST_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2;
+ break;
+ case SFX_COL_METAL_CHAIN_FENCE_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4;
+ break;
+ case SFX_COL_PED_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 5;
+ break;
+ case SFX_COL_WOOD_CRATES_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4;
+ break;
+ case SFX_COL_WOOD_BENCH_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4;
+ break;
+ case SFX_COL_VEG_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5;
+ break;
+ case SFX_COL_NEWS_VENDOR_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3;
+ break;
+ case SFX_COL_CAR_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5;
+ break;
+ case SFX_COL_CARDBOARD_1:
+ m_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2;
+ break;
+ default: break;
+ }
+ switch(s1) {
+ case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break;
+ case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break;
+ case SURFACE_PUDDLE:
+ m_sQueueSample.m_nFrequency =
+ 2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
+ break;
+ case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break;
+ case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break;
+ default:
+ m_sQueueSample.m_nFrequency =
+ SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
+ break;
+ }
+ m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);
+ m_sQueueSample.m_counter = counter++;
+ if(counter >= 255) counter = 28;
+ m_sQueueSample.m_vecPos = col->m_vecPosition;
+ m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
+ m_sQueueSample.m_bIs2D = false;
+ m_sQueueSample.m_nReleasingVolumeModificator = 11;
+ m_sQueueSample.m_nLoopCount = 1;
+ m_sQueueSample.m_bEmittingVolume = emittingVol;
+ m_sQueueSample.m_nLoopStart = 0;
+ m_sQueueSample.m_nLoopEnd = -1;
+ m_sQueueSample.m_fSpeedMultiplier = 4.0f;
+ m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
+ m_sQueueSample.m_bReleasingSoundFlag = 1;
+ m_sQueueSample.m_bReverbFlag = true;
+ m_sQueueSample.m_bRequireReflection = false;
+ AddSampleToRequestedQueue();
+ }
+ }
+ }
+}
+
+void
+cAudioManager::ServiceCollisions()
+{
+ int i, j;
+ bool someArr1[NUMAUDIOCOLLISIONS];
+ bool someArr2[NUMAUDIOCOLLISIONS];
+
+ m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
+
+ for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
+ someArr1[i] = someArr2[i] = false;
+
+ for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
+ for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
+ int index = m_sCollisionManager.m_bIndicesTable[i];
+ if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
+ && (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
+ && (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)
+ ) {
+ someArr1[index] = true;
+ someArr2[j] = true;
+ m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
+ SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
+ if (!someArr2[i]) {
+ m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
+ m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
+ m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = 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_fIntensity1 = 0.0f;
+ m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
+ m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
+ }
+ }
+
+ for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
+ int index = m_sCollisionManager.m_bIndicesTable[i];
+ if (!someArr1[index]) {
+ for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
+ if (someArr2[j]) {
+ m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
+ m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
+ 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_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
+ break;
+ }
+ }
+ SetUpOneShotCollisionSound(&m_sCollisionManager.m_asCollisions1[index]);
+ SetUpLoopingCollisionSound(&m_sCollisionManager.m_asCollisions1[index], j);
+ }
+ }
+
+ for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
+ m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
+ m_sCollisionManager.m_bCollisionsInQueue = 0;
+}
+
+void
+cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
+ float velocity)
+{
+ float distSquared;
+ CVector v1;
+ CVector v2;
+
+ if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bUserPause ||
+ (velocity < 0.0016f && collisionPower < 0.01f))
+ return;
+
+ if(entity1->IsBuilding()) {
+ v1 = v2 = entity2->GetPosition();
+ } else if(entity2->IsBuilding()) {
+ v1 = v2 = entity1->GetPosition();
+ } else {
+ v1 = entity1->GetPosition();
+ v2 = entity2->GetPosition();
+ }
+ CVector pos = (v1 + v2) * 0.5f;
+ distSquared = GetDistanceSquared(&pos);
+ if(distSquared < SQR(CollisionSoundIntensity)) {
+ m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
+ m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
+ m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
+ m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
+ m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
+ m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
+ m_sCollisionManager.m_sQueue.m_vecPosition = pos;
+ m_sCollisionManager.m_sQueue.m_fDistance = distSquared;
+ m_sCollisionManager.AddCollisionToRequestedQueue();
+ }
+}
+
+STARTPATCHES
+InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP);
+InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP);
+InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP);
+InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP);
+InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP);
+InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP);
+InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP);
+InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/audio/AudioCollision.h b/src/audio/AudioCollision.h
index cf201735..956da3e3 100644
--- a/src/audio/AudioCollision.h
+++ b/src/audio/AudioCollision.h
@@ -1,36 +1,36 @@
-#pragma once
-
-#define NUMAUDIOCOLLISIONS 10
-
-class cAudioCollision
-{
-public:
- CEntity *m_pEntity1;
- CEntity *m_pEntity2;
- uint8 m_bSurface1;
- uint8 m_bSurface2;
- float m_fIntensity1;
- float m_fIntensity2;
- CVector m_vecPosition;
- float m_fDistance;
- int32 m_nBaseVolume;
-
- // no methods
-};
-
-static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error");
-
-class cAudioCollisionManager
-{
-public:
- cAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS];
- cAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS];
- uint8 m_bIndicesTable[NUMAUDIOCOLLISIONS];
- uint8 m_bCollisionsInQueue;
- cAudioCollision m_sQueue;
-
- // reversed all methods
- void AddCollisionToRequestedQueue(); /// ok
-};
-
+#pragma once
+
+#define NUMAUDIOCOLLISIONS 10
+
+class cAudioCollision
+{
+public:
+ CEntity *m_pEntity1;
+ CEntity *m_pEntity2;
+ uint8 m_bSurface1;
+ uint8 m_bSurface2;
+ float m_fIntensity1;
+ float m_fIntensity2;
+ CVector m_vecPosition;
+ float m_fDistance;
+ int32 m_nBaseVolume;
+
+ // no methods
+};
+
+static_assert(sizeof(cAudioCollision) == 40, "cAudioCollision: error");
+
+class cAudioCollisionManager
+{
+public:
+ cAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS];
+ cAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS];
+ uint8 m_bIndicesTable[NUMAUDIOCOLLISIONS];
+ uint8 m_bCollisionsInQueue;
+ cAudioCollision m_sQueue;
+
+ // reversed all methods
+ void AddCollisionToRequestedQueue(); /// ok
+};
+
static_assert(sizeof(cAudioCollisionManager) == 852, "cAudioCollisionManager: error"); \ No newline at end of file
diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h
index 0e656475..910ffcaf 100644
--- a/src/audio/AudioManager.h
+++ b/src/audio/AudioManager.h
@@ -1,4 +1,4 @@
-#pragma once
+#pragma once
#include "DMAudio.h"
#include "common.h"
diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp
index 91312867..3ba16ef3 100644
--- a/src/audio/PoliceRadio.cpp
+++ b/src/audio/PoliceRadio.cpp
@@ -1,789 +1,789 @@
-#include "common.h"
-#include "patcher.h"
-#include "DMAudio.h"
-#include "AudioManager.h"
-#include "AudioSamples.h"
-#include "MusicManager.h"
-#include "PoliceRadio.h"
-#include "PlayerPed.h"
-#include "sampman.h"
-#include "Zones.h"
-#include "Vehicle.h"
-#include "World.h"
-
-const int maxVolume = 127;
-const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples);
-const int policeChannel = channels + 1;
-
-struct tPoliceRadioZone {
- char m_aName[8];
- uint32 m_nSampleIndex;
- int32 field_12;
-};
-
-tPoliceRadioZone (&ZoneSfx)[NUMAUDIOZONES] = *(tPoliceRadioZone(*)[NUMAUDIOZONES])*(uintptr*)0x880240;
-char *SubZo2Label = (char*)0x6E9918;
-char *SubZo3Label = (char*)0x6E9870;
-
-int32 &g_nMissionAudioSfx = *(int32*)0x60ED84;
-int8 &g_nMissionAudioPlayingStatus = *(int8*)0x60ED88;
-uint8 &gSpecialSuspectLastSeenReport = *(uint8*)0x95CD4D;
-uint32 (&gMinTimeToNextReport)[NUM_CRIME_TYPES] = *(uint32(*)[NUM_CRIME_TYPES])*(uintptr*)0x8E2828;
-
-void
-cAudioManager::InitialisePoliceRadioZones()
-{
- for (int32 i = 0; i < NUMAUDIOZONES; i++)
- memset(ZoneSfx[i].m_aName, 0, 8);
-
-#define SETZONESFX(i, name, sample) \
- strcpy(ZoneSfx[i].m_aName, name); \
- ZoneSfx[i].m_nSampleIndex = sample;
-
- SETZONESFX(0, "HOSPI_2", SFX_POLICE_RADIO_ROCKFORD);
- SETZONESFX(1, "CONSTRU", SFX_POLICE_RADIO_FORT_STAUNTON);
- SETZONESFX(2, "STADIUM", SFX_POLICE_RADIO_ASPATRIA);
- SETZONESFX(3, "YAKUSA", SFX_POLICE_RADIO_TORRINGTON);
- SETZONESFX(4, "SHOPING", SFX_POLICE_RADIO_BEDFORD_POINT);
- SETZONESFX(5, "COM_EAS", SFX_POLICE_RADIO_NEWPORT);
- SETZONESFX(6, "PARK", SFX_POLICE_RADIO_BELLEVILLE_PARK);
- SETZONESFX(7, "UNIVERS", SFX_POLICE_RADIO_LIBERTY_CAMPUS);
- SETZONESFX(8, "BIG_DAM", SFX_POLICE_RADIO_COCHRANE_DAM);
- SETZONESFX(9, "SUB_IND", SFX_POLICE_RADIO_PIKE_CREEK);
- SETZONESFX(10, "SWANKS", SFX_POLICE_RADIO_CEDAR_GROVE);
- SETZONESFX(11, "PROJECT", SFX_POLICE_RADIO_WICHITA_GARDENS);
- SETZONESFX(12, "AIRPORT", SFX_POLICE_RADIO_FRANCIS_INTERNATIONAL_AIRPORT);
- SETZONESFX(13, "PORT_W", SFX_POLICE_RADIO_CALLAHAN_POINT);
- SETZONESFX(14, "PORT_S", SFX_POLICE_RADIO_ATLANTIC_QUAYS);
- SETZONESFX(15, "PORT_E", SFX_POLICE_RADIO_PORTLAND_HARBOUR);
- SETZONESFX(16, "PORT_I", SFX_POLICE_RADIO_TRENTON);
- SETZONESFX(17, "CHINA", SFX_POLICE_RADIO_CHINATOWN);
- SETZONESFX(18, "REDLIGH", SFX_POLICE_RADIO_RED_LIGHT_DISTRICT);
- SETZONESFX(19, "TOWERS", SFX_POLICE_RADIO_HEPBURN_HEIGHTS);
- SETZONESFX(20, "LITTLEI", SFX_POLICE_RADIO_SAINT_MARKS);
- SETZONESFX(21, "HARWOOD", SFX_POLICE_RADIO_HARWOOD);
- SETZONESFX(22, "EASTBAY", SFX_POLICE_RADIO_PORTLAND_BEACH);
- SETZONESFX(23, "S_VIEW", SFX_POLICE_RADIO_PORTLAND_STRAIGHTS);
- SETZONESFX(24, "CITYZON", SFX_POLICE_RADIO_LIBERTY_CITY);
- SETZONESFX(25, "IND_ZON", SFX_POLICE_RADIO_PORTLAND);
- SETZONESFX(26, "COM_ZON", SFX_POLICE_RADIO_STAUNTON_ISLAND);
- SETZONESFX(27, "SUB_ZON", SFX_POLICE_RADIO_SHORESIDE_VALE);
- SETZONESFX(28, "SUB_ZO2", SFX_POLICE_RADIO_SHORESIDE_VALE);
- SETZONESFX(29, "SUB_ZO3", SFX_POLICE_RADIO_SHORESIDE_VALE);
- SETZONESFX(30, "A", SFX_POLICE_RADIO_ROCKFORD);
- SETZONESFX(31, "A", SFX_POLICE_RADIO_ROCKFORD);
- SETZONESFX(32, "A", SFX_POLICE_RADIO_ROCKFORD);
- SETZONESFX(33, "A", SFX_POLICE_RADIO_ROCKFORD);
- SETZONESFX(34, "A", SFX_POLICE_RADIO_ROCKFORD);
-
-#undef SETZONESFX
-
- strcpy(SubZo2Label, "SUB_ZO2");
- strcpy(SubZo3Label, "SUB_ZO3");
-}
-
-void
-cAudioManager::InitialisePoliceRadio()
-{
- m_sPoliceRadioQueue.policeChannelTimer = 0;
- m_sPoliceRadioQueue.policeChannelTimerSeconds = 0;
- m_sPoliceRadioQueue.policeChannelCounterSeconds = 0;
- for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++)
- m_sPoliceRadioQueue.crimes[i].type = 0;
-
- SampleManager.SetChannelReverbFlag(policeChannel, 0);
- gSpecialSuspectLastSeenReport = false;
- for (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++)
- gMinTimeToNextReport[i] = m_FrameCounter;
-}
-
-void
-cAudioManager::ResetPoliceRadio()
-{
- if (!m_bIsInitialised) return;
- if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
- InitialisePoliceRadio();
-}
-
-void
-cAudioManager::SetMissionScriptPoliceAudio(int32 sfx) const
-{
- if (!m_bIsInitialised) return;
- if (g_nMissionAudioPlayingStatus != 1) {
- g_nMissionAudioPlayingStatus = 0;
- g_nMissionAudioSfx = sfx;
- }
-}
-
-int8
-cAudioManager::GetMissionScriptPoliceAudioPlayingStatus() const
-{
- return g_nMissionAudioPlayingStatus;
-}
-
-void
-cAudioManager::DoPoliceRadioCrackle()
-{
- m_sQueueSample.m_nEntityIndex = m_nPoliceChannelEntity;
- m_sQueueSample.m_counter = 0;
- m_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE;
- m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
- m_sQueueSample.m_bIs2D = true;
- m_sQueueSample.m_nReleasingVolumeModificator = 10;
- m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE);
- m_sQueueSample.m_bVolume = m_anRandomTable[2] % 20 + 15;
- m_sQueueSample.m_nLoopCount = 0;
- m_sQueueSample.m_bEmittingVolume = m_sQueueSample.m_bVolume;
- m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_POLICE_RADIO_CRACKLE);
- m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_POLICE_RADIO_CRACKLE);
- m_sQueueSample.m_bReleasingSoundFlag = 0;
- m_sQueueSample.m_bReverbFlag = false;
- m_sQueueSample.m_bOffset = 63;
- m_sQueueSample.m_nReleasingVolumeDivider = 3;
- m_sQueueSample.m_bRequireReflection = false;
- AddSampleToRequestedQueue();
-}
-
-void
-cAudioManager::ServicePoliceRadio()
-{
- int32 wantedLevel = 0; // bug?;
- static uint32 nLastSeen = 300;
-
- if (!m_bIsInitialised) return;
-
- if (!m_bUserPause) {
- bool crimeReport = SetupCrimeReport();
- wantedLevel = FindPlayerPed()->m_pWanted->m_nWantedLevel;
- if (!crimeReport) {
- if (wantedLevel) {
- if (nLastSeen) {
- --nLastSeen;
- } else {
- nLastSeen = m_anRandomTable[1] % 1000 + 2000;
- SetupSuspectLastSeenReport();
- }
- }
- }
- }
- ServicePoliceRadioChannel(wantedLevel);
-}
-
-void
-cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel)
-{
- bool processed = false;
- uint32 sample;
- int32 freq;
-
- static int cWait = 0;
- static bool bChannelOpen = false;
- static uint8 bMissionAudioPhysicalPlayingStatus = 0;
- static int32 PoliceChannelFreq = 5500;
-
- if (!m_bIsInitialised) return;
-
- if (m_bUserPause) {
- if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
- if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && bMissionAudioPhysicalPlayingStatus == 1 &&
- SampleManager.IsStreamPlaying(1)) {
- SampleManager.PauseStream(1, 1);
- }
- } else {
- if (m_bPreviousUserPause && g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES &&
- bMissionAudioPhysicalPlayingStatus == 1) {
- SampleManager.PauseStream(0, 1);
- }
- if (m_sPoliceRadioQueue.policeChannelTimer == 0) bChannelOpen = false;
- if (cWait) {
- --cWait;
- return;
- }
- if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && !bChannelOpen) {
- if (g_nMissionAudioPlayingStatus) {
- if (g_nMissionAudioPlayingStatus == 1 && !bMissionAudioPhysicalPlayingStatus &&
- SampleManager.IsStreamPlaying(1)) {
- bMissionAudioPhysicalPlayingStatus = 1;
- }
- if (bMissionAudioPhysicalPlayingStatus == 1) {
- if (SampleManager.IsStreamPlaying(1)) {
- DoPoliceRadioCrackle();
- } else {
- bMissionAudioPhysicalPlayingStatus = 2;
- g_nMissionAudioPlayingStatus = 2;
- g_nMissionAudioSfx = TOTAL_AUDIO_SAMPLES;
- cWait = 30;
- }
- return;
- }
- } else if (!SampleManager.GetChannelUsedFlag(policeChannel)) {
- SampleManager.PreloadStreamedFile(g_nMissionAudioSfx, 1);
- SampleManager.SetStreamedVolumeAndPan(maxVolume, 63, 1, 1);
- SampleManager.StartPreloadedStreamedFile(1);
- g_nMissionAudioPlayingStatus = 1;
- bMissionAudioPhysicalPlayingStatus = 0;
- return;
- }
- }
- if (bChannelOpen) DoPoliceRadioCrackle();
- if ((g_nMissionAudioSfx == TOTAL_AUDIO_SAMPLES || g_nMissionAudioPlayingStatus != 1) &&
- !SampleManager.GetChannelUsedFlag(policeChannel) && m_sPoliceRadioQueue.policeChannelTimer) {
- if (m_sPoliceRadioQueue.policeChannelTimer) {
- sample = m_sPoliceRadioQueue.crimesSamples[m_sPoliceRadioQueue.policeChannelCounterSeconds];
- m_sPoliceRadioQueue.policeChannelTimer--;
- m_sPoliceRadioQueue.policeChannelCounterSeconds = (m_sPoliceRadioQueue.policeChannelCounterSeconds + 1) % 60;
- } else {
- sample = TOTAL_AUDIO_SAMPLES;
- }
- if (!wantedLevel) {
- if (gSpecialSuspectLastSeenReport) {
- gSpecialSuspectLastSeenReport = 0;
- } else if (((sample >= SFX_POLICE_RADIO_MESSAGE_NOISE_1) && (sample <= SFX_POLICE_RADIO_MESSAGE_NOISE_3)) || sample == TOTAL_AUDIO_SAMPLES) {
- bChannelOpen = false;
- processed = true;
- }
- }
- if (sample == TOTAL_AUDIO_SAMPLES) {
- if (!processed) cWait = 30;
- } else {
- SampleManager.InitialiseChannel(policeChannel, sample, 0);
- switch (sample) {
- case SFX_POLICE_RADIO_MESSAGE_NOISE_1:
- case SFX_POLICE_RADIO_MESSAGE_NOISE_2:
- case SFX_POLICE_RADIO_MESSAGE_NOISE_3:
- freq = m_anRandomTable[4] % 2000 + 10025;
- bChannelOpen = bChannelOpen == false;
- break;
- default: freq = SampleManager.GetSampleBaseFrequency(sample); break;
- }
- PoliceChannelFreq = freq;
- SampleManager.SetChannelFrequency(policeChannel, freq);
- SampleManager.SetChannelVolume(policeChannel, 100);
- SampleManager.SetChannelPan(policeChannel, 63);
- SampleManager.SetChannelLoopCount(policeChannel, 1);
- SampleManager.SetChannelLoopPoints(policeChannel, 0, -1);
- SampleManager.StartChannel(policeChannel);
- }
- if (processed) ResetPoliceRadio();
- }
- }
-}
-
-bool
-cAudioManager::SetupCrimeReport()
-{
- int16 audioZoneId;
- CZone *zone;
- float rangeX;
- float rangeY;
- float halfX;
- float halfY;
- float quarterX;
- float quarterY;
- int i;
- int32 sampleIndex;
- bool processed = false;
-
- if (MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE) return false;
-
- if (60 - m_sPoliceRadioQueue.policeChannelTimer <= 9) {
- AgeCrimes();
- return true;
- }
-
- for (i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
- if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE)
- break;
- }
-
- if (i == ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) return false;
- audioZoneId = CTheZones::FindAudioZone(&m_sPoliceRadioQueue.crimes[i].position);
- if (audioZoneId >= 0 && audioZoneId < NUMAUDIOZONES) {
- zone = &CTheZones::ZoneArray[CTheZones::AudioZoneArray[audioZoneId]];
- for (int j = 0; j < NUMAUDIOZONES; j++) {
- if (strcmp(zone->name, ZoneSfx[j].m_aName) == 0) {
- sampleIndex = ZoneSfx[j].m_nSampleIndex;
- m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_WEVE_GOT);
- m_sPoliceRadioQueue.Add(m_anRandomTable[1] % 2 + SFX_A_10_1);
- switch (m_sPoliceRadioQueue.crimes[i].type) {
- case CRIME_PED_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_PED; break;
- case CRIME_COP_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_COP; break;
- case CRIME_VEHICLE_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_STEAL_CAR; break;
- case CRIME_DESTROYED_CESSNA: m_sPoliceRadioQueue.crimes[i].type = CRIME_SHOOT_HELI; break;
- default: break;
- }
- m_sPoliceRadioQueue.Add(m_sPoliceRadioQueue.crimes[i].type + SFX_CRIME_1 - 1);
- m_sPoliceRadioQueue.Add(SFX_IN);
- if (sampleIndex == SFX_POLICE_RADIO_SHORESIDE_VALE &&
- (strcmp(zone->name, SubZo2Label) == 0 || strcmp(zone->name, SubZo3Label) == 0)) {
- m_sPoliceRadioQueue.Add(SFX_NORTH);
- m_sPoliceRadioQueue.Add(SFX_EAST);
- } else {
- rangeX = zone->maxx - zone->minx;
- rangeY = zone->maxy - zone->miny;
- halfX = 0.5f * rangeX + zone->minx;
- halfY = 0.5f * rangeY + zone->miny;
- quarterX = 0.25f * rangeX;
- quarterY = 0.25f * rangeY;
-
- if (m_sPoliceRadioQueue.crimes[i].position.y > halfY + quarterY) {
- m_sPoliceRadioQueue.Add(SFX_NORTH);
- processed = true;
- } else if (m_sPoliceRadioQueue.crimes[i].position.y < halfY - quarterY) {
- m_sPoliceRadioQueue.Add(SFX_SOUTH);
- processed = true;
- }
-
- if (m_sPoliceRadioQueue.crimes[i].position.x > halfX + quarterX)
- m_sPoliceRadioQueue.Add(SFX_EAST);
- else if (m_sPoliceRadioQueue.crimes[i].position.x < halfX - quarterX)
- m_sPoliceRadioQueue.Add(SFX_WEST);
- else if (!processed)
- m_sPoliceRadioQueue.Add(SFX_CENTRAL);
-
- m_sPoliceRadioQueue.Add(sampleIndex);
- m_sPoliceRadioQueue.Add(m_anRandomTable[2] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
- }
- break;
- }
- }
- }
- m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
- AgeCrimes();
- return true;
-}
-
-void
-cAudioManager::SetupSuspectLastSeenReport()
-{
- CVehicle *veh;
- uint8 color1;
- int32 main_color;
- int32 sample;
-
- int32 color_pre_modifier;
- int32 color_post_modifier;
-
- const int32 gCarColourTable[][3] = {
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLACK, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_WHITE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_BRIGHT, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, SFX_POLICE_RADIO_GREY},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
-#else
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
-#endif
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
-#else
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
-#endif
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
-#else
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
-#endif
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
-#else
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
-#endif
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
-#else
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
-#endif
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, SFX_POLICE_RADIO_BLUE},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
-#else
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
-#endif
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, SFX_POLICE_RADIO_GREY},
-#else
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
-#endif
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
-#else
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
-#endif
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
-#ifdef FIX_BUGS
- {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
-#else
- {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
-#endif
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
- {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES}
- };
-
- if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
- veh = FindPlayerVehicle();
- if (veh != nil) {
- if (60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
- color1 = veh->m_currentColour1;
- if (color1 >= ARRAY_SIZE(gCarColourTable)) {
- debug("\n *** UNKNOWN CAR COLOUR %d *** ", color1);
- } else {
- main_color = gCarColourTable[color1][1];
- color_pre_modifier = gCarColourTable[color1][0];
- color_post_modifier = gCarColourTable[color1][2];
- switch (veh->m_modelIndex) {
-#ifdef FIX_BUGS
- case MI_COLUMB:
- main_color = SFX_POLICE_RADIO_BLUE;
- color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
-#endif
- case MI_LANDSTAL:
- case MI_BLISTA: sample = SFX_POLICE_RADIO_CRUISER; break;
-#ifdef FIX_BUGS
- case MI_YARDIE:
- color_pre_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_RED;
- color_post_modifier = SFX_POLICE_RADIO_YELLOW;
- sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
- case MI_DIABLOS:
- main_color = SFX_POLICE_RADIO_BLACK;
-#endif
- case MI_IDAHO:
- case MI_STALLION: sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
-#ifdef FIX_BUGS
- case MI_YAKUZA:
- color_pre_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_SILVER;
- color_post_modifier = SFX_POLICE_RADIO_RED;
-#endif
- case MI_STINGER:
- case MI_INFERNUS:
- case MI_CHEETAH:
- case MI_BANSHEE: sample = SFX_POLICE_RADIO_SPORTS_CAR; break;
-#ifdef FIX_BUGS
- case MI_MAFIA:
- color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_GREY;
- case MI_KURUMA:
-#endif
- case MI_PEREN:
- case MI_SENTINEL:
- case MI_FBICAR: sample = SFX_POLICE_RADIO_SALOON; break;
- case MI_PATRIOT:
- case MI_BOBCAT: sample = SFX_POLICE_RADIO_PICKUP; break;
- case MI_FIRETRUCK: sample = SFX_POLICE_RADIO_FIRE_TRUCK; break;
-#ifdef FIX_BUGS
- case MI_LINERUN:
- case MI_FLATBED:
-#endif
- case MI_TRASH:
- case MI_BARRACKS: sample = SFX_POLICE_RADIO_TRUCK; break;
- case MI_STRETCH: sample = SFX_POLICE_RADIO_LIMO; break;
-#ifdef FIX_BUGS
- case MI_CORPSE:
-#endif
- case MI_MANANA:
- case MI_ESPERANT: sample = SFX_POLICE_RADIO_2_DOOR; break;
-#ifdef FIX_BUGS
- case MI_HOODS:
- color_pre_modifier = TOTAL_AUDIO_SAMPLES;
- main_color = SFX_POLICE_RADIO_BLUE;
- color_post_modifier = SFX_POLICE_RADIO_GREEN;
- case MI_BELLYUP:
- case MI_YANKEE:
- case MI_TOYZ:
- case MI_MRWONGS:
- case MI_PANLANT:
-#endif
- case MI_PONY:
- case MI_MULE:
- case MI_MOONBEAM:
- case MI_ENFORCER:
- case MI_SECURICA:
- case MI_RUMPO: sample = SFX_POLICE_RADIO_VAN; break;
- case MI_AMBULAN: sample = SFX_POLICE_RADIO_AMBULANCE; break;
- case MI_TAXI:
- case MI_CABBIE:
- case MI_BORGNINE: sample = SFX_POLICE_RADIO_TAXI; break;
- case MI_MRWHOOP:
- sample = SFX_POLICE_RADIO_ICE_CREAM_VAN;
- break;
- case MI_BFINJECT: sample = SFX_POLICE_RADIO_BUGGY; break;
- case MI_POLICE: sample = SFX_POLICE_RADIO_POLICE_CAR; break;
-#ifdef FIX_BUGS
- case MI_SPEEDER:
- case MI_REEFER:
- case MI_GHOST:
-#endif
- case MI_PREDATOR: sample = SFX_POLICE_RADIO_BOAT; break;
- case MI_BUS:
- case MI_COACH: sample = SFX_POLICE_RADIO_BUS; break;
- case MI_RHINO:
- sample = SFX_POLICE_RADIO_TANK;
- main_color = TOTAL_AUDIO_SAMPLES;
- color_post_modifier = TOTAL_AUDIO_SAMPLES;
- break;
- case MI_TRAIN:
- sample = SFX_POLICE_RADIO_SUBWAY_CAR;
- main_color = TOTAL_AUDIO_SAMPLES;
- color_post_modifier = TOTAL_AUDIO_SAMPLES;
-
- break;
- default:
- debug("\n *** UNKNOWN CAR MODEL INDEX %d *** ", veh->m_modelIndex);
- return;
- }
- m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
- if (m_anRandomTable[3] % 2)
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
-#ifdef FIX_BUGS
- if (main_color == SFX_POLICE_RADIO_ORANGE && color_pre_modifier == TOTAL_AUDIO_SAMPLES)
-#else
- if (main_color == SFX_POLICE_RADIO_ORANGE)
-#endif
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_AN);
- else
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_A);
- if (color_pre_modifier != TOTAL_AUDIO_SAMPLES)
- m_sPoliceRadioQueue.Add(color_pre_modifier);
- if (main_color != TOTAL_AUDIO_SAMPLES)
- m_sPoliceRadioQueue.Add(main_color);
- if (color_post_modifier != TOTAL_AUDIO_SAMPLES)
- m_sPoliceRadioQueue.Add(color_post_modifier);
- m_sPoliceRadioQueue.Add(sample);
- m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
- }
- }
- } else if (60 - m_sPoliceRadioQueue.policeChannelTimer > 4) {
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_ON_FOOT);
- m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
- }
- }
-}
-
-
-
-void
-cAudioManager::ReportCrime(int32 type, const CVector *pos)
-{
- int32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes);
- if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 &&
- (type > CRIME_NONE || type < NUM_CRIME_TYPES) && m_FrameCounter >= gMinTimeToNextReport[type]) {
- for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
- if (m_sPoliceRadioQueue.crimes[i].type) {
- if (m_sPoliceRadioQueue.crimes[i].type == type) {
- m_sPoliceRadioQueue.crimes[i].position = *pos;
- m_sPoliceRadioQueue.crimes[i].timer = 0;
- return;
- }
- } else {
- lastCrime = i;
- }
- }
-
- if (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) {
- m_sPoliceRadioQueue.crimes[lastCrime].type = type;
- m_sPoliceRadioQueue.crimes[lastCrime].position = *pos;
- m_sPoliceRadioQueue.crimes[lastCrime].timer = 0;
- gMinTimeToNextReport[type] = m_FrameCounter + 500;
- }
- }
-}
-
-void
-cAudioManager::PlaySuspectLastSeen(float x, float y, float z)
-{
- int16 audioZone;
- CZone *zone;
- float rangeX;
- float rangeY;
- float halfX;
- float halfY;
- float quarterX;
- float quarterY;
- int32 sample;
- bool processed = false;
- CVector vec = CVector(x, y, z);
-
- if (!m_bIsInitialised) return;
-
- if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && 60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
- audioZone = CTheZones::FindAudioZone(&vec);
- if (audioZone >= 0 && audioZone < NUMAUDIOZONES) {
- zone = &CTheZones::ZoneArray[CTheZones::AudioZoneArray[audioZone]];
- for (int i = 0; i < NUMAUDIOZONES; i++) {
- if (strcmp(zone->name, ZoneSfx[i].m_aName) == 0) {
- sample = ZoneSfx[i].m_nSampleIndex;
- m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
- m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
- m_sPoliceRadioQueue.Add(SFX_IN);
- if (sample == SFX_POLICE_RADIO_SHORESIDE_VALE &&
- (strcmp(zone->name, SubZo2Label) == 0 ||
- strcmp(zone->name, SubZo3Label) == 0)) {
- m_sPoliceRadioQueue.Add(SFX_NORTH);
- m_sPoliceRadioQueue.Add(SFX_EAST);
- } else {
- rangeX = zone->maxx - zone->minx;
- rangeY = zone->maxy - zone->miny;
- halfX = 0.5f * rangeX + zone->minx;
- halfY = 0.5f * rangeY + zone->miny;
- quarterX = 0.25f * rangeX;
- quarterY = 0.25f * rangeY;
-
- if (vec.y > halfY + quarterY) {
- m_sPoliceRadioQueue.Add(SFX_NORTH);
- processed = true;
- } else if (vec.y < halfY - quarterY) {
- m_sPoliceRadioQueue.Add(SFX_SOUTH);
- processed = true;
- }
-
- if (vec.x > halfX + quarterX)
- m_sPoliceRadioQueue.Add(SFX_EAST);
- else if (vec.x < halfX - quarterX)
- m_sPoliceRadioQueue.Add(SFX_WEST);
- else if (!processed)
- m_sPoliceRadioQueue.Add(SFX_CENTRAL);
- }
- m_sPoliceRadioQueue.Add(sample);
- m_sPoliceRadioQueue.Add(m_anRandomTable[2] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
- m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
- gSpecialSuspectLastSeenReport = true;
- break;
- }
- }
- }
- }
-}
-
-void
-cAudioManager::AgeCrimes()
-{
- for (uint8 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
- if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE) {
- if (++m_sPoliceRadioQueue.crimes[i].timer > 1500) m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
- }
- }
-}
-
-STARTPATCHES
-InjectHook(0x580AF0, &cAudioManager::AgeCrimes, PATCH_JUMP);
-InjectHook(0x57F060, &cAudioManager::DoPoliceRadioCrackle, PATCH_JUMP);
-InjectHook(0x57F050, &cAudioManager::GetMissionScriptPoliceAudioPlayingStatus, PATCH_JUMP);
-InjectHook(0x57EEC0, &cAudioManager::InitialisePoliceRadio, PATCH_JUMP);
-InjectHook(0x57EAC0, &cAudioManager::InitialisePoliceRadioZones, PATCH_JUMP);
-InjectHook(0x580500, &cAudioManager::PlaySuspectLastSeen, PATCH_JUMP);
-InjectHook(0x5803D0, &cAudioManager::ReportCrime, PATCH_JUMP);
-InjectHook(0x57EFF0, &cAudioManager::ResetPoliceRadio, PATCH_JUMP);
-InjectHook(0x57F110, &cAudioManager::ServicePoliceRadio, PATCH_JUMP);
-InjectHook(0x57F1B0, &cAudioManager::ServicePoliceRadioChannel, PATCH_JUMP);
-InjectHook(0x57F020, &cAudioManager::SetMissionScriptPoliceAudio, PATCH_JUMP);
-InjectHook(0x57F5B0, &cAudioManager::SetupCrimeReport, PATCH_JUMP);
-InjectHook(0x57FCC0, &cAudioManager::SetupSuspectLastSeenReport, PATCH_JUMP);
-ENDPATCHES
+#include "common.h"
+#include "patcher.h"
+#include "DMAudio.h"
+#include "AudioManager.h"
+#include "AudioSamples.h"
+#include "MusicManager.h"
+#include "PoliceRadio.h"
+#include "PlayerPed.h"
+#include "sampman.h"
+#include "Zones.h"
+#include "Vehicle.h"
+#include "World.h"
+
+const int maxVolume = 127;
+const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples);
+const int policeChannel = channels + 1;
+
+struct tPoliceRadioZone {
+ char m_aName[8];
+ uint32 m_nSampleIndex;
+ int32 field_12;
+};
+
+tPoliceRadioZone (&ZoneSfx)[NUMAUDIOZONES] = *(tPoliceRadioZone(*)[NUMAUDIOZONES])*(uintptr*)0x880240;
+char *SubZo2Label = (char*)0x6E9918;
+char *SubZo3Label = (char*)0x6E9870;
+
+int32 &g_nMissionAudioSfx = *(int32*)0x60ED84;
+int8 &g_nMissionAudioPlayingStatus = *(int8*)0x60ED88;
+uint8 &gSpecialSuspectLastSeenReport = *(uint8*)0x95CD4D;
+uint32 (&gMinTimeToNextReport)[NUM_CRIME_TYPES] = *(uint32(*)[NUM_CRIME_TYPES])*(uintptr*)0x8E2828;
+
+void
+cAudioManager::InitialisePoliceRadioZones()
+{
+ for (int32 i = 0; i < NUMAUDIOZONES; i++)
+ memset(ZoneSfx[i].m_aName, 0, 8);
+
+#define SETZONESFX(i, name, sample) \
+ strcpy(ZoneSfx[i].m_aName, name); \
+ ZoneSfx[i].m_nSampleIndex = sample;
+
+ SETZONESFX(0, "HOSPI_2", SFX_POLICE_RADIO_ROCKFORD);
+ SETZONESFX(1, "CONSTRU", SFX_POLICE_RADIO_FORT_STAUNTON);
+ SETZONESFX(2, "STADIUM", SFX_POLICE_RADIO_ASPATRIA);
+ SETZONESFX(3, "YAKUSA", SFX_POLICE_RADIO_TORRINGTON);
+ SETZONESFX(4, "SHOPING", SFX_POLICE_RADIO_BEDFORD_POINT);
+ SETZONESFX(5, "COM_EAS", SFX_POLICE_RADIO_NEWPORT);
+ SETZONESFX(6, "PARK", SFX_POLICE_RADIO_BELLEVILLE_PARK);
+ SETZONESFX(7, "UNIVERS", SFX_POLICE_RADIO_LIBERTY_CAMPUS);
+ SETZONESFX(8, "BIG_DAM", SFX_POLICE_RADIO_COCHRANE_DAM);
+ SETZONESFX(9, "SUB_IND", SFX_POLICE_RADIO_PIKE_CREEK);
+ SETZONESFX(10, "SWANKS", SFX_POLICE_RADIO_CEDAR_GROVE);
+ SETZONESFX(11, "PROJECT", SFX_POLICE_RADIO_WICHITA_GARDENS);
+ SETZONESFX(12, "AIRPORT", SFX_POLICE_RADIO_FRANCIS_INTERNATIONAL_AIRPORT);
+ SETZONESFX(13, "PORT_W", SFX_POLICE_RADIO_CALLAHAN_POINT);
+ SETZONESFX(14, "PORT_S", SFX_POLICE_RADIO_ATLANTIC_QUAYS);
+ SETZONESFX(15, "PORT_E", SFX_POLICE_RADIO_PORTLAND_HARBOUR);
+ SETZONESFX(16, "PORT_I", SFX_POLICE_RADIO_TRENTON);
+ SETZONESFX(17, "CHINA", SFX_POLICE_RADIO_CHINATOWN);
+ SETZONESFX(18, "REDLIGH", SFX_POLICE_RADIO_RED_LIGHT_DISTRICT);
+ SETZONESFX(19, "TOWERS", SFX_POLICE_RADIO_HEPBURN_HEIGHTS);
+ SETZONESFX(20, "LITTLEI", SFX_POLICE_RADIO_SAINT_MARKS);
+ SETZONESFX(21, "HARWOOD", SFX_POLICE_RADIO_HARWOOD);
+ SETZONESFX(22, "EASTBAY", SFX_POLICE_RADIO_PORTLAND_BEACH);
+ SETZONESFX(23, "S_VIEW", SFX_POLICE_RADIO_PORTLAND_STRAIGHTS);
+ SETZONESFX(24, "CITYZON", SFX_POLICE_RADIO_LIBERTY_CITY);
+ SETZONESFX(25, "IND_ZON", SFX_POLICE_RADIO_PORTLAND);
+ SETZONESFX(26, "COM_ZON", SFX_POLICE_RADIO_STAUNTON_ISLAND);
+ SETZONESFX(27, "SUB_ZON", SFX_POLICE_RADIO_SHORESIDE_VALE);
+ SETZONESFX(28, "SUB_ZO2", SFX_POLICE_RADIO_SHORESIDE_VALE);
+ SETZONESFX(29, "SUB_ZO3", SFX_POLICE_RADIO_SHORESIDE_VALE);
+ SETZONESFX(30, "A", SFX_POLICE_RADIO_ROCKFORD);
+ SETZONESFX(31, "A", SFX_POLICE_RADIO_ROCKFORD);
+ SETZONESFX(32, "A", SFX_POLICE_RADIO_ROCKFORD);
+ SETZONESFX(33, "A", SFX_POLICE_RADIO_ROCKFORD);
+ SETZONESFX(34, "A", SFX_POLICE_RADIO_ROCKFORD);
+
+#undef SETZONESFX
+
+ strcpy(SubZo2Label, "SUB_ZO2");
+ strcpy(SubZo3Label, "SUB_ZO3");
+}
+
+void
+cAudioManager::InitialisePoliceRadio()
+{
+ m_sPoliceRadioQueue.policeChannelTimer = 0;
+ m_sPoliceRadioQueue.policeChannelTimerSeconds = 0;
+ m_sPoliceRadioQueue.policeChannelCounterSeconds = 0;
+ for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++)
+ m_sPoliceRadioQueue.crimes[i].type = 0;
+
+ SampleManager.SetChannelReverbFlag(policeChannel, 0);
+ gSpecialSuspectLastSeenReport = false;
+ for (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++)
+ gMinTimeToNextReport[i] = m_FrameCounter;
+}
+
+void
+cAudioManager::ResetPoliceRadio()
+{
+ if (!m_bIsInitialised) return;
+ if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
+ InitialisePoliceRadio();
+}
+
+void
+cAudioManager::SetMissionScriptPoliceAudio(int32 sfx) const
+{
+ if (!m_bIsInitialised) return;
+ if (g_nMissionAudioPlayingStatus != 1) {
+ g_nMissionAudioPlayingStatus = 0;
+ g_nMissionAudioSfx = sfx;
+ }
+}
+
+int8
+cAudioManager::GetMissionScriptPoliceAudioPlayingStatus() const
+{
+ return g_nMissionAudioPlayingStatus;
+}
+
+void
+cAudioManager::DoPoliceRadioCrackle()
+{
+ m_sQueueSample.m_nEntityIndex = m_nPoliceChannelEntity;
+ m_sQueueSample.m_counter = 0;
+ m_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE;
+ m_sQueueSample.m_bBankIndex = SAMPLEBANK_MAIN;
+ m_sQueueSample.m_bIs2D = true;
+ m_sQueueSample.m_nReleasingVolumeModificator = 10;
+ m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE);
+ m_sQueueSample.m_bVolume = m_anRandomTable[2] % 20 + 15;
+ m_sQueueSample.m_nLoopCount = 0;
+ m_sQueueSample.m_bEmittingVolume = m_sQueueSample.m_bVolume;
+ m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_POLICE_RADIO_CRACKLE);
+ m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_POLICE_RADIO_CRACKLE);
+ m_sQueueSample.m_bReleasingSoundFlag = 0;
+ m_sQueueSample.m_bReverbFlag = false;
+ m_sQueueSample.m_bOffset = 63;
+ m_sQueueSample.m_nReleasingVolumeDivider = 3;
+ m_sQueueSample.m_bRequireReflection = false;
+ AddSampleToRequestedQueue();
+}
+
+void
+cAudioManager::ServicePoliceRadio()
+{
+ int32 wantedLevel = 0; // bug?;
+ static uint32 nLastSeen = 300;
+
+ if (!m_bIsInitialised) return;
+
+ if (!m_bUserPause) {
+ bool crimeReport = SetupCrimeReport();
+ wantedLevel = FindPlayerPed()->m_pWanted->m_nWantedLevel;
+ if (!crimeReport) {
+ if (wantedLevel) {
+ if (nLastSeen) {
+ --nLastSeen;
+ } else {
+ nLastSeen = m_anRandomTable[1] % 1000 + 2000;
+ SetupSuspectLastSeenReport();
+ }
+ }
+ }
+ }
+ ServicePoliceRadioChannel(wantedLevel);
+}
+
+void
+cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel)
+{
+ bool processed = false;
+ uint32 sample;
+ int32 freq;
+
+ static int cWait = 0;
+ static bool bChannelOpen = false;
+ static uint8 bMissionAudioPhysicalPlayingStatus = 0;
+ static int32 PoliceChannelFreq = 5500;
+
+ if (!m_bIsInitialised) return;
+
+ if (m_bUserPause) {
+ if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
+ if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && bMissionAudioPhysicalPlayingStatus == 1 &&
+ SampleManager.IsStreamPlaying(1)) {
+ SampleManager.PauseStream(1, 1);
+ }
+ } else {
+ if (m_bPreviousUserPause && g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES &&
+ bMissionAudioPhysicalPlayingStatus == 1) {
+ SampleManager.PauseStream(0, 1);
+ }
+ if (m_sPoliceRadioQueue.policeChannelTimer == 0) bChannelOpen = false;
+ if (cWait) {
+ --cWait;
+ return;
+ }
+ if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && !bChannelOpen) {
+ if (g_nMissionAudioPlayingStatus) {
+ if (g_nMissionAudioPlayingStatus == 1 && !bMissionAudioPhysicalPlayingStatus &&
+ SampleManager.IsStreamPlaying(1)) {
+ bMissionAudioPhysicalPlayingStatus = 1;
+ }
+ if (bMissionAudioPhysicalPlayingStatus == 1) {
+ if (SampleManager.IsStreamPlaying(1)) {
+ DoPoliceRadioCrackle();
+ } else {
+ bMissionAudioPhysicalPlayingStatus = 2;
+ g_nMissionAudioPlayingStatus = 2;
+ g_nMissionAudioSfx = TOTAL_AUDIO_SAMPLES;
+ cWait = 30;
+ }
+ return;
+ }
+ } else if (!SampleManager.GetChannelUsedFlag(policeChannel)) {
+ SampleManager.PreloadStreamedFile(g_nMissionAudioSfx, 1);
+ SampleManager.SetStreamedVolumeAndPan(maxVolume, 63, 1, 1);
+ SampleManager.StartPreloadedStreamedFile(1);
+ g_nMissionAudioPlayingStatus = 1;
+ bMissionAudioPhysicalPlayingStatus = 0;
+ return;
+ }
+ }
+ if (bChannelOpen) DoPoliceRadioCrackle();
+ if ((g_nMissionAudioSfx == TOTAL_AUDIO_SAMPLES || g_nMissionAudioPlayingStatus != 1) &&
+ !SampleManager.GetChannelUsedFlag(policeChannel) && m_sPoliceRadioQueue.policeChannelTimer) {
+ if (m_sPoliceRadioQueue.policeChannelTimer) {
+ sample = m_sPoliceRadioQueue.crimesSamples[m_sPoliceRadioQueue.policeChannelCounterSeconds];
+ m_sPoliceRadioQueue.policeChannelTimer--;
+ m_sPoliceRadioQueue.policeChannelCounterSeconds = (m_sPoliceRadioQueue.policeChannelCounterSeconds + 1) % 60;
+ } else {
+ sample = TOTAL_AUDIO_SAMPLES;
+ }
+ if (!wantedLevel) {
+ if (gSpecialSuspectLastSeenReport) {
+ gSpecialSuspectLastSeenReport = 0;
+ } else if (((sample >= SFX_POLICE_RADIO_MESSAGE_NOISE_1) && (sample <= SFX_POLICE_RADIO_MESSAGE_NOISE_3)) || sample == TOTAL_AUDIO_SAMPLES) {
+ bChannelOpen = false;
+ processed = true;
+ }
+ }
+ if (sample == TOTAL_AUDIO_SAMPLES) {
+ if (!processed) cWait = 30;
+ } else {
+ SampleManager.InitialiseChannel(policeChannel, sample, 0);
+ switch (sample) {
+ case SFX_POLICE_RADIO_MESSAGE_NOISE_1:
+ case SFX_POLICE_RADIO_MESSAGE_NOISE_2:
+ case SFX_POLICE_RADIO_MESSAGE_NOISE_3:
+ freq = m_anRandomTable[4] % 2000 + 10025;
+ bChannelOpen = bChannelOpen == false;
+ break;
+ default: freq = SampleManager.GetSampleBaseFrequency(sample); break;
+ }
+ PoliceChannelFreq = freq;
+ SampleManager.SetChannelFrequency(policeChannel, freq);
+ SampleManager.SetChannelVolume(policeChannel, 100);
+ SampleManager.SetChannelPan(policeChannel, 63);
+ SampleManager.SetChannelLoopCount(policeChannel, 1);
+ SampleManager.SetChannelLoopPoints(policeChannel, 0, -1);
+ SampleManager.StartChannel(policeChannel);
+ }
+ if (processed) ResetPoliceRadio();
+ }
+ }
+}
+
+bool
+cAudioManager::SetupCrimeReport()
+{
+ int16 audioZoneId;
+ CZone *zone;
+ float rangeX;
+ float rangeY;
+ float halfX;
+ float halfY;
+ float quarterX;
+ float quarterY;
+ int i;
+ int32 sampleIndex;
+ bool processed = false;
+
+ if (MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE) return false;
+
+ if (60 - m_sPoliceRadioQueue.policeChannelTimer <= 9) {
+ AgeCrimes();
+ return true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
+ if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) return false;
+ audioZoneId = CTheZones::FindAudioZone(&m_sPoliceRadioQueue.crimes[i].position);
+ if (audioZoneId >= 0 && audioZoneId < NUMAUDIOZONES) {
+ zone = &CTheZones::ZoneArray[CTheZones::AudioZoneArray[audioZoneId]];
+ for (int j = 0; j < NUMAUDIOZONES; j++) {
+ if (strcmp(zone->name, ZoneSfx[j].m_aName) == 0) {
+ sampleIndex = ZoneSfx[j].m_nSampleIndex;
+ m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_WEVE_GOT);
+ m_sPoliceRadioQueue.Add(m_anRandomTable[1] % 2 + SFX_A_10_1);
+ switch (m_sPoliceRadioQueue.crimes[i].type) {
+ case CRIME_PED_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_PED; break;
+ case CRIME_COP_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_COP; break;
+ case CRIME_VEHICLE_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_STEAL_CAR; break;
+ case CRIME_DESTROYED_CESSNA: m_sPoliceRadioQueue.crimes[i].type = CRIME_SHOOT_HELI; break;
+ default: break;
+ }
+ m_sPoliceRadioQueue.Add(m_sPoliceRadioQueue.crimes[i].type + SFX_CRIME_1 - 1);
+ m_sPoliceRadioQueue.Add(SFX_IN);
+ if (sampleIndex == SFX_POLICE_RADIO_SHORESIDE_VALE &&
+ (strcmp(zone->name, SubZo2Label) == 0 || strcmp(zone->name, SubZo3Label) == 0)) {
+ m_sPoliceRadioQueue.Add(SFX_NORTH);
+ m_sPoliceRadioQueue.Add(SFX_EAST);
+ } else {
+ rangeX = zone->maxx - zone->minx;
+ rangeY = zone->maxy - zone->miny;
+ halfX = 0.5f * rangeX + zone->minx;
+ halfY = 0.5f * rangeY + zone->miny;
+ quarterX = 0.25f * rangeX;
+ quarterY = 0.25f * rangeY;
+
+ if (m_sPoliceRadioQueue.crimes[i].position.y > halfY + quarterY) {
+ m_sPoliceRadioQueue.Add(SFX_NORTH);
+ processed = true;
+ } else if (m_sPoliceRadioQueue.crimes[i].position.y < halfY - quarterY) {
+ m_sPoliceRadioQueue.Add(SFX_SOUTH);
+ processed = true;
+ }
+
+ if (m_sPoliceRadioQueue.crimes[i].position.x > halfX + quarterX)
+ m_sPoliceRadioQueue.Add(SFX_EAST);
+ else if (m_sPoliceRadioQueue.crimes[i].position.x < halfX - quarterX)
+ m_sPoliceRadioQueue.Add(SFX_WEST);
+ else if (!processed)
+ m_sPoliceRadioQueue.Add(SFX_CENTRAL);
+
+ m_sPoliceRadioQueue.Add(sampleIndex);
+ m_sPoliceRadioQueue.Add(m_anRandomTable[2] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
+ }
+ break;
+ }
+ }
+ }
+ m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
+ AgeCrimes();
+ return true;
+}
+
+void
+cAudioManager::SetupSuspectLastSeenReport()
+{
+ CVehicle *veh;
+ uint8 color1;
+ int32 main_color;
+ int32 sample;
+
+ int32 color_pre_modifier;
+ int32 color_post_modifier;
+
+ const int32 gCarColourTable[][3] = {
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLACK, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_WHITE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_BRIGHT, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, SFX_POLICE_RADIO_GREY},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+#else
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+#endif
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_RED, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+#else
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+#endif
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_ORANGE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+#else
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+#endif
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_YELLOW, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+#else
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+#endif
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_GREEN, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+#else
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+#endif
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, SFX_POLICE_RADIO_BLUE},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+#else
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+#endif
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, SFX_POLICE_RADIO_GREY},
+#else
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+#endif
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_PURPLE, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+#else
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+#endif
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+#ifdef FIX_BUGS
+ {SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+#else
+ {TOTAL_AUDIO_SAMPLES, SFX_POLICE_RADIO_SILVER, TOTAL_AUDIO_SAMPLES},
+#endif
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_LIGHT, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES},
+ {SFX_POLICE_RADIO_DARK, TOTAL_AUDIO_SAMPLES, TOTAL_AUDIO_SAMPLES}
+ };
+
+ if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
+ veh = FindPlayerVehicle();
+ if (veh != nil) {
+ if (60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
+ color1 = veh->m_currentColour1;
+ if (color1 >= ARRAY_SIZE(gCarColourTable)) {
+ debug("\n *** UNKNOWN CAR COLOUR %d *** ", color1);
+ } else {
+ main_color = gCarColourTable[color1][1];
+ color_pre_modifier = gCarColourTable[color1][0];
+ color_post_modifier = gCarColourTable[color1][2];
+ switch (veh->m_modelIndex) {
+#ifdef FIX_BUGS
+ case MI_COLUMB:
+ main_color = SFX_POLICE_RADIO_BLUE;
+ color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
+#endif
+ case MI_LANDSTAL:
+ case MI_BLISTA: sample = SFX_POLICE_RADIO_CRUISER; break;
+#ifdef FIX_BUGS
+ case MI_YARDIE:
+ color_pre_modifier = TOTAL_AUDIO_SAMPLES;
+ main_color = SFX_POLICE_RADIO_RED;
+ color_post_modifier = SFX_POLICE_RADIO_YELLOW;
+ sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
+ case MI_DIABLOS:
+ main_color = SFX_POLICE_RADIO_BLACK;
+#endif
+ case MI_IDAHO:
+ case MI_STALLION: sample = SFX_POLICE_RADIO_CONVERTIBLE; break;
+#ifdef FIX_BUGS
+ case MI_YAKUZA:
+ color_pre_modifier = TOTAL_AUDIO_SAMPLES;
+ main_color = SFX_POLICE_RADIO_SILVER;
+ color_post_modifier = SFX_POLICE_RADIO_RED;
+#endif
+ case MI_STINGER:
+ case MI_INFERNUS:
+ case MI_CHEETAH:
+ case MI_BANSHEE: sample = SFX_POLICE_RADIO_SPORTS_CAR; break;
+#ifdef FIX_BUGS
+ case MI_MAFIA:
+ color_pre_modifier = color_post_modifier = TOTAL_AUDIO_SAMPLES;
+ main_color = SFX_POLICE_RADIO_GREY;
+ case MI_KURUMA:
+#endif
+ case MI_PEREN:
+ case MI_SENTINEL:
+ case MI_FBICAR: sample = SFX_POLICE_RADIO_SALOON; break;
+ case MI_PATRIOT:
+ case MI_BOBCAT: sample = SFX_POLICE_RADIO_PICKUP; break;
+ case MI_FIRETRUCK: sample = SFX_POLICE_RADIO_FIRE_TRUCK; break;
+#ifdef FIX_BUGS
+ case MI_LINERUN:
+ case MI_FLATBED:
+#endif
+ case MI_TRASH:
+ case MI_BARRACKS: sample = SFX_POLICE_RADIO_TRUCK; break;
+ case MI_STRETCH: sample = SFX_POLICE_RADIO_LIMO; break;
+#ifdef FIX_BUGS
+ case MI_CORPSE:
+#endif
+ case MI_MANANA:
+ case MI_ESPERANT: sample = SFX_POLICE_RADIO_2_DOOR; break;
+#ifdef FIX_BUGS
+ case MI_HOODS:
+ color_pre_modifier = TOTAL_AUDIO_SAMPLES;
+ main_color = SFX_POLICE_RADIO_BLUE;
+ color_post_modifier = SFX_POLICE_RADIO_GREEN;
+ case MI_BELLYUP:
+ case MI_YANKEE:
+ case MI_TOYZ:
+ case MI_MRWONGS:
+ case MI_PANLANT:
+#endif
+ case MI_PONY:
+ case MI_MULE:
+ case MI_MOONBEAM:
+ case MI_ENFORCER:
+ case MI_SECURICA:
+ case MI_RUMPO: sample = SFX_POLICE_RADIO_VAN; break;
+ case MI_AMBULAN: sample = SFX_POLICE_RADIO_AMBULANCE; break;
+ case MI_TAXI:
+ case MI_CABBIE:
+ case MI_BORGNINE: sample = SFX_POLICE_RADIO_TAXI; break;
+ case MI_MRWHOOP:
+ sample = SFX_POLICE_RADIO_ICE_CREAM_VAN;
+ break;
+ case MI_BFINJECT: sample = SFX_POLICE_RADIO_BUGGY; break;
+ case MI_POLICE: sample = SFX_POLICE_RADIO_POLICE_CAR; break;
+#ifdef FIX_BUGS
+ case MI_SPEEDER:
+ case MI_REEFER:
+ case MI_GHOST:
+#endif
+ case MI_PREDATOR: sample = SFX_POLICE_RADIO_BOAT; break;
+ case MI_BUS:
+ case MI_COACH: sample = SFX_POLICE_RADIO_BUS; break;
+ case MI_RHINO:
+ sample = SFX_POLICE_RADIO_TANK;
+ main_color = TOTAL_AUDIO_SAMPLES;
+ color_post_modifier = TOTAL_AUDIO_SAMPLES;
+ break;
+ case MI_TRAIN:
+ sample = SFX_POLICE_RADIO_SUBWAY_CAR;
+ main_color = TOTAL_AUDIO_SAMPLES;
+ color_post_modifier = TOTAL_AUDIO_SAMPLES;
+
+ break;
+ default:
+ debug("\n *** UNKNOWN CAR MODEL INDEX %d *** ", veh->m_modelIndex);
+ return;
+ }
+ m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
+ if (m_anRandomTable[3] % 2)
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
+#ifdef FIX_BUGS
+ if (main_color == SFX_POLICE_RADIO_ORANGE && color_pre_modifier == TOTAL_AUDIO_SAMPLES)
+#else
+ if (main_color == SFX_POLICE_RADIO_ORANGE)
+#endif
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_AN);
+ else
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_A);
+ if (color_pre_modifier != TOTAL_AUDIO_SAMPLES)
+ m_sPoliceRadioQueue.Add(color_pre_modifier);
+ if (main_color != TOTAL_AUDIO_SAMPLES)
+ m_sPoliceRadioQueue.Add(main_color);
+ if (color_post_modifier != TOTAL_AUDIO_SAMPLES)
+ m_sPoliceRadioQueue.Add(color_post_modifier);
+ m_sPoliceRadioQueue.Add(sample);
+ m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
+ }
+ }
+ } else if (60 - m_sPoliceRadioQueue.policeChannelTimer > 4) {
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_ON_FOOT);
+ m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
+ }
+ }
+}
+
+
+
+void
+cAudioManager::ReportCrime(int32 type, const CVector *pos)
+{
+ int32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes);
+ if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 &&
+ (type > CRIME_NONE || type < NUM_CRIME_TYPES) && m_FrameCounter >= gMinTimeToNextReport[type]) {
+ for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
+ if (m_sPoliceRadioQueue.crimes[i].type) {
+ if (m_sPoliceRadioQueue.crimes[i].type == type) {
+ m_sPoliceRadioQueue.crimes[i].position = *pos;
+ m_sPoliceRadioQueue.crimes[i].timer = 0;
+ return;
+ }
+ } else {
+ lastCrime = i;
+ }
+ }
+
+ if (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) {
+ m_sPoliceRadioQueue.crimes[lastCrime].type = type;
+ m_sPoliceRadioQueue.crimes[lastCrime].position = *pos;
+ m_sPoliceRadioQueue.crimes[lastCrime].timer = 0;
+ gMinTimeToNextReport[type] = m_FrameCounter + 500;
+ }
+ }
+}
+
+void
+cAudioManager::PlaySuspectLastSeen(float x, float y, float z)
+{
+ int16 audioZone;
+ CZone *zone;
+ float rangeX;
+ float rangeY;
+ float halfX;
+ float halfY;
+ float quarterX;
+ float quarterY;
+ int32 sample;
+ bool processed = false;
+ CVector vec = CVector(x, y, z);
+
+ if (!m_bIsInitialised) return;
+
+ if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && 60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
+ audioZone = CTheZones::FindAudioZone(&vec);
+ if (audioZone >= 0 && audioZone < NUMAUDIOZONES) {
+ zone = &CTheZones::ZoneArray[CTheZones::AudioZoneArray[audioZone]];
+ for (int i = 0; i < NUMAUDIOZONES; i++) {
+ if (strcmp(zone->name, ZoneSfx[i].m_aName) == 0) {
+ sample = ZoneSfx[i].m_nSampleIndex;
+ m_sPoliceRadioQueue.Add(m_anRandomTable[4] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
+ m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
+ m_sPoliceRadioQueue.Add(SFX_IN);
+ if (sample == SFX_POLICE_RADIO_SHORESIDE_VALE &&
+ (strcmp(zone->name, SubZo2Label) == 0 ||
+ strcmp(zone->name, SubZo3Label) == 0)) {
+ m_sPoliceRadioQueue.Add(SFX_NORTH);
+ m_sPoliceRadioQueue.Add(SFX_EAST);
+ } else {
+ rangeX = zone->maxx - zone->minx;
+ rangeY = zone->maxy - zone->miny;
+ halfX = 0.5f * rangeX + zone->minx;
+ halfY = 0.5f * rangeY + zone->miny;
+ quarterX = 0.25f * rangeX;
+ quarterY = 0.25f * rangeY;
+
+ if (vec.y > halfY + quarterY) {
+ m_sPoliceRadioQueue.Add(SFX_NORTH);
+ processed = true;
+ } else if (vec.y < halfY - quarterY) {
+ m_sPoliceRadioQueue.Add(SFX_SOUTH);
+ processed = true;
+ }
+
+ if (vec.x > halfX + quarterX)
+ m_sPoliceRadioQueue.Add(SFX_EAST);
+ else if (vec.x < halfX - quarterX)
+ m_sPoliceRadioQueue.Add(SFX_WEST);
+ else if (!processed)
+ m_sPoliceRadioQueue.Add(SFX_CENTRAL);
+ }
+ m_sPoliceRadioQueue.Add(sample);
+ m_sPoliceRadioQueue.Add(m_anRandomTable[2] % 3 + SFX_POLICE_RADIO_MESSAGE_NOISE_1);
+ m_sPoliceRadioQueue.Add(TOTAL_AUDIO_SAMPLES);
+ gSpecialSuspectLastSeenReport = true;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void
+cAudioManager::AgeCrimes()
+{
+ for (uint8 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
+ if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE) {
+ if (++m_sPoliceRadioQueue.crimes[i].timer > 1500) m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
+ }
+ }
+}
+
+STARTPATCHES
+InjectHook(0x580AF0, &cAudioManager::AgeCrimes, PATCH_JUMP);
+InjectHook(0x57F060, &cAudioManager::DoPoliceRadioCrackle, PATCH_JUMP);
+InjectHook(0x57F050, &cAudioManager::GetMissionScriptPoliceAudioPlayingStatus, PATCH_JUMP);
+InjectHook(0x57EEC0, &cAudioManager::InitialisePoliceRadio, PATCH_JUMP);
+InjectHook(0x57EAC0, &cAudioManager::InitialisePoliceRadioZones, PATCH_JUMP);
+InjectHook(0x580500, &cAudioManager::PlaySuspectLastSeen, PATCH_JUMP);
+InjectHook(0x5803D0, &cAudioManager::ReportCrime, PATCH_JUMP);
+InjectHook(0x57EFF0, &cAudioManager::ResetPoliceRadio, PATCH_JUMP);
+InjectHook(0x57F110, &cAudioManager::ServicePoliceRadio, PATCH_JUMP);
+InjectHook(0x57F1B0, &cAudioManager::ServicePoliceRadioChannel, PATCH_JUMP);
+InjectHook(0x57F020, &cAudioManager::SetMissionScriptPoliceAudio, PATCH_JUMP);
+InjectHook(0x57F5B0, &cAudioManager::SetupCrimeReport, PATCH_JUMP);
+InjectHook(0x57FCC0, &cAudioManager::SetupSuspectLastSeenReport, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/audio/PoliceRadio.h b/src/audio/PoliceRadio.h
index 4c7030f1..0f351f52 100644
--- a/src/audio/PoliceRadio.h
+++ b/src/audio/PoliceRadio.h
@@ -1,46 +1,46 @@
-#pragma once
-
-#include "Wanted.h"
-
-struct cAMCrime {
- int32 type;
- CVector position;
- uint16 timer;
-
- cAMCrime()
- {
- type = CRIME_NONE;
- position = CVector(0.0f, 0.0f, 0.0f);
- timer = 0;
- }
-};
-
-static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error ");
-
-class cPoliceRadioQueue
-{
-public:
- int32 crimesSamples[60];
- uint8 policeChannelTimer;
- uint8 policeChannelTimerSeconds;
- uint8 policeChannelCounterSeconds;
- cAMCrime crimes[10];
-
- cPoliceRadioQueue()
- {
- policeChannelTimerSeconds = 0;
- policeChannelCounterSeconds = 0;
- policeChannelTimer = 0;
- }
-
- void Add(uint32 sample)
- {
- if (policeChannelTimer != 60) {
- crimesSamples[policeChannelTimerSeconds] = sample;
- policeChannelTimer++;
- policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
- }
- }
-};
-
+#pragma once
+
+#include "Wanted.h"
+
+struct cAMCrime {
+ int32 type;
+ CVector position;
+ uint16 timer;
+
+ cAMCrime()
+ {
+ type = CRIME_NONE;
+ position = CVector(0.0f, 0.0f, 0.0f);
+ timer = 0;
+ }
+};
+
+static_assert(sizeof(cAMCrime) == 20, "cAMCrime: error ");
+
+class cPoliceRadioQueue
+{
+public:
+ int32 crimesSamples[60];
+ uint8 policeChannelTimer;
+ uint8 policeChannelTimerSeconds;
+ uint8 policeChannelCounterSeconds;
+ cAMCrime crimes[10];
+
+ cPoliceRadioQueue()
+ {
+ policeChannelTimerSeconds = 0;
+ policeChannelCounterSeconds = 0;
+ policeChannelTimer = 0;
+ }
+
+ void Add(uint32 sample)
+ {
+ if (policeChannelTimer != 60) {
+ crimesSamples[policeChannelTimerSeconds] = sample;
+ policeChannelTimer++;
+ policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
+ }
+ }
+};
+
static_assert(sizeof(cPoliceRadioQueue) == 444, "cPoliceRadioQueue: error "); \ No newline at end of file
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index 3174a253..cdcfbba6 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -90,7 +90,7 @@ uint32 (&aCarsToKeepTime)[MAX_CARS_TO_KEEP] = *(uint32(*)[MAX_CARS_TO_KEEP])*(ui
void
CCarCtrl::GenerateRandomCars()
{
- if (CCutsceneMgr::IsCutsceneProcessing())
+ if (CCutsceneMgr::IsRunning())
return;
if (NumRandomCars < 30){
if (CountDownToCarsAtStart == 0){
diff --git a/src/control/CarGen.cpp b/src/control/CarGen.cpp
index 49a96f50..721ac35a 100644
--- a/src/control/CarGen.cpp
+++ b/src/control/CarGen.cpp
@@ -242,7 +242,7 @@ void CCarGenerator::Load(uint8 *&buffer)
void CTheCarGenerators::Process()
{
- if (FindPlayerTrain() || CCutsceneMgr::IsRunning())
+ if (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing())
return;
if (++CTheCarGenerators::ProcessCounter == 4)
CTheCarGenerators::ProcessCounter = 0;
diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp
index 0abae7d6..8e0ea02d 100644
--- a/src/control/GameLogic.cpp
+++ b/src/control/GameLogic.cpp
@@ -1,294 +1,294 @@
#include "common.h"
#include "patcher.h"
-#include "GameLogic.h"
-#include "Clock.h"
-#include "Stats.h"
-#include "Pickups.h"
-#include "Timer.h"
-#include "Streaming.h"
-#include "CutsceneMgr.h"
-#include "World.h"
-#include "PlayerPed.h"
-#include "Wanted.h"
-#include "Camera.h"
-#include "Messages.h"
-#include "CarCtrl.h"
-#include "Restart.h"
-#include "Pad.h"
-#include "References.h"
-#include "Fire.h"
-#include "Script.h"
-#include "Garages.h"
-
-uint8 CGameLogic::ActivePlayers; // 0x95CD5E
-
-void
-CGameLogic::InitAtStartOfGame()
-{
- ActivePlayers = 1;
-}
-
-void
-CGameLogic::PassTime(uint32 time)
-{
- int32 minutes, hours, days;
-
- minutes = time + CClock::GetMinutes();
- hours = CClock::GetHours();
-
- for (; minutes >= 60; minutes -= 60)
- hours++;
-
- if (hours > 23) {
- days = CStats::DaysPassed;
- for (; hours >= 24; hours -= 24)
- days++;
- CStats::DaysPassed = days;
- }
-
- CClock::SetGameClock(hours, minutes);
- CPickups::PassTime(time * 1000);
-}
-
-void
-CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
-{
- CTimer::Stop();
- CStreaming::FlushRequestList();
- CStreaming::DeleteRwObjectsAfterDeath(pos);
- CStreaming::RemoveUnusedModelsInLoadedList();
- CGame::DrasticTidyUpMemory(true);
- CStreaming::LoadScene(pos);
- CTimer::Update();
-}
-
-void
-CGameLogic::Update()
-{
- CVector vecRestartPos;
- float fRestartFloat;
-
- if (CCutsceneMgr::IsCutsceneProcessing()) return;
-
- CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
- switch (pPlayerInfo.m_WBState) {
- case WBSTATE_PLAYING:
- if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
- pPlayerInfo.m_pPed->ClearAdrenaline();
- pPlayerInfo.KillPlayer();
- }
- if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
- pPlayerInfo.m_pPed->ClearAdrenaline();
- pPlayerInfo.ArrestPlayer();
- }
- break;
- case WBSTATE_WASTED:
- if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
- TheCamera.SetFadeColour(200, 200, 200);
- TheCamera.Fade(2.0f, FADE_OUT);
- }
-
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
- pPlayerInfo.m_WBState = WBSTATE_PLAYING;
- if (pPlayerInfo.m_bGetOutOfHospitalFree) {
- pPlayerInfo.m_bGetOutOfHospitalFree = false;
- } else {
- pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
- pPlayerInfo.m_pPed->ClearWeapons();
- }
-
- if (pPlayerInfo.m_pPed->bInVehicle) {
- CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
- if (pVehicle != nil) {
- if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
- pVehicle->pDriver = nil;
- if (pVehicle->m_status != STATUS_WRECKED)
- pVehicle->m_status = STATUS_ABANDONED;
- } else
- pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
- }
- }
- CEventList::Initialise();
- CMessages::ClearMessages();
- CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
- CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
- CRestart::OverrideHospitalLevel = LEVEL_NONE;
- CRestart::OverridePoliceStationLevel = LEVEL_NONE;
- PassTime(720);
- RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
- SortOutStreamingAndMemory(pPlayerInfo.GetPos());
- TheCamera.m_fCamShakeForce = 0.0f;
- TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
- CPad::GetPad(0)->StopShaking(0);
- CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
- CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
- if (CRestart::bFadeInAfterNextDeath) {
- TheCamera.SetFadeColour(200, 200, 200);
- TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextDeath = true;
- }
- break;
- case WBSTATE_BUSTED:
- if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(2.0f, FADE_OUT);
- }
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
- pPlayerInfo.m_WBState = WBSTATE_PLAYING;
- int takeMoney;
-
- switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
- case 0:
- case 1:
- takeMoney = 100;
- break;
- case 2:
- takeMoney = 200;
- break;
- case 3:
- takeMoney = 400;
- break;
- case 4:
- takeMoney = 600;
- break;
- case 5:
- takeMoney = 900;
- break;
- case 6:
- takeMoney = 1500;
- break;
- }
- if (pPlayerInfo.m_bGetOutOfJailFree) {
- pPlayerInfo.m_bGetOutOfJailFree = false;
- } else {
- pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
- pPlayerInfo.m_pPed->ClearWeapons();
- }
-
- if (pPlayerInfo.m_pPed->bInVehicle) {
- CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
- if (pVehicle != nil) {
- if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
- pVehicle->pDriver = nil;
- if (pVehicle->m_status != STATUS_WRECKED)
- pVehicle->m_status = STATUS_ABANDONED;
- }
- else
- pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
- }
- }
- CEventList::Initialise();
- CMessages::ClearMessages();
- CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
- CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
- CRestart::OverrideHospitalLevel = LEVEL_NONE;
- CRestart::OverridePoliceStationLevel = LEVEL_NONE;
- PassTime(720);
- RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
- pPlayerInfo.m_pPed->ClearWeapons();
- SortOutStreamingAndMemory(pPlayerInfo.GetPos());
- TheCamera.m_fCamShakeForce = 0.0f;
- TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
- CPad::GetPad(0)->StopShaking(0);
- CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
- CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
- if (CRestart::bFadeInAfterNextArrest) {
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextArrest = true;
- }
- break;
- case WBSTATE_FAILED_CRITICAL_MISSION:
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(2.0f, FADE_OUT);
- }
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
- pPlayerInfo.m_WBState = WBSTATE_PLAYING;
- if (pPlayerInfo.m_pPed->bInVehicle) {
- CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
- if (pVehicle != nil) {
- if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
- pVehicle->pDriver = nil;
- if (pVehicle->m_status != STATUS_WRECKED)
- pVehicle->m_status = STATUS_ABANDONED;
- } else
- pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
- }
- }
- CEventList::Initialise();
- CMessages::ClearMessages();
- CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
- CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
- CRestart::OverridePoliceStationLevel = LEVEL_NONE;
- CRestart::OverrideHospitalLevel = LEVEL_NONE;
- RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
- SortOutStreamingAndMemory(pPlayerInfo.GetPos());
- TheCamera.m_fCamShakeForce = 0.0f;
- TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
- CPad::GetPad(0)->StopShaking(0);
- CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
- CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(4.0f, FADE_IN);
- }
- break;
- case 4:
- return;
- }
-}
-
-void
-CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
-{
- pPlayerPed->m_fHealth = 100.0f;
- pPlayerPed->m_fArmour = 0.0f;
- pPlayerPed->bIsVisible = true;
- pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
- pPlayerPed->bDoBloodyFootprints = false;
- pPlayerPed->ClearAdrenaline();
- pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
- if (pPlayerPed->m_pFire)
- pPlayerPed->m_pFire->Extinguish();
- pPlayerPed->bInVehicle = false;
- pPlayerPed->m_pMyVehicle = nil;
- pPlayerPed->m_pVehicleAnim = nil;
- pPlayerPed->m_pWanted->Reset();
- pPlayerPed->RestartNonPartialAnims();
- pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
- pPlayerPed->bRemoveFromWorld = false;
- pPlayerPed->ClearWeaponTarget();
- pPlayerPed->SetInitialState();
- CCarCtrl::ClearInterestingVehicleList();
-
- pos.z += 1.0f;
- pPlayerPed->Teleport(pos);
- pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
-
- pPlayerPed->m_fRotationCur = DEGTORAD(angle);
- pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
- pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
- CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
- CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
- pPlayerPed->RestoreHeadingRate();
- TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
- CReferences::RemoveReferencesToPlayer();
- CGarages::PlayerArrestedOrDied();
- CStats::CheckPointReachedUnsuccessfully();
- CWorld::Remove(pPlayerPed);
- CWorld::Add(pPlayerPed);
-}
-
+#include "GameLogic.h"
+#include "Clock.h"
+#include "Stats.h"
+#include "Pickups.h"
+#include "Timer.h"
+#include "Streaming.h"
+#include "CutsceneMgr.h"
+#include "World.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "Camera.h"
+#include "Messages.h"
+#include "CarCtrl.h"
+#include "Restart.h"
+#include "Pad.h"
+#include "References.h"
+#include "Fire.h"
+#include "Script.h"
+#include "Garages.h"
+
+uint8 CGameLogic::ActivePlayers; // 0x95CD5E
+
+void
+CGameLogic::InitAtStartOfGame()
+{
+ ActivePlayers = 1;
+}
+
+void
+CGameLogic::PassTime(uint32 time)
+{
+ int32 minutes, hours, days;
+
+ minutes = time + CClock::GetMinutes();
+ hours = CClock::GetHours();
+
+ for (; minutes >= 60; minutes -= 60)
+ hours++;
+
+ if (hours > 23) {
+ days = CStats::DaysPassed;
+ for (; hours >= 24; hours -= 24)
+ days++;
+ CStats::DaysPassed = days;
+ }
+
+ CClock::SetGameClock(hours, minutes);
+ CPickups::PassTime(time * 1000);
+}
+
+void
+CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
+{
+ CTimer::Stop();
+ CStreaming::FlushRequestList();
+ CStreaming::DeleteRwObjectsAfterDeath(pos);
+ CStreaming::RemoveUnusedModelsInLoadedList();
+ CGame::DrasticTidyUpMemory(true);
+ CStreaming::LoadScene(pos);
+ CTimer::Update();
+}
+
+void
+CGameLogic::Update()
+{
+ CVector vecRestartPos;
+ float fRestartFloat;
+
+ if (CCutsceneMgr::IsCutsceneProcessing()) return;
+
+ CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
+ switch (pPlayerInfo.m_WBState) {
+ case WBSTATE_PLAYING:
+ if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
+ pPlayerInfo.m_pPed->ClearAdrenaline();
+ pPlayerInfo.KillPlayer();
+ }
+ if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
+ pPlayerInfo.m_pPed->ClearAdrenaline();
+ pPlayerInfo.ArrestPlayer();
+ }
+ break;
+ case WBSTATE_WASTED:
+ if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
+ TheCamera.SetFadeColour(200, 200, 200);
+ TheCamera.Fade(2.0f, FADE_OUT);
+ }
+
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
+ pPlayerInfo.m_WBState = WBSTATE_PLAYING;
+ if (pPlayerInfo.m_bGetOutOfHospitalFree) {
+ pPlayerInfo.m_bGetOutOfHospitalFree = false;
+ } else {
+ pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
+ pPlayerInfo.m_pPed->ClearWeapons();
+ }
+
+ if (pPlayerInfo.m_pPed->bInVehicle) {
+ CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
+ if (pVehicle != nil) {
+ if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
+ pVehicle->pDriver = nil;
+ if (pVehicle->m_status != STATUS_WRECKED)
+ pVehicle->m_status = STATUS_ABANDONED;
+ } else
+ pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
+ }
+ }
+ CEventList::Initialise();
+ CMessages::ClearMessages();
+ CCarCtrl::ClearInterestingVehicleList();
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
+ CRestart::OverrideHospitalLevel = LEVEL_NONE;
+ CRestart::OverridePoliceStationLevel = LEVEL_NONE;
+ PassTime(720);
+ RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ SortOutStreamingAndMemory(pPlayerInfo.GetPos());
+ TheCamera.m_fCamShakeForce = 0.0f;
+ TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
+ CPad::GetPad(0)->StopShaking(0);
+ CReferences::RemoveReferencesToPlayer();
+ CCarCtrl::CountDownToCarsAtStart = 2;
+ CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
+ if (CRestart::bFadeInAfterNextDeath) {
+ TheCamera.SetFadeColour(200, 200, 200);
+ TheCamera.Fade(4.0f, FADE_IN);
+ } else CRestart::bFadeInAfterNextDeath = true;
+ }
+ break;
+ case WBSTATE_BUSTED:
+ if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(2.0f, FADE_OUT);
+ }
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
+ pPlayerInfo.m_WBState = WBSTATE_PLAYING;
+ int takeMoney;
+
+ switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
+ case 0:
+ case 1:
+ takeMoney = 100;
+ break;
+ case 2:
+ takeMoney = 200;
+ break;
+ case 3:
+ takeMoney = 400;
+ break;
+ case 4:
+ takeMoney = 600;
+ break;
+ case 5:
+ takeMoney = 900;
+ break;
+ case 6:
+ takeMoney = 1500;
+ break;
+ }
+ if (pPlayerInfo.m_bGetOutOfJailFree) {
+ pPlayerInfo.m_bGetOutOfJailFree = false;
+ } else {
+ pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
+ pPlayerInfo.m_pPed->ClearWeapons();
+ }
+
+ if (pPlayerInfo.m_pPed->bInVehicle) {
+ CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
+ if (pVehicle != nil) {
+ if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
+ pVehicle->pDriver = nil;
+ if (pVehicle->m_status != STATUS_WRECKED)
+ pVehicle->m_status = STATUS_ABANDONED;
+ }
+ else
+ pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
+ }
+ }
+ CEventList::Initialise();
+ CMessages::ClearMessages();
+ CCarCtrl::ClearInterestingVehicleList();
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
+ CRestart::OverrideHospitalLevel = LEVEL_NONE;
+ CRestart::OverridePoliceStationLevel = LEVEL_NONE;
+ PassTime(720);
+ RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ pPlayerInfo.m_pPed->ClearWeapons();
+ SortOutStreamingAndMemory(pPlayerInfo.GetPos());
+ TheCamera.m_fCamShakeForce = 0.0f;
+ TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
+ CPad::GetPad(0)->StopShaking(0);
+ CReferences::RemoveReferencesToPlayer();
+ CCarCtrl::CountDownToCarsAtStart = 2;
+ CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
+ if (CRestart::bFadeInAfterNextArrest) {
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(4.0f, FADE_IN);
+ } else CRestart::bFadeInAfterNextArrest = true;
+ }
+ break;
+ case WBSTATE_FAILED_CRITICAL_MISSION:
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(2.0f, FADE_OUT);
+ }
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
+ pPlayerInfo.m_WBState = WBSTATE_PLAYING;
+ if (pPlayerInfo.m_pPed->bInVehicle) {
+ CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
+ if (pVehicle != nil) {
+ if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
+ pVehicle->pDriver = nil;
+ if (pVehicle->m_status != STATUS_WRECKED)
+ pVehicle->m_status = STATUS_ABANDONED;
+ } else
+ pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
+ }
+ }
+ CEventList::Initialise();
+ CMessages::ClearMessages();
+ CCarCtrl::ClearInterestingVehicleList();
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
+ CRestart::OverridePoliceStationLevel = LEVEL_NONE;
+ CRestart::OverrideHospitalLevel = LEVEL_NONE;
+ RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ SortOutStreamingAndMemory(pPlayerInfo.GetPos());
+ TheCamera.m_fCamShakeForce = 0.0f;
+ TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
+ CPad::GetPad(0)->StopShaking(0);
+ CReferences::RemoveReferencesToPlayer();
+ CCarCtrl::CountDownToCarsAtStart = 2;
+ CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(4.0f, FADE_IN);
+ }
+ break;
+ case 4:
+ return;
+ }
+}
+
+void
+CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
+{
+ pPlayerPed->m_fHealth = 100.0f;
+ pPlayerPed->m_fArmour = 0.0f;
+ pPlayerPed->bIsVisible = true;
+ pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
+ pPlayerPed->bDoBloodyFootprints = false;
+ pPlayerPed->ClearAdrenaline();
+ pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
+ if (pPlayerPed->m_pFire)
+ pPlayerPed->m_pFire->Extinguish();
+ pPlayerPed->bInVehicle = false;
+ pPlayerPed->m_pMyVehicle = nil;
+ pPlayerPed->m_pVehicleAnim = nil;
+ pPlayerPed->m_pWanted->Reset();
+ pPlayerPed->RestartNonPartialAnims();
+ pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
+ pPlayerPed->bRemoveFromWorld = false;
+ pPlayerPed->ClearWeaponTarget();
+ pPlayerPed->SetInitialState();
+ CCarCtrl::ClearInterestingVehicleList();
+
+ pos.z += 1.0f;
+ pPlayerPed->Teleport(pos);
+ pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
+
+ pPlayerPed->m_fRotationCur = DEGTORAD(angle);
+ pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
+ pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
+ CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
+ CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
+ pPlayerPed->RestoreHeadingRate();
+ TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
+ CReferences::RemoveReferencesToPlayer();
+ CGarages::PlayerArrestedOrDied();
+ CStats::CheckPointReachedUnsuccessfully();
+ CWorld::Remove(pPlayerPed);
+ CWorld::Add(pPlayerPed);
+}
+
STARTPATCHES
InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP);
InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP);
InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP);
InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP);
- InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
+ InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/control/GameLogic.h b/src/control/GameLogic.h
index db626558..43e244a3 100644
--- a/src/control/GameLogic.h
+++ b/src/control/GameLogic.h
@@ -1,13 +1,13 @@
-#pragma once
-
-class CGameLogic
-{
-public:
- static void InitAtStartOfGame();
- static void PassTime(uint32 time);
- static void SortOutStreamingAndMemory(const CVector &pos);
- static void Update();
- static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
-
- static uint8 ActivePlayers;
+#pragma once
+
+class CGameLogic
+{
+public:
+ static void InitAtStartOfGame();
+ static void PassTime(uint32 time);
+ static void SortOutStreamingAndMemory(const CVector &pos);
+ static void Update();
+ static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
+
+ static uint8 ActivePlayers;
}; \ No newline at end of file
diff --git a/src/control/Gangs.cpp b/src/control/Gangs.cpp
index ac32ad98..57d9c67e 100644
--- a/src/control/Gangs.cpp
+++ b/src/control/Gangs.cpp
@@ -1,7 +1,7 @@
#include "common.h"
#include "patcher.h"
#include "ModelIndices.h"
-#include "Gangs.h"
+#include "Gangs.h"
#include "Weapon.h"
//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
@@ -57,20 +57,20 @@ void CGangs::SaveAllGangData(uint8 *buf, uint32 *size)
{
INITSAVEBUF
- *size = SAVE_HEADER_SIZE + sizeof(Gang);
+ *size = SAVE_HEADER_SIZE + sizeof(Gang);
WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE);
- for (int i = 0; i < NUM_GANGS; i++)
- WriteSaveBuf(buf, Gang[i]);
-
+ for (int i = 0; i < NUM_GANGS; i++)
+ WriteSaveBuf(buf, Gang[i]);
+
VALIDATESAVEBUF(*size);
}
void CGangs::LoadAllGangData(uint8 *buf, uint32 size)
{
- Initialise();
-
-INITSAVEBUF
- // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
+ Initialise();
+
+INITSAVEBUF
+ // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_GANGS; i++)
diff --git a/src/control/OnscreenTimer.h b/src/control/OnscreenTimer.h
index b1e0e622..fb139266 100644
--- a/src/control/OnscreenTimer.h
+++ b/src/control/OnscreenTimer.h
@@ -1,49 +1,49 @@
-#pragma once
-
-enum
-{
- COUNTER_DISPLAY_NUMBER,
- COUNTER_DISPLAY_BAR,
-};
-
-class COnscreenTimerEntry
-{
-public:
- uint32 m_nTimerOffset;
- uint32 m_nCounterOffset;
- char m_aTimerText[10];
- char m_aCounterText[10];
- uint16 m_nType;
- char m_bCounterBuffer[42];
- char m_bTimerBuffer[42];
- bool m_bTimerProcessed;
- bool m_bCounterProcessed;
-
- void Process();
- bool ProcessForDisplay();
-
- void ProcessForDisplayClock();
- void ProcessForDisplayCounter();
-};
-
-static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
-
-class COnscreenTimer
-{
-public:
- COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
- bool m_bProcessed;
- bool m_bDisabled;
-
- void Init();
- void Process();
- void ProcessForDisplay();
-
- void ClearCounter(uint32 offset);
- void ClearClock(uint32 offset);
-
- void AddCounter(uint32 offset, uint16 type, char* text);
- void AddClock(uint32 offset, char* text);
-};
-
+#pragma once
+
+enum
+{
+ COUNTER_DISPLAY_NUMBER,
+ COUNTER_DISPLAY_BAR,
+};
+
+class COnscreenTimerEntry
+{
+public:
+ uint32 m_nTimerOffset;
+ uint32 m_nCounterOffset;
+ char m_aTimerText[10];
+ char m_aCounterText[10];
+ uint16 m_nType;
+ char m_bCounterBuffer[42];
+ char m_bTimerBuffer[42];
+ bool m_bTimerProcessed;
+ bool m_bCounterProcessed;
+
+ void Process();
+ bool ProcessForDisplay();
+
+ void ProcessForDisplayClock();
+ void ProcessForDisplayCounter();
+};
+
+static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
+
+class COnscreenTimer
+{
+public:
+ COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
+ bool m_bProcessed;
+ bool m_bDisabled;
+
+ void Init();
+ void Process();
+ void ProcessForDisplay();
+
+ void ClearCounter(uint32 offset);
+ void ClearClock(uint32 offset);
+
+ void AddCounter(uint32 offset, uint16 type, char* text);
+ void AddClock(uint32 offset, char* text);
+};
+
static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error"); \ No newline at end of file
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 3e3c2a48..774abd8c 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -1,1049 +1,1049 @@
-#include "common.h"
-#include "patcher.h"
-#include "main.h"
-
-#include "Camera.h"
-#include "Coronas.h"
-#include "Darkel.h"
-#include "Entity.h"
-#include "Explosion.h"
-#include "Font.h"
-#include "Garages.h"
-#include "General.h"
-#include "ModelIndices.h"
-#include "Object.h"
-#include "Pad.h"
-#include "Pickups.h"
-#include "PlayerPed.h"
-#include "Wanted.h"
-#include "DMAudio.h"
-#include "Fire.h"
-#include "PointLights.h"
-#include "Pools.h"
-#ifdef FIX_BUGS
-#include "Replay.h"
-#endif
-#include "Script.h"
-#include "Shadows.h"
-#include "SpecialFX.h"
-#include "Sprite.h"
-#include "Timer.h"
-#include "WaterLevel.h"
-#include "World.h"
-
-CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98;
-int16 CPickups::NumMessages;// = *(int16*)0x95CC98;
-int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];// = *(int32(*)[NUMCOLLECTEDPICKUPS])*(uintptr*)0x87C538;
-int16 CPickups::CollectedPickUpIndex;// = *(int16*)0x95CC8A;
-
-// unused
-bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71;
-CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8;
-CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8;
-uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C;
-
-tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];
-
-// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4)
-uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 };
-uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 };
-uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 };
-
-uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 128, 0, 255, 0 };
-uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 };
-uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
-float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
-
-WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); }
-WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); }
-WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); }
-WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); }
-WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); }
-WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
-WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); }
-WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); }
-WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); }
-WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); }
-WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); }
-WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); }
-WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); }
-WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); }
-WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); }
-
-
-void
-CPickup::RemoveKeepType()
-{
- CWorld::Remove(m_pObject);
- delete m_pObject;
-
- m_bRemoved = true;
- m_pObject = nil;
-}
-
-void
-CPickup::Remove()
-{
- RemoveKeepType();
- m_eType = PICKUP_NONE;
-}
-
-CObject *
-CPickup::GiveUsAPickUpObject(int32 handle)
-{
- CObject *object;
-
- if (handle <= 0) object = new CObject(m_eModelIndex, false);
- else {
- CPools::MakeSureSlotInObjectPoolIsEmpty(handle);
- object = new(handle) CObject(m_eModelIndex, false);
- }
-
- if (object == nil) return nil;
- object->ObjectCreatedBy = MISSION_OBJECT;
- object->GetPosition() = m_vecPos;
- object->SetOrientation(0.0f, 0.0f, -HALFPI);
- object->GetMatrix().UpdateRW();
- object->UpdateRwFrame();
-
- object->bAffectedByGravity = false;
- object->bExplosionProof = true;
- object->bUsesCollision = false;
- object->bIsPickup = true;
-
- object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0;
-
- switch (m_eType)
- {
- case PICKUP_IN_SHOP:
- object->m_obj_flag2 = true;
- object->bOutOfStock = false;
- break;
- case PICKUP_ON_STREET:
- case PICKUP_ONCE:
- case PICKUP_ONCE_TIMEOUT:
- case PICKUP_COLLECTABLE1:
- case PICKUP_MONEY:
- case PICKUP_MINE_INACTIVE:
- case PICKUP_MINE_ARMED:
- case PICKUP_NAUTICAL_MINE_INACTIVE:
- case PICKUP_NAUTICAL_MINE_ARMED:
- case PICKUP_FLOATINGPACKAGE:
- case PICKUP_ON_STREET_SLOW:
- object->m_obj_flag2 = false;
- object->bOutOfStock = false;
- break;
- case PICKUP_IN_SHOP_OUT_OF_STOCK:
- object->m_obj_flag2 = false;
- object->bOutOfStock = true;
- object->bRenderScorched = true;
- break;
- case PICKUP_FLOATINGPACKAGE_FLOATING:
- default:
- break;
- }
- return object;
-}
-
-bool
-CPickup::CanBePickedUp(CPlayerPed *player)
-{
- assert(m_pObject != nil);
- bool cannotBePickedUp =
- (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
- || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
- || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0)
- || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
- return !cannotBePickedUp;
-}
-
-bool
-CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
-{
- float waterLevel;
-
- if (m_bRemoved) {
- if (CTimer::GetTimeInMilliseconds() > m_nTimer) {
- // respawn pickup if we're far enough
- float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y);
- if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) {
- m_pObject = GiveUsAPickUpObject(-1);
- if (m_pObject) {
- CWorld::Add(m_pObject);
- m_bRemoved = false;
- }
- }
- }
- return false;
- }
-
- if (!m_pObject) return false;
-
- if (!IsMine()) {
- // let's check if we touched the pickup
- bool isPickupTouched = false;
- if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) {
- if (vehicle != nil) {
- if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f))
- isPickupTouched = true;
- }
- else {
- if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
- if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
- (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
- isPickupTouched = true;
- }
- }
- } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) {
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
- isPickupTouched = true;
- }
- } else if (vehicle == nil) {
- if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
- if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
- (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
- isPickupTouched = true;
- }
- }
-
- // if we didn't then we've got nothing to do
- if (isPickupTouched && CanBePickedUp(player)) {
- CPad::GetPad(0)->StartShake(120, 100);
- switch (m_eType)
- {
- case PICKUP_IN_SHOP:
- if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) {
- CGarages::TriggerMessage("PU_MONY", -1, 6000, -1);
- } else {
- CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())];
- if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);
- }
- RemoveKeepType();
- m_nTimer = CTimer::GetTimeInMilliseconds() + 5000;
- return true;
- }
- break;
- case PICKUP_ON_STREET:
- case PICKUP_ON_STREET_SLOW:
- if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) {
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
- }
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
- } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- CPickups::bPickUpcamActivated = true;
- CPickups::pPlayerVehicle = FindPlayerVehicle();
- CPickups::StaticCamCoors = m_pObject->GetPosition();
- CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds();
- }
- }
- if (m_eType == PICKUP_ON_STREET) {
- m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
- } else if (m_eType == PICKUP_ON_STREET_SLOW) {
- if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex)
- m_nTimer = CTimer::GetTimeInMilliseconds() + 300000;
- else
- m_nTimer = CTimer::GetTimeInMilliseconds() + 720000;
- }
-
- RemoveKeepType();
- return true;
- case PICKUP_ONCE:
- case PICKUP_ONCE_TIMEOUT:
- if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
- }
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
- }
- Remove();
- return true;
- case PICKUP_COLLECTABLE1:
- CWorld::Players[playerId].m_nCollectedPackages++;
- CWorld::Players[playerId].m_nMoney += 1000;
-
- if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) {
- printf("All collectables have been picked up\n");
- CGarages::TriggerMessage("CO_ALL", -1, 5000, -1);
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000;
- } else
- CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
-
- Remove();
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0);
- return true;
- case PICKUP_MONEY:
- CWorld::Players[playerId].m_nMoney += m_nQuantity;
- sprintf(gString, "$%d", m_nQuantity);
-#ifdef MONEY_MESSAGES
- CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f);
-#endif
- Remove();
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
- return true;
- //case PICKUP_IN_SHOP_OUT_OF_STOCK:
- //case PICKUP_MINE_INACTIVE:
- //case PICKUP_MINE_ARMED:
- //case PICKUP_NAUTICAL_MINE_INACTIVE:
- //case PICKUP_NAUTICAL_MINE_ARMED:
- //case PICKUP_FLOATINGPACKAGE:
- //case PICKUP_FLOATINGPACKAGE_FLOATING:
- default:
- break;
- }
- }
- } else {
- switch (m_eType)
- {
- case PICKUP_MINE_INACTIVE:
- if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
- m_eType = PICKUP_MINE_ARMED;
- m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
- }
- break;
- case PICKUP_NAUTICAL_MINE_INACTIVE:
- {
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
- m_pObject->GetPosition().z = waterLevel + 0.6f;
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
-
- bool touched = false;
- for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
- CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
- touched = true;
- break; // added break here
- }
- }
-
- if (!touched) {
- m_eType = PICKUP_NAUTICAL_MINE_ARMED;
- m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
- }
- break;
- }
- case PICKUP_NAUTICAL_MINE_ARMED:
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
- m_pObject->GetPosition().z = waterLevel + 0.6f;
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
- // no break here
- case PICKUP_MINE_ARMED:
- {
- bool explode = false;
- if (CTimer::GetTimeInMilliseconds() > m_nTimer)
- explode = true;
- else {// added else here since vehicle lookup is useless
- for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
- CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
- explode = true;
- break; // added break here
- }
- }
- }
- if (explode) {
- CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);
- Remove();
- }
- break;
- }
- case PICKUP_FLOATINGPACKAGE:
- m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep();
- m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep();
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z)
- m_eType = PICKUP_FLOATINGPACKAGE_FLOATING;
- break;
- case PICKUP_FLOATINGPACKAGE_FLOATING:
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0))
- m_pObject->GetPosition().z = waterLevel;
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
- Remove();
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0);
- return true;
- }
- break;
- }
- }
- if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
- Remove();
- return false;
-}
-
-void
-CPickups::Init(void)
-{
- NumMessages = 0;
- for (int i = 0; i < NUMPICKUPS; i++) {
- aPickUps[i].m_eType = PICKUP_NONE;
- aPickUps[i].m_nIndex = 1;
- aPickUps[i].m_pObject = nil;
- }
-
- for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++)
- aPickUpsCollected[i] = 0;
-
- CollectedPickUpIndex = 0;
-}
-
-bool
-CPickups::IsPickUpPickedUp(int32 pickupId)
-{
- for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
- if (pickupId == aPickUpsCollected[i]) {
- aPickUpsCollected[i] = 0;
- return true;
- }
- }
- return false;
-}
-
-void
-CPickups::PassTime(uint32 time)
-{
- for (int i = 0; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType != PICKUP_NONE) {
- if (aPickUps[i].m_nTimer <= time)
- aPickUps[i].m_nTimer = 0;
- else
- aPickUps[i].m_nTimer -= time;
- }
- }
-}
-
-int32
-CPickups::GetActualPickupIndex(int32 index)
-{
- if (index == -1) return -1;
-
- // doesn't look nice
- if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1;
- return (uint16)index;
-}
-
-bool
-CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
-{
- CPlayerPed *player;
-
- if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
- else player = CWorld::Players[playerIndex].m_pPed;
-
- if (modelIndex == MI_PICKUP_ADRENALINE) {
- player->m_bAdrenalineActive = true;
- player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000;
- player->m_fCurrentStamina = player->m_fMaxStamina;
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_BODYARMOUR) {
- player->m_fArmour = 100.0f;
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_INFO) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_HEALTH) {
- player->m_fHealth = 100.0f;
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_BONUS) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_BRIBE) {
- int32 level = FindPlayerPed()->m_pWanted->m_nWantedLevel - 1;
- if (level < 0) level = 0;
- player->SetWantedLevel(level);
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_KILLFRENZY) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- }
- return false;
-}
-
-void
-CPickups::RemoveAllFloatingPickups()
-{
- for (int i = 0; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) {
- if (aPickUps[i].m_pObject) {
- CWorld::Remove(aPickUps[i].m_pObject);
- delete aPickUps[i].m_pObject;
- aPickUps[i].m_pObject = nil;
- }
- }
- }
-}
-
-void
-CPickups::RemovePickUp(int32 pickupIndex)
-{
- int32 index = CPickups::GetActualPickupIndex(pickupIndex);
- if (index == -1) return;
-
- if (aPickUps[index].m_pObject) {
- CWorld::Remove(aPickUps[index].m_pObject);
- delete aPickUps[index].m_pObject;
- aPickUps[index].m_pObject = nil;
- }
- aPickUps[index].m_eType = PICKUP_NONE;
- aPickUps[index].m_bRemoved = true;
-}
-
-int32
-CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
-{
- bool bFreeFound = false;
- int32 slot = 0;
-
- if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) {
- for (slot = NUMPICKUPS; slot >= 0; slot--) {
- if (aPickUps[slot].m_eType == PICKUP_NONE) {
- bFreeFound = true;
- break;
- }
- }
- } else {
- for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
- if (aPickUps[slot].m_eType == PICKUP_NONE) {
- bFreeFound = true;
- break;
- }
- }
- }
-
- if (!bFreeFound)
- {
- for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
- if (aPickUps[slot].m_eType == PICKUP_MONEY) break;
- }
-
- if (slot >= NUMGENERALPICKUPS)
- {
- for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
- if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break;
- }
-
- if (slot >= NUMGENERALPICKUPS) return -1;
- }
- }
-
- if (slot >= NUMPICKUPS) return -1;
-
- aPickUps[slot].m_eType = (ePickupType)type;
- aPickUps[slot].m_bRemoved = false;
- aPickUps[slot].m_nQuantity = quantity;
- if (type == PICKUP_ONCE_TIMEOUT)
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000;
- else if (type == PICKUP_MONEY)
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
- else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) {
- aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE;
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
- } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) {
- aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE;
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
- }
- aPickUps[slot].m_eModelIndex = modelIndex;
- aPickUps[slot].m_vecPos = pos;
- aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1);
- if (aPickUps[slot].m_pObject)
- CWorld::Add(aPickUps[slot].m_pObject);
- return GetNewUniquePickupIndex(slot);
-}
-
-int32
-CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity)
-{
- return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity);
-}
-
-int32
-CPickups::GetNewUniquePickupIndex(int32 slot)
-{
- if (aPickUps[slot].m_nIndex >= 0xFFFE)
- aPickUps[slot].m_nIndex = 1;
- else
- aPickUps[slot].m_nIndex++;
- return slot | (aPickUps[slot].m_nIndex << 16);
-}
-
-int32
-CPickups::ModelForWeapon(eWeaponType weaponType)
-{
- switch (weaponType)
- {
- case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT;
- case WEAPONTYPE_COLT45: return MI_COLT;
- case WEAPONTYPE_UZI: return MI_UZI;
- case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN;
- case WEAPONTYPE_AK47: return MI_AK47;
- case WEAPONTYPE_M16: return MI_M16;
- case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER;
- case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER;
- case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER;
- case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV;
- case WEAPONTYPE_GRENADE: return MI_GRENADE;
- }
- return 0;
-}
-
-eWeaponType
-CPickups::WeaponForModel(int32 model)
-{
- if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;
- switch (model)
- {
- case MI_GRENADE: return WEAPONTYPE_GRENADE;
- case MI_AK47: return WEAPONTYPE_AK47;
- case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT;
- case MI_COLT: return WEAPONTYPE_COLT45;
- case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV;
- case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER;
- case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN;
- case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE;
- case MI_UZI: return WEAPONTYPE_UZI;
- case MI_MISSILE: return WEAPONTYPE_UNARMED;
- case MI_M16: return WEAPONTYPE_M16;
- case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER;
- }
- return WEAPONTYPE_UNARMED;
-}
-
-int32
-CPickups::FindColourIndexForWeaponMI(int32 model)
-{
- return WeaponForModel(model) - 1;
-}
-
-void
-CPickups::AddToCollectedPickupsArray(int32 index)
-{
- aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16);
- if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS)
- CollectedPickUpIndex = 0;
-}
-
-void
-CPickups::Update()
-{
-#ifdef FIX_BUGS // RIP speedrunning (solution from SA)
- if (CReplay::IsPlayingBack())
- return;
-#endif
-#define PICKUPS_FRAME_SPAN (6)
-#ifdef FIX_BUGS
- for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) {
-#else // BUG: this code can only reach 318 out of 320 pickups
- for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) {
-#endif
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
- AddToCollectedPickupsArray(i);
- }
- }
-#undef PICKUPS_FRAME_SPAN
- for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
- AddToCollectedPickupsArray(i);
- }
- }
-}
-
-void
-CPickups::DoPickUpEffects(CEntity *entity)
-{
- if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
- entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame;
-
- if (!entity->m_flagD80) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
- float modifiedSin = 0.3f * (s + 1.0f);
-
-
- int16 colorId;
-
- if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA)
- colorId = 11;
- else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE)
- colorId = 12;
- else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
- colorId = 13;
- else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS)
- colorId = 14;
- else
- colorId = FindColourIndexForWeaponMI(entity->GetModelIndex());
-
- assert(colorId >= 0);
-
- CVector &pos = entity->GetPosition();
-
- float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f;
- CShadows::StoreStaticShadow(
- (uintptr)entity,
- SHADOWTYPE_ADDITIVE,
- gpShadowExplosionTex,
- &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
-
- float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f;
- CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true);
- float size = (CGeneral::GetRandomNumber() & 0xF) * 0.0005f + 0.6f;
- CCoronas::RegisterCorona( (uintptr)entity,
- aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f,
- 255,
- pos,
- size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
-
- CObject *object = (CObject*)entity;
- if (object->m_obj_flag2 || object->bOutOfStock || object->field_172) {
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 12.0f;
-
- if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {
- RwV3d vecOut;
- float fDistX, fDistY;
- if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) {
- aMessages[NumMessages].m_pos.x = vecOut.x;
- aMessages[NumMessages].m_pos.y = vecOut.y;
- aMessages[NumMessages].m_dist.x = fDistX;
- aMessages[NumMessages].m_dist.y = fDistY;
- aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex());
- aMessages[NumMessages].m_color.red = aWeaponReds[colorId];
- aMessages[NumMessages].m_color.green = aWeaponGreens[colorId];
- aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId];
- aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f;
- aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock;
- aMessages[NumMessages].m_quantity = object->field_172;
- NumMessages++;
- }
- }
- }
-
- entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), aWeaponScale[colorId]);
- }
-}
-
-void
-CPickups::DoMineEffects(CEntity *entity)
-{
- CVector &pos = entity->GetPosition();
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 20.0f;
-
- if (dist < MAXDIST) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200));
-
- int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f;
- CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- red, 0, 0,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
- CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- }
-
- entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400));
-}
-
-void
-CPickups::DoMoneyEffects(CEntity *entity)
-{
- CVector &pos = entity->GetPosition();
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 20.0f;
-
- if (dist < MAXDIST) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400));
-
- int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f;
- CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- 0, green, 0,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
- CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- }
-
- entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800));
-}
-
-void
-CPickups::DoCollectableEffects(CEntity *entity)
-{
- CVector &pos = entity->GetPosition();
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 14.0f;
-
- if (dist < MAXDIST) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
-
- int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f;
- CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- color, color, color,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
- CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- }
-
- entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000));
-}
-
-void
-CPickups::RenderPickUpText()
-{
- wchar *strToPrint;
- for (int32 i = 0; i < NumMessages; i++) {
- if (aMessages[i].m_quantity <= 39) {
- switch (aMessages[i].m_quantity) // could use some enum maybe
- {
- case 0:
- if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code?
- // what is this??
- sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903);
- } else {
- if (aMessages[i].m_bOutOfStock)
- strToPrint = TheText.Get("STOCK");
- else {
- sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]);
- AsciiToUnicode(gString, gUString);
- strToPrint = gUString;
- }
- }
- break;
- case 1:
- strToPrint = TheText.Get("SECURI");
- break;
- case 2:
- strToPrint = TheText.Get("MOONBM");
- break;
- case 3:
- strToPrint = TheText.Get("COACH");
- break;
- case 4:
- strToPrint = TheText.Get("FLATBED");
- break;
- case 5:
- strToPrint = TheText.Get("LINERUN");
- break;
- case 6:
- strToPrint = TheText.Get("TRASHM");
- break;
- case 7:
- strToPrint = TheText.Get("PATRIOT");
- break;
- case 8:
- strToPrint = TheText.Get("WHOOPEE");
- break;
- case 9:
- strToPrint = TheText.Get("BLISTA");
- break;
- case 10:
- strToPrint = TheText.Get("MULE");
- break;
- case 11:
- strToPrint = TheText.Get("YANKEE");
- break;
- case 12:
- strToPrint = TheText.Get("BOBCAT");
- break;
- case 13:
- strToPrint = TheText.Get("DODO");
- break;
- case 14:
- strToPrint = TheText.Get("BUS");
- break;
- case 15:
- strToPrint = TheText.Get("RUMPO");
- break;
- case 16:
- strToPrint = TheText.Get("PONY");
- break;
- case 17:
- strToPrint = TheText.Get("SENTINL");
- break;
- case 18:
- strToPrint = TheText.Get("CHEETAH");
- break;
- case 19:
- strToPrint = TheText.Get("BANSHEE");
- break;
- case 20:
- strToPrint = TheText.Get("IDAHO");
- break;
- case 21:
- strToPrint = TheText.Get("INFERNS");
- break;
- case 22:
- strToPrint = TheText.Get("TAXI");
- break;
- case 23:
- strToPrint = TheText.Get("KURUMA");
- break;
- case 24:
- strToPrint = TheText.Get("STRETCH");
- break;
- case 25:
- strToPrint = TheText.Get("PEREN");
- break;
- case 26:
- strToPrint = TheText.Get("STINGER");
- break;
- case 27:
- strToPrint = TheText.Get("MANANA");
- break;
- case 28:
- strToPrint = TheText.Get("LANDSTK");
- break;
- case 29:
- strToPrint = TheText.Get("STALION");
- break;
- case 30:
- strToPrint = TheText.Get("BFINJC");
- break;
- case 31:
- strToPrint = TheText.Get("CABBIE");
- break;
- case 32:
- strToPrint = TheText.Get("ESPERAN");
- break;
- case 33:
- strToPrint = TheText.Get("FIRETRK");
- break;
- case 34:
- strToPrint = TheText.Get("AMBULAN");
- break;
- case 35:
- strToPrint = TheText.Get("ENFORCR");
- break;
- case 36:
- strToPrint = TheText.Get("FBICAR");
- break;
- case 37:
- strToPrint = TheText.Get("RHINO");
- break;
- case 38:
- strToPrint = TheText.Get("BARRCKS");
- break;
- case 39:
- strToPrint = TheText.Get("POLICAR");
- break;
- default:
- break;
- }
- }
- CFont::SetPropOn();
- CFont::SetBackgroundOff();
-
- const float MAX_SCALE = 1.0f;
-
- float fScaleY = aMessages[i].m_dist.y / 100.0f;
- if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
-
- float fScaleX = aMessages[i].m_dist.x / 100.0f;
- if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
-
- CFont::SetScale(fScaleX, fScaleY);
- CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_WIDTH);
- CFont::SetJustifyOff();
-
- CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha));
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_BANK);
- CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint);
- }
- NumMessages = 0;
-}
-
-void
-CPickups::Load(uint8 *buf, uint32 size)
-{
-INITSAVEBUF
-
- for (int32 i = 0; i < NUMPICKUPS; i++) {
- aPickUps[i] = ReadSaveBuf<CPickup>(buf);
-
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
- aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1);
- }
-
- CollectedPickUpIndex = ReadSaveBuf<uint16>(buf);
- ReadSaveBuf<uint16>(buf);
- NumMessages = 0;
-
- for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
- aPickUpsCollected[i] = ReadSaveBuf<int32>(buf);
-
-VALIDATESAVEBUF(size)
-}
-
-void
-CPickups::Save(uint8 *buf, uint32 *size)
-{
- *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
-
-INITSAVEBUF
-
- for (int32 i = 0; i < NUMPICKUPS; i++) {
- CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
- if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
- buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1);
- }
-
- WriteSaveBuf(buf, CollectedPickUpIndex);
- WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages
-
- for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
- WriteSaveBuf(buf, aPickUpsCollected[i]);
-
-VALIDATESAVEBUF(*size)
-}
-
-STARTPATCHES
- InjectHook(0x430220, CPickups::Init, PATCH_JUMP);
- InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP);
- InjectHook(0x432440, CPickups::RenderPickUpText, PATCH_JUMP);
- InjectHook(0x431C30, CPickups::DoCollectableEffects, PATCH_JUMP);
- InjectHook(0x431F40, CPickups::DoMoneyEffects, PATCH_JUMP);
- InjectHook(0x4321C0, CPickups::DoMineEffects, PATCH_JUMP);
- InjectHook(0x431520, CPickups::DoPickUpEffects, PATCH_JUMP);
- InjectHook(0x4304B0, CPickups::GenerateNewOne, PATCH_JUMP);
- InjectHook(0x430660, CPickups::GenerateNewOne_WeaponType, PATCH_JUMP);
- InjectHook(0x4307A0, CPickups::RemovePickUp, PATCH_JUMP);
- InjectHook(0x430800, CPickups::RemoveAllFloatingPickups, PATCH_JUMP);
- InjectHook(0x433D60, CPickups::AddToCollectedPickupsArray, PATCH_JUMP);
- InjectHook(0x430770, CPickups::IsPickUpPickedUp, PATCH_JUMP);
- InjectHook(0x430690, CPickups::ModelForWeapon, PATCH_JUMP);
- InjectHook(0x4306F0, CPickups::WeaponForModel, PATCH_JUMP);
- InjectHook(0x431510, CPickups::FindColourIndexForWeaponMI, PATCH_JUMP);/**/
- InjectHook(0x433DF0, CPickups::GetActualPickupIndex, PATCH_JUMP);
- InjectHook(0x433DB0, CPickups::GetNewUniquePickupIndex, PATCH_JUMP);
- InjectHook(0x433B60, CPickups::PassTime, PATCH_JUMP);
- InjectHook(0x4339F0, CPickups::GivePlayerGoodiesWithPickUpMI, PATCH_JUMP);
- InjectHook(0x433F60, CPickups::Load, PATCH_JUMP);
- InjectHook(0x433E40, CPickups::Save, PATCH_JUMP);
- InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP);
- InjectHook(0x430860, &CPickup::Update, PATCH_JUMP);
-ENDPATCHES
+#include "common.h"
+#include "patcher.h"
+#include "main.h"
+
+#include "Camera.h"
+#include "Coronas.h"
+#include "Darkel.h"
+#include "Entity.h"
+#include "Explosion.h"
+#include "Font.h"
+#include "Garages.h"
+#include "General.h"
+#include "ModelIndices.h"
+#include "Object.h"
+#include "Pad.h"
+#include "Pickups.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "DMAudio.h"
+#include "Fire.h"
+#include "PointLights.h"
+#include "Pools.h"
+#ifdef FIX_BUGS
+#include "Replay.h"
+#endif
+#include "Script.h"
+#include "Shadows.h"
+#include "SpecialFX.h"
+#include "Sprite.h"
+#include "Timer.h"
+#include "WaterLevel.h"
+#include "World.h"
+
+CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98;
+int16 CPickups::NumMessages;// = *(int16*)0x95CC98;
+int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];// = *(int32(*)[NUMCOLLECTEDPICKUPS])*(uintptr*)0x87C538;
+int16 CPickups::CollectedPickUpIndex;// = *(int16*)0x95CC8A;
+
+// unused
+bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71;
+CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8;
+CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8;
+uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C;
+
+tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];
+
+// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4)
+uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 };
+uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 };
+uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 };
+
+uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 128, 0, 255, 0 };
+uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 };
+uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
+float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
+
+WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); }
+WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); }
+WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); }
+WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); }
+WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); }
+WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
+WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); }
+WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); }
+WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); }
+WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); }
+WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); }
+WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); }
+WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); }
+WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); }
+WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); }
+
+
+void
+CPickup::RemoveKeepType()
+{
+ CWorld::Remove(m_pObject);
+ delete m_pObject;
+
+ m_bRemoved = true;
+ m_pObject = nil;
+}
+
+void
+CPickup::Remove()
+{
+ RemoveKeepType();
+ m_eType = PICKUP_NONE;
+}
+
+CObject *
+CPickup::GiveUsAPickUpObject(int32 handle)
+{
+ CObject *object;
+
+ if (handle <= 0) object = new CObject(m_eModelIndex, false);
+ else {
+ CPools::MakeSureSlotInObjectPoolIsEmpty(handle);
+ object = new(handle) CObject(m_eModelIndex, false);
+ }
+
+ if (object == nil) return nil;
+ object->ObjectCreatedBy = MISSION_OBJECT;
+ object->GetPosition() = m_vecPos;
+ object->SetOrientation(0.0f, 0.0f, -HALFPI);
+ object->GetMatrix().UpdateRW();
+ object->UpdateRwFrame();
+
+ object->bAffectedByGravity = false;
+ object->bExplosionProof = true;
+ object->bUsesCollision = false;
+ object->bIsPickup = true;
+
+ object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0;
+
+ switch (m_eType)
+ {
+ case PICKUP_IN_SHOP:
+ object->m_obj_flag2 = true;
+ object->bOutOfStock = false;
+ break;
+ case PICKUP_ON_STREET:
+ case PICKUP_ONCE:
+ case PICKUP_ONCE_TIMEOUT:
+ case PICKUP_COLLECTABLE1:
+ case PICKUP_MONEY:
+ case PICKUP_MINE_INACTIVE:
+ case PICKUP_MINE_ARMED:
+ case PICKUP_NAUTICAL_MINE_INACTIVE:
+ case PICKUP_NAUTICAL_MINE_ARMED:
+ case PICKUP_FLOATINGPACKAGE:
+ case PICKUP_ON_STREET_SLOW:
+ object->m_obj_flag2 = false;
+ object->bOutOfStock = false;
+ break;
+ case PICKUP_IN_SHOP_OUT_OF_STOCK:
+ object->m_obj_flag2 = false;
+ object->bOutOfStock = true;
+ object->bRenderScorched = true;
+ break;
+ case PICKUP_FLOATINGPACKAGE_FLOATING:
+ default:
+ break;
+ }
+ return object;
+}
+
+bool
+CPickup::CanBePickedUp(CPlayerPed *player)
+{
+ assert(m_pObject != nil);
+ bool cannotBePickedUp =
+ (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
+ return !cannotBePickedUp;
+}
+
+bool
+CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
+{
+ float waterLevel;
+
+ if (m_bRemoved) {
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer) {
+ // respawn pickup if we're far enough
+ float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y);
+ if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) {
+ m_pObject = GiveUsAPickUpObject(-1);
+ if (m_pObject) {
+ CWorld::Add(m_pObject);
+ m_bRemoved = false;
+ }
+ }
+ }
+ return false;
+ }
+
+ if (!m_pObject) return false;
+
+ if (!IsMine()) {
+ // let's check if we touched the pickup
+ bool isPickupTouched = false;
+ if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) {
+ if (vehicle != nil) {
+ if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f))
+ isPickupTouched = true;
+ }
+ else {
+ if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
+ if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
+ (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
+ isPickupTouched = true;
+ }
+ }
+ } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) {
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ isPickupTouched = true;
+ }
+ } else if (vehicle == nil) {
+ if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
+ if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
+ (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
+ isPickupTouched = true;
+ }
+ }
+
+ // if we didn't then we've got nothing to do
+ if (isPickupTouched && CanBePickedUp(player)) {
+ CPad::GetPad(0)->StartShake(120, 100);
+ switch (m_eType)
+ {
+ case PICKUP_IN_SHOP:
+ if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) {
+ CGarages::TriggerMessage("PU_MONY", -1, 6000, -1);
+ } else {
+ CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())];
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);
+ }
+ RemoveKeepType();
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ return true;
+ }
+ break;
+ case PICKUP_ON_STREET:
+ case PICKUP_ON_STREET_SLOW:
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) {
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ }
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
+ } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ CPickups::bPickUpcamActivated = true;
+ CPickups::pPlayerVehicle = FindPlayerVehicle();
+ CPickups::StaticCamCoors = m_pObject->GetPosition();
+ CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds();
+ }
+ }
+ if (m_eType == PICKUP_ON_STREET) {
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ } else if (m_eType == PICKUP_ON_STREET_SLOW) {
+ if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex)
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 300000;
+ else
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 720000;
+ }
+
+ RemoveKeepType();
+ return true;
+ case PICKUP_ONCE:
+ case PICKUP_ONCE_TIMEOUT:
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ }
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
+ }
+ Remove();
+ return true;
+ case PICKUP_COLLECTABLE1:
+ CWorld::Players[playerId].m_nCollectedPackages++;
+ CWorld::Players[playerId].m_nMoney += 1000;
+
+ if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) {
+ printf("All collectables have been picked up\n");
+ CGarages::TriggerMessage("CO_ALL", -1, 5000, -1);
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000;
+ } else
+ CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
+
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0);
+ return true;
+ case PICKUP_MONEY:
+ CWorld::Players[playerId].m_nMoney += m_nQuantity;
+ sprintf(gString, "$%d", m_nQuantity);
+#ifdef MONEY_MESSAGES
+ CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f);
+#endif
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
+ return true;
+ //case PICKUP_IN_SHOP_OUT_OF_STOCK:
+ //case PICKUP_MINE_INACTIVE:
+ //case PICKUP_MINE_ARMED:
+ //case PICKUP_NAUTICAL_MINE_INACTIVE:
+ //case PICKUP_NAUTICAL_MINE_ARMED:
+ //case PICKUP_FLOATINGPACKAGE:
+ //case PICKUP_FLOATINGPACKAGE_FLOATING:
+ default:
+ break;
+ }
+ }
+ } else {
+ switch (m_eType)
+ {
+ case PICKUP_MINE_INACTIVE:
+ if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ m_eType = PICKUP_MINE_ARMED;
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ }
+ break;
+ case PICKUP_NAUTICAL_MINE_INACTIVE:
+ {
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
+ m_pObject->GetPosition().z = waterLevel + 0.6f;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+
+ bool touched = false;
+ for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
+ CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
+ touched = true;
+ break; // added break here
+ }
+ }
+
+ if (!touched) {
+ m_eType = PICKUP_NAUTICAL_MINE_ARMED;
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ }
+ break;
+ }
+ case PICKUP_NAUTICAL_MINE_ARMED:
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
+ m_pObject->GetPosition().z = waterLevel + 0.6f;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ // no break here
+ case PICKUP_MINE_ARMED:
+ {
+ bool explode = false;
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer)
+ explode = true;
+ else {// added else here since vehicle lookup is useless
+ for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
+ CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
+ explode = true;
+ break; // added break here
+ }
+ }
+ }
+ if (explode) {
+ CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);
+ Remove();
+ }
+ break;
+ }
+ case PICKUP_FLOATINGPACKAGE:
+ m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep();
+ m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep();
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z)
+ m_eType = PICKUP_FLOATINGPACKAGE_FLOATING;
+ break;
+ case PICKUP_FLOATINGPACKAGE_FLOATING:
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0))
+ m_pObject->GetPosition().z = waterLevel;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0);
+ return true;
+ }
+ break;
+ }
+ }
+ if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
+ Remove();
+ return false;
+}
+
+void
+CPickups::Init(void)
+{
+ NumMessages = 0;
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ aPickUps[i].m_eType = PICKUP_NONE;
+ aPickUps[i].m_nIndex = 1;
+ aPickUps[i].m_pObject = nil;
+ }
+
+ for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ aPickUpsCollected[i] = 0;
+
+ CollectedPickUpIndex = 0;
+}
+
+bool
+CPickups::IsPickUpPickedUp(int32 pickupId)
+{
+ for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
+ if (pickupId == aPickUpsCollected[i]) {
+ aPickUpsCollected[i] = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+CPickups::PassTime(uint32 time)
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE) {
+ if (aPickUps[i].m_nTimer <= time)
+ aPickUps[i].m_nTimer = 0;
+ else
+ aPickUps[i].m_nTimer -= time;
+ }
+ }
+}
+
+int32
+CPickups::GetActualPickupIndex(int32 index)
+{
+ if (index == -1) return -1;
+
+ // doesn't look nice
+ if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1;
+ return (uint16)index;
+}
+
+bool
+CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
+{
+ CPlayerPed *player;
+
+ if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ else player = CWorld::Players[playerIndex].m_pPed;
+
+ if (modelIndex == MI_PICKUP_ADRENALINE) {
+ player->m_bAdrenalineActive = true;
+ player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000;
+ player->m_fCurrentStamina = player->m_fMaxStamina;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BODYARMOUR) {
+ player->m_fArmour = 100.0f;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_INFO) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_HEALTH) {
+ player->m_fHealth = 100.0f;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BONUS) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BRIBE) {
+ int32 level = FindPlayerPed()->m_pWanted->m_nWantedLevel - 1;
+ if (level < 0) level = 0;
+ player->SetWantedLevel(level);
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_KILLFRENZY) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ }
+ return false;
+}
+
+void
+CPickups::RemoveAllFloatingPickups()
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) {
+ if (aPickUps[i].m_pObject) {
+ CWorld::Remove(aPickUps[i].m_pObject);
+ delete aPickUps[i].m_pObject;
+ aPickUps[i].m_pObject = nil;
+ }
+ }
+ }
+}
+
+void
+CPickups::RemovePickUp(int32 pickupIndex)
+{
+ int32 index = CPickups::GetActualPickupIndex(pickupIndex);
+ if (index == -1) return;
+
+ if (aPickUps[index].m_pObject) {
+ CWorld::Remove(aPickUps[index].m_pObject);
+ delete aPickUps[index].m_pObject;
+ aPickUps[index].m_pObject = nil;
+ }
+ aPickUps[index].m_eType = PICKUP_NONE;
+ aPickUps[index].m_bRemoved = true;
+}
+
+int32
+CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
+{
+ bool bFreeFound = false;
+ int32 slot = 0;
+
+ if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) {
+ for (slot = NUMPICKUPS; slot >= 0; slot--) {
+ if (aPickUps[slot].m_eType == PICKUP_NONE) {
+ bFreeFound = true;
+ break;
+ }
+ }
+ } else {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_NONE) {
+ bFreeFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFreeFound)
+ {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_MONEY) break;
+ }
+
+ if (slot >= NUMGENERALPICKUPS)
+ {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break;
+ }
+
+ if (slot >= NUMGENERALPICKUPS) return -1;
+ }
+ }
+
+ if (slot >= NUMPICKUPS) return -1;
+
+ aPickUps[slot].m_eType = (ePickupType)type;
+ aPickUps[slot].m_bRemoved = false;
+ aPickUps[slot].m_nQuantity = quantity;
+ if (type == PICKUP_ONCE_TIMEOUT)
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000;
+ else if (type == PICKUP_MONEY)
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) {
+ aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE;
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) {
+ aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE;
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ }
+ aPickUps[slot].m_eModelIndex = modelIndex;
+ aPickUps[slot].m_vecPos = pos;
+ aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1);
+ if (aPickUps[slot].m_pObject)
+ CWorld::Add(aPickUps[slot].m_pObject);
+ return GetNewUniquePickupIndex(slot);
+}
+
+int32
+CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity)
+{
+ return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity);
+}
+
+int32
+CPickups::GetNewUniquePickupIndex(int32 slot)
+{
+ if (aPickUps[slot].m_nIndex >= 0xFFFE)
+ aPickUps[slot].m_nIndex = 1;
+ else
+ aPickUps[slot].m_nIndex++;
+ return slot | (aPickUps[slot].m_nIndex << 16);
+}
+
+int32
+CPickups::ModelForWeapon(eWeaponType weaponType)
+{
+ switch (weaponType)
+ {
+ case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT;
+ case WEAPONTYPE_COLT45: return MI_COLT;
+ case WEAPONTYPE_UZI: return MI_UZI;
+ case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN;
+ case WEAPONTYPE_AK47: return MI_AK47;
+ case WEAPONTYPE_M16: return MI_M16;
+ case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER;
+ case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER;
+ case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER;
+ case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV;
+ case WEAPONTYPE_GRENADE: return MI_GRENADE;
+ }
+ return 0;
+}
+
+eWeaponType
+CPickups::WeaponForModel(int32 model)
+{
+ if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;
+ switch (model)
+ {
+ case MI_GRENADE: return WEAPONTYPE_GRENADE;
+ case MI_AK47: return WEAPONTYPE_AK47;
+ case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT;
+ case MI_COLT: return WEAPONTYPE_COLT45;
+ case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV;
+ case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER;
+ case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN;
+ case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE;
+ case MI_UZI: return WEAPONTYPE_UZI;
+ case MI_MISSILE: return WEAPONTYPE_UNARMED;
+ case MI_M16: return WEAPONTYPE_M16;
+ case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER;
+ }
+ return WEAPONTYPE_UNARMED;
+}
+
+int32
+CPickups::FindColourIndexForWeaponMI(int32 model)
+{
+ return WeaponForModel(model) - 1;
+}
+
+void
+CPickups::AddToCollectedPickupsArray(int32 index)
+{
+ aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16);
+ if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS)
+ CollectedPickUpIndex = 0;
+}
+
+void
+CPickups::Update()
+{
+#ifdef FIX_BUGS // RIP speedrunning (solution from SA)
+ if (CReplay::IsPlayingBack())
+ return;
+#endif
+#define PICKUPS_FRAME_SPAN (6)
+#ifdef FIX_BUGS
+ for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) {
+#else // BUG: this code can only reach 318 out of 320 pickups
+ for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) {
+#endif
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ AddToCollectedPickupsArray(i);
+ }
+ }
+#undef PICKUPS_FRAME_SPAN
+ for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ AddToCollectedPickupsArray(i);
+ }
+ }
+}
+
+void
+CPickups::DoPickUpEffects(CEntity *entity)
+{
+ if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
+ entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame;
+
+ if (!entity->m_flagD80) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
+ float modifiedSin = 0.3f * (s + 1.0f);
+
+
+ int16 colorId;
+
+ if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA)
+ colorId = 11;
+ else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE)
+ colorId = 12;
+ else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
+ colorId = 13;
+ else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS)
+ colorId = 14;
+ else
+ colorId = FindColourIndexForWeaponMI(entity->GetModelIndex());
+
+ assert(colorId >= 0);
+
+ CVector &pos = entity->GetPosition();
+
+ float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f;
+ CShadows::StoreStaticShadow(
+ (uintptr)entity,
+ SHADOWTYPE_ADDITIVE,
+ gpShadowExplosionTex,
+ &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+
+ float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f;
+ CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true);
+ float size = (CGeneral::GetRandomNumber() & 0xF) * 0.0005f + 0.6f;
+ CCoronas::RegisterCorona( (uintptr)entity,
+ aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f,
+ 255,
+ pos,
+ size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+
+ CObject *object = (CObject*)entity;
+ if (object->m_obj_flag2 || object->bOutOfStock || object->field_172) {
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 12.0f;
+
+ if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {
+ RwV3d vecOut;
+ float fDistX, fDistY;
+ if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) {
+ aMessages[NumMessages].m_pos.x = vecOut.x;
+ aMessages[NumMessages].m_pos.y = vecOut.y;
+ aMessages[NumMessages].m_dist.x = fDistX;
+ aMessages[NumMessages].m_dist.y = fDistY;
+ aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex());
+ aMessages[NumMessages].m_color.red = aWeaponReds[colorId];
+ aMessages[NumMessages].m_color.green = aWeaponGreens[colorId];
+ aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId];
+ aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f;
+ aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock;
+ aMessages[NumMessages].m_quantity = object->field_172;
+ NumMessages++;
+ }
+ }
+ }
+
+ entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), aWeaponScale[colorId]);
+ }
+}
+
+void
+CPickups::DoMineEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 20.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200));
+
+ int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ red, 0, 0,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400));
+}
+
+void
+CPickups::DoMoneyEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 20.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400));
+
+ int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ 0, green, 0,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800));
+}
+
+void
+CPickups::DoCollectableEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 14.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
+
+ int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ color, color, color,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000));
+}
+
+void
+CPickups::RenderPickUpText()
+{
+ wchar *strToPrint;
+ for (int32 i = 0; i < NumMessages; i++) {
+ if (aMessages[i].m_quantity <= 39) {
+ switch (aMessages[i].m_quantity) // could use some enum maybe
+ {
+ case 0:
+ if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code?
+ // what is this??
+ sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903);
+ } else {
+ if (aMessages[i].m_bOutOfStock)
+ strToPrint = TheText.Get("STOCK");
+ else {
+ sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]);
+ AsciiToUnicode(gString, gUString);
+ strToPrint = gUString;
+ }
+ }
+ break;
+ case 1:
+ strToPrint = TheText.Get("SECURI");
+ break;
+ case 2:
+ strToPrint = TheText.Get("MOONBM");
+ break;
+ case 3:
+ strToPrint = TheText.Get("COACH");
+ break;
+ case 4:
+ strToPrint = TheText.Get("FLATBED");
+ break;
+ case 5:
+ strToPrint = TheText.Get("LINERUN");
+ break;
+ case 6:
+ strToPrint = TheText.Get("TRASHM");
+ break;
+ case 7:
+ strToPrint = TheText.Get("PATRIOT");
+ break;
+ case 8:
+ strToPrint = TheText.Get("WHOOPEE");
+ break;
+ case 9:
+ strToPrint = TheText.Get("BLISTA");
+ break;
+ case 10:
+ strToPrint = TheText.Get("MULE");
+ break;
+ case 11:
+ strToPrint = TheText.Get("YANKEE");
+ break;
+ case 12:
+ strToPrint = TheText.Get("BOBCAT");
+ break;
+ case 13:
+ strToPrint = TheText.Get("DODO");
+ break;
+ case 14:
+ strToPrint = TheText.Get("BUS");
+ break;
+ case 15:
+ strToPrint = TheText.Get("RUMPO");
+ break;
+ case 16:
+ strToPrint = TheText.Get("PONY");
+ break;
+ case 17:
+ strToPrint = TheText.Get("SENTINL");
+ break;
+ case 18:
+ strToPrint = TheText.Get("CHEETAH");
+ break;
+ case 19:
+ strToPrint = TheText.Get("BANSHEE");
+ break;
+ case 20:
+ strToPrint = TheText.Get("IDAHO");
+ break;
+ case 21:
+ strToPrint = TheText.Get("INFERNS");
+ break;
+ case 22:
+ strToPrint = TheText.Get("TAXI");
+ break;
+ case 23:
+ strToPrint = TheText.Get("KURUMA");
+ break;
+ case 24:
+ strToPrint = TheText.Get("STRETCH");
+ break;
+ case 25:
+ strToPrint = TheText.Get("PEREN");
+ break;
+ case 26:
+ strToPrint = TheText.Get("STINGER");
+ break;
+ case 27:
+ strToPrint = TheText.Get("MANANA");
+ break;
+ case 28:
+ strToPrint = TheText.Get("LANDSTK");
+ break;
+ case 29:
+ strToPrint = TheText.Get("STALION");
+ break;
+ case 30:
+ strToPrint = TheText.Get("BFINJC");
+ break;
+ case 31:
+ strToPrint = TheText.Get("CABBIE");
+ break;
+ case 32:
+ strToPrint = TheText.Get("ESPERAN");
+ break;
+ case 33:
+ strToPrint = TheText.Get("FIRETRK");
+ break;
+ case 34:
+ strToPrint = TheText.Get("AMBULAN");
+ break;
+ case 35:
+ strToPrint = TheText.Get("ENFORCR");
+ break;
+ case 36:
+ strToPrint = TheText.Get("FBICAR");
+ break;
+ case 37:
+ strToPrint = TheText.Get("RHINO");
+ break;
+ case 38:
+ strToPrint = TheText.Get("BARRCKS");
+ break;
+ case 39:
+ strToPrint = TheText.Get("POLICAR");
+ break;
+ default:
+ break;
+ }
+ }
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+
+ const float MAX_SCALE = 1.0f;
+
+ float fScaleY = aMessages[i].m_dist.y / 100.0f;
+ if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
+
+ float fScaleX = aMessages[i].m_dist.x / 100.0f;
+ if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
+
+ CFont::SetScale(fScaleX, fScaleY);
+ CFont::SetCentreOn();
+ CFont::SetCentreSize(SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+
+ CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint);
+ }
+ NumMessages = 0;
+}
+
+void
+CPickups::Load(uint8 *buf, uint32 size)
+{
+INITSAVEBUF
+
+ for (int32 i = 0; i < NUMPICKUPS; i++) {
+ aPickUps[i] = ReadSaveBuf<CPickup>(buf);
+
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
+ aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1);
+ }
+
+ CollectedPickUpIndex = ReadSaveBuf<uint16>(buf);
+ ReadSaveBuf<uint16>(buf);
+ NumMessages = 0;
+
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ aPickUpsCollected[i] = ReadSaveBuf<int32>(buf);
+
+VALIDATESAVEBUF(size)
+}
+
+void
+CPickups::Save(uint8 *buf, uint32 *size)
+{
+ *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
+
+INITSAVEBUF
+
+ for (int32 i = 0; i < NUMPICKUPS; i++) {
+ CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
+ if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
+ buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1);
+ }
+
+ WriteSaveBuf(buf, CollectedPickUpIndex);
+ WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages
+
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ WriteSaveBuf(buf, aPickUpsCollected[i]);
+
+VALIDATESAVEBUF(*size)
+}
+
+STARTPATCHES
+ InjectHook(0x430220, CPickups::Init, PATCH_JUMP);
+ InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP);
+ InjectHook(0x432440, CPickups::RenderPickUpText, PATCH_JUMP);
+ InjectHook(0x431C30, CPickups::DoCollectableEffects, PATCH_JUMP);
+ InjectHook(0x431F40, CPickups::DoMoneyEffects, PATCH_JUMP);
+ InjectHook(0x4321C0, CPickups::DoMineEffects, PATCH_JUMP);
+ InjectHook(0x431520, CPickups::DoPickUpEffects, PATCH_JUMP);
+ InjectHook(0x4304B0, CPickups::GenerateNewOne, PATCH_JUMP);
+ InjectHook(0x430660, CPickups::GenerateNewOne_WeaponType, PATCH_JUMP);
+ InjectHook(0x4307A0, CPickups::RemovePickUp, PATCH_JUMP);
+ InjectHook(0x430800, CPickups::RemoveAllFloatingPickups, PATCH_JUMP);
+ InjectHook(0x433D60, CPickups::AddToCollectedPickupsArray, PATCH_JUMP);
+ InjectHook(0x430770, CPickups::IsPickUpPickedUp, PATCH_JUMP);
+ InjectHook(0x430690, CPickups::ModelForWeapon, PATCH_JUMP);
+ InjectHook(0x4306F0, CPickups::WeaponForModel, PATCH_JUMP);
+ InjectHook(0x431510, CPickups::FindColourIndexForWeaponMI, PATCH_JUMP);/**/
+ InjectHook(0x433DF0, CPickups::GetActualPickupIndex, PATCH_JUMP);
+ InjectHook(0x433DB0, CPickups::GetNewUniquePickupIndex, PATCH_JUMP);
+ InjectHook(0x433B60, CPickups::PassTime, PATCH_JUMP);
+ InjectHook(0x4339F0, CPickups::GivePlayerGoodiesWithPickUpMI, PATCH_JUMP);
+ InjectHook(0x433F60, CPickups::Load, PATCH_JUMP);
+ InjectHook(0x433E40, CPickups::Save, PATCH_JUMP);
+ InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP);
+ InjectHook(0x430860, &CPickup::Update, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index 4bb0ddff..3e075b24 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -1,124 +1,124 @@
-#pragma once
-#include "Weapon.h"
-
-enum ePickupType : uint8
-{
- PICKUP_NONE = 0,
- PICKUP_IN_SHOP,
- PICKUP_ON_STREET,
- PICKUP_ONCE,
- PICKUP_ONCE_TIMEOUT,
- PICKUP_COLLECTABLE1,
- PICKUP_IN_SHOP_OUT_OF_STOCK,
- PICKUP_MONEY,
- PICKUP_MINE_INACTIVE,
- PICKUP_MINE_ARMED,
- PICKUP_NAUTICAL_MINE_INACTIVE,
- PICKUP_NAUTICAL_MINE_ARMED,
- PICKUP_FLOATINGPACKAGE,
- PICKUP_FLOATINGPACKAGE_FLOATING,
- PICKUP_ON_STREET_SLOW,
- PICKUP_NUMOFTYPES
-};
-
-class CEntity;
-class CObject;
-class CVehicle;
-class CPlayerPed;
-
-class CPickup
-{
-public:
- ePickupType m_eType;
- bool m_bRemoved;
- uint16 m_nQuantity;
- CObject *m_pObject;
- uint32 m_nTimer;
- int16 m_eModelIndex;
- uint16 m_nIndex;
- CVector m_vecPos;
-
- CObject *GiveUsAPickUpObject(int32 handle);
- bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
-private:
- bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
- inline bool CanBePickedUp(CPlayerPed *player);
- void RemoveKeepType();
- void Remove();
-};
-
-static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
-
-struct tPickupMessage
-{
- CVector2D m_pos;
- eWeaponType m_weaponType;
- CVector2D m_dist;
- CRGBA m_color;
- uint8 m_bOutOfStock : 1;
- uint8 m_quantity;
-};
-
-class CPickups
-{
- static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
- static int16 CollectedPickUpIndex;
- static int16 NumMessages;
- static tPickupMessage aMessages[NUMPICKUPMESSAGES];
-public:
- static void Init();
- static void Update();
- static void RenderPickUpText();
- static void DoCollectableEffects(CEntity *ent);
- static void DoMoneyEffects(CEntity *ent);
- static void DoMineEffects(CEntity *ent);
- static void DoPickUpEffects(CEntity *ent);
- static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
- static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
- static void RemovePickUp(int32 pickupIndex);
- static void RemoveAllFloatingPickups();
- static void AddToCollectedPickupsArray(int32 index);
- static bool IsPickUpPickedUp(int32 pickupId);
- static int32 ModelForWeapon(eWeaponType weaponType);
- static enum eWeaponType WeaponForModel(int32 model);
- static int32 FindColourIndexForWeaponMI(int32 model);
- static int32 GetActualPickupIndex(int32 index);
- static int32 GetNewUniquePickupIndex(int32 slot);
- static void PassTime(uint32 time);
- static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
- static void Load(uint8 *buf, uint32 size);
- static void Save(uint8 *buf, uint32 *size);
-
- static CPickup(&aPickUps)[NUMPICKUPS];
-
- // unused
- static bool &bPickUpcamActivated;
- static CVehicle *&pPlayerVehicle;
- static CVector &StaticCamCoors;
- static uint32 &StaticCamStartTime;
-};
-
-extern uint16 AmmoForWeapon[20];
-extern uint16 AmmoForWeapon_OnStreet[20];
-extern uint16 CostOfWeapon[20];
-
-class CPacManPickups
-{
-public:
- static void Init(void);
- static void Update(void);
- static void GeneratePMPickUps(CVector, float, int16, uint8);
- static void GeneratePMPickUpsForRace(int32);
- static void GenerateOnePMPickUp(CVector);
- static void Render(void);
- static void DoCleanUpPacManStuff(void);
- static void StartPacManRace(int32);
- static void StartPacManRecord(void);
- static uint32 QueryPowerPillsEatenInRace(void);
- static void ResetPowerPillsEatenInRace(void);
- static void CleanUpPacManStuff(void);
- static void StartPacManScramble(CVector, float, int16);
- static uint32 QueryPowerPillsCarriedByPlayer(void);
- static void ResetPowerPillsCarriedByPlayer(void);
-
-};
+#pragma once
+#include "Weapon.h"
+
+enum ePickupType : uint8
+{
+ PICKUP_NONE = 0,
+ PICKUP_IN_SHOP,
+ PICKUP_ON_STREET,
+ PICKUP_ONCE,
+ PICKUP_ONCE_TIMEOUT,
+ PICKUP_COLLECTABLE1,
+ PICKUP_IN_SHOP_OUT_OF_STOCK,
+ PICKUP_MONEY,
+ PICKUP_MINE_INACTIVE,
+ PICKUP_MINE_ARMED,
+ PICKUP_NAUTICAL_MINE_INACTIVE,
+ PICKUP_NAUTICAL_MINE_ARMED,
+ PICKUP_FLOATINGPACKAGE,
+ PICKUP_FLOATINGPACKAGE_FLOATING,
+ PICKUP_ON_STREET_SLOW,
+ PICKUP_NUMOFTYPES
+};
+
+class CEntity;
+class CObject;
+class CVehicle;
+class CPlayerPed;
+
+class CPickup
+{
+public:
+ ePickupType m_eType;
+ bool m_bRemoved;
+ uint16 m_nQuantity;
+ CObject *m_pObject;
+ uint32 m_nTimer;
+ int16 m_eModelIndex;
+ uint16 m_nIndex;
+ CVector m_vecPos;
+
+ CObject *GiveUsAPickUpObject(int32 handle);
+ bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
+private:
+ bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
+ inline bool CanBePickedUp(CPlayerPed *player);
+ void RemoveKeepType();
+ void Remove();
+};
+
+static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
+
+struct tPickupMessage
+{
+ CVector2D m_pos;
+ eWeaponType m_weaponType;
+ CVector2D m_dist;
+ CRGBA m_color;
+ uint8 m_bOutOfStock : 1;
+ uint8 m_quantity;
+};
+
+class CPickups
+{
+ static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
+ static int16 CollectedPickUpIndex;
+ static int16 NumMessages;
+ static tPickupMessage aMessages[NUMPICKUPMESSAGES];
+public:
+ static void Init();
+ static void Update();
+ static void RenderPickUpText();
+ static void DoCollectableEffects(CEntity *ent);
+ static void DoMoneyEffects(CEntity *ent);
+ static void DoMineEffects(CEntity *ent);
+ static void DoPickUpEffects(CEntity *ent);
+ static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
+ static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
+ static void RemovePickUp(int32 pickupIndex);
+ static void RemoveAllFloatingPickups();
+ static void AddToCollectedPickupsArray(int32 index);
+ static bool IsPickUpPickedUp(int32 pickupId);
+ static int32 ModelForWeapon(eWeaponType weaponType);
+ static enum eWeaponType WeaponForModel(int32 model);
+ static int32 FindColourIndexForWeaponMI(int32 model);
+ static int32 GetActualPickupIndex(int32 index);
+ static int32 GetNewUniquePickupIndex(int32 slot);
+ static void PassTime(uint32 time);
+ static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
+ static void Load(uint8 *buf, uint32 size);
+ static void Save(uint8 *buf, uint32 *size);
+
+ static CPickup(&aPickUps)[NUMPICKUPS];
+
+ // unused
+ static bool &bPickUpcamActivated;
+ static CVehicle *&pPlayerVehicle;
+ static CVector &StaticCamCoors;
+ static uint32 &StaticCamStartTime;
+};
+
+extern uint16 AmmoForWeapon[20];
+extern uint16 AmmoForWeapon_OnStreet[20];
+extern uint16 CostOfWeapon[20];
+
+class CPacManPickups
+{
+public:
+ static void Init(void);
+ static void Update(void);
+ static void GeneratePMPickUps(CVector, float, int16, uint8);
+ static void GeneratePMPickUpsForRace(int32);
+ static void GenerateOnePMPickUp(CVector);
+ static void Render(void);
+ static void DoCleanUpPacManStuff(void);
+ static void StartPacManRace(int32);
+ static void StartPacManRecord(void);
+ static uint32 QueryPowerPillsEatenInRace(void);
+ static void ResetPowerPillsEatenInRace(void);
+ static void CleanUpPacManStuff(void);
+ static void StartPacManScramble(CVector, float, int16);
+ static uint32 QueryPowerPillsCarriedByPlayer(void);
+ static void ResetPowerPillsCarriedByPlayer(void);
+
+};
diff --git a/src/control/PowerPoints.cpp b/src/control/PowerPoints.cpp
index 4bc773a9..9a74e8d9 100644
--- a/src/control/PowerPoints.cpp
+++ b/src/control/PowerPoints.cpp
@@ -1,22 +1,22 @@
-#include "common.h"
-#include "PowerPoints.h"
-
-// Some cut beta feature
-
-void CPowerPoint::Update()
-{}
-
-void CPowerPoints::Init()
-{}
-
-void CPowerPoints::Update()
-{}
-
-void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
-{}
-
-void CPowerPoints::Save(uint8**, uint32*)
-{}
-
-void CPowerPoints::Load(uint8*, uint32)
+#include "common.h"
+#include "PowerPoints.h"
+
+// Some cut beta feature
+
+void CPowerPoint::Update()
+{}
+
+void CPowerPoints::Init()
+{}
+
+void CPowerPoints::Update()
+{}
+
+void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
+{}
+
+void CPowerPoints::Save(uint8**, uint32*)
+{}
+
+void CPowerPoints::Load(uint8*, uint32)
{} \ No newline at end of file
diff --git a/src/control/PowerPoints.h b/src/control/PowerPoints.h
index d7478076..ee3750cd 100644
--- a/src/control/PowerPoints.h
+++ b/src/control/PowerPoints.h
@@ -1,26 +1,26 @@
-#pragma once
-
-enum
-{
- POWERPOINT_NONE = 0,
- POWERPOINT_HEALTH,
- POWERPOINT_HIDEOUT_INDUSTRIAL,
- POWERPOINT_HIDEOUT_COMMERCIAL,
- POWERPOINT_HIDEOUT_SUBURBAN
-};
-
-class CPowerPoint
-{
-public:
- void Update();
-};
-
-class CPowerPoints
-{
-public:
- static void Init();
- static void Update();
- static void GenerateNewOne(float, float, float, float, float, float, uint8);
- static void Save(uint8**, uint32*);
- static void Load(uint8*, uint32);
+#pragma once
+
+enum
+{
+ POWERPOINT_NONE = 0,
+ POWERPOINT_HEALTH,
+ POWERPOINT_HIDEOUT_INDUSTRIAL,
+ POWERPOINT_HIDEOUT_COMMERCIAL,
+ POWERPOINT_HIDEOUT_SUBURBAN
+};
+
+class CPowerPoint
+{
+public:
+ void Update();
+};
+
+class CPowerPoints
+{
+public:
+ static void Init();
+ static void Update();
+ static void GenerateNewOne(float, float, float, float, float, float, uint8);
+ static void Save(uint8**, uint32*);
+ static void Load(uint8*, uint32);
}; \ No newline at end of file
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index b8e2318d..0da32dd2 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1129,8 +1129,8 @@ void CReplay::StoreStuffInMem(void)
pEmptyReferences = CReferences::pEmptyList;
pStoredCam = new uint8[sizeof(CCamera)];
memcpy(pStoredCam, &TheCamera, sizeof(CCamera));
- pRadarBlips = new uint8[sizeof(CBlip) * NUMRADARBLIPS];
- memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(CBlip));
+ pRadarBlips = new uint8[sizeof(sRadarTrace) * NUMRADARBLIPS];
+ memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(sRadarTrace));
PlayerWanted = *FindPlayerPed()->m_pWanted;
PlayerInfo = CWorld::Players[0];
Time1 = CTimer::GetTimeInMilliseconds();
@@ -1179,7 +1179,7 @@ void CReplay::RestoreStuffFromMem(void)
memcpy(&TheCamera, pStoredCam, sizeof(CCamera));
delete[] pStoredCam;
pStoredCam = nil;
- memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMRADARBLIPS);
+ memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(sRadarTrace) * NUMRADARBLIPS);
delete[] pRadarBlips;
pRadarBlips = nil;
FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted);
diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp
index 8e983555..788a054a 100644
--- a/src/control/Restart.cpp
+++ b/src/control/Restart.cpp
@@ -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;
uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44;
-void
-CRestart::Initialise()
-{
- OverridePoliceStationLevel = LEVEL_NONE;
- OverrideHospitalLevel = LEVEL_NONE;
- bFadeInAfterNextArrest = true;
- bFadeInAfterNextDeath = true;
- OverrideHeading = 0.0f;
- OverridePosition = CVector(0.0f, 0.0f, 0.0f);
- bOverrideRestart = false;
- NumberOfPoliceRestarts = 0;
- NumberOfHospitalRestarts = 0;
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
- HospitalRestartHeadings[i] = 0.0f;
- PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
- PoliceRestartHeadings[i] = 0.0f;
- }
+void
+CRestart::Initialise()
+{
+ OverridePoliceStationLevel = LEVEL_NONE;
+ OverrideHospitalLevel = LEVEL_NONE;
+ bFadeInAfterNextArrest = true;
+ bFadeInAfterNextDeath = true;
+ OverrideHeading = 0.0f;
+ OverridePosition = CVector(0.0f, 0.0f, 0.0f);
+ bOverrideRestart = false;
+ NumberOfPoliceRestarts = 0;
+ NumberOfHospitalRestarts = 0;
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
+ HospitalRestartHeadings[i] = 0.0f;
+ PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
+ PoliceRestartHeadings[i] = 0.0f;
+ }
+}
+
+void
+CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
+{
+ HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
+ HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
+}
+
+void
+CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
+{
+ PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
+ PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
+}
+
+void
+CRestart::OverrideNextRestart(const CVector &pos, float heading)
+{
+ bOverrideRestart = true;
+ OverridePosition = pos;
+ OverrideHeading = heading;
}
-void
-CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
-{
- HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
- HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
+void
+CRestart::CancelOverrideRestart()
+{
+ bOverrideRestart = false;
}
-void
-CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
-{
- PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
- PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
+void
+CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
+{
+ if (bOverrideRestart) {
+ *outPos = OverridePosition;
+ *outHeading = OverrideHeading;
+ CancelOverrideRestart();
+ return;
+ }
+
+ eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ float fMinDist = 16000000.0f;
+ int closestPoint = NUM_RESTART_POINTS;
+
+ // find closest point on this level
+ for (int i = 0; i < NumberOfHospitalRestarts; i++) {
+ if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
+ float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we didn't find anything, find closest point on any level
+ if (closestPoint == NUM_RESTART_POINTS) {
+ for (int i = 0; i < NumberOfHospitalRestarts; i++) {
+ float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we still didn't find anything, find closest path node
+ if (closestPoint == NUM_RESTART_POINTS) {
+ *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
+ *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);
+ } else {
+ *outPos = HospitalRestartPoints[closestPoint];
+ *outHeading = HospitalRestartHeadings[closestPoint];
+ }
}
-void
-CRestart::OverrideNextRestart(const CVector &pos, float heading)
-{
- bOverrideRestart = true;
- OverridePosition = pos;
- OverrideHeading = heading;
+void
+CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
+{
+ if (bOverrideRestart) {
+ *outPos = OverridePosition;
+ *outHeading = OverrideHeading;
+ CancelOverrideRestart();
+ return;
+ }
+
+ eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ float fMinDist = 16000000.0f;
+ int closestPoint = NUM_RESTART_POINTS;
+
+ // find closest point on this level
+ for (int i = 0; i < NumberOfPoliceRestarts; i++) {
+ if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
+ float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we didn't find anything, find closest point on any level
+ if (closestPoint == NUM_RESTART_POINTS) {
+ for (int i = 0; i < NumberOfPoliceRestarts; i++) {
+ float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we still didn't find anything, find closest path node
+ if (closestPoint == NUM_RESTART_POINTS) {
+ printf("Couldn't find a police restart zone near the player\n");
+ *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
+ *outHeading = 0.0f;
+ } else {
+ *outPos = PoliceRestartPoints[closestPoint];
+ *outHeading = PoliceRestartHeadings[closestPoint];
+ }
}
-void
-CRestart::CancelOverrideRestart()
-{
- bOverrideRestart = false;
+void
+CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
+{
+ Initialise();
+
+INITSAVEBUF
+ CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
+ HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
+ }
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
+ PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
+ }
+
+ NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
+ NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
+ bOverrideRestart = ReadSaveBuf<bool>(buf);
+
+ // skip something unused
+ ReadSaveBuf<uint8>(buf);
+ ReadSaveBuf<uint16>(buf);
+
+ OverridePosition = ReadSaveBuf<CVector>(buf);
+ OverrideHeading = ReadSaveBuf<float>(buf);
+ bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
+ bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
+ OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
+ OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
+VALIDATESAVEBUF(size);
}
-void
-CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
-{
- if (bOverrideRestart) {
- *outPos = OverridePosition;
- *outHeading = OverrideHeading;
- CancelOverrideRestart();
- return;
- }
-
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
- float fMinDist = 16000000.0f;
- int closestPoint = NUM_RESTART_POINTS;
-
- // find closest point on this level
- for (int i = 0; i < NumberOfHospitalRestarts; i++) {
- if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
- float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we didn't find anything, find closest point on any level
- if (closestPoint == NUM_RESTART_POINTS) {
- for (int i = 0; i < NumberOfHospitalRestarts; i++) {
- float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we still didn't find anything, find closest path node
- if (closestPoint == NUM_RESTART_POINTS) {
- *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
- *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);
- } else {
- *outPos = HospitalRestartPoints[closestPoint];
- *outHeading = HospitalRestartHeadings[closestPoint];
- }
+void
+CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
+{
+ *size = SAVE_HEADER_SIZE
+ + sizeof(HospitalRestartPoints)
+ + sizeof(HospitalRestartHeadings)
+ + sizeof(PoliceRestartPoints)
+ + sizeof(PoliceRestartHeadings)
+ + sizeof(NumberOfHospitalRestarts)
+ + sizeof(NumberOfPoliceRestarts)
+ + sizeof(bOverrideRestart)
+ + sizeof(uint8)
+ + sizeof(uint16)
+ + sizeof(OverridePosition)
+ + sizeof(OverrideHeading)
+ + sizeof(bFadeInAfterNextDeath)
+ + sizeof(bFadeInAfterNextArrest)
+ + sizeof(OverrideHospitalLevel)
+ + sizeof(OverridePoliceStationLevel); // == 292
+
+INITSAVEBUF
+ WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ WriteSaveBuf(buf, HospitalRestartPoints[i]);
+ WriteSaveBuf(buf, HospitalRestartHeadings[i]);
+ }
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ WriteSaveBuf(buf, PoliceRestartPoints[i]);
+ WriteSaveBuf(buf, PoliceRestartHeadings[i]);
+ }
+
+ WriteSaveBuf(buf, NumberOfHospitalRestarts);
+ WriteSaveBuf(buf, NumberOfPoliceRestarts);
+ WriteSaveBuf(buf, bOverrideRestart);
+
+ WriteSaveBuf(buf, (uint8)0);
+ WriteSaveBuf(buf, (uint16)0);
+
+ WriteSaveBuf(buf, OverridePosition);
+ WriteSaveBuf(buf, OverrideHeading);
+ WriteSaveBuf(buf, bFadeInAfterNextDeath);
+ WriteSaveBuf(buf, bFadeInAfterNextArrest);
+ WriteSaveBuf(buf, OverrideHospitalLevel);
+ WriteSaveBuf(buf, OverridePoliceStationLevel);
+VALIDATESAVEBUF(*size);
}
-void
-CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
-{
- if (bOverrideRestart) {
- *outPos = OverridePosition;
- *outHeading = OverrideHeading;
- CancelOverrideRestart();
- return;
- }
-
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
- float fMinDist = 16000000.0f;
- int closestPoint = NUM_RESTART_POINTS;
-
- // find closest point on this level
- for (int i = 0; i < NumberOfPoliceRestarts; i++) {
- if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
- float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we didn't find anything, find closest point on any level
- if (closestPoint == NUM_RESTART_POINTS) {
- for (int i = 0; i < NumberOfPoliceRestarts; i++) {
- float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we still didn't find anything, find closest path node
- if (closestPoint == NUM_RESTART_POINTS) {
- printf("Couldn't find a police restart zone near the player\n");
- *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
- *outHeading = 0.0f;
- } else {
- *outPos = PoliceRestartPoints[closestPoint];
- *outHeading = PoliceRestartHeadings[closestPoint];
- }
-}
-
-void
-CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
-{
- Initialise();
-
-INITSAVEBUF
- CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
- HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
- }
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
- PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
- }
-
- NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
- NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
- bOverrideRestart = ReadSaveBuf<bool>(buf);
-
- // skip something unused
- ReadSaveBuf<uint8>(buf);
- ReadSaveBuf<uint16>(buf);
-
- OverridePosition = ReadSaveBuf<CVector>(buf);
- OverrideHeading = ReadSaveBuf<float>(buf);
- bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
- bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
- OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
- OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
-VALIDATESAVEBUF(size);
-}
-
-void
-CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
-{
- *size = SAVE_HEADER_SIZE
- + sizeof(HospitalRestartPoints)
- + sizeof(HospitalRestartHeadings)
- + sizeof(PoliceRestartPoints)
- + sizeof(PoliceRestartHeadings)
- + sizeof(NumberOfHospitalRestarts)
- + sizeof(NumberOfPoliceRestarts)
- + sizeof(bOverrideRestart)
- + sizeof(uint8)
- + sizeof(uint16)
- + sizeof(OverridePosition)
- + sizeof(OverrideHeading)
- + sizeof(bFadeInAfterNextDeath)
- + sizeof(bFadeInAfterNextArrest)
- + sizeof(OverrideHospitalLevel)
- + sizeof(OverridePoliceStationLevel); // == 292
-
-INITSAVEBUF
- WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- WriteSaveBuf(buf, HospitalRestartPoints[i]);
- WriteSaveBuf(buf, HospitalRestartHeadings[i]);
- }
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- WriteSaveBuf(buf, PoliceRestartPoints[i]);
- WriteSaveBuf(buf, PoliceRestartHeadings[i]);
- }
-
- WriteSaveBuf(buf, NumberOfHospitalRestarts);
- WriteSaveBuf(buf, NumberOfPoliceRestarts);
- WriteSaveBuf(buf, bOverrideRestart);
-
- WriteSaveBuf(buf, (uint8)0);
- WriteSaveBuf(buf, (uint16)0);
-
- WriteSaveBuf(buf, OverridePosition);
- WriteSaveBuf(buf, OverrideHeading);
- WriteSaveBuf(buf, bFadeInAfterNextDeath);
- WriteSaveBuf(buf, bFadeInAfterNextArrest);
- WriteSaveBuf(buf, OverrideHospitalLevel);
- WriteSaveBuf(buf, OverridePoliceStationLevel);
-VALIDATESAVEBUF(*size);
-}
-
-
+
STARTPATCHES
InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP);
InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP);
@@ -258,5 +258,5 @@ STARTPATCHES
InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP);
InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP);
InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP);
- InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
+ InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index db2c93a3..ff89f0fc 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -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;
int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200;
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;
-CScriptRectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(CScriptRectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108;
+intro_text_line (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(intro_text_line (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68;
+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;
-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;
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;
@@ -313,7 +313,7 @@ bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)
return false;
}
-void CStuckCarCheckEntry::Reset()
+void stuck_car_data::Reset()
{
m_nVehicleIndex = -1;
m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);
@@ -8442,7 +8442,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
CPad::GetPad(ScriptParams[0])->DisablePlayerControls |= PLAYERCONTROL_DISABLED_80;
pPlayerInfo->MakePlayerSafe(true);
- CCutsceneMgr::SetRunning(true);
+ CCutsceneMgr::StartCutsceneProcessing();
return 0;
}
case COMMAND_USE_TEXT_COMMANDS:
@@ -11373,15 +11373,15 @@ void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntit
continue;
CEntity* pFound = aEntities[i];
int cols;
- if (CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel()->numLines <= 0)
- cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(),
- pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, nil, nil);
+ if (pEntity->GetColModel()->numLines <= 0)
+ cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
+ pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil);
else {
float lines[4];
lines[0] = lines[1] = lines[2] = lines[3] = 1.0f;
- CColPoint tmp;
- cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(),
- pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, &tmp, lines);
+ CColPoint tmp[4];
+ cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
+ pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines);
}
if (cols <= 0)
continue;
diff --git a/src/control/Script.h b/src/control/Script.h
index 8143bd43..4338bd18 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -15,22 +15,25 @@ class CRunningScript;
#define KEY_LENGTH_IN_SCRIPT 8
-struct CScriptRectangle
+struct intro_script_rectangle
{
bool m_bIsUsed;
bool m_bBeforeFade;
int16 m_nTextureId;
CRect m_sRect;
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 {
SCRIPT_TEXT_MAX_LENGTH = 500
};
-struct CTextLine
+struct intro_text_line
{
float m_fScaleX;
float m_fScaleY;
@@ -50,6 +53,9 @@ struct CTextLine
float m_fAtY;
wchar m_Text[SCRIPT_TEXT_MAX_LENGTH];
+ intro_text_line() { }
+ ~intro_text_line() { }
+
void Reset()
{
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;
uint16 m_Index;
uint32 m_Id;
CVector m_vecCenter;
float m_fRadius;
+
+ script_sphere_struct() { }
};
struct CStoredLine
@@ -145,7 +153,7 @@ public:
bool HasCarBeenUpsideDownForAWhile(int32);
};
-struct CStuckCarCheckEntry
+struct stuck_car_data
{
int32 m_nVehicleIndex;
CVector m_vecPos;
@@ -154,12 +162,13 @@ struct CStuckCarCheckEntry
uint32 m_nStuckTime;
bool m_bStuck;
+ stuck_car_data() { }
inline void Reset();
};
class CStuckCarCheck
{
- CStuckCarCheckEntry m_sCars[MAX_STUCK_CAR_CHECKS];
+ stuck_car_data m_sCars[MAX_STUCK_CAR_CHECKS];
public:
void Init();
@@ -235,10 +244,10 @@ class CTheScripts
static CRunningScript(&ScriptsArray)[MAX_NUM_SCRIPTS];
static int32(&BaseBriefIdForContact)[MAX_NUM_CONTACTS];
static int32(&OnAMissionForContactFlag)[MAX_NUM_CONTACTS];
- static CTextLine(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES];
- static CScriptRectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES];
+ static intro_text_line(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES];
+ static intro_script_rectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES];
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 tUsedObject(&UsedObjectArray)[MAX_NUM_USED_OBJECTS];
static int32(&MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS];
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 00c838cf..91dd6573 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -142,7 +142,7 @@ CCamera::Init(void)
PlayerExhaustion = 1.0f;
DebugCamMode = CCam::MODE_NONE;
m_PedOrientForBehindOrInFront = 0.0f;
- if(!FrontEndMenuManager.m_bStartGameLoading){
+ if(!FrontEndMenuManager.m_bWantToRestart){
m_bFading = false;
CDraw::FadeValue = 0;
m_fFLOATingFade = 0.0f;
@@ -151,7 +151,7 @@ CCamera::Init(void)
m_fFLOATingFadeMusic = 0.0f;
}
m_bMoveCamToAvoidGeom = false;
- if(FrontEndMenuManager.m_bStartGameLoading)
+ if(FrontEndMenuManager.m_bWantToRestart)
m_bMoveCamToAvoidGeom = true;
m_bStartingSpline = false;
m_iTypeOfSwitch = INTERPOLATION;
@@ -3269,7 +3269,7 @@ void
CCamera::SetRwCamera(RwCamera *cam)
{
m_pRwCamera = cam;
- m_viewMatrix.Attach(&m_pRwCamera->viewMatrix, false);
+ m_viewMatrix.Attach(RwCameraGetViewMatrix(m_pRwCamera), false);
CMBlur::MotionBlurOpen(m_pRwCamera);
}
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index 6305bf33..e0c8b01e 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -311,7 +311,7 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)
int n;
RpClump *clump = (RpClump*)data;
- nodename = GetFrameNodeName(RpClumpGetFrame(atomic));
+ nodename = GetFrameNodeName(RpAtomicGetFrame(atomic));
GetNameAndLOD(nodename, name, &n);
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, nil);
if(mi){
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index 98d67fa2..beebacf9 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -555,7 +555,7 @@ void CMenuManager::DoSettingsBeforeStartingAGame()
m_PrefsVsync = m_PrefsVsyncDisp;
DMAudio.Service();
- m_bStartGameLoading = true;
+ m_bWantToRestart = true;
ShutdownJustMenu();
UnloadTextures();
@@ -2819,7 +2819,7 @@ void CMenuManager::Process(void)
if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0)
return;
- m_bStartGameLoading = false;
+ m_bWantToRestart = false;
InitialiseChangedLanguageSettings();
if (CPad::GetPad(0)->GetEscapeJustDown())
@@ -2861,9 +2861,9 @@ void CMenuManager::Process(void)
if (m_PrefsVsyncDisp != m_PrefsVsync)
m_PrefsVsync = m_PrefsVsyncDisp;
DMAudio.Service();
- m_bStartGameLoading = true;
+ m_bWantToRestart = true;
RequestFrontEndShutDown();
- m_bLoadingSavedGame = true;
+ m_bWantToLoad = true;
b_FoundRecentSavedGameWantToLoad = true;
DMAudio.SetEffectsFadeVol(0);
DMAudio.SetMusicFadeVol(0);
@@ -2960,7 +2960,7 @@ void CMenuManager::Process(void)
m_bWaitingForNewKeyBind = false;
}
- if (!m_bStartGameLoading) {
+ if (!m_bWantToRestart) {
if (m_bGameNotLoaded)
DMAudio.Service();
}
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index a97afb24..20cf9e42 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -464,7 +464,7 @@ public:
bool m_bMenuActive;
bool m_bMenuStateChanged;
bool m_bWaitingForNewKeyBind;
- bool m_bStartGameLoading;
+ bool m_bWantToRestart;
bool m_bFirstTime;
bool m_bGameNotLoaded;
int32 m_nMousePosX;
@@ -484,7 +484,7 @@ public:
bool m_bQuitGameNoCD;
bool m_bRenderGameInMenu;
bool m_bSaveMenuActive;
- bool m_bLoadingSavedGame;
+ bool m_bWantToLoad;
char field_455;
bool m_bStartWaitingForKeyBind;
bool m_bSpritesLoaded;
@@ -550,10 +550,10 @@ public:
static int32 &sthWithButtons;
static int32 &sthWithButtons2;
-#ifndef MASTER
- static bool m_PrefsMarketing;
- static bool m_PrefsDisableTutorials;
-#endif // !MASTER
+#ifndef MASTER
+ static bool m_PrefsMarketing;
+ static bool m_PrefsDisableTutorials;
+#endif // !MASTER
#ifdef MENU_MAP
static bool bMenuMapActive;
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index 8571e93e..daac3ec5 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -89,8 +89,6 @@
-#define DEFAULT_VIEWWINDOW (0.7f)
-
eLevelName &CGame::currLevel = *(eLevelName*)0x941514;
bool &CGame::bDemoMode = *(bool*)0x5F4DD0;
bool &CGame::nastyGame = *(bool*)0x5F4DD4;
@@ -492,7 +490,7 @@ void CGame::ReInitGameObjectVariables(void)
CParticle::ReloadConfig();
CCullZones::ResolveVisibilities();
- if ( !FrontEndMenuManager.m_bLoadingSavedGame )
+ if ( !FrontEndMenuManager.m_bWantToLoad )
{
CCranes::InitCranes();
CTheScripts::StartTestScript();
@@ -566,7 +564,7 @@ void CGame::InitialiseWhenRestarting(void)
TheCamera.Init();
- if ( FrontEndMenuManager.m_bLoadingSavedGame == true )
+ if ( FrontEndMenuManager.m_bWantToLoad == true )
{
RestoreForStartLoad();
CStreaming::LoadScene(TheCamera.GetPosition());
@@ -574,7 +572,7 @@ void CGame::InitialiseWhenRestarting(void)
ReInitGameObjectVariables();
- if ( FrontEndMenuManager.m_bLoadingSavedGame == true )
+ if ( FrontEndMenuManager.m_bWantToLoad == true )
{
if ( GenericLoad() == true )
{
@@ -593,7 +591,7 @@ void CGame::InitialiseWhenRestarting(void)
ShutDownForRestart();
CTimer::Stop();
CTimer::Initialise();
- FrontEndMenuManager.m_bLoadingSavedGame = false;
+ FrontEndMenuManager.m_bWantToLoad = false;
ReInitGameObjectVariables();
currLevel = LEVEL_INDUSTRIAL;
CCollision::SortOutCollisionAfterLoad();
@@ -609,6 +607,9 @@ extern void (*DebugMenuProcess)(void);
void CGame::Process(void)
{
CPad::UpdatePads();
+#ifdef GTA_PS2
+ ProcessTidyUpMemory();
+#endif
TheCamera.SetMotionBlurAlpha(0);
if (TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_SNIPER || TheCamera.m_BlurType == MBLUR_NORMAL)
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
@@ -695,6 +696,13 @@ void CGame::TidyUpMemory(bool, bool)
#endif
}
+void CGame::ProcessTidyUpMemory(void)
+{
+#ifdef PS2
+ // meow
+#endif
+}
+
STARTPATCHES
InjectHook(0x48BB80, CGame::InitialiseOnceBeforeRW, PATCH_JUMP);
InjectHook(0x48BBA0, CGame::InitialiseRenderWare, PATCH_JUMP);
diff --git a/src/core/Game.h b/src/core/Game.h
index 318ff54b..30581893 100644
--- a/src/core/Game.h
+++ b/src/core/Game.h
@@ -39,4 +39,5 @@ public:
// NB: these do something on PS2
static void TidyUpMemory(bool, bool);
static void DrasticTidyUpMemory(bool);
+ static void ProcessTidyUpMemory(void);
};
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index ff7b2fb7..b03272f9 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -29,12 +29,17 @@
#include "Replay.h"
#include "Weather.h"
#include "win.h"
+#include "Streaming.h"
+#include "PathFind.h"
+#include "Wanted.h"
+#include "General.h"
CPad *Pads = (CPad*)0x6F0360; // [2]
CMousePointerStateHelper &MousePointerStateHelper = *(CMousePointerStateHelper*)0x95CC8C;
bool &CPad::bDisplayNoControllerMessage = *(bool *)0x95CD52;
bool &CPad::bObsoleteControllerMessage = *(bool *)0x95CDB8;
+bool CPad::bOldDisplayNoControllerMessage;
bool &CPad::m_bMapPadOneToPadTwo = *(bool *)0x95CD48;
CKeyboardState &CPad::OldKeyState = *(CKeyboardState*)0x6F1E70;
@@ -50,29 +55,217 @@ CMouseControllerState &CPad::PCTempMouseControllerState = *(CMouseControllerStat
_TODO("gbFastTime");
extern bool &gbFastTime;
-WRAPPER void WeaponCheat() { EAXJMP(0x490D90); }
-WRAPPER void HealthCheat() { EAXJMP(0x490E70); }
-WRAPPER void TankCheat() { EAXJMP(0x490EE0); }
-WRAPPER void BlowUpCarsCheat() { EAXJMP(0x491040); }
-WRAPPER void ChangePlayerCheat() { EAXJMP(0x4910B0); }
-WRAPPER void MayhemCheat() { EAXJMP(0x4911C0); }
-WRAPPER void EverybodyAttacksPlayerCheat() { EAXJMP(0x491270); }
-WRAPPER void WeaponsForAllCheat() { EAXJMP(0x491370); }
-WRAPPER void FastTimeCheat() { EAXJMP(0x4913A0); }
-WRAPPER void SlowTimeCheat() { EAXJMP(0x4913F0); }
-WRAPPER void MoneyCheat() { EAXJMP(0x491430); }
-WRAPPER void ArmourCheat() { EAXJMP(0x491460); }
-WRAPPER void WantedLevelUpCheat() { EAXJMP(0x491490); }
-WRAPPER void WantedLevelDownCheat() { EAXJMP(0x4914F0); }
-WRAPPER void SunnyWeatherCheat() { EAXJMP(0x491520); }
-WRAPPER void CloudyWeatherCheat() { EAXJMP(0x491550); }
-WRAPPER void RainyWeatherCheat() { EAXJMP(0x491580); }
-WRAPPER void FoggyWeatherCheat() { EAXJMP(0x4915B0); }
-WRAPPER void FastWeatherCheat() { EAXJMP(0x4915E0); }
-WRAPPER void OnlyRenderWheelsCheat() { EAXJMP(0x491610); }
-WRAPPER void ChittyChittyBangBangCheat() { EAXJMP(0x491640); }
-WRAPPER void StrongGripCheat() { EAXJMP(0x491670); }
-WRAPPER void NastyLimbsCheat() { EAXJMP(0x4916A0); }
+void WeaponCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT2"), true);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 0);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_UZI, 100);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 20);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_AK47, 200);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_M16, 200);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_FLAMETHROWER, 200);
+}
+
+void HealthCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT3"), true);
+ FindPlayerPed()->m_fHealth = 100.0f;
+ if (FindPlayerVehicle()) {
+ FindPlayerVehicle()->m_fHealth = 1000.0f;
+ 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
@@ -89,7 +282,7 @@ void KangarooCheat()
string = TheText.Get("CHEAT1");
m_fMass = 15.0f;
}
- CHud::SetHelpMessage(string, 1);
+ CHud::SetHelpMessage(string, true);
playerPed->m_ped_flagI80 = !playerPed->m_ped_flagI80;
playerPed->m_fMass = m_fMass;
@@ -138,6 +331,21 @@ void CKeyboardState::Clear()
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)
{
NewState.Clear();
@@ -165,13 +373,13 @@ void CPad::Clear(bool bResetPlayerControls)
bApplyBrakes = false;
- for ( int32 i = 0; i < _TODOCONST(5); i++ )
+ for ( int32 i = 0; i < HORNHISTORY_SIZE; i++ )
bHornHistory[i] = false;
iCurrHornHistory = 0;
- for ( int32 i = 0; i < _TODOCONST(12); i++ )
- _unk[i] = ' ';
+ for ( int32 i = 0; i < ARRAY_SIZE(CheatString); i++ )
+ CheatString[i] = ' ';
LastTimeTouched = CTimer::GetTimeInMilliseconds();
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)
{
for ( int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i-- )
@@ -672,7 +982,7 @@ void CPad::Update(int16 unk)
ProcessPCSpecificStuff();
- if ( ++iCurrHornHistory >= _TODOCONST(5) )
+ if ( ++iCurrHornHistory >= HORNHISTORY_SIZE )
iCurrHornHistory = 0;
bHornHistory[iCurrHornHistory] = GetHorn();
@@ -689,7 +999,7 @@ void CPad::DoCheats(void)
void CPad::DoCheats(int16 unk)
{
-#ifdef PS2
+#ifdef GTA_PS2_STUFF
if ( GetTriangleJustDown() )
AddToCheatString('T');
@@ -2092,7 +2402,31 @@ int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize)
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(0x491760, &CKeyboardState::Clear, PATCH_JUMP);
InjectHook(0x491A10, &CPad::Clear, PATCH_JUMP);
diff --git a/src/core/Pad.h b/src/core/Pad.h
index ca44a9f7..78bfac1d 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -136,6 +136,10 @@ enum
class CPad
{
public:
+ enum
+ {
+ HORNHISTORY_SIZE = 5,
+ };
CControllerState NewState;
CControllerState OldState;
CControllerState PCTempKeyState;
@@ -146,11 +150,11 @@ public:
int16 Mode;
int16 ShakeDur;
uint8 ShakeFreq;
- bool bHornHistory[5];
+ bool bHornHistory[HORNHISTORY_SIZE];
uint8 iCurrHornHistory;
uint8 DisablePlayerControls;
int8 bApplyBrakes;
- char _unk[12]; //int32 unk[3];
+ char CheatString[12];
char _pad0[3];
int32 LastTimeTouched;
int32 AverageWeapon;
@@ -161,6 +165,7 @@ public:
static bool &bDisplayNoControllerMessage;
static bool &bObsoleteControllerMessage;
+ static bool bOldDisplayNoControllerMessage;
static bool &m_bMapPadOneToPadTwo;
static CKeyboardState &OldKeyState;
@@ -172,8 +177,9 @@ public:
static CMouseControllerState &PCTempMouseControllerState;
-
-
+#ifdef GTA_PS2_STUFF
+ static void Initialise(void);
+#endif
void Clear(bool bResetPlayerControls);
void ClearMouseHistory();
void UpdateMouse();
@@ -181,6 +187,9 @@ public:
void StartShake(int16 nDur, uint8 nFreq);
void StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fz);
void StartShake_Train(float fX, float fY);
+#ifdef GTA_PS2_STUFF
+ void AddToCheatString(char c);
+#endif
void AddToPCCheatString(char c);
static void UpdatePads(void);
diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp
index ead32ee7..0043c2f4 100644
--- a/src/core/PlayerInfo.cpp
+++ b/src/core/PlayerInfo.cpp
@@ -48,45 +48,45 @@ CPlayerInfo::GetPos()
void
CPlayerInfo::LoadPlayerSkin()
-{
- DeletePlayerSkin();
-
- m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName);
- if (!m_pSkinTexture)
+{
+ DeletePlayerSkin();
+
+ m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName);
+ if (!m_pSkinTexture)
m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME);
}
void
CPlayerInfo::DeletePlayerSkin()
-{
- if (m_pSkinTexture) {
- RwTextureDestroy(m_pSkinTexture);
- m_pSkinTexture = nil;
+{
+ if (m_pSkinTexture) {
+ RwTextureDestroy(m_pSkinTexture);
+ m_pSkinTexture = nil;
}
}
-void
-CPlayerInfo::KillPlayer()
-{
- if (m_WBState != WBSTATE_PLAYING) return;
-
- m_WBState = WBSTATE_WASTED;
- m_nWBTime = CTimer::GetTimeInMilliseconds();
- CDarkel::ResetOnPlayerDeath();
- CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2);
- CStats::TimesDied++;
+void
+CPlayerInfo::KillPlayer()
+{
+ if (m_WBState != WBSTATE_PLAYING) return;
+
+ m_WBState = WBSTATE_WASTED;
+ m_nWBTime = CTimer::GetTimeInMilliseconds();
+ CDarkel::ResetOnPlayerDeath();
+ CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2);
+ CStats::TimesDied++;
}
-void
-CPlayerInfo::ArrestPlayer()
-{
- if (m_WBState != WBSTATE_PLAYING) return;
-
- m_WBState = WBSTATE_BUSTED;
- m_nWBTime = CTimer::GetTimeInMilliseconds();
- CDarkel::ResetOnPlayerDeath();
- CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2);
- CStats::TimesArrested++;
+void
+CPlayerInfo::ArrestPlayer()
+{
+ if (m_WBState != WBSTATE_PLAYING) return;
+
+ m_WBState = WBSTATE_BUSTED;
+ m_nWBTime = CTimer::GetTimeInMilliseconds();
+ CDarkel::ResetOnPlayerDeath();
+ CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2);
+ CStats::TimesArrested++;
}
bool
@@ -105,102 +105,102 @@ CPlayerInfo::PlayerFailedCriticalMission()
CDarkel::ResetOnPlayerDeath();
}
-void
-CPlayerInfo::Clear(void)
-{
- m_pPed = nil;
- m_pRemoteVehicle = nil;
- if (m_pVehicleEx) {
- m_pVehicleEx->bUsingSpecialColModel = false;
- m_pVehicleEx = nil;
- }
- m_nVisibleMoney = 0;
- m_nMoney = m_nVisibleMoney;
- m_WBState = WBSTATE_PLAYING;
- m_nWBTime = 0;
- m_nTrafficMultiplier = 0;
- m_fRoadDensity = 1.0f;
- m_bInRemoteMode = false;
- m_bUnusedTaxiThing = false;
- m_nUnusedTaxiTimer = 0;
- m_nCollectedPackages = 0;
- m_nTotalPackages = 3;
- m_nTimeLastHealthLoss = 0;
- m_nTimeLastArmourLoss = 0;
- m_nNextSexFrequencyUpdateTime = 0;
- m_nNextSexMoneyUpdateTime = 0;
- m_nSexFrequency = 0;
- m_pHooker = nil;
- m_nTimeTankShotGun = 0;
- field_248 = 0;
- m_nUpsideDownCounter = 0;
- m_bInfiniteSprint = false;
- m_bFastReload = false;
- m_bGetOutOfJailFree = false;
- m_bGetOutOfHospitalFree = false;
- m_nPreviousTimeRewardedForExplosion = 0;
- m_nExplosionsSinceLastReward = 0;
+void
+CPlayerInfo::Clear(void)
+{
+ m_pPed = nil;
+ m_pRemoteVehicle = nil;
+ if (m_pVehicleEx) {
+ m_pVehicleEx->bUsingSpecialColModel = false;
+ m_pVehicleEx = nil;
+ }
+ m_nVisibleMoney = 0;
+ m_nMoney = m_nVisibleMoney;
+ m_WBState = WBSTATE_PLAYING;
+ m_nWBTime = 0;
+ m_nTrafficMultiplier = 0;
+ m_fRoadDensity = 1.0f;
+ m_bInRemoteMode = false;
+ m_bUnusedTaxiThing = false;
+ m_nUnusedTaxiTimer = 0;
+ m_nCollectedPackages = 0;
+ m_nTotalPackages = 3;
+ m_nTimeLastHealthLoss = 0;
+ m_nTimeLastArmourLoss = 0;
+ m_nNextSexFrequencyUpdateTime = 0;
+ m_nNextSexMoneyUpdateTime = 0;
+ m_nSexFrequency = 0;
+ m_pHooker = nil;
+ m_nTimeTankShotGun = 0;
+ field_248 = 0;
+ m_nUpsideDownCounter = 0;
+ m_bInfiniteSprint = false;
+ m_bFastReload = false;
+ m_bGetOutOfJailFree = false;
+ m_bGetOutOfHospitalFree = false;
+ m_nPreviousTimeRewardedForExplosion = 0;
+ m_nExplosionsSinceLastReward = 0;
}
-void
-CPlayerInfo::BlowUpRCBuggy(void)
-{
- if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld)
- return;
-
- CRemote::TakeRemoteControlledCarFromPlayer();
- m_pRemoteVehicle->BlowUpCar(FindPlayerPed());
+void
+CPlayerInfo::BlowUpRCBuggy(void)
+{
+ if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld)
+ return;
+
+ CRemote::TakeRemoteControlledCarFromPlayer();
+ 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
+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
-CPlayerInfo::MakePlayerSafe(bool toggle)
-{
- if (toggle) {
- CTheScripts::ResetCountdownToMakePlayerUnsafe();
- m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
- CWorld::StopAllLawEnforcersInTheirTracks();
- CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
- CPad::StopPadsShaking();
- m_pPed->bBulletProof = true;
- m_pPed->bFireProof = true;
- m_pPed->bCollisionProof = true;
- m_pPed->bMeleeProof = true;
- m_pPed->bOnlyDamagedByPlayer = true;
- m_pPed->bExplosionProof = true;
- m_pPed->m_bCanBeDamaged = false;
- ((CPlayerPed*)m_pPed)->ClearAdrenaline();
- CancelPlayerEnteringCars(false);
- gFireManager.ExtinguishPoint(GetPos(), 4000.0f);
- CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f);
- CProjectileInfo::RemoveAllProjectiles();
- CWorld::SetAllCarsCanBeDamaged(false);
- CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
- CReplay::DisableReplays();
-
- } 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();
- }
+void
+CPlayerInfo::MakePlayerSafe(bool toggle)
+{
+ if (toggle) {
+ CTheScripts::ResetCountdownToMakePlayerUnsafe();
+ m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
+ CWorld::StopAllLawEnforcersInTheirTracks();
+ CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
+ CPad::StopPadsShaking();
+ m_pPed->bBulletProof = true;
+ m_pPed->bFireProof = true;
+ m_pPed->bCollisionProof = true;
+ m_pPed->bMeleeProof = true;
+ m_pPed->bOnlyDamagedByPlayer = true;
+ m_pPed->bExplosionProof = true;
+ m_pPed->m_bCanBeDamaged = false;
+ ((CPlayerPed*)m_pPed)->ClearAdrenaline();
+ CancelPlayerEnteringCars(false);
+ gFireManager.ExtinguishPoint(GetPos(), 4000.0f);
+ CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f);
+ CProjectileInfo::RemoveAllProjectiles();
+ CWorld::SetAllCarsCanBeDamaged(false);
+ CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
+ CReplay::DisableReplays();
+
+ } 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
@@ -216,347 +216,347 @@ CPlayerInfo::IsRestartingAfterArrest()
}
// lastCloseness is passed to other calls of this function
-void
-CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput)
-{
- // This dist used for determining the angle to face
- CVector2D dist(carToTest->GetPosition() - player->GetPosition());
- float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y);
- while (neededTurn >= PI) {
- neededTurn -= 2 * PI;
- }
-
- while (neededTurn < -PI) {
- neededTurn += 2 * PI;
- }
-
- // This dist used for evaluating cars' distances, weird...
- // Accounts inverted needed turn (or needed turn in long way) and car dist.
- float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist);
- if (closeness > *lastCloseness) {
- *lastCloseness = closeness;
- *closestCarOutput = (CVehicle*)carToTest;
- }
+void
+CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput)
+{
+ // This dist used for determining the angle to face
+ CVector2D dist(carToTest->GetPosition() - player->GetPosition());
+ float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y);
+ while (neededTurn >= PI) {
+ neededTurn -= 2 * PI;
+ }
+
+ while (neededTurn < -PI) {
+ neededTurn += 2 * PI;
+ }
+
+ // This dist used for evaluating cars' distances, weird...
+ // Accounts inverted needed turn (or needed turn in long way) and car dist.
+ float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist);
+ if (closeness > *lastCloseness) {
+ *lastCloseness = closeness;
+ *closestCarOutput = (CVehicle*)carToTest;
+ }
}
// There is something unfinished in here... Sadly all IDBs we have have it unfinished.
-void
-CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar)
-{
- if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000)
- ++m_nExplosionsSinceLastReward;
- else
- m_nExplosionsSinceLastReward = 1;
-
- m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds();
- int award = wreckedCar->pHandling->nMonetaryValue * 0.002f;
- sprintf(gString, "$%d", award);
-#ifdef MONEY_MESSAGES
- // This line is a leftover from PS2, I don't know what it was meant to be.
- // 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);
-#endif
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
-
- for (int i = m_nExplosionsSinceLastReward; i > 1; --i) {
- CGeneral::GetRandomNumber();
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
- }
+void
+CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar)
+{
+ if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000)
+ ++m_nExplosionsSinceLastReward;
+ else
+ m_nExplosionsSinceLastReward = 1;
+
+ m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds();
+ int award = wreckedCar->pHandling->nMonetaryValue * 0.002f;
+ sprintf(gString, "$%d", award);
+#ifdef MONEY_MESSAGES
+ // This line is a leftover from PS2, I don't know what it was meant to be.
+ // 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);
+#endif
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
+
+ for (int i = m_nExplosionsSinceLastReward; i > 1; --i) {
+ CGeneral::GetRandomNumber();
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
+ }
}
-void
-CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size)
-{
- // Interesting
- *size = sizeof(CPlayerInfo);
-
-INITSAVEBUF
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);
- for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
- WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i]);
- }
-// Save struct is different
-// VALIDATESAVEBUF(*size)
+void
+CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size)
+{
+ // Interesting
+ *size = sizeof(CPlayerInfo);
+
+INITSAVEBUF
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);
+ for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i]);
+ }
+// Save struct is different
+// VALIDATESAVEBUF(*size)
}
-void
-CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size)
-{
-INITSAVEBUF
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney = ReadSaveBuf<uint32>(buf);
- CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf<int8>(buf);
- CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf<uint32>(buf);
- CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf<int16>(buf);
- CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf<float>(buf);
- CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = 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_bInfiniteSprint = 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_bGetOutOfHospitalFree = ReadSaveBuf<bool>(buf);
- for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
- CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf<char>(buf);
- }
-// Save struct is different
-// VALIDATESAVEBUF(size)
+void
+CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size)
+{
+INITSAVEBUF
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = ReadSaveBuf<uint32>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf<int8>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf<uint32>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf<int16>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf<float>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = 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_bInfiniteSprint = 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_bGetOutOfHospitalFree = ReadSaveBuf<bool>(buf);
+ for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
+ CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf<char>(buf);
+ }
+// Save struct is different
+// VALIDATESAVEBUF(size)
}
-void
-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) {
- CVehicle *car = (CVehicle*)node->item;
- if(car->m_scanCode != CWorld::GetCurrentScanCode()) {
- if (!car->bUsesCollision || !car->IsVehicle())
- continue;
-
- car->m_scanCode = CWorld::GetCurrentScanCode();
- 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))) {
- CVector carCentre = car->GetBoundCentre();
-
- if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) {
- float dist = (ped->GetPosition() - carCentre).Magnitude2D();
- if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
- EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput);
- }
- }
- }
- }
- }
+void
+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) {
+ CVehicle *car = (CVehicle*)node->item;
+ if(car->m_scanCode != CWorld::GetCurrentScanCode()) {
+ if (!car->bUsesCollision || !car->IsVehicle())
+ continue;
+
+ car->m_scanCode = CWorld::GetCurrentScanCode();
+ 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))) {
+ CVector carCentre = car->GetBoundCentre();
+
+ if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) {
+ float dist = (ped->GetPosition() - carCentre).Magnitude2D();
+ if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
+ EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput);
+ }
+ }
+ }
+ }
+ }
}
-void
-CPlayerInfo::Process(void)
-{
- // Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode.
- bool startTaxiTimer = true;
- if (m_bUnusedTaxiThing && m_pPed->bInVehicle) {
- CVehicle *veh = m_pPed->m_pMyVehicle;
- if ((veh->m_modelIndex == MI_TAXI || veh->m_modelIndex == MI_CABBIE || veh->m_modelIndex == MI_BORGNINE)
- && veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) {
- for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) {
- timePassed -= 1000;
- ++m_nMoney;
- }
- startTaxiTimer = false;
- }
- }
- if (startTaxiTimer)
- m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
-
- // The effect that makes money counter does while earning/losing money
- if (m_nVisibleMoney != m_nMoney) {
- int diff = m_nMoney - m_nVisibleMoney;
- int diffAbs = Abs(diff);
- int changeBy;
-
- if (diffAbs > 100000)
- changeBy = 12345;
- else if (diffAbs > 10000)
- changeBy = 1234;
- else if (diffAbs > 1000)
- changeBy = 123;
- else if (diffAbs > 50)
- changeBy = 42;
- else
- changeBy = 1;
-
- if (diff < 0)
- m_nVisibleMoney -= changeBy;
- else
- m_nVisibleMoney += changeBy;
- }
-
- if (!(CTimer::GetFrameCounter() & 15)) {
- CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition();
- m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y);
- }
-
- m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f);
-
- // Because vehicle enter/exit use same key binding.
- bool enterOrExitVeh;
- if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle)
- enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown();
- else
- enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle();
-
- if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_ODE) {
- if (m_pPed->bInVehicle) {
- if (!m_pRemoteVehicle) {
- CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity;
- if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->m_modelIndex)) {
- CVehicle *veh = m_pPed->m_pMyVehicle;
- if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
-
- // 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_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) {
- m_pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh);
- }
- }
- } else {
- CVector sth = 0.7f * veh->GetRight() + veh->GetPosition();
- bool found = false;
- float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found);
-
- if (found)
- sth.z = 1.0f + groundZ;
- m_pPed->m_nPedState = PED_IDLE;
- m_pPed->SetMoveState(PEDMOVE_STILL);
- CPed::PedSetOutCarCB(0, m_pPed);
- 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);
- m_pPed->GetPosition() = sth;
- m_pPed->SetMoveState(PEDMOVE_STILL);
- m_pPed->m_vecMoveSpeed = veh->m_vecMoveSpeed;
- }
- } else {
- // The code in here was under CPed::SetExitBoat in VC, did the same for here.
- m_pPed->SetExitBoat(veh);
- m_pPed->bTryingToReachDryLand = true;
- }
- }
- }
- } else {
- // Enter vehicle
- if (CPad::GetPad(0)->ExitVehicleJustDown()) {
- bool weAreOnBoat = false;
- float lastCloseness = 0.0f;
- CVehicle *carBelow = nil;
- CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface;
- if (surfaceBelow && surfaceBelow->IsVehicle()) {
- carBelow = (CVehicle*)surfaceBelow;
- if (carBelow->IsBoat()) {
- weAreOnBoat = true;
- m_pPed->bOnBoat = true;
-#ifdef VC_PED_PORTS
- if (carBelow->m_status != STATUS_WRECKED && carBelow->GetUp().z > 0.3f)
-#else
- if (carBelow->m_status != STATUS_WRECKED)
-#endif
- m_pPed->SetSeekBoatPosition(carBelow);
- }
- }
- // Find closest car
- if (!weAreOnBoat) {
- float minX = m_pPed->GetPosition().x - 10.0f;
- float maxX = 10.0f + m_pPed->GetPosition().x;
- float minY = m_pPed->GetPosition().y - 10.0f;
- float maxY = 10.0f + m_pPed->GetPosition().y;
-
- int minXSector = CWorld::GetSectorIndexX(minX);
- if (minXSector < 0) minXSector = 0;
- int minYSector = CWorld::GetSectorIndexY(minY);
- if (minYSector < 0) minYSector = 0;
- int maxXSector = CWorld::GetSectorIndexX(maxX);
- if (maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1;
- int maxYSector = CWorld::GetSectorIndexY(maxY);
- if (maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1;
-
- CWorld::AdvanceCurrentScanCode();
-
- for (int curY = minYSector; curY <= maxYSector; curY++) {
- for (int curX = minXSector; curX <= maxXSector; curX++) {
- CSector *sector = CWorld::GetSector(curX, curY);
- FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed,
- minX, minY, maxX, maxY, &lastCloseness, &carBelow);
- FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed,
- minX, minY, maxX, maxY, &lastCloseness, &carBelow);
- }
- }
- }
- // carBelow is now closest vehicle
- if (carBelow && !weAreOnBoat) {
- if (carBelow->m_status == STATUS_TRAIN_NOT_MOVING) {
- m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, carBelow);
- } else if (carBelow->IsBoat()) {
- if (!carBelow->pDriver) {
- m_pPed->m_vehEnterType = 0;
- m_pPed->SetEnterCar(carBelow, m_pPed->m_vehEnterType);
- }
- } else {
- m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carBelow);
- }
- }
- }
- }
- }
- if (m_bInRemoteMode) {
- uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar;
- if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) {
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(1.0f, 0);
- }
- if (timeWithoutRemoteCar > 2000) {
- if (m_WBState == WBSTATE_PLAYING) {
- TheCamera.RestoreWithJumpCut();
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(1.0f, 1);
- TheCamera.Process();
- CTimer::Stop();
- CCullZones::ForceCullZoneCoors(TheCamera.GetPosition());
- CRenderer::RequestObjectsInFrustum();
- CStreaming::LoadAllRequestedModels(false);
- CTimer::Update();
- }
- m_bInRemoteMode = false;
- CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil;
- if (FindPlayerVehicle()) {
- FindPlayerVehicle()->m_status = STATUS_PLAYER;
- }
- }
- }
- if (!(CTimer::GetFrameCounter() & 31)) {
- CVehicle *veh = FindPlayerVehicle();
- if (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f
- && veh->m_vecMoveSpeed.Magnitude() < 0.05f && veh->IsCar() && !veh->bIsInWater) {
-
- if (veh->GetUp().z < -0.5f) {
- m_nUpsideDownCounter += 2;
-
- } else {
- m_nUpsideDownCounter++;
- }
- } else {
- m_nUpsideDownCounter = 0;
- }
-
- if (m_nUpsideDownCounter > 6 && veh->bCanBeDamaged) {
- veh->m_fHealth = 249.0f < veh->m_fHealth ? 249.0f : veh->m_fHealth;
- if (veh->IsCar()) {
- CAutomobile* car = (CAutomobile*)veh;
- car->Damage.SetEngineStatus(225);
- car->m_pSetOnFireEntity = nil;
- }
- }
- }
- if (FindPlayerVehicle()) {
- CVehicle *veh = FindPlayerVehicle();
- veh->m_nZoneLevel = -1;
- for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {
- if (veh->pPassengers[i])
- veh->pPassengers[i]->m_nZoneLevel = 0;
- }
- CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled;
- } else {
- CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled;
- }
+void
+CPlayerInfo::Process(void)
+{
+ // Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode.
+ bool startTaxiTimer = true;
+ if (m_bUnusedTaxiThing && m_pPed->bInVehicle) {
+ CVehicle *veh = m_pPed->m_pMyVehicle;
+ if ((veh->m_modelIndex == MI_TAXI || veh->m_modelIndex == MI_CABBIE || veh->m_modelIndex == MI_BORGNINE)
+ && veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) {
+ for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) {
+ timePassed -= 1000;
+ ++m_nMoney;
+ }
+ startTaxiTimer = false;
+ }
+ }
+ if (startTaxiTimer)
+ m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();
+
+ // The effect that makes money counter does while earning/losing money
+ if (m_nVisibleMoney != m_nMoney) {
+ int diff = m_nMoney - m_nVisibleMoney;
+ int diffAbs = Abs(diff);
+ int changeBy;
+
+ if (diffAbs > 100000)
+ changeBy = 12345;
+ else if (diffAbs > 10000)
+ changeBy = 1234;
+ else if (diffAbs > 1000)
+ changeBy = 123;
+ else if (diffAbs > 50)
+ changeBy = 42;
+ else
+ changeBy = 1;
+
+ if (diff < 0)
+ m_nVisibleMoney -= changeBy;
+ else
+ m_nVisibleMoney += changeBy;
+ }
+
+ if (!(CTimer::GetFrameCounter() & 15)) {
+ CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition();
+ m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y);
+ }
+
+ m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f);
+
+ // Because vehicle enter/exit use same key binding.
+ bool enterOrExitVeh;
+ if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle)
+ enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown();
+ else
+ enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle();
+
+ if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_ODE) {
+ if (m_pPed->bInVehicle) {
+ if (!m_pRemoteVehicle) {
+ CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity;
+ if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->m_modelIndex)) {
+ CVehicle *veh = m_pPed->m_pMyVehicle;
+ if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {
+
+ // 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_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) {
+ m_pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh);
+ }
+ }
+ } else {
+ CVector sth = 0.7f * veh->GetRight() + veh->GetPosition();
+ bool found = false;
+ float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found);
+
+ if (found)
+ sth.z = 1.0f + groundZ;
+ m_pPed->m_nPedState = PED_IDLE;
+ m_pPed->SetMoveState(PEDMOVE_STILL);
+ CPed::PedSetOutCarCB(0, m_pPed);
+ 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);
+ m_pPed->GetPosition() = sth;
+ m_pPed->SetMoveState(PEDMOVE_STILL);
+ m_pPed->m_vecMoveSpeed = veh->m_vecMoveSpeed;
+ }
+ } else {
+ // The code in here was under CPed::SetExitBoat in VC, did the same for here.
+ m_pPed->SetExitBoat(veh);
+ m_pPed->bTryingToReachDryLand = true;
+ }
+ }
+ }
+ } else {
+ // Enter vehicle
+ if (CPad::GetPad(0)->ExitVehicleJustDown()) {
+ bool weAreOnBoat = false;
+ float lastCloseness = 0.0f;
+ CVehicle *carBelow = nil;
+ CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface;
+ if (surfaceBelow && surfaceBelow->IsVehicle()) {
+ carBelow = (CVehicle*)surfaceBelow;
+ if (carBelow->IsBoat()) {
+ weAreOnBoat = true;
+ m_pPed->bOnBoat = true;
+#ifdef VC_PED_PORTS
+ if (carBelow->m_status != STATUS_WRECKED && carBelow->GetUp().z > 0.3f)
+#else
+ if (carBelow->m_status != STATUS_WRECKED)
+#endif
+ m_pPed->SetSeekBoatPosition(carBelow);
+ }
+ }
+ // Find closest car
+ if (!weAreOnBoat) {
+ float minX = m_pPed->GetPosition().x - 10.0f;
+ float maxX = 10.0f + m_pPed->GetPosition().x;
+ float minY = m_pPed->GetPosition().y - 10.0f;
+ float maxY = 10.0f + m_pPed->GetPosition().y;
+
+ int minXSector = CWorld::GetSectorIndexX(minX);
+ if (minXSector < 0) minXSector = 0;
+ int minYSector = CWorld::GetSectorIndexY(minY);
+ if (minYSector < 0) minYSector = 0;
+ int maxXSector = CWorld::GetSectorIndexX(maxX);
+ if (maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1;
+ int maxYSector = CWorld::GetSectorIndexY(maxY);
+ if (maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1;
+
+ CWorld::AdvanceCurrentScanCode();
+
+ for (int curY = minYSector; curY <= maxYSector; curY++) {
+ for (int curX = minXSector; curX <= maxXSector; curX++) {
+ CSector *sector = CWorld::GetSector(curX, curY);
+ FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed,
+ minX, minY, maxX, maxY, &lastCloseness, &carBelow);
+ FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed,
+ minX, minY, maxX, maxY, &lastCloseness, &carBelow);
+ }
+ }
+ }
+ // carBelow is now closest vehicle
+ if (carBelow && !weAreOnBoat) {
+ if (carBelow->m_status == STATUS_TRAIN_NOT_MOVING) {
+ m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, carBelow);
+ } else if (carBelow->IsBoat()) {
+ if (!carBelow->pDriver) {
+ m_pPed->m_vehEnterType = 0;
+ m_pPed->SetEnterCar(carBelow, m_pPed->m_vehEnterType);
+ }
+ } else {
+ m_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carBelow);
+ }
+ }
+ }
+ }
+ }
+ if (m_bInRemoteMode) {
+ uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar;
+ if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) {
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(1.0f, 0);
+ }
+ if (timeWithoutRemoteCar > 2000) {
+ if (m_WBState == WBSTATE_PLAYING) {
+ TheCamera.RestoreWithJumpCut();
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(1.0f, 1);
+ TheCamera.Process();
+ CTimer::Stop();
+ CCullZones::ForceCullZoneCoors(TheCamera.GetPosition());
+ CRenderer::RequestObjectsInFrustum();
+ CStreaming::LoadAllRequestedModels(false);
+ CTimer::Update();
+ }
+ m_bInRemoteMode = false;
+ CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil;
+ if (FindPlayerVehicle()) {
+ FindPlayerVehicle()->m_status = STATUS_PLAYER;
+ }
+ }
+ }
+ if (!(CTimer::GetFrameCounter() & 31)) {
+ CVehicle *veh = FindPlayerVehicle();
+ if (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f
+ && veh->m_vecMoveSpeed.Magnitude() < 0.05f && veh->IsCar() && !veh->bIsInWater) {
+
+ if (veh->GetUp().z < -0.5f) {
+ m_nUpsideDownCounter += 2;
+
+ } else {
+ m_nUpsideDownCounter++;
+ }
+ } else {
+ m_nUpsideDownCounter = 0;
+ }
+
+ if (m_nUpsideDownCounter > 6 && veh->bCanBeDamaged) {
+ veh->m_fHealth = 249.0f < veh->m_fHealth ? 249.0f : veh->m_fHealth;
+ if (veh->IsCar()) {
+ CAutomobile* car = (CAutomobile*)veh;
+ car->Damage.SetEngineStatus(225);
+ car->m_pSetOnFireEntity = nil;
+ }
+ }
+ }
+ if (FindPlayerVehicle()) {
+ CVehicle *veh = FindPlayerVehicle();
+ veh->m_nZoneLevel = -1;
+ for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {
+ if (veh->pPassengers[i])
+ veh->pPassengers[i]->m_nZoneLevel = 0;
+ }
+ CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled;
+ } else {
+ CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled;
+ }
}
STARTPATCHES
diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp
index 07ddb5d8..994c94ca 100644
--- a/src/core/Radar.cpp
+++ b/src/core/Radar.cpp
@@ -1,1504 +1,1506 @@
-#include "config.h"
-#include "common.h"
-#include "patcher.h"
-#include "RwHelper.h"
-#include "Radar.h"
-#include "Camera.h"
-#include "Hud.h"
-#include "World.h"
-#include "Frontend.h"
-#include "General.h"
-#include "Vehicle.h"
-#include "Pools.h"
-#include "Script.h"
-#include "TxdStore.h"
-#include "World.h"
-#include "Streaming.h"
-#include "SpecialFX.h"
-
-float &CRadar::m_radarRange = *(float*)0x8E281C;
-CBlip (&CRadar::ms_RadarTrace)[NUMRADARBLIPS] = *(CBlip(*)[NUMRADARBLIPS]) * (uintptr*)0x6ED5E0;
-CVector2D &vec2DRadarOrigin = *(CVector2D*)0x6299B8;
-int32 gRadarTxdIds[64];// = (int*)0x6299C0;
-
-CSprite2d CRadar::AsukaSprite;// = *(CSprite2d*)0x8F1A40;
-CSprite2d CRadar::BombSprite;// = (CSprite2d*)0x8F5FB4;
-CSprite2d CRadar::CatSprite;// = (CSprite2d*)0x885B24;
-CSprite2d CRadar::CentreSprite;// = (CSprite2d*)0x8F6268;
-CSprite2d CRadar::CopcarSprite;// = (CSprite2d*)0x8F1A2C;
-CSprite2d CRadar::DonSprite;// = (CSprite2d*)0x8F2BE0;
-CSprite2d CRadar::EightSprite;// = (CSprite2d*)0x8F2BCC;
-CSprite2d CRadar::ElSprite;// = (CSprite2d*)0x8F1B80;
-CSprite2d CRadar::IceSprite;// = (CSprite2d*)0x9415FC;
-CSprite2d CRadar::JoeySprite;// = (CSprite2d*)0x8F2C00;
-CSprite2d CRadar::KenjiSprite;// = (CSprite2d*)0x8F2C68;
-CSprite2d CRadar::LizSprite;// = (CSprite2d*)0x8F5830;
-CSprite2d CRadar::LuigiSprite;// = (CSprite2d*)0x8F1A3C;
-CSprite2d CRadar::NorthSprite;// = (CSprite2d*)0x8F6274;
-CSprite2d CRadar::RaySprite;// = (CSprite2d*)0x8E2A7C;
-CSprite2d CRadar::SalSprite;// = (CSprite2d*)0x8F29EC;
-CSprite2d CRadar::SaveSprite;// = (CSprite2d*)0x8F5F74;
-CSprite2d CRadar::SpraySprite;// = (CSprite2d*)0x94307C;
-CSprite2d CRadar::TonySprite;// = (CSprite2d*)0x885B58;
-CSprite2d CRadar::WeaponSprite;// = (CSprite2d*)0x941534;
-
-CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = {
- nil,
- &AsukaSprite,
- &BombSprite,
- &CatSprite,
- &CentreSprite,
- &CopcarSprite,
- &DonSprite,
- &EightSprite,
- &ElSprite,
- &IceSprite,
- &JoeySprite,
- &KenjiSprite,
- &LizSprite,
- &LuigiSprite,
- &NorthSprite,
- &RaySprite,
- &SalSprite,
- &SaveSprite,
- &SpraySprite,
- &TonySprite,
- &WeaponSprite
-};
-
-#define RADAR_NUM_TILES (8)
-#define RADAR_TILE_SIZE (WORLD_SIZE_X / RADAR_NUM_TILES)
-static_assert(RADAR_TILE_SIZE == (WORLD_SIZE_Y / RADAR_NUM_TILES), "CRadar: not a square");
-
-#define RADAR_MIN_RANGE (120.0f)
-#define RADAR_MAX_RANGE (350.0f)
-#define RADAR_MIN_SPEED (0.3f)
-#define RADAR_MAX_SPEED (0.9f)
-
-#ifdef MENU_MAP
-CRGBA CRadar::ArrowBlipColour1;
-CRGBA CRadar::ArrowBlipColour2;
-uint16 CRadar::MapLegendCounter;
-uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS];
-int CRadar::TargetMarkerId = -1;
-#endif
-
-// taken from VC
-float CRadar::cachedCos;
-float CRadar::cachedSin;
-
-uint8 CRadar::CalculateBlipAlpha(float dist)
-{
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive)
- return 255;
-#endif
- if (dist <= 1.0f)
- return 255;
-
- if (dist <= 5.0f)
- return (128.0f * ((dist - 1.0f) / 4.0f)) + ((1.0f - (dist - 1.0f) / 4.0f) * 255.0f);
-
- return 128;
-}
-
-void CRadar::ChangeBlipBrightness(int32 i, int32 bright)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_bDim = bright != 1;
-}
-
-void CRadar::ChangeBlipColour(int32 i, int32 color)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_nColor = color;
-}
-
-void CRadar::ChangeBlipDisplay(int32 i, eBlipDisplay display)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_eBlipDisplay = display;
-}
-
-void CRadar::ChangeBlipScale(int32 i, int32 scale)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_wScale = scale;
-}
-
-void CRadar::ClearBlip(int32 i)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1) {
- SetRadarMarkerState(index, false);
- ms_RadarTrace[index].m_bInUse = false;
-#ifndef MENU_MAP
- // Ssshhh
- ms_RadarTrace[index].m_eBlipType = BLIP_NONE;
- ms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
- ms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE;
-#endif
- }
-}
-
-void CRadar::ClearBlipForEntity(eBlipType type, int32 id)
-{
- for (int i = 0; i < NUMRADARBLIPS; i++) {
- if (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) {
- SetRadarMarkerState(i, false);
- ms_RadarTrace[i].m_bInUse = false;
- ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
- ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
- ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
- }
- };
-}
-
-// Why not a proper clipping algorithm?
-int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect)
-{
- CVector2D corners[4] = {
- { 1.0f, -1.0f }, // top right
- { 1.0f, 1.0f }, // bottom right
- { -1.0f, 1.0f }, // bottom left
- { -1.0f, -1.0f }, // top left
- };
- CVector2D tmp;
- int i, j, n;
- int laste, e, e1, e2;;
- bool inside[4];
-
- for (i = 0; i < 4; i++)
- inside[i] = IsPointInsideRadar(rect[i]);
-
- laste = -1;
- n = 0;
- for (i = 0; i < 4; i++)
- if (inside[i]) {
- // point is inside, just add
- poly[n++] = rect[i];
- }
- else {
- // point is outside but line to this point might be clipped
- e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 4 - 1) % 4]);
- if (e1 != -1) {
- laste = e1;
- n++;
- }
- // and line from this point might be clipped as well
- e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 1) % 4]);
- if (e2 != -1) {
- if (e1 == -1) {
- // if other line wasn't clipped, i.e. it was complete outside,
- // we may have to insert another vertex if last clipped line
- // was on a different edge
-
- // find the last intersection if we haven't seen it yet
- if (laste == -1)
- for (j = 3; j >= i; j--) {
- // game uses an if here for j == 0
- e = LineRadarBoxCollision(tmp, rect[j], rect[(j + 4 - 1) % 4]);
- if (e != -1) {
- laste = e;
- break;
- }
- }
- assert(laste != -1);
-
- // insert corners that were skipped
- tmp = poly[n];
- for (e = laste; e != e2; e = (e + 1) % 4)
- poly[n++] = corners[e];
- poly[n] = tmp;
- }
- n++;
- }
- }
-
- if (n == 0) {
- // If no points, either the rectangle is completely outside or completely surrounds the radar
- // no idea what's going on here...
- float m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x);
- if ((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
- m = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x);
- if ((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
- poly[0] = corners[0];
- poly[1] = corners[1];
- poly[2] = corners[2];
- poly[3] = corners[3];
- n = 4;
- }
- }
- }
-
- return n;
-}
-
-bool CRadar::DisplayThisBlip(int32 counter)
-{
- switch (ms_RadarTrace[counter].m_eRadarSprite) {
- case RADAR_SPRITE_BOMB:
- case RADAR_SPRITE_SPRAY:
- case RADAR_SPRITE_WEAPON:
- return true;
- default:
- return false;
- }
-}
-
-void CRadar::Draw3dMarkers()
-{
- for (int i = 0; i < NUMRADARBLIPS; i++) {
- if (ms_RadarTrace[i].m_bInUse) {
- switch (ms_RadarTrace[i].m_eBlipType) {
- case BLIP_CAR:
- {
- CEntity *entity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- CVector pos = entity->GetPosition();
- pos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f;
- C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
- }
- break;
- }
- case BLIP_CHAR:
- {
- CEntity *entity = CPools::GetPedPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
- if (entity != nil) {
- if (((CPed*)entity)->InVehicle())
- entity = ((CPed * )entity)->m_pMyVehicle;
- }
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- CVector pos = entity->GetPosition();
- pos.z += 3.0f;
- C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
- }
- break;
- }
- case BLIP_OBJECT:
- {
- CEntity *entity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- CVector pos = entity->GetPosition();
- pos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f;
- C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, 0, 128, 255, 255, 1024, 0.2f, 5);
- }
- break;
- }
- case BLIP_COORD:
- break;
- case BLIP_CONTACT_POINT:
- if (!CTheScripts::IsPlayerOnAMission()) {
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY)
- C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, 128, 255, 128, 2048, 0.2f, 0);
- }
- break;
- }
- }
- }
-}
-
-void CRadar::DrawBlips()
-{
- if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
-
- CVector2D out;
- CVector2D in = CVector2D(0.0f, 0.0f);
- TransformRadarPointToScreenSpace(out, in);
-
-#ifdef MENU_MAP
- if (!CMenuManager::bMenuMapActive) {
-#endif
- float angle;
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN)
- angle = PI + FindPlayerHeading();
-#ifdef FIX_BUGS
- else if (TheCamera.GetLookDirection() != LOOKING_FORWARD)
- angle = FindPlayerHeading() - (PI + (TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind).Heading());
-#endif
- else
- angle = FindPlayerHeading() - (PI + TheCamera.GetForward().Heading());
-
- DrawRotatingRadarSprite(&CentreSprite, out.x, out.y, angle, 255);
-
- CVector2D vec2d;
- vec2d.x = vec2DRadarOrigin.x;
- vec2d.y = M_SQRT2 * m_radarRange + vec2DRadarOrigin.y;
- TransformRealWorldPointToRadarSpace(in, vec2d);
- LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255);
-#ifdef MENU_MAP
- }
-#endif
-
- CEntity *blipEntity = nil;
- for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
-#ifdef MENU_MAP
- // A little hack to reuse cleared blips in menu map. hehe
- if (!CMenuManager::bMenuMapActive || ms_RadarTrace[blipId].m_eBlipType == BLIP_CAR ||
- ms_RadarTrace[blipId].m_eBlipType == BLIP_CHAR || ms_RadarTrace[blipId].m_eBlipType == BLIP_OBJECT)
-#endif
- if (!ms_RadarTrace[blipId].m_bInUse)
- continue;
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- case BLIP_CHAR:
- case BLIP_OBJECT:
- if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
- || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) {
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- case BLIP_CHAR:
- blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- if (blipEntity != nil) {
- if (((CPed*)blipEntity)->InVehicle())
- blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
- }
- break;
- case BLIP_OBJECT:
- blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- default:
- break;
- }
- if (blipEntity) {
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- } else {
-#ifdef TRIANGULAR_BLIPS
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = blipEntity->GetPosition();
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- }
- }
- break;
- case BLIP_COORD:
- case BLIP_CONTACT_POINT:
- if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
- || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON)
- && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
-
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- } else {
-#ifdef TRIANGULAR_BLIPS
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- }
- break;
- default:
- break;
- }
- }
- for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
- if (!ms_RadarTrace[blipId].m_bInUse)
- continue;
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- case BLIP_CHAR:
- case BLIP_OBJECT:
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
- && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON) {
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- case BLIP_CHAR:
- blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- if (blipEntity != nil) {
- if (((CPed*)blipEntity)->InVehicle())
- blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
- }
- break;
- case BLIP_OBJECT:
- blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- default:
- break;
- }
-
- if (blipEntity) {
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- else
-#ifdef TRIANGULAR_BLIPS
- {
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = blipEntity->GetPosition();
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
- }
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- }
- break;
- default:
- break;
- }
- }
- for (int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
- if (!ms_RadarTrace[blipId].m_bInUse)
- continue;
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_COORD:
- case BLIP_CONTACT_POINT:
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
- && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON
- && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
-
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- else
-#ifdef TRIANGULAR_BLIPS
- {
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
- }
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- break;
- default:
- break;
- }
- }
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive) {
- CVector2D in, out;
- TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift());
- TransformRadarPointToScreenSpace(out, in);
- DrawYouAreHereSprite(out.x, out.y);
- }
-#endif
- }
-}
-
-void CRadar::DrawMap()
-{
- if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
-#if 1 // from VC
- CalculateCachedSinCos();
-#endif
- if (FindPlayerVehicle()) {
- float speed = FindPlayerSpeed().Magnitude();
- if (speed < RADAR_MIN_SPEED)
- m_radarRange = RADAR_MIN_RANGE;
- else if (speed < RADAR_MAX_SPEED)
- m_radarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE;
- else
- m_radarRange = RADAR_MAX_RANGE;
- }
- else
- m_radarRange = RADAR_MIN_RANGE;
-
- vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift());
- DrawRadarMap();
- }
-}
-
-void CRadar::DrawRadarMap()
-{
- // Game calculates an unused CRect here
-
- DrawRadarMask();
-
- // top left ist (0, 0)
- int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE);
- int y = ceilf((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE);
- StreamRadarSections(x, y);
-
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
- RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
- RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE);
-
- DrawRadarSection(x - 1, y - 1);
- DrawRadarSection(x, y - 1);
- DrawRadarSection(x + 1, y - 1);
- DrawRadarSection(x - 1, y);
- DrawRadarSection(x, y);
- DrawRadarSection(x + 1, y);
- DrawRadarSection(x - 1, y + 1);
- DrawRadarSection(x, y + 1);
- DrawRadarSection(x + 1, y + 1);
-}
-
-void CRadar::DrawRadarMask()
-{
- CVector2D corners[4] = {
- CVector2D(1.0f, -1.0f),
- CVector2D(1.0f, 1.0f),
- CVector2D(-1.0f, 1.0f),
- CVector2D(-1.0, -1.0f)
- };
-
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
- RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONALWAYS);
-
- CVector2D out[8];
- CVector2D in;
-
- // Draw the shape we want to mask out from the radar in four segments
- for (int i = 0; i < 4; i++) {
- // First point is always the corner itself
- in.x = corners[i].x;
- in.y = corners[i].y;
- TransformRadarPointToScreenSpace(out[0], in);
-
- // Then generate a quarter of the circle
- for (int j = 0; j < 7; j++) {
- in.x = corners[i].x * Cos(j * (PI / 2.0f / 6.0f));
- in.y = corners[i].y * Sin(j * (PI / 2.0f / 6.0f));
- TransformRadarPointToScreenSpace(out[j + 1], in);
- };
-
- CSprite2d::SetMaskVertices(8, (float *)out);
- RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8);
- };
-
- RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONGREATER);
-}
-
-void CRadar::DrawRadarSection(int32 x, int32 y)
-{
- int i;
- RwTexDictionary *txd;
- CVector2D worldPoly[8];
- CVector2D radarCorners[4];
- CVector2D radarPoly[8];
- CVector2D texCoords[8];
- CVector2D screenPoly[8];
- int numVertices;
- RwTexture *texture = nil;
-
- GetTextureCorners(x, y, worldPoly);
- ClipRadarTileCoords(x, y);
-
- assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y]));
- txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict;
- if (txd)
- texture = GetFirstTexture(txd);
- if (texture == nil)
- return;
-
- for (i = 0; i < 4; i++)
- TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]);
-
- numVertices = ClipRadarPoly(radarPoly, radarCorners);
-
- // FIX: can return earlier here
-// if(numVertices == 0)
- if (numVertices < 3)
- return;
-
- for (i = 0; i < numVertices; i++) {
- TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]);
- TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y);
- TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]);
- }
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture));
- CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255));
- // check done above now
-// if(numVertices > 2)
- RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices);
-}
-
-void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha)
-{
- RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha));
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive) {
- bool alreadyThere = false;
- for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
- if (MapLegendList[i] == sprite)
- alreadyThere = true;
- }
- if (!alreadyThere) {
- MapLegendList[MapLegendCounter] = sprite;
- MapLegendCounter++;
- }
- }
-#endif
-}
-
-void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha)
-{
- CVector curPosn[4];
- CVector oldPosn[4];
-
- curPosn[0].x = x - SCREEN_SCALE_X(5.6f);
- curPosn[0].y = y + SCREEN_SCALE_Y(5.6f);
-
- curPosn[1].x = x + SCREEN_SCALE_X(5.6f);
- curPosn[1].y = y + SCREEN_SCALE_Y(5.6f);
-
- curPosn[2].x = x - SCREEN_SCALE_X(5.6f);
- curPosn[2].y = y - SCREEN_SCALE_Y(5.6f);
-
- curPosn[3].x = x + SCREEN_SCALE_X(5.6f);
- curPosn[3].y = y - SCREEN_SCALE_Y(5.6f);
-
- for (uint32 i = 0; i < 4; i++) {
- oldPosn[i] = curPosn[i];
-
- curPosn[i].x = x + (oldPosn[i].x - x) * Cos(angle) + (oldPosn[i].y - y) * Sin(angle);
- curPosn[i].y = y - (oldPosn[i].x - x) * Sin(angle) + (oldPosn[i].y - y) * Cos(angle);
- }
-
- sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha));
-}
-
-int32 CRadar::GetActualBlipArrayIndex(int32 i)
-{
- if (i == -1)
- return -1;
- else if ((i & 0xFFFF0000) >> 16 != ms_RadarTrace[(uint16)i].m_BlipIndex)
- return -1;
- else
- return (uint16)i;
-}
-
-int32 CRadar::GetNewUniqueBlipIndex(int32 i)
-{
- if (ms_RadarTrace[i].m_BlipIndex >= UINT16_MAX - 1)
- ms_RadarTrace[i].m_BlipIndex = 1;
- else
- ms_RadarTrace[i].m_BlipIndex++;
- return i | (ms_RadarTrace[i].m_BlipIndex << 16);
-}
-
-uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright)
-{
- int32 c;
- switch (color) {
- case 0:
- if (bright)
- c = 0x712B49FF;
- else
- c = 0x7F0000FF;
- break;
- case 1:
- if (bright)
- c = 0x5FA06AFF;
- else
- c = 0x007F00FF;
- break;
- case 2:
- if (bright)
- c = 0x80A7F3FF;
- else
- c = 0x00007FFF;
- break;
- case 3:
- if (bright)
- c = 0xE1E1E1FF;
- else
- c = 0x7F7F7FFF;
- break;
- case 4:
- if (bright)
- c = 0xFFFF00FF;
- else
- c = 0x7F7F00FF;
- break;
- case 5:
- if (bright)
- c = 0xFF00FFFF;
- else
- c = 0x7F007FFF;
- break;
- case 6:
- if (bright)
- c = 0x00FFFFFF;
- else
- c = 0x007F7FFF;
- break;
- default:
- c = color;
- break;
- };
- return c;
-}
-
-const char* gRadarTexNames[] = {
- "radar00", "radar01", "radar02", "radar03", "radar04", "radar05", "radar06", "radar07",
- "radar08", "radar09", "radar10", "radar11", "radar12", "radar13", "radar14", "radar15",
- "radar16", "radar17", "radar18", "radar19", "radar20", "radar21", "radar22", "radar23",
- "radar24", "radar25", "radar26", "radar27", "radar28", "radar29", "radar30", "radar31",
- "radar32", "radar33", "radar34", "radar35", "radar36", "radar37", "radar38", "radar39",
- "radar40", "radar41", "radar42", "radar43", "radar44", "radar45", "radar46", "radar47",
- "radar48", "radar49", "radar50", "radar51", "radar52", "radar53", "radar54", "radar55",
- "radar56", "radar57", "radar58", "radar59", "radar60", "radar61", "radar62", "radar63",
-};
-
-void
-CRadar::Initialise()
-{
- for (int i = 0; i < NUMRADARBLIPS; i++) {
- ms_RadarTrace[i].m_BlipIndex = 1;
- SetRadarMarkerState(i, false);
- ms_RadarTrace[i].m_bInUse = false;
- ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
- ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
- ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
- }
-
- m_radarRange = 350.0f;
- for (int i = 0; i < 64; i++)
- gRadarTxdIds[i] = CTxdStore::FindTxdSlot(gRadarTexNames[i]);
-}
-
-float CRadar::LimitRadarPoint(CVector2D &point)
-{
- float dist, invdist;
-
- dist = point.Magnitude();
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive)
- return dist;
-#endif
- if (dist > 1.0f) {
- invdist = 1.0f / dist;
- point.x *= invdist;
- point.y *= invdist;
- }
- return dist;
-}
-
-void CRadar::LoadAllRadarBlips(uint8 *buf, uint32 size)
-{
- Initialise();
-INITSAVEBUF
- CheckSaveHeader(buf, 'R', 'D', 'R', '\0', size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUMRADARBLIPS; i++)
- ms_RadarTrace[i] = ReadSaveBuf<CBlip>(buf);
-
-VALIDATESAVEBUF(size);
-}
-
-void
-CRadar::LoadTextures()
-{
- CTxdStore::PushCurrentTxd();
- CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("hud"));
- AsukaSprite.SetTexture("radar_asuka");
- BombSprite.SetTexture("radar_bomb");
- CatSprite.SetTexture("radar_cat");
- CentreSprite.SetTexture("radar_centre");
- CopcarSprite.SetTexture("radar_copcar");
- DonSprite.SetTexture("radar_don");
- EightSprite.SetTexture("radar_eight");
- ElSprite.SetTexture("radar_el");
- IceSprite.SetTexture("radar_ice");
- JoeySprite.SetTexture("radar_joey");
- KenjiSprite.SetTexture("radar_kenji");
- LizSprite.SetTexture("radar_liz");
- LuigiSprite.SetTexture("radar_luigi");
- NorthSprite.SetTexture("radar_north");
- RaySprite.SetTexture("radar_ray");
- SalSprite.SetTexture("radar_sal");
- SaveSprite.SetTexture("radar_save");
- SpraySprite.SetTexture("radar_spray");
- TonySprite.SetTexture("radar_tony");
- WeaponSprite.SetTexture("radar_weapon");
- CTxdStore::PopCurrentTxd();
-}
-
-void RemoveMapSection(int32 x, int32 y)
-{
- if (x >= 0 && x <= 7 && y >= 0 && y <= 7)
- CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]);
-}
-
-void CRadar::RemoveRadarSections()
-{
- for (int i = 0; i < 8; i++)
- for (int j = 0; j < 8; j++)
- RemoveMapSection(i, j);
-}
-
-void CRadar::RequestMapSection(int32 x, int32 y)
-{
- ClipRadarTileCoords(x, y);
- CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);
-}
-
-void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size)
-{
- *size = SAVE_HEADER_SIZE + sizeof(ms_RadarTrace);
-INITSAVEBUF
- WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUMRADARBLIPS; i++)
- WriteSaveBuf(buf, ms_RadarTrace[i]);
-
-VALIDATESAVEBUF(*size);
-}
-
-void CRadar::SetBlipSprite(int32 i, int32 icon)
-{
- int index = CRadar::GetActualBlipArrayIndex(i);
- if (index != -1) {
- ms_RadarTrace[index].m_eRadarSprite = icon;
- }
-}
-
-int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay display)
-{
- int nextBlip;
- for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
- if (!ms_RadarTrace[nextBlip].m_bInUse)
- break;
- }
- ms_RadarTrace[nextBlip].m_eBlipType = type;
- ms_RadarTrace[nextBlip].m_nColor = color;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
- ms_RadarTrace[nextBlip].m_Radius = 1.0f;
- ms_RadarTrace[nextBlip].m_vec2DPos = pos;
- ms_RadarTrace[nextBlip].m_vecPos = pos;
- ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
- ms_RadarTrace[nextBlip].m_wScale = 1;
- ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
- ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
- return CRadar::GetNewUniqueBlipIndex(nextBlip);
-}
-
-int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDisplay display)
-{
- int nextBlip;
- for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
- if (!ms_RadarTrace[nextBlip].m_bInUse)
- break;
- }
- ms_RadarTrace[nextBlip].m_eBlipType = type;
- ms_RadarTrace[nextBlip].m_nColor = color;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
- ms_RadarTrace[nextBlip].m_Radius = 1.0f;
- ms_RadarTrace[nextBlip].m_nEntityHandle = handle;
- ms_RadarTrace[nextBlip].m_wScale = 1;
- ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
- ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
- return GetNewUniqueBlipIndex(nextBlip);
-}
-
-void CRadar::SetRadarMarkerState(int32 counter, bool flag)
-{
- CEntity *e;
- switch (ms_RadarTrace[counter].m_eBlipType) {
- case BLIP_CAR:
- e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
- break;
- case BLIP_CHAR:
- e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
- break;
- case BLIP_OBJECT:
- e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
- break;
- default:
- return;
- }
-
- if (e)
- e->bHasBlip = flag;
-}
-
-void CRadar::ShowRadarMarker(CVector pos, uint32 color, float radius) {
- float f1 = radius * 1.4f;
- float f2 = radius * 0.5f;
- CVector p1, p2;
-
- p1 = pos + TheCamera.GetUp()*f1;
- p2 = pos + TheCamera.GetUp()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-
- p1 = pos - TheCamera.GetUp()*f1;
- p2 = pos - TheCamera.GetUp()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-
- p1 = pos + TheCamera.GetRight()*f1;
- p2 = pos + TheCamera.GetRight()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-
- p1 = pos - TheCamera.GetRight()*f1;
- p2 = pos - TheCamera.GetRight()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-}
-
-void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha)
-{
- if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
- return;
-
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
-}
-
-void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha, uint8 mode)
-{
- if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
- return;
-
- switch (mode)
- {
- case BLIP_MODE_TRIANGULAR_UP:
- // size++; // VC does size + 1 for triangles
- CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 3.0f), y + SCREEN_SCALE_Y(size + 2.0f), x - (SCREEN_SCALE_X(size + 3.0f)), y + SCREEN_SCALE_Y(size + 2.0f), x, y - (SCREEN_SCALE_Y(size + 3.0f)), x, y - (SCREEN_SCALE_Y(size + 3.0f)), CRGBA(0, 0, 0, alpha));
- CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 1.0f), y + SCREEN_SCALE_Y(size + 1.0f), x - (SCREEN_SCALE_X(size + 1.0f)), y + SCREEN_SCALE_Y(size + 1.0f), x, y - (SCREEN_SCALE_Y(size + 1.0f)), x, y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
- break;
- case BLIP_MODE_TRIANGULAR_DOWN:
- // size++; // VC does size + 1 for triangles
- CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 2.0f), x, y + SCREEN_SCALE_Y(size + 3.0f), x + SCREEN_SCALE_X(size + 3.0f), y - (SCREEN_SCALE_Y(size + 2.0f)), x - (SCREEN_SCALE_X(size + 3.0f)), y - (SCREEN_SCALE_Y(size + 2.0f)), CRGBA(0, 0, 0, alpha));
- CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 1.0f), x, y + SCREEN_SCALE_Y(size + 1.0f), x + SCREEN_SCALE_X(size + 1.0f), y - (SCREEN_SCALE_Y(size + 1.0f)), x - (SCREEN_SCALE_X(size + 1.0f)), y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
- break;
- case BLIP_MODE_SQUARE:
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
- break;
- }
-#ifdef MENU_MAP
- // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips
- if (CMenuManager::bMenuMapActive) {
- bool alreadyThere = false;
- for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
- if (MapLegendList[i] == -1)
- alreadyThere = true;
- }
- if (!alreadyThere) {
- MapLegendList[MapLegendCounter] = -1;
- MapLegendCounter++;
- ArrowBlipColour1 = CRGBA(red, green, blue, alpha);
- }
- }
-#endif
-}
-
-void CRadar::Shutdown()
-{
- AsukaSprite.Delete();
- BombSprite.Delete();
- CatSprite.Delete();
- CentreSprite.Delete();
- CopcarSprite.Delete();
- DonSprite.Delete();
- EightSprite.Delete();
- ElSprite.Delete();
- IceSprite.Delete();
- JoeySprite.Delete();
- KenjiSprite.Delete();
- LizSprite.Delete();
- LuigiSprite.Delete();
- NorthSprite.Delete();
- RaySprite.Delete();
- SalSprite.Delete();
- SaveSprite.Delete();
- SpraySprite.Delete();
- TonySprite.Delete();
- WeaponSprite.Delete();
- RemoveRadarSections();
-}
-
-void CRadar::StreamRadarSections(const CVector &posn)
-{
- StreamRadarSections(floorf((2000.0f + posn.x) / 500.0f), ceilf(7.0f - (2000.0f + posn.y) / 500.0f));
-}
-
-void CRadar::StreamRadarSections(int32 x, int32 y)
-{
- for (int i = 0; i < RADAR_NUM_TILES; ++i) {
- for (int j = 0; j < RADAR_NUM_TILES; ++j) {
- if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1))
- RequestMapSection(i, j);
- else
- RemoveMapSection(i, j);
- };
- };
-}
-
-void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y)
-{
- out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X);
- out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y));
- out.x /= RADAR_TILE_SIZE;
- out.y /= RADAR_TILE_SIZE;
-}
-
-void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in)
-{
- float s, c;
-#if 1
- s = -cachedSin;
- c = cachedCos;
-#else
- // Original code
-
- s = -Sin(TheCamera.GetForward().Heading());
- c = Cos(TheCamera.GetForward().Heading());
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
- s = 0.0f;
- c = 1.0f;
- }
- else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) {
- CVector forward;
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
- forward.Normalise(); // a bit useless...
- }
- else
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
-
- s = -Sin(forward.Heading());
- c = Cos(forward.Heading());
- }
-#endif
-
- out.x = s * in.y + c * in.x;
- out.y = c * in.y - s * in.x;
-
- out = out * m_radarRange + vec2DRadarOrigin;
-}
-
-// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0)
-void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in)
+#include "config.h"
+#include "common.h"
+#include "patcher.h"
+#include "RwHelper.h"
+#include "Radar.h"
+#include "Camera.h"
+#include "Hud.h"
+#include "World.h"
+#include "Frontend.h"
+#include "General.h"
+#include "Vehicle.h"
+#include "Pools.h"
+#include "Script.h"
+#include "TxdStore.h"
+#include "World.h"
+#include "Streaming.h"
+#include "SpecialFX.h"
+
+float &CRadar::m_radarRange = *(float*)0x8E281C;
+sRadarTrace (&CRadar::ms_RadarTrace)[NUMRADARBLIPS] = *(sRadarTrace(*)[NUMRADARBLIPS]) * (uintptr*)0x6ED5E0;
+CVector2D &vec2DRadarOrigin = *(CVector2D*)0x6299B8;
+int32 gRadarTxdIds[64];// = (int*)0x6299C0;
+
+CSprite2d CRadar::AsukaSprite;// = *(CSprite2d*)0x8F1A40;
+CSprite2d CRadar::BombSprite;// = (CSprite2d*)0x8F5FB4;
+CSprite2d CRadar::CatSprite;// = (CSprite2d*)0x885B24;
+CSprite2d CRadar::CentreSprite;// = (CSprite2d*)0x8F6268;
+CSprite2d CRadar::CopcarSprite;// = (CSprite2d*)0x8F1A2C;
+CSprite2d CRadar::DonSprite;// = (CSprite2d*)0x8F2BE0;
+CSprite2d CRadar::EightSprite;// = (CSprite2d*)0x8F2BCC;
+CSprite2d CRadar::ElSprite;// = (CSprite2d*)0x8F1B80;
+CSprite2d CRadar::IceSprite;// = (CSprite2d*)0x9415FC;
+CSprite2d CRadar::JoeySprite;// = (CSprite2d*)0x8F2C00;
+CSprite2d CRadar::KenjiSprite;// = (CSprite2d*)0x8F2C68;
+CSprite2d CRadar::LizSprite;// = (CSprite2d*)0x8F5830;
+CSprite2d CRadar::LuigiSprite;// = (CSprite2d*)0x8F1A3C;
+CSprite2d CRadar::NorthSprite;// = (CSprite2d*)0x8F6274;
+CSprite2d CRadar::RaySprite;// = (CSprite2d*)0x8E2A7C;
+CSprite2d CRadar::SalSprite;// = (CSprite2d*)0x8F29EC;
+CSprite2d CRadar::SaveSprite;// = (CSprite2d*)0x8F5F74;
+CSprite2d CRadar::SpraySprite;// = (CSprite2d*)0x94307C;
+CSprite2d CRadar::TonySprite;// = (CSprite2d*)0x885B58;
+CSprite2d CRadar::WeaponSprite;// = (CSprite2d*)0x941534;
+
+CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = {
+ nil,
+ &AsukaSprite,
+ &BombSprite,
+ &CatSprite,
+ &CentreSprite,
+ &CopcarSprite,
+ &DonSprite,
+ &EightSprite,
+ &ElSprite,
+ &IceSprite,
+ &JoeySprite,
+ &KenjiSprite,
+ &LizSprite,
+ &LuigiSprite,
+ &NorthSprite,
+ &RaySprite,
+ &SalSprite,
+ &SaveSprite,
+ &SpraySprite,
+ &TonySprite,
+ &WeaponSprite
+};
+
+#define RADAR_NUM_TILES (8)
+#define RADAR_TILE_SIZE (WORLD_SIZE_X / RADAR_NUM_TILES)
+static_assert(RADAR_TILE_SIZE == (WORLD_SIZE_Y / RADAR_NUM_TILES), "CRadar: not a square");
+
+#define RADAR_MIN_RANGE (120.0f)
+#define RADAR_MAX_RANGE (350.0f)
+#define RADAR_MIN_SPEED (0.3f)
+#define RADAR_MAX_SPEED (0.9f)
+
+#ifdef MENU_MAP
+CRGBA CRadar::ArrowBlipColour1;
+CRGBA CRadar::ArrowBlipColour2;
+uint16 CRadar::MapLegendCounter;
+uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS];
+int CRadar::TargetMarkerId = -1;
+#endif
+
+// taken from VC
+float CRadar::cachedCos;
+float CRadar::cachedSin;
+
+void ClipRadarTileCoords(int32 &x, int32 &y)
{
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive) {
- // fMapSize is actually half map size. Radar range is 1000, so if x is -2000, in.x + 2.0f is 0.
- out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (in.x + 2.0f) * CMenuManager::fMapSize * 2.0f / 4.0f;
- out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (2.0f - in.y) * CMenuManager::fMapSize * 2.0f / 4.0f;
- } else
-#endif
- {
-#ifdef FIX_BUGS
- out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT);
-#else
- out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + RADAR_LEFT;
-#endif
- out.y = (1.0f - in.y) * 0.5f * SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT);
+ if (x < 0)
+ x = 0;
+ if (x > RADAR_NUM_TILES-1)
+ x = RADAR_NUM_TILES-1;
+ if (y < 0)
+ y = 0;
+ if (y > RADAR_NUM_TILES-1)
+ y = RADAR_NUM_TILES-1;
+}
+
+void RequestMapSection(int32 x, int32 y)
+{
+ ClipRadarTileCoords(x, y);
+ CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);
+}
+
+void RemoveMapSection(int32 x, int32 y)
+{
+ if (x >= 0 && x <= 7 && y >= 0 && y <= 7)
+ CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]);
+}
+
+// Transform from section indices to world coordinates
+void GetTextureCorners(int32 x, int32 y, CVector2D *out)
+{
+ x = x - RADAR_NUM_TILES/2;
+ y = -(y - RADAR_NUM_TILES/2);
+
+ // bottom left
+ out[0].x = RADAR_TILE_SIZE * (x);
+ out[0].y = RADAR_TILE_SIZE * (y - 1);
+
+ // bottom right
+ out[1].x = RADAR_TILE_SIZE * (x + 1);
+ out[1].y = RADAR_TILE_SIZE * (y - 1);
+
+ // top right
+ out[2].x = RADAR_TILE_SIZE * (x + 1);
+ out[2].y = RADAR_TILE_SIZE * (y);
+
+ // top left
+ out[3].x = RADAR_TILE_SIZE * (x);
+ out[3].y = RADAR_TILE_SIZE * (y);
+}
+
+
+bool IsPointInsideRadar(const CVector2D &point)
+{
+ if (point.x < -1.0f || point.x > 1.0f) return false;
+ if (point.y < -1.0f || point.y > 1.0f) return false;
+ return true;
+}
+
+// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1
+int LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2)
+{
+ float d1, d2;
+ float t;
+ float x, y;
+ float shortest = 1.0f;
+ int edge = -1;
+
+ // clip against left edge, x = -1.0
+ d1 = -1.0f - p1.x;
+ d2 = -1.0f - p2.x;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ y = (p2.y - p1.y)*t + p1.y;
+ if (y >= -1.0f && y <= 1.0f && t <= shortest) {
+ out.x = -1.0f;
+ out.y = y;
+ edge = 3;
+ shortest = t;
+ }
+ }
+
+ // clip against right edge, x = 1.0
+ d1 = p1.x - 1.0f;
+ d2 = p2.x - 1.0f;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ y = (p2.y - p1.y)*t + p1.y;
+ if (y >= -1.0f && y <= 1.0f && t <= shortest) {
+ out.x = 1.0f;
+ out.y = y;
+ edge = 1;
+ shortest = t;
+ }
+ }
+
+ // clip against top edge, y = -1.0
+ d1 = -1.0f - p1.y;
+ d2 = -1.0f - p2.y;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ x = (p2.x - p1.x)*t + p1.x;
+ if (x >= -1.0f && x <= 1.0f && t <= shortest) {
+ out.y = -1.0f;
+ out.x = x;
+ edge = 0;
+ shortest = t;
+ }
+ }
+
+ // clip against bottom edge, y = 1.0
+ d1 = p1.y - 1.0f;
+ d2 = p2.y - 1.0f;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ x = (p2.x - p1.x)*t + p1.x;
+ if (x >= -1.0f && x <= 1.0f && t <= shortest) {
+ out.y = 1.0f;
+ out.x = x;
+ edge = 2;
+ shortest = t;
+ }
+ }
+
+ return edge;
+}
+
+
+uint8 CRadar::CalculateBlipAlpha(float dist)
+{
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive)
+ return 255;
+#endif
+ if (dist <= 1.0f)
+ return 255;
+
+ if (dist <= 5.0f)
+ return (128.0f * ((dist - 1.0f) / 4.0f)) + ((1.0f - (dist - 1.0f) / 4.0f) * 255.0f);
+
+ return 128;
+}
+
+void CRadar::ChangeBlipBrightness(int32 i, int32 bright)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_bDim = bright != 1;
+}
+
+void CRadar::ChangeBlipColour(int32 i, int32 color)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_nColor = color;
+}
+
+void CRadar::ChangeBlipDisplay(int32 i, eBlipDisplay display)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_eBlipDisplay = display;
+}
+
+void CRadar::ChangeBlipScale(int32 i, int32 scale)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_wScale = scale;
+}
+
+void CRadar::ClearBlip(int32 i)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1) {
+ SetRadarMarkerState(index, false);
+ ms_RadarTrace[index].m_bInUse = false;
+#ifndef MENU_MAP
+ // Ssshhh
+ ms_RadarTrace[index].m_eBlipType = BLIP_NONE;
+ ms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
+ ms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE;
+#endif
+ }
+}
+
+void CRadar::ClearBlipForEntity(eBlipType type, int32 id)
+{
+ for (int i = 0; i < NUMRADARBLIPS; i++) {
+ if (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) {
+ SetRadarMarkerState(i, false);
+ ms_RadarTrace[i].m_bInUse = false;
+ ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
+ ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
+ ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
+ }
+ };
+}
+
+// Why not a proper clipping algorithm?
+int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect)
+{
+ CVector2D corners[4] = {
+ { 1.0f, -1.0f }, // top right
+ { 1.0f, 1.0f }, // bottom right
+ { -1.0f, 1.0f }, // bottom left
+ { -1.0f, -1.0f }, // top left
+ };
+ CVector2D tmp;
+ int i, j, n;
+ int laste, e, e1, e2;;
+ bool inside[4];
+
+ for (i = 0; i < 4; i++)
+ inside[i] = IsPointInsideRadar(rect[i]);
+
+ laste = -1;
+ n = 0;
+ for (i = 0; i < 4; i++)
+ if (inside[i]) {
+ // point is inside, just add
+ poly[n++] = rect[i];
+ }
+ else {
+ // point is outside but line to this point might be clipped
+ e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 4 - 1) % 4]);
+ if (e1 != -1) {
+ laste = e1;
+ n++;
+ }
+ // and line from this point might be clipped as well
+ e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 1) % 4]);
+ if (e2 != -1) {
+ if (e1 == -1) {
+ // if other line wasn't clipped, i.e. it was complete outside,
+ // we may have to insert another vertex if last clipped line
+ // was on a different edge
+
+ // find the last intersection if we haven't seen it yet
+ if (laste == -1)
+ for (j = 3; j >= i; j--) {
+ // game uses an if here for j == 0
+ e = LineRadarBoxCollision(tmp, rect[j], rect[(j + 4 - 1) % 4]);
+ if (e != -1) {
+ laste = e;
+ break;
+ }
+ }
+ assert(laste != -1);
+
+ // insert corners that were skipped
+ tmp = poly[n];
+ for (e = laste; e != e2; e = (e + 1) % 4)
+ poly[n++] = corners[e];
+ poly[n] = tmp;
+ }
+ n++;
+ }
+ }
+
+ if (n == 0) {
+ // If no points, either the rectangle is completely outside or completely surrounds the radar
+ // no idea what's going on here...
+ float m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x);
+ if ((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
+ m = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x);
+ if ((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
+ poly[0] = corners[0];
+ poly[1] = corners[1];
+ poly[2] = corners[2];
+ poly[3] = corners[3];
+ n = 4;
+ }
+ }
+ }
+
+ return n;
+}
+
+bool CRadar::DisplayThisBlip(int32 counter)
+{
+ switch (ms_RadarTrace[counter].m_eRadarSprite) {
+ case RADAR_SPRITE_BOMB:
+ case RADAR_SPRITE_SPRAY:
+ case RADAR_SPRITE_WEAPON:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void CRadar::Draw3dMarkers()
+{
+ for (int i = 0; i < NUMRADARBLIPS; i++) {
+ if (ms_RadarTrace[i].m_bInUse) {
+ switch (ms_RadarTrace[i].m_eBlipType) {
+ case BLIP_CAR:
+ {
+ CEntity *entity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ CVector pos = entity->GetPosition();
+ pos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f;
+ C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
+ }
+ break;
+ }
+ case BLIP_CHAR:
+ {
+ CEntity *entity = CPools::GetPedPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
+ if (entity != nil) {
+ if (((CPed*)entity)->InVehicle())
+ entity = ((CPed * )entity)->m_pMyVehicle;
+ }
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ CVector pos = entity->GetPosition();
+ pos.z += 3.0f;
+ C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
+ }
+ break;
+ }
+ case BLIP_OBJECT:
+ {
+ CEntity *entity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ CVector pos = entity->GetPosition();
+ pos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f;
+ C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, 0, 128, 255, 255, 1024, 0.2f, 5);
+ }
+ break;
+ }
+ case BLIP_COORD:
+ break;
+ case BLIP_CONTACT_POINT:
+ if (!CTheScripts::IsPlayerOnAMission()) {
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY)
+ C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, 128, 255, 128, 2048, 0.2f, 0);
+ }
+ break;
+ }
+ }
+ }
+}
+
+void CRadar::DrawBlips()
+{
+ if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+
+ CVector2D out;
+ CVector2D in = CVector2D(0.0f, 0.0f);
+ TransformRadarPointToScreenSpace(out, in);
+
+#ifdef MENU_MAP
+ if (!CMenuManager::bMenuMapActive) {
+#endif
+ float angle;
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN)
+ angle = PI + FindPlayerHeading();
+#ifdef FIX_BUGS
+ else if (TheCamera.GetLookDirection() != LOOKING_FORWARD)
+ angle = FindPlayerHeading() - (PI + (TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind).Heading());
+#endif
+ else
+ angle = FindPlayerHeading() - (PI + TheCamera.GetForward().Heading());
+
+ DrawRotatingRadarSprite(&CentreSprite, out.x, out.y, angle, 255);
+
+ CVector2D vec2d;
+ vec2d.x = vec2DRadarOrigin.x;
+ vec2d.y = M_SQRT2 * m_radarRange + vec2DRadarOrigin.y;
+ TransformRealWorldPointToRadarSpace(in, vec2d);
+ LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255);
+#ifdef MENU_MAP
+ }
+#endif
+
+ CEntity *blipEntity = nil;
+ for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
+#ifdef MENU_MAP
+ // A little hack to reuse cleared blips in menu map. hehe
+ if (!CMenuManager::bMenuMapActive || ms_RadarTrace[blipId].m_eBlipType == BLIP_CAR ||
+ ms_RadarTrace[blipId].m_eBlipType == BLIP_CHAR || ms_RadarTrace[blipId].m_eBlipType == BLIP_OBJECT)
+#endif
+ if (!ms_RadarTrace[blipId].m_bInUse)
+ continue;
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ case BLIP_CHAR:
+ case BLIP_OBJECT:
+ if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
+ || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) {
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ case BLIP_CHAR:
+ blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ if (blipEntity != nil) {
+ if (((CPed*)blipEntity)->InVehicle())
+ blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
+ }
+ break;
+ case BLIP_OBJECT:
+ blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ default:
+ break;
+ }
+ if (blipEntity) {
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ } else {
+#ifdef TRIANGULAR_BLIPS
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = blipEntity->GetPosition();
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ }
+ }
+ break;
+ case BLIP_COORD:
+ case BLIP_CONTACT_POINT:
+ if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
+ || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON)
+ && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
+
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ } else {
+#ifdef TRIANGULAR_BLIPS
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
+ if (!ms_RadarTrace[blipId].m_bInUse)
+ continue;
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ case BLIP_CHAR:
+ case BLIP_OBJECT:
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
+ && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON) {
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ case BLIP_CHAR:
+ blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ if (blipEntity != nil) {
+ if (((CPed*)blipEntity)->InVehicle())
+ blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
+ }
+ break;
+ case BLIP_OBJECT:
+ blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ default:
+ break;
+ }
+
+ if (blipEntity) {
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ else
+#ifdef TRIANGULAR_BLIPS
+ {
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = blipEntity->GetPosition();
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+ }
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ for (int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
+ if (!ms_RadarTrace[blipId].m_bInUse)
+ continue;
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_COORD:
+ case BLIP_CONTACT_POINT:
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
+ && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON
+ && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
+
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ else
+#ifdef TRIANGULAR_BLIPS
+ {
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+ }
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive) {
+ CVector2D in, out;
+ TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift());
+ TransformRadarPointToScreenSpace(out, in);
+ DrawYouAreHereSprite(out.x, out.y);
+ }
+#endif
+ }
+}
+
+void CRadar::DrawMap()
+{
+ if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
+#if 1 // from VC
+ CalculateCachedSinCos();
+#endif
+ if (FindPlayerVehicle()) {
+ float speed = FindPlayerSpeed().Magnitude();
+ if (speed < RADAR_MIN_SPEED)
+ m_radarRange = RADAR_MIN_RANGE;
+ else if (speed < RADAR_MAX_SPEED)
+ m_radarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE;
+ else
+ m_radarRange = RADAR_MAX_RANGE;
+ }
+ else
+ m_radarRange = RADAR_MIN_RANGE;
+
+ vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift());
+ DrawRadarMap();
+ }
+}
+
+void CRadar::DrawRadarMap()
+{
+ // Game calculates an unused CRect here
+
+ DrawRadarMask();
+
+ // top left ist (0, 0)
+ int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE);
+ int y = ceilf((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE);
+ StreamRadarSections(x, y);
+
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
+ RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE);
+
+ DrawRadarSection(x - 1, y - 1);
+ DrawRadarSection(x, y - 1);
+ DrawRadarSection(x + 1, y - 1);
+ DrawRadarSection(x - 1, y);
+ DrawRadarSection(x, y);
+ DrawRadarSection(x + 1, y);
+ DrawRadarSection(x - 1, y + 1);
+ DrawRadarSection(x, y + 1);
+ DrawRadarSection(x + 1, y + 1);
+}
+
+void CRadar::DrawRadarMask()
+{
+ CVector2D corners[4] = {
+ CVector2D(1.0f, -1.0f),
+ CVector2D(1.0f, 1.0f),
+ CVector2D(-1.0f, 1.0f),
+ CVector2D(-1.0, -1.0f)
+ };
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+
+ CVector2D out[8];
+ CVector2D in;
+
+ // Draw the shape we want to mask out from the radar in four segments
+ for (int i = 0; i < 4; i++) {
+ // First point is always the corner itself
+ in.x = corners[i].x;
+ in.y = corners[i].y;
+ TransformRadarPointToScreenSpace(out[0], in);
+
+ // Then generate a quarter of the circle
+ for (int j = 0; j < 7; j++) {
+ in.x = corners[i].x * Cos(j * (PI / 2.0f / 6.0f));
+ in.y = corners[i].y * Sin(j * (PI / 2.0f / 6.0f));
+ TransformRadarPointToScreenSpace(out[j + 1], in);
+ };
+
+ CSprite2d::SetMaskVertices(8, (float *)out);
+ RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8);
+ };
+}
+
+void CRadar::DrawRadarSection(int32 x, int32 y)
+{
+ int i;
+ RwTexDictionary *txd;
+ CVector2D worldPoly[8];
+ CVector2D radarCorners[4];
+ CVector2D radarPoly[8];
+ CVector2D texCoords[8];
+ CVector2D screenPoly[8];
+ int numVertices;
+ RwTexture *texture = nil;
+
+ GetTextureCorners(x, y, worldPoly);
+ ClipRadarTileCoords(x, y);
+
+ assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y]));
+ txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict;
+ if (txd)
+ texture = GetFirstTexture(txd);
+ if (texture == nil)
+ return;
+
+ for (i = 0; i < 4; i++)
+ TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]);
+
+ numVertices = ClipRadarPoly(radarPoly, radarCorners);
+
+ // FIX: can return earlier here
+// if(numVertices == 0)
+ if (numVertices < 3)
+ return;
+
+ for (i = 0; i < numVertices; i++) {
+ TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]);
+ TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y);
+ TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]);
+ }
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture));
+ CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255));
+ // check done above now
+// if(numVertices > 2)
+ RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices);
+}
+
+void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha)
+{
+ RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha));
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive) {
+ bool alreadyThere = false;
+ for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
+ if (MapLegendList[i] == sprite)
+ alreadyThere = true;
+ }
+ if (!alreadyThere) {
+ MapLegendList[MapLegendCounter] = sprite;
+ MapLegendCounter++;
+ }
+ }
+#endif
+}
+
+void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha)
+{
+ CVector curPosn[4];
+ CVector oldPosn[4];
+
+ curPosn[0].x = x - SCREEN_SCALE_X(5.6f);
+ curPosn[0].y = y + SCREEN_SCALE_Y(5.6f);
+
+ curPosn[1].x = x + SCREEN_SCALE_X(5.6f);
+ curPosn[1].y = y + SCREEN_SCALE_Y(5.6f);
+
+ curPosn[2].x = x - SCREEN_SCALE_X(5.6f);
+ curPosn[2].y = y - SCREEN_SCALE_Y(5.6f);
+
+ curPosn[3].x = x + SCREEN_SCALE_X(5.6f);
+ curPosn[3].y = y - SCREEN_SCALE_Y(5.6f);
+
+ for (uint32 i = 0; i < 4; i++) {
+ oldPosn[i] = curPosn[i];
+
+ curPosn[i].x = x + (oldPosn[i].x - x) * Cos(angle) + (oldPosn[i].y - y) * Sin(angle);
+ curPosn[i].y = y - (oldPosn[i].x - x) * Sin(angle) + (oldPosn[i].y - y) * Cos(angle);
+ }
+
+ sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha));
+}
+
+int32 CRadar::GetActualBlipArrayIndex(int32 i)
+{
+ if (i == -1)
+ return -1;
+ else if ((i & 0xFFFF0000) >> 16 != ms_RadarTrace[(uint16)i].m_BlipIndex)
+ return -1;
+ else
+ return (uint16)i;
+}
+
+int32 CRadar::GetNewUniqueBlipIndex(int32 i)
+{
+ if (ms_RadarTrace[i].m_BlipIndex >= UINT16_MAX - 1)
+ ms_RadarTrace[i].m_BlipIndex = 1;
+ else
+ ms_RadarTrace[i].m_BlipIndex++;
+ return i | (ms_RadarTrace[i].m_BlipIndex << 16);
+}
+
+uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright)
+{
+ int32 c;
+ switch (color) {
+ case 0:
+ if (bright)
+ c = 0x712B49FF;
+ else
+ c = 0x7F0000FF;
+ break;
+ case 1:
+ if (bright)
+ c = 0x5FA06AFF;
+ else
+ c = 0x007F00FF;
+ break;
+ case 2:
+ if (bright)
+ c = 0x80A7F3FF;
+ else
+ c = 0x00007FFF;
+ break;
+ case 3:
+ if (bright)
+ c = 0xE1E1E1FF;
+ else
+ c = 0x7F7F7FFF;
+ break;
+ case 4:
+ if (bright)
+ c = 0xFFFF00FF;
+ else
+ c = 0x7F7F00FF;
+ break;
+ case 5:
+ if (bright)
+ c = 0xFF00FFFF;
+ else
+ c = 0x7F007FFF;
+ break;
+ case 6:
+ if (bright)
+ c = 0x00FFFFFF;
+ else
+ c = 0x007F7FFF;
+ break;
+ default:
+ c = color;
+ break;
+ };
+ return c;
+}
+
+const char* gRadarTexNames[] = {
+ "radar00", "radar01", "radar02", "radar03", "radar04", "radar05", "radar06", "radar07",
+ "radar08", "radar09", "radar10", "radar11", "radar12", "radar13", "radar14", "radar15",
+ "radar16", "radar17", "radar18", "radar19", "radar20", "radar21", "radar22", "radar23",
+ "radar24", "radar25", "radar26", "radar27", "radar28", "radar29", "radar30", "radar31",
+ "radar32", "radar33", "radar34", "radar35", "radar36", "radar37", "radar38", "radar39",
+ "radar40", "radar41", "radar42", "radar43", "radar44", "radar45", "radar46", "radar47",
+ "radar48", "radar49", "radar50", "radar51", "radar52", "radar53", "radar54", "radar55",
+ "radar56", "radar57", "radar58", "radar59", "radar60", "radar61", "radar62", "radar63",
+};
+
+void
+CRadar::Initialise()
+{
+ for (int i = 0; i < NUMRADARBLIPS; i++) {
+ ms_RadarTrace[i].m_BlipIndex = 1;
+ SetRadarMarkerState(i, false);
+ ms_RadarTrace[i].m_bInUse = false;
+ ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
+ ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
+ ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
+ }
+
+ m_radarRange = 350.0f;
+ for (int i = 0; i < 64; i++)
+ gRadarTxdIds[i] = CTxdStore::FindTxdSlot(gRadarTexNames[i]);
+}
+
+float CRadar::LimitRadarPoint(CVector2D &point)
+{
+ float dist, invdist;
+
+ dist = point.Magnitude();
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive)
+ return dist;
+#endif
+ if (dist > 1.0f) {
+ invdist = 1.0f / dist;
+ point.x *= invdist;
+ point.y *= invdist;
+ }
+ return dist;
+}
+
+void CRadar::LoadAllRadarBlips(uint8 *buf, uint32 size)
+{
+ Initialise();
+INITSAVEBUF
+ CheckSaveHeader(buf, 'R', 'D', 'R', '\0', size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUMRADARBLIPS; i++)
+ ms_RadarTrace[i] = ReadSaveBuf<sRadarTrace>(buf);
+
+VALIDATESAVEBUF(size);
+}
+
+void
+CRadar::LoadTextures()
+{
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("hud"));
+ AsukaSprite.SetTexture("radar_asuka");
+ BombSprite.SetTexture("radar_bomb");
+ CatSprite.SetTexture("radar_cat");
+ CentreSprite.SetTexture("radar_centre");
+ CopcarSprite.SetTexture("radar_copcar");
+ DonSprite.SetTexture("radar_don");
+ EightSprite.SetTexture("radar_eight");
+ ElSprite.SetTexture("radar_el");
+ IceSprite.SetTexture("radar_ice");
+ JoeySprite.SetTexture("radar_joey");
+ KenjiSprite.SetTexture("radar_kenji");
+ LizSprite.SetTexture("radar_liz");
+ LuigiSprite.SetTexture("radar_luigi");
+ NorthSprite.SetTexture("radar_north");
+ RaySprite.SetTexture("radar_ray");
+ SalSprite.SetTexture("radar_sal");
+ SaveSprite.SetTexture("radar_save");
+ SpraySprite.SetTexture("radar_spray");
+ TonySprite.SetTexture("radar_tony");
+ WeaponSprite.SetTexture("radar_weapon");
+ CTxdStore::PopCurrentTxd();
+}
+
+void CRadar::RemoveRadarSections()
+{
+ for (int i = 0; i < 8; i++)
+ for (int j = 0; j < 8; j++)
+ RemoveMapSection(i, j);
+}
+
+void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size)
+{
+ *size = SAVE_HEADER_SIZE + sizeof(ms_RadarTrace);
+INITSAVEBUF
+ WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUMRADARBLIPS; i++)
+ WriteSaveBuf(buf, ms_RadarTrace[i]);
+
+VALIDATESAVEBUF(*size);
+}
+
+void CRadar::SetBlipSprite(int32 i, int32 icon)
+{
+ int index = CRadar::GetActualBlipArrayIndex(i);
+ if (index != -1) {
+ ms_RadarTrace[index].m_eRadarSprite = icon;
+ }
+}
+
+int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay display)
+{
+ int nextBlip;
+ for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
+ if (!ms_RadarTrace[nextBlip].m_bInUse)
+ break;
+ }
+ ms_RadarTrace[nextBlip].m_eBlipType = type;
+ ms_RadarTrace[nextBlip].m_nColor = color;
+ ms_RadarTrace[nextBlip].m_bDim = 1;
+ ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_Radius = 1.0f;
+ ms_RadarTrace[nextBlip].m_vec2DPos = pos;
+ ms_RadarTrace[nextBlip].m_vecPos = pos;
+ ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
+ ms_RadarTrace[nextBlip].m_wScale = 1;
+ ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
+ ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
+ return CRadar::GetNewUniqueBlipIndex(nextBlip);
+}
+
+int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDisplay display)
+{
+ int nextBlip;
+ for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
+ if (!ms_RadarTrace[nextBlip].m_bInUse)
+ break;
+ }
+ ms_RadarTrace[nextBlip].m_eBlipType = type;
+ ms_RadarTrace[nextBlip].m_nColor = color;
+ ms_RadarTrace[nextBlip].m_bDim = 1;
+ ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_Radius = 1.0f;
+ ms_RadarTrace[nextBlip].m_nEntityHandle = handle;
+ ms_RadarTrace[nextBlip].m_wScale = 1;
+ ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
+ ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
+ return GetNewUniqueBlipIndex(nextBlip);
+}
+
+void CRadar::SetRadarMarkerState(int32 counter, bool flag)
+{
+ CEntity *e;
+ switch (ms_RadarTrace[counter].m_eBlipType) {
+ case BLIP_CAR:
+ e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
+ break;
+ case BLIP_CHAR:
+ e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
+ break;
+ case BLIP_OBJECT:
+ e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
+ break;
+ default:
+ return;
+ }
+
+ if (e)
+ e->bHasBlip = flag;
+}
+
+void CRadar::ShowRadarMarker(CVector pos, uint32 color, float radius) {
+ float f1 = radius * 1.4f;
+ float f2 = radius * 0.5f;
+ CVector p1, p2;
+
+ p1 = pos + TheCamera.GetUp()*f1;
+ p2 = pos + TheCamera.GetUp()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+
+ p1 = pos - TheCamera.GetUp()*f1;
+ p2 = pos - TheCamera.GetUp()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+
+ p1 = pos + TheCamera.GetRight()*f1;
+ p2 = pos + TheCamera.GetRight()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+
+ p1 = pos - TheCamera.GetRight()*f1;
+ p2 = pos - TheCamera.GetRight()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+}
+
+void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha)
+{
+ if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
+ return;
+
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
+}
+
+void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha, uint8 mode)
+{
+ if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
+ return;
+
+ switch (mode)
+ {
+ case BLIP_MODE_TRIANGULAR_UP:
+ // size++; // VC does size + 1 for triangles
+ CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 3.0f), y + SCREEN_SCALE_Y(size + 2.0f), x - (SCREEN_SCALE_X(size + 3.0f)), y + SCREEN_SCALE_Y(size + 2.0f), x, y - (SCREEN_SCALE_Y(size + 3.0f)), x, y - (SCREEN_SCALE_Y(size + 3.0f)), CRGBA(0, 0, 0, alpha));
+ CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 1.0f), y + SCREEN_SCALE_Y(size + 1.0f), x - (SCREEN_SCALE_X(size + 1.0f)), y + SCREEN_SCALE_Y(size + 1.0f), x, y - (SCREEN_SCALE_Y(size + 1.0f)), x, y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
+ break;
+ case BLIP_MODE_TRIANGULAR_DOWN:
+ // size++; // VC does size + 1 for triangles
+ CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 2.0f), x, y + SCREEN_SCALE_Y(size + 3.0f), x + SCREEN_SCALE_X(size + 3.0f), y - (SCREEN_SCALE_Y(size + 2.0f)), x - (SCREEN_SCALE_X(size + 3.0f)), y - (SCREEN_SCALE_Y(size + 2.0f)), CRGBA(0, 0, 0, alpha));
+ CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 1.0f), x, y + SCREEN_SCALE_Y(size + 1.0f), x + SCREEN_SCALE_X(size + 1.0f), y - (SCREEN_SCALE_Y(size + 1.0f)), x - (SCREEN_SCALE_X(size + 1.0f)), y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
+ break;
+ case BLIP_MODE_SQUARE:
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
+ break;
+ }
+#ifdef MENU_MAP
+ // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips
+ if (CMenuManager::bMenuMapActive) {
+ bool alreadyThere = false;
+ for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
+ if (MapLegendList[i] == -1)
+ alreadyThere = true;
+ }
+ if (!alreadyThere) {
+ MapLegendList[MapLegendCounter] = -1;
+ MapLegendCounter++;
+ ArrowBlipColour1 = CRGBA(red, green, blue, alpha);
+ }
+ }
+#endif
+}
+
+void CRadar::Shutdown()
+{
+ AsukaSprite.Delete();
+ BombSprite.Delete();
+ CatSprite.Delete();
+ CentreSprite.Delete();
+ CopcarSprite.Delete();
+ DonSprite.Delete();
+ EightSprite.Delete();
+ ElSprite.Delete();
+ IceSprite.Delete();
+ JoeySprite.Delete();
+ KenjiSprite.Delete();
+ LizSprite.Delete();
+ LuigiSprite.Delete();
+ NorthSprite.Delete();
+ RaySprite.Delete();
+ SalSprite.Delete();
+ SaveSprite.Delete();
+ SpraySprite.Delete();
+ TonySprite.Delete();
+ WeaponSprite.Delete();
+ RemoveRadarSections();
+}
+
+void CRadar::StreamRadarSections(const CVector &posn)
+{
+ StreamRadarSections(floorf((2000.0f + posn.x) / 500.0f), ceilf(7.0f - (2000.0f + posn.y) / 500.0f));
+}
+
+void CRadar::StreamRadarSections(int32 x, int32 y)
+{
+ for (int i = 0; i < RADAR_NUM_TILES; ++i) {
+ for (int j = 0; j < RADAR_NUM_TILES; ++j) {
+ if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1))
+ RequestMapSection(i, j);
+ else
+ RemoveMapSection(i, j);
+ };
+ };
+}
+
+void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y)
+{
+ out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X);
+ out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y));
+ out.x /= RADAR_TILE_SIZE;
+ out.y /= RADAR_TILE_SIZE;
+}
+
+void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in)
+{
+ float s, c;
+#if 1
+ s = -cachedSin;
+ c = cachedCos;
+#else
+ // Original code
+
+ s = -Sin(TheCamera.GetForward().Heading());
+ c = Cos(TheCamera.GetForward().Heading());
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
+ s = 0.0f;
+ c = 1.0f;
+ }
+ else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) {
+ CVector forward;
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
+ forward.Normalise(); // a bit useless...
+ }
+ else
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
+
+ s = -Sin(forward.Heading());
+ c = Cos(forward.Heading());
+ }
+#endif
+
+ out.x = s * in.y + c * in.x;
+ out.y = c * in.y - s * in.x;
+
+ out = out * m_radarRange + vec2DRadarOrigin;
+}
+
+// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0)
+void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in)
+{
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive) {
+ // fMapSize is actually half map size. Radar range is 1000, so if x is -2000, in.x + 2.0f is 0.
+ out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (in.x + 2.0f) * CMenuManager::fMapSize * 2.0f / 4.0f;
+ out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (2.0f - in.y) * CMenuManager::fMapSize * 2.0f / 4.0f;
+ } else
+#endif
+ {
+#ifdef FIX_BUGS
+ out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT);
+#else
+ out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + RADAR_LEFT;
+#endif
+ out.y = (1.0f - in.y) * 0.5f * SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT);
+ }
+}
+
+void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in)
+{
+ float s, c;
+#if 1
+ s = cachedSin;
+ c = cachedCos;
+#else
+ // Original code
+
+ float s, c;
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
+ s = 0.0f;
+ c = 1.0f;
+ }
+ else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
+ s = Sin(TheCamera.GetForward().Heading());
+ c = Cos(TheCamera.GetForward().Heading());
+ }
+ else {
+ CVector forward;
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
+ forward.Normalise(); // a bit useless...
+ }
+ else
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
+
+ s = Sin(forward.Heading());
+ c = Cos(forward.Heading());
+ }
+#endif
+
+ float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_radarRange);
+ float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_radarRange);
+
+ out.x = s * y + c * x;
+ out.y = c * y - s * x;
+}
+
+void
+CRadar::CalculateCachedSinCos()
+{
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED
+#ifdef MENU_MAP
+ || CMenuManager::bMenuMapActive
+#endif
+ ) {
+ cachedSin = 0.0f;
+ cachedCos = 1.0f;
+ } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
+ cachedSin = Sin(TheCamera.GetForward().Heading());
+ cachedCos = Cos(TheCamera.GetForward().Heading());
+ } else {
+ CVector forward;
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
+ forward.Normalise(); // a bit useless...
+ }
+ else
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
+
+ cachedSin = Sin(forward.Heading());
+ cachedCos = Cos(forward.Heading());
+ }
+}
+
+#ifdef MENU_MAP
+void
+CRadar::InitFrontEndMap()
+{
+ CalculateCachedSinCos();
+ vec2DRadarOrigin.x = 0.0f;
+ vec2DRadarOrigin.y = 0.0f;
+ m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace
+ for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
+ MapLegendList[i] = RADAR_SPRITE_NONE;
+ }
+ MapLegendCounter = 0;
+ ArrowBlipColour1 = CRGBA(0, 0, 0, 0);
+ ArrowBlipColour2 = CRGBA(0, 0, 0, 0);
+}
+
+void
+CRadar::DrawYouAreHereSprite(float x, float y)
+{
+ static uint32 lastChange = 0;
+ static bool show = true;
+
+ if (show) {
+ if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 500) {
+ lastChange = CTimer::GetTimeInMillisecondsPauseMode();
+ show = !show;
+ }
+ } else {
+ if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 200) {
+ lastChange = CTimer::GetTimeInMillisecondsPauseMode();
+ show = !show;
+ }
+ }
+
+ if (show) {
+ float left = x - SCREEN_SCALE_X(12.0f);
+ float top = y - SCREEN_SCALE_Y(2.0f);
+ float right = SCREEN_SCALE_X(12.0) + x;
+ float bottom = y - SCREEN_SCALE_Y(26.0f);
+ CentreSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 217, 106, 255));
+ }
+ MapLegendList[MapLegendCounter++] = RADAR_SPRITE_CENTRE;
+}
+
+void
+CRadar::ToggleTargetMarker(float x, float y)
+{
+ if (TargetMarkerId == -1) {
+ int nextBlip;
+ for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
+ if (!ms_RadarTrace[nextBlip].m_bInUse)
+ break;
+ }
+ ms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD;
+ ms_RadarTrace[nextBlip].m_nColor = 0x333333FF;
+ ms_RadarTrace[nextBlip].m_bDim = 1;
+ ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_Radius = 1.0f;
+ CVector pos(x, y, CWorld::FindGroundZForCoord(x,y));
+ ms_RadarTrace[nextBlip].m_vec2DPos = pos;
+ ms_RadarTrace[nextBlip].m_vecPos = pos;
+ ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
+ ms_RadarTrace[nextBlip].m_wScale = 5;
+ ms_RadarTrace[nextBlip].m_eBlipDisplay = BLIP_DISPLAY_BLIP_ONLY;
+ ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
+ TargetMarkerId = CRadar::GetNewUniqueBlipIndex(nextBlip);
+ } else {
+ ClearBlip(TargetMarkerId);
+ TargetMarkerId = -1;
}
-}
-
-void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in)
-{
- float s, c;
-#if 1
- s = cachedSin;
- c = cachedCos;
-#else
- // Original code
-
- float s, c;
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
- s = 0.0f;
- c = 1.0f;
- }
- else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
- s = Sin(TheCamera.GetForward().Heading());
- c = Cos(TheCamera.GetForward().Heading());
- }
- else {
- CVector forward;
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
- forward.Normalise(); // a bit useless...
- }
- else
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
-
- s = Sin(forward.Heading());
- c = Cos(forward.Heading());
- }
-#endif
-
- float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_radarRange);
- float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_radarRange);
-
- out.x = s * y + c * x;
- out.y = c * y - s * x;
-}
-
-// Transform from section indices to world coordinates
-void CRadar::GetTextureCorners(int32 x, int32 y, CVector2D *out)
-{
- x = x - RADAR_NUM_TILES/2;
- y = -(y - RADAR_NUM_TILES/2);
-
- // bottom left
- out[0].x = RADAR_TILE_SIZE * (x);
- out[0].y = RADAR_TILE_SIZE * (y - 1);
-
- // bottom right
- out[1].x = RADAR_TILE_SIZE * (x + 1);
- out[1].y = RADAR_TILE_SIZE * (y - 1);
-
- // top right
- out[2].x = RADAR_TILE_SIZE * (x + 1);
- out[2].y = RADAR_TILE_SIZE * (y);
-
- // top left
- out[3].x = RADAR_TILE_SIZE * (x);
- out[3].y = RADAR_TILE_SIZE * (y);
-}
-
-void CRadar::ClipRadarTileCoords(int32 &x, int32 &y)
-{
- if (x < 0)
- x = 0;
- if (x > RADAR_NUM_TILES-1)
- x = RADAR_NUM_TILES-1;
- if (y < 0)
- y = 0;
- if (y > RADAR_NUM_TILES-1)
- y = RADAR_NUM_TILES-1;
-}
-
-
-bool CRadar::IsPointInsideRadar(const CVector2D &point)
-{
- if (point.x < -1.0f || point.x > 1.0f) return false;
- if (point.y < -1.0f || point.y > 1.0f) return false;
- return true;
-}
-
-// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1
-int CRadar::LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2)
-{
- float d1, d2;
- float t;
- float x, y;
- float shortest = 1.0f;
- int edge = -1;
-
- // clip against left edge, x = -1.0
- d1 = -1.0f - p1.x;
- d2 = -1.0f - p2.x;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- y = (p2.y - p1.y)*t + p1.y;
- if (y >= -1.0f && y <= 1.0f && t <= shortest) {
- out.x = -1.0f;
- out.y = y;
- edge = 3;
- shortest = t;
- }
- }
-
- // clip against right edge, x = 1.0
- d1 = p1.x - 1.0f;
- d2 = p2.x - 1.0f;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- y = (p2.y - p1.y)*t + p1.y;
- if (y >= -1.0f && y <= 1.0f && t <= shortest) {
- out.x = 1.0f;
- out.y = y;
- edge = 1;
- shortest = t;
- }
- }
-
- // clip against top edge, y = -1.0
- d1 = -1.0f - p1.y;
- d2 = -1.0f - p2.y;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- x = (p2.x - p1.x)*t + p1.x;
- if (x >= -1.0f && x <= 1.0f && t <= shortest) {
- out.y = -1.0f;
- out.x = x;
- edge = 0;
- shortest = t;
- }
- }
-
- // clip against bottom edge, y = 1.0
- d1 = p1.y - 1.0f;
- d2 = p2.y - 1.0f;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- x = (p2.x - p1.x)*t + p1.x;
- if (x >= -1.0f && x <= 1.0f && t <= shortest) {
- out.y = 1.0f;
- out.x = x;
- edge = 2;
- shortest = t;
- }
- }
-
- return edge;
-}
-
-void
-CRadar::CalculateCachedSinCos()
-{
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED
-#ifdef MENU_MAP
- || CMenuManager::bMenuMapActive
-#endif
- ) {
- cachedSin = 0.0f;
- cachedCos = 1.0f;
- } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
- cachedSin = Sin(TheCamera.GetForward().Heading());
- cachedCos = Cos(TheCamera.GetForward().Heading());
- } else {
- CVector forward;
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
- forward.Normalise(); // a bit useless...
- }
- else
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
-
- cachedSin = Sin(forward.Heading());
- cachedCos = Cos(forward.Heading());
- }
-}
-
-#ifdef MENU_MAP
-void
-CRadar::InitFrontEndMap()
-{
- CalculateCachedSinCos();
- vec2DRadarOrigin.x = 0.0f;
- vec2DRadarOrigin.y = 0.0f;
- m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace
- for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
- MapLegendList[i] = RADAR_SPRITE_NONE;
- }
- MapLegendCounter = 0;
- ArrowBlipColour1 = CRGBA(0, 0, 0, 0);
- ArrowBlipColour2 = CRGBA(0, 0, 0, 0);
-}
-
-void
-CRadar::DrawYouAreHereSprite(float x, float y)
-{
- static uint32 lastChange = 0;
- static bool show = true;
-
- if (show) {
- if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 500) {
- lastChange = CTimer::GetTimeInMillisecondsPauseMode();
- show = !show;
- }
- } else {
- if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 200) {
- lastChange = CTimer::GetTimeInMillisecondsPauseMode();
- show = !show;
- }
- }
-
- if (show) {
- float left = x - SCREEN_SCALE_X(12.0f);
- float top = y - SCREEN_SCALE_Y(2.0f);
- float right = SCREEN_SCALE_X(12.0) + x;
- float bottom = y - SCREEN_SCALE_Y(26.0f);
- CentreSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 217, 106, 255));
- }
- MapLegendList[MapLegendCounter++] = RADAR_SPRITE_CENTRE;
-}
-
-void
-CRadar::ToggleTargetMarker(float x, float y)
-{
- if (TargetMarkerId == -1) {
- int nextBlip;
- for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
- if (!ms_RadarTrace[nextBlip].m_bInUse)
- break;
- }
- ms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD;
- ms_RadarTrace[nextBlip].m_nColor = 0x333333FF;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
- ms_RadarTrace[nextBlip].m_Radius = 1.0f;
- CVector pos(x, y, CWorld::FindGroundZForCoord(x,y));
- ms_RadarTrace[nextBlip].m_vec2DPos = pos;
- ms_RadarTrace[nextBlip].m_vecPos = pos;
- ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
- ms_RadarTrace[nextBlip].m_wScale = 5;
- ms_RadarTrace[nextBlip].m_eBlipDisplay = BLIP_DISPLAY_BLIP_ONLY;
- ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
- TargetMarkerId = CRadar::GetNewUniqueBlipIndex(nextBlip);
- } else {
- ClearBlip(TargetMarkerId);
- TargetMarkerId = -1;
- }
-}
-#endif
-
-STARTPATCHES
- InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP);
- InjectHook(0x4A3F60, CRadar::Shutdown, PATCH_JUMP);
- InjectHook(0x4A4030, CRadar::LoadTextures, PATCH_JUMP);
- InjectHook(0x4A4180, CRadar::GetNewUniqueBlipIndex, PATCH_JUMP);
- InjectHook(0x4A41C0, CRadar::GetActualBlipArrayIndex, PATCH_JUMP);
- InjectHook(0x4A4200, CRadar::DrawMap, PATCH_JUMP);
- InjectHook(0x4A42F0, CRadar::DrawBlips, PATCH_JUMP);
- InjectHook(0x4A4C70, CRadar::Draw3dMarkers, PATCH_JUMP);
- InjectHook(0x4A4F30, CRadar::LimitRadarPoint, PATCH_JUMP);
- InjectHook(0x4A4F90, CRadar::CalculateBlipAlpha, PATCH_JUMP);
- InjectHook(0x4A5040, CRadar::TransformRadarPointToScreenSpace, PATCH_JUMP);
- InjectHook(0x4A50D0, CRadar::TransformRealWorldPointToRadarSpace, PATCH_JUMP);
- InjectHook(0x4A5300, CRadar::TransformRadarPointToRealWorldSpace, PATCH_JUMP);
- InjectHook(0x4A5530, CRadar::TransformRealWorldToTexCoordSpace, PATCH_JUMP);
- InjectHook(0x4A5590, CRadar::SetCoordBlip, PATCH_JUMP);
- InjectHook(0x4A5640, CRadar::SetEntityBlip, PATCH_JUMP);
- InjectHook(0x4A56C0, CRadar::ClearBlipForEntity, PATCH_JUMP);
- InjectHook(0x4A5720, CRadar::ClearBlip, PATCH_JUMP);
- InjectHook(0x4A5770, CRadar::ChangeBlipColour, PATCH_JUMP);
- InjectHook(0x4A57A0, CRadar::ChangeBlipBrightness, PATCH_JUMP);
- InjectHook(0x4A57E0, CRadar::ChangeBlipScale, PATCH_JUMP);
- InjectHook(0x4A5810, CRadar::ChangeBlipDisplay, PATCH_JUMP);
- InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP);
- InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP);
- InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP);
- InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP);
- InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP);
- InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP);
- InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP);
- InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP);
- InjectHook(0x4A6100, (void (*)(int32, int32))&CRadar::StreamRadarSections, PATCH_JUMP);
- InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP);
- InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP);
- InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP);
- InjectHook(0x4A6B60, (void (*)(const CVector&))&CRadar::StreamRadarSections, PATCH_JUMP);
- InjectHook(0x4A6C20, CRadar::DrawRadarMap, PATCH_JUMP);
- InjectHook(0x4A6E30, CRadar::SaveAllRadarBlips, PATCH_JUMP);
- InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP);
-
- InjectHook(0x4A61C0, CRadar::GetTextureCorners, PATCH_JUMP);
- InjectHook(0x4A6160, CRadar::IsPointInsideRadar, PATCH_JUMP);
- InjectHook(0x4A6250, CRadar::LineRadarBoxCollision, PATCH_JUMP);
-ENDPATCHES
+}
+#endif
+
+STARTPATCHES
+ InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP);
+ InjectHook(0x4A3F60, CRadar::Shutdown, PATCH_JUMP);
+ InjectHook(0x4A4030, CRadar::LoadTextures, PATCH_JUMP);
+ InjectHook(0x4A4180, CRadar::GetNewUniqueBlipIndex, PATCH_JUMP);
+ InjectHook(0x4A41C0, CRadar::GetActualBlipArrayIndex, PATCH_JUMP);
+ InjectHook(0x4A4200, CRadar::DrawMap, PATCH_JUMP);
+ InjectHook(0x4A42F0, CRadar::DrawBlips, PATCH_JUMP);
+ InjectHook(0x4A4C70, CRadar::Draw3dMarkers, PATCH_JUMP);
+ InjectHook(0x4A4F30, CRadar::LimitRadarPoint, PATCH_JUMP);
+ InjectHook(0x4A4F90, CRadar::CalculateBlipAlpha, PATCH_JUMP);
+ InjectHook(0x4A5040, CRadar::TransformRadarPointToScreenSpace, PATCH_JUMP);
+ InjectHook(0x4A50D0, CRadar::TransformRealWorldPointToRadarSpace, PATCH_JUMP);
+ InjectHook(0x4A5300, CRadar::TransformRadarPointToRealWorldSpace, PATCH_JUMP);
+ InjectHook(0x4A5530, CRadar::TransformRealWorldToTexCoordSpace, PATCH_JUMP);
+ InjectHook(0x4A5590, CRadar::SetCoordBlip, PATCH_JUMP);
+ InjectHook(0x4A5640, CRadar::SetEntityBlip, PATCH_JUMP);
+ InjectHook(0x4A56C0, CRadar::ClearBlipForEntity, PATCH_JUMP);
+ InjectHook(0x4A5720, CRadar::ClearBlip, PATCH_JUMP);
+ InjectHook(0x4A5770, CRadar::ChangeBlipColour, PATCH_JUMP);
+ InjectHook(0x4A57A0, CRadar::ChangeBlipBrightness, PATCH_JUMP);
+ InjectHook(0x4A57E0, CRadar::ChangeBlipScale, PATCH_JUMP);
+ InjectHook(0x4A5810, CRadar::ChangeBlipDisplay, PATCH_JUMP);
+ InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP);
+ InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP);
+ InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP);
+ InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP);
+ InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP);
+ InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP);
+ InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP);
+ InjectHook(0x4A6020, ClipRadarTileCoords, PATCH_JUMP);
+ InjectHook(0x4A6060, RequestMapSection, PATCH_JUMP);
+ InjectHook(0x4A60A0, RemoveMapSection, PATCH_JUMP);
+ InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP);
+ InjectHook(0x4A6100, (void (*)(int32, int32))&CRadar::StreamRadarSections, PATCH_JUMP);
+ InjectHook(0x4A6160, IsPointInsideRadar, PATCH_JUMP);
+ InjectHook(0x4A61C0, GetTextureCorners, PATCH_JUMP);
+ InjectHook(0x4A6250, LineRadarBoxCollision, PATCH_JUMP);
+ InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP);
+ InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP);
+ InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP);
+ InjectHook(0x4A6B60, (void (*)(const CVector&))&CRadar::StreamRadarSections, PATCH_JUMP);
+ InjectHook(0x4A6C20, CRadar::DrawRadarMap, PATCH_JUMP);
+ InjectHook(0x4A6E30, CRadar::SaveAllRadarBlips, PATCH_JUMP);
+ InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP);
+ //InjectHook(0x4A7000, `global constructor keyed to'Radar.cpp, PATCH_JUMP);
+ //InjectHook(0x4A7260, sRadarTrace::sRadarTrace, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/core/Radar.h b/src/core/Radar.h
index 6d5bb196..27f3a6f0 100644
--- a/src/core/Radar.h
+++ b/src/core/Radar.h
@@ -56,7 +56,7 @@ enum
BLIP_MODE_SQUARE,
};
-struct CBlip
+struct sRadarTrace
{
uint32 m_nColor;
uint32 m_eBlipType; // eBlipType
@@ -71,7 +71,7 @@ struct CBlip
uint16 m_eBlipDisplay; // eBlipDisplay
uint16 m_eRadarSprite; // eRadarSprite
};
-static_assert(sizeof(CBlip) == 0x30, "CBlip: error");
+static_assert(sizeof(sRadarTrace) == 0x30, "sRadarTrace: error");
// Values for screen space
#define RADAR_LEFT (40.0f)
@@ -83,7 +83,7 @@ class CRadar
{
public:
static float &m_radarRange;
- static CBlip (&ms_RadarTrace)[NUMRADARBLIPS];
+ static sRadarTrace (&ms_RadarTrace)[NUMRADARBLIPS];
static CSprite2d AsukaSprite;
static CSprite2d BombSprite;
static CSprite2d CatSprite;
@@ -144,7 +144,6 @@ public:
static void LoadAllRadarBlips(uint8 *buf, uint32 size);
static void LoadTextures();
static void RemoveRadarSections();
- static void RequestMapSection(int32 x, int32 y);
static void SaveAllRadarBlips(uint8*, uint32*);
static void SetBlipSprite(int32 i, int32 icon);
static int32 SetCoordBlip(eBlipType type, CVector pos, int32, eBlipDisplay);
@@ -161,10 +160,6 @@ public:
static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in);
static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in);
- // 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 &);
+ // no in CRadar in the game:
static void CalculateCachedSinCos();
};
diff --git a/src/core/RwHelper.cpp b/src/core/RwHelper.cpp
index 6325bf15..44866f4f 100644
--- a/src/core/RwHelper.cpp
+++ b/src/core/RwHelper.cpp
@@ -347,13 +347,6 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)
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()
{
;
diff --git a/src/core/RwTexRead.cpp b/src/core/RwTexRead.cpp
index 6b717b34..ef1ac197 100644
--- a/src/core/RwTexRead.cpp
+++ b/src/core/RwTexRead.cpp
@@ -3,10 +3,24 @@
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#pragma warning( pop )
+#define WITHWINDOWS
#include "common.h"
#include "win.h"
#include "patcher.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;
int32 &texNumLoaded = *(int32*)0x8F252C;
@@ -132,9 +146,198 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *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
InjectHook(0x592380, RwTextureGtaStreamRead, PATCH_JUMP);
InjectHook(0x5924A0, RwTexDictionaryGtaStreamRead, PATCH_JUMP);
InjectHook(0x592550, RwTexDictionaryGtaStreamRead1, 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
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index aeb7afe5..02092a30 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -1,14 +1,14 @@
#include "common.h"
#include "patcher.h"
#include "Stats.h"
-
-WRAPPER void CStats::SaveStats(uint8 *buf, uint32 *size) { EAXJMP(0x4ab3e0); }
+#include "Text.h"
+#include "World.h"
int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
int32 &CStats::HeadsPopped = *(int32*)0x8F647C;
-bool& CStats::CommercialPassed = *(bool*)0x8F4334;
-bool& CStats::IndustrialPassed = *(bool*)0x8E2A68;
-bool& CStats::SuburbanPassed = *(bool*)0x8F2740;
+int32& CStats::CommercialPassed = *(int32*)0x8F4334;
+int32& CStats::IndustrialPassed = *(int32*)0x8E2A68;
+int32& CStats::SuburbanPassed = *(int32*)0x8F2740;
int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64;
@@ -48,7 +48,7 @@ int32& CStats::LongestFlightInDodo = *(int32*)0x8F5FE4;
int32& CStats::TimeTakenDefuseMission = *(int32*)0x880E24;
int32& CStats::TotalNumberKillFrenzies = *(int32*)0x8E2884;
int32& CStats::TotalNumberMissions = *(int32*)0x8E2820;
-int32& CStats::ShotsMade = *(int32*)0x8E2BE8;
+int32& CStats::RoundsFiredByPlayer = *(int32*)0x8E2BE8;
int32& CStats::KgsOfExplosivesUsed = *(int32*)0x8F2510;
int32& CStats::InstantHitsFiredByPlayer = *(int32*)0x943070;
int32& CStats::InstantHitsHitByPlayer = *(int32*)0x95CB8C;
@@ -62,7 +62,7 @@ void CStats::Init()
{
PeopleKilledByOthers = 0;
PeopleKilledByPlayer = 0;
- ShotsMade = 0;
+ RoundsFiredByPlayer = 0;
CarsExploded = 0;
HelisDestroyed = 0;
ProgressMade = 0;
@@ -200,6 +200,229 @@ void CStats::SetTotalNumberMissions(int32 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
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 \ No newline at end of file
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 029b2307..ac3259f9 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -11,9 +11,9 @@ public:
};
static int32 &DaysPassed;
static int32 &HeadsPopped;
- static bool& CommercialPassed;
- static bool& IndustrialPassed;
- static bool& SuburbanPassed;
+ static int32& CommercialPassed;
+ static int32& IndustrialPassed;
+ static int32& SuburbanPassed;
static int32 &NumberKillFrenziesPassed;
static int32 &PeopleKilledByOthers;
static int32 &HelisDestroyed;
@@ -53,7 +53,7 @@ public:
static int32 &TimeTakenDefuseMission;
static int32 &TotalNumberKillFrenzies;
static int32 &TotalNumberMissions;
- static int32 &ShotsMade;
+ static int32 &RoundsFiredByPlayer;
static int32 &KgsOfExplosivesUsed;
static int32 &InstantHitsFiredByPlayer;
static int32 &InstantHitsHitByPlayer;
@@ -64,24 +64,27 @@ public:
static int32(&HighestScores)[TOTAL_HIGHEST_SCORES];
public:
+ static void Init(void);
static void RegisterFastestTime(int32, int32);
static void RegisterHighestScore(int32, int32);
- static void AnotherKillFrenzyPassed();
- static void AnotherLifeSavedWithAmbulance();
- static void AnotherCriminalCaught();
- static void RegisterLevelAmbulanceMission(int32);
- static void AnotherFireExtinguished();
+ static void RegisterElBurroTime(int32);
static void Register4x4OneTime(int32);
static void Register4x4TwoTime(int32);
static void Register4x4ThreeTime(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 RegisterTimeTakenDefuseMission(int32);
+ static void AnotherKillFrenzyPassed();
static void SetTotalNumberKillFrenzies(int32);
static void SetTotalNumberMissions(int32);
- static void CheckPointReachedUnsuccessfully() { 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 Init(void);
+ static void LoadStats(uint8 *buf, uint32 size);
};
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 4a0230ce..d64569b3 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -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::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); }
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
CWorld::Initialise()
diff --git a/src/core/World.h b/src/core/World.h
index c4103eb2..07e7889f 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -132,6 +132,7 @@ public:
static void SetAllCarsCanBeDamaged(bool);
static void ExtinguishAllCarFiresInArea(CVector, float);
static void SetCarsOnFire(float, float, float, float, CEntity*);
+ static void SetPedsOnFire(float, float, float, float, CEntity*);
static void Initialise();
static void AddParticles();
@@ -140,6 +141,7 @@ public:
static void RepositionCertainDynamicObjects();
static void RemoveStaticObjects();
static void Process();
+ static void TriggerExplosion(const CVector &, float, float, CEntity*, bool);
};
extern CColPoint *gaTempSphereColPoints;
diff --git a/src/core/common.h b/src/core/common.h
index b58b93af..6ea88f2f 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -84,12 +84,14 @@ extern void **rwengine;
#define DEFAULT_SCREEN_WIDTH (640)
#define DEFAULT_SCREEN_HEIGHT (448)
#define DEFAULT_ASPECT_RATIO (4.0f/3.0f)
+#define DEFAULT_VIEWWINDOW (0.7f)
// game uses maximumWidth/Height, but this probably won't work
// with RW windowed mode
#define SCREEN_WIDTH ((float)RsGlobal.width)
#define SCREEN_HEIGHT ((float)RsGlobal.height)
#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
#define SCREEN_STRETCH_X(a) ((a) * (float) SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH)
@@ -105,10 +107,8 @@ extern void **rwengine;
#ifdef ASPECT_RATIO_SCALE
#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
#define SCREEN_SCALE_AR(a) (a)
-#define SCREEN_SCALE_AR2(a) (a)
#endif
#include "maths.h"
diff --git a/src/core/config.h b/src/core/config.h
index f653f724..8dea3216 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -79,6 +79,7 @@ enum Config {
NUMPICKUPMESSAGES = 16,
NUMBULLETTRACES = 16,
NUMMBLURSTREAKS = 4,
+ NUMSKIDMARKS = 32,
NUMONSCREENTIMERENTRIES = 1,
NUMRADARBLIPS = 32,
@@ -125,7 +126,9 @@ enum Config {
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
@@ -150,6 +153,7 @@ enum Config {
//#define MASTER
#if defined GTA_PS2
+# define GTA_PS2_STUFF
# define RANDOMSPLASH
#elif defined GTA_PC
# define GTA3_1_1_PATCH
diff --git a/src/core/main.cpp b/src/core/main.cpp
index fb5beee0..93e4c71c 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -1,6 +1,11 @@
#include "common.h"
+#include "rpmatfx.h"
+#include "rpskin.h"
+#include "rphanim.h"
+#include "rtbmp.h"
#include "patcher.h"
#include "main.h"
+#include "CdStream.h"
#include "General.h"
#include "RwHelper.h"
#include "Clouds.h"
@@ -52,9 +57,7 @@
#include "Debug.h"
#include "Console.h"
#include "timebars.h"
-
-#define DEFAULT_VIEWWINDOW (Tan(DEGTORAD(CDraw::GetFOV() * 0.5f)))
-
+#include "GenericGameStorage.h"
GlobalScene &Scene = *(GlobalScene*)0x726768;
@@ -68,293 +71,68 @@ char *gString2 = (char*)0x878A40;
wchar *gUString = (wchar*)0x74B018;
wchar *gUString2 = (wchar*)0x6EDD70;
-bool &b_FoundRecentSavedGameWantToLoad = *(bool*)0x95CDA8;
-
-
-char version_name[64];
float FramesPerSecond = 30.0f;
bool gbPrintShite = false;
bool &gbModelViewer = *(bool*)0x95CD93;
-bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
-bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
-void DoRWStuffEndOfFrame(void);
+int32 frameCount;
+
+RwRGBA gColourTop;
+
+bool gameAlreadyInitialised;
+
+float NumberOfChunksLoaded;
+#define TOTALNUMCHUNKS 73.0f
-void RenderScene(void);
-void RenderDebugShit(void);
-void RenderEffects(void);
-void Render2dStuff(void);
-void RenderMenus(void);
-void DoFade(void);
-void Render2dStuffAfterFade(void);
+bool g_SlowMode = false;
+char version_name[64];
-CSprite2d *LoadSplash(const char *name);
+void GameInit(void);
+void SystemInit(void);
+void TheGame(void);
extern void (*DebugMenuProcess)(void);
extern void (*DebugMenuRender)(void);
void DebugMenuInit(void);
void DebugMenuPopulate(void);
-void PrintGameVersion();
-
-RwRGBA gColourTop;
-
-void
-InitialiseGame(void)
-{
- LoadingScreen(nil, nil, "loadsc0");
- CGame::Initialise("DATA\\GTA3.DAT");
-}
-
-#ifndef MASTER
-void
-TheModelViewer(void)
-{
-#ifdef ASPECT_RATIO_SCALE
- CDraw::SetAspectRatio(CDraw::FindAspectRatio());
-#endif
- CAnimViewer::Update();
- CTimer::Update();
- SetLightsWithTimeOfDayColour(Scene.world);
- CRenderer::ConstructRenderList();
- DoRWStuffStartOfFrame(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
- CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
- 255);
-
- CSprite2d::InitPerFrame();
- CFont::InitPerFrame();
- DefinedState();
- CVisibilityPlugins::InitAlphaEntityList();
- CAnimViewer::Render();
- Render2dStuff();
- DoRWStuffEndOfFrame();
-}
-#endif
void
-Idle(void *arg)
+ValidateVersion()
{
-#ifdef ASPECT_RATIO_SCALE
- CDraw::SetAspectRatio(CDraw::FindAspectRatio());
-#endif
-
- CTimer::Update();
-
-#ifdef TIMEBARS
- tbInit();
-#endif
-
- CSprite2d::InitPerFrame();
- CFont::InitPerFrame();
-
- // We're basically merging FrontendIdle and Idle (just like TheGame on PS2)
-#ifdef PS2_SAVE_DIALOG
- // Only exists on PC FrontendIdle, probably some PS2 bug fix
- if (FrontEndMenuManager.m_bMenuActive)
- CSprite2d::SetRecipNearClip();
-
- if (FrontEndMenuManager.m_bGameNotLoaded) {
- CPad::UpdatePads();
- FrontEndMenuManager.Process();
- } else {
- CPointLights::InitPerFrame();
-#ifdef TIMEBARS
- tbStartTimer(0, "CGame::Process");
-#endif
- CGame::Process();
-#ifdef TIMEBARS
- tbEndTimer("CGame::Process");
- tbStartTimer(0, "DMAudio.Service");
-#endif
- DMAudio.Service();
-
-#ifdef TIMEBARS
- tbEndTimer("DMAudio.Service");
-#endif
- }
-
- if (RsGlobal.quit)
- return;
-#else
- CPointLights::InitPerFrame();
-#ifdef TIMEBARS
- tbStartTimer(0, "CGame::Process");
-#endif
- CGame::Process();
-#ifdef TIMEBARS
- tbEndTimer("CGame::Process");
- tbStartTimer(0, "DMAudio.Service");
-#endif
-
- DMAudio.Service();
-
-#ifdef TIMEBARS
- tbEndTimer("DMAudio.Service");
-#endif
-#endif
-
- if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){
- FrontEndMenuManager.m_bStartGameLoading = true;
- FrontEndMenuManager.m_bLoadingSavedGame = false;
- return;
- }
-
- if(FrontEndMenuManager.m_bStartGameLoading || b_FoundRecentSavedGameWantToLoad)
- return;
-
- SetLightsWithTimeOfDayColour(Scene.world);
-
- if(arg == nil)
- return;
-
- if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) &&
- TheCamera.GetScreenFadeStatus() != FADE_2){
-#ifdef GTA_PC
- if (!FrontEndMenuManager.m_bRenderGameInMenu) {
- // This is from SA, but it's nice for windowed mode
- RwV2d pos;
- pos.x = SCREEN_WIDTH / 2.0f;
- pos.y = SCREEN_HEIGHT / 2.0f;
- RsMouseSetPos(&pos);
- }
-#endif
-#ifdef TIMEBARS
- tbStartTimer(0, "CnstrRenderList");
-#endif
- CRenderer::ConstructRenderList();
-#ifdef TIMEBARS
- tbEndTimer("CnstrRenderList");
- tbStartTimer(0, "PreRender");
-#endif
- CRenderer::PreRender();
-#ifdef TIMEBARS
- tbEndTimer("PreRender");
-#endif
+ int32 file = CFileMgr::OpenFile("models\\coll\\peds.col", "rb");
+ char buff[128];
- if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
- if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))
- return;
- }else{
- if(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
- CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
- 255))
- return;
+ if ( file != -1 )
+ {
+ CFileMgr::Seek(file, 100, SEEK_SET);
+
+ for ( int i = 0; i < 128; i++ )
+ {
+ CFileMgr::Read(file, &buff[i], sizeof(char));
+ buff[i] -= 23;
+ if ( buff[i] == '\0' )
+ break;
+ CFileMgr::Seek(file, 99, SEEK_CUR);
}
-
- DefinedState();
-
- // BUG. This has to be done BEFORE RwCameraBeginUpdate
- RwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());
- RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());
-
-#ifdef TIMEBARS
- tbStartTimer(0, "RenderScene");
-#endif
- RenderScene();
-#ifdef TIMEBARS
- tbEndTimer("RenderScene");
-#endif
- RenderDebugShit();
- RenderEffects();
-
-#ifdef TIMEBARS
- tbStartTimer(0, "RenderMotionBlur");
-#endif
- if((TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL) &&
- TheCamera.m_ScreenReductionPercentage > 0.0f)
- TheCamera.SetMotionBlurAlpha(150);
- TheCamera.RenderMotionBlur();
-#ifdef TIMEBARS
- tbEndTimer("RenderMotionBlur");
- tbStartTimer(0, "Render2dStuff");
-#endif
- Render2dStuff();
-#ifdef TIMEBARS
- tbEndTimer("Render2dStuff");
-#endif
- }else{
- float viewWindow = DEFAULT_VIEWWINDOW;
-#ifdef ASPECT_RATIO_SCALE
- CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
-#else
- CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
-#endif
- CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
- RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
- if(!RsCameraBeginUpdate(Scene.camera))
+
+ if ( !strncmp(buff, "grandtheftauto3", 15) )
+ {
+ strncpy(version_name, &buff[15], 64);
+ CFileMgr::CloseFile(file);
return;
+ }
}
-#ifdef PS2_SAVE_DIALOG
- if (FrontEndMenuManager.m_bMenuActive)
- DefinedState();
-#endif
-#ifdef TIMEBARS
- tbStartTimer(0, "RenderMenus");
-#endif
- RenderMenus();
-#ifdef TIMEBARS
- tbEndTimer("RenderMenus");
- tbStartTimer(0, "DoFade");
-#endif
- DoFade();
-#ifdef TIMEBARS
- tbEndTimer("DoFade");
- tbStartTimer(0, "Render2dStuff-Fade");
-#endif
- Render2dStuffAfterFade();
-#ifdef TIMEBARS
- tbEndTimer("Render2dStuff-Fade");
-#endif
- CCredits::Render();
-
-#ifdef TIMEBARS
- tbDisplay();
-#endif
-
- DoRWStuffEndOfFrame();
-
-// if(g_SlowMode)
-// ProcessSlowMode();
-}
-
-void
-FrontendIdle(void)
-{
-#ifdef ASPECT_RATIO_SCALE
- CDraw::SetAspectRatio(CDraw::FindAspectRatio());
-#endif
-
- CTimer::Update();
- CSprite2d::SetRecipNearClip(); // this should be on InitialiseRenderWare according to PS2 asm. seems like a bug fix
- CSprite2d::InitPerFrame();
- CFont::InitPerFrame();
- CPad::UpdatePads();
- FrontEndMenuManager.Process();
-
- if(RsGlobal.quit)
- return;
-
- float viewWindow = DEFAULT_VIEWWINDOW;
-#ifdef ASPECT_RATIO_SCALE
- CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
-#else
- CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
-#endif
- CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
- RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
- if(!RsCameraBeginUpdate(Scene.camera))
- return;
-
- DefinedState(); // seems redundant, but breaks resolution change.
- RenderMenus();
- DoFade();
- Render2dStuffAfterFade();
-// CFont::DrawFonts(); // redundant
- DoRWStuffEndOfFrame();
+ LoadingScreen("Invalid version", NULL, NULL);
+
+ while(true)
+ {
+ ;
+ }
}
bool
@@ -363,7 +141,7 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR
CRGBA TopColor(TopRed, TopGreen, TopBlue, Alpha);
CRGBA BottomColor(BottomRed, BottomGreen, BottomBlue, Alpha);
- CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, SCREEN_ASPECT_RATIO);
+ CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
@@ -381,7 +159,7 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR
bool
DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha)
{
- CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, SCREEN_ASPECT_RATIO);
+ CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
@@ -394,17 +172,6 @@ DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16
return true;
}
-void
-DoRWStuffEndOfFrame(void)
-{
- CDebug::DisplayScreenStrings(); // custom
- CDebug::DebugDisplayTextBuffer();
- FlushObrsPrintfs();
- RwCameraEndUpdate(Scene.camera);
- RsCameraShowRaster(Scene.camera);
-}
-
-
// This is certainly a very useful function
void
DoRWRenderHorizon(void)
@@ -413,127 +180,6 @@ DoRWRenderHorizon(void)
}
void
-RenderScene(void)
-{
- CClouds::Render();
- DoRWRenderHorizon();
- CRenderer::RenderRoads();
- CCoronas::RenderReflections();
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
- CRenderer::RenderEverythingBarRoads();
- CRenderer::RenderBoats();
- DefinedState();
- CWaterLevel::RenderWater();
- CRenderer::RenderFadingInEntities();
- CRenderer::RenderVehiclesButNotBoats();
- CWeather::RenderRainStreaks();
-}
-
-void
-RenderDebugShit(void)
-{
- CTheScripts::RenderTheScriptDebugLines();
- if(gbShowCollisionLines)
- CRenderer::RenderCollisionLines();
-}
-
-void
-RenderEffects(void)
-{
- CGlass::Render();
- CWaterCannons::Render();
- CSpecialFX::Render();
- CShadows::RenderStaticShadows();
- CShadows::RenderStoredShadows();
- CSkidmarks::Render();
- CAntennas::Render();
- CRubbish::Render();
- CCoronas::Render();
- CParticle::Render();
- CPacManPickups::Render();
- CWeaponEffects::Render();
- CPointLights::RenderFogEffect();
- CMovingThings::Render();
- CRenderer::RenderFirstPersonVehicle();
-}
-
-void
-Render2dStuff(void)
-{
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
-
- CReplay::Display();
- CPickups::RenderPickUpText();
-
- if(TheCamera.m_WideScreenOn)
- TheCamera.DrawBordersForWideScreen();
-
- CPed *player = FindPlayerPed();
- int weaponType = 0;
- if(player)
- weaponType = player->GetWeapon()->m_eWeaponType;
-
- bool firstPersonWeapon = false;
- int cammode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
- if(cammode == CCam::MODE_SNIPER ||
- cammode == CCam::MODE_SNIPER_RUNABOUT ||
- cammode == CCam::MODE_ROCKETLAUNCHER ||
- cammode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT)
- firstPersonWeapon = true;
-
- // Draw black border for sniper and rocket launcher
- if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER) && firstPersonWeapon){
- CRGBA black(0, 0, 0, 255);
-
- // top and bottom strips
- if (weaponType == WEAPONTYPE_ROCKETLAUNCHER) {
- CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(180)), black);
- CSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(170), SCREEN_WIDTH, SCREEN_HEIGHT), black);
- }
- else {
- CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(210)), black);
- CSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(210), SCREEN_WIDTH, SCREEN_HEIGHT), black);
- }
- CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH / 2 - SCREEN_SCALE_X(210), SCREEN_HEIGHT), black);
- CSprite2d::DrawRect(CRect(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(210), 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), black);
- }
-
- MusicManager.DisplayRadioStationName();
- TheConsole.Display();
-/*
- if(CSceneEdit::m_bEditOn)
- CSceneEdit::Draw();
- else
-*/
- CHud::Draw();
- CUserDisplay::OnscnTimer.ProcessForDisplay();
- CMessages::Display();
- CDarkel::DrawMessages();
- CGarages::PrintMessages();
- CPad::PrintErrorMessage();
- CFont::DrawFonts();
-
- DebugMenuRender();
-}
-
-void
-RenderMenus(void)
-{
- if(FrontEndMenuManager.m_bMenuActive)
- FrontEndMenuManager.DrawFrontEnd();
-}
-
-bool &JustLoadedDontFadeInYet = *(bool*)0x95CDB4;
-bool &StillToFadeOut = *(bool*)0x95CD99;
-uint32 &TimeStartedCountingForFade = *(uint32*)0x9430EC;
-uint32 &TimeToStayFadedBeforeFadeOut = *(uint32*)0x611564;
-
-void
DoFade(void)
{
if(CTimer::GetIsPaused())
@@ -613,139 +259,95 @@ DoFade(void)
}
}
-float FramesPerSecondCounter;
-int32 FrameSamples;
-
-struct tZonePrint
-{
- char name[12];
- CRect rect;
-};
-
-tZonePrint ZonePrint[] =
-{
- { "suburban", CRect(-1639.4f, 1014.3f, -226.23f, -1347.9f) },
- { "comntop", CRect(-223.52f, 203.62f, 616.79f, -413.6f) },
- { "comnbtm", CRect(-227.24f, -413.6f, 620.51f, -911.84f) },
- { "comse", CRect( 200.35f, -911.84f, 620.51f, -1737.3f) },
- { "comsw", CRect(-223.52f, -911.84f, 200.35f, -1737.3f) },
- { "industsw", CRect( 744.05f, -473.0f, 1067.5f, -1331.5f) },
- { "industne", CRect( 1067.5f, 282.19f, 1915.3f, -473.0f) },
- { "industnw", CRect( 744.05f, 324.95f, 1067.5f, -473.0f) },
- { "industse", CRect( 1070.3f, -473.0f, 1918.1f, -1331.5f) },
- { "no zone", CRect( 0.0f, 0.0f, 0.0f, 0.0f) }
-};
-
-#ifndef MASTER
void
-DisplayGameDebugText()
+DoRWStuffEndOfFrame(void)
{
- static bool bDisplayPosn = false;
- static bool bDisplayRate = false;
+ CDebug::DisplayScreenStrings(); // custom
+ CDebug::DebugDisplayTextBuffer();
+ FlushObrsPrintfs();
+ RwCameraEndUpdate(Scene.camera);
+ RsCameraShowRaster(Scene.camera);
+}
+static RwBool
+PluginAttach(void)
+{
+ if( !RpWorldPluginAttach() )
{
- SETTWEAKPATH("GameDebugText");
- TWEAKBOOL(bDisplayPosn);
- TWEAKBOOL(bDisplayRate);
+ printf("Couldn't attach world plugin\n");
+
+ return FALSE;
}
-
-
- char str[200];
- wchar ustr[200];
- wchar ver[200];
-
- AsciiToUnicode(version_name, ver);
-
- CFont::SetPropOn();
- CFont::SetBackgroundOff();
- CFont::SetFontStyle(FONT_BANK);
- CFont::SetScale(SCREEN_STRETCH_X(0.5f), SCREEN_STRETCH_Y(0.5f));
- CFont::SetCentreOff();
- CFont::SetRightJustifyOff();
- CFont::SetWrapx(SCREEN_WIDTH);
- CFont::SetJustifyOff();
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetColor(CRGBA(255, 108, 0, 255));
- CFont::PrintString(10.0f, 10.0f, ver);
-
- FrameSamples++;
- FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f);
- FramesPerSecond = FramesPerSecondCounter / FrameSamples;
- if ( FrameSamples > 30 )
+ if( !RpSkinPluginAttach() )
{
- FramesPerSecondCounter = 0.0f;
- FrameSamples = 0;
+ printf("Couldn't attach RpSkin plugin\n");
+
+ return FALSE;
}
-
- if ( !TheCamera.WorldViewerBeingUsed
- && CPad::GetPad(1)->GetSquare()
- && CPad::GetPad(1)->GetTriangle()
- && CPad::GetPad(1)->GetLeftShoulder2JustDown() )
+
+ if( !RpHAnimPluginAttach() )
{
- bDisplayPosn = !bDisplayPosn;
+ printf("Couldn't attach RpHAnim plugin\n");
+
+ return FALSE;
}
-
- if ( CPad::GetPad(1)->GetSquare()
- && CPad::GetPad(1)->GetTriangle()
- && CPad::GetPad(1)->GetRightShoulder2JustDown() )
+
+ if( !NodeNamePluginAttach() )
{
- bDisplayRate = !bDisplayRate;
+ printf("Couldn't attach node name plugin\n");
+
+ return FALSE;
}
- if ( bDisplayPosn || bDisplayRate )
+ if( !CVisibilityPlugins::PluginAttach() )
{
- CVector pos = FindPlayerCoors();
- int32 ZoneId = ARRAY_SIZE(ZonePrint)-1; // no zone
-
- for ( int32 i = 0; i < ARRAY_SIZE(ZonePrint)-1; i++ )
- {
- if ( pos.x > ZonePrint[i].rect.left
- && pos.x < ZonePrint[i].rect.right
- && pos.y > ZonePrint[i].rect.bottom
- && pos.y < ZonePrint[i].rect.top )
- {
- ZoneId = i;
- }
- }
-
- //NOTE: fps should be 30, but its 29 due to different fp2int conversion
- if ( bDisplayRate )
- sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, F-%d, %s", pos.x, pos.y, pos.z, (int32)FramesPerSecond, ZonePrint[ZoneId].name);
- else
- sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, %s", pos.x, pos.y, pos.z, ZonePrint[ZoneId].name);
-
- AsciiToUnicode(str, ustr);
+ printf("Couldn't attach visibility plugins\n");
- CFont::SetPropOff();
- CFont::SetBackgroundOff();
- CFont::SetScale(0.7f, 1.5f);
- CFont::SetCentreOff();
- CFont::SetRightJustifyOff();
- CFont::SetJustifyOff();
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetWrapx(640.0f);
- CFont::SetFontStyle(FONT_HEADING);
+ return FALSE;
+ }
+
+ if( !RpAnimBlendPluginAttach() )
+ {
+ printf("Couldn't attach RpAnimBlend plugin\n");
- CFont::SetColor(CRGBA(0, 0, 0, 255));
- CFont::PrintString(42.0f, 42.0f, ustr);
+ return FALSE;
+ }
+
+ if( !RpMatFXPluginAttach() )
+ {
+ printf("Couldn't attach RpMatFX plugin\n");
- CFont::SetColor(CRGBA(255, 108, 0, 255));
- CFont::PrintString(40.0f, 40.0f, ustr);
+ return FALSE;
}
+
+ return TRUE;
}
-#endif
-void
-Render2dStuffAfterFade(void)
+static RwBool
+Initialise3D(void *param)
{
-#ifndef MASTER
- DisplayGameDebugText();
- //PrintGameVersion();
-#endif
+ if (RsRwInitialise(param))
+ {
+ //
+ DebugMenuInit();
+ DebugMenuPopulate();
+ //
- CHud::DrawAfterFade();
- CFont::DrawFonts();
+ return CGame::InitialiseRenderWare();
+ }
+
+ return (FALSE);
+}
+
+static void
+Terminate3D(void)
+{
+ CGame::ShutdownRenderWare();
+
+ RsRwTerminate();
+
+ return;
}
CSprite2d splash;
@@ -796,8 +398,41 @@ DestroySplashScreen(void)
splashTxdId = -1;
}
-float NumberOfChunksLoaded;
-#define TOTALNUMCHUNKS 73.0f
+char*
+GetRandomSplashScreen(void)
+{
+ int index;
+ static int index2 = 0;
+ static char splashName[128];
+ static int splashIndex[24] = {
+ 25, 22, 4, 13,
+ 1, 21, 14, 16,
+ 10, 12, 5, 9,
+ 11, 18, 3, 2,
+ 19, 23, 7, 17,
+ 15, 6, 8, 20
+ };
+
+ index = splashIndex[4*index2 + CGeneral::GetRandomNumberInRange(0, 3)];
+ index2++;
+ if(index2 == 6)
+ index2 = 0;
+ sprintf(splashName, "loadsc%d", index);
+ return splashName;
+}
+
+char*
+GetLevelSplashScreen(int level)
+{
+ static char *splashScreens[4] = {
+ nil,
+ "splash1",
+ "splash2",
+ "splash3",
+ };
+
+ return splashScreens[level];
+}
void
ResetLoadingScreenBar()
@@ -820,8 +455,10 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen)
splash = LoadSplash(splashscreen);
+#ifndef GTA_PS2
if(RsGlobal.quit)
return;
+#endif
if(DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)){
CSprite2d::SetRecipNearClip();
@@ -914,131 +551,585 @@ LoadingIslandScreen(const char *levelName)
DoRWStuffEndOfFrame();
}
-char*
-GetLevelSplashScreen(int level)
-{
- static char *splashScreens[4] = {
- nil,
- "splash1",
- "splash2",
- "splash3",
- };
-
- return splashScreens[level];
+void
+ProcessSlowMode(void)
+{
+ int16 lX = CPad::GetPad(0)->NewState.LeftStickX;
+ int16 lY = CPad::GetPad(0)->NewState.LeftStickY;
+ int16 rX = CPad::GetPad(0)->NewState.RightStickX;
+ int16 rY = CPad::GetPad(0)->NewState.RightStickY;
+ int16 L1 = CPad::GetPad(0)->NewState.LeftShoulder1;
+ int16 L2 = CPad::GetPad(0)->NewState.LeftShoulder2;
+ int16 R1 = CPad::GetPad(0)->NewState.RightShoulder1;
+ int16 R2 = CPad::GetPad(0)->NewState.RightShoulder2;
+ int16 up = CPad::GetPad(0)->NewState.DPadUp;
+ int16 down = CPad::GetPad(0)->NewState.DPadDown;
+ int16 left = CPad::GetPad(0)->NewState.DPadLeft;
+ int16 right = CPad::GetPad(0)->NewState.DPadRight;
+ int16 start = CPad::GetPad(0)->NewState.Start;
+ int16 select = CPad::GetPad(0)->NewState.Select;
+ int16 square = CPad::GetPad(0)->NewState.Square;
+ int16 triangle = CPad::GetPad(0)->NewState.Triangle;
+ int16 cross = CPad::GetPad(0)->NewState.Cross;
+ int16 circle = CPad::GetPad(0)->NewState.Circle;
+ int16 L3 = CPad::GetPad(0)->NewState.LeftShock;
+ int16 R3 = CPad::GetPad(0)->NewState.RightShock;
+ int16 networktalk = CPad::GetPad(0)->NewState.NetworkTalk;
+ int16 stop = true;
+
+ do
+ {
+ if ( CPad::GetPad(1)->GetLeftShoulder1JustDown() || CPad::GetPad(1)->GetRightShoulder1() )
+ break;
+
+ if ( stop )
+ {
+ CTimer::Stop();
+ stop = false;
+ }
+
+ CPad::UpdatePads();
+
+ RwCameraBeginUpdate(Scene.camera);
+ RwCameraEndUpdate(Scene.camera);
+
+ if ( CPad::GetPad(1)->GetLeftShoulder1JustDown() || CPad::GetPad(1)->GetRightShoulder1() )
+ break;
+
+ } while (!CPad::GetPad(1)->GetRightShoulder1());
+
+
+ CPad::GetPad(0)->OldState.LeftStickX = lX;
+ CPad::GetPad(0)->OldState.LeftStickY = lY;
+ CPad::GetPad(0)->OldState.RightStickX = rX;
+ CPad::GetPad(0)->OldState.RightStickY = rY;
+ CPad::GetPad(0)->OldState.LeftShoulder1 = L1;
+ CPad::GetPad(0)->OldState.LeftShoulder2 = L2;
+ CPad::GetPad(0)->OldState.RightShoulder1 = R1;
+ CPad::GetPad(0)->OldState.RightShoulder2 = R2;
+ CPad::GetPad(0)->OldState.DPadUp = up;
+ CPad::GetPad(0)->OldState.DPadDown = down;
+ CPad::GetPad(0)->OldState.DPadLeft = left;
+ CPad::GetPad(0)->OldState.DPadRight = right;
+ CPad::GetPad(0)->OldState.Start = start;
+ CPad::GetPad(0)->OldState.Select = select;
+ CPad::GetPad(0)->OldState.Square = square;
+ CPad::GetPad(0)->OldState.Triangle = triangle;
+ CPad::GetPad(0)->OldState.Cross = cross;
+ CPad::GetPad(0)->OldState.Circle = circle;
+ CPad::GetPad(0)->OldState.LeftShock = L3;
+ CPad::GetPad(0)->OldState.RightShock = R3;
+ CPad::GetPad(0)->OldState.NetworkTalk = networktalk;
+ CPad::GetPad(0)->NewState.LeftStickX = lX;
+ CPad::GetPad(0)->NewState.LeftStickY = lY;
+ CPad::GetPad(0)->NewState.RightStickX = rX;
+ CPad::GetPad(0)->NewState.RightStickY = rY;
+ CPad::GetPad(0)->NewState.LeftShoulder1 = L1;
+ CPad::GetPad(0)->NewState.LeftShoulder2 = L2;
+ CPad::GetPad(0)->NewState.RightShoulder1 = R1;
+ CPad::GetPad(0)->NewState.RightShoulder2 = R2;
+ CPad::GetPad(0)->NewState.DPadUp = up;
+ CPad::GetPad(0)->NewState.DPadDown = down;
+ CPad::GetPad(0)->NewState.DPadLeft = left;
+ CPad::GetPad(0)->NewState.DPadRight = right;
+ CPad::GetPad(0)->NewState.Start = start;
+ CPad::GetPad(0)->NewState.Select = select;
+ CPad::GetPad(0)->NewState.Square = square;
+ CPad::GetPad(0)->NewState.Triangle = triangle;
+ CPad::GetPad(0)->NewState.Cross = cross;
+ CPad::GetPad(0)->NewState.Circle = circle;
+ CPad::GetPad(0)->NewState.LeftShock = L3;
+ CPad::GetPad(0)->NewState.RightShock = R3;
+ CPad::GetPad(0)->NewState.NetworkTalk = networktalk;
}
-char*
-GetRandomSplashScreen(void)
-{
- int index;
- static int index2 = 0;
- static char splashName[128];
- static int splashIndex[24] = {
- 25, 22, 4, 13,
- 1, 21, 14, 16,
- 10, 12, 5, 9,
- 11, 18, 3, 2,
- 19, 23, 7, 17,
- 15, 6, 8, 20
- };
- index = splashIndex[4*index2 + CGeneral::GetRandomNumberInRange(0, 3)];
- index2++;
- if(index2 == 6)
- index2 = 0;
- sprintf(splashName, "loadsc%d", index);
- return splashName;
-}
+float FramesPerSecondCounter;
+int32 FrameSamples;
-#include "rwcore.h"
-#include "rpworld.h"
-#include "rpmatfx.h"
-#include "rpskin.h"
-#include "rphanim.h"
-#include "rtbmp.h"
+struct tZonePrint
+{
+ char name[12];
+ CRect rect;
+};
-_TODO("temp, move this includes out of here")
+tZonePrint ZonePrint[] =
+{
+ { "suburban", CRect(-1639.4f, 1014.3f, -226.23f, -1347.9f) },
+ { "comntop", CRect(-223.52f, 203.62f, 616.79f, -413.6f) },
+ { "comnbtm", CRect(-227.24f, -413.6f, 620.51f, -911.84f) },
+ { "comse", CRect( 200.35f, -911.84f, 620.51f, -1737.3f) },
+ { "comsw", CRect(-223.52f, -911.84f, 200.35f, -1737.3f) },
+ { "industsw", CRect( 744.05f, -473.0f, 1067.5f, -1331.5f) },
+ { "industne", CRect( 1067.5f, 282.19f, 1915.3f, -473.0f) },
+ { "industnw", CRect( 744.05f, 324.95f, 1067.5f, -473.0f) },
+ { "industse", CRect( 1070.3f, -473.0f, 1918.1f, -1331.5f) },
+ { "no zone", CRect( 0.0f, 0.0f, 0.0f, 0.0f) }
+};
-static RwBool
-PluginAttach(void)
+#ifndef MASTER
+void
+DisplayGameDebugText()
{
- if( !RpWorldPluginAttach() )
+ static bool bDisplayPosn = false;
+ static bool bDisplayRate = false;
+
{
- printf("Couldn't attach world plugin\n");
-
- return FALSE;
+ SETTWEAKPATH("GameDebugText");
+ TWEAKBOOL(bDisplayPosn);
+ TWEAKBOOL(bDisplayRate);
}
+
+
+ char str[200];
+ wchar ustr[200];
+ wchar ver[200];
- if( !RpSkinPluginAttach() )
- {
- printf("Couldn't attach RpSkin plugin\n");
-
- return FALSE;
- }
+ AsciiToUnicode(version_name, ver);
+
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::SetScale(SCREEN_STRETCH_X(0.5f), SCREEN_STRETCH_Y(0.5f));
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOff();
+ CFont::SetWrapx(SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetColor(CRGBA(255, 108, 0, 255));
+ CFont::PrintString(10.0f, 10.0f, ver);
+
+ FrameSamples++;
+ FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f);
+ FramesPerSecond = FramesPerSecondCounter / FrameSamples;
- if( !RpHAnimPluginAttach() )
+ if ( FrameSamples > 30 )
{
- printf("Couldn't attach RpHAnim plugin\n");
-
- return FALSE;
+ FramesPerSecondCounter = 0.0f;
+ FrameSamples = 0;
}
-
- if( !NodeNamePluginAttach() )
+
+ if ( !TheCamera.WorldViewerBeingUsed
+ && CPad::GetPad(1)->GetSquare()
+ && CPad::GetPad(1)->GetTriangle()
+ && CPad::GetPad(1)->GetLeftShoulder2JustDown() )
{
- printf("Couldn't attach node name plugin\n");
-
- return FALSE;
+ bDisplayPosn = !bDisplayPosn;
}
-
- if( !CVisibilityPlugins::PluginAttach() )
+
+ if ( CPad::GetPad(1)->GetSquare()
+ && CPad::GetPad(1)->GetTriangle()
+ && CPad::GetPad(1)->GetRightShoulder2JustDown() )
{
- printf("Couldn't attach visibility plugins\n");
-
- return FALSE;
+ bDisplayRate = !bDisplayRate;
}
- if( !RpAnimBlendPluginAttach() )
+ if ( bDisplayPosn || bDisplayRate )
{
- printf("Couldn't attach RpAnimBlend plugin\n");
+ CVector pos = FindPlayerCoors();
+ int32 ZoneId = ARRAY_SIZE(ZonePrint)-1; // no zone
- return FALSE;
- }
-
- if( !RpMatFXPluginAttach() )
- {
- printf("Couldn't attach RpMatFX plugin\n");
+ for ( int32 i = 0; i < ARRAY_SIZE(ZonePrint)-1; i++ )
+ {
+ if ( pos.x > ZonePrint[i].rect.left
+ && pos.x < ZonePrint[i].rect.right
+ && pos.y > ZonePrint[i].rect.bottom
+ && pos.y < ZonePrint[i].rect.top )
+ {
+ ZoneId = i;
+ }
+ }
+
+ //NOTE: fps should be 30, but its 29 due to different fp2int conversion
+ if ( bDisplayRate )
+ sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, F-%d, %s", pos.x, pos.y, pos.z, (int32)FramesPerSecond, ZonePrint[ZoneId].name);
+ else
+ sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, %s", pos.x, pos.y, pos.z, ZonePrint[ZoneId].name);
- return FALSE;
+ AsciiToUnicode(str, ustr);
+
+ CFont::SetPropOff();
+ CFont::SetBackgroundOff();
+ CFont::SetScale(0.7f, 1.5f);
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOff();
+ CFont::SetJustifyOff();
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetWrapx(640.0f);
+ CFont::SetFontStyle(FONT_HEADING);
+
+ CFont::SetColor(CRGBA(0, 0, 0, 255));
+ CFont::PrintString(42.0f, 42.0f, ustr);
+
+ CFont::SetColor(CRGBA(255, 108, 0, 255));
+ CFont::PrintString(40.0f, 40.0f, ustr);
}
+}
+#endif
- return TRUE;
+void
+RenderScene(void)
+{
+ CClouds::Render();
+ DoRWRenderHorizon();
+ CRenderer::RenderRoads();
+ CCoronas::RenderReflections();
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ CRenderer::RenderEverythingBarRoads();
+ CRenderer::RenderBoats();
+ DefinedState();
+ CWaterLevel::RenderWater();
+ CRenderer::RenderFadingInEntities();
+ CRenderer::RenderVehiclesButNotBoats();
+ CWeather::RenderRainStreaks();
}
-static RwBool
-Initialise3D(void *param)
+void
+RenderDebugShit(void)
{
- if (RsRwInitialise(param))
- {
- //
- DebugMenuInit();
- DebugMenuPopulate();
- //
+ CTheScripts::RenderTheScriptDebugLines();
+ if(gbShowCollisionLines)
+ CRenderer::RenderCollisionLines();
+}
- return CGame::InitialiseRenderWare();
+void
+RenderEffects(void)
+{
+ CGlass::Render();
+ CWaterCannons::Render();
+ CSpecialFX::Render();
+ CShadows::RenderStaticShadows();
+ CShadows::RenderStoredShadows();
+ CSkidmarks::Render();
+ CAntennas::Render();
+ CRubbish::Render();
+ CCoronas::Render();
+ CParticle::Render();
+ CPacManPickups::Render();
+ CWeaponEffects::Render();
+ CPointLights::RenderFogEffect();
+ CMovingThings::Render();
+ CRenderer::RenderFirstPersonVehicle();
+}
+
+void
+Render2dStuff(void)
+{
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
+
+ CReplay::Display();
+ CPickups::RenderPickUpText();
+
+ if(TheCamera.m_WideScreenOn)
+ TheCamera.DrawBordersForWideScreen();
+
+ CPed *player = FindPlayerPed();
+ int weaponType = 0;
+ if(player)
+ weaponType = player->GetWeapon()->m_eWeaponType;
+
+ bool firstPersonWeapon = false;
+ int cammode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
+ if(cammode == CCam::MODE_SNIPER ||
+ cammode == CCam::MODE_SNIPER_RUNABOUT ||
+ cammode == CCam::MODE_ROCKETLAUNCHER ||
+ cammode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT)
+ firstPersonWeapon = true;
+
+ // Draw black border for sniper and rocket launcher
+ if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER) && firstPersonWeapon){
+ CRGBA black(0, 0, 0, 255);
+
+ // top and bottom strips
+ if (weaponType == WEAPONTYPE_ROCKETLAUNCHER) {
+ CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(180)), black);
+ CSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(170), SCREEN_WIDTH, SCREEN_HEIGHT), black);
+ }
+ else {
+ CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(210)), black);
+ CSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(210), SCREEN_WIDTH, SCREEN_HEIGHT), black);
+ }
+ CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH / 2 - SCREEN_SCALE_X(210), SCREEN_HEIGHT), black);
+ CSprite2d::DrawRect(CRect(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(210), 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), black);
}
- return (FALSE);
+ MusicManager.DisplayRadioStationName();
+ TheConsole.Display();
+/*
+ if(CSceneEdit::m_bEditOn)
+ CSceneEdit::Draw();
+ else
+*/
+ CHud::Draw();
+ CUserDisplay::OnscnTimer.ProcessForDisplay();
+ CMessages::Display();
+ CDarkel::DrawMessages();
+ CGarages::PrintMessages();
+ CPad::PrintErrorMessage();
+ CFont::DrawFonts();
+
+ DebugMenuRender();
+}
+
+void
+RenderMenus(void)
+{
+#ifdef PS2
+ if (FrontEndMenuManager.m_bWantToDraw)
+ {
+ gMainHeap.PushMemId(_TODOCONST(17));
+ FrontEndMenuManager.DrawFrontEnd();
+ gMainHeap.PopMemId();
+ }
+#else
+ if(FrontEndMenuManager.m_bMenuActive)
+ FrontEndMenuManager.DrawFrontEnd();
+#endif
}
+void
+Render2dStuffAfterFade(void)
+{
+#ifndef MASTER
+ DisplayGameDebugText();
+#endif
+
+ CHud::DrawAfterFade();
+ CFont::DrawFonts();
+}
-static void
-Terminate3D(void)
+void
+Idle(void *arg)
{
- CGame::ShutdownRenderWare();
+#ifdef ASPECT_RATIO_SCALE
+ CDraw::SetAspectRatio(CDraw::FindAspectRatio());
+#endif
+
+ CTimer::Update();
+
+#ifdef TIMEBARS
+ tbInit();
+#endif
+
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+
+ // We're basically merging FrontendIdle and Idle (just like TheGame on PS2)
+#ifdef PS2_SAVE_DIALOG
+ // Only exists on PC FrontendIdle, probably some PS2 bug fix
+ if (FrontEndMenuManager.m_bMenuActive)
+ CSprite2d::SetRecipNearClip();
- RsRwTerminate();
+ if (FrontEndMenuManager.m_bGameNotLoaded) {
+ CPad::UpdatePads();
+ FrontEndMenuManager.Process();
+ } else {
+ CPointLights::InitPerFrame();
+#ifdef TIMEBARS
+ tbStartTimer(0, "CGame::Process");
+#endif
+ CGame::Process();
+#ifdef TIMEBARS
+ tbEndTimer("CGame::Process");
+ tbStartTimer(0, "DMAudio.Service");
+#endif
+ DMAudio.Service();
- return;
+#ifdef TIMEBARS
+ tbEndTimer("DMAudio.Service");
+#endif
+ }
+
+ if (RsGlobal.quit)
+ return;
+#else
+ CPointLights::InitPerFrame();
+#ifdef TIMEBARS
+ tbStartTimer(0, "CGame::Process");
+#endif
+ CGame::Process();
+#ifdef TIMEBARS
+ tbEndTimer("CGame::Process");
+ tbStartTimer(0, "DMAudio.Service");
+#endif
+
+ DMAudio.Service();
+
+#ifdef TIMEBARS
+ tbEndTimer("DMAudio.Service");
+#endif
+#endif
+
+ if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){
+ FrontEndMenuManager.m_bWantToRestart = true;
+ FrontEndMenuManager.m_bWantToLoad = false;
+ return;
+ }
+
+ if(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
+ return;
+
+ SetLightsWithTimeOfDayColour(Scene.world);
+
+ if(arg == nil)
+ return;
+
+ if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) &&
+ TheCamera.GetScreenFadeStatus() != FADE_2)
+ {
+#ifdef GTA_PC
+ if (!FrontEndMenuManager.m_bRenderGameInMenu) {
+ // This is from SA, but it's nice for windowed mode
+ RwV2d pos;
+ pos.x = SCREEN_WIDTH / 2.0f;
+ pos.y = SCREEN_HEIGHT / 2.0f;
+ RsMouseSetPos(&pos);
+ }
+#endif
+#ifdef TIMEBARS
+ tbStartTimer(0, "CnstrRenderList");
+#endif
+ CRenderer::ConstructRenderList();
+#ifdef TIMEBARS
+ tbEndTimer("CnstrRenderList");
+ tbStartTimer(0, "PreRender");
+#endif
+ CRenderer::PreRender();
+#ifdef TIMEBARS
+ tbEndTimer("PreRender");
+#endif
+
+ if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
+ if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))
+ return;
+ }else{
+ if(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
+ CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
+ 255))
+ return;
+ }
+
+ DefinedState();
+
+ // BUG. This has to be done BEFORE RwCameraBeginUpdate
+ RwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());
+ RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());
+
+#ifdef TIMEBARS
+ tbStartTimer(0, "RenderScene");
+#endif
+ RenderScene();
+#ifdef TIMEBARS
+ tbEndTimer("RenderScene");
+#endif
+ RenderDebugShit();
+ RenderEffects();
+
+#ifdef TIMEBARS
+ tbStartTimer(0, "RenderMotionBlur");
+#endif
+ if((TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL) &&
+ TheCamera.m_ScreenReductionPercentage > 0.0f)
+ TheCamera.SetMotionBlurAlpha(150);
+ TheCamera.RenderMotionBlur();
+#ifdef TIMEBARS
+ tbEndTimer("RenderMotionBlur");
+ tbStartTimer(0, "Render2dStuff");
+#endif
+ Render2dStuff();
+#ifdef TIMEBARS
+ tbEndTimer("Render2dStuff");
+#endif
+ }else{
+#ifdef ASPECT_RATIO_SCALE
+ CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);
+#else
+ CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
+#endif
+ CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
+ RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
+ if(!RsCameraBeginUpdate(Scene.camera))
+ return;
+ }
+
+#ifdef PS2_SAVE_DIALOG
+ if (FrontEndMenuManager.m_bMenuActive)
+ DefinedState();
+#endif
+#ifdef TIMEBARS
+ tbStartTimer(0, "RenderMenus");
+#endif
+ RenderMenus();
+#ifdef TIMEBARS
+ tbEndTimer("RenderMenus");
+ tbStartTimer(0, "DoFade");
+#endif
+ DoFade();
+#ifdef TIMEBARS
+ tbEndTimer("DoFade");
+ tbStartTimer(0, "Render2dStuff-Fade");
+#endif
+ Render2dStuffAfterFade();
+#ifdef TIMEBARS
+ tbEndTimer("Render2dStuff-Fade");
+#endif
+ CCredits::Render();
+
+#ifdef TIMEBARS
+ tbDisplay();
+#endif
+
+ DoRWStuffEndOfFrame();
+
+ if(g_SlowMode)
+ ProcessSlowMode();
+}
+
+void
+FrontendIdle(void)
+{
+#ifdef ASPECT_RATIO_SCALE
+ CDraw::SetAspectRatio(CDraw::FindAspectRatio());
+#endif
+
+ CTimer::Update();
+ CSprite2d::SetRecipNearClip(); // this should be on InitialiseRenderWare according to PS2 asm. seems like a bug fix
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+ CPad::UpdatePads();
+ FrontEndMenuManager.Process();
+
+ if(RsGlobal.quit)
+ return;
+
+#ifdef ASPECT_RATIO_SCALE
+ CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);
+#else
+ CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
+#endif
+ CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
+ RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
+ if(!RsCameraBeginUpdate(Scene.camera))
+ return;
+
+ DefinedState(); // seems redundant, but breaks resolution change.
+ RenderMenus();
+ DoFade();
+ Render2dStuffAfterFade();
+// CFont::DrawFonts(); // redundant
+ DoRWStuffEndOfFrame();
+}
+
+void
+InitialiseGame(void)
+{
+ LoadingScreen(nil, nil, "loadsc0");
+ CGame::Initialise("DATA\\GTA3.DAT");
}
RsEventStatus
@@ -1056,7 +1147,7 @@ AppEventHandler(RsEvent event, void *param)
{
CameraSize(Scene.camera, (RwRect *)param,
- DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
+ SCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
return rsEVENTPROCESSED;
}
@@ -1133,58 +1224,615 @@ AppEventHandler(RsEvent event, void *param)
}
}
-void PrintGameVersion()
+#ifndef MASTER
+void
+TheModelViewer(void)
{
- CFont::SetPropOn();
- CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.5f));
- CFont::SetCentreOff();
- CFont::SetRightJustifyOff();
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_BANK);
- CFont::SetWrapx(SCREEN_WIDTH);
- CFont::SetDropShadowPosition(0);
- CFont::SetDropColor(CRGBA(0, 0, 0, 255));
- CFont::SetColor(CRGBA(235, 170, 50, 255));
+#if (defined(GTA_PS2) || defined(GTA_XBOX))
+ //TODO
+#else
+#ifdef ASPECT_RATIO_SCALE
+ CDraw::SetAspectRatio(CDraw::FindAspectRatio());
+#endif
+ CAnimViewer::Update();
+ CTimer::Update();
+ SetLightsWithTimeOfDayColour(Scene.world);
+ CRenderer::ConstructRenderList();
+ DoRWStuffStartOfFrame(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
+ CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
+ 255);
- strcpy(gString, "RE3");
- AsciiToUnicode(gString, gUString);
- CFont::PrintString(SCREEN_SCALE_X(10.5f), SCREEN_SCALE_Y(8.0f), gUString);
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+ DefinedState();
+ CVisibilityPlugins::InitAlphaEntityList();
+ CAnimViewer::Render();
+ Render2dStuff();
+ DoRWStuffEndOfFrame();
+#endif
}
+#endif
-void
-ValidateVersion()
+void TheGame(void)
{
- int32 file = CFileMgr::OpenFile("models\\coll\\peds.col", "rb");
- char buff[128];
+ printf("Into TheGame!!!\n");
- if ( file != -1 )
+#ifdef GTA_PS2
+ gMainHeap.PushMemId(_TODOCONST(1));
+#endif
+
+ CTimer::Initialise();
+
+#ifdef GTA_PS2
+ CGame::Initialise();
+#else
+ CGame::Initialise("DATA\\GTA3.DAT");
+#endif
+
+ char *splash = GetRandomSplashScreen(); // inlined here
+
+ LoadingScreen("Starting Game", NULL, splash);
+
+#ifdef GTA_PS2
+ if ( TheMemoryCard.CheckCardInserted(_TODOCONST(0)) == _TODOCONST(26)
+ && TheMemoryCard.ChangeDirectory(_TODOCONST(0), TheMemoryCard.field154)
+ && TheMemoryCard.FindMostRecentFileName(_TODOCONST(0), TheMemoryCard.field37) == 1
+ && TheMemoryCard.CheckDataNotCorrupt(TheMemoryCard.field37))
{
- CFileMgr::Seek(file, 100, SEEK_SET);
-
- for ( int i = 0; i < 128; i++ )
+ strcpy(TheMemoryCard.LoadFileName, TheMemoryCard.field37);
+ TheMemoryCard.b_FoundRecentSavedGameWantToLoad = true;
+
+ if (CMenuManager::m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad())
{
- CFileMgr::Read(file, &buff[i], sizeof(char));
- buff[i] -= 23;
- if ( buff[i] == '\0' )
+ CMenuManager::m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad();
+ TheText.Unload();
+ TheText.Load();
+ }
+
+ CGame::currLevel = TheMemoryCard.GetLevelToLoad();
+ }
+#else
+ //TODO
+#endif
+
+ while (true)
+ {
+#ifdef PS2
+ if (TheMemoryCard.m_bWantToLoad)
+#else
+ if (FrontEndMenuManager.m_bWantToLoad)
+#endif
+ {
+ char *splash1 = GetLevelSplashScreen(CGame::currLevel);
+ LoadSplash(splash1);
+ }
+
+#ifdef PS2
+ TheMemoryCard.m_bWantToLoad = false;
+#else
+ FrontEndMenuManager.m_bWantToLoad = false;
+#endif
+
+ CTimer::Update();
+
+#ifdef PS2
+ while (!(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad))
+#else
+ while (!(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad))
+#endif
+ {
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+
+#ifdef GTA_PS2
+ gMainHeap.PushMemId(_TODOCONST(12));
+#endif
+ CPointLights::NumLights = 0;
+ CGame::Process();
+#ifdef GTA_PS2
+ gMainHeap.PopMemId();
+#endif
+
+ DMAudio.Service();
+
+ if (CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing())
+ {
+#ifdef PS2
+ TheMemoryCard.m_bWantToLoad = false;
+#else
+ FrontEndMenuManager.m_bWantToLoad = false;
+#endif
+ FrontEndMenuManager.m_bWantToRestart = true;
break;
- CFileMgr::Seek(file, 99, SEEK_CUR);
+ }
+
+#ifdef PS2
+ if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
+#else
+ if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
+#endif
+ break;
+
+ SetLightsWithTimeOfDayColour(Scene.world);
+#ifdef GTA_PS2
+ gMainHeap.PushMemId(_TODOCONST(15));
+#endif
+
+ if (!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true && TheCamera.GetScreenFadeStatus() != FADE_2 )
+ {
+#ifdef GTA_PS2
+ gMainHeap.PushMemId(_TODOCONST(11));
+#endif
+ CRenderer::ConstructRenderList();
+ CRenderer::PreRender();
+#ifdef GTA_PS2
+ gMainHeap.PopMemId();
+#endif
+
+ if (CWeather::LightningFlash && !CCullZones::CamNoRain())
+ DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255);
+ else
+ DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(), CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(), 255);
+
+ DefinedState();
+ RwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());
+ RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());
+
+ RenderScene();
+ RenderDebugShit();
+ RenderEffects();
+
+ if ((TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL) && TheCamera.m_ScreenReductionPercentage > 0.0f)
+ TheCamera.SetMotionBlurAlpha(150);
+ TheCamera.RenderMotionBlur();
+
+ Render2dStuff();
+ }
+ else
+ {
+ CameraSize(Scene.camera, NULL, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);
+ CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
+ RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
+ if (!RsCameraBeginUpdate(Scene.camera))
+ break;
+ }
+
+ RenderMenus();
+
+#ifdef PS2
+ if (TheMemoryCard.m_bWantToLoad)
+#else
+ if (FrontEndMenuManager.m_bWantToLoad)
+#endif
+ {
+#ifdef GTA_PS2
+ gMainHeap.PopMemId();
+#endif
+ break;
+ }
+
+ DoFade();
+ Render2dStuffAfterFade();
+ CCredits::Render();
+
+ DoRWStuffEndOfFrame();
+
+ while (frameCount < 2)
+ ;
+
+ frameCount = 0;
+
+ CTimer::Update();
+
+#ifdef GTA_PS2
+ gMainHeap.PopMemId();
+#endif
+
+ if (g_SlowMode)
+ ProcessSlowMode();
}
-
- if ( !strncmp(buff, "grandtheftauto3", 15) )
+
+ CPad::ResetCheats();
+ CPad::StopPadsShaking();
+ DMAudio.ChangeMusicMode(MUSICMODE_DISABLE);
+ CGame::ShutDownForRestart();
+ CTimer::Stop();
+
+#ifdef PS2
+ if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
+#else
+ if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
+#endif
{
- strncpy(version_name, &buff[15], 64);
- CFileMgr::CloseFile(file);
- return;
+#ifdef PS2
+ if (TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
+#else
+ if (b_FoundRecentSavedGameWantToLoad)
+#endif
+ {
+ FrontEndMenuManager.m_bWantToRestart = true;
+#ifdef PS2
+ TheMemoryCard.m_bWantToLoad = true;
+#else
+ FrontEndMenuManager.m_bWantToLoad = true;
+#endif
+ }
+
+ CGame::InitialiseWhenRestarting();
+ DMAudio.ChangeMusicMode(MUSICMODE_GAME);
+ FrontEndMenuManager.m_bWantToRestart = false;
+
+ continue;
}
+
+ break;
}
- LoadingScreen("Invalid version", NULL, NULL);
+ DMAudio.Terminate();
+}
+
+
+void SystemInit()
+{
+#ifdef __MWERKS__
+ mwInit();
+#endif
- while(true)
- {
+#ifdef GTA_PS2
+ InitMemoryMgr();
+#endif
+
+#ifdef GTA_PS2
+ CFileMgr::InitCdSystem();
+
+ char path[256];
+
+ sprintf(path, "cdrom0:\\%s%s;1", "SYSTEM\\", "IOPRP23.IMG");
+
+ sceSifInitRpc(0);
+
+ while ( !sceSifRebootIop(path) )
+ ;
+ while( !sceSifSyncIop() )
;
+
+ sceSifInitRpc(0);
+
+ CFileMgr::InitCdSystem();
+
+ sceFsReset();
+#endif
+
+ CFileMgr::Initialise();
+
+#ifdef GTA_PS2
+ CFileMgr::InitCd();
+
+ Char modulepath[256];
+
+ strcpy(modulepath, "cdrom0:\\");
+ strcat(modulepath, "SYSTEM\\");
+ strcat(modulepath, "SIO2MAN.IRX");
+ LoadModule(modulepath);
+
+ strcpy(modulepath, "cdrom0:\\");
+ strcat(modulepath, "SYSTEM\\");
+ strcat(modulepath, "PADMAN.IRX");
+ LoadModule(modulepath);
+
+ strcpy(modulepath, "cdrom0:\\");
+ strcat(modulepath, "SYSTEM\\");
+ strcat(modulepath, "LIBSD.IRX");
+ LoadModule(modulepath);
+
+ strcpy(modulepath, "cdrom0:\\");
+ strcat(modulepath, "SYSTEM\\");
+ strcat(modulepath, "SDRDRV.IRX");
+ LoadModule(modulepath);
+
+ strcpy(modulepath, "cdrom0:\\");
+ strcat(modulepath, "SYSTEM\\");
+ strcat(modulepath, "MCMAN.IRX");
+ LoadModule(modulepath);
+
+ strcpy(modulepath, "cdrom0:\\");
+ strcat(modulepath, "SYSTEM\\");
+ strcat(modulepath, "MCSERV.IRX");
+ LoadModule(modulepath);
+#endif
+
+
+#ifdef GTA_PS2
+ ThreadParam param;
+
+ param.entry = &IdleThread;
+ param.stack = idleThreadStack;
+ param.stackSize = 2048;
+ param.initPriority = 127;
+ param.gpReg = &_gp;
+
+ int thread = CreateThread(&param);
+ StartThread(thread, NULL);
+#else
+ //
+#endif
+
+
+ CPad::Initialise();
+ CPad::GetPad(0)->Mode = 0;
+
+ CGame::frenchGame = false;
+ CGame::germanGame = false;
+ CGame::nastyGame = true;
+ CMenuManager::m_PrefsAllowNastyGame = true;
+
+#ifdef GTA_PS2
+ int32 lang = sceScfGetLanguage();
+ if ( lang == SCE_ITALIAN_LANGUAGE )
+ CMenuManager::m_PrefsLanguage = LANGUAGE_ITALIAN;
+ else if ( lang == SCE_SPANISH_LANGUAGE )
+ CMenuManager::m_PrefsLanguage = LANGUAGE_SPANISH;
+ else if ( lang == SCE_GERMAN_LANGUAGE )
+ {
+ CGame::germanGame = true;
+ CGame::nastyGame = false;
+ CMenuManager::m_PrefsAllowNastyGame = false;
+ CMenuManager::m_PrefsLanguage = LANGUAGE_GERMAN;
}
+ else if ( lang == SCE_FRENCH_LANGUAGE )
+ {
+ CGame::frenchGame = true;
+ CGame::nastyGame = false;
+ CMenuManager::m_PrefsAllowNastyGame = false;
+ CMenuManager::m_PrefsLanguage = LANGUAGE_FRENCH;
+ }
+ else
+ CMenuManager::m_PrefsLanguage = LANGUAGE_AMERICAN;
+
+ FrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame();
+#else
+ //
+#endif
+
+#ifdef PS2
+ TheMemoryCard.Init();
+#endif
+}
+
+void GameInit()
+{
+ if ( !gameAlreadyInitialised )
+ {
+#ifdef GTA_PS2
+ char path[256];
+
+ strcpy(path, "cdrom0:\\");
+ strcat(path, "SYSTEM\\");
+ strcat(path, "CDSTREAM.IRX");
+ LoadModule(path);
+
+ strcpy(path, "cdrom0:\\");
+ strcat(path, "SYSTEM\\");
+ strcat(path, "SAMPMAN.IRX");
+ LoadModule(path);
+
+ strcpy(path, "cdrom0:\\");
+ strcat(path, "SYSTEM\\");
+ strcat(path, "MUSICSTR.IRX");
+ LoadModule(path);
+#endif
+ CdStreamInit(MAX_CDCHANNELS);
+
+#ifdef PS2
+ Initialise3D(); //no params
+#else
+ //TODO
+#endif
+
+#ifdef GTA_PS2
+ char *files[] =
+ {
+ "\\ANIM\\CUTS.IMG;1",
+ "\\ANIM\\CUTS.DIR;1",
+ "\\ANIM\\PED.IFP;1",
+ "\\MODELS\\FRONTEND.TXD;1",
+ "\\MODELS\\FONTS.TXD;1",
+ "\\MODELS\\HUD.TXD;1",
+ "\\MODELS\\PARTICLE.TXD;1",
+ "\\MODELS\\MISC.TXD;1",
+ "\\MODELS\\GENERIC.TXD;1",
+ "\\MODELS\\GTA3.DIR;1",
+ "\\TEXT\\ENGLISH.GXT;1",
+ "\\TEXT\\FRENCH.GXT;1",
+ "\\TEXT\\GERMAN.GXT;1",
+ "\\TEXT\\ITALIAN.GXT;1",
+ "\\TEXT\\SPANISH.GXT;1",
+ "\\TXD\\LOADSC0.TXD;1",
+ "\\TXD\\LOADSC1.TXD;1",
+ "\\TXD\\LOADSC2.TXD;1",
+ "\\TXD\\LOADSC3.TXD;1",
+ "\\TXD\\LOADSC4.TXD;1",
+ "\\TXD\\LOADSC5.TXD;1",
+ "\\TXD\\LOADSC6.TXD;1",
+ "\\TXD\\LOADSC7.TXD;1",
+ "\\TXD\\LOADSC8.TXD;1",
+ "\\TXD\\LOADSC9.TXD;1",
+ "\\TXD\\LOADSC10.TXD;1",
+ "\\TXD\\LOADSC11.TXD;1",
+ "\\TXD\\LOADSC12.TXD;1",
+ "\\TXD\\LOADSC13.TXD;1",
+ "\\TXD\\LOADSC14.TXD;1",
+ "\\TXD\\LOADSC15.TXD;1",
+ "\\TXD\\LOADSC16.TXD;1",
+ "\\TXD\\LOADSC17.TXD;1",
+ "\\TXD\\LOADSC18.TXD;1",
+ "\\TXD\\LOADSC19.TXD;1",
+ "\\TXD\\LOADSC20.TXD;1",
+ "\\TXD\\LOADSC21.TXD;1",
+ "\\TXD\\LOADSC22.TXD;1",
+ "\\TXD\\LOADSC23.TXD;1",
+ "\\TXD\\LOADSC24.TXD;1",
+ "\\TXD\\LOADSC25.TXD;1",
+ "\\TXD\\NEWS.TXD;1",
+ "\\MODELS\\COLL\\GENERIC.COL;1",
+ "\\MODELS\\COLL\\INDUST.COL;1",
+ "\\MODELS\\COLL\\COMMER.COL;1",
+ "\\MODELS\\COLL\\SUBURB.COL;1",
+ "\\MODELS\\COLL\\WEAPONS.COL;1",
+ "\\MODELS\\COLL\\VEHICLES.COL;1",
+ "\\MODELS\\COLL\\PEDS.COL;1",
+ "\\MODELS\\GENERIC\\AIR_VLO.DFF;1",
+ "\\MODELS\\GENERIC\\WEAPONS.DFF;1",
+ "\\MODELS\\GENERIC\\WHEELS.DFF;1",
+ "\\MODELS\\GENERIC\\LOPLYGUY.DFF;1",
+ "\\MODELS\\GENERIC\\ARROW.DFF;1",
+ "\\MODELS\\GENERIC\\ZONECYLB.DFF;1",
+ "\\DATA\\MAPS\\COMNTOP.IPL;1",
+ "\\DATA\\MAPS\\COMNBTM.IPL;1",
+ "\\DATA\\MAPS\\COMSE.IPL;1",
+ "\\DATA\\MAPS\\COMSW.IPL;1",
+ "\\DATA\\MAPS\\CULL.IPL;1",
+ "\\DATA\\MAPS\\INDUSTNE.IPL;1",
+ "\\DATA\\MAPS\\INDUSTNW.IPL;1",
+ "\\DATA\\MAPS\\INDUSTSE.IPL;1",
+ "\\DATA\\MAPS\\INDUSTSW.IPL;1",
+ "\\DATA\\MAPS\\SUBURBNE.IPL;1",
+ "\\DATA\\MAPS\\SUBURBSW.IPL;1",
+ "\\DATA\\MAPS\\OVERVIEW.IPL;1",
+ "\\DATA\\MAPS\\PROPS.IPL;1",
+ "\\DATA\\MAPS\\GTA3.IDE;1",
+ "\\DATA\\PATHS\\FLIGHT.DAT;1",
+ "\\DATA\\PATHS\\FLIGHT2.DAT;1",
+ "\\DATA\\PATHS\\FLIGHT3.DAT;1",
+ "\\DATA\\PATHS\\FLIGHT4.DAT;1",
+ "\\DATA\\PATHS\\TRACKS.DAT;1",
+ "\\DATA\\PATHS\\TRACKS2.DAT;1",
+ "\\DATA\\PATHS\\CHASE0.DAT;1",
+ "\\DATA\\PATHS\\CHASE1.DAT;1",
+ "\\DATA\\PATHS\\CHASE2.DAT;1",
+ "\\DATA\\PATHS\\CHASE3.DAT;1",
+ "\\DATA\\PATHS\\CHASE4.DAT;1",
+ "\\DATA\\PATHS\\CHASE5.DAT;1",
+ "\\DATA\\PATHS\\CHASE6.DAT;1",
+ "\\DATA\\PATHS\\CHASE7.DAT;1",
+ "\\DATA\\PATHS\\CHASE10.DAT;1",
+ "\\DATA\\PATHS\\CHASE11.DAT;1",
+ "\\DATA\\PATHS\\CHASE14.DAT;1",
+ "\\DATA\\PATHS\\CHASE16.DAT;1",
+ "\\DATA\\PATHS\\CHASE18.DAT;1",
+ "\\DATA\\PATHS\\CHASE19.DAT;1"
+ };
+
+ for ( int32 i = 0; i < ARRAY_SIZE(files); i++ )
+ SkyRegisterFileOnCd([i]);
+#endif
+
+ CreateDebugFont();
+
+#ifdef GTA_PS2
+ AddIntcHandler(_TODOCONST(2), VBlankCounter, 0);
+#endif
+
+ CameraSize(Scene.camera, NULL, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
+
+ CSprite2d::SetRecipNearClip();
+ CTxdStore::Initialise();
+#ifdef GTA_PS2
+ gMainHeap.PushMemId(_TODOCONST(9));
+#endif
+ CFont::Initialise();
+ CHud::Initialise();
+#ifdef GTA_PS2
+ gMainHeap.PopMemId();
+#endif
+
+ ValidateVersion();
+
+#ifdef GTA_PS2
+ sceCdCLOCK rtc;
+ sceCdReadClock(&rtc);
+ uint32 seed = rtc.minute + rtc.day;
+ uint32 seed2 = (seed << 4)-seed;
+ uint32 seed3 = (seed2 << 4)-seed2;
+ srand ((seed3<<4)+rtc.second);
+#else
+ //TODO: mysrand();
+#endif
+
+ gameAlreadyInitialised = true;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+#ifdef __MWERKS__
+ mwInit(); // metrowerks initialisation
+#endif
+
+ SystemInit();
+
+#ifdef PS2
+ int32 state = TheMemoryCard.CheckCardStateAtGameStartUp(_TODOCONST(0));
+
+ if ( state == _TODOCONST(2) || state == _TODOCONST(1) && state != _TODOCONST(3) && state != _TODOCONST(0) )
+ {
+ GameInit();
+
+ TheText.Unload();
+ TheText.Load();
+
+ CFont::Initialise();
+
+ FrontEndMenuManager.DrawMemoryCardStartUpMenus();
+ }
+#endif
+
+#ifdef GTA_PS2
+ {
+ if (gameAlreadyInitialised)
+ RpSkySuspend();
+
+ InitMPEGPlayer();
+
+ PlayMPEG("cdrom0:\\MOVIES\\DMAPAL.PSS;1", false);
+
+ if (CGame::frenchGame || CGame::germanGame)
+ PlayMPEG("cdrom0:\\MOVIES\\INTROPAF.PSS;1", true);
+ else
+ PlayMPEG("cdrom0:\\MOVIES\\INTROPAL.PSS;1", true);
+
+ ShutdownMPEGPlayer();
+
+ if ( gameAlreadyInitialised )
+ RpSkyResume();
+ }
+#else
+ //TODO
+#endif
+
+ GameInit();
+
+ if ( CGame::frenchGame || CGame::germanGame )
+ LoadingScreen(NULL, version_name, "loadsc24");
+ else
+ LoadingScreen(NULL, version_name, "loadsc0");
+
+ DMAudio.Initialise();
+
+ TheGame();
+
+ CGame::ShutDown();
+
+ RwEngineStop();
+ RwEngineClose();
+ RwEngineTerm();
+
+#ifdef __MWERKS__
+ mwExit(); // metrowerks shutdown
+#endif
+
+ return 0;
}
STARTPATCHES
diff --git a/src/core/obrstr.cpp b/src/core/obrstr.cpp
index 3663d134..d9f7e9b4 100644
--- a/src/core/obrstr.cpp
+++ b/src/core/obrstr.cpp
@@ -1,119 +1,119 @@
-#include "common.h"
-#include "Debug.h"
-#include "obrstr.h"
-
-char obrstr[128];
-char obrstr2[128];
-
-void ObrInt(int32 n1)
-{
- IntToStr(n1, obrstr);
- CDebug::DebugAddText(obrstr);
-}
-
-void ObrInt2(int32 n1, int32 n2)
-{
- IntToStr(n1, obrstr);
- strcat(obrstr, " ");
- IntToStr(n2, obrstr2);
- strcat(obrstr, obrstr2);
- CDebug::DebugAddText(obrstr);
-}
-
-void ObrInt3(int32 n1, int32 n2, int32 n3)
-{
- IntToStr(n1, obrstr);
- strcat(obrstr, " ");
- IntToStr(n2, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n3, obrstr2);
- strcat(obrstr, obrstr2);
- CDebug::DebugAddText(obrstr);
-}
-
-void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4)
-{
- IntToStr(n1, obrstr);
- strcat(obrstr, " ");
- IntToStr(n2, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n3, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n4, obrstr2);
- strcat(obrstr, obrstr2);
- CDebug::DebugAddText(obrstr);
-}
-
-void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5)
-{
- IntToStr(n1, obrstr);
- strcat(obrstr, " ");
- IntToStr(n2, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n3, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n4, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n5, obrstr2);
- strcat(obrstr, obrstr2);
- CDebug::DebugAddText(obrstr);
-}
-
-void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
-{
- IntToStr(n1, obrstr);
- strcat(obrstr, " ");
- IntToStr(n2, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n3, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n4, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n5, obrstr2);
- strcat(obrstr, obrstr2);
- strcat(obrstr, " ");
- IntToStr(n6, obrstr2);
- strcat(obrstr, obrstr2);
- CDebug::DebugAddText(obrstr);
-}
-
-void IntToStr(int32 inNum, char *outStr)
-{
- bool isNeg = inNum < 0;
-
- if (isNeg) {
- inNum = -inNum;
- *outStr = '-';
- }
-
- int16 digits = 1;
-
- if (inNum > 9) {
- int32 _inNum = inNum;
- do {
- digits++;
- _inNum /= 10;
- } while (_inNum > 9);
- }
-
- int32 strSize = digits;
- if (isNeg)
- strSize++;
-
- char *pStr = &outStr[strSize];
- int32 i = 0;
- do {
- *(pStr-- - 1) = (inNum % 10) + '0';
- inNum /= 10;
- } while (++i < strSize);
- outStr[strSize] = '\0';
+#include "common.h"
+#include "Debug.h"
+#include "obrstr.h"
+
+char obrstr[128];
+char obrstr2[128];
+
+void ObrInt(int32 n1)
+{
+ IntToStr(n1, obrstr);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt2(int32 n1, int32 n2)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt3(int32 n1, int32 n2, int32 n3)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n4, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n4, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n5, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ IntToStr(n1, obrstr);
+ strcat(obrstr, " ");
+ IntToStr(n2, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n3, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n4, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n5, obrstr2);
+ strcat(obrstr, obrstr2);
+ strcat(obrstr, " ");
+ IntToStr(n6, obrstr2);
+ strcat(obrstr, obrstr2);
+ CDebug::DebugAddText(obrstr);
+}
+
+void IntToStr(int32 inNum, char *outStr)
+{
+ bool isNeg = inNum < 0;
+
+ if (isNeg) {
+ inNum = -inNum;
+ *outStr = '-';
+ }
+
+ int16 digits = 1;
+
+ if (inNum > 9) {
+ int32 _inNum = inNum;
+ do {
+ digits++;
+ _inNum /= 10;
+ } while (_inNum > 9);
+ }
+
+ int32 strSize = digits;
+ if (isNeg)
+ strSize++;
+
+ char *pStr = &outStr[strSize];
+ int32 i = 0;
+ do {
+ *(pStr-- - 1) = (inNum % 10) + '0';
+ inNum /= 10;
+ } while (++i < strSize);
+ outStr[strSize] = '\0';
} \ No newline at end of file
diff --git a/src/core/obrstr.h b/src/core/obrstr.h
index 6838afb5..c1633614 100644
--- a/src/core/obrstr.h
+++ b/src/core/obrstr.h
@@ -1,9 +1,9 @@
-#pragma once
-
-void ObrInt(int32 n1);
-void ObrInt2(int32 n1, int32 n2);
-void ObrInt3(int32 n1, int32 n2, int32 n3);
-void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4);
-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);
+#pragma once
+
+void ObrInt(int32 n1);
+void ObrInt2(int32 n1, int32 n2);
+void ObrInt3(int32 n1, int32 n2, int32 n3);
+void ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4);
+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 IntToStr(int32 inNum, char *outStr); \ No newline at end of file
diff --git a/src/core/timebars.cpp b/src/core/timebars.cpp
index 30421731..93d85f8d 100644
--- a/src/core/timebars.cpp
+++ b/src/core/timebars.cpp
@@ -1,121 +1,121 @@
-#ifndef MASTER
-#include "common.h"
-#include "Font.h"
-#include "Frontend.h"
-#include "Timer.h"
-#include "Text.h"
-
-#define MAX_TIMERS (50)
-#define MAX_MS_COLLECTED (40)
-
-// enables frame time output
-#define FRAMETIME
-
-struct sTimeBar
-{
- char name[20];
- float startTime;
- float endTime;
- int32 unk;
-};
-
-struct
-{
- sTimeBar Timers[MAX_TIMERS];
- uint32 count;
-} TimerBar;
-float MaxTimes[MAX_TIMERS];
-float MaxFrameTime;
-
-uint32 curMS;
-uint32 msCollected[MAX_MS_COLLECTED];
-#ifdef FRAMETIME
-float FrameInitTime;
-#endif
-
-void tbInit()
-{
- TimerBar.count = 0;
- uint32 i = CTimer::GetFrameCounter() & 0x7F;
- if (i == 0) {
- do
- MaxTimes[i++] = 0.0f;
- while (i != MAX_TIMERS);
-#ifdef FRAMETIME
- MaxFrameTime = 0.0f;
-#endif
- }
-#ifdef FRAMETIME
- FrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
-#endif
-}
-
-void tbStartTimer(int32 unk, char *name)
-{
- strcpy(TimerBar.Timers[TimerBar.count].name, name);
- TimerBar.Timers[TimerBar.count].unk = unk;
- TimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
- TimerBar.count++;
-}
-
-void tbEndTimer(char* name)
-{
- uint32 n = 1500;
- for (uint32 i = 0; i < TimerBar.count; i++) {
- if (strcmp(name, TimerBar.Timers[i].name) == 0)
- n = i;
- }
- assert(n != 1500);
- TimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
-}
-
-float Diag_GetFPS()
-{
- return 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]);
-}
-
-void tbDisplay()
-{
- char temp[200];
- wchar wtemp[200];
-
-#ifdef FRAMETIME
- float FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
-#endif
-
- msCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer();
- CFont::SetBackgroundOff();
- CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
- CFont::SetScale(0.48f, 1.12f);
- CFont::SetCentreOff();
- CFont::SetJustifyOff();
- CFont::SetWrapx(640.0f);
- CFont::SetRightJustifyOff();
- CFont::SetPropOn();
- CFont::SetFontStyle(FONT_BANK);
- sprintf(temp, "FPS: %.2f", Diag_GetFPS());
- AsciiToUnicode(temp, wtemp);
- CFont::SetColor(CRGBA(255, 255, 255, 255));
- if (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) {
- CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp);
-
-#ifndef FINAL
- // Timers output (my own implementation)
- for (uint32 i = 0; i < TimerBar.count; i++) {
- MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime);
- sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]);
- AsciiToUnicode(temp, wtemp);
- CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp);
- }
-
-#ifdef FRAMETIME
- MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime);
- sprintf(temp, "Frame Time: %.2f", MaxFrameTime);
- AsciiToUnicode(temp, wtemp);
-
- CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp);
-#endif // FRAMETIME
-#endif // !FINAL
- }
-}
+#ifndef MASTER
+#include "common.h"
+#include "Font.h"
+#include "Frontend.h"
+#include "Timer.h"
+#include "Text.h"
+
+#define MAX_TIMERS (50)
+#define MAX_MS_COLLECTED (40)
+
+// enables frame time output
+#define FRAMETIME
+
+struct sTimeBar
+{
+ char name[20];
+ float startTime;
+ float endTime;
+ int32 unk;
+};
+
+struct
+{
+ sTimeBar Timers[MAX_TIMERS];
+ uint32 count;
+} TimerBar;
+float MaxTimes[MAX_TIMERS];
+float MaxFrameTime;
+
+uint32 curMS;
+uint32 msCollected[MAX_MS_COLLECTED];
+#ifdef FRAMETIME
+float FrameInitTime;
+#endif
+
+void tbInit()
+{
+ TimerBar.count = 0;
+ uint32 i = CTimer::GetFrameCounter() & 0x7F;
+ if (i == 0) {
+ do
+ MaxTimes[i++] = 0.0f;
+ while (i != MAX_TIMERS);
+#ifdef FRAMETIME
+ MaxFrameTime = 0.0f;
+#endif
+ }
+#ifdef FRAMETIME
+ FrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
+#endif
+}
+
+void tbStartTimer(int32 unk, char *name)
+{
+ strcpy(TimerBar.Timers[TimerBar.count].name, name);
+ TimerBar.Timers[TimerBar.count].unk = unk;
+ TimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
+ TimerBar.count++;
+}
+
+void tbEndTimer(char* name)
+{
+ uint32 n = 1500;
+ for (uint32 i = 0; i < TimerBar.count; i++) {
+ if (strcmp(name, TimerBar.Timers[i].name) == 0)
+ n = i;
+ }
+ assert(n != 1500);
+ TimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
+}
+
+float Diag_GetFPS()
+{
+ return 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]);
+}
+
+void tbDisplay()
+{
+ char temp[200];
+ wchar wtemp[200];
+
+#ifdef FRAMETIME
+ float FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
+#endif
+
+ msCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer();
+ CFont::SetBackgroundOff();
+ CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
+ CFont::SetScale(0.48f, 1.12f);
+ CFont::SetCentreOff();
+ CFont::SetJustifyOff();
+ CFont::SetWrapx(640.0f);
+ CFont::SetRightJustifyOff();
+ CFont::SetPropOn();
+ CFont::SetFontStyle(FONT_BANK);
+ sprintf(temp, "FPS: %.2f", Diag_GetFPS());
+ AsciiToUnicode(temp, wtemp);
+ CFont::SetColor(CRGBA(255, 255, 255, 255));
+ if (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) {
+ CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp);
+
+#ifndef FINAL
+ // Timers output (my own implementation)
+ for (uint32 i = 0; i < TimerBar.count; i++) {
+ MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime);
+ sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]);
+ AsciiToUnicode(temp, wtemp);
+ CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp);
+ }
+
+#ifdef FRAMETIME
+ MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime);
+ sprintf(temp, "Frame Time: %.2f", MaxFrameTime);
+ AsciiToUnicode(temp, wtemp);
+
+ CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp);
+#endif // FRAMETIME
+#endif // !FINAL
+ }
+}
#endif // !MASTER \ No newline at end of file
diff --git a/src/core/timebars.h b/src/core/timebars.h
index 8ffccd8e..6d3b853e 100644
--- a/src/core/timebars.h
+++ b/src/core/timebars.h
@@ -1,6 +1,6 @@
-#pragma once
-
-void tbInit();
-void tbStartTimer(int32, char*);
-void tbEndTimer(char*);
+#pragma once
+
+void tbInit();
+void tbStartTimer(int32, char*);
+void tbEndTimer(char*);
void tbDisplay(); \ No newline at end of file
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index 7a050818..07d70394 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -275,9 +275,9 @@ CEntity::CreateRwObject(void)
if(IsBuilding())
gBuildings++;
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)
- m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame(m_rwObject)), false);
+ m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
mi->AddRef();
}
}
@@ -290,7 +290,7 @@ CEntity::DeleteRwObject(void)
m_matrix.Detach();
if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC){
- f = RpAtomicGetFrame(m_rwObject);
+ f = RpAtomicGetFrame((RpAtomic*)m_rwObject);
RpAtomicDestroy((RpAtomic*)m_rwObject);
RwFrameDestroy(f);
}else if(RwObjectGetType(m_rwObject) == rpCLUMP)
@@ -307,9 +307,9 @@ CEntity::UpdateRwFrame(void)
{
if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC)
- RwFrameUpdateObjects(RpAtomicGetFrame(m_rwObject));
+ RwFrameUpdateObjects(RpAtomicGetFrame((RpAtomic*)m_rwObject));
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;
if(m_rwObject){
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)
- m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame(m_rwObject)), false);
+ m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
CModelInfo::GetModelInfo(m_modelIndex)->AddRef();
}
}
diff --git a/src/entities/Solid.h b/src/entities/Solid.h
index e67c8e29..4ca800c2 100644
--- a/src/entities/Solid.h
+++ b/src/entities/Solid.h
@@ -1,12 +1,12 @@
-#pragma once
-
-#include "Entity.h"
-
-class CSolid : public CEntity
-{
-public:
- CSolid(void) {
- m_type = ENTITY_TYPE_BUILDING;
- bUsesCollision = true;
- }
+#pragma once
+
+#include "Entity.h"
+
+class CSolid : public CEntity
+{
+public:
+ CSolid(void) {
+ m_type = ENTITY_TYPE_BUILDING;
+ bUsesCollision = true;
+ }
}; \ No newline at end of file
diff --git a/src/modelinfo/MloModelInfo.h b/src/modelinfo/MloModelInfo.h
index 19ae63d5..d4344706 100644
--- a/src/modelinfo/MloModelInfo.h
+++ b/src/modelinfo/MloModelInfo.h
@@ -1,14 +1,14 @@
-#pragma once
-
-#include "ClumpModelInfo.h"
-
-class CMloModelInfo : public CClumpModelInfo
-{
-public:
- float field_34; // draw distance?
- int firstInstance;
- int lastInstance;
-public:
- CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {}
- void ConstructClump();
+#pragma once
+
+#include "ClumpModelInfo.h"
+
+class CMloModelInfo : public CClumpModelInfo
+{
+public:
+ float field_34; // draw distance?
+ int firstInstance;
+ int lastInstance;
+public:
+ CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {}
+ void ConstructClump();
}; \ No newline at end of file
diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp
index 7b087fbd..015c6949 100644
--- a/src/modelinfo/PedModelInfo.cpp
+++ b/src/modelinfo/PedModelInfo.cpp
@@ -216,7 +216,7 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame)
RwMatrixCopy(mat, RwFrameGetMatrix(f));
for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) {
- RwMatrixTransform(mat, &f->modelling, rwCOMBINEPOSTCONCAT);
+ RwMatrixTransform(mat, RwFrameGetMatrix(f), rwCOMBINEPOSTCONCAT);
if (RwFrameGetParent(f) == frame)
break;
}
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp
index 42ad635b..432a9ea2 100644
--- a/src/modelinfo/VehicleModelInfo.cpp
+++ b/src/modelinfo/VehicleModelInfo.cpp
@@ -707,7 +707,7 @@ RpMaterial*
CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial *material, void *data)
{
static RwRGBA white = { 255, 255, 255, 255 };
- RwRGBA *col;
+ const RwRGBA *col;
editableMatCBData *cbdata;
cbdata = (editableMatCBData*)data;
@@ -758,8 +758,8 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
col = ms_vehicleColourTable[c1];
coltex = ms_colourTextureTable[c1];
for(matp = m_materials1; *matp; matp++){
- if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){
- colp = RpMaterialGetColor(*matp);
+ if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
+ colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
colp->red = col.red;
colp->green = col.green;
colp->blue = col.blue;
@@ -773,8 +773,8 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
col = ms_vehicleColourTable[c2];
coltex = ms_colourTextureTable[c2];
for(matp = m_materials2; *matp; matp++){
- if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){
- colp = RpMaterialGetColor(*matp);
+ if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
+ colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
colp->red = col.red;
colp->green = col.green;
colp->blue = col.blue;
@@ -861,7 +861,7 @@ CreateCarColourTexture(uint8 r, uint8 g, uint8 b)
RwImageDestroy(img);
RwFree(pixels);
tex = RwTextureCreate(ras);
- tex->name[0] = '@';
+ RwTextureGetName(tex)[0] = '@';
return tex;
}
@@ -1058,7 +1058,7 @@ CVehicleModelInfo::LoadEnvironmentMaps(void)
}
if(gpWhiteTexture == nil){
gpWhiteTexture = RwTextureRead("white", nil);
- gpWhiteTexture->name[0] = '@';
+ RwTextureGetName(gpWhiteTexture)[0] = '@';
RwTextureSetFilterMode(gpWhiteTexture, rwFILTERLINEAR);
}
CTxdStore::PopCurrentTxd();
diff --git a/src/modelinfo/XtraCompsModelInfo.h b/src/modelinfo/XtraCompsModelInfo.h
index bb37ffe3..9832399c 100644
--- a/src/modelinfo/XtraCompsModelInfo.h
+++ b/src/modelinfo/XtraCompsModelInfo.h
@@ -1,12 +1,12 @@
-#pragma once
-
-#include "ClumpModelInfo.h"
-
-class CXtraCompsModelInfo : public CClumpModelInfo
-{
- int field_34;
-public:
- CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; }
- void SetClump(RpClump*) {};
- void Shutdown(void) {};
+#pragma once
+
+#include "ClumpModelInfo.h"
+
+class CXtraCompsModelInfo : public CClumpModelInfo
+{
+ int field_34;
+public:
+ CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; }
+ void SetClump(RpClump*) {};
+ void Shutdown(void) {};
}; \ No newline at end of file
diff --git a/src/objects/CutsceneHead.cpp b/src/objects/CutsceneHead.cpp
index 8c417973..a7722b8a 100644
--- a/src/objects/CutsceneHead.cpp
+++ b/src/objects/CutsceneHead.cpp
@@ -20,7 +20,7 @@ CCutsceneHead::CCutsceneHead(CObject *obj)
m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame;
atm = (RpAtomic*)GetFirstObject(m_pHeadNode);
if(atm){
- assert(RwObjectGetType(atm) == rpATOMIC);
+ assert(RwObjectGetType((RwObject*)atm) == rpATOMIC);
RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER);
}
}
diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp
index 881510e8..9f7bcda5 100644
--- a/src/objects/ParticleObject.cpp
+++ b/src/objects/ParticleObject.cpp
@@ -154,7 +154,7 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe
pobj->m_nRemoveTimer = 0;
if ( color.alpha != 0 )
- RwRGBAAssign(&pobj->m_Color, &color);
+ pobj->m_Color, color;
else
pobj->m_Color.alpha = 0;
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 54816b1c..2cd942f9 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -676,7 +676,7 @@ RemoveAllModelCB(RwObject *object, void *data)
{
RpAtomic *atomic = (RpAtomic*)object;
if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {
- RpClumpRemoveAtomic(atomic->clump, atomic);
+ RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);
RpAtomicDestroy(atomic);
}
return object;
@@ -902,7 +902,7 @@ static RwObject*
SetPedAtomicVisibilityCB(RwObject* object, void* data)
{
if (data == nil)
- RpAtomicSetFlags(object, 0);
+ RpAtomicSetFlags((RpAtomic*)object, 0);
return object;
}
diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp
index cc4b0dd0..8e450ee6 100644
--- a/src/peds/PedIK.cpp
+++ b/src/peds/PedIK.cpp
@@ -340,7 +340,7 @@ CPedIK::RestoreLookAt(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);
*yaw = Acos(f);
@@ -352,7 +352,7 @@ CPedIK::ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch)
}
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);
*yaw = Acos(f);
diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h
index df9017f3..7b82d1ac 100644
--- a/src/peds/PedIK.h
+++ b/src/peds/PedIK.h
@@ -54,8 +54,8 @@ public:
void GetComponentPosition(RwV3d *pos, uint32 node);
static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination);
void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);
- void ExtractYawAndPitchLocal(RwMatrixTag *mat, float *yaw, float *pitch);
- void ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch);
+ void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch);
+ void ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch);
LimbMoveStatus MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo);
bool RestoreGunPosn(void);
bool LookInDirection(float phi, float theta);
diff --git a/src/peds/PedType.h b/src/peds/PedType.h
index 1f3ecb59..3d927df5 100644
--- a/src/peds/PedType.h
+++ b/src/peds/PedType.h
@@ -85,6 +85,7 @@ public:
static uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; }
static uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; }
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 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; }
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 6dbf7687..ccc0a43a 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -1,1535 +1,1535 @@
-#include "common.h"
-#include "patcher.h"
-#include "PlayerPed.h"
-#include "Wanted.h"
-#include "Fire.h"
-#include "DMAudio.h"
-#include "Pad.h"
-#include "Camera.h"
-#include "WeaponEffects.h"
-#include "ModelIndices.h"
-#include "World.h"
-#include "RpAnimBlend.h"
-#include "AnimBlendAssociation.h"
-#include "General.h"
-#include "Pools.h"
-#include "Darkel.h"
-#include "CarCtrl.h"
-
-#define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f
-
-CPlayerPed::~CPlayerPed()
-{
- delete m_pWanted;
-}
-
-CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
-{
- m_fMoveSpeed = 0.0f;
- SetModelIndex(MI_PLAYER);
- SetInitialState();
-
- m_pWanted = new CWanted();
- m_pWanted->Initialise();
- m_pArrestingCop = nil;
- m_currentWeapon = WEAPONTYPE_UNARMED;
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
- m_nSpeedTimer = 0;
- m_bSpeedTimerFlag = false;
- m_pPointGunAt = nil;
- m_nPedState = PED_IDLE;
- m_fMaxStamina = 150.0f;
- m_fCurrentStamina = m_fMaxStamina;
- m_fStaminaProgress = 0.0f;
- m_nEvadeAmount = 0;
- field_1367 = 0;
- m_nShotDelay = 0;
- field_1376 = 0.0f;
- m_bHaveTargetSelected = false;
- m_bHasLockOnTarget = false;
- m_bCanBeDamaged = true;
- m_fWalkAngle = 0.0f;
- m_fFPSMoveHeading = 0.0f;
- m_nTargettableObjects[0] = m_nTargettableObjects[1] = m_nTargettableObjects[2] = m_nTargettableObjects[3] = -1;
- field_1413 = 0;
- for (int i = 0; i < 6; i++) {
- m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f);
- m_pPedAtSafePos[i] = nil;
- }
-}
-
-void CPlayerPed::ClearWeaponTarget()
-{
- if (m_nPedType == PEDTYPE_PLAYER1) {
- m_pPointGunAt = nil;
- TheCamera.ClearPlayerWeaponMode();
- CWeaponEffects::ClearCrossHair();
- }
- ClearPointGunAt();
-}
-
-void
-CPlayerPed::SetWantedLevel(int32 level)
-{
- m_pWanted->SetWantedLevel(level);
-}
-
-void
-CPlayerPed::SetWantedLevelNoDrop(int32 level)
-{
- m_pWanted->SetWantedLevelNoDrop(level);
-}
-
-void
-CPlayerPed::MakeObjectTargettable(int32 handle)
-{
- for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
- if (
-#ifdef FIX_BUGS
- m_nTargettableObjects[i] == -1 ||
-#endif
- CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {
- m_nTargettableObjects[i] = handle;
- return;
- }
- }
-}
-
-// I don't know the actual purpose of parameter
-void
-CPlayerPed::AnnoyPlayerPed(bool annoyedByPassingEntity)
-{
- if (m_pedStats->m_temper < 52) {
- m_pedStats->m_temper++;
- } else {
- if (annoyedByPassingEntity) {
- if (m_pedStats->m_temper < 55) {
- m_pedStats->m_temper++;
- } else {
- m_pedStats->m_temper = 46;
- }
- }
- }
-}
-
-void
-CPlayerPed::ClearAdrenaline(void)
-{
- if (m_bAdrenalineActive && m_nAdrenalineTime != 0) {
- m_nAdrenalineTime = 0;
- CTimer::SetTimeScale(1.0f);
- }
-}
-
-CPlayerInfo *
-CPlayerPed::GetPlayerInfoForThisPlayerPed()
-{
- if (CWorld::Players[0].m_pPed == this)
- return &CWorld::Players[0];
-
- return nil;
-}
-
-void
-CPlayerPed::SetupPlayerPed(int32 index)
-{
- CPlayerPed *player = new CPlayerPed();
- CWorld::Players[index].m_pPed = player;
-
- player->SetOrientation(0.0f, 0.0f, 0.0f);
-
- CWorld::Add(player);
- player->m_wepAccuracy = 100;
-}
-
-void
-CPlayerPed::DeactivatePlayerPed(int32 index)
-{
- CWorld::Remove(CWorld::Players[index].m_pPed);
-}
-
-void
-CPlayerPed::ReactivatePlayerPed(int32 index)
-{
- CWorld::Add(CWorld::Players[index].m_pPed);
-}
-
-void
-CPlayerPed::UseSprintEnergy(void)
-{
- if (m_fCurrentStamina > -150.0f && !CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint
- && !m_bAdrenalineActive) {
- m_fCurrentStamina = m_fCurrentStamina - CTimer::GetTimeStep();
- m_fStaminaProgress = m_fStaminaProgress + CTimer::GetTimeStep();
- }
-
- if (m_fStaminaProgress >= 500.0f) {
- m_fStaminaProgress = 0;
- if (m_fMaxStamina < 1000.0f)
- m_fMaxStamina += 10.0f;
- }
-}
-
-void
-CPlayerPed::MakeChangesForNewWeapon(int8 weapon)
-{
- if (m_nPedState == PED_SNIPER_MODE) {
- RestorePreviousState();
- TheCamera.ClearPlayerWeaponMode();
- }
- SetCurrentWeapon(weapon);
-
- GetWeapon()->m_nAmmoInClip = min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition);
-
- if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAim))
- ClearWeaponTarget();
-
- CAnimBlendAssociation *weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE)->m_AnimToPlay);
- if (weaponAnim) {
- weaponAnim->SetRun();
- weaponAnim->flags |= ASSOC_FADEOUTWHENDONE;
- }
- TheCamera.ClearPlayerWeaponMode();
-}
-
-void
-CPlayerPed::ReApplyMoveAnims(void)
-{
- static AnimationId moveAnims[] = { ANIM_WALK, ANIM_RUN, ANIM_SPRINT, ANIM_IDLE_STANCE, ANIM_WALK_START };
-
- for(int i = 0; i < ARRAY_SIZE(moveAnims); i++) {
- CAnimBlendAssociation *curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), moveAnims[i]);
- if (curMoveAssoc) {
- if (strcmp(CAnimManager::GetAnimAssociation(m_animGroup, moveAnims[i])->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) {
- CAnimBlendAssociation *newMoveAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, moveAnims[i]);
- newMoveAssoc->blendDelta = curMoveAssoc->blendDelta;
- newMoveAssoc->blendAmount = curMoveAssoc->blendAmount;
- curMoveAssoc->blendDelta = -1000.0f;
- curMoveAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- }
-}
-
-void
-CPlayerPed::SetInitialState(void)
-{
- m_bAdrenalineActive = false;
- m_nAdrenalineTime = 0;
- CTimer::SetTimeStep(1.0f);
- m_pSeekTarget = nil;
- m_vecSeekPos = { 0.0f, 0.0f, 0.0f };
- m_fleeFromPosX = 0.0f;
- m_fleeFromPosY = 0.0f;
- m_fleeFrom = nil;
- m_fleeTimer = 0;
- m_objective = OBJECTIVE_NONE;
- m_prevObjective = OBJECTIVE_NONE;
- bUsesCollision = true;
- ClearAimFlag();
- ClearLookFlag();
- bIsPointingGunAt = false;
- bRenderPedInCar = true;
- if (m_pFire)
- m_pFire->Extinguish();
- RpAnimBlendClumpRemoveAllAssociations(GetClump());
- m_nPedState = PED_IDLE;
- SetMoveState(PEDMOVE_STILL);
- m_nLastPedState = PED_NONE;
- m_animGroup = ASSOCGRP_PLAYER;
- m_fMoveSpeed = 0.0f;
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
- m_nEvadeAmount = 0;
- m_pEvadingFrom = nil;
- bIsPedDieAnimPlaying = false;
- SetRealMoveAnim();
- m_bCanBeDamaged = true;
- m_pedStats->m_temper = 50;
- m_fWalkAngle = 0.0f;
-}
-
-void
-CPlayerPed::SetRealMoveAnim(void)
-{
- CAnimBlendAssociation *curWalkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK);
- CAnimBlendAssociation *curRunAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN);
- CAnimBlendAssociation *curSprintAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
- CAnimBlendAssociation *curWalkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
- CAnimBlendAssociation *curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- CAnimBlendAssociation *curRunStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
- CAnimBlendAssociation *curRunStopRAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
- if (bResetWalkAnims) {
- if (curWalkAssoc)
- curWalkAssoc->SetCurrentTime(0.0f);
- if (curRunAssoc)
- curRunAssoc->SetCurrentTime(0.0f);
- if (curSprintAssoc)
- curSprintAssoc->SetCurrentTime(0.0f);
- bResetWalkAnims = false;
- }
-
- if (!curIdleAssoc)
- curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- if (!curIdleAssoc)
- curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
-
- if ((!curRunStopAssoc || !(curRunStopAssoc->IsRunning())) && (!curRunStopRAssoc || !(curRunStopRAssoc->IsRunning()))) {
-
- if (curRunStopAssoc && curRunStopAssoc->blendDelta >= 0.0f || curRunStopRAssoc && curRunStopRAssoc->blendDelta >= 0.0f) {
- if (curRunStopAssoc) {
- curRunStopAssoc->flags |= ASSOC_DELETEFADEDOUT;
- curRunStopAssoc->blendAmount = 1.0f;
- curRunStopAssoc->blendDelta = -8.0f;
- } else if (curRunStopRAssoc) {
- curRunStopRAssoc->flags |= ASSOC_DELETEFADEDOUT;
- curRunStopRAssoc->blendAmount = 1.0f;
- curRunStopRAssoc->blendDelta = -8.0f;
- }
-
- RestoreHeadingRate();
- if (!curIdleAssoc) {
- if (m_fCurrentStamina < 0.0f && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.0f,
- nil, true, false, false, false, false, false)) {
- curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 8.0f);
-
- } else {
- curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
- }
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2500, 4000);
- }
- curIdleAssoc->blendAmount = 0.0f;
- curIdleAssoc->blendDelta = 8.0f;
-
- } else if (m_fMoveSpeed == 0.0f && !curSprintAssoc) {
- if (!curIdleAssoc) {
- if (m_fCurrentStamina < 0.0f && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.0f,
- nil, true, false, false, false, false, false)) {
- curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
-
- } else {
- curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- }
-
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2500, 4000);
- }
-
- if (m_fCurrentStamina > 0.0f && curIdleAssoc->animId == ANIM_IDLE_TIRED) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
-
- } else if (m_nPedState != PED_FIGHT) {
- if (m_fCurrentStamina < 0.0f && curIdleAssoc->animId != ANIM_IDLE_TIRED
- && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.0f, nil, true, false, false, false, false, false)) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
-
- } else if (curIdleAssoc->animId != ANIM_IDLE_STANCE) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- }
- }
-
- m_nMoveState = PEDMOVE_STILL;
- } else {
- if (curIdleAssoc) {
- if (curWalkStartAssoc) {
- curWalkStartAssoc->blendAmount = 1.0f;
- curWalkStartAssoc->blendDelta = 0.0f;
- } else {
- curWalkStartAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_WALK_START);
- }
- if (curWalkAssoc)
- curWalkAssoc->SetCurrentTime(0.0f);
- if (curRunAssoc)
- curRunAssoc->SetCurrentTime(0.0f);
-
- delete curIdleAssoc;
- delete RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- delete RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
- delete curSprintAssoc;
-
- curSprintAssoc = nil;
- m_nMoveState = PEDMOVE_WALK;
- }
- if (curRunStopAssoc) {
- delete curRunStopAssoc;
- RestoreHeadingRate();
- }
- if (curRunStopRAssoc) {
- delete curRunStopRAssoc;
- RestoreHeadingRate();
- }
- if (!curWalkAssoc) {
- curWalkAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_WALK);
- curWalkAssoc->blendAmount = 0.0f;
- }
- if (!curRunAssoc) {
- curRunAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_RUN);
- curRunAssoc->blendAmount = 0.0f;
- }
- if (curWalkStartAssoc && !(curWalkStartAssoc->IsRunning())) {
- delete curWalkStartAssoc;
- curWalkStartAssoc = nil;
- curWalkAssoc->SetRun();
- curRunAssoc->SetRun();
- }
- if (m_nMoveState == PEDMOVE_SPRINT) {
- if (m_fCurrentStamina < 0.0f && (m_fCurrentStamina <= -150.0f || !curSprintAssoc || curSprintAssoc->blendDelta < 0.0f))
- m_nMoveState = PEDMOVE_STILL;
-
- if (curWalkStartAssoc)
- m_nMoveState = PEDMOVE_STILL;
- }
-
- if (curSprintAssoc && (m_nMoveState != PEDMOVE_SPRINT || m_fMoveSpeed < 0.4f)) {
- if (curSprintAssoc->blendAmount == 0.0f) {
- curSprintAssoc->blendDelta = -1000.0f;
- curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;
-
- } else if (curSprintAssoc->blendDelta >= 0.0f || curSprintAssoc->blendAmount >= 0.8f) {
- if (m_fMoveSpeed < 0.4f) {
- AnimationId runStopAnim;
- if (curSprintAssoc->currentTime / curSprintAssoc->hierarchy->totalLength < 0.5) // double
- runStopAnim = ANIM_RUN_STOP;
- else
- runStopAnim = ANIM_RUN_STOP_R;
- CAnimBlendAssociation* newRunStopAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, runStopAnim);
- newRunStopAssoc->blendAmount = 1.0f;
- newRunStopAssoc->SetDeleteCallback(RestoreHeadingRateCB, this);
- m_headingRate = 0.0f;
- curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;
- curSprintAssoc->blendDelta = -1000.0f;
- curWalkAssoc->flags &= ~ASSOC_RUNNING;
- curWalkAssoc->blendAmount = 0.0f;
- curWalkAssoc->blendDelta = 0.0f;
- curRunAssoc->flags &= ~ASSOC_RUNNING;
- curRunAssoc->blendAmount = 0.0f;
- curRunAssoc->blendDelta = 0.0f;
- } else if (curSprintAssoc->blendDelta >= 0.0f) {
-
- // Stop sprinting when tired
- curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;
- curSprintAssoc->blendDelta = -1.0f;
- curRunAssoc->blendDelta = 1.0f;
- }
- } else if (m_fMoveSpeed < 1.0f) {
- curSprintAssoc->blendDelta = -8.0f;
- curRunAssoc->blendDelta = 8.0f;
- }
- } else if (curWalkStartAssoc) {
- curWalkAssoc->flags &= ~ASSOC_RUNNING;
- curRunAssoc->flags &= ~ASSOC_RUNNING;
- curWalkAssoc->blendAmount = 0.0f;
- curRunAssoc->blendAmount = 0.0f;
-
- } else if (m_nMoveState == PEDMOVE_SPRINT) {
- if (curSprintAssoc) {
- if (curSprintAssoc->blendDelta < 0.0f) {
- curSprintAssoc->blendDelta = 2.0f;
- curRunAssoc->blendDelta = -2.0f;
- }
- } else {
- curWalkAssoc->blendAmount = 0.0f;
- curRunAssoc->blendAmount = 1.0f;
- curSprintAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_SPRINT, 2.0f);
- }
- UseSprintEnergy();
- } else {
- if (m_fMoveSpeed < 1.0f) {
- curWalkAssoc->blendAmount = 1.0f;
- curRunAssoc->blendAmount = 0.0f;
- m_nMoveState = PEDMOVE_WALK;
- } else if (m_fMoveSpeed < 2.0f) {
- curWalkAssoc->blendAmount = 2.0f - m_fMoveSpeed;
- curRunAssoc->blendAmount = m_fMoveSpeed - 1.0f;
- m_nMoveState = PEDMOVE_RUN;
- } else {
- curWalkAssoc->blendAmount = 0.0f;
- curRunAssoc->blendAmount = 1.0f;
- m_nMoveState = PEDMOVE_RUN;
- }
- }
- }
- }
- if (m_bAdrenalineActive) {
- if (CTimer::GetTimeInMilliseconds() > m_nAdrenalineTime) {
- m_bAdrenalineActive = false;
- CTimer::SetTimeScale(1.0f);
- if (curWalkStartAssoc)
- curWalkStartAssoc->speed = 1.0f;
- if (curWalkAssoc)
- curWalkAssoc->speed = 1.0f;
- if (curRunAssoc)
- curRunAssoc->speed = 1.0f;
- if (curSprintAssoc)
- curSprintAssoc->speed = 1.0f;
- } else {
- CTimer::SetTimeScale(1.0f / 3);
- if (curWalkStartAssoc)
- curWalkStartAssoc->speed = 2.0f;
- if (curWalkAssoc)
- curWalkAssoc->speed = 2.0f;
- if (curRunAssoc)
- curRunAssoc->speed = 2.0f;
- if (curSprintAssoc)
- curSprintAssoc->speed = 2.0f;
- }
- }
-}
-
-void
-CPlayerPed::RestoreSprintEnergy(float restoreSpeed)
-{
- if (m_fCurrentStamina < m_fMaxStamina)
- m_fCurrentStamina += restoreSpeed * CTimer::GetTimeStep() * 0.5f;
-}
-
-bool
-CPlayerPed::DoWeaponSmoothSpray(void)
-{
- if (m_nPedState == PED_ATTACK && !m_pPointGunAt) {
- eWeaponType weapon = GetWeapon()->m_eWeaponType;
- if (weapon == WEAPONTYPE_FLAMETHROWER || weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI || weapon == WEAPONTYPE_SHOTGUN ||
- weapon == WEAPONTYPE_AK47 || weapon == WEAPONTYPE_M16 || weapon == WEAPONTYPE_HELICANNON)
- return true;
- }
- return false;
-}
-
-void
-CPlayerPed::DoStuffToGoOnFire(void)
-{
- if (m_nPedState == PED_SNIPER_MODE)
- TheCamera.ClearPlayerWeaponMode();
-}
-
-bool
-CPlayerPed::DoesTargetHaveToBeBroken(CVector target, CWeapon *weaponUsed)
-{
- CVector distVec = target - GetPosition();
-
- if (distVec.Magnitude() > CWeaponInfo::GetWeaponInfo(weaponUsed->m_eWeaponType)->m_fRange)
- return true;
-
- if (weaponUsed->m_eWeaponType != WEAPONTYPE_SHOTGUN && weaponUsed->m_eWeaponType != WEAPONTYPE_AK47)
- return false;
-
- distVec.Normalise();
-
- if (DotProduct(distVec,GetForward()) < 0.4f)
- return true;
-
- return false;
-}
-
-// Cancels landing anim while running & jumping? I think
-void
-CPlayerPed::RunningLand(CPad *padUsed)
-{
- CAnimBlendAssociation *landAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_LAND);
- if (landAssoc && landAssoc->currentTime == 0.0f && m_fMoveSpeed > 1.5f
- && padUsed && (padUsed->GetPedWalkLeftRight() != 0.0f || padUsed->GetPedWalkUpDown() != 0.0f)) {
-
- landAssoc->blendDelta = -1000.0f;
- landAssoc->flags |= ASSOC_DELETEFADEDOUT;
-
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAND)->SetFinishCallback(FinishJumpCB, this);
-
- if (m_nPedState == PED_JUMP)
- RestorePreviousState();
- }
-}
-
-bool
-CPlayerPed::IsThisPedAttackingPlayer(CPed *suspect)
-{
- if (suspect->m_pPointGunAt == this)
- return true;
-
- switch (suspect->m_objective) {
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- if (suspect->m_pedInObjective == this)
- return true;
-
- break;
- default:
- break;
- }
- return false;
-}
-
-void
-CPlayerPed::PlayerControlSniper(CPad *padUsed)
-{
- ProcessWeaponSwitch(padUsed);
- TheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f;
-
- if (!padUsed->GetTarget()) {
- RestorePreviousState();
- TheCamera.ClearPlayerWeaponMode();
- }
-
- if (padUsed->WeaponJustDown()) {
- CVector firePos(0.0f, 0.0f, 0.6f);
- firePos = GetMatrix() * firePos;
- GetWeapon()->Fire(this, &firePos);
- }
- GetWeapon()->Update(m_audioEntityId);
-}
-
-// I think R* also used goto in here.
-void
-CPlayerPed::ProcessWeaponSwitch(CPad *padUsed)
-{
- if (CDarkel::FrenzyOnGoing())
- goto switchDetectDone;
-
- if (padUsed->CycleWeaponRightJustDown() && !m_pPointGunAt) {
-
- if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {
-
- for (m_nSelectedWepSlot = m_currentWeapon + 1; m_nSelectedWepSlot < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; ++m_nSelectedWepSlot) {
- if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
- goto switchDetectDone;
- }
- }
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
- }
- } else if (padUsed->CycleWeaponLeftJustDown() && !m_pPointGunAt) {
- if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) {
-
- for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) {
- if (m_nSelectedWepSlot < WEAPONTYPE_UNARMED)
- m_nSelectedWepSlot = WEAPONTYPE_DETONATOR;
-
- if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
- goto switchDetectDone;
- }
- }
- }
- } else if (CWeaponInfo::GetWeaponInfo((eWeaponType)m_currentWeapon)->m_eWeaponFire != WEAPON_FIRE_MELEE) {
- if (GetWeapon(m_currentWeapon).m_nAmmoTotal <= 0) {
- if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) {
-
- for (m_nSelectedWepSlot = m_currentWeapon - 1; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) {
- if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && HasWeapon(WEAPONTYPE_BASEBALLBAT)
- || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE) {
- goto switchDetectDone;
- }
- }
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
- }
- }
- }
-
-switchDetectDone:
- if (m_nSelectedWepSlot != m_currentWeapon) {
- if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT)
- MakeChangesForNewWeapon(m_nSelectedWepSlot);
- }
-}
-
-void
-CPlayerPed::PlayerControlM16(CPad *padUsed)
-{
- ProcessWeaponSwitch(padUsed);
- TheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f;
-
- if (!padUsed->GetTarget()) {
- RestorePreviousState();
- TheCamera.ClearPlayerWeaponMode();
- }
-
- if (padUsed->GetWeapon()) {
- CVector firePos(0.0f, 0.0f, 0.6f);
- firePos = GetMatrix() * firePos;
- GetWeapon()->Fire(this, &firePos);
- }
- GetWeapon()->Update(m_audioEntityId);
-}
-
-void
-CPlayerPed::PlayerControlFighter(CPad *padUsed)
-{
- float leftRight = padUsed->GetPedWalkLeftRight();
- float upDown = padUsed->GetPedWalkUpDown();
- float padMove = CVector2D(leftRight, upDown).Magnitude();
-
- if (padMove > 0.0f) {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation;
- m_takeAStepAfterAttack = padMove > 2 * PAD_MOVE_TO_GAME_WORLD_MOVE;
- if (padUsed->GetSprint() && padMove > 1 * PAD_MOVE_TO_GAME_WORLD_MOVE)
- bIsAttacking = false;
- }
-
- if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy && padUsed->JumpJustDown()) {
- if (m_nEvadeAmount != 0 && m_pEvadingFrom) {
- SetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);
- m_nEvadeAmount = 0;
- m_pEvadingFrom = nil;
- } else {
- SetJump();
- }
- }
-}
-
-void
-CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed)
-{
- float leftRight = padUsed->GetPedWalkLeftRight();
- float upDown = padUsed->GetPedWalkUpDown();
- float padMove = CVector2D(leftRight, upDown).Magnitude();
- float padMoveInGameUnit = padMove / PAD_MOVE_TO_GAME_WORLD_MOVE;
- if (padMoveInGameUnit > 0.0f) {
-#ifdef FREE_CAM
- if (!CCamera::bFreeCam)
- m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation);
- else
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation;
-#else
- m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation);
-#endif
- m_fMoveSpeed = min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed);
- } else {
- m_fMoveSpeed = 0.0f;
- }
-
- if (m_nPedState == PED_JUMP) {
- if (bIsInTheAir) {
- if (bUsesCollision && !bHitSteepSlope &&
- (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f)
- && m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) {
-
- float angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O
- float angleCos = Cos(m_fRotationCur);
- ApplyMoveForce(-angleSin * 3.0f, 3.0f * angleCos, 0.05f);
- }
- } else if (bIsLanding) {
- m_fMoveSpeed = 0.0f;
- }
- }
- if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
- && padUsed->GetSprint()) {
- m_nMoveState = PEDMOVE_SPRINT;
- }
- if (m_nPedState != PED_FIGHT)
- SetRealMoveAnim();
-
- if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
- && padUsed->JumpJustDown() && m_nPedState != PED_JUMP) {
- ClearAttack();
- ClearWeaponTarget();
- if (m_nEvadeAmount != 0 && m_pEvadingFrom) {
- SetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);
- m_nEvadeAmount = 0;
- m_pEvadingFrom = nil;
- } else {
- SetJump();
- }
- }
-}
-
-void
-CPlayerPed::KeepAreaAroundPlayerClear(void)
-{
- BuildPedLists();
- for (int i = 0; i < m_numNearPeds; ++i) {
- CPed *nearPed = m_nearPeds[i];
- if (nearPed->CharCreatedBy == RANDOM_CHAR && !nearPed->DyingOrDead()) {
- if (nearPed->GetIsOnScreen()) {
- if (nearPed->m_objective == OBJECTIVE_NONE) {
- nearPed->SetFindPathAndFlee(this, 5000, true);
- } else {
- if (nearPed->EnteringCar())
- nearPed->QuitEnteringCar();
-
- nearPed->ClearObjective();
- }
- } else {
- nearPed->FlagToDestroyWhenNextProcessed();
- }
- }
- }
- CVector playerPos = (InVehicle() ? m_pMyVehicle->GetPosition() : GetPosition());
-
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity *vehicles[8];
- CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
-
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle *veh = (CVehicle*)vehicles[i];
- if (veh->VehicleCreatedBy != MISSION_VEHICLE) {
- if (veh->m_status != STATUS_PLAYER && veh->m_status != STATUS_PLAYER_DISABLED) {
- if ((veh->GetPosition() - playerPos).MagnitudeSqr() > 25.0f) {
- veh->AutoPilot.m_nTempAction = TEMPACT_WAIT;
- veh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 5000;
- } else {
- if (DotProduct2D(playerPos - veh->GetPosition(), veh->GetForward()) > 0.0f)
- veh->AutoPilot.m_nTempAction = TEMPACT_REVERSE;
- else
- veh->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
-
- veh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
- }
- CCarCtrl::PossiblyRemoveVehicle(veh);
- }
- }
- }
-}
-
-void
-CPlayerPed::EvaluateNeighbouringTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool lookToLeft)
-{
- CVector distVec = candidate->GetPosition() - GetPosition();
- if (distVec.Magnitude2D() <= distLimit) {
- if (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) {
-#ifdef VC_PED_PORTS
- float angleBetweenUs = CGeneral::GetATanOfXY(candidate->GetPosition().x - TheCamera.GetPosition().x,
- candidate->GetPosition().y - TheCamera.GetPosition().y);
-#else
- float angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y);
-#endif
- angleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset);
- float closeness;
- if (lookToLeft) {
- closeness = angleBetweenUs > 0.0f ? -Abs(angleBetweenUs) : -100000.0f;
- } else {
- closeness = angleBetweenUs > 0.0f ? -100000.0f : -Abs(angleBetweenUs);
- }
-
- if (closeness > *lastCloseness) {
- *targetPtr = candidate;
- *lastCloseness = closeness;
- }
- }
- }
-}
-
-void
-CPlayerPed::EvaluateTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool priority)
-{
- CVector distVec = candidate->GetPosition() - GetPosition();
- float dist = distVec.Magnitude2D();
- if (dist <= distLimit) {
- if (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) {
- float angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y);
- angleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset);
-
- float closeness = -dist - 5.0f * Abs(angleBetweenUs);
- if (priority) {
- closeness += 5.0f;
- }
-
- if (closeness > *lastCloseness) {
- *targetPtr = candidate;
- *lastCloseness = closeness;
- }
- }
- }
-}
-
-bool
-CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft)
-{
- CEntity *nextTarget = nil;
- float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;
- // nextTarget = nil;
- float lastCloseness = -10000.0f;
- // unused
- // CGeneral::GetATanOfXY(GetForward().x, GetForward().y);
- CVector distVec = previousTarget->GetPosition() - GetPosition();
- float referenceBeta = CGeneral::GetATanOfXY(distVec.x, distVec.y);
-
- for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) {
- CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h);
- if (pedToCheck) {
- if (pedToCheck != FindPlayerPed() && pedToCheck != previousTarget) {
- if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle
- && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) {
-
- EvaluateNeighbouringTarget(pedToCheck, &nextTarget, &lastCloseness,
- weaponRange, referenceBeta, lookToLeft);
- }
- }
- }
- }
- for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
- CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]);
- if (obj)
- EvaluateNeighbouringTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, lookToLeft);
- }
- if (!nextTarget)
- return false;
-
- m_pPointGunAt = nextTarget;
- if (nextTarget)
- nextTarget->RegisterReference((CEntity**)&m_pPointGunAt);
- SetPointGunAt(nextTarget);
- return true;
-}
-
-bool
-CPlayerPed::FindWeaponLockOnTarget(void)
-{
- CEntity *nextTarget = nil;
- float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;
-
- if (m_pPointGunAt) {
- CVector distVec = m_pPointGunAt->GetPosition() - GetPosition();
- if (distVec.Magnitude2D() > weaponRange) {
- m_pPointGunAt = nil;
- return false;
- } else {
- return true;
- }
- }
-
- // nextTarget = nil;
- float lastCloseness = -10000.0f;
- float referenceBeta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y);
- for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) {
- CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h);
- if (pedToCheck) {
- if (pedToCheck != FindPlayerPed()) {
- if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle
- && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) {
-
- EvaluateTarget(pedToCheck, &nextTarget, &lastCloseness,
- weaponRange, referenceBeta, IsThisPedAttackingPlayer(pedToCheck));
- }
- }
- }
- }
- for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
- CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]);
- if (obj)
- EvaluateTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, false);
- }
- if (!nextTarget)
- return false;
-
- m_pPointGunAt = nextTarget;
- if (nextTarget)
- nextTarget->RegisterReference((CEntity**)&m_pPointGunAt);
- SetPointGunAt(nextTarget);
- return true;
-}
-
-void
-CPlayerPed::ProcessAnimGroups(void)
-{
- AssocGroupId groupToSet;
- if ((m_fWalkAngle <= -DEGTORAD(50.0f) || m_fWalkAngle >= DEGTORAD(50.0f))
- && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()
- && CanStrafeOrMouseControl()) {
-
- if (m_fWalkAngle >= -DEGTORAD(130.0f) && m_fWalkAngle <= DEGTORAD(130.0f)) {
- if (m_fWalkAngle > 0.0f) {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
- groupToSet = ASSOCGRP_ROCKETLEFT;
- else
- groupToSet = ASSOCGRP_PLAYERLEFT;
- } else {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
- groupToSet = ASSOCGRP_ROCKETRIGHT;
- else
- groupToSet = ASSOCGRP_PLAYERRIGHT;
- }
- } else {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
- groupToSet = ASSOCGRP_ROCKETBACK;
- else
- groupToSet = ASSOCGRP_PLAYERBACK;
- }
- } else {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {
- groupToSet = ASSOCGRP_PLAYERROCKET;
- } else {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT) {
- groupToSet = ASSOCGRP_PLAYERBBBAT;
- } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI) {
- if (!GetWeapon()->IsType2Handed()) {
- groupToSet = ASSOCGRP_PLAYER;
- } else {
- groupToSet = ASSOCGRP_PLAYER2ARMED;
- }
- } else {
- groupToSet = ASSOCGRP_PLAYER1ARMED;
- }
- }
- }
-
- if (m_animGroup != groupToSet) {
- m_animGroup = groupToSet;
- ReApplyMoveAnims();
- }
-}
-
-void
-CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
-{
- CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- if (m_bHasLockOnTarget && !m_pPointGunAt) {
- TheCamera.ClearPlayerWeaponMode();
- CWeaponEffects::ClearCrossHair();
- ClearPointGunAt();
- }
- if (!m_pFire) {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ||
- GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) {
- if (padUsed->TargetJustDown()) {
- SetStoredState();
- m_nPedState = PED_SNIPER_MODE;
-#ifdef FREE_CAM
- if (CCamera::bFreeCam && TheCamera.Cams[0].Using3rdPersonMouseCam()) {
- m_fRotationCur = CGeneral::LimitRadianAngle(-TheCamera.Orientation);
- SetHeading(m_fRotationCur);
- }
-#endif
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
- TheCamera.SetNewPlayerWeaponMode(CCam::MODE_ROCKETLAUNCHER, 0, 0);
- else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE)
- TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SNIPER, 0, 0);
- else
- TheCamera.SetNewPlayerWeaponMode(CCam::MODE_M16_1STPERSON, 0, 0);
-
- m_fMoveSpeed = 0.0f;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 1000.0f);
- }
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE
- || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON)
- return;
- }
- }
-
- if (padUsed->GetWeapon() && m_nMoveState != PEDMOVE_SPRINT) {
- if (m_nSelectedWepSlot == m_currentWeapon) {
- if (m_pPointGunAt) {
-#ifdef FREE_CAM
- if (CCamera::bFreeCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE && m_fMoveSpeed < 1.0f)
- StartFightAttack(padUsed->GetWeapon());
- else
-#endif
- SetAttack(m_pPointGunAt);
- } else if (m_currentWeapon != WEAPONTYPE_UNARMED) {
- if (m_nPedState == PED_ATTACK) {
- if (padUsed->WeaponJustDown()) {
- m_bHaveTargetSelected = true;
- } else if (!m_bHaveTargetSelected) {
- field_1376 += CTimer::GetTimeStepNonClipped();
- }
- } else {
- field_1376 = 0.0f;
- m_bHaveTargetSelected = false;
- }
- SetAttack(nil);
- } else if (padUsed->WeaponJustDown()) {
- if (m_fMoveSpeed < 1.0f)
- StartFightAttack(padUsed->GetWeapon());
- else
- SetAttack(nil);
- }
- }
- } else {
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
- if (m_nPedState == PED_ATTACK) {
- m_bHaveTargetSelected = true;
- bIsAttacking = false;
- }
- }
-
-#ifdef FREE_CAM
- // Rotate player/arm when shooting. We don't have auto-rotation anymore
- if (CCamera::m_bUseMouse3rdPerson && CCamera::bFreeCam &&
- m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {
-
- // Weapons except throwable and melee ones
- if (weaponInfo->m_bCanAim || weaponInfo->m_b1stPerson || weaponInfo->m_bExpands) {
- if ((padUsed->GetTarget() && weaponInfo->m_bCanAimWithArm) || padUsed->GetWeapon()) {
- float limitedCam = CGeneral::LimitRadianAngle(-TheCamera.Orientation);
-
- // On this one we can rotate arm.
- if (weaponInfo->m_bCanAimWithArm) {
- if (!padUsed->GetWeapon()) { // making this State != ATTACK still stops it after attack. Re-start it immediately!
- SetPointGunAt(nil);
- bIsPointingGunAt = false; // to not stop after attack
- }
-
- SetLookFlag(limitedCam, true);
- SetAimFlag(limitedCam);
-#ifdef VC_PED_PORTS
- SetLookTimer(INT_MAX); // removing this makes head move for real, but I experinced some bugs.
-#endif
- } else {
- m_fRotationDest = limitedCam;
- m_headingRate = 50.0f;
-
- // Anim. fix for shotgun, ak47 and m16 (we must finish rot. it quickly)
- if (weaponInfo->m_bCanAim && padUsed->WeaponJustDown()) {
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- float limitedRotDest = m_fRotationDest;
-
- if (m_fRotationCur - PI > m_fRotationDest) {
- limitedRotDest += 2 * PI;
- } else if (PI + m_fRotationCur < m_fRotationDest) {
- limitedRotDest -= 2 * PI;
- }
-
- m_fRotationCur += (limitedRotDest - m_fRotationCur) / 2;
- }
- }
- } else if (weaponInfo->m_bCanAimWithArm)
- ClearPointGunAt();
- else
- RestoreHeadingRate();
- }
- }
-#endif
-
- if (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {
- if (m_pPointGunAt) {
- // what??
- if (!m_pPointGunAt
-#ifdef FREE_CAM
- || (!CCamera::bFreeCam && CCamera::m_bUseMouse3rdPerson)
-#else
- || CCamera::m_bUseMouse3rdPerson
-#endif
- || m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->bInVehicle) {
- ClearWeaponTarget();
- return;
- }
- if (CPlayerPed::DoesTargetHaveToBeBroken(m_pPointGunAt->GetPosition(), GetWeapon())) {
- ClearWeaponTarget();
- return;
- }
- if (m_pPointGunAt) {
- if (padUsed->ShiftTargetLeftJustDown())
- FindNextWeaponLockOnTarget(m_pPointGunAt, true);
- if (padUsed->ShiftTargetRightJustDown())
- FindNextWeaponLockOnTarget(m_pPointGunAt, false);
- }
- TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SYPHON, 0, 0);
- TheCamera.UpdateAimingCoors(m_pPointGunAt->GetPosition());
- }
-#ifdef FREE_CAM
- else if ((CCamera::bFreeCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE) || (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson)) {
-#else
- else if (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson) {
-#endif
- if (padUsed->TargetJustDown())
- FindWeaponLockOnTarget();
- }
- } else if (m_pPointGunAt) {
- ClearWeaponTarget();
- }
-
- if (m_pPointGunAt) {
-#ifndef VC_PED_PORTS
- CVector markPos = m_pPointGunAt->GetPosition();
-#else
- CVector markPos;
- if (m_pPointGunAt->IsPed()) {
- ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d*)markPos, PED_MID);
- } else {
- markPos = m_pPointGunAt->GetPosition();
- }
-#endif
- if (bCanPointGunAtTarget) {
- CWeaponEffects::MarkTarget(markPos, 64, 0, 0, 255, 0.8f);
- } else {
- CWeaponEffects::MarkTarget(markPos, 64, 32, 0, 255, 0.8f);
- }
- }
- m_bHasLockOnTarget = m_pPointGunAt != nil;
-}
-
-void
-CPlayerPed::PlayerControlZelda(CPad *padUsed)
-{
- bool doSmoothSpray = DoWeaponSmoothSpray();
- float camOrientation = TheCamera.Orientation;
- float leftRight = padUsed->GetPedWalkLeftRight();
- float upDown = padUsed->GetPedWalkUpDown();
- float padMoveInGameUnit;
- bool smoothSprayWithoutMove = false;
-
- if (doSmoothSpray && upDown > 0.0f) {
- padMoveInGameUnit = 0.0f;
- smoothSprayWithoutMove = true;
- } else {
- padMoveInGameUnit = CVector2D(leftRight, upDown).Magnitude() / PAD_MOVE_TO_GAME_WORLD_MOVE;
- }
-
- if (padMoveInGameUnit > 0.0f || smoothSprayWithoutMove) {
- float padHeading = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
- float neededTurn = CGeneral::LimitRadianAngle(padHeading - camOrientation);
- if (doSmoothSpray) {
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || GetWeapon()->m_eWeaponType == WEAPONTYPE_COLT45
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI)
- m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 80.0f) * CTimer::GetTimeStep();
- else
- m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 128.0f) * CTimer::GetTimeStep();
- } else {
- m_fRotationDest = neededTurn;
- }
-
- float maxAcc = 0.07f * CTimer::GetTimeStep();
- m_fMoveSpeed = min(padMoveInGameUnit, m_fMoveSpeed + maxAcc);
-
- } else {
- m_fMoveSpeed = 0.0f;
- }
-
- if (m_nPedState == PED_JUMP) {
- if (bIsInTheAir) {
- if (bUsesCollision && !bHitSteepSlope &&
- (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f)
- && m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) {
-
- float angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O
- float angleCos = Cos(m_fRotationCur);
- ApplyMoveForce(-angleSin * 3.0f, 3.0f * angleCos, 0.05f);
- }
- } else if (bIsLanding) {
- m_fMoveSpeed = 0.0f;
- }
- }
-
- if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
- && padUsed->GetSprint()) {
- m_nMoveState = PEDMOVE_SPRINT;
- }
- if (m_nPedState != PED_FIGHT)
- SetRealMoveAnim();
-
- if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
- && padUsed->JumpJustDown() && m_nPedState != PED_JUMP) {
- ClearAttack();
- ClearWeaponTarget();
- if (m_nEvadeAmount != 0 && m_pEvadingFrom) {
- SetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);
- m_nEvadeAmount = 0;
- m_pEvadingFrom = nil;
- } else {
- SetJump();
- }
- }
-}
-
-void
-CPlayerPed::ProcessControl(void)
-{
- if (m_nEvadeAmount != 0)
- --m_nEvadeAmount;
-
- if (m_nEvadeAmount == 0)
- m_pEvadingFrom = nil;
-
- if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
- bTryingToReachDryLand = true;
- } else if (!(((uint8)CTimer::GetFrameCounter() + m_randomSeed) & 0xF)) {
- CVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(GetPosition(), 7.0f, nil,
- false, true, false, false, false, false);
- if (nearVeh && nearVeh->IsBoat())
- bTryingToReachDryLand = true;
- else
- bTryingToReachDryLand = false;
- }
- CPed::ProcessControl();
- if (bWasPostponed)
- return;
-
- CPad *padUsed = CPad::GetPad(0);
- m_pWanted->Update();
- CEntity::PruneReferences();
-
- if (m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT)
- RestoreSprintEnergy(1.0f);
- else if (m_nMoveState == PEDMOVE_RUN)
- RestoreSprintEnergy(0.3f);
-
- if (m_nPedState == PED_DEAD) {
- ClearWeaponTarget();
- return;
- }
- if (m_nPedState == PED_DIE) {
- ClearWeaponTarget();
- if (CTimer::GetTimeInMilliseconds() > m_bloodyFootprintCountOrDeathTime + 4000)
- SetDead();
- return;
- }
- if (m_nPedState == PED_DRIVING && m_objective != OBJECTIVE_LEAVE_VEHICLE) {
- if (m_pMyVehicle->IsCar() && ((CAutomobile*)m_pMyVehicle)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) {
- CAnimBlendAssociation *rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR);
- if (!rollDoorAssoc) {
- rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR_LOW);
- }
-
- // These comparisons are wrong, they return uint16
- if (m_pMyVehicle->m_nGettingOutFlags & CAR_DOOR_FLAG_LF || rollDoorAssoc || padUsed
- && (padUsed->GetAccelerate() != 0.0f || padUsed->GetSteeringLeftRight() != 0.0f
- || padUsed->GetBrake() != 0.0f)) {
-
- if (rollDoorAssoc)
- m_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, rollDoorAssoc->currentTime);
- } else {
- m_pMyVehicle->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF;
- if (m_pMyVehicle->bLowVehicle)
- rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR_LOW);
- else
- rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR);
-
- rollDoorAssoc->SetFinishCallback(PedAnimDoorCloseRollingCB, this);
- }
- }
- return;
- }
- if (m_objective == OBJECTIVE_NONE)
- m_nMoveState = PEDMOVE_STILL;
- if (bIsLanding)
- RunningLand(padUsed);
- if (padUsed && padUsed->WeaponJustDown() && m_nPedState != PED_SNIPER_MODE) {
-
- // ...Really?
- eWeaponType playerWeapon = FindPlayerPed()->GetWeapon()->m_eWeaponType;
- if (playerWeapon == WEAPONTYPE_SNIPERRIFLE) {
- DMAudio.PlayFrontEndSound(SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM, 0);
- } else if (playerWeapon == WEAPONTYPE_ROCKETLAUNCHER) {
- DMAudio.PlayFrontEndSound(SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM, 0);
- }
- }
-
- switch (m_nPedState) {
- case PED_NONE:
- case PED_IDLE:
- case PED_FLEE_POS:
- case PED_FLEE_ENTITY:
- case PED_ATTACK:
- case PED_FIGHT:
- case PED_AIM_GUN:
- if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG400)) {
- if (TheCamera.Cams[0].Using3rdPersonMouseCam()) {
- if (padUsed)
- PlayerControl1stPersonRunAround(padUsed);
- } else if (m_nPedState == PED_FIGHT) {
- if (padUsed)
- PlayerControlFighter(padUsed);
- } else if (padUsed) {
- PlayerControlZelda(padUsed);
- }
- }
- if (IsPedInControl() && padUsed)
- ProcessPlayerWeapon(padUsed);
- break;
- case PED_LOOK_ENTITY:
- case PED_LOOK_HEADING:
- case PED_WANDER_RANGE:
- case PED_WANDER_PATH:
- case PED_PURSUE:
- case PED_FOLLOW_PATH:
- case PED_ROCKET_ODE:
- case PED_DUMMY:
- case PED_PAUSE:
- case PED_FACE_PHONE:
- case PED_MAKE_CALL:
- case PED_CHAT:
- case PED_MUG:
- case PED_AI_CONTROL:
- case PED_FOLLOW_ROUTE:
- case PED_CPR:
- case PED_SOLICIT:
- case PED_BUY_ICECREAM:
- case PED_INVESTIGATE:
- case PED_STEP_AWAY:
- case PED_ON_FIRE:
- case PED_UNKNOWN:
- case PED_STATES_NO_AI:
- case PED_STAGGER:
- case PED_DIVE_AWAY:
- case PED_STATES_NO_ST:
- case PED_ARREST_PLAYER:
- case PED_DRIVING:
- case PED_PASSENGER:
- case PED_TAXI_PASSENGER:
- case PED_OPEN_DOOR:
- case PED_DIE:
- case PED_DEAD:
- case PED_HANDS_UP:
- break;
- case PED_SEEK_ENTITY:
- m_vecSeekPos = m_pSeekTarget->GetPosition();
-
- // fall through
- case PED_SEEK_POS:
- switch (m_nMoveState) {
- case PEDMOVE_WALK:
- m_fMoveSpeed = 1.0f;
- break;
- case PEDMOVE_RUN:
- m_fMoveSpeed = 1.8f;
- break;
- case PEDMOVE_SPRINT:
- m_fMoveSpeed = 2.5f;
- break;
- default:
- m_fMoveSpeed = 0.0f;
- break;
- }
- SetRealMoveAnim();
- if (Seek()) {
- RestorePreviousState();
- SetMoveState(PEDMOVE_STILL);
- }
- break;
- case PED_SNIPER_MODE:
- if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) {
- if (padUsed)
- PlayerControlM16(padUsed);
- } else if (padUsed) {
- PlayerControlSniper(padUsed);
- }
- break;
- case PED_SEEK_CAR:
- case PED_SEEK_IN_BOAT:
- if (bVehEnterDoorIsBlocked || bKindaStayInSamePlace) {
- m_fMoveSpeed = 0.0f;
- } else {
- m_fMoveSpeed = min(2.0f, 2.0f * (m_vecSeekPos - GetPosition()).Magnitude2D());
- }
- if (padUsed && !padUsed->ArePlayerControlsDisabled()) {
- if (padUsed->GetTarget() || padUsed->GetLeftStickXJustDown() || padUsed->GetLeftStickYJustDown() ||
- padUsed->GetDPadUpJustDown() || padUsed->GetDPadDownJustDown() || padUsed->GetDPadLeftJustDown() ||
- padUsed->GetDPadRightJustDown()) {
-
- RestorePreviousState();
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- RestorePreviousObjective();
- }
- }
- }
- if (padUsed && padUsed->GetSprint())
- m_nMoveState = PEDMOVE_SPRINT;
- SetRealMoveAnim();
- break;
- case PED_JUMP:
- if (padUsed)
- PlayerControlZelda(padUsed);
- if (bIsLanding)
- break;
-
- // This has been added later it seems
- return;
- case PED_FALL:
- case PED_GETUP:
- case PED_ENTER_TRAIN:
- case PED_EXIT_TRAIN:
- case PED_CARJACK:
- case PED_DRAG_FROM_CAR:
- case PED_ENTER_CAR:
- case PED_STEAL_CAR:
- case PED_EXIT_CAR:
- ClearWeaponTarget();
- break;
- case PED_ARRESTED:
- if (m_nLastPedState == PED_DRAG_FROM_CAR && m_pVehicleAnim)
- BeingDraggedFromCar();
- break;
- }
- if (padUsed && IsPedShootable()) {
- ProcessWeaponSwitch(padUsed);
- GetWeapon()->Update(m_audioEntityId);
- }
- ProcessAnimGroups();
- if (padUsed) {
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED
- && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_BEHIND) {
-
- m_lookTimer = 0;
- float camAngle = CGeneral::LimitRadianAngle(TheCamera.Cams[TheCamera.ActiveCam].Front.Heading());
- float angleBetweenPlayerAndCam = Abs(camAngle - m_fRotationCur);
- if (m_nPedState != PED_ATTACK
- && angleBetweenPlayerAndCam > DEGTORAD(30.0f) && angleBetweenPlayerAndCam < DEGTORAD(330.0f)) {
-
- if (angleBetweenPlayerAndCam > DEGTORAD(150.0f) && angleBetweenPlayerAndCam < DEGTORAD(210.0f)) {
- float rightTurnAngle = CGeneral::LimitRadianAngle(m_fRotationCur - DEGTORAD(150.0f));
- float leftTurnAngle = CGeneral::LimitRadianAngle(DEGTORAD(150.0f) + m_fRotationCur);
- if (m_fLookDirection != 999999.0f) {
- if (Abs(rightTurnAngle - m_fLookDirection) < Abs(leftTurnAngle - m_fLookDirection))
- camAngle = rightTurnAngle;
- else
- camAngle = leftTurnAngle;
- } else {
- camAngle = rightTurnAngle;
- }
- }
- SetLookFlag(camAngle, true);
- SetLookTimer(CTimer::GetTimeStepInMilliseconds() * 5.0f);
- } else {
- ClearLookFlag();
- }
- }
- }
- if (m_nMoveState == PEDMOVE_SPRINT && bIsLooking) {
- ClearLookFlag();
- SetLookTimer(250);
- }
-
- if (m_vecMoveSpeed.Magnitude2D() < 0.1f) {
- if (m_nSpeedTimer) {
- if (CTimer::GetTimeInMilliseconds() > m_nSpeedTimer)
- m_bSpeedTimerFlag = true;
- } else {
- m_nSpeedTimer = CTimer::GetTimeInMilliseconds() + 500;
- }
- } else {
- m_nSpeedTimer = 0;
- m_bSpeedTimerFlag = false;
- }
-}
-
-#include <new>
-
-class CPlayerPed_ : public CPlayerPed
-{
-public:
- CPlayerPed* ctor(void) { return ::new (this) CPlayerPed(); }
- void dtor(void) { CPlayerPed::~CPlayerPed(); }
- void SetMoveAnim_(void) { CPlayerPed::SetMoveAnim(); }
- void ProcessControl_(void) { CPlayerPed::ProcessControl(); }
-};
-
-STARTPATCHES
- InjectHook(0x4EF7E0, &CPlayerPed_::ctor, PATCH_JUMP);
- InjectHook(0x4EFB30, &CPlayerPed_::dtor, PATCH_JUMP);
- InjectHook(0x4F3760, &CPlayerPed_::SetMoveAnim_, PATCH_JUMP);
- InjectHook(0x4EFD90, &CPlayerPed_::ProcessControl_, PATCH_JUMP);
- InjectHook(0x4F28A0, &CPlayerPed::ClearWeaponTarget, PATCH_JUMP);
- InjectHook(0x4F3700, &CPlayerPed::AnnoyPlayerPed, PATCH_JUMP);
- InjectHook(0x4F36C0, &CPlayerPed::GetPlayerInfoForThisPlayerPed, PATCH_JUMP);
- InjectHook(0x4F2560, &CPlayerPed::MakeChangesForNewWeapon, PATCH_JUMP);
- InjectHook(0x4F07C0, &CPlayerPed::ReApplyMoveAnims, PATCH_JUMP);
- InjectHook(0x4F0880, &CPlayerPed::SetRealMoveAnim, PATCH_JUMP);
- InjectHook(0x4F1810, &CPlayerPed::PlayerControlFighter, PATCH_JUMP);
- InjectHook(0x4F1340, &CPlayerPed::RestoreSprintEnergy, PATCH_JUMP);
- InjectHook(0x4F1380, &CPlayerPed::DoWeaponSmoothSpray, PATCH_JUMP);
- InjectHook(0x4F36E0, &CPlayerPed::DoStuffToGoOnFire, PATCH_JUMP);
- InjectHook(0x4F3350, &CPlayerPed::DoesTargetHaveToBeBroken, PATCH_JUMP);
- InjectHook(0x4F31D0, &CPlayerPed::RunningLand, PATCH_JUMP);
- InjectHook(0x4F2D00, &CPlayerPed::IsThisPedAttackingPlayer, PATCH_JUMP);
- InjectHook(0x4F1CF0, &CPlayerPed::PlayerControlSniper, PATCH_JUMP);
- InjectHook(0x4F2310, &CPlayerPed::ProcessWeaponSwitch, PATCH_JUMP);
- InjectHook(0x4F1DF0, &CPlayerPed::PlayerControlM16, PATCH_JUMP);
- InjectHook(0x4F3460, &CPlayerPed::KeepAreaAroundPlayerClear, PATCH_JUMP);
- InjectHook(0x4F1970, &CPlayerPed::PlayerControl1stPersonRunAround, PATCH_JUMP);
- InjectHook(0x4F1EF0, &CPlayerPed::ProcessPlayerWeapon, PATCH_JUMP);
- InjectHook(0x4F2640, &CPlayerPed::ProcessAnimGroups, PATCH_JUMP);
-ENDPATCHES
+#include "common.h"
+#include "patcher.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "Fire.h"
+#include "DMAudio.h"
+#include "Pad.h"
+#include "Camera.h"
+#include "WeaponEffects.h"
+#include "ModelIndices.h"
+#include "World.h"
+#include "RpAnimBlend.h"
+#include "AnimBlendAssociation.h"
+#include "General.h"
+#include "Pools.h"
+#include "Darkel.h"
+#include "CarCtrl.h"
+
+#define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f
+
+CPlayerPed::~CPlayerPed()
+{
+ delete m_pWanted;
+}
+
+CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
+{
+ m_fMoveSpeed = 0.0f;
+ SetModelIndex(MI_PLAYER);
+ SetInitialState();
+
+ m_pWanted = new CWanted();
+ m_pWanted->Initialise();
+ m_pArrestingCop = nil;
+ m_currentWeapon = WEAPONTYPE_UNARMED;
+ m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
+ m_nSpeedTimer = 0;
+ m_bSpeedTimerFlag = false;
+ m_pPointGunAt = nil;
+ m_nPedState = PED_IDLE;
+ m_fMaxStamina = 150.0f;
+ m_fCurrentStamina = m_fMaxStamina;
+ m_fStaminaProgress = 0.0f;
+ m_nEvadeAmount = 0;
+ field_1367 = 0;
+ m_nShotDelay = 0;
+ field_1376 = 0.0f;
+ m_bHaveTargetSelected = false;
+ m_bHasLockOnTarget = false;
+ m_bCanBeDamaged = true;
+ m_fWalkAngle = 0.0f;
+ m_fFPSMoveHeading = 0.0f;
+ m_nTargettableObjects[0] = m_nTargettableObjects[1] = m_nTargettableObjects[2] = m_nTargettableObjects[3] = -1;
+ field_1413 = 0;
+ for (int i = 0; i < 6; i++) {
+ m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f);
+ m_pPedAtSafePos[i] = nil;
+ }
+}
+
+void CPlayerPed::ClearWeaponTarget()
+{
+ if (m_nPedType == PEDTYPE_PLAYER1) {
+ m_pPointGunAt = nil;
+ TheCamera.ClearPlayerWeaponMode();
+ CWeaponEffects::ClearCrossHair();
+ }
+ ClearPointGunAt();
+}
+
+void
+CPlayerPed::SetWantedLevel(int32 level)
+{
+ m_pWanted->SetWantedLevel(level);
+}
+
+void
+CPlayerPed::SetWantedLevelNoDrop(int32 level)
+{
+ m_pWanted->SetWantedLevelNoDrop(level);
+}
+
+void
+CPlayerPed::MakeObjectTargettable(int32 handle)
+{
+ for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
+ if (
+#ifdef FIX_BUGS
+ m_nTargettableObjects[i] == -1 ||
+#endif
+ CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {
+ m_nTargettableObjects[i] = handle;
+ return;
+ }
+ }
+}
+
+// I don't know the actual purpose of parameter
+void
+CPlayerPed::AnnoyPlayerPed(bool annoyedByPassingEntity)
+{
+ if (m_pedStats->m_temper < 52) {
+ m_pedStats->m_temper++;
+ } else {
+ if (annoyedByPassingEntity) {
+ if (m_pedStats->m_temper < 55) {
+ m_pedStats->m_temper++;
+ } else {
+ m_pedStats->m_temper = 46;
+ }
+ }
+ }
+}
+
+void
+CPlayerPed::ClearAdrenaline(void)
+{
+ if (m_bAdrenalineActive && m_nAdrenalineTime != 0) {
+ m_nAdrenalineTime = 0;
+ CTimer::SetTimeScale(1.0f);
+ }
+}
+
+CPlayerInfo *
+CPlayerPed::GetPlayerInfoForThisPlayerPed()
+{
+ if (CWorld::Players[0].m_pPed == this)
+ return &CWorld::Players[0];
+
+ return nil;
+}
+
+void
+CPlayerPed::SetupPlayerPed(int32 index)
+{
+ CPlayerPed *player = new CPlayerPed();
+ CWorld::Players[index].m_pPed = player;
+
+ player->SetOrientation(0.0f, 0.0f, 0.0f);
+
+ CWorld::Add(player);
+ player->m_wepAccuracy = 100;
+}
+
+void
+CPlayerPed::DeactivatePlayerPed(int32 index)
+{
+ CWorld::Remove(CWorld::Players[index].m_pPed);
+}
+
+void
+CPlayerPed::ReactivatePlayerPed(int32 index)
+{
+ CWorld::Add(CWorld::Players[index].m_pPed);
+}
+
+void
+CPlayerPed::UseSprintEnergy(void)
+{
+ if (m_fCurrentStamina > -150.0f && !CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint
+ && !m_bAdrenalineActive) {
+ m_fCurrentStamina = m_fCurrentStamina - CTimer::GetTimeStep();
+ m_fStaminaProgress = m_fStaminaProgress + CTimer::GetTimeStep();
+ }
+
+ if (m_fStaminaProgress >= 500.0f) {
+ m_fStaminaProgress = 0;
+ if (m_fMaxStamina < 1000.0f)
+ m_fMaxStamina += 10.0f;
+ }
+}
+
+void
+CPlayerPed::MakeChangesForNewWeapon(int8 weapon)
+{
+ if (m_nPedState == PED_SNIPER_MODE) {
+ RestorePreviousState();
+ TheCamera.ClearPlayerWeaponMode();
+ }
+ SetCurrentWeapon(weapon);
+
+ GetWeapon()->m_nAmmoInClip = min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition);
+
+ if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAim))
+ ClearWeaponTarget();
+
+ CAnimBlendAssociation *weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE)->m_AnimToPlay);
+ if (weaponAnim) {
+ weaponAnim->SetRun();
+ weaponAnim->flags |= ASSOC_FADEOUTWHENDONE;
+ }
+ TheCamera.ClearPlayerWeaponMode();
+}
+
+void
+CPlayerPed::ReApplyMoveAnims(void)
+{
+ static AnimationId moveAnims[] = { ANIM_WALK, ANIM_RUN, ANIM_SPRINT, ANIM_IDLE_STANCE, ANIM_WALK_START };
+
+ for(int i = 0; i < ARRAY_SIZE(moveAnims); i++) {
+ CAnimBlendAssociation *curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), moveAnims[i]);
+ if (curMoveAssoc) {
+ if (strcmp(CAnimManager::GetAnimAssociation(m_animGroup, moveAnims[i])->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) {
+ CAnimBlendAssociation *newMoveAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, moveAnims[i]);
+ newMoveAssoc->blendDelta = curMoveAssoc->blendDelta;
+ newMoveAssoc->blendAmount = curMoveAssoc->blendAmount;
+ curMoveAssoc->blendDelta = -1000.0f;
+ curMoveAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ }
+}
+
+void
+CPlayerPed::SetInitialState(void)
+{
+ m_bAdrenalineActive = false;
+ m_nAdrenalineTime = 0;
+ CTimer::SetTimeStep(1.0f);
+ m_pSeekTarget = nil;
+ m_vecSeekPos = { 0.0f, 0.0f, 0.0f };
+ m_fleeFromPosX = 0.0f;
+ m_fleeFromPosY = 0.0f;
+ m_fleeFrom = nil;
+ m_fleeTimer = 0;
+ m_objective = OBJECTIVE_NONE;
+ m_prevObjective = OBJECTIVE_NONE;
+ bUsesCollision = true;
+ ClearAimFlag();
+ ClearLookFlag();
+ bIsPointingGunAt = false;
+ bRenderPedInCar = true;
+ if (m_pFire)
+ m_pFire->Extinguish();
+ RpAnimBlendClumpRemoveAllAssociations(GetClump());
+ m_nPedState = PED_IDLE;
+ SetMoveState(PEDMOVE_STILL);
+ m_nLastPedState = PED_NONE;
+ m_animGroup = ASSOCGRP_PLAYER;
+ m_fMoveSpeed = 0.0f;
+ m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
+ m_nEvadeAmount = 0;
+ m_pEvadingFrom = nil;
+ bIsPedDieAnimPlaying = false;
+ SetRealMoveAnim();
+ m_bCanBeDamaged = true;
+ m_pedStats->m_temper = 50;
+ m_fWalkAngle = 0.0f;
+}
+
+void
+CPlayerPed::SetRealMoveAnim(void)
+{
+ CAnimBlendAssociation *curWalkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK);
+ CAnimBlendAssociation *curRunAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN);
+ CAnimBlendAssociation *curSprintAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
+ CAnimBlendAssociation *curWalkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
+ CAnimBlendAssociation *curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ CAnimBlendAssociation *curRunStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+ CAnimBlendAssociation *curRunStopRAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+ if (bResetWalkAnims) {
+ if (curWalkAssoc)
+ curWalkAssoc->SetCurrentTime(0.0f);
+ if (curRunAssoc)
+ curRunAssoc->SetCurrentTime(0.0f);
+ if (curSprintAssoc)
+ curSprintAssoc->SetCurrentTime(0.0f);
+ bResetWalkAnims = false;
+ }
+
+ if (!curIdleAssoc)
+ curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
+ if (!curIdleAssoc)
+ curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+
+ if ((!curRunStopAssoc || !(curRunStopAssoc->IsRunning())) && (!curRunStopRAssoc || !(curRunStopRAssoc->IsRunning()))) {
+
+ if (curRunStopAssoc && curRunStopAssoc->blendDelta >= 0.0f || curRunStopRAssoc && curRunStopRAssoc->blendDelta >= 0.0f) {
+ if (curRunStopAssoc) {
+ curRunStopAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ curRunStopAssoc->blendAmount = 1.0f;
+ curRunStopAssoc->blendDelta = -8.0f;
+ } else if (curRunStopRAssoc) {
+ curRunStopRAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ curRunStopRAssoc->blendAmount = 1.0f;
+ curRunStopRAssoc->blendDelta = -8.0f;
+ }
+
+ RestoreHeadingRate();
+ if (!curIdleAssoc) {
+ if (m_fCurrentStamina < 0.0f && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.0f,
+ nil, true, false, false, false, false, false)) {
+ curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 8.0f);
+
+ } else {
+ curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ }
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2500, 4000);
+ }
+ curIdleAssoc->blendAmount = 0.0f;
+ curIdleAssoc->blendDelta = 8.0f;
+
+ } else if (m_fMoveSpeed == 0.0f && !curSprintAssoc) {
+ if (!curIdleAssoc) {
+ if (m_fCurrentStamina < 0.0f && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.0f,
+ nil, true, false, false, false, false, false)) {
+ curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
+
+ } else {
+ curIdleAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ }
+
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2500, 4000);
+ }
+
+ if (m_fCurrentStamina > 0.0f && curIdleAssoc->animId == ANIM_IDLE_TIRED) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+
+ } else if (m_nPedState != PED_FIGHT) {
+ if (m_fCurrentStamina < 0.0f && curIdleAssoc->animId != ANIM_IDLE_TIRED
+ && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.0f, nil, true, false, false, false, false, false)) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
+
+ } else if (curIdleAssoc->animId != ANIM_IDLE_STANCE) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ }
+ }
+
+ m_nMoveState = PEDMOVE_STILL;
+ } else {
+ if (curIdleAssoc) {
+ if (curWalkStartAssoc) {
+ curWalkStartAssoc->blendAmount = 1.0f;
+ curWalkStartAssoc->blendDelta = 0.0f;
+ } else {
+ curWalkStartAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_WALK_START);
+ }
+ if (curWalkAssoc)
+ curWalkAssoc->SetCurrentTime(0.0f);
+ if (curRunAssoc)
+ curRunAssoc->SetCurrentTime(0.0f);
+
+ delete curIdleAssoc;
+ delete RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
+ delete RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+ delete curSprintAssoc;
+
+ curSprintAssoc = nil;
+ m_nMoveState = PEDMOVE_WALK;
+ }
+ if (curRunStopAssoc) {
+ delete curRunStopAssoc;
+ RestoreHeadingRate();
+ }
+ if (curRunStopRAssoc) {
+ delete curRunStopRAssoc;
+ RestoreHeadingRate();
+ }
+ if (!curWalkAssoc) {
+ curWalkAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_WALK);
+ curWalkAssoc->blendAmount = 0.0f;
+ }
+ if (!curRunAssoc) {
+ curRunAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_RUN);
+ curRunAssoc->blendAmount = 0.0f;
+ }
+ if (curWalkStartAssoc && !(curWalkStartAssoc->IsRunning())) {
+ delete curWalkStartAssoc;
+ curWalkStartAssoc = nil;
+ curWalkAssoc->SetRun();
+ curRunAssoc->SetRun();
+ }
+ if (m_nMoveState == PEDMOVE_SPRINT) {
+ if (m_fCurrentStamina < 0.0f && (m_fCurrentStamina <= -150.0f || !curSprintAssoc || curSprintAssoc->blendDelta < 0.0f))
+ m_nMoveState = PEDMOVE_STILL;
+
+ if (curWalkStartAssoc)
+ m_nMoveState = PEDMOVE_STILL;
+ }
+
+ if (curSprintAssoc && (m_nMoveState != PEDMOVE_SPRINT || m_fMoveSpeed < 0.4f)) {
+ if (curSprintAssoc->blendAmount == 0.0f) {
+ curSprintAssoc->blendDelta = -1000.0f;
+ curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;
+
+ } else if (curSprintAssoc->blendDelta >= 0.0f || curSprintAssoc->blendAmount >= 0.8f) {
+ if (m_fMoveSpeed < 0.4f) {
+ AnimationId runStopAnim;
+ if (curSprintAssoc->currentTime / curSprintAssoc->hierarchy->totalLength < 0.5) // double
+ runStopAnim = ANIM_RUN_STOP;
+ else
+ runStopAnim = ANIM_RUN_STOP_R;
+ CAnimBlendAssociation* newRunStopAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, runStopAnim);
+ newRunStopAssoc->blendAmount = 1.0f;
+ newRunStopAssoc->SetDeleteCallback(RestoreHeadingRateCB, this);
+ m_headingRate = 0.0f;
+ curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ curSprintAssoc->blendDelta = -1000.0f;
+ curWalkAssoc->flags &= ~ASSOC_RUNNING;
+ curWalkAssoc->blendAmount = 0.0f;
+ curWalkAssoc->blendDelta = 0.0f;
+ curRunAssoc->flags &= ~ASSOC_RUNNING;
+ curRunAssoc->blendAmount = 0.0f;
+ curRunAssoc->blendDelta = 0.0f;
+ } else if (curSprintAssoc->blendDelta >= 0.0f) {
+
+ // Stop sprinting when tired
+ curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ curSprintAssoc->blendDelta = -1.0f;
+ curRunAssoc->blendDelta = 1.0f;
+ }
+ } else if (m_fMoveSpeed < 1.0f) {
+ curSprintAssoc->blendDelta = -8.0f;
+ curRunAssoc->blendDelta = 8.0f;
+ }
+ } else if (curWalkStartAssoc) {
+ curWalkAssoc->flags &= ~ASSOC_RUNNING;
+ curRunAssoc->flags &= ~ASSOC_RUNNING;
+ curWalkAssoc->blendAmount = 0.0f;
+ curRunAssoc->blendAmount = 0.0f;
+
+ } else if (m_nMoveState == PEDMOVE_SPRINT) {
+ if (curSprintAssoc) {
+ if (curSprintAssoc->blendDelta < 0.0f) {
+ curSprintAssoc->blendDelta = 2.0f;
+ curRunAssoc->blendDelta = -2.0f;
+ }
+ } else {
+ curWalkAssoc->blendAmount = 0.0f;
+ curRunAssoc->blendAmount = 1.0f;
+ curSprintAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_SPRINT, 2.0f);
+ }
+ UseSprintEnergy();
+ } else {
+ if (m_fMoveSpeed < 1.0f) {
+ curWalkAssoc->blendAmount = 1.0f;
+ curRunAssoc->blendAmount = 0.0f;
+ m_nMoveState = PEDMOVE_WALK;
+ } else if (m_fMoveSpeed < 2.0f) {
+ curWalkAssoc->blendAmount = 2.0f - m_fMoveSpeed;
+ curRunAssoc->blendAmount = m_fMoveSpeed - 1.0f;
+ m_nMoveState = PEDMOVE_RUN;
+ } else {
+ curWalkAssoc->blendAmount = 0.0f;
+ curRunAssoc->blendAmount = 1.0f;
+ m_nMoveState = PEDMOVE_RUN;
+ }
+ }
+ }
+ }
+ if (m_bAdrenalineActive) {
+ if (CTimer::GetTimeInMilliseconds() > m_nAdrenalineTime) {
+ m_bAdrenalineActive = false;
+ CTimer::SetTimeScale(1.0f);
+ if (curWalkStartAssoc)
+ curWalkStartAssoc->speed = 1.0f;
+ if (curWalkAssoc)
+ curWalkAssoc->speed = 1.0f;
+ if (curRunAssoc)
+ curRunAssoc->speed = 1.0f;
+ if (curSprintAssoc)
+ curSprintAssoc->speed = 1.0f;
+ } else {
+ CTimer::SetTimeScale(1.0f / 3);
+ if (curWalkStartAssoc)
+ curWalkStartAssoc->speed = 2.0f;
+ if (curWalkAssoc)
+ curWalkAssoc->speed = 2.0f;
+ if (curRunAssoc)
+ curRunAssoc->speed = 2.0f;
+ if (curSprintAssoc)
+ curSprintAssoc->speed = 2.0f;
+ }
+ }
+}
+
+void
+CPlayerPed::RestoreSprintEnergy(float restoreSpeed)
+{
+ if (m_fCurrentStamina < m_fMaxStamina)
+ m_fCurrentStamina += restoreSpeed * CTimer::GetTimeStep() * 0.5f;
+}
+
+bool
+CPlayerPed::DoWeaponSmoothSpray(void)
+{
+ if (m_nPedState == PED_ATTACK && !m_pPointGunAt) {
+ eWeaponType weapon = GetWeapon()->m_eWeaponType;
+ if (weapon == WEAPONTYPE_FLAMETHROWER || weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI || weapon == WEAPONTYPE_SHOTGUN ||
+ weapon == WEAPONTYPE_AK47 || weapon == WEAPONTYPE_M16 || weapon == WEAPONTYPE_HELICANNON)
+ return true;
+ }
+ return false;
+}
+
+void
+CPlayerPed::DoStuffToGoOnFire(void)
+{
+ if (m_nPedState == PED_SNIPER_MODE)
+ TheCamera.ClearPlayerWeaponMode();
+}
+
+bool
+CPlayerPed::DoesTargetHaveToBeBroken(CVector target, CWeapon *weaponUsed)
+{
+ CVector distVec = target - GetPosition();
+
+ if (distVec.Magnitude() > CWeaponInfo::GetWeaponInfo(weaponUsed->m_eWeaponType)->m_fRange)
+ return true;
+
+ if (weaponUsed->m_eWeaponType != WEAPONTYPE_SHOTGUN && weaponUsed->m_eWeaponType != WEAPONTYPE_AK47)
+ return false;
+
+ distVec.Normalise();
+
+ if (DotProduct(distVec,GetForward()) < 0.4f)
+ return true;
+
+ return false;
+}
+
+// Cancels landing anim while running & jumping? I think
+void
+CPlayerPed::RunningLand(CPad *padUsed)
+{
+ CAnimBlendAssociation *landAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_LAND);
+ if (landAssoc && landAssoc->currentTime == 0.0f && m_fMoveSpeed > 1.5f
+ && padUsed && (padUsed->GetPedWalkLeftRight() != 0.0f || padUsed->GetPedWalkUpDown() != 0.0f)) {
+
+ landAssoc->blendDelta = -1000.0f;
+ landAssoc->flags |= ASSOC_DELETEFADEDOUT;
+
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAND)->SetFinishCallback(FinishJumpCB, this);
+
+ if (m_nPedState == PED_JUMP)
+ RestorePreviousState();
+ }
+}
+
+bool
+CPlayerPed::IsThisPedAttackingPlayer(CPed *suspect)
+{
+ if (suspect->m_pPointGunAt == this)
+ return true;
+
+ switch (suspect->m_objective) {
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ if (suspect->m_pedInObjective == this)
+ return true;
+
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void
+CPlayerPed::PlayerControlSniper(CPad *padUsed)
+{
+ ProcessWeaponSwitch(padUsed);
+ TheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f;
+
+ if (!padUsed->GetTarget()) {
+ RestorePreviousState();
+ TheCamera.ClearPlayerWeaponMode();
+ }
+
+ if (padUsed->WeaponJustDown()) {
+ CVector firePos(0.0f, 0.0f, 0.6f);
+ firePos = GetMatrix() * firePos;
+ GetWeapon()->Fire(this, &firePos);
+ }
+ GetWeapon()->Update(m_audioEntityId);
+}
+
+// I think R* also used goto in here.
+void
+CPlayerPed::ProcessWeaponSwitch(CPad *padUsed)
+{
+ if (CDarkel::FrenzyOnGoing())
+ goto switchDetectDone;
+
+ if (padUsed->CycleWeaponRightJustDown() && !m_pPointGunAt) {
+
+ if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {
+
+ for (m_nSelectedWepSlot = m_currentWeapon + 1; m_nSelectedWepSlot < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; ++m_nSelectedWepSlot) {
+ if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
+ goto switchDetectDone;
+ }
+ }
+ m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
+ }
+ } else if (padUsed->CycleWeaponLeftJustDown() && !m_pPointGunAt) {
+ if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) {
+
+ for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) {
+ if (m_nSelectedWepSlot < WEAPONTYPE_UNARMED)
+ m_nSelectedWepSlot = WEAPONTYPE_DETONATOR;
+
+ if (HasWeapon(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
+ goto switchDetectDone;
+ }
+ }
+ }
+ } else if (CWeaponInfo::GetWeaponInfo((eWeaponType)m_currentWeapon)->m_eWeaponFire != WEAPON_FIRE_MELEE) {
+ if (GetWeapon(m_currentWeapon).m_nAmmoTotal <= 0) {
+ if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER) {
+
+ for (m_nSelectedWepSlot = m_currentWeapon - 1; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) {
+ if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && HasWeapon(WEAPONTYPE_BASEBALLBAT)
+ || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE) {
+ goto switchDetectDone;
+ }
+ }
+ m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
+ }
+ }
+ }
+
+switchDetectDone:
+ if (m_nSelectedWepSlot != m_currentWeapon) {
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT)
+ MakeChangesForNewWeapon(m_nSelectedWepSlot);
+ }
+}
+
+void
+CPlayerPed::PlayerControlM16(CPad *padUsed)
+{
+ ProcessWeaponSwitch(padUsed);
+ TheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f;
+
+ if (!padUsed->GetTarget()) {
+ RestorePreviousState();
+ TheCamera.ClearPlayerWeaponMode();
+ }
+
+ if (padUsed->GetWeapon()) {
+ CVector firePos(0.0f, 0.0f, 0.6f);
+ firePos = GetMatrix() * firePos;
+ GetWeapon()->Fire(this, &firePos);
+ }
+ GetWeapon()->Update(m_audioEntityId);
+}
+
+void
+CPlayerPed::PlayerControlFighter(CPad *padUsed)
+{
+ float leftRight = padUsed->GetPedWalkLeftRight();
+ float upDown = padUsed->GetPedWalkUpDown();
+ float padMove = CVector2D(leftRight, upDown).Magnitude();
+
+ if (padMove > 0.0f) {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation;
+ m_takeAStepAfterAttack = padMove > 2 * PAD_MOVE_TO_GAME_WORLD_MOVE;
+ if (padUsed->GetSprint() && padMove > 1 * PAD_MOVE_TO_GAME_WORLD_MOVE)
+ bIsAttacking = false;
+ }
+
+ if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy && padUsed->JumpJustDown()) {
+ if (m_nEvadeAmount != 0 && m_pEvadingFrom) {
+ SetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);
+ m_nEvadeAmount = 0;
+ m_pEvadingFrom = nil;
+ } else {
+ SetJump();
+ }
+ }
+}
+
+void
+CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed)
+{
+ float leftRight = padUsed->GetPedWalkLeftRight();
+ float upDown = padUsed->GetPedWalkUpDown();
+ float padMove = CVector2D(leftRight, upDown).Magnitude();
+ float padMoveInGameUnit = padMove / PAD_MOVE_TO_GAME_WORLD_MOVE;
+ if (padMoveInGameUnit > 0.0f) {
+#ifdef FREE_CAM
+ if (!CCamera::bFreeCam)
+ m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation);
+ else
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation;
+#else
+ m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation);
+#endif
+ m_fMoveSpeed = min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed);
+ } else {
+ m_fMoveSpeed = 0.0f;
+ }
+
+ if (m_nPedState == PED_JUMP) {
+ if (bIsInTheAir) {
+ if (bUsesCollision && !bHitSteepSlope &&
+ (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f)
+ && m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) {
+
+ float angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O
+ float angleCos = Cos(m_fRotationCur);
+ ApplyMoveForce(-angleSin * 3.0f, 3.0f * angleCos, 0.05f);
+ }
+ } else if (bIsLanding) {
+ m_fMoveSpeed = 0.0f;
+ }
+ }
+ if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
+ && padUsed->GetSprint()) {
+ m_nMoveState = PEDMOVE_SPRINT;
+ }
+ if (m_nPedState != PED_FIGHT)
+ SetRealMoveAnim();
+
+ if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
+ && padUsed->JumpJustDown() && m_nPedState != PED_JUMP) {
+ ClearAttack();
+ ClearWeaponTarget();
+ if (m_nEvadeAmount != 0 && m_pEvadingFrom) {
+ SetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);
+ m_nEvadeAmount = 0;
+ m_pEvadingFrom = nil;
+ } else {
+ SetJump();
+ }
+ }
+}
+
+void
+CPlayerPed::KeepAreaAroundPlayerClear(void)
+{
+ BuildPedLists();
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->CharCreatedBy == RANDOM_CHAR && !nearPed->DyingOrDead()) {
+ if (nearPed->GetIsOnScreen()) {
+ if (nearPed->m_objective == OBJECTIVE_NONE) {
+ nearPed->SetFindPathAndFlee(this, 5000, true);
+ } else {
+ if (nearPed->EnteringCar())
+ nearPed->QuitEnteringCar();
+
+ nearPed->ClearObjective();
+ }
+ } else {
+ nearPed->FlagToDestroyWhenNextProcessed();
+ }
+ }
+ }
+ CVector playerPos = (InVehicle() ? m_pMyVehicle->GetPosition() : GetPosition());
+
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle *veh = (CVehicle*)vehicles[i];
+ if (veh->VehicleCreatedBy != MISSION_VEHICLE) {
+ if (veh->m_status != STATUS_PLAYER && veh->m_status != STATUS_PLAYER_DISABLED) {
+ if ((veh->GetPosition() - playerPos).MagnitudeSqr() > 25.0f) {
+ veh->AutoPilot.m_nTempAction = TEMPACT_WAIT;
+ veh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 5000;
+ } else {
+ if (DotProduct2D(playerPos - veh->GetPosition(), veh->GetForward()) > 0.0f)
+ veh->AutoPilot.m_nTempAction = TEMPACT_REVERSE;
+ else
+ veh->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+
+ veh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+ CCarCtrl::PossiblyRemoveVehicle(veh);
+ }
+ }
+ }
+}
+
+void
+CPlayerPed::EvaluateNeighbouringTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool lookToLeft)
+{
+ CVector distVec = candidate->GetPosition() - GetPosition();
+ if (distVec.Magnitude2D() <= distLimit) {
+ if (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) {
+#ifdef VC_PED_PORTS
+ float angleBetweenUs = CGeneral::GetATanOfXY(candidate->GetPosition().x - TheCamera.GetPosition().x,
+ candidate->GetPosition().y - TheCamera.GetPosition().y);
+#else
+ float angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y);
+#endif
+ angleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset);
+ float closeness;
+ if (lookToLeft) {
+ closeness = angleBetweenUs > 0.0f ? -Abs(angleBetweenUs) : -100000.0f;
+ } else {
+ closeness = angleBetweenUs > 0.0f ? -100000.0f : -Abs(angleBetweenUs);
+ }
+
+ if (closeness > *lastCloseness) {
+ *targetPtr = candidate;
+ *lastCloseness = closeness;
+ }
+ }
+ }
+}
+
+void
+CPlayerPed::EvaluateTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool priority)
+{
+ CVector distVec = candidate->GetPosition() - GetPosition();
+ float dist = distVec.Magnitude2D();
+ if (dist <= distLimit) {
+ if (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) {
+ float angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y);
+ angleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset);
+
+ float closeness = -dist - 5.0f * Abs(angleBetweenUs);
+ if (priority) {
+ closeness += 5.0f;
+ }
+
+ if (closeness > *lastCloseness) {
+ *targetPtr = candidate;
+ *lastCloseness = closeness;
+ }
+ }
+ }
+}
+
+bool
+CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft)
+{
+ CEntity *nextTarget = nil;
+ float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;
+ // nextTarget = nil;
+ float lastCloseness = -10000.0f;
+ // unused
+ // CGeneral::GetATanOfXY(GetForward().x, GetForward().y);
+ CVector distVec = previousTarget->GetPosition() - GetPosition();
+ float referenceBeta = CGeneral::GetATanOfXY(distVec.x, distVec.y);
+
+ for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) {
+ CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h);
+ if (pedToCheck) {
+ if (pedToCheck != FindPlayerPed() && pedToCheck != previousTarget) {
+ if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle
+ && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) {
+
+ EvaluateNeighbouringTarget(pedToCheck, &nextTarget, &lastCloseness,
+ weaponRange, referenceBeta, lookToLeft);
+ }
+ }
+ }
+ }
+ for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
+ CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]);
+ if (obj)
+ EvaluateNeighbouringTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, lookToLeft);
+ }
+ if (!nextTarget)
+ return false;
+
+ m_pPointGunAt = nextTarget;
+ if (nextTarget)
+ nextTarget->RegisterReference((CEntity**)&m_pPointGunAt);
+ SetPointGunAt(nextTarget);
+ return true;
+}
+
+bool
+CPlayerPed::FindWeaponLockOnTarget(void)
+{
+ CEntity *nextTarget = nil;
+ float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;
+
+ if (m_pPointGunAt) {
+ CVector distVec = m_pPointGunAt->GetPosition() - GetPosition();
+ if (distVec.Magnitude2D() > weaponRange) {
+ m_pPointGunAt = nil;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ // nextTarget = nil;
+ float lastCloseness = -10000.0f;
+ float referenceBeta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y);
+ for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) {
+ CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h);
+ if (pedToCheck) {
+ if (pedToCheck != FindPlayerPed()) {
+ if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle
+ && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) {
+
+ EvaluateTarget(pedToCheck, &nextTarget, &lastCloseness,
+ weaponRange, referenceBeta, IsThisPedAttackingPlayer(pedToCheck));
+ }
+ }
+ }
+ }
+ for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
+ CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]);
+ if (obj)
+ EvaluateTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, false);
+ }
+ if (!nextTarget)
+ return false;
+
+ m_pPointGunAt = nextTarget;
+ if (nextTarget)
+ nextTarget->RegisterReference((CEntity**)&m_pPointGunAt);
+ SetPointGunAt(nextTarget);
+ return true;
+}
+
+void
+CPlayerPed::ProcessAnimGroups(void)
+{
+ AssocGroupId groupToSet;
+ if ((m_fWalkAngle <= -DEGTORAD(50.0f) || m_fWalkAngle >= DEGTORAD(50.0f))
+ && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()
+ && CanStrafeOrMouseControl()) {
+
+ if (m_fWalkAngle >= -DEGTORAD(130.0f) && m_fWalkAngle <= DEGTORAD(130.0f)) {
+ if (m_fWalkAngle > 0.0f) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
+ groupToSet = ASSOCGRP_ROCKETLEFT;
+ else
+ groupToSet = ASSOCGRP_PLAYERLEFT;
+ } else {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
+ groupToSet = ASSOCGRP_ROCKETRIGHT;
+ else
+ groupToSet = ASSOCGRP_PLAYERRIGHT;
+ }
+ } else {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
+ groupToSet = ASSOCGRP_ROCKETBACK;
+ else
+ groupToSet = ASSOCGRP_PLAYERBACK;
+ }
+ } else {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {
+ groupToSet = ASSOCGRP_PLAYERROCKET;
+ } else {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT) {
+ groupToSet = ASSOCGRP_PLAYERBBBAT;
+ } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI) {
+ if (!GetWeapon()->IsType2Handed()) {
+ groupToSet = ASSOCGRP_PLAYER;
+ } else {
+ groupToSet = ASSOCGRP_PLAYER2ARMED;
+ }
+ } else {
+ groupToSet = ASSOCGRP_PLAYER1ARMED;
+ }
+ }
+ }
+
+ if (m_animGroup != groupToSet) {
+ m_animGroup = groupToSet;
+ ReApplyMoveAnims();
+ }
+}
+
+void
+CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
+{
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ if (m_bHasLockOnTarget && !m_pPointGunAt) {
+ TheCamera.ClearPlayerWeaponMode();
+ CWeaponEffects::ClearCrossHair();
+ ClearPointGunAt();
+ }
+ if (!m_pFire) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ||
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) {
+ if (padUsed->TargetJustDown()) {
+ SetStoredState();
+ m_nPedState = PED_SNIPER_MODE;
+#ifdef FREE_CAM
+ if (CCamera::bFreeCam && TheCamera.Cams[0].Using3rdPersonMouseCam()) {
+ m_fRotationCur = CGeneral::LimitRadianAngle(-TheCamera.Orientation);
+ SetHeading(m_fRotationCur);
+ }
+#endif
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
+ TheCamera.SetNewPlayerWeaponMode(CCam::MODE_ROCKETLAUNCHER, 0, 0);
+ else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE)
+ TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SNIPER, 0, 0);
+ else
+ TheCamera.SetNewPlayerWeaponMode(CCam::MODE_M16_1STPERSON, 0, 0);
+
+ m_fMoveSpeed = 0.0f;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 1000.0f);
+ }
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE
+ || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON)
+ return;
+ }
+ }
+
+ if (padUsed->GetWeapon() && m_nMoveState != PEDMOVE_SPRINT) {
+ if (m_nSelectedWepSlot == m_currentWeapon) {
+ if (m_pPointGunAt) {
+#ifdef FREE_CAM
+ if (CCamera::bFreeCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE && m_fMoveSpeed < 1.0f)
+ StartFightAttack(padUsed->GetWeapon());
+ else
+#endif
+ SetAttack(m_pPointGunAt);
+ } else if (m_currentWeapon != WEAPONTYPE_UNARMED) {
+ if (m_nPedState == PED_ATTACK) {
+ if (padUsed->WeaponJustDown()) {
+ m_bHaveTargetSelected = true;
+ } else if (!m_bHaveTargetSelected) {
+ field_1376 += CTimer::GetTimeStepNonClipped();
+ }
+ } else {
+ field_1376 = 0.0f;
+ m_bHaveTargetSelected = false;
+ }
+ SetAttack(nil);
+ } else if (padUsed->WeaponJustDown()) {
+ if (m_fMoveSpeed < 1.0f)
+ StartFightAttack(padUsed->GetWeapon());
+ else
+ SetAttack(nil);
+ }
+ }
+ } else {
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
+ if (m_nPedState == PED_ATTACK) {
+ m_bHaveTargetSelected = true;
+ bIsAttacking = false;
+ }
+ }
+
+#ifdef FREE_CAM
+ // Rotate player/arm when shooting. We don't have auto-rotation anymore
+ if (CCamera::m_bUseMouse3rdPerson && CCamera::bFreeCam &&
+ m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {
+
+ // Weapons except throwable and melee ones
+ if (weaponInfo->m_bCanAim || weaponInfo->m_b1stPerson || weaponInfo->m_bExpands) {
+ if ((padUsed->GetTarget() && weaponInfo->m_bCanAimWithArm) || padUsed->GetWeapon()) {
+ float limitedCam = CGeneral::LimitRadianAngle(-TheCamera.Orientation);
+
+ // On this one we can rotate arm.
+ if (weaponInfo->m_bCanAimWithArm) {
+ if (!padUsed->GetWeapon()) { // making this State != ATTACK still stops it after attack. Re-start it immediately!
+ SetPointGunAt(nil);
+ bIsPointingGunAt = false; // to not stop after attack
+ }
+
+ SetLookFlag(limitedCam, true);
+ SetAimFlag(limitedCam);
+#ifdef VC_PED_PORTS
+ SetLookTimer(INT_MAX); // removing this makes head move for real, but I experinced some bugs.
+#endif
+ } else {
+ m_fRotationDest = limitedCam;
+ m_headingRate = 50.0f;
+
+ // Anim. fix for shotgun, ak47 and m16 (we must finish rot. it quickly)
+ if (weaponInfo->m_bCanAim && padUsed->WeaponJustDown()) {
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ float limitedRotDest = m_fRotationDest;
+
+ if (m_fRotationCur - PI > m_fRotationDest) {
+ limitedRotDest += 2 * PI;
+ } else if (PI + m_fRotationCur < m_fRotationDest) {
+ limitedRotDest -= 2 * PI;
+ }
+
+ m_fRotationCur += (limitedRotDest - m_fRotationCur) / 2;
+ }
+ }
+ } else if (weaponInfo->m_bCanAimWithArm)
+ ClearPointGunAt();
+ else
+ RestoreHeadingRate();
+ }
+ }
+#endif
+
+ if (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {
+ if (m_pPointGunAt) {
+ // what??
+ if (!m_pPointGunAt
+#ifdef FREE_CAM
+ || (!CCamera::bFreeCam && CCamera::m_bUseMouse3rdPerson)
+#else
+ || CCamera::m_bUseMouse3rdPerson
+#endif
+ || m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->bInVehicle) {
+ ClearWeaponTarget();
+ return;
+ }
+ if (CPlayerPed::DoesTargetHaveToBeBroken(m_pPointGunAt->GetPosition(), GetWeapon())) {
+ ClearWeaponTarget();
+ return;
+ }
+ if (m_pPointGunAt) {
+ if (padUsed->ShiftTargetLeftJustDown())
+ FindNextWeaponLockOnTarget(m_pPointGunAt, true);
+ if (padUsed->ShiftTargetRightJustDown())
+ FindNextWeaponLockOnTarget(m_pPointGunAt, false);
+ }
+ TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SYPHON, 0, 0);
+ TheCamera.UpdateAimingCoors(m_pPointGunAt->GetPosition());
+ }
+#ifdef FREE_CAM
+ else if ((CCamera::bFreeCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE) || (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson)) {
+#else
+ else if (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson) {
+#endif
+ if (padUsed->TargetJustDown())
+ FindWeaponLockOnTarget();
+ }
+ } else if (m_pPointGunAt) {
+ ClearWeaponTarget();
+ }
+
+ if (m_pPointGunAt) {
+#ifndef VC_PED_PORTS
+ CVector markPos = m_pPointGunAt->GetPosition();
+#else
+ CVector markPos;
+ if (m_pPointGunAt->IsPed()) {
+ ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d*)markPos, PED_MID);
+ } else {
+ markPos = m_pPointGunAt->GetPosition();
+ }
+#endif
+ if (bCanPointGunAtTarget) {
+ CWeaponEffects::MarkTarget(markPos, 64, 0, 0, 255, 0.8f);
+ } else {
+ CWeaponEffects::MarkTarget(markPos, 64, 32, 0, 255, 0.8f);
+ }
+ }
+ m_bHasLockOnTarget = m_pPointGunAt != nil;
+}
+
+void
+CPlayerPed::PlayerControlZelda(CPad *padUsed)
+{
+ bool doSmoothSpray = DoWeaponSmoothSpray();
+ float camOrientation = TheCamera.Orientation;
+ float leftRight = padUsed->GetPedWalkLeftRight();
+ float upDown = padUsed->GetPedWalkUpDown();
+ float padMoveInGameUnit;
+ bool smoothSprayWithoutMove = false;
+
+ if (doSmoothSpray && upDown > 0.0f) {
+ padMoveInGameUnit = 0.0f;
+ smoothSprayWithoutMove = true;
+ } else {
+ padMoveInGameUnit = CVector2D(leftRight, upDown).Magnitude() / PAD_MOVE_TO_GAME_WORLD_MOVE;
+ }
+
+ if (padMoveInGameUnit > 0.0f || smoothSprayWithoutMove) {
+ float padHeading = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
+ float neededTurn = CGeneral::LimitRadianAngle(padHeading - camOrientation);
+ if (doSmoothSpray) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || GetWeapon()->m_eWeaponType == WEAPONTYPE_COLT45
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI)
+ m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 80.0f) * CTimer::GetTimeStep();
+ else
+ m_fRotationDest = m_fRotationCur - leftRight / 128.0f * (PI / 128.0f) * CTimer::GetTimeStep();
+ } else {
+ m_fRotationDest = neededTurn;
+ }
+
+ float maxAcc = 0.07f * CTimer::GetTimeStep();
+ m_fMoveSpeed = min(padMoveInGameUnit, m_fMoveSpeed + maxAcc);
+
+ } else {
+ m_fMoveSpeed = 0.0f;
+ }
+
+ if (m_nPedState == PED_JUMP) {
+ if (bIsInTheAir) {
+ if (bUsesCollision && !bHitSteepSlope &&
+ (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f)
+ && m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) {
+
+ float angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O
+ float angleCos = Cos(m_fRotationCur);
+ ApplyMoveForce(-angleSin * 3.0f, 3.0f * angleCos, 0.05f);
+ }
+ } else if (bIsLanding) {
+ m_fMoveSpeed = 0.0f;
+ }
+ }
+
+ if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
+ && padUsed->GetSprint()) {
+ m_nMoveState = PEDMOVE_SPRINT;
+ }
+ if (m_nPedState != PED_FIGHT)
+ SetRealMoveAnim();
+
+ if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy)
+ && padUsed->JumpJustDown() && m_nPedState != PED_JUMP) {
+ ClearAttack();
+ ClearWeaponTarget();
+ if (m_nEvadeAmount != 0 && m_pEvadingFrom) {
+ SetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);
+ m_nEvadeAmount = 0;
+ m_pEvadingFrom = nil;
+ } else {
+ SetJump();
+ }
+ }
+}
+
+void
+CPlayerPed::ProcessControl(void)
+{
+ if (m_nEvadeAmount != 0)
+ --m_nEvadeAmount;
+
+ if (m_nEvadeAmount == 0)
+ m_pEvadingFrom = nil;
+
+ if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
+ bTryingToReachDryLand = true;
+ } else if (!(((uint8)CTimer::GetFrameCounter() + m_randomSeed) & 0xF)) {
+ CVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(GetPosition(), 7.0f, nil,
+ false, true, false, false, false, false);
+ if (nearVeh && nearVeh->IsBoat())
+ bTryingToReachDryLand = true;
+ else
+ bTryingToReachDryLand = false;
+ }
+ CPed::ProcessControl();
+ if (bWasPostponed)
+ return;
+
+ CPad *padUsed = CPad::GetPad(0);
+ m_pWanted->Update();
+ CEntity::PruneReferences();
+
+ if (m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT)
+ RestoreSprintEnergy(1.0f);
+ else if (m_nMoveState == PEDMOVE_RUN)
+ RestoreSprintEnergy(0.3f);
+
+ if (m_nPedState == PED_DEAD) {
+ ClearWeaponTarget();
+ return;
+ }
+ if (m_nPedState == PED_DIE) {
+ ClearWeaponTarget();
+ if (CTimer::GetTimeInMilliseconds() > m_bloodyFootprintCountOrDeathTime + 4000)
+ SetDead();
+ return;
+ }
+ if (m_nPedState == PED_DRIVING && m_objective != OBJECTIVE_LEAVE_VEHICLE) {
+ if (m_pMyVehicle->IsCar() && ((CAutomobile*)m_pMyVehicle)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) {
+ CAnimBlendAssociation *rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR);
+ if (!rollDoorAssoc) {
+ rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR_LOW);
+ }
+
+ // These comparisons are wrong, they return uint16
+ if (m_pMyVehicle->m_nGettingOutFlags & CAR_DOOR_FLAG_LF || rollDoorAssoc || padUsed
+ && (padUsed->GetAccelerate() != 0.0f || padUsed->GetSteeringLeftRight() != 0.0f
+ || padUsed->GetBrake() != 0.0f)) {
+
+ if (rollDoorAssoc)
+ m_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, rollDoorAssoc->currentTime);
+ } else {
+ m_pMyVehicle->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF;
+ if (m_pMyVehicle->bLowVehicle)
+ rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR_LOW);
+ else
+ rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR);
+
+ rollDoorAssoc->SetFinishCallback(PedAnimDoorCloseRollingCB, this);
+ }
+ }
+ return;
+ }
+ if (m_objective == OBJECTIVE_NONE)
+ m_nMoveState = PEDMOVE_STILL;
+ if (bIsLanding)
+ RunningLand(padUsed);
+ if (padUsed && padUsed->WeaponJustDown() && m_nPedState != PED_SNIPER_MODE) {
+
+ // ...Really?
+ eWeaponType playerWeapon = FindPlayerPed()->GetWeapon()->m_eWeaponType;
+ if (playerWeapon == WEAPONTYPE_SNIPERRIFLE) {
+ DMAudio.PlayFrontEndSound(SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM, 0);
+ } else if (playerWeapon == WEAPONTYPE_ROCKETLAUNCHER) {
+ DMAudio.PlayFrontEndSound(SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM, 0);
+ }
+ }
+
+ switch (m_nPedState) {
+ case PED_NONE:
+ case PED_IDLE:
+ case PED_FLEE_POS:
+ case PED_FLEE_ENTITY:
+ case PED_ATTACK:
+ case PED_FIGHT:
+ case PED_AIM_GUN:
+ if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG400)) {
+ if (TheCamera.Cams[0].Using3rdPersonMouseCam()) {
+ if (padUsed)
+ PlayerControl1stPersonRunAround(padUsed);
+ } else if (m_nPedState == PED_FIGHT) {
+ if (padUsed)
+ PlayerControlFighter(padUsed);
+ } else if (padUsed) {
+ PlayerControlZelda(padUsed);
+ }
+ }
+ if (IsPedInControl() && padUsed)
+ ProcessPlayerWeapon(padUsed);
+ break;
+ case PED_LOOK_ENTITY:
+ case PED_LOOK_HEADING:
+ case PED_WANDER_RANGE:
+ case PED_WANDER_PATH:
+ case PED_PURSUE:
+ case PED_FOLLOW_PATH:
+ case PED_ROCKET_ODE:
+ case PED_DUMMY:
+ case PED_PAUSE:
+ case PED_FACE_PHONE:
+ case PED_MAKE_CALL:
+ case PED_CHAT:
+ case PED_MUG:
+ case PED_AI_CONTROL:
+ case PED_FOLLOW_ROUTE:
+ case PED_CPR:
+ case PED_SOLICIT:
+ case PED_BUY_ICECREAM:
+ case PED_INVESTIGATE:
+ case PED_STEP_AWAY:
+ case PED_ON_FIRE:
+ case PED_UNKNOWN:
+ case PED_STATES_NO_AI:
+ case PED_STAGGER:
+ case PED_DIVE_AWAY:
+ case PED_STATES_NO_ST:
+ case PED_ARREST_PLAYER:
+ case PED_DRIVING:
+ case PED_PASSENGER:
+ case PED_TAXI_PASSENGER:
+ case PED_OPEN_DOOR:
+ case PED_DIE:
+ case PED_DEAD:
+ case PED_HANDS_UP:
+ break;
+ case PED_SEEK_ENTITY:
+ m_vecSeekPos = m_pSeekTarget->GetPosition();
+
+ // fall through
+ case PED_SEEK_POS:
+ switch (m_nMoveState) {
+ case PEDMOVE_WALK:
+ m_fMoveSpeed = 1.0f;
+ break;
+ case PEDMOVE_RUN:
+ m_fMoveSpeed = 1.8f;
+ break;
+ case PEDMOVE_SPRINT:
+ m_fMoveSpeed = 2.5f;
+ break;
+ default:
+ m_fMoveSpeed = 0.0f;
+ break;
+ }
+ SetRealMoveAnim();
+ if (Seek()) {
+ RestorePreviousState();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ break;
+ case PED_SNIPER_MODE:
+ if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) {
+ if (padUsed)
+ PlayerControlM16(padUsed);
+ } else if (padUsed) {
+ PlayerControlSniper(padUsed);
+ }
+ break;
+ case PED_SEEK_CAR:
+ case PED_SEEK_IN_BOAT:
+ if (bVehEnterDoorIsBlocked || bKindaStayInSamePlace) {
+ m_fMoveSpeed = 0.0f;
+ } else {
+ m_fMoveSpeed = min(2.0f, 2.0f * (m_vecSeekPos - GetPosition()).Magnitude2D());
+ }
+ if (padUsed && !padUsed->ArePlayerControlsDisabled()) {
+ if (padUsed->GetTarget() || padUsed->GetLeftStickXJustDown() || padUsed->GetLeftStickYJustDown() ||
+ padUsed->GetDPadUpJustDown() || padUsed->GetDPadDownJustDown() || padUsed->GetDPadLeftJustDown() ||
+ padUsed->GetDPadRightJustDown()) {
+
+ RestorePreviousState();
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ RestorePreviousObjective();
+ }
+ }
+ }
+ if (padUsed && padUsed->GetSprint())
+ m_nMoveState = PEDMOVE_SPRINT;
+ SetRealMoveAnim();
+ break;
+ case PED_JUMP:
+ if (padUsed)
+ PlayerControlZelda(padUsed);
+ if (bIsLanding)
+ break;
+
+ // This has been added later it seems
+ return;
+ case PED_FALL:
+ case PED_GETUP:
+ case PED_ENTER_TRAIN:
+ case PED_EXIT_TRAIN:
+ case PED_CARJACK:
+ case PED_DRAG_FROM_CAR:
+ case PED_ENTER_CAR:
+ case PED_STEAL_CAR:
+ case PED_EXIT_CAR:
+ ClearWeaponTarget();
+ break;
+ case PED_ARRESTED:
+ if (m_nLastPedState == PED_DRAG_FROM_CAR && m_pVehicleAnim)
+ BeingDraggedFromCar();
+ break;
+ }
+ if (padUsed && IsPedShootable()) {
+ ProcessWeaponSwitch(padUsed);
+ GetWeapon()->Update(m_audioEntityId);
+ }
+ ProcessAnimGroups();
+ if (padUsed) {
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED
+ && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_BEHIND) {
+
+ m_lookTimer = 0;
+ float camAngle = CGeneral::LimitRadianAngle(TheCamera.Cams[TheCamera.ActiveCam].Front.Heading());
+ float angleBetweenPlayerAndCam = Abs(camAngle - m_fRotationCur);
+ if (m_nPedState != PED_ATTACK
+ && angleBetweenPlayerAndCam > DEGTORAD(30.0f) && angleBetweenPlayerAndCam < DEGTORAD(330.0f)) {
+
+ if (angleBetweenPlayerAndCam > DEGTORAD(150.0f) && angleBetweenPlayerAndCam < DEGTORAD(210.0f)) {
+ float rightTurnAngle = CGeneral::LimitRadianAngle(m_fRotationCur - DEGTORAD(150.0f));
+ float leftTurnAngle = CGeneral::LimitRadianAngle(DEGTORAD(150.0f) + m_fRotationCur);
+ if (m_fLookDirection != 999999.0f) {
+ if (Abs(rightTurnAngle - m_fLookDirection) < Abs(leftTurnAngle - m_fLookDirection))
+ camAngle = rightTurnAngle;
+ else
+ camAngle = leftTurnAngle;
+ } else {
+ camAngle = rightTurnAngle;
+ }
+ }
+ SetLookFlag(camAngle, true);
+ SetLookTimer(CTimer::GetTimeStepInMilliseconds() * 5.0f);
+ } else {
+ ClearLookFlag();
+ }
+ }
+ }
+ if (m_nMoveState == PEDMOVE_SPRINT && bIsLooking) {
+ ClearLookFlag();
+ SetLookTimer(250);
+ }
+
+ if (m_vecMoveSpeed.Magnitude2D() < 0.1f) {
+ if (m_nSpeedTimer) {
+ if (CTimer::GetTimeInMilliseconds() > m_nSpeedTimer)
+ m_bSpeedTimerFlag = true;
+ } else {
+ m_nSpeedTimer = CTimer::GetTimeInMilliseconds() + 500;
+ }
+ } else {
+ m_nSpeedTimer = 0;
+ m_bSpeedTimerFlag = false;
+ }
+}
+
+#include <new>
+
+class CPlayerPed_ : public CPlayerPed
+{
+public:
+ CPlayerPed* ctor(void) { return ::new (this) CPlayerPed(); }
+ void dtor(void) { CPlayerPed::~CPlayerPed(); }
+ void SetMoveAnim_(void) { CPlayerPed::SetMoveAnim(); }
+ void ProcessControl_(void) { CPlayerPed::ProcessControl(); }
+};
+
+STARTPATCHES
+ InjectHook(0x4EF7E0, &CPlayerPed_::ctor, PATCH_JUMP);
+ InjectHook(0x4EFB30, &CPlayerPed_::dtor, PATCH_JUMP);
+ InjectHook(0x4F3760, &CPlayerPed_::SetMoveAnim_, PATCH_JUMP);
+ InjectHook(0x4EFD90, &CPlayerPed_::ProcessControl_, PATCH_JUMP);
+ InjectHook(0x4F28A0, &CPlayerPed::ClearWeaponTarget, PATCH_JUMP);
+ InjectHook(0x4F3700, &CPlayerPed::AnnoyPlayerPed, PATCH_JUMP);
+ InjectHook(0x4F36C0, &CPlayerPed::GetPlayerInfoForThisPlayerPed, PATCH_JUMP);
+ InjectHook(0x4F2560, &CPlayerPed::MakeChangesForNewWeapon, PATCH_JUMP);
+ InjectHook(0x4F07C0, &CPlayerPed::ReApplyMoveAnims, PATCH_JUMP);
+ InjectHook(0x4F0880, &CPlayerPed::SetRealMoveAnim, PATCH_JUMP);
+ InjectHook(0x4F1810, &CPlayerPed::PlayerControlFighter, PATCH_JUMP);
+ InjectHook(0x4F1340, &CPlayerPed::RestoreSprintEnergy, PATCH_JUMP);
+ InjectHook(0x4F1380, &CPlayerPed::DoWeaponSmoothSpray, PATCH_JUMP);
+ InjectHook(0x4F36E0, &CPlayerPed::DoStuffToGoOnFire, PATCH_JUMP);
+ InjectHook(0x4F3350, &CPlayerPed::DoesTargetHaveToBeBroken, PATCH_JUMP);
+ InjectHook(0x4F31D0, &CPlayerPed::RunningLand, PATCH_JUMP);
+ InjectHook(0x4F2D00, &CPlayerPed::IsThisPedAttackingPlayer, PATCH_JUMP);
+ InjectHook(0x4F1CF0, &CPlayerPed::PlayerControlSniper, PATCH_JUMP);
+ InjectHook(0x4F2310, &CPlayerPed::ProcessWeaponSwitch, PATCH_JUMP);
+ InjectHook(0x4F1DF0, &CPlayerPed::PlayerControlM16, PATCH_JUMP);
+ InjectHook(0x4F3460, &CPlayerPed::KeepAreaAroundPlayerClear, PATCH_JUMP);
+ InjectHook(0x4F1970, &CPlayerPed::PlayerControl1stPersonRunAround, PATCH_JUMP);
+ InjectHook(0x4F1EF0, &CPlayerPed::ProcessPlayerWeapon, PATCH_JUMP);
+ InjectHook(0x4F2640, &CPlayerPed::ProcessAnimGroups, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index 3bf81066..dbfd40c6 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -704,12 +704,15 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
if (i != 0) {
// Gang member
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;
gangLeader->m_nPedState = PED_UNKNOWN;
newPed->m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints(
gangLeader->GetPosition().x, gangLeader->GetPosition().y,
newPed->GetPosition().x, newPed->GetPosition().y);
newPed->m_fRotationDest = newPed->m_fRotationCur;
+#endif
} else {
gangLeader = newPed;
}
diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp
index 2884894c..39866294 100644
--- a/src/render/Clouds.cpp
+++ b/src/render/Clouds.cpp
@@ -87,7 +87,7 @@ CClouds::Render(void)
RwV3d pos = { 0.0f, -100.0f, 15.0f };
RwV3dAdd(&worldpos, &campos, &pos);
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[2]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2]));
if(CCoronas::bSmallMoon){
szx *= 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 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;
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
for(i = 0; i < 11; i++){
RwV3d pos = { 100.0f, 0.0f, 10.0f };
if(i >= 9) pos.x = -pos.x;
@@ -132,7 +132,7 @@ CClouds::Render(void)
CSprite::FlushSpriteBuffer();
// *
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
RwV3d pos = { 100.0f, 0.0f, 10.0f };
RwV3dAdd(&worldpos, &campos, &pos);
worldpos.y -= 90.0f;
@@ -156,7 +156,7 @@ CClouds::Render(void)
int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity;
for(int cloudtype = 0; cloudtype < 3; cloudtype++){
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] };
worldpos.x = campos.x + pos.x;
worldpos.y = campos.y + pos.y;
@@ -202,7 +202,7 @@ CClouds::Render(void)
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[4]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[4]));
for(i = 0; i < 37; i++){
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;
@@ -244,7 +244,7 @@ CClouds::Render(void)
// Highlights
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[3]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[3]));
for(i = 0; i < 37; i++){
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 BowGreen[6] = { 0, 15, 30, 30, 0, 0 };
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++){
RwV3d pos = { i*1.5f, 100.0f, 5.0f };
RwV3dAdd(&worldpos, &campos, &pos);
diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp
index c934540b..68994b0b 100644
--- a/src/render/Coronas.cpp
+++ b/src/render/Coronas.cpp
@@ -320,7 +320,7 @@ CCoronas::Render(void)
CSprite::RenderOneXLUSprite(spriteCoors.x, spriteCoors.y, spriteCoors.z,
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].green / fogscale,
CCoronas::aCoronas[i].blue / fogscale,
@@ -331,7 +331,7 @@ CCoronas::Render(void)
CSprite::RenderOneXLUSprite_Rotate_Aspect(
spriteCoors.x, spriteCoors.y, spriteCoors.z,
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].green / fogscale,
CCoronas::aCoronas[i].blue / fogscale,
diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp
index 8d7fad92..e2899532 100644
--- a/src/render/Fluff.cpp
+++ b/src/render/Fluff.cpp
@@ -755,14 +755,14 @@ void CTowerClock::Render()
&TempV[1],
m_Position.x + Sin(angleMinute) * m_fScale * m_Size.x,
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[3],
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.z + Cos(angleHour) * 0.75f * m_fScale;
+ m_Position.z + Cos(angleHour) * 0.75f * m_fScale
);
LittleTest();
diff --git a/src/render/Font.cpp b/src/render/Font.cpp
index 6f336f1e..ca15cba7 100644
--- a/src/render/Font.cpp
+++ b/src/render/Font.cpp
@@ -1,636 +1,636 @@
-#include "common.h"
-#include "patcher.h"
-#include "Sprite2d.h"
-#include "TxdStore.h"
-#include "Font.h"
-
-CFontDetails &CFont::Details = *(CFontDetails*)0x8F317C;
-int16 &CFont::NewLine = *(int16*)0x95CC94;
-CSprite2d *CFont::Sprite = (CSprite2d*)0x95CC04;
-
-#ifdef MORE_LANGUAGES
-uint8 CFont::LanguageSet = FONT_LANGSET_EFIGS;
-int32 CFont::Slot = -1;
-
-int16 CFont::Size[2][3][193] = {
- {
-#else
-int16 CFont::Size[3][193] = {
-#endif
- {
- 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31,
- 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10, 35, 26, 26, 26, 26,
- 30, 26, 24, 23, 24, 22, 21, 24, 26, 10, 20, 26, 22, 29, 26, 25,
- 23, 25, 24, 24, 22, 25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37,
- 35, 21, 22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21, 21,
- 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 33, 33, 33, 33, 35,
- 27, 27, 27, 27, 32, 24, 23, 23, 23, 23, 11, 11, 11, 11, 26, 26,
- 26, 26, 26, 26, 26, 25, 26, 21, 21, 21, 21, 32, 23, 22, 22, 22,
- 22, 11, 11, 11, 11, 22, 22, 22, 22, 22, 22, 22, 22, 26, 21, 24,
- 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 18, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 20
- },
-
- {
- 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11, 17, 13, 33,
- 28, 14, 22, 21, 24, 23, 23, 21, 23, 22, 10, 35, 13, 35, 13, 33,
- 5, 25, 22, 23, 24, 21, 21, 24, 24, 9, 20, 24, 21, 27, 25, 25,
- 22, 25, 23, 20, 23, 23, 23, 31, 23, 23, 23, 37, 33, 37, 35, 37,
- 35, 21, 19, 19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21,
- 20, 22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33, 33, 35,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 16
- },
-
- {
- 15, 14, 16, 25, 19, 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27,
- 19, 18, 19, 19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35,
- 15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29, 19, 20,
- 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19, 33, 31, 39, 37, 39,
- 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23, 23,
- 20, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35, 35, 35, 35, 37,
- 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, 9, 9, 9, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 30, 19, 19, 19, 19,
- 19, 10, 10, 10, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 35,
- 12, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19
- }
-#ifdef MORE_LANGUAGES
- },
- {
- { 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17,
- 13, 31, 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10,
- 35, 26, 26, 26, 26, 30, 26, 24, 23, 24, 22, 21, 24,
- 26, 10, 20, 26, 22, 29, 26, 25, 23, 25, 24, 24, 22,
- 25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37, 35, 21,
- 22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21,
- 21, 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 13,
- 33, 13, 13, 13, 24, 22, 22, 19, 26, 21, 30, 20, 23,
- 23, 21, 24, 26, 23, 22, 23, 21, 22, 20, 20, 26, 25,
- 24, 22, 31, 32, 23, 30, 22, 22, 32, 23, 19, 18, 18,
- 15, 22, 19, 27, 19, 20, 20, 18, 22, 24, 20, 19, 19,
- 20, 19, 16, 19, 28, 20, 20, 18, 26, 27, 19, 26, 18,
- 19, 27, 19, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 18, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 20 },
- { 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11,
- 17, 13, 33, 28, 14, 22, 21, 24, 23, 23, 21, 23, 22,
- 10, 35, 13, 35, 13, 33, 5, 25, 22, 23, 24, 21, 21, 24,
- 24, 9, 20, 24, 21, 27, 25, 25, 22, 25, 23, 20, 23, 23,
- 23, 31, 23, 23, 23, 37, 33, 37, 35, 37, 35, 21, 19,
- 19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21, 20,
- 22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33,
- 33, 35, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 16, },
- { 15, 14, 16, 25, 19,
- 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27, 19, 18, 19,
- 19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35,
- 15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29,
- 19, 20, 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19,
- 33, 31, 39, 37, 39, 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23,
- 21, 21, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35,
- 35, 35, 35, 37, 19, 19, 19, 19, 19, 19, 29, 19, 19,
- 19, 20, 22, 31, 19, 19, 19, 19, 19, 29, 19, 29, 19,
- 21, 19, 30, 31, 21, 29, 19, 19, 29, 19, 21, 23, 32,
- 21, 21, 30, 31, 22, 21, 32, 33, 23, 32, 21, 21, 32,
- 21, 19, 19, 30, 31, 22, 22, 21, 32, 33, 23, 32, 21,
- 21, 32, 21, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 11, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 },
- }
-#endif
-};
-
-wchar foreign_table[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 177, 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 175,
- 128, 129, 130, 0, 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
- 0, 173, 142, 143, 144, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 150,
- 151, 152, 153, 0, 154, 0, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
- 0, 174, 165, 166, 167, 0, 168, 0, 0, 169, 170, 171, 172, 0, 0, 0,
-};
-
-void
-CFont::Initialise(void)
-{
- int slot;
-
- slot = CTxdStore::AddTxdSlot("fonts");
-#ifdef MORE_LANGUAGES
- Slot = slot;
- switch (LanguageSet)
- {
- case FONT_LANGSET_EFIGS:
- default:
- CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD");
- break;
- case FONT_LANGSET_RUSSIAN:
- CTxdStore::LoadTxd(slot, "MODELS/FONTS_R.TXD");
- break;
- }
-#else
- CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD");
-#endif
- CTxdStore::AddRef(slot);
- CTxdStore::PushCurrentTxd();
- CTxdStore::SetCurrentTxd(slot);
- Sprite[0].SetTexture("font2", "font2_mask");
- Sprite[1].SetTexture("pager", "pager_mask");
- Sprite[2].SetTexture("font1", "font1_mask");
- SetScale(1.0f, 1.0f);
- SetSlantRefPoint(SCREEN_WIDTH, 0.0f);
- SetSlant(0.0f);
- SetColor(CRGBA(0xFF, 0xFF, 0xFF, 0));
- SetJustifyOff();
- SetCentreOff();
- SetWrapx(640.0f);
- SetCentreSize(640.0f);
- SetBackgroundOff();
- SetBackgroundColor(CRGBA(0x80, 0x80, 0x80, 0x80));
- SetBackGroundOnlyTextOff();
- SetPropOn();
- SetFontStyle(FONT_BANK);
- SetRightJustifyWrap(0.0f);
- SetAlphaFade(255.0f);
- SetDropShadowPosition(0);
- CTxdStore::PopCurrentTxd();
-}
-
-#ifdef MORE_LANGUAGES
-void
-CFont::ReloadFonts(uint8 set)
-{
- if (Slot != -1 && LanguageSet != set) {
- Sprite[0].Delete();
- Sprite[1].Delete();
- Sprite[2].Delete();
- CTxdStore::PushCurrentTxd();
- CTxdStore::RemoveTxd(Slot);
- switch (set)
- {
- case FONT_LANGSET_EFIGS:
- default:
- CTxdStore::LoadTxd(Slot, "MODELS/FONTS.TXD");
- break;
- case FONT_LANGSET_RUSSIAN:
- CTxdStore::LoadTxd(Slot, "MODELS/FONTS_R.TXD");
- break;
- }
- CTxdStore::SetCurrentTxd(Slot);
- Sprite[0].SetTexture("font2", "font2_mask");
- Sprite[1].SetTexture("pager", "pager_mask");
- Sprite[2].SetTexture("font1", "font1_mask");
- CTxdStore::PopCurrentTxd();
- }
- LanguageSet = set;
-}
-#endif
-
-void
-CFont::Shutdown(void)
-{
- Sprite[0].Delete();
- Sprite[1].Delete();
- Sprite[2].Delete();
-#ifdef MORE_LANGUAGES
- CTxdStore::RemoveTxdSlot(Slot);
- Slot = -1;
-#else
- CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("fonts"));
-#endif
-}
-
-void
-CFont::InitPerFrame(void)
-{
- Details.bank = CSprite2d::GetBank(30, Sprite[0].m_pTexture);
- CSprite2d::GetBank(15, Sprite[1].m_pTexture);
- CSprite2d::GetBank(15, Sprite[2].m_pTexture);
- SetDropShadowPosition(0);
- NewLine = 0;
-}
-
-void
-CFont::PrintChar(float x, float y, wchar c)
-{
- if(x <= 0.0f || x > SCREEN_WIDTH ||
- y <= 0.0f || y > SCREEN_HEIGHT) // BUG: game uses SCREENW again
- return;
-
- float w = GetCharacterWidth(c) / 32.0f;
- float xoff = c & 0xF;
- float yoff = c >> 4;
-
- if(Details.style == FONT_BANK || Details.style == FONT_HEADING){
- if(Details.dropShadowPosition != 0){
- CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
- CRect(x + SCREEN_SCALE_X(Details.dropShadowPosition),
- y + SCREEN_SCALE_Y(Details.dropShadowPosition),
- x + SCREEN_SCALE_X(Details.dropShadowPosition) + 32.0f * Details.scaleX * 1.0f,
- y + SCREEN_SCALE_Y(Details.dropShadowPosition) + 40.0f * Details.scaleY * 0.5f),
- Details.dropColor,
- xoff/16.0f, yoff/12.8f,
- (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f,
- xoff/16.0f, (yoff+1.0f)/12.8f,
- (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.0001f);
- }
- CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
- CRect(x, y,
- x + 32.0f * Details.scaleX * 1.0f,
- y + 40.0f * Details.scaleY * 0.5f),
- Details.color,
- xoff/16.0f, yoff/12.8f,
- (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f,
- xoff/16.0f, (yoff+1.0f)/12.8f - 0.002f,
- (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.002f);
- }else{
- CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
- CRect(x, y,
- x + 32.0f * Details.scaleX * w,
- y + 32.0f * Details.scaleY * 0.5f),
- Details.color,
- xoff/16.0f, yoff/16.0f,
- (xoff+w)/16.0f, yoff/16.0f,
- xoff/16.0f, (yoff+1.0f)/16.0f,
- (xoff+w)/16.0f - 0.0001f, (yoff+1.0f)/16.0f - 0.0001f);
- }
-}
-
-void
-CFont::PrintString(float xstart, float ystart, wchar *s)
-{
- CRect rect;
- int numSpaces;
- float lineLength;
- float x, y;
- bool first;
- wchar *start, *t;
-
- if(*s == '*')
- return;
-
- if(Details.background){
- GetNumberLines(xstart, ystart, s); // BUG: result not used
- GetTextRect(&rect, xstart, ystart, s);
- CSprite2d::DrawRect(rect, Details.backgroundColor);
- }
-
- lineLength = 0.0f;
- numSpaces = 0;
- first = true;
- if(Details.centre || Details.rightJustify)
- x = 0.0f;
- else
- x = xstart;
- y = ystart;
- start = s;
-
- // This is super ugly, I blame R*
- for(;;){
- for(;;){
- for(;;){
- if(*s == '\0')
- return;
- int xend = Details.centre ? Details.centreSize :
- Details.rightJustify ? xstart - Details.rightJustifyWrap :
- Details.wrapX;
- if(x + GetStringWidth(s) > xend && !first){
- // flush line
- float spaceWidth = !Details.justify || Details.centre ? 0.0f :
- (Details.wrapX - lineLength) / numSpaces;
- float xleft = Details.centre ? xstart - x/2 :
- Details.rightJustify ? xstart - x :
- xstart;
- PrintString(xleft, y, start, s, spaceWidth);
- // reset things
- lineLength = 0.0f;
- numSpaces = 0;
- first = true;
- if(Details.centre || Details.rightJustify)
- x = 0.0f;
- else
- x = xstart;
- y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY;
- start = s;
- }else
- break;
- }
- // advance by one word
- t = GetNextSpace(s);
- if(t[0] == '\0' ||
- t[0] == ' ' && t[1] == '\0')
- break;
- if(!first)
- numSpaces++;
- first = false;
- x += GetStringWidth(s) + GetCharacterSize(*t - ' ');
- lineLength = x;
- s = t+1;
- }
- // print rest
- if(t[0] == ' ' && t[1] == '\0')
- t[0] = '\0';
- x += GetStringWidth(s);
- s = t;
- float xleft = Details.centre ? xstart - x/2 :
- Details.rightJustify ? xstart - x :
- xstart;
- PrintString(xleft, y, start, s, 0.0f);
- }
-}
-
-int
-CFont::GetNumberLines(float xstart, float ystart, wchar *s)
-{
- int n;
- float x, y;
- wchar *t;
-
- n = 0;
- if(Details.centre || Details.rightJustify)
- x = 0.0f;
- else
- x = xstart;
- y = ystart;
-
- while(*s){
- if(x + GetStringWidth(s) > (Details.centre ? Details.centreSize : Details.wrapX)){
- // reached end of line
- if(Details.centre || Details.rightJustify)
- x = 0.0f;
- else
- x = xstart;
- n++;
- // Why even?
- y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY;
- }else{
- // still space in current line
- t = GetNextSpace(s);
- if(*t == '\0'){
- // end of string
- x += GetStringWidth(s);
- n++;
- s = t;
- }else{
- x += GetStringWidth(s);
- x += GetCharacterSize(*t - ' ');
- s = t+1;
- }
- }
- }
-
- return n;
-}
-
-void
-CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s)
-{
- int numLines;
- float x, y;
- int16 maxlength;
- wchar *t;
-
- maxlength = 0;
- numLines = 0;
- if(Details.centre || Details.rightJustify)
- x = 0.0f;
- else
- x = xstart;
- y = ystart;
-
- while(*s){
- if(x + GetStringWidth(s) > (Details.centre ? Details.centreSize : Details.wrapX)){
- // reached end of line
- if(x > maxlength)
- maxlength = x;
- if(Details.centre || Details.rightJustify)
- x = 0.0f;
- else
- x = xstart;
- numLines++;
- y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY;
- }else{
- // still space in current line
- t = GetNextSpace(s);
- if(*t == '\0'){
- // end of string
- x += GetStringWidth(s);
- if(x > maxlength)
- maxlength = x;
- numLines++;
- s = t;
- }else{
- x += GetStringWidth(s);
- x += GetCharacterSize(*t - ' ');
- s = t+1;
- }
- }
- }
-
- if(Details.centre){
- if(Details.backgroundOnlyText){
- rect->left = xstart - maxlength/2 - 4.0f;
- rect->right = xstart + maxlength/2 + 4.0f;
- rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines +
- ystart + 2.0f;
- rect->top = ystart - 2.0f;
- }else{
- rect->left = xstart - Details.centreSize*0.5f - 4.0f;
- rect->right = xstart + Details.centreSize*0.5f + 4.0f;
- rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines +
- ystart + 2.0f;
- rect->top = ystart - 2.0f;
- }
- }else{
- rect->left = xstart - 4.0f;
- rect->right = Details.wrapX;
- // WTF?
- rect->bottom = ystart - 4.0f + 4.0f;
- rect->top = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines +
- ystart + 2.0f + 2.0f;
- }
-}
-
-void
-CFont::PrintString(float x, float y, wchar *start, wchar *end, float spwidth)
-{
- wchar *s, c, unused;
-
- for(s = start; s < end; s++){
- if(*s == '~')
- s = ParseToken(s, &unused);
- c = *s - ' ';
- if(Details.slant != 0.0f)
- y = (Details.slantRefX - x)*Details.slant + Details.slantRefY;
- PrintChar(x, y, c);
- x += GetCharacterSize(c);
- if(c == 0) // space
- x += spwidth;
- }
-}
-
-float
-CFont::GetCharacterWidth(wchar c)
-{
-#ifdef MORE_LANGUAGES
- if (Details.proportional)
- return Size[LanguageSet][Details.style][c];
- else
- return Size[LanguageSet][Details.style][192];
-#else
- if (Details.proportional)
- return Size[Details.style][c];
- else
- return Size[Details.style][192];
-#endif // MORE_LANGUAGES
-}
-
-float
-CFont::GetCharacterSize(wchar c)
-{
-#ifdef MORE_LANGUAGES
- if(Details.proportional)
- return Size[LanguageSet][Details.style][c] * Details.scaleX;
- else
- return Size[LanguageSet][Details.style][192] * Details.scaleX;
-#else
- if (Details.proportional)
- return Size[Details.style][c] * Details.scaleX;
- else
- return Size[Details.style][192] * Details.scaleX;
-#endif // MORE_LANGUAGES
-}
-
-float
-CFont::GetStringWidth(wchar *s, bool spaces)
-{
- float w;
-
- w = 0.0f;
- for(; (*s != ' ' || spaces) && *s != '\0'; s++){
- if(*s == '~'){
- s++;
- while(*s != '~') s++;
- s++;
- if(*s == ' ' && !spaces)
- break;
- }
- w += GetCharacterSize(*s - ' ');
- }
- return w;
-}
-
-wchar*
-CFont::GetNextSpace(wchar *s)
-{
- for(; *s != ' ' && *s != '\0'; s++)
- if(*s == '~'){
- s++;
- while(*s != '~') s++;
- s++;
- if(*s == ' ')
- break;
- }
- return s;
-}
-
-wchar*
-CFont::ParseToken(wchar *s, wchar*)
-{
- s++;
- if(Details.color.r || Details.color.g || Details.color.b)
- switch(*s){
- case 'N':
- case 'n':
- NewLine = 1;
- break;
- case 'b': SetColor(CRGBA(0x80, 0xA7, 0xF3, 0xFF)); break;
- case 'g': SetColor(CRGBA(0x5F, 0xA0, 0x6A, 0xFF)); break;
- case 'h': SetColor(CRGBA(0xE1, 0xE1, 0xE1, 0xFF)); break;
- case 'l': SetColor(CRGBA(0x00, 0x00, 0x00, 0xFF)); break;
- case 'p': SetColor(CRGBA(0xA8, 0x6E, 0xFC, 0xFF)); break;
- case 'r': SetColor(CRGBA(0x71, 0x2B, 0x49, 0xFF)); break;
- case 'w': SetColor(CRGBA(0xAF, 0xAF, 0xAF, 0xFF)); break;
- case 'y': SetColor(CRGBA(0xD2, 0xC4, 0x6A, 0xFF)); break;
- }
- while(*s != '~') s++;
- return s+1;
-}
-
-void
-CFont::DrawFonts(void)
-{
- CSprite2d::DrawBank(Details.bank);
- CSprite2d::DrawBank(Details.bank+1);
- CSprite2d::DrawBank(Details.bank+2);
-}
-
-wchar
-CFont::character_code(uint8 c)
-{
- if(c < 128)
- return c;
- return foreign_table[c-128];
-}
-
-STARTPATCHES
-
- InjectHook(0x500A40, CFont::Initialise, PATCH_JUMP);
- InjectHook(0x500BA0, CFont::Shutdown, PATCH_JUMP);
- InjectHook(0x500BE0, CFont::InitPerFrame, PATCH_JUMP);
- InjectHook(0x500C30, CFont::PrintChar, PATCH_JUMP);
- InjectHook(0x500F50, (void (*)(float, float, wchar*))CFont::PrintString, PATCH_JUMP);
- InjectHook(0x501260, CFont::GetNumberLines, PATCH_JUMP);
- InjectHook(0x5013B0, CFont::GetTextRect, PATCH_JUMP);
- InjectHook(0x501730, (void (*)(float, float, wchar*, wchar*, float))CFont::PrintString, PATCH_JUMP);
- InjectHook(0x5017E0, CFont::GetCharacterWidth, PATCH_JUMP);
- InjectHook(0x501840, CFont::GetCharacterSize, PATCH_JUMP);
- InjectHook(0x5018A0, CFont::GetStringWidth, PATCH_JUMP);
- InjectHook(0x501960, CFont::GetNextSpace, PATCH_JUMP);
- InjectHook(0x5019A0, CFont::ParseToken, PATCH_JUMP);
- InjectHook(0x501B50, CFont::DrawFonts, PATCH_JUMP);
- InjectHook(0x501E80, CFont::character_code, PATCH_JUMP);
-
- InjectHook(0x501B80, CFont::SetScale, PATCH_JUMP);
- InjectHook(0x501BA0, CFont::SetSlantRefPoint, PATCH_JUMP);
- InjectHook(0x501BC0, CFont::SetSlant, PATCH_JUMP);
- InjectHook(0x501BD0, CFont::SetColor, PATCH_JUMP);
- InjectHook(0x501C60, CFont::SetJustifyOn, PATCH_JUMP);
- InjectHook(0x501C80, CFont::SetJustifyOff, PATCH_JUMP);
- InjectHook(0x501C90, CFont::SetCentreOn, PATCH_JUMP);
- InjectHook(0x501CB0, CFont::SetCentreOff, PATCH_JUMP);
- InjectHook(0x501CC0, CFont::SetWrapx, PATCH_JUMP);
- InjectHook(0x501CD0, CFont::SetCentreSize, PATCH_JUMP);
- InjectHook(0x501CE0, CFont::SetBackgroundOn, PATCH_JUMP);
- InjectHook(0x501CF0, CFont::SetBackgroundOff, PATCH_JUMP);
- InjectHook(0x501D00, CFont::SetBackgroundColor, PATCH_JUMP);
- InjectHook(0x501D30, CFont::SetBackGroundOnlyTextOn, PATCH_JUMP);
- InjectHook(0x501D40, CFont::SetBackGroundOnlyTextOff, PATCH_JUMP);
- InjectHook(0x501D50, CFont::SetRightJustifyOn, PATCH_JUMP);
- InjectHook(0x501D70, CFont::SetRightJustifyOff, PATCH_JUMP);
- InjectHook(0x501D90, CFont::SetPropOff, PATCH_JUMP);
- InjectHook(0x501DA0, CFont::SetPropOn, PATCH_JUMP);
- InjectHook(0x501DB0, CFont::SetFontStyle, PATCH_JUMP);
- InjectHook(0x501DC0, CFont::SetRightJustifyWrap, PATCH_JUMP);
- InjectHook(0x501DD0, CFont::SetAlphaFade, PATCH_JUMP);
- InjectHook(0x501DE0, CFont::SetDropColor, PATCH_JUMP);
- InjectHook(0x501E70, CFont::SetDropShadowPosition, PATCH_JUMP);
-
-ENDPATCHES
+#include "common.h"
+#include "patcher.h"
+#include "Sprite2d.h"
+#include "TxdStore.h"
+#include "Font.h"
+
+CFontDetails &CFont::Details = *(CFontDetails*)0x8F317C;
+int16 &CFont::NewLine = *(int16*)0x95CC94;
+CSprite2d *CFont::Sprite = (CSprite2d*)0x95CC04;
+
+#ifdef MORE_LANGUAGES
+uint8 CFont::LanguageSet = FONT_LANGSET_EFIGS;
+int32 CFont::Slot = -1;
+
+int16 CFont::Size[2][3][193] = {
+ {
+#else
+int16 CFont::Size[3][193] = {
+#endif
+ {
+ 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31,
+ 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10, 35, 26, 26, 26, 26,
+ 30, 26, 24, 23, 24, 22, 21, 24, 26, 10, 20, 26, 22, 29, 26, 25,
+ 23, 25, 24, 24, 22, 25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37,
+ 35, 21, 22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21, 21,
+ 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 33, 33, 33, 33, 35,
+ 27, 27, 27, 27, 32, 24, 23, 23, 23, 23, 11, 11, 11, 11, 26, 26,
+ 26, 26, 26, 26, 26, 25, 26, 21, 21, 21, 21, 32, 23, 22, 22, 22,
+ 22, 11, 11, 11, 11, 22, 22, 22, 22, 22, 22, 22, 22, 26, 21, 24,
+ 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 18, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 20
+ },
+
+ {
+ 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11, 17, 13, 33,
+ 28, 14, 22, 21, 24, 23, 23, 21, 23, 22, 10, 35, 13, 35, 13, 33,
+ 5, 25, 22, 23, 24, 21, 21, 24, 24, 9, 20, 24, 21, 27, 25, 25,
+ 22, 25, 23, 20, 23, 23, 23, 31, 23, 23, 23, 37, 33, 37, 35, 37,
+ 35, 21, 19, 19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21,
+ 20, 22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33, 33, 35,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 16
+ },
+
+ {
+ 15, 14, 16, 25, 19, 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27,
+ 19, 18, 19, 19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35,
+ 15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29, 19, 20,
+ 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19, 33, 31, 39, 37, 39,
+ 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23, 23,
+ 20, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35, 35, 35, 35, 37,
+ 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, 9, 9, 9, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 30, 19, 19, 19, 19,
+ 19, 10, 10, 10, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 35,
+ 12, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19
+ }
+#ifdef MORE_LANGUAGES
+ },
+ {
+ { 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17,
+ 13, 31, 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10,
+ 35, 26, 26, 26, 26, 30, 26, 24, 23, 24, 22, 21, 24,
+ 26, 10, 20, 26, 22, 29, 26, 25, 23, 25, 24, 24, 22,
+ 25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37, 35, 21,
+ 22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21,
+ 21, 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 13,
+ 33, 13, 13, 13, 24, 22, 22, 19, 26, 21, 30, 20, 23,
+ 23, 21, 24, 26, 23, 22, 23, 21, 22, 20, 20, 26, 25,
+ 24, 22, 31, 32, 23, 30, 22, 22, 32, 23, 19, 18, 18,
+ 15, 22, 19, 27, 19, 20, 20, 18, 22, 24, 20, 19, 19,
+ 20, 19, 16, 19, 28, 20, 20, 18, 26, 27, 19, 26, 18,
+ 19, 27, 19, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 18, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 20 },
+ { 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11,
+ 17, 13, 33, 28, 14, 22, 21, 24, 23, 23, 21, 23, 22,
+ 10, 35, 13, 35, 13, 33, 5, 25, 22, 23, 24, 21, 21, 24,
+ 24, 9, 20, 24, 21, 27, 25, 25, 22, 25, 23, 20, 23, 23,
+ 23, 31, 23, 23, 23, 37, 33, 37, 35, 37, 35, 21, 19,
+ 19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21, 20,
+ 22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33,
+ 33, 35, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 16, },
+ { 15, 14, 16, 25, 19,
+ 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27, 19, 18, 19,
+ 19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35,
+ 15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29,
+ 19, 20, 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19,
+ 33, 31, 39, 37, 39, 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23,
+ 21, 21, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35,
+ 35, 35, 35, 37, 19, 19, 19, 19, 19, 19, 29, 19, 19,
+ 19, 20, 22, 31, 19, 19, 19, 19, 19, 29, 19, 29, 19,
+ 21, 19, 30, 31, 21, 29, 19, 19, 29, 19, 21, 23, 32,
+ 21, 21, 30, 31, 22, 21, 32, 33, 23, 32, 21, 21, 32,
+ 21, 19, 19, 30, 31, 22, 22, 21, 32, 33, 23, 32, 21,
+ 21, 32, 21, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 11, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 },
+ }
+#endif
+};
+
+wchar foreign_table[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 177, 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 175,
+ 128, 129, 130, 0, 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 0, 173, 142, 143, 144, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 150,
+ 151, 152, 153, 0, 154, 0, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 0, 174, 165, 166, 167, 0, 168, 0, 0, 169, 170, 171, 172, 0, 0, 0,
+};
+
+void
+CFont::Initialise(void)
+{
+ int slot;
+
+ slot = CTxdStore::AddTxdSlot("fonts");
+#ifdef MORE_LANGUAGES
+ Slot = slot;
+ switch (LanguageSet)
+ {
+ case FONT_LANGSET_EFIGS:
+ default:
+ CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD");
+ break;
+ case FONT_LANGSET_RUSSIAN:
+ CTxdStore::LoadTxd(slot, "MODELS/FONTS_R.TXD");
+ break;
+ }
+#else
+ CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD");
+#endif
+ CTxdStore::AddRef(slot);
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::SetCurrentTxd(slot);
+ Sprite[0].SetTexture("font2", "font2_mask");
+ Sprite[1].SetTexture("pager", "pager_mask");
+ Sprite[2].SetTexture("font1", "font1_mask");
+ SetScale(1.0f, 1.0f);
+ SetSlantRefPoint(SCREEN_WIDTH, 0.0f);
+ SetSlant(0.0f);
+ SetColor(CRGBA(0xFF, 0xFF, 0xFF, 0));
+ SetJustifyOff();
+ SetCentreOff();
+ SetWrapx(640.0f);
+ SetCentreSize(640.0f);
+ SetBackgroundOff();
+ SetBackgroundColor(CRGBA(0x80, 0x80, 0x80, 0x80));
+ SetBackGroundOnlyTextOff();
+ SetPropOn();
+ SetFontStyle(FONT_BANK);
+ SetRightJustifyWrap(0.0f);
+ SetAlphaFade(255.0f);
+ SetDropShadowPosition(0);
+ CTxdStore::PopCurrentTxd();
+}
+
+#ifdef MORE_LANGUAGES
+void
+CFont::ReloadFonts(uint8 set)
+{
+ if (Slot != -1 && LanguageSet != set) {
+ Sprite[0].Delete();
+ Sprite[1].Delete();
+ Sprite[2].Delete();
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::RemoveTxd(Slot);
+ switch (set)
+ {
+ case FONT_LANGSET_EFIGS:
+ default:
+ CTxdStore::LoadTxd(Slot, "MODELS/FONTS.TXD");
+ break;
+ case FONT_LANGSET_RUSSIAN:
+ CTxdStore::LoadTxd(Slot, "MODELS/FONTS_R.TXD");
+ break;
+ }
+ CTxdStore::SetCurrentTxd(Slot);
+ Sprite[0].SetTexture("font2", "font2_mask");
+ Sprite[1].SetTexture("pager", "pager_mask");
+ Sprite[2].SetTexture("font1", "font1_mask");
+ CTxdStore::PopCurrentTxd();
+ }
+ LanguageSet = set;
+}
+#endif
+
+void
+CFont::Shutdown(void)
+{
+ Sprite[0].Delete();
+ Sprite[1].Delete();
+ Sprite[2].Delete();
+#ifdef MORE_LANGUAGES
+ CTxdStore::RemoveTxdSlot(Slot);
+ Slot = -1;
+#else
+ CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("fonts"));
+#endif
+}
+
+void
+CFont::InitPerFrame(void)
+{
+ Details.bank = CSprite2d::GetBank(30, Sprite[0].m_pTexture);
+ CSprite2d::GetBank(15, Sprite[1].m_pTexture);
+ CSprite2d::GetBank(15, Sprite[2].m_pTexture);
+ SetDropShadowPosition(0);
+ NewLine = 0;
+}
+
+void
+CFont::PrintChar(float x, float y, wchar c)
+{
+ if(x <= 0.0f || x > SCREEN_WIDTH ||
+ y <= 0.0f || y > SCREEN_HEIGHT) // BUG: game uses SCREENW again
+ return;
+
+ float w = GetCharacterWidth(c) / 32.0f;
+ float xoff = c & 0xF;
+ float yoff = c >> 4;
+
+ if(Details.style == FONT_BANK || Details.style == FONT_HEADING){
+ if(Details.dropShadowPosition != 0){
+ CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
+ CRect(x + SCREEN_SCALE_X(Details.dropShadowPosition),
+ y + SCREEN_SCALE_Y(Details.dropShadowPosition),
+ x + SCREEN_SCALE_X(Details.dropShadowPosition) + 32.0f * Details.scaleX * 1.0f,
+ y + SCREEN_SCALE_Y(Details.dropShadowPosition) + 40.0f * Details.scaleY * 0.5f),
+ Details.dropColor,
+ xoff/16.0f, yoff/12.8f,
+ (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f,
+ xoff/16.0f, (yoff+1.0f)/12.8f,
+ (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.0001f);
+ }
+ CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
+ CRect(x, y,
+ x + 32.0f * Details.scaleX * 1.0f,
+ y + 40.0f * Details.scaleY * 0.5f),
+ Details.color,
+ xoff/16.0f, yoff/12.8f,
+ (xoff+1.0f)/16.0f - 0.001f, yoff/12.8f,
+ xoff/16.0f, (yoff+1.0f)/12.8f - 0.002f,
+ (xoff+1.0f)/16.0f - 0.001f, (yoff+1.0f)/12.8f - 0.002f);
+ }else{
+ CSprite2d::AddSpriteToBank(Details.bank + Details.style, // BUG: game doesn't add bank
+ CRect(x, y,
+ x + 32.0f * Details.scaleX * w,
+ y + 32.0f * Details.scaleY * 0.5f),
+ Details.color,
+ xoff/16.0f, yoff/16.0f,
+ (xoff+w)/16.0f, yoff/16.0f,
+ xoff/16.0f, (yoff+1.0f)/16.0f,
+ (xoff+w)/16.0f - 0.0001f, (yoff+1.0f)/16.0f - 0.0001f);
+ }
+}
+
+void
+CFont::PrintString(float xstart, float ystart, wchar *s)
+{
+ CRect rect;
+ int numSpaces;
+ float lineLength;
+ float x, y;
+ bool first;
+ wchar *start, *t;
+
+ if(*s == '*')
+ return;
+
+ if(Details.background){
+ GetNumberLines(xstart, ystart, s); // BUG: result not used
+ GetTextRect(&rect, xstart, ystart, s);
+ CSprite2d::DrawRect(rect, Details.backgroundColor);
+ }
+
+ lineLength = 0.0f;
+ numSpaces = 0;
+ first = true;
+ if(Details.centre || Details.rightJustify)
+ x = 0.0f;
+ else
+ x = xstart;
+ y = ystart;
+ start = s;
+
+ // This is super ugly, I blame R*
+ for(;;){
+ for(;;){
+ for(;;){
+ if(*s == '\0')
+ return;
+ int xend = Details.centre ? Details.centreSize :
+ Details.rightJustify ? xstart - Details.rightJustifyWrap :
+ Details.wrapX;
+ if(x + GetStringWidth(s) > xend && !first){
+ // flush line
+ float spaceWidth = !Details.justify || Details.centre ? 0.0f :
+ (Details.wrapX - lineLength) / numSpaces;
+ float xleft = Details.centre ? xstart - x/2 :
+ Details.rightJustify ? xstart - x :
+ xstart;
+ PrintString(xleft, y, start, s, spaceWidth);
+ // reset things
+ lineLength = 0.0f;
+ numSpaces = 0;
+ first = true;
+ if(Details.centre || Details.rightJustify)
+ x = 0.0f;
+ else
+ x = xstart;
+ y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY;
+ start = s;
+ }else
+ break;
+ }
+ // advance by one word
+ t = GetNextSpace(s);
+ if(t[0] == '\0' ||
+ t[0] == ' ' && t[1] == '\0')
+ break;
+ if(!first)
+ numSpaces++;
+ first = false;
+ x += GetStringWidth(s) + GetCharacterSize(*t - ' ');
+ lineLength = x;
+ s = t+1;
+ }
+ // print rest
+ if(t[0] == ' ' && t[1] == '\0')
+ t[0] = '\0';
+ x += GetStringWidth(s);
+ s = t;
+ float xleft = Details.centre ? xstart - x/2 :
+ Details.rightJustify ? xstart - x :
+ xstart;
+ PrintString(xleft, y, start, s, 0.0f);
+ }
+}
+
+int
+CFont::GetNumberLines(float xstart, float ystart, wchar *s)
+{
+ int n;
+ float x, y;
+ wchar *t;
+
+ n = 0;
+ if(Details.centre || Details.rightJustify)
+ x = 0.0f;
+ else
+ x = xstart;
+ y = ystart;
+
+ while(*s){
+ if(x + GetStringWidth(s) > (Details.centre ? Details.centreSize : Details.wrapX)){
+ // reached end of line
+ if(Details.centre || Details.rightJustify)
+ x = 0.0f;
+ else
+ x = xstart;
+ n++;
+ // Why even?
+ y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY;
+ }else{
+ // still space in current line
+ t = GetNextSpace(s);
+ if(*t == '\0'){
+ // end of string
+ x += GetStringWidth(s);
+ n++;
+ s = t;
+ }else{
+ x += GetStringWidth(s);
+ x += GetCharacterSize(*t - ' ');
+ s = t+1;
+ }
+ }
+ }
+
+ return n;
+}
+
+void
+CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s)
+{
+ int numLines;
+ float x, y;
+ int16 maxlength;
+ wchar *t;
+
+ maxlength = 0;
+ numLines = 0;
+ if(Details.centre || Details.rightJustify)
+ x = 0.0f;
+ else
+ x = xstart;
+ y = ystart;
+
+ while(*s){
+ if(x + GetStringWidth(s) > (Details.centre ? Details.centreSize : Details.wrapX)){
+ // reached end of line
+ if(x > maxlength)
+ maxlength = x;
+ if(Details.centre || Details.rightJustify)
+ x = 0.0f;
+ else
+ x = xstart;
+ numLines++;
+ y += 32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY;
+ }else{
+ // still space in current line
+ t = GetNextSpace(s);
+ if(*t == '\0'){
+ // end of string
+ x += GetStringWidth(s);
+ if(x > maxlength)
+ maxlength = x;
+ numLines++;
+ s = t;
+ }else{
+ x += GetStringWidth(s);
+ x += GetCharacterSize(*t - ' ');
+ s = t+1;
+ }
+ }
+ }
+
+ if(Details.centre){
+ if(Details.backgroundOnlyText){
+ rect->left = xstart - maxlength/2 - 4.0f;
+ rect->right = xstart + maxlength/2 + 4.0f;
+ rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines +
+ ystart + 2.0f;
+ rect->top = ystart - 2.0f;
+ }else{
+ rect->left = xstart - Details.centreSize*0.5f - 4.0f;
+ rect->right = xstart + Details.centreSize*0.5f + 4.0f;
+ rect->bottom = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines +
+ ystart + 2.0f;
+ rect->top = ystart - 2.0f;
+ }
+ }else{
+ rect->left = xstart - 4.0f;
+ rect->right = Details.wrapX;
+ // WTF?
+ rect->bottom = ystart - 4.0f + 4.0f;
+ rect->top = (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * numLines +
+ ystart + 2.0f + 2.0f;
+ }
+}
+
+void
+CFont::PrintString(float x, float y, wchar *start, wchar *end, float spwidth)
+{
+ wchar *s, c, unused;
+
+ for(s = start; s < end; s++){
+ if(*s == '~')
+ s = ParseToken(s, &unused);
+ c = *s - ' ';
+ if(Details.slant != 0.0f)
+ y = (Details.slantRefX - x)*Details.slant + Details.slantRefY;
+ PrintChar(x, y, c);
+ x += GetCharacterSize(c);
+ if(c == 0) // space
+ x += spwidth;
+ }
+}
+
+float
+CFont::GetCharacterWidth(wchar c)
+{
+#ifdef MORE_LANGUAGES
+ if (Details.proportional)
+ return Size[LanguageSet][Details.style][c];
+ else
+ return Size[LanguageSet][Details.style][192];
+#else
+ if (Details.proportional)
+ return Size[Details.style][c];
+ else
+ return Size[Details.style][192];
+#endif // MORE_LANGUAGES
+}
+
+float
+CFont::GetCharacterSize(wchar c)
+{
+#ifdef MORE_LANGUAGES
+ if(Details.proportional)
+ return Size[LanguageSet][Details.style][c] * Details.scaleX;
+ else
+ return Size[LanguageSet][Details.style][192] * Details.scaleX;
+#else
+ if (Details.proportional)
+ return Size[Details.style][c] * Details.scaleX;
+ else
+ return Size[Details.style][192] * Details.scaleX;
+#endif // MORE_LANGUAGES
+}
+
+float
+CFont::GetStringWidth(wchar *s, bool spaces)
+{
+ float w;
+
+ w = 0.0f;
+ for(; (*s != ' ' || spaces) && *s != '\0'; s++){
+ if(*s == '~'){
+ s++;
+ while(*s != '~') s++;
+ s++;
+ if(*s == ' ' && !spaces)
+ break;
+ }
+ w += GetCharacterSize(*s - ' ');
+ }
+ return w;
+}
+
+wchar*
+CFont::GetNextSpace(wchar *s)
+{
+ for(; *s != ' ' && *s != '\0'; s++)
+ if(*s == '~'){
+ s++;
+ while(*s != '~') s++;
+ s++;
+ if(*s == ' ')
+ break;
+ }
+ return s;
+}
+
+wchar*
+CFont::ParseToken(wchar *s, wchar*)
+{
+ s++;
+ if(Details.color.r || Details.color.g || Details.color.b)
+ switch(*s){
+ case 'N':
+ case 'n':
+ NewLine = 1;
+ break;
+ case 'b': SetColor(CRGBA(0x80, 0xA7, 0xF3, 0xFF)); break;
+ case 'g': SetColor(CRGBA(0x5F, 0xA0, 0x6A, 0xFF)); break;
+ case 'h': SetColor(CRGBA(0xE1, 0xE1, 0xE1, 0xFF)); break;
+ case 'l': SetColor(CRGBA(0x00, 0x00, 0x00, 0xFF)); break;
+ case 'p': SetColor(CRGBA(0xA8, 0x6E, 0xFC, 0xFF)); break;
+ case 'r': SetColor(CRGBA(0x71, 0x2B, 0x49, 0xFF)); break;
+ case 'w': SetColor(CRGBA(0xAF, 0xAF, 0xAF, 0xFF)); break;
+ case 'y': SetColor(CRGBA(0xD2, 0xC4, 0x6A, 0xFF)); break;
+ }
+ while(*s != '~') s++;
+ return s+1;
+}
+
+void
+CFont::DrawFonts(void)
+{
+ CSprite2d::DrawBank(Details.bank);
+ CSprite2d::DrawBank(Details.bank+1);
+ CSprite2d::DrawBank(Details.bank+2);
+}
+
+wchar
+CFont::character_code(uint8 c)
+{
+ if(c < 128)
+ return c;
+ return foreign_table[c-128];
+}
+
+STARTPATCHES
+
+ InjectHook(0x500A40, CFont::Initialise, PATCH_JUMP);
+ InjectHook(0x500BA0, CFont::Shutdown, PATCH_JUMP);
+ InjectHook(0x500BE0, CFont::InitPerFrame, PATCH_JUMP);
+ InjectHook(0x500C30, CFont::PrintChar, PATCH_JUMP);
+ InjectHook(0x500F50, (void (*)(float, float, wchar*))CFont::PrintString, PATCH_JUMP);
+ InjectHook(0x501260, CFont::GetNumberLines, PATCH_JUMP);
+ InjectHook(0x5013B0, CFont::GetTextRect, PATCH_JUMP);
+ InjectHook(0x501730, (void (*)(float, float, wchar*, wchar*, float))CFont::PrintString, PATCH_JUMP);
+ InjectHook(0x5017E0, CFont::GetCharacterWidth, PATCH_JUMP);
+ InjectHook(0x501840, CFont::GetCharacterSize, PATCH_JUMP);
+ InjectHook(0x5018A0, CFont::GetStringWidth, PATCH_JUMP);
+ InjectHook(0x501960, CFont::GetNextSpace, PATCH_JUMP);
+ InjectHook(0x5019A0, CFont::ParseToken, PATCH_JUMP);
+ InjectHook(0x501B50, CFont::DrawFonts, PATCH_JUMP);
+ InjectHook(0x501E80, CFont::character_code, PATCH_JUMP);
+
+ InjectHook(0x501B80, CFont::SetScale, PATCH_JUMP);
+ InjectHook(0x501BA0, CFont::SetSlantRefPoint, PATCH_JUMP);
+ InjectHook(0x501BC0, CFont::SetSlant, PATCH_JUMP);
+ InjectHook(0x501BD0, CFont::SetColor, PATCH_JUMP);
+ InjectHook(0x501C60, CFont::SetJustifyOn, PATCH_JUMP);
+ InjectHook(0x501C80, CFont::SetJustifyOff, PATCH_JUMP);
+ InjectHook(0x501C90, CFont::SetCentreOn, PATCH_JUMP);
+ InjectHook(0x501CB0, CFont::SetCentreOff, PATCH_JUMP);
+ InjectHook(0x501CC0, CFont::SetWrapx, PATCH_JUMP);
+ InjectHook(0x501CD0, CFont::SetCentreSize, PATCH_JUMP);
+ InjectHook(0x501CE0, CFont::SetBackgroundOn, PATCH_JUMP);
+ InjectHook(0x501CF0, CFont::SetBackgroundOff, PATCH_JUMP);
+ InjectHook(0x501D00, CFont::SetBackgroundColor, PATCH_JUMP);
+ InjectHook(0x501D30, CFont::SetBackGroundOnlyTextOn, PATCH_JUMP);
+ InjectHook(0x501D40, CFont::SetBackGroundOnlyTextOff, PATCH_JUMP);
+ InjectHook(0x501D50, CFont::SetRightJustifyOn, PATCH_JUMP);
+ InjectHook(0x501D70, CFont::SetRightJustifyOff, PATCH_JUMP);
+ InjectHook(0x501D90, CFont::SetPropOff, PATCH_JUMP);
+ InjectHook(0x501DA0, CFont::SetPropOn, PATCH_JUMP);
+ InjectHook(0x501DB0, CFont::SetFontStyle, PATCH_JUMP);
+ InjectHook(0x501DC0, CFont::SetRightJustifyWrap, PATCH_JUMP);
+ InjectHook(0x501DD0, CFont::SetAlphaFade, PATCH_JUMP);
+ InjectHook(0x501DE0, CFont::SetDropColor, PATCH_JUMP);
+ InjectHook(0x501E70, CFont::SetDropShadowPosition, PATCH_JUMP);
+
+ENDPATCHES
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index c4aca8e4..80d7fe47 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -815,7 +815,7 @@ void CHud::Draw()
DrawScriptText
*/
if (!CTimer::GetIsUserPaused()) {
- CTextLine* IntroText = CTheScripts::IntroTextLines;
+ intro_text_line* IntroText = CTheScripts::IntroTextLines;
for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++) {
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++) {
if (CTheScripts::IntroRectangles[i].m_bIsUsed && CTheScripts::IntroRectangles[i].m_bBeforeFade) {
diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp
index 1cf27ee0..d28671fa 100644
--- a/src/render/MBlur.cpp
+++ b/src/render/MBlur.cpp
@@ -4,12 +4,13 @@
#include "Camera.h"
#include "MBlur.h"
+// Originally taken from RW example 'mblur'
+
RwRaster *&CMBlur::pFrontBuffer = *(RwRaster**)0x8E2C48;
bool &CMBlur::ms_bJustInitialised = *(bool*)0x95CDAB;
bool &CMBlur::BlurOn = *(bool*)0x95CDAD;
static RwIm2DVertex Vertex[4];
-//static RwIm2DVertex *Vertex = (RwIm2DVertex*)0x62F780;
static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
void
diff --git a/src/core/PlayerSkin.cpp b/src/render/PlayerSkin.cpp
index bf780666..2cba45fe 100644
--- a/src/core/PlayerSkin.cpp
+++ b/src/render/PlayerSkin.cpp
@@ -1,169 +1,174 @@
-#include "common.h"
-#include "patcher.h"
-#include "main.h"
-#include "PlayerSkin.h"
-#include "TxdStore.h"
-#include "rtbmp.h"
-#include "ClumpModelInfo.h"
-#include "VisibilityPlugins.h"
-#include "World.h"
-#include "PlayerInfo.h"
-#include "CdStream.h"
-#include "FileMgr.h"
-#include "Directory.h"
-#include "RwHelper.h"
-#include "Timer.h"
-#include "Lights.h"
-
-int CPlayerSkin::m_txdSlot;
-
-void
-FindPlayerDff(uint32 &offset, uint32 &size)
-{
- int file;
- CDirectory::DirectoryInfo info;
-
- file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
-
- do {
- if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
- return;
- } while (strcasecmp("player.dff", info.name) != 0);
-
- offset = info.offset;
- size = info.size;
-}
-
-void
-LoadPlayerDff(void)
-{
- RwStream *stream;
- RwMemory mem;
- uint32 offset, size;
- uint8 *buffer;
- bool streamWasAdded = false;
-
- if (CdStreamGetNumImages() == 0) {
- CdStreamAddImage("models\\gta3.img");
- streamWasAdded = true;
- }
-
- FindPlayerDff(offset, size);
- buffer = (uint8*)RwMallocAlign(size << 11, 2048);
- CdStreamRead(0, buffer, offset, size);
- CdStreamSync(0);
-
- mem.start = buffer;
- mem.length = size << 11;
- stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
-
- if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
- gpPlayerClump = RpClumpStreamRead(stream);
-
- RwStreamClose(stream, &mem);
- RwFreeAlign(buffer);
-
- if (streamWasAdded)
- CdStreamRemoveImages();
-}
-
-void
-CPlayerSkin::Initialise(void)
-{
- m_txdSlot = CTxdStore::AddTxdSlot("skin");
- CTxdStore::Create(m_txdSlot);
- CTxdStore::AddRef(m_txdSlot);
-}
-
-void
-CPlayerSkin::Shutdown(void)
-{
- CTxdStore::RemoveTxdSlot(m_txdSlot);
-}
-
-RwTexture *
-CPlayerSkin::GetSkinTexture(const char *texName)
-{
- RwTexture *tex;
- RwRaster *raster;
- int32 width, height, depth, format;
-
- CTxdStore::PushCurrentTxd();
- CTxdStore::SetCurrentTxd(m_txdSlot);
- tex = RwTextureRead(texName, NULL);
- CTxdStore::PopCurrentTxd();
- if (tex) return tex;
-
- if (strcmp(DEFAULT_SKIN_NAME, texName) == 0)
- sprintf(gString, "models\\generic\\player.bmp");
- else
- sprintf(gString, "skins\\%s.bmp", texName);
-
- if (RwImage *image = RtBMPImageRead(gString)) {
- RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
- raster = RwRasterCreate(width, height, depth, format);
- RwRasterSetFromImage(raster, image);
-
- tex = RwTextureCreate(raster);
- RwTextureSetName(tex, texName);
- RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
- RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
-
- RwImageDestroy(image);
- }
- return tex;
-}
-
-void
-CPlayerSkin::BeginFrontendSkinEdit(void)
-{
- LoadPlayerDff();
- RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
- CWorld::Players[0].LoadPlayerSkin();
- gOldFov = CDraw::GetFOV();
- CDraw::SetFOV(30.0f);
-}
-
-void
-CPlayerSkin::EndFrontendSkinEdit(void)
-{
- RpClumpDestroy(gpPlayerClump);
- gpPlayerClump = NULL;
- CDraw::SetFOV(gOldFov);
-}
-
-void
-CPlayerSkin::RenderFrontendSkinEdit(void)
-{
- static float rotation = 0.0f;
- RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
- RwV3d pos = { 1.35f, 0.35f, 7.725f };
- const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
- const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
- static uint32 LastFlash = 0;
-
- RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
-
- if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
- rotation += 2.0f;
- if (rotation > 360.0f)
- rotation -= 360.0f;
- LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
- }
- RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
- RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
- RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT);
- RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT);
- RwFrameUpdateObjects(frame);
- SetAmbientColours(&AmbientColor);
- RpClumpRender(gpPlayerClump);
-}
-
-STARTPATCHES
-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);
+#include "common.h"
+#include "patcher.h"
+#include "main.h"
+#include "PlayerSkin.h"
+#include "TxdStore.h"
+#include "rtbmp.h"
+#include "ClumpModelInfo.h"
+#include "VisibilityPlugins.h"
+#include "World.h"
+#include "PlayerInfo.h"
+#include "CdStream.h"
+#include "FileMgr.h"
+#include "Directory.h"
+#include "RwHelper.h"
+#include "Timer.h"
+#include "Lights.h"
+
+RpClump *gpPlayerClump;
+float gOldFov;
+
+int CPlayerSkin::m_txdSlot;
+
+void
+FindPlayerDff(uint32 &offset, uint32 &size)
+{
+ int file;
+ CDirectory::DirectoryInfo info;
+
+ file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
+
+ do {
+ if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
+ return;
+ } while (strcasecmp("player.dff", info.name) != 0);
+
+ offset = info.offset;
+ size = info.size;
+}
+
+void
+LoadPlayerDff(void)
+{
+ RwStream *stream;
+ RwMemory mem;
+ uint32 offset, size;
+ uint8 *buffer;
+ bool streamWasAdded = false;
+
+ if (CdStreamGetNumImages() == 0) {
+ CdStreamAddImage("models\\gta3.img");
+ streamWasAdded = true;
+ }
+
+ FindPlayerDff(offset, size);
+ buffer = (uint8*)RwMallocAlign(size << 11, 2048);
+ CdStreamRead(0, buffer, offset, size);
+ CdStreamSync(0);
+
+ mem.start = buffer;
+ mem.length = size << 11;
+ stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
+
+ if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
+ gpPlayerClump = RpClumpStreamRead(stream);
+
+ RwStreamClose(stream, &mem);
+ RwFreeAlign(buffer);
+
+ if (streamWasAdded)
+ CdStreamRemoveImages();
+}
+
+void
+CPlayerSkin::Initialise(void)
+{
+ m_txdSlot = CTxdStore::AddTxdSlot("skin");
+ CTxdStore::Create(m_txdSlot);
+ CTxdStore::AddRef(m_txdSlot);
+}
+
+void
+CPlayerSkin::Shutdown(void)
+{
+ CTxdStore::RemoveTxdSlot(m_txdSlot);
+}
+
+RwTexture *
+CPlayerSkin::GetSkinTexture(const char *texName)
+{
+ RwTexture *tex;
+ RwRaster *raster;
+ int32 width, height, depth, format;
+
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::SetCurrentTxd(m_txdSlot);
+ tex = RwTextureRead(texName, NULL);
+ CTxdStore::PopCurrentTxd();
+ if (tex != nil) return tex;
+
+ if (strcmp(DEFAULT_SKIN_NAME, texName) == 0)
+ sprintf(gString, "models\\generic\\player.bmp");
+ else
+ sprintf(gString, "skins\\%s.bmp", texName);
+
+ if (RwImage *image = RtBMPImageRead(gString)) {
+ RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
+ raster = RwRasterCreate(width, height, depth, format);
+ RwRasterSetFromImage(raster, image);
+
+ tex = RwTextureCreate(raster);
+ RwTextureSetName(tex, texName);
+#ifdef FIX_BUGS
+ RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
+#endif
+ RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
+
+ RwImageDestroy(image);
+ }
+ return tex;
+}
+
+void
+CPlayerSkin::BeginFrontendSkinEdit(void)
+{
+ LoadPlayerDff();
+ RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
+ CWorld::Players[0].LoadPlayerSkin();
+ gOldFov = CDraw::GetFOV();
+ CDraw::SetFOV(30.0f);
+}
+
+void
+CPlayerSkin::EndFrontendSkinEdit(void)
+{
+ RpClumpDestroy(gpPlayerClump);
+ gpPlayerClump = NULL;
+ CDraw::SetFOV(gOldFov);
+}
+
+void
+CPlayerSkin::RenderFrontendSkinEdit(void)
+{
+ static float rotation = 0.0f;
+ RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
+ const RwV3d pos = { 1.35f, 0.35f, 7.725f };
+ const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
+ const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
+ static uint32 LastFlash = 0;
+
+ RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
+
+ if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
+ rotation += 2.0f;
+ if (rotation > 360.0f)
+ rotation -= 360.0f;
+ LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
+ }
+ RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
+ RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
+ RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT);
+ RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT);
+ RwFrameUpdateObjects(frame);
+ SetAmbientColours(&AmbientColor);
+ RpClumpRender(gpPlayerClump);
+}
+
+STARTPATCHES
+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 \ No newline at end of file
diff --git a/src/core/PlayerSkin.h b/src/render/PlayerSkin.h
index 2d82ec12..e0214ce0 100644
--- a/src/core/PlayerSkin.h
+++ b/src/render/PlayerSkin.h
@@ -2,12 +2,6 @@
#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
{
static int m_txdSlot;
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index c2725ed6..41ee5d1d 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -1,12 +1,247 @@
#include "common.h"
#include "patcher.h"
+#include "main.h"
+#include "TxdStore.h"
+#include "Timer.h"
+#include "Replay.h"
#include "Skidmarks.h"
-WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); }
-WRAPPER void CSkidmarks::Update() { EAXJMP(0x518200); }
+CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS];
-WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); }
-WRAPPER void CSkidmarks::RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy) { EAXJMP(0x5185C0); }
+RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6];
+RwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2];
+RwTexture *gpSkidTex;
+RwTexture *gpSkidBloodTex;
+RwTexture *gpSkidMudTex;
-WRAPPER void CSkidmarks::Init(void) { EAXJMP(0x517D70); }
-WRAPPER void CSkidmarks::Shutdown(void) { EAXJMP(0x518100); }
+void
+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
+}
diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h
index bf2da7e4..085b4c6d 100644
--- a/src/render/Skidmarks.h
+++ b/src/render/Skidmarks.h
@@ -1,12 +1,32 @@
#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
{
+ static CSkidmark aSkidmarks[NUMSKIDMARKS];
public:
+
+ static void Init(void);
+ static void Shutdown(void);
static void Clear(void);
static void Update(void);
static void Render(void);
- static void RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy);
- static void Init(void);
- static void Shutdown(void);
+ static void RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody);
};
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 0d856d9c..9189a7c2 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -22,10 +22,10 @@
#include "Shadows.h"
#include "main.h"
-RxObjSpace3DVertex StreakVertices[4];
+RwIm3DVertex StreakVertices[4];
RwImVertexIndex StreakIndexList[12];
-RxObjSpace3DVertex TraceVertices[6];
+RwIm3DVertex TraceVertices[6];
RwImVertexIndex TraceIndexList[12];
@@ -34,60 +34,60 @@ CSpecialFX::Init(void)
{
CBulletTraces::Init();
- RwIm3DVertexSetU(&StreakVertices[0], 0.0f);
- RwIm3DVertexSetV(&StreakVertices[0], 0.0f);
- RwIm3DVertexSetU(&StreakVertices[1], 1.0f);
- RwIm3DVertexSetV(&StreakVertices[1], 0.0f);
- RwIm3DVertexSetU(&StreakVertices[2], 0.0f);
- RwIm3DVertexSetV(&StreakVertices[2], 0.0f);
- RwIm3DVertexSetU(&StreakVertices[3], 1.0f);
- RwIm3DVertexSetV(&StreakVertices[3], 0.0f);
-
- StreakIndexList[0] = 0;
- StreakIndexList[1] = 1;
- StreakIndexList[2] = 2;
- StreakIndexList[3] = 1;
- StreakIndexList[4] = 3;
- StreakIndexList[5] = 2;
- StreakIndexList[6] = 0;
- StreakIndexList[7] = 2;
- StreakIndexList[8] = 1;
- StreakIndexList[9] = 1;
- StreakIndexList[10] = 2;
- StreakIndexList[11] = 3;
-
- RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255);
- RwIm3DVertexSetU(&TraceVertices[0], 0.0);
- RwIm3DVertexSetV(&TraceVertices[0], 0.0);
- RwIm3DVertexSetU(&TraceVertices[1], 1.0);
- RwIm3DVertexSetV(&TraceVertices[1], 0.0);
- RwIm3DVertexSetU(&TraceVertices[2], 0.0);
- RwIm3DVertexSetV(&TraceVertices[2], 0.5);
- RwIm3DVertexSetU(&TraceVertices[3], 1.0);
- RwIm3DVertexSetV(&TraceVertices[3], 0.5);
- RwIm3DVertexSetU(&TraceVertices[4], 0.0);
- RwIm3DVertexSetV(&TraceVertices[4], 1.0);
- RwIm3DVertexSetU(&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;
-
+ RwIm3DVertexSetU(&StreakVertices[0], 0.0f);
+ RwIm3DVertexSetV(&StreakVertices[0], 0.0f);
+ RwIm3DVertexSetU(&StreakVertices[1], 1.0f);
+ RwIm3DVertexSetV(&StreakVertices[1], 0.0f);
+ RwIm3DVertexSetU(&StreakVertices[2], 0.0f);
+ RwIm3DVertexSetV(&StreakVertices[2], 0.0f);
+ RwIm3DVertexSetU(&StreakVertices[3], 1.0f);
+ RwIm3DVertexSetV(&StreakVertices[3], 0.0f);
+
+ StreakIndexList[0] = 0;
+ StreakIndexList[1] = 1;
+ StreakIndexList[2] = 2;
+ StreakIndexList[3] = 1;
+ StreakIndexList[4] = 3;
+ StreakIndexList[5] = 2;
+ StreakIndexList[6] = 0;
+ StreakIndexList[7] = 2;
+ StreakIndexList[8] = 1;
+ StreakIndexList[9] = 1;
+ StreakIndexList[10] = 2;
+ StreakIndexList[11] = 3;
+
+ RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255);
+ RwIm3DVertexSetU(&TraceVertices[0], 0.0);
+ RwIm3DVertexSetV(&TraceVertices[0], 0.0);
+ RwIm3DVertexSetU(&TraceVertices[1], 1.0);
+ RwIm3DVertexSetV(&TraceVertices[1], 0.0);
+ RwIm3DVertexSetU(&TraceVertices[2], 0.0);
+ RwIm3DVertexSetV(&TraceVertices[2], 0.5);
+ RwIm3DVertexSetU(&TraceVertices[3], 1.0);
+ RwIm3DVertexSetV(&TraceVertices[3], 0.5);
+ RwIm3DVertexSetU(&TraceVertices[4], 0.0);
+ RwIm3DVertexSetV(&TraceVertices[4], 1.0);
+ RwIm3DVertexSetU(&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;
+
CMotionBlurStreaks::Init();
CBrightLights::Init();
CShinyTexts::Init();
@@ -112,13 +112,13 @@ LookForBatCB(RwObject *object, void *data)
void
CSpecialFX::Update(void)
{
- CMotionBlurStreaks::Update();
- CBulletTraces::Update();
-
- if(FindPlayerPed() &&
- FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT &&
- FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING)
- RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT));
+ CMotionBlurStreaks::Update();
+ CBulletTraces::Update();
+
+ if(FindPlayerPed() &&
+ FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT &&
+ FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING)
+ RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT));
}
void
@@ -130,78 +130,78 @@ CSpecialFX::Shutdown(void)
void
CSpecialFX::Render(void)
{
- CMotionBlurStreaks::Render();
- CBulletTraces::Render();
- CBrightLights::Render();
- CShinyTexts::Render();
- CMoneyMessages::Render();
- C3dMarkers::Render();
+ CMotionBlurStreaks::Render();
+ CBulletTraces::Render();
+ CBrightLights::Render();
+ CShinyTexts::Render();
+ CMoneyMessages::Render();
+ C3dMarkers::Render();
}
CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS];
-void
-CRegisteredMotionBlurStreak::Update(void)
-{
- int i;
- bool wasUpdated;
- bool lastWasUpdated = false;
- for(i = 2; i > 0; i--){
- m_pos1[i] = m_pos1[i-1];
- m_pos2[i] = m_pos2[i-1];
- m_isValid[i] = m_isValid[i-1];
- wasUpdated = true;
- if(!lastWasUpdated && !m_isValid[i])
- wasUpdated = false;
- lastWasUpdated = wasUpdated;
- }
- m_isValid[0] = false;
- if(!wasUpdated)
- m_id = 0;
-}
-
-void
-CRegisteredMotionBlurStreak::Render(void)
-{
- int i;
- int a1, a2;
- for(i = 0; i < 2; i++)
- if(m_isValid[i] && m_isValid[i+1]){
- a1 = (255/3)*(3-i)/3;
- RwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1);
- RwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1);
- a2 = (255/3)*(3-(i+1))/3;
- RwIm3DVertexSetRGBA(&StreakVertices[2], 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[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[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z);
+void
+CRegisteredMotionBlurStreak::Update(void)
+{
+ int i;
+ bool wasUpdated;
+ bool lastWasUpdated = false;
+ for(i = 2; i > 0; i--){
+ m_pos1[i] = m_pos1[i-1];
+ m_pos2[i] = m_pos2[i-1];
+ m_isValid[i] = m_isValid[i-1];
+ wasUpdated = true;
+ if(!lastWasUpdated && !m_isValid[i])
+ wasUpdated = false;
+ lastWasUpdated = wasUpdated;
+ }
+ m_isValid[0] = false;
+ if(!wasUpdated)
+ m_id = 0;
+}
+
+void
+CRegisteredMotionBlurStreak::Render(void)
+{
+ int i;
+ int a1, a2;
+ for(i = 0; i < 2; i++)
+ if(m_isValid[i] && m_isValid[i+1]){
+ a1 = (255/3)*(3-i)/3;
+ RwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1);
+ RwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1);
+ a2 = (255/3)*(3-(i+1))/3;
+ RwIm3DVertexSetRGBA(&StreakVertices[2], 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[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[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z);
LittleTest();
if(RwIm3DTransform(StreakVertices, 4, nil, rwIM3D_VERTEXUV)){
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, StreakIndexList, 12);
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
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;
}
-void
-CMotionBlurStreaks::Render(void)
-{
+void
+CMotionBlurStreaks::Render(void)
+{
bool setRenderStates = false;
int i;
- for(i = 0; i < NUMMBLURSTREAKS; i++)
- if(aStreaks[i].m_id){
- if(!setRenderStates){
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
+ for(i = 0; i < NUMMBLURSTREAKS; i++)
+ if(aStreaks[i].m_id){
+ if(!setRenderStates){
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGCOLOR,
(void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
- setRenderStates = true;
- }
- aStreaks[i].Render();
- }
- if(setRenderStates){
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
- }
-}
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
+ setRenderStates = true;
+ }
+ aStreaks[i].Render();
+ }
+ if(setRenderStates){
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
+ }
+}
CBulletTrace CBulletTraces::aTraces[NUMBULLETTRACES];
@@ -291,10 +291,10 @@ void CBulletTraces::Render(void)
for (int i = 0; i < NUMBULLETTRACES; i++) {
if (!aTraces[i].m_bInUse)
continue;
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)2);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpShadowExplosionTex->raster);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpShadowExplosionTex));
CVector inf = aTraces[i].m_vecCurrentPos;
CVector sup = aTraces[i].m_vecTargetPos;
CVector center = (inf + sup) / 2;
@@ -316,9 +316,9 @@ void CBulletTraces::Render(void)
RwIm3DEnd();
}
}
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}
void CBulletTraces::Update(void)
@@ -414,8 +414,7 @@ C3dMarker::Render()
{
if (m_pAtomic == nil) return;
- RwRGBA *color = RpMaterialGetColor(m_pMaterial);
- *color = m_Color;
+ RpMaterialSetColor(m_pMaterial, &m_Color);
m_Matrix.UpdateRW();
@@ -643,13 +642,13 @@ C3dMarkers::Update()
int CBrightLights::NumBrightLights;
CBrightLight CBrightLights::aBrightLights[NUMBRIGHTLIGHTS];
-
-void
-CBrightLights::Init(void)
-{
- NumBrightLights = 0;
-}
-
+
+void
+CBrightLights::Init(void)
+{
+ NumBrightLights = 0;
+}
+
void
CBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front,
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)
return;
- aBrightLights[NumBrightLights].m_pos = pos;
- aBrightLights[NumBrightLights].m_up = up;
- aBrightLights[NumBrightLights].m_side = side;
- aBrightLights[NumBrightLights].m_front = front;
- aBrightLights[NumBrightLights].m_type = type;
- aBrightLights[NumBrightLights].m_red = red;
- aBrightLights[NumBrightLights].m_green = green;
+ aBrightLights[NumBrightLights].m_pos = pos;
+ aBrightLights[NumBrightLights].m_up = up;
+ aBrightLights[NumBrightLights].m_side = side;
+ aBrightLights[NumBrightLights].m_front = front;
+ aBrightLights[NumBrightLights].m_type = type;
+ aBrightLights[NumBrightLights].m_red = red;
+ aBrightLights[NumBrightLights].m_green = green;
aBrightLights[NumBrightLights].m_blue = blue;
NumBrightLights++;
@@ -696,22 +695,22 @@ static RwImVertexIndex CubeIndices[12*3] = {
6, 0, 4, 6, 2, 0, 6, 5, 7, 6, 4, 5
};
-void
-CBrightLights::Render(void)
-{
+void
+CBrightLights::Render(void)
+{
int i, j;
CVector pos;
- if(NumBrightLights == 0)
- return;
-
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
-
- for(i = 0; i < NumBrightLights; i++){
+ if(NumBrightLights == 0)
+ return;
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+
+ for(i = 0; i < NumBrightLights; i++){
if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40)
RenderOutGeometryBuffer();
@@ -753,14 +752,14 @@ CBrightLights::Render(void)
a = 255;
else
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
- if(aBrightLights[i].m_type >= BRIGHTLIGHT_FRONT_LONG && aBrightLights[i].m_type <= BRIGHTLIGHT_REAR_TALL){
+ // 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_camDist < CARLIGHTS_FADE_DIST)
a = 31;
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));
- }
-
+ }
+
switch(aBrightLights[i].m_type){
case BRIGHTLIGHT_TRAFFIC_GREEN:
case BRIGHTLIGHT_TRAFFIC_YELLOW:
@@ -793,7 +792,7 @@ CBrightLights::Render(void)
TempBufferVerticesStored += 8;
TempBufferIndicesStored += 12*3;
break;
-
+
case BRIGHTLIGHT_FRONT_SMALL:
case BRIGHTLIGHT_REAR_SMALL:
for(j = 0; j < 8; j++){
@@ -809,7 +808,7 @@ CBrightLights::Render(void)
TempBufferVerticesStored += 8;
TempBufferIndicesStored += 12*3;
break;
-
+
case BRIGHTLIGHT_FRONT_TALL:
case BRIGHTLIGHT_REAR_TALL:
for(j = 0; j < 8; j++){
@@ -840,17 +839,17 @@ CBrightLights::Render(void)
TempBufferIndicesStored += 4*3;
break;
- }
- }
-
- RenderOutGeometryBuffer();
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- NumBrightLights = 0;
-}
-
-void
-CBrightLights::RenderOutGeometryBuffer(void)
-{
+ }
+ }
+
+ RenderOutGeometryBuffer();
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ NumBrightLights = 0;
+}
+
+void
+CBrightLights::RenderOutGeometryBuffer(void)
+{
if(TempBufferIndicesStored != 0){
LittleTest();
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
@@ -864,13 +863,13 @@ CBrightLights::RenderOutGeometryBuffer(void)
int CShinyTexts::NumShinyTexts;
CShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS];
-
-void
-CShinyTexts::Init(void)
-{
- NumShinyTexts = 0;
-}
-
+
+void
+CShinyTexts::Init(void)
+{
+ NumShinyTexts = 0;
+}
+
void
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,
@@ -910,20 +909,20 @@ CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
NumShinyTexts++;
}
-void
-CShinyTexts::Render(void)
-{
- int i, ix, v;
- RwTexture *lastTex = nil;
-
- if(NumShinyTexts == 0)
- return;
-
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
-
+void
+CShinyTexts::Render(void)
+{
+ int i, ix, v;
+ RwTexture *lastTex = nil;
+
+ if(NumShinyTexts == 0)
+ return;
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
@@ -984,15 +983,15 @@ CShinyTexts::Render(void)
RenderOutGeometryBuffer();
NumShinyTexts = 0;
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
-}
-
-void
-CShinyTexts::RenderOutGeometryBuffer(void)
-{
+}
+
+void
+CShinyTexts::RenderOutGeometryBuffer(void)
+{
if(TempBufferIndicesStored != 0){
LittleTest();
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
@@ -1002,8 +1001,8 @@ CShinyTexts::RenderOutGeometryBuffer(void)
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
}
-}
-
+}
+
#define MONEY_MESSAGE_LIFETIME_MS 2000
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index 8519ae79..2d9f18b1 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -12,26 +12,26 @@ public:
class CRegisteredMotionBlurStreak
{
public:
- uintptr m_id;
- uint8 m_red;
- uint8 m_green;
- uint8 m_blue;
- CVector m_pos1[3];
- CVector m_pos2[3];
+ uintptr m_id;
+ uint8 m_red;
+ uint8 m_green;
+ uint8 m_blue;
+ CVector m_pos1[3];
+ CVector m_pos2[3];
bool m_isValid[3];
- void Update(void);
- void Render(void);
+ void Update(void);
+ void Render(void);
};
class CMotionBlurStreaks
{
static CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS];
public:
- static void Init(void);
- static void Update(void);
+ static void Init(void);
+ static void Update(void);
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
@@ -133,18 +133,18 @@ enum
BRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG,
};
-class CBrightLight
-{
-public:
- CVector m_pos;
- CVector m_up;
- CVector m_side;
- CVector m_front;
- float m_camDist;
- uint8 m_type;
- uint8 m_red;
- uint8 m_green;
- uint8 m_blue;
+class CBrightLight
+{
+public:
+ CVector m_pos;
+ CVector m_up;
+ CVector m_side;
+ CVector m_front;
+ float m_camDist;
+ uint8 m_type;
+ uint8 m_red;
+ uint8 m_green;
+ uint8 m_blue;
};
class CBrightLights
@@ -152,11 +152,11 @@ class CBrightLights
static int NumBrightLights;
static CBrightLight aBrightLights[NUMBRIGHTLIGHTS];
public:
- static void Init(void);
+ static void Init(void);
static void RegisterOne(CVector pos, CVector up, CVector side, CVector front,
uint8 type, uint8 red = 0, uint8 green = 0, uint8 blue = 0);
- static void Render(void);
- static void RenderOutGeometryBuffer(void);
+ static void Render(void);
+ static void RenderOutGeometryBuffer(void);
};
@@ -169,12 +169,12 @@ enum
class CShinyText
{
public:
- CVector m_verts[4];
- CVector2D m_texCoords[4];
- float m_camDist;
- uint8 m_type;
- uint8 m_red;
- uint8 m_green;
+ CVector m_verts[4];
+ CVector2D m_texCoords[4];
+ float m_camDist;
+ uint8 m_type;
+ uint8 m_red;
+ uint8 m_green;
uint8 m_blue;
};
@@ -183,12 +183,12 @@ class CShinyTexts
static int NumShinyTexts;
static CShinyText aShinyTexts[NUMSHINYTEXTS];
public:
- static void Init(void);
+ static void Init(void);
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,
uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist);
- static void Render(void);
- static void RenderOutGeometryBuffer(void);
+ static void Render(void);
+ static void RenderOutGeometryBuffer(void);
};
class CMoneyMessage
diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp
index 24577f41..8ac2315f 100644
--- a/src/render/Sprite.cpp
+++ b/src/render/Sprite.cpp
@@ -30,10 +30,12 @@ CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh,
out->x *= SCREEN_WIDTH * recip;
out->y *= SCREEN_HEIGHT * recip;
// What is this? size?
- *outw = 70.0f/CDraw::GetFOV();
- *outh = 70.0f/CDraw::GetFOV();
- *outw *= SCREEN_WIDTH * recip;
- *outh *= SCREEN_HEIGHT * recip;
+ *outw = 70.0f/CDraw::GetFOV() * SCREEN_WIDTH * recip;
+#ifdef ASPECT_RATIO_SCALE
+ *outh = 70.0f/CDraw::GetFOV() / (DEFAULT_ASPECT_RATIO / SCREEN_ASPECT_RATIO) * SCREEN_HEIGHT * recip;
+#else
+ *outh = 70.0f/CDraw::GetFOV() * SCREEN_HEIGHT * recip;
+#endif
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)
{
float screenz, recipz;
+ float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = m_f2DNearScreenZ;
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)
{
float screenz, recipz;
+ float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = m_f2DNearScreenZ;
recipz = m_fRecipNearClipPlane;
diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp
index c4dbcdaa..3f21516a 100644
--- a/src/render/Sprite2d.cpp
+++ b/src/render/Sprite2d.cpp
@@ -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)
{
float screenz, recipz;
+ float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip;
@@ -312,10 +313,11 @@ void
CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col)
{
int i;
- float screenz, recipz;
+ float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip;
+ z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
for(i = 0; i < n; i++){
@@ -334,10 +336,11 @@ void
CSprite2d::SetMaskVertices(int n, float *positions)
{
int i;
- float screenz, recipz;
+ float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip;
+ z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
for(i = 0; i < n; i++){
RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);
@@ -345,7 +348,7 @@ CSprite2d::SetMaskVertices(int n, float *positions)
RwIm2DVertexSetScreenZ(&maVertices[i], screenz);
RwIm2DVertexSetCameraZ(&maVertices[i], z);
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,
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();
recipz = RecipNearClip;
+ z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
RwIm2DVertexSetScreenX(&verts[0], r.left);
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)
{
- SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
- RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));
- RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));
+ RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
}
diff --git a/src/render/TexList.cpp b/src/render/TexList.cpp
new file mode 100644
index 00000000..1689837f
--- /dev/null
+++ b/src/render/TexList.cpp
@@ -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");
+} \ No newline at end of file
diff --git a/src/render/TexList.h b/src/render/TexList.h
new file mode 100644
index 00000000..7e042211
--- /dev/null
+++ b/src/render/TexList.h
@@ -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();
+}; \ No newline at end of file
diff --git a/src/render/VisibilityPlugins.cpp b/src/render/VisibilityPlugins.cpp
index 74cd2590..f8b1f6b2 100644
--- a/src/render/VisibilityPlugins.cpp
+++ b/src/render/VisibilityPlugins.cpp
@@ -117,7 +117,7 @@ CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera)
RpMaterial*
SetAlphaCB(RpMaterial *material, void *data)
{
- material->color.alpha = (uint8)(uint32)data;
+ ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uint32)data;
return material;
}
diff --git a/src/render/WeaponEffects.cpp b/src/render/WeaponEffects.cpp
index 3101def9..2ed9e662 100644
--- a/src/render/WeaponEffects.cpp
+++ b/src/render/WeaponEffects.cpp
@@ -83,7 +83,7 @@ CWeaponEffects::Render(void)
{
float recipz = 1.0f / 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,
recipz, 255);
}
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index d132ffdb..b440e77c 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -71,8 +71,8 @@ const int16 WeatherTypesList[] = {
const float Windiness[] = {
0.0f, // WEATHER_SUNNY
- 0.7f, // WEATHER_RAINY
- 1.0f, // WEATHER_CLOUDY
+ 0.7f, // WEATHER_CLOUDY
+ 1.0f, // WEATHER_RAINY
0.5f // WEATHER_FOGGY
};
@@ -106,7 +106,7 @@ void CWeather::Init(void)
{
NewWeatherType = WEATHER_SUNNY;
bScriptsForceRain = false;
- OldWeatherType = WEATHER_RAINY;
+ OldWeatherType = WEATHER_CLOUDY;
Stored_StateStored = false;
InterpolationValue = 0.0f;
WhenToPlayLightningSound = 0;
@@ -475,7 +475,7 @@ void CWeather::RenderRainStreaks(void)
// 1/16 probability
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);
- if (!CCutsceneMgr::IsCutsceneProcessing()) {
+ if (!CCutsceneMgr::IsRunning()) {
Streaks[i].position.x += 2.0f * FindPlayerSpeed().x * 60.0f;
Streaks[i].position.y += 2.0f * FindPlayerSpeed().y * 60.0f;
}
diff --git a/src/save/Date.h b/src/save/Date.h
index 3e022d09..15646c23 100644
--- a/src/save/Date.h
+++ b/src/save/Date.h
@@ -1,18 +1,18 @@
-#pragma once
-
-class CDate
-{
-public:
- int m_nSecond;
- int m_nMinute;
- int m_nHour;
- int m_nDay;
- int m_nMonth;
- int m_nYear;
-
- CDate();
- 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);
+#pragma once
+
+class CDate
+{
+public:
+ int m_nSecond;
+ int m_nMinute;
+ int m_nHour;
+ int m_nDay;
+ int m_nMonth;
+ int m_nYear;
+
+ CDate();
+ 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);
}; \ No newline at end of file
diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp
index d71b0c22..2545b9ab 100644
--- a/src/save/GenericGameStorage.cpp
+++ b/src/save/GenericGameStorage.cpp
@@ -48,6 +48,13 @@ char SaveFileNameJustSaved[260];
int (&Slots)[SLOT_COUNT+1] = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C;
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 WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from));
diff --git a/src/save/GenericGameStorage.h b/src/save/GenericGameStorage.h
index e22dfc7e..e6fd2e2d 100644
--- a/src/save/GenericGameStorage.h
+++ b/src/save/GenericGameStorage.h
@@ -1,37 +1,43 @@
-#pragma once
-
-#include "PCSave.h"
-
-#define SLOT_COUNT (8)
-
-bool GenericSave(int file);
-bool GenericLoad();
-bool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size);
-bool ReadDataFromFile(int32 file, uint8 *buf, uint32 size);
-bool CloseFile(int32 file);
-void DoGameSpecificStuffAfterSucessLoad();
-bool CheckSlotDataValid(int32 slot);
-void MakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize);
-void CopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size);
-void DoGameSpecificStuffBeforeSave();
-void MakeValidSaveName(int32 slot);
-wchar *GetSavedGameDateAndTime(int32 slot);
-wchar *GetNameOfSavedGame(int32 slot);
-bool CheckDataNotCorrupt(int32 slot, char *name);
-bool RestoreForStartLoad();
-int align4bytes(int32 size);
-
-extern class CDate& CompileDateAndTime;
-
-extern char (&DefaultPCSaveFileName)[260];
-extern char (&ValidSaveName)[260];
-extern char (&LoadFileName)[256];
-extern wchar (&SlotFileName)[SLOT_COUNT][260];
-extern wchar (&SlotSaveDate)[SLOT_COUNT][70];
-extern int &CheckSum;
-extern enum eLevelName &m_LevelToLoad;
-extern int (&Slots)[SLOT_COUNT+1];
-
-extern char SaveFileNameJustSaved[260]; // 8F2570
-
+#pragma once
+
+#include "PCSave.h"
+
+#define SLOT_COUNT (8)
+
+bool GenericSave(int file);
+bool GenericLoad();
+bool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size);
+bool ReadDataFromFile(int32 file, uint8 *buf, uint32 size);
+bool CloseFile(int32 file);
+void DoGameSpecificStuffAfterSucessLoad();
+bool CheckSlotDataValid(int32 slot);
+void MakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize);
+void CopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size);
+void DoGameSpecificStuffBeforeSave();
+void MakeValidSaveName(int32 slot);
+wchar *GetSavedGameDateAndTime(int32 slot);
+wchar *GetNameOfSavedGame(int32 slot);
+bool CheckDataNotCorrupt(int32 slot, char *name);
+bool RestoreForStartLoad();
+int align4bytes(int32 size);
+
+extern class CDate& CompileDateAndTime;
+
+extern char (&DefaultPCSaveFileName)[260];
+extern char (&ValidSaveName)[260];
+extern char (&LoadFileName)[256];
+extern wchar (&SlotFileName)[SLOT_COUNT][260];
+extern wchar (&SlotSaveDate)[SLOT_COUNT][70];
+extern int &CheckSum;
+extern enum eLevelName &m_LevelToLoad;
+extern int (&Slots)[SLOT_COUNT+1];
+
+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"; \ No newline at end of file
diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp
index 7993426a..ec84e968 100644
--- a/src/skel/win/win.cpp
+++ b/src/skel/win/win.cpp
@@ -1927,7 +1927,7 @@ _WinMain(HINSTANCE instance,
* 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) )
{
@@ -2059,13 +2059,13 @@ _WinMain(HINSTANCE instance,
if (wp.showCmd != SW_SHOWMINIMIZED)
RsEventHandler(rsFRONTENDIDLE, nil);
- if ( !FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bLoadingSavedGame )
+ if ( !FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bWantToLoad )
{
gGameState = GS_INIT_PLAYING_GAME;
TRACE("gGameState = GS_INIT_PLAYING_GAME;");
}
- if ( FrontEndMenuManager.m_bLoadingSavedGame )
+ if ( FrontEndMenuManager.m_bWantToLoad )
{
InitialiseGame();
FrontEndMenuManager.m_bGameNotLoaded = false;
@@ -2128,7 +2128,7 @@ _WinMain(HINSTANCE instance,
RwInitialised = FALSE;
FrontEndMenuManager.UnloadTextures();
- if ( !FrontEndMenuManager.m_bStartGameLoading )
+ if ( !FrontEndMenuManager.m_bWantToRestart )
break;
CPad::ResetCheats();
@@ -2138,13 +2138,13 @@ _WinMain(HINSTANCE instance,
CTimer::Stop();
- if ( FrontEndMenuManager.m_bLoadingSavedGame )
+ if ( FrontEndMenuManager.m_bWantToLoad )
{
CGame::ShutDownForRestart();
CGame::InitialiseWhenRestarting();
DMAudio.ChangeMusicMode(MUSICMODE_GAME);
LoadSplash(GetLevelSplashScreen(CGame::currLevel));
- FrontEndMenuManager.m_bLoadingSavedGame = false;
+ FrontEndMenuManager.m_bWantToLoad = false;
}
else
{
@@ -2168,7 +2168,7 @@ _WinMain(HINSTANCE instance,
}
FrontEndMenuManager.m_bFirstTime = false;
- FrontEndMenuManager.m_bStartGameLoading = false;
+ FrontEndMenuManager.m_bWantToRestart = false;
}
diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp
index db5b9036..9896a8e0 100644
--- a/src/text/Messages.cpp
+++ b/src/text/Messages.cpp
@@ -1,835 +1,835 @@
-#define DIRECTINPUT_VERSION 0x0800
-#include "dinput.h"
-
-#include "common.h"
-#include "patcher.h"
-#include "Messages.h"
-#include "RwHelper.h"
-#include "Hud.h"
-#include "User.h"
-#include "Timer.h"
-#include "Text.h"
-
-#include "ControllerConfig.h"
-
-tMessage(&CMessages::BriefMessages)[NUMBRIEFMESSAGES] = *(tMessage(*)[NUMBRIEFMESSAGES])*(uintptr*)0x8786E0;
-tPreviousBrief(&CMessages::PreviousBriefs)[NUMPREVIOUSBRIEFS] = *(tPreviousBrief(*)[NUMPREVIOUSBRIEFS])*(uintptr*)0x713C08;
-tBigMessage(&CMessages::BIGMessages)[NUMBIGMESSAGES] = *(tBigMessage(*)[NUMBIGMESSAGES])*(uintptr*)0x773628;
-char CMessages::PreviousMissionTitle[16]; // unused
-
-void
-CMessages::Init()
-{
- ClearMessages();
-
- for (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {
- PreviousBriefs[i].m_pText = nil;
- PreviousBriefs[i].m_pString = nil;
- }
-}
-
-uint16
-CMessages::GetWideStringLength(wchar *src)
-{
- uint16 length = 0;
- while (*(src++)) length++;
- return length;
-}
-
-void
-CMessages::WideStringCopy(wchar *dst, wchar *src, uint16 size)
-{
- int32 i = 0;
- if (src) {
- while (i < size - 1) {
- if (!src[i]) break;
- dst[i] = src[i];
- i++;
- }
- } else {
- while (i < size - 1)
- dst[i++] = '\0';
- }
- dst[i] = '\0';
-}
-
-bool
-CMessages::WideStringCompare(wchar *str1, wchar *str2, uint16 size)
-{
- uint16 len1 = GetWideStringLength(str1);
- uint16 len2 = GetWideStringLength(str2);
- if (len1 != len2 && (len1 < size || len2 < size))
- return false;
-
- for (int32 i = 0; i < size; i++) {
- if (!str1[i])
- break;
-
- if (str1[i] != str2[i])
- return false;
- }
- return true;
-}
-
-void
-CMessages::Process()
-{
- for (int32 style = 0; style < 6; style++) {
- if (BIGMessages[style].m_Stack[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BIGMessages[style].m_Stack[0].m_nTime + BIGMessages[style].m_Stack[0].m_nStartTime) {
- BIGMessages[style].m_Stack[0].m_pText = nil;
-
- int32 i = 0;
- while (i < 3) {
- if (BIGMessages[style].m_Stack[i + 1].m_pText == nil) break;
- BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
- i++;
- }
-
- BIGMessages[style].m_Stack[i].m_pText = nil;
- BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- }
- }
-
- if (BriefMessages[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BriefMessages[0].m_nTime + BriefMessages[0].m_nStartTime) {
- BriefMessages[0].m_pText = nil;
- int32 i = 0;
- while (i < NUMBRIEFMESSAGES-1) {
- if (BriefMessages[i + 1].m_pText == nil)
- break;
-
- BriefMessages[i] = BriefMessages[i + 1];
- i++;
- }
- CMessages::BriefMessages[i].m_pText = nil;
- CMessages::BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- if (BriefMessages[0].m_pText != nil)
- AddToPreviousBriefArray(
- BriefMessages[0].m_pText,
- BriefMessages[0].m_nNumber[0],
- BriefMessages[0].m_nNumber[1],
- BriefMessages[0].m_nNumber[2],
- BriefMessages[0].m_nNumber[3],
- BriefMessages[0].m_nNumber[4],
- BriefMessages[0].m_nNumber[5],
- BriefMessages[0].m_pString);
- }
-}
-
-void
-CMessages::Display()
-{
- wchar outstr[256];
-
- DefinedState();
-
- for (int32 i = 0; i < NUMBIGMESSAGES; i++) {
- InsertNumberInString(
- BIGMessages[i].m_Stack[0].m_pText,
- BIGMessages[i].m_Stack[0].m_nNumber[0],
- BIGMessages[i].m_Stack[0].m_nNumber[1],
- BIGMessages[i].m_Stack[0].m_nNumber[2],
- BIGMessages[i].m_Stack[0].m_nNumber[3],
- BIGMessages[i].m_Stack[0].m_nNumber[4],
- BIGMessages[i].m_Stack[0].m_nNumber[5],
- outstr);
- InsertStringInString(outstr, BIGMessages[i].m_Stack[0].m_pString);
- InsertPlayerControlKeysInString(outstr);
- CHud::SetBigMessage(outstr, i);
- }
-
- InsertNumberInString(
- BriefMessages[0].m_pText,
- BriefMessages[0].m_nNumber[0],
- BriefMessages[0].m_nNumber[1],
- BriefMessages[0].m_nNumber[2],
- BriefMessages[0].m_nNumber[3],
- BriefMessages[0].m_nNumber[4],
- BriefMessages[0].m_nNumber[5],
- outstr);
- InsertStringInString(outstr, BriefMessages[0].m_pString);
- InsertPlayerControlKeysInString(outstr);
- CHud::SetMessage(outstr);
-}
-
-void
-CMessages::AddMessage(wchar *msg, uint32 time, uint16 flag)
-{
- wchar outstr[512]; // unused
- WideStringCopy(outstr, msg, 256);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- int32 i = 0;
- while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)
- i++;
- if (i >= NUMBRIEFMESSAGES) return;
-
- BriefMessages[i].m_pText = msg;
- BriefMessages[i].m_nFlag = flag;
- BriefMessages[i].m_nTime = time;
- BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[i].m_nNumber[0] = -1;
- BriefMessages[i].m_nNumber[1] = -1;
- BriefMessages[i].m_nNumber[2] = -1;
- BriefMessages[i].m_nNumber[3] = -1;
- BriefMessages[i].m_nNumber[4] = -1;
- BriefMessages[i].m_nNumber[5] = -1;
- BriefMessages[i].m_pString = nil;
- if (i == 0)
- AddToPreviousBriefArray(
- BriefMessages[0].m_pText,
- BriefMessages[0].m_nNumber[0],
- BriefMessages[0].m_nNumber[1],
- BriefMessages[0].m_nNumber[2],
- BriefMessages[0].m_nNumber[3],
- BriefMessages[0].m_nNumber[4],
- BriefMessages[0].m_nNumber[5],
- BriefMessages[0].m_pString);
-}
-
-void
-CMessages::AddMessageJumpQ(wchar *msg, uint32 time, uint16 flag)
-{
- wchar outstr[512]; // unused
- WideStringCopy(outstr, msg, 256);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- BriefMessages[0].m_pText = msg;
- BriefMessages[0].m_nFlag = flag;
- BriefMessages[0].m_nTime = time;
- BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[0].m_nNumber[0] = -1;
- BriefMessages[0].m_nNumber[1] = -1;
- BriefMessages[0].m_nNumber[2] = -1;
- BriefMessages[0].m_nNumber[3] = -1;
- BriefMessages[0].m_nNumber[4] = -1;
- BriefMessages[0].m_nNumber[5] = -1;
- BriefMessages[0].m_pString = nil;
- AddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, 0);
-}
-
-void
-CMessages::AddMessageSoon(wchar *msg, uint32 time, uint16 flag)
-{
- wchar outstr[512]; // unused
- WideStringCopy(outstr, msg, 256);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- if (BriefMessages[0].m_pText != nil) {
- for (int i = NUMBRIEFMESSAGES-1; i > 1; i--)
- BriefMessages[i] = BriefMessages[i-1];
-
- BriefMessages[1].m_pText = msg;
- BriefMessages[1].m_nFlag = flag;
- BriefMessages[1].m_nTime = time;
- BriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[1].m_nNumber[0] = -1;
- BriefMessages[1].m_nNumber[1] = -1;
- BriefMessages[1].m_nNumber[2] = -1;
- BriefMessages[1].m_nNumber[3] = -1;
- BriefMessages[1].m_nNumber[4] = -1;
- BriefMessages[1].m_nNumber[5] = -1;
- BriefMessages[1].m_pString = nil;
- }else{
- BriefMessages[0].m_pText = msg;
- BriefMessages[0].m_nFlag = flag;
- BriefMessages[0].m_nTime = time;
- BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[0].m_nNumber[0] = -1;
- BriefMessages[0].m_nNumber[1] = -1;
- BriefMessages[0].m_nNumber[2] = -1;
- BriefMessages[0].m_nNumber[3] = -1;
- BriefMessages[0].m_nNumber[4] = -1;
- BriefMessages[0].m_nNumber[5] = -1;
- BriefMessages[0].m_pString = nil;
- AddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, nil);
- }
-}
-
-void
-CMessages::ClearMessages()
-{
- for (int32 i = 0; i < NUMBIGMESSAGES; i++) {
- for (int32 j = 0; j < 4; j++) {
- BIGMessages[i].m_Stack[j].m_pText = nil;
- BIGMessages[i].m_Stack[j].m_pString = nil;
- }
- }
- ClearSmallMessagesOnly();
-}
-
-void
-CMessages::ClearSmallMessagesOnly()
-{
- for (int32 i = 0; i < NUMBRIEFMESSAGES; i++) {
- BriefMessages[i].m_pText = nil;
- BriefMessages[i].m_pString = nil;
- }
-}
-
-void
-CMessages::AddBigMessage(wchar *msg, uint32 time, uint16 style)
-{
- wchar outstr[512]; // unused
- WideStringCopy(outstr, msg, 256);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- BIGMessages[style].m_Stack[0].m_pText = msg;
- BIGMessages[style].m_Stack[0].m_nFlag = 0;
- BIGMessages[style].m_Stack[0].m_nTime = time;
- BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BIGMessages[style].m_Stack[0].m_nNumber[0] = -1;
- BIGMessages[style].m_Stack[0].m_nNumber[1] = -1;
- BIGMessages[style].m_Stack[0].m_nNumber[2] = -1;
- BIGMessages[style].m_Stack[0].m_nNumber[3] = -1;
- BIGMessages[style].m_Stack[0].m_nNumber[4] = -1;
- BIGMessages[style].m_Stack[0].m_nNumber[5] = -1;
- BIGMessages[style].m_Stack[0].m_pString = nil;
-}
-void
-CMessages::AddBigMessageQ(wchar *msg, uint32 time, uint16 style)
-{
- wchar outstr[512]; // unused
- WideStringCopy(outstr, msg, 256);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- int32 i = 0;
- while (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)
- i++;
-
- if (i >= 4) return;
-
- BIGMessages[style].m_Stack[i].m_pText = msg;
- BIGMessages[style].m_Stack[i].m_nFlag = 0;
- BIGMessages[style].m_Stack[i].m_nTime = time;
- BIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BIGMessages[style].m_Stack[i].m_nNumber[0] = -1;
- BIGMessages[style].m_Stack[i].m_nNumber[1] = -1;
- BIGMessages[style].m_Stack[i].m_nNumber[2] = -1;
- BIGMessages[style].m_Stack[i].m_nNumber[3] = -1;
- BIGMessages[style].m_Stack[i].m_nNumber[4] = -1;
- BIGMessages[style].m_Stack[i].m_nNumber[5] = -1;
- BIGMessages[style].m_Stack[i].m_pString = nil;
-}
-
-void
-CMessages::AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string)
-{
- int32 i = 0;
- while (i < NUMPREVIOUSBRIEFS) {
- if (PreviousBriefs[i].m_pText == nil)
- break;
- if (PreviousBriefs[i].m_nNumber[0] == n1
- && PreviousBriefs[i].m_nNumber[1] == n2
- && PreviousBriefs[i].m_nNumber[2] == n3
- && PreviousBriefs[i].m_nNumber[3] == n4
- && PreviousBriefs[i].m_nNumber[4] == n5
- && PreviousBriefs[i].m_nNumber[5] == n6
- && PreviousBriefs[i].m_pText == text
- && PreviousBriefs[i].m_pString == string)
- return;
-
- i++;
- }
-
- if (i != 0) {
- if (i == NUMPREVIOUSBRIEFS) i -= 2;
- else i--;
-
- while (i >= 0) {
- PreviousBriefs[i + 1] = PreviousBriefs[i];
- i--;
- }
- }
- PreviousBriefs[0].m_pText = text;
- PreviousBriefs[0].m_nNumber[0] = n1;
- PreviousBriefs[0].m_nNumber[1] = n2;
- PreviousBriefs[0].m_nNumber[2] = n3;
- PreviousBriefs[0].m_nNumber[3] = n4;
- PreviousBriefs[0].m_nNumber[4] = n5;
- PreviousBriefs[0].m_nNumber[5] = n6;
- PreviousBriefs[0].m_pString = string;
-}
-
-void
-CMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *outstr)
-{
- char numStr[10];
- wchar wNumStr[10];
-
- if (str == nil) {
- *outstr = '\0';
- return;
- }
-
- int32 size = GetWideStringLength(str);
-
- int32 i = 0;
-
- for (int32 c = 0; c < size;) {
- if (str[c] == '~' && str[c + 1] == '1' && str[c + 2] == '~') {
- switch (i) {
- case 0: sprintf(numStr, "%d", n1); break;
- case 1: sprintf(numStr, "%d", n2); break;
- case 2: sprintf(numStr, "%d", n3); break;
- case 3: sprintf(numStr, "%d", n4); break;
- case 4: sprintf(numStr, "%d", n5); break;
- case 5: sprintf(numStr, "%d", n6); break;
- }
- i++;
- AsciiToUnicode(numStr, wNumStr);
-
- int j = 0;
- while (wNumStr[j] != '\0')
- *(outstr++) = wNumStr[j++];
-
- c += 3;
- } else {
- *(outstr++) = str[c++];
- }
- }
- *outstr = '\0';
-}
-
-void
-CMessages::InsertStringInString(wchar *str1, wchar *str2)
-{
- wchar tempstr[256];
-
- if (!str1 || !str2) return;
-
- int32 str1_size = GetWideStringLength(str1);
- int32 str2_size = GetWideStringLength(str2);
- int32 total_size = str1_size + str2_size;
-
- wchar *_str1 = str1;
- uint16 i;
- for (i = 0; i < total_size; ) {
- if (*_str1 == '~' && *(_str1 + 1) == 'a' && *(_str1 + 2) == '~') {
- _str1 += 3;
- for (int j = 0; j < str2_size; j++) {
- tempstr[i++] = str2[j];
- }
- } else {
- tempstr[i++] = *(_str1++);
- }
- }
- tempstr[i] = '\0';
-
- for (i = 0; i < total_size; i++)
- str1[i] = tempstr[i];
-
- while (i < 256)
- str1[i++] = '\0';
-}
-
-void
-CMessages::InsertPlayerControlKeysInString(wchar *str)
-{
- uint16 i;
- wchar outstr[256];
- wchar keybuf[256];
-
- if (!str) return;
- uint16 strSize = GetWideStringLength(str);
- memset(keybuf, 0, 256*sizeof(wchar));
-
- wchar *_outstr = outstr;
- for (i = 0; i < strSize;) {
- if (str[i] == '~' && str[i + 1] == 'k' && str[i + 2] == '~') {
- i += 4;
- for (int32 cont = 0; cont < MAX_CONTROLLERACTIONS; cont++) {
- uint16 contSize = GetWideStringLength(ControlsManager.m_aActionNames[cont]);
- if (contSize != 0) {
- if (WideStringCompare(&str[i], ControlsManager.m_aActionNames[cont], contSize)) {
- ControlsManager.GetWideStringOfCommandKeys(cont, keybuf, 256);
- uint16 keybuf_size = GetWideStringLength(keybuf);
- for (uint16 j = 0; j < keybuf_size; j++) {
- *(_outstr++) = keybuf[j];
- keybuf[j] = '\0';
- }
- i += contSize + 1;
- }
- }
- }
- } else {
- *(_outstr++) = str[i++];
- }
- }
- *_outstr = '\0';
-
- for (i = 0; i < GetWideStringLength(outstr); i++)
- str[i] = outstr[i];
-
- while (i < 256)
- str[i++] = '\0';
-}
-
-void
-CMessages::AddMessageWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
-{
- wchar outstr[512]; // unused
- InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- uint16 i = 0;
- while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText)
- i++;
-
- if (i >= NUMBRIEFMESSAGES) return;
-
- BriefMessages[i].m_pText = str;
- BriefMessages[i].m_nFlag = flag;
- BriefMessages[i].m_nTime = time;
- BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[i].m_nNumber[0] = n1;
- BriefMessages[i].m_nNumber[1] = n2;
- BriefMessages[i].m_nNumber[2] = n3;
- BriefMessages[i].m_nNumber[3] = n4;
- BriefMessages[i].m_nNumber[4] = n5;
- BriefMessages[i].m_nNumber[5] = n6;
- BriefMessages[i].m_pString = nil;
- if (i == 0)
- AddToPreviousBriefArray(
- BriefMessages[0].m_pText,
- BriefMessages[0].m_nNumber[0],
- BriefMessages[0].m_nNumber[1],
- BriefMessages[0].m_nNumber[2],
- BriefMessages[0].m_nNumber[3],
- BriefMessages[0].m_nNumber[4],
- BriefMessages[0].m_nNumber[5],
- BriefMessages[0].m_pString);
-}
-
-void
-CMessages::AddMessageJumpQWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
-{
- wchar outstr[512]; // unused
- InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- BriefMessages[0].m_pText = str;
- BriefMessages[0].m_nFlag = flag;
- BriefMessages[0].m_nTime = time;
- BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[0].m_nNumber[0] = n1;
- BriefMessages[0].m_nNumber[1] = n2;
- BriefMessages[0].m_nNumber[2] = n3;
- BriefMessages[0].m_nNumber[3] = n4;
- BriefMessages[0].m_nNumber[4] = n5;
- BriefMessages[0].m_nNumber[5] = n6;
- BriefMessages[0].m_pString = nil;
- AddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);
-}
-
-void
-CMessages::AddMessageSoonWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
-{
- wchar outstr[512]; // unused
- InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- if (BriefMessages[0].m_pText != nil) {
- for (int32 i = NUMBRIEFMESSAGES-1; i > 1; i--)
- BriefMessages[i] = BriefMessages[i-1];
-
- BriefMessages[1].m_pText = str;
- BriefMessages[1].m_nFlag = flag;
- BriefMessages[1].m_nTime = time;
- BriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[1].m_nNumber[0] = n1;
- BriefMessages[1].m_nNumber[1] = n2;
- BriefMessages[1].m_nNumber[2] = n3;
- BriefMessages[1].m_nNumber[3] = n4;
- BriefMessages[1].m_nNumber[4] = n5;
- BriefMessages[1].m_nNumber[5] = n6;
- BriefMessages[1].m_pString = nil;
- } else {
- BriefMessages[0].m_pText = str;
- BriefMessages[0].m_nFlag = flag;
- BriefMessages[0].m_nTime = time;
- BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[0].m_nNumber[0] = n1;
- BriefMessages[0].m_nNumber[1] = n2;
- BriefMessages[0].m_nNumber[2] = n3;
- BriefMessages[0].m_nNumber[3] = n4;
- BriefMessages[0].m_nNumber[4] = n5;
- BriefMessages[0].m_nNumber[5] = n6;
- BriefMessages[0].m_pString = nil;
- AddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);
- }
-}
-
-void
-CMessages::AddBigMessageWithNumber(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
-{
- wchar outstr[512]; // unused
- InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- BIGMessages[style].m_Stack[0].m_pText = str;
- BIGMessages[style].m_Stack[0].m_nFlag = 0;
- BIGMessages[style].m_Stack[0].m_nTime = time;
- BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BIGMessages[style].m_Stack[0].m_nNumber[0] = n1;
- BIGMessages[style].m_Stack[0].m_nNumber[1] = n2;
- BIGMessages[style].m_Stack[0].m_nNumber[2] = n3;
- BIGMessages[style].m_Stack[0].m_nNumber[3] = n4;
- BIGMessages[style].m_Stack[0].m_nNumber[4] = n5;
- BIGMessages[style].m_Stack[0].m_nNumber[5] = n6;
- BIGMessages[style].m_Stack[0].m_pString = nil;
-}
-
-void
-CMessages::AddBigMessageWithNumberQ(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
-{
- wchar outstr[512]; // unused
- InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- int32 i = 0;
-
- while (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)
- i++;
-
- if (i >= 4) return;
-
- BIGMessages[style].m_Stack[i].m_pText = str;
- BIGMessages[style].m_Stack[i].m_nFlag = 0;
- BIGMessages[style].m_Stack[i].m_nTime = time;
- BIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BIGMessages[style].m_Stack[i].m_nNumber[0] = n1;
- BIGMessages[style].m_Stack[i].m_nNumber[1] = n2;
- BIGMessages[style].m_Stack[i].m_nNumber[2] = n3;
- BIGMessages[style].m_Stack[i].m_nNumber[3] = n4;
- BIGMessages[style].m_Stack[i].m_nNumber[4] = n5;
- BIGMessages[style].m_Stack[i].m_nNumber[5] = n6;
- BIGMessages[style].m_Stack[i].m_pString = nil;
-}
-
-void
-CMessages::AddMessageWithString(wchar *text, uint32 time, uint16 flag, wchar *str)
-{
- wchar outstr[512]; // unused
- WideStringCopy(outstr, text, 256);
- InsertStringInString(outstr, str);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- int32 i = 0;
- while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)
- i++;
-
- if (i >= NUMBRIEFMESSAGES) return;
-
- BriefMessages[i].m_pText = text;
- BriefMessages[i].m_nFlag = flag;
- BriefMessages[i].m_nTime = time;
- BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[i].m_nNumber[0] = -1;
- BriefMessages[i].m_nNumber[1] = -1;
- BriefMessages[i].m_nNumber[2] = -1;
- BriefMessages[i].m_nNumber[3] = -1;
- BriefMessages[i].m_nNumber[4] = -1;
- BriefMessages[i].m_nNumber[5] = -1;
- BriefMessages[i].m_pString = str;
- if (i == 0)
- AddToPreviousBriefArray(
- BriefMessages[0].m_pText,
- BriefMessages[0].m_nNumber[0],
- BriefMessages[0].m_nNumber[1],
- BriefMessages[0].m_nNumber[2],
- BriefMessages[0].m_nNumber[3],
- BriefMessages[0].m_nNumber[4],
- BriefMessages[0].m_nNumber[5],
- BriefMessages[0].m_pString);
-}
-
-void
-CMessages::AddMessageJumpQWithString(wchar *text, uint32 time, uint16 flag, wchar *str)
-{
- wchar outstr[512]; // unused
- WideStringCopy(outstr, text, 256);
- InsertStringInString(outstr, str);
- InsertPlayerControlKeysInString(outstr);
- GetWideStringLength(outstr);
-
- BriefMessages[0].m_pText = text;
- BriefMessages[0].m_nFlag = flag;
- BriefMessages[0].m_nTime = time;
- BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- BriefMessages[0].m_nNumber[0] = -1;
- BriefMessages[0].m_nNumber[1] = -1;
- BriefMessages[0].m_nNumber[2] = -1;
- BriefMessages[0].m_nNumber[3] = -1;
- BriefMessages[0].m_nNumber[4] = -1;
- BriefMessages[0].m_nNumber[5] = -1;
- BriefMessages[0].m_pString = str;
- AddToPreviousBriefArray(text, -1, -1, -1, -1, -1, -1, str);
-}
-
-inline bool
-FastWideStringComparison(wchar *str1, wchar *str2)
-{
- while (*str1 == *str2) {
- ++str1;
- ++str2;
- if (!*str1 && !*str2) return true;
- }
- return false;
-}
-
-void
-CMessages::ClearThisPrint(wchar *str)
-{
- bool equal;
-
- do {
- equal = false;
- uint16 i = 0;
- while (i < NUMBRIEFMESSAGES) {
- if (BriefMessages[i].m_pText == nil)
- break;
-
- equal = FastWideStringComparison(str, BriefMessages[i].m_pText);
-
- if (equal) break;
- i++;
- }
-
- if (equal) {
- if (i != 0) {
- BriefMessages[i].m_pText = nil;
- while (i < NUMBRIEFMESSAGES-1) {
- if (BriefMessages[i + 1].m_pText == nil)
- break;
-
- BriefMessages[i] = BriefMessages[i + 1];
- i++;
- }
- BriefMessages[i].m_pText = nil;
- } else {
- BriefMessages[0].m_pText = nil;
- while (i < NUMBRIEFMESSAGES-1) {
- if (BriefMessages[i + 1].m_pText == nil)
- break;
- BriefMessages[i] = BriefMessages[i + 1];
- i++;
- }
- BriefMessages[i].m_pText = nil;
- BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- if (BriefMessages[0].m_pText == nil)
- AddToPreviousBriefArray(
- BriefMessages[0].m_pText,
- BriefMessages[0].m_nNumber[0],
- BriefMessages[0].m_nNumber[1],
- BriefMessages[0].m_nNumber[2],
- BriefMessages[0].m_nNumber[3],
- BriefMessages[0].m_nNumber[4],
- BriefMessages[0].m_nNumber[5],
- BriefMessages[0].m_pString);
- }
- }
- } while (equal);
-}
-
-void
-CMessages::ClearThisBigPrint(wchar *str)
-{
- bool equal;
-
- do {
- uint16 i = 0;
- equal = false;
- uint16 style = 0;
- while (style < NUMBIGMESSAGES)
- {
- if (i >= 4)
- break;
-
- if (CMessages::BIGMessages[style].m_Stack[i].m_pText == nil || equal)
- break;
-
- equal = FastWideStringComparison(str, BIGMessages[style].m_Stack[i].m_pText);
-
- if (!equal && ++i == 4) {
- i = 0;
- style++;
- }
- }
- if (equal) {
- if (i != 0) {
- BIGMessages[style].m_Stack[i].m_pText = nil;
- while (i < 3) {
- if (BIGMessages[style].m_Stack[i + 1].m_pText == nil)
- break;
- BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
- i++;
- }
- BIGMessages[style].m_Stack[i].m_pText = nil;
- } else {
- BIGMessages[style].m_Stack[0].m_pText = 0;
- i = 0;
- while (i < 3) {
- if (BIGMessages[style].m_Stack[i + 1].m_pText == nil)
- break;
- BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
- i++;
- }
- BIGMessages[style].m_Stack[i].m_pText = nil;
- BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
- }
- }
- } while (equal);
-}
-
-void
-CMessages::ClearAllMessagesDisplayedByGame()
-{
- ClearMessages();
- for (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {
- PreviousBriefs[i].m_pText = nil;
- PreviousBriefs[i].m_pString = nil;
- }
- CHud::GetRidOfAllHudMessages();
- CUserDisplay::Pager.ClearMessages();
-}
-
-STARTPATCHES
- InjectHook(0x529310, CMessages::Init, PATCH_JUMP);
- InjectHook(0x529490, CMessages::GetWideStringLength, PATCH_JUMP);
- InjectHook(0x5294B0, CMessages::WideStringCopy, PATCH_JUMP);
- InjectHook(0x529510, CMessages::WideStringCompare, PATCH_JUMP);
- InjectHook(0x529580, CMessages::Process, PATCH_JUMP);
- InjectHook(0x529800, CMessages::Display, PATCH_JUMP);
- InjectHook(0x529900, CMessages::AddMessage, PATCH_JUMP);
- InjectHook(0x529A10, CMessages::AddMessageJumpQ, PATCH_JUMP);
- InjectHook(0x529AF0, CMessages::AddMessageSoon, PATCH_JUMP);
- InjectHook(0x529CE0, CMessages::ClearMessages, PATCH_JUMP);
- InjectHook(0x529E00, CMessages::ClearSmallMessagesOnly, PATCH_JUMP);
- InjectHook(0x529EB0, CMessages::AddBigMessage, PATCH_JUMP);
- InjectHook(0x529F60, CMessages::AddBigMessageQ, PATCH_JUMP);
- InjectHook(0x52A040, CMessages::AddToPreviousBriefArray, PATCH_JUMP);
- InjectHook(0x52A1A0, CMessages::InsertNumberInString, PATCH_JUMP);
- InjectHook(0x52A300, CMessages::InsertStringInString, PATCH_JUMP);
- InjectHook(0x52A490, CMessages::InsertPlayerControlKeysInString, PATCH_JUMP);
- InjectHook(0x52A850, CMessages::AddMessageWithNumber, PATCH_JUMP);
- InjectHook(0x52A9A0, CMessages::AddMessageJumpQWithNumber, PATCH_JUMP);
- InjectHook(0x52AAC0, CMessages::AddMessageSoonWithNumber, PATCH_JUMP);
- InjectHook(0x52AD10, CMessages::AddBigMessageWithNumber, PATCH_JUMP);
- InjectHook(0x52AE00, CMessages::AddBigMessageWithNumberQ, PATCH_JUMP);
- InjectHook(0x52AF30, CMessages::AddMessageWithString, PATCH_JUMP);
- InjectHook(0x52B050, CMessages::AddMessageJumpQWithString, PATCH_JUMP);
- InjectHook(0x52B140, CMessages::ClearThisPrint, PATCH_JUMP);
- InjectHook(0x52B3C0, CMessages::ClearThisBigPrint, PATCH_JUMP);
- InjectHook(0x52B670, CMessages::ClearAllMessagesDisplayedByGame, PATCH_JUMP);
-ENDPATCHES
+#define DIRECTINPUT_VERSION 0x0800
+#include "dinput.h"
+
+#include "common.h"
+#include "patcher.h"
+#include "Messages.h"
+#include "RwHelper.h"
+#include "Hud.h"
+#include "User.h"
+#include "Timer.h"
+#include "Text.h"
+
+#include "ControllerConfig.h"
+
+tMessage(&CMessages::BriefMessages)[NUMBRIEFMESSAGES] = *(tMessage(*)[NUMBRIEFMESSAGES])*(uintptr*)0x8786E0;
+tPreviousBrief(&CMessages::PreviousBriefs)[NUMPREVIOUSBRIEFS] = *(tPreviousBrief(*)[NUMPREVIOUSBRIEFS])*(uintptr*)0x713C08;
+tBigMessage(&CMessages::BIGMessages)[NUMBIGMESSAGES] = *(tBigMessage(*)[NUMBIGMESSAGES])*(uintptr*)0x773628;
+char CMessages::PreviousMissionTitle[16]; // unused
+
+void
+CMessages::Init()
+{
+ ClearMessages();
+
+ for (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {
+ PreviousBriefs[i].m_pText = nil;
+ PreviousBriefs[i].m_pString = nil;
+ }
+}
+
+uint16
+CMessages::GetWideStringLength(wchar *src)
+{
+ uint16 length = 0;
+ while (*(src++)) length++;
+ return length;
+}
+
+void
+CMessages::WideStringCopy(wchar *dst, wchar *src, uint16 size)
+{
+ int32 i = 0;
+ if (src) {
+ while (i < size - 1) {
+ if (!src[i]) break;
+ dst[i] = src[i];
+ i++;
+ }
+ } else {
+ while (i < size - 1)
+ dst[i++] = '\0';
+ }
+ dst[i] = '\0';
+}
+
+bool
+CMessages::WideStringCompare(wchar *str1, wchar *str2, uint16 size)
+{
+ uint16 len1 = GetWideStringLength(str1);
+ uint16 len2 = GetWideStringLength(str2);
+ if (len1 != len2 && (len1 < size || len2 < size))
+ return false;
+
+ for (int32 i = 0; i < size; i++) {
+ if (!str1[i])
+ break;
+
+ if (str1[i] != str2[i])
+ return false;
+ }
+ return true;
+}
+
+void
+CMessages::Process()
+{
+ for (int32 style = 0; style < 6; style++) {
+ if (BIGMessages[style].m_Stack[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BIGMessages[style].m_Stack[0].m_nTime + BIGMessages[style].m_Stack[0].m_nStartTime) {
+ BIGMessages[style].m_Stack[0].m_pText = nil;
+
+ int32 i = 0;
+ while (i < 3) {
+ if (BIGMessages[style].m_Stack[i + 1].m_pText == nil) break;
+ BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
+ i++;
+ }
+
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ }
+ }
+
+ if (BriefMessages[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BriefMessages[0].m_nTime + BriefMessages[0].m_nStartTime) {
+ BriefMessages[0].m_pText = nil;
+ int32 i = 0;
+ while (i < NUMBRIEFMESSAGES-1) {
+ if (BriefMessages[i + 1].m_pText == nil)
+ break;
+
+ BriefMessages[i] = BriefMessages[i + 1];
+ i++;
+ }
+ CMessages::BriefMessages[i].m_pText = nil;
+ CMessages::BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ if (BriefMessages[0].m_pText != nil)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+ }
+}
+
+void
+CMessages::Display()
+{
+ wchar outstr[256];
+
+ DefinedState();
+
+ for (int32 i = 0; i < NUMBIGMESSAGES; i++) {
+ InsertNumberInString(
+ BIGMessages[i].m_Stack[0].m_pText,
+ BIGMessages[i].m_Stack[0].m_nNumber[0],
+ BIGMessages[i].m_Stack[0].m_nNumber[1],
+ BIGMessages[i].m_Stack[0].m_nNumber[2],
+ BIGMessages[i].m_Stack[0].m_nNumber[3],
+ BIGMessages[i].m_Stack[0].m_nNumber[4],
+ BIGMessages[i].m_Stack[0].m_nNumber[5],
+ outstr);
+ InsertStringInString(outstr, BIGMessages[i].m_Stack[0].m_pString);
+ InsertPlayerControlKeysInString(outstr);
+ CHud::SetBigMessage(outstr, i);
+ }
+
+ InsertNumberInString(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ outstr);
+ InsertStringInString(outstr, BriefMessages[0].m_pString);
+ InsertPlayerControlKeysInString(outstr);
+ CHud::SetMessage(outstr);
+}
+
+void
+CMessages::AddMessage(wchar *msg, uint32 time, uint16 flag)
+{
+ wchar outstr[512]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+ while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)
+ i++;
+ if (i >= NUMBRIEFMESSAGES) return;
+
+ BriefMessages[i].m_pText = msg;
+ BriefMessages[i].m_nFlag = flag;
+ BriefMessages[i].m_nTime = time;
+ BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[i].m_nNumber[0] = -1;
+ BriefMessages[i].m_nNumber[1] = -1;
+ BriefMessages[i].m_nNumber[2] = -1;
+ BriefMessages[i].m_nNumber[3] = -1;
+ BriefMessages[i].m_nNumber[4] = -1;
+ BriefMessages[i].m_nNumber[5] = -1;
+ BriefMessages[i].m_pString = nil;
+ if (i == 0)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+}
+
+void
+CMessages::AddMessageJumpQ(wchar *msg, uint32 time, uint16 flag)
+{
+ wchar outstr[512]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BriefMessages[0].m_pText = msg;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = -1;
+ BriefMessages[0].m_nNumber[1] = -1;
+ BriefMessages[0].m_nNumber[2] = -1;
+ BriefMessages[0].m_nNumber[3] = -1;
+ BriefMessages[0].m_nNumber[4] = -1;
+ BriefMessages[0].m_nNumber[5] = -1;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, 0);
+}
+
+void
+CMessages::AddMessageSoon(wchar *msg, uint32 time, uint16 flag)
+{
+ wchar outstr[512]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ if (BriefMessages[0].m_pText != nil) {
+ for (int i = NUMBRIEFMESSAGES-1; i > 1; i--)
+ BriefMessages[i] = BriefMessages[i-1];
+
+ BriefMessages[1].m_pText = msg;
+ BriefMessages[1].m_nFlag = flag;
+ BriefMessages[1].m_nTime = time;
+ BriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[1].m_nNumber[0] = -1;
+ BriefMessages[1].m_nNumber[1] = -1;
+ BriefMessages[1].m_nNumber[2] = -1;
+ BriefMessages[1].m_nNumber[3] = -1;
+ BriefMessages[1].m_nNumber[4] = -1;
+ BriefMessages[1].m_nNumber[5] = -1;
+ BriefMessages[1].m_pString = nil;
+ }else{
+ BriefMessages[0].m_pText = msg;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = -1;
+ BriefMessages[0].m_nNumber[1] = -1;
+ BriefMessages[0].m_nNumber[2] = -1;
+ BriefMessages[0].m_nNumber[3] = -1;
+ BriefMessages[0].m_nNumber[4] = -1;
+ BriefMessages[0].m_nNumber[5] = -1;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, nil);
+ }
+}
+
+void
+CMessages::ClearMessages()
+{
+ for (int32 i = 0; i < NUMBIGMESSAGES; i++) {
+ for (int32 j = 0; j < 4; j++) {
+ BIGMessages[i].m_Stack[j].m_pText = nil;
+ BIGMessages[i].m_Stack[j].m_pString = nil;
+ }
+ }
+ ClearSmallMessagesOnly();
+}
+
+void
+CMessages::ClearSmallMessagesOnly()
+{
+ for (int32 i = 0; i < NUMBRIEFMESSAGES; i++) {
+ BriefMessages[i].m_pText = nil;
+ BriefMessages[i].m_pString = nil;
+ }
+}
+
+void
+CMessages::AddBigMessage(wchar *msg, uint32 time, uint16 style)
+{
+ wchar outstr[512]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BIGMessages[style].m_Stack[0].m_pText = msg;
+ BIGMessages[style].m_Stack[0].m_nFlag = 0;
+ BIGMessages[style].m_Stack[0].m_nTime = time;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[0].m_nNumber[0] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[1] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[2] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[3] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[4] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[5] = -1;
+ BIGMessages[style].m_Stack[0].m_pString = nil;
+}
+void
+CMessages::AddBigMessageQ(wchar *msg, uint32 time, uint16 style)
+{
+ wchar outstr[512]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+ while (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)
+ i++;
+
+ if (i >= 4) return;
+
+ BIGMessages[style].m_Stack[i].m_pText = msg;
+ BIGMessages[style].m_Stack[i].m_nFlag = 0;
+ BIGMessages[style].m_Stack[i].m_nTime = time;
+ BIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[i].m_nNumber[0] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[1] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[2] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[3] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[4] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[5] = -1;
+ BIGMessages[style].m_Stack[i].m_pString = nil;
+}
+
+void
+CMessages::AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string)
+{
+ int32 i = 0;
+ while (i < NUMPREVIOUSBRIEFS) {
+ if (PreviousBriefs[i].m_pText == nil)
+ break;
+ if (PreviousBriefs[i].m_nNumber[0] == n1
+ && PreviousBriefs[i].m_nNumber[1] == n2
+ && PreviousBriefs[i].m_nNumber[2] == n3
+ && PreviousBriefs[i].m_nNumber[3] == n4
+ && PreviousBriefs[i].m_nNumber[4] == n5
+ && PreviousBriefs[i].m_nNumber[5] == n6
+ && PreviousBriefs[i].m_pText == text
+ && PreviousBriefs[i].m_pString == string)
+ return;
+
+ i++;
+ }
+
+ if (i != 0) {
+ if (i == NUMPREVIOUSBRIEFS) i -= 2;
+ else i--;
+
+ while (i >= 0) {
+ PreviousBriefs[i + 1] = PreviousBriefs[i];
+ i--;
+ }
+ }
+ PreviousBriefs[0].m_pText = text;
+ PreviousBriefs[0].m_nNumber[0] = n1;
+ PreviousBriefs[0].m_nNumber[1] = n2;
+ PreviousBriefs[0].m_nNumber[2] = n3;
+ PreviousBriefs[0].m_nNumber[3] = n4;
+ PreviousBriefs[0].m_nNumber[4] = n5;
+ PreviousBriefs[0].m_nNumber[5] = n6;
+ PreviousBriefs[0].m_pString = string;
+}
+
+void
+CMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *outstr)
+{
+ char numStr[10];
+ wchar wNumStr[10];
+
+ if (str == nil) {
+ *outstr = '\0';
+ return;
+ }
+
+ int32 size = GetWideStringLength(str);
+
+ int32 i = 0;
+
+ for (int32 c = 0; c < size;) {
+ if (str[c] == '~' && str[c + 1] == '1' && str[c + 2] == '~') {
+ switch (i) {
+ case 0: sprintf(numStr, "%d", n1); break;
+ case 1: sprintf(numStr, "%d", n2); break;
+ case 2: sprintf(numStr, "%d", n3); break;
+ case 3: sprintf(numStr, "%d", n4); break;
+ case 4: sprintf(numStr, "%d", n5); break;
+ case 5: sprintf(numStr, "%d", n6); break;
+ }
+ i++;
+ AsciiToUnicode(numStr, wNumStr);
+
+ int j = 0;
+ while (wNumStr[j] != '\0')
+ *(outstr++) = wNumStr[j++];
+
+ c += 3;
+ } else {
+ *(outstr++) = str[c++];
+ }
+ }
+ *outstr = '\0';
+}
+
+void
+CMessages::InsertStringInString(wchar *str1, wchar *str2)
+{
+ wchar tempstr[256];
+
+ if (!str1 || !str2) return;
+
+ int32 str1_size = GetWideStringLength(str1);
+ int32 str2_size = GetWideStringLength(str2);
+ int32 total_size = str1_size + str2_size;
+
+ wchar *_str1 = str1;
+ uint16 i;
+ for (i = 0; i < total_size; ) {
+ if (*_str1 == '~' && *(_str1 + 1) == 'a' && *(_str1 + 2) == '~') {
+ _str1 += 3;
+ for (int j = 0; j < str2_size; j++) {
+ tempstr[i++] = str2[j];
+ }
+ } else {
+ tempstr[i++] = *(_str1++);
+ }
+ }
+ tempstr[i] = '\0';
+
+ for (i = 0; i < total_size; i++)
+ str1[i] = tempstr[i];
+
+ while (i < 256)
+ str1[i++] = '\0';
+}
+
+void
+CMessages::InsertPlayerControlKeysInString(wchar *str)
+{
+ uint16 i;
+ wchar outstr[256];
+ wchar keybuf[256];
+
+ if (!str) return;
+ uint16 strSize = GetWideStringLength(str);
+ memset(keybuf, 0, 256*sizeof(wchar));
+
+ wchar *_outstr = outstr;
+ for (i = 0; i < strSize;) {
+ if (str[i] == '~' && str[i + 1] == 'k' && str[i + 2] == '~') {
+ i += 4;
+ for (int32 cont = 0; cont < MAX_CONTROLLERACTIONS; cont++) {
+ uint16 contSize = GetWideStringLength(ControlsManager.m_aActionNames[cont]);
+ if (contSize != 0) {
+ if (WideStringCompare(&str[i], ControlsManager.m_aActionNames[cont], contSize)) {
+ ControlsManager.GetWideStringOfCommandKeys(cont, keybuf, 256);
+ uint16 keybuf_size = GetWideStringLength(keybuf);
+ for (uint16 j = 0; j < keybuf_size; j++) {
+ *(_outstr++) = keybuf[j];
+ keybuf[j] = '\0';
+ }
+ i += contSize + 1;
+ }
+ }
+ }
+ } else {
+ *(_outstr++) = str[i++];
+ }
+ }
+ *_outstr = '\0';
+
+ for (i = 0; i < GetWideStringLength(outstr); i++)
+ str[i] = outstr[i];
+
+ while (i < 256)
+ str[i++] = '\0';
+}
+
+void
+CMessages::AddMessageWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[512]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ uint16 i = 0;
+ while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText)
+ i++;
+
+ if (i >= NUMBRIEFMESSAGES) return;
+
+ BriefMessages[i].m_pText = str;
+ BriefMessages[i].m_nFlag = flag;
+ BriefMessages[i].m_nTime = time;
+ BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[i].m_nNumber[0] = n1;
+ BriefMessages[i].m_nNumber[1] = n2;
+ BriefMessages[i].m_nNumber[2] = n3;
+ BriefMessages[i].m_nNumber[3] = n4;
+ BriefMessages[i].m_nNumber[4] = n5;
+ BriefMessages[i].m_nNumber[5] = n6;
+ BriefMessages[i].m_pString = nil;
+ if (i == 0)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+}
+
+void
+CMessages::AddMessageJumpQWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[512]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BriefMessages[0].m_pText = str;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = n1;
+ BriefMessages[0].m_nNumber[1] = n2;
+ BriefMessages[0].m_nNumber[2] = n3;
+ BriefMessages[0].m_nNumber[3] = n4;
+ BriefMessages[0].m_nNumber[4] = n5;
+ BriefMessages[0].m_nNumber[5] = n6;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);
+}
+
+void
+CMessages::AddMessageSoonWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[512]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ if (BriefMessages[0].m_pText != nil) {
+ for (int32 i = NUMBRIEFMESSAGES-1; i > 1; i--)
+ BriefMessages[i] = BriefMessages[i-1];
+
+ BriefMessages[1].m_pText = str;
+ BriefMessages[1].m_nFlag = flag;
+ BriefMessages[1].m_nTime = time;
+ BriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[1].m_nNumber[0] = n1;
+ BriefMessages[1].m_nNumber[1] = n2;
+ BriefMessages[1].m_nNumber[2] = n3;
+ BriefMessages[1].m_nNumber[3] = n4;
+ BriefMessages[1].m_nNumber[4] = n5;
+ BriefMessages[1].m_nNumber[5] = n6;
+ BriefMessages[1].m_pString = nil;
+ } else {
+ BriefMessages[0].m_pText = str;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = n1;
+ BriefMessages[0].m_nNumber[1] = n2;
+ BriefMessages[0].m_nNumber[2] = n3;
+ BriefMessages[0].m_nNumber[3] = n4;
+ BriefMessages[0].m_nNumber[4] = n5;
+ BriefMessages[0].m_nNumber[5] = n6;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);
+ }
+}
+
+void
+CMessages::AddBigMessageWithNumber(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[512]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BIGMessages[style].m_Stack[0].m_pText = str;
+ BIGMessages[style].m_Stack[0].m_nFlag = 0;
+ BIGMessages[style].m_Stack[0].m_nTime = time;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[0].m_nNumber[0] = n1;
+ BIGMessages[style].m_Stack[0].m_nNumber[1] = n2;
+ BIGMessages[style].m_Stack[0].m_nNumber[2] = n3;
+ BIGMessages[style].m_Stack[0].m_nNumber[3] = n4;
+ BIGMessages[style].m_Stack[0].m_nNumber[4] = n5;
+ BIGMessages[style].m_Stack[0].m_nNumber[5] = n6;
+ BIGMessages[style].m_Stack[0].m_pString = nil;
+}
+
+void
+CMessages::AddBigMessageWithNumberQ(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[512]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+
+ while (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)
+ i++;
+
+ if (i >= 4) return;
+
+ BIGMessages[style].m_Stack[i].m_pText = str;
+ BIGMessages[style].m_Stack[i].m_nFlag = 0;
+ BIGMessages[style].m_Stack[i].m_nTime = time;
+ BIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[i].m_nNumber[0] = n1;
+ BIGMessages[style].m_Stack[i].m_nNumber[1] = n2;
+ BIGMessages[style].m_Stack[i].m_nNumber[2] = n3;
+ BIGMessages[style].m_Stack[i].m_nNumber[3] = n4;
+ BIGMessages[style].m_Stack[i].m_nNumber[4] = n5;
+ BIGMessages[style].m_Stack[i].m_nNumber[5] = n6;
+ BIGMessages[style].m_Stack[i].m_pString = nil;
+}
+
+void
+CMessages::AddMessageWithString(wchar *text, uint32 time, uint16 flag, wchar *str)
+{
+ wchar outstr[512]; // unused
+ WideStringCopy(outstr, text, 256);
+ InsertStringInString(outstr, str);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+ while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)
+ i++;
+
+ if (i >= NUMBRIEFMESSAGES) return;
+
+ BriefMessages[i].m_pText = text;
+ BriefMessages[i].m_nFlag = flag;
+ BriefMessages[i].m_nTime = time;
+ BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[i].m_nNumber[0] = -1;
+ BriefMessages[i].m_nNumber[1] = -1;
+ BriefMessages[i].m_nNumber[2] = -1;
+ BriefMessages[i].m_nNumber[3] = -1;
+ BriefMessages[i].m_nNumber[4] = -1;
+ BriefMessages[i].m_nNumber[5] = -1;
+ BriefMessages[i].m_pString = str;
+ if (i == 0)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+}
+
+void
+CMessages::AddMessageJumpQWithString(wchar *text, uint32 time, uint16 flag, wchar *str)
+{
+ wchar outstr[512]; // unused
+ WideStringCopy(outstr, text, 256);
+ InsertStringInString(outstr, str);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BriefMessages[0].m_pText = text;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = -1;
+ BriefMessages[0].m_nNumber[1] = -1;
+ BriefMessages[0].m_nNumber[2] = -1;
+ BriefMessages[0].m_nNumber[3] = -1;
+ BriefMessages[0].m_nNumber[4] = -1;
+ BriefMessages[0].m_nNumber[5] = -1;
+ BriefMessages[0].m_pString = str;
+ AddToPreviousBriefArray(text, -1, -1, -1, -1, -1, -1, str);
+}
+
+inline bool
+FastWideStringComparison(wchar *str1, wchar *str2)
+{
+ while (*str1 == *str2) {
+ ++str1;
+ ++str2;
+ if (!*str1 && !*str2) return true;
+ }
+ return false;
+}
+
+void
+CMessages::ClearThisPrint(wchar *str)
+{
+ bool equal;
+
+ do {
+ equal = false;
+ uint16 i = 0;
+ while (i < NUMBRIEFMESSAGES) {
+ if (BriefMessages[i].m_pText == nil)
+ break;
+
+ equal = FastWideStringComparison(str, BriefMessages[i].m_pText);
+
+ if (equal) break;
+ i++;
+ }
+
+ if (equal) {
+ if (i != 0) {
+ BriefMessages[i].m_pText = nil;
+ while (i < NUMBRIEFMESSAGES-1) {
+ if (BriefMessages[i + 1].m_pText == nil)
+ break;
+
+ BriefMessages[i] = BriefMessages[i + 1];
+ i++;
+ }
+ BriefMessages[i].m_pText = nil;
+ } else {
+ BriefMessages[0].m_pText = nil;
+ while (i < NUMBRIEFMESSAGES-1) {
+ if (BriefMessages[i + 1].m_pText == nil)
+ break;
+ BriefMessages[i] = BriefMessages[i + 1];
+ i++;
+ }
+ BriefMessages[i].m_pText = nil;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ if (BriefMessages[0].m_pText == nil)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+ }
+ }
+ } while (equal);
+}
+
+void
+CMessages::ClearThisBigPrint(wchar *str)
+{
+ bool equal;
+
+ do {
+ uint16 i = 0;
+ equal = false;
+ uint16 style = 0;
+ while (style < NUMBIGMESSAGES)
+ {
+ if (i >= 4)
+ break;
+
+ if (CMessages::BIGMessages[style].m_Stack[i].m_pText == nil || equal)
+ break;
+
+ equal = FastWideStringComparison(str, BIGMessages[style].m_Stack[i].m_pText);
+
+ if (!equal && ++i == 4) {
+ i = 0;
+ style++;
+ }
+ }
+ if (equal) {
+ if (i != 0) {
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ while (i < 3) {
+ if (BIGMessages[style].m_Stack[i + 1].m_pText == nil)
+ break;
+ BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
+ i++;
+ }
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ } else {
+ BIGMessages[style].m_Stack[0].m_pText = 0;
+ i = 0;
+ while (i < 3) {
+ if (BIGMessages[style].m_Stack[i + 1].m_pText == nil)
+ break;
+ BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
+ i++;
+ }
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ }
+ }
+ } while (equal);
+}
+
+void
+CMessages::ClearAllMessagesDisplayedByGame()
+{
+ ClearMessages();
+ for (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {
+ PreviousBriefs[i].m_pText = nil;
+ PreviousBriefs[i].m_pString = nil;
+ }
+ CHud::GetRidOfAllHudMessages();
+ CUserDisplay::Pager.ClearMessages();
+}
+
+STARTPATCHES
+ InjectHook(0x529310, CMessages::Init, PATCH_JUMP);
+ InjectHook(0x529490, CMessages::GetWideStringLength, PATCH_JUMP);
+ InjectHook(0x5294B0, CMessages::WideStringCopy, PATCH_JUMP);
+ InjectHook(0x529510, CMessages::WideStringCompare, PATCH_JUMP);
+ InjectHook(0x529580, CMessages::Process, PATCH_JUMP);
+ InjectHook(0x529800, CMessages::Display, PATCH_JUMP);
+ InjectHook(0x529900, CMessages::AddMessage, PATCH_JUMP);
+ InjectHook(0x529A10, CMessages::AddMessageJumpQ, PATCH_JUMP);
+ InjectHook(0x529AF0, CMessages::AddMessageSoon, PATCH_JUMP);
+ InjectHook(0x529CE0, CMessages::ClearMessages, PATCH_JUMP);
+ InjectHook(0x529E00, CMessages::ClearSmallMessagesOnly, PATCH_JUMP);
+ InjectHook(0x529EB0, CMessages::AddBigMessage, PATCH_JUMP);
+ InjectHook(0x529F60, CMessages::AddBigMessageQ, PATCH_JUMP);
+ InjectHook(0x52A040, CMessages::AddToPreviousBriefArray, PATCH_JUMP);
+ InjectHook(0x52A1A0, CMessages::InsertNumberInString, PATCH_JUMP);
+ InjectHook(0x52A300, CMessages::InsertStringInString, PATCH_JUMP);
+ InjectHook(0x52A490, CMessages::InsertPlayerControlKeysInString, PATCH_JUMP);
+ InjectHook(0x52A850, CMessages::AddMessageWithNumber, PATCH_JUMP);
+ InjectHook(0x52A9A0, CMessages::AddMessageJumpQWithNumber, PATCH_JUMP);
+ InjectHook(0x52AAC0, CMessages::AddMessageSoonWithNumber, PATCH_JUMP);
+ InjectHook(0x52AD10, CMessages::AddBigMessageWithNumber, PATCH_JUMP);
+ InjectHook(0x52AE00, CMessages::AddBigMessageWithNumberQ, PATCH_JUMP);
+ InjectHook(0x52AF30, CMessages::AddMessageWithString, PATCH_JUMP);
+ InjectHook(0x52B050, CMessages::AddMessageJumpQWithString, PATCH_JUMP);
+ InjectHook(0x52B140, CMessages::ClearThisPrint, PATCH_JUMP);
+ InjectHook(0x52B3C0, CMessages::ClearThisBigPrint, PATCH_JUMP);
+ InjectHook(0x52B670, CMessages::ClearAllMessagesDisplayedByGame, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/text/Pager.cpp b/src/text/Pager.cpp
index 9e484c29..5c6b3ee2 100644
--- a/src/text/Pager.cpp
+++ b/src/text/Pager.cpp
@@ -1,194 +1,194 @@
-#include "common.h"
-#include "patcher.h"
-#include "Pager.h"
-#include "Timer.h"
-#include "Messages.h"
-#include "Hud.h"
-#include "Camera.h"
-
-void
-CPager::Init()
-{
- ClearMessages();
- m_nNumDisplayLetters = 8;
-}
-
-void
-CPager::Process()
-{
- if (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) {
- m_messages[0].m_pText = nil;
- uint16 i = 0;
- while (i < NUMPAGERMESSAGES-1) {
- if (m_messages[i + 1].m_pText == nil) break;
- m_messages[i] = m_messages[i + 1];
- i++;
- }
- m_messages[i].m_pText = nil;
- if (m_messages[0].m_pText != nil)
- CMessages::AddToPreviousBriefArray(
- m_messages[0].m_pText,
- m_messages[0].m_nNumber[0],
- m_messages[0].m_nNumber[1],
- m_messages[0].m_nNumber[2],
- m_messages[0].m_nNumber[3],
- m_messages[0].m_nNumber[4],
- m_messages[0].m_nNumber[5],
- 0);
- }
- Display();
- 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]) {
- RestartCurrentMessage();
- } else {
- if (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) {
- m_messages[0].m_nCurrentPosition++;
- m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
- }
- }
- }
-}
-
-void
-CPager::Display()
-{
- wchar outstr1[256];
- wchar outstr2[260];
-
- wchar *pText = m_messages[0].m_pText;
- uint16 i = 0;
- if (pText != nil) {
- CMessages::InsertNumberInString(
- pText,
- m_messages[0].m_nNumber[0],
- m_messages[0].m_nNumber[1],
- m_messages[0].m_nNumber[2],
- m_messages[0].m_nNumber[3],
- m_messages[0].m_nNumber[4],
- m_messages[0].m_nNumber[5],
- outstr1);
- for (; i < m_nNumDisplayLetters; i++) {
- int pos = m_messages[0].m_nCurrentPosition + i;
- if (pos >= 0) {
- if (!outstr1[pos]) break;
-
- outstr2[i] = outstr1[pos];
- } else {
- outstr2[i] = ' ';
- }
- }
- }
- outstr2[i] = '\0';
- CHud::SetPagerMessage(outstr2);
-}
-
-void
-CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5)
-{
- uint16 size = CMessages::GetWideStringLength(str);
- for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
- if (m_messages[i].m_pText) {
- if (m_messages[i].m_nPriority >= priority)
- continue;
-
- for (int j = NUMPAGERMESSAGES-1; j > i; j--)
- m_messages[j] = m_messages[j-1];
-
- }
- m_messages[i].m_pText = str;
- m_messages[i].m_nSpeedMs = speed;
- m_messages[i].m_nPriority = priority;
- m_messages[i].field_10 = a5;
- m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
- m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
- m_messages[i].m_nStringLength = size;
- m_messages[i].m_nNumber[0] = -1;
- m_messages[i].m_nNumber[1] = -1;
- m_messages[i].m_nNumber[2] = -1;
- m_messages[i].m_nNumber[3] = -1;
- m_messages[i].m_nNumber[4] = -1;
- m_messages[i].m_nNumber[5] = -1;
-
- if (i == 0)
- CMessages::AddToPreviousBriefArray(
- m_messages[0].m_pText,
- m_messages[0].m_nNumber[0],
- m_messages[0].m_nNumber[1],
- m_messages[0].m_nNumber[2],
- m_messages[0].m_nNumber[3],
- m_messages[0].m_nNumber[4],
- m_messages[0].m_nNumber[5],
- nil);
- return;
- }
-}
-
-void
-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];
-
- CMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr);
- uint16 size = CMessages::GetWideStringLength(nstr);
- for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
- if (m_messages[i].m_pText) {
- if (m_messages[i].m_nPriority >= priority)
- continue;
-
- for (int j = NUMPAGERMESSAGES-1; j > i; j--)
- m_messages[j] = m_messages[j - 1];
-
- }
- m_messages[i].m_pText = str;
- m_messages[i].m_nSpeedMs = speed;
- m_messages[i].m_nPriority = priority;
- m_messages[i].field_10 = a11;
- m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
- m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
- m_messages[i].m_nStringLength = size;
- m_messages[i].m_nNumber[0] = n1;
- m_messages[i].m_nNumber[1] = n2;
- m_messages[i].m_nNumber[2] = n3;
- m_messages[i].m_nNumber[3] = n4;
- m_messages[i].m_nNumber[4] = n5;
- m_messages[i].m_nNumber[5] = n6;
-
- if (i == 0)
- CMessages::AddToPreviousBriefArray(
- m_messages[0].m_pText,
- m_messages[0].m_nNumber[0],
- m_messages[0].m_nNumber[1],
- m_messages[0].m_nNumber[2],
- m_messages[0].m_nNumber[3],
- m_messages[0].m_nNumber[4],
- m_messages[0].m_nNumber[5],
- nil);
- return;
- }
-}
-
-void
-CPager::ClearMessages()
-{
- for (int32 i = 0; i < NUMPAGERMESSAGES; i++)
- m_messages[i].m_pText = nil;
-}
-
-void
-CPager::RestartCurrentMessage()
-{
- if (m_messages[0].m_pText != nil) {
- m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
- m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
- }
-}
-
-STARTPATCHES
- InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP);
- InjectHook(0x52B740, &CPager::Process, PATCH_JUMP);
- InjectHook(0x52B890, &CPager::Display, PATCH_JUMP);
- InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP);
- InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP);
- InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP);
- InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP);
+#include "common.h"
+#include "patcher.h"
+#include "Pager.h"
+#include "Timer.h"
+#include "Messages.h"
+#include "Hud.h"
+#include "Camera.h"
+
+void
+CPager::Init()
+{
+ ClearMessages();
+ m_nNumDisplayLetters = 8;
+}
+
+void
+CPager::Process()
+{
+ if (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) {
+ m_messages[0].m_pText = nil;
+ uint16 i = 0;
+ while (i < NUMPAGERMESSAGES-1) {
+ if (m_messages[i + 1].m_pText == nil) break;
+ m_messages[i] = m_messages[i + 1];
+ i++;
+ }
+ m_messages[i].m_pText = nil;
+ if (m_messages[0].m_pText != nil)
+ CMessages::AddToPreviousBriefArray(
+ m_messages[0].m_pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ 0);
+ }
+ Display();
+ 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]) {
+ RestartCurrentMessage();
+ } else {
+ if (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) {
+ m_messages[0].m_nCurrentPosition++;
+ m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
+ }
+ }
+ }
+}
+
+void
+CPager::Display()
+{
+ wchar outstr1[256];
+ wchar outstr2[260];
+
+ wchar *pText = m_messages[0].m_pText;
+ uint16 i = 0;
+ if (pText != nil) {
+ CMessages::InsertNumberInString(
+ pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ outstr1);
+ for (; i < m_nNumDisplayLetters; i++) {
+ int pos = m_messages[0].m_nCurrentPosition + i;
+ if (pos >= 0) {
+ if (!outstr1[pos]) break;
+
+ outstr2[i] = outstr1[pos];
+ } else {
+ outstr2[i] = ' ';
+ }
+ }
+ }
+ outstr2[i] = '\0';
+ CHud::SetPagerMessage(outstr2);
+}
+
+void
+CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5)
+{
+ uint16 size = CMessages::GetWideStringLength(str);
+ for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
+ if (m_messages[i].m_pText) {
+ if (m_messages[i].m_nPriority >= priority)
+ continue;
+
+ for (int j = NUMPAGERMESSAGES-1; j > i; j--)
+ m_messages[j] = m_messages[j-1];
+
+ }
+ m_messages[i].m_pText = str;
+ m_messages[i].m_nSpeedMs = speed;
+ m_messages[i].m_nPriority = priority;
+ m_messages[i].field_10 = a5;
+ m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
+ m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
+ m_messages[i].m_nStringLength = size;
+ m_messages[i].m_nNumber[0] = -1;
+ m_messages[i].m_nNumber[1] = -1;
+ m_messages[i].m_nNumber[2] = -1;
+ m_messages[i].m_nNumber[3] = -1;
+ m_messages[i].m_nNumber[4] = -1;
+ m_messages[i].m_nNumber[5] = -1;
+
+ if (i == 0)
+ CMessages::AddToPreviousBriefArray(
+ m_messages[0].m_pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ nil);
+ return;
+ }
+}
+
+void
+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];
+
+ CMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr);
+ uint16 size = CMessages::GetWideStringLength(nstr);
+ for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
+ if (m_messages[i].m_pText) {
+ if (m_messages[i].m_nPriority >= priority)
+ continue;
+
+ for (int j = NUMPAGERMESSAGES-1; j > i; j--)
+ m_messages[j] = m_messages[j - 1];
+
+ }
+ m_messages[i].m_pText = str;
+ m_messages[i].m_nSpeedMs = speed;
+ m_messages[i].m_nPriority = priority;
+ m_messages[i].field_10 = a11;
+ m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
+ m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
+ m_messages[i].m_nStringLength = size;
+ m_messages[i].m_nNumber[0] = n1;
+ m_messages[i].m_nNumber[1] = n2;
+ m_messages[i].m_nNumber[2] = n3;
+ m_messages[i].m_nNumber[3] = n4;
+ m_messages[i].m_nNumber[4] = n5;
+ m_messages[i].m_nNumber[5] = n6;
+
+ if (i == 0)
+ CMessages::AddToPreviousBriefArray(
+ m_messages[0].m_pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ nil);
+ return;
+ }
+}
+
+void
+CPager::ClearMessages()
+{
+ for (int32 i = 0; i < NUMPAGERMESSAGES; i++)
+ m_messages[i].m_pText = nil;
+}
+
+void
+CPager::RestartCurrentMessage()
+{
+ if (m_messages[0].m_pText != nil) {
+ m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
+ m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
+ }
+}
+
+STARTPATCHES
+ InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP);
+ InjectHook(0x52B740, &CPager::Process, PATCH_JUMP);
+ InjectHook(0x52B890, &CPager::Display, PATCH_JUMP);
+ InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP);
+ InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP);
+ InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP);
+ InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/text/Pager.h b/src/text/Pager.h
index 1719e726..a628be6f 100644
--- a/src/text/Pager.h
+++ b/src/text/Pager.h
@@ -1,28 +1,28 @@
-#pragma once
-
-struct PagerMessage {
- wchar *m_pText;
- uint16 m_nSpeedMs;
- int16 m_nCurrentPosition;
- uint16 m_nStringLength;
- uint16 m_nPriority;
- uint32 m_nTimeToChangePosition;
- int16 field_10;
- int32 m_nNumber[6];
-};
-
-#define NUMPAGERMESSAGES 8
-
-class CPager
-{
- int16 m_nNumDisplayLetters;
- PagerMessage m_messages[NUMPAGERMESSAGES];
-public:
- void Init();
- void Process();
- void Display();
- 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 ClearMessages();
- void RestartCurrentMessage();
+#pragma once
+
+struct PagerMessage {
+ wchar *m_pText;
+ uint16 m_nSpeedMs;
+ int16 m_nCurrentPosition;
+ uint16 m_nStringLength;
+ uint16 m_nPriority;
+ uint32 m_nTimeToChangePosition;
+ int16 field_10;
+ int32 m_nNumber[6];
+};
+
+#define NUMPAGERMESSAGES 8
+
+class CPager
+{
+ int16 m_nNumDisplayLetters;
+ PagerMessage m_messages[NUMPAGERMESSAGES];
+public:
+ void Init();
+ void Process();
+ void Display();
+ 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 ClearMessages();
+ void RestartCurrentMessage();
}; \ No newline at end of file
diff --git a/src/text/Text.cpp b/src/text/Text.cpp
index d0cdb310..5fc19f12 100644
--- a/src/text/Text.cpp
+++ b/src/text/Text.cpp
@@ -1,324 +1,324 @@
-#include "common.h"
-#include "patcher.h"
-#include "FileMgr.h"
-#include "Frontend.h"
-#include "Messages.h"
-#include "Text.h"
-
-static wchar WideErrorString[25];
-
-CText &TheText = *(CText*)0x941520;
-
-CText::CText(void)
-{
- encoding = 'e';
- memset(WideErrorString, 0, sizeof(WideErrorString));
-}
-
-void
-CText::Load(void)
-{
- uint8 *filedata;
- char filename[32], type[4];
- int length;
- int offset, sectlen;
-
- Unload();
- filedata = new uint8[0x40000];
-
- CFileMgr::SetDir("TEXT");
- switch(CMenuManager::m_PrefsLanguage){
- case LANGUAGE_AMERICAN:
- sprintf(filename, "AMERICAN.GXT");
- break;
- case LANGUAGE_FRENCH:
- sprintf(filename, "FRENCH.GXT");
- break;
- case LANGUAGE_GERMAN:
- sprintf(filename, "GERMAN.GXT");
- break;
- case LANGUAGE_ITALIAN:
- sprintf(filename, "ITALIAN.GXT");
- break;
- case LANGUAGE_SPANISH:
- sprintf(filename, "SPANISH.GXT");
- break;
-#ifdef MORE_LANGUAGES
- case LANGUAGE_RUSSIAN:
- sprintf(filename, "RUSSIAN.GXT");
- break;
-#endif
- }
-
- length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
- CFileMgr::SetDir("");
-
- offset = 0;
- while(offset < length){
- type[0] = filedata[offset++];
- type[1] = filedata[offset++];
- type[2] = filedata[offset++];
- type[3] = filedata[offset++];
- sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
- (int)filedata[offset+1]<<8 | (int)filedata[offset+0];
- offset += 4;
- if(sectlen != 0){
- if(strncmp(type, "TKEY", 4) == 0)
- keyArray.Load(sectlen, filedata, &offset);
- else if(strncmp(type, "TDAT", 4) == 0)
- data.Load(sectlen, filedata, &offset);
- else
- offset += sectlen;
- }
- }
-
- keyArray.Update(data.chars);
-
- delete[] filedata;
-}
-
-void
-CText::Unload(void)
-{
- CMessages::ClearAllMessagesDisplayedByGame();
- data.Unload();
- keyArray.Unload();
-}
-
-wchar*
-CText::Get(const char *key)
-{
- return keyArray.Search(key);
-}
-
-wchar UpperCaseTable[128] = {
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
- 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
- 150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
- 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
- 149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182,
- 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
- 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
- 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
- 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
- 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
- 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
- 249, 250, 251, 252, 253, 254, 255
-};
-
-wchar FrenchUpperCaseTable[128] = {
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
- 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
- 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,
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
- 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
- 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
- 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
- 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
- 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
- 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
- 253, 254, 255
-};
-
-wchar
-CText::GetUpperCase(wchar c)
-{
- switch (encoding)
- {
- case 'e':
- if (c >= 'a' && c <= 'z')
- return c - 32;
- break;
- case 'f':
- if (c >= 'a' && c <= 'z')
- return c - 32;
-
- if (c >= 128 && c <= 255)
- return FrenchUpperCaseTable[c-128];
- break;
- case 'g':
- case 'i':
- case 's':
- if (c >= 'a' && c <= 'z')
- return c - 32;
-
- if (c >= 128 && c <= 255)
- return UpperCaseTable[c-128];
- break;
- default:
- break;
- }
- return c;
-}
-
-void
-CText::UpperCase(wchar *s)
-{
- while(*s){
- *s = GetUpperCase(*s);
- s++;
- }
-}
-
-
-void
-CKeyArray::Load(uint32 length, uint8 *data, int *offset)
-{
- uint32 i;
- uint8 *rawbytes;
-
- numEntries = length / sizeof(CKeyEntry);
- entries = new CKeyEntry[numEntries];
- rawbytes = (uint8*)entries;
-
- for(i = 0; i < length; i++)
- rawbytes[i] = data[(*offset)++];
-}
-
-void
-CKeyArray::Unload(void)
-{
- delete[] entries;
- entries = nil;
- numEntries = 0;
-}
-
-void
-CKeyArray::Update(wchar *chars)
-{
- int i;
- for(i = 0; i < numEntries; i++)
- entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value);
-}
-
-CKeyEntry*
-CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
-{
- int mid;
- int diff;
-
- if(low > high)
- return nil;
-
- mid = (low + high)/2;
- diff = strcmp(key, entries[mid].key);
- if(diff == 0)
- return &entries[mid];
- if(diff < 0)
- return BinarySearch(key, entries, low, mid-1);
- if(diff > 0)
- return BinarySearch(key, entries, mid+1, high);
- return nil;
-}
-
-wchar*
-CKeyArray::Search(const char *key)
-{
- CKeyEntry *found;
- char errstr[25];
- int i;
-
- found = BinarySearch(key, entries, 0, numEntries-1);
- if(found)
- return found->value;
- sprintf(errstr, "%s missing", key);
- for(i = 0; i < 25; i++)
- WideErrorString[i] = errstr[i];
- return WideErrorString;
-}
-
-
-void
-CData::Load(uint32 length, uint8 *data, int *offset)
-{
- uint32 i;
- uint8 *rawbytes;
-
- numChars = length / sizeof(wchar);
- chars = new wchar[numChars];
- rawbytes = (uint8*)chars;
-
- for(i = 0; i < length; i++)
- rawbytes[i] = data[(*offset)++];
-}
-
-void
-CData::Unload(void)
-{
- delete[] chars;
- chars = nil;
- numChars = 0;
-}
-
-void
-AsciiToUnicode(const char *src, wchar *dst)
-{
- while((*dst++ = *src++) != '\0');
-}
-
-char*
-UnicodeToAscii(wchar *src)
-{
- static char aStr[256];
- int len;
- for(len = 0; *src != '\0' && len < 256-1; len++, src++)
- if(*src < 128)
- aStr[len] = *src;
- else
- aStr[len] = '#';
- aStr[len] = '\0';
- return aStr;
-}
-
-char*
-UnicodeToAsciiForSaveLoad(wchar *src)
-{
- static char aStr[256];
- int len;
- for(len = 0; *src != '\0' && len < 256-1; len++, src++)
- if(*src < 256)
- aStr[len] = *src;
- else
- aStr[len] = '#';
- aStr[len] = '\0';
- return aStr;
-}
-
-void
-UnicodeStrcpy(wchar *dst, const wchar *src)
-{
- while((*dst++ = *src++) != '\0');
-}
-
-int
-UnicodeStrlen(const wchar *str)
-{
- int len;
- for(len = 0; *str != '\0'; len++, str++);
- return len;
-}
-
-void
-TextCopy(wchar *dst, const wchar *src)
-{
- while((*dst++ = *src++) != '\0');
-}
-
-
-STARTPATCHES
- InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
- InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
- InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
- InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP);
- InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP);
-
- InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
- InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
- InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
- InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
- InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
-
- InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
- InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
-ENDPATCHES
+#include "common.h"
+#include "patcher.h"
+#include "FileMgr.h"
+#include "Frontend.h"
+#include "Messages.h"
+#include "Text.h"
+
+static wchar WideErrorString[25];
+
+CText &TheText = *(CText*)0x941520;
+
+CText::CText(void)
+{
+ encoding = 'e';
+ memset(WideErrorString, 0, sizeof(WideErrorString));
+}
+
+void
+CText::Load(void)
+{
+ uint8 *filedata;
+ char filename[32], type[4];
+ int length;
+ int offset, sectlen;
+
+ Unload();
+ filedata = new uint8[0x40000];
+
+ CFileMgr::SetDir("TEXT");
+ switch(CMenuManager::m_PrefsLanguage){
+ case LANGUAGE_AMERICAN:
+ sprintf(filename, "AMERICAN.GXT");
+ break;
+ case LANGUAGE_FRENCH:
+ sprintf(filename, "FRENCH.GXT");
+ break;
+ case LANGUAGE_GERMAN:
+ sprintf(filename, "GERMAN.GXT");
+ break;
+ case LANGUAGE_ITALIAN:
+ sprintf(filename, "ITALIAN.GXT");
+ break;
+ case LANGUAGE_SPANISH:
+ sprintf(filename, "SPANISH.GXT");
+ break;
+#ifdef MORE_LANGUAGES
+ case LANGUAGE_RUSSIAN:
+ sprintf(filename, "RUSSIAN.GXT");
+ break;
+#endif
+ }
+
+ length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
+ CFileMgr::SetDir("");
+
+ offset = 0;
+ while(offset < length){
+ type[0] = filedata[offset++];
+ type[1] = filedata[offset++];
+ type[2] = filedata[offset++];
+ type[3] = filedata[offset++];
+ sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
+ (int)filedata[offset+1]<<8 | (int)filedata[offset+0];
+ offset += 4;
+ if(sectlen != 0){
+ if(strncmp(type, "TKEY", 4) == 0)
+ keyArray.Load(sectlen, filedata, &offset);
+ else if(strncmp(type, "TDAT", 4) == 0)
+ data.Load(sectlen, filedata, &offset);
+ else
+ offset += sectlen;
+ }
+ }
+
+ keyArray.Update(data.chars);
+
+ delete[] filedata;
+}
+
+void
+CText::Unload(void)
+{
+ CMessages::ClearAllMessagesDisplayedByGame();
+ data.Unload();
+ keyArray.Unload();
+}
+
+wchar*
+CText::Get(const char *key)
+{
+ return keyArray.Search(key);
+}
+
+wchar UpperCaseTable[128] = {
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255
+};
+
+wchar FrenchUpperCaseTable[128] = {
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 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,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
+ 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
+ 253, 254, 255
+};
+
+wchar
+CText::GetUpperCase(wchar c)
+{
+ switch (encoding)
+ {
+ case 'e':
+ if (c >= 'a' && c <= 'z')
+ return c - 32;
+ break;
+ case 'f':
+ if (c >= 'a' && c <= 'z')
+ return c - 32;
+
+ if (c >= 128 && c <= 255)
+ return FrenchUpperCaseTable[c-128];
+ break;
+ case 'g':
+ case 'i':
+ case 's':
+ if (c >= 'a' && c <= 'z')
+ return c - 32;
+
+ if (c >= 128 && c <= 255)
+ return UpperCaseTable[c-128];
+ break;
+ default:
+ break;
+ }
+ return c;
+}
+
+void
+CText::UpperCase(wchar *s)
+{
+ while(*s){
+ *s = GetUpperCase(*s);
+ s++;
+ }
+}
+
+
+void
+CKeyArray::Load(uint32 length, uint8 *data, int *offset)
+{
+ uint32 i;
+ uint8 *rawbytes;
+
+ numEntries = length / sizeof(CKeyEntry);
+ entries = new CKeyEntry[numEntries];
+ rawbytes = (uint8*)entries;
+
+ for(i = 0; i < length; i++)
+ rawbytes[i] = data[(*offset)++];
+}
+
+void
+CKeyArray::Unload(void)
+{
+ delete[] entries;
+ entries = nil;
+ numEntries = 0;
+}
+
+void
+CKeyArray::Update(wchar *chars)
+{
+ int i;
+ for(i = 0; i < numEntries; i++)
+ entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value);
+}
+
+CKeyEntry*
+CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
+{
+ int mid;
+ int diff;
+
+ if(low > high)
+ return nil;
+
+ mid = (low + high)/2;
+ diff = strcmp(key, entries[mid].key);
+ if(diff == 0)
+ return &entries[mid];
+ if(diff < 0)
+ return BinarySearch(key, entries, low, mid-1);
+ if(diff > 0)
+ return BinarySearch(key, entries, mid+1, high);
+ return nil;
+}
+
+wchar*
+CKeyArray::Search(const char *key)
+{
+ CKeyEntry *found;
+ char errstr[25];
+ int i;
+
+ found = BinarySearch(key, entries, 0, numEntries-1);
+ if(found)
+ return found->value;
+ sprintf(errstr, "%s missing", key);
+ for(i = 0; i < 25; i++)
+ WideErrorString[i] = errstr[i];
+ return WideErrorString;
+}
+
+
+void
+CData::Load(uint32 length, uint8 *data, int *offset)
+{
+ uint32 i;
+ uint8 *rawbytes;
+
+ numChars = length / sizeof(wchar);
+ chars = new wchar[numChars];
+ rawbytes = (uint8*)chars;
+
+ for(i = 0; i < length; i++)
+ rawbytes[i] = data[(*offset)++];
+}
+
+void
+CData::Unload(void)
+{
+ delete[] chars;
+ chars = nil;
+ numChars = 0;
+}
+
+void
+AsciiToUnicode(const char *src, wchar *dst)
+{
+ while((*dst++ = *src++) != '\0');
+}
+
+char*
+UnicodeToAscii(wchar *src)
+{
+ static char aStr[256];
+ int len;
+ for(len = 0; *src != '\0' && len < 256-1; len++, src++)
+ if(*src < 128)
+ aStr[len] = *src;
+ else
+ aStr[len] = '#';
+ aStr[len] = '\0';
+ return aStr;
+}
+
+char*
+UnicodeToAsciiForSaveLoad(wchar *src)
+{
+ static char aStr[256];
+ int len;
+ for(len = 0; *src != '\0' && len < 256-1; len++, src++)
+ if(*src < 256)
+ aStr[len] = *src;
+ else
+ aStr[len] = '#';
+ aStr[len] = '\0';
+ return aStr;
+}
+
+void
+UnicodeStrcpy(wchar *dst, const wchar *src)
+{
+ while((*dst++ = *src++) != '\0');
+}
+
+int
+UnicodeStrlen(const wchar *str)
+{
+ int len;
+ for(len = 0; *str != '\0'; len++, str++);
+ return len;
+}
+
+void
+TextCopy(wchar *dst, const wchar *src)
+{
+ while((*dst++ = *src++) != '\0');
+}
+
+
+STARTPATCHES
+ InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
+ InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
+ InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
+ InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP);
+ InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP);
+
+ InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
+ InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
+ InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
+ InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
+ InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
+
+ InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
+ InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 0c8f0dd4..1c0d673e 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -182,17 +182,17 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_weaponDoorTimerRight = m_weaponDoorTimerLeft;
if(GetModelIndex() == MI_DODO){
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
CMatrix mat1;
mat1.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
CMatrix mat2(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
mat1.GetPosition() += CVector(mat2.GetPosition().x + 0.1f, 0.0f, mat2.GetPosition().z);
mat1.UpdateRW();
}else if(GetModelIndex() == MI_MIAMI_SPARROW || GetModelIndex() == MI_MIAMI_RCRAIDER){
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
}else if(GetModelIndex() == MI_RHINO){
bExplosionProof = true;
bBulletProof = true;
diff --git a/src/vehicles/Bike.h b/src/vehicles/Bike.h
new file mode 100644
index 00000000..4e7e5a0e
--- /dev/null
+++ b/src/vehicles/Bike.h
@@ -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
+}; \ No newline at end of file
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index 6d584017..9c7cbb4f 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -94,7 +94,7 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos)
pos = *RwMatrixGetPos(RwFrameGetLTM(m_aBoatNodes[component]));
}
-RxObjSpace3DVertex KeepWaterOutVertices[4];
+RwIm3DVertex KeepWaterOutVertices[4];
RwImVertexIndex KeepWaterOutIndices[6];
void
@@ -103,7 +103,7 @@ CBoat::Render()
CMatrix matrix;
if (m_aBoatNodes[1] != nil) {
- matrix.Attach(&m_aBoatNodes[1]->modelling);
+ matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[1]));
CVector pos = matrix.GetPosition();
matrix.SetRotateZ(m_fMovingHiRotation);
@@ -111,7 +111,7 @@ CBoat::Render()
matrix.UpdateRW();
if (CVehicle::bWheelsOnlyCheat) {
- RpAtomicRenderMacro((RpAtomic*)GetFirstObject(m_aBoatNodes[1]));
+ RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[1]));
}
}
m_fMovingHiRotation += 0.05f;
@@ -130,47 +130,23 @@ CBoat::Render()
KeepWaterOutIndices[5] = 3;
switch (GetModelIndex()) {
case MI_SPEEDER:
- KeepWaterOutVertices[0].objVertex.x = -1.15f;
- KeepWaterOutVertices[0].objVertex.y = 3.61f;
- KeepWaterOutVertices[0].objVertex.z = 1.03f;
- KeepWaterOutVertices[1].objVertex.x = 1.15f;
- 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;
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.15f, 3.61f, 1.03f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.15f, 3.61f, 1.03f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.15f, 0.06f, 1.03f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.15f, 0.06f, 1.03f);
break;
case MI_REEFER:
- KeepWaterOutVertices[2].objVertex.x = -1.9f;
- KeepWaterOutVertices[2].objVertex.y = 2.83f;
- KeepWaterOutVertices[2].objVertex.z = 1.0f;
- KeepWaterOutVertices[3].objVertex.x = 1.9f;
- 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;
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.9f, 2.83f, 1.0f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.9f, 2.83f, 1.0f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.66f, -4.48f, 0.83f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.66f, -4.48f, 0.83f);
break;
case MI_PREDATOR:
default:
- KeepWaterOutVertices[0].objVertex.x = -1.45f;
- KeepWaterOutVertices[0].objVertex.y = 1.9f;
- KeepWaterOutVertices[0].objVertex.z = 0.96f;
- KeepWaterOutVertices[1].objVertex.x = 1.45f;
- 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;
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.45f, 1.9f, 0.96f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.45f, 1.9f, 0.96f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.45f, -3.75f, 0.96f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.45f, -3.75f, 0.96f);
break;
}
KeepWaterOutVertices[0].u = 0.0f;
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 4639f3e1..c7be3674 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -238,6 +238,7 @@ public:
bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; }
bool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; }
bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; }
+ bool IsBike(void) { return m_vehType == VEHICLE_TYPE_BIKE; }
void FlyingControl(eFlightModel flightModel);
void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
diff --git a/src/weapons/Explosion.cpp b/src/weapons/Explosion.cpp
index e99dc918..3d00052a 100644
--- a/src/weapons/Explosion.cpp
+++ b/src/weapons/Explosion.cpp
@@ -1,11 +1,29 @@
#include "common.h"
#include "patcher.h"
+#include "Automobile.h"
+#include "Bike.h"
+#include "Camera.h"
+#include "Coronas.h"
#include "DMAudio.h"
+#include "Entity.h"
+#include "EventList.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;
@@ -15,26 +33,25 @@ CExplosion::Initialise()
debug("Initialising CExplosion...\n");
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
gaExplosion[i].m_ExplosionType = EXPLOSION_GRENADE;
- gaExplosion[i].m_vecPosition.x = 0.0f;
- gaExplosion[i].m_vecPosition.y = 0.0f;
- gaExplosion[i].m_vecPosition.z = 0.0f;
+ gaExplosion[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
gaExplosion[i].m_fRadius = 1.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_pVictimEntity = nil;
gaExplosion[i].m_fStopTime = 0.0f;
- gaExplosion[i].m_bActive = false;
- gaExplosion[i].m_nStartTime = 0;
- gaExplosion[i].field_34 = 0;
+ gaExplosion[i].m_nIteration = 0;
+ gaExplosion[i].m_fStartTime = 0.0f;
+ gaExplosion[i].m_bIsBoat = false;
}
AudioHandle = DMAudio.CreateEntity(AUDIOTYPE_EXPLOSION, (void*)1);
if (AudioHandle >= 0)
- DMAudio.SetEntityStatus(AudioHandle, 1);
+ DMAudio.SetEntityStatus(AudioHandle, true);
debug("CExplosion ready\n");
}
-void CExplosion::Shutdown()
+void
+CExplosion::Shutdown()
{
debug("Shutting down CExplosion...\n");
if (AudioHandle >= 0) {
@@ -44,21 +61,22 @@ void CExplosion::Shutdown()
debug("CExplosion shut down\n");
}
+int8
+CExplosion::GetExplosionActiveCounter(uint8 id)
+{
+ return gaExplosion[id].m_nActiveCounter;
+}
+
void
-CExplosion::RemoveAllExplosionsInArea(CVector pos, float radius)
+CExplosion::ResetExplosionActiveCounter(uint8 id)
{
- 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;
- }
- }
+ gaExplosion[id].m_nActiveCounter = 0;
}
-int8
-CExplosion::GetExplosionActiveCounter(uint8 id)
+uint8
+CExplosion::GetExplosionType(uint8 id)
{
- return gaExplosion[id].m_bActiveCounter;
+ return gaExplosion[id].m_ExplosionType;
}
CVector *
@@ -67,24 +85,357 @@ CExplosion::GetExplosionPosition(uint8 id)
return &gaExplosion[id].m_vecPosition;
}
-uint8
-CExplosion::GetExplosionType(uint8 id)
+bool
+CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime)
{
- return gaExplosion[id].m_ExplosionType;
+ 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::ResetExplosionActiveCounter(uint8 id)
+CExplosion::Update()
{
- gaExplosion[id].m_bActiveCounter = 0;
+ 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 a1, float x1, float x2, float y1, float y2, float z1, float z2)
+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++) {
- if (gaExplosion[i].m_bActive) {
- if (a1 == gaExplosion[i].m_ExplosionType) {
+ if (gaExplosion[i].m_nIteration != 0) {
+ if (type == gaExplosion[i].m_ExplosionType) {
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.z >= z1 && gaExplosion[i].m_vecPosition.z <= z2)
@@ -97,13 +448,26 @@ CExplosion::TestForExplosionInArea(eExplosionType a1, float x1, float x2, float
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
InjectHook(0x559030, &CExplosion::Initialise, PATCH_JUMP);
InjectHook(0x559100, &CExplosion::Shutdown, PATCH_JUMP);
- InjectHook(0x55AD40, &CExplosion::RemoveAllExplosionsInArea, 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(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(0x55AD40, &CExplosion::RemoveAllExplosionsInArea, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/weapons/Explosion.h b/src/weapons/Explosion.h
index e6ef9496..45e2d5bb 100644
--- a/src/weapons/Explosion.h
+++ b/src/weapons/Explosion.h
@@ -26,25 +26,24 @@ class CExplosion
CEntity *m_pCreatorEntity;
CEntity *m_pVictimEntity;
float m_fStopTime;
- bool m_bActive;
- int8 m_bActiveCounter;
- int32 m_nStartTime;
+ uint8 m_nIteration;
+ uint8 m_nActiveCounter;
+ float m_fStartTime;
uint32 m_nParticlesExpireTime;
float m_fPower;
- int32 field_34;
- int32 field_38;
+ bool m_bIsBoat;
+ float m_fZshift;
public:
static void Initialise();
static void Shutdown();
- static void AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type,
- const CVector &pos, uint32);
-
static int8 GetExplosionActiveCounter(uint8 id);
- static CVector *GetExplosionPosition(uint8 id);
- static uint8 GetExplosionType(uint8 id);
static void ResetExplosionActiveCounter(uint8 id);
- static void RemoveAllExplosionsInArea(CVector, float);
- static bool TestForExplosionInArea(eExplosionType, float, float, float, float, float, float);
+ static uint8 GetExplosionType(uint8 id);
+ 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]; \ No newline at end of file
+extern CExplosion (&gaExplosion)[NUM_EXPLOSIONS]; \ No newline at end of file
diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h
index dafb48db..a4ea369a 100644
--- a/src/weapons/ProjectileInfo.h
+++ b/src/weapons/ProjectileInfo.h
@@ -1,32 +1,32 @@
-#pragma once
-
-class CEntity;
-class CObject;
-class CProjectile;
-enum eWeaponType;
-
-class CProjectileInfo
-{
-public:
- eWeaponType m_eWeaponType;
- CEntity* m_pSource;
- uint32 m_nExplosionTime;
- bool m_bInUse;
- CVector m_vecPos;
-
-public:
- static CProjectileInfo* GetProjectileInfo(int32 id);
- static CProjectile* (&ms_apProjectile)[NUM_PROJECTILES];
-
- static void Initialise();
- static void Shutdown();
- static bool AddProjectile(CEntity *ped, eWeaponType weapon, CVector pos, float speed);
- static void RemoveProjectile(CProjectileInfo *info, CProjectile *projectile);
- static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);
- static bool RemoveIfThisIsAProjectile(CObject *pObject);
- static void RemoveAllProjectiles();
- static void Update();
- static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
-};
-
+#pragma once
+
+class CEntity;
+class CObject;
+class CProjectile;
+enum eWeaponType;
+
+class CProjectileInfo
+{
+public:
+ eWeaponType m_eWeaponType;
+ CEntity* m_pSource;
+ uint32 m_nExplosionTime;
+ bool m_bInUse;
+ CVector m_vecPos;
+
+public:
+ static CProjectileInfo* GetProjectileInfo(int32 id);
+ static CProjectile* (&ms_apProjectile)[NUM_PROJECTILES];
+
+ static void Initialise();
+ static void Shutdown();
+ static bool AddProjectile(CEntity *ped, eWeaponType weapon, CVector pos, float speed);
+ static void RemoveProjectile(CProjectileInfo *info, CProjectile *projectile);
+ static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);
+ static bool RemoveIfThisIsAProjectile(CObject *pObject);
+ static void RemoveAllProjectiles();
+ static void Update();
+ static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
+};
+
extern CProjectileInfo (&gaProjectileInfo)[NUM_PROJECTILES]; \ No newline at end of file