From a51757429e0b6f71f59fd90c87203aa0d7fa0a72 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 6 Jan 2021 15:46:59 +0200 Subject: [PATCH 01/20] Implementing our own WAV decoder to replace SndFile --- src/audio/oal/stream.cpp | 357 ++++++++++++++++++++++++++++++++++++--- src/core/config.h | 1 + 2 files changed, 330 insertions(+), 28 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index ff3fed68..6f06a4d4 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -8,10 +8,14 @@ #include #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 +#endif #include #endif @@ -78,6 +82,290 @@ public: 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* pFile; + bool bIsOpen; + tFormatHeader FormatHeader; + + uint32 DataStartOffset; + uint32 SampleCount; + uint32 SamplesPerBlock; + + // ADPCM things + uint8 *AdpcmBlock; + int16 **buffers; + CImaADPCMDecoder* decoders; + + void Close() + { + if (pFile) { + fclose(pFile); + pFile = nil; + } + if (AdpcmBlock) delete AdpcmBlock; + if (buffers) delete buffers; + if (decoders) delete decoders; + } + +public: + CWavFile(const char* path) : bIsOpen(false), DataStartOffset(0), SampleCount(0), SamplesPerBlock(0), AdpcmBlock(nil), buffers(nil), decoders(nil) + { + pFile = fopen(path, "rb"); + if (!pFile) return; + +#define CLOSE_ON_ERROR(op)\ + if (op) { \ + Close(); \ + return; \ + } + + tDataHeader DataHeader; + + CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0); + CLOSE_ON_ERROR(DataHeader.ID != 'FFIR'); + + int WAVE; + CLOSE_ON_ERROR(fread(&WAVE, 4, 1, pFile) == 0); + CLOSE_ON_ERROR(WAVE != 'EVAW') + CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0); + CLOSE_ON_ERROR(DataHeader.ID != ' tmf'); + + CLOSE_ON_ERROR(fread(&FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, pFile) == 0); + CLOSE_ON_ERROR(DataHeader.Size > sizeof(tFormatHeader)); + + switch (FormatHeader.AudioFormat) + { + case WAVEFMT_XBOX_ADPCM: + FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM; + case WAVEFMT_IMA_ADPCM: + SamplesPerBlock = (FormatHeader.BlockAlign / FormatHeader.NumChannels - 4) * 2 + 1; + AdpcmBlock = new uint8[FormatHeader.BlockAlign]; + buffers = new int16*[FormatHeader.NumChannels]; + decoders = new CImaADPCMDecoder[FormatHeader.NumChannels]; + break; + case WAVEFMT_PCM: + SamplesPerBlock = 1; + if (FormatHeader.BitsPerSample != 16) + { + debug("Unsupported PCM (%d bits), only signed 16-bit is supported (%s)\n", FormatHeader.BitsPerSample, path); + return; + } + break; + default: + debug("Unsupported wav format 0x%x (%s)\n", FormatHeader.AudioFormat, path); + return; + } + + while (true) { + CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0); + if (DataHeader.ID == 'atad') + break; + fseek(pFile, DataHeader.Size, SEEK_CUR); + } + + DataStartOffset = ftell(pFile); + SampleCount = DataHeader.Size / FormatHeader.BlockAlign * SamplesPerBlock; + + bIsOpen = true; +#undef CLOSE_ON_ERROR + } + + ~CWavFile() + { + Close(); + } + + bool IsOpened() + { + return bIsOpen; + } + + uint32 GetSampleSize() + { + return sizeof(uint16); + } + + uint32 GetSampleCount() + { + return SampleCount; + } + + uint32 GetSampleRate() + { + return FormatHeader.SampleRate; + } + + uint32 GetChannels() + { + return FormatHeader.NumChannels; + } + + void Seek(uint32 milliseconds) + { + if (!IsOpened()) return; + fseek(pFile, DataStartOffset + ms2samples(milliseconds) / SamplesPerBlock * FormatHeader.BlockAlign, SEEK_SET); + } + + uint32 Tell() + { + if (!IsOpened()) return 0; + return samples2ms((ftell(pFile) - DataStartOffset) / FormatHeader.BlockAlign * SamplesPerBlock); + } + +#define SAMPLES_IN_LINE (8) + + uint32 Decode(void* buffer) + { + if (!IsOpened()) return 0; + + if (FormatHeader.AudioFormat == WAVEFMT_PCM) + { + uint32 size = fread(buffer, 1, GetBufferSize(), pFile); + if (FormatHeader.NumChannels == 2) + SortStereoBuffer.SortStereo(buffer, size); + return size; + } + else if (FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM) + { + uint32 MaxSamples = GetBufferSamples() / FormatHeader.NumChannels; + uint32 CurSample = (ftell(pFile) - DataStartOffset) / FormatHeader.BlockAlign * SamplesPerBlock; + + MaxSamples = Min(MaxSamples, SampleCount - CurSample); + MaxSamples = MaxSamples / SamplesPerBlock * SamplesPerBlock; + uint32 OutBufSizePerChannel = MaxSamples * GetSampleSize(); + uint32 OutBufSize = OutBufSizePerChannel * FormatHeader.NumChannels; + int16** buffers = new int16*[FormatHeader.NumChannels]; + CImaADPCMDecoder* decoders = new CImaADPCMDecoder[FormatHeader.NumChannels]; + for (uint32 i = 0; i < FormatHeader.NumChannels; i++) + buffers[i] = (int16*)((int8*)buffer + OutBufSizePerChannel * i); + + uint32 samplesRead = 0; + while (samplesRead < MaxSamples) + { + uint8* AdpcmBuf = AdpcmBlock; + if (fread(AdpcmBlock, 1, FormatHeader.BlockAlign, pFile) == 0) + return 0; + + for (uint32 i = 0; i < FormatHeader.NumChannels; i++) + { + int16 Sample = *(int16*)AdpcmBuf; + AdpcmBuf += sizeof(int16); + int16 Step = *(int16*)AdpcmBuf; + AdpcmBuf += sizeof(int16); + decoders[i].Init(Sample, Step); + *(buffers[i]) = Sample; + buffers[i]++; + } + samplesRead++; + for (uint32 s = 1; s < SamplesPerBlock; s += SAMPLES_IN_LINE) + { + for (uint32 i = 0; i < FormatHeader.NumChannels; i++) + { + decoders[i].Decode(AdpcmBuf, buffers[i], SAMPLES_IN_LINE / 2); + AdpcmBuf += SAMPLES_IN_LINE / 2; + buffers[i] += SAMPLES_IN_LINE; + } + samplesRead += SAMPLES_IN_LINE; + } + } + return OutBufSize; + } + return 0; + } +}; + +#ifdef AUDIO_OAL_USE_SNDFILE class CSndFile : public IDecoder { SNDFILE *m_pfSound; @@ -146,6 +434,7 @@ public: return size; } }; +#endif #ifdef _WIN32 // fuzzy seek eliminates stutter when playing ADF but spams errors a lot (nothing breaks though) @@ -287,7 +576,7 @@ public: static short quantize(double sample) { int a = int(sample + 0.5); - return short(clamp(int(sample + 0.5), -32768, 32767)); + return short(clamp(a, -32768, 32767)); } void Decode(void* _inbuf, int16* _outbuf, size_t size) @@ -343,6 +632,7 @@ class CVbFile : public IDecoder size_t m_CurrentBlock; uint8** ppTempBuffers; + int16** buffers; void ReadBlock(int32 block = -1) { @@ -356,22 +646,24 @@ class CVbFile : public IDecoder } public: - CVbFile(const char* path, uint32 nSampleRate = 32000, uint8 nChannels = 2) : m_nSampleRate(nSampleRate), m_nChannels(nChannels) + CVbFile(const char* path, uint32 nSampleRate = 32000, uint8 nChannels = 2) : m_nSampleRate(nSampleRate), m_nChannels(nChannels), decoders(nil), ppTempBuffers(nil), buffers(nil), + m_FileSize(0), m_nNumberOfBlocks(0), m_bBlockRead(false), m_LineInBlock(0), m_CurrentBlock(0) { pFile = fopen(path, "rb"); - if (pFile) { - fseek(pFile, 0, SEEK_END); - m_FileSize = ftell(pFile); - fseek(pFile, 0, SEEK_SET); - m_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE); - decoders = new CVagDecoder[nChannels]; - m_CurrentBlock = 0; - m_LineInBlock = 0; - m_bBlockRead = false; - ppTempBuffers = new uint8 * [nChannels]; - for (uint8 i = 0; i < nChannels; i++) - ppTempBuffers[i] = new uint8[VB_BLOCK_SIZE]; - } + if (!pFile) return; + + fseek(pFile, 0, SEEK_END); + m_FileSize = ftell(pFile); + fseek(pFile, 0, SEEK_SET); + m_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE); + decoders = new CVagDecoder[nChannels]; + m_CurrentBlock = 0; + m_LineInBlock = 0; + m_bBlockRead = false; + ppTempBuffers = new uint8*[nChannels]; + buffers = new int16*[nChannels]; + for (uint8 i = 0; i < nChannels; i++) + ppTempBuffers[i] = new uint8[VB_BLOCK_SIZE]; } ~CVbFile() @@ -383,6 +675,7 @@ public: for (int i = 0; i < m_nChannels; i++) delete ppTempBuffers[i]; delete ppTempBuffers; + delete buffers; } } @@ -416,14 +709,14 @@ public: { if (!IsOpened()) return; uint32 samples = ms2samples(milliseconds); - int32 block = samples / NUM_VAG_SAMPLES_IN_BLOCK; + uint32 block = samples / NUM_VAG_SAMPLES_IN_BLOCK; if (block > m_nNumberOfBlocks) { samples = 0; block = 0; } if (block != m_CurrentBlock) - ReadBlock(block); + m_bBlockRead = false; uint32 remainingSamples = samples - block * NUM_VAG_SAMPLES_IN_BLOCK; uint32 newLine = remainingSamples / VAG_SAMPLES_IN_LINE / VAG_LINE_SIZE; @@ -432,7 +725,7 @@ public: { m_CurrentBlock = block; m_LineInBlock = newLine; - for (int i = 0; i < GetChannels(); i++) + for (uint32 i = 0; i < GetChannels(); i++) decoders[i].ResetState(); } @@ -455,18 +748,19 @@ public: if (m_CurrentBlock == m_nNumberOfBlocks) return 0; int size = 0; - int numberOfRequiredLines = GetBufferSamples() / GetChannels() / VAG_SAMPLES_IN_LINE; + 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(); if (numberOfRequiredLines > numberOfRemainingLines) numberOfRemainingLines = numberOfRemainingLines; - int16* buffers[2] = { (int16*)buffer, &((int16*)buffer)[bufSizePerChannel / GetSampleSize()] }; + for (uint32 i = 0; i < m_nChannels; i++) + buffers[i] = (int16*)((int8*)buffer + bufSizePerChannel * i); while (size < bufSizePerChannel) { - for (int i = 0; i < GetChannels(); i++) + for (uint32 i = 0; i < m_nChannels; i++) { decoders[i].Decode(ppTempBuffers[i] + m_LineInBlock * VAG_LINE_SIZE, buffers[i], VAG_LINE_SIZE); buffers[i] += VAG_SAMPLES_IN_LINE; @@ -483,7 +777,7 @@ public: } } - return bufSizePerChannel * GetChannels(); + return bufSizePerChannel * m_nChannels; } }; #else @@ -676,7 +970,11 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU 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")) @@ -979,12 +1277,15 @@ void CStream::Update() // Relying a lot on left buffer states in here - //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]); + 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_pAlSources[0], AL_LOOPING, &looping); diff --git a/src/core/config.h b/src/core/config.h index 8fd3bc1c..139feddf 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -360,6 +360,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 From d9e2b1f0deff2c1f2962ff8c54c3439982055073 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Wed, 6 Jan 2021 17:24:22 +0100 Subject: [PATCH 02/20] Remove fastmath from premake's config --- premake5.lua | 4 ---- 1 file changed, 4 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" From 2bcb2a40e48616b6fae57a530254f2f1dcc15f2e Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Wed, 6 Jan 2021 17:57:43 +0100 Subject: [PATCH 03/20] Small fixes for new wav decoder --- src/audio/oal/stream.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 6f06a4d4..ce0698c2 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -193,9 +193,9 @@ class CWavFile : public IDecoder fclose(pFile); pFile = nil; } - if (AdpcmBlock) delete AdpcmBlock; - if (buffers) delete buffers; - if (decoders) delete decoders; + if (AdpcmBlock) delete[] AdpcmBlock; + if (buffers) delete[] buffers; + if (decoders) delete[] decoders; } public: From ff9d6e4fd69745cca8f1bc8be33fd1d19420c485 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Wed, 6 Jan 2021 18:15:32 +0100 Subject: [PATCH 04/20] Fixes for CVbFile --- src/audio/oal/stream.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index ce0698c2..33f5bda9 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -671,11 +671,11 @@ public: if (pFile) { fclose(pFile); - delete decoders; + delete[] decoders; for (int i = 0; i < m_nChannels; i++) - delete ppTempBuffers[i]; - delete ppTempBuffers; - delete buffers; + delete[] ppTempBuffers[i]; + delete[] ppTempBuffers; + delete[] buffers; } } From 0b73b13b9a7d22c6277bafa253baddeff3443648 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 6 Jan 2021 20:22:09 +0200 Subject: [PATCH 05/20] Cleanup and fixes for new decoders --- src/audio/oal/stream.cpp | 265 ++++++++++++++++++++++----------------- 1 file changed, 148 insertions(+), 117 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 33f5bda9..cdf063fa 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -174,35 +174,45 @@ class CWavFile : public IDecoder tFormatHeader() { memset(this, 0, sizeof(*this)); } }; - FILE* pFile; - bool bIsOpen; - tFormatHeader FormatHeader; + FILE *m_pFile; + bool m_bIsOpen; - uint32 DataStartOffset; - uint32 SampleCount; - uint32 SamplesPerBlock; + tFormatHeader m_FormatHeader; + + uint32 m_DataStartOffset; // TODO: 64 bit? + uint32 m_nSampleCount; + uint32 m_nSamplesPerBlock; // ADPCM things - uint8 *AdpcmBlock; - int16 **buffers; - CImaADPCMDecoder* decoders; + uint8 *m_pAdpcmBuffer; + int16 **m_ppPcmBuffers; + CImaADPCMDecoder *m_pAdpcmDecoders; void Close() { - if (pFile) { - fclose(pFile); - pFile = nil; + if (m_pFile) { + fclose(m_pFile); + m_pFile = nil; } - if (AdpcmBlock) delete[] AdpcmBlock; - if (buffers) delete[] buffers; - if (decoders) delete[] decoders; + 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) : bIsOpen(false), DataStartOffset(0), SampleCount(0), SamplesPerBlock(0), AdpcmBlock(nil), buffers(nil), decoders(nil) + 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) { - pFile = fopen(path, "rb"); - if (!pFile) return; + m_pFile = fopen(path, "rb"); + if (!m_pFile) return; #define CLOSE_ON_ERROR(op)\ if (op) { \ @@ -212,52 +222,58 @@ public: tDataHeader DataHeader; - CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0); + 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, pFile) == 0); + CLOSE_ON_ERROR(fread(&WAVE, 4, 1, m_pFile) == 0); CLOSE_ON_ERROR(WAVE != 'EVAW') - CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0); + CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0); CLOSE_ON_ERROR(DataHeader.ID != ' tmf'); - CLOSE_ON_ERROR(fread(&FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, pFile) == 0); + CLOSE_ON_ERROR(fread(&m_FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, m_pFile) == 0); CLOSE_ON_ERROR(DataHeader.Size > sizeof(tFormatHeader)); - switch (FormatHeader.AudioFormat) + switch (m_FormatHeader.AudioFormat) { case WAVEFMT_XBOX_ADPCM: - FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM; + m_FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM; case WAVEFMT_IMA_ADPCM: - SamplesPerBlock = (FormatHeader.BlockAlign / FormatHeader.NumChannels - 4) * 2 + 1; - AdpcmBlock = new uint8[FormatHeader.BlockAlign]; - buffers = new int16*[FormatHeader.NumChannels]; - decoders = new CImaADPCMDecoder[FormatHeader.NumChannels]; + 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: - SamplesPerBlock = 1; - if (FormatHeader.BitsPerSample != 16) + m_nSamplesPerBlock = 1; + if (m_FormatHeader.BitsPerSample != 16) { - debug("Unsupported PCM (%d bits), only signed 16-bit is supported (%s)\n", FormatHeader.BitsPerSample, path); + 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", FormatHeader.AudioFormat, path); + debug("Unsupported wav format 0x%x (%s)\n", m_FormatHeader.AudioFormat, path); + Close(); return; } while (true) { - CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, pFile) == 0); + CLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0); if (DataHeader.ID == 'atad') break; - fseek(pFile, DataHeader.Size, SEEK_CUR); + fseek(m_pFile, DataHeader.Size, SEEK_CUR); + // TODO? validate data size + // maybe check if there no extreme custom headers that might break this } - DataStartOffset = ftell(pFile); - SampleCount = DataHeader.Size / FormatHeader.BlockAlign * SamplesPerBlock; + m_DataStartOffset = ftell(m_pFile); + m_nSampleCount = DataHeader.Size / m_FormatHeader.BlockAlign * m_nSamplesPerBlock; - bIsOpen = true; + m_bIsOpen = true; #undef CLOSE_ON_ERROR } @@ -268,7 +284,7 @@ public: bool IsOpened() { - return bIsOpen; + return m_bIsOpen; } uint32 GetSampleSize() @@ -278,29 +294,29 @@ public: uint32 GetSampleCount() { - return SampleCount; + return m_nSampleCount; } uint32 GetSampleRate() { - return FormatHeader.SampleRate; + return m_FormatHeader.SampleRate; } uint32 GetChannels() { - return FormatHeader.NumChannels; + return m_FormatHeader.NumChannels; } void Seek(uint32 milliseconds) { if (!IsOpened()) return; - fseek(pFile, DataStartOffset + ms2samples(milliseconds) / SamplesPerBlock * FormatHeader.BlockAlign, SEEK_SET); + fseek(m_pFile, m_DataStartOffset + ms2samples(milliseconds) / m_nSamplesPerBlock * m_FormatHeader.BlockAlign, SEEK_SET); } uint32 Tell() { if (!IsOpened()) return 0; - return samples2ms((ftell(pFile) - DataStartOffset) / FormatHeader.BlockAlign * SamplesPerBlock); + return samples2ms(GetCurrentSample()); } #define SAMPLES_IN_LINE (8) @@ -309,52 +325,61 @@ public: { if (!IsOpened()) return 0; - if (FormatHeader.AudioFormat == WAVEFMT_PCM) + if (m_FormatHeader.AudioFormat == WAVEFMT_PCM) { - uint32 size = fread(buffer, 1, GetBufferSize(), pFile); - if (FormatHeader.NumChannels == 2) + // 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 (FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM) + else if (m_FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM) { - uint32 MaxSamples = GetBufferSamples() / FormatHeader.NumChannels; - uint32 CurSample = (ftell(pFile) - DataStartOffset) / FormatHeader.BlockAlign * SamplesPerBlock; + // 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); - MaxSamples = Min(MaxSamples, SampleCount - CurSample); - MaxSamples = MaxSamples / SamplesPerBlock * SamplesPerBlock; - uint32 OutBufSizePerChannel = MaxSamples * GetSampleSize(); - uint32 OutBufSize = OutBufSizePerChannel * FormatHeader.NumChannels; - int16** buffers = new int16*[FormatHeader.NumChannels]; - CImaADPCMDecoder* decoders = new CImaADPCMDecoder[FormatHeader.NumChannels]; - for (uint32 i = 0; i < FormatHeader.NumChannels; i++) - buffers[i] = (int16*)((int8*)buffer + OutBufSizePerChannel * i); + // 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 < MaxSamples) + while (samplesRead < nMaxSamples) { - uint8* AdpcmBuf = AdpcmBlock; - if (fread(AdpcmBlock, 1, FormatHeader.BlockAlign, pFile) == 0) + // read the file + uint8 *pAdpcmBuf = m_pAdpcmBuffer; + if (fread(m_pAdpcmBuffer, 1, m_FormatHeader.BlockAlign, m_pFile) == 0) return 0; - for (uint32 i = 0; i < FormatHeader.NumChannels; i++) + // get the first sample in adpcm block and initialise the decoder(s) + for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++) { - int16 Sample = *(int16*)AdpcmBuf; - AdpcmBuf += sizeof(int16); - int16 Step = *(int16*)AdpcmBuf; - AdpcmBuf += sizeof(int16); - decoders[i].Init(Sample, Step); - *(buffers[i]) = Sample; - buffers[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++; - for (uint32 s = 1; s < SamplesPerBlock; s += SAMPLES_IN_LINE) + + // decode the rest of the block + for (uint32 s = 1; s < m_nSamplesPerBlock; s += SAMPLES_IN_LINE) { - for (uint32 i = 0; i < FormatHeader.NumChannels; i++) + for (uint32 i = 0; i < m_FormatHeader.NumChannels; i++) { - decoders[i].Decode(AdpcmBuf, buffers[i], SAMPLES_IN_LINE / 2); - AdpcmBuf += SAMPLES_IN_LINE / 2; - buffers[i] += SAMPLES_IN_LINE; + 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; } @@ -620,68 +645,68 @@ public: class CVbFile : public IDecoder { - FILE* pFile; - size_t m_FileSize; - size_t m_nNumberOfBlocks; - CVagDecoder* decoders; + FILE *m_pFile; + CVagDecoder *m_pVagDecoders; - uint32 m_nSampleRate; - uint8 m_nChannels; - bool m_bBlockRead; - uint16 m_LineInBlock; - size_t m_CurrentBlock; + size_t m_FileSize; + size_t m_nNumberOfBlocks; - uint8** ppTempBuffers; - int16** buffers; + 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(pFile, block * m_nChannels * VB_BLOCK_SIZE, SEEK_SET); + fseek(m_pFile, block * m_nChannels * VB_BLOCK_SIZE, SEEK_SET); for (int i = 0; i < m_nChannels; i++) - fread(ppTempBuffers[i], VB_BLOCK_SIZE, 1, pFile); + 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), decoders(nil), ppTempBuffers(nil), buffers(nil), + 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) { - pFile = fopen(path, "rb"); - if (!pFile) return; + 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); - fseek(pFile, 0, SEEK_END); - m_FileSize = ftell(pFile); - fseek(pFile, 0, SEEK_SET); m_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE); - decoders = new CVagDecoder[nChannels]; - m_CurrentBlock = 0; - m_LineInBlock = 0; - m_bBlockRead = false; - ppTempBuffers = new uint8*[nChannels]; - buffers = new int16*[nChannels]; + m_pVagDecoders = new CVagDecoder[nChannels]; + m_ppVagBuffers = new uint8*[nChannels]; + m_ppPcmBuffers = new int16*[nChannels]; for (uint8 i = 0; i < nChannels; i++) - ppTempBuffers[i] = new uint8[VB_BLOCK_SIZE]; + m_ppVagBuffers[i] = new uint8[VB_BLOCK_SIZE]; } ~CVbFile() { - if (pFile) + if (m_pFile) { - fclose(pFile); - delete[] decoders; + fclose(m_pFile); + + delete[] m_pVagDecoders; for (int i = 0; i < m_nChannels; i++) - delete[] ppTempBuffers[i]; - delete[] ppTempBuffers; - delete[] buffers; + delete[] m_ppVagBuffers[i]; + delete[] m_ppVagBuffers; + delete[] m_ppPcmBuffers; } } bool IsOpened() { - return pFile != nil; + return m_pFile != nil; } uint32 GetSampleSize() @@ -709,6 +734,8 @@ public: { 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) { @@ -718,6 +745,7 @@ public: 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; @@ -726,7 +754,7 @@ public: m_CurrentBlock = block; m_LineInBlock = newLine; for (uint32 i = 0; i < GetChannels(); i++) - decoders[i].ResetState(); + m_pVagDecoders[i].ResetState(); } } @@ -742,35 +770,38 @@ public: { if (!IsOpened()) return 0; + if (m_CurrentBlock >= m_nNumberOfBlocks) return 0; + + // cache current ADPCM block if (!m_bBlockRead) ReadBlock(m_CurrentBlock); - if (m_CurrentBlock == m_nNumberOfBlocks) return 0; - int size = 0; - + // 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(); - if (numberOfRequiredLines > numberOfRemainingLines) - numberOfRemainingLines = numberOfRemainingLines; - + // calculate the pointers to individual channel buffers for (uint32 i = 0; i < m_nChannels; i++) - buffers[i] = (int16*)((int8*)buffer + bufSizePerChannel * 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++) { - decoders[i].Decode(ppTempBuffers[i] + m_LineInBlock * VAG_LINE_SIZE, buffers[i], VAG_LINE_SIZE); - buffers[i] += VAG_SAMPLES_IN_LINE; + 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) + if (m_CurrentBlock >= m_nNumberOfBlocks) // end of file break; m_LineInBlock = 0; ReadBlock(); From f61e2d04f1887d2aa62119dc9d1ec8a3d30b62cf Mon Sep 17 00:00:00 2001 From: majestic Date: Wed, 6 Jan 2021 11:56:13 -0800 Subject: [PATCH 06/20] GET_WHEELIE_STATS fix --- src/control/Script7.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/control/Script7.cpp b/src/control/Script7.cpp index 1bad3407..8d13bbae 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; From 0845abf6404647a949e132177bf1614d0c768088 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 7 Jan 2021 15:16:24 +0200 Subject: [PATCH 07/20] Fix 16KHz track --- src/audio/sampman_oal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index 84726c9e..0d82d552 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -396,7 +396,7 @@ set_new_provider(int index) static bool IsThisTrackAt16KHz(uint32 track) { - return track == STREAMED_SOUND_RADIO_KCHAT || track == STREAMED_SOUND_RADIO_VCPR || track == STREAMED_SOUND_AMBSIL_AMBIENT; + return track == STREAMED_SOUND_RADIO_KCHAT || track == STREAMED_SOUND_RADIO_VCPR || track == STREAMED_SOUND_RADIO_POLICE; } cSampleManager::cSampleManager(void) From db1bdfd62d5d0eb663f9844845de98fdbc0acd02 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 7 Jan 2021 16:33:42 +0300 Subject: [PATCH 08/20] minor refactoring --- src/collision/ColStore.cpp | 14 ++- src/control/Garages.h | 10 +- src/control/Script.cpp | 223 +++++++++++++++---------------------- src/control/Script.h | 61 +++++----- src/control/Script2.cpp | 14 +-- src/control/Script3.cpp | 10 +- src/control/Script4.cpp | 8 +- src/control/Script5.cpp | 74 ++++++++++++ src/control/Script6.cpp | 6 +- src/control/Script7.cpp | 4 +- src/control/Script8.cpp | 2 +- src/core/config.h | 5 + 12 files changed, 233 insertions(+), 198 deletions(-) diff --git a/src/collision/ColStore.cpp b/src/collision/ColStore.cpp index 4317655a..f1e695fe 100644 --- a/src/collision/ColStore.cpp +++ b/src/collision/ColStore.cpp @@ -12,6 +12,7 @@ #include "Physical.h" #include "ColStore.h" #include "VarConsole.h" +#include "Pools.h" CPool *CColStore::ms_pColPool; #ifndef MASTER @@ -184,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.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/Script.cpp b/src/control/Script.cpp index 4fdd6fd0..79ef408e 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; @@ -1711,23 +1711,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: @@ -1746,23 +1761,44 @@ void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObjects() switch (m_sEntities[i].type) { case CLEANUP_CAR: { - CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); - if (v) - PossiblyWakeThisEntity(v, true); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); + if (pVehicle) { + if (pVehicle->bIsStaticWaitingForCollision) { + if (CColStore::HasCollisionLoaded(pVehicle->GetPosition())) { + 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, true); + CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id); + if (pPed) { + if (pPed->bIsStaticWaitingForCollision) { + if (CColStore::HasCollisionLoaded(pPed->GetPosition())) { + 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, true); + CObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id); + if (pObject) { + if (pObject->bIsStaticWaitingForCollision) { + if (CColStore::HasCollisionLoaded(pObject->GetPosition())) { + pObject->bIsStaticWaitingForCollision = false; + if (!pObject->GetIsStatic()) + pObject->AddToMovingList(); + } + } + } break; } default: @@ -1771,21 +1807,6 @@ void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObjects() } } -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; -} - void CMissionCleanup::Process() { CPopulation::m_AllRandomPedsThisType = -1; @@ -1878,10 +1899,16 @@ void CUpsideDownCarCheck::Init() 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; } void CUpsideDownCarCheck::UpdateTimers() @@ -1904,7 +1931,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; @@ -1915,8 +1942,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; } @@ -1935,7 +1964,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; } @@ -1985,7 +2014,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(); @@ -2217,7 +2249,7 @@ void CTheScripts::Init() ScriptsArray[i].Init(); ScriptsArray[i].AddScriptToList(&pIdleScripts); } - MissionCleanup.Init(); + MissionCleanUp.Init(); UpsideDownCars.Init(); StuckCars.Init(); CFileMgr::SetDir("data"); @@ -2345,7 +2377,7 @@ void CTheScripts::Process() float timeStep = CTimer::GetTimeStepInMilliseconds(); UpsideDownCars.UpdateTimers(); StuckCars.Process(); - MissionCleanup.CheckIfCollisionHasLoadedForMissionObjects(); + MissionCleanUp.CheckIfCollisionHasLoadedForMissionObjects(); DrawScriptSpheres(); if (FailCurrentMission) --FailCurrentMission; @@ -3669,7 +3701,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: @@ -3678,7 +3710,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: @@ -3899,7 +3931,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: @@ -3912,7 +3944,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: @@ -4227,7 +4259,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: @@ -4250,7 +4282,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); } } @@ -4261,14 +4293,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: @@ -4301,7 +4333,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); } } @@ -4312,14 +4344,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: @@ -4468,7 +4500,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: @@ -4481,7 +4513,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: @@ -4697,7 +4729,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: @@ -4747,81 +4779,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(buf, m_abScriptName[i]); - WriteSaveBuf(buf, m_nIp); -#ifdef CHECK_STRUCT_SIZES - static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6"); -#endif - for (int i = 0; i < MAX_STACK_DEPTH; i++) - WriteSaveBuf(buf, m_anStack[i]); - WriteSaveBuf(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(buf, m_anLocalVariables[i]); - WriteSaveBuf(buf, m_bIsActive); - WriteSaveBuf(buf, m_bCondResult); - WriteSaveBuf(buf, m_bIsMissionScript); - WriteSaveBuf(buf, m_bSkipWakeTime); - WriteSaveBuf(buf, m_nWakeTime); - WriteSaveBuf(buf, m_nAndOrState); - WriteSaveBuf(buf, m_bNotFlag); - WriteSaveBuf(buf, m_bDeatharrestEnabled); - WriteSaveBuf(buf, m_bDeatharrestExecuted); - WriteSaveBuf(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(buf); - m_nIp = ReadSaveBuf(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(buf); - m_nStackPointer = ReadSaveBuf(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(buf); - m_bIsActive = ReadSaveBuf(buf); - m_bCondResult = ReadSaveBuf(buf); - m_bIsMissionScript = ReadSaveBuf(buf); - m_bSkipWakeTime = ReadSaveBuf(buf); - m_nWakeTime = ReadSaveBuf(buf); - m_nAndOrState = ReadSaveBuf(buf); - m_bNotFlag = ReadSaveBuf(buf); - m_bDeatharrestEnabled = ReadSaveBuf(buf); - m_bDeatharrestExecuted = ReadSaveBuf(buf); - m_bMissionFlag = ReadSaveBuf(buf); - SkipSaveBuf(buf, 2); -#else - CRunningScript* n = next; - CRunningScript* p = prev; - *this = ReadSaveBuf(buf); - next = n; - prev = p; -#endif -} - #ifdef MISSION_REPLAY bool CRunningScript::CanAllowMissionReplay() @@ -4856,7 +4813,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 ad8ccf74..aafc681c 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -21,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 @@ -96,7 +101,7 @@ struct intro_text_line m_bBackground = false; m_bBackgroundOnly = false; m_fWrapX = 182.0f; - m_fCenterSize = 640.0f; + m_fCenterSize = DEFAULT_SCREEN_WIDTH; m_sBackgroundColor = CRGBA(128, 128, 128, 128); m_bTextProportional = true; m_bTextBeforeFade = false; @@ -149,10 +154,10 @@ enum { class CMissionCleanup { +public: cleanup_entity_struct m_sEntities[MAX_CLEANUP]; uint8 m_nCount; -public: CMissionCleanup(); void Init(); @@ -161,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; @@ -172,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); @@ -194,7 +199,7 @@ struct stuck_car_data bool m_bStuck; stuck_car_data() { } - inline void Reset(); + void Reset(); }; class CStuckCarCheck @@ -273,6 +278,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 +292,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; @@ -319,11 +325,10 @@ class CTheScripts static int16 CardStack[CARDS_IN_STACK]; static int16 CardStackPosition; #endif -public: static bool bPlayerIsInTheStatium; static uint8 RiotIntensity; static bool bPlayerHasMetDebbieHarry; -public: + static void Init(); static void Process(); @@ -377,8 +382,6 @@ public: return Read4BytesFromScript(&tmp); } -private: - static CRunningScript* StartNewScript(uint32); static void CleanUpThisVehicle(CVehicle*); @@ -436,18 +439,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 }; @@ -474,6 +470,7 @@ class CRunningScript ORS_8 }; +public: CRunningScript* next; CRunningScript* prev; char m_abScriptName[8]; @@ -512,7 +509,6 @@ public: static const uint32 nSaveStructSize; -private: void CollectParameters(uint32*, int16); int32 CollectNextParameterWithoutIncreasingPC(uint32); int32* GetPointerToScriptVariable(uint32*, int16); @@ -580,7 +576,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 8f56745c..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: @@ -1157,7 +1157,7 @@ int8 CRunningScript::ProcessCommands400To499(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_OBJ_KILL_CHAR_ON_FOOT: diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp index b4c2bb7c..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; } /* @@ -1834,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); @@ -1889,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 d350bafd..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); @@ -609,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: @@ -1056,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(buf, m_abScriptName[i]); + WriteSaveBuf(buf, m_nIp); +#ifdef CHECK_STRUCT_SIZES + static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6"); +#endif + for (int i = 0; i < MAX_STACK_DEPTH; i++) + WriteSaveBuf(buf, m_anStack[i]); + WriteSaveBuf(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(buf, m_anLocalVariables[i]); + WriteSaveBuf(buf, m_bIsActive); + WriteSaveBuf(buf, m_bCondResult); + WriteSaveBuf(buf, m_bIsMissionScript); + WriteSaveBuf(buf, m_bSkipWakeTime); + WriteSaveBuf(buf, m_nWakeTime); + WriteSaveBuf(buf, m_nAndOrState); + WriteSaveBuf(buf, m_bNotFlag); + WriteSaveBuf(buf, m_bDeatharrestEnabled); + WriteSaveBuf(buf, m_bDeatharrestExecuted); + WriteSaveBuf(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(buf); + m_nIp = ReadSaveBuf(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(buf); + m_nStackPointer = ReadSaveBuf(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(buf); + m_bIsActive = ReadSaveBuf(buf); + m_bCondResult = ReadSaveBuf(buf); + m_bIsMissionScript = ReadSaveBuf(buf); + m_bSkipWakeTime = ReadSaveBuf(buf); + m_nWakeTime = ReadSaveBuf(buf); + m_nAndOrState = ReadSaveBuf(buf); + m_bNotFlag = ReadSaveBuf(buf); + m_bDeatharrestEnabled = ReadSaveBuf(buf); + m_bDeatharrestExecuted = ReadSaveBuf(buf); + m_bMissionFlag = ReadSaveBuf(buf); + SkipSaveBuf(buf, 2); +#else + CRunningScript* n = next; + CRunningScript* p = prev; + *this = ReadSaveBuf(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 b9ec31ee..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: @@ -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 8d13bbae..1eaa6cd0 100644 --- a/src/control/Script7.cpp +++ b/src/control/Script7.cpp @@ -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/core/config.h b/src/core/config.h index 139feddf..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!) From 9d6db921bd05089a8d0cc420685509b4da2e344b Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 7 Jan 2021 18:31:54 +0300 Subject: [PATCH 09/20] fail --- src/control/Script.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 79ef408e..23527e55 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1693,17 +1693,6 @@ void CMissionCleanup::AddEntityToList(int32 id, uint8 type) m_nCount++; } -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(); - } -} - void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type) { for (int i = 0; i < MAX_CLEANUP; i++){ From eecf095077471c9f44ef3ff2599b70bb0a7738e5 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 7 Jan 2021 20:57:17 +0200 Subject: [PATCH 10/20] Add missing GXT line --- gamefiles/TEXT/american.gxt | Bin 423398 -> 423418 bytes utils/gxt/american.txt | 3 +++ 2 files changed, 3 insertions(+) diff --git a/gamefiles/TEXT/american.gxt b/gamefiles/TEXT/american.gxt index eaeab8bb702946874d439f590c954d844f563abc..767454de46933b66db4f95ed2a701ff08b148880 100644 GIT binary patch delta 1012 zcmXxiK}Zx)7zgmbyR#+)QP4rjh)Bdkm)Tt-3aYo$Q>U4onPz9x6-)(hX+{)mw6#Hz z5>i4QA`F7|6iI@CLUa&17{F)0_FpEO7N=U+*QKcxlO<^?#m0SdwyRg< zEIcH;EXd>w=z0`~!MreDnh^Fy80ktmTzJgavGtPddh`xxoD$AE0qxW{txTtVd`Hex z&lC?nC{uj!i!$Bf+L|&ou=+EOHq&7?2Nr8Ivd;tG!qy=T?cCvhndum7RtuIyUu)zP zw$DUP*gu23~6@ zn@-@nlr%Q0!Qx@V82Cgs4J#J}IQ~t8%{mL5CiH$KauTI@Ld8>9I}$mKlAb`;WLcAj zT{%t8irWBMCIR;XvwgE2OJ@`CI!v1yC}YEx3(>)JKsLL(8QJS4yS|t-ng*ps4sJ_} zF87W~)1*;(M)uusDo>`Q!~D0>;r}t8fX@t`qx^}_WTV`{ZBxhOSF!MHheniM78Yqb z)>g=_VTntWzDtWu7k*2NP3LwJ$Z@}2jr2Re)Jod5s; delta 992 zcmXxiK}Zx)7zgmbyEEb`47x}~3x#y(GP@cQQa;DY9cOlCn4L{mA{9EUBo$FGkTPMB z(xH~{5MdDHDUbvOCF&q}2|7qDl%*&UA}AHqrAX*|^WH2B{N6X;_ul)yoxi(H+q+HG zBhmG>6j-rnIvQ|uLplr0Y)R*U=iAaPfbv7S6$t;N(8(ODhia?)(p1~tkQQ;OJ#<)_ zYDb#6eV3oL(-}K*9V+Y3sl@1!Z-_feW|G5AfI8hHObjq|3%Yy()TQ^>v%_!icWDd;vF!;hGTuvsox7Itgm z9CkVqw_xj1;#NGlrXbHuem8s?6Xug>d?3sxvGWVR#?NrfwC304KgEuvu@}pb5=wCeEUgR%JYg)#HgAHUf#5+fe1BQEO-ag0om;DXXN$)vg`9nqj5x-=j@FM z^Dh5Q2-BodeMa`(cq;d1h2#9!!twX9tioryQKbAkHL@P%4cpW(`I#>~+o2IwZu8J-5^^=d1`(+ef#u${!Hd<-GRHq;lyxQw>TW84h~I>uchco M)1xeouc_hme-o?j761SM diff --git a/utils/gxt/american.txt b/utils/gxt/american.txt index bb1f44e9..fcb3a80f 100644 --- a/utils/gxt/american.txt +++ b/utils/gxt/american.txt @@ -14394,6 +14394,9 @@ XBOX [FEC_IVP] INVERT PAD VERTICALLY +[FEM_NON] +NONE + { end of file } [DUMMY] THIS LABEL NEEDS TO BE HERE !!! From c2672bd630e2c7d748d759aa9b6e81ba7ecfc0fe Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 7 Jan 2021 21:00:20 +0200 Subject: [PATCH 11/20] Fix char in stats --- src/core/Frontend.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index e5e42b8c..11488aec 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -3639,7 +3639,7 @@ CMenuManager::ExportStats() char *statValue = UnicodeToAscii(gUString2); for (int j = 0; statValue[j] != '\0'; ++j) { if (statValue[j] == '_') - statValue[j] = 0xBA; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation + statValue[j] = '\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation } if (statValue) fprintf(txtFile, "%s\n\n", statValue); @@ -3701,7 +3701,7 @@ CMenuManager::ExportStats() char *statValue = UnicodeToAscii(gUString2); for (int l = 0; statValue[l] != '\0'; ++l) { if (statValue[l] == '_') - statValue[l] = 0xBA; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation + statValue[l] = '\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation } if (statValue) fprintf(htmlFile, "%s", statValue); From 0428b5b694b47a5135b8e09ee779a923b44c93bc Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 7 Jan 2021 21:55:41 +0200 Subject: [PATCH 12/20] Fix pickup text --- src/control/Pickups.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index bd0fa989..3470e475 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1336,7 +1336,7 @@ CPickups::RenderPickUpText() #ifdef FIX_BUGS const float MAX_SCALE = SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH; #else - const float MAX_SCALE = RsGlobal.width / DEFAULT_SCREEN_WIDTH; + float MAX_SCALE = RsGlobal.width / DEFAULT_SCREEN_WIDTH; #endif float fScaleY = aMessages[i].m_dist.y / 30.0f; @@ -1345,11 +1345,7 @@ CPickups::RenderPickUpText() float fScaleX = aMessages[i].m_dist.x / 30.0f; if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE; -#ifdef FIX_BUGS - CFont::SetScale(SCREEN_SCALE_X(fScaleX), SCREEN_SCALE_Y(fScaleY)); -#else - CFont::SetScale(fScaleX, fScaleY); -#endif + CFont::SetScale(fScaleX, fScaleY); // this shouldn't be scaled CFont::SetCentreOn(); CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetJustifyOff(); From 6b0fa20b8b40b7211b18129ebad108f314a0d5e0 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 7 Jan 2021 22:01:44 +0200 Subject: [PATCH 13/20] Make opus available alongside other formats --- src/audio/oal/stream.cpp | 130 +++++++++++++++++++------------------- src/audio/sampman.h | 8 +-- src/audio/sampman_oal.cpp | 12 ++-- src/core/config.h | 14 +++- 4 files changed, 88 insertions(+), 76 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index cdf063fa..32ce9537 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -4,20 +4,23 @@ #include "stream.h" #include "sampman.h" -#ifdef AUDIO_OPUS -#include -#else #ifdef _WIN32 #ifdef AUDIO_OAL_USE_SNDFILE #pragma comment( lib, "libsndfile-1.lib" ) #endif +#ifdef AUDIO_OAL_USE_MPG123 #pragma comment( lib, "libmpg123-0.lib" ) #endif +#endif #ifdef AUDIO_OAL_USE_SNDFILE #include #endif +#ifdef AUDIO_OAL_USE_MPG123 #include #endif +#ifdef AUDIO_OAL_USE_OPUS +#include +#endif #ifndef _WIN32 #include "crossplatform.h" @@ -81,7 +84,6 @@ public: CSortStereoBuffer SortStereoBuffer; -#ifndef AUDIO_OPUS class CImaADPCMDecoder { const uint16 StepTable[89] = { @@ -461,11 +463,9 @@ public: }; #endif -#ifdef _WIN32 +#ifdef AUDIO_OAL_USE_MPG123 // 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 { @@ -574,6 +574,55 @@ public: } }; +class CADFFile : public CMP3File +{ + static ssize_t r_read(void* fh, void* buf, size_t size) + { + size_t bytesRead = fread(buf, 1, size, (FILE*)fh); + uint8* _buf = (uint8*)buf; + for (size_t i = 0; i < size; i++) + _buf[i] ^= 0x22; + return bytesRead; + } + static off_t r_seek(void* fh, off_t pos, int seekType) + { + fseek((FILE*)fh, pos, seekType); + return ftell((FILE*)fh); + } + static void r_close(void* fh) + { + fclose((FILE*)fh); + } +public: + CADFFile(const char* path) + { + 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 | MPG123_QUIET, 0.0); +#endif + long rate = 0; + int channels = 0; + int encoding = 0; + + FILE* f = fopen(path, "rb"); + + m_bOpened = mpg123_replace_reader_handle(m_pMH, r_read, r_seek, r_close) == MPG123_OK + && mpg123_open_handle(m_pMH, f) == MPG123_OK && mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK; + m_nRate = rate; + m_nChannels = channels; + + if (IsOpened()) + { + mpg123_format_none(m_pMH); + mpg123_format(m_pMH, rate, channels, encoding); + } + } + } +}; + +#endif #define VAG_LINE_SIZE (0x10) #define VAG_SAMPLES_IN_LINE (28) @@ -811,7 +860,7 @@ public: return bufSizePerChannel * m_nChannels; } }; -#else +#ifdef AUDIO_OAL_USE_OPUS class COpusFile : public IDecoder { OggOpusFile *m_FileH; @@ -907,64 +956,16 @@ public: }; #endif -class CADFFile : public CMP3File -{ - static ssize_t r_read(void* fh, void* buf, size_t size) - { - size_t bytesRead = fread(buf, 1, size, (FILE*)fh); - uint8* _buf = (uint8*)buf; - for (size_t i = 0; i < size; i++) - _buf[i] ^= 0x22; - return bytesRead; - } - static off_t r_seek(void* fh, off_t pos, int seekType) - { - fseek((FILE*)fh, pos, seekType); - return ftell((FILE*)fh); - } - static void r_close(void* fh) - { - fclose((FILE*)fh); - } -public: - CADFFile(const char* path) - { - 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; - - FILE* f = fopen(path, "rb"); - - m_bOpened = mpg123_replace_reader_handle(m_pMH, r_read, r_seek, r_close) == MPG123_OK - && mpg123_open_handle(m_pMH, f) == MPG123_OK && mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK; - m_nRate = rate; - m_nChannels = channels; - - if (IsOpened()) - { - mpg123_format_none(m_pMH); - mpg123_format(m_pMH, rate, channels, encoding); - } - } - } -}; - void CStream::Initialise() { -#ifndef AUDIO_OPUS +#ifdef AUDIO_OAL_USE_MPG123 mpg123_init(); #endif } void CStream::Terminate() { -#ifndef AUDIO_OPUS +#ifdef AUDIO_OAL_USE_MPG123 mpg123_exit(); #endif } @@ -997,21 +998,22 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU DEV("Stream %s\n", m_aFilename); -#ifndef AUDIO_OPUS - 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")) + 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 +#ifdef AUDIO_OAL_USE_MPG123 + else 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(".adf")], ".adf")) m_pSoundFile = new CADFFile(m_aFilename); +#endif 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")) +#ifdef AUDIO_OAL_USE_OPUS + else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".opus")], ".opus")) m_pSoundFile = new COpusFile(m_aFilename); #endif else diff --git a/src/audio/sampman.h b/src/audio/sampman.h index d3e4415f..2db29244 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -240,7 +240,7 @@ public: extern cSampleManager SampleManager; extern uint32 BankStartOffset[MAX_SFX_BANKS]; -#ifdef AUDIO_OPUS +#if defined(OPUS_AUDIO_PATHS) static char StreamedNameTable[][25] = { "AUDIO\\HEAD.OPUS", "AUDIO\\CLASS.OPUS", "AUDIO\\KJAH.OPUS", "AUDIO\\RISE.OPUS", "AUDIO\\LIPS.OPUS", "AUDIO\\GAME.OPUS", "AUDIO\\MSX.OPUS", "AUDIO\\FLASH.OPUS", "AUDIO\\CHAT.OPUS", "AUDIO\\HEAD.OPUS", "AUDIO\\POLICE.OPUS", "AUDIO\\CITY.OPUS", @@ -275,8 +275,7 @@ static char StreamedNameTable[][25] = { "AUDIO\\h5_b.OPUS", "AUDIO\\h5_c.OPUS", "AUDIO\\ammu_a.OPUS", "AUDIO\\ammu_b.OPUS", "AUDIO\\ammu_c.OPUS", "AUDIO\\door_1.OPUS", "AUDIO\\door_2.OPUS", "AUDIO\\door_3.OPUS", "AUDIO\\door_4.OPUS", "AUDIO\\door_5.OPUS", "AUDIO\\door_6.OPUS", "AUDIO\\t3_a.OPUS", "AUDIO\\t3_b.OPUS", "AUDIO\\t3_c.OPUS", "AUDIO\\k1_b.OPUS", "AUDIO\\cat1.OPUS"}; -#else -#ifdef PS2_AUDIO +#elif defined(PS2_AUDIO_PATHS) static char StreamedNameTable[][40] = { "AUDIO\\MUSIC\\WILD.VB", @@ -1610,5 +1609,4 @@ static char StreamedNameTable[][25] = "AUDIO\\BUST_26.WAV", "AUDIO\\BUST_27.WAV", "AUDIO\\BUST_28.WAV", -}; -#endif \ No newline at end of file +}; \ No newline at end of file diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index 0d82d552..ce6458e6 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -30,7 +30,7 @@ #include "MusicManager.h" #include "Frontend.h" #include "Timer.h" -#ifdef AUDIO_OPUS +#ifdef AUDIO_OAL_USE_OPUS #include #endif @@ -83,7 +83,7 @@ char SampleBankDescFilename[] = "audio/sfx.SDT"; char SampleBankDataFilename[] = "audio/sfx.RAW"; FILE *fpSampleDescHandle; -#ifdef AUDIO_OPUS +#ifdef OPUS_SFX OggOpusFile *fpSampleDataHandle; #else FILE *fpSampleDataHandle; @@ -1245,7 +1245,7 @@ cSampleManager::LoadSampleBank(uint8 nBank) return false; } -#ifdef AUDIO_OPUS +#ifdef OPUS_SFX int samplesRead = 0; int samplesSize = nSampleBankSize[nBank] / 2; op_pcm_seek(fpSampleDataHandle, 0); @@ -1350,7 +1350,7 @@ cSampleManager::LoadPedComment(uint32 nComment) } } -#ifdef AUDIO_OPUS +#ifdef OPUS_SFX int samplesRead = 0; int samplesSize = m_aSamples[nComment].nSize / 2; op_pcm_seek(fpSampleDataHandle, m_aSamples[nComment].nOffset / 2); @@ -2007,7 +2007,7 @@ cSampleManager::InitialiseSampleBanks(void) fpSampleDescHandle = fcaseopen(SampleBankDescFilename, "rb"); if ( fpSampleDescHandle == NULL ) return false; -#ifndef AUDIO_OPUS +#ifndef OPUS_SFX fpSampleDataHandle = fcaseopen(SampleBankDataFilename, "rb"); if ( fpSampleDataHandle == NULL ) { @@ -2025,7 +2025,7 @@ cSampleManager::InitialiseSampleBanks(void) fpSampleDataHandle = op_open_file(SampleBankDataFilename, &e); #endif fread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle); -#ifdef AUDIO_OPUS +#ifdef OPUS_SFX int32 _nSampleDataEndOffset = m_aSamples[TOTAL_AUDIO_SAMPLES - 1].nOffset + m_aSamples[TOTAL_AUDIO_SAMPLES - 1].nSize; #endif fclose(fpSampleDescHandle); diff --git a/src/core/config.h b/src/core/config.h index a06ed1be..874ff39a 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -364,9 +364,21 @@ 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 PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds) //#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder +#define AUDIO_OAL_USE_MPG123 // use mpg123 to support mp3 files +#ifdef AUDIO_OPUS +#define AUDIO_OAL_USE_OPUS // enable support of opus files +//#define OPUS_AUDIO_PATHS // (not supported on VC yet) changes audio paths to opus paths (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled) +//#define OPUS_SFX // enable if your sfx.raw is encoded with opus (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled) + +#ifndef AUDIO_OAL_USE_OPUS +#undef OPUS_AUDIO_PATHS +#undef OPUS_SFX +#endif + +#endif #ifdef LIBRW // these are not supported with librw yet From c423c59365dbdaf2e268ae61f8a67dd652bffa17 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 7 Jan 2021 22:15:30 +0200 Subject: [PATCH 14/20] Add MPG123_QUIET to mp3 files --- src/audio/oal/stream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 32ce9537..81a78381 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -491,7 +491,7 @@ public: if ( m_pMH ) { #ifdef MP3_USE_FUZZY_SEEK - mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0); + mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS | MPG123_QUIET, 0.0); #endif long rate = 0; int channels = 0; From debf39fe6466eb3e2b222f067ed2ebd21b1de47a Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 7 Jan 2021 23:47:17 +0200 Subject: [PATCH 15/20] Fix font on green screen counter --- src/render/SpecialFX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index b1cce8e2..4eed988d 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -186,7 +186,7 @@ CSpecialFX::Render2DFXs(void) CFont::SetCentreOff(); CFont::SetPropOn(); CFont::SetColor(CRGBA(0, 255, 0, 200)); - FONT_LOCALE(FONT_STANDARD); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); sprintf(gString, "%d", CTimer::GetFrameCounter() & 0x3F); // mb % 63 AsciiToUnicode(gString, gUString); CFont::PrintString(SCREEN_WIDTH * 8 / 10, SCREEN_HEIGHT * 8 / 10, gUString); @@ -211,7 +211,7 @@ CSpecialFX::Render2DFXs(void) CFont::SetCentreOff(); CFont::SetPropOn(); CFont::SetColor(CRGBA(100, 100, 100, 200)); - FONT_LOCALE(FONT_STANDARD); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); CFont::PrintString(SCREEN_WIDTH * 8 / 10, SCREEN_HEIGHT * 8 / 10, gUString); for (int32 i = 0; i < SCREEN_HEIGHT; i += 4) { RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); From 24d73aeb7167059307fb6a913cdacf4578107adf Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 8 Jan 2021 00:04:38 +0200 Subject: [PATCH 16/20] Fix garage messages position --- src/control/Garages.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 72053f8d..89377db5 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1414,11 +1414,7 @@ void CGarages::PrintMessages() CFont::SetDropShadowPosition(2); CFont::SetDropColor(CRGBA(0, 0, 0, 255)); -#if defined(GTA_PS2) || defined (FIX_BUGS) - float y_offset = SCREEN_HEIGHT / 3 - SCREEN_SCALE_Y(40.0f); // THIS is PS2 calculation -#else - float y_offset = SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(84.0f); // This is PC and results in text being written over some HUD elements -#endif + float y_offset = SCREEN_SCALE_Y(140.0f); if (MessageNumberInString2 >= 0) { CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString); From 556b9ae574c02b0065e854a2cccf5a8fa54e62a8 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 8 Jan 2021 00:47:21 +0200 Subject: [PATCH 17/20] Fix gOneShotCol --- src/audio/AudioCollision.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/audio/AudioCollision.cpp b/src/audio/AudioCollision.cpp index c5aa170c..250cd18e 100644 --- a/src/audio/AudioCollision.cpp +++ b/src/audio/AudioCollision.cpp @@ -219,7 +219,9 @@ static const int32 gOneShotCol[] = {SFX_COL_TARMAC_1, SFX_TYRE_BUMP, SFX_COL_CARDBOARD_1, SFX_COL_TARMAC_1, - SFX_COL_GATE}; + SFX_COL_GATE, + SFX_COL_SAND_1, + SFX_COL_TARMAC_1 }; void cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col) From d820df0dbe2301928c8c1e5bf5c368f635a131f5 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 8 Jan 2021 01:44:19 +0100 Subject: [PATCH 18/20] small cleanup --- src/animation/CutsceneMgr.cpp | 4 ++-- src/peds/Population.cpp | 9 +++------ src/vehicles/HandlingMgr.cpp | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/animation/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp index b312236b..003385da 100644 --- a/src/animation/CutsceneMgr.cpp +++ b/src/animation/CutsceneMgr.cpp @@ -633,8 +633,8 @@ CCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver() CStreaming::RemoveCurrentZonesModels(); CStreaming::SetModelIsDeletable(MI_MALE01); CStreaming::SetModelTxdIsDeletable(MI_MALE01); - CStreaming::SetModelIsDeletable(MI_HMOCA); - CStreaming::SetModelTxdIsDeletable(MI_HMOCA); + CStreaming::SetModelIsDeletable(MI_TAXI_D); + CStreaming::SetModelTxdIsDeletable(MI_TAXI_D); CStreaming::SetModelIsDeletable(MI_NIGHTSTICK); CStreaming::SetModelTxdIsDeletable(MI_NIGHTSTICK); CStreaming::SetModelIsDeletable(MI_MISSILE); diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 7314080b..f886597f 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -558,11 +558,8 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree // Taxi side mission if (CTheScripts::IsPlayerOnAMission()) { CPed *player = FindPlayerPed(); - if (player && player->InVehicle()) { - int32 model = player->m_pMyVehicle->GetModelIndex(); - if (model == MI_TAXI || model == MI_CABBIE || model == MI_ZEBRA || model == MI_KAUFMAN) - missionAndWeatherMult = 1.0f; - } + if (player && player->InVehicle() && player->m_pMyVehicle->IsTaxi()) + missionAndWeatherMult = 1.0f; } if (CDarkel::FrenzyOnGoing()) missionAndWeatherMult = 1.0f; @@ -843,7 +840,7 @@ CPopulation::AddPedInCar(CVehicle* car, bool isDriver) pedType = PEDTYPE_COP; break; default: - if (car->GetModelIndex() == MI_TAXI || car->GetModelIndex() == MI_CABBIE || car->GetModelIndex() == MI_ZEBRA || car->GetModelIndex() == MI_KAUFMAN) { + if (car->IsTaxi()) { if (isDriver) { pedType = PEDTYPE_CIVMALE; preferredModel = MI_TAXI_D; diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 611ddcc9..9aa834ac 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -350,7 +350,7 @@ void cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling) { // convert distance to m, time to 1/50s - float velocity, a, b, specificVolume; + float velocity, a, b; handling->Transmission.fEngineAcceleration *= 1.0f/(50.0f*50.0f); handling->Transmission.fMaxVelocity *= 1000.0f/(60.0f*60.0f * 50.0f); From f8569a74cbbd8366a39d63c8b6699a7fdf24e14a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 8 Jan 2021 12:59:51 +0300 Subject: [PATCH 19/20] fix --- src/control/Script4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp index 2177afa4..5ffbac2e 100644 --- a/src/control/Script4.cpp +++ b/src/control/Script4.cpp @@ -68,7 +68,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed; script_assert(pPed); script_assert(pLeader); - UpdateCompareFlag(pPed->m_leader == pLeader); + UpdateCompareFlag(pPed->m_leader == pLeader && !pPed->bWaitForLeaderToComeCloser); return 0; } case COMMAND_EXPLODE_CHAR_HEAD: From 824ca7599ce380a12af0f42b892b7994b31e8f96 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 8 Jan 2021 13:07:36 +0300 Subject: [PATCH 20/20] wtf --- src/control/Script4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp index 5ffbac2e..a3ded9a5 100644 --- a/src/control/Script4.cpp +++ b/src/control/Script4.cpp @@ -92,7 +92,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CollectParameters(&m_nIp, 2); CBoat* pBoat = (CBoat*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(pBoat && pBoat->m_vehType == VEHICLE_TYPE_BOAT); - pBoat->m_bIsAnchored = (ScriptParams[1] == 0); + pBoat->m_bIsAnchored = (ScriptParams[1] != 0); return 0; } case COMMAND_SET_ZONE_GROUP: