diff options
-rw-r--r-- | .github/workflows/re3_msvc_amd64.yml | 2 | ||||
-rw-r--r-- | .vscode/settings.json | 2 | ||||
-rw-r--r-- | codewarrior/re3.mcp.xml | 6 | ||||
-rw-r--r-- | gamefiles/TEXT/american.gxt | bin | 220570 -> 220642 bytes | |||
-rw-r--r-- | gamefiles/TEXT/french.gxt | bin | 246544 -> 246616 bytes | |||
-rw-r--r-- | gamefiles/TEXT/german.gxt | bin | 242608 -> 242680 bytes | |||
-rw-r--r-- | gamefiles/TEXT/italian.gxt | bin | 241978 -> 242050 bytes | |||
-rwxr-xr-x | gamefiles/TEXT/polish.gxt | bin | 241610 -> 241682 bytes | |||
-rw-r--r-- | gamefiles/TEXT/russian.gxt | bin | 222396 -> 222468 bytes | |||
-rw-r--r-- | gamefiles/TEXT/spanish.gxt | bin | 235542 -> 235614 bytes | |||
-rw-r--r-- | premake5.lua | 13 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/animation/AnimBlendAssociation.h | 2 | ||||
-rw-r--r-- | src/animation/AnimBlendClumpData.cpp | 1 | ||||
-rw-r--r-- | src/audio/AudioCollision.cpp | 409 | ||||
-rw-r--r-- | src/audio/AudioCollision.h | 23 | ||||
-rw-r--r-- | src/audio/AudioLogic.cpp | 663 | ||||
-rw-r--r-- | src/audio/AudioManager.cpp | 66 | ||||
-rw-r--r-- | src/audio/AudioManager.h | 507 | ||||
-rw-r--r-- | src/audio/MusicManager.cpp | 20 | ||||
-rw-r--r-- | src/audio/PolRadio.cpp | 6 | ||||
-rw-r--r-- | src/audio/oal/stream.cpp | 3 | ||||
-rw-r--r-- | src/audio/sampman.h | 110 | ||||
-rw-r--r-- | src/audio/sampman_miles.cpp | 146 | ||||
-rw-r--r-- | src/audio/sampman_oal.cpp | 53 | ||||
-rw-r--r-- | src/control/AutoPilot.cpp | 58 | ||||
-rw-r--r-- | src/control/CarCtrl.cpp | 2 | ||||
-rw-r--r-- | src/control/Garages.cpp | 118 | ||||
-rw-r--r-- | src/control/Garages.h | 22 | ||||
-rw-r--r-- | src/control/Phones.cpp | 45 | ||||
-rw-r--r-- | src/control/Pickups.cpp | 33 | ||||
-rw-r--r-- | src/control/Script.cpp | 28 | ||||
-rw-r--r-- | src/control/Script.h | 1 | ||||
-rw-r--r-- | src/control/Script5.cpp | 36 | ||||
-rw-r--r-- | src/control/Script6.cpp | 4 | ||||
-rw-r--r-- | src/core/Fire.cpp | 2 | ||||
-rw-r--r-- | src/core/Frontend.cpp | 98 | ||||
-rw-r--r-- | src/core/Frontend.h | 29 | ||||
-rw-r--r-- | src/core/Game.cpp | 6 | ||||
-rw-r--r-- | src/core/IniFile.cpp | 4 | ||||
-rw-r--r-- | src/core/IniFile.h | 3 | ||||
-rw-r--r-- | src/core/MenuScreensCustom.cpp | 27 | ||||
-rw-r--r-- | src/core/Pools.cpp | 10 | ||||
-rw-r--r-- | src/core/Zones.cpp | 78 | ||||
-rw-r--r-- | src/core/config.h | 191 | ||||
-rw-r--r-- | src/core/re3.cpp | 135 | ||||
-rw-r--r-- | src/entities/Entity.cpp | 4 | ||||
-rw-r--r-- | src/extras/frontendoption.h | 2 | ||||
-rw-r--r-- | src/extras/ini.h | 761 | ||||
-rw-r--r-- | src/extras/ini_parser.hpp | 333 | ||||
-rw-r--r-- | src/objects/ParticleObject.cpp | 109 | ||||
-rw-r--r-- | src/peds/Ped.cpp | 28 | ||||
-rw-r--r-- | src/peds/PedFight.cpp | 8 | ||||
-rw-r--r-- | src/peds/PedIK.h | 2 | ||||
-rw-r--r-- | src/peds/PlayerPed.cpp | 17 | ||||
-rw-r--r-- | src/peds/Population.cpp | 8 | ||||
-rw-r--r-- | src/renderer/2dEffect.h (renamed from src/render/2dEffect.h) | 0 | ||||
-rw-r--r-- | src/renderer/Antennas.cpp (renamed from src/render/Antennas.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Antennas.h (renamed from src/render/Antennas.h) | 0 | ||||
-rw-r--r-- | src/renderer/Clouds.cpp (renamed from src/render/Clouds.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Clouds.h (renamed from src/render/Clouds.h) | 0 | ||||
-rw-r--r-- | src/renderer/Console.cpp (renamed from src/render/Console.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Console.h (renamed from src/render/Console.h) | 0 | ||||
-rw-r--r-- | src/renderer/Coronas.cpp (renamed from src/render/Coronas.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Coronas.h (renamed from src/render/Coronas.h) | 0 | ||||
-rw-r--r-- | src/renderer/Credits.cpp (renamed from src/render/Credits.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Credits.h (renamed from src/render/Credits.h) | 0 | ||||
-rw-r--r-- | src/renderer/Draw.cpp (renamed from src/render/Draw.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Draw.h (renamed from src/render/Draw.h) | 0 | ||||
-rw-r--r-- | src/renderer/Fluff.cpp (renamed from src/render/Fluff.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Fluff.h (renamed from src/render/Fluff.h) | 0 | ||||
-rw-r--r-- | src/renderer/Font.cpp (renamed from src/render/Font.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Font.h (renamed from src/render/Font.h) | 0 | ||||
-rw-r--r-- | src/renderer/Glass.cpp (renamed from src/render/Glass.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Glass.h (renamed from src/render/Glass.h) | 0 | ||||
-rw-r--r-- | src/renderer/Hud.cpp (renamed from src/render/Hud.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Hud.h (renamed from src/render/Hud.h) | 0 | ||||
-rw-r--r-- | src/renderer/Instance.cpp (renamed from src/render/Instance.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Instance.h (renamed from src/render/Instance.h) | 0 | ||||
-rw-r--r-- | src/renderer/Lines.cpp (renamed from src/render/Lines.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Lines.h (renamed from src/render/Lines.h) | 0 | ||||
-rw-r--r-- | src/renderer/MBlur.cpp (renamed from src/render/MBlur.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/MBlur.h (renamed from src/render/MBlur.h) | 0 | ||||
-rw-r--r-- | src/renderer/Particle.cpp (renamed from src/render/Particle.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Particle.h (renamed from src/render/Particle.h) | 0 | ||||
-rw-r--r-- | src/renderer/ParticleMgr.cpp (renamed from src/render/ParticleMgr.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/ParticleMgr.h (renamed from src/render/ParticleMgr.h) | 0 | ||||
-rw-r--r-- | src/renderer/ParticleType.h (renamed from src/render/ParticleType.h) | 0 | ||||
-rw-r--r-- | src/renderer/PlayerSkin.cpp (renamed from src/render/PlayerSkin.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/PlayerSkin.h (renamed from src/render/PlayerSkin.h) | 0 | ||||
-rw-r--r-- | src/renderer/PointLights.cpp (renamed from src/render/PointLights.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/PointLights.h (renamed from src/render/PointLights.h) | 0 | ||||
-rw-r--r-- | src/renderer/RenderBuffer.cpp (renamed from src/render/RenderBuffer.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/RenderBuffer.h (renamed from src/render/RenderBuffer.h) | 0 | ||||
-rw-r--r-- | src/renderer/Renderer.cpp (renamed from src/render/Renderer.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Renderer.h (renamed from src/render/Renderer.h) | 0 | ||||
-rw-r--r-- | src/renderer/Rubbish.cpp (renamed from src/render/Rubbish.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Rubbish.h (renamed from src/render/Rubbish.h) | 0 | ||||
-rw-r--r-- | src/renderer/Shadows.cpp (renamed from src/render/Shadows.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Shadows.h (renamed from src/render/Shadows.h) | 0 | ||||
-rw-r--r-- | src/renderer/Skidmarks.cpp (renamed from src/render/Skidmarks.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Skidmarks.h (renamed from src/render/Skidmarks.h) | 0 | ||||
-rw-r--r-- | src/renderer/SpecialFX.cpp (renamed from src/render/SpecialFX.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/SpecialFX.h (renamed from src/render/SpecialFX.h) | 0 | ||||
-rw-r--r-- | src/renderer/Sprite.cpp (renamed from src/render/Sprite.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Sprite.h (renamed from src/render/Sprite.h) | 0 | ||||
-rw-r--r-- | src/renderer/Sprite2d.cpp (renamed from src/render/Sprite2d.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Sprite2d.h (renamed from src/render/Sprite2d.h) | 0 | ||||
-rw-r--r-- | src/renderer/TexList.cpp (renamed from src/render/TexList.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/TexList.h (renamed from src/render/TexList.h) | 0 | ||||
-rw-r--r-- | src/renderer/Timecycle.cpp (renamed from src/render/Timecycle.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Timecycle.h (renamed from src/render/Timecycle.h) | 0 | ||||
-rw-r--r-- | src/renderer/WaterCannon.cpp (renamed from src/render/WaterCannon.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/WaterCannon.h (renamed from src/render/WaterCannon.h) | 0 | ||||
-rw-r--r-- | src/renderer/WaterLevel.cpp (renamed from src/render/WaterLevel.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/WaterLevel.h (renamed from src/render/WaterLevel.h) | 0 | ||||
-rw-r--r-- | src/renderer/Weather.cpp (renamed from src/render/Weather.cpp) | 0 | ||||
-rw-r--r-- | src/renderer/Weather.h (renamed from src/render/Weather.h) | 0 | ||||
-rw-r--r-- | src/save/GenericGameStorage.cpp | 546 | ||||
-rw-r--r-- | src/save/GenericGameStorage.h | 5 | ||||
-rw-r--r-- | src/save/PCSave.cpp | 7 | ||||
-rw-r--r-- | src/save/PCSave.h | 2 | ||||
-rw-r--r-- | src/save/SaveBuf.h | 9 | ||||
-rw-r--r-- | src/skel/crossplatform.cpp | 23 | ||||
-rw-r--r-- | src/skel/crossplatform.h | 3 | ||||
-rw-r--r-- | src/vehicles/Automobile.cpp | 4 | ||||
-rw-r--r-- | src/vehicles/Boat.cpp | 2 | ||||
-rw-r--r-- | src/vehicles/Cranes.cpp | 86 | ||||
-rw-r--r-- | src/vehicles/Vehicle.cpp | 99 | ||||
-rw-r--r-- | src/weapons/Weapon.cpp | 12 | ||||
-rw-r--r-- | utils/gxt/american.txt | 6 | ||||
-rw-r--r-- | utils/gxt/french.txt | 6 | ||||
-rw-r--r-- | utils/gxt/german.txt | 6 | ||||
-rw-r--r-- | utils/gxt/italian.txt | 6 | ||||
-rwxr-xr-x | utils/gxt/polish.txt | 6 | ||||
-rw-r--r-- | utils/gxt/russian.txt | 6 | ||||
-rw-r--r-- | utils/gxt/spanish.txt | 6 |
137 files changed, 3425 insertions, 1651 deletions
diff --git a/.github/workflows/re3_msvc_amd64.yml b/.github/workflows/re3_msvc_amd64.yml index 428da540..014ac4f7 100644 --- a/.github/workflows/re3_msvc_amd64.yml +++ b/.github/workflows/re3_msvc_amd64.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: platform: [win-amd64-librw_d3d9-oal, win-amd64-librw_gl3_glfw-oal] - buildtype: [Debug, Release, Vanilla] + buildtype: [Debug, Release] steps: - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v1.0.2 diff --git a/.vscode/settings.json b/.vscode/settings.json index 10cb5627..fee80960 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,7 +13,7 @@ "src/modelinfo", "src/objects", "src/peds", - "src/render", + "src/renderer", "src/rw", "src/save", "src/skel", diff --git a/codewarrior/re3.mcp.xml b/codewarrior/re3.mcp.xml index b18e2bcc..ca20ec2a 100644 --- a/codewarrior/re3.mcp.xml +++ b/codewarrior/re3.mcp.xml @@ -187,7 +187,7 @@ </SETTING>
<SETTING>
<SETTING><NAME>SearchPath</NAME>
- <SETTING><NAME>Path</NAME><VALUE>..\src\render</VALUE></SETTING>
+ <SETTING><NAME>Path</NAME><VALUE>..\src\renderer</VALUE></SETTING>
<SETTING><NAME>PathFormat</NAME><VALUE>Windows</VALUE></SETTING>
<SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
</SETTING>
@@ -6424,7 +6424,7 @@ </SETTING>
<SETTING>
<SETTING><NAME>SearchPath</NAME>
- <SETTING><NAME>Path</NAME><VALUE>..\src\render</VALUE></SETTING>
+ <SETTING><NAME>Path</NAME><VALUE>..\src\renderer</VALUE></SETTING>
<SETTING><NAME>PathFormat</NAME><VALUE>Windows</VALUE></SETTING>
<SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
</SETTING>
@@ -14281,7 +14281,7 @@ <PATHFORMAT>Windows</PATHFORMAT>
</FILEREF>
</GROUP>
- <GROUP><NAME>render</NAME>
+ <GROUP><NAME>renderer</NAME>
<FILEREF>
<TARGETNAME>Debug</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
diff --git a/gamefiles/TEXT/american.gxt b/gamefiles/TEXT/american.gxt Binary files differindex ebd1ac39..d4034411 100644 --- a/gamefiles/TEXT/american.gxt +++ b/gamefiles/TEXT/american.gxt diff --git a/gamefiles/TEXT/french.gxt b/gamefiles/TEXT/french.gxt Binary files differindex 5b4c9e05..16c7a716 100644 --- a/gamefiles/TEXT/french.gxt +++ b/gamefiles/TEXT/french.gxt diff --git a/gamefiles/TEXT/german.gxt b/gamefiles/TEXT/german.gxt Binary files differindex 1d6ec988..c3309d61 100644 --- a/gamefiles/TEXT/german.gxt +++ b/gamefiles/TEXT/german.gxt diff --git a/gamefiles/TEXT/italian.gxt b/gamefiles/TEXT/italian.gxt Binary files differindex 746f07da..b30b74f4 100644 --- a/gamefiles/TEXT/italian.gxt +++ b/gamefiles/TEXT/italian.gxt diff --git a/gamefiles/TEXT/polish.gxt b/gamefiles/TEXT/polish.gxt Binary files differindex 5519c290..d771427b 100755 --- a/gamefiles/TEXT/polish.gxt +++ b/gamefiles/TEXT/polish.gxt diff --git a/gamefiles/TEXT/russian.gxt b/gamefiles/TEXT/russian.gxt Binary files differindex 90c8b13d..0075c691 100644 --- a/gamefiles/TEXT/russian.gxt +++ b/gamefiles/TEXT/russian.gxt diff --git a/gamefiles/TEXT/spanish.gxt b/gamefiles/TEXT/spanish.gxt Binary files differindex be659528..8980eb4d 100644 --- a/gamefiles/TEXT/spanish.gxt +++ b/gamefiles/TEXT/spanish.gxt diff --git a/premake5.lua b/premake5.lua index 72ff4d09..25090dc6 100644 --- a/premake5.lua +++ b/premake5.lua @@ -68,7 +68,7 @@ end workspace "re3"
language "C++"
- configurations { "Debug", "Release", "Vanilla" }
+ configurations { "Debug", "Release" }
startproject "re3"
location "build"
symbols "Full"
@@ -80,6 +80,7 @@ workspace "re3" end
filter { "system:windows" }
+ configurations { "Vanilla" }
platforms {
"win-x86-RW33_d3d8-mss",
"win-x86-librw_d3d9-mss",
@@ -123,9 +124,6 @@ workspace "re3" flags { "LinkTimeOptimization" }
end
- filter "configurations:Vanilla"
- defines { "VANILLA_DEFINES" }
-
filter { "platforms:win*" }
system "windows"
@@ -266,7 +264,7 @@ project "re3" files { addSrcFiles("src/modelinfo") }
files { addSrcFiles("src/objects") }
files { addSrcFiles("src/peds") }
- files { addSrcFiles("src/render") }
+ files { addSrcFiles("src/renderer") }
files { addSrcFiles("src/rw") }
files { addSrcFiles("src/save") }
files { addSrcFiles("src/skel") }
@@ -295,7 +293,7 @@ project "re3" includedirs { "src/modelinfo" }
includedirs { "src/objects" }
includedirs { "src/peds" }
- includedirs { "src/render" }
+ includedirs { "src/renderer" }
includedirs { "src/rw" }
includedirs { "src/save/" }
includedirs { "src/skel/" }
@@ -315,6 +313,9 @@ project "re3" includedirs { "vendor/opusfile/include" }
end
+ filter "configurations:Vanilla"
+ defines { "VANILLA_DEFINES" }
+
filter "platforms:*mss"
defines { "AUDIO_MSS" }
includedirs { "vendor/milessdk/include" }
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 35b7ec11..28090d7e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,7 +39,7 @@ target_compile_definitions(${EXECUTABLE} PRIVATE $<IF:$<CONFIG:DEBUG>,DEBUG,NDEBUG> LIBRW - ${PROJECT}_NO_AUTOLINK + CMAKE_NO_AUTOLINK ) if(LIBRW_PLATFORM_D3D9) diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h index 80927da2..45720b6f 100644 --- a/src/animation/AnimBlendAssociation.h +++ b/src/animation/AnimBlendAssociation.h @@ -35,7 +35,7 @@ public: CAnimBlendLink link; - int numNodes; // taken from CAnimBlendClumpData::numFrames + int32 numNodes; // taken from CAnimBlendClumpData::numFrames // NB: Order of these depends on order of nodes in Clump this was built from CAnimBlendNode *nodes; CAnimBlendHierarchy *hierarchy; diff --git a/src/animation/AnimBlendClumpData.cpp b/src/animation/AnimBlendClumpData.cpp index 702ee811..b333a449 100644 --- a/src/animation/AnimBlendClumpData.cpp +++ b/src/animation/AnimBlendClumpData.cpp @@ -3,7 +3,6 @@ #include "AnimBlendClumpData.h" #include "MemoryMgr.h" - CAnimBlendClumpData::CAnimBlendClumpData(void) { numFrames = 0; diff --git a/src/audio/AudioCollision.cpp b/src/audio/AudioCollision.cpp index fd819641..cfd13fb6 100644 --- a/src/audio/AudioCollision.cpp +++ b/src/audio/AudioCollision.cpp @@ -10,20 +10,39 @@ const int CollisionSoundIntensity = 60; -cAudioCollisionManager::cAudioCollisionManager() +void +cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, + float velocity) { - m_sQueue.m_pEntity1 = nil; - m_sQueue.m_pEntity2 = nil; - m_sQueue.m_bSurface1 = SURFACE_DEFAULT; - m_sQueue.m_bSurface2 = SURFACE_DEFAULT; - m_sQueue.m_fIntensity2 = 0.0f; - m_sQueue.m_fIntensity1 = 0.0f; - m_sQueue.m_vecPosition = CVector(0.0f, 0.0f, 0.0f); + float distSquared; + CVector v1; + CVector v2; - for (int i = 0; i < NUMAUDIOCOLLISIONS; i++) - m_bIndicesTable[i] = NUMAUDIOCOLLISIONS; + if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_nUserPause || + (velocity < 0.0016f && collisionPower < 0.01f)) + return; - m_bCollisionsInQueue = 0; + 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(); + } } void @@ -55,133 +74,71 @@ cAudioCollisionManager::AddCollisionToRequestedQueue() 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 +void +cAudioManager::ServiceCollisions() { - float result; - - switch(a) { - case SURFACE_DEFAULT: - case SURFACE_TARMAC: - case SURFACE_PAVEMENT: - case SURFACE_STEEP_CLIFF: - case SURFACE_TRANSPARENT_STONE: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break; - case SURFACE_GRASS: - case SURFACE_CARDBOARDBOX: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_GRAVEL: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_MUD_DRY: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_CAR: 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_TRANSPARENT_CLOTH: - case SURFACE_THICK_METAL_PLATE: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break; - case SURFACE_GARAGE_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break; - case SURFACE_CAR_PANEL: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break; - case SURFACE_SCAFFOLD_POLE: - case SURFACE_METAL_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; - case SURFACE_LAMP_POST: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; - case SURFACE_FIRE_HYDRANT: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break; - case SURFACE_GIRDER: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break; - case SURFACE_METAL_CHAIN_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; - case SURFACE_PED: 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_WATER: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_WOOD_CRATES: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break; - case SURFACE_WOOD_BENCH: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break; - case SURFACE_WOOD_SOLID: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break; - case SURFACE_RUBBER: - case SURFACE_WHEELBASE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_PLASTIC: 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_CONTAINER: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break; - case SURFACE_NEWS_VENDOR: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break; - default: result = 0.f; break; - } + int i, j; + bool8 abRepeatedCollision1[NUMAUDIOCOLLISIONS]; + bool8 abRepeatedCollision2[NUMAUDIOCOLLISIONS]; - return result; -} + m_sQueueSample.m_nEntityIndex = m_nCollisionEntity; -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; -} + for (int i = 0; i < NUMAUDIOCOLLISIONS; i++) + abRepeatedCollision1[i] = abRepeatedCollision2[i] = FALSE; -uint32 -cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision) -{ - uint8 surface1 = audioCollision.m_bSurface1; - uint8 surface2 = audioCollision.m_bSurface2; - int32 vol; - float ratio; + 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) + ) { + abRepeatedCollision1[index] = TRUE; + abRepeatedCollision2[j] = TRUE; + m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume; + SetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j); + break; + } + } + } - 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_WATER || surface2 == SURFACE_WATER) { - 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_GRAVEL || surface2 == SURFACE_GRAVEL || surface1 == SURFACE_MUD_DRY || - surface2 == SURFACE_MUD_DRY || 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_PED || surface2 == SURFACE_PED) { - return 0; - } else { - 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; + for (i = 0; i < NUMAUDIOCOLLISIONS; i++) { + if (!abRepeatedCollision2[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; + } } - if(audioCollision.m_nBaseVolume < 2) vol = audioCollision.m_nBaseVolume * vol / 2; - return vol; -} -void -cAudioManager::SetUpLoopingCollisionSound(const 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_nVolume = - ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance); - if(m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = counter; - m_sQueueSample.m_vecPos = col.m_vecPosition; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_bIs2D = FALSE; - m_sQueueSample.m_nReleasingVolumeModificator = 7; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - SET_LOOP_OFFSETS(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity; - m_sQueueSample.m_bReleasingSoundFlag = FALSE; - m_sQueueSample.m_nReleasingVolumeDivider = 5; - m_sQueueSample.m_bReverbFlag = TRUE; - m_sQueueSample.m_bRequireReflection = FALSE; - AddSampleToRequestedQueue(); + for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) { + int index = m_sCollisionManager.m_bIndicesTable[i]; + if (!abRepeatedCollision1[index]) { + for (j = 0; j < NUMAUDIOCOLLISIONS; j++) { + if (!abRepeatedCollision2[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; } + static const int32 gOneShotCol[] = {SFX_COL_TARMAC_1, SFX_COL_TARMAC_1, SFX_COL_GRASS_1, @@ -219,9 +176,8 @@ static const int32 gOneShotCol[] = {SFX_COL_TARMAC_1, void cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col) { - - int16 s1; - int16 s2; + uint16 s1; + uint16 s2; int32 emittingVol; float ratio; @@ -321,101 +277,126 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col) } void -cAudioManager::ServiceCollisions() +cAudioManager::SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter) { - int i, j; - bool8 abRepeatedCollision1[NUMAUDIOCOLLISIONS]; - bool8 abRepeatedCollision2[NUMAUDIOCOLLISIONS]; - - m_sQueueSample.m_nEntityIndex = m_nCollisionEntity; - - for (int i = 0; i < NUMAUDIOCOLLISIONS; i++) - abRepeatedCollision1[i] = abRepeatedCollision2[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) - ) { - abRepeatedCollision1[index] = TRUE; - abRepeatedCollision2[j] = TRUE; - m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume; - SetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j); - break; + if(col.m_fIntensity2 > 0.0016f) { + uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col); + if(emittingVol) { + m_sQueueSample.m_fDistance = Sqrt(col.m_fDistance); + m_sQueueSample.m_nVolume = + ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance); + if(m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = counter; + m_sQueueSample.m_vecPos = col.m_vecPosition; + m_sQueueSample.m_nBankIndex = SFX_BANK_0; + m_sQueueSample.m_bIs2D = FALSE; + m_sQueueSample.m_nReleasingVolumeModificator = 7; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + SET_LOOP_OFFSETS(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity; + m_sQueueSample.m_bReleasingSoundFlag = FALSE; + m_sQueueSample.m_nReleasingVolumeDivider = 5; + m_sQueueSample.m_bReverbFlag = TRUE; + m_sQueueSample.m_bRequireReflection = FALSE; + AddSampleToRequestedQueue(); } } } +} - for (i = 0; i < NUMAUDIOCOLLISIONS; i++) { - if (!abRepeatedCollision2[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; - } +uint32 +cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(const 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_WATER || surface2 == SURFACE_WATER) { + 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_GRAVEL || surface2 == SURFACE_GRAVEL || surface1 == SURFACE_MUD_DRY || + surface2 == SURFACE_MUD_DRY || 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_PED || surface2 == SURFACE_PED) { + return 0; + } else { + 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; +} - for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) { - int index = m_sCollisionManager.m_bIndicesTable[i]; - if (!abRepeatedCollision1[index]) { - for (j = 0; j < NUMAUDIOCOLLISIONS; j++) { - if (!abRepeatedCollision2[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); - } +float +cAudioManager::GetCollisionOneShotRatio(uint32 a, float b) +{ + switch(a) { + case SURFACE_DEFAULT: + case SURFACE_TARMAC: + case SURFACE_PAVEMENT: + case SURFACE_STEEP_CLIFF: + case SURFACE_TRANSPARENT_STONE: return GetCollisionRatio(b, 10.f, 60.f, 50.f); + case SURFACE_GRASS: + case SURFACE_CARDBOARDBOX: return GetCollisionRatio(b, 0.f, 2.f, 2.f); + case SURFACE_GRAVEL: return GetCollisionRatio(b, 0.f, 2.f, 2.f); + case SURFACE_MUD_DRY: return GetCollisionRatio(b, 0.f, 2.f, 2.f); + case SURFACE_CAR: return GetCollisionRatio(b, 6.f, 50.f, 44.f); + case SURFACE_GLASS: return GetCollisionRatio(b, 0.1f, 10.f, 9.9f); + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_THICK_METAL_PLATE: return GetCollisionRatio(b, 30.f, 130.f, 100.f); + case SURFACE_GARAGE_DOOR: return GetCollisionRatio(b, 20.f, 100.f, 80.f); + case SURFACE_CAR_PANEL: return GetCollisionRatio(b, 0.f, 4.f, 4.f); + case SURFACE_SCAFFOLD_POLE: + case SURFACE_METAL_GATE: return GetCollisionRatio(b, 1.f, 10.f, 9.f); + case SURFACE_LAMP_POST: return GetCollisionRatio(b, 1.f, 10.f, 9.f); + case SURFACE_FIRE_HYDRANT: return GetCollisionRatio(b, 1.f, 15.f, 14.f); + case SURFACE_GIRDER: return GetCollisionRatio(b, 8.f, 50.f, 42.f); + case SURFACE_METAL_CHAIN_FENCE: return GetCollisionRatio(b, 0.1f, 10.f, 9.9f); + case SURFACE_PED: return GetCollisionRatio(b, 0.f, 20.f, 20.f); + case SURFACE_SAND: return GetCollisionRatio(b, 0.f, 10.f, 10.f); + case SURFACE_WATER: return GetCollisionRatio(b, 0.f, 10.f, 10.f); + case SURFACE_WOOD_CRATES: return GetCollisionRatio(b, 1.f, 4.f, 3.f); + case SURFACE_WOOD_BENCH: return GetCollisionRatio(b, 0.1f, 5.f, 4.9f); + case SURFACE_WOOD_SOLID: return GetCollisionRatio(b, 0.1f, 40.f, 39.9f); + case SURFACE_RUBBER: + case SURFACE_WHEELBASE: return GetCollisionRatio(b, 0.f, 10.f, 10.f); + case SURFACE_PLASTIC: return GetCollisionRatio(b, 0.1f, 4.f, 3.9f); + case SURFACE_HEDGE: return GetCollisionRatio(b, 0.f, 0.5f, 0.5f); + case SURFACE_CONTAINER: return GetCollisionRatio(b, 4.f, 40.f, 36.f); + case SURFACE_NEWS_VENDOR: return GetCollisionRatio(b, 0.f, 5.f, 5.f); } - for (int i = 0; i < NUMAUDIOCOLLISIONS; i++) - m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS; - m_sCollisionManager.m_bCollisionsInQueue = 0; + return 0.f; } -void -cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, - float velocity) +float +cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) { - float distSquared; - CVector v1; - CVector v2; - - if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_nUserPause || - (velocity < 0.0016f && collisionPower < 0.01f)) - return; + return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f); +} - 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(); - } +float +cAudioManager::GetCollisionRatio(float a, float b, float c, float d) +{ + float e; + e = a; + if(a <= b) return 0.0f; + if(c <= a) e = c; + return (e - b) / d; } diff --git a/src/audio/AudioCollision.h b/src/audio/AudioCollision.h index 0a058916..a201d500 100644 --- a/src/audio/AudioCollision.h +++ b/src/audio/AudioCollision.h @@ -17,7 +17,18 @@ public: float m_fDistance; int32 m_nBaseVolume; - // no methods + cAudioCollision() { Reset(); } + + void Reset() + { + m_pEntity1 = nil; + m_pEntity2 = nil; + m_bSurface1 = 0; + m_bSurface2 = 0; + m_fIntensity1 = m_fIntensity2 = 0.0f; + m_vecPosition = CVector(0.0f, 0.0f, 0.0f); + m_fDistance = 0.0f; + } }; VALIDATE_SIZE(cAudioCollision, 40); @@ -31,7 +42,15 @@ public: uint8 m_bCollisionsInQueue; cAudioCollision m_sQueue; - cAudioCollisionManager(); + cAudioCollisionManager() + { + m_sQueue.Reset(); + + for(int i = 0; i < NUMAUDIOCOLLISIONS; i++) + m_bIndicesTable[i] = NUMAUDIOCOLLISIONS; + + m_bCollisionsInQueue = 0; + } void AddCollisionToRequestedQueue(); }; diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index fdc7305b..44664f8a 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -52,11 +52,8 @@ uint32 gHomeNextTime; uint32 gCellNextTime; uint32 gNextCryTime; -enum PLAY_STATUS { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING, PLAY_STATUS_FINISHED }; -enum LOADING_STATUS { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED, LOADING_STATUS_FAILED }; - void -cAudioManager::PreInitialiseGameSpecificSetup() const +cAudioManager::PreInitialiseGameSpecificSetup() { BankStartOffset[SFX_BANK_0] = SAMPLEBANK_START; #ifdef GTA_PS2 @@ -163,6 +160,7 @@ cAudioManager::PostInitialiseGameSpecificSetup() m_sMissionAudio.m_nMissionAudioCounter = 0; ResetAudioLogicTimers(CTimer::GetTimeInMilliseconds()); } + void cAudioManager::PreTerminateGameSpecificShutdown() { @@ -228,7 +226,7 @@ cAudioManager::ResetAudioLogicTimers(uint32 timer) } void -cAudioManager::ProcessReverb() const +cAudioManager::ProcessReverb() { if (SampleManager.UpdateReverb() && m_bDynamicAcousticModelingStatus) { #ifndef GTA_PS2 @@ -248,7 +246,7 @@ cAudioManager::ProcessReverb() const } float -cAudioManager::GetDistanceSquared(const CVector &v) const +cAudioManager::GetDistanceSquared(const CVector &v) { const CVector &c = TheCamera.GetPosition(); return sq(v.x - c.x) + sq(v.y - c.y) + sq((v.z - c.z) * 0.2f); @@ -801,8 +799,6 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams& params) } } - - bool8 cAudioManager::ProcessVehicleRoadNoise(cVehicleParams& params) { @@ -1063,20 +1059,20 @@ cAudioManager::UpdateGasPedalAudio(CAutomobile *automobile) } void -cAudioManager::PlayerJustGotInCar() const +cAudioManager::PlayerJustGotInCar() { if (m_bIsInitialised) bPlayerJustEnteredCar = TRUE; } void -cAudioManager::PlayerJustLeftCar(void) const +cAudioManager::PlayerJustLeftCar(void) { // UNUSED: This is a perfectly empty function. } void -cAudioManager::AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, uint8 counter, bool8 notLooping) +cAudioManager::AddPlayerCarSample(uint8 emittingVolume, uint32 freq, uint32 sample, uint8 bank, uint8 counter, bool8 notLooping) { m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, 50.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { @@ -1581,7 +1577,7 @@ cAudioManager::ProcessVehicleHorn(cVehicleParams& params) } bool8 -cAudioManager::UsesSiren(int32 model) const +cAudioManager::UsesSiren(uint32 model) { switch (model) { case FIRETRUK: @@ -1597,7 +1593,7 @@ cAudioManager::UsesSiren(int32 model) const } bool8 -cAudioManager::UsesSirenSwitching(int32 model) const +cAudioManager::UsesSirenSwitching(uint32 model) { switch (model) { case AMBULAN: @@ -1663,7 +1659,7 @@ cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams& params) } bool8 -cAudioManager::UsesReverseWarning(int32 model) const +cAudioManager::UsesReverseWarning(uint32 model) { return model == LINERUN || model == FIRETRUK || model == TRASH || model == BUS || model == COACH; } @@ -1792,7 +1788,7 @@ cAudioManager::ProcessAirBrakes(cVehicleParams& params) } bool8 -cAudioManager::HasAirBrakes(int32 model) const +cAudioManager::HasAirBrakes(uint32 model) { return model == LINERUN || model == FIRETRUK || model == TRASH || model == BUS || model == COACH; } @@ -2631,8 +2627,8 @@ uint8 gJumboVolOffsetPercentage; void DoJumboVolOffset() { - if (!(AudioManager.GetFrameCounter() % (AudioManager.GetRandomNumber(0) % 6 + 3))) - gJumboVolOffsetPercentage = AudioManager.GetRandomNumber(1) % 60; + if (!(AudioManager.m_FrameCounter % (AudioManager.m_anRandomTable[0] % 6 + 3))) + gJumboVolOffsetPercentage = AudioManager.m_anRandomTable[1] % 60; } void @@ -2910,7 +2906,7 @@ cAudioManager::SetupJumboRumbleSound(uint8 emittingVol) } int32 -cAudioManager::GetJumboTaxiFreq() const +cAudioManager::GetJumboTaxiFreq() { return (60.833f * m_sQueueSample.m_fDistance) + 22050; } @@ -3565,23 +3561,23 @@ cAudioManager::SetupPedComments(cPedParams ¶ms, uint16 sound) switch (sound) { case SOUND_PED_HELI_PLAYER_FOUND: soundIntensity = 400.0f; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_POLICE_HELI_1, SFX_POLICE_HELI_29); + pedComment.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % 4] % 29 + SFX_POLICE_HELI_1; break; case SOUND_PED_BODYCAST_HIT: if (CTimer::GetTimeInMilliseconds() <= gNextCryTime) return; soundIntensity = 50.0f; gNextCryTime = CTimer::GetTimeInMilliseconds() + 500; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_PLASTER_BLOKE_1, SFX_PLASTER_BLOKE_4); + pedComment.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % 4] % 4 + SFX_PLASTER_BLOKE_1; break; case SOUND_INJURED_PED_MALE_OUCH: case SOUND_INJURED_PED_MALE_PRISON: soundIntensity = 50.0f; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_MALE_GRUNT_1, SFX_GENERIC_MALE_GRUNT_15); + pedComment.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % 4] % 15 + SFX_GENERIC_MALE_GRUNT_1; break; case SOUND_INJURED_PED_FEMALE: soundIntensity = 50.0f; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_FEMALE_GRUNT_1, SFX_GENERIC_FEMALE_GRUNT_11); + pedComment.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % 4] % 11 + SFX_GENERIC_FEMALE_GRUNT_1; break; default: return; @@ -3618,7 +3614,7 @@ cAudioManager::SetupPedComments(cPedParams ¶ms, uint16 sound) } int32 -cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) +cAudioManager::GetPedCommentSfx(CPed *ped, uint16 sound) { if (ped->IsPlayer()) return GetPlayerTalkSfx(sound); @@ -3639,7 +3635,7 @@ cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) case MI_MALE01: return GetNormalMaleTalkSfx(sound); case MI_TAXI_D: - return GetTaxiDriverTalkSfx(sound); + return GetAsianTaxiDriverTalkSfx(sound); case MI_PIMP: return GetPimpTalkSfx(sound); case MI_GANG01: @@ -3673,7 +3669,7 @@ cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) case MI_SPECIAL04: return GetSpecialCharacterTalkSfx(ped->GetModelIndex(), sound); case MI_MALE02: - return GetMaleNo2TalkSfx(sound); + return GetCasualMaleOldTalkSfx(sound); case MI_MALE03: case MI_P_MAN1: case MI_P_MAN2: @@ -3768,14 +3764,14 @@ cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) case MI_STUD_WOM: return GetStudentFemaleTalkSfx(sound); case MI_CAS_MAN: - return GetCasualMaleOldTalkSfx(sound); + return GetCasualMaleYoungTalkSfx(sound); default: return GetGenericMaleTalkSfx(sound); } } void -cAudioManager::GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const +cAudioManager::GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) { phrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset; @@ -3789,7 +3785,7 @@ cAudioManager::GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint #pragma region PED_COMMENTS uint32 -cAudioManager::GetPlayerTalkSfx(int16 sound) +cAudioManager::GetPlayerTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -3812,7 +3808,7 @@ cAudioManager::GetPlayerTalkSfx(int16 sound) } uint32 -cAudioManager::GetCopTalkSfx(int16 sound) +cAudioManager::GetCopTalkSfx(uint16 sound) { uint32 sfx; PedState pedState; @@ -3836,7 +3832,7 @@ cAudioManager::GetCopTalkSfx(int16 sound) } uint32 -cAudioManager::GetSwatTalkSfx(int16 sound) +cAudioManager::GetSwatTalkSfx(uint16 sound) { uint32 sfx; PedState pedState; @@ -3860,7 +3856,7 @@ cAudioManager::GetSwatTalkSfx(int16 sound) } uint32 -cAudioManager::GetFBITalkSfx(int16 sound) +cAudioManager::GetFBITalkSfx(uint16 sound) { uint32 sfx; PedState pedState; @@ -3884,7 +3880,7 @@ cAudioManager::GetFBITalkSfx(int16 sound) } uint32 -cAudioManager::GetArmyTalkSfx(int16 sound) +cAudioManager::GetArmyTalkSfx(uint16 sound) { uint32 sfx; PedState pedState; @@ -3903,7 +3899,7 @@ cAudioManager::GetArmyTalkSfx(int16 sound) } uint32 -cAudioManager::GetMedicTalkSfx(int16 sound) +cAudioManager::GetMedicTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -3931,41 +3927,41 @@ cAudioManager::GetMedicTalkSfx(int16 sound) } uint32 -cAudioManager::GetFiremanTalkSfx(int16 sound) +cAudioManager::GetFiremanTalkSfx(uint16 sound) { return GetGenericMaleTalkSfx(sound); } uint32 -cAudioManager::GetNormalMaleTalkSfx(int16 sound) +cAudioManager::GetBusinessMaleOldTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_DODGE_1, 9); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4); break; case SOUND_PED_FLEE_RUN: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_EYING_1, 8); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CHAT_1, 25); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -3974,61 +3970,47 @@ cAudioManager::GetNormalMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetTaxiDriverTalkSfx(int16 sound) +cAudioManager::GetBusinessMaleYoungTalkSfx(uint16 sound, uint32 model) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); - break; - case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - - return (SFX_ASIAN_TAXI_DRIVER_VOICE_2_DRIVER_ABUSE_1 - SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetPimpTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(sfx, lastSfx, SFX_PIMP_GUN_COOL_1, 7); + case SOUND_PED_HANDS_COWER: + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: - GetPhrase(sfx, lastSfx, SFX_PIMP_CARJACKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); break; - case SOUND_PED_DEFEND: - GetPhrase(sfx, lastSfx, SFX_PIMP_FIGHT_1, 9); + case SOUND_PED_ROBBED: + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(sfx, lastSfx, SFX_PIMP_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4); break; - case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(sfx, lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5); + case SOUND_PED_FLEE_RUN: + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5); break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(sfx, lastSfx, SFX_PIMP_SHOCKED_1, 2); + case SOUND_PED_ANNOYED_DRIVER: + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT: - GetPhrase(sfx, lastSfx, SFX_PIMP_CHAT_1, 17); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); } + + if (model == MI_B_MAN3) + sfx += (SFX_BUSINESS_MALE_YOUNG_VOICE_2_DRIVER_ABUSE_1 - SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1); return sfx; } uint32 -cAudioManager::GetMafiaTalkSfx(int16 sound) +cAudioManager::GetMafiaTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4062,7 +4044,7 @@ cAudioManager::GetMafiaTalkSfx(int16 sound) } uint32 -cAudioManager::GetTriadTalkSfx(int16 sound) +cAudioManager::GetTriadTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4099,7 +4081,7 @@ cAudioManager::GetTriadTalkSfx(int16 sound) } uint32 -cAudioManager::GetDiabloTalkSfx(int16 sound) +cAudioManager::GetDiabloTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4140,7 +4122,7 @@ cAudioManager::GetDiabloTalkSfx(int16 sound) } uint32 -cAudioManager::GetYakuzaTalkSfx(int16 sound) +cAudioManager::GetYakuzaTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4171,7 +4153,7 @@ cAudioManager::GetYakuzaTalkSfx(int16 sound) } uint32 -cAudioManager::GetYardieTalkSfx(int16 sound) +cAudioManager::GetYardieTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4208,7 +4190,7 @@ cAudioManager::GetYardieTalkSfx(int16 sound) } uint32 -cAudioManager::GetColumbianTalkSfx(int16 sound) +cAudioManager::GetColumbianTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4242,7 +4224,7 @@ cAudioManager::GetColumbianTalkSfx(int16 sound) } uint32 -cAudioManager::GetHoodTalkSfx(int16 sound) +cAudioManager::GetHoodTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4281,7 +4263,7 @@ cAudioManager::GetHoodTalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackCriminalTalkSfx(int16 sound) +cAudioManager::GetBlackCriminalTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4313,7 +4295,7 @@ cAudioManager::GetBlackCriminalTalkSfx(int16 sound) } uint32 -cAudioManager::GetWhiteCriminalTalkSfx(int16 sound) +cAudioManager::GetWhiteCriminalTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4345,7 +4327,7 @@ cAudioManager::GetWhiteCriminalTalkSfx(int16 sound) } uint32 -cAudioManager::GetMaleNo2TalkSfx(int16 sound) +cAudioManager::GetCasualMaleOldTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4379,79 +4361,13 @@ cAudioManager::GetMaleNo2TalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackProjectMaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch(sound) { - case SOUND_PED_HANDS_UP: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3); break; - case SOUND_PED_CAR_JACKED: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2); break; - case SOUND_PED_ROBBED: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2); break; - case SOUND_PED_ATTACK: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6); break; - case SOUND_PED_EVADE: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5); break; - case SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7); break; - case SOUND_PED_CHAT_SEXY: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3); break; - case SOUND_PED_CHAT: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6); break; - default: return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_P_MAN2) - sfx += (SFX_BLACK_PROJECT_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetWhiteFatMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch(sound) { - case SOUND_PED_CAR_JACKED: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3); break; - case SOUND_PED_ROBBED: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3); break; - case SOUND_PED_EVADE: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9); break; - case SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9); break; - case SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2); break; - case SOUND_PED_CHAT: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9); break; - default: return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackFatMaleTalkSfx(int16 sound) +cAudioManager::GetCasualMaleYoungTalkSfx(uint16 sound) { - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7); - break; - case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; + return GetGenericMaleTalkSfx(sound); } uint32 -cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound) +cAudioManager::GetBlackCasualFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4488,7 +4404,7 @@ cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound) +cAudioManager::GetWhiteCasualFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4525,7 +4441,7 @@ cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetFemaleNo3TalkSfx(int16 sound) +cAudioManager::GetFemaleNo3TalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4562,7 +4478,47 @@ cAudioManager::GetFemaleNo3TalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound) +cAudioManager::GetWhiteBusinessFemaleTalkSfx(uint16 sound, uint32 model) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4); + break; + case SOUND_PED_ANNOYED_DRIVER: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + + if (model == MI_B_WOM2) + sfx += (SFX_WHITE_BUSINESS_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1); + return sfx; +} + +uint32 +cAudioManager::GetBlackFatFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4596,7 +4552,56 @@ cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound) +cAudioManager::GetWhiteFatMaleTalkSfx(uint16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch(sound) { + case SOUND_PED_CAR_JACKED: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3); break; + case SOUND_PED_ROBBED: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3); break; + case SOUND_PED_EVADE: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9); break; + case SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9); break; + case SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2); break; + case SOUND_PED_CHAT: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9); break; + default: return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackFatMaleTalkSfx(uint16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4); + break; + case SOUND_PED_ROBBED: + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7); + break; + case SOUND_PED_ANNOYED_DRIVER: + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_WAIT_DOUBLEBACK: + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteFatFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4630,7 +4635,7 @@ cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound) +cAudioManager::GetBlackFemaleProstituteTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4664,7 +4669,7 @@ cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound) } uint32 -cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound) +cAudioManager::GetWhiteFemaleProstituteTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4695,7 +4700,30 @@ cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound) +cAudioManager::GetBlackProjectMaleTalkSfx(uint16 sound, uint32 model) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch(sound) { + case SOUND_PED_HANDS_UP: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3); break; + case SOUND_PED_CAR_JACKED: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2); break; + case SOUND_PED_ROBBED: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2); break; + case SOUND_PED_ATTACK: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6); break; + case SOUND_PED_EVADE: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5); break; + case SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7); break; + case SOUND_PED_CHAT_SEXY: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3); break; + case SOUND_PED_CHAT: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6); break; + default: return GetGenericMaleTalkSfx(sound); + } + + if (model == MI_P_MAN2) + sfx += (SFX_BLACK_PROJECT_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1); + return sfx; +} + +uint32 +cAudioManager::GetBlackProjectFemaleOldTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4729,7 +4757,7 @@ cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound) +cAudioManager::GetBlackProjectFemaleYoungTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4763,7 +4791,7 @@ cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound) } uint32 -cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound) +cAudioManager::GetChinatownMaleOldTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4797,7 +4825,7 @@ cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound) } uint32 -cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound) +cAudioManager::GetChinatownMaleYoungTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4831,7 +4859,7 @@ cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound) } uint32 -cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound) +cAudioManager::GetChinatownFemaleOldTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4862,7 +4890,7 @@ cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound) } uint32 -cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound) +cAudioManager::GetChinatownFemaleYoungTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4893,7 +4921,7 @@ cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound) } uint32 -cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound) +cAudioManager::GetLittleItalyMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4927,7 +4955,7 @@ cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound) +cAudioManager::GetLittleItalyFemaleOldTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4958,7 +4986,7 @@ cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound) } uint32 -cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound) +cAudioManager::GetLittleItalyFemaleYoungTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -4989,7 +5017,7 @@ cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound) } uint32 -cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound) +cAudioManager::GetWhiteDockerMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5020,7 +5048,7 @@ cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound) +cAudioManager::GetBlackDockerMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5051,7 +5079,7 @@ cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetScumMaleTalkSfx(int16 sound) +cAudioManager::GetScumMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5088,7 +5116,7 @@ cAudioManager::GetScumMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetScumFemaleTalkSfx(int16 sound) +cAudioManager::GetScumFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5119,7 +5147,7 @@ cAudioManager::GetScumFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound) +cAudioManager::GetWhiteWorkerMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5150,7 +5178,7 @@ cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound) +cAudioManager::GetBlackWorkerMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5181,124 +5209,7 @@ cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetBusinessMaleYoungTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_B_MAN3) - sfx += (SFX_BUSINESS_MALE_YOUNG_VOICE_2_DRIVER_ABUSE_1 - SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetBusinessMaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4); - break; - case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - - if (model == MI_B_WOM2) - sfx += (SFX_WHITE_BUSINESS_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound) +cAudioManager::GetBlackBusinessFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5335,7 +5246,7 @@ cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetSupermodelMaleTalkSfx(int16 sound) +cAudioManager::GetSupermodelMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5369,7 +5280,7 @@ cAudioManager::GetSupermodelMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound) +cAudioManager::GetSupermodelFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5400,7 +5311,7 @@ cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetStewardMaleTalkSfx(int16 sound) +cAudioManager::GetStewardMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5428,7 +5339,7 @@ cAudioManager::GetStewardMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetStewardFemaleTalkSfx(int16 sound) +cAudioManager::GetStewardFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5453,7 +5364,7 @@ cAudioManager::GetStewardFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model) +cAudioManager::GetFanMaleTalkSfx(uint16 sound, uint32 model) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5484,7 +5395,7 @@ cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model) } uint32 -cAudioManager::GetFanFemaleTalkSfx(int16 sound) +cAudioManager::GetFanFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5512,7 +5423,7 @@ cAudioManager::GetFanFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetHospitalMaleTalkSfx(int16 sound) +cAudioManager::GetHospitalMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5540,7 +5451,7 @@ cAudioManager::GetHospitalMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetHospitalFemaleTalkSfx(int16 sound) +cAudioManager::GetHospitalFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5562,7 +5473,7 @@ cAudioManager::GetHospitalFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound) +cAudioManager::GetWhiteConstructionWorkerTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5596,7 +5507,7 @@ cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound) } uint32 -cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound) +cAudioManager::GetBlackConstructionWorkerTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5630,7 +5541,7 @@ cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound) } uint32 -cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model) +cAudioManager::GetShopperFemaleTalkSfx(uint16 sound, uint32 model) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5667,7 +5578,7 @@ cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model) } uint32 -cAudioManager::GetStudentMaleTalkSfx(int16 sound) +cAudioManager::GetStudentMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5701,7 +5612,7 @@ cAudioManager::GetStudentMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetStudentFemaleTalkSfx(int16 sound) +cAudioManager::GetStudentFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5735,29 +5646,23 @@ cAudioManager::GetStudentFemaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetCasualMaleOldTalkSfx(int16 sound) -{ - return GetGenericMaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound) +cAudioManager::GetSpecialCharacterTalkSfx(uint32 modelIndex, uint16 sound) { char *modelName = CModelInfo::GetModelInfo(modelIndex)->GetModelName(); if (!CGeneral::faststricmp(modelName, "eight") || !CGeneral::faststricmp(modelName, "eight2")) { - return GetEightTalkSfx(sound); + return GetEightBallTalkSfx(sound); } if (!CGeneral::faststricmp(modelName, "frankie")) { - return GetFrankieTalkSfx(sound); + return GetSalvatoreTalkSfx(sound); } if (!CGeneral::faststricmp(modelName, "misty")) { return GetMistyTalkSfx(sound); } if (!CGeneral::faststricmp(modelName, "ojg") || !CGeneral::faststricmp(modelName, "ojg_p")) { - return GetOJGTalkSfx(sound); + return GetOldJapTalkSfx(sound); } if (!CGeneral::faststricmp(modelName, "cat")) { - return GetCatatalinaTalkSfx(sound); + return GetCatalinaTalkSfx(sound); } if (!CGeneral::faststricmp(modelName, "bomber")) { return GetBomberTalkSfx(sound); @@ -5777,8 +5682,9 @@ cAudioManager::GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound) return GetGenericMaleTalkSfx(sound); } + uint32 -cAudioManager::GetEightTalkSfx(int16 sound) +cAudioManager::GetEightBallTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5803,7 +5709,7 @@ cAudioManager::GetEightTalkSfx(int16 sound) } uint32 -cAudioManager::GetFrankieTalkSfx(int16 sound) +cAudioManager::GetSalvatoreTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5828,7 +5734,7 @@ cAudioManager::GetFrankieTalkSfx(int16 sound) } uint32 -cAudioManager::GetMistyTalkSfx(int16 sound) +cAudioManager::GetMistyTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5857,19 +5763,19 @@ cAudioManager::GetMistyTalkSfx(int16 sound) } uint32 -cAudioManager::GetOJGTalkSfx(int16 sound) +cAudioManager::GetOldJapTalkSfx(uint16 sound) { return GetGenericMaleTalkSfx(sound); } uint32 -cAudioManager::GetCatatalinaTalkSfx(int16 sound) +cAudioManager::GetCatalinaTalkSfx(uint16 sound) { return GetGenericFemaleTalkSfx(sound); } uint32 -cAudioManager::GetBomberTalkSfx(int16 sound) +cAudioManager::GetBomberTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5886,7 +5792,7 @@ cAudioManager::GetBomberTalkSfx(int16 sound) } uint32 -cAudioManager::GetSecurityGuardTalkSfx(int16 sound) +cAudioManager::GetSecurityGuardTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5919,7 +5825,7 @@ cAudioManager::GetSecurityGuardTalkSfx(int16 sound) } uint32 -cAudioManager::GetChunkyTalkSfx(int16 sound) +cAudioManager::GetChunkyTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5939,7 +5845,98 @@ cAudioManager::GetChunkyTalkSfx(int16 sound) } uint32 -cAudioManager::GetGenericMaleTalkSfx(int16 sound) +cAudioManager::GetAsianTaxiDriverTalkSfx(uint16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); + break; + case SOUND_PED_ANNOYED_DRIVER: + GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + + return (SFX_ASIAN_TAXI_DRIVER_VOICE_2_DRIVER_ABUSE_1 - SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetPimpTalkSfx(uint16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(sfx, lastSfx, SFX_PIMP_GUN_COOL_1, 7); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(sfx, lastSfx, SFX_PIMP_CARJACKED_1, 4); + break; + case SOUND_PED_DEFEND: + GetPhrase(sfx, lastSfx, SFX_PIMP_FIGHT_1, 9); + break; + case SOUND_PED_EVADE: + GetPhrase(sfx, lastSfx, SFX_PIMP_DODGE_1, 6); + break; + case SOUND_PED_ANNOYED_DRIVER: + GetPhrase(sfx, lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(sfx, lastSfx, SFX_PIMP_SHOCKED_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(sfx, lastSfx, SFX_PIMP_CHAT_1, 17); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetNormalMaleTalkSfx(uint16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7); + break; + case SOUND_PED_EVADE: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_DODGE_1, 9); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5); + break; + case SOUND_PED_ANNOYED_DRIVER: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_EYING_1, 8); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10); + break; + case SOUND_PED_CHAT: + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CHAT_1, 25); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetGenericMaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -5965,7 +5962,7 @@ cAudioManager::GetGenericMaleTalkSfx(int16 sound) } uint32 -cAudioManager::GetGenericFemaleTalkSfx(int16 sound) +cAudioManager::GetGenericFemaleTalkSfx(uint16 sound) { uint32 sfx; static uint32 lastSfx = NO_SAMPLE; @@ -8353,7 +8350,7 @@ FindMissionAudioSfx(const char *name) } bool8 -cAudioManager::MissionScriptAudioUsesPoliceChannel(int32 soundMission) const +cAudioManager::MissionScriptAudioUsesPoliceChannel(uint32 soundMission) { switch (soundMission) { case STREAMED_SOUND_MISSION_J6_D: @@ -8394,7 +8391,7 @@ cAudioManager::PreloadMissionAudio(Const char *name) } uint8 -cAudioManager::GetMissionAudioLoadingStatus() const +cAudioManager::GetMissionAudioLoadingStatus() { if (m_bIsInitialised) return m_sMissionAudio.m_nLoadingStatus; diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 2e391349..c3565828 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -109,7 +109,9 @@ cAudioManager::Service() if (m_bIsInitialised) { m_nPreviousUserPause = m_nUserPause; m_nUserPause = CTimer::GetIsUserPaused(); +#ifdef GTA_PC UpdateReflections(); +#endif ServiceSoundEffects(); MusicManager.Service(); } @@ -216,33 +218,33 @@ cAudioManager::PlayOneShot(int32 index, uint16 sound, float vol) } void -cAudioManager::SetEffectsMasterVolume(uint8 volume) const +cAudioManager::SetEffectsMasterVolume(uint8 volume) { SampleManager.SetEffectsMasterVolume(volume); } void -cAudioManager::SetMusicMasterVolume(uint8 volume) const +cAudioManager::SetMusicMasterVolume(uint8 volume) { SampleManager.SetMusicMasterVolume(volume); } void -cAudioManager::SetEffectsFadeVol(uint8 volume) const +cAudioManager::SetEffectsFadeVol(uint8 volume) { SampleManager.SetEffectsFadeVolume(volume); } void -cAudioManager::SetMonoMode(bool8 mono) +cAudioManager::SetMusicFadeVol(uint8 volume) { - SampleManager.SetMonoMode(mono); + SampleManager.SetMusicFadeVolume(volume); } void -cAudioManager::SetMusicFadeVol(uint8 volume) const +cAudioManager::SetMonoMode(bool8 mono) { - SampleManager.SetMusicFadeVolume(volume); + SampleManager.SetMonoMode(mono); } void @@ -307,8 +309,10 @@ cAudioManager::DestroyAllGameCreatedEntities() } } +#ifdef GTA_PC + uint8 -cAudioManager::GetNum3DProvidersAvailable() const +cAudioManager::GetNum3DProvidersAvailable() { if (m_bIsInitialised) return SampleManager.GetNum3DProvidersAvailable(); @@ -316,7 +320,7 @@ cAudioManager::GetNum3DProvidersAvailable() const } char * -cAudioManager::Get3DProviderName(uint8 id) const +cAudioManager::Get3DProviderName(uint8 id) { if (!m_bIsInitialised) return nil; @@ -331,7 +335,7 @@ cAudioManager::Get3DProviderName(uint8 id) const } int8 -cAudioManager::GetCurrent3DProviderIndex() const +cAudioManager::GetCurrent3DProviderIndex() { if (m_bIsInitialised) return SampleManager.GetCurrent3DProviderIndex(); @@ -363,13 +367,13 @@ cAudioManager::SetCurrent3DProvider(uint8 which) } void -cAudioManager::SetSpeakerConfig(int32 conf) const +cAudioManager::SetSpeakerConfig(int32 conf) { SampleManager.SetSpeakerConfig(conf); } bool8 -cAudioManager::IsMP3RadioChannelAvailable() const +cAudioManager::IsMP3RadioChannelAvailable() { if (m_bIsInitialised) return SampleManager.IsMP3RadioChannelAvailable(); @@ -378,7 +382,7 @@ cAudioManager::IsMP3RadioChannelAvailable() const } void -cAudioManager::ReleaseDigitalHandle() const +cAudioManager::ReleaseDigitalHandle() { if (m_bIsInitialised) { SampleManager.ReleaseDigitalHandle(); @@ -386,7 +390,7 @@ cAudioManager::ReleaseDigitalHandle() const } void -cAudioManager::ReacquireDigitalHandle() const +cAudioManager::ReacquireDigitalHandle() { if (m_bIsInitialised) { SampleManager.ReacquireDigitalHandle(); @@ -400,13 +404,13 @@ cAudioManager::SetDynamicAcousticModelingStatus(bool8 status) } bool8 -cAudioManager::CheckForAnAudioFileOnCD() const +cAudioManager::CheckForAnAudioFileOnCD() { return SampleManager.CheckForAnAudioFileOnCD(); } char -cAudioManager::GetCDAudioDriveLetter() const +cAudioManager::GetCDAudioDriveLetter() { if (m_bIsInitialised) return SampleManager.GetCDAudioDriveLetter(); @@ -415,11 +419,13 @@ cAudioManager::GetCDAudioDriveLetter() const } bool8 -cAudioManager::IsAudioInitialised() const +cAudioManager::IsAudioInitialised() { return m_bIsInitialised; } +#endif // GTA_PC + void cAudioManager::ServiceSoundEffects() { @@ -469,8 +475,14 @@ cAudioManager::ServiceSoundEffects() m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; } +uint32 +cAudioManager::FL(float f) +{ + return SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) * f; +} + uint8 -cAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const +cAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) { float newSoundIntensity; if (soundIntensity <= 0.0f) @@ -482,7 +494,7 @@ cAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float d } void -cAudioManager::TranslateEntity(Const CVector *in, CVector *out) const +cAudioManager::TranslateEntity(Const CVector *in, CVector *out) { *out = MultiplyInverse(TheCamera.GetMatrix(), *in); } @@ -501,7 +513,7 @@ cAudioManager::ComputePan(float dist, CVector *vec) } int32 -cAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const +cAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) { uint32 newFreq = oldFreq; if (!TheCamera.Get_Just_Switched_Status() && speedMultiplier != 0.0f) { @@ -522,7 +534,7 @@ cAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, } int32 -cAudioManager::RandomDisplacement(uint32 seed) const +cAudioManager::RandomDisplacement(uint32 seed) { int32 value; @@ -593,6 +605,7 @@ cAudioManager::AddSampleToRequestedQueue() AddReflectionsToRequestedQueue(); } } + void cAudioManager::AddDetailsToRequestedOrderList(uint8 sample) { @@ -610,6 +623,7 @@ cAudioManager::AddDetailsToRequestedOrderList(uint8 sample) m_abSampleQueueIndexTable[m_nActiveSampleQueue][i] = sample; } +#ifdef GTA_PC void cAudioManager::AddReflectionsToRequestedQueue() { @@ -687,6 +701,7 @@ cAudioManager::UpdateReflections() m_afReflectionsDistances[4] = 50.0f; } } +#endif // GTA_PC void cAudioManager::AddReleasingSounds() @@ -965,6 +980,13 @@ cAudioManager::ClearActiveSamples() } void +cAudioManager::LoadBankIfNecessary(uint8 bank) +{ + if(!SampleManager.IsSampleBankLoaded(bank)) + SampleManager.LoadSampleBank(bank); +} + +void cAudioManager::GenerateIntegerRandomNumberTable() { for (int32 i = 0; i < ARRAY_SIZE(m_anRandomTable); i++) { @@ -993,4 +1015,4 @@ cAudioManager::ComputeEmittingVolume(uint8 emittingVolume, float intensity, floa return (quatIntensity - (dist - diffIntensity)) * (float)emittingVolume / quatIntensity; return emittingVolume; } -#endif
\ No newline at end of file +#endif diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 70302745..7c591a1e 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -20,8 +20,8 @@ public: #ifndef GTA_PS2 int32 m_nLoopStart; int32 m_nLoopEnd; -#endif uint8 m_nEmittingVolume; +#endif float m_fSpeedMultiplier; float m_fSoundIntensity; bool8 m_bReleasingSoundFlag; @@ -183,6 +183,9 @@ enum { MAX_REFLECTIONS, }; +enum PLAY_STATUS { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING, PLAY_STATUS_FINISHED }; +enum LOADING_STATUS { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED, LOADING_STATUS_FAILED }; + class cAudioManager { public: @@ -204,8 +207,10 @@ public: tAudioEntity m_asAudioEntities[NUM_AUDIOENTITIES]; int32 m_anAudioEntityIndices[NUM_AUDIOENTITIES]; int32 m_nAudioEntitiesTotal; +#ifdef GTA_PC CVector m_avecReflectionsPos[NUM_AUDIO_REFLECTIONS]; float m_afReflectionsDistances[NUM_AUDIO_REFLECTIONS]; +#endif cAudioScriptObjectManager m_sAudioScriptObjectManager; cPedComments m_sPedComments; int32 m_nFireAudioEntity; @@ -227,277 +232,279 @@ public: cAudioManager(); ~cAudioManager(); - // getters - uint32 GetFrameCounter() const { return m_FrameCounter; } - float GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; } - int32 GetRandomNumber(int32 idx) const { return m_anRandomTable[idx]; } - int32 GetRandomNumberInRange(int32 idx, int32 low, int32 high) const { return (m_anRandomTable[idx] % (high - low + 1)) + low; } - bool8 ShouldDuckMissionAudio() const { return m_sMissionAudio.m_nPlayStatus == 1; } - - // "Should" be in alphabetic order, except "getXTalkSfx" - void AddDetailsToRequestedOrderList(uint8 sample); - void AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, - uint8 counter, bool8 notLooping); - void AddReflectionsToRequestedQueue(); - void AddReleasingSounds(); - void AddSampleToRequestedQueue(); - void AgeCrimes(); - - void CalculateDistance(bool8 &condition, float dist); - bool8 CheckForAnAudioFileOnCD() const; - void ClearActiveSamples(); - void ClearMissionAudio(); - void ClearRequestedQueue(); - int32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, - float speedMultiplier) const; - int32 ComputePan(float, CVector *); - uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const; + void Initialise(); + void Terminate(); + void Service(); int32 CreateEntity(eAudioType type, void *entity); - - void DestroyAllGameCreatedEntities(); void DestroyEntity(int32 id); - void DoPoliceRadioCrackle(); + void SetEntityStatus(int32 id, bool8 status); + void PlayOneShot(int32 index, uint16 sound, float vol); + void SetEffectsMasterVolume(uint8 volume); + void SetMusicMasterVolume(uint8 volume); + void SetEffectsFadeVol(uint8 volume); + void SetMusicFadeVol(uint8 volume); + void SetMonoMode(bool8 mono); + void ResetTimers(uint32 time); + void DestroyAllGameCreatedEntities(); - // functions returning talk sfx, - // order from GetPedCommentSfx - uint32 GetPlayerTalkSfx(int16 sound); - uint32 GetCopTalkSfx(int16 sound); - uint32 GetSwatTalkSfx(int16 sound); - uint32 GetFBITalkSfx(int16 sound); - uint32 GetArmyTalkSfx(int16 sound); - uint32 GetMedicTalkSfx(int16 sound); - uint32 GetFiremanTalkSfx(int16 sound); - uint32 GetNormalMaleTalkSfx(int16 sound); - uint32 GetTaxiDriverTalkSfx(int16 sound); - uint32 GetPimpTalkSfx(int16 sound); - uint32 GetMafiaTalkSfx(int16 sound); - uint32 GetTriadTalkSfx(int16 sound); - uint32 GetDiabloTalkSfx(int16 sound); - uint32 GetYakuzaTalkSfx(int16 sound); - uint32 GetYardieTalkSfx(int16 sound); - uint32 GetColumbianTalkSfx(int16 sound); - uint32 GetHoodTalkSfx(int16 sound); - uint32 GetBlackCriminalTalkSfx(int16 sound); - uint32 GetWhiteCriminalTalkSfx(int16 sound); - uint32 GetMaleNo2TalkSfx(int16 sound); - uint32 GetBlackProjectMaleTalkSfx(int16 sound, int32 model); - uint32 GetWhiteFatMaleTalkSfx(int16 sound); - uint32 GetBlackFatMaleTalkSfx(int16 sound); - uint32 GetBlackCasualFemaleTalkSfx(int16 sound); - uint32 GetWhiteCasualFemaleTalkSfx(int16 sound); - uint32 GetFemaleNo3TalkSfx(int16 sound); - uint32 GetBlackFatFemaleTalkSfx(int16 sound); - uint32 GetWhiteFatFemaleTalkSfx(int16 sound); - uint32 GetBlackFemaleProstituteTalkSfx(int16 sound); - uint32 GetWhiteFemaleProstituteTalkSfx(int16 sound); - uint32 GetBlackProjectFemaleOldTalkSfx(int16 sound); - uint32 GetBlackProjectFemaleYoungTalkSfx(int16 sound); - uint32 GetChinatownMaleOldTalkSfx(int16 sound); - uint32 GetChinatownMaleYoungTalkSfx(int16 sound); - uint32 GetChinatownFemaleOldTalkSfx(int16 sound); - uint32 GetChinatownFemaleYoungTalkSfx(int16 sound); - uint32 GetLittleItalyMaleTalkSfx(int16 sound); - uint32 GetLittleItalyFemaleOldTalkSfx(int16 sound); - uint32 GetLittleItalyFemaleYoungTalkSfx(int16 sound); - uint32 GetWhiteDockerMaleTalkSfx(int16 sound); - uint32 GetBlackDockerMaleTalkSfx(int16 sound); - uint32 GetScumMaleTalkSfx(int16 sound); - uint32 GetScumFemaleTalkSfx(int16 sound); - uint32 GetWhiteWorkerMaleTalkSfx(int16 sound); - uint32 GetBlackWorkerMaleTalkSfx(int16 sound); - uint32 GetBusinessMaleYoungTalkSfx(int16 sound, int32 model); - uint32 GetBusinessMaleOldTalkSfx(int16 sound); - uint32 GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model); - uint32 GetBlackBusinessFemaleTalkSfx(int16 sound); - uint32 GetSupermodelMaleTalkSfx(int16 sound); - uint32 GetSupermodelFemaleTalkSfx(int16 sound); - uint32 GetStewardMaleTalkSfx(int16 sound); - uint32 GetStewardFemaleTalkSfx(int16 sound); - uint32 GetFanMaleTalkSfx(int16 sound, int32 model); - uint32 GetFanFemaleTalkSfx(int16 sound); - uint32 GetHospitalMaleTalkSfx(int16 sound); - uint32 GetHospitalFemaleTalkSfx(int16 sound); - uint32 GetWhiteConstructionWorkerTalkSfx(int16 sound); - uint32 GetBlackConstructionWorkerTalkSfx(int16 sound); - uint32 GetShopperFemaleTalkSfx(int16 sound, int32 model); - uint32 GetStudentMaleTalkSfx(int16 sound); - uint32 GetStudentFemaleTalkSfx(int16 sound); - uint32 GetCasualMaleOldTalkSfx(int16 sound); - - uint32 GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound); - uint32 GetEightTalkSfx(int16 sound); - uint32 GetFrankieTalkSfx(int16 sound); - uint32 GetMistyTalkSfx(int16 sound); - uint32 GetOJGTalkSfx(int16 sound); - uint32 GetCatatalinaTalkSfx(int16 sound); - uint32 GetBomberTalkSfx(int16 sound); - uint32 GetSecurityGuardTalkSfx(int16 sound); - uint32 GetChunkyTalkSfx(int16 sound); - - uint32 GetGenericMaleTalkSfx(int16 sound); - uint32 GetGenericFemaleTalkSfx(int16 sound); - // end of functions returning talk sfx - - void GenerateIntegerRandomNumberTable(); - char *Get3DProviderName(uint8 id) const; - char GetCDAudioDriveLetter() const; - int8 GetCurrent3DProviderIndex() const; - float GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const; // not used - float GetCollisionOneShotRatio(int32 a, float b) const; - float GetCollisionRatio(float a, float b, float c, float d) const; - float GetDistanceSquared(const CVector &v) const; - int32 GetJumboTaxiFreq() const; - uint8 GetMissionAudioLoadingStatus() const; - int8 GetMissionScriptPoliceAudioPlayingStatus() const; - uint8 GetNum3DProvidersAvailable() const; - int32 GetPedCommentSfx(CPed *ped, int32 sound); - void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const; - float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, - cTransmission *transmission, float velocityChange); - float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, - cTransmission *transmission, float velocityChange); - - bool8 HasAirBrakes(int32 model) const; +#ifdef GTA_PC + uint8 GetNum3DProvidersAvailable(); + char *Get3DProviderName(uint8 id); + int8 GetCurrent3DProviderIndex(); + int8 SetCurrent3DProvider(uint8 which); + void SetSpeakerConfig(int32 conf); + bool8 IsMP3RadioChannelAvailable(); + void ReleaseDigitalHandle(); + void ReacquireDigitalHandle(); + void SetDynamicAcousticModelingStatus(bool8 status); + bool8 CheckForAnAudioFileOnCD(); + char GetCDAudioDriveLetter(); + bool8 IsAudioInitialised(); +#endif - void Initialise(); - void InitialisePoliceRadio(); - void InitialisePoliceRadioZones(); - void InterrogateAudioEntities(); - bool8 IsAudioInitialised() const; - bool8 IsMissionAudioSampleFinished(); - bool8 IsMP3RadioChannelAvailable() const; + void ServiceSoundEffects(); + uint32 FL(float f); // not used + uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance); + void TranslateEntity(Const CVector *v1, CVector *v2); + int32 ComputePan(float, CVector *); + int32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier); // inlined on PS2 + int32 RandomDisplacement(uint32 seed); + void InterrogateAudioEntities(); // inlined on PS2 + void AddSampleToRequestedQueue(); + void AddDetailsToRequestedOrderList(uint8 sample); // inlined on PS2 +#ifdef GTA_PC + void AddReflectionsToRequestedQueue(); + void UpdateReflections(); +#endif + void AddReleasingSounds(); + void ProcessActiveQueues(); + void ClearRequestedQueue(); // inlined on PS2 + void ClearActiveSamples(); + void GenerateIntegerRandomNumberTable(); // inlined on PS2 + void LoadBankIfNecessary(uint8 bank); // this is used only on PS2 but technically not a platform code - bool8 MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; +#ifdef GTA_PC + void AdjustSamplesVolume(); + uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); +#endif - void PlayLoadedMissionAudio(); - void PlayOneShot(int32 index, uint16 sound, float vol); - void PlaySuspectLastSeen(float x, float y, float z); - void PlayerJustGotInCar() const; - void PlayerJustLeftCar() const; + // audio logic + void PreInitialiseGameSpecificSetup(); void PostInitialiseGameSpecificSetup(); - void PostTerminateGameSpecificShutdown(); - void PreInitialiseGameSpecificSetup() const; - void PreloadMissionAudio(Const char *name); void PreTerminateGameSpecificShutdown(); - /// processX - main logic of adding new sounds - void ProcessActiveQueues(); - bool8 ProcessAirBrakes(cVehicleParams& params); - void ProcessAirportScriptObject(uint8 sound); - bool8 ProcessBoatEngine(cVehicleParams& params); - bool8 ProcessBoatMovingOverWater(cVehicleParams& params); - void ProcessBridge(); - void ProcessBridgeMotor(); - void ProcessBridgeOneShots(); - void ProcessBridgeWarning(); - bool8 ProcessCarBombTick(cVehicleParams& params); - void ProcessCesna(cVehicleParams& params); - void ProcessCinemaScriptObject(uint8 sound); - void ProcessCrane(); - void ProcessDocksScriptObject(uint8 sound); - bool8 ProcessEngineDamage(cVehicleParams& params); + void PostTerminateGameSpecificShutdown(); + void ResetAudioLogicTimers(uint32 timer); + void ProcessReverb(); + float GetDistanceSquared(const CVector &v); + void CalculateDistance(bool8 &condition, float dist); + void ProcessSpecial(); void ProcessEntity(int32 sound); - void ProcessExplosions(int32 explosion); - void ProcessFireHydrant(); - void ProcessFires(int32 entity); - void ProcessFrontEnd(); - void ProcessGarages(); - bool8 ProcessHelicopter(cVehicleParams& params); - void ProcessHomeScriptObject(uint8 sound); - void ProcessJumbo(cVehicleParams& params); + void ProcessPhysical(int32 id); + void ProcessVehicle(CVehicle *vehicle); + void ProcessRainOnVehicle(cVehicleParams ¶ms); + bool8 ProcessReverseGear(cVehicleParams ¶ms); + void ProcessModelCarEngine(cVehicleParams ¶ms); + bool8 ProcessVehicleRoadNoise(cVehicleParams ¶ms); + bool8 ProcessWetRoadNoise(cVehicleParams ¶ms); + + // vehicles + void ProcessVehicleEngine(cVehicleParams ¶ms); + void UpdateGasPedalAudio(CAutomobile *automobile); // inlined on PS2 + void PlayerJustGotInCar(); + void PlayerJustLeftCar(); + void AddPlayerCarSample(uint8 emittingVolume, uint32 freq, uint32 sample, uint8 bank, uint8 counter, bool8 notLooping); + void ProcessCesna(cVehicleParams ¶ms); + void ProcessPlayersVehicleEngine(cVehicleParams ¶ms, CAutomobile *automobile); + bool8 ProcessVehicleSkidding(cVehicleParams ¶ms); + float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange); + float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange); // was in .h on PS2 + void ProcessVehicleHorn(cVehicleParams ¶ms); + bool8 UsesSiren(uint32 model); // inlined on PS2 + bool8 UsesSirenSwitching(uint32 model); // inlined on PS2 + bool8 ProcessVehicleSirenOrAlarm(cVehicleParams ¶ms); + bool8 UsesReverseWarning(uint32 model); // inlined on PS2 + bool8 ProcessVehicleReverseWarning(cVehicleParams ¶ms); + bool8 ProcessVehicleDoors(cVehicleParams ¶ms); + bool8 ProcessAirBrakes(cVehicleParams ¶ms); + bool8 HasAirBrakes(uint32 model); // inlined on PS2 + bool8 ProcessEngineDamage(cVehicleParams ¶ms); + bool8 ProcessCarBombTick(cVehicleParams ¶ms); + void ProcessVehicleOneShots(cVehicleParams ¶ms); + bool8 ProcessTrainNoise(cVehicleParams ¶ms); + bool8 ProcessBoatEngine(cVehicleParams ¶ms); + bool8 ProcessBoatMovingOverWater(cVehicleParams ¶ms); + bool8 ProcessHelicopter(cVehicleParams ¶ms); + void ProcessPlane(cVehicleParams ¶ms); // inlined on PS2 + void ProcessJumbo(cVehicleParams ¶ms); + void ProcessJumboTaxi(); // inlined on PS2 void ProcessJumboAccel(CPlane *plane); - void ProcessJumboDecel(CPlane *plane); - void ProcessJumboFlying(); - void ProcessJumboLanding(CPlane *plane); - void ProcessJumboTakeOff(CPlane *plane); - void ProcessJumboTaxi(); - void ProcessLaunderetteScriptObject(uint8 sound); - void ProcessLoopingScriptObject(uint8 sound); - void ProcessMissionAudio(); - void ProcessModelCarEngine(cVehicleParams& params); - void ProcessOneShotScriptObject(uint8 sound); - void ProcessPed(CPhysical *ped); + void ProcessJumboTakeOff(CPlane *plane); // inlined on PS2 + void ProcessJumboFlying(); // inlined on PS2 + void ProcessJumboLanding(CPlane *plane); // inlined on PS2 + void ProcessJumboDecel(CPlane *plane); // inlined on PS2 + bool8 SetupJumboTaxiSound(uint8 vol); + bool8 SetupJumboWhineSound(uint8 emittingVol, uint32 freq); + bool8 SetupJumboEngineSound(uint8 vol, uint32 freq); + bool8 SetupJumboFlySound(uint8 emittingVol); + bool8 SetupJumboRumbleSound(uint8 emittingVol); + int32 GetJumboTaxiFreq(); // inlined on PS2 + + // peds + void ProcessPed(CPhysical *ped); // inlined on PS2 void ProcessPedHeadphones(cPedParams ¶ms); void ProcessPedOneShots(cPedParams ¶ms); - void ProcessPhysical(int32 id); - void ProcessPlane(cVehicleParams& params); - void ProcessPlayersVehicleEngine(cVehicleParams& params, CAutomobile *automobile); - void ProcessPoliceCellBeatingScriptObject(uint8 sound); + + // ped comments + void SetupPedComments(cPedParams ¶ms, uint16 sound); + int32 GetPedCommentSfx(CPed *ped, uint16 sound); + void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset); // inlined on PS2 + uint32 GetPlayerTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetCopTalkSfx(uint16 sound); + uint32 GetSwatTalkSfx(uint16 sound); + uint32 GetFBITalkSfx(uint16 sound); + uint32 GetArmyTalkSfx(uint16 sound); + uint32 GetMedicTalkSfx(uint16 sound); + uint32 GetFiremanTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetBusinessMaleOldTalkSfx(uint16 sound); + uint32 GetBusinessMaleYoungTalkSfx(uint16 sound, uint32 model); + uint32 GetMafiaTalkSfx(uint16 sound); + uint32 GetTriadTalkSfx(uint16 sound); + uint32 GetDiabloTalkSfx(uint16 sound); + uint32 GetYakuzaTalkSfx(uint16 sound); + uint32 GetYardieTalkSfx(uint16 sound); + uint32 GetColumbianTalkSfx(uint16 sound); + uint32 GetHoodTalkSfx(uint16 sound); + uint32 GetBlackCriminalTalkSfx(uint16 sound); + uint32 GetWhiteCriminalTalkSfx(uint16 sound); + uint32 GetCasualMaleOldTalkSfx(uint16 sound); + uint32 GetCasualMaleYoungTalkSfx(uint16 sound); + uint32 GetBlackCasualFemaleTalkSfx(uint16 sound); + uint32 GetWhiteCasualFemaleTalkSfx(uint16 sound); + uint32 GetFemaleNo3TalkSfx(uint16 sound); + uint32 GetWhiteBusinessFemaleTalkSfx(uint16 sound, uint32 model); + uint32 GetBlackFatFemaleTalkSfx(uint16 sound); + uint32 GetWhiteFatMaleTalkSfx(uint16 sound); + uint32 GetBlackFatMaleTalkSfx(uint16 sound); + uint32 GetWhiteFatFemaleTalkSfx(uint16 sound); + uint32 GetBlackFemaleProstituteTalkSfx(uint16 sound); + uint32 GetWhiteFemaleProstituteTalkSfx(uint16 sound); + uint32 GetBlackProjectMaleTalkSfx(uint16 sound, uint32 model); + uint32 GetBlackProjectFemaleOldTalkSfx(uint16 sound); + uint32 GetBlackProjectFemaleYoungTalkSfx(uint16 sound); + uint32 GetChinatownMaleOldTalkSfx(uint16 sound); + uint32 GetChinatownMaleYoungTalkSfx(uint16 sound); + uint32 GetChinatownFemaleOldTalkSfx(uint16 sound); + uint32 GetChinatownFemaleYoungTalkSfx(uint16 sound); + uint32 GetLittleItalyMaleTalkSfx(uint16 sound); + uint32 GetLittleItalyFemaleOldTalkSfx(uint16 sound); + uint32 GetLittleItalyFemaleYoungTalkSfx(uint16 sound); + uint32 GetWhiteDockerMaleTalkSfx(uint16 sound); + uint32 GetBlackDockerMaleTalkSfx(uint16 sound); + uint32 GetScumMaleTalkSfx(uint16 sound); + uint32 GetScumFemaleTalkSfx(uint16 sound); + uint32 GetWhiteWorkerMaleTalkSfx(uint16 sound); + uint32 GetBlackWorkerMaleTalkSfx(uint16 sound); + uint32 GetBlackBusinessFemaleTalkSfx(uint16 sound); + uint32 GetSupermodelMaleTalkSfx(uint16 sound); + uint32 GetSupermodelFemaleTalkSfx(uint16 sound); + uint32 GetStewardMaleTalkSfx(uint16 sound); + uint32 GetStewardFemaleTalkSfx(uint16 sound); + uint32 GetFanMaleTalkSfx(uint16 sound, uint32 model); + uint32 GetFanFemaleTalkSfx(uint16 sound); + uint32 GetHospitalMaleTalkSfx(uint16 sound); + uint32 GetHospitalFemaleTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetWhiteConstructionWorkerTalkSfx(uint16 sound); + uint32 GetBlackConstructionWorkerTalkSfx(uint16 sound); + uint32 GetShopperFemaleTalkSfx(uint16 sound, uint32 model); + uint32 GetStudentMaleTalkSfx(uint16 sound); + uint32 GetStudentFemaleTalkSfx(uint16 sound); + + uint32 GetSpecialCharacterTalkSfx(uint32 modelIndex, uint16 sound); + uint32 GetEightBallTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetSalvatoreTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetMistyTalkSfx(uint16 sound); + uint32 GetOldJapTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetCatalinaTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetBomberTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetSecurityGuardTalkSfx(uint16 sound); + uint32 GetChunkyTalkSfx(uint16 sound); // inlined on PS2 + + uint32 GetAsianTaxiDriverTalkSfx(uint16 sound); // inlined on PS2 + uint32 GetPimpTalkSfx(uint16 sound); + uint32 GetNormalMaleTalkSfx(uint16 sound); + uint32 GetGenericMaleTalkSfx(uint16 sound); + uint32 GetGenericFemaleTalkSfx(uint16 sound); + + // particles + void ProcessExplosions(int32 explosion); + void ProcessFires(int32 entity); + void ProcessWaterCannon(int32); + + // script objects + void ProcessScriptObject(int32 id); // inlined on PS2 + void ProcessOneShotScriptObject(uint8 sound); + void ProcessLoopingScriptObject(uint8 sound); void ProcessPornCinema(uint8 sound); - void ProcessProjectiles(); - void ProcessRainOnVehicle(cVehicleParams& params); - void ProcessReverb() const; - bool8 ProcessReverseGear(cVehicleParams& params); + void ProcessWorkShopScriptObject(uint8 sound); void ProcessSawMillScriptObject(uint8 sound); - void ProcessScriptObject(int32 id); + void ProcessLaunderetteScriptObject(uint8 sound); void ProcessShopScriptObject(uint8 sound); - void ProcessSpecial(); - bool8 ProcessTrainNoise(cVehicleParams& params); - void ProcessVehicle(CVehicle *vehicle); - bool8 ProcessVehicleDoors(cVehicleParams& params); - void ProcessVehicleEngine(cVehicleParams& params); - void ProcessVehicleHorn(cVehicleParams& params); - void ProcessVehicleOneShots(cVehicleParams& params); - bool8 ProcessVehicleReverseWarning(cVehicleParams& params); - bool8 ProcessVehicleRoadNoise(cVehicleParams& params); - bool8 ProcessVehicleSirenOrAlarm(cVehicleParams& params); - bool8 ProcessVehicleSkidding(cVehicleParams& params); - void ProcessWaterCannon(int32); + void ProcessAirportScriptObject(uint8 sound); + void ProcessCinemaScriptObject(uint8 sound); + void ProcessDocksScriptObject(uint8 sound); + void ProcessHomeScriptObject(uint8 sound); + void ProcessPoliceCellBeatingScriptObject(uint8 sound); + + // misc void ProcessWeather(int32 id); - bool8 ProcessWetRoadNoise(cVehicleParams& params); - void ProcessWorkShopScriptObject(uint8 sound); + void ProcessFrontEnd(); + void ProcessCrane(); + void ProcessProjectiles(); + void ProcessGarages(); + void ProcessFireHydrant(); - int32 RandomDisplacement(uint32 seed) const; - void ReacquireDigitalHandle() const; - void ReleaseDigitalHandle() const; - void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, - float collisionPower, float intensity2); - void ReportCrime(eCrimeType crime, const CVector &pos); - void ResetAudioLogicTimers(uint32 timer); - void ResetPoliceRadio(); - void ResetTimers(uint32 time); + // bridge + void ProcessBridge(); // inlined on PS2 + void ProcessBridgeWarning(); + void ProcessBridgeMotor(); + void ProcessBridgeOneShots(); - void Service(); - void ServiceCollisions(); + // mission audio + bool8 MissionScriptAudioUsesPoliceChannel(uint32 soundMission); + void PreloadMissionAudio(Const char *name); + uint8 GetMissionAudioLoadingStatus(); + void SetMissionAudioLocation(float x, float y, float z); + void PlayLoadedMissionAudio(); + bool8 IsMissionAudioSampleFinished(); + bool8 IsMissionAudioSamplePlaying() { return m_sMissionAudio.m_nPlayStatus == PLAY_STATUS_PLAYING; } + bool8 ShouldDuckMissionAudio() { return IsMissionAudioSamplePlaying(); } + void ClearMissionAudio(); + void ProcessMissionAudio(); + + // police radio + void InitialisePoliceRadioZones(); + void InitialisePoliceRadio(); + void ResetPoliceRadio(); + void SetMissionScriptPoliceAudio(int32 sfx); + int8 GetMissionScriptPoliceAudioPlayingStatus(); + void DoPoliceRadioCrackle(); void ServicePoliceRadio(); void ServicePoliceRadioChannel(uint8 wantedLevel); - void ServiceSoundEffects(); - int8 SetCurrent3DProvider(uint8 which); - void SetDynamicAcousticModelingStatus(bool8 status); - void SetEffectsFadeVol(uint8 volume) const; - void SetEffectsMasterVolume(uint8 volume) const; - void SetEntityStatus(int32 id, bool8 status); - uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision); - void SetMissionAudioLocation(float x, float y, float z); - void SetMissionScriptPoliceAudio(int32 sfx) const; - void SetMonoMode(bool8 mono); - void SetMusicFadeVol(uint8 volume) const; - void SetMusicMasterVolume(uint8 volume) const; - void SetSpeakerConfig(int32 conf) const; - void SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter); - void SetUpOneShotCollisionSound(const cAudioCollision &col); bool8 SetupCrimeReport(); - bool8 SetupJumboEngineSound(uint8 vol, uint32 freq); - bool8 SetupJumboFlySound(uint8 emittingVol); - bool8 SetupJumboRumbleSound(uint8 emittingVol); - bool8 SetupJumboTaxiSound(uint8 vol); - bool8 SetupJumboWhineSound(uint8 emittingVol, uint32 freq); - void SetupPedComments(cPedParams ¶ms, uint16 sound); void SetupSuspectLastSeenReport(); - - void Terminate(); - void TranslateEntity(Const CVector *v1, CVector *v2) const; - - void UpdateGasPedalAudio(CAutomobile *automobile); - void UpdateReflections(); - bool8 UsesReverseWarning(int32 model) const; - bool8 UsesSiren(int32 model) const; - bool8 UsesSirenSwitching(int32 model) const; - -#ifdef GTA_PC - // only used in pc - void AdjustSamplesVolume(); - uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); -#endif + void ReportCrime(eCrimeType crime, const CVector &pos); + void PlaySuspectLastSeen(float x, float y, float z); + void AgeCrimes(); // inlined on PS2 + + // collision stuff + void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, float intensity2); + void ServiceCollisions(); + void SetUpOneShotCollisionSound(const cAudioCollision &col); + void SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter); + uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision); + float GetCollisionOneShotRatio(uint32 a, float b); + float GetCollisionLoopingRatio(uint32 a, uint32 b, float c); // not used + float GetCollisionRatio(float a, float b, float c, float d); // inlined on PS2 }; /* diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index cb441622..815e55f2 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -236,23 +236,23 @@ cMusicManager::Initialise() if (!IsInitialised()) { time_t timevalue = time(0); if (timevalue == -1) { - pos = AudioManager.GetRandomNumber(0); + pos = AudioManager.m_anRandomTable[0]; } else { tm *pTm = localtime(&timevalue); if (pTm->tm_sec == 0) - pTm->tm_sec = AudioManager.GetRandomNumber(0); + pTm->tm_sec = AudioManager.m_anRandomTable[0]; if (pTm->tm_min == 0) - pTm->tm_min = AudioManager.GetRandomNumber(1); + pTm->tm_min = AudioManager.m_anRandomTable[1]; if (pTm->tm_hour == 0) - pTm->tm_hour = AudioManager.GetRandomNumber(2); + pTm->tm_hour = AudioManager.m_anRandomTable[2]; if (pTm->tm_mday == 0) - pTm->tm_mday = AudioManager.GetRandomNumber(3); + pTm->tm_mday = AudioManager.m_anRandomTable[3]; if (pTm->tm_mon == 0) - pTm->tm_mon = AudioManager.GetRandomNumber(4); + pTm->tm_mon = AudioManager.m_anRandomTable[4]; if (pTm->tm_year == 0) - pTm->tm_year = AudioManager.GetRandomNumber(3); + pTm->tm_year = AudioManager.m_anRandomTable[3]; if (pTm->tm_wday == 0) - pTm->tm_wday = AudioManager.GetRandomNumber(2); + pTm->tm_wday = AudioManager.m_anRandomTable[2]; pos = pTm->tm_yday * pTm->tm_wday * pTm->tm_year @@ -265,7 +265,7 @@ cMusicManager::Initialise() for (int i = 0; i < TOTAL_STREAMED_SOUNDS; i++) { m_aTracks[i].m_nLength = SampleManager.GetStreamedFileLength(i); - m_aTracks[i].m_nPosition = pos * AudioManager.GetRandomNumber(i % 5) % m_aTracks[i].m_nLength; + m_aTracks[i].m_nPosition = pos * AudioManager.m_anRandomTable[i % 5] % m_aTracks[i].m_nLength; m_aTracks[i].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode(); } @@ -949,7 +949,7 @@ cMusicManager::GetCarTuning() if (veh == nil) return RADIO_OFF; if (UsesPoliceRadio(veh)) return POLICE_RADIO; if (veh->m_nRadioStation == USERTRACK && !SampleManager.IsMP3RadioChannelAvailable()) - veh->m_nRadioStation = AudioManager.GetRandomNumber(2) % USERTRACK; + veh->m_nRadioStation = AudioManager.m_anRandomTable[2] % USERTRACK; return veh->m_nRadioStation; } diff --git a/src/audio/PolRadio.cpp b/src/audio/PolRadio.cpp index 235a53d3..9a98de35 100644 --- a/src/audio/PolRadio.cpp +++ b/src/audio/PolRadio.cpp @@ -106,7 +106,7 @@ cAudioManager::ResetPoliceRadio() } void -cAudioManager::SetMissionScriptPoliceAudio(int32 sfx) const +cAudioManager::SetMissionScriptPoliceAudio(int32 sfx) { if (!m_bIsInitialised) return; if (g_nMissionAudioPlayingStatus != 1) { @@ -116,7 +116,7 @@ cAudioManager::SetMissionScriptPoliceAudio(int32 sfx) const } int8 -cAudioManager::GetMissionScriptPoliceAudioPlayingStatus() const +cAudioManager::GetMissionScriptPoliceAudioPlayingStatus() { return g_nMissionAudioPlayingStatus; } @@ -677,8 +677,6 @@ cAudioManager::SetupSuspectLastSeenReport() } } - - void cAudioManager::ReportCrime(eCrimeType type, const CVector &pos) { diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 0209202a..6afe8e30 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -2,7 +2,7 @@ #ifdef AUDIO_OAL -#if defined _MSC_VER && !defined RE3_NO_AUTOLINK +#if defined _MSC_VER && !defined CMAKE_NO_AUTOLINK #ifdef AUDIO_OAL_USE_SNDFILE #pragma comment( lib, "libsndfile-1.lib" ) #endif @@ -504,6 +504,7 @@ public: class CMP3File : public IDecoder { +protected: mpg123_handle *m_pMH; bool m_bOpened; uint32 m_nRate; diff --git a/src/audio/sampman.h b/src/audio/sampman.h index d1ad9a26..dc95622b 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -259,8 +259,8 @@ static char StreamedNameTable[][25] = { "AUDIO\\door_2.OPUS", "AUDIO\\door_3.OPUS", "AUDIO\\door_4.OPUS", "AUDIO\\door_5.OPUS", "AUDIO\\door_6.OPUS", "AUDIO\\t3_a.OPUS", "AUDIO\\t3_b.OPUS", "AUDIO\\t3_c.OPUS", "AUDIO\\k1_b.OPUS", "AUDIO\\cat1.OPUS"}; #else -#if defined(PS2_AUDIO_PATHS) -static char StreamedNameTable[][25]= +#ifdef PS2_AUDIO_PATHS +static char PS2StreamedNameTable[][25]= { "AUDIO\\MUSIC\\HEAD.VB", "AUDIO\\MUSIC\\CLASS.VB", @@ -357,7 +357,110 @@ static char StreamedNameTable[][25]= "AUDIO\\PHONE\\MT_PH4.VB", "AUDIO\\MUSIC\\MISCOM.VB", "AUDIO\\MUSIC\\END.VB", -#else + "AUDIO\\lib_a1.WAV", + "AUDIO\\lib_a2.WAV", + "AUDIO\\lib_a.WAV", + "AUDIO\\lib_b.WAV", + "AUDIO\\lib_c.WAV", + "AUDIO\\lib_d.WAV", + "AUDIO\\l2_a.WAV", + "AUDIO\\j4t_1.WAV", + "AUDIO\\j4t_2.WAV", + "AUDIO\\j4t_3.WAV", + "AUDIO\\j4t_4.WAV", + "AUDIO\\j4_a.WAV", + "AUDIO\\j4_b.WAV", + "AUDIO\\j4_c.WAV", + "AUDIO\\j4_d.WAV", + "AUDIO\\j4_e.WAV", + "AUDIO\\j4_f.WAV", + "AUDIO\\j6_1.WAV", + "AUDIO\\j6_a.WAV", + "AUDIO\\j6_b.WAV", + "AUDIO\\j6_c.WAV", + "AUDIO\\j6_d.WAV", + "AUDIO\\t4_a.WAV", + "AUDIO\\s1_a.WAV", + "AUDIO\\s1_a1.WAV", + "AUDIO\\s1_b.WAV", + "AUDIO\\s1_c.WAV", + "AUDIO\\s1_c1.WAV", + "AUDIO\\s1_d.WAV", + "AUDIO\\s1_e.WAV", + "AUDIO\\s1_f.WAV", + "AUDIO\\s1_g.WAV", + "AUDIO\\s1_h.WAV", + "AUDIO\\s1_i.WAV", + "AUDIO\\s1_j.WAV", + "AUDIO\\s1_k.WAV", + "AUDIO\\s1_l.WAV", + "AUDIO\\s3_a.WAV", + "AUDIO\\s3_b.WAV", + "AUDIO\\el3_a.WAV", + "AUDIO\\mf1_a.WAV", + "AUDIO\\mf2_a.WAV", + "AUDIO\\mf3_a.WAV", + "AUDIO\\mf3_b.WAV", + "AUDIO\\mf3_b1.WAV", + "AUDIO\\mf3_c.WAV", + "AUDIO\\mf4_a.WAV", + "AUDIO\\mf4_b.WAV", + "AUDIO\\mf4_c.WAV", + "AUDIO\\a1_a.WAV", + "AUDIO\\a3_a.WAV", + "AUDIO\\a5_a.WAV", + "AUDIO\\a4_a.WAV", + "AUDIO\\a4_b.WAV", + "AUDIO\\a4_c.WAV", + "AUDIO\\a4_d.WAV", + "AUDIO\\k1_a.WAV", + "AUDIO\\k3_a.WAV", + "AUDIO\\r1_a.WAV", + "AUDIO\\r2_a.WAV", + "AUDIO\\r2_b.WAV", + "AUDIO\\r2_c.WAV", + "AUDIO\\r2_d.WAV", + "AUDIO\\r2_e.WAV", + "AUDIO\\r2_f.WAV", + "AUDIO\\r2_g.WAV", + "AUDIO\\r2_h.WAV", + "AUDIO\\r5_a.WAV", + "AUDIO\\r6_a.WAV", + "AUDIO\\r6_a1.WAV", + "AUDIO\\r6_b.WAV", + "AUDIO\\lo2_a.WAV", + "AUDIO\\lo6_a.WAV", + "AUDIO\\yd2_a.WAV", + "AUDIO\\yd2_b.WAV", + "AUDIO\\yd2_c.WAV", + "AUDIO\\yd2_c1.WAV", + "AUDIO\\yd2_d.WAV", + "AUDIO\\yd2_e.WAV", + "AUDIO\\yd2_f.WAV", + "AUDIO\\yd2_g.WAV", + "AUDIO\\yd2_h.WAV", + "AUDIO\\yd2_ass.WAV", + "AUDIO\\yd2_ok.WAV", + "AUDIO\\h5_a.WAV", + "AUDIO\\h5_b.WAV", + "AUDIO\\h5_c.WAV", + "AUDIO\\ammu_a.WAV", + "AUDIO\\ammu_b.WAV", + "AUDIO\\ammu_c.WAV", + "AUDIO\\door_1.WAV", + "AUDIO\\door_2.WAV", + "AUDIO\\door_3.WAV", + "AUDIO\\door_4.WAV", + "AUDIO\\door_5.WAV", + "AUDIO\\door_6.WAV", + "AUDIO\\t3_a.WAV", + "AUDIO\\t3_b.WAV", + "AUDIO\\t3_c.WAV", + "AUDIO\\k1_b.WAV", + "AUDIO\\cat1.WAV" +}; +#endif + static char StreamedNameTable[][25] = { "AUDIO\\HEAD.WAV", @@ -455,7 +558,6 @@ static char StreamedNameTable[][25] = "AUDIO\\MT_PH4.MP3", "AUDIO\\MISCOM.WAV", "AUDIO\\END.MP3", -#endif "AUDIO\\lib_a1.WAV", "AUDIO\\lib_a2.WAV", "AUDIO\\lib_a.WAV", diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index e820864c..7c40d15d 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -992,11 +992,20 @@ cSampleManager::Initialise(void) if ( GetDriveType(m_szCDRomRootPath) == DRIVE_CDROM ) { + FILE *f; +#ifdef PS2_AUDIO_PATHS strcpy(filepath, m_szCDRomRootPath); - strcat(filepath, StreamedNameTable[0]); - - FILE *f = fopen(filepath, "rb"); + strcat(filepath, PS2StreamedNameTable[0]); + f = fopen(filepath, "rb"); + + if ( !f ) +#endif + { + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[0]); + f = fopen(filepath, "rb"); + } if ( f ) { fclose(f); @@ -1005,11 +1014,20 @@ cSampleManager::Initialise(void) for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) { +#ifdef PS2_AUDIO_PATHS strcpy(filepath, m_szCDRomRootPath); - strcat(filepath, StreamedNameTable[i]); - + strcat(filepath, PS2StreamedNameTable[i]); + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); - + if ( !mp3Stream[0] ) +#endif + { + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[i]); + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + } + if ( mp3Stream[0] ) { AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); @@ -1078,7 +1096,14 @@ cSampleManager::Initialise(void) strcpy(_aHDDPath, m_szCDRomRootPath); rootpath[0] = '\0'; - FILE *f = fopen(StreamedNameTable[0], "rb"); + FILE *f; + +#ifdef PS2_AUDIO_PATHS + f = fopen(PS2StreamedNameTable[0], "rb"); + if (!f) +#endif + + f = fopen(StreamedNameTable[0], "rb"); if ( f ) { @@ -1086,11 +1111,20 @@ cSampleManager::Initialise(void) for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) { +#ifdef PS2_AUDIO_PATHS strcpy(filepath, rootpath); - strcat(filepath, StreamedNameTable[i]); - + strcat(filepath, PS2StreamedNameTable[i]); + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); - + if ( !mp3Stream[0] ) +#endif + { + strcpy(filepath, rootpath); + strcat(filepath, StreamedNameTable[i]); + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + } + if ( mp3Stream[0] ) { AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); @@ -1211,7 +1245,7 @@ cSampleManager::Initialise(void) int32 randval; if ( bUseRandomTable ) - randval = AudioManager.GetRandomNumber(1); + randval = AudioManager.m_anRandomTable[1]; else randval = localtm->tm_sec * localtm->tm_min; @@ -1222,7 +1256,7 @@ cSampleManager::Initialise(void) randmp3 = randmp3->pNext; if ( bUseRandomTable ) - _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + _CurMP3Pos = AudioManager.m_anRandomTable[0] % randmp3->nTrackLength; else { if ( localtm->tm_sec > 0 ) @@ -1231,7 +1265,7 @@ cSampleManager::Initialise(void) _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; } else - _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + _CurMP3Pos = AudioManager.m_anRandomTable[0] % randmp3->nTrackLength; } } else @@ -1299,9 +1333,11 @@ cSampleManager::CheckForAnAudioFileOnCD(void) { #if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK) char filepath[MAX_PATH]; + FILE *f; +#ifdef PS2_AUDIO_PATHS #if GTA_VERSION >= GTA3_PC_11 - if (_bUseHDDAudio) + if(_bUseHDDAudio) strcpy(filepath, _aHDDPath); else strcpy(filepath, m_szCDRomRootPath); @@ -1309,10 +1345,25 @@ cSampleManager::CheckForAnAudioFileOnCD(void) strcpy(filepath, m_szCDRomRootPath); #endif // #if GTA_VERSION >= GTA3_PC_11 - strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]); - - FILE *f = fopen(filepath, "rb"); + strcat(filepath, PS2StreamedNameTable[AudioManager.m_anRandomTable[1] % TOTAL_STREAMED_SOUNDS]); + + f = fopen(filepath, "rb"); + if ( !f ) +#endif // PS2_AUDIO_PATHS + { +#if GTA_VERSION >= GTA3_PC_11 + if (_bUseHDDAudio) + strcpy(filepath, _aHDDPath); + else + strcpy(filepath, m_szCDRomRootPath); +#else + strcpy(filepath, m_szCDRomRootPath); +#endif // #if GTA_VERSION >= GTA3_PC_11 + + strcat(filepath, StreamedNameTable[AudioManager.m_anRandomTable[1] % TOTAL_STREAMED_SOUNDS]); + f = fopen(filepath, "rb"); + } if ( f ) { fclose(f); @@ -1580,12 +1631,12 @@ cSampleManager::UpdateReverb(void) if ( !usingEAX ) return FALSE; - if ( AudioManager.GetFrameCounter() & 15 ) + if ( AudioManager.m_FrameCounter & 15 ) return FALSE; - float y = AudioManager.GetReflectionsDistance(REFLECTION_TOP) + AudioManager.GetReflectionsDistance(REFLECTION_BOTTOM); - float x = AudioManager.GetReflectionsDistance(REFLECTION_LEFT) + AudioManager.GetReflectionsDistance(REFLECTION_RIGHT); - float z = AudioManager.GetReflectionsDistance(REFLECTION_UP); + float y = AudioManager.m_afReflectionsDistances[REFLECTION_TOP] + AudioManager.m_afReflectionsDistances[REFLECTION_BOTTOM]; + float x = AudioManager.m_afReflectionsDistances[REFLECTION_LEFT] + AudioManager.m_afReflectionsDistances[REFLECTION_RIGHT]; + float z = AudioManager.m_afReflectionsDistances[REFLECTION_UP]; float normy = norm(y, 5.0f, 40.0f); float normx = norm(x, 5.0f, 40.0f); @@ -2007,11 +2058,19 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) } char filepath[MAX_PATH]; - +#ifdef PS2_AUDIO_PATHS strcpy(filepath, m_szCDRomRootPath); - strcat(filepath, StreamedNameTable[nFile]); - + strcat(filepath, PS2StreamedNameTable[nFile]); + mp3Stream[nStream] = AIL_open_stream(DIG, filepath, 0); + if ( !mp3Stream[nStream] ) +#endif + { + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filepath, 0); + } if ( mp3Stream[nStream] ) { @@ -2073,10 +2132,19 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) // Try to continue from previous song, if already started if(!_GetMP3PosFromStreamPos(&position, &e) && !e) { nFile = 0; +#ifdef PS2_AUDIO_PATHS strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - + strcat(filename, PS2StreamedNameTable[nFile]); + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + if ( !mp3Stream[nStream] ) +#endif + { + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + } if ( mp3Stream[nStream] ) { AIL_set_stream_loop_count(mp3Stream[nStream], 1); @@ -2120,10 +2188,19 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) { nFile = 0; _bIsMp3Active = 0; +#ifdef PS2_AUDIO_PATHS strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - + strcat(filename, PS2StreamedNameTable[nFile]); + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + if ( !mp3Stream[nStream] ) +#endif + { + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + } if ( mp3Stream[nStream] ) { AIL_set_stream_loop_count(mp3Stream[nStream], 1); @@ -2161,10 +2238,19 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) position = 0; nFile = 0; } +#ifdef PS2_AUDIO_PATHS strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - + strcat(filename, PS2StreamedNameTable[nFile]); + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + if ( !mp3Stream[nStream] ) +#endif + { + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + } if ( mp3Stream[nStream] ) { AIL_set_stream_loop_count(mp3Stream[nStream], 1); diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index fdd449f7..17776347 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -894,7 +894,11 @@ cSampleManager::Initialise(void) for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) { - if ( aStream[0] && aStream[0]->Open(StreamedNameTable[i], IsThisTrackAt16KHz(i) ? 16000 : 32000) ) + if(aStream[0] && ( +#ifdef PS2_AUDIO_PATHS + aStream[0]->Open(PS2StreamedNameTable[i], IsThisTrackAt16KHz(i) ? 16000 : 32000) || +#endif + aStream[0]->Open(StreamedNameTable[i], IsThisTrackAt16KHz(i) ? 16000 : 32000))) { uint32 tatalms = aStream[0]->GetLengthMS(); aStream[0]->Close(); @@ -991,7 +995,7 @@ cSampleManager::Initialise(void) int32 randval; if ( bUseRandomTable ) - randval = AudioManager.GetRandomNumber(1); + randval = AudioManager.m_anRandomTable[1]; else randval = localtm->tm_sec * localtm->tm_min; @@ -1002,7 +1006,7 @@ cSampleManager::Initialise(void) randmp3 = randmp3->pNext; if ( bUseRandomTable ) - _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + _CurMP3Pos = AudioManager.m_anRandomTable[0] % randmp3->nTrackLength; else { if ( localtm->tm_sec > 0 ) @@ -1011,7 +1015,7 @@ cSampleManager::Initialise(void) _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; } else - _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + _CurMP3Pos = AudioManager.m_anRandomTable[0] % randmp3->nTrackLength; } } else @@ -1356,12 +1360,12 @@ bool8 cSampleManager::UpdateReverb(void) if ( !usingEAX && !_usingEFX ) return FALSE; - if ( AudioManager.GetFrameCounter() & 15 ) + if ( AudioManager.m_FrameCounter & 15 ) return FALSE; - float y = AudioManager.GetReflectionsDistance(REFLECTION_TOP) + AudioManager.GetReflectionsDistance(REFLECTION_BOTTOM); - float x = AudioManager.GetReflectionsDistance(REFLECTION_LEFT) + AudioManager.GetReflectionsDistance(REFLECTION_RIGHT); - float z = AudioManager.GetReflectionsDistance(REFLECTION_UP); + float y = AudioManager.m_afReflectionsDistances[REFLECTION_TOP] + AudioManager.m_afReflectionsDistances[REFLECTION_BOTTOM]; + float x = AudioManager.m_afReflectionsDistances[REFLECTION_LEFT] + AudioManager.m_afReflectionsDistances[REFLECTION_RIGHT]; + float z = AudioManager.m_afReflectionsDistances[REFLECTION_UP]; float normy = norm(y, 5.0f, 40.0f); float normx = norm(x, 5.0f, 40.0f); @@ -1601,8 +1605,6 @@ cSampleManager::StopChannel(uint32 nChannel) void cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) { - char filename[MAX_PATH]; - ASSERT( nStream < MAX_STREAMS ); if ( nFile < TOTAL_STREAMED_SOUNDS ) @@ -1611,9 +1613,10 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) stream->Close(); - strcpy(filename, StreamedNameTable[nFile]); - - stream->Open(filename, IsThisTrackAt16KHz(nFile) ? 16000 : 32000); +#ifdef PS2_AUDIO_PATHS + if(!stream->Open(PS2StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000)) +#endif + stream->Open(StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000); if ( !stream->Setup() ) { stream->Close(); @@ -1673,10 +1676,11 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) // Try to continue from previous song, if already started if(!_GetMP3PosFromStreamPos(&position, &e) && !e) { nFile = 0; - strcpy(filename, StreamedNameTable[nFile]); - CStream *stream = aStream[nStream]; - stream->Open(filename, IsThisTrackAt16KHz(nFile) ? 16000 : 32000); +#ifdef PS2_AUDIO_PATHS + if(!stream->Open(PS2StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000)) +#endif + stream->Open(StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000); if ( stream->Setup() ) { if (position != 0) stream->SetPosMS(position); @@ -1725,10 +1729,11 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) { nFile = 0; _bIsMp3Active = 0; - strcpy(filename, StreamedNameTable[nFile]); - - CStream* stream = aStream[nStream]; - stream->Open(filename, IsThisTrackAt16KHz(nFile) ? 16000 : 32000); + CStream *stream = aStream[nStream]; +#ifdef PS2_AUDIO_PATHS + if(!stream->Open(PS2StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000)) +#endif + stream->Open(StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000); if (stream->Setup()) { if (position != 0) @@ -1768,11 +1773,11 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) position = 0; nFile = 0; } - strcpy(filename, StreamedNameTable[nFile]); - CStream *stream = aStream[nStream]; - - aStream[nStream]->Open(filename, IsThisTrackAt16KHz(nFile) ? 16000 : 32000); +#ifdef PS2_AUDIO_PATHS + if(!stream->Open(PS2StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000)) +#endif + stream->Open(StreamedNameTable[nFile], IsThisTrackAt16KHz(nFile) ? 16000 : 32000); if ( stream->Setup() ) { if (position != 0) diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 22a73179..5af4071a 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -50,41 +50,41 @@ void CAutoPilot::RemoveOnePathNode() #ifdef COMPATIBLE_SAVES void CAutoPilot::Save(uint8*& buf) { - WriteSaveBuf<int32>(buf, m_nCurrentRouteNode); - WriteSaveBuf<int32>(buf, m_nNextRouteNode); - WriteSaveBuf<int32>(buf, m_nPrevRouteNode); - WriteSaveBuf<int32>(buf, m_nTimeEnteredCurve); - WriteSaveBuf<int32>(buf, m_nTimeToSpendOnCurrentCurve); - WriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo); - WriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo); - WriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo); - WriteSaveBuf<uint32>(buf, m_nAntiReverseTimer); - WriteSaveBuf<uint32>(buf, m_nTimeToStartMission); - WriteSaveBuf<int8>(buf, m_nPreviousDirection); - WriteSaveBuf<int8>(buf, m_nCurrentDirection); - WriteSaveBuf<int8>(buf, m_nNextDirection); - WriteSaveBuf<int8>(buf, m_nCurrentLane); - WriteSaveBuf<int8>(buf, m_nNextLane); - WriteSaveBuf<uint8>(buf, m_nDrivingStyle); - WriteSaveBuf<uint8>(buf, m_nCarMission); - WriteSaveBuf<uint8>(buf, m_nTempAction); - WriteSaveBuf<uint32>(buf, m_nTimeTempAction); - WriteSaveBuf<float>(buf, m_fMaxTrafficSpeed); - WriteSaveBuf<uint8>(buf, m_nCruiseSpeed); + WriteSaveBuf(buf, m_nCurrentRouteNode); + WriteSaveBuf(buf, m_nNextRouteNode); + WriteSaveBuf(buf, m_nPrevRouteNode); + WriteSaveBuf(buf, m_nTimeEnteredCurve); + WriteSaveBuf(buf, m_nTimeToSpendOnCurrentCurve); + WriteSaveBuf(buf, m_nCurrentPathNodeInfo); + WriteSaveBuf(buf, m_nNextPathNodeInfo); + WriteSaveBuf(buf, m_nPreviousPathNodeInfo); + WriteSaveBuf(buf, m_nAntiReverseTimer); + WriteSaveBuf(buf, m_nTimeToStartMission); + WriteSaveBuf(buf, m_nPreviousDirection); + WriteSaveBuf(buf, m_nCurrentDirection); + WriteSaveBuf(buf, m_nNextDirection); + WriteSaveBuf(buf, m_nCurrentLane); + WriteSaveBuf(buf, m_nNextLane); + WriteSaveBuf(buf, m_nDrivingStyle); + WriteSaveBuf(buf, m_nCarMission); + WriteSaveBuf(buf, m_nTempAction); + WriteSaveBuf(buf, m_nTimeTempAction); + WriteSaveBuf(buf, m_fMaxTrafficSpeed); + WriteSaveBuf(buf, m_nCruiseSpeed); uint8 flags = 0; if (m_bSlowedDownBecauseOfCars) flags |= BIT(0); if (m_bSlowedDownBecauseOfPeds) flags |= BIT(1); if (m_bStayInCurrentLevel) flags |= BIT(2); if (m_bStayInFastLane) flags |= BIT(3); if (m_bIgnorePathfinding) flags |= BIT(4); - WriteSaveBuf<uint8>(buf, flags); - SkipSaveBuf(buf, 2); - WriteSaveBuf<float>(buf, m_vecDestinationCoors.x); - WriteSaveBuf<float>(buf, m_vecDestinationCoors.y); - WriteSaveBuf<float>(buf, m_vecDestinationCoors.z); - SkipSaveBuf(buf, 32); - WriteSaveBuf<int16>(buf, m_nPathFindNodesCount); - SkipSaveBuf(buf, 6); + WriteSaveBuf(buf, flags); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, m_vecDestinationCoors.x); + WriteSaveBuf(buf, m_vecDestinationCoors.y); + WriteSaveBuf(buf, m_vecDestinationCoors.z); + ZeroSaveBuf(buf, 32); + WriteSaveBuf(buf, m_nPathFindNodesCount); + ZeroSaveBuf(buf, 6); } void CAutoPilot::Load(uint8*& buf) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 0516e214..35580053 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -77,7 +77,7 @@ int32 CCarCtrl::NumRandomCars; int32 CCarCtrl::NumParkedCars; int32 CCarCtrl::NumPermanentCars; int8 CCarCtrl::CountDownToCarsAtStart; -int32 CCarCtrl::MaxNumberOfCarsInUse = 12; +int32 CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS; uint32 CCarCtrl::LastTimeLawEnforcerCreated; uint32 CCarCtrl::LastTimeFireTruckCreated; uint32 CCarCtrl::LastTimeAmbulanceCreated; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 3410c881..245e961d 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -26,13 +26,6 @@ #include "World.h" #include "SaveBuf.h" -#define CRUSHER_GARAGE_X1 (1135.5f) -#define CRUSHER_GARAGE_Y1 (57.0f) -#define CRUSHER_GARAGE_Z1 (-1.0f) -#define CRUSHER_GARAGE_X2 (1149.5f) -#define CRUSHER_GARAGE_Y2 (63.7f) -#define CRUSHER_GARAGE_Z2 (3.5f) - #define ROTATED_DOOR_OPEN_SPEED (0.015f) #define ROTATED_DOOR_CLOSE_SPEED (0.02f) #define DEFAULT_DOOR_OPEN_SPEED (0.035f) @@ -1883,11 +1876,12 @@ void CStoredCar::StoreCar(CVehicle* pVehicle) m_nRadioStation = pVehicle->m_nRadioStation; m_nVariationA = pVehicle->m_aExtras[0]; m_nVariationB = pVehicle->m_aExtras[1]; - m_bBulletproof = pVehicle->bBulletProof; - m_bFireproof = pVehicle->bFireProof; - m_bExplosionproof = pVehicle->bExplosionProof; - m_bCollisionproof = pVehicle->bCollisionProof; - m_bMeleeproof = pVehicle->bMeleeProof; + m_nFlags = 0; + if (pVehicle->bBulletProof) m_nFlags |= FLAG_BULLETPROOF; + if (pVehicle->bFireProof) m_nFlags |= FLAG_FIREPROOF; + if (pVehicle->bExplosionProof) m_nFlags |= FLAG_EXPLOSIONPROOF; + if (pVehicle->bCollisionProof) m_nFlags |= FLAG_COLLISIONPROOF; + if (pVehicle->bMeleeProof) m_nFlags |= FLAG_MELEEPROOF; if (pVehicle->IsCar()) m_nCarBombType = ((CAutomobile*)pVehicle)->m_bombType; } @@ -1936,11 +1930,11 @@ CVehicle* CStoredCar::RestoreCar() } pVehicle->bHasBeenOwnedByPlayer = true; pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; - pVehicle->bBulletProof = m_bBulletproof; - pVehicle->bFireProof = m_bFireproof; - pVehicle->bExplosionProof = m_bExplosionproof; - pVehicle->bCollisionProof = m_bCollisionproof; - pVehicle->bMeleeProof = m_bMeleeproof; + if (m_nFlags & FLAG_BULLETPROOF) pVehicle->bBulletProof = true; + if (m_nFlags & FLAG_FIREPROOF) pVehicle->bFireProof = true; + if (m_nFlags & FLAG_EXPLOSIONPROOF) pVehicle->bExplosionProof = true; + if (m_nFlags & FLAG_COLLISIONPROOF) pVehicle->bCollisionProof = true; + if (m_nFlags & FLAG_MELEEPROOF) pVehicle->bMeleeProof = true; return pVehicle; } @@ -2312,6 +2306,9 @@ void CGarages::Save(uint8 * buf, uint32 * size) #else * size = 5484; #endif +#if !defined THIS_IS_STUPID && !defined FIX_GARAGE_SIZE && defined COMPATIBLE_SAVES + memset(buf + 5240, 0, *size - 5240); // garbage data is written otherwise +#endif CloseHideOutGaragesBeforeSave(); WriteSaveBuf(buf, NumGarages); WriteSaveBuf(buf, (uint32)BombsAreFree); @@ -2327,8 +2324,47 @@ void CGarages::Save(uint8 * buf, uint32 * size) WriteSaveBuf(buf, aCarsInSafeHouse2[i]); WriteSaveBuf(buf, aCarsInSafeHouse3[i]); } - for (int i = 0; i < NUM_GARAGES; i++) + for (int i = 0; i < NUM_GARAGES; i++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aGarages[i].m_eGarageType); + WriteSaveBuf(buf, aGarages[i].m_eGarageState); + WriteSaveBuf(buf, aGarages[i].field_2); + WriteSaveBuf(buf, aGarages[i].m_bClosingWithoutTargetCar); + WriteSaveBuf(buf, aGarages[i].m_bDeactivated); + WriteSaveBuf(buf, aGarages[i].m_bResprayHappened); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, aGarages[i].m_nTargetModelIndex); + ZeroSaveBuf(buf, 4 + 4); + WriteSaveBuf(buf, aGarages[i].m_bDoor1PoolIndex); + WriteSaveBuf(buf, aGarages[i].m_bDoor2PoolIndex); + WriteSaveBuf(buf, aGarages[i].m_bDoor1IsDummy); + WriteSaveBuf(buf, aGarages[i].m_bDoor2IsDummy); + WriteSaveBuf(buf, aGarages[i].m_bRecreateDoorOnNextRefresh); + WriteSaveBuf(buf, aGarages[i].m_bRotatedDoor); + WriteSaveBuf(buf, aGarages[i].m_bCameraFollowsPlayer); + ZeroSaveBuf(buf, 1); + WriteSaveBuf(buf, aGarages[i].m_fX1); + WriteSaveBuf(buf, aGarages[i].m_fX2); + WriteSaveBuf(buf, aGarages[i].m_fY1); + WriteSaveBuf(buf, aGarages[i].m_fY2); + WriteSaveBuf(buf, aGarages[i].m_fZ1); + WriteSaveBuf(buf, aGarages[i].m_fZ2); + WriteSaveBuf(buf, aGarages[i].m_fDoorPos); + WriteSaveBuf(buf, aGarages[i].m_fDoorHeight); + WriteSaveBuf(buf, aGarages[i].m_fDoor1X); + WriteSaveBuf(buf, aGarages[i].m_fDoor1Y); + WriteSaveBuf(buf, aGarages[i].m_fDoor2X); + WriteSaveBuf(buf, aGarages[i].m_fDoor2Y); + WriteSaveBuf(buf, aGarages[i].m_fDoor1Z); + WriteSaveBuf(buf, aGarages[i].m_fDoor2Z); + WriteSaveBuf(buf, aGarages[i].m_nTimeToStartAction); + WriteSaveBuf(buf, aGarages[i].m_bCollectedCarsState); + ZeroSaveBuf(buf, 3 + 4 + 4); + ZeroSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar)); +#else WriteSaveBuf(buf, aGarages[i]); +#endif + } #ifdef FIX_GARAGE_SIZE VALIDATESAVEBUF(*size); #endif @@ -2339,11 +2375,7 @@ const CStoredCar &CStoredCar::operator=(const CStoredCar & other) m_nModelIndex = other.m_nModelIndex; m_vecPos = other.m_vecPos; m_vecAngle = other.m_vecAngle; - m_bBulletproof = other.m_bBulletproof; - m_bFireproof = other.m_bFireproof; - m_bExplosionproof = other.m_bExplosionproof; - m_bCollisionproof = other.m_bCollisionproof; - m_bMeleeproof = other.m_bMeleeproof; + m_nFlags = other.m_nFlags; m_nPrimaryColor = other.m_nPrimaryColor; m_nSecondaryColor = other.m_nSecondaryColor; m_nRadioStation = other.m_nRadioStation; @@ -2357,7 +2389,7 @@ void CGarages::Load(uint8* buf, uint32 size) { #ifdef FIX_GARAGE_SIZE INITSAVEBUF - assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); + assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage))); #else assert(size == 5484); #endif @@ -2380,7 +2412,45 @@ void CGarages::Load(uint8* buf, uint32 size) ReadSaveBuf(&aCarsInSafeHouse3[i], buf); } for (int i = 0; i < NUM_GARAGES; i++) { +#ifdef COMPATIBLE_SAVES + ReadSaveBuf(&aGarages[i].m_eGarageType, buf); + ReadSaveBuf(&aGarages[i].m_eGarageState, buf); + ReadSaveBuf(&aGarages[i].field_2, buf); + ReadSaveBuf(&aGarages[i].m_bClosingWithoutTargetCar, buf); + ReadSaveBuf(&aGarages[i].m_bDeactivated, buf); + ReadSaveBuf(&aGarages[i].m_bResprayHappened, buf); + SkipSaveBuf(buf, 2); + ReadSaveBuf(&aGarages[i].m_nTargetModelIndex, buf); + SkipSaveBuf(buf, 4 + 4); + ReadSaveBuf(&aGarages[i].m_bDoor1PoolIndex, buf);
+ ReadSaveBuf(&aGarages[i].m_bDoor2PoolIndex, buf);
+ ReadSaveBuf(&aGarages[i].m_bDoor1IsDummy, buf);
+ ReadSaveBuf(&aGarages[i].m_bDoor2IsDummy, buf);
+ ReadSaveBuf(&aGarages[i].m_bRecreateDoorOnNextRefresh, buf);
+ ReadSaveBuf(&aGarages[i].m_bRotatedDoor, buf);
+ ReadSaveBuf(&aGarages[i].m_bCameraFollowsPlayer, buf); + SkipSaveBuf(buf, 1); + ReadSaveBuf(&aGarages[i].m_fX1, buf);
+ ReadSaveBuf(&aGarages[i].m_fX2, buf);
+ ReadSaveBuf(&aGarages[i].m_fY1, buf);
+ ReadSaveBuf(&aGarages[i].m_fY2, buf);
+ ReadSaveBuf(&aGarages[i].m_fZ1, buf);
+ ReadSaveBuf(&aGarages[i].m_fZ2, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoorPos, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoorHeight, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor1X, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor1Y, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor2X, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor2Y, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor1Z, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor2Z, buf);
+ ReadSaveBuf(&aGarages[i].m_nTimeToStartAction, buf);
+ ReadSaveBuf(&aGarages[i].m_bCollectedCarsState, buf); + SkipSaveBuf(buf, 3 + 4 + 4); + SkipSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar)); +#else ReadSaveBuf(&aGarages[i], buf); +#endif aGarages[i].m_pDoor1 = nil; aGarages[i].m_pDoor2 = nil; aGarages[i].m_pTarget = nil; diff --git a/src/control/Garages.h b/src/control/Garages.h index a7dfa462..8a9fd1b6 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -51,14 +51,17 @@ enum class CStoredCar { + enum { + FLAG_BULLETPROOF = 0x1, + FLAG_FIREPROOF = 0x2, + FLAG_EXPLOSIONPROOF = 0x4, + FLAG_COLLISIONPROOF = 0x8, + FLAG_MELEEPROOF = 0x10, + }; int32 m_nModelIndex; CVector m_vecPos; CVector m_vecAngle; - int32 m_bBulletproof : 1; - int32 m_bFireproof : 1; - int32 m_bExplosionproof : 1; - int32 m_bCollisionproof : 1; - int32 m_bMeleeproof : 1; + int32 m_nFlags; int8 m_nPrimaryColor; int8 m_nSecondaryColor; int8 m_nRadioStation; @@ -78,6 +81,13 @@ VALIDATE_SIZE(CStoredCar, 0x28); #define SWITCH_GARAGE_DISTANCE_CLOSE 40.0f +#define CRUSHER_GARAGE_X1 (1135.5f) +#define CRUSHER_GARAGE_Y1 (57.0f) +#define CRUSHER_GARAGE_Z1 (-1.0f) +#define CRUSHER_GARAGE_X2 (1149.5f) +#define CRUSHER_GARAGE_Y2 (63.7f) +#define CRUSHER_GARAGE_Z2 (3.5f) + class CGarage { public: @@ -87,7 +97,7 @@ public: bool m_bClosingWithoutTargetCar; bool m_bDeactivated; bool m_bResprayHappened; - int m_nTargetModelIndex; + int32 m_nTargetModelIndex; CEntity *m_pDoor1; CEntity *m_pDoor2; uint8 m_bDoor1PoolIndex; diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index f9cb1421..7632cfa3 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -18,6 +18,12 @@ #include "Replay.h" #endif +#ifdef COMPATIBLE_SAVES +#define PHONEINFO_SAVE_SIZE 0xA30 +#else +#define PHONEINFO_SAVE_SIZE sizeof(CPhoneInfo) +#endif + CPhoneInfo gPhoneInfo; bool CPhoneInfo::bDisplayingPhoneMessage; // is phone picked up @@ -209,6 +215,22 @@ CPhoneInfo::IsMessageBeingDisplayed(int phoneId) return pPhoneDisplayingMessages == &m_aPhones[phoneId]; } +#ifdef COMPATIBLE_SAVES +static inline void +LoadPhone(CPhone &phone, uint8 *&buf) +{ + ReadSaveBuf(&phone.m_vecPos, buf); + SkipSaveBuf(buf, 6 * 4); + ReadSaveBuf<uint32>(&phone.m_repeatedMessagePickupStart, buf); + uint32 tmp; + ReadSaveBuf(&tmp, buf); + phone.m_pEntity = (CEntity*)(uintptr)tmp; + ReadSaveBuf<PhoneState>(&phone.m_nState, buf); + ReadSaveBuf<bool>(&phone.m_visibleToCam, buf); + SkipSaveBuf(buf, 3); +} +#endif + void CPhoneInfo::Load(uint8 *buf, uint32 size) { @@ -226,7 +248,12 @@ INITSAVEBUF // We can do it without touching saves. We'll only load script phones, others are already loaded in Initialise for (int i = 0; i < 50; i++) { CPhone phoneToLoad; +#ifdef COMPATIBLE_SAVES + phoneToLoad.m_apMessages[0]=phoneToLoad.m_apMessages[1]=phoneToLoad.m_apMessages[2]=phoneToLoad.m_apMessages[3]=phoneToLoad.m_apMessages[4]=phoneToLoad.m_apMessages[5] = nil; + LoadPhone(phoneToLoad, buf); +#else ReadSaveBuf(&phoneToLoad, buf); +#endif if (ignoreOtherPhones) continue; @@ -252,7 +279,11 @@ INITSAVEBUF m_nScriptPhonesMax = scriptPhonesMax; for (int i = 0; i < NUMPHONES; i++) { +#ifdef COMPATIBLE_SAVES + LoadPhone(m_aPhones[i], buf); +#else ReadSaveBuf(&m_aPhones[i], buf); +#endif // It's saved as building pool index in save file, convert it to true entity if (m_aPhones[i].m_pEntity) { m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1); @@ -376,7 +407,7 @@ CPhoneInfo::Initialise(void) void CPhoneInfo::Save(uint8 *buf, uint32 *size) { - *size = sizeof(CPhoneInfo); + *size = PHONEINFO_SAVE_SIZE; INITSAVEBUF WriteSaveBuf(buf, m_nMax); WriteSaveBuf(buf, m_nScriptPhonesMax); @@ -385,12 +416,24 @@ INITSAVEBUF #else for (int phoneId = 0; phoneId < NUMPHONES; phoneId++) { #endif +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, m_aPhones[phoneId].m_vecPos); + ZeroSaveBuf(buf, 6 * 4); + WriteSaveBuf(buf, m_aPhones[phoneId].m_repeatedMessagePickupStart); + // Convert entity pointer to building pool index while saving + int32 tmp = m_aPhones[phoneId].m_pEntity ? CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)m_aPhones[phoneId].m_pEntity) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, m_aPhones[phoneId].m_nState); + WriteSaveBuf(buf, m_aPhones[phoneId].m_visibleToCam); + ZeroSaveBuf(buf, 3); +#else CPhone* phone = WriteSaveBuf(buf, m_aPhones[phoneId]); // Convert entity pointer to building pool index while saving if (phone->m_pEntity) { phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1); } +#endif } VALIDATESAVEBUF(*size) } diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 10175fba..8d3472ea 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -32,6 +32,12 @@ #include "WaterLevel.h" #include "World.h" +#ifdef COMPATIBLE_SAVES +#define PICKUPS_SAVE_SIZE 0x24C0 +#else +#define PICKUPS_SAVE_SIZE sizeof(aPickUps) +#endif + CPickup CPickups::aPickUps[NUMPICKUPS]; int16 CPickups::NumMessages; int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS]; @@ -1000,10 +1006,23 @@ CPickups::Load(uint8 *buf, uint32 size) INITSAVEBUF for (int32 i = 0; i < NUMPICKUPS; i++) { +#ifdef COMPATIBLE_SAVES + ReadSaveBuf(&aPickUps[i].m_eType, buf); + ReadSaveBuf(&aPickUps[i].m_bRemoved, buf); + ReadSaveBuf(&aPickUps[i].m_nQuantity, buf); + int32 tmp; + ReadSaveBuf(&tmp, buf); + aPickUps[i].m_pObject = aPickUps[i].m_eType != PICKUP_NONE && tmp != 0 ? CPools::GetObjectPool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&aPickUps[i].m_nTimer, buf); + ReadSaveBuf(&aPickUps[i].m_eModelIndex, buf); + ReadSaveBuf(&aPickUps[i].m_nIndex, buf); + ReadSaveBuf(&aPickUps[i].m_vecPos, buf); +#else ReadSaveBuf(&aPickUps[i], buf); if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil) aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pObject - 1); +#endif } ReadSaveBuf(&CollectedPickUpIndex, buf); @@ -1019,14 +1038,26 @@ VALIDATESAVEBUF(size) void CPickups::Save(uint8 *buf, uint32 *size) { - *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected); + *size = PICKUPS_SAVE_SIZE + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected); INITSAVEBUF for (int32 i = 0; i < NUMPICKUPS; i++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aPickUps[i].m_eType); + WriteSaveBuf(buf, aPickUps[i].m_bRemoved); + WriteSaveBuf(buf, aPickUps[i].m_nQuantity); + int32 tmp = aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aPickUps[i].m_pObject) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, aPickUps[i].m_nTimer); + WriteSaveBuf(buf, aPickUps[i].m_eModelIndex); + WriteSaveBuf(buf, aPickUps[i].m_nIndex); + WriteSaveBuf(buf, aPickUps[i].m_vecPos); +#else 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_NoFreeAssert(buf_pickup->m_pObject) + 1); +#endif } WriteSaveBuf(buf, CollectedPickUpIndex); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index e06acdc3..b07c0701 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1771,20 +1771,12 @@ int scriptToLoad = 0; int open_script() { - // glfwGetKey doesn't work because of CGame::Initialise is blocking - CPad::UpdatePads(); - if (CPad::GetPad(0)->GetChar('G')) - scriptToLoad = 0; - if (CPad::GetPad(0)->GetChar('R')) - scriptToLoad = 1; - if (CPad::GetPad(0)->GetChar('D')) - scriptToLoad = 2; switch (scriptToLoad) { - case 0: return CFileMgr::OpenFile("main.scm", "rb"); - case 1: return CFileMgr::OpenFile("main_freeroam.scm", "rb"); - case 2: return CFileMgr::OpenFile("main_d.scm", "rb"); + case 0: return CFileMgr::OpenFile("data\\main.scm", "rb"); + case 1: return CFileMgr::OpenFile("data\\main_freeroam.scm", "rb"); + case 2: return CFileMgr::OpenFile("data\\main_d.scm", "rb"); } - return CFileMgr::OpenFile("main.scm", "rb"); + return CFileMgr::OpenFile("data\\main.scm", "rb"); } #endif @@ -1800,10 +1792,16 @@ void CTheScripts::Init() MissionCleanUp.Init(); UpsideDownCars.Init(); StuckCars.Init(); - CFileMgr::SetDir("data"); #ifdef USE_DEBUG_SCRIPT_LOADER + // glfwGetKey doesn't work because of CGame::Initialise is blocking + CPad::UpdatePads(); + if(CPad::GetPad(0)->GetChar('G')) scriptToLoad = 0; + if(CPad::GetPad(0)->GetChar('R')) scriptToLoad = 1; + if(CPad::GetPad(0)->GetChar('D')) scriptToLoad = 2; + int mainf = open_script(); #else + CFileMgr::SetDir("data"); int mainf = CFileMgr::OpenFile("main.scm", "rb"); #endif CFileMgr::Read(mainf, (char*)ScriptSpace, SIZE_MAIN_SCRIPT); @@ -4392,7 +4390,11 @@ CTheScripts::SwitchToMission(int32 mission) CTimer::Suspend(); int offset = CTheScripts::MultiScriptArray[mission]; CFileMgr::ChangeDir("\\"); +#ifdef USE_DEBUG_SCRIPT_LOADER + int handle = open_script(); +#else int handle = CFileMgr::OpenFile("data\\main.scm", "rb"); +#endif CFileMgr::Seek(handle, offset, 0); CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT); CFileMgr::CloseFile(handle); diff --git a/src/control/Script.h b/src/control/Script.h index 5682024b..cefd6747 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -591,5 +591,6 @@ void RetryMission(int, int); #endif #ifdef USE_DEBUG_SCRIPT_LOADER +int open_script(); extern int scriptToLoad; #endif
\ No newline at end of file diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp index a9aec18e..953a1f50 100644 --- a/src/control/Script5.cpp +++ b/src/control/Script5.cpp @@ -2089,33 +2089,33 @@ VALIDATESAVEBUF(size) void CRunningScript::Save(uint8*& buf) { #ifdef COMPATIBLE_SAVES - SkipSaveBuf(buf, 8); + ZeroSaveBuf(buf, 8); for (int i = 0; i < 8; i++) - WriteSaveBuf<char>(buf, m_abScriptName[i]); - WriteSaveBuf<uint32>(buf, m_nIp); + WriteSaveBuf(buf, m_abScriptName[i]); + WriteSaveBuf(buf, m_nIp); #ifdef CHECK_STRUCT_SIZES static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6"); #endif for (int i = 0; i < MAX_STACK_DEPTH; i++) - WriteSaveBuf<uint32>(buf, m_anStack[i]); - WriteSaveBuf<uint16>(buf, m_nStackPointer); - SkipSaveBuf(buf, 2); + WriteSaveBuf(buf, m_anStack[i]); + WriteSaveBuf(buf, m_nStackPointer); + ZeroSaveBuf(buf, 2); #ifdef CHECK_STRUCT_SIZES static_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18"); #endif for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++) - WriteSaveBuf<int32>(buf, m_anLocalVariables[i]); - WriteSaveBuf<bool>(buf, m_bCondResult); - WriteSaveBuf<bool>(buf, m_bIsMissionScript); - WriteSaveBuf<bool>(buf, m_bSkipWakeTime); - SkipSaveBuf(buf, 1); - WriteSaveBuf<uint32>(buf, m_nWakeTime); - WriteSaveBuf<uint16>(buf, m_nAndOrState); - WriteSaveBuf<bool>(buf, m_bNotFlag); - WriteSaveBuf<bool>(buf, m_bDeatharrestEnabled); - WriteSaveBuf<bool>(buf, m_bDeatharrestExecuted); - WriteSaveBuf<bool>(buf, m_bMissionFlag); - SkipSaveBuf(buf, 2); + WriteSaveBuf(buf, m_anLocalVariables[i]); + WriteSaveBuf(buf, m_bCondResult); + WriteSaveBuf(buf, m_bIsMissionScript); + WriteSaveBuf(buf, m_bSkipWakeTime); + ZeroSaveBuf(buf, 1); + WriteSaveBuf(buf, m_nWakeTime); + WriteSaveBuf(buf, m_nAndOrState); + WriteSaveBuf(buf, m_bNotFlag); + WriteSaveBuf(buf, m_bDeatharrestEnabled); + WriteSaveBuf(buf, m_bDeatharrestExecuted); + WriteSaveBuf(buf, m_bMissionFlag); + ZeroSaveBuf(buf, 2); #else WriteSaveBuf(buf, *this); #endif diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp index 31be6987..c9b2b070 100644 --- a/src/control/Script6.cpp +++ b/src/control/Script6.cpp @@ -305,7 +305,11 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CTimer::Suspend(); int offset = CTheScripts::MultiScriptArray[ScriptParams[0]]; CFileMgr::ChangeDir("\\"); +#ifdef USE_DEBUG_SCRIPT_LOADER + int handle = open_script(); +#else int handle = CFileMgr::OpenFile("data\\main.scm", "rb"); +#endif CFileMgr::Seek(handle, offset, 0); CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT); CFileMgr::CloseFile(handle); diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index 984b21bb..8b184622 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -396,7 +396,7 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt if (target) { if (target->IsPed()) { ped->m_pFire = fire; - if (target != (CVehicle *)FindPlayerPed()) { + if (target != FindPlayerPed()) { CVector2D pos = target->GetPosition(); ped->SetFlee(pos, 10000); ped->SetMoveAnim(); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 7ff80697..ecb893b4 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -336,6 +336,7 @@ const char* MenuFilenames[][2] = { CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); \ CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); +// value must be between 0.0-1.0 #define ProcessSlider(value, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ do { \ lastActiveBarX = DisplaySlider(MENU_X_RIGHT_ALIGNED(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ @@ -489,7 +490,7 @@ CMenuManager::ThingsToDoBeforeGoingBack() option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); if (option.m_Action == MENUACTION_CFO_SELECT && option.m_CFOSelect->onlyApplyOnEnter && option.m_CFOSelect->lastSavedValue != option.m_CFOSelect->displayedValue) - option.m_CFOSelect->displayedValue = *option.m_CFO->value = option.m_CFOSelect->lastSavedValue; + option.m_CFOSelect->displayedValue = *(int8*)option.m_CFO->value = option.m_CFOSelect->lastSavedValue; if (aScreens[m_nCurrScreen].returnPrevPageFunc) { aScreens[m_nCurrScreen].returnPrevPageFunc(); @@ -898,29 +899,29 @@ CMenuManager::CheckSliderMovement(int value) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { case MENUACTION_BRIGHTNESS: - m_PrefsBrightness += value * (512/16); + m_PrefsBrightness += value * (512/MENUSLIDER_LOGICAL_BARS); m_PrefsBrightness = Clamp(m_PrefsBrightness, 0, 511); break; case MENUACTION_DRAWDIST: if(value > 0) - m_PrefsLOD += ((1.8f - 0.8f) / 16.0f); + m_PrefsLOD += ((1.8f - 0.8f) / MENUSLIDER_LOGICAL_BARS); else - m_PrefsLOD -= ((1.8f - 0.8f) / 16.0f); + m_PrefsLOD -= ((1.8f - 0.8f) / MENUSLIDER_LOGICAL_BARS); m_PrefsLOD = Clamp(m_PrefsLOD, 0.8f, 1.8f); CRenderer::ms_lodDistScale = m_PrefsLOD; break; case MENUACTION_MUSICVOLUME: - m_PrefsMusicVolume += value * (128/16); + m_PrefsMusicVolume += value * (128/MENUSLIDER_LOGICAL_BARS); m_PrefsMusicVolume = Clamp(m_PrefsMusicVolume, 0, 127); DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); break; case MENUACTION_SFXVOLUME: - m_PrefsSfxVolume += value * (128/16); + m_PrefsSfxVolume += value * (128/MENUSLIDER_LOGICAL_BARS); m_PrefsSfxVolume = Clamp(m_PrefsSfxVolume, 0, 127); DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); break; case MENUACTION_MOUSESENS: - TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // ??? + TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // probably because diving it to 15 instead of 16(MENUSLIDER_LOGICAL_BARS) had more accurate steps TheCamera.m_fMouseAccelHorzntl = Clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f); #ifdef FIX_BUGS TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; @@ -928,6 +929,20 @@ CMenuManager::CheckSliderMovement(int value) TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; #endif break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_CFO_SLIDER: + { + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; + float oldValue = *(float*)option.m_CFOSlider->value; + *(float*)option.m_CFOSlider->value += value * ((option.m_CFOSlider->max - option.m_CFOSlider->min) / MENUSLIDER_LOGICAL_BARS); + *(float*)option.m_CFOSlider->value = Clamp(*(float*)option.m_CFOSlider->value, option.m_CFOSlider->min, option.m_CFOSlider->max); + + if (*(float*)option.m_CFOSlider->value != oldValue && option.m_CFOSlider->changeFunc) + option.m_CFOSlider->changeFunc(oldValue, *(float*)option.m_CFOSlider->value); + + break; + } +#endif default: return; } @@ -1001,10 +1016,10 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR int lastActiveBarX = 0; float curBarX = 0.0f; float spacing = SCREEN_SCALE_X(10.0f); - for (int i = 0; i < 16; i++) { - curBarX = i * rectSize/16.0f + x; + for (int i = 0; i < MENUSLIDER_BARS; i++) { + curBarX = i * rectSize/MENUSLIDER_BARS + x; - if (i / 16.0f + 1 / 32.0f < progress) { + if (i / (float)MENUSLIDER_BARS + 1 / (MENUSLIDER_BARS * 2.f) < progress) { color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255)); lastActiveBarX = curBarX; } else @@ -1012,7 +1027,7 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); - float curBarFreeSpace = ((16 - i) * mostLeftBarSize + i * mostRightBarSize) / 16.0f; + float curBarFreeSpace = ((MENUSLIDER_BARS - i) * mostLeftBarSize + i * mostRightBarSize) / (float)MENUSLIDER_BARS; float left = curBarX; float top = y + maxBarHeight - curBarFreeSpace; float right = spacing + curBarX; @@ -1595,10 +1610,10 @@ CMenuManager::Draw() // If that was previously selected option, restore it to default value. // if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) - option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value; + option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *(int8*)option.m_CFO->value; } else { - if (option.m_CFOSelect->displayedValue != *option.m_CFO->value) + if (option.m_CFOSelect->displayedValue != *(int8*)option.m_CFO->value) SetHelperText(1); // Enter to apply else if (m_nHelperTextMsgId == 1) ResetHelperText(); // Applied @@ -1606,8 +1621,8 @@ CMenuManager::Draw() } // To whom manipulate option.m_CFO->value of select options externally (like RestoreDef functions) - if (*option.m_CFO->value != option.m_CFOSelect->lastSavedValue) - option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value; + if (*(int8*)option.m_CFO->value != option.m_CFOSelect->lastSavedValue) + option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *(int8*)option.m_CFO->value; if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) option.m_CFOSelect->displayedValue = 0; @@ -1799,6 +1814,12 @@ CMenuManager::Draw() case MENUACTION_MOUSESENS: ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, MENU_X_LEFT_ALIGNED(200.0f), SCREEN_WIDTH); break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_CFO_SLIDER: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; + ProcessSlider((*(float*)option.m_CFOSlider->value - option.m_CFOSlider->min) / (option.m_CFOSlider->max - option.m_CFOSlider->min), HOVEROPTION_INCREASE_CFO_SLIDER, HOVEROPTION_DECREASE_CFO_SLIDER, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; +#endif } // Needed after the bug fix in Font.cpp @@ -4477,7 +4498,7 @@ CMenuManager::ProcessButtonPresses(void) #ifndef TIDY_UP_PBP switch (m_nHoverOption) { case HOVEROPTION_INCREASE_BRIGHTNESS: - m_PrefsBrightness = m_PrefsBrightness + 32; + m_PrefsBrightness = m_PrefsBrightness + (512 / MENUSLIDER_LOGICAL_BARS); if (m_PrefsBrightness < 0) { m_PrefsBrightness = 0; } @@ -4487,7 +4508,7 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; case HOVEROPTION_DECREASE_BRIGHTNESS: - m_PrefsBrightness = m_PrefsBrightness - 32; + m_PrefsBrightness = m_PrefsBrightness - (512 / MENUSLIDER_LOGICAL_BARS); if (m_PrefsBrightness < 0) { m_PrefsBrightness = 0; } @@ -4497,25 +4518,25 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; case HOVEROPTION_INCREASE_DRAWDIST: - m_PrefsLOD = m_PrefsLOD + (1.0f / 16); + m_PrefsLOD = m_PrefsLOD + (1.0f / MENUSLIDER_LOGICAL_BARS); m_PrefsLOD = min(1.8f, m_PrefsLOD); CRenderer::ms_lodDistScale = m_PrefsLOD; SaveSettings(); break; case HOVEROPTION_DECREASE_DRAWDIST: - m_PrefsLOD = m_PrefsLOD - (1.0f / 16); + m_PrefsLOD = m_PrefsLOD - (1.0f / MENUSLIDER_LOGICAL_BARS); m_PrefsLOD = max(0.8f, m_PrefsLOD); CRenderer::ms_lodDistScale = m_PrefsLOD; SaveSettings(); break; case HOVEROPTION_INCREASE_MUSICVOLUME: - m_PrefsMusicVolume = m_PrefsMusicVolume + 8; + m_PrefsMusicVolume = m_PrefsMusicVolume + (128 / MENUSLIDER_LOGICAL_BARS); m_PrefsMusicVolume = Clamp(m_PrefsMusicVolume, 0, 127); DMAudio.SetMusicMasterVolume(uchar)(m_PrefsMusicVolume); SaveSettings(); break; case HOVEROPTION_DECREASE_MUSICVOLUME: - m_PrefsMusicVolume = m_PrefsMusicVolume - 8; + m_PrefsMusicVolume = m_PrefsMusicVolume - (128 / MENUSLIDER_LOGICAL_BARS); if (m_PrefsMusicVolume < 0) { m_PrefsMusicVolume = 0; } @@ -4526,7 +4547,7 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; case HOVEROPTION_INCREASE_SFXVOLUME: - m_PrefsSFXVolume = m_PrefsSFXVolume + 8; + m_PrefsSFXVolume = m_PrefsSFXVolume + (128 / MENUSLIDER_LOGICAL_BARS); if (m_PrefsSFXVolume < 0) { m_PrefsSFXVolume = 0; } @@ -4537,7 +4558,7 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; case HOVEROPTION_DECREASE_SFXVOLUME: - m_PrefsSFXVolume = m_PrefsSFXVolume - 8; + m_PrefsSFXVolume = m_PrefsSFXVolume - (128 / MENUSLIDER_LOGICAL_BARS); if (m_PrefsSFXVolume < 0) { m_PrefsSFXVolume = 0; } @@ -4548,7 +4569,7 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; case HOVEROPTION_INCREASE_MOUSESENS: - TheCamera.m_fMouseAccelHorzntl += (1.0f / 3000); + TheCamera.m_fMouseAccelHorzntl += 1.0f/200.0f/15.0f; // probably because diving it to 15 instead of 16(MENUSLIDER_LOGICAL_BARS) had more accurate steps TheCamera.m_fMouseAccelHorzntl = Clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); #ifdef FIX_BUGS TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; @@ -4558,7 +4579,7 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; case HOVEROPTION_DECREASE_MOUSESENS: - TheCamera.m_fMouseAccelHorzntl -= (1.0f / 3000); + TheCamera.m_fMouseAccelHorzntl -= 1.0f/200.0f/15.0f; // probably because diving it to 15 instead of 16(MENUSLIDER_LOGICAL_BARS) had more accurate steps TheCamera.m_fMouseAccelHorzntl = Clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); #ifdef FIX_BUGS TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; @@ -4575,6 +4596,9 @@ CMenuManager::ProcessButtonPresses(void) case HOVEROPTION_INCREASE_MUSICVOLUME: case HOVEROPTION_INCREASE_SFXVOLUME: case HOVEROPTION_INCREASE_MOUSESENS: +#ifdef CUSTOM_FRONTEND_OPTIONS + case HOVEROPTION_INCREASE_CFO_SLIDER: +#endif CheckSliderMovement(1); break; case HOVEROPTION_DECREASE_BRIGHTNESS: @@ -4582,6 +4606,9 @@ CMenuManager::ProcessButtonPresses(void) case HOVEROPTION_DECREASE_MUSICVOLUME: case HOVEROPTION_DECREASE_SFXVOLUME: case HOVEROPTION_DECREASE_MOUSESENS: +#ifdef CUSTOM_FRONTEND_OPTIONS + case HOVEROPTION_DECREASE_CFO_SLIDER: +#endif CheckSliderMovement(-1); break; } @@ -4612,7 +4639,11 @@ CMenuManager::ProcessButtonPresses(void) || CPad::GetPad(0)->GetAnaloguePadLeftJustUp() || CPad::GetPad(0)->GetAnaloguePadRightJustUp() || CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown()) { int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if (option == MENUACTION_BRIGHTNESS || option == MENUACTION_DRAWDIST) + if (option == MENUACTION_BRIGHTNESS || option == MENUACTION_DRAWDIST +#ifdef CUSTOM_FRONTEND_OPTIONS + || option == MENUACTION_CFO_SLIDER +#endif + ) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); else if (option == MENUACTION_SFXVOLUME) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_AUDIO_TEST, 0); @@ -4775,7 +4806,12 @@ CMenuManager::ProcessButtonPresses(void) } else if (option != MENUACTION_CHANGEMENU && option != MENUACTION_BRIGHTNESS && option != MENUACTION_DRAWDIST && option != MENUACTION_MUSICVOLUME && option != MENUACTION_SFXVOLUME && option != MENUACTION_CHECKSAVE && option != MENUACTION_UNK24 - && option != MENUACTION_MOUSESENS && option != MENUACTION_SCREENRES) { + && option != MENUACTION_MOUSESENS && option != MENUACTION_SCREENRES +#ifdef CUSTOM_FRONTEND_OPTIONS + && option != MENUACTION_CFO_SLIDER +#endif + ) + { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); } @@ -5166,9 +5202,9 @@ CMenuManager::ProcessButtonPresses(void) if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) option.m_CFOSelect->displayedValue = 0; } - int8 oldValue = *option.m_CFO->value; + int8 oldValue = *(int8*)option.m_CFO->value; - *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; + *(int8*)option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; // Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO // if (option.m_CFOSelect->save) @@ -5412,9 +5448,9 @@ CMenuManager::ProcessButtonPresses(void) option.m_CFOSelect->displayedValue = option.m_CFOSelect->numRightTexts - 1; } if (!option.m_CFOSelect->onlyApplyOnEnter) { - int8 oldValue = *option.m_CFO->value; + int8 oldValue = *(int8*)option.m_CFO->value; - *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; + *(int8*)option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; // Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO // if (option.m_CFOSelect->save) diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 5c3523ab..32e5ef9d 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -25,6 +25,9 @@ #define MENUSLIDER_X 256.0f #define MENUSLIDER_UNK 256.0f +#define MENUSLIDER_BARS 16 +#define MENUSLIDER_LOGICAL_BARS MENUSLIDER_BARS + #define BIGTEXT_X_SCALE 0.75f // For FONT_HEADING #define BIGTEXT_Y_SCALE 0.9f #define MEDIUMTEXT_X_SCALE 0.55f // For FONT_HEADING @@ -256,6 +259,7 @@ enum eMenuScreen enum eMenuAction { #ifdef CUSTOM_FRONTEND_OPTIONS + MENUACTION_CFO_SLIDER = -3, MENUACTION_CFO_SELECT = -2, MENUACTION_CFO_DYNAMIC = -1, #endif @@ -424,6 +428,10 @@ enum eCheckHover HOVEROPTION_DECREASE_SFXVOLUME, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, +#ifdef CUSTOM_FRONTEND_OPTIONS + HOVEROPTION_INCREASE_CFO_SLIDER, + HOVEROPTION_DECREASE_CFO_SLIDER, +#endif HOVEROPTION_NOT_HOVERING, }; @@ -493,7 +501,7 @@ struct CCustomScreenLayout { struct CCFO { - int8 *value; + void *value; const char *saveCat; const char *save; }; @@ -524,6 +532,24 @@ struct CCFOSelect : CCFO } }; +// Value is float in here +struct CCFOSlider : CCFO +{ + ChangeFuncFloat changeFunc; + float min; + float max; + + CCFOSlider() {}; + CCFOSlider(float* value, const char* saveCat, const char* save, float min, float max, ChangeFuncFloat changeFunc = nil){ + this->value = value; + this->saveCat = saveCat; + this->save = save; + this->changeFunc = changeFunc; + this->min = min; + this->max = max; + } +}; + struct CCFODynamic : CCFO { DrawFunc drawFunc; @@ -555,6 +581,7 @@ struct CMenuScreenCustom CCFO *m_CFO; // for initializing CCFOSelect *m_CFOSelect; CCFODynamic *m_CFODynamic; + CCFOSlider *m_CFOSlider; }; int32 m_SaveSlot; // eSaveSlot int32 m_TargetMenu; // eMenuScreen diff --git a/src/core/Game.cpp b/src/core/Game.cpp index f6156a4c..b3dd1eda 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -409,7 +409,11 @@ bool CGame::Initialise(const char* datFile) #endif #ifndef GTA_PS2 - CIniFile::LoadIniFile(); +#ifdef PED_CAR_DENSITY_SLIDERS + // Load density values from gta3.ini only if our re3.ini have them 1.f + if (CIniFile::PedNumberMultiplier == 1.f && CIniFile::CarNumberMultiplier == 1.f) +#endif + CIniFile::LoadIniFile(); #endif currLevel = LEVEL_INDUSTRIAL; diff --git a/src/core/IniFile.cpp b/src/core/IniFile.cpp index df01b440..524632fe 100644 --- a/src/core/IniFile.cpp +++ b/src/core/IniFile.cpp @@ -23,6 +23,6 @@ void CIniFile::LoadIniFile() CarNumberMultiplier = Min(3.0f, Max(0.5f, CarNumberMultiplier)); CFileMgr::CloseFile(f); } - CPopulation::MaxNumberOfPedsInUse = 25.0f * PedNumberMultiplier; - CCarCtrl::MaxNumberOfCarsInUse = 12.0f * CarNumberMultiplier; + CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS * PedNumberMultiplier; + CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS * CarNumberMultiplier; }
\ No newline at end of file diff --git a/src/core/IniFile.h b/src/core/IniFile.h index 1e30c4de..30dc8c21 100644 --- a/src/core/IniFile.h +++ b/src/core/IniFile.h @@ -1,5 +1,8 @@ #pragma once +#define DEFAULT_MAX_NUMBER_OF_PEDS 25.0f +#define DEFAULT_MAX_NUMBER_OF_CARS 12.0f + class CIniFile { public: diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index 6e23f76a..033ed9b9 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -26,6 +26,9 @@ #include "ModelInfo.h" #include "Pad.h" #include "ControllerConfig.h" +#include "IniFile.h" +#include "CarCtrl.h" +#include "Population.h" // Menu screens array is at the bottom of the file. @@ -63,6 +66,15 @@ #define DUALPASS_SELECTOR #endif +#ifdef PED_CAR_DENSITY_SLIDERS + // 0.2f - 3.4f makes it possible to have 1.0f somewhere inbetween + #define DENSITY_SLIDERS \ + MENUACTION_CFO_SLIDER, "FEM_PED", { new CCFOSlider(&CIniFile::PedNumberMultiplier, "Display", "PedDensity", 0.2f, 3.4f, PedDensityChange) }, \ + MENUACTION_CFO_SLIDER, "FEM_CAR", { new CCFOSlider(&CIniFile::CarNumberMultiplier, "Display", "CarDensity", 0.2f, 3.4f, CarDensityChange) }, +#else + #define DENSITY_SLIDERS +#endif + #ifdef NO_ISLAND_LOADING #define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, "FEM_ISL", { new CCFOSelect((int8*)&CMenuManager::m_PrefsIslandLoading, "Graphics", "IslandLoading", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) }, #else @@ -145,6 +157,9 @@ void RestoreDefDisplay(int8 action) { #ifdef FREE_CAM TheCamera.bFreeCam = false; #endif + #ifdef PED_CAR_DENSITY_SLIDERS + CIniFile::LoadIniFile(); + #endif #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those CMenuManager::m_PrefsBrightness = 256; CMenuManager::m_PrefsLOD = 1.2f; @@ -195,6 +210,16 @@ void IslandLoadingAfterChange(int8 before, int8 after) { } #endif +#ifdef PED_CAR_DENSITY_SLIDERS +void PedDensityChange(float before, float after) { + CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS * after; +} + +void CarDensityChange(float before, float after) { + CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS * after; +} +#endif + #ifndef MULTISAMPLING void GraphicsGoBack() { } @@ -423,6 +448,7 @@ CMenuScreenCustom aScreens[MENUPAGES] = { { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + DENSITY_SLIDERS MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, #ifndef EXTENDED_COLOURFILTER @@ -447,6 +473,7 @@ CMenuScreenCustom aScreens[MENUPAGES] = { { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + DENSITY_SLIDERS CUTSCENE_BORDERS_TOGGLE FREE_CAM_TOGGLE MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index 5cffe9e4..b0248664 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -281,9 +281,9 @@ INITSAVEBUF #else if ((pVehicle->IsCar() || pVehicle->IsBoat()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif - WriteSaveBuf<uint32>(buf, pVehicle->m_vehType); - WriteSaveBuf<int16>(buf, pVehicle->GetModelIndex()); - WriteSaveBuf<int32>(buf, GetVehicleRef(pVehicle)); + WriteSaveBuf(buf, pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->GetModelIndex()); + WriteSaveBuf(buf, GetVehicleRef(pVehicle)); pVehicle->Save(buf); } #else @@ -292,7 +292,7 @@ INITSAVEBUF #else if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif - WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, GetVehicleRef(pVehicle)); memcpy(buf, pVehicle, sizeof(CAutomobile)); @@ -303,7 +303,7 @@ INITSAVEBUF #else if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif - WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, GetVehicleRef(pVehicle)); memcpy(buf, pVehicle, sizeof(CBoat)); diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 107b1db8..82fbc047 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -10,6 +10,14 @@ #include "Timer.h" #include "SaveBuf.h" +#ifdef COMPATIBLE_SAVES +#define ZONEARRAY_SAVE_SIZE 0xAF0 +#define MAPZONEARRAY_SAVE_SIZE 0x578 +#else +#define ZONEARRAY_SAVE_SIZE sizeof(ZoneArray) +#define MAPZONEARRAY_SAVE_SIZE sizeof(MapZoneArray) +#endif + eLevelName CTheZones::m_CurrLevel; CZone *CTheZones::m_pPlayersZone; int16 CTheZones::FindIndex; @@ -633,6 +641,28 @@ CTheZones::InitialiseAudioZoneArray(void) } } +#ifdef COMPATIBLE_SAVES +static inline void +SaveOneZone(CZone &zone, uint8 *&buffer) +{ + memcpy(buffer, zone.name, sizeof(zone.name)); + SkipSaveBuf(buffer, sizeof(zone.name)); + WriteSaveBuf(buffer, zone.minx); + WriteSaveBuf(buffer, zone.miny); + WriteSaveBuf(buffer, zone.minz); + WriteSaveBuf(buffer, zone.maxx); + WriteSaveBuf(buffer, zone.maxy); + WriteSaveBuf(buffer, zone.maxz); + WriteSaveBuf(buffer, zone.type); + WriteSaveBuf(buffer, zone.level); + WriteSaveBuf(buffer, zone.zoneinfoDay); + WriteSaveBuf(buffer, zone.zoneinfoNight); + WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.child)); + WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.parent)); + WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.next)); +} +#endif + void CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) { @@ -643,9 +673,9 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) + sizeof(int32) // GetIndexForZonePointer + sizeof(m_CurrLevel) + sizeof(FindIndex) + sizeof(int16) // padding - + sizeof(ZoneArray) + sizeof(ZoneInfoArray) + + ZONEARRAY_SAVE_SIZE + sizeof(ZoneInfoArray) + sizeof(TotalNumberOfZones) + sizeof(TotalNumberOfZoneInfos) - + sizeof(MapZoneArray) + sizeof(AudioZoneArray) + + MAPZONEARRAY_SAVE_SIZE + sizeof(AudioZoneArray) + sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); @@ -656,10 +686,14 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) WriteSaveBuf(buffer, (int16)0); // padding for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ +#ifdef COMPATIBLE_SAVES + SaveOneZone(ZoneArray[i], buffer); +#else CZone *zone = WriteSaveBuf(buffer, ZoneArray[i]); zone->child = (CZone*)GetIndexForZonePointer(ZoneArray[i].child); zone->parent = (CZone*)GetIndexForZonePointer(ZoneArray[i].parent); zone->next = (CZone*)GetIndexForZonePointer(ZoneArray[i].next); +#endif } for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) @@ -669,7 +703,9 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) WriteSaveBuf(buffer, TotalNumberOfZoneInfos); for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { +#ifndef COMPATIBLE_SAVES CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]); +#endif /* The call of GetIndexForZonePointer is wrong, as it is @@ -679,9 +715,13 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) assert(MapZoneArray[i].child == nil); assert(MapZoneArray[i].parent == nil); assert(MapZoneArray[i].next == nil); +#ifndef COMPATIBLE_SAVES zone->child = (CZone*)GetIndexForZonePointer(MapZoneArray[i].child); zone->parent = (CZone*)GetIndexForZonePointer(MapZoneArray[i].parent); zone->next = (CZone*)GetIndexForZonePointer(MapZoneArray[i].next); +#else + SaveOneZone(MapZoneArray[i], buffer); +#endif } for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) @@ -693,6 +733,32 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) VALIDATESAVEBUF(*size) } +#ifdef COMPATIBLE_SAVES +static inline void +LoadOneZone(CZone &zone, uint8 *&buffer) +{ + memcpy(zone.name, buffer, sizeof(zone.name)); + SkipSaveBuf(buffer, sizeof(zone.name)); + ReadSaveBuf(&zone.minx, buffer); + ReadSaveBuf(&zone.miny, buffer); + ReadSaveBuf(&zone.minz, buffer); + ReadSaveBuf(&zone.maxx, buffer); + ReadSaveBuf(&zone.maxy, buffer); + ReadSaveBuf(&zone.maxz, buffer); + ReadSaveBuf(&zone.type, buffer); + ReadSaveBuf(&zone.level, buffer); + ReadSaveBuf(&zone.zoneinfoDay, buffer); + ReadSaveBuf(&zone.zoneinfoNight, buffer); + int32 tmp; + ReadSaveBuf(&tmp, buffer); + zone.child = CTheZones::GetPointerForZoneIndex(tmp); + ReadSaveBuf(&tmp, buffer); + zone.parent = CTheZones::GetPointerForZoneIndex(tmp); + ReadSaveBuf(&tmp, buffer); + zone.next = CTheZones::GetPointerForZoneIndex(tmp); +} +#endif + void CTheZones::LoadAllZones(uint8 *buffer, uint32 size) { @@ -708,11 +774,15 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) SkipSaveBuf(buffer, 2); for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ +#ifdef COMPATIBLE_SAVES + LoadOneZone(ZoneArray[i], buffer); +#else ReadSaveBuf(&ZoneArray[i], buffer); ZoneArray[i].child = GetPointerForZoneIndex((uintptr)ZoneArray[i].child); ZoneArray[i].parent = GetPointerForZoneIndex((uintptr)ZoneArray[i].parent); ZoneArray[i].next = GetPointerForZoneIndex((uintptr)ZoneArray[i].next); +#endif } for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) @@ -722,6 +792,9 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) ReadSaveBuf(&TotalNumberOfZoneInfos, buffer); for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ +#ifdef COMPATIBLE_SAVES + LoadOneZone(MapZoneArray[i], buffer); +#else ReadSaveBuf(&MapZoneArray[i], buffer); /* @@ -732,6 +805,7 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) MapZoneArray[i].child = GetPointerForZoneIndex((uintptr)MapZoneArray[i].child); MapZoneArray[i].parent = GetPointerForZoneIndex((uintptr)MapZoneArray[i].parent); MapZoneArray[i].next = GetPointerForZoneIndex((uintptr)MapZoneArray[i].next); +#endif assert(MapZoneArray[i].child == nil); assert(MapZoneArray[i].parent == nil); assert(MapZoneArray[i].next == nil); diff --git a/src/core/config.h b/src/core/config.h index 298b2a1a..2abaec13 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -1,7 +1,9 @@ #pragma once -// disables (most) stuff that wasn't in original gta3.exe - check section at the bottom of this file -//#define VANILLA_DEFINES +// disables (most) stuff that wasn't in original gta3.exe +#ifdef __MWERKS__ +#define VANILLA_DEFINES +#endif enum Config { NUMPLAYERS = 1, // 4 on PS2 @@ -11,7 +13,7 @@ enum Config { MAX_CDCHANNELS = 5, MODELINFOSIZE = 5500, // 3150 on PS2 -#if defined __MWERKS__ || defined VANILLA_DEFINES +#ifdef VANILLA_DEFINES TXDSTORESIZE = 850, #else TXDSTORESIZE = 1024, // for Xbox map @@ -146,8 +148,30 @@ enum Config { //#define GTA_PS2 //#define GTA_XBOX -// This enables things from the PS2 version on PC -#define GTA_PS2_STUFF +// Version defines +#define GTA3_PS2_140 300 +#define GTA3_PS2_160 301 +#define GTA3_PC_10 310 +#define GTA3_PC_11 311 +#define GTA3_PC_STEAM 312 +// TODO? maybe something for xbox or android? + +#define GTA_VERSION GTA3_PC_11 + +#if defined GTA_PS2 +# define GTA_PS2_STUFF +# define RANDOMSPLASH +# define USE_CUSTOM_ALLOCATOR +# define VU_COLLISION +# define ANIM_COMPRESSION +# define PS2_MENU +#elif defined GTA_PC +# define PC_PLAYER_CONTROLS // mouse player/cam mode +# define GTA_REPLAY +# define GTA_SCENE_EDIT +# define PC_MENU +#elif defined GTA_XBOX +#endif // This is enabled for all released games. // any debug stuff that isn't left in any game is not in FINAL @@ -166,19 +190,29 @@ enum Config { #define FINAL #endif -// Version defines -#define GTA3_PS2_140 300 -#define GTA3_PS2_160 301 -#define GTA3_PC_10 310 -#define GTA3_PC_11 311 -#define GTA3_PC_STEAM 312 -// TODO? maybe something for xbox or android? +// these are placed here to work with VANILLA_DEFINES for compatibility +#define NO_CDCHECK // skip audio CD check +#define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) -#define GTA_VERSION GTA3_PC_11 +#ifdef VANILLA_DEFINES +#if !defined(_WIN32) || defined(__LP64__) || defined(_WIN64) +#error Vanilla can only be built for win-x86 +#endif + +#define FINAL +#define MASTER +//#define USE_MY_DOCUMENTS +#define THIS_IS_STUPID +#define PC_PARTICLE +#define DONT_FIX_REPLAY_BUGS +#define USE_TXD_CDIMAGE // generate and load textures from txd.img +//#define USE_TEXTURE_POOL // not possible because R* used custom RW33 +#else +// This enables things from the PS2 version on PC +#define GTA_PS2_STUFF // quality of life fixes that should also be in FINAL #define NASTY_GAME // nasty game for all languages -#define NO_CDCHECK // those infamous texts #define DRAW_GAME_VERSION_TEXT @@ -194,22 +228,10 @@ enum Config { //#define COMPRESSED_COL_VECTORS // use compressed vectors for collision vertices //#define ANIM_COMPRESSION // only keep most recently used anims uncompressed -#if defined GTA_PS2 -# define GTA_PS2_STUFF -# define RANDOMSPLASH -# define USE_CUSTOM_ALLOCATOR -# define VU_COLLISION -# define ANIM_COMPRESSION -#elif defined GTA_PC -# ifdef GTA_PS2_STUFF -# define USE_PS2_RAND -# define RANDOMSPLASH // use random splash as on PS2 -# define PS2_MATFX -# endif -# define PC_PLAYER_CONTROLS // mouse player/cam mode -# define GTA_REPLAY -# define GTA_SCENE_EDIT -#elif defined GTA_XBOX +#if defined GTA_PC && defined GTA_PS2_STUFF +# define USE_PS2_RAND +# define RANDOMSPLASH // use random splash as on PS2 +# define PS2_MATFX #endif #ifdef VU_COLLISION @@ -237,7 +259,8 @@ enum Config { #define FIX_BUGS // fixes bugs that we've came across during reversing. You can undefine this only on release builds. #define MORE_LANGUAGES // Add more translations to the game -#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible +#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible, and keeps saves compatible between platforms, needs to be enabled on 64bit builds! +#define FIX_INCOMPATIBLE_SAVES // try to fix incompatible saves, requires COMPATIBLE_SAVES #define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS #define NO_MOVIES // add option to disable intro videos @@ -248,7 +271,7 @@ enum Config { #define ASCII_STRCMP // use faster ascii str comparisons -#if !defined _WIN32 || defined __MWERKS__ || defined __MINGW32__ || defined VANILLA_DEFINES +#if !defined _WIN32 || defined __MINGW32__ #undef ASCII_STRCMP #endif @@ -340,6 +363,7 @@ enum Config { # define CUTSCENE_BORDERS_SWITCH # define MULTISAMPLING // adds MSAA option # define INVERT_LOOK_FOR_PAD // add bInvertLook4Pad from VC +# define PED_CAR_DENSITY_SLIDERS # endif #endif @@ -385,7 +409,7 @@ enum Config { // #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle // #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward #define CANCELLABLE_CAR_ENTER -//#define PEDS_REPORT_CRIMES_ON_PHONE, requires COMPATIBLE_SAVES +//#define PEDS_REPORT_CRIMES_ON_PHONE // requires COMPATIBLE_SAVES // Camera //#define PS2_CAM_TRANSITION // old way of transitioning between cam modes @@ -396,7 +420,7 @@ enum Config { #define RADIO_SCROLL_TO_PREV_STATION #define AUDIO_CACHE #define PS2_AUDIO_CHANNELS // increases the maximum number of audio channels to PS2 value of 44 (PC has 28 originally) -//#define PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds) +#define PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds) //#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder #define AUDIO_OAL_USE_MPG123 // use mpg123 to support mp3 files #define PAUSE_RADIO_IN_FRONTEND // pause radio when game is paused @@ -437,101 +461,4 @@ enum Config { #undef PEDS_REPORT_CRIMES_ON_PHONE #endif -// ------- - -#if defined __MWERKS__ || defined VANILLA_DEFINES -#define FINAL -#undef CHATTYSPLASH -#undef TIMEBARS -//#define USE_MY_DOCUMENTS - -#define MASTER -#undef VALIDATE_SAVE_SIZE -#undef NO_MOVIES -#undef DEBUGMENU - -//#undef NASTY_GAME -//#undef NO_CDCHECK - -#undef DRAW_GAME_VERSION_TEXT -#undef DRAW_MENU_VERSION_TEXT - -#undef GTA_PS2_STUFF -#undef USE_PS2_RAND -#undef RANDOMSPLASH -#undef PS2_MATFX - -#undef FIX_BUGS -#define THIS_IS_STUPID -#undef MORE_LANGUAGES -#undef COMPATIBLE_SAVES -#undef LOAD_INI_SETTINGS - -#undef ASPECT_RATIO_SCALE -#undef PROPER_SCALING -//#undef DEFAULT_NATIVE_RESOLUTION -#undef PS2_ALPHA_TEST -#undef IMPROVED_VIDEOMODE -#undef DISABLE_LOADING_SCREEN -#undef DISABLE_VSYNC_ON_TEXTURE_CONVERSION -#undef ANISOTROPIC_FILTERING -//#define USE_TEXTURE_POOL // not possible because R* used custom RW33 - -#undef EXTENDED_COLOURFILTER -#undef EXTENDED_PIPELINES -#undef SCREEN_DROPLETS -#undef NEW_RENDERER - -#undef FIX_SPRITES - -#define PC_PARTICLE - -#undef XINPUT -#undef DETECT_PAD_INPUT_SWITCH -#undef KANGAROO_CHEAT -#undef ALLCARSHELI_CHEAT -#undef ALT_DODO_CHEAT -#undef REGISTER_START_BUTTON -#undef BIND_VEHICLE_FIREWEAPON -#undef BUTTON_ICONS - -#undef HUD_ENHANCEMENTS -#undef TRIANGULAR_BLIPS -#undef FIX_RADAR -#undef RADIO_OFF_TEXT - -#undef MENU_MAP -#undef GAMEPAD_MENU -#undef SCROLLABLE_STATS_PAGE -#undef CUSTOM_FRONTEND_OPTIONS - -#undef GRAPHICS_MENU_OPTIONS -#undef NO_ISLAND_LOADING -#undef CUTSCENE_BORDERS_SWITCH -#undef MULTISAMPLING -#undef INVERT_LOOK_FOR_PAD - -#undef USE_DEBUG_SCRIPT_LOADER -#undef USE_MEASUREMENTS_IN_METERS -#undef USE_PRECISE_MEASUREMENT_CONVERTION -#undef MISSION_REPLAY -#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT -#undef USE_BASIC_SCRIPT_DEBUG_OUTPUT - -#define DONT_FIX_REPLAY_BUGS - -#undef EXPLODING_AIRTRAIN -#undef CAMERA_PICKUP -#undef PED_SKIN -#undef ANIMATE_PED_COL_MODEL -#undef CANCELLABLE_CAR_ENTER -#undef IMPROVED_CAMERA -#undef FREE_CAM - -#undef RADIO_SCROLL_TO_PREV_STATION -#undef AUDIO_CACHE -#undef PS2_AUDIO_CHANNELS -#undef PAUSE_RADIO_IN_FRONTEND -#undef MULTITHREADED_AUDIO -#undef BIG_IMG -#endif +#endif // VANILLA_DEFINES diff --git a/src/core/re3.cpp b/src/core/re3.cpp index fe0347d9..b7d89363 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -41,6 +41,9 @@ #include "Camera.h" #include "MBlur.h" #include "ControllerConfig.h" +#include "CarCtrl.h" +#include "Population.h" +#include "IniFile.h" #ifdef DETECT_JOYSTICK_MENU #include "crossplatform.h" @@ -179,16 +182,29 @@ CustomFrontendOptionsPopulate(void) #endif #ifdef LOAD_INI_SETTINGS -#include "ini_parser.hpp" +#define MINI_CASE_SENSITIVE +#include "ini.h" + +mINI::INIFile ini("re3.ini"); +mINI::INIStructure cfg; -linb::ini cfg; bool ReadIniIfExists(const char *cat, const char *key, uint32 *out) { - std::string strval = cfg.get(cat, key, "\xBA"); - const char *value = strval.c_str(); - char *endPtr; - if (value && value[0] != '\xBA') { - *out = strtoul(value, &endPtr, 0); + mINI::INIMap<std::string> section = cfg.get(cat); + if (section.has(key)) { + char *endPtr; + *out = strtoul(section.get(key).c_str(), &endPtr, 0); + return true; + } + return false; +} + +bool ReadIniIfExists(const char *cat, const char *key, uint8 *out) +{ + mINI::INIMap<std::string> section = cfg.get(cat); + if (section.has(key)) { + char *endPtr; + *out = strtoul(section.get(key).c_str(), &endPtr, 0); return true; } return false; @@ -196,11 +212,10 @@ bool ReadIniIfExists(const char *cat, const char *key, uint32 *out) bool ReadIniIfExists(const char *cat, const char *key, bool *out) { - std::string strval = cfg.get(cat, key, "\xBA"); - const char *value = strval.c_str(); - char *endPtr; - if (value && value[0] != '\xBA') { - *out = strtoul(value, &endPtr, 0); + mINI::INIMap<std::string> section = cfg.get(cat); + if (section.has(key)) { + char *endPtr; + *out = strtoul(section.get(key).c_str(), &endPtr, 0); return true; } return false; @@ -208,11 +223,10 @@ bool ReadIniIfExists(const char *cat, const char *key, bool *out) bool ReadIniIfExists(const char *cat, const char *key, int32 *out) { - std::string strval = cfg.get(cat, key, "\xBA"); - const char *value = strval.c_str(); - char *endPtr; - if (value && value[0] != '\xBA') { - *out = strtol(value, &endPtr, 0); + mINI::INIMap<std::string> section = cfg.get(cat); + if (section.has(key)) { + char *endPtr; + *out = strtol(section.get(key).c_str(), &endPtr, 0); return true; } return false; @@ -220,11 +234,10 @@ bool ReadIniIfExists(const char *cat, const char *key, int32 *out) bool ReadIniIfExists(const char *cat, const char *key, int8 *out) { - std::string strval = cfg.get(cat, key, "\xBA"); - const char *value = strval.c_str(); - char *endPtr; - if (value && value[0] != '\xBA') { - *out = strtol(value, &endPtr, 0); + mINI::INIMap<std::string> section = cfg.get(cat); + if (section.has(key)) { + char *endPtr; + *out = strtol(section.get(key).c_str(), &endPtr, 0); return true; } return false; @@ -232,10 +245,10 @@ bool ReadIniIfExists(const char *cat, const char *key, int8 *out) bool ReadIniIfExists(const char *cat, const char *key, float *out) { - std::string strval = cfg.get(cat, key, "\xBA"); - const char *value = strval.c_str(); - if (value && value[0] != '\xBA') { - *out = atof(value); + mINI::INIMap<std::string> section = cfg.get(cat); + if (section.has(key)) { + char *endPtr; + *out = strtof(section.get(key).c_str(), &endPtr); return true; } return false; @@ -243,10 +256,10 @@ bool ReadIniIfExists(const char *cat, const char *key, float *out) bool ReadIniIfExists(const char *cat, const char *key, char *out, int size) { - std::string strval = cfg.get(cat, key, "\xBA"); - const char *value = strval.c_str(); - if (value && value[0] != '\xBA') { - strncpy(out, value, size); + mINI::INIMap<std::string> section = cfg.get(cat); + if (section.has(key)) { + strncpy(out, section.get(key).c_str(), size - 1); + out[size - 1] = '\0'; return true; } return false; @@ -254,42 +267,42 @@ bool ReadIniIfExists(const char *cat, const char *key, char *out, int size) void StoreIni(const char *cat, const char *key, uint32 val) { - char temp[10]; + char temp[11]; sprintf(temp, "%u", val); - cfg.set(cat, key, temp); + cfg[cat][key] = temp; } void StoreIni(const char *cat, const char *key, uint8 val) { - char temp[10]; - sprintf(temp, "%u", (uint32)val); - cfg.set(cat, key, temp); + char temp[11]; + sprintf(temp, "%u", val); + cfg[cat][key] = temp; } void StoreIni(const char *cat, const char *key, int32 val) { - char temp[10]; + char temp[11]; sprintf(temp, "%d", val); - cfg.set(cat, key, temp); + cfg[cat][key] = temp; } void StoreIni(const char *cat, const char *key, int8 val) { - char temp[10]; - sprintf(temp, "%d", (int32)val); - cfg.set(cat, key, temp); + char temp[11]; + sprintf(temp, "%d", val); + cfg[cat][key] = temp; } void StoreIni(const char *cat, const char *key, float val) { - char temp[10]; + char temp[50]; sprintf(temp, "%f", val); - cfg.set(cat, key, temp); + cfg[cat][key] = temp; } void StoreIni(const char *cat, const char *key, char *val, int size) { - cfg.set(cat, key, val); + cfg[cat][key] = val; } const char *iniControllerActions[] = { "PED_FIREWEAPON", "PED_CYCLE_WEAPON_RIGHT", "PED_CYCLE_WEAPON_LEFT", "GO_FORWARD", "GO_BACK", "GO_LEFT", "GO_RIGHT", "PED_SNIPER_ZOOM_IN", @@ -351,7 +364,7 @@ void LoadINIControllerSettings() #endif // force to default GTA behaviour (never overwrite bindings on joy change/initialization) if user init'ed/set bindings before we introduced that if (!ReadIniIfExists("Controller", "PadButtonsInited", &ControlsManager.ms_padButtonsInited)) { - ControlsManager.ms_padButtonsInited = cfg.category_size("Bindings") != 0 ? 16 : 0; + ControlsManager.ms_padButtonsInited = cfg.get("Bindings").size() != 0 ? 16 : 0; } for (int32 i = 0; i < MAX_CONTROLLERACTIONS; i++) { @@ -453,12 +466,13 @@ void SaveINIControllerSettings() #endif #endif StoreIni("Controller", "PadButtonsInited", ControlsManager.ms_padButtonsInited); - cfg.write_file("re3.ini"); + + ini.write(cfg); } bool LoadINISettings() { - if (!cfg.load_file("re3.ini")) + if (!ini.read(cfg)) return false; #ifdef IMPROVED_VIDEOMODE @@ -524,7 +538,7 @@ bool LoadINISettings() #endif #ifdef CUSTOM_FRONTEND_OPTIONS - bool migrate = cfg.category_size("FrontendOptions") != 0; + bool migrate = cfg.get("FrontendOptions").size() != 0; for (int i = 0; i < MENUPAGES; i++) { for (int j = 0; j < NUM_MENUROWS; j++) { CMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j]; @@ -533,22 +547,29 @@ bool LoadINISettings() // CFO check if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) { - // CFO only supports saving uint8 right now - // Migrate from old .ini to new .ini - if (migrate && ReadIniIfExists("FrontendOptions", option.m_CFO->save, option.m_CFO->value)) - cfg.remove("FrontendOptions", option.m_CFO->save); + // Old values can only be int8, new ones can contain float if it is slider + if (migrate && ReadIniIfExists("FrontendOptions", option.m_CFO->save, (int8*)option.m_CFO->value)) + cfg["FrontendOptions"].remove(option.m_CFO->save); + else if (option.m_Action == MENUACTION_CFO_SLIDER) + ReadIniIfExists(option.m_CFO->saveCat, option.m_CFO->save, (float*)option.m_CFO->value); else - ReadIniIfExists(option.m_CFO->saveCat, option.m_CFO->save, option.m_CFO->value); + ReadIniIfExists(option.m_CFO->saveCat, option.m_CFO->save, (int8*)option.m_CFO->value); if (option.m_Action == MENUACTION_CFO_SELECT) { - option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue = *option.m_CFO->value; + option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue = *(int8*)option.m_CFO->value; } } } } #endif + // Fetched in above block, but needs evaluation +#ifdef PED_CAR_DENSITY_SLIDERS + CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS * CIniFile::PedNumberMultiplier; + CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS * CIniFile::CarNumberMultiplier; +#endif + return true; } @@ -623,14 +644,16 @@ void SaveINISettings() break; if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) { - // Beware: CFO only supports saving uint8 right now - StoreIni(option.m_CFO->saveCat, option.m_CFO->save, *option.m_CFO->value); + if (option.m_Action == MENUACTION_CFO_SLIDER) + StoreIni(option.m_CFO->saveCat, option.m_CFO->save, *(float*)option.m_CFO->value); + else + StoreIni(option.m_CFO->saveCat, option.m_CFO->save, *(int8*)option.m_CFO->value); } } } #endif - cfg.write_file("re3.ini"); + ini.write(cfg); } #endif diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index a7f4bd45..c38f12c7 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -732,7 +732,7 @@ CEntity::SaveEntityFlags(uint8*& buf) if (bZoneCulled) tmp |= BIT(30); if (bZoneCulled2) tmp |= BIT(31); - WriteSaveBuf<uint32>(buf, tmp); + WriteSaveBuf(buf, tmp); tmp = 0; @@ -748,7 +748,7 @@ CEntity::SaveEntityFlags(uint8*& buf) if (bDistanceFade) tmp |= BIT(8); if (m_flagE2) tmp |= BIT(9); - WriteSaveBuf<uint32>(buf, tmp); + WriteSaveBuf(buf, tmp); } void diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h index 8b64335a..a571170f 100644 --- a/src/extras/frontendoption.h +++ b/src/extras/frontendoption.h @@ -40,6 +40,8 @@ typedef void (*ReturnPrevPageFunc)(); typedef void (*ChangeFunc)(int8 before, int8 after); // called after updating the value. // only called on enter if onlyApplyOnEnter set, otherwise called on every value change +typedef void (*ChangeFuncFloat)(float before, float after); // called after updating the value. + // for dynamic options typedef wchar* (*DrawFunc)(bool* disabled, bool userHovering); // you must return a pointer for right text. // you can also set *disabled if you want to gray it out. diff --git a/src/extras/ini.h b/src/extras/ini.h new file mode 100644 index 00000000..44dd3d57 --- /dev/null +++ b/src/extras/ini.h @@ -0,0 +1,761 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2018 Danijel Durakovic + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/////////////////////////////////////////////////////////////////////////////// +// +// /mINI/ v0.9.10 +// An INI file reader and writer for the modern age. +// +/////////////////////////////////////////////////////////////////////////////// +// +// A tiny utility library for manipulating INI files with a straightforward +// API and a minimal footprint. It conforms to the (somewhat) standard INI +// format - sections and keys are case insensitive and all leading and +// trailing whitespace is ignored. Comments are lines that begin with a +// semicolon. Trailing comments are allowed on section lines. +// +// Files are read on demand, upon which data is kept in memory and the file +// is closed. This utility supports lazy writing, which only writes changes +// and updates to a file and preserves custom formatting and comments. A lazy +// write invoked by a write() call will read the output file, find what +// changes have been made and update the file accordingly. If you only need to +// generate files, use generate() instead. Section and key order is preserved +// on read, write and insert. +// +/////////////////////////////////////////////////////////////////////////////// +// +// /* BASIC USAGE EXAMPLE: */ +// +// /* read from file */ +// mINI::INIFile file("myfile.ini"); +// mINI::INIStructure ini; +// file.read(ini); +// +// /* read value; gets a reference to actual value in the structure. +// if key or section don't exist, a new empty value will be created */ +// std::string& value = ini["section"]["key"]; +// +// /* read value safely; gets a copy of value in the structure. +// does not alter the structure */ +// std::string value = ini.get("section").get("key"); +// +// /* set or update values */ +// ini["section"]["key"] = "value"; +// +// /* set multiple values */ +// ini["section2"].set({ +// {"key1", "value1"}, +// {"key2", "value2"} +// }); +// +// /* write updates back to file, preserving comments and formatting */ +// file.write(ini); +// +// /* or generate a file (overwrites the original) */ +// file.generate(ini); +// +/////////////////////////////////////////////////////////////////////////////// +// +// Long live the INI file!!! +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef MINI_INI_H_ +#define MINI_INI_H_ + +#include <string> +#include <sstream> +#include <algorithm> +#include <utility> +#include <unordered_map> +#include <vector> +#include <memory> +#include <fstream> +#include <sys/stat.h> +#include <cctype> + +namespace mINI +{ + namespace INIStringUtil + { + const char* const whitespaceDelimiters = " \t\n\r\f\v"; + inline void trim(std::string& str) + { + str.erase(str.find_last_not_of(whitespaceDelimiters) + 1); + str.erase(0, str.find_first_not_of(whitespaceDelimiters)); + } +#ifndef MINI_CASE_SENSITIVE + inline void toLower(std::string& str) + { + std::transform(str.begin(), str.end(), str.begin(), [](const char c) { + return static_cast<const char>(std::tolower(c)); + }); + } +#endif + inline void replace(std::string& str, std::string const& a, std::string const& b) + { + if (!a.empty()) + { + std::size_t pos = 0; + while ((pos = str.find(a, pos)) != std::string::npos) + { + str.replace(pos, a.size(), b); + pos += b.size(); + } + } + } +#ifdef _WIN32 + const char* const endl = "\r\n"; +#else + const char* const endl = "\n"; +#endif + }; + + template<typename T> + class INIMap + { + private: + using T_DataIndexMap = std::unordered_map<std::string, std::size_t>; + using T_DataItem = std::pair<std::string, T>; + using T_DataContainer = std::vector<T_DataItem>; + using T_MultiArgs = typename std::vector<std::pair<std::string, T>>; + + T_DataIndexMap dataIndexMap; + T_DataContainer data; + + inline std::size_t setEmpty(std::string& key) + { + std::size_t index = data.size(); + dataIndexMap[key] = index; + data.emplace_back(key, T()); + return index; + } + + public: + using const_iterator = typename T_DataContainer::const_iterator; + + INIMap() { } + + INIMap(INIMap const& other) + { + std::size_t data_size = other.data.size(); + for (std::size_t i = 0; i < data_size; ++i) + { + auto const& key = other.data[i].first; + auto const& obj = other.data[i].second; + data.emplace_back(key, obj); + } + dataIndexMap = T_DataIndexMap(other.dataIndexMap); + } + + T& operator[](std::string key) + { + INIStringUtil::trim(key); +#ifndef MINI_CASE_SENSITIVE + INIStringUtil::toLower(key); +#endif + auto it = dataIndexMap.find(key); + bool hasIt = (it != dataIndexMap.end()); + std::size_t index = (hasIt) ? it->second : setEmpty(key); + return data[index].second; + } + T get(std::string key) const + { + INIStringUtil::trim(key); +#ifndef MINI_CASE_SENSITIVE + INIStringUtil::toLower(key); +#endif + auto it = dataIndexMap.find(key); + if (it == dataIndexMap.end()) + { + return T(); + } + return T(data[it->second].second); + } + bool has(std::string key) const + { + INIStringUtil::trim(key); +#ifndef MINI_CASE_SENSITIVE + INIStringUtil::toLower(key); +#endif + return (dataIndexMap.count(key) == 1); + } + void set(std::string key, T obj) + { + INIStringUtil::trim(key); +#ifndef MINI_CASE_SENSITIVE + INIStringUtil::toLower(key); +#endif + auto it = dataIndexMap.find(key); + if (it != dataIndexMap.end()) + { + data[it->second].second = obj; + } + else + { + dataIndexMap[key] = data.size(); + data.emplace_back(key, obj); + } + } + void set(T_MultiArgs const& multiArgs) + { + for (auto const& it : multiArgs) + { + auto const& key = it.first; + auto const& obj = it.second; + set(key, obj); + } + } + bool remove(std::string key) + { + INIStringUtil::trim(key); +#ifndef MINI_CASE_SENSITIVE + INIStringUtil::toLower(key); +#endif + auto it = dataIndexMap.find(key); + if (it != dataIndexMap.end()) + { + std::size_t index = it->second; + data.erase(data.begin() + index); + dataIndexMap.erase(it); + for (auto& it2 : dataIndexMap) + { + auto& vi = it2.second; + if (vi > index) + { + vi--; + } + } + return true; + } + return false; + } + void clear() + { + data.clear(); + dataIndexMap.clear(); + } + std::size_t size() const + { + return data.size(); + } + const_iterator begin() const { return data.begin(); } + const_iterator end() const { return data.end(); } + }; + + using INIStructure = INIMap<INIMap<std::string>>; + + namespace INIParser + { + using T_ParseValues = std::pair<std::string, std::string>; + + enum class PDataType : char + { + PDATA_NONE, + PDATA_COMMENT, + PDATA_SECTION, + PDATA_KEYVALUE, + PDATA_UNKNOWN + }; + + inline PDataType parseLine(std::string line, T_ParseValues& parseData) + { + parseData.first.clear(); + parseData.second.clear(); + INIStringUtil::trim(line); + if (line.empty()) + { + return PDataType::PDATA_NONE; + } + char firstCharacter = line[0]; + if (firstCharacter == ';') + { + return PDataType::PDATA_COMMENT; + } + if (firstCharacter == '[') + { + auto commentAt = line.find_first_of(';'); + if (commentAt != std::string::npos) + { + line = line.substr(0, commentAt); + } + auto closingBracketAt = line.find_last_of(']'); + if (closingBracketAt != std::string::npos) + { + auto section = line.substr(1, closingBracketAt - 1); + INIStringUtil::trim(section); + parseData.first = section; + return PDataType::PDATA_SECTION; + } + } + auto lineNorm = line; + INIStringUtil::replace(lineNorm, "\\=", " "); + auto equalsAt = lineNorm.find_first_of('='); + if (equalsAt != std::string::npos) + { + auto key = line.substr(0, equalsAt); + INIStringUtil::trim(key); + INIStringUtil::replace(key, "\\=", "="); + auto value = line.substr(equalsAt + 1); + INIStringUtil::trim(value); + parseData.first = key; + parseData.second = value; + return PDataType::PDATA_KEYVALUE; + } + return PDataType::PDATA_UNKNOWN; + } + }; + + class INIReader + { + public: + using T_LineData = std::vector<std::string>; + using T_LineDataPtr = std::shared_ptr<T_LineData>; + + private: + std::ifstream fileReadStream; + T_LineDataPtr lineData; + + T_LineData readFile() + { + std::string fileContents; + fileReadStream.seekg(0, std::ios::end); + fileContents.resize(fileReadStream.tellg()); + fileReadStream.seekg(0, std::ios::beg); + std::size_t fileSize = fileContents.size(); + fileReadStream.read(&fileContents[0], fileSize); + fileReadStream.close(); + T_LineData output; + if (fileSize == 0) + { + return output; + } + std::string buffer; + buffer.reserve(50); + for (std::size_t i = 0; i < fileSize; ++i) + { + char& c = fileContents[i]; + if (c == '\n') + { + output.emplace_back(buffer); + buffer.clear(); + continue; + } + if (c != '\0' && c != '\r') + { + buffer += c; + } + } + output.emplace_back(buffer); + return output; + } + + public: + INIReader(std::string const& filename, bool keepLineData = false) + { + fileReadStream.open(filename, std::ios::in | std::ios::binary); + if (keepLineData) + { + lineData = std::make_shared<T_LineData>(); + } + } + ~INIReader() { } + + bool operator>>(INIStructure& data) + { + if (!fileReadStream.is_open()) + { + return false; + } + T_LineData fileLines = readFile(); + std::string section; + bool inSection = false; + INIParser::T_ParseValues parseData; + for (auto const& line : fileLines) + { + auto parseResult = INIParser::parseLine(line, parseData); + if (parseResult == INIParser::PDataType::PDATA_SECTION) + { + inSection = true; + data[section = parseData.first]; + } + else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE) + { + auto const& key = parseData.first; + auto const& value = parseData.second; + data[section][key] = value; + } + if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN) + { + if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection) + { + continue; + } + lineData->emplace_back(line); + } + } + return true; + } + T_LineDataPtr getLines() + { + return lineData; + } + }; + + class INIGenerator + { + private: + std::ofstream fileWriteStream; + + public: + bool prettyPrint = false; + + INIGenerator(std::string const& filename) + { + fileWriteStream.open(filename, std::ios::out | std::ios::binary); + } + ~INIGenerator() { } + + bool operator<<(INIStructure const& data) + { + if (!fileWriteStream.is_open()) + { + return false; + } + if (!data.size()) + { + return true; + } + auto it = data.begin(); + for (;;) + { + auto const& section = it->first; + auto const& collection = it->second; + fileWriteStream + << "[" + << section + << "]"; + if (collection.size()) + { + fileWriteStream << INIStringUtil::endl; + auto it2 = collection.begin(); + for (;;) + { + auto key = it2->first; + INIStringUtil::replace(key, "=", "\\="); + auto value = it2->second; + INIStringUtil::trim(value); + fileWriteStream + << key + << ((prettyPrint) ? " = " : "=") + << value; + if (++it2 == collection.end()) + { + break; + } + fileWriteStream << INIStringUtil::endl; + } + } + if (++it == data.end()) + { + break; + } + fileWriteStream << INIStringUtil::endl; + if (prettyPrint) + { + fileWriteStream << INIStringUtil::endl; + } + } + return true; + } + }; + + class INIWriter + { + private: + using T_LineData = std::vector<std::string>; + using T_LineDataPtr = std::shared_ptr<T_LineData>; + + std::string filename; + + T_LineData getLazyOutput(T_LineDataPtr const& lineData, INIStructure& data, INIStructure& original) + { + T_LineData output; + INIParser::T_ParseValues parseData; + std::string sectionCurrent; + bool parsingSection = false; + bool continueToNextSection = false; + bool discardNextEmpty = false; + bool writeNewKeys = false; + std::size_t lastKeyLine = 0; + for (auto line = lineData->begin(); line != lineData->end(); ++line) + { + if (!writeNewKeys) + { + auto parseResult = INIParser::parseLine(*line, parseData); + if (parseResult == INIParser::PDataType::PDATA_SECTION) + { + if (parsingSection) + { + writeNewKeys = true; + parsingSection = false; + --line; + continue; + } + sectionCurrent = parseData.first; + if (data.has(sectionCurrent)) + { + parsingSection = true; + continueToNextSection = false; + discardNextEmpty = false; + output.emplace_back(*line); + lastKeyLine = output.size(); + } + else + { + continueToNextSection = true; + discardNextEmpty = true; + continue; + } + } + else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE) + { + if (continueToNextSection) + { + continue; + } + if (data.has(sectionCurrent)) + { + auto& collection = data[sectionCurrent]; + auto const& key = parseData.first; + auto const& value = parseData.second; + if (collection.has(key)) + { + auto outputValue = collection[key]; + if (value == outputValue) + { + output.emplace_back(*line); + } + else + { + INIStringUtil::trim(outputValue); + auto lineNorm = *line; + INIStringUtil::replace(lineNorm, "\\=", " "); + auto equalsAt = lineNorm.find_first_of('='); + auto valueAt = lineNorm.find_first_not_of( + INIStringUtil::whitespaceDelimiters, + equalsAt + 1 + ); + std::string outputLine = line->substr(0, valueAt); + if (prettyPrint && equalsAt + 1 == valueAt) + { + outputLine += " "; + } + outputLine += outputValue; + output.emplace_back(outputLine); + } + lastKeyLine = output.size(); + } + } + } + else + { + if (discardNextEmpty && line->empty()) + { + discardNextEmpty = false; + } + else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN) + { + output.emplace_back(*line); + } + } + } + if (writeNewKeys || std::next(line) == lineData->end()) + { + T_LineData linesToAdd; + if (data.has(sectionCurrent) && original.has(sectionCurrent)) + { + auto const& collection = data[sectionCurrent]; + auto const& collectionOriginal = original[sectionCurrent]; + for (auto const& it : collection) + { + auto key = it.first; + if (collectionOriginal.has(key)) + { + continue; + } + auto value = it.second; + INIStringUtil::replace(key, "=", "\\="); + INIStringUtil::trim(value); + linesToAdd.emplace_back( + key + ((prettyPrint) ? " = " : "=") + value + ); + } + } + if (!linesToAdd.empty()) + { + output.insert( + output.begin() + lastKeyLine, + linesToAdd.begin(), + linesToAdd.end() + ); + } + if (writeNewKeys) + { + writeNewKeys = false; + --line; + } + } + } + for (auto const& it : data) + { + auto const& section = it.first; + if (original.has(section)) + { + continue; + } + if (prettyPrint && output.size() > 0 && !output.back().empty()) + { + output.emplace_back(); + } + output.emplace_back("[" + section + "]"); + auto const& collection = it.second; + for (auto const& it2 : collection) + { + auto key = it2.first; + auto value = it2.second; + INIStringUtil::replace(key, "=", "\\="); + INIStringUtil::trim(value); + output.emplace_back( + key + ((prettyPrint) ? " = " : "=") + value + ); + } + } + return output; + } + + public: + bool prettyPrint = false; + + INIWriter(std::string const& filename) + : filename(filename) + { + } + ~INIWriter() { } + + bool operator<<(INIStructure& data) + { + struct stat buf; + bool fileExists = (stat(filename.c_str(), &buf) == 0); + if (!fileExists) + { + INIGenerator generator(filename); + generator.prettyPrint = prettyPrint; + return generator << data; + } + INIStructure originalData; + T_LineDataPtr lineData; + bool readSuccess = false; + { + INIReader reader(filename, true); + if ((readSuccess = reader >> originalData)) + { + lineData = reader.getLines(); + } + } + if (!readSuccess) + { + return false; + } + T_LineData output = getLazyOutput(lineData, data, originalData); + std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary); + if (fileWriteStream.is_open()) + { + if (output.size()) + { + auto line = output.begin(); + for (;;) + { + fileWriteStream << *line; + if (++line == output.end()) + { + break; + } + fileWriteStream << INIStringUtil::endl; + } + } + return true; + } + return false; + } + }; + + class INIFile + { + private: + std::string filename; + + public: + INIFile(std::string const& filename) + : filename(filename) + { } + + ~INIFile() { } + + bool read(INIStructure& data) const + { + if (data.size()) + { + data.clear(); + } + if (filename.empty()) + { + return false; + } + INIReader reader(filename); + return reader >> data; + } + bool generate(INIStructure const& data, bool pretty = false) const + { + if (filename.empty()) + { + return false; + } + INIGenerator generator(filename); + generator.prettyPrint = pretty; + return generator << data; + } + bool write(INIStructure& data, bool pretty = false) const + { + if (filename.empty()) + { + return false; + } + INIWriter writer(filename); + writer.prettyPrint = pretty; + return writer << data; + } + }; +} + +#endif // MINI_INI_H_ diff --git a/src/extras/ini_parser.hpp b/src/extras/ini_parser.hpp deleted file mode 100644 index 7bea024c..00000000 --- a/src/extras/ini_parser.hpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com> - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - */ -#ifndef LINB_INI_PARSER_HPP -#define LINB_INI_PARSER_HPP - -/* - * STL-like INI Container - */ - -#include <string> // for std::string -#include <map> // for std::map -#include <cstdio> // for std::FILE -#include <algorithm> // for std::find_if -#include <functional> // for std::function - -namespace linb -{ - template< - class CharT = char, /* Not compatible with other type here, since we're using C streams */ - class StringType = std::basic_string<CharT>, - class KeyContainer = std::map<StringType, StringType>, - class SectionContainer = std::map<StringType, KeyContainer> - > class basic_ini - { - public: - typedef CharT char_type; - typedef StringType string_type; - typedef KeyContainer key_container; - typedef SectionContainer section_container; - - // Typedef container values types - typedef typename section_container::value_type value_type; - typedef typename section_container::key_type key_type; - typedef typename section_container::mapped_type mapped_type; - - // Typedef common types - typedef typename section_container::size_type size_type; - typedef typename section_container::difference_type difference_type; - - // Typedef iterators - typedef typename section_container::iterator iterator; - typedef typename section_container::const_iterator const_iterator; - typedef typename section_container::reverse_iterator reverse_iterator; - typedef typename section_container::const_reverse_iterator const_reverse_iterator; - - // typedef References and pointers - typedef typename section_container::reference reference; - typedef typename section_container::const_reference const_reference; - typedef typename section_container::pointer pointer; - typedef typename section_container::const_pointer const_pointer; - - private: - section_container data; - - public: - - basic_ini() - { } - - basic_ini(const char_type* filename) - { this->read_file(filename); } - - /* Iterator methods */ - iterator begin() - { return data.begin(); } - const_iterator begin() const - { return data.begin(); } - iterator end() - { return data.end(); } - const_iterator end() const - { return data.end(); } - const_iterator cbegin() const - { return data.cbegin(); } - const_iterator cend() const - { return data.cend(); } - - /* Reverse iterator methods */ - reverse_iterator rbegin() - { return data.rbegin(); } - const_reverse_iterator rbegin() const - { return data.rbegin(); } - reverse_iterator rend() - { return data.rend(); } - const_reverse_iterator rend() const - { return data.rend(); } - const_reverse_iterator crbegin() const - { return data.crbegin(); } - const_reverse_iterator crend() const - { return data.crend(); } - - /* Acessing index methods */ - mapped_type& operator[](const string_type& sect) - { return data[sect]; } - mapped_type& operator[](string_type&& sect) - { return data[std::forward<string_type>(sect)]; } - mapped_type& at( const string_type& sect) - { return data.at(sect); } - const mapped_type& at(const string_type& sect) const - { return data.at(sect); } - - /* Capacity information */ - bool empty() const - { return data.empty(); } - size_type size() const - { return data.size(); } - size_type max_size() const - { return data.max_size(); } - - /* Modifiers */ - void clear() - { return data.clear(); } - - /* Lookup */ - size_type count(const string_type& sect) - { return data.count(sect); } - iterator find(const string_type& sect) - { return data.find(sect); } - - /* Gets a value from the specified section & key, default_value is returned if the sect & key doesn't exist */ - string_type get(const string_type& sect, const key_type& key, const string_type& default_value) - { - auto it = this->find(sect); - if(it != this->end()) - { - auto itv = it->second.find(key); - if(itv != it->second.end()) - return itv->second; - } - return default_value; - } - - /* Sets the value of a value in the ini */ - void set(const string_type& sect, const key_type& key, const string_type& value) - { - (*this)[sect][key] = value; // no emplace since overwrite! - } - - /* Too lazy to continue this container... If you need more methods, just add it */ - - // re3 - void remove(const string_type& sect, const key_type& key) - { - auto it = this->find(sect); - if(it != this->end()) - { - it->second.erase(key); - } - } - - int category_size(const string_type& sect) - { - auto it = this->find(sect); - if(it != this->end()) - { - return it->second.size(); - } - return 0; - } - -#if 1 - bool read_file(const char_type* filename) - { - /* Using C stream in a STL-like container, funny? - */ - if(FILE* f = fopen(filename, "r")) - { - key_container* keys = nullptr; - char_type buf[2048]; - string_type line; - string_type key; - string_type value; - string_type null_string; - size_type pos; - - // Trims an string - auto trim = [](string_type& s, bool trimLeft, bool trimRight) -> string_type& - { - if(s.size()) - { - // Ignore UTF-8 BOM - while(s.size() >= 3 && s[0] == (char)(0xEF) && s[1] == (char)(0xBB) && s[2] == (char)(0xBF)) - s.erase(s.begin(), s.begin() + 3); - - if(trimLeft) - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::function<int(int)>(::isspace)))); - if(trimRight) - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::function<int(int)>(::isspace))).base(), s.end()); - } - return s; - }; - - // Start parsing - while(fgets(buf, sizeof(buf), f)) - { - // What a thing, reading into a char buffer and then putting in the string... - line = buf; - - // Find comment and remove anything after it from the line - if((pos = line.find_first_of(';')) != line.npos) - line.erase(pos); - - // Trim the string, and if it gets empty, skip this line - if(trim(line, true, true).empty()) - continue; - - // Find section name - if(line.front() == '[' && line.back() == ']') - { - pos = line.length() - 1; //line.find_first_of(']'); - if(pos != line.npos) - { - trim(key.assign(line, 1, pos-1), true, true); - keys = &data[std::move(key)]; // Create section - } - else - keys = nullptr; - } - else - { - // Find key and value positions - pos = line.find_first_of('='); - if(pos == line.npos) - { - // There's only the key - key = line; // No need for trim, line is already trimmed - value.clear(); - } - else - { - // There's the key and the value - trim(key.assign(line, 0, pos), false, true); // trim the right - trim(value.assign(line, pos + 1, line.npos), true, false); // trim the left - } - - // Put the key/value into the current keys object, or into the section "" if no section has been found - #if __cplusplus >= 201103L || _MSC_VER >= 1800 - (keys ? *keys : data[null_string]).emplace(std::move(key), std::move(value)); - #else - (keys ? *keys : data[null_string])[key] = value; - key.clear(); value.clear(); - #endif - } - } - - fclose(f); - return true; - } - return false; - } - - /* - * Dumps the content of this container into an ini file - */ - bool write_file(const char_type* filename) - { - if(FILE* f = fopen(filename, "w")) - { - bool first = true; - for(auto& sec : this->data) - { - fprintf(f, first? "[%s]\n" : "\n[%s]\n", sec.first.c_str()); - first = false; - for(auto& kv : sec.second) - { - if(kv.second.empty()) - fprintf(f, "%s\n", kv.first.c_str()); - else - fprintf(f, "%s = %s\n", kv.first.c_str(), kv.second.c_str()); - } - } - fclose(f); - return true; - } - return false; - } - - - /* - */ - bool load_file(const char_type* filename) - { - return read_file(filename); - } - - bool load_file(const StringType& filename) - { - return load_file(filename.c_str()); - } - - bool write_file(const StringType& filename) - { - return write_file(filename.c_str()); - } -#endif - - - - }; - - - /* Use default basic_ini - * - * Limitations: - * * Not unicode aware - * * Case sensitive - * * Sections must have unique keys - */ - typedef basic_ini<> ini; -} - -#endif - diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index 211a568c..5d480ecc 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -10,6 +10,12 @@ #include "DMAudio.h" #include "screendroplets.h" +#ifdef COMPATIBLE_SAVES +#define PARTICLE_OBJECT_SIZEOF 0x88 +#else +#define PARTICLE_OBJECT_SIZEOF sizeof(CParticleObject) +#endif + CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS]; @@ -1111,6 +1117,49 @@ CParticleObject::UpdateFar(void) } } +#ifdef COMPATIBLE_SAVES +static inline void +SaveOneParticle(CParticleObject *p, uint8 *&buffer) +{ +#define SkipBuf(buf, num) buf += num +#define ZeroBuf(buf, num) memset(buf, 0, num); SkipBuf(buf, num) +#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipBuf(buf, sizeof(data)) + // CPlaceable + { + ZeroBuf(buffer, 4); + CopyToBuf(buffer, p->GetMatrix().f); + ZeroBuf(buffer, 4); + CopyToBuf(buffer, p->GetMatrix().m_hasRwMatrix); + ZeroBuf(buffer, 3); + } + + // CParticleObject + { + ZeroBuf(buffer, 4); + ZeroBuf(buffer, 4); + ZeroBuf(buffer, 4); + CopyToBuf(buffer, p->m_nRemoveTimer); + CopyToBuf(buffer, p->m_Type); + CopyToBuf(buffer, p->m_ParticleType); + CopyToBuf(buffer, p->m_nNumEffectCycles); + CopyToBuf(buffer, p->m_nSkipFrames); + CopyToBuf(buffer, p->m_nFrameCounter); + CopyToBuf(buffer, p->m_nState); + ZeroBuf(buffer, 2); + CopyToBuf(buffer, p->m_vecTarget); + CopyToBuf(buffer, p->m_fRandVal); + CopyToBuf(buffer, p->m_fSize); + CopyToBuf(buffer, p->m_Color); + CopyToBuf(buffer, p->m_bRemove); + CopyToBuf(buffer, p->m_nCreationChance); + ZeroBuf(buffer, 2); + } +#undef SkipBuf +#undef ZeroBuf +#undef CopyToBuf +} +#endif + bool CParticleObject::SaveParticle(uint8 *buffer, uint32 *length) { @@ -1128,27 +1177,35 @@ CParticleObject::SaveParticle(uint8 *buffer, uint32 *length) *(int32 *)buffer = numObjects; buffer += sizeof(int32); - int32 objectsLength = sizeof(CParticleObject) * (numObjects + 1); + int32 objectsLength = PARTICLE_OBJECT_SIZEOF * (numObjects + 1); int32 dataLength = objectsLength + sizeof(int32); for ( CParticleObject *p = pCloseListHead; p != NULL; p = p->m_pNext ) { -#if 0 // todo better +#ifdef COMPATIBLE_SAVES + SaveOneParticle(p, buffer); +#else +#ifdef THIS_IS_STUPID *(CParticleObject*)buffer = *p; #else memcpy(buffer, p, sizeof(CParticleObject)); #endif buffer += sizeof(CParticleObject); +#endif } for ( CParticleObject *p = pFarListHead; p != NULL; p = p->m_pNext ) { -#if 0 // todo better +#ifdef COMPATIBLE_SAVES + SaveOneParticle(p, buffer); +#else +#ifdef THIS_IS_STUPID *(CParticleObject*)buffer = *p; #else memcpy(buffer, p, sizeof(CParticleObject)); #endif buffer += sizeof(CParticleObject); +#endif } *length = dataLength; @@ -1166,7 +1223,7 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length) int32 numObjects = *(int32 *)buffer; buffer += sizeof(int32); - if ( length != sizeof(CParticleObject) * (numObjects + 1) + sizeof(int32) ) + if ( length != PARTICLE_OBJECT_SIZEOF * (numObjects + 1) + sizeof(int32) ) return false; if ( numObjects == 0 ) @@ -1177,14 +1234,17 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length) while ( i < numObjects ) { CParticleObject *dst = pUnusedListHead; +#ifndef COMPATIBLE_SAVES CParticleObject *src = (CParticleObject *)buffer; buffer += sizeof(CParticleObject); +#endif if ( dst == NULL ) return false; MoveToList(&pUnusedListHead, &pCloseListHead, dst); +#ifndef COMPATIBLE_SAVES dst->m_nState = POBJECTSTATE_UPDATE_CLOSE; dst->m_Type = src->m_Type; dst->m_ParticleType = src->m_ParticleType; @@ -1200,6 +1260,47 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length) dst->m_nNumEffectCycles = src->m_nNumEffectCycles; dst->m_nSkipFrames = src->m_nSkipFrames; dst->m_nCreationChance = src->m_nCreationChance; +#else + dst->m_nState = POBJECTSTATE_UPDATE_CLOSE; + dst->m_pParticle = NULL; + +#define SkipBuf(buf, num) buf += num +#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipBuf(buf, sizeof(data)) + // CPlaceable + { + SkipBuf(buffer, 4); + CMatrix matrix; + CopyFromBuf(buffer, matrix.f); + SkipBuf(buffer, 4); + CopyFromBuf(buffer, matrix.m_hasRwMatrix); + SkipBuf(buffer, 3); + dst->SetPosition(matrix.GetPosition()); + } + + // CParticleObject + { + SkipBuf(buffer, 4); + SkipBuf(buffer, 4); + SkipBuf(buffer, 4); + CopyFromBuf(buffer, dst->m_nRemoveTimer); + CopyFromBuf(buffer, dst->m_Type); + CopyFromBuf(buffer, dst->m_ParticleType); + CopyFromBuf(buffer, dst->m_nNumEffectCycles); + CopyFromBuf(buffer, dst->m_nSkipFrames); + CopyFromBuf(buffer, dst->m_nFrameCounter); + SkipBuf(buffer, 2); + SkipBuf(buffer, 2); + CopyFromBuf(buffer, dst->m_vecTarget); + CopyFromBuf(buffer, dst->m_fRandVal); + CopyFromBuf(buffer, dst->m_fSize); + CopyFromBuf(buffer, dst->m_Color); + CopyFromBuf(buffer, dst->m_bRemove); + CopyFromBuf(buffer, dst->m_nCreationChance); + SkipBuf(buffer, 2); + } +#undef CopyFromBuf +#undef SkipBuf +#endif i++; } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 5a72f288..3ccae5d0 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -326,6 +326,7 @@ CPed::~CPed(void) nearPed->m_nearPeds[k] = nearPed->m_nearPeds[k + 1]; nearPed->m_nearPeds[k + 1] = nil; } + nearPed->m_nearPeds[ARRAY_SIZE(m_nearPeds) - 1] = nil; nearPed->m_numNearPeds--; } else j++; @@ -1359,6 +1360,9 @@ CPed::CalculateNewVelocity(void) limitedRotDest -= 2 * PI; } +#ifdef FREE_CAM + if (!TheCamera.Cams[0].Using3rdPersonMouseCam()) +#endif if (IsPlayer() && m_nPedState == PED_ATTACK) headAmount /= 4.0f; @@ -2485,12 +2489,12 @@ CPed::ProcessControl(void) obstacleForFlyingOtherDirZ = 501.0f; } #ifdef VC_PED_PORTS - uint8 flyDir = 0; + int16 flyDir = 0; float feetZ = GetPosition().z - FEET_OFFSET; #ifdef FIX_BUGS - if (obstacleForFlyingZ > feetZ && obstacleForFlyingOtherDirZ < 501.0f) + if (obstacleForFlyingZ > feetZ && obstacleForFlyingZ < 500.0f) flyDir = 1; - else if (obstacleForFlyingOtherDirZ > feetZ && obstacleForFlyingZ < 500.0f) + else if (obstacleForFlyingOtherDirZ > feetZ && obstacleForFlyingOtherDirZ < 501.0f) flyDir = 2; #else if ((obstacleForFlyingZ > feetZ && obstacleForFlyingOtherDirZ < 500.0f) || (obstacleForFlyingZ > feetZ && obstacleForFlyingOtherDirZ > feetZ)) @@ -2499,8 +2503,8 @@ CPed::ProcessControl(void) flyDir = 2; #endif - if (flyDir != 0 && !bSomeVCflag1) { - SetPosition((flyDir == 2 ? obstacleForFlyingOtherDir.point : obstacleForFlying.point)); + if (flyDir > 0 && !bSomeVCflag1) { + GetMatrix().SetTranslateOnly((flyDir == 2 ? obstacleForFlyingOtherDir.point : obstacleForFlying.point)); GetMatrix().GetPosition().z += FEET_OFFSET; GetMatrix().UpdateRW(); SetLanding(); @@ -3199,7 +3203,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) lowerSpeedLimit *= 1.5f; } CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL); - if (!bWasStanding && speed > upperSpeedLimit && (/*!bPushedAlongByCar ||*/ m_vecMoveSpeed.z < lowerSpeedLimit) + if (!bWasStanding && ((speed > upperSpeedLimit /* ||!bPushedAlongByCar*/) || (m_vecMoveSpeed.z < lowerSpeedLimit)) && m_pCollidingEntity != collidingEnt) { float damage = 100.0f * Max(speed - 0.25f, 0.0f); @@ -8508,21 +8512,21 @@ CPed::renderLimb(int node) void CPed::Save(uint8*& buf) { - SkipSaveBuf(buf, 52); + ZeroSaveBuf(buf, 52); CopyToBuf(buf, GetPosition().x); CopyToBuf(buf, GetPosition().y); CopyToBuf(buf, GetPosition().z); - SkipSaveBuf(buf, 288); + ZeroSaveBuf(buf, 288); CopyToBuf(buf, CharCreatedBy); - SkipSaveBuf(buf, 351); + ZeroSaveBuf(buf, 351); CopyToBuf(buf, m_fHealth); CopyToBuf(buf, m_fArmour); - SkipSaveBuf(buf, 148); + ZeroSaveBuf(buf, 148); for (int i = 0; i < 13; i++) // has to be hardcoded m_weapons[i].Save(buf); - SkipSaveBuf(buf, 5); + ZeroSaveBuf(buf, 5); CopyToBuf(buf, m_maxWeaponTypeAllowed); - SkipSaveBuf(buf, 162); + ZeroSaveBuf(buf, 162); } void diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp index 46ac369c..13d3930c 100644 --- a/src/peds/PedFight.cpp +++ b/src/peds/PedFight.cpp @@ -320,6 +320,14 @@ CPed::SetAttack(CEntity *victim) ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch(); } } +#ifdef FIX_BUGS + // fix aiming for flamethrower while using PC controls + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER && TheCamera.Cams[0].Using3rdPersonMouseCam() && this == FindPlayerPed()) + { + SetAimFlag(m_fRotationCur); + ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch(); + } +#endif if (m_nPedState == PED_ATTACK) { bIsAttacking = true; return; diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h index 9077fbea..1543fa34 100644 --- a/src/peds/PedIK.h +++ b/src/peds/PedIK.h @@ -29,7 +29,7 @@ class CPedIK { public: enum { - GUN_POINTED_SUCCESSFULLY = 1, // set but unused + GUN_POINTED_SUCCESSFULLY = 1, LOOKAROUND_HEAD_ONLY = 2, AIMS_WITH_ARM = 4, }; diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 93a403bd..416fb949 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -503,6 +503,10 @@ CPlayerPed::DoWeaponSmoothSpray(void) { if (m_nPedState == PED_ATTACK && !m_pPointGunAt) { eWeaponType weapon = GetWeapon()->m_eWeaponType; +#ifdef FREE_CAM + if(TheCamera.Cams[0].Using3rdPersonMouseCam() && (weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI)) + return false; +#endif if (weapon == WEAPONTYPE_FLAMETHROWER || weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI || weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_AK47 || weapon == WEAPONTYPE_M16 || weapon == WEAPONTYPE_HELICANNON) return true; @@ -1183,6 +1187,13 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) padMoveInGameUnit = CVector2D(leftRight, upDown).Magnitude() / PAD_MOVE_TO_GAME_WORLD_MOVE; } +#ifdef FREE_CAM + if(TheCamera.Cams[0].Using3rdPersonMouseCam() && doSmoothSpray) { + padMoveInGameUnit = 0.0f; + smoothSprayWithoutMove = false; + } +#endif + if (padMoveInGameUnit > 0.0f || smoothSprayWithoutMove) { float padHeading = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown); float neededTurn = CGeneral::LimitRadianAngle(padHeading - camOrientation); @@ -1492,14 +1503,14 @@ void CPlayerPed::Save(uint8*& buf) { CPed::Save(buf); - SkipSaveBuf(buf, 16); + ZeroSaveBuf(buf, 16); CopyToBuf(buf, m_fMaxStamina); - SkipSaveBuf(buf, 28); + ZeroSaveBuf(buf, 28); CopyToBuf(buf, m_nTargettableObjects[0]); CopyToBuf(buf, m_nTargettableObjects[1]); CopyToBuf(buf, m_nTargettableObjects[2]); CopyToBuf(buf, m_nTargettableObjects[3]); - SkipSaveBuf(buf, 116); + ZeroSaveBuf(buf, 116); } void diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index ace6d37c..1d2a5798 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -55,7 +55,7 @@ bool CPopulation::ms_bGivePedsWeapons; int32 CPopulation::m_AllRandomPedsThisType = -1; float CPopulation::PedDensityMultiplier = 1.0f; uint32 CPopulation::ms_nTotalMissionPeds; -int32 CPopulation::MaxNumberOfPedsInUse = 25; +int32 CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS; uint32 CPopulation::ms_nNumCivMale; uint32 CPopulation::ms_nNumCivFemale; uint32 CPopulation::ms_nNumCop; @@ -1122,12 +1122,6 @@ CPopulation::ManagePopulation(void) } float dist = (ped->GetPosition() - playerPos).Magnitude2D(); -#ifdef SQUEEZE_PERFORMANCE - if (dist > 50.f) - ped->bUsesCollision = false; - else - ped->bUsesCollision = true; -#endif bool pedIsFarAway = false; if (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist diff --git a/src/render/2dEffect.h b/src/renderer/2dEffect.h index a8013b34..a8013b34 100644 --- a/src/render/2dEffect.h +++ b/src/renderer/2dEffect.h diff --git a/src/render/Antennas.cpp b/src/renderer/Antennas.cpp index 5e30aca2..5e30aca2 100644 --- a/src/render/Antennas.cpp +++ b/src/renderer/Antennas.cpp diff --git a/src/render/Antennas.h b/src/renderer/Antennas.h index 47cb1dad..47cb1dad 100644 --- a/src/render/Antennas.h +++ b/src/renderer/Antennas.h diff --git a/src/render/Clouds.cpp b/src/renderer/Clouds.cpp index 957844a5..957844a5 100644 --- a/src/render/Clouds.cpp +++ b/src/renderer/Clouds.cpp diff --git a/src/render/Clouds.h b/src/renderer/Clouds.h index 4d8cd2c8..4d8cd2c8 100644 --- a/src/render/Clouds.h +++ b/src/renderer/Clouds.h diff --git a/src/render/Console.cpp b/src/renderer/Console.cpp index 8ea5b7a3..8ea5b7a3 100644 --- a/src/render/Console.cpp +++ b/src/renderer/Console.cpp diff --git a/src/render/Console.h b/src/renderer/Console.h index 9f22236f..9f22236f 100644 --- a/src/render/Console.h +++ b/src/renderer/Console.h diff --git a/src/render/Coronas.cpp b/src/renderer/Coronas.cpp index e9f9e662..e9f9e662 100644 --- a/src/render/Coronas.cpp +++ b/src/renderer/Coronas.cpp diff --git a/src/render/Coronas.h b/src/renderer/Coronas.h index 46eb4315..46eb4315 100644 --- a/src/render/Coronas.h +++ b/src/renderer/Coronas.h diff --git a/src/render/Credits.cpp b/src/renderer/Credits.cpp index 60581793..60581793 100644 --- a/src/render/Credits.cpp +++ b/src/renderer/Credits.cpp diff --git a/src/render/Credits.h b/src/renderer/Credits.h index e049ce76..e049ce76 100644 --- a/src/render/Credits.h +++ b/src/renderer/Credits.h diff --git a/src/render/Draw.cpp b/src/renderer/Draw.cpp index f702f188..f702f188 100644 --- a/src/render/Draw.cpp +++ b/src/renderer/Draw.cpp diff --git a/src/render/Draw.h b/src/renderer/Draw.h index 8727e0e0..8727e0e0 100644 --- a/src/render/Draw.h +++ b/src/renderer/Draw.h diff --git a/src/render/Fluff.cpp b/src/renderer/Fluff.cpp index c4cfe7f7..c4cfe7f7 100644 --- a/src/render/Fluff.cpp +++ b/src/renderer/Fluff.cpp diff --git a/src/render/Fluff.h b/src/renderer/Fluff.h index fe3ab256..fe3ab256 100644 --- a/src/render/Fluff.h +++ b/src/renderer/Fluff.h diff --git a/src/render/Font.cpp b/src/renderer/Font.cpp index 6a9944e1..6a9944e1 100644 --- a/src/render/Font.cpp +++ b/src/renderer/Font.cpp diff --git a/src/render/Font.h b/src/renderer/Font.h index 9316ed34..9316ed34 100644 --- a/src/render/Font.h +++ b/src/renderer/Font.h diff --git a/src/render/Glass.cpp b/src/renderer/Glass.cpp index cc45648c..cc45648c 100644 --- a/src/render/Glass.cpp +++ b/src/renderer/Glass.cpp diff --git a/src/render/Glass.h b/src/renderer/Glass.h index 51c5aae9..51c5aae9 100644 --- a/src/render/Glass.h +++ b/src/renderer/Glass.h diff --git a/src/render/Hud.cpp b/src/renderer/Hud.cpp index bba8c525..bba8c525 100644 --- a/src/render/Hud.cpp +++ b/src/renderer/Hud.cpp diff --git a/src/render/Hud.h b/src/renderer/Hud.h index adfdf1fc..adfdf1fc 100644 --- a/src/render/Hud.h +++ b/src/renderer/Hud.h diff --git a/src/render/Instance.cpp b/src/renderer/Instance.cpp index be6d73d6..be6d73d6 100644 --- a/src/render/Instance.cpp +++ b/src/renderer/Instance.cpp diff --git a/src/render/Instance.h b/src/renderer/Instance.h index 693cfdf1..693cfdf1 100644 --- a/src/render/Instance.h +++ b/src/renderer/Instance.h diff --git a/src/render/Lines.cpp b/src/renderer/Lines.cpp index b5c85149..b5c85149 100644 --- a/src/render/Lines.cpp +++ b/src/renderer/Lines.cpp diff --git a/src/render/Lines.h b/src/renderer/Lines.h index f2694fc0..f2694fc0 100644 --- a/src/render/Lines.h +++ b/src/renderer/Lines.h diff --git a/src/render/MBlur.cpp b/src/renderer/MBlur.cpp index 8e5fba2a..8e5fba2a 100644 --- a/src/render/MBlur.cpp +++ b/src/renderer/MBlur.cpp diff --git a/src/render/MBlur.h b/src/renderer/MBlur.h index e2e5d38c..e2e5d38c 100644 --- a/src/render/MBlur.h +++ b/src/renderer/MBlur.h diff --git a/src/render/Particle.cpp b/src/renderer/Particle.cpp index 76ddde50..76ddde50 100644 --- a/src/render/Particle.cpp +++ b/src/renderer/Particle.cpp diff --git a/src/render/Particle.h b/src/renderer/Particle.h index 7f02e318..7f02e318 100644 --- a/src/render/Particle.h +++ b/src/renderer/Particle.h diff --git a/src/render/ParticleMgr.cpp b/src/renderer/ParticleMgr.cpp index 3387d471..3387d471 100644 --- a/src/render/ParticleMgr.cpp +++ b/src/renderer/ParticleMgr.cpp diff --git a/src/render/ParticleMgr.h b/src/renderer/ParticleMgr.h index 0100bb65..0100bb65 100644 --- a/src/render/ParticleMgr.h +++ b/src/renderer/ParticleMgr.h diff --git a/src/render/ParticleType.h b/src/renderer/ParticleType.h index 8d352c44..8d352c44 100644 --- a/src/render/ParticleType.h +++ b/src/renderer/ParticleType.h diff --git a/src/render/PlayerSkin.cpp b/src/renderer/PlayerSkin.cpp index f0fae45a..f0fae45a 100644 --- a/src/render/PlayerSkin.cpp +++ b/src/renderer/PlayerSkin.cpp diff --git a/src/render/PlayerSkin.h b/src/renderer/PlayerSkin.h index e0214ce0..e0214ce0 100644 --- a/src/render/PlayerSkin.h +++ b/src/renderer/PlayerSkin.h diff --git a/src/render/PointLights.cpp b/src/renderer/PointLights.cpp index 84ac4ab2..84ac4ab2 100644 --- a/src/render/PointLights.cpp +++ b/src/renderer/PointLights.cpp diff --git a/src/render/PointLights.h b/src/renderer/PointLights.h index 9e94328f..9e94328f 100644 --- a/src/render/PointLights.h +++ b/src/renderer/PointLights.h diff --git a/src/render/RenderBuffer.cpp b/src/renderer/RenderBuffer.cpp index 6120dfe2..6120dfe2 100644 --- a/src/render/RenderBuffer.cpp +++ b/src/renderer/RenderBuffer.cpp diff --git a/src/render/RenderBuffer.h b/src/renderer/RenderBuffer.h index 485d24e3..485d24e3 100644 --- a/src/render/RenderBuffer.h +++ b/src/renderer/RenderBuffer.h diff --git a/src/render/Renderer.cpp b/src/renderer/Renderer.cpp index 1c0bd445..1c0bd445 100644 --- a/src/render/Renderer.cpp +++ b/src/renderer/Renderer.cpp diff --git a/src/render/Renderer.h b/src/renderer/Renderer.h index 0322939c..0322939c 100644 --- a/src/render/Renderer.h +++ b/src/renderer/Renderer.h diff --git a/src/render/Rubbish.cpp b/src/renderer/Rubbish.cpp index 8da6b025..8da6b025 100644 --- a/src/render/Rubbish.cpp +++ b/src/renderer/Rubbish.cpp diff --git a/src/render/Rubbish.h b/src/renderer/Rubbish.h index 37f895f3..37f895f3 100644 --- a/src/render/Rubbish.h +++ b/src/renderer/Rubbish.h diff --git a/src/render/Shadows.cpp b/src/renderer/Shadows.cpp index 3884d3bb..3884d3bb 100644 --- a/src/render/Shadows.cpp +++ b/src/renderer/Shadows.cpp diff --git a/src/render/Shadows.h b/src/renderer/Shadows.h index 8c909df3..8c909df3 100644 --- a/src/render/Shadows.h +++ b/src/renderer/Shadows.h diff --git a/src/render/Skidmarks.cpp b/src/renderer/Skidmarks.cpp index 4c662a79..4c662a79 100644 --- a/src/render/Skidmarks.cpp +++ b/src/renderer/Skidmarks.cpp diff --git a/src/render/Skidmarks.h b/src/renderer/Skidmarks.h index c061782d..c061782d 100644 --- a/src/render/Skidmarks.h +++ b/src/renderer/Skidmarks.h diff --git a/src/render/SpecialFX.cpp b/src/renderer/SpecialFX.cpp index 6d96d21a..6d96d21a 100644 --- a/src/render/SpecialFX.cpp +++ b/src/renderer/SpecialFX.cpp diff --git a/src/render/SpecialFX.h b/src/renderer/SpecialFX.h index 2d9f18b1..2d9f18b1 100644 --- a/src/render/SpecialFX.h +++ b/src/renderer/SpecialFX.h diff --git a/src/render/Sprite.cpp b/src/renderer/Sprite.cpp index 3fef0733..3fef0733 100644 --- a/src/render/Sprite.cpp +++ b/src/renderer/Sprite.cpp diff --git a/src/render/Sprite.h b/src/renderer/Sprite.h index ec4c1d1b..ec4c1d1b 100644 --- a/src/render/Sprite.h +++ b/src/renderer/Sprite.h diff --git a/src/render/Sprite2d.cpp b/src/renderer/Sprite2d.cpp index 59622516..59622516 100644 --- a/src/render/Sprite2d.cpp +++ b/src/renderer/Sprite2d.cpp diff --git a/src/render/Sprite2d.h b/src/renderer/Sprite2d.h index 0e12d441..0e12d441 100644 --- a/src/render/Sprite2d.h +++ b/src/renderer/Sprite2d.h diff --git a/src/render/TexList.cpp b/src/renderer/TexList.cpp index 1689837f..1689837f 100644 --- a/src/render/TexList.cpp +++ b/src/renderer/TexList.cpp diff --git a/src/render/TexList.h b/src/renderer/TexList.h index 7e042211..7e042211 100644 --- a/src/render/TexList.h +++ b/src/renderer/TexList.h diff --git a/src/render/Timecycle.cpp b/src/renderer/Timecycle.cpp index 0d94dbd6..0d94dbd6 100644 --- a/src/render/Timecycle.cpp +++ b/src/renderer/Timecycle.cpp diff --git a/src/render/Timecycle.h b/src/renderer/Timecycle.h index d5d7b67a..d5d7b67a 100644 --- a/src/render/Timecycle.h +++ b/src/renderer/Timecycle.h diff --git a/src/render/WaterCannon.cpp b/src/renderer/WaterCannon.cpp index 08898be8..08898be8 100644 --- a/src/render/WaterCannon.cpp +++ b/src/renderer/WaterCannon.cpp diff --git a/src/render/WaterCannon.h b/src/renderer/WaterCannon.h index a37bdd12..a37bdd12 100644 --- a/src/render/WaterCannon.h +++ b/src/renderer/WaterCannon.h diff --git a/src/render/WaterLevel.cpp b/src/renderer/WaterLevel.cpp index 7001c0cf..7001c0cf 100644 --- a/src/render/WaterLevel.cpp +++ b/src/renderer/WaterLevel.cpp diff --git a/src/render/WaterLevel.h b/src/renderer/WaterLevel.h index b797f251..b797f251 100644 --- a/src/render/WaterLevel.h +++ b/src/renderer/WaterLevel.h diff --git a/src/render/Weather.cpp b/src/renderer/Weather.cpp index e57d57d6..e57d57d6 100644 --- a/src/render/Weather.cpp +++ b/src/renderer/Weather.cpp diff --git a/src/render/Weather.h b/src/renderer/Weather.h index 9c670317..9c670317 100644 --- a/src/render/Weather.h +++ b/src/renderer/Weather.h diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 23a8fd6a..f51f8233 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -600,6 +600,552 @@ align4bytes(int32 size) return (size + 3) & 0xFFFFFFFC; } +#ifdef FIX_INCOMPATIBLE_SAVES +#define LoadSaveDataBlockNoCheck(buf, file, size) \ +do { \ + CFileMgr::Read(file, (const char *)&size, sizeof(size)); \ + size = align4bytes(size); \ + CFileMgr::Read(file, (const char *)work_buff, size); \ + buf = work_buff; \ +} while(0) + +#define WriteSavaDataBlockNoFunc(buf, file, size) \ +do { \ + if (!PcSaveHelper.PcClassSaveRoutine(file, buf, size)) \ + goto fail; \ + totalSize += size; \ +} while(0) + +#define FixSaveDataBlock(fix_func, file, size) \ +do { \ + ReadDataFromBufferPointer(buf, size); \ + memset(work_buff2, 0, sizeof(work_buff2)); \ + buf2 = work_buff2; \ + reserved = 0; \ + MakeSpaceForSizeInBufferPointer(presize, buf2, postsize); \ + fix_func(save_type, buf, buf2, &size); \ + CopySizeAndPreparePointer(presize, buf2, postsize, reserved, size); \ + if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff2, buf2 - work_buff2)) \ + goto fail; \ + totalSize += buf2 - work_buff2; \ +} while(0) + +#define ReadDataFromBufferPointerWithSize(buf, to, size) memcpy(&to, buf, size); buf += align4bytes(size) + +#define ReadBuf(buf, to) memcpy(&to, buf, sizeof(to)); buf += sizeof(to) +#define WriteBuf(buf, from) memcpy(buf, &from, sizeof(from)); buf += sizeof(from) +#define CopyBuf(from, to, size) memcpy(to, from, size); to += (size); from += (size) +#define CopyPtr(from, to) memcpy(to, from, 4); to += 4; from += 8 +#define SkipBuf(buf, size) buf += (size) +#define SkipBoth(from, to, size) to += (size); from += (size) +#define SkipPtr(from, to) to += 4; from += 8 + +// unfortunately we need a 2nd buffer of the same size to store the fixed output ... +static uint8 work_buff2[sizeof(work_buff)]; + +enum +{ + SAVE_TYPE_NONE = 0, + SAVE_TYPE_32_BIT = 1, + SAVE_TYPE_64_BIT = 2, + SAVE_TYPE_MSVC = 4, + SAVE_TYPE_GCC = 8, +}; + +uint8 +GetSaveType(char *savename) +{ + uint8 save_type = SAVE_TYPE_NONE; + int file = CFileMgr::OpenFile(savename, "rb"); + + uint32 size; + CFileMgr::Read(file, (const char *)&size, sizeof(size)); + + uint8 *buf = work_buff; + CFileMgr::Read(file, (const char *)work_buff, size); // simple vars + scripts + + LoadSaveDataBlockNoCheck(buf, file, size); // ped pool + + LoadSaveDataBlockNoCheck(buf, file, size); // garages + ReadDataFromBufferPointer(buf, size); + + // store for later after we know how much data we need to skip + ReadDataFromBufferPointerWithSize(buf, work_buff2, size); + + LoadSaveDataBlockNoCheck(buf, file, size); // vehicle pool + LoadSaveDataBlockNoCheck(buf, file, size); // object pool + LoadSaveDataBlockNoCheck(buf, file, size); // paths + + LoadSaveDataBlockNoCheck(buf, file, size); // cranes + + CFileMgr::CloseFile(file); + + ReadDataFromBufferPointer(buf, size); + + if (size == 1032) + save_type |= SAVE_TYPE_32_BIT; + else if (size == 1160) + save_type |= SAVE_TYPE_64_BIT; + else + assert(0); // this should never happen + + buf = work_buff2; + + buf += 760; // skip everything before the first garage + buf += save_type & SAVE_TYPE_32_BIT ? 28 : 40; // skip first garage up to m_fX1 + + // now the values we want to verify + float fX1, fX2, fY1, fY2, fZ1, fZ2; + + ReadBuf(buf, fX1); + ReadBuf(buf, fX2); + ReadBuf(buf, fY1); + ReadBuf(buf, fY2); + ReadBuf(buf, fZ1); + ReadBuf(buf, fZ2); + + if (fX1 == CRUSHER_GARAGE_X1 && fX2 == CRUSHER_GARAGE_X2 && + fY1 == CRUSHER_GARAGE_Y1 && fY2 == CRUSHER_GARAGE_Y2 && + fZ1 == CRUSHER_GARAGE_Z1 && fZ2 == CRUSHER_GARAGE_Z2) + save_type |= SAVE_TYPE_MSVC; + else + save_type |= SAVE_TYPE_GCC; + + return save_type; +} + +static void +FixGarages(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + // hardcoded: 5484 + // x86 msvc: 5240 + // x86 gcc: 5040 + // amd64 msvc: 5880 + // amd64 gcc: 5808 + + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read; + uint32 written = 5240; + + if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_GCC) + read = 5040; + else if (save_type & SAVE_TYPE_64_BIT && save_type & SAVE_TYPE_GCC) + read = 5808; + else + read = 5880; + + uint32 ptrsize = save_type & SAVE_TYPE_32_BIT ? 4 : 8; + + CopyBuf(buf, buf2, 4 * 6); + CopyBuf(buf, buf2, 4 * TOTAL_COLLECTCARS_GARAGES); + CopyBuf(buf, buf2, 4); + + if (save_type & SAVE_TYPE_GCC) + { + for (int32 i = 0; i < NUM_GARAGE_STORED_CARS; i++) + { +#define FixStoredCar(buf, buf2) \ +do { \ + CopyBuf(buf, buf2, 4 + sizeof(CVector) + sizeof(CVector)); \ + uint8 nFlags8; \ + ReadBuf(buf, nFlags8); \ + int32 nFlags32 = nFlags8; \ + WriteBuf(buf2, nFlags32); \ + CopyBuf(buf, buf2, 1 * 6); \ + SkipBuf(buf, 1); \ + SkipBuf(buf2, 2); \ +} while(0) + + FixStoredCar(buf, buf2); + FixStoredCar(buf, buf2); + FixStoredCar(buf, buf2); + +#undef FixStoredCar + } + } + else + { + CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS); + CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS); + CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS); + } + + for (int32 i = 0; i < NUM_GARAGES; i++) + { + // skip the last 5 garages in 64bit builds without FIX_GARAGE_SIZE since they weren't actually saved and are unused + if (save_type & SAVE_TYPE_64_BIT && *size == 5484 && i >= NUM_GARAGES - 5) + { + SkipBuf(buf, 160); // sizeof(CGarage) on x64 + SkipBuf(buf2, 140); // sizeof(CGarage) on x86 + } + else + { + CopyBuf(buf, buf2, 1 * 6); + SkipBoth(buf, buf2, 2); + CopyBuf(buf, buf2, 4); + SkipBuf(buf, ptrsize - 4); // write 4 bytes padding if 8 byte pointer, if not, write 0 + SkipBuf(buf, ptrsize * 2); + SkipBuf(buf2, 4 * 2); + CopyBuf(buf, buf2, 1 * 7); + SkipBoth(buf, buf2, 1); + CopyBuf(buf, buf2, 4 * 15 + 1); + SkipBoth(buf, buf2, 3); + SkipBuf(buf, ptrsize * 2); + SkipBuf(buf2, 4 * 2); + + if (save_type & SAVE_TYPE_GCC) + SkipBuf(buf, save_type & SAVE_TYPE_64_BIT ? 36 + 4 : 36); // sizeof(CStoredCar) on gcc 64/32 before fix + else + SkipBuf(buf, sizeof(CStoredCar)); + + SkipBuf(buf2, sizeof(CStoredCar)); + } + } + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + +#ifdef FIX_GARAGE_SIZE + *size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CGarages::CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); +#else + *size = 5484; +#endif +} + +static void +FixCranes(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read = 2 * sizeof(uint32) + 0x480; // sizeof(aCranes) + uint32 written = 2 * sizeof(uint32) + 0x400; // see CRANES_SAVE_SIZE + + CopyBuf(buf, buf2, 4 + 4); + + for (int32 i = 0; i < NUM_CRANES; i++) + { + CopyPtr(buf, buf2); + CopyPtr(buf, buf2); + CopyBuf(buf, buf2, 15 * 4 + sizeof(CVector) * 3 + sizeof(CVector2D)); + CopyPtr(buf, buf2); + CopyBuf(buf, buf2, 4 + 7 * 1); + SkipBuf(buf, 5); + SkipBuf(buf2, 1); + } + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void +FixPickups(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read = 0x3480 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // sizeof(aPickUps) + uint32 written = 0x24C0 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // see PICKUPS_SAVE_SIZE + + for (int32 i = 0; i < NUMPICKUPS; i++) + { + CopyBuf(buf, buf2, 1 + 1 + 2); + SkipBuf(buf, 4); + CopyPtr(buf, buf2); + CopyBuf(buf, buf2, 4 + 2 + 2 + sizeof(CVector)); + SkipBuf(buf, 4); + } + + CopyBuf(buf, buf2, 2); + SkipBoth(buf, buf2, 2); + + CopyBuf(buf, buf2, NUMCOLLECTEDPICKUPS * 4); + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void +FixPhoneInfo(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read = 0x1138; // sizeof(CPhoneInfo) + uint32 written = 0xA30; // see PHONEINFO_SAVE_SIZE + + CopyBuf(buf, buf2, 4 + 4); + + for (int32 i = 0; i < NUMPHONES; i++) + { + CopyBuf(buf, buf2, sizeof(CVector)); + SkipBuf(buf, 4); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 4); + SkipBuf(buf, 4); + CopyPtr(buf, buf2); + CopyBuf(buf, buf2, 4 + 1); + SkipBoth(buf, buf2, 3); + } + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void +FixZones(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read = 11300; // see SaveAllZones + uint32 written = 10100; // see SaveAllZones + + CopyBuf(buf, buf2, 1 * 4); + + SkipBuf(buf, 4); + uint32 hdr_size = 10100 - (1 * 4 + 4); // see SaveAllZones + WriteBuf(buf2, hdr_size); + + CopyBuf(buf, buf2, 4 * 2 + 2); + SkipBoth(buf, buf2, 2); + +#define FixOneZone(buf, buf2) \ +do { \ + CopyBuf(buf, buf2, 8 + 8 * 4 + 2 * 2); \ + SkipBuf(buf, 4); \ + CopyPtr(buf, buf2); \ + CopyPtr(buf, buf2); \ + CopyPtr(buf, buf2); \ +} while(0) + + for (int32 i = 0; i < NUMZONES; i++) + FixOneZone(buf, buf2); + + CopyBuf(buf, buf2, sizeof(CZoneInfo) * NUMZONES * 2); + CopyBuf(buf, buf2, 2 + 2); + + for (int32 i = 0; i < NUMMAPZONES; i++) + FixOneZone(buf, buf2); + + CopyBuf(buf, buf2, 2 * NUMAUDIOZONES); + CopyBuf(buf, buf2, 2 + 2); + +#undef FixOneZone + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void +FixParticles(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + + int32 numObjects; + ReadBuf(buf, numObjects); + WriteBuf(buf2, numObjects); + + uint32 read = 0xA0 * (numObjects + 1) + 4; // sizeof(CParticleObject) + uint32 written = 0x88 * (numObjects + 1) + 4; // see PARTICLE_OBJECT_SIZEOF + + for (int32 i = 0; i < numObjects; i++) + { + // CPlaceable + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 4 * 4 * 4); + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 1); + SkipBuf(buf, 7); + SkipBuf(buf2, 3); + + // CParticleObject + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 4 * 3 + 2 * 1 + 2 * 2); + SkipBoth(buf, buf2, 2); + CopyBuf(buf, buf2, sizeof(CVector) + 2 * 4 + sizeof(CRGBA) + 2 * 1); + SkipBoth(buf, buf2, 2); + } + + SkipBuf(buf, 0xA0); // sizeof(CParticleObject) + SkipBuf(buf2, 0x88); // see PARTICLE_OBJECT_SIZEOF + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +bool +FixSave(int32 slot, uint8 save_type) +{ + if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_MSVC) + return true; + + bool success = false; + + uint8 *buf, *presize, *postsize, *buf2; + uint32 size; + uint32 reserved; + + uint32 totalSize; + + char savename[MAX_PATH]; + char savename_bak[MAX_PATH]; + + sprintf(savename, "%s%i%s", DefaultPCSaveFileName, slot + 1, ".b"); + sprintf(savename_bak, "%s%i%s.%lld.bak", DefaultPCSaveFileName, slot + 1, ".b", time(nil)); + + assert(caserename(savename, savename_bak) == 0); + + int file_in = CFileMgr::OpenFile(savename_bak, "rb"); + int file_out = CFileMgr::OpenFileForWriting(savename); + + CheckSum = 0; + totalSize = 0; + + CFileMgr::Read(file_in, (const char *)&size, sizeof(size)); + + buf = work_buff; + CFileMgr::Read(file_in, (const char *)work_buff, size); // simple vars + scripts + + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // ped pool + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // garages + FixSaveDataBlock(FixGarages, file_out, size); // garages need to be fixed in either case + + LoadSaveDataBlockNoCheck(buf, file_in, size); // vehicle pool + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // object pool + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // paths + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // cranes + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixCranes, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // pickups + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixPickups, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // phoneinfo + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixPhoneInfo, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // restart + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // radar blips + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // zones + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixZones, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // gang data + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // car generators + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // particles + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixParticles, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // audio script objects + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // player info + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // stats + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // streaming + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // ped type + WriteSavaDataBlockNoFunc(buf, file_out, size); + + memset(work_buff, 0, sizeof(work_buff)); + + for (int i = 0; i < 4; i++) { + size = align4bytes(SIZE_OF_ONE_GAME_IN_BYTES - totalSize - 4); + if (size > sizeof(work_buff)) + size = sizeof(work_buff); + if (size > 4) { + if (!PcSaveHelper.PcClassSaveRoutine(file_out, work_buff, size)) + goto fail; + totalSize += size; + } + } + + if (!CFileMgr::Write(file_out, (const char *)&CheckSum, sizeof(CheckSum))) + goto fail; + + success = true; + +fail:; + CFileMgr::CloseFile(file_in); + CFileMgr::CloseFile(file_out); + + return success; +} + +#undef LoadSaveDataBlockNoCheck +#undef WriteSavaDataBlockNoFunc +#undef FixSaveDataBlock +#undef ReadDataFromBufferPointerWithSize +#undef ReadBuf +#undef WriteBuf +#undef CopyBuf +#undef CopyPtr +#undef SkipBuf +#undef SkipBoth +#undef SkipPtr +#endif + #ifdef MISSION_REPLAY void DisplaySaveResult(int unk, char* name) diff --git a/src/save/GenericGameStorage.h b/src/save/GenericGameStorage.h index 069ba7cd..b291ddf9 100644 --- a/src/save/GenericGameStorage.h +++ b/src/save/GenericGameStorage.h @@ -22,6 +22,11 @@ bool CheckDataNotCorrupt(int32 slot, char *name); bool RestoreForStartLoad(); int align4bytes(int32 size); +#ifdef FIX_INCOMPATIBLE_SAVES +uint8 GetSaveType(char *savename); +bool FixSave(int32 slot, uint8 save_type); +#endif + extern class CDate CompileDateAndTime; extern char DefaultPCSaveFileName[260]; diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index a9df00af..0c228a6d 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -122,6 +122,13 @@ C_PcSave::PopulateSlotInfo() } if (Slots[i + 1] == SLOT_OK) { if (CheckDataNotCorrupt(i, savename)) { +#ifdef FIX_INCOMPATIBLE_SAVES + if (!FixSave(i, GetSaveType(savename))) { + CMessages::InsertNumberInString(TheText.Get("FEC_SLC"), i + 1, -1, -1, -1, -1, -1, SlotFileName[i]); + Slots[i + 1] = SLOT_CORRUPTED; + continue; + } +#endif SYSTEMTIME st; memcpy(&st, &header.SaveDateTime, sizeof(SYSTEMTIME)); const char *month; diff --git a/src/save/PCSave.h b/src/save/PCSave.h index 4a2d9a66..83471b5d 100644 --- a/src/save/PCSave.h +++ b/src/save/PCSave.h @@ -33,7 +33,7 @@ public: void PopulateSlotInfo(); bool DeleteSlot(int32 slot); bool SaveSlot(int32 slot); - bool PcClassSaveRoutine(int32 a2, uint8 *data, uint32 size); + bool PcClassSaveRoutine(int32 file, uint8 *data, uint32 size); static void SetSaveDirectory(const char *path); }; diff --git a/src/save/SaveBuf.h b/src/save/SaveBuf.h index 98fe888b..aad2e1a8 100644 --- a/src/save/SaveBuf.h +++ b/src/save/SaveBuf.h @@ -36,6 +36,15 @@ WriteSaveBuf(uint8 *&buf, const T &value) return p; } +#ifdef COMPATIBLE_SAVES +inline void +ZeroSaveBuf(uint8 *&buf, uint32 length) +{ + memset(buf, 0, length); + SkipSaveBuf(buf, length); +} +#endif + #define SAVE_HEADER_SIZE (4 * sizeof(char) + sizeof(uint32)) #define WriteSaveHeader(buf, a, b, c, d, size) \ diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 1d49ebd2..577983b6 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -155,6 +155,29 @@ FILE* _fcaseopen(char const* filename, char const* mode) return result; } +int _caserename(const char *old_filename, const char *new_filename) +{ + int result; + char *real_old = casepath(old_filename); + char *real_new = casepath(new_filename); + + // hack so we don't even try to rename it to new_filename if it already exists + if (!real_new) { + free(real_old); + return -1; + } + + if (!real_old) + result = rename(old_filename, real_new); + else + result = rename(real_old, real_new); + + free(real_old); + free(real_new); + + return result; +} + // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) // Returned string should freed manually (if exists) char* casepath(char const* path, bool checkPathFirst) diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 2dd9c162..aa90ce5a 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -29,6 +29,7 @@ enum eWinVersion #endif extern DWORD _dwOperatingSystemVersion; #define fcaseopen fopen +#define caserename rename #else char *strupr(char *str); char *strlwr(char *str); @@ -51,6 +52,8 @@ extern long _dwOperatingSystemVersion; char *casepath(char const *path, bool checkPathFirst = true); FILE *_fcaseopen(char const *filename, char const *mode); #define fcaseopen _fcaseopen +int _caserename(const char *old_filename, const char *new_filename); +#define caserename _caserename #endif #ifdef RW_GL3 diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 3de3e12b..7d942dcd 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -4717,8 +4717,8 @@ void CAutomobile::Save(uint8*& buf) { CVehicle::Save(buf); - WriteSaveBuf<CDamageManager>(buf, Damage); - SkipSaveBuf(buf, 800 - sizeof(CDamageManager)); + WriteSaveBuf(buf, Damage); + ZeroSaveBuf(buf, 800 - sizeof(CDamageManager)); } void diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 88444e95..65cdd8c6 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -940,7 +940,7 @@ void CBoat::Save(uint8*& buf) { CVehicle::Save(buf); - SkipSaveBuf(buf, 1156 - 648); + ZeroSaveBuf(buf, 1156 - 648); } void diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index 0f1b8b4c..db9d2e00 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -37,6 +37,12 @@ #define MIN_VALID_POSITION (-10000.0f) #define DEFAULT_OFFSET (20.0f) +#ifdef COMPATIBLE_SAVES +#define CRANES_SAVE_SIZE 0x400 +#else +#define CRANES_SAVE_SIZE sizeof(aCranes) +#endif + uint32 TimerForCamInterpolation; uint32 CCranes::CarsCollectedMilitaryCrane; @@ -634,10 +640,46 @@ void CCranes::Save(uint8* buf, uint32* size) { INITSAVEBUF - *size = 2 * sizeof(uint32) + sizeof(aCranes); + *size = 2 * sizeof(uint32) + CRANES_SAVE_SIZE; WriteSaveBuf(buf, NumCranes); WriteSaveBuf(buf, CarsCollectedMilitaryCrane); for (int i = 0; i < NUM_CRANES; i++) { +#ifdef COMPATIBLE_SAVES + int32 tmp = aCranes[i].m_pCraneEntity != nil ? CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pCraneEntity) + 1 : 0; + WriteSaveBuf(buf, tmp); + tmp = aCranes[i].m_pHook != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pHook) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, aCranes[i].m_nAudioEntity); + WriteSaveBuf(buf, aCranes[i].m_fPickupX1); + WriteSaveBuf(buf, aCranes[i].m_fPickupX2); + WriteSaveBuf(buf, aCranes[i].m_fPickupY1); + WriteSaveBuf(buf, aCranes[i].m_fPickupY2); + WriteSaveBuf(buf, aCranes[i].m_vecDropoffTarget); + WriteSaveBuf(buf, aCranes[i].m_fDropoffHeading); + WriteSaveBuf(buf, aCranes[i].m_fPickupAngle); + WriteSaveBuf(buf, aCranes[i].m_fDropoffAngle); + WriteSaveBuf(buf, aCranes[i].m_fPickupDistance); + WriteSaveBuf(buf, aCranes[i].m_fDropoffDistance); + WriteSaveBuf(buf, aCranes[i].m_fPickupHeight); + WriteSaveBuf(buf, aCranes[i].m_fDropoffHeight); + WriteSaveBuf(buf, aCranes[i].m_fHookAngle); + WriteSaveBuf(buf, aCranes[i].m_fHookOffset); + WriteSaveBuf(buf, aCranes[i].m_fHookHeight); + WriteSaveBuf(buf, aCranes[i].m_vecHookInitPos); + WriteSaveBuf(buf, aCranes[i].m_vecHookCurPos); + WriteSaveBuf(buf, aCranes[i].m_vecHookVelocity); + tmp = aCranes[i].m_pVehiclePickedUp != nil ? CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pVehiclePickedUp) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, aCranes[i].m_nTimeForNextCheck); + WriteSaveBuf(buf, aCranes[i].m_nCraneStatus); + WriteSaveBuf(buf, aCranes[i].m_nCraneState); + WriteSaveBuf(buf, aCranes[i].m_nVehiclesCollected); + WriteSaveBuf(buf, aCranes[i].m_bIsCrusher); + WriteSaveBuf(buf, aCranes[i].m_bIsMilitaryCrane); + WriteSaveBuf(buf, aCranes[i].m_bWasMilitaryCrane); + WriteSaveBuf(buf, aCranes[i].m_bIsTop); + ZeroSaveBuf(buf, 1); +#else CCrane *pCrane = WriteSaveBuf(buf, aCranes[i]); if (pCrane->m_pCraneEntity != nil) pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pCrane->m_pCraneEntity) + 1); @@ -645,6 +687,7 @@ void CCranes::Save(uint8* buf, uint32* size) pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pCrane->m_pHook) + 1); if (pCrane->m_pVehiclePickedUp != nil) pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pCrane->m_pVehiclePickedUp) + 1); +#endif } VALIDATESAVEBUF(*size); @@ -656,8 +699,46 @@ void CCranes::Load(uint8* buf, uint32 size) ReadSaveBuf(&NumCranes, buf); ReadSaveBuf(&CarsCollectedMilitaryCrane, buf); - for (int i = 0; i < NUM_CRANES; i++) + for (int i = 0; i < NUM_CRANES; i++) { +#ifdef COMPATIBLE_SAVES + int32 tmp; + ReadSaveBuf(&tmp, buf); + aCranes[i].m_pCraneEntity = tmp != 0 ? CPools::GetBuildingPool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&tmp, buf); + aCranes[i].m_pHook = tmp != 0 ? CPools::GetObjectPool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&aCranes[i].m_nAudioEntity, buf);
+ ReadSaveBuf(&aCranes[i].m_fPickupX1, buf);
+ ReadSaveBuf(&aCranes[i].m_fPickupX2, buf);
+ ReadSaveBuf(&aCranes[i].m_fPickupY1, buf);
+ ReadSaveBuf(&aCranes[i].m_fPickupY2, buf);
+ ReadSaveBuf(&aCranes[i].m_vecDropoffTarget, buf);
+ ReadSaveBuf(&aCranes[i].m_fDropoffHeading, buf);
+ ReadSaveBuf(&aCranes[i].m_fPickupAngle, buf);
+ ReadSaveBuf(&aCranes[i].m_fDropoffAngle, buf);
+ ReadSaveBuf(&aCranes[i].m_fPickupDistance, buf);
+ ReadSaveBuf(&aCranes[i].m_fDropoffDistance, buf);
+ ReadSaveBuf(&aCranes[i].m_fPickupHeight, buf);
+ ReadSaveBuf(&aCranes[i].m_fDropoffHeight, buf);
+ ReadSaveBuf(&aCranes[i].m_fHookAngle, buf);
+ ReadSaveBuf(&aCranes[i].m_fHookOffset, buf);
+ ReadSaveBuf(&aCranes[i].m_fHookHeight, buf);
+ ReadSaveBuf(&aCranes[i].m_vecHookInitPos, buf);
+ ReadSaveBuf(&aCranes[i].m_vecHookCurPos, buf);
+ ReadSaveBuf(&aCranes[i].m_vecHookVelocity, buf); + ReadSaveBuf(&tmp, buf); + aCranes[i].m_pVehiclePickedUp = tmp != 0 ? CPools::GetVehiclePool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&aCranes[i].m_nTimeForNextCheck, buf);
+ ReadSaveBuf(&aCranes[i].m_nCraneStatus, buf);
+ ReadSaveBuf(&aCranes[i].m_nCraneState, buf);
+ ReadSaveBuf(&aCranes[i].m_nVehiclesCollected, buf);
+ ReadSaveBuf(&aCranes[i].m_bIsCrusher, buf);
+ ReadSaveBuf(&aCranes[i].m_bIsMilitaryCrane, buf);
+ ReadSaveBuf(&aCranes[i].m_bWasMilitaryCrane, buf);
+ ReadSaveBuf(&aCranes[i].m_bIsTop, buf); + SkipSaveBuf(buf, 1); +#else ReadSaveBuf(&aCranes[i], buf); + } for (int i = 0; i < NUM_CRANES; i++) { CCrane *pCrane = &aCranes[i]; if (pCrane->m_pCraneEntity != nil) @@ -666,6 +747,7 @@ void CCranes::Load(uint8* buf, uint32 size) pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uintptr)pCrane->m_pHook - 1); if (pCrane->m_pVehiclePickedUp != nil) pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uintptr)pCrane->m_pVehiclePickedUp - 1); +#endif } for (int i = 0; i < NUM_CRANES; i++) { aCranes[i].m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &aCranes[i]); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 3d3ba8f2..4259f9d8 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1262,42 +1262,42 @@ DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle) void CVehicle::Save(uint8*& buf) { - SkipSaveBuf(buf, 4); - WriteSaveBuf<float>(buf, GetRight().x); - WriteSaveBuf<float>(buf, GetRight().y); - WriteSaveBuf<float>(buf, GetRight().z); - SkipSaveBuf(buf, 4); - WriteSaveBuf<float>(buf, GetForward().x); - WriteSaveBuf<float>(buf, GetForward().y); - WriteSaveBuf<float>(buf, GetForward().z); - SkipSaveBuf(buf, 4); - WriteSaveBuf<float>(buf, GetUp().x); - WriteSaveBuf<float>(buf, GetUp().y); - WriteSaveBuf<float>(buf, GetUp().z); - SkipSaveBuf(buf, 4); - WriteSaveBuf<float>(buf, GetPosition().x); - WriteSaveBuf<float>(buf, GetPosition().y); - WriteSaveBuf<float>(buf, GetPosition().z); - SkipSaveBuf(buf, 16); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetRight().x); + WriteSaveBuf(buf, GetRight().y); + WriteSaveBuf(buf, GetRight().z); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetForward().x); + WriteSaveBuf(buf, GetForward().y); + WriteSaveBuf(buf, GetForward().z); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetUp().x); + WriteSaveBuf(buf, GetUp().y); + WriteSaveBuf(buf, GetUp().z); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetPosition().x); + WriteSaveBuf(buf, GetPosition().y); + WriteSaveBuf(buf, GetPosition().z); + ZeroSaveBuf(buf, 16); SaveEntityFlags(buf); - SkipSaveBuf(buf, 212); + ZeroSaveBuf(buf, 212); AutoPilot.Save(buf); - WriteSaveBuf<int8>(buf, m_currentColour1); - WriteSaveBuf<int8>(buf, m_currentColour2); - SkipSaveBuf(buf, 2); - WriteSaveBuf<int16>(buf, m_nAlarmState); - SkipSaveBuf(buf, 43); - WriteSaveBuf<uint8>(buf, m_nNumMaxPassengers); - SkipSaveBuf(buf, 2); - WriteSaveBuf<float>(buf, field_1D0[0]); - WriteSaveBuf<float>(buf, field_1D0[1]); - WriteSaveBuf<float>(buf, field_1D0[2]); - WriteSaveBuf<float>(buf, field_1D0[3]); - SkipSaveBuf(buf, 8); - WriteSaveBuf<float>(buf, m_fSteerAngle); - WriteSaveBuf<float>(buf, m_fGasPedal); - WriteSaveBuf<float>(buf, m_fBrakePedal); - WriteSaveBuf<uint8>(buf, VehicleCreatedBy); + WriteSaveBuf(buf, m_currentColour1); + WriteSaveBuf(buf, m_currentColour2); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, m_nAlarmState); + ZeroSaveBuf(buf, 43); + WriteSaveBuf(buf, m_nNumMaxPassengers); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, field_1D0[0]); + WriteSaveBuf(buf, field_1D0[1]); + WriteSaveBuf(buf, field_1D0[2]); + WriteSaveBuf(buf, field_1D0[3]); + ZeroSaveBuf(buf, 8); + WriteSaveBuf(buf, m_fSteerAngle); + WriteSaveBuf(buf, m_fGasPedal); + WriteSaveBuf(buf, m_fBrakePedal); + WriteSaveBuf(buf, VehicleCreatedBy); uint8 flags = 0; if (bIsLawEnforcer) flags |= BIT(0); if (bIsLocked) flags |= BIT(3); @@ -1305,19 +1305,19 @@ CVehicle::Save(uint8*& buf) if (bIsHandbrakeOn) flags |= BIT(5); if (bLightsOn) flags |= BIT(6); if (bFreebies) flags |= BIT(7); - WriteSaveBuf<uint8>(buf, flags); - SkipSaveBuf(buf, 10); - WriteSaveBuf<float>(buf, m_fHealth); - WriteSaveBuf<uint8>(buf, m_nCurrentGear); - SkipSaveBuf(buf, 3); - WriteSaveBuf<float>(buf, m_fChangeGearTime); - SkipSaveBuf(buf, 4); - WriteSaveBuf<uint32>(buf, m_nTimeOfDeath); - SkipSaveBuf(buf, 2); - WriteSaveBuf<int16>(buf, m_nBombTimer); - SkipSaveBuf(buf, 12); - WriteSaveBuf<int8>(buf, m_nDoorLock); - SkipSaveBuf(buf, 99); + WriteSaveBuf(buf, flags); + ZeroSaveBuf(buf, 10); + WriteSaveBuf(buf, m_fHealth); + WriteSaveBuf(buf, m_nCurrentGear); + ZeroSaveBuf(buf, 3); + WriteSaveBuf(buf, m_fChangeGearTime); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, m_nTimeOfDeath); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, m_nBombTimer); + ZeroSaveBuf(buf, 12); + WriteSaveBuf(buf, m_nDoorLock); + ZeroSaveBuf(buf, 96); } void @@ -1379,8 +1379,7 @@ CVehicle::Load(uint8*& buf) SkipSaveBuf(buf, 2); ReadSaveBuf(&m_nBombTimer, buf); SkipSaveBuf(buf, 12); - ReadSaveBuf(&flags, buf); - m_nDoorLock = (eCarLock)flags; - SkipSaveBuf(buf, 99); + ReadSaveBuf(&m_nDoorLock, buf); + SkipSaveBuf(buf, 96); } #endif diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 43a85db8..6eab1a65 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -592,6 +592,16 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { CVector src, trgt; TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt); +#ifdef FREE_CAM + CPed *shooterPed = (CPed *)shooter; + if((shooterPed->m_pedIK.m_flags & CPedIK::GUN_POINTED_SUCCESSFULLY) == 0) { + trgt.x = info->m_fRange; + trgt.y = 0.0f; + trgt.z = 0.0f; + + shooterPed->TransformToNode(trgt, PED_HANDR); + } +#endif #ifdef FIX_BUGS // fix muzzleflash rotation @@ -2337,7 +2347,7 @@ CWeapon::Save(uint8*& buf) CopyToBuf(buf, m_nAmmoTotal); CopyToBuf(buf, m_nTimer); CopyToBuf(buf, m_bAddRotOffset); - SkipSaveBuf(buf, 3); + ZeroSaveBuf(buf, 3); } void diff --git a/utils/gxt/american.txt b/utils/gxt/american.txt index cf71c958..d8f79f05 100644 --- a/utils/gxt/american.txt +++ b/utils/gxt/american.txt @@ -8094,6 +8094,12 @@ VIBRATION [FET_AGS] GAMEPAD SETTINGS +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + { end of file } [DUMMY] diff --git a/utils/gxt/french.txt b/utils/gxt/french.txt index 09a1f5c2..bd4acf96 100644 --- a/utils/gxt/french.txt +++ b/utils/gxt/french.txt @@ -8362,6 +8362,12 @@ VIBRATIONS [FET_AGS] GAMEPAD SETTINGS +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + { end of file } [DUMMY] diff --git a/utils/gxt/german.txt b/utils/gxt/german.txt index 4f7ee052..5f5c53c4 100644 --- a/utils/gxt/german.txt +++ b/utils/gxt/german.txt @@ -8179,6 +8179,12 @@ Vibration : [FET_AGS] KONTROLLEREINSTELLUNGEN +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + [DUMMY] THIS LABEL NEEDS TO BE HERE !!! AS THE LAST LABEL DOES NOT GET COMPILED diff --git a/utils/gxt/italian.txt b/utils/gxt/italian.txt index 54c9fee8..803b7fbf 100644 --- a/utils/gxt/italian.txt +++ b/utils/gxt/italian.txt @@ -8191,6 +8191,12 @@ VIBRAZIONE [FET_AGS] GAMEPAD SETTINGS +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + [DUMMY] THIS LABEL NEEDS TO BE HERE !!! AS THE LAST LABEL DOES NOT GET COMPILED
\ No newline at end of file diff --git a/utils/gxt/polish.txt b/utils/gxt/polish.txt index 39727554..33716291 100755 --- a/utils/gxt/polish.txt +++ b/utils/gxt/polish.txt @@ -8100,6 +8100,12 @@ WIBRACJA [FET_AGS]
GAMEPAD SETTINGS
+[FEM_PED]
+PED DENSITY
+
+[FEM_CAR]
+CAR DENSITY
+
{ end of file }
[DUMMY]
diff --git a/utils/gxt/russian.txt b/utils/gxt/russian.txt index 3a723aa2..221e59f5 100644 --- a/utils/gxt/russian.txt +++ b/utils/gxt/russian.txt @@ -8102,6 +8102,12 @@ DUALSHOCK 4 [FET_AGS] НАСТРОЙКИ ГЕЙМПАДА +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + { end of file } [DUMMY] diff --git a/utils/gxt/spanish.txt b/utils/gxt/spanish.txt index b2e418dd..5f108d3b 100644 --- a/utils/gxt/spanish.txt +++ b/utils/gxt/spanish.txt @@ -8161,6 +8161,12 @@ VIBRACIÓN [FET_AGS] AJUSTES DE MANDO +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + { end of file } [DUMMY] |