summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--premake5.lua4
-rw-r--r--src/audio/AudioLogic.cpp213
-rw-r--r--src/audio/AudioManager.cpp18
-rw-r--r--src/audio/MusicManager.cpp5
-rw-r--r--src/audio/oal/stream.cpp784
-rw-r--r--src/audio/oal/stream.h10
-rw-r--r--src/audio/sampman_oal.cpp50
-rw-r--r--src/collision/ColStore.cpp21
-rw-r--r--src/control/Garages.cpp8
-rw-r--r--src/control/Garages.h10
-rw-r--r--src/control/Replay.cpp4
-rw-r--r--src/control/Script.cpp204
-rw-r--r--src/control/Script.h68
-rw-r--r--src/control/Script2.cpp17
-rw-r--r--src/control/Script3.cpp11
-rw-r--r--src/control/Script4.cpp9
-rw-r--r--src/control/Script5.cpp74
-rw-r--r--src/control/Script6.cpp8
-rw-r--r--src/control/Script7.cpp10
-rw-r--r--src/control/Script8.cpp2
-rw-r--r--src/control/SetPieces.cpp7
-rw-r--r--src/core/Cam.cpp11
-rw-r--r--src/core/Clock.cpp13
-rw-r--r--src/core/ControllerConfig.cpp86
-rw-r--r--src/core/Frontend.cpp13
-rw-r--r--src/core/Frontend.h4
-rw-r--r--src/core/Game.cpp21
-rw-r--r--src/core/Game.h5
-rw-r--r--src/core/MenuScreens.cpp4
-rw-r--r--src/core/MenuScreensCustom.cpp18
-rw-r--r--src/core/Pad.cpp7
-rw-r--r--src/core/Streaming.cpp19
-rw-r--r--src/core/SurfaceTable.cpp2
-rw-r--r--src/core/common.h4
-rw-r--r--src/core/config.h6
-rw-r--r--src/core/main.cpp14
-rw-r--r--src/core/re3.cpp3
-rw-r--r--src/entities/Entity.cpp10
-rw-r--r--src/entities/Physical.cpp75
-rw-r--r--src/extras/frontendoption.cpp3
-rw-r--r--src/extras/frontendoption.h2
-rw-r--r--src/extras/ini_parser.hpp2
-rw-r--r--src/extras/screendroplets.cpp2
-rw-r--r--src/fakerw/fake.cpp1
-rw-r--r--src/fakerw/rwplcore.h4
-rw-r--r--src/peds/Ped.h2
-rw-r--r--src/peds/PedAI.cpp16
-rw-r--r--src/peds/PedFight.cpp58
-rw-r--r--src/peds/PlayerPed.cpp45
-rw-r--r--src/peds/PlayerPed.h5
-rw-r--r--src/render/Font.cpp67
-rw-r--r--src/render/Font.h4
-rw-r--r--src/render/Hud.cpp8
-rw-r--r--src/render/Occlusion.cpp11
-rw-r--r--src/render/Occlusion.h2
-rw-r--r--src/render/Shadows.cpp8
-rw-r--r--src/render/VarConsole.cpp786
-rw-r--r--src/render/VarConsole.h92
-rw-r--r--src/render/WaterLevel.cpp4
-rw-r--r--src/render/Weather.cpp8
-rw-r--r--src/vehicles/Automobile.cpp25
-rw-r--r--src/vehicles/Bike.cpp2
-rw-r--r--src/vehicles/HandlingMgr.cpp20
-rw-r--r--src/vehicles/Transmission.cpp2
-rw-r--r--src/vehicles/Transmission.h2
-rw-r--r--src/vehicles/Vehicle.cpp16
-rw-r--r--src/vehicles/Vehicle.h3
67 files changed, 2439 insertions, 613 deletions
diff --git a/premake5.lua b/premake5.lua
index 26c64c35..9796b8a9 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -125,11 +125,9 @@ workspace "reVC"
filter { "platforms:*x86*" }
architecture "x86"
- floatingpoint "Fast"
filter { "platforms:*amd64*" }
architecture "amd64"
- floatingpoint "Fast"
filter { "platforms:*arm*" }
architecture "ARM"
@@ -192,11 +190,9 @@ project "librw"
filter { "platforms:*x86*" }
architecture "x86"
- floatingpoint "Fast"
filter { "platforms:*amd64*" }
architecture "amd64"
- floatingpoint "Fast"
filter "platforms:win*"
staticruntime "on"
diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp
index 8f03d66a..01b33fa5 100644
--- a/src/audio/AudioLogic.cpp
+++ b/src/audio/AudioLogic.cpp
@@ -4201,109 +4201,109 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
switch (sound) {
case SOUND_STEP_START:
case SOUND_STEP_END:
- if (!params.m_pPed->bIsLooking) {
- emittingVol = m_anRandomTable[3] % 15 + 45;
- if (FindPlayerPed() != m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity)
- emittingVol /= 2;
- maxDist = 400.f;
- switch (params.m_pPed->m_nSurfaceTouched) {
- case SURFACE_GRASS:
- sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1;
- break;
- case SURFACE_GRAVEL:
- case SURFACE_MUD_DRY:
- sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1;
- break;
- case SURFACE_CAR:
- case SURFACE_GARAGE_DOOR:
- case SURFACE_CAR_PANEL:
- case SURFACE_THICK_METAL_PLATE:
- case SURFACE_SCAFFOLD_POLE:
- case SURFACE_LAMP_POST:
- case SURFACE_FIRE_HYDRANT:
- case SURFACE_GIRDER:
- case SURFACE_METAL_CHAIN_FENCE:
- case SURFACE_CONTAINER:
- case SURFACE_NEWS_VENDOR:
- sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1;
- break;
- case SURFACE_SAND:
- sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1;
- break;
- case SURFACE_WATER:
- sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
- break;
- case SURFACE_WOOD_CRATES:
- case SURFACE_WOOD_BENCH:
- case SURFACE_WOOD_SOLID:
- sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1;
- break;
- case SURFACE_HEDGE:
- sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_VEG_1;
- break;
- default:
- sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_CONCRETE_1;
- break;
- }
- m_sQueueSample.m_nSampleIndex = sampleIndex;
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - 32;
- m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
- m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);
- switch (params.m_pPed->m_nMoveState) {
- case PEDMOVE_WALK:
- emittingVol /= 4;
- m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10;
- break;
- case PEDMOVE_RUN:
- emittingVol /= 2;
- m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10;
- break;
- case PEDMOVE_SPRINT:
- m_sQueueSample.m_nFrequency = 12 * m_sQueueSample.m_nFrequency / 10;
- break;
- default:
- break;
- }
- m_sQueueSample.m_nReleasingVolumeModificator = 5;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 20.0f;
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
+ if (params.m_pPed->bIsInTheAir)
+ continue;
+ emittingVol = m_anRandomTable[3] % 15 + 45;
+ if (FindPlayerPed() != m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity)
+ emittingVol /= 2;
+ maxDist = 400.f;
+ switch (params.m_pPed->m_nSurfaceTouched) {
+ case SURFACE_GRASS:
+ sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1;
+ break;
+ case SURFACE_GRAVEL:
+ case SURFACE_MUD_DRY:
+ sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1;
+ break;
+ case SURFACE_CAR:
+ case SURFACE_GARAGE_DOOR:
+ case SURFACE_CAR_PANEL:
+ case SURFACE_THICK_METAL_PLATE:
+ case SURFACE_SCAFFOLD_POLE:
+ case SURFACE_LAMP_POST:
+ case SURFACE_FIRE_HYDRANT:
+ case SURFACE_GIRDER:
+ case SURFACE_METAL_CHAIN_FENCE:
+ case SURFACE_CONTAINER:
+ case SURFACE_NEWS_VENDOR:
+ sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1;
+ break;
+ case SURFACE_SAND:
+ sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1;
+ break;
+ case SURFACE_WATER:
+ sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
+ break;
+ case SURFACE_WOOD_CRATES:
+ case SURFACE_WOOD_BENCH:
+ case SURFACE_WOOD_SOLID:
+ sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1;
+ break;
+ case SURFACE_HEDGE:
+ sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_VEG_1;
+ break;
+ default:
+ sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_CONCRETE_1;
+ break;
+ }
+ m_sQueueSample.m_nSampleIndex = sampleIndex;
+ m_sQueueSample.m_nBankIndex = SFX_BANK_0;
+ m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - SOUND_STEP_START + 1;
+ m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
+ m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);
+ switch (params.m_pPed->m_nMoveState) {
+ case PEDMOVE_WALK:
+ emittingVol /= 4;
+ m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10;
+ break;
+ case PEDMOVE_RUN:
+ emittingVol /= 2;
+ m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10;
+ break;
+ case PEDMOVE_SPRINT:
+ m_sQueueSample.m_nFrequency = 12 * m_sQueueSample.m_nFrequency / 10;
+ break;
+ default:
+ break;
}
+ m_sQueueSample.m_nReleasingVolumeModificator = 5;
+ m_sQueueSample.m_fSpeedMultiplier = 0.0f;
+ m_sQueueSample.m_fSoundIntensity = 20.0f;
+ m_sQueueSample.m_nLoopCount = 1;
+ m_sQueueSample.m_nLoopStart = 0;
+ m_sQueueSample.m_nLoopEnd = -1;
+ m_sQueueSample.m_nEmittingVolume = emittingVol;
+ m_sQueueSample.m_bIs2D = false;
+ m_sQueueSample.m_bReleasingSoundFlag = true;
+ m_sQueueSample.m_bRequireReflection = true;
break;
case SOUND_FALL_LAND:
case SOUND_FALL_COLLAPSE:
- if (!ped->bIsLooking) {
- maxDist = SQR(30);
- emittingVol = m_anRandomTable[3] % 20 + 80;
- if (ped->m_nSurfaceTouched == SURFACE_WATER) {
- m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
- } else if (sound == SOUND_FALL_LAND) {
- m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND;
- } else {
- m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND_AND_FALL;
- }
- m_sQueueSample.m_nBankIndex = SFX_BANK_0;
- m_sQueueSample.m_nCounter = 1;
- m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
- m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);
- m_sQueueSample.m_nReleasingVolumeModificator = 2;
- m_sQueueSample.m_fSpeedMultiplier = 0.0f;
- m_sQueueSample.m_fSoundIntensity = 30.0f;
- m_sQueueSample.m_nLoopCount = 1;
- m_sQueueSample.m_nLoopStart = 0;
- m_sQueueSample.m_nLoopEnd = -1;
- m_sQueueSample.m_nEmittingVolume = emittingVol;
- m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReleasingSoundFlag = true;
- m_sQueueSample.m_bRequireReflection = true;
+ if (ped->bIsInTheAir)
+ continue;
+ maxDist = SQR(30);
+ emittingVol = m_anRandomTable[3] % 20 + 80;
+ if (ped->m_nSurfaceTouched == SURFACE_WATER) {
+ m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;
+ } else if (sound == SOUND_FALL_LAND) {
+ m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND;
+ } else {
+ m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND_AND_FALL;
}
+ m_sQueueSample.m_nBankIndex = SFX_BANK_0;
+ m_sQueueSample.m_nCounter = 1;
+ m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);
+ m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);
+ m_sQueueSample.m_nReleasingVolumeModificator = 2;
+ m_sQueueSample.m_fSpeedMultiplier = 0.0f;
+ m_sQueueSample.m_fSoundIntensity = 30.0f;
+ m_sQueueSample.m_nLoopCount = 1;
+ m_sQueueSample.m_nLoopStart = 0;
+ m_sQueueSample.m_nLoopEnd = -1;
+ m_sQueueSample.m_nEmittingVolume = emittingVol;
+ m_sQueueSample.m_bIs2D = false;
+ m_sQueueSample.m_bReleasingSoundFlag = true;
+ m_sQueueSample.m_bRequireReflection = true;
break;
case SOUND_FIGHT_37:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;
@@ -4342,6 +4342,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nFrequency = 20000;
goto AddFightSound;
case SOUND_FIGHT_46:
+ case SOUND_187:
m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;
m_sQueueSample.m_nFrequency = 18000;
goto AddFightSound;
@@ -4354,7 +4355,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nFrequency = 20000;
AddFightSound:
{
- uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? stroring int as float
+ uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? storing int as float
uint8 damagerType = soundParams & 0xFF;
uint32 weaponType = soundParams >> 8;
@@ -4402,7 +4403,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
case SOUND_WEAPON_BAT_ATTACK:
case SOUND_WEAPON_KNIFE_ATTACK:
{
- uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? stroring int as float
+ uint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? storing int as float
uint8 damagerType = soundParams & 0xFF;
uint32 weaponType = soundParams >> 8;
if (damagerType == ENTITY_TYPE_PED) {
@@ -4461,7 +4462,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
continue;
m_sQueueSample.m_nSampleIndex = SFX_CAR_ACCEL_13;
m_sQueueSample.m_nBankIndex = SFX_BANK_0; // SFX_BANK_CAR_CHAINSAW
- m_sQueueSample.m_nCounter = 64;
+ m_sQueueSample.m_nCounter = 70;
m_sQueueSample.m_nFrequency = 27000;
m_sQueueSample.m_nReleasingVolumeModificator = 3;
m_sQueueSample.m_fSpeedMultiplier = 3.0f;
@@ -4473,7 +4474,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_CAR_ACCEL_13);
m_sQueueSample.m_nEmittingVolume = 100;
m_sQueueSample.m_bIs2D = false;
- m_sQueueSample.m_bReverbFlag = false;
+ m_sQueueSample.m_bReleasingSoundFlag = false;
m_sQueueSample.m_nReleasingVolumeDivider = 5;
break;
case SOUND_WEAPON_CHAINSAW_IDLE:
@@ -5159,7 +5160,7 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
m_sQueueSample.m_nReleasingVolumeDivider = 3;
}
}
- break;
+ continue;
default:
SetupPedComments(params, sound);
continue;
@@ -9922,7 +9923,7 @@ cAudioManager::ProcessMissionAudioSlot(uint8 slot)
nCheckPlayingDelay[slot] = 0;
nFramesUntilFailedLoad[slot] = 0;
} else if (!m_nUserPause) {
- if (++nFramesForPretendPlaying[slot] < 120) {
+ if (++nFramesForPretendPlaying[slot] < 90) {
m_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_PLAYING;
} else {
m_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_FINISHED;
@@ -9938,7 +9939,7 @@ cAudioManager::ProcessMissionAudioSlot(uint8 slot)
} else {
if (m_nUserPause)
SampleManager.PauseStream(1, slot + 1);
- if (m_sMissionAudio.m_bPredefinedProperties) {
+ if (m_sMissionAudio.m_bPredefinedProperties[slot]) {
if (m_sMissionAudio.m_nSampleIndex[slot] == STREAMED_SOUND_MISSION_CAMERAL)
SampleManager.SetStreamedVolumeAndPan(80, 0, 1, slot + 1);
else if (m_sMissionAudio.m_nSampleIndex[slot] == STREAMED_SOUND_MISSION_CAMERAR)
@@ -9992,7 +9993,7 @@ cAudioManager::ProcessMissionAudioSlot(uint8 slot)
else
{
SampleManager.PauseStream(0, slot + 1);
- if (!m_sMissionAudio.m_bPredefinedProperties) {
+ if (!m_sMissionAudio.m_bPredefinedProperties[slot]) {
distSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos[slot]);
if (distSquared >= SQR(80.0f)) {
emittingVol = 0;
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index d441b750..721a7acc 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -10,6 +10,7 @@
#include "sampman.h"
#include "Camera.h"
#include "World.h"
+#include "ZoneCull.h"
cAudioManager AudioManager;
@@ -17,12 +18,16 @@ const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples);
const int policeChannel = channels + 1;
const int allChannels = channels + 2;
+#define SPEED_OF_SOUND 343.f
+#define TIME_SPENT 40
+
cAudioManager::cAudioManager()
{
m_bIsInitialised = false;
m_bReverb = true;
- m_fSpeedOfSound = 6.86f;
- m_nTimeSpent = 50;
+ field_6 = 0;
+ m_fSpeedOfSound = SPEED_OF_SOUND / TIME_SPENT;
+ m_nTimeSpent = TIME_SPENT;
m_nActiveSamples = NUM_SOUNDS_SAMPLES_SLOTS;
m_nActiveSampleQueue = 1;
ClearRequestedQueue();
@@ -585,7 +590,7 @@ cAudioManager::AddSampleToRequestedQueue()
}
m_sQueueSample.m_nCalculatedVolume = calculatedVolume;
m_sQueueSample.m_bLoopEnded = false;
- if (m_sQueueSample.m_bIs2D) {
+ if (m_sQueueSample.m_bIs2D || CCullZones::InRoomForAudio()) {
m_sQueueSample.m_bRequireReflection = false;
m_sQueueSample.m_nLoopsRemaining = 0;
}
@@ -597,6 +602,9 @@ cAudioManager::AddSampleToRequestedQueue()
}
m_sQueueSample.m_bRequireReflection = false;
+ if ( m_bReverb && m_sQueueSample.m_bIs2D )
+ m_sQueueSample.field_4C = 30;
+
if (!m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bReverbFlag = false;
@@ -643,9 +651,9 @@ cAudioManager::AddReflectionsToRequestedQueue()
emittingVolume = m_sQueueSample.m_nVolume;
oldFreq = m_sQueueSample.m_nFrequency;
} else {
- emittingVolume = (m_sQueueSample.m_nVolume / 2) + (m_sQueueSample.m_nVolume / 16);
+ emittingVolume = (9 * m_sQueueSample.m_nVolume) / 16;
}
- m_sQueueSample.m_fSoundIntensity = m_sQueueSample.m_fSoundIntensity / 2.f;
+ m_sQueueSample.m_fSoundIntensity /= 2.f;
int halfOldFreq = oldFreq >> 1;
diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp
index c4abf351..acfe09c3 100644
--- a/src/audio/MusicManager.cpp
+++ b/src/audio/MusicManager.cpp
@@ -25,7 +25,7 @@ cMusicManager MusicManager;
int32 gNumRetunePresses;
int32 gRetuneCounter;
bool g_bAnnouncementReadPosAlready;
-uint8 RadioStaticCounter;
+uint8 RadioStaticCounter = 5;
uint32 RadioStaticTimer;
CVector vecRiotPosition(300.7f, -322.0f, 12.0f);
@@ -435,7 +435,7 @@ cMusicManager::ServiceFrontEndMode()
else {
if (m_nCurrentVolume < m_nMaxVolume)
m_nCurrentVolume = Min(m_nMaxVolume, m_nCurrentVolume + 6);
- SampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63u, 0, 0);
+ SampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);
}
} else {
if (m_nPlayingTrack == STREAMED_SOUND_RADIO_MP3_PLAYER)
@@ -991,6 +991,7 @@ cMusicManager::ServiceTrack(CVehicle *veh, CPed *ped)
}
} else if (AudioManager.ShouldDuckMissionAudio(0) || AudioManager.ShouldDuckMissionAudio(1)) {
SampleManager.SetStreamedVolumeAndPan(Min(m_nCurrentVolume, 25), 63, 0, 0);
+ nFramesSinceCutsceneEnded = 0;
} else {
if (nFramesSinceCutsceneEnded == -1)
volume = m_nCurrentVolume;
diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp
index 3a1f748f..cdf063fa 100644
--- a/src/audio/oal/stream.cpp
+++ b/src/audio/oal/stream.cpp
@@ -8,10 +8,14 @@
#include <opusfile.h>
#else
#ifdef _WIN32
+#ifdef AUDIO_OAL_USE_SNDFILE
#pragma comment( lib, "libsndfile-1.lib" )
+#endif
#pragma comment( lib, "libmpg123-0.lib" )
#endif
+#ifdef AUDIO_OAL_USE_SNDFILE
#include <sndfile.h>
+#endif
#include <mpg123.h>
#endif
@@ -19,7 +23,374 @@
#include "crossplatform.h"
#endif
+/*
+As we ran onto an issue of having different volume levels for mono streams
+and stereo streams we are now handling all the stereo panning ourselves.
+Each stream now has two sources - one panned to the left and one to the right,
+and uses two separate buffers to store data for each individual channel.
+For that we also have to reshuffle all decoded PCM stereo data from LRLRLRLR to
+LLLLRRRR (handled by CSortStereoBuffer).
+*/
+
+class CSortStereoBuffer
+{
+ uint16* PcmBuf;
+ size_t BufSize;
+public:
+ CSortStereoBuffer() : PcmBuf(nil), BufSize(0) {}
+ ~CSortStereoBuffer()
+ {
+ if (PcmBuf)
+ free(PcmBuf);
+ }
+
+ uint16* GetBuffer(size_t size)
+ {
+ if (size == 0) return nil;
+ if (!PcmBuf)
+ {
+ BufSize = size;
+ PcmBuf = (uint16*)malloc(BufSize);
+ }
+ else if (BufSize < size)
+ {
+ BufSize = size;
+ PcmBuf = (uint16*)realloc(PcmBuf, size);
+ }
+ return PcmBuf;
+ }
+
+ void SortStereo(void* buf, size_t size)
+ {
+ uint16* InBuf = (uint16*)buf;
+ uint16* OutBuf = GetBuffer(size);
+
+ if (!OutBuf) return;
+
+ size_t rightStart = size / 4;
+ for (size_t i = 0; i < size / 4; i++)
+ {
+ OutBuf[i] = InBuf[i*2];
+ OutBuf[i+rightStart] = InBuf[i*2+1];
+ }
+
+ memcpy(InBuf, OutBuf, size);
+ }
+
+};
+
+CSortStereoBuffer SortStereoBuffer;
+
#ifndef AUDIO_OPUS
+class CImaADPCMDecoder
+{
+ const uint16 StepTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 16, 17, 19, 21, 23, 25, 28, 31,
+ 34, 37, 41, 45, 50, 55, 60, 66,
+ 73, 80, 88, 97, 107, 118, 130, 143,
+ 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1411,
+ 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
+ 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
+ 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
+ 32767
+ };
+
+ int16 Sample, StepIndex;
+
+public:
+ CImaADPCMDecoder()
+ {
+ Init(0, 0);
+ }
+
+ void Init(int16 _Sample, int16 _StepIndex)
+ {
+ Sample = _Sample;
+ StepIndex = _StepIndex;
+ }
+
+ void Decode(uint8 *inbuf, int16 *_outbuf, size_t size)
+ {
+ int16* outbuf = _outbuf;
+ for (size_t i = 0; i < size; i++)
+ {
+ *(outbuf++) = DecodeSample(inbuf[i] & 0xF);
+ *(outbuf++) = DecodeSample(inbuf[i] >> 4);
+ }
+ }
+
+ int16 DecodeSample(uint8 adpcm)
+ {
+ uint16 step = StepTable[StepIndex];
+
+ if (adpcm & 4)
+ StepIndex += ((adpcm & 3) + 1) * 2;
+ else
+ StepIndex--;
+
+ StepIndex = clamp(StepIndex, 0, 88);
+
+ int delta = step >> 3;
+ if (adpcm & 1) delta += step >> 2;
+ if (adpcm & 2) delta += step >> 1;
+ if (adpcm & 4) delta += step;
+ if (adpcm & 8) delta = -delta;
+
+ int newSample = Sample + delta;
+ Sample = clamp(newSample, -32768, 32767);
+ return Sample;
+ }
+};
+
+class CWavFile : public IDecoder
+{
+ enum
+ {
+ WAVEFMT_PCM = 1,
+ WAVEFMT_IMA_ADPCM = 0x11,
+ WAVEFMT_XBOX_ADPCM = 0x69,
+ };
+
+ struct tDataHeader
+ {
+ uint32 ID;
+ uint32 Size;
+ };
+
+ struct tFormatHeader
+ {
+ uint16 AudioFormat;
+ uint16 NumChannels;
+ uint32 SampleRate;
+ uint32 ByteRate;
+ uint16 BlockAlign;
+ uint16 BitsPerSample;
+ uint16 extra[2]; // adpcm only
+
+ tFormatHeader() { memset(this, 0, sizeof(*this)); }
+ };
+
+ FILE *m_pFile;
+ bool m_bIsOpen;
+
+ tFormatHeader m_FormatHeader;
+
+ uint32 m_DataStartOffset; // TODO: 64 bit?
+ uint32 m_nSampleCount;
+ uint32 m_nSamplesPerBlock;
+
+ // ADPCM things
+ uint8 *m_pAdpcmBuffer;
+ int16 **m_ppPcmBuffers;
+ CImaADPCMDecoder *m_pAdpcmDecoders;
+
+ void Close()
+ {
+ if (m_pFile) {
+ fclose(m_pFile);
+ m_pFile = nil;
+ }
+ delete[] m_pAdpcmBuffer;
+ delete[] m_ppPcmBuffers;
+ delete[] m_pAdpcmDecoders;
+ }
+
+ uint32 GetCurrentSample() const
+ {
+ // TODO: 64 bit?
+ uint32 FilePos = ftell(m_pFile);
+ if (FilePos <= m_DataStartOffset)
+ return 0;
+ return (FilePos - m_DataStartOffset) / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;
+ }
+
+public:
+ CWavFile(const char* path) : m_bIsOpen(false), m_DataStartOffset(0), m_nSampleCount(0), m_nSamplesPerBlock(0), m_pAdpcmBuffer(nil), m_ppPcmBuffers(nil), m_pAdpcmDecoders(nil)
+ {
+ m_pFile = fopen(path, "rb");
+ if (!m_pFile) return;
+
+#define CLOSE_ON_ERROR(op)\
+ if (op) { \
+ Close(); \
+ return; \
+ }
+
+ tDataHeader DataHeader;
+
+ CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
+ CLOSE_ON_ERROR(DataHeader.ID != 'FFIR');
+
+ // TODO? validate filesizes
+
+ int WAVE;
+ CLOSE_ON_ERROR(fread(&WAVE, 4, 1, m_pFile) == 0);
+ CLOSE_ON_ERROR(WAVE != 'EVAW')
+ CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
+ CLOSE_ON_ERROR(DataHeader.ID != ' tmf');
+
+ CLOSE_ON_ERROR(fread(&m_FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, m_pFile) == 0);
+ CLOSE_ON_ERROR(DataHeader.Size > sizeof(tFormatHeader));
+
+ switch (m_FormatHeader.AudioFormat)
+ {
+ case WAVEFMT_XBOX_ADPCM:
+ m_FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM;
+ case WAVEFMT_IMA_ADPCM:
+ m_nSamplesPerBlock = (m_FormatHeader.BlockAlign / m_FormatHeader.NumChannels - 4) * 2 + 1;
+ m_pAdpcmBuffer = new uint8[m_FormatHeader.BlockAlign];
+ m_ppPcmBuffers = new int16*[m_FormatHeader.NumChannels];
+ m_pAdpcmDecoders = new CImaADPCMDecoder[m_FormatHeader.NumChannels];
+ break;
+ case WAVEFMT_PCM:
+ m_nSamplesPerBlock = 1;
+ if (m_FormatHeader.BitsPerSample != 16)
+ {
+ debug("Unsupported PCM (%d bits), only signed 16-bit is supported (%s)\n", m_FormatHeader.BitsPerSample, path);
+ Close();
+ return;
+ }
+ break;
+ default:
+ debug("Unsupported wav format 0x%x (%s)\n", m_FormatHeader.AudioFormat, path);
+ Close();
+ return;
+ }
+
+ while (true) {
+ CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);
+ if (DataHeader.ID == 'atad')
+ break;
+ fseek(m_pFile, DataHeader.Size, SEEK_CUR);
+ // TODO? validate data size
+ // maybe check if there no extreme custom headers that might break this
+ }
+
+ m_DataStartOffset = ftell(m_pFile);
+ m_nSampleCount = DataHeader.Size / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;
+
+ m_bIsOpen = true;
+#undef CLOSE_ON_ERROR
+ }
+
+ ~CWavFile()
+ {
+ Close();
+ }
+
+ bool IsOpened()
+ {
+ return m_bIsOpen;
+ }
+
+ uint32 GetSampleSize()
+ {
+ return sizeof(uint16);
+ }
+
+ uint32 GetSampleCount()
+ {
+ return m_nSampleCount;
+ }
+
+ uint32 GetSampleRate()
+ {
+ return m_FormatHeader.SampleRate;
+ }
+
+ uint32 GetChannels()
+ {
+ return m_FormatHeader.NumChannels;
+ }
+
+ void Seek(uint32 milliseconds)
+ {
+ if (!IsOpened()) return;
+ fseek(m_pFile, m_DataStartOffset + ms2samples(milliseconds) / m_nSamplesPerBlock * m_FormatHeader.BlockAlign, SEEK_SET);
+ }
+
+ uint32 Tell()
+ {
+ if (!IsOpened()) return 0;
+ return samples2ms(GetCurrentSample());
+ }
+
+#define SAMPLES_IN_LINE (8)
+
+ uint32 Decode(void* buffer)
+ {
+ if (!IsOpened()) return 0;
+
+ if (m_FormatHeader.AudioFormat == WAVEFMT_PCM)
+ {
+ // just read the file and sort the samples
+ uint32 size = fread(buffer, 1, GetBufferSize(), m_pFile);
+ if (m_FormatHeader.NumChannels == 2)
+ SortStereoBuffer.SortStereo(buffer, size);
+ return size;
+ }
+ else if (m_FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM)
+ {
+ // trim the buffer size if we're at the end of our file
+ uint32 nMaxSamples = GetBufferSamples() / m_FormatHeader.NumChannels;
+ uint32 nSamplesLeft = m_nSampleCount - GetCurrentSample();
+ nMaxSamples = Min(nMaxSamples, nSamplesLeft);
+
+ // align sample count to our block
+ nMaxSamples = nMaxSamples / m_nSamplesPerBlock * m_nSamplesPerBlock;
+
+ // count the size of output buffer
+ uint32 OutBufSizePerChannel = nMaxSamples * GetSampleSize();
+ uint32 OutBufSize = OutBufSizePerChannel * m_FormatHeader.NumChannels;
+
+ // calculate the pointers to individual channel buffers
+ for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
+ m_ppPcmBuffers[i] = (int16*)((int8*)buffer + OutBufSizePerChannel * i);
+
+ uint32 samplesRead = 0;
+ while (samplesRead < nMaxSamples)
+ {
+ // read the file
+ uint8 *pAdpcmBuf = m_pAdpcmBuffer;
+ if (fread(m_pAdpcmBuffer, 1, m_FormatHeader.BlockAlign, m_pFile) == 0)
+ return 0;
+
+ // get the first sample in adpcm block and initialise the decoder(s)
+ for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
+ {
+ int16 Sample = *(int16*)pAdpcmBuf;
+ pAdpcmBuf += sizeof(int16);
+ int16 Step = *(int16*)pAdpcmBuf;
+ pAdpcmBuf += sizeof(int16);
+ m_pAdpcmDecoders[i].Init(Sample, Step);
+ *(m_ppPcmBuffers[i]) = Sample;
+ m_ppPcmBuffers[i]++;
+ }
+ samplesRead++;
+
+ // decode the rest of the block
+ for (uint32 s = 1; s < m_nSamplesPerBlock; s += SAMPLES_IN_LINE)
+ {
+ for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)
+ {
+ m_pAdpcmDecoders[i].Decode(pAdpcmBuf, m_ppPcmBuffers[i], SAMPLES_IN_LINE / 2);
+ pAdpcmBuf += SAMPLES_IN_LINE / 2;
+ m_ppPcmBuffers[i] += SAMPLES_IN_LINE;
+ }
+ samplesRead += SAMPLES_IN_LINE;
+ }
+ }
+ return OutBufSize;
+ }
+ return 0;
+ }
+};
+
+#ifdef AUDIO_OAL_USE_SNDFILE
class CSndFile : public IDecoder
{
SNDFILE *m_pfSound;
@@ -81,9 +452,20 @@ public:
uint32 Decode(void *buffer)
{
if ( !IsOpened() ) return 0;
- return sf_read_short(m_pfSound, (short *)buffer, GetBufferSamples()) * GetSampleSize();
+
+ size_t size = sf_read_short(m_pfSound, (short*)buffer, GetBufferSamples()) * GetSampleSize();
+ if (GetChannels()==2)
+ SortStereoBuffer.SortStereo(buffer, size);
+ return size;
}
};
+#endif
+
+#ifdef _WIN32
+// fuzzy seek eliminates stutter when playing ADF but spams errors a lot (nothing breaks though)
+#define MP3_USE_FUZZY_SEEK
+#endif // _WIN32
+
class CMP3File : public IDecoder
{
@@ -108,6 +490,9 @@ public:
m_pMH = mpg123_new(nil, nil);
if ( m_pMH )
{
+#ifdef MP3_USE_FUZZY_SEEK
+ mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);
+#endif
long rate = 0;
int channels = 0;
int encoding = 0;
@@ -183,9 +568,249 @@ public:
assert("We can't handle audio files more then 2 GB yet :shrug:" && (size < UINT32_MAX));
#endif
if (err != MPG123_OK && err != MPG123_DONE) return 0;
+ if (GetChannels() == 2)
+ SortStereoBuffer.SortStereo(buffer, size);
return (uint32)size;
}
};
+
+#define VAG_LINE_SIZE (0x10)
+#define VAG_SAMPLES_IN_LINE (28)
+
+class CVagDecoder
+{
+ const double f[5][2] = { { 0.0, 0.0 },
+ { 60.0 / 64.0, 0.0 },
+ { 115.0 / 64.0, -52.0 / 64.0 },
+ { 98.0 / 64.0, -55.0 / 64.0 },
+ { 122.0 / 64.0, -60.0 / 64.0 } };
+
+ double s_1;
+ double s_2;
+public:
+ CVagDecoder()
+ {
+ ResetState();
+ }
+
+ void ResetState()
+ {
+ s_1 = s_2 = 0.0;
+ }
+
+ static short quantize(double sample)
+ {
+ int a = int(sample + 0.5);
+ return short(clamp(a, -32768, 32767));
+ }
+
+ void Decode(void* _inbuf, int16* _outbuf, size_t size)
+ {
+ uint8* inbuf = (uint8*)_inbuf;
+ int16* outbuf = _outbuf;
+ size &= ~(VAG_LINE_SIZE - 1);
+
+ while (size > 0) {
+ double samples[VAG_SAMPLES_IN_LINE];
+
+ int predict_nr, shift_factor, flags;
+ predict_nr = *(inbuf++);
+ shift_factor = predict_nr & 0xf;
+ predict_nr >>= 4;
+ flags = *(inbuf++);
+ if (flags == 7) // TODO: ignore?
+ break;
+ for (int i = 0; i < VAG_SAMPLES_IN_LINE; i += 2) {
+ int d = *(inbuf++);
+ int16 s = int16((d & 0xf) << 12);
+ samples[i] = (double)(s >> shift_factor);
+ s = int16((d & 0xf0) << 8);
+ samples[i + 1] = (double)(s >> shift_factor);
+ }
+
+ for (int i = 0; i < VAG_SAMPLES_IN_LINE; i++) {
+ samples[i] = samples[i] + s_1 * f[predict_nr][0] + s_2 * f[predict_nr][1];
+ s_2 = s_1;
+ s_1 = samples[i];
+ *(outbuf++) = quantize(samples[i] + 0.5);
+ }
+ size -= VAG_LINE_SIZE;
+ }
+ }
+};
+
+#define VB_BLOCK_SIZE (0x2000)
+#define NUM_VAG_LINES_IN_BLOCK (VB_BLOCK_SIZE / VAG_LINE_SIZE)
+#define NUM_VAG_SAMPLES_IN_BLOCK (NUM_VAG_LINES_IN_BLOCK * VAG_SAMPLES_IN_LINE)
+
+class CVbFile : public IDecoder
+{
+ FILE *m_pFile;
+ CVagDecoder *m_pVagDecoders;
+
+ size_t m_FileSize;
+ size_t m_nNumberOfBlocks;
+
+ uint32 m_nSampleRate;
+ uint8 m_nChannels;
+ bool m_bBlockRead;
+ uint16 m_LineInBlock;
+ size_t m_CurrentBlock;
+
+ uint8 **m_ppVagBuffers; // buffers that cache actual ADPCM file data
+ int16 **m_ppPcmBuffers;
+
+ void ReadBlock(int32 block = -1)
+ {
+ // just read next block if -1
+ if (block != -1)
+ fseek(m_pFile, block * m_nChannels * VB_BLOCK_SIZE, SEEK_SET);
+
+ for (int i = 0; i < m_nChannels; i++)
+ fread(m_ppVagBuffers[i], VB_BLOCK_SIZE, 1, m_pFile);
+ m_bBlockRead = true;
+ }
+
+public:
+ CVbFile(const char* path, uint32 nSampleRate = 32000, uint8 nChannels = 2) : m_nSampleRate(nSampleRate), m_nChannels(nChannels), m_pVagDecoders(nil), m_ppVagBuffers(nil), m_ppPcmBuffers(nil),
+ m_FileSize(0), m_nNumberOfBlocks(0), m_bBlockRead(false), m_LineInBlock(0), m_CurrentBlock(0)
+ {
+ m_pFile = fopen(path, "rb");
+ if (!m_pFile) return;
+
+ fseek(m_pFile, 0, SEEK_END);
+ m_FileSize = ftell(m_pFile);
+ fseek(m_pFile, 0, SEEK_SET);
+
+ m_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE);
+ m_pVagDecoders = new CVagDecoder[nChannels];
+ m_ppVagBuffers = new uint8*[nChannels];
+ m_ppPcmBuffers = new int16*[nChannels];
+ for (uint8 i = 0; i < nChannels; i++)
+ m_ppVagBuffers[i] = new uint8[VB_BLOCK_SIZE];
+ }
+
+ ~CVbFile()
+ {
+ if (m_pFile)
+ {
+ fclose(m_pFile);
+
+ delete[] m_pVagDecoders;
+ for (int i = 0; i < m_nChannels; i++)
+ delete[] m_ppVagBuffers[i];
+ delete[] m_ppVagBuffers;
+ delete[] m_ppPcmBuffers;
+ }
+ }
+
+ bool IsOpened()
+ {
+ return m_pFile != nil;
+ }
+
+ uint32 GetSampleSize()
+ {
+ return sizeof(uint16);
+ }
+
+ uint32 GetSampleCount()
+ {
+ if (!IsOpened()) return 0;
+ return m_nNumberOfBlocks * NUM_VAG_LINES_IN_BLOCK * VAG_SAMPLES_IN_LINE;
+ }
+
+ uint32 GetSampleRate()
+ {
+ return m_nSampleRate;
+ }
+
+ uint32 GetChannels()
+ {
+ return m_nChannels;
+ }
+
+ void Seek(uint32 milliseconds)
+ {
+ if (!IsOpened()) return;
+ uint32 samples = ms2samples(milliseconds);
+
+ // find the block of our sample
+ uint32 block = samples / NUM_VAG_SAMPLES_IN_BLOCK;
+ if (block > m_nNumberOfBlocks)
+ {
+ samples = 0;
+ block = 0;
+ }
+ if (block != m_CurrentBlock)
+ m_bBlockRead = false;
+
+ // find a line of our sample within our block
+ uint32 remainingSamples = samples - block * NUM_VAG_SAMPLES_IN_BLOCK;
+ uint32 newLine = remainingSamples / VAG_SAMPLES_IN_LINE / VAG_LINE_SIZE;
+
+ if (m_CurrentBlock != block || m_LineInBlock != newLine)
+ {
+ m_CurrentBlock = block;
+ m_LineInBlock = newLine;
+ for (uint32 i = 0; i < GetChannels(); i++)
+ m_pVagDecoders[i].ResetState();
+ }
+
+ }
+
+ uint32 Tell()
+ {
+ if (!IsOpened()) return 0;
+ uint32 pos = (m_CurrentBlock * NUM_VAG_LINES_IN_BLOCK + m_LineInBlock) * VAG_SAMPLES_IN_LINE;
+ return samples2ms(pos);
+ }
+
+ uint32 Decode(void* buffer)
+ {
+ if (!IsOpened()) return 0;
+
+ if (m_CurrentBlock >= m_nNumberOfBlocks) return 0;
+
+ // cache current ADPCM block
+ if (!m_bBlockRead)
+ ReadBlock(m_CurrentBlock);
+
+ // trim the buffer size if we're at the end of our file
+ int numberOfRequiredLines = GetBufferSamples() / m_nChannels / VAG_SAMPLES_IN_LINE;
+ int numberOfRemainingLines = (m_nNumberOfBlocks - m_CurrentBlock) * NUM_VAG_LINES_IN_BLOCK - m_LineInBlock;
+ int bufSizePerChannel = Min(numberOfRequiredLines, numberOfRemainingLines) * VAG_SAMPLES_IN_LINE * GetSampleSize();
+
+ // calculate the pointers to individual channel buffers
+ for (uint32 i = 0; i < m_nChannels; i++)
+ m_ppPcmBuffers[i] = (int16*)((int8*)buffer + bufSizePerChannel * i);
+
+ int size = 0;
+ while (size < bufSizePerChannel)
+ {
+ // decode the VAG lines
+ for (uint32 i = 0; i < m_nChannels; i++)
+ {
+ m_pVagDecoders[i].Decode(m_ppVagBuffers[i] + m_LineInBlock * VAG_LINE_SIZE, m_ppPcmBuffers[i], VAG_LINE_SIZE);
+ m_ppPcmBuffers[i] += VAG_SAMPLES_IN_LINE;
+ }
+ size += VAG_SAMPLES_IN_LINE * GetSampleSize();
+ m_LineInBlock++;
+
+ // block is over, read the next block
+ if (m_LineInBlock >= NUM_VAG_LINES_IN_BLOCK)
+ {
+ m_CurrentBlock++;
+ if (m_CurrentBlock >= m_nNumberOfBlocks) // end of file
+ break;
+ m_LineInBlock = 0;
+ ReadBlock();
+ }
+ }
+
+ return bufSizePerChannel * m_nChannels;
+ }
+};
#else
class COpusFile : public IDecoder
{
@@ -274,6 +899,9 @@ public:
if (size < 0)
return 0;
+ if (GetChannels() == 2)
+ SortStereoBuffer.SortStereo(buffer, size * m_nChannels * GetSampleSize());
+
return size * m_nChannels * GetSampleSize();
}
};
@@ -285,7 +913,7 @@ class CADFFile : public CMP3File
{
size_t bytesRead = fread(buf, 1, size, (FILE*)fh);
uint8* _buf = (uint8*)buf;
- for (int i = 0; i < size; i++)
+ for (size_t i = 0; i < size; i++)
_buf[i] ^= 0x22;
return bytesRead;
}
@@ -304,6 +932,9 @@ public:
m_pMH = mpg123_new(nil, nil);
if (m_pMH)
{
+#ifdef MP3_USE_FUZZY_SEEK
+ mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);
+#endif
long rate = 0;
int channels = 0;
int encoding = 0;
@@ -338,8 +969,8 @@ void CStream::Terminate()
#endif
}
-CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUFFERS]) :
- m_alSource(source),
+CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate) :
+ m_pAlSources(sources),
m_alBuffers(buffers),
m_pBuffer(nil),
m_bPaused(false),
@@ -370,9 +1001,15 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF
if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".mp3")], ".mp3"))
m_pSoundFile = new CMP3File(m_aFilename);
else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".wav")], ".wav"))
+#ifdef AUDIO_OAL_USE_SNDFILE
m_pSoundFile = new CSndFile(m_aFilename);
+#else
+ m_pSoundFile = new CWavFile(m_aFilename);
+#endif
else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".adf")], ".adf"))
m_pSoundFile = new CADFFile(m_aFilename);
+ else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".vb")], ".VB"))
+ m_pSoundFile = new CVbFile(m_aFilename, overrideSampleRate);
#else
if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".opus")], ".opus"))
m_pSoundFile = new COpusFile(m_aFilename);
@@ -422,7 +1059,7 @@ void CStream::Delete()
bool CStream::HasSource()
{
- return m_alSource != AL_NONE;
+ return (m_pAlSources[0] != AL_NONE) && (m_pAlSources[1] != AL_NONE);
}
bool CStream::IsOpened()
@@ -436,9 +1073,10 @@ bool CStream::IsPlaying()
if ( !m_bPaused )
{
- ALint sourceState;
- alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
- if ( m_bActive || sourceState == AL_PLAYING )
+ ALint sourceState[2];
+ alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]);
+ alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);
+ if ( m_bActive || sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING)
return true;
}
@@ -449,9 +1087,12 @@ void CStream::Pause()
{
if ( !HasSource() ) return;
ALint sourceState = AL_PAUSED;
- alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
- if (sourceState != AL_PAUSED )
- alSourcePause(m_alSource);
+ alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
+ if (sourceState != AL_PAUSED)
+ alSourcePause(m_pAlSources[0]);
+ alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);
+ if (sourceState != AL_PAUSED)
+ alSourcePause(m_pAlSources[1]);
}
void CStream::SetPause(bool bPause)
@@ -473,19 +1114,21 @@ void CStream::SetPause(bool bPause)
void CStream::SetPitch(float pitch)
{
if ( !HasSource() ) return;
- alSourcef(m_alSource, AL_PITCH, pitch);
+ alSourcef(m_pAlSources[0], AL_PITCH, pitch);
+ alSourcef(m_pAlSources[1], AL_PITCH, pitch);
}
void CStream::SetGain(float gain)
{
if ( !HasSource() ) return;
- alSourcef(m_alSource, AL_GAIN, gain);
+ alSourcef(m_pAlSources[0], AL_GAIN, gain);
+ alSourcef(m_pAlSources[1], AL_GAIN, gain);
}
-void CStream::SetPosition(float x, float y, float z)
+void CStream::SetPosition(int i, float x, float y, float z)
{
if ( !HasSource() ) return;
- alSource3f(m_alSource, AL_POSITION, x, y, z);
+ alSource3f(m_pAlSources[i], AL_POSITION, x, y, z);
}
void CStream::SetVolume(uint32 nVol)
@@ -496,8 +1139,13 @@ void CStream::SetVolume(uint32 nVol)
void CStream::SetPan(uint8 nPan)
{
+ m_nPan = clamp((int8)nPan - 63, 0, 63);
+ SetPosition(0, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));
+
+ m_nPan = clamp((int8)nPan + 64, 64, 127);
+ SetPosition(1, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));
+
m_nPan = nPan;
- SetPosition((nPan - 63)/64.0f, 0.0f, Sqrt(1.0f-SQR((nPan-63)/64.0f)));
}
void CStream::SetPosMS(uint32 nPos)
@@ -514,10 +1162,10 @@ uint32 CStream::GetPosMS()
ALint offset;
//alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset);
- alGetSourcei(m_alSource, AL_BYTE_OFFSET, &offset);
+ alGetSourcei(m_pAlSources[0], AL_BYTE_OFFSET, &offset);
return m_pSoundFile->Tell()
- - m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS-1)) / m_pSoundFile->GetChannels()
+ - m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS/2-1)) / m_pSoundFile->GetChannels()
+ m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()) / m_pSoundFile->GetChannels();
}
@@ -527,33 +1175,41 @@ uint32 CStream::GetLengthMS()
return m_pSoundFile->GetLength();
}
-bool CStream::FillBuffer(ALuint alBuffer)
+bool CStream::FillBuffer(ALuint *alBuffer)
{
if ( !HasSource() )
return false;
if ( !IsOpened() )
return false;
- if ( !(alBuffer != AL_NONE && alIsBuffer(alBuffer)) )
+ if ( !(alBuffer[0] != AL_NONE && alIsBuffer(alBuffer[0])) )
+ return false;
+ if ( !(alBuffer[1] != AL_NONE && alIsBuffer(alBuffer[1])) )
return false;
uint32 size = m_pSoundFile->Decode(m_pBuffer);
if( size == 0 )
return false;
- alBufferData(alBuffer, m_pSoundFile->GetChannels() == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
- m_pBuffer, size, m_pSoundFile->GetSampleRate());
-
+ uint32 channelSize = size / m_pSoundFile->GetChannels();
+
+ alBufferData(alBuffer[0], AL_FORMAT_MONO16, m_pBuffer, channelSize, m_pSoundFile->GetSampleRate());
+ // TODO: use just one buffer if we play mono
+ if (m_pSoundFile->GetChannels() == 1)
+ alBufferData(alBuffer[1], AL_FORMAT_MONO16, m_pBuffer, channelSize, m_pSoundFile->GetSampleRate());
+ else
+ alBufferData(alBuffer[1], AL_FORMAT_MONO16, (uint8*)m_pBuffer + channelSize, channelSize, m_pSoundFile->GetSampleRate());
return true;
}
int32 CStream::FillBuffers()
{
int32 i = 0;
- for ( i = 0; i < NUM_STREAMBUFFERS; i++ )
+ for ( i = 0; i < NUM_STREAMBUFFERS/2; i++ )
{
- if ( !FillBuffer(m_alBuffers[i]) )
+ if ( !FillBuffer(&m_alBuffers[i*2]) )
break;
- alSourceQueueBuffers(m_alSource, 1, &m_alBuffers[i]);
+ alSourceQueueBuffers(m_pAlSources[0], 1, &m_alBuffers[i*2]);
+ alSourceQueueBuffers(m_pAlSources[1], 1, &m_alBuffers[i*2+1]);
}
return i;
@@ -563,12 +1219,15 @@ void CStream::ClearBuffers()
{
if ( !HasSource() ) return;
- ALint buffersQueued;
- alGetSourcei(m_alSource, AL_BUFFERS_QUEUED, &buffersQueued);
+ ALint buffersQueued[2];
+ alGetSourcei(m_pAlSources[0], AL_BUFFERS_QUEUED, &buffersQueued[0]);
+ alGetSourcei(m_pAlSources[1], AL_BUFFERS_QUEUED, &buffersQueued[1]);
ALuint value;
- while (buffersQueued--)
- alSourceUnqueueBuffers(m_alSource, 1, &value);
+ while (buffersQueued[0]--)
+ alSourceUnqueueBuffers(m_pAlSources[0], 1, &value);
+ while (buffersQueued[1]--)
+ alSourceUnqueueBuffers(m_pAlSources[1], 1, &value);
}
bool CStream::Setup()
@@ -576,7 +1235,6 @@ bool CStream::Setup()
if ( IsOpened() )
{
m_pSoundFile->Seek(0);
- alSourcei(m_alSource, AL_SOURCE_RELATIVE, AL_TRUE);
//SetPosition(0.0f, 0.0f, 0.0f);
SetPitch(1.0f);
//SetPan(m_nPan);
@@ -592,17 +1250,29 @@ void CStream::SetPlay(bool state)
if ( state )
{
ALint sourceState = AL_PLAYING;
- alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
+ alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_PLAYING )
- alSourcePlay(m_alSource);
+ alSourcePlay(m_pAlSources[0]);
+
+ sourceState = AL_PLAYING;
+ alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);
+ if (sourceState != AL_PLAYING)
+ alSourcePlay(m_pAlSources[1]);
+
m_bActive = true;
}
else
{
ALint sourceState = AL_STOPPED;
- alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
+ alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_STOPPED )
- alSourceStop(m_alSource);
+ alSourceStop(m_pAlSources[0]);
+
+ sourceState = AL_STOPPED;
+ alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);
+ if (sourceState != AL_STOPPED)
+ alSourceStop(m_pAlSources[1]);
+
m_bActive = false;
}
}
@@ -633,35 +1303,51 @@ void CStream::Update()
if ( !m_bPaused )
{
- ALint sourceState;
- ALint buffersProcessed = 0;
+ ALint sourceState[2];
+ ALint buffersProcessed[2] = { 0, 0 };
- alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
- alGetSourcei(m_alSource, AL_BUFFERS_PROCESSED, &buffersProcessed);
+ // Relying a lot on left buffer states in here
+
+ do
+ {
+ //alSourcef(m_pAlSources[0], AL_ROLLOFF_FACTOR, 0.0f);
+ alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]);
+ alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);
+ //alSourcef(m_pAlSources[1], AL_ROLLOFF_FACTOR, 0.0f);
+ alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);
+ alGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]);
+ } while (buffersProcessed[0] != buffersProcessed[1]);
ALint looping = AL_FALSE;
- alGetSourcei(m_alSource, AL_LOOPING, &looping);
+ alGetSourcei(m_pAlSources[0], AL_LOOPING, &looping);
if ( looping == AL_TRUE )
{
TRACE("stream set looping");
- alSourcei(m_alSource, AL_LOOPING, AL_TRUE);
+ alSourcei(m_pAlSources[0], AL_LOOPING, AL_TRUE);
+ alSourcei(m_pAlSources[1], AL_LOOPING, AL_TRUE);
}
- while( buffersProcessed-- )
+ assert(buffersProcessed[0] == buffersProcessed[1]);
+
+ while( buffersProcessed[0]-- )
{
- ALuint buffer;
+ ALuint buffer[2];
- alSourceUnqueueBuffers(m_alSource, 1, &buffer);
+ alSourceUnqueueBuffers(m_pAlSources[0], 1, &buffer[0]);
+ alSourceUnqueueBuffers(m_pAlSources[1], 1, &buffer[1]);
- if ( m_bActive && FillBuffer(buffer) )
- alSourceQueueBuffers(m_alSource, 1, &buffer);
+ if (m_bActive && FillBuffer(buffer))
+ {
+ alSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]);
+ alSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]);
+ }
}
- if ( sourceState != AL_PLAYING )
+ if ( sourceState[0] != AL_PLAYING )
{
- alGetSourcei(m_alSource, AL_BUFFERS_PROCESSED, &buffersProcessed);
- SetPlay(buffersProcessed!=0);
+ alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);
+ SetPlay(buffersProcessed[0]!=0);
}
}
}
diff --git a/src/audio/oal/stream.h b/src/audio/oal/stream.h
index 2476abcc..bcbc5e54 100644
--- a/src/audio/oal/stream.h
+++ b/src/audio/oal/stream.h
@@ -3,7 +3,7 @@
#ifdef AUDIO_OAL
#include <AL/al.h>
-#define NUM_STREAMBUFFERS 4
+#define NUM_STREAMBUFFERS 8
class IDecoder
{
@@ -57,7 +57,7 @@ public:
class CStream
{
char m_aFilename[128];
- ALuint &m_alSource;
+ ALuint *m_pAlSources;
ALuint (&m_alBuffers)[NUM_STREAMBUFFERS];
bool m_bPaused;
@@ -73,20 +73,20 @@ class CStream
IDecoder *m_pSoundFile;
bool HasSource();
- void SetPosition(float x, float y, float z);
+ void SetPosition(int i, float x, float y, float z);
void SetPitch(float pitch);
void SetGain(float gain);
void Pause();
void SetPlay(bool state);
- bool FillBuffer(ALuint alBuffer);
+ bool FillBuffer(ALuint *alBuffer);
int32 FillBuffers();
void ClearBuffers();
public:
static void Initialise();
static void Terminate();
- CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUFFERS]);
+ CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate = 32000);
~CStream();
void Delete();
diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp
index 80f19e50..0d82d552 100644
--- a/src/audio/sampman_oal.cpp
+++ b/src/audio/sampman_oal.cpp
@@ -102,7 +102,7 @@ CChannel aChannel[MAXCHANNELS+MAX2DCHANNELS];
uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS];
uint32 nStreamLength[TOTAL_STREAMED_SOUNDS];
-ALuint ALStreamSources[MAX_STREAMS];
+ALuint ALStreamSources[MAX_STREAMS][2];
ALuint ALStreamBuffers[MAX_STREAMS][NUM_STREAMBUFFERS];
struct tMP3Entry
@@ -245,9 +245,9 @@ release_existing()
if (stream)
stream->ProviderTerm();
- alDeleteSources(1, &ALStreamSources[i]);
alDeleteBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);
}
+ alDeleteSources(MAX_STREAMS*2, ALStreamSources[0]);
CChannel::DestroyChannels();
@@ -287,7 +287,10 @@ set_new_provider(int index)
//TODO:
_maxSamples = MAXCHANNELS;
- ALCint attr[] = {ALC_FREQUENCY,MAX_FREQ,0};
+ ALCint attr[] = {ALC_FREQUENCY,MAX_FREQ,
+ ALC_MONO_SOURCES, MAX_STREAMS * 2 + MAXCHANNELS,
+ 0,
+ };
ALDevice = alcOpenDevice(providers[index].id);
ASSERT(ALDevice != NULL);
@@ -319,11 +322,17 @@ set_new_provider(int index)
alGenAuxiliaryEffectSlots(1, &ALEffectSlot);
alGenEffects(1, &ALEffect);
}
-
+
+ alGenSources(MAX_STREAMS*2, ALStreamSources[0]);
for ( int32 i = 0; i < MAX_STREAMS; i++ )
{
- alGenSources(1, &ALStreamSources[i]);
alGenBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);
+ alSourcei(ALStreamSources[i][0], AL_SOURCE_RELATIVE, AL_TRUE);
+ alSource3f(ALStreamSources[i][0], AL_POSITION, 0.0f, 0.0f, 0.0f);
+ alSourcef(ALStreamSources[i][0], AL_GAIN, 1.0f);
+ alSourcei(ALStreamSources[i][1], AL_SOURCE_RELATIVE, AL_TRUE);
+ alSource3f(ALStreamSources[i][1], AL_POSITION, 0.0f, 0.0f, 0.0f);
+ alSourcef(ALStreamSources[i][1], AL_GAIN, 1.0f);
CStream *stream = aStream[i];
if (stream)
@@ -384,6 +393,12 @@ set_new_provider(int index)
return false;
}
+static bool
+IsThisTrackAt16KHz(uint32 track)
+{
+ return track == STREAMED_SOUND_RADIO_KCHAT || track == STREAMED_SOUND_RADIO_VCPR || track == STREAMED_SOUND_RADIO_POLICE;
+}
+
cSampleManager::cSampleManager(void)
{
;
@@ -989,7 +1004,7 @@ cSampleManager::Initialise(void)
for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )
{
- aStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0]);
+ aStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0], IsThisTrackAt16KHz(i) ? 16000 : 32000);
if ( aStream[0] && aStream[0]->IsOpened() )
{
@@ -1542,10 +1557,11 @@ cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)
nChannelVolume[nChannel] = vol;
- if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE
- && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_FINALE )
- {
- nChannelVolume[nChannel] = vol / 4;
+ if (MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE ) {
+ if (MusicManager.GetCurrentTrack() == STREAMED_SOUND_CUTSCENE_FINALE)
+ nChannelVolume[nChannel] = 0;
+ else
+ nChannelVolume[nChannel] >>= 2;
}
// no idea, does this one looks like a bug or it's SetChannelVolume ?
@@ -1671,7 +1687,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
strcpy(filename, StreamedNameTable[nFile]);
- CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
+ CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;
@@ -1746,7 +1762,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
nFile = 0;
strcat(filename, StreamedNameTable[nFile]);
- CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
+ CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;
@@ -1770,12 +1786,12 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
}
if (mp3->pLinkPath != NULL)
- aStream[nStream] = new CStream(mp3->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream]);
+ aStream[nStream] = new CStream(mp3->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
else {
strcpy(filename, _mp3DirectoryPath);
strcat(filename, mp3->aFilename);
- aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
+ aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
}
if (aStream[nStream]->IsOpened()) {
@@ -1802,7 +1818,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
{
nFile = 0;
strcat(filename, StreamedNameTable[nFile]);
- CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
+ CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;
@@ -1826,7 +1842,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
}
if (e->pLinkPath != NULL)
- aStream[nStream] = new CStream(e->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream]);
+ aStream[nStream] = new CStream(e->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
else {
strcpy(filename, _mp3DirectoryPath);
strcat(filename, e->aFilename);
@@ -1859,7 +1875,7 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
strcpy(filename, StreamedNameTable[nFile]);
- CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
+ CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
ASSERT(stream != NULL);
aStream[nStream] = stream;
diff --git a/src/collision/ColStore.cpp b/src/collision/ColStore.cpp
index 192c373d..f1e695fe 100644
--- a/src/collision/ColStore.cpp
+++ b/src/collision/ColStore.cpp
@@ -11,8 +11,13 @@
#include "Frontend.h"
#include "Physical.h"
#include "ColStore.h"
+#include "VarConsole.h"
+#include "Pools.h"
CPool<ColDef,ColDef> *CColStore::ms_pColPool;
+#ifndef MASTER
+bool bDispColInMem;
+#endif
void
CColStore::Initialise(void)
@@ -20,6 +25,9 @@ CColStore::Initialise(void)
if(ms_pColPool == nil)
ms_pColPool = new CPool<ColDef,ColDef>(COLSTORESIZE, "CollisionFiles");
AddColSlot("generic"); // slot 0. not streamed
+#ifndef MASTER
+ VarConsole.Add("Display collision in memory", &bDispColInMem, true);
+#endif
}
void
@@ -177,7 +185,18 @@ CColStore::LoadCollision(const CVector2D &pos)
wantThisOne = true;
}else{
for (int j = 0; j < MAX_CLEANUP; j++) {
- CPhysical* pEntity = CTheScripts::MissionCleanup.DoesThisEntityWaitForCollision(j);
+ CPhysical* pEntity = nil;
+ cleanup_entity_struct* pCleanup = &CTheScripts::MissionCleanUp.m_sEntities[i];
+ if (pCleanup->type == CLEANUP_CAR) {
+ pEntity = CPools::GetVehiclePool()->GetAt(pCleanup->id);
+ if (!pEntity || pEntity->GetStatus() == STATUS_WRECKED)
+ continue;
+ }
+ else if (pCleanup->type == CLEANUP_CHAR) {
+ pEntity = CPools::GetPedPool()->GetAt(pCleanup->id);
+ if (!pEntity || ((CPed*)pEntity)->DyingOrDead())
+ continue;
+ }
if (pEntity && !pEntity->bDontLoadCollision && !pEntity->bIsFrozen) {
if (GetBoundingBox(i).IsPointInside(pEntity->GetPosition(), -80.0f))
wantThisOne = true;
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index 779041cc..72053f8d 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -23,6 +23,7 @@
#include "Vehicle.h"
#include "Wanted.h"
#include "World.h"
+#include "VarConsole.h"
//--MIAMI: file done
@@ -129,8 +130,15 @@ int32 hGarages = AEHANDLE_NONE;
CGarage CGarages::aGarages[NUM_GARAGES];
bool CGarages::bCamShouldBeOutisde;
+#ifndef MASTER
+bool bPrintNearestObject;
+#endif
+
void CGarages::Init(void)
{
+#ifndef MASTER
+ VarConsole.Add("Print nearest object", &bPrintNearestObject, true);
+#endif
CrushedCarId = -1;
NumGarages = 0;
MessageEndTime = 0;
diff --git a/src/control/Garages.h b/src/control/Garages.h
index 46ae1542..3d12d4a2 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -93,6 +93,7 @@ VALIDATE_SIZE(CStoredCar, 0x28);
class CGarage
{
+public:
uint8 m_eGarageType;
uint8 m_eGarageState;
uint8 m_nMaxStoredCars;
@@ -189,9 +190,6 @@ class CGarage
int32 FindMaxNumStoredCarsForGarage() { return Min(NUM_GARAGE_STORED_CARS, m_nMaxStoredCars); }
- friend class CGarages;
- friend class cAudioManager;
- friend class CCamera;
};
class CGarages
@@ -199,6 +197,7 @@ class CGarages
enum {
MESSAGE_LENGTH = 8,
};
+public:
static int32 BankVansCollected;
static bool BombsAreFree;
static bool RespraysAreFree;
@@ -218,7 +217,6 @@ class CGarages
static CStoredCar aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][NUM_GARAGE_STORED_CARS];
static bool bCamShouldBeOutisde;
-public:
static void Init(void);
#ifndef PS2
static void Shutdown(void);
@@ -259,7 +257,6 @@ public:
static void SetFreeResprays(bool bValue) { RespraysAreFree = bValue; }
static void SetMaxNumStoredCarsForGarage(int16 garage, uint8 num) { aGarages[garage].m_nMaxStoredCars = num; }
-private:
static bool IsCarSprayable(CVehicle*);
static float FindDoorHeightForMI(int32);
static void CloseHideOutGaragesBeforeSave(void);
@@ -296,7 +293,4 @@ private:
}
static bool IsThisGarageTypeSafehouse(uint8 type) { return FindSafeHouseIndexForGarageType(type) >= 0; }
- friend class cAudioManager;
- friend class CReplay;
- friend class CGarage;
};
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 1c68cad9..37a54999 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1508,12 +1508,12 @@ void CReplay::RestoreStuffFromMem(void)
tmp1.UpdateRW();
}
else if (mi == MI_HUNTER) {
- RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);
- RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);
}
else if (vehicle->IsRealHeli()) {
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RF]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);
RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);
}
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 4e34c4b2..a453c077 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -85,7 +85,7 @@ uint16 CTheScripts::NumScriptDebugLines;
uint16 CTheScripts::NumberOfIntroRectanglesThisFrame;
uint16 CTheScripts::NumberOfIntroTextLinesThisFrame;
uint8 CTheScripts::UseTextCommands;
-CMissionCleanup CTheScripts::MissionCleanup;
+CMissionCleanup CTheScripts::MissionCleanUp;
CUpsideDownCarCheck CTheScripts::UpsideDownCars;
CStuckCarCheck CTheScripts::StuckCars;
uint16 CTheScripts::CommandsExecuted;
@@ -1751,19 +1751,6 @@ void CMissionCleanup::AddEntityToList(int32 id, uint8 type)
m_nCount++;
}
-// done(LCS)
-static void PossiblyWakeThisEntity(CPhysical* pEntity, bool ifColLoaded = false)
-{
- if (!pEntity->bIsStaticWaitingForCollision)
- return;
- if (!ifColLoaded || CColStore::HasCollisionLoaded(pEntity->GetPosition())) {
- pEntity->bIsStaticWaitingForCollision = false;
- if (!pEntity->GetIsStatic())
- pEntity->AddToMovingList();
- }
-}
-
-// done(LCS)
void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
{
for (int i = 0; i < MAX_CLEANUP; i++){
@@ -1771,23 +1758,38 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
switch (m_sEntities[i].type) {
case CLEANUP_CAR:
{
- CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
- if (v)
- PossiblyWakeThisEntity(v);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (pVehicle) {
+ if (pVehicle->bIsStaticWaitingForCollision) {
+ pVehicle->bIsStaticWaitingForCollision = false;
+ if (!pVehicle->GetIsStatic())
+ pVehicle->AddToMovingList();
+ }
+ }
break;
}
case CLEANUP_CHAR:
{
- CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
- if (p)
- PossiblyWakeThisEntity(p);
+ CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (pPed) {
+ if (pPed->bIsStaticWaitingForCollision) {
+ pPed->bIsStaticWaitingForCollision = false;
+ if (!pPed->GetIsStatic())
+ pPed->AddToMovingList();
+ }
+ }
break;
}
case CLEANUP_OBJECT:
{
- CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
- if (o)
- PossiblyWakeThisEntity(o);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
+ if (pObject) {
+ if (pObject->bIsStaticWaitingForCollision) {
+ pObject->bIsStaticWaitingForCollision = false;
+ if (!pObject->GetIsStatic())
+ pObject->AddToMovingList();
+ }
+ }
break;
}
default:
@@ -1895,23 +1897,6 @@ void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObjects()
}
}
-// TODO(LCS)
-CPhysical* CMissionCleanup::DoesThisEntityWaitForCollision(int i)
-{
- if (m_sEntities[i].type == CLEANUP_CAR) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
- if (pVehicle && pVehicle->GetStatus() != STATUS_WRECKED)
- return pVehicle;
- }
- else if (m_sEntities[i].type == CLEANUP_CHAR) {
- CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
- if (pPed && !pPed->DyingOrDead())
- return pPed;
- }
- return nil;
-}
-
-// done(LCS) except TODO
void CMissionCleanup::Process()
{
CPopulation::m_AllRandomPedsThisType = -1;
@@ -2012,13 +1997,18 @@ void CUpsideDownCarCheck::Init()
// done(LCS)
bool CUpsideDownCarCheck::IsCarUpsideDown(int32 id)
{
- CVehicle* v = CPools::GetVehiclePool()->GetAt(id);
- return v->GetUp().z <= -0.97f &&
- v->GetMoveSpeed().Magnitude() < 0.01f &&
- v->GetTurnSpeed().Magnitude() < 0.02f;
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(id);
+ return IsCarUpsideDown(pVehicle);
+}
+
+bool CUpsideDownCarCheck::IsCarUpsideDown(CVehicle* pVehicle)
+{
+ assert(pVehicle);
+ return pVehicle->GetUp().z <= UPSIDEDOWN_UP_THRESHOLD &&
+ pVehicle->GetMoveSpeed().Magnitude() < UPSIDEDOWN_MOVE_SPEED_THRESHOLD &&
+ pVehicle->GetTurnSpeed().Magnitude() < UPSIDEDOWN_TURN_SPEED_THRESHOLD;
}
-// done(LCS)
void CUpsideDownCarCheck::UpdateTimers()
{
uint32 timeStep = CTimer::GetTimeStepInMilliseconds();
@@ -2040,7 +2030,7 @@ void CUpsideDownCarCheck::UpdateTimers()
bool CUpsideDownCarCheck::AreAnyCarsUpsideDown()
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
- if (m_sCars[i].m_nVehicleIndex >= 0 && m_sCars[i].m_nUpsideDownTimer > 1000)
+ if (m_sCars[i].m_nVehicleIndex >= 0 && m_sCars[i].m_nUpsideDownTimer > UPSIDEDOWN_TIMER_THRESHOLD)
return true;
}
return false;
@@ -2052,8 +2042,10 @@ void CUpsideDownCarCheck::AddCarToCheck(int32 id)
uint16 index = 0;
while (index < MAX_UPSIDEDOWN_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
index++;
+#ifdef FIX_BUGS
if (index >= MAX_UPSIDEDOWN_CAR_CHECKS)
return;
+#endif
m_sCars[index].m_nVehicleIndex = id;
m_sCars[index].m_nUpsideDownTimer = 0;
}
@@ -2074,7 +2066,7 @@ bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex == id)
- return m_sCars[i].m_nUpsideDownTimer > 1000;
+ return m_sCars[i].m_nUpsideDownTimer > UPSIDEDOWN_TIMER_THRESHOLD;
}
return false;
}
@@ -2124,7 +2116,10 @@ void CStuckCarCheck::AddCarToCheck(int32 id, float radius, uint32 time)
int index = 0;
while (index < MAX_STUCK_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
index++;
- /* Would be nice to return if index >= MAX_STUCK_CAR_CHECKS... */
+#ifdef FIX_BUGS
+ if (index >= MAX_STUCK_CAR_CHECKS)
+ return;
+#endif
m_sCars[index].m_nVehicleIndex = id;
m_sCars[index].m_vecPos = pv->GetPosition();
m_sCars[index].m_nLastCheck = CTimer::GetTimeInMilliseconds();
@@ -2356,7 +2351,7 @@ void CTheScripts::Init()
ScriptsArray[i].Init();
ScriptsArray[i].AddScriptToList(&pIdleScripts);
}
- MissionCleanup.Init();
+ MissionCleanUp.Init();
UpsideDownCars.Init();
StuckCars.Init();
CFileMgr::SetDir("data");
@@ -2484,7 +2479,7 @@ void CTheScripts::Process()
float timeStep = CTimer::GetTimeStepInMilliseconds();
UpsideDownCars.UpdateTimers();
StuckCars.Process();
- MissionCleanup.CheckIfCollisionHasLoadedForMissionObjects();
+ MissionCleanUp.CheckIfCollisionHasLoadedForMissionObjects();
DrawScriptSpheres();
if (FailCurrentMission)
--FailCurrentMission;
@@ -3808,7 +3803,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_DELETE_CHAR:
@@ -3817,7 +3812,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
CTheScripts::RemoveThisPed(ped);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_CHAR_WANDER_DIR:
@@ -4038,7 +4033,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ScriptParams[0] = handle;
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);
return 0;
}
case COMMAND_DELETE_CAR:
@@ -4051,7 +4046,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
delete car;
}
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_CAR_GOTO_COORDINATES:
@@ -4171,9 +4166,9 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
car->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];
if (missionRetryScriptIndex == 40 && car->GetModelIndex() == MI_CHEETAH) // Turismo
car->AutoPilot.m_nCruiseSpeed = 8 * car->AutoPilot.m_nCruiseSpeed / 10;
- car->AutoPilot.m_nCruiseSpeed = Min(car->AutoPilot.m_nCruiseSpeed, 60.0f * car->pHandling->Transmission.fUnkMaxVelocity);
+ car->AutoPilot.m_nCruiseSpeed = Min(car->AutoPilot.m_nCruiseSpeed, 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);
#else
- car->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fUnkMaxVelocity);
+ car->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);
#endif
return 0;
}
@@ -4366,7 +4361,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
if (!m_bIsMissionScript)
return 0;
- CTheScripts::MissionCleanup.Process();
+ CTheScripts::MissionCleanUp.Process();
return 0;
}
case COMMAND_STORE_CAR_CHAR_IS_IN:
@@ -4389,7 +4384,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
- CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
}
@@ -4400,14 +4395,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CCarCtrl::NumMissionCars++;
CCarCtrl::NumRandomCars--;
CTheScripts::StoreVehicleWasRandom = true;
- CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case PARKED_VEHICLE:
pCurrent->VehicleCreatedBy = MISSION_VEHICLE;
CCarCtrl::NumMissionCars++;
CCarCtrl::NumParkedCars--;
CTheScripts::StoreVehicleWasRandom = true;
- CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case MISSION_VEHICLE:
case PERMANENT_VEHICLE:
@@ -4440,7 +4435,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
- CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
}
@@ -4451,14 +4446,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CCarCtrl::NumMissionCars++;
CCarCtrl::NumRandomCars--;
CTheScripts::StoreVehicleWasRandom = true;
- CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case PARKED_VEHICLE:
pCurrent->VehicleCreatedBy = MISSION_VEHICLE;
CCarCtrl::NumMissionCars++;
CCarCtrl::NumParkedCars--;
CTheScripts::StoreVehicleWasRandom = true;
- CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
break;
case MISSION_VEHICLE:
case PERMANENT_VEHICLE:
@@ -4607,7 +4602,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_DELETE_OBJECT:
@@ -4620,7 +4615,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
delete pObj;
}
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_ADD_SCORE:
@@ -4836,7 +4831,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_WARP_PLAYER_FROM_CAR_TO_COORD:
@@ -4886,81 +4881,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
return -1;
}
-
-void CRunningScript::Save(uint8*& buf)
-{
-#ifdef COMPATIBLE_SAVES
- SkipSaveBuf(buf, 8);
- for (int i = 0; i < 8; i++)
- WriteSaveBuf<char>(buf, m_abScriptName[i]);
- WriteSaveBuf<uint32>(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);
-#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_bIsActive);
- WriteSaveBuf<bool>(buf, m_bCondResult);
- WriteSaveBuf<bool>(buf, m_bIsMissionScript);
- WriteSaveBuf<bool>(buf, m_bSkipWakeTime);
- 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);
-#else
- WriteSaveBuf(buf, *this);
-#endif
-}
-
-void CRunningScript::Load(uint8*& buf)
-{
-#ifdef COMPATIBLE_SAVES
- SkipSaveBuf(buf, 8);
- for (int i = 0; i < 8; i++)
- m_abScriptName[i] = ReadSaveBuf<char>(buf);
- m_nIp = ReadSaveBuf<uint32>(buf);
-#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++)
- m_anStack[i] = ReadSaveBuf<uint32>(buf);
- m_nStackPointer = ReadSaveBuf<uint16>(buf);
- SkipSaveBuf(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++)
- m_anLocalVariables[i] = ReadSaveBuf<int32>(buf);
- m_bIsActive = ReadSaveBuf<bool>(buf);
- m_bCondResult = ReadSaveBuf<bool>(buf);
- m_bIsMissionScript = ReadSaveBuf<bool>(buf);
- m_bSkipWakeTime = ReadSaveBuf<bool>(buf);
- m_nWakeTime = ReadSaveBuf<uint32>(buf);
- m_nAndOrState = ReadSaveBuf<uint16>(buf);
- m_bNotFlag = ReadSaveBuf<bool>(buf);
- m_bDeatharrestEnabled = ReadSaveBuf<bool>(buf);
- m_bDeatharrestExecuted = ReadSaveBuf<bool>(buf);
- m_bMissionFlag = ReadSaveBuf<bool>(buf);
- SkipSaveBuf(buf, 2);
-#else
- CRunningScript* n = next;
- CRunningScript* p = prev;
- *this = ReadSaveBuf<CRunningScript>(buf);
- next = n;
- prev = p;
-#endif
-}
-
#ifdef MISSION_REPLAY
bool CRunningScript::CanAllowMissionReplay()
@@ -4995,7 +4915,7 @@ void RetryMission(int type, int unk)
else if (type == 2) {
doingMissionRetry = false;
AllowMissionReplay = 6;
- CTheScripts::MissionCleanup.Process();
+ CTheScripts::MissionCleanUp.Process();
}
}
diff --git a/src/control/Script.h b/src/control/Script.h
index 2690b4ff..f35d0261 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -1,5 +1,6 @@
#pragma once
#include "common.h"
+#include "Font.h"
#include "Ped.h"
#include "PedType.h"
#include "Text.h"
@@ -20,26 +21,31 @@ extern int32 ScriptParams[32];
void FlushLog();
#define script_assert(_Expression) FlushLog(); assert(_Expression);
-#define PICKUP_PLACEMENT_OFFSET 0.5f
-#define PED_FIND_Z_OFFSET 5.0f
-#define COP_PED_FIND_Z_OFFSET 10.0f
+#define PICKUP_PLACEMENT_OFFSET (0.5f)
+#define PED_FIND_Z_OFFSET (5.0f)
+#define COP_PED_FIND_Z_OFFSET (10.0f)
-#define SPHERE_MARKER_R 252
-#define SPHERE_MARKER_G 138
-#define SPHERE_MARKER_B 242
-#define SPHERE_MARKER_A 228
+#define UPSIDEDOWN_UP_THRESHOLD (-0.97f)
+#define UPSIDEDOWN_MOVE_SPEED_THRESHOLD (0.01f)
+#define UPSIDEDOWN_TURN_SPEED_THRESHOLD (0.02f)
+#define UPSIDEDOWN_TIMER_THRESHOLD (1000)
+
+#define SPHERE_MARKER_R (252)
+#define SPHERE_MARKER_G (138)
+#define SPHERE_MARKER_B (242)
+#define SPHERE_MARKER_A (228)
#define SPHERE_MARKER_PULSE_PERIOD 2048
#define SPHERE_MARKER_PULSE_FRACTION 0.1f
#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
-#define METERS_IN_FOOT 0.3048f
-#define FEET_IN_METER 3.28084f
+#define METERS_IN_FOOT (0.3048f)
+#define FEET_IN_METER (3.28084f)
#else
-#define METERS_IN_FOOT 0.3f
-#define FEET_IN_METER 3.33f
+#define METERS_IN_FOOT (0.3f)
+#define FEET_IN_METER (3.33f)
#endif
-#define KEY_LENGTH_IN_SCRIPT 8
+#define KEY_LENGTH_IN_SCRIPT (8)
//#define GTA_SCRIPT_COLLECTIVE
@@ -94,12 +100,12 @@ struct intro_text_line
m_bCentered = false;
m_bBackground = false;
m_bBackgroundOnly = false;
- m_fWrapX = 182.0f; /* TODO: scaling as bugfix */
- m_fCenterSize = 640.0f; /* --||-- */
+ m_fWrapX = 182.0f;
+ m_fCenterSize = DEFAULT_SCREEN_WIDTH;
m_sBackgroundColor = CRGBA(128, 128, 128, 128);
m_bTextProportional = true;
m_bTextBeforeFade = false;
- m_nFont = 2; /* enum? */
+ m_nFont = FONT_STANDARD;
m_fAtX = 0.0f;
m_fAtY = 0.0f;
memset(&m_Text, 0, sizeof(m_Text));
@@ -148,10 +154,10 @@ enum {
class CMissionCleanup
{
+public:
cleanup_entity_struct m_sEntities[MAX_CLEANUP];
uint8 m_nCount;
-public:
CMissionCleanup();
void Init();
@@ -160,10 +166,9 @@ public:
void RemoveEntityFromList(int32, uint8);
void Process();
void CheckIfCollisionHasLoadedForMissionObjects();
- CPhysical* DoesThisEntityWaitForCollision(int i);
};
-struct CUpsideDownCarCheckEntry
+struct upsidedown_car_data
{
int32 m_nVehicleIndex;
uint32 m_nUpsideDownTimer;
@@ -171,11 +176,12 @@ struct CUpsideDownCarCheckEntry
class CUpsideDownCarCheck
{
- CUpsideDownCarCheckEntry m_sCars[MAX_UPSIDEDOWN_CAR_CHECKS];
+ upsidedown_car_data m_sCars[MAX_UPSIDEDOWN_CAR_CHECKS];
public:
void Init();
bool IsCarUpsideDown(int32);
+ bool IsCarUpsideDown(CVehicle*);
void UpdateTimers();
bool AreAnyCarsUpsideDown();
void AddCarToCheck(int32);
@@ -193,7 +199,7 @@ struct stuck_car_data
bool m_bStuck;
stuck_car_data() { }
- inline void Reset();
+ void Reset();
};
class CStuckCarCheck
@@ -259,7 +265,7 @@ enum {
enum {
MAX_NUM_SCRIPTS = 128,
- MAX_NUM_INTRO_TEXT_LINES = 2,
+ MAX_NUM_INTRO_TEXT_LINES = 48,
MAX_NUM_INTRO_RECTANGLES = 16,
MAX_NUM_SCRIPT_SRPITES = 16,
MAX_NUM_SCRIPT_SPHERES = 16,
@@ -273,6 +279,7 @@ enum {
class CTheScripts
{
+public:
static uint8 ScriptSpace[SIZE_SCRIPT_SPACE];
static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS];
static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
@@ -286,7 +293,7 @@ class CTheScripts
static CStoredLine aStoredLines[MAX_NUM_STORED_LINES];
static bool DbgFlag;
static uint32 OnAMissionFlag;
- static CMissionCleanup MissionCleanup;
+ static CMissionCleanup MissionCleanUp;
static CStuckCarCheck StuckCars;
static CUpsideDownCarCheck UpsideDownCars;
static int32 StoreVehicleIndex;
@@ -321,11 +328,10 @@ class CTheScripts
static int AllowedCollision[MAX_ALLOWED_COLLISIONS];
#endif
-public:
static bool bPlayerIsInTheStatium;
static uint8 RiotIntensity;
static bool bPlayerHasMetDebbieHarry;
-public:
+
static void Init();
static void Process();
@@ -379,8 +385,6 @@ public:
return Read4BytesFromScript(&tmp);
}
-private:
-
static CRunningScript* StartNewScript(uint32);
static void CleanUpThisVehicle(CVehicle*);
@@ -438,18 +442,11 @@ public:
static void SetObjectiveForAllPedsInCollective(int, eObjective);
#endif
- friend class CRunningScript;
- friend class CHud;
- friend void CMissionCleanup::Process();
- friend class CColStore;
-#ifdef FIX_BUGS
- friend void RetryMission(int, int);
-#endif
};
enum {
- MAX_STACK_DEPTH = 6, // 4 PS2
+ MAX_STACK_DEPTH = 6,
NUM_LOCAL_VARS = 16,
NUM_TIMERS = 2
};
@@ -476,6 +473,7 @@ class CRunningScript
ORS_8
};
+public:
CRunningScript* next;
CRunningScript* prev;
char m_abScriptName[8];
@@ -514,7 +512,6 @@ public:
static const uint32 nSaveStructSize;
-private:
void CollectParameters(uint32*, int16);
int32 CollectNextParameterWithoutIncreasingPC(uint32);
int32* GetPointerToScriptVariable(uint32*, int16);
@@ -582,7 +579,6 @@ private:
static bool ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami);
- friend class CTheScripts;
};
#ifdef USE_DEBUG_SCRIPT_LOADER
diff --git a/src/control/Script2.cpp b/src/control/Script2.cpp
index 93098dac..a94bf907 100644
--- a/src/control/Script2.cpp
+++ b/src/control/Script2.cpp
@@ -1048,7 +1048,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
CTheScripts::CleanUpThisPed(pPed);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED:
@@ -1057,7 +1057,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
CTheScripts::CleanUpThisVehicle(pVehicle);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED:
@@ -1066,7 +1066,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
CTheScripts::CleanUpThisObject(pObject);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_DONT_REMOVE_CHAR:
@@ -1074,7 +1074,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_DONT_REMOVE_CAR:
@@ -1082,7 +1082,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_DONT_REMOVE_OBJECT:
@@ -1090,7 +1090,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 1);
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
script_assert(pObject);
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
case COMMAND_CREATE_CHAR_AS_PASSENGER:
@@ -1142,6 +1142,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetPosition(pVehicle->GetPosition());
pPed->SetOrientation(0.0f, 0.0f, 0.0f);
CPopulation::ms_nTotalMissionPeds++;
+ CWorld::Add(pPed);
if (ScriptParams[3] >= 0)
pVehicle->AddPassenger(pPed, ScriptParams[3]);
else
@@ -1149,16 +1150,14 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->m_pMyVehicle = pVehicle;
pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
pPed->bInVehicle = true;
- pVehicle->SetStatus(STATUS_PHYSICS);
pPed->SetPedState(PED_DRIVING);
pPed->bUsesCollision = false;
pPed->AddInCarAnims(pVehicle, false);
pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
- CWorld::Add(pPed);
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT:
diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp
index a34c89a9..7476d8de 100644
--- a/src/control/Script3.cpp
+++ b/src/control/Script3.cpp
@@ -325,11 +325,11 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CGarages::HasCarBeenDroppedOffYet(ScriptParams[0]));
return 0;
+/*
case COMMAND_SET_FREE_BOMBS:
CollectParameters(&m_nIp, 1);
CGarages::SetFreeBombs(ScriptParams[0] != 0);
return 0;
-#ifdef GTA_PS2
case COMMAND_SET_POWERPOINT:
{
CollectParameters(&m_nIp, 7);
@@ -363,8 +363,6 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
return 0;
}
-#endif // GTA_PS2
- /*
case COMMAND_SET_ALL_TAXI_LIGHTS:
CollectParameters(&m_nIp, 1);
CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0);
@@ -1279,7 +1277,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
/*
@@ -1343,7 +1341,6 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
return 0;
}
#endif
- /*
case COMMAND_IS_PLAYER_STOPPED:
{
CollectParameters(&m_nIp, 1);
@@ -1835,7 +1832,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);
@@ -1890,7 +1887,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);
diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp
index 31f50257..2177afa4 100644
--- a/src/control/Script4.cpp
+++ b/src/control/Script4.cpp
@@ -155,7 +155,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
++CCarCtrl::NumMissionCars;
--CCarCtrl::NumRandomCars;
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);
}
ScriptParams[0] = handle;
StoreParameters(&m_nIp, 1);
@@ -188,7 +188,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
++CCarCtrl::NumMissionCars;
--CCarCtrl::NumRandomCars;
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);
}
ScriptParams[0] = handle;
StoreParameters(&m_nIp, 1);
@@ -254,6 +254,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->SetObjective(OBJECTIVE_CATCH_TRAIN);
return 0;
}
+ */
#ifdef GTA_SCRIPT_COLLECTIVE
case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
CollectParameters(&m_nIp, 1);
@@ -608,7 +609,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
}
}
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE:
@@ -1055,7 +1056,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR:
diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp
index ab3c5b7f..822a70a8 100644
--- a/src/control/Script5.cpp
+++ b/src/control/Script5.cpp
@@ -2251,6 +2251,80 @@ VALIDATESAVEBUF(size)
#undef SCRIPT_DATA_SIZE
+void CRunningScript::Save(uint8*& buf)
+{
+#ifdef COMPATIBLE_SAVES
+ SkipSaveBuf(buf, 8);
+ for (int i = 0; i < 8; i++)
+ WriteSaveBuf<char>(buf, m_abScriptName[i]);
+ WriteSaveBuf<uint32>(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);
+#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_bIsActive);
+ WriteSaveBuf<bool>(buf, m_bCondResult);
+ WriteSaveBuf<bool>(buf, m_bIsMissionScript);
+ WriteSaveBuf<bool>(buf, m_bSkipWakeTime);
+ 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);
+#else
+ WriteSaveBuf(buf, *this);
+#endif
+}
+
+void CRunningScript::Load(uint8*& buf)
+{
+#ifdef COMPATIBLE_SAVES
+ SkipSaveBuf(buf, 8);
+ for (int i = 0; i < 8; i++)
+ m_abScriptName[i] = ReadSaveBuf<char>(buf);
+ m_nIp = ReadSaveBuf<uint32>(buf);
+#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++)
+ m_anStack[i] = ReadSaveBuf<uint32>(buf);
+ m_nStackPointer = ReadSaveBuf<uint16>(buf);
+ SkipSaveBuf(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++)
+ m_anLocalVariables[i] = ReadSaveBuf<int32>(buf);
+ m_bIsActive = ReadSaveBuf<bool>(buf);
+ m_bCondResult = ReadSaveBuf<bool>(buf);
+ m_bIsMissionScript = ReadSaveBuf<bool>(buf);
+ m_bSkipWakeTime = ReadSaveBuf<bool>(buf);
+ m_nWakeTime = ReadSaveBuf<uint32>(buf);
+ m_nAndOrState = ReadSaveBuf<uint16>(buf);
+ m_bNotFlag = ReadSaveBuf<bool>(buf);
+ m_bDeatharrestEnabled = ReadSaveBuf<bool>(buf);
+ m_bDeatharrestExecuted = ReadSaveBuf<bool>(buf);
+ m_bMissionFlag = ReadSaveBuf<bool>(buf);
+ SkipSaveBuf(buf, 2);
+#else
+ CRunningScript* n = next;
+ CRunningScript* p = prev;
+ *this = ReadSaveBuf<CRunningScript>(buf);
+ next = n;
+ prev = p;
+#endif
+}
+
void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity)
{
static CColPoint aTempColPoints[MAX_COLLISION_POINTS];
diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp
index 501a7873..76780941 100644
--- a/src/control/Script6.cpp
+++ b/src/control/Script6.cpp
@@ -703,7 +703,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CAR);
return 0;
}
case COMMAND_START_BOAT_FOAM_ANIMATION:
@@ -1191,7 +1191,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 8);
CPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
CVehicle *pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- pPed->AttachPedToEntity(pVehicle, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(ScriptParams[6]), (eWeaponType)ScriptParams[7]);
+ pPed->AttachPedToEntity(pVehicle, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(*(float*)&ScriptParams[6]), (eWeaponType)ScriptParams[7]);
return 0;
}
case COMMAND_DETACH_CHAR_FROM_CAR:
@@ -1272,7 +1272,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);
@@ -1320,7 +1320,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);
diff --git a/src/control/Script7.cpp b/src/control/Script7.cpp
index 1bad3407..1eaa6cd0 100644
--- a/src/control/Script7.cpp
+++ b/src/control/Script7.cpp
@@ -576,11 +576,11 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
CollectParameters(&m_nIp, 1);
CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
ScriptParams[0] = pPlayerInfo->m_nLastTimeCarSpentOnTwoWheels;
- ScriptParams[1] = *(int*)&pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels;
+ *(float*)&ScriptParams[1] = pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels;
ScriptParams[2] = pPlayerInfo->m_nLastTimeSpentOnWheelie;
- ScriptParams[3] = *(int*)&pPlayerInfo->m_nLastDistanceTravelledOnWheelie;
+ *(float*)&ScriptParams[3] = pPlayerInfo->m_nLastDistanceTravelledOnWheelie;
ScriptParams[4] = pPlayerInfo->m_nLastTimeSpentOnStoppie;
- ScriptParams[5] = *(int*)&pPlayerInfo->m_nLastDistanceTravelledOnStoppie;
+ *(float*)&ScriptParams[5] = pPlayerInfo->m_nLastDistanceTravelledOnStoppie;
StoreParameters(&m_nIp, 6);
pPlayerInfo->m_nLastTimeCarSpentOnTwoWheels = 0;
pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels = 0.0f;
@@ -1201,7 +1201,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER:
@@ -1231,7 +1231,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command)
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
return 0;
}
case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS:
diff --git a/src/control/Script8.cpp b/src/control/Script8.cpp
index a75692a0..0416d464 100644
--- a/src/control/Script8.cpp
+++ b/src/control/Script8.cpp
@@ -283,7 +283,7 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command)
pPed->bRespondsToThreats = false;
++CPopulation::ms_nTotalMissionPeds;
if (m_bIsMissionScript)
- CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
}
ScriptParams[0] = ped_handle;
StoreParameters(&m_nIp, 1);
diff --git a/src/control/SetPieces.cpp b/src/control/SetPieces.cpp
index c5142a0a..bbcfa1ea 100644
--- a/src/control/SetPieces.cpp
+++ b/src/control/SetPieces.cpp
@@ -10,6 +10,7 @@
#include "Vehicle.h"
#include "Wanted.h"
#include "World.h"
+#include "VarConsole.h"
#define TIME_BETWEEN_SETPIECE_SPAWNS 20000
@@ -23,6 +24,9 @@ void CSetPieces::Init(void)
{
bDebug = false;
NumSetPieces = 0;
+#ifndef MASTER
+ VarConsole.Add("Show set pieces", &bDebug, true);
+#endif
}
void CSetPieces::AddOne(uint8 type, CVector2D vTriggerInf, CVector2D vTriggerSup, CVector2D vSpawn1, CVector2D vTarget1, CVector2D vSpawn2, CVector2D vTarget2)
@@ -47,6 +51,9 @@ void CSetPieces::Update(void)
int nLast = NumSetPieces * (CTimer::GetFrameCounter() % 8 + 1) / 8;
for (int i = nFirst; i < nLast; i++)
aSetPieces[i].Update();
+#ifndef MASTER
+ // TODO: debug code from mobile
+#endif // !MASTER
}
void CSetPieces::Save(uint8* buf, uint32* size)
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
index 2cf1748c..d4188299 100644
--- a/src/core/Cam.cpp
+++ b/src/core/Cam.cpp
@@ -2370,8 +2370,10 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
}
- while(Beta >= PI) Beta -= 2*PI;
- while(Beta < -PI) Beta += 2*PI;
+ if (!isAttached) {
+ while(Beta >= TWOPI) Beta -= TWOPI;
+ while(Beta < 0) Beta += TWOPI;
+ }
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
@@ -2414,13 +2416,14 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
}
}
}else{
- while(Beta < -PI) Beta += 2*PI;
- while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += TWOPI;
+ while(Beta >= PI) Beta -= TWOPI;
}
mat = TargetPed->m_attachedTo->GetMatrix();
rot.SetRotateX(Alpha);
switch(TargetPed->m_attachType){
+ case 0: rot.RotateZ(Beta); break;
case 1: rot.RotateZ(Beta + HALFPI); break;
case 2: rot.RotateZ(Beta + PI); break;
case 3: rot.RotateZ(Beta - HALFPI); break;
diff --git a/src/core/Clock.cpp b/src/core/Clock.cpp
index 6c54ac63..b391e508 100644
--- a/src/core/Clock.cpp
+++ b/src/core/Clock.cpp
@@ -4,6 +4,7 @@
#include "Pad.h"
#include "Clock.h"
#include "Stats.h"
+#include "VarConsole.h"
// --MIAMI: File done
@@ -20,6 +21,10 @@ uint32 CClock::ms_nMillisecondsPerGameMinute;
uint32 CClock::ms_nLastClockTick;
bool CClock::ms_bClockHasBeenStored;
+#ifndef MASTER
+bool gbFreezeTime;
+#endif
+
void
CClock::Initialise(uint32 scale)
{
@@ -31,6 +36,10 @@ CClock::Initialise(uint32 scale)
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
ms_bClockHasBeenStored = false;
debug("CClock ready\n");
+#ifndef MASTER
+ VarConsole.Add("Time (hour of day)", &ms_nGameClockHours, 1, 0, 23, true);
+ VarConsole.Add("Freeze time", &gbFreezeTime, true);
+#endif
}
void
@@ -50,6 +59,10 @@ CClock::Update(void)
}
}
+#ifndef MASTER
+ else if (gbFreezeTime)
+ ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
+#endif
else if(CTimer::GetTimeInMilliseconds() - ms_nLastClockTick > ms_nMillisecondsPerGameMinute || gbFastTime)
{
ms_nGameClockMinutes++;
diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp
index fe865865..b2dad358 100644
--- a/src/core/ControllerConfig.cpp
+++ b/src/core/ControllerConfig.cpp
@@ -2354,15 +2354,15 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
#define VFB(b)
#endif
-#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT) \
+#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT, RSL, RSR) \
{{ \
O, /* PED_FIREWEAPON */ \
R2, /* PED_CYCLE_WEAPON_RIGHT */ \
L2, /* PED_CYCLE_WEAPON_LEFT */ \
nil, /* GO_FORWARD */ \
nil, /* GO_BACK */ \
- nil, /* GO_LEFT */ \
- nil, /* GO_RIGHT */ \
+ LEFT, /* GO_LEFT */ \
+ RIGHT, /* GO_RIGHT */ \
Q, /* PED_SNIPER_ZOOM_IN */ \
X, /* PED_SNIPER_ZOOM_OUT */ \
T, /* VEHICLE_ENTER_EXIT */ \
@@ -2370,6 +2370,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
X, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
+ L3, /* PED_DUCK */ \
+ L1, /* PED_ANSWER_PHONE */ \
VFB(O) /* VEHICLE_FIREWEAPON */ \
X, /* VEHICLE_ACCELERATE */ \
Q, /* VEHICLE_BRAKE */ \
@@ -2382,10 +2384,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
- nil, /* VEHICLE_TURRETLEFT */ \
- nil, /* VEHICLE_TURRETRIGHT */ \
- nil, /* VEHICLE_TURRETUP */ \
- nil, /* VEHICLE_TURRETDOWN */ \
+ RSL, /* VEHICLE_TURRETLEFT */ \
+ RSR, /* VEHICLE_TURRETRIGHT */ \
+ UP, /* VEHICLE_TURRETUP */ \
+ DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@@ -2397,6 +2399,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}, \
{ \
@@ -2405,8 +2408,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* PED_CYCLE_WEAPON_LEFT */ \
nil, /* GO_FORWARD */ \
nil, /* GO_BACK */ \
- nil, /* GO_LEFT */ \
- nil, /* GO_RIGHT */ \
+ LEFT, /* GO_LEFT */ \
+ RIGHT, /* GO_RIGHT */ \
Q, /* PED_SNIPER_ZOOM_IN */ \
X, /* PED_SNIPER_ZOOM_OUT */ \
T, /* VEHICLE_ENTER_EXIT */ \
@@ -2414,6 +2417,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
X, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
+ L3, /* PED_DUCK */ \
+ L1, /* PED_ANSWER_PHONE */ \
VFB(O) /* VEHICLE_FIREWEAPON */ \
X, /* VEHICLE_ACCELERATE */ \
Q, /* VEHICLE_BRAKE */ \
@@ -2426,10 +2431,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
- nil, /* VEHICLE_TURRETLEFT */ \
- nil, /* VEHICLE_TURRETRIGHT */ \
- nil, /* VEHICLE_TURRETUP */ \
- nil, /* VEHICLE_TURRETDOWN */ \
+ RSL, /* VEHICLE_TURRETLEFT */ \
+ RSR, /* VEHICLE_TURRETRIGHT */ \
+ UP, /* VEHICLE_TURRETUP */ \
+ DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@@ -2441,6 +2446,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}, \
{ \
@@ -2449,8 +2455,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* PED_CYCLE_WEAPON_LEFT */ \
nil, /* GO_FORWARD */ \
nil, /* GO_BACK */ \
- nil, /* GO_LEFT */ \
- nil, /* GO_RIGHT */ \
+ LEFT, /* GO_LEFT */ \
+ RIGHT, /* GO_RIGHT */ \
T, /* PED_SNIPER_ZOOM_IN */ \
Q, /* PED_SNIPER_ZOOM_OUT */ \
L1, /* VEHICLE_ENTER_EXIT */ \
@@ -2458,6 +2464,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
O, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
+ L3, /* PED_DUCK */ \
+ L1, /* PED_ANSWER_PHONE */ \
VFB(O) /* VEHICLE_FIREWEAPON */ \
X, /* VEHICLE_ACCELERATE */ \
Q, /* VEHICLE_BRAKE */ \
@@ -2470,10 +2478,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
- nil, /* VEHICLE_TURRETLEFT */ \
- nil, /* VEHICLE_TURRETRIGHT */ \
- nil, /* VEHICLE_TURRETUP */ \
- nil, /* VEHICLE_TURRETDOWN */ \
+ RSL, /* VEHICLE_TURRETLEFT */ \
+ RSR, /* VEHICLE_TURRETRIGHT */ \
+ UP, /* VEHICLE_TURRETUP */ \
+ DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
T, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@@ -2485,6 +2493,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}, \
{ \
@@ -2493,8 +2502,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* PED_CYCLE_WEAPON_LEFT */ \
nil, /* GO_FORWARD */ \
nil, /* GO_BACK */ \
- nil, /* GO_LEFT */ \
- nil, /* GO_RIGHT */ \
+ LEFT, /* GO_LEFT */ \
+ RIGHT, /* GO_RIGHT */ \
Q, /* PED_SNIPER_ZOOM_IN */ \
X, /* PED_SNIPER_ZOOM_OUT */ \
T, /* VEHICLE_ENTER_EXIT */ \
@@ -2502,6 +2511,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
Q, /* PED_JUMPING */ \
X, /* PED_SPRINT */ \
R3, /* PED_LOOKBEHIND */ \
+ L3, /* PED_DUCK */ \
+ L1, /* PED_ANSWER_PHONE */ \
VFB(R1) /* VEHICLE_FIREWEAPON */ \
nil, /* VEHICLE_ACCELERATE */ \
nil, /* VEHICLE_BRAKE */ \
@@ -2514,10 +2525,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
L2, /* VEHICLE_LOOKLEFT */ \
R2, /* VEHICLE_LOOKRIGHT */ \
nil, /* VEHICLE_LOOKBEHIND */ \
- nil, /* VEHICLE_TURRETLEFT */ \
- nil, /* VEHICLE_TURRETRIGHT */ \
- nil, /* VEHICLE_TURRETUP */ \
- nil, /* VEHICLE_TURRETDOWN */ \
+ RSL, /* VEHICLE_TURRETLEFT */ \
+ RSR, /* VEHICLE_TURRETRIGHT */ \
+ UP, /* VEHICLE_TURRETUP */ \
+ DOWN, /* VEHICLE_TURRETDOWN */ \
L2, /* PED_CYCLE_TARGET_LEFT */ \
R2, /* PED_CYCLE_TARGET_RIGHT */ \
O, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
@@ -2529,14 +2540,26 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
nil, /* TOGGLE_DPAD */ \
nil, /* SWITCH_DEBUG_CAM_ON */ \
nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* UNKNOWN_ACTION */ \
nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
}}
+#ifdef BUTTON_ICONS
+#define UP "~U~"
+#define DOWN "~D~"
+#define LEFT "~<~"
+#define RIGHT "~>~"
+#else
+#define UP "UP"
+#define DOWN "DOWN"
+#define LEFT "LEFT"
+#define RIGHT "RIGHT"
+#endif
-const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK");
+const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK", "right stick left", "right stick right");
#ifdef BUTTON_ICONS
-const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK");
+const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK", "~(~", "~)~");
#endif
@@ -2558,11 +2581,11 @@ const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O
#endif
const char *PlayStationButtons_noIcons[][MAX_CONTROLLERACTIONS] =
- CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT");
+ CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT", "right stick left", "right stick right");
#ifdef BUTTON_ICONS
const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] =
- CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT");
+ CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT", "~(~", "~)~");
#endif
#undef PS2_TRIANGLE
@@ -2570,6 +2593,11 @@ const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] =
#undef PS2_CROSS
#undef PS2_SQUARE
+#undef UP
+#undef DOWN
+#undef LEFT
+#undef RIGHT
+
#undef CONTROLLER_BUTTONS
#undef VFB
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index db5da918..e5e42b8c 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -1280,6 +1280,9 @@ CMenuManager::DrawStandardMenus(bool activeScreen)
case MENUACTION_CFO_SELECT:
CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i];
if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded)
+ CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));
+
// To whom manipulate option.m_CFO->value of static 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;
@@ -4786,7 +4789,11 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
TheCamera.m_fMouseAccelHorzntl = 0.0025f;
CVehicle::m_bDisableMouseSteering = true;
m_ControlMethod = CONTROL_STANDARD;
+#ifdef PC_PLAYER_CONTROLS
TheCamera.m_bUseMouse3rdPerson = true;
+#else
+ TheCamera.m_bUseMouse3rdPerson = false;
+#endif
SaveSettings();
}
SetHelperText(2);
@@ -4806,6 +4813,9 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
case MENUACTION_CFO_DYNAMIC:
CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded)
+ break;
+
if (!option.m_CFOSelect->onlyApplyOnEnter) {
option.m_CFOSelect->displayedValue++;
if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)
@@ -4954,6 +4964,9 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
case MENUACTION_CFO_DYNAMIC:
CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded)
+ break;
+
if (changeAmount > 0) {
option.m_CFOSelect->displayedValue++;
if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts)
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index 5e18c29a..b27cccb5 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -403,9 +403,10 @@ struct CCFOSelect : CCFO
int8 displayedValue; // only if onlyApplyOnEnter enabled for now
int8 lastSavedValue; // only if onlyApplyOnEnter enabled
ChangeFunc changeFunc;
+ bool disableIfGameLoaded;
CCFOSelect() {};
- CCFOSelect(int8* value, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc){
+ CCFOSelect(int8* value, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc = nil, bool disableIfGameLoaded = false){
this->value = value;
if (value)
this->lastSavedValue = this->displayedValue = *value;
@@ -415,6 +416,7 @@ struct CCFOSelect : CCFO
this->numRightTexts = numRightTexts;
this->onlyApplyOnEnter = onlyApplyOnEnter;
this->changeFunc = changeFunc;
+ this->disableIfGameLoaded = disableIfGameLoaded;
}
};
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index 348ac26d..8405c2ec 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -96,6 +96,7 @@
#include "postfx.h"
#include "custompipes.h"
#include "screendroplets.h"
+#include "VarConsole.h"
#ifdef USE_TEXTURE_POOL
#include "TexturePools.h"
#endif
@@ -113,6 +114,10 @@ char CGame::aDatFile[32];
bool CGame::russianGame = false;
bool CGame::japaneseGame = false;
#endif
+#ifndef MASTER
+CVector CGame::PlayerCoords;
+bool8 CGame::VarUpdatePlayerCoords;
+#endif
int gameTxdSlot;
@@ -557,6 +562,16 @@ bool CGame::Initialise(const char* datFile)
#ifdef USE_TEXTURE_POOL
_TexturePoolsUnknown(true);
#endif
+
+#ifndef MASTER
+ PlayerCoords = FindPlayerCoors();
+ VarConsole.Add("X PLAYER COORD", &PlayerCoords.x, 10.0f, -10000.0f, 10000.0f, true);
+ VarConsole.Add("Y PLAYER COORD", &PlayerCoords.y, 10.0f, -10000.0f, 10000.0f, true);
+ VarConsole.Add("Z PLAYER COORD", &PlayerCoords.z, 10.0f, -10000.0f, 10000.0f, true);
+ VarConsole.Add("UPDATE PLAYER COORD", &VarUpdatePlayerCoords, true);
+#endif
+
+
DMAudio.SetStartingTrackPositions(true);
DMAudio.ChangeMusicMode(MUSICMODE_GAME);
return true;
@@ -837,6 +852,12 @@ void CGame::Process(void)
CWindModifiers::Number = 0;
if (!CTimer::GetIsPaused())
{
+#ifndef MASTER
+ if (VarUpdatePlayerCoords) {
+ FindPlayerPed()->Teleport(PlayerCoords);
+ VarUpdatePlayerCoords = false;
+ }
+#endif
CSprite2d::SetRecipNearClip();
CSprite2d::InitPerFrame();
CFont::InitPerFrame();
diff --git a/src/core/Game.h b/src/core/Game.h
index ee9ca943..4052eb00 100644
--- a/src/core/Game.h
+++ b/src/core/Game.h
@@ -48,6 +48,11 @@ public:
static bool playingIntro;
static char aDatFile[32];
+#ifndef MASTER
+ static CVector PlayerCoords;
+ static bool8 VarUpdatePlayerCoords;
+#endif
+
static bool InitialiseOnceBeforeRW(void);
static bool InitialiseRenderWare(void);
static void ShutdownRenderWare(void);
diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp
index 173de805..72e19c49 100644
--- a/src/core/MenuScreens.cpp
+++ b/src/core/MenuScreens.cpp
@@ -217,8 +217,10 @@ CMenuScreen aScreens[] = {
{ "FET_CTL", MENUPAGE_OPTIONS, 0,
#ifdef PC_PLAYER_CONTROLS
MENUACTION_CTRLMETHOD, "FET_STI", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 320, 150, MENUALIGN_CENTER,
-#endif
MENUACTION_KEYBOARDCTRLS,"FEC_RED", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 0, 0, MENUALIGN_CENTER,
+#else
+ MENUACTION_KEYBOARDCTRLS,"FEC_RED", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 320, 150, MENUALIGN_CENTER,
+#endif
MENUACTION_CHANGEMENU, "FEC_MOU", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_CENTER,
MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 0, 0, MENUALIGN_CENTER,
MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER,
diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp
index 96e3be07..70c92ce8 100644
--- a/src/core/MenuScreensCustom.cpp
+++ b/src/core/MenuScreensCustom.cpp
@@ -24,7 +24,7 @@
#ifdef CUSTOM_FRONTEND_OPTIONS
#ifdef IMPROVED_VIDEOMODE
- #define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, nil, screenModes, 2, true, ScreenModeAfterChange) }, 0, 0, MENUALIGN_LEFT,
+ #define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, nil, screenModes, 2, true, ScreenModeAfterChange, true) }, 0, 0, MENUALIGN_LEFT,
#else
#define VIDEOMODE_SELECTOR
#endif
@@ -36,19 +36,19 @@
#endif
#ifdef CUTSCENE_BORDERS_SWITCH
- #define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&FrontEndMenuManager.m_PrefsCutsceneBorders, "CutsceneBorders", off_on, 2, false, nil) }, 0, 0, MENUALIGN_LEFT,
+ #define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&FrontEndMenuManager.m_PrefsCutsceneBorders, "CutsceneBorders", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#else
#define CUTSCENE_BORDERS_TOGGLE
#endif
#ifdef FREE_CAM
- #define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "FreeCam", off_on, 2, false, nil) }, 0, 0, MENUALIGN_LEFT,
+ #define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "FreeCam", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#else
#define FREE_CAM_TOGGLE
#endif
#ifdef PS2_ALPHA_TEST
- #define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "PS2AlphaTest", off_on, 2, false, nil) }, 0, 0, MENUALIGN_LEFT,
+ #define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "PS2AlphaTest", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#else
#define DUALPASS_SELECTOR
#endif
@@ -61,14 +61,14 @@
#ifdef EXTENDED_COLOURFILTER
#define POSTFX_SELECTORS \
- MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, 0, 0, MENUALIGN_LEFT, \
- MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) }, 0, 0, MENUALIGN_LEFT,
+ MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false) }, 0, 0, MENUALIGN_LEFT, \
+ MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,
#else
#define POSTFX_SELECTORS
#endif
#ifdef INVERT_LOOK_FOR_PAD
- #define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_ILU", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, nil, off_on, 2, false, nil) }, 150, 0, MENUALIGN_LEFT,
+ #define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_ILU", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, nil, off_on, 2, false) }, 150, 0, MENUALIGN_LEFT,
#else
#define INVERT_PAD_SELECTOR
#endif
@@ -548,8 +548,10 @@ CMenuScreenCustom aScreens[] = {
{ "FET_CTL", MENUPAGE_OPTIONS, new CCustomScreenLayout({0, 0, MENU_DEFAULT_LINE_HEIGHT, false, false, 150}), nil,
#ifdef PC_PLAYER_CONTROLS
MENUACTION_CTRLMETHOD, "FET_STI", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 150, MENUALIGN_CENTER,
-#endif
MENUACTION_KEYBOARDCTRLS,"FEC_RED", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 0, 0, MENUALIGN_CENTER,
+#else
+ MENUACTION_KEYBOARDCTRLS,"FEC_RED", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 320, 150, MENUALIGN_CENTER,
+#endif
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
MENUACTION_CHANGEMENU, "FEC_JOD", {nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK}, 0, 0, MENUALIGN_CENTER,
#endif
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index 4a78e834..feda19c6 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -1692,12 +1692,11 @@ void CPad::UpdatePads(void)
bUpdate = false;
if ( bUpdate )
- {
GetPad(0)->Update(0);
- // GetPad(1)->Update(0); // not in VC
- }
-#if defined(MASTER) && !defined(XINPUT)
+#ifndef MASTER
+ GetPad(1)->Update(1);
+#else
GetPad(1)->NewState.Clear();
GetPad(1)->OldState.Clear();
#endif
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index 2fd8bf1c..3e470fde 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -36,6 +36,7 @@
#include "MemoryHeap.h"
#include "Font.h"
#include "Frontend.h"
+#include "VarConsole.h"
//--MIAMI: file done (possibly bugs)
@@ -82,6 +83,12 @@ CEntity *pIslandLODbeachEntity;
int32 islandLODmainland;
int32 islandLODbeach;
+#ifndef MASTER
+bool gbPrintStats;
+bool gbPrintVehiclesInMemory; // TODO
+bool gbPrintStreamingBuffer; // TODO
+#endif
+
bool
CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)
{
@@ -237,8 +244,14 @@ CStreaming::Init2(void)
pIslandLODbeachEntity = nil;
islandLODmainland = -1;
islandLODbeach = -1;
- CModelInfo::GetModelInfo("IslandLODmainland", &islandLODmainland);
- CModelInfo::GetModelInfo("IslandLODbeach", &islandLODbeach);
+ CModelInfo::GetModelInfo("IslandLODmainland", &islandLODmainland);
+ CModelInfo::GetModelInfo("IslandLODbeach", &islandLODbeach);
+
+#ifndef MASTER
+ VarConsole.Add("Streaming Debug", &gbPrintStats, true);
+ VarConsole.Add("Streaming Vehicle Debug", &gbPrintVehiclesInMemory, true);
+ VarConsole.Add("Printf Streaming Buffer contents", &gbPrintStreamingBuffer, true);
+#endif
}
void
@@ -1908,10 +1921,12 @@ CStreaming::LoadBigBuildingsWhenNeeded(void)
ISLAND_LOADING_IS(LOW)
CStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition());
+#ifdef NO_ISLAND_LOADING
else if(FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM) {
RemoveIslandsNotUsed(CGame::currLevel);
CStreaming::RequestIslands(CGame::currLevel);
}
+#endif
CStreaming::LoadAllRequestedModels(false);
diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp
index 56cea203..8018076d 100644
--- a/src/core/SurfaceTable.cpp
+++ b/src/core/SurfaceTable.cpp
@@ -138,7 +138,7 @@ CSurfaceTable::GetWetMultiplier(uint8 surfaceType)
case SURFACE_SAND:
case SURFACE_SAND_BEACH:
- return 1.0f - CWeather::WetRoads*0.5f;
+ return 1.0f + CWeather::WetRoads*0.5f;
default:
return 1.0f;
diff --git a/src/core/common.h b/src/core/common.h
index 155b5dba..3fb2e963 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -79,6 +79,10 @@ typedef int64_t int64;
// hardcode ucs-2
typedef uint16_t wchar;
+typedef uint8 bool8;
+typedef uint16 bool16;
+typedef uint32 bool32;
+
#if defined(_MSC_VER)
typedef ptrdiff_t ssize_t;
#endif
diff --git a/src/core/config.h b/src/core/config.h
index 8fd3bc1c..a06ed1be 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -338,6 +338,11 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#define USE_BASIC_SCRIPT_DEBUG_OUTPUT
#endif
+#ifdef MASTER
+#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
+#undef USE_BASIC_SCRIPT_DEBUG_OUTPUT
+#endif
+
// Replay
//#define DONT_FIX_REPLAY_BUGS // keeps various bugs in CReplay, some of which are fairly cool!
//#define USE_BETA_REPLAY_MODE // adds another replay mode, a few seconds slomo (caution: buggy!)
@@ -360,6 +365,7 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
// Audio
#define AUDIO_CACHE // cache sound lengths to speed up the cold boot
//#define PS2_AUDIO // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS
+//#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder
#ifdef LIBRW
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 85e04540..d9579fee 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -72,6 +72,7 @@
#include "postfx.h"
#include "custompipes.h"
#include "screendroplets.h"
+#include "VarConsole.h"
GlobalScene Scene;
@@ -133,6 +134,9 @@ bool gbNewRenderer;
#define CLEARMODE (rwCAMERACLEARZ)
#endif
+bool bDisplayNumOfAtomicsRendered = false;
+bool bDisplayPosn = false;
+
void
ValidateVersion()
{
@@ -473,6 +477,11 @@ Initialise3D(void *param)
{
PUSH_MEMID(MEMID_RENDER);
+#ifndef MASTER
+ VarConsole.Add("Display number of atomics rendered", &bDisplayNumOfAtomicsRendered, true);
+ VarConsole.Add("Display posn and framerate", &bDisplayPosn, true);
+#endif
+
if (RsRwInitialize(param))
{
POP_MEMID();
@@ -1008,7 +1017,6 @@ return;
void
DisplayGameDebugText()
{
- static bool bDisplayPosn = false;
static bool bDisplayCheatStr = false; // custom
#ifndef FINAL
@@ -1382,6 +1390,10 @@ RenderMenus(void)
{
FrontEndMenuManager.DrawFrontEnd();
}
+#ifndef MASTER
+ else
+ VarConsole.Check();
+#endif
}
void
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 5e3d8922..0e5ed2af 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -225,7 +225,6 @@ void LoadINISettings()
void SaveINISettings()
{
bool changed = false;
- char temp[4];
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
if (strncmp(cfg.get("DetectJoystick", "JoystickName", "").c_str(), gSelectedJoystickName, strlen(gSelectedJoystickName)) != 0) {
@@ -647,7 +646,7 @@ extern bool gbRenderWorld2;
#endif
DebugMenuAddVar("Render", "Drunkness", &CMBlur::Drunkness, nil, 0.05f, 0, 1.0f);
#ifndef MASTER
- DebugMenuAddVarBool8("Render", "Occlusion debug", &bDisplayOccDebugStuff, nil);
+ DebugMenuAddVarBool8("Render", "Occlusion debug", &bDispayOccDebugStuff, nil);
#endif
#ifdef EXTENDED_PIPELINES
static const char *vehpipenames[] = { "MatFX", "Neo" };
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index 9b6be5f6..1073deb3 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -126,6 +126,7 @@ CEntity::CreateRwObject(void)
m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
+
mi->AddRef();
}
}
@@ -139,6 +140,7 @@ CEntity::AttachToRwObject(RwObject *obj)
m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
+
CModelInfo::GetModelInfo(m_modelIndex)->AddRef();
}
}
@@ -239,12 +241,8 @@ CEntity::GetBoundRadius(void)
void
CEntity::UpdateRwFrame(void)
{
- if(m_rwObject){
- if(RwObjectGetType(m_rwObject) == rpATOMIC)
- RwFrameUpdateObjects(RpAtomicGetFrame((RpAtomic*)m_rwObject));
- else if(RwObjectGetType(m_rwObject) == rpCLUMP)
- RwFrameUpdateObjects(RpClumpGetFrame((RpClump*)m_rwObject));
- }
+ if(m_rwObject)
+ RwFrameUpdateObjects((RwFrame*)rwObjectGetParent(m_rwObject));
}
void
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index acf9c702..706b469c 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -235,6 +235,7 @@ CPhysical::GetBoundRect(void)
return CRect(center.x-radius, center.y-radius, center.x+radius, center.y+radius);
}
+// --MIAMI: Proof-read once
void
CPhysical::AddToMovingList(void)
{
@@ -242,6 +243,7 @@ CPhysical::AddToMovingList(void)
m_movingListNode = CWorld::GetMovingEntityList().InsertItem(this);
}
+// --MIAMI: Proof-read once
void
CPhysical::RemoveFromMovingList(void)
{
@@ -261,12 +263,14 @@ CPhysical::SetDamagedPieceRecord(uint16 piece, float impulse, CEntity *entity, C
m_vecDamageNormal = dir;
}
+// --MIAMI: Proof-read once
void
CPhysical::AddCollisionRecord(CEntity *ent)
{
AddCollisionRecord_Treadable(ent);
this->bHasCollided = true;
ent->bHasCollided = true;
+ this->m_nLastTimeCollided = CTimer::GetTimeInMilliseconds();
if(IsVehicle() && ent->IsVehicle()){
if(((CVehicle*)this)->m_nAlarmState == -1)
((CVehicle*)this)->m_nAlarmState = 15000;
@@ -280,10 +284,10 @@ CPhysical::AddCollisionRecord(CEntity *ent)
return;
if(m_nCollisionRecords < PHYSICAL_MAX_COLLISIONRECORDS)
m_aCollisionRecords[m_nCollisionRecords++] = ent;
- m_nLastTimeCollided = CTimer::GetTimeInMilliseconds();
}
}
+// --MIAMI: Proof-read once
void
CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
{
@@ -291,6 +295,7 @@ CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
}
}
+// --MIAMI: Proof-read once
bool
CPhysical::GetHasCollidedWith(CEntity *ent)
{
@@ -302,20 +307,23 @@ CPhysical::GetHasCollidedWith(CEntity *ent)
return false;
}
+// --MIAMI: Proof-read once
void
CPhysical::RemoveRefsToEntity(CEntity *ent)
{
- int i, j;
+ int i = 0, j;
- for(i = 0; i < m_nCollisionRecords; i++){
+ while (i < m_nCollisionRecords){
if(m_aCollisionRecords[i] == ent){
for(j = i; j < m_nCollisionRecords-1; j++)
m_aCollisionRecords[j] = m_aCollisionRecords[j+1];
m_nCollisionRecords--;
- }
+ } else
+ i++;
}
}
+// --MIAMI: Proof-read once
void
CPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos)
{
@@ -332,6 +340,7 @@ CPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phy
CWorld::Add(phys);
}
+// --MIAMI: Proof-read once
int32
CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
{
@@ -350,6 +359,7 @@ CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
return numSpheres;
}
+// --MIAMI: Proof-read once
void
CPhysical::ProcessControl(void)
{
@@ -417,6 +427,7 @@ CPhysical::GetSpeed(const CVector &r)
return m_vecMoveSpeed + m_vecMoveFriction + CrossProduct(m_vecTurnFriction + m_vecTurnSpeed, r);
}
+// --MIAMI: Proof-read once
void
CPhysical::ApplyMoveSpeed(void)
{
@@ -426,7 +437,7 @@ CPhysical::ApplyMoveSpeed(void)
GetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep());
}
-
+// --MIAMI: Proof-read once
void
CPhysical::ApplyTurnSpeed(void)
{
@@ -442,12 +453,14 @@ CPhysical::ApplyTurnSpeed(void)
}
}
+// --MIAMI: Proof-read once
void
CPhysical::ApplyMoveForce(float jx, float jy, float jz)
{
m_vecMoveSpeed += CVector(jx, jy, jz)*(1.0f/m_fMass);
}
+// --MIAMI: Proof-read once
void
CPhysical::ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz)
{
@@ -462,6 +475,7 @@ CPhysical::ApplyFrictionMoveForce(float jx, float jy, float jz)
m_vecMoveFriction += CVector(jx, jy, jz)*(1.0f/m_fMass);
}
+// --MIAMI: Proof-read once
void
CPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float py, float pz)
{
@@ -470,6 +484,7 @@ CPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float
m_vecTurnFriction += turnimpulse*(1.0f/m_fTurnMass);
}
+// --MIAMI: Proof-read once
bool
CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias)
{
@@ -483,6 +498,7 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &
return true;
}
+// --MIAMI: Proof-read once
bool
CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir)
{
@@ -500,6 +516,7 @@ CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVecto
return true;
}
+// --MIAMI: Proof-read once
// What exactly is speed?
bool
CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)
@@ -560,17 +577,16 @@ CPhysical::ApplyFriction(void)
m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);
}
+// --MIAMI: Proof-read once
void
CPhysical::ApplyAirResistance(void)
{
if(m_fAirResistance > 0.1f){
- if(GetStatus() != STATUS_GHOST){
- float f = Pow(m_fAirResistance, CTimer::GetTimeStep());
- m_vecMoveSpeed *= f;
- m_vecTurnSpeed *= f;
- }
- }else{
- float f = Pow(1.0f/(m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr() + 1.0f), CTimer::GetTimeStep());
+ float f = Pow(m_fAirResistance, CTimer::GetTimeStep());
+ m_vecMoveSpeed *= f;
+ m_vecTurnSpeed *= f;
+ }else if(GetStatus() != STATUS_GHOST){
+ float f = Pow(1.0f/Abs(1.0f + m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr()), CTimer::GetTimeStep());
m_vecMoveSpeed *= f;
m_vecTurnSpeed *= 0.99f;
}
@@ -1015,6 +1031,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV
return false;
}
+// --MIAMI: Proof-read once
bool
CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
{
@@ -1044,7 +1061,11 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
impulseB = (speedSum - fOtherSpeedB) * B->m_fMass;
impulseLimit = adhesiveLimit*CTimer::GetTimeStep();
if(impulseA < -impulseLimit) impulseA = -impulseLimit;
- if(impulseB > impulseLimit) impulseB = impulseLimit; // BUG: game has A's clamp again here, but this can't be right
+#ifdef FIX_BUGS
+ if(impulseB > impulseLimit) impulseB = impulseLimit;
+#else
+ if(impulseA < -impulseLimit) impulseA = -impulseLimit; // duplicate
+#endif
A->ApplyFrictionMoveForce(frictionDir*impulseA);
B->ApplyFrictionMoveForce(frictionDir*impulseB);
return true;
@@ -1139,6 +1160,7 @@ CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
return false;
}
+// --MIAMI: Proof-read once
bool
CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
{
@@ -1176,7 +1198,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
if(fOtherSpeed > 0.0f){
frictionDir = vOtherSpeed * (1.0f/fOtherSpeed);
fImpulse = -fOtherSpeed * m_fMass;
- impulseLimit = adhesiveLimit*CTimer::GetTimeStep() * 1.5f;
+ impulseLimit = adhesiveLimit*CTimer::GetTimeStep() * 1.5;
if(fImpulse < -impulseLimit) fImpulse = -impulseLimit;
ApplyFrictionMoveForce(frictionDir*fImpulse);
ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos);
@@ -1194,6 +1216,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
return false;
}
+// --MIAMI: Proof-read once
bool
CPhysical::ProcessShiftSectorList(CPtrList *lists)
{
@@ -1267,7 +1290,8 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
skipShift = true;
Aobj->m_pCollidingEntity = B;
}
- }
+ } else
+ skipShift = true;
}else if(B->IsObject() && A->IsVehicle()){
CObject *Bobj = (CObject*)B;
if(Bobj->ObjectCreatedBy != TEMP_OBJECT &&
@@ -1282,7 +1306,8 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
if(size.z < A->GetPosition().z ||
(Invert(A->GetMatrix(), inv) * size).z < 0.0f)
skipShift = true;
- }
+ } else
+ skipShift = true;
}else if(IsBodyPart(A->GetModelIndex()) && B->IsPed())
skipShift = true;
else if(A->IsPed() && IsBodyPart(B->GetModelIndex()))
@@ -1354,6 +1379,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
return true;
}
+// --MIAMI: Proof-read once
bool
CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists)
{
@@ -1520,6 +1546,7 @@ collision:
return true;
}
+// --MIAMI: Proof-read once
bool
CPhysical::ProcessCollisionSectorList(CPtrList *lists)
{
@@ -1656,8 +1683,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
return true;
if(numCollisions == 0 && A == (CEntity*)FindPlayerPed() && Aped->m_pCollidingEntity == B)
Aped->m_pCollidingEntity = nil;
- }else if(B->IsBuilding() || B->bIsStuck || B->bInfiniteMass || altcollision){
-
+ }else if(B->IsBuilding() || B->bIsStuck || B->m_phy_flagA08 || altcollision){
// This is the case where B doesn't move
B->m_scanCode = CWorld::GetCurrentScanCode();
@@ -1925,18 +1951,22 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
CMatrix inv;
CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = B->GetMatrix() * size;
- if(size.z < B->GetPosition().z ||
+ if(size.z < A->GetPosition().z ||
(Invert(A->GetMatrix(), inv) * size).z < 0.0f)
Bobj->ObjectDamage(50.0f);
}
}else if(A->IsObject() && A->bUsesCollision && B->IsVehicle()){
if(Aobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f)
Aobj->ObjectDamage(maxImpulseB);
+#ifdef FIX_BUGS
else if(Aobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){
+#else
+ else if(Bobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){
+#endif
CMatrix inv;
CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = A->GetMatrix() * size;
- if(size.z < A->GetPosition().z ||
+ if(size.z < B->GetPosition().z ||
(Invert(B->GetMatrix(), inv) * size).z < 0.0f)
Aobj->ObjectDamage(50.0f);
}
@@ -1987,6 +2017,7 @@ CPhysical::CheckCollision_SimpleCar(void)
float PHYSICAL_SHIFT_SPEED_DAMP = 0.707f;
+// --MIAMI: Proof-read once
void
CPhysical::ProcessShift(void)
{
@@ -1997,8 +2028,8 @@ CPhysical::ProcessShift(void)
RemoveAndAdd();
}else{
CPhysical *surf;
- if(bHasHitWall && IsPed() && (surf = ((CPed*)this)->m_pCurrentPhysSurface, surf == nil || !surf->bInfiniteMass || surf->m_phy_flagA08) ||
- CWorld::bSecondShift){
+ if(bHasHitWall && (IsPed() && (surf = ((CPed*)this)->m_pCurrentPhysSurface, surf == nil || !surf->bInfiniteMass || surf->m_phy_flagA08) ||
+ CWorld::bSecondShift)){
m_vecMoveSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());
m_vecTurnSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());
}
diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp
index 1f154250..8a95a49a 100644
--- a/src/extras/frontendoption.cpp
+++ b/src/extras/frontendoption.cpp
@@ -111,7 +111,7 @@ void FrontendOptionAddBuiltinAction(const char* gxtKey, uint16 x, uint16 y, uint
option.m_TargetMenu = targetMenu;
}
-void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName)
+void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName, bool disableIfGameLoaded)
{
int8 screenOptionOrder = RegisterNewOption();
@@ -133,6 +133,7 @@ void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align
option.m_CFOSelect->save = saveName;
option.m_CFOSelect->onlyApplyOnEnter = onlyApplyOnEnter;
option.m_CFOSelect->changeFunc = changeFunc;
+ option.m_CFOSelect->disableIfGameLoaded = disableIfGameLoaded;
}
void FrontendOptionAddDynamic(const char* gxtKey, uint16 x, uint16 y, uint8 align, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName)
diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h
index 6670c323..2719f076 100644
--- a/src/extras/frontendoption.h
+++ b/src/extras/frontendoption.h
@@ -78,7 +78,7 @@ void FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false);
// var is optional in AddDynamic, enables you to save them in an INI file(also needs passing char array to saveName param. obv), otherwise pass nil/0
void FrontendOptionAddBuiltinAction(const char* gxtKey, uint16 x, uint16 y, uint8 align, int action, int targetMenu = MENUPAGE_NONE, int saveSlot = SAVESLOT_NONE);
-void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName = nil);
+void FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName = nil, bool disableIfGameLoaded = false);
void FrontendOptionAddDynamic(const char* gxtKey, uint16 x, uint16 y, uint8 align, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName = nil);
// lineHeight = 0 means game will use MENU_DEFAULT_LINE_HEIGHT
diff --git a/src/extras/ini_parser.hpp b/src/extras/ini_parser.hpp
index 99acf1ee..8e88bc29 100644
--- a/src/extras/ini_parser.hpp
+++ b/src/extras/ini_parser.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015 Denilson das Mercęs Amorim <dma_2012@hotmail.com>
+ * 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
diff --git a/src/extras/screendroplets.cpp b/src/extras/screendroplets.cpp
index 6ea72f09..ac3a17b2 100644
--- a/src/extras/screendroplets.cpp
+++ b/src/extras/screendroplets.cpp
@@ -391,7 +391,7 @@ void
ScreenDroplets::RegisterSplash(CParticleObject *pobj)
{
CVector dist = pobj->GetPosition() - ms_prevCamPos;
- if(dist.MagnitudeSqr() < 20.0f){
+ if(dist.MagnitudeSqr() < 50.0f){ // 20 originally
ms_splashDuration = 14;
ms_splashObject = pobj;
}
diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp
index 37567927..863407b9 100644
--- a/src/fakerw/fake.cpp
+++ b/src/fakerw/fake.cpp
@@ -14,6 +14,7 @@
using namespace rw;
RwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; }
+RwFrame* rwObjectGetParent(const RwObject *obj) { return (RwFrame*)obj->parent; }
void *RwMalloc(size_t size) { return engine->memfuncs.rwmalloc(size, 0); }
diff --git a/src/fakerw/rwplcore.h b/src/fakerw/rwplcore.h
index 511f7678..69c921cc 100644
--- a/src/fakerw/rwplcore.h
+++ b/src/fakerw/rwplcore.h
@@ -108,12 +108,12 @@ enum RwCorePluginID
//struct RwObject;
typedef rw::Object RwObject;
+typedef rw::Frame RwFrame;
typedef RwObject *(*RwObjectCallBack)(RwObject *object, void *data);
RwUInt8 RwObjectGetType(const RwObject *obj);
-
-
+RwFrame* rwObjectGetParent(const RwObject *obj);
#define rwsprintf sprintf
#define rwvsprintf vsprintf
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 88a16a95..6c0d9987 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -1003,7 +1003,7 @@ public:
// My names. Inlined in VC
AnimationId GetFireAnimNotDucking(CWeaponInfo* weapon) {
if (m_nPedType == PEDTYPE_COP && weapon->IsFlagSet(WEAPONFLAG_COP3_RD))
- return ANIM_WEAPON_FIRE_3RD;
+ return Get3rdFireAnim(weapon);
else
return GetPrimaryFireAnim(weapon);
}
diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp
index 364e18d8..16e6c8e2 100644
--- a/src/peds/PedAI.cpp
+++ b/src/peds/PedAI.cpp
@@ -924,10 +924,10 @@ CPed::ProcessObjective(void)
m_pMyVehicle->SetStatus(STATUS_PHYSICS);
m_pMyVehicle->AutoPilot.m_nPrevRouteNode = 0;
if (m_nPedType == PEDTYPE_COP) {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity);
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity);
m_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
} else {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity * 0.8f;
m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
}
m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
@@ -1921,7 +1921,7 @@ CPed::ProcessObjective(void)
ClearObjective();
CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity;
m_pMyVehicle->SetStatus(STATUS_PHYSICS);
} else {
SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
@@ -2147,10 +2147,10 @@ CPed::SelectGunIfArmed(void)
if (GetWeapon(i).m_nAmmoTotal > 0) {
eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
- if (weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_PYTHON || weaponType == WEAPONTYPE_SHOTGUN ||
+ if (weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_MP5 || weaponType == WEAPONTYPE_M4 ||
+ weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_PYTHON || weaponType == WEAPONTYPE_SHOTGUN ||
weaponType == WEAPONTYPE_SPAS12_SHOTGUN || weaponType == WEAPONTYPE_STUBBY_SHOTGUN ||
- weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_M4 || weaponType == WEAPONTYPE_MP5 ||
- weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_SNIPERRIFLE) {
+ weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_FLAMETHROWER) {
SetCurrentWeapon(i);
return true;
}
@@ -2269,7 +2269,7 @@ CPed::ReactToAttack(CEntity *attacker)
CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity;
m_pMyVehicle->SetStatus(STATUS_PHYSICS);
}
@@ -5458,7 +5458,7 @@ CPed::RegisterThreatWithGangPeds(CEntity *attacker)
if (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType && nearVehDriver->CharCreatedBy == RANDOM_CHAR) {
if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {
- nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fMaxCruiseVelocity * 0.8f;
nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
nearVeh->SetStatus(STATUS_PHYSICS);
nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;
diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp
index 79c6f367..eaa2aa3d 100644
--- a/src/peds/PedFight.cpp
+++ b/src/peds/PedFight.cpp
@@ -661,9 +661,7 @@ CPed::Attack(void)
{
CAnimBlendAssociation *weaponAnimAssoc;
int32 weaponAnim;
- eWeaponType ourWeaponType;
float weaponAnimTime;
- eWeaponFire ourWeaponFire;
float animLoopEnd;
CWeaponInfo *ourWeapon;
bool attackShouldContinue;
@@ -673,9 +671,7 @@ CPed::Attack(void)
float animLoopStart;
CVector firePos;
- ourWeaponType = GetWeapon()->m_eWeaponType;
- ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
- ourWeaponFire = ourWeapon->m_eWeaponFire;
+ ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
weaponAnimAssoc = nil;
attackShouldContinue = !!bIsAttacking;
reloadAnimAssoc = nil;
@@ -694,14 +690,15 @@ CPed::Attack(void)
delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
}
}
- } else {
- AnimationId anim = GetFireAnimNotDucking(ourWeapon);
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), anim);
- if (anim == ANIM_WEAPON_FIRE_3RD && weaponAnimAssoc) {
+ } else if (m_nPedType == PEDTYPE_COP && Get3rdFireAnim(ourWeapon)){
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), Get3rdFireAnim(ourWeapon));
+ if (weaponAnimAssoc) {
animLoopStart = 11.f/30.f;
animLoopEnd = 19.f/30.f;
delayBetweenAnimAndFire = 14.f/30.f;
}
+ } else {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(ourWeapon));
}
if (GetReloadAnim(ourWeapon)) {
@@ -778,15 +775,15 @@ CPed::Attack(void)
if (!weaponAnimAssoc) {
if (!throwAssoc) {
if (attackShouldContinue) {
- if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
+ if (ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(ourWeapon)) {
weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetCrouchFireAnim(ourWeapon), 8.0f);
} else if(GetSecondFireAnim(ourWeapon) && CGeneral::GetRandomNumber() & 1){
weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f);
- } else if(!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE ||
- GetFireAnimGround(ourWeapon) ||
+ } else if(!CGame::nastyGame || ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE ||
+ !GetFireAnimGround(ourWeapon, false) ||
CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimNotDucking(ourWeapon), 8.0f);
@@ -831,11 +828,11 @@ CPed::Attack(void)
m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
- if (ourWeaponType != WEAPONTYPE_CHAINSAW
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_CHAINSAW
|| !meleeAttackStarted && delayBetweenAnimAndFire - 0.5f >= weaponAnimAssoc->currentTime
|| weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire) {
- if (ourWeaponType == WEAPONTYPE_CHAINSAW) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW) {
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_ATTACK, 0.0f);
} else if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
if (weaponAnimAssoc->speed < 1.0f)
@@ -859,11 +856,11 @@ CPed::Attack(void)
GetWeapon()->Fire(this, &firePos);
- if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE || ourWeaponType == WEAPONTYPE_DETONATOR_GRENADE ||
- ourWeaponType == WEAPONTYPE_TEARGAS) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_MOLOTOV || GetWeapon()->m_eWeaponType == WEAPONTYPE_GRENADE || GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE ||
+ GetWeapon()->m_eWeaponType == WEAPONTYPE_TEARGAS) {
RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nModelId);
}
- if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
+ if (GetWeapon()->m_nAmmoTotal == 0 && ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
SelectGunIfArmed();
}
@@ -875,13 +872,13 @@ CPed::Attack(void)
switch (ourWeapon->m_AnimToPlay) {
case ASSOCGRP_UNARMED:
if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, (damagerType | (ourWeaponType << 8)));
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, (damagerType | (GetWeapon()->m_eWeaponType << 8)));
break;
case ASSOCGRP_KNIFE:
case ASSOCGRP_BASEBALLBAT:
case ASSOCGRP_GOLFCLUB:
case ASSOCGRP_CHAINSAW:
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (ourWeaponType << 8)));
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (GetWeapon()->m_eWeaponType << 8)));
break;
default:
break;
@@ -944,14 +941,13 @@ CPed::Attack(void)
}
if (IsPlayer()) {
- eWeaponType weaponType = GetWeapon()->m_eWeaponType;
- if (weaponType == WEAPONTYPE_BASEBALLBAT || weaponType == WEAPONTYPE_GOLFCLUB || weaponType == WEAPONTYPE_KATANA) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT || GetWeapon()->m_eWeaponType == WEAPONTYPE_GOLFCLUB || GetWeapon()->m_eWeaponType == WEAPONTYPE_KATANA) {
float loopEndWithDelay = animLoopEnd;
if (loopEndWithDelay >= 98.0f)
loopEndWithDelay = (14.0f / 30.0f) + delayBetweenAnimAndFire;
if (weaponAnimAssoc->flags & ASSOC_RUNNING) {
if (weaponAnimAssoc->currentTime >= animLoopStart && weaponAnimAssoc->currentTime <= loopEndWithDelay)
- CSpecialFX::AddWeaponStreak(weaponType);
+ CSpecialFX::AddWeaponStreak(GetWeapon()->m_eWeaponType);
}
}
}
@@ -970,7 +966,7 @@ CPed::Attack(void)
weaponAnimTime = weaponAnimAssoc->currentTime;
// Anim loop end, either start the loop again or finish the attack
- if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeaponFire != WEAPON_FIRE_PROJECTILE) {
+ if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE) {
if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING) {
if (GetReloadAnim(ourWeapon) && !reloadAnimAssoc) {
if (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload) {
@@ -997,7 +993,7 @@ CPed::Attack(void)
PedOnGroundState pedOnGroundState;
if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE &&
(CGame::nastyGame && ((pedOnGroundState = CheckForPedsOnGroundToAttack(this, nil)) > PED_IN_FRONT_OF_ATTACKER)
- || ourWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) {
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) {
AnimationId fireAnim = GetFireAnimGround(ourWeapon, false);
if (weaponAnimAssoc->animId == fireAnim)
@@ -1030,10 +1026,10 @@ CPed::Attack(void)
// Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)
if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < animLoopEnd)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, ourWeaponType);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);
// Fun fact: removing this part leds to reloading flamethrower
- if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
weaponAnimAssoc->blendDelta = -4.0f;
@@ -2021,9 +2017,9 @@ CPed::PlayHitSound(CPed *hitTo)
if (weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE) {
if (m_curFightMove >= FIGHTMOVE_MELEE1) {
if (m_curFightMove == FIGHTMOVE_MELEE3) {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (weapon << 8) | 3);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);
} else {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_KNIFE_ATTACK, (weapon << 8) | 3);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_KNIFE_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);
}
return;
}
@@ -2048,7 +2044,7 @@ CPed::PlayHitSound(CPed *hitTo)
}
if (soundId != NO_SND)
- DMAudio.PlayOneShot(m_audioEntityId, soundId, (weapon << 8) | 3);
+ DMAudio.PlayOneShot(m_audioEntityId, soundId, (weapon << 8) | ENTITY_TYPE_PED);
}
// --MIAMI: Done
@@ -3567,7 +3563,7 @@ CPed::CollideWithPed(CPed *collideWith)
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
if (m_nPedState == PED_ATTACK)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_49, 0.0f);
}
} else {
// We're at his right side
@@ -3985,7 +3981,7 @@ CPed::DriveVehicle(void)
}
if (neededAngForWheelie >= 0.15f) {
if (bike->m_fBrakePedal <= 0.5f || velocityFwdDotProd <= 0.01f) {
- if (bike->m_fGasPedal > 0.5f && targetUDLean <= 0.0f && 0.3f * bike->pHandling->Transmission.fUnkMaxVelocity > velocityFwdDotProd) {
+ if (bike->m_fGasPedal > 0.5f && targetUDLean <= 0.0f && 0.3f * bike->pHandling->Transmission.fMaxCruiseVelocity > velocityFwdDotProd) {
targetUDLean = Min(0.1f, targetUDLean);
}
} else {
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 8220b370..f07d1ac7 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -22,10 +22,14 @@
#include "Script.h"
#include "Replay.h"
#include "PedPlacement.h"
+#include "VarConsole.h"
#define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f
bool CPlayerPed::bDontAllowWeaponChange;
+#ifndef MASTER
+bool CPlayerPed::bDebugPlayerInfo;
+#endif
const uint32 CPlayerPed::nSaveStructSize =
#ifdef COMPATIBLE_SAVES
@@ -61,7 +65,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
m_pWanted->Initialise();
m_pArrestingCop = nil;
m_currentWeapon = WEAPONTYPE_UNARMED;
- m_nSelectedWepSlot = 0;
+ m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
m_nSpeedTimer = 0;
m_bSpeedTimerFlag = false;
SetWeaponLockOnTarget(nil);
@@ -182,6 +186,11 @@ CPlayerPed::SetupPlayerPed(int32 index)
CWorld::Add(player);
player->m_wepAccuracy = 100;
+
+#ifndef MASTER
+ VarConsole.Add("Debug PlayerPed", &CPlayerPed::bDebugPlayerInfo, true);
+ VarConsole.Add("Tweak Vehicle Handling", &CVehicle::m_bDisplayHandlingInfo, true);
+#endif
}
// --MIAMI: Done
@@ -300,7 +309,7 @@ CPlayerPed::SetInitialState(void)
m_nLastPedState = PED_NONE;
m_animGroup = ASSOCGRP_PLAYER;
m_fMoveSpeed = 0.0f;
- m_nSelectedWepSlot = WEAPONTYPE_UNARMED;
+ m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
m_nEvadeAmount = 0;
m_pEvadingFrom = nil;
bIsPedDieAnimPlaying = false;
@@ -748,17 +757,20 @@ CPlayerPed::ProcessWeaponSwitch(CPad *padUsed)
&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER
&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_CAMERA) {
- for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) {
+ // I don't know what kind of loop that was
+ m_nSelectedWepSlot = m_currentWeapon - 1;
+ do {
if (m_nSelectedWepSlot < 0)
m_nSelectedWepSlot = TOTAL_WEAPON_SLOTS - 1;
- if (m_nSelectedWepSlot == 0)
+ if (m_nSelectedWepSlot == WEAPONSLOT_UNARMED)
break;
- if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {
+ if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed())
break;
- }
- }
+
+ --m_nSelectedWepSlot;
+ } while (m_nSelectedWepSlot != WEAPONSLOT_UNARMED);
}
}
}
@@ -772,17 +784,17 @@ spentAmmoCheck:
|| TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)
return;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR
- || GetWeapon(2).m_eWeaponType != WEAPONTYPE_DETONATOR_GRENADE)
- m_nSelectedWepSlot = m_currentWeapon - 1;
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR
+ && GetWeapon(WEAPONSLOT_PROJECTILE).m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE)
+ m_nSelectedWepSlot = WEAPONSLOT_PROJECTILE;
else
- m_nSelectedWepSlot = 2;
+ m_nSelectedWepSlot = m_currentWeapon - 1;
- for (; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) {
+ for (; m_nSelectedWepSlot >= WEAPONSLOT_UNARMED; --m_nSelectedWepSlot) {
// BUG: m_nSelectedWepSlot and GetWeapon(..) takes slot in VC but they compared them against weapon types in whole condition! jeez
#ifdef FIX_BUGS
- if (m_nSelectedWepSlot == 1 || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != 2) {
+ if (m_nSelectedWepSlot == WEAPONSLOT_MELEE || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != WEAPONSLOT_PROJECTILE) {
#else
if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && GetWeapon(WEAPONTYPE_BASEBALLBAT).m_eWeaponType == WEAPONTYPE_BASEBALLBAT
|| GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0
@@ -791,15 +803,16 @@ spentAmmoCheck:
goto switchDetectDone;
}
}
- m_nSelectedWepSlot = 0;
+ m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
}
}
switchDetectDone:
if (m_nSelectedWepSlot != m_currentWeapon) {
- if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT)
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT) {
RemoveWeaponAnims(m_currentWeapon, -1000.0f);
MakeChangesForNewWeapon(m_nSelectedWepSlot);
+ }
}
}
@@ -1775,7 +1788,7 @@ CPlayerPed::ProcessControl(void)
if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK) && !m_attachedTo) {
if (TheCamera.Using1stPersonWeaponMode()) {
if (padUsed)
- PlayerControlFighter(padUsed);
+ PlayerControlSniper(padUsed);
} else if (TheCamera.Cams[0].Using3rdPersonMouseCam()
#ifdef FREE_CAM
diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h
index 3c58f7f5..1b7158b5 100644
--- a/src/peds/PlayerPed.h
+++ b/src/peds/PlayerPed.h
@@ -15,7 +15,7 @@ public:
float m_fCurrentStamina;
float m_fMaxStamina;
float m_fStaminaProgress;
- int8 m_nSelectedWepSlot; // eWeaponType
+ int8 m_nSelectedWepSlot;
bool m_bSpeedTimerFlag;
uint8 m_nEvadeAmount;
uint32 m_nSpeedTimer; // m_nStandStillTimer?
@@ -46,6 +46,9 @@ public:
unsigned int m_nLastBusFareCollected;
static bool bDontAllowWeaponChange;
+#ifndef MASTER
+ static bool bDebugPlayerInfo;
+#endif
CPlayerPed();
~CPlayerPed();
diff --git a/src/render/Font.cpp b/src/render/Font.cpp
index d6a06db8..3517031d 100644
--- a/src/render/Font.cpp
+++ b/src/render/Font.cpp
@@ -297,12 +297,10 @@ CFont::Initialise(void)
CTxdStore::AddRef(ButtonsSlot);
CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(ButtonsSlot);
-#if 0 // unused
- ButtonSprite[BUTTON_UP].SetTexture("up");
- ButtonSprite[BUTTON_DOWN].SetTexture("down");
- ButtonSprite[BUTTON_LEFT].SetTexture("left");
- ButtonSprite[BUTTON_RIGHT].SetTexture("right");
-#endif
+ ButtonSprite[BUTTON_UP].SetTexture("thumblyu");
+ ButtonSprite[BUTTON_DOWN].SetTexture("thumblyd");
+ ButtonSprite[BUTTON_LEFT].SetTexture("thumblxl");
+ ButtonSprite[BUTTON_RIGHT].SetTexture("thumblxr");
ButtonSprite[BUTTON_CROSS].SetTexture("cross");
ButtonSprite[BUTTON_CIRCLE].SetTexture("circle");
ButtonSprite[BUTTON_SQUARE].SetTexture("square");
@@ -313,6 +311,8 @@ CFont::Initialise(void)
ButtonSprite[BUTTON_R1].SetTexture("r1");
ButtonSprite[BUTTON_R2].SetTexture("r2");
ButtonSprite[BUTTON_R3].SetTexture("r3");
+ ButtonSprite[BUTTON_RSTICK_LEFT].SetTexture("thumbrxl");
+ ButtonSprite[BUTTON_RSTICK_RIGHT].SetTexture("thumbrxr");
CTxdStore::PopCurrentTxd();
}
#endif // BUTTON_ICONS
@@ -411,9 +411,12 @@ CFont::DrawButton(float x, float y)
rect.bottom = Details.scaleY * 19.0f + y;
int vertexAlphaState;
+ void *raster;
RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState);
+ RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, Details.color.a));
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState);
}
}
@@ -926,14 +929,6 @@ CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, f
if (Details.slant != 0.0f && !IsJapanese())
y = (Details.slantRefX - x) * Details.slant + Details.slantRefY;
-#ifdef BUTTON_ICONS
- if (PS2Symbol != BUTTON_NONE) {
- DrawButton(x, y);
- x += Details.scaleY * 17.0f;
- PS2Symbol = BUTTON_NONE;
- }
-#endif
-
PrintChar(x, y, c);
x += GetCharacterSize(c);
if (c == 0 && (!NewLine || !IsJapanese())) // space
@@ -1132,12 +1127,10 @@ CFont::GetStringWidth(wchar *s, bool spaces)
s++;
#ifdef BUTTON_ICONS
switch (*s) {
-#if 0 // unused
case 'U':
case 'D':
case '<':
case '>':
-#endif
case 'X':
case 'O':
case 'Q':
@@ -1148,6 +1141,8 @@ CFont::GetStringWidth(wchar *s, bool spaces)
case 'J':
case 'V':
case 'C':
+ case '(':
+ case ')':
w += 17.0f * Details.scaleY;
break;
default:
@@ -1170,12 +1165,10 @@ CFont::GetStringWidth(wchar *s, bool spaces)
s++;
#ifdef BUTTON_ICONS
switch (*s) {
-#if 0 // unused
case 'U':
case 'D':
case '<':
case '>':
-#endif
case 'X':
case 'O':
case 'Q':
@@ -1186,6 +1179,8 @@ CFont::GetStringWidth(wchar *s, bool spaces)
case 'J':
case 'V':
case 'C':
+ case '(':
+ case ')':
w += 17.0f * Details.scaleY;
break;
default:
@@ -1280,12 +1275,10 @@ CFont::ParseToken(wchar *s, bool japShit)
case 'w': SetColor(CRGBA(175, 175, 175, 255)); break;
case 'y': SetColor(CRGBA(210, 196, 106, 255)); break;
#ifdef BUTTON_ICONS
-#if 0 // unused
case 'U': PS2Symbol = BUTTON_UP; break;
case 'D': PS2Symbol = BUTTON_DOWN; break;
case '<': PS2Symbol = BUTTON_LEFT; break;
case '>': PS2Symbol = BUTTON_RIGHT; break;
-#endif
case 'X': PS2Symbol = BUTTON_CROSS; break;
case 'O': PS2Symbol = BUTTON_CIRCLE; break;
case 'Q': PS2Symbol = BUTTON_SQUARE; break;
@@ -1296,6 +1289,8 @@ CFont::ParseToken(wchar *s, bool japShit)
case 'J': PS2Symbol = BUTTON_R1; break;
case 'V': PS2Symbol = BUTTON_R2; break;
case 'C': PS2Symbol = BUTTON_R3; break;
+ case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;
+ case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;
#endif
}
} else if (IsJapanese()) {
@@ -1342,12 +1337,10 @@ CFont::ParseToken(wchar *s)
#endif
case 'y': SetColor(CRGBA(255, 227, 79, 255)); Details.anonymous_23 = true; break;
#ifdef BUTTON_ICONS
-#if 0 // unused
case 'U': PS2Symbol = BUTTON_UP; break;
case 'D': PS2Symbol = BUTTON_DOWN; break;
case '<': PS2Symbol = BUTTON_LEFT; break;
case '>': PS2Symbol = BUTTON_RIGHT; break;
-#endif
case 'X': PS2Symbol = BUTTON_CROSS; break;
case 'O': PS2Symbol = BUTTON_CIRCLE; break;
case 'Q': PS2Symbol = BUTTON_SQUARE; break;
@@ -1358,6 +1351,8 @@ CFont::ParseToken(wchar *s)
case 'J': PS2Symbol = BUTTON_R1; break;
case 'V': PS2Symbol = BUTTON_R2; break;
case 'C': PS2Symbol = BUTTON_R3; break;
+ case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;
+ case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;
#endif
}
while(*s != '~') s++;
@@ -1450,6 +1445,24 @@ CFont::ParseToken(wchar* str, CRGBA &color, bool &flash, bool &bold)
color.g = 227;
color.b = 79;
break;
+#ifdef BUTTON_ICONS
+ case 'U': PS2Symbol = BUTTON_UP; break;
+ case 'D': PS2Symbol = BUTTON_DOWN; break;
+ case '<': PS2Symbol = BUTTON_LEFT; break;
+ case '>': PS2Symbol = BUTTON_RIGHT; break;
+ case 'X': PS2Symbol = BUTTON_CROSS; break;
+ case 'O': PS2Symbol = BUTTON_CIRCLE; break;
+ case 'Q': PS2Symbol = BUTTON_SQUARE; break;
+ case 'T': PS2Symbol = BUTTON_TRIANGLE; break;
+ case 'K': PS2Symbol = BUTTON_L1; break;
+ case 'M': PS2Symbol = BUTTON_L2; break;
+ case 'A': PS2Symbol = BUTTON_L3; break;
+ case 'J': PS2Symbol = BUTTON_R1; break;
+ case 'V': PS2Symbol = BUTTON_R2; break;
+ case 'C': PS2Symbol = BUTTON_R3; break;
+ case '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;
+ case ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;
+#endif
default:
break;
}
@@ -1503,7 +1516,17 @@ CFont::RenderFontBuffer()
color = RenderState.color;
}
if (*pRenderStateBufPointer.pStr == '~') {
+#ifdef BUTTON_ICONS
+ PS2Symbol = BUTTON_NONE;
+#endif
pRenderStateBufPointer.pStr = ParseToken(pRenderStateBufPointer.pStr, color, bFlash, bBold);
+#ifdef BUTTON_ICONS
+ if(PS2Symbol != BUTTON_NONE) {
+ DrawButton(textPosX, textPosY);
+ textPosX += Details.scaleY * 17.0f;
+ PS2Symbol = BUTTON_NONE;
+ }
+#endif
if (bFlash) {
if (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) {
Details.bFlashState = !Details.bFlashState;
diff --git a/src/render/Font.h b/src/render/Font.h
index d61ca6e7..36424bf5 100644
--- a/src/render/Font.h
+++ b/src/render/Font.h
@@ -95,12 +95,10 @@ enum
enum
{
BUTTON_NONE = -1,
-#if 0 // unused
BUTTON_UP,
BUTTON_DOWN,
BUTTON_LEFT,
BUTTON_RIGHT,
-#endif
BUTTON_CROSS,
BUTTON_CIRCLE,
BUTTON_SQUARE,
@@ -111,6 +109,8 @@ enum
BUTTON_R1,
BUTTON_R2,
BUTTON_R3,
+ BUTTON_RSTICK_LEFT,
+ BUTTON_RSTICK_RIGHT,
MAX_BUTTON_ICONS
};
#endif // BUTTON_ICONS
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index c4e78a91..3432f32c 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -24,6 +24,7 @@
#include "Stats.h"
#include "main.h"
#include "General.h"
+#include "VarConsole.h"
// --MIAMI: file done
@@ -1119,7 +1120,7 @@ void CHud::Draw()
CFont::SetPropOff();
CFont::SetFontStyle(FONT_LOCALE(CTheScripts::IntroTextLines[i].m_nFont));
- CFont::PrintString(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text);
+ CFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text);
}
}
for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) {
@@ -1461,7 +1462,7 @@ void CHud::DrawAfterFade()
CFont::SetPropOff();
CFont::SetFontStyle(line.m_nFont);
- CFont::PrintString(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text);
+ CFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text);
}
}
for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) {
@@ -1760,6 +1761,9 @@ void CHud::Initialise()
m_LastWanted = 0;
m_LastWeapon = 0;
+#ifndef MASTER
+ VarConsole.Add("Draw HUD", &m_Wants_To_Draw_Hud, false);
+#endif
CTxdStore::PopCurrentTxd();
}
diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp
index 2b15e75b..3ea5678c 100644
--- a/src/render/Occlusion.cpp
+++ b/src/render/Occlusion.cpp
@@ -9,6 +9,7 @@
#include "Draw.h"
#include "Timer.h"
#include "RwHelper.h"
+#include "VarConsole.h"
int32 COcclusion::NumOccludersOnMap;
int16 COcclusion::FarAwayList;
@@ -31,20 +32,20 @@ CVector gOccluderCoorsOnScreen[8];
CVector gOccluderCoors[8];
#ifndef MASTER
-bool bDisplayOccDebugStuff;
+bool bDispayOccDebugStuff; // disPAY, yeah
#endif
void
COcclusion::Init(void)
{
NumOccludersOnMap = 0;
+#ifndef MASTER
+ VarConsole.Add("Occlusion debug", &bDispayOccDebugStuff, true);
+#endif
FarAwayList = -1;
NearbyList = -1;
ListWalkThroughFA = -1;
PreviousListWalkThroughFA = -1;
-#ifndef MASTER
- bDisplayOccDebugStuff = false;
-#endif
}
void
@@ -458,7 +459,7 @@ bool COcclusion::IsPositionOccluded(CVector pos, float side) {
RwIm2DVertex vertexbufferT[2];
void COcclusion::Render() {
- if (!bDisplayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200))
+ if (!bDispayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200))
return;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
diff --git a/src/render/Occlusion.h b/src/render/Occlusion.h
index 8a444525..e0edef53 100644
--- a/src/render/Occlusion.h
+++ b/src/render/Occlusion.h
@@ -58,5 +58,5 @@ bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh);
bool CalcScreenCoors(CVector const &in, CVector *out);
#ifndef MASTER
-extern bool bDisplayOccDebugStuff;
+extern bool bDispayOccDebugStuff;
#endif \ No newline at end of file
diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp
index e8be23bd..2b1df555 100644
--- a/src/render/Shadows.cpp
+++ b/src/render/Shadows.cpp
@@ -25,6 +25,7 @@
#include "CutsceneObject.h"
#include "CutsceneShadow.h"
#include "Clock.h"
+#include "VarConsole.h"
#ifdef DEBUGMENU
SETTWEAKPATH("Shadows");
@@ -57,6 +58,9 @@ CStaticShadow CShadows::aStaticShadows [MAX_STATICSHADOWS];
CPolyBunch *CShadows::pEmptyBunchList;
CPermanentShadow CShadows::aPermanentShadows[MAX_PERMAMENTSHADOWS];
+#ifndef MASTER
+bool gbCountPolysInShadow;
+#endif
void
CShadows::Init(void)
@@ -154,6 +158,10 @@ CShadows::Init(void)
{
aPermanentShadows[i].m_nType = SHADOWTYPE_NONE;
}
+
+#ifndef MASTER
+ VarConsole.Add("Count polys in shadow", &gbCountPolysInShadow, true);
+#endif
}
void
diff --git a/src/render/VarConsole.cpp b/src/render/VarConsole.cpp
new file mode 100644
index 00000000..372a091a
--- /dev/null
+++ b/src/render/VarConsole.cpp
@@ -0,0 +1,786 @@
+#include "common.h"
+#include "VarConsole.h"
+#include "Font.h"
+#include "Pad.h"
+
+#define VAR_CONSOLE_PAD 1
+
+CVarConsole VarConsole;
+
+void
+CVarConsole::Initialise()
+{
+ m_nCountEntries = 0;
+ m_nCurPage = 1;
+ m_bIsOpen = false;
+ m_nCurEntry = 0;
+ m_nFirstEntryOnPage = 0;
+}
+
+void
+CVarConsole::Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pInt8Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_INT8;
+ m_aEntries[i].I8_step = step;
+ m_aEntries[i].I8_min = min;
+ m_aEntries[i].I8_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pInt16Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_INT16;
+ m_aEntries[i].I16_step = step;
+ m_aEntries[i].I16_min = min;
+ m_aEntries[i].I16_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pInt32Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_INT32;
+ m_aEntries[i].I32_step = step;
+ m_aEntries[i].I32_min = min;
+ m_aEntries[i].I32_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pInt64Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_INT64;
+ m_aEntries[i].I64_step = step;
+ m_aEntries[i].I64_min = min;
+ m_aEntries[i].I64_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pUint8Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_UINT8;
+ m_aEntries[i].I8_step = step;
+ m_aEntries[i].I8_min = min;
+ m_aEntries[i].I8_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pUint16Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_UINT16;
+ m_aEntries[i].I16_step = step;
+ m_aEntries[i].I16_min = min;
+ m_aEntries[i].I16_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pUint32Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_UINT32;
+ m_aEntries[i].I32_step = step;
+ m_aEntries[i].I32_min = min;
+ m_aEntries[i].I32_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pUint64Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_UINT64;
+ m_aEntries[i].I64_step = step;
+ m_aEntries[i].I64_min = min;
+ m_aEntries[i].I64_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, float *pVal, float step, float min, float max, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pFloatValue = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_FLOAT;
+ m_aEntries[i].F_step = step;
+ m_aEntries[i].F_min = min;
+ m_aEntries[i].F_max = max;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, bool *pVal, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pBoolValue = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_BOOL;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, bool8 *pVal, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pUint8Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_BOOL8;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, bool16 *pVal, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pUint16Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_BOOL16;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, bool32 *pVal, bool8 isVar)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pUint32Value = pVal;
+ m_aEntries[i].bAllowExceedBounds = isVar;
+ m_aEntries[i].VarType = VCE_TYPE_BOOL32;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Add(char *text, void (*pCallback)(void))
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ return;
+ }
+
+ m_aEntries[i].text = text;
+ m_aEntries[i].pCallback = pCallback;
+ m_aEntries[i].VarType = VCE_TYPE_FUNCTION;
+ m_nCountEntries++;
+}
+
+void
+CVarConsole::Remove(char *text)
+{
+ int i;
+ for (i = 0; i < m_nCountEntries; i++) {
+ if (m_aEntries[i].text == text)
+ {
+ for (int j = i; j < m_nCountEntries-1; j++)
+ m_aEntries[j] = m_aEntries[j+1];
+ m_nCountEntries--;
+ return;
+ }
+ }
+}
+
+void
+CVarConsole::SortPages()
+{
+ m_nNumPages = m_nCountEntries / 30 + 1;
+}
+
+void
+CVarConsole::Display()
+{
+ char s[256];
+ wchar ws[256];
+
+ CFont::SetColor(CRGBA(200, 200, 200, 255));
+ CFont::SetFontStyle(FONT_STANDARD);
+ CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.6f));
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
+ CFont::SetPropOn();
+ CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+ CFont::SetRightJustifyWrap(0.0f);
+ sprintf(s, "PAGE %d", m_nCurPage);
+ AsciiToUnicode(s, ws);
+ CFont::SetRightJustifyOn();
+ CFont::PrintString(SCREEN_SCALE_X(310.0f), SCREEN_SCALE_Y(30.0f), ws);
+ CFont::SetRightJustifyOff();
+ int y = 45;
+ for (int i = m_nFirstEntryOnPage; i < m_nCountEntries && i < m_nFirstEntryOnPage + 30; i++)
+ {
+ switch (m_aEntries[i].VarType)
+ {
+ case VCE_TYPE_INT8:
+ sprintf(s, "(%d) %s:I8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt8Value);
+ break;
+ case VCE_TYPE_INT16:
+ sprintf(s, "(%d) %s:I16:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt16Value);
+ break;
+ case VCE_TYPE_INT32:
+ sprintf(s, "(%d) %s:I32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt32Value);
+ break;
+ case VCE_TYPE_INT64:
+#ifdef FIX_BUGS
+ sprintf(s, "(%d) %s:I64:%lld", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt64Value);
+#else
+ sprintf(s, "(%d) %s:I64:%d", i + 1, m_aEntries[i].text, (int32)*m_aEntries[i].pInt64Value);
+#endif
+ break;
+ case VCE_TYPE_UINT8:
+ sprintf(s, "(%d) %s:U8:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint8Value);
+ break;
+ case VCE_TYPE_UINT16:
+ sprintf(s, "(%d) %s:U6:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint16Value);
+ break;
+ case VCE_TYPE_UINT32:
+ sprintf(s, "(%d) %s:U32:%d", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint32Value);
+ break;
+ case VCE_TYPE_UINT64:
+#ifdef FIX_BUGS
+ sprintf(s, "(%d) %s:U64:%llu", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint64Value);
+#else
+ sprintf(s, "(%d) %s:U64:%d", i + 1, m_aEntries[i].text, (uint32)*m_aEntries[i].pUint64Value);
+#endif
+ break;
+ case VCE_TYPE_FLOAT:
+ sprintf(s, "(%d) %s:F:%f", i + 1, m_aEntries[i].text, *m_aEntries[i].pFloatValue);
+ break;
+ case VCE_TYPE_BOOL:
+ if (*m_aEntries[i].pBoolValue)
+ sprintf(s, "(%d) %s:B:TRUE", i + 1, m_aEntries[i].text);
+ else
+ sprintf(s, "(%d) %s:B : FALSE", i + 1, m_aEntries[i].text);
+ break;
+ case VCE_TYPE_BOOL8:
+ if (*m_aEntries[i].pUint8Value == FALSE)
+ sprintf(s, "(%d) %s:B8:FALSE", i + 1, m_aEntries[i].text);
+ else
+ sprintf(s, "(%d) %s:B8:TRUE", i + 1, m_aEntries[i].text);
+ break;
+ case VCE_TYPE_BOOL16:
+ if (*m_aEntries[i].pUint16Value == FALSE)
+ sprintf(s, "(%d) %s:B16:FALSE", i + 1, m_aEntries[i].text);
+ else
+ sprintf(s, "(%d) %s:B16:TRUE", i + 1, m_aEntries[i].text);
+ break;
+ case VCE_TYPE_BOOL32:
+ if (*m_aEntries[i].pUint32Value == FALSE)
+ sprintf(s, "(%d) %s:B32:FALSE", i + 1, m_aEntries[i].text);
+ else
+ sprintf(s, "(%d) %s:B32:TRUE", i + 1, m_aEntries[i].text);
+ break;
+ case VCE_TYPE_FUNCTION:
+ sprintf(s, "(%d) %s:FUNCTION:call this function?", i + 1, m_aEntries[i].text);
+ break;
+ }
+ AsciiToUnicode(s, ws);
+ if (m_nCurEntry == i) {
+ CFont::SetBackgroundOn();
+#ifdef FIX_BUGS
+ CFont::SetBackgroundColor(CRGBA(128, 128, 128, 128));
+#endif
+ }
+#ifdef FIX_BUGS
+ else
+ CFont::SetBackgroundColor(CRGBA(128, 128, 128, 0));
+#endif
+
+ CFont::SetColor(CRGBA(200, 200, 200, 255));
+ CFont::PrintString(SCREEN_SCALE_X(30.0f), SCREEN_SCALE_Y(y), ws);
+ if (m_nCurEntry == i)
+ CFont::SetBackgroundOff();
+ y += 12;
+ }
+}
+
+void
+CVarConsole::ModifyLeft()
+{
+ CVarConsoleEntry &entry = m_aEntries[m_nCurEntry];
+ switch (entry.VarType)
+ {
+ case VCE_TYPE_INT8:
+ *entry.pInt8Value -= entry.I8_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt8Value < entry.I8_min)
+ *entry.pInt8Value = entry.I8_max;
+ } else {
+ if (*entry.pInt8Value < entry.I8_min)
+ *entry.pInt8Value = entry.I8_min;
+ }
+ break;
+ case VCE_TYPE_INT16:
+ *entry.pInt16Value -= entry.I16_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt16Value < entry.I16_min)
+ *entry.pInt16Value = entry.I16_max;
+ }
+ else {
+ if (*entry.pInt16Value < entry.I16_min)
+ *entry.pInt16Value = entry.I16_min;
+ }
+ break;
+ case VCE_TYPE_INT32:
+ *entry.pInt32Value -= entry.I32_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt32Value < entry.I32_min)
+ *entry.pInt32Value = entry.I32_max;
+ }
+ else {
+ if (*entry.pInt32Value < entry.I32_min)
+ *entry.pInt32Value = entry.I32_min;
+ }
+ break;
+ case VCE_TYPE_INT64:
+ *entry.pInt64Value -= entry.I64_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt64Value < entry.I64_min)
+ *entry.pInt64Value = entry.I64_max;
+ }
+ else {
+ if (*entry.pInt64Value < entry.I64_min)
+ *entry.pInt64Value = entry.I64_min;
+ }
+ break;
+ case VCE_TYPE_UINT8:
+ *entry.pUint8Value -= entry.I8_step;
+ if (entry.bAllowExceedBounds) {
+ if (*(int8*)entry.pUint8Value < entry.I8_min)
+ *entry.pUint8Value = entry.I8_max;
+ }
+ else {
+ if (*(int8*)entry.pUint8Value < entry.I8_min)
+ *entry.pUint8Value = entry.I8_min;
+ }
+ break;
+ case VCE_TYPE_UINT16:
+ *entry.pUint16Value -= entry.I16_step;
+ if (entry.bAllowExceedBounds) {
+ if (*(int16*)entry.pUint16Value < entry.I16_min)
+ *entry.pUint16Value = entry.I16_max;
+ }
+ else {
+ if (*(int16*)entry.pUint16Value < entry.I16_min)
+ *entry.pUint16Value = entry.I16_min;
+ }
+ break;
+ case VCE_TYPE_UINT32:
+ *entry.pUint32Value -= entry.I32_step;
+ if (entry.bAllowExceedBounds) {
+ if (*(int32*)entry.pUint32Value < entry.I32_min)
+ *entry.pUint32Value = entry.I32_max;
+ }
+ else {
+ if (*(int32*)entry.pUint32Value < entry.I32_min)
+ *entry.pUint32Value = entry.I32_min;
+ }
+ break;
+ case VCE_TYPE_UINT64:
+ *entry.pUint64Value -= entry.I64_step;
+ if (entry.bAllowExceedBounds) {
+ if (*(int64*)entry.pUint64Value < entry.I64_min)
+ *entry.pUint64Value = entry.I64_max;
+ }
+ else {
+ if (*(int64*)entry.pUint64Value < entry.I64_min)
+ *entry.pUint64Value = entry.I64_min;
+ }
+ break;
+ case VCE_TYPE_FLOAT:
+ *entry.pFloatValue -= entry.F_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pFloatValue < entry.F_min)
+ *entry.pFloatValue = entry.F_max;
+ }
+ else {
+ if (*entry.pFloatValue < entry.F_min)
+ *entry.pFloatValue = entry.F_min;
+ }
+ break;
+ case VCE_TYPE_BOOL:
+ if (entry.bAllowExceedBounds)
+ *entry.pBoolValue ^= true;
+ else
+ *entry.pBoolValue = false;
+ break;
+ case VCE_TYPE_BOOL8:
+ if (entry.bAllowExceedBounds)
+ *entry.pUint8Value = *entry.pUint8Value == false;
+ else
+ *entry.pUint8Value = false;
+ break;
+ case VCE_TYPE_BOOL16:
+ if (entry.bAllowExceedBounds)
+ *entry.pUint16Value = *entry.pUint16Value == false;
+ else
+ *entry.pUint16Value = false;
+ break;
+ case VCE_TYPE_BOOL32:
+ if (entry.bAllowExceedBounds)
+ *entry.pUint32Value = *entry.pUint32Value == false;
+ else
+ *entry.pUint32Value = false;
+ break;
+ case VCE_TYPE_FUNCTION:
+ entry.pCallback();
+ break;
+ default:
+ return;
+ }
+}
+
+void
+CVarConsole::ModifyRight()
+{
+ CVarConsoleEntry &entry = m_aEntries[m_nCurEntry];
+ switch (entry.VarType)
+ {
+ case VCE_TYPE_INT8:
+ *entry.pInt8Value += entry.I8_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt8Value > entry.I8_max)
+ *entry.pInt8Value = entry.I8_min;
+ }
+ else {
+ if (*entry.pInt8Value > entry.I8_max)
+ *entry.pInt8Value = entry.I8_max;
+ }
+ break;
+ case VCE_TYPE_INT16:
+ *entry.pInt16Value += entry.I16_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt16Value > entry.I16_max)
+ *entry.pInt16Value = entry.I16_min;
+ }
+ else {
+ if (*entry.pInt16Value > entry.I16_max)
+ *entry.pInt16Value = entry.I16_max;
+ }
+ break;
+ case VCE_TYPE_INT32:
+ *entry.pInt32Value += entry.I32_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt32Value > entry.I32_max)
+ *entry.pInt32Value = entry.I32_min;
+ }
+ else {
+ if (*entry.pInt32Value > entry.I32_max)
+ *entry.pInt32Value = entry.I32_max;
+ }
+ break;
+ case VCE_TYPE_INT64:
+ *entry.pInt64Value += entry.I64_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pInt64Value > entry.I64_max)
+ *entry.pInt64Value = entry.I64_min;
+ }
+ else {
+ if (*entry.pInt64Value > entry.I64_max)
+ *entry.pInt64Value = entry.I64_max;
+ }
+ break;
+ case VCE_TYPE_UINT8:
+ *entry.pUint8Value += entry.I8_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pUint8Value > (uint8)entry.I8_max)
+ *entry.pUint8Value = entry.I8_min;
+ }
+ else {
+ if (*entry.pUint8Value > (uint8)entry.I8_max)
+ *entry.pUint8Value = entry.I8_max;
+ }
+ break;
+ case VCE_TYPE_UINT16:
+ *entry.pUint16Value += entry.I16_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pUint16Value > (uint16)entry.I16_max)
+ *entry.pUint16Value = entry.I16_min;
+ }
+ else {
+ if (*entry.pUint16Value > (uint16)entry.I16_max)
+ *entry.pUint16Value = entry.I16_max;
+ }
+ break;
+ case VCE_TYPE_UINT32:
+ *entry.pUint32Value += entry.I32_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pUint32Value > (uint32)entry.I32_max)
+ *entry.pUint32Value = entry.I32_min;
+ }
+ else {
+ if (*entry.pUint32Value > (uint32)entry.I32_max)
+ *entry.pUint32Value = entry.I32_max;
+ }
+ break;
+ case VCE_TYPE_UINT64:
+ *entry.pUint64Value += entry.I64_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pUint64Value > (uint64)entry.I64_max)
+ *entry.pUint64Value = entry.I64_min;
+ }
+ else {
+ if (*entry.pUint64Value > (uint64)entry.I64_max)
+ *entry.pUint64Value = entry.I64_max;
+ }
+ break;
+ case VCE_TYPE_FLOAT:
+ *entry.pFloatValue += entry.F_step;
+ if (entry.bAllowExceedBounds) {
+ if (*entry.pFloatValue > entry.F_max)
+ *entry.pFloatValue = entry.F_min;
+ }
+ else {
+ if (*entry.pFloatValue > entry.F_max)
+ *entry.pFloatValue = entry.F_max;
+ }
+ break;
+ case VCE_TYPE_BOOL:
+ if (entry.bAllowExceedBounds)
+ *entry.pBoolValue ^= true;
+ else
+ *entry.pBoolValue = true;
+ break;
+ case VCE_TYPE_BOOL8:
+ if (entry.bAllowExceedBounds)
+ *entry.pUint8Value = *entry.pUint8Value == false;
+ else
+ *entry.pUint8Value = true;
+ break;
+ case VCE_TYPE_BOOL16:
+ if (entry.bAllowExceedBounds)
+ *entry.pUint16Value = *entry.pUint16Value == false;
+ else
+ *entry.pUint16Value = true;
+ break;
+ case VCE_TYPE_BOOL32:
+ if (entry.bAllowExceedBounds)
+ *entry.pUint32Value = *entry.pUint32Value == false;
+ else
+ *entry.pUint32Value = true;
+ break;
+ case VCE_TYPE_FUNCTION:
+ entry.pCallback();
+ break;
+ default:
+ return;
+ }
+}
+
+void
+CVarConsole::Enter()
+{
+ m_bIsOpen = true;
+}
+
+void
+CVarConsole::Exit()
+{
+ m_bIsOpen = false;
+}
+
+void
+CVarConsole::Input()
+{
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadDownJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadDown())
+ {
+ m_nCurEntry++;
+ if (m_nCurEntry < m_nCountEntries)
+ {
+ if (m_nCurEntry > m_nFirstEntryOnPage + 29)
+ {
+ m_nFirstEntryOnPage = m_nCurEntry;
+ ++m_nCurPage;
+ }
+ }
+ else
+ {
+ m_nCurEntry = m_nCountEntries - 1;
+ }
+ }
+
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadUpJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadUp())
+ {
+ m_nCurEntry--;
+ if (m_nCurEntry < m_nFirstEntryOnPage)
+ {
+ m_nFirstEntryOnPage = m_nCurEntry - 29;
+ --m_nCurPage;
+ }
+ if (m_nFirstEntryOnPage < 0)
+ {
+ m_nCurEntry = 0;
+ m_nFirstEntryOnPage = 0;
+ m_nCurPage = 1;
+ }
+ }
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetSquare())
+ ModifyLeft();
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetTriangle())
+ ModifyRight();
+
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadLeftJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadLeft())
+ ModifyLeft();
+
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadRightJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadRight())
+ ModifyRight();
+
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder2JustDown())
+ {
+ if (m_nCurPage > 1)
+ {
+ m_nCurPage--;
+ m_nFirstEntryOnPage -= 30;
+ m_nCurEntry = m_nFirstEntryOnPage;
+ if (m_nFirstEntryOnPage < 0)
+ {
+ m_nFirstEntryOnPage = 0;
+ m_nCurEntry = m_nFirstEntryOnPage;
+ m_nCurPage = 1;
+ }
+ }
+ }
+
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder2JustDown())
+ {
+ if (m_nCurPage < m_nNumPages)
+ {
+ m_nCurPage++;
+ m_nFirstEntryOnPage += 30;
+ m_nCurEntry = m_nFirstEntryOnPage;
+ if (m_nFirstEntryOnPage >= m_nCountEntries)
+ {
+ m_nFirstEntryOnPage -= 30;
+ m_nCurEntry = m_nFirstEntryOnPage;
+ m_nCurPage--;
+ }
+ }
+ }
+
+ if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())
+ Exit();
+}
+
+void
+CVarConsole::Process()
+{
+ Input();
+ SortPages();
+ Display();
+}
+
+bool8
+CVarConsole::Open()
+{
+ return m_bIsOpen;
+}
+
+void
+CVarConsole::Check()
+{
+ if (Open())
+ Process();
+ else if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())
+ Enter();
+} \ No newline at end of file
diff --git a/src/render/VarConsole.h b/src/render/VarConsole.h
new file mode 100644
index 00000000..5179a10d
--- /dev/null
+++ b/src/render/VarConsole.h
@@ -0,0 +1,92 @@
+#pragma once
+
+enum eVarConsoleEntryType
+{
+ VCE_TYPE_INT8,
+ VCE_TYPE_INT16,
+ VCE_TYPE_INT32,
+ VCE_TYPE_INT64,
+ VCE_TYPE_UINT8,
+ VCE_TYPE_UINT16,
+ VCE_TYPE_UINT32,
+ VCE_TYPE_UINT64,
+ VCE_TYPE_FLOAT,
+ VCE_TYPE_BOOL,
+ VCE_TYPE_BOOL8,
+ VCE_TYPE_BOOL16,
+ VCE_TYPE_BOOL32,
+ VCE_TYPE_FUNCTION,
+};
+
+struct CVarConsoleEntry
+{
+ char *text;
+ int8 *pInt8Value;
+ int16 *pInt16Value;
+ int32 *pInt32Value;
+ int64 *pInt64Value;
+ uint8 *pUint8Value;
+ uint16 *pUint16Value;
+ uint32 *pUint32Value;
+ uint64 *pUint64Value;
+ float *pFloatValue;
+ bool *pBoolValue;
+ void (*pCallback)(void);
+ int8 I8_step, I8_max, I8_min;
+ int16 I16_step, I16_max, I16_min;
+ int32 I32_step, I32_max, I32_min;
+ int64 I64_step, I64_max, I64_min;
+ float F_step, F_max, F_min;
+ bool8 bAllowExceedBounds;
+ uint8 VarType;
+};
+
+
+class CVarConsole
+{
+ int32 m_nCountEntries;
+ bool8 m_bIsOpen;
+ int32 m_nCurEntry;
+ int32 m_nFirstEntryOnPage;
+ int32 m_nCurPage;
+ int32 m_nNumPages;
+ CVarConsoleEntry m_aEntries[91];
+public:
+#ifdef FIX_BUGS
+ CVarConsole() { Initialise(); }
+#endif
+ void Initialise();
+ void Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);
+ void Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);
+ void Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);
+ void Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);
+ void Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);
+ void Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);
+ void Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);
+ void Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);
+ void Add(char *text, float *pVal, float step, float min, float max, bool8 isVar);
+ void Add(char *text, bool *pVal, bool8 isVar);
+ void Add(char *text, bool8 *pVal, bool8 isVar);
+ void Add(char *text, bool16 *pVal, bool8 isVar);
+ void Add(char *text, bool32 *pVal, bool8 isVar);
+ void Add(char *text, void (*pVar)(void));
+
+ void Remove(char *text);
+
+ void SortPages();
+ void Display();
+
+ void ModifyLeft();
+ void ModifyRight();
+
+ void Enter();
+ void Exit();
+
+ void Input();
+ void Process();
+
+ bool8 Open();
+ void Check();
+};
+
+extern CVarConsole VarConsole; \ No newline at end of file
diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp
index b698a5b2..854653f0 100644
--- a/src/render/WaterLevel.cpp
+++ b/src/render/WaterLevel.cpp
@@ -58,7 +58,7 @@ int32 CWaterLevel::m_nRenderWaterLayers;
RpAtomic *CWaterLevel::ms_pWavyAtomic;
RpAtomic *CWaterLevel::ms_pMaskAtomic;
-//"Custom" Donīt Render Water Toggle
+//"Custom" Don't Render Water Toggle
bool gbDontRenderWater;
@@ -895,7 +895,7 @@ SectorRadius(float fSize)
void
CWaterLevel::RenderWater()
{
-//"Custom" Donīt Render Water Toggle
+//"Custom" Don't Render Water Toggle
#ifndef MASTER
if (gbDontRenderWater)
return;
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index 52e93951..17c45fcd 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -226,15 +226,15 @@ void CWeather::Update(void)
// Rain
float fNewRain;
if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) {
- // if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
- fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f;
+ // if raining for >1 hour, values: 0, 0.33, switching every ~16.5s
+ fNewRain = (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.33f;
if (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) {
if (InterpolationValue < 0.4f)
// if rain has just started (<24 minutes), always 0.5
fNewRain = 0.5f;
else
- // if rain is ongoing for >24 minutes, values: 0.25, 0.5, 0.75, 1.0, switching every ~16.5s
- fNewRain = 0.25f + ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.25f;
+ // if rain is ongoing for >24 minutes, values: 0.25, 0.5, switching every ~16.5s
+ fNewRain = 0.25f + (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.25f;
}
fNewRain = Max(fNewRain, 0.5f);
}
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 8a771a40..a946bacb 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -252,12 +252,15 @@ CVector vecHunterRocketPos(2.5f, 1.0f, -0.5f);
CVector vecDAMAGE_ENGINE_POS_SMALL(-0.1f, -0.1f, 0.0f);
CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f);
+#pragma optimize("", off) // a workaround for another compiler bug
+
void
CAutomobile::ProcessControl(void)
{
int i;
float wheelRot;
CColModel *colModel;
+ float brake = 0.0f;
if(bUsingSpecialColModel)
colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
@@ -448,7 +451,7 @@ CAutomobile::ProcessControl(void)
m_fBrakePedal = 1.0f;
m_fGasPedal = 0.0f;
}
- if(CPad::GetPad(0)->WeaponJustDown())
+ if(CPad::GetPad(0)->CarGunJustDown())
ActivateBomb();
break;
@@ -680,7 +683,6 @@ CAutomobile::ProcessControl(void)
AutoPilot.m_nCarMission == MISSION_PLANE_FLYTOCOORS)
skipPhysics = true;
- float brake;
if(skipPhysics){
bHasContacted = false;
bIsInSafePosition = false;
@@ -835,11 +837,16 @@ CAutomobile::ProcessControl(void)
if(bAudioChangingGear && m_fGasPedal > 0.4f && m_fBrakePedal < 0.1f && fwdSpeed > 0.15f &&
this == FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){
- if(GetStatus() == STATUS_PLAYER && pHandling->Flags & HANDLING_IS_BUS){
+ if(GetStatus() == STATUS_PLAYER && !(pHandling->Flags & HANDLING_IS_BUS)){
if(m_nBusDoorTimerEnd == 0)
m_nBusDoorTimerEnd = 1000;
- else if(m_nBusDoorTimerEnd > CTimer::GetTimeStepInMilliseconds())
- m_nBusDoorTimerEnd -= CTimer::GetTimeStepInMilliseconds();
+ else {
+ uint32 timeStepInMs = CTimer::GetTimeStepInMilliseconds();
+ if(m_nBusDoorTimerEnd > timeStepInMs)
+ m_nBusDoorTimerEnd -= timeStepInMs;
+ else
+ m_nBusDoorTimerEnd = 0;
+ }
}
if((m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[2] < 1.0f) &&
@@ -1676,8 +1683,8 @@ CAutomobile::ProcessControl(void)
Abs(m_vecMoveSpeed.y) < 0.005f &&
Abs(m_vecMoveSpeed.z) < 0.005f &&
!(m_fDamageImpulse > 0.0f && m_pDamageEntity == FindPlayerPed()) &&
- (m_aSuspensionSpringRatioPrev[0] < 1.0f && m_aSuspensionSpringRatioPrev[1] < 1.0f &&
- m_aSuspensionSpringRatioPrev[2] < 1.0f && m_aSuspensionSpringRatioPrev[3] < 1.0f)){
+ (m_aSuspensionSpringRatioPrev[0] < 1.0f || m_aSuspensionSpringRatioPrev[1] < 1.0f ||
+ m_aSuspensionSpringRatioPrev[2] < 1.0f || m_aSuspensionSpringRatioPrev[3] < 1.0f)){
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
m_vecTurnSpeed.z = 0.0f;
}
@@ -1701,6 +1708,8 @@ CAutomobile::ProcessControl(void)
}
}
+#pragma optimize("", on)
+
void
CAutomobile::Teleport(CVector pos)
{
@@ -5786,7 +5795,7 @@ CAutomobile::PopBootUsingPhysics(void)
case DOOR_STATUS_OK:
case DOOR_STATUS_SMASHED:
Damage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_SWINGING);
- Doors[DOOR_BOOT].m_fAngle = -2.0f;
+ Doors[DOOR_BOOT].m_fAngVel = -2.0f;
}
void
diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp
index 0cfbedc1..19e95a6e 100644
--- a/src/vehicles/Bike.cpp
+++ b/src/vehicles/Bike.cpp
@@ -2694,7 +2694,7 @@ CBike::KnockOffRider(eWeaponType weapon, uint8 direction, CPed *ped, bool bGetBa
switch(direction){
case 0: anim = ANIM_KO_SKID_BACK; break;
case 1: anim = ANIM_KD_RIGHT; break;
- case 2: anim = ANIM_KO_SKID_FRONT; break;
+ case 2: anim = ANIM_BIKE_FALL_R; break;
case 3: anim = ANIM_KD_LEFT; break;
}
if(m_nWheelsOnGround == 0)
diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp
index b8c8566c..611ddcc9 100644
--- a/src/vehicles/HandlingMgr.cpp
+++ b/src/vehicles/HandlingMgr.cpp
@@ -300,7 +300,7 @@ cHandlingDataMgr::LoadHandlingData(void)
case 11: handling->fTractionBias = atof(word); break;
case 12: handling->Transmission.nNumberOfGears = atoi(word); break;
case 13: handling->Transmission.fMaxVelocity = atof(word); break;
- case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4f; break;
+ case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4; break;
case 15: handling->Transmission.nDriveType = word[0]; break;
case 16: handling->Transmission.nEngineType = word[0]; break;
case 17: handling->fBrakeDeceleration = atof(word); break;
@@ -362,26 +362,32 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass;
handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * GRAVITY*handling->fMass;
- // What the hell is going on here?
- specificVolume = handling->Dimension.x*handling->Dimension.z*0.5f / handling->fMass; // ?
+ // Don't quite understand this. What seems to be going on is that
+ // we calculate a drag (air resistance) deceleration for a given velocity and
+ // find the intersection between that and the max engine acceleration.
+ // at that point the car cannot accelerate any further and we've found the max velocity.
a = 0.0f;
b = 100.0f;
velocity = handling->Transmission.fMaxVelocity;
while(a < b && velocity > 0.0f){
velocity -= 0.01f;
+ // what's the 1/6?
a = handling->Transmission.fEngineAcceleration/6.0f;
- b = -velocity * (1.0f/(specificVolume * sq(velocity) + 1.0f) - 1.0f);
+ // no density or drag coefficient here...
+ float a_drag = 0.5f*SQR(velocity) * handling->Dimension.x*handling->Dimension.z / handling->fMass;
+ // can't make sense of this... maybe v - v/(drag + 1) ? but that doesn't make so much sense either
+ b = -velocity * (1.0f/(a_drag + 1.0f) - 1.0f);
}
if(handling->nIdentifier == HANDLING_RCBANDIT){
- handling->Transmission.fUnkMaxVelocity = handling->Transmission.fMaxVelocity;
+ handling->Transmission.fMaxCruiseVelocity = handling->Transmission.fMaxVelocity;
handling->Transmission.fMaxReverseVelocity = -handling->Transmission.fMaxVelocity;
}else if(handling->nIdentifier >= HANDLING_BIKE && handling->nIdentifier <= HANDLING_FREEWAY){
- handling->Transmission.fUnkMaxVelocity = velocity;
+ handling->Transmission.fMaxCruiseVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f;
handling->Transmission.fMaxReverseVelocity = -0.05f;
}else{
- handling->Transmission.fUnkMaxVelocity = velocity;
+ handling->Transmission.fMaxCruiseVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f;
handling->Transmission.fMaxReverseVelocity = -0.2f;
}
diff --git a/src/vehicles/Transmission.cpp b/src/vehicles/Transmission.cpp
index cc994ac6..b3e1af7d 100644
--- a/src/vehicles/Transmission.cpp
+++ b/src/vehicles/Transmission.cpp
@@ -123,7 +123,7 @@ cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, fl
else
fCheat = 1.0f;
float targetVelocity = Gears[gear].fMaxVelocity*speedMul*fCheat;
- float accel = fEngineAcceleration*accelMul * (targetVelocity - fVelocity)/Abs(targetVelocity);
+ float accel = (targetVelocity - fVelocity) * (fEngineAcceleration*accelMul) / Abs(targetVelocity);
if(Abs(fVelocity) < Abs(Gears[gear].fMaxVelocity*fCheat))
fAcceleration = gasPedal * accel * CTimer::GetTimeStep();
else
diff --git a/src/vehicles/Transmission.h b/src/vehicles/Transmission.h
index 8eeef1e8..a3d15513 100644
--- a/src/vehicles/Transmission.h
+++ b/src/vehicles/Transmission.h
@@ -18,7 +18,7 @@ public:
uint8 Flags;
float fEngineAcceleration;
float fMaxVelocity;
- float fUnkMaxVelocity;
+ float fMaxCruiseVelocity;
float fMaxReverseVelocity;
float fCurVelocity;
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 325eb160..1849fd7f 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -48,6 +48,9 @@ bool CVehicle::bAllTaxisHaveNitro;
bool CVehicle::m_bDisableMouseSteering = true;
bool CVehicle::bDisableRemoteDetonation;
bool CVehicle::bDisableRemoteDetonationOnContact;
+#ifndef MASTER
+bool CVehicle::m_bDisplayHandlingInfo;
+#endif
void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); }
void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); }
@@ -146,6 +149,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_nAlarmState = 0;
m_nDoorLock = CARLOCK_UNLOCKED;
m_nLastWeaponDamage = -1;
+ m_pLastDamageEntity = nil;
m_fMapObjectHeightAhead = m_fMapObjectHeightBehind = 0.0f;
m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this);
if(m_audioEntityId >= 0)
@@ -836,11 +840,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
if(IsBike())
brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f);
else if(pHandling->fMass < 500.0f)
- brake = mod_HandlingManager.fWheelFriction / m_fMass;
+ brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;
else if(GetModelIndex() == MI_RCBANDIT)
- brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;
+ brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;
else
- brake = mod_HandlingManager.fWheelFriction / m_fMass;
+ brake = mod_HandlingManager.fWheelFriction / pHandling->fMass;
#ifdef FIX_BUGS
brake *= CTimer::GetTimeStepFix();
#endif
@@ -1232,7 +1236,7 @@ CVehicle::InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage
if (m_randomSeed < DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE) {
CCarCtrl::SwitchVehicleToRealPhysics(this);
AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * pHandling->Transmission.fUnkMaxVelocity;
+ AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * pHandling->Transmission.fMaxCruiseVelocity;
SetStatus(STATUS_PHYSICS);
}
}
@@ -1873,7 +1877,7 @@ CVehicle::AddPassenger(CPed *passenger)
int i;
if(IsBike())
- ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
+ ApplyTurnForce(-0.02f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
else
ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
passenger->GetPosition().x - GetPosition().x,
@@ -1896,7 +1900,7 @@ CVehicle::AddPassenger(CPed *passenger, uint8 n)
return AddPassenger(passenger);
if(IsBike())
- ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
+ ApplyTurnForce(-0.02f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
else
ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
passenger->GetPosition().x - GetPosition().x,
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index a42106cc..7388bfab 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -402,6 +402,9 @@ public:
static bool m_bDisableMouseSteering;
static bool bDisableRemoteDetonation;
static bool bDisableRemoteDetonationOnContact;
+#ifndef MASTER
+ static bool m_bDisplayHandlingInfo;
+#endif
};
void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);