From 5654347c5d511c53146fe4ce1710938b311d986e Mon Sep 17 00:00:00 2001 From: Greg V Date: Mon, 28 Sep 2020 04:50:57 +0300 Subject: Use glfwSetFramebufferSizeCallback instead of glfwSetWindowSizeCallback Framebuffer size is scaled by the display scale. This fixes the game being shrunk to the bottom left quarter of the window on Wayland HiDPI setups. Corresponding change in librw: glfwGetWindowSize -> glfwGetFramebufferSize. --- src/skel/glfw/glfw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index b9dbf5ac..f1b9c695 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -881,7 +881,7 @@ void psPostRWinit(void) RwEngineGetVideoModeInfo(&vm, GcurSelVM); glfwSetKeyCallback(PSGLOBAL(window), keypressCB); - glfwSetWindowSizeCallback(PSGLOBAL(window), resizeCB); + glfwSetFramebufferSizeCallback(PSGLOBAL(window), resizeCB); glfwSetScrollCallback(PSGLOBAL(window), scrollCB); glfwSetCursorPosCallback(PSGLOBAL(window), cursorCB); glfwSetCursorEnterCallback(PSGLOBAL(window), cursorEnterCB); -- cgit v1.2.3 From b95accb8ff6a594d1a920b94823b38be3515f149 Mon Sep 17 00:00:00 2001 From: Greg V Date: Mon, 28 Sep 2020 04:52:13 +0300 Subject: glfw: scale cursor position by the ratio of framebuffer to screen size This fixes the mouse being constrained to the top left quarter of the window on Wayland HiDPI setups. --- src/skel/glfw/glfw.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index f1b9c695..d7054b9c 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1397,8 +1397,11 @@ _InputTranslateShiftKeyUpDown(RsKeyCodes *rs) { // TODO this only works in frontend(and luckily only frontend use this). Fun fact: if I get pos manually in game, glfw reports that it's > 32000 void cursorCB(GLFWwindow* window, double xpos, double ypos) { - FrontEndMenuManager.m_nMouseTempPosX = xpos; - FrontEndMenuManager.m_nMouseTempPosY = ypos; + int bufw, bufh, winw, winh; + glfwGetWindowSize(window, &winw, &winh); + glfwGetFramebufferSize(window, &bufw, &bufh); + FrontEndMenuManager.m_nMouseTempPosX = xpos * (bufw / winw); + FrontEndMenuManager.m_nMouseTempPosY = ypos * (bufh / winh); } void -- cgit v1.2.3 From 0205960a2fe13174b5dc17abf080b6821a3c883a Mon Sep 17 00:00:00 2001 From: Greg V Date: Mon, 28 Sep 2020 04:53:15 +0300 Subject: Use GLFW_CURSOR_DISABLED (glfw's native mouse restriction) On Wayland, clients cannot move the mouse pointer. Mouse constraints, as required for 3D camera movement, are an explicit specific thing, and glfw supports it with GLFW_CURSOR_DISABLED. Use DISABLED, unless we're in a menu in windowed mode, where HIDDEN is still appropriate. --- src/skel/glfw/glfw.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index d7054b9c..e954e04b 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1628,6 +1628,8 @@ main(int argc, char *argv[]) #endif { glfwPollEvents(); + glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, + (FrontEndMenuManager.m_bMenuActive && !PSGLOBAL(fullScreen)) ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_DISABLED); if( ForegroundApp ) { switch ( gGameState ) -- cgit v1.2.3 From 7d03a6fe291ff72edcf517dda1de8aee40941019 Mon Sep 17 00:00:00 2001 From: Greg V Date: Mon, 28 Sep 2020 04:59:14 +0300 Subject: Use CLOCK_MONOTONIC_FAST when available (FreeBSD) CLOCK_MONOTONIC_FAST is the equivalent of Linux's CLOCK_MONOTONIC_RAW. --- src/skel/glfw/glfw.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index e954e04b..02546ffc 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -235,8 +235,10 @@ double psTimer(void) { struct timespec start; -#ifdef __linux__ +#if defined(CLOCK_MONOTONIC_RAW) clock_gettime(CLOCK_MONOTONIC_RAW, &start); +#elif defined(CLOCK_MONOTONIC_FAST) + clock_gettime(CLOCK_MONOTONIC_FAST, &start); #else clock_gettime(CLOCK_MONOTONIC, &start); #endif -- cgit v1.2.3 From a6aa782d6d5fa9a2165dafec5794a2e2cfbc653f Mon Sep 17 00:00:00 2001 From: erorcun Date: Sun, 18 Oct 2020 19:16:37 +0300 Subject: Fixes and style changes from miami --- src/audio/AudioManager.cpp | 5 + src/audio/DMAudio.cpp | 7 +- src/audio/oal/stream.cpp | 18 +- src/audio/sampman.h | 4 + src/audio/sampman_miles.cpp | 3 +- src/audio/sampman_oal.cpp | 751 +++++++++++++++++++++++++++++++++++++++----- src/core/Pad.cpp | 4 +- src/core/Radar.cpp | 100 ++---- src/core/Radar.h | 16 +- src/peds/Ped.cpp | 70 ++--- src/render/Hud.cpp | 36 +-- src/render/Hud.h | 13 +- src/render/Particle.cpp | 4 +- src/render/WaterCannon.cpp | 4 +- src/rw/RwHelper.cpp | 11 +- src/skel/glfw/glfw.cpp | 15 +- src/skel/win/win.cpp | 18 +- 17 files changed, 847 insertions(+), 232 deletions(-) (limited to 'src') diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index a42aa16f..d8054181 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -321,8 +321,13 @@ cAudioManager::Get3DProviderName(uint8 id) const { if (!m_bIsInitialised) return nil; +#ifdef AUDIO_OAL + id = clamp(id, 0, SampleManager.GetNum3DProvidersAvailable() - 1); +#else + // We don't want that either since it will crash the game, but skipping for now if (id >= SampleManager.GetNum3DProvidersAvailable()) return nil; +#endif return SampleManager.Get3DProviderName(id); } diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 7174c23c..17963cc9 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -118,7 +118,12 @@ int8 cDMAudio::AutoDetect3DProviders(void) for ( int32 i = 0; i < GetNum3DProvidersAvailable(); i++ ) { wchar buff[64]; - + +#ifdef AUDIO_OAL + if (defaultProvider >= 0 && defaultProvider < GetNum3DProvidersAvailable()) { + return i; + } +#endif char *name = Get3DProviderName(i); AsciiToUnicode(name, buff); char *providername = UnicodeToAscii(buff); diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index c4f1b67c..3af50ea8 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -323,8 +323,8 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF #endif else m_pSoundFile = nil; - ASSERT(m_pSoundFile != nil); - if (m_pSoundFile && m_pSoundFile->IsOpened() ) + + if ( IsOpened() ) { m_pBuffer = malloc(m_pSoundFile->GetBufferSize()); ASSERT(m_pBuffer!=nil); @@ -371,14 +371,14 @@ bool CStream::HasSource() bool CStream::IsOpened() { - return m_pSoundFile->IsOpened(); + return m_pSoundFile && m_pSoundFile->IsOpened(); } bool CStream::IsPlaying() { if ( !HasSource() || !IsOpened() ) return false; - if ( m_pSoundFile->IsOpened() && !m_bPaused ) + if ( !m_bPaused ) { ALint sourceState; alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState); @@ -446,7 +446,7 @@ void CStream::SetPan(uint8 nPan) void CStream::SetPosMS(uint32 nPos) { - if ( !m_pSoundFile->IsOpened() ) return; + if ( !IsOpened() ) return; m_pSoundFile->Seek(nPos); ClearBuffers(); } @@ -454,7 +454,7 @@ void CStream::SetPosMS(uint32 nPos) uint32 CStream::GetPosMS() { if ( !HasSource() ) return 0; - if ( !m_pSoundFile->IsOpened() ) return 0; + if ( !IsOpened() ) return 0; ALint offset; //alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset); @@ -467,7 +467,7 @@ uint32 CStream::GetPosMS() uint32 CStream::GetLengthMS() { - if ( !m_pSoundFile->IsOpened() ) return 0; + if ( !IsOpened() ) return 0; return m_pSoundFile->GetLength(); } @@ -475,7 +475,7 @@ bool CStream::FillBuffer(ALuint alBuffer) { if ( !HasSource() ) return false; - if ( !m_pSoundFile->IsOpened() ) + if ( !IsOpened() ) return false; if ( !(alBuffer != AL_NONE && alIsBuffer(alBuffer)) ) return false; @@ -517,7 +517,7 @@ void CStream::ClearBuffers() bool CStream::Setup() { - if ( m_pSoundFile->IsOpened() ) + if ( IsOpened() ) { m_pSoundFile->Seek(0); alSourcei(m_alSource, AL_SOURCE_RELATIVE, AL_TRUE); diff --git a/src/audio/sampman.h b/src/audio/sampman.h index d4b2621a..aec61144 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -218,6 +218,10 @@ public: extern cSampleManager SampleManager; extern uint32 BankStartOffset[MAX_SFX_BANKS]; +#ifdef AUDIO_OAL +extern int defaultProvider; +#endif + #ifdef AUDIO_OPUS static char StreamedNameTable[][25] = { "AUDIO\\HEAD.OPUS", "AUDIO\\CLASS.OPUS", "AUDIO\\KJAH.OPUS", "AUDIO\\RISE.OPUS", "AUDIO\\LIPS.OPUS", "AUDIO\\GAME.OPUS", diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index 70ea942e..392bface 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -2176,7 +2176,8 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) if ( mp3Stream[nStream] ) { AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_ms_position(mp3Stream[nStream], position); + AIL_set_stream_loop_count(mp3Stream[nStream], nStreamLoopedFlag[nStream] ? 0 : 1); + nStreamLoopedFlag[nStream] = true; AIL_pause_stream(mp3Stream[nStream], 0); return true; } diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index 9f3156cb..720849f8 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -1,4 +1,3 @@ -#include "common.h" //#define JUICY_OAL #ifdef AUDIO_OAL @@ -9,6 +8,10 @@ #include "eax.h" #include "eax-util.h" +#define WITHWINDOWS +#include "common.h" +#include "crossplatform.h" + #ifdef _WIN32 #include #include @@ -27,20 +30,27 @@ #include "MusicManager.h" #include "Frontend.h" #include "Timer.h" -#include "crossplatform.h" #ifdef AUDIO_OPUS #include #endif //TODO: fix eax3 reverb -//TODO: max channals +//TODO: max channels //TODO: loop count -//TODO: mp3 player #ifdef _WIN32 #pragma comment( lib, "OpenAL32.lib" ) #endif +// for user MP3s +#ifdef _WIN32 +#include +#include +#include +#else +#define _getcwd getcwd +#endif + cSampleManager SampleManager; bool _bSampmanInitialised = false; @@ -128,11 +138,27 @@ struct } }ALBuffers[SAMPLEBANK_MAX]; -uint32 nNumMP3s; +struct tMP3Entry +{ + char aFilename[MAX_PATH]; + + uint32 nTrackLength; + uint32 nTrackStreamPos; + + tMP3Entry* pNext; + char* pLinkPath; +}; + +uint32 nNumMP3s; +tMP3Entry* _pMP3List; +char _mp3DirectoryPath[MAX_PATH]; CStream *aStream[MAX_STREAMS]; uint8 nStreamPan [MAX_STREAMS]; uint8 nStreamVolume[MAX_STREAMS]; - +uint8 nStreamLoopedFlag[MAX_STREAMS]; +uint32 _CurMP3Index; +int32 _CurMP3Pos; +bool _bIsMp3Active; /////////////////////////////////////////////////////////////// // Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS EAXLISTENERPROPERTIES StartEAX3 = @@ -451,22 +477,419 @@ int8 cSampleManager::GetCurrent3DProviderIndex(void) int8 cSampleManager::SetCurrent3DProvider(uint8 nProvider) { - if (nProvider >= m_nNumberOfProviders) - nProvider = 0; - ASSERT( nProvider < m_nNumberOfProviders ); int savedprovider = curprovider; + + nProvider = clamp(nProvider, 0, m_nNumberOfProviders - 1); + + if ( set_new_provider(nProvider) ) + return curprovider; + else if ( savedprovider != -1 && savedprovider < m_nNumberOfProviders && set_new_provider(savedprovider) ) + return curprovider; + else + return curprovider; +} + +static bool +_ResolveLink(char const *path, char *out) +{ +#ifdef _WIN32 + size_t len = strlen(path); + if (len < 4 || strcmp(&path[len - 4], ".lnk") != 0) + return false; + + IShellLink* psl; + WIN32_FIND_DATA fd; + char filepath[MAX_PATH]; + + CoInitialize(NULL); + + if (SUCCEEDED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl ) )) + { + IPersistFile *ppf; + + if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf))) + { + WCHAR wpath[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); + + if (SUCCEEDED(ppf->Load(wpath, STGM_READ))) + { + /* Resolve the link */ + if (SUCCEEDED(psl->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI|SLR_NOSEARCH))) + { + strcpy(filepath, path); + + if (SUCCEEDED(psl->GetPath(filepath, MAX_PATH, &fd, SLGP_UNCPRIORITY))) + { + OutputDebugString(fd.cFileName); + + strcpy(out, filepath); + // FIX: Release the objects. Taken from SA. +#ifdef FIX_BUGS + ppf->Release(); + psl->Release(); +#endif + return true; + } + } + } + + ppf->Release(); + } + psl->Release(); + } + + return false; +#else + struct stat sb; + + if (lstat(path, &sb) == -1) { + perror("lstat: "); + return false; + } + + if (S_ISLNK(sb.st_mode)) { + char* linkname = (char*)alloca(sb.st_size + 1); + if (linkname == NULL) { + fprintf(stderr, "insufficient memory\n"); + return false; + } + + if (readlink(path, linkname, sb.st_size + 1) < 0) { + perror("readlink: "); + return false; + } + linkname[sb.st_size] = '\0'; + strcpy(out, linkname); + return true; + } else { + return false; + } +#endif +} + +static void +_FindMP3s(void) +{ + tMP3Entry *pList; + bool bShortcut; + bool bInitFirstEntry; + HANDLE hFind; + char path[MAX_PATH]; + char filepath[MAX_PATH*2]; + int total_ms; + WIN32_FIND_DATA fd; + + if (getcwd(_mp3DirectoryPath, MAX_PATH) == NULL) { + perror("getcwd: "); + return; + } + + OutputDebugString("Finding MP3s..."); + strcpy(path, _mp3DirectoryPath); + strcat(path, "\\MP3\\"); + + strcpy(_mp3DirectoryPath, path); + OutputDebugString(_mp3DirectoryPath); + + strcat(path, "*"); + + hFind = FindFirstFile(path, &fd); + + if ( hFind == INVALID_HANDLE_VALUE ) + { + return; + } + + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + size_t filepathlen = strlen(filepath); + + if ( filepathlen <= 0) + { + FindClose(hFind); + return; + } + + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + bShortcut = true; + } else + bShortcut = false; - if ( nProvider < m_nNumberOfProviders ) + aStream[0] = new CStream(filepath, ALStreamSources[0], ALStreamBuffers[0]); + + if (aStream[0] && aStream[0]->IsOpened()) { - if ( set_new_provider(nProvider) ) - return curprovider; - else if ( savedprovider != -1 && savedprovider < m_nNumberOfProviders && set_new_provider(savedprovider) ) - return curprovider; + total_ms = aStream[0]->GetLengthMS(); + delete aStream[0]; + aStream[0] = NULL; + + OutputDebugString(fd.cFileName); + + _pMP3List = new tMP3Entry; + + if ( _pMP3List == NULL ) + { + FindClose(hFind); + return; + } + + nNumMP3s = 1; + + strcpy(_pMP3List->aFilename, fd.cFileName); + + _pMP3List->nTrackLength = total_ms; + + _pMP3List->pNext = NULL; + + pList = _pMP3List; + + if ( bShortcut ) + { + _pMP3List->pLinkPath = new char[MAX_PATH*2]; + strcpy(_pMP3List->pLinkPath, filepath); + } else - return -1; + { + _pMP3List->pLinkPath = NULL; + } + + bInitFirstEntry = false; } else - return curprovider; + { + strcat(filepath, " - NOT A VALID MP3"); + + OutputDebugString(filepath); + + bInitFirstEntry = true; + } + + while ( true ) + { + if ( !FindNextFile(hFind, &fd) ) + break; + + if ( bInitFirstEntry ) + { + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + size_t filepathlen = strlen(filepath); + + if ( filepathlen > 0 ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + bShortcut = true; + } else { + bShortcut = false; + if (filepathlen > MAX_PATH) { + continue; + } + } + aStream[0] = new CStream(filepath, ALStreamSources[0], ALStreamBuffers[0]); + + if (aStream[0] && aStream[0]->IsOpened()) + { + total_ms = aStream[0]->GetLengthMS(); + delete aStream[0]; + aStream[0] = NULL; + + OutputDebugString(fd.cFileName); + + _pMP3List = new tMP3Entry; + + if ( _pMP3List == NULL) + break; + + nNumMP3s = 1; + + strcpy(_pMP3List->aFilename, fd.cFileName); + + _pMP3List->nTrackLength = total_ms; + _pMP3List->pNext = NULL; + + if ( bShortcut ) + { + _pMP3List->pLinkPath = new char [MAX_PATH*2]; + strcpy(_pMP3List->pLinkPath, filepath); + } + else + { + _pMP3List->pLinkPath = NULL; + } + + pList = _pMP3List; + + bInitFirstEntry = false; + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + OutputDebugString(filepath); + } + } + } + else + { + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + size_t filepathlen = strlen(filepath); + + if ( filepathlen > 0 ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + bShortcut = true; + } else + bShortcut = false; + + aStream[0] = new CStream(filepath, ALStreamSources[0], ALStreamBuffers[0]); + + if (aStream[0] && aStream[0]->IsOpened()) + { + total_ms = aStream[0]->GetLengthMS(); + delete aStream[0]; + aStream[0] = NULL; + + OutputDebugString(fd.cFileName); + + pList->pNext = new tMP3Entry; + + tMP3Entry *e = pList->pNext; + + if ( e == NULL ) + break; + + pList = pList->pNext; + + strcpy(e->aFilename, fd.cFileName); + e->nTrackLength = total_ms; + e->pNext = NULL; + + if ( bShortcut ) + { + e->pLinkPath = new char [MAX_PATH*2]; + strcpy(e->pLinkPath, filepath); + } + else + { + e->pLinkPath = NULL; + } + + nNumMP3s++; + + OutputDebugString(fd.cFileName); + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + OutputDebugString(filepath); + } + } + } + } + + FindClose(hFind); +} + +static void +_DeleteMP3Entries(void) +{ + tMP3Entry *e = _pMP3List; + + while ( e != NULL ) + { + tMP3Entry *next = e->pNext; + + if ( next == NULL ) + next = NULL; + + if ( e->pLinkPath != NULL ) + { +#ifndef FIX_BUGS + delete e->pLinkPath; // BUG: should be delete [] +#else + delete[] e->pLinkPath; +#endif + e->pLinkPath = NULL; + } + + delete e; + + if ( next ) + e = next; + else + e = NULL; + + nNumMP3s--; + } + + + if ( nNumMP3s != 0 ) + { + OutputDebugString("Not all MP3 entries were deleted"); + nNumMP3s = 0; + } + + _pMP3List = NULL; +} + +static tMP3Entry * +_GetMP3EntryByIndex(uint32 idx) +{ + uint32 n = ( idx < nNumMP3s ) ? idx : 0; + + if ( _pMP3List != NULL ) + { + tMP3Entry *e = _pMP3List; + + for ( uint32 i = 0; i < n; i++ ) + e = e->pNext; + + return e; + + } + + return NULL; +} + +static inline bool +_GetMP3PosFromStreamPos(uint32 *pPosition, tMP3Entry **pEntry) +{ + _CurMP3Index = 0; + + for ( *pEntry = _pMP3List; *pEntry != NULL; *pEntry = (*pEntry)->pNext ) + { + if ( *pPosition >= (*pEntry)->nTrackStreamPos + && *pPosition < (*pEntry)->nTrackLength + (*pEntry)->nTrackStreamPos ) + { + *pPosition -= (*pEntry)->nTrackStreamPos; + _CurMP3Pos = *pPosition; + + return true; + } + + _CurMP3Index++; + } + + *pPosition = 0; + *pEntry = _pMP3List; + _CurMP3Pos = 0; + _CurMP3Index = 0; + + return false; } bool @@ -566,21 +989,45 @@ cSampleManager::Initialise(void) nChannelVolume[i] = 0; } - { - for ( int32 i = 0; i < MAX_STREAMS; i++ ) - { - aStream[i] = NULL; - nStreamVolume[i] = 100; - nStreamPan[i] = 63; - } - + { for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) nStreamLength[i] = 0; } - { add_providers(); - + +#ifdef AUDIO_CACHE + FILE *cacheFile = fcaseopen("audio\\sound.cache", "rb"); + if (cacheFile) { + fread(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); + fclose(cacheFile); + } else +#endif + { + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + { + aStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0]); + + if ( aStream[0] && aStream[0]->IsOpened() ) + { + uint32 tatalms = aStream[0]->GetLengthMS(); + delete aStream[0]; + aStream[0] = NULL; + + nStreamLength[i] = tatalms; + } + else + USERERROR("Can't open '%s'\n", StreamedNameTable[i]); + } +#ifdef AUDIO_CACHE + cacheFile = fcaseopen("audio\\sound.cache", "wb"); + fwrite(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); + fclose(cacheFile); +#endif + } + + { if ( !InitialiseSampleBanks() ) { Terminate(); @@ -598,13 +1045,23 @@ cSampleManager::Initialise(void) nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] = (uintptr)malloc(PED_BLOCKSIZE*MAX_PEDSFX); ASSERT(nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] != 0); + + LoadSampleBank(SFX_BANK_0); } + { + for ( int32 i = 0; i < MAX_STREAMS; i++ ) + { + aStream[i] = NULL; + nStreamVolume[i] = 100; + nStreamPan[i] = 63; + } + } { _bSampmanInitialised = true; - if ( 0 >= defaultProvider && defaultProvider < m_nNumberOfProviders ) + if ( defaultProvider >= 0 && defaultProvider < m_nNumberOfProviders ) { set_new_provider(defaultProvider); } @@ -614,38 +1071,66 @@ cSampleManager::Initialise(void) return false; } } -#ifdef AUDIO_CACHE - FILE *cacheFile = fopen("audio\\sound.cache", "rb"); - if (cacheFile) { - fread(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); - fclose(cacheFile); - } else -#endif + { - - for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) - { - aStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0]); + nNumMP3s = 0; + + _pMP3List = NULL; + + _FindMP3s(); + + if ( nNumMP3s != 0 ) + { + nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] = 0; - if ( aStream[0] && aStream[0]->IsOpened() ) + for ( tMP3Entry *e = _pMP3List; e != NULL; e = e->pNext ) { - uint32 tatalms = aStream[0]->GetLengthMS(); - delete aStream[0]; - aStream[0] = NULL; - - nStreamLength[i] = tatalms; + e->nTrackStreamPos = nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER]; + nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] += e->nTrackLength; + } + + time_t t = time(NULL); + tm *localtm; + bool bUseRandomTable; + + if ( t == -1 ) + bUseRandomTable = true; + else + { + bUseRandomTable = false; + localtm = localtime(&t); } + + int32 randval; + if ( bUseRandomTable ) + randval = AudioManager.GetRandomNumber(1); else - USERERROR("Can't open '%s'\n", StreamedNameTable[i]); + randval = localtm->tm_sec * localtm->tm_min; + + _CurMP3Index = randval % nNumMP3s; + + tMP3Entry *randmp3 = _pMP3List; + for ( int32 i = randval % nNumMP3s; i > 0; --i) + randmp3 = randmp3->pNext; + + if ( bUseRandomTable ) + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + else + { + if ( localtm->tm_sec > 0 ) + { + int32 s = localtm->tm_sec; + _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; + } + else + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + } } -#ifdef AUDIO_CACHE - cacheFile = fopen("audio\\sound.cache", "wb"); - fwrite(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); - fclose(cacheFile); -#endif - } + else + _CurMP3Pos = 0; - LoadSampleBank(SFX_BANK_0); + _bIsMp3Active = false; + } return true; } @@ -653,8 +1138,6 @@ cSampleManager::Initialise(void) void cSampleManager::Terminate(void) { - release_existing(); - for (int32 i = 0; i < MAX_STREAMS; i++) { CStream *stream = aStream[i]; @@ -665,6 +1148,10 @@ cSampleManager::Terminate(void) } } + release_existing(); + + _DeleteMP3Entries(); + CStream::Terminate(); if ( nSampleBankMemoryStartAddress[SFX_BANK_0] != 0 ) @@ -752,7 +1239,7 @@ cSampleManager::SetMonoMode(uint8 nMode) bool cSampleManager::LoadSampleBank(uint8 nBank) { - ASSERT( nBank < MAX_SFX_BANKS ); + ASSERT( nBank < MAX_SFX_BANKS); if ( CTimer::GetIsCodePaused() ) return false; @@ -793,7 +1280,7 @@ cSampleManager::LoadSampleBank(uint8 nBank) void cSampleManager::UnloadSampleBank(uint8 nBank) { - ASSERT( nBank < MAX_SFX_BANKS ); + ASSERT( nBank < MAX_SFX_BANKS); bSampleBankLoaded[nBank] = false; } @@ -801,7 +1288,7 @@ cSampleManager::UnloadSampleBank(uint8 nBank) bool cSampleManager::IsSampleBankLoaded(uint8 nBank) { - ASSERT( nBank < MAX_SFX_BANKS ); + ASSERT( nBank < MAX_SFX_BANKS); return bSampleBankLoaded[nBank]; } @@ -1225,7 +1712,7 @@ cSampleManager::StopChannel(uint32 nChannel) void cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) { - char filename[256]; + char filename[MAX_PATH]; ASSERT( nStream < MAX_STREAMS ); @@ -1283,6 +1770,7 @@ cSampleManager::StartPreloadedStreamedFile(uint8 nStream) bool cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) { + uint32 position = nPos; char filename[256]; ASSERT( nStream < MAX_STREAMS ); @@ -1295,6 +1783,135 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) aStream[nStream] = NULL; } + if ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER ) + { + uint32 i = 0; + do { + if(i != 0 || _bIsMp3Active) { + if(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0; + + _CurMP3Pos = 0; + + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if(mp3) { + mp3 = _pMP3List; + if(mp3 == NULL) { + _bIsMp3Active = false; + nFile = 0; + strcat(filename, StreamedNameTable[nFile]); + + CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); + ASSERT(stream != NULL); + + aStream[nStream] = stream; + + if (stream->IsOpened()) { + if (stream->Setup()) { + if (position != 0) + stream->SetPosMS(position); + + stream->Start(); + } + + return true; + } else { + delete stream; + aStream[nStream] = NULL; + } + + return false; + } + } + + if (mp3->pLinkPath != NULL) + aStream[nStream] = new CStream(mp3->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream]); + else { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, mp3->aFilename); + + aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); + } + + if (aStream[nStream]->IsOpened()) { + if (aStream[nStream]->Setup()) { + aStream[nStream]->Start(); + } + + return true; + } else { + delete aStream[nStream]; + aStream[nStream] = NULL; + } + + _bIsMp3Active = false; + continue; + } + if ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] ) + position = 0; + + tMP3Entry *e; + if ( !_GetMP3PosFromStreamPos(&position, &e) ) + { + if ( e == NULL ) + { + nFile = 0; + strcat(filename, StreamedNameTable[nFile]); + CStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); + ASSERT(stream != NULL); + + aStream[nStream] = stream; + + if (stream->IsOpened()) { + if (stream->Setup()) { + if (position != 0) + stream->SetPosMS(position); + + stream->Start(); + } + + return true; + } else { + delete stream; + aStream[nStream] = NULL; + } + + return false; + } + } + + if (e->pLinkPath != NULL) + aStream[nStream] = new CStream(e->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream]); + else { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, e->aFilename); + + aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); + } + + if (aStream[nStream]->IsOpened()) { + if (aStream[nStream]->Setup()) { + if (position != 0) + aStream[nStream]->SetPosMS(position); + + aStream[nStream]->Start(); + } + + _bIsMp3Active = true; + return true; + } else { + delete aStream[nStream]; + aStream[nStream] = NULL; + } + + _bIsMp3Active = false; + + } while(++i < nNumMP3s); + + position = 0; + nFile = 0; + } + strcpy(filename, StreamedNameTable[nFile]); CStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); @@ -1302,21 +1919,16 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) aStream[nStream] = stream; - if ( stream->IsOpened() ) - { - nStreamLength[nFile] = stream->GetLengthMS(); - if ( stream->Setup() ) - { - if ( nPos != 0 ) - stream->SetPosMS(nPos); - + if ( stream->IsOpened() ) { + if ( stream->Setup() ) { + if (position != 0) + stream->SetPosMS(position); + stream->Start(); } return true; - } - else - { + } else { delete stream; aStream[nStream] = NULL; } @@ -1468,5 +2080,4 @@ cSampleManager::InitialiseSampleBanks(void) return true; } - #endif diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 3b46a110..e2f90a7c 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -2399,7 +2399,7 @@ bool CPad::GetAnaloguePadLeftJustUp(void) if ( X == 0 && oldfStickX < 0 ) { - oldfStickX = X; + oldfStickX = 0; return true; } @@ -2419,7 +2419,7 @@ bool CPad::GetAnaloguePadRightJustUp(void) if ( X == 0 && oldfStickX > 0 ) { - oldfStickX = X; + oldfStickX = 0; return true; } diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index af28aae7..816da6b9 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -84,10 +84,6 @@ static_assert(RADAR_TILE_SIZE == (RADAR_SIZE_Y / RADAR_NUM_TILES), "CRadar: not #define RADAR_MAX_SPEED (0.9f) #ifdef MENU_MAP -CRGBA CRadar::ArrowBlipColour1; -CRGBA CRadar::ArrowBlipColour2; -uint16 CRadar::MapLegendCounter; -uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS]; int CRadar::TargetMarkerId = -1; CVector CRadar::TargetMarkerPos; #endif @@ -116,7 +112,7 @@ void RequestMapSection(int32 x, int32 y) void RemoveMapSection(int32 x, int32 y) { - if (x >= 0 && x <= 7 && y >= 0 && y <= 7) + if (x >= 0 && x <= RADAR_NUM_TILES - 1 && y >= 0 && y <= RADAR_NUM_TILES - 1) CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]); } @@ -709,6 +705,7 @@ void CRadar::DrawBlips() if (CMenuManager::bMenuMapActive) { CVector2D in, out; TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift()); + LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); DrawYouAreHereSprite(out.x, out.y); } @@ -782,14 +779,20 @@ void CRadar::DrawRadarMask() }; RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); +#if !defined(GTA_PS2_STUFF) && defined(RWLIBS) + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS); +#else + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); +#endif CVector2D out[8]; CVector2D in; @@ -810,7 +813,10 @@ void CRadar::DrawRadarMask() CSprite2d::SetMaskVertices(8, (float *)out); RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8); - }; + } +#if !defined(GTA_PS2_STUFF) && defined(RWLIBS) + RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); +#endif } void CRadar::DrawRadarSection(int32 x, int32 y) @@ -860,46 +866,22 @@ void CRadar::DrawRadarSection(int32 x, int32 y) void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha) { RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { - bool alreadyThere = false; - for (int i = 0; i < NUM_MAP_LEGENDS; i++) { - if (MapLegendList[i] == sprite) - alreadyThere = true; - } - if (!alreadyThere) { - MapLegendList[MapLegendCounter] = sprite; - MapLegendCounter++; - } - } -#endif } void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) { CVector curPosn[4]; - CVector oldPosn[4]; - - curPosn[0].x = x - SCREEN_SCALE_X(5.6f); - curPosn[0].y = y + SCREEN_SCALE_Y(5.6f); - - curPosn[1].x = x + SCREEN_SCALE_X(5.6f); - curPosn[1].y = y + SCREEN_SCALE_Y(5.6f); - - curPosn[2].x = x - SCREEN_SCALE_X(5.6f); - curPosn[2].y = y - SCREEN_SCALE_Y(5.6f); - - curPosn[3].x = x + SCREEN_SCALE_X(5.6f); - curPosn[3].y = y - SCREEN_SCALE_Y(5.6f); + const float sizeX = SCREEN_SCALE_X(8.0f); + const float correctedAngle = angle - PI / 4.f; + const float sizeY = SCREEN_SCALE_Y(8.0f); for (uint32 i = 0; i < 4; i++) { - oldPosn[i] = curPosn[i]; - - curPosn[i].x = x + (oldPosn[i].x - x) * Cos(angle) + (oldPosn[i].y - y) * Sin(angle); - curPosn[i].y = y - (oldPosn[i].x - x) * Sin(angle) + (oldPosn[i].y - y) * Cos(angle); + const float cornerAngle = i * HALFPI + correctedAngle; + curPosn[i].x = x + (0.0f * Cos(cornerAngle) + 1.0f * Sin(cornerAngle)) * sizeX; + curPosn[i].y = y - (0.0f * Sin(cornerAngle) - 1.0f * Cos(cornerAngle)) * sizeY; } - sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha)); + sprite->Draw(curPosn[3].x, curPosn[3].y, curPosn[2].x, curPosn[2].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha)); } int32 CRadar::GetActualBlipArrayIndex(int32 i) @@ -925,43 +907,43 @@ uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright) { int32 c; switch (color) { - case 0: + case RADAR_TRACE_RED: if (bright) c = 0x712B49FF; else c = 0x7F0000FF; break; - case 1: + case RADAR_TRACE_GREEN: if (bright) c = 0x5FA06AFF; else c = 0x007F00FF; break; - case 2: + case RADAR_TRACE_LIGHT_BLUE: if (bright) c = 0x80A7F3FF; else c = 0x00007FFF; break; - case 3: + case RADAR_TRACE_GRAY: if (bright) c = 0xE1E1E1FF; else c = 0x7F7F7FFF; break; - case 4: + case RADAR_TRACE_YELLOW: if (bright) c = 0xFFFF00FF; else c = 0x7F7F00FF; break; - case 5: + case RADAR_TRACE_MAGENTA: if (bright) c = 0xFF00FFFF; else c = 0x7F007FFF; break; - case 6: + case RADAR_TRACE_CYAN: if (bright) c = 0x00FFFFFF; else @@ -1215,21 +1197,6 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha)); break; } -#ifdef MENU_MAP - // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips - if (CMenuManager::bMenuMapActive) { - bool alreadyThere = false; - for (int i = 0; i < NUM_MAP_LEGENDS; i++) { - if (MapLegendList[i] == -1) - alreadyThere = true; - } - if (!alreadyThere) { - MapLegendList[MapLegendCounter] = -1; - MapLegendCounter++; - ArrowBlipColour1 = CRGBA(red, green, blue, alpha); - } - } -#endif } void CRadar::Shutdown() @@ -1415,12 +1382,6 @@ CRadar::InitFrontEndMap() vec2DRadarOrigin.x = 0.0f; vec2DRadarOrigin.y = 0.0f; m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace - for (int i = 0; i < NUM_MAP_LEGENDS; i++) { - MapLegendList[i] = RADAR_SPRITE_NONE; - } - MapLegendCounter = 0; - ArrowBlipColour1 = CRGBA(0, 0, 0, 0); - ArrowBlipColour2 = CRGBA(0, 0, 0, 0); } void @@ -1448,7 +1409,6 @@ CRadar::DrawYouAreHereSprite(float x, float y) float bottom = y - SCREEN_SCALE_Y(24.0f); CentreSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 255, 255, 255)); } - MapLegendList[MapLegendCounter++] = RADAR_SPRITE_CENTRE; } void @@ -1465,8 +1425,8 @@ CRadar::ToggleTargetMarker(float x, float y) return; #endif ms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD; - ms_RadarTrace[nextBlip].m_nColor = 0x333333FF; - ms_RadarTrace[nextBlip].m_bDim = 1; + ms_RadarTrace[nextBlip].m_nColor = RADAR_TRACE_GRAY; + ms_RadarTrace[nextBlip].m_bDim = 0; ms_RadarTrace[nextBlip].m_bInUse = 1; ms_RadarTrace[nextBlip].m_Radius = 1.0f; CVector pos(x, y, CWorld::FindGroundZForCoord(x,y)); diff --git a/src/core/Radar.h b/src/core/Radar.h index ec2bacd0..793d62b0 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -49,6 +49,17 @@ enum eRadarSprite RADAR_SPRITE_COUNT }; +enum +{ + RADAR_TRACE_RED, + RADAR_TRACE_GREEN, + RADAR_TRACE_LIGHT_BLUE, + RADAR_TRACE_GRAY, + RADAR_TRACE_YELLOW, + RADAR_TRACE_MAGENTA, + RADAR_TRACE_CYAN +}; + enum { BLIP_MODE_TRIANGULAR_UP = 0, @@ -108,11 +119,6 @@ public: static float cachedCos; static float cachedSin; #ifdef MENU_MAP -#define NUM_MAP_LEGENDS 75 - static CRGBA ArrowBlipColour1; - static CRGBA ArrowBlipColour2; - static uint16 MapLegendList[NUM_MAP_LEGENDS]; - static uint16 MapLegendCounter; static int TargetMarkerId; static CVector TargetMarkerPos; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7c9b78f4..fcfd9bce 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -631,7 +631,7 @@ CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer) // BUG: This condition will always return true. Even fixing it won't work, because these states are unused. // if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) { - CPed::SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); // } bBodyPartJustCameOff = true; @@ -814,15 +814,15 @@ CPed::Avoid(void) // Get distance to ped we want to avoid CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition; - if (distToPed.Magnitude() <= 1.0f && CPed::OurPedCanSeeThisOne((CEntity*)nearestPed)) { + if (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) { m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 / 5; m_fRotationDest += DEGTORAD(45.0f); if (!bIsLooking) { - CPed::SetLookFlag(nearestPed, false); - CPed::SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800)); + SetLookFlag(nearestPed, false); + SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800)); } } } @@ -861,8 +861,7 @@ CPed::ClearLookFlag(void) { m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000; if (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) { - RestorePreviousState(); - ClearLookFlag(); + ClearLook(); } } } @@ -985,7 +984,7 @@ CPed::Attack(void) weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); } - weaponAnimAssoc->SetFinishCallback(CPed::FinishedAttackCB, this); + weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this); weaponAnimAssoc->SetRun(); if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength) @@ -2900,7 +2899,7 @@ CPed::ReactToAttack(CEntity *attacker) #ifdef VC_PED_PORTS if (m_nPedState == PED_DRIVING && InVehicle() - && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING)) { + && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) { if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS) @@ -4435,11 +4434,11 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) bool vehPressedHorn = false; if (neededTurn > PI) - neededTurn = 2 * PI - neededTurn; + neededTurn = TWOPI - neededTurn; CVehicle *veh = (CVehicle*)reason; if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR) { - if (veh->m_nCarHornTimer) { + if (veh->m_nCarHornTimer != 0) { vehPressedHorn = true; if (!IsPlayer()) animType = 1; @@ -4459,7 +4458,7 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) angleToFace += PI; if (angleToFace > PI) - angleToFace -= 2*PI; + angleToFace -= TWOPI; // We don't want to run towards car's direction float dangerZone = angleToFace - vehDirection; @@ -4467,16 +4466,15 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) // So, add or subtract 90deg (jump to left/right) according to that if (dangerZone <= 0.0f) - angleToFace = 0.5f*PI + vehDirection; + angleToFace = HALFPI + vehDirection; else - angleToFace = vehDirection - 0.5f*PI; + angleToFace = vehDirection - HALFPI; - if (animType == 2) - stepAnim = ANIM_HANDSCOWER; - else if (animType < 2) + stepAnim = NUM_ANIMS; + if (animType == 0 || animType == 1) stepAnim = ANIM_EV_STEP; - else - stepAnim = NUM_ANIMS; + else if (animType == 2) + stepAnim = ANIM_HANDSCOWER; } if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) { CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f); @@ -4506,7 +4504,7 @@ CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump) angleToFace = m_fRotationCur; CVehicle *veh = (CVehicle*) reason; - if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer && !IsPlayer()) { + if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) { onlyRandomJump = true; } @@ -8341,7 +8339,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq); } bIsStanding = false; - damageDir = CPed::GetLocalDirection(-m_vecMoveSpeed); + damageDir = GetLocalDirection(-m_vecMoveSpeed); vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex()); vehColModel = vehModel->GetColModel(); float carRightAndDistDotProd = DotProduct(distVec, car->GetRight()); @@ -8477,7 +8475,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) pieceToDamage = PEDPIECE_MID; break; } - CPed::InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir); + InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir); if (DyingOrDead() && bIsPedDieAnimPlaying && !m_pCollidingEntity) { @@ -8507,8 +8505,8 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) else damage = 30.0f; - CPed::InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection); - CPed::SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true); + InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection); + SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true); if (OnGround() && !m_pCollidingEntity && (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) { @@ -9680,7 +9678,7 @@ CPed::ProcessControl(void) } else if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) { - CPed::SetDirectionToWalkAroundObject(collidingVeh); + SetDirectionToWalkAroundObject(collidingVeh); CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; } else if (m_fleeFrom != collidingVeh) { @@ -9906,7 +9904,7 @@ CPed::ProcessControl(void) SetHeading(m_fRotationCur); if (m_nPedState != PED_FALL && !bIsPedDieAnimPlaying) { - CPed::SetFall(1000, ANIM_KO_SKID_BACK, true); + SetFall(1000, ANIM_KO_SKID_BACK, true); } bIsInTheAir = false; } else if (m_vecDamageNormal.z > 0.4f) { @@ -10217,19 +10215,19 @@ CPed::ProcessControl(void) Flee(); break; case PED_FOLLOW_PATH: - CPed::FollowPath(); + FollowPath(); break; case PED_PAUSE: - CPed::Pause(); + Pause(); break; case PED_ATTACK: - CPed::Attack(); + Attack(); break; case PED_FIGHT: - CPed::Fight(); + Fight(); break; case PED_CHAT: - CPed::Chat(); + Chat(); break; case PED_AIM_GUN: if (m_pPointGunAt && m_pPointGunAt->IsPed() @@ -15982,7 +15980,7 @@ CPed::SeekCar(void) if (m_vehEnterType == CAR_DOOR_RF && vehToSeek->pPassengers[0]) { if (vehToSeek->pPassengers[0]->bDontDragMeOutCar) { if (IsPlayer()) - CPed::SetEnterCar(vehToSeek, m_vehEnterType); + SetEnterCar(vehToSeek, m_vehEnterType); } else { SetCarJack(vehToSeek); } @@ -16152,15 +16150,15 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) case HITLEVEL_LOW: #ifndef VC_PED_PORTS if (direction == 2) { - CPed::SetFall(1000, ANIM_KO_SKID_BACK, false); + SetFall(1000, ANIM_KO_SKID_BACK, false); return; } #else if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) { - CPed::SetFall(1000, ANIM_KO_SKID_BACK, false); + SetFall(1000, ANIM_KO_SKID_BACK, false); return; } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) { - CPed::SetFall(1000, ANIM_KO_SHOT_STOM, false); + SetFall(1000, ANIM_KO_SHOT_STOM, false); return; } #endif @@ -17366,12 +17364,12 @@ CPed::SetExitBoat(CVehicle *boat) CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) { m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f); - m_pVehicleAnim->SetFinishCallback(CPed::PedSetOutCarCB, this); + m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this); m_vehEnterType = CAR_DOOR_RF; m_nPedState = PED_EXIT_CAR; } else { m_vehEnterType = CAR_DOOR_RF; - CPed::PedSetOutCarCB(nil, this); + PedSetOutCarCB(nil, this); bIsStanding = true; m_pCurSurface = boat; m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface); diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 63bf0b06..a6e6bccf 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -41,13 +41,13 @@ CRGBA ODDJOB_COLOR(89, 115, 150, 255); CRGBA ODDJOB2_COLOR(156, 91, 40, 255); CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255); -wchar CHud::m_HelpMessage[256]; -wchar CHud::m_LastHelpMessage[256]; +wchar CHud::m_HelpMessage[HELP_MSG_LENGTH]; +wchar CHud::m_LastHelpMessage[HELP_MSG_LENGTH]; uint32 CHud::m_HelpMessageState; uint32 CHud::m_HelpMessageTimer; int32 CHud::m_HelpMessageFadeTimer; -wchar CHud::m_HelpMessageToPrint[256]; -float CHud::m_fHelpMessageTime; +wchar CHud::m_HelpMessageToPrint[HELP_MSG_LENGTH]; +float CHud::m_HelpMessageDisplayTime; bool CHud::m_HelpMessageQuick; uint32 CHud::m_ZoneState; int32 CHud::m_ZoneFadeTimer; @@ -1047,14 +1047,14 @@ void CHud::DrawAfterFade() return; if (m_HelpMessage[0]) { - if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, 256)) { + if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, HELP_MSG_LENGTH)) { switch (m_HelpMessageState) { case 0: m_HelpMessageFadeTimer = 0; m_HelpMessageState = 2; m_HelpMessageTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256); - m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH); + m_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; if (TheCamera.m_ScreenReductionPercentage == 0.0f) DMAudio.PlayFrontEndSound(SOUND_HUD, 0); @@ -1069,7 +1069,7 @@ void CHud::DrawAfterFade() default: break; } - CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256); + CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH); } float fAlpha = 225.0f; @@ -1079,7 +1079,7 @@ void CHud::DrawAfterFade() case 1: fAlpha = 225.0f; m_HelpMessageFadeTimer = 600; - if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { + if (m_HelpMessageTimer > m_HelpMessageDisplayTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { m_HelpMessageFadeTimer = 600; m_HelpMessageState = 3; } @@ -1105,7 +1105,7 @@ void CHud::DrawAfterFade() if (m_HelpMessageFadeTimer < 0) { m_HelpMessageState = 2; m_HelpMessageFadeTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256); + CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, HELP_MSG_LENGTH); } fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; break; @@ -1371,7 +1371,7 @@ void CHud::GetRidOfAllHudMessages() m_ZoneNameTimer = 0; m_pZoneName = nil; - for (int i = 0; i < 256; i++) { + for (int i = 0; i < HELP_MSG_LENGTH; i++) { m_HelpMessage[i] = 0; m_LastHelpMessage[i] = 0; m_HelpMessageToPrint[i] = 0; @@ -1381,7 +1381,7 @@ void CHud::GetRidOfAllHudMessages() m_HelpMessageFadeTimer = 0; m_HelpMessageState = 0; m_HelpMessageQuick = 0; - m_fHelpMessageTime = 1.0f; + m_HelpMessageDisplayTime = 1.0f; m_VehicleName = nil; m_pLastVehicleName = nil; m_pVehicleNameToPrint = nil; @@ -1389,7 +1389,7 @@ void CHud::GetRidOfAllHudMessages() m_VehicleFadeTimer = 0; m_VehicleState = 0; - for (int i = 0; i < 256; i++) + for (int i = 0; i < ARRAY_SIZE(m_Message); i++) m_Message[i] = 0; for (int i = 0; i < 6; i++) { @@ -1464,7 +1464,7 @@ void CHud::ReInitialise() { wchar LastBigMessage[6][128]; -void CHud::SetBigMessage(wchar *message, int16 style) +void CHud::SetBigMessage(wchar *message, uint16 style) { int i = 0; @@ -1495,10 +1495,10 @@ void CHud::SetBigMessage(wchar *message, int16 style) void CHud::SetHelpMessage(wchar *message, bool quick) { if (!CReplay::IsPlayingBack()) { - CMessages::WideStringCopy(m_HelpMessage, message, 256); + CMessages::WideStringCopy(m_HelpMessage, message, HELP_MSG_LENGTH); CMessages::InsertPlayerControlKeysInString(m_HelpMessage); - for (int i = 0; i < 256; i++) { + for (int i = 0; i < HELP_MSG_LENGTH; i++) { m_LastHelpMessage[i] = 0; } @@ -1510,7 +1510,7 @@ void CHud::SetHelpMessage(wchar *message, bool quick) void CHud::SetMessage(wchar *message) { int i = 0; - for (i = 0; i < 256; i++) { + for (i = 0; i < ARRAY_SIZE(m_Message); i++) { if (message[i] == 0) break; @@ -1522,7 +1522,7 @@ void CHud::SetMessage(wchar *message) void CHud::SetPagerMessage(wchar *message) { int i = 0; - for (i = 0; i < 256; i++) { + for (i = 0; i < ARRAY_SIZE(m_PagerMessage); i++) { if (message[i] == 0) break; diff --git a/src/render/Hud.h b/src/render/Hud.h index 701e47e2..bef73cc2 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -1,6 +1,8 @@ #pragma once #include "Sprite2d.h" +#define HELP_MSG_LENGTH 256 + enum eItems { ITEM_NONE = -1, @@ -36,14 +38,13 @@ class CHud { public: static CSprite2d Sprites[NUM_HUD_SPRITES]; - static wchar m_HelpMessage[256]; - static wchar m_LastHelpMessage[256]; + static wchar m_HelpMessage[HELP_MSG_LENGTH]; + static wchar m_LastHelpMessage[HELP_MSG_LENGTH]; static uint32 m_HelpMessageState; static uint32 m_HelpMessageTimer; static int32 m_HelpMessageFadeTimer; - static wchar m_HelpMessageToPrint[256]; - static float &m_HelpMessageDisplayTime; - static float m_fHelpMessageTime; + static wchar m_HelpMessageToPrint[HELP_MSG_LENGTH]; + static float m_HelpMessageDisplayTime; static bool m_HelpMessageQuick; static uint32 m_ZoneState; static int32 m_ZoneFadeTimer; @@ -88,7 +89,7 @@ public: static void GetRidOfAllHudMessages(); static void Initialise(); static void ReInitialise(); - static void SetBigMessage(wchar *message, int16 style); + static void SetBigMessage(wchar *message, uint16 style); static void SetHelpMessage(wchar *message, bool quick); static void SetMessage(wchar *message); static void SetPagerMessage(wchar *message); diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index a867ae13..acce946b 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -302,8 +302,8 @@ void CParticle::Initialise() { float angle = DEGTORAD(float(i) * float(360.0f / SIN_COS_TABLE_SIZE)); - m_SinTable[i] = Sin(angle); - m_CosTable[i] = Cos(angle); + m_SinTable[i] = ::Sin(angle); + m_CosTable[i] = ::Cos(angle); } int32 slot = CTxdStore::FindTxdSlot("particle"); diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp index 2b34db37..f54b31b9 100644 --- a/src/render/WaterCannon.cpp +++ b/src/render/WaterCannon.cpp @@ -64,7 +64,7 @@ void CWaterCannon::Update_OncePerFrame(int16 index) if (CTimer::GetTimeInMilliseconds() > m_nTimeCreated + WATERCANNON_LIFETIME ) { - m_nCur = (m_nCur + 1) % -NUM_SEGMENTPOINTS; + m_nCur = (m_nCur + 1) % NUM_SEGMENTPOINTS; m_abUsed[m_nCur] = false; } @@ -124,7 +124,7 @@ void CWaterCannon::Render(void) RwIm3DVertexSetV(&WaterCannonVertices[2], v); RwIm3DVertexSetV(&WaterCannonVertices[3], v); - int16 pointA = m_nCur % -NUM_SEGMENTPOINTS; + int16 pointA = m_nCur % NUM_SEGMENTPOINTS; int16 pointB = pointA - 1; if ( (pointA - 1) < 0 ) diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index f568532a..fca5b4a4 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -431,11 +431,13 @@ CameraSize(RwCamera * camera, RwRect * rect, } } - if (( origSize.w != rect->w ) && ( origSize.h != rect->h )) + if (( origSize.w != rect->w ) || ( origSize.h != rect->h )) { RwRaster *raster; RwRaster *zRaster; + // BUG: game just changes camera raster's sizes, but this is a hack +#ifdef FIX_BUGS /* * Destroy rasters... */ @@ -493,6 +495,13 @@ CameraSize(RwCamera * camera, RwRect * rect, RwCameraSetRaster(camera, raster); RwCameraSetZRaster(camera, zRaster); } +#else + raster = RwCameraGetRaster(camera); + zRaster = RwCameraGetZRaster(camera); + + raster->width = zRaster->width = rect->w; + raster->height = zRaster->height = rect->h; +#endif } /* Figure out the view window */ diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index cdb73992..4d41a900 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -418,7 +418,7 @@ psInitialize(void) } else if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) { - if ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion == 1 ) + if ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion != 0 ) { debug("Operating System is Win98\n"); _dwOperatingSystemVersion = OS_WIN98; @@ -1220,14 +1220,17 @@ void resizeCB(GLFWwindow* window, int width, int height) { * memory things don't work. */ /* redraw window */ - if (RwInitialised && (gGameState == GS_PLAYING_GAME #ifndef MASTER - || gGameState == GS_ANIMVIEWER -#endif - )) + if (RwInitialised && (gGameState == GS_PLAYING_GAME || gGameState == GS_ANIMVIEWER)) { - RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void*)TRUE); + RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void *)TRUE); } +#else + if (RwInitialised && gGameState == GS_PLAYING_GAME) + { + RsEventHandler(rsIDLE, (void *)TRUE); + } +#endif if (RwInitialised && height > 0 && width > 0) { RwRect r; diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index ac46d23a..9effaa31 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -684,7 +684,7 @@ psInitialize(void) } else if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) { - if ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion == 1 ) + if ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion != 0 ) { debug("Operating System is Win98\n"); _dwOperatingSystemVersion = OS_WIN98; @@ -1012,11 +1012,17 @@ MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) RECT rect; /* redraw window */ +#ifndef MASTER if (RwInitialised && (gGameState == GS_PLAYING_GAME || gGameState == GS_ANIMVIEWER)) { RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void *)TRUE); } - +#else + if (RwInitialised && gGameState == GS_PLAYING_GAME) + { + RsEventHandler(rsIDLE, (void *)TRUE); + } +#endif /* Manually resize window */ rect.left = rect.top = 0; rect.bottom = newPos->bottom - newPos->top; @@ -1369,14 +1375,20 @@ UINT GetBestRefreshRate(UINT width, UINT height, UINT depth) #endif if ( mode.Width == width && mode.Height == height && mode.Format == format ) { - if ( mode.RefreshRate == 0 ) + if ( mode.RefreshRate == 0 ) { + // From VC +#ifdef FIX_BUGS + d3d->Release(); +#endif return 0; + } if ( mode.RefreshRate < refreshRate && mode.RefreshRate >= 60 ) refreshRate = mode.RefreshRate; } } + // From VC #ifdef FIX_BUGS d3d->Release(); #endif -- cgit v1.2.3 From 0eb4aca1d64c16bcbf2c48dfeae05ac9adf39d73 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sun, 18 Oct 2020 20:09:55 +0300 Subject: Fix build --- src/audio/sampman_miles.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index 392bface..185e08d6 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -2176,8 +2176,7 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) if ( mp3Stream[nStream] ) { AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_loop_count(mp3Stream[nStream], nStreamLoopedFlag[nStream] ? 0 : 1); - nStreamLoopedFlag[nStream] = true; + AIL_set_stream_ms_position(mp3Stream[nStream], position); AIL_pause_stream(mp3Stream[nStream], 0); return true; } @@ -2332,4 +2331,4 @@ cSampleManager::InitialiseSampleBanks(void) return true; } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 7ae25761d5f60c78631bfafa3fc10ac7199f3039 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Sun, 18 Oct 2020 19:57:39 +0200 Subject: Tweak comparison in CFallingGlassPane::Render --- src/render/Glass.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index aabb6e52..0b25525e 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -1,4 +1,4 @@ -#include "common.h" +#include "common.h" #include "Glass.h" #include "Timer.h" @@ -138,7 +138,11 @@ CFallingGlassPane::Render(void) fwdNorm.Normalise(); uint8 alpha = CGlass::CalcAlphaWithNormal(&fwdNorm); - int32 time = clamp(CTimer::GetTimeInMilliseconds() - m_nTimer, 0, 500); +#ifdef FIX_BUGS + uint16 time = clamp(CTimer::GetTimeInMilliseconds() > m_nTimer ? CTimer::GetTimeInMilliseconds() - m_nTimer : 0u, 0u, 500u); +#else + uint16 time = clamp(CTimer::GetTimeInMilliseconds() - m_nTimer, 0, 500); +#endif uint8 color = int32( float(alpha) * (float(time) / 500) ); -- cgit v1.2.3 From af53267b74c4e831787761ae12472a98ada110b0 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 21 Oct 2020 03:11:10 +0300 Subject: Text and cross-platform fix --- src/skel/crossplatform.cpp | 41 +++++++++++++++++++++++------------------ src/text/Messages.cpp | 38 ++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index ac4bbe85..626403f8 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -26,34 +26,39 @@ void GetLocalTime_CP(SYSTEMTIME *out) { // Compatible with Linux/POSIX and MinGW on Windows #ifndef _WIN32 HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) { - char newpathname[32]; + char pathCopy[32]; - strncpy(newpathname, pathname, 32); - char* path = strtok(newpathname, "*"); + strncpy(pathCopy, pathname, 32); + char* folder = strtok(pathCopy, "*"); // Case-sensitivity and backslashes... - char *real = casepath(path); - if (real) { - real[strlen(real)] = '*'; - char *extension = strtok(NULL, "*"); - if (extension) - strcat(real, extension); + char *realFolder = casepath(folder); + char *extension = nil; + if (realFolder) { + realFolder[strlen(realFolder)] = '*'; + extension = strtok(NULL, "*"); + if (extension) { + strcat(realFolder, extension); + } - strncpy(newpathname, real, 32); - free(real); - path = strtok(newpathname, "*"); + strncpy(pathCopy, realFolder, 32); + free(realFolder); + folder = strtok(pathCopy, "*"); + } else { + // Wildcard (*) + if (strlen(folder) + 1 != strlen(pathname)) + extension = strtok(NULL, "*"); } - strncpy(firstfile->folder, path, sizeof(firstfile->folder)); + strncpy(firstfile->folder, folder, sizeof(firstfile->folder)); - // Both w/ extension and w/o extension is ok - if (strlen(path) + 1 != strlen(pathname)) - strncpy(firstfile->extension, strtok(NULL, "*"), sizeof(firstfile->extension)); + if (extension) + strncpy(firstfile->extension, extension, sizeof(firstfile->extension)); else - strncpy(firstfile->extension, "", sizeof(firstfile->extension)); + firstfile->extension[0] = '\0'; HANDLE d; - if ((d = (HANDLE)opendir(path)) == NULL || !FindNextFile(d, firstfile)) + if ((d = (HANDLE)opendir(folder)) == NULL || !FindNextFile(d, firstfile)) return NULL; return d; diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index 82ab294c..2e0323eb 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -69,10 +69,7 @@ CMessages::WideStringCompare(wchar *str1, wchar *str2, uint16 size) if (len1 != len2 && (len1 < size || len2 < size)) return false; - for (int32 i = 0; i < size; i++) { - if (FixupChar(str1[i]) == '\0') - break; - + for (int32 i = 0; FixupChar(str1[i]) != '\0' && i < size; i++) { if (FixupChar(str1[i]) != FixupChar(str2[i])) return false; } @@ -328,9 +325,7 @@ void CMessages::AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string) { int32 i = 0; - while (i < NUMPREVIOUSBRIEFS) { - if (PreviousBriefs[i].m_pText == nil) - break; + for (i = 0; PreviousBriefs[i].m_pText && i < NUMPREVIOUSBRIEFS; i++) { if (PreviousBriefs[i].m_nNumber[0] == n1 && PreviousBriefs[i].m_nNumber[1] == n2 && PreviousBriefs[i].m_nNumber[2] == n3 @@ -340,8 +335,6 @@ CMessages::AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, in && PreviousBriefs[i].m_pText == text && PreviousBriefs[i].m_pString == string) return; - - i++; } if (i != 0) { @@ -374,6 +367,14 @@ CMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 return; } + sprintf(numStr, "%d", n1); + size_t outLen = strlen(numStr); + AsciiToUnicode(numStr, wNumStr); + if (str[0] == 0) { + *outstr = '\0'; + return; + } + int32 size = GetWideStringLength(str); int32 i = 0; @@ -385,6 +386,11 @@ CMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 #else if (str[c] == '~' && str[c + 1] == '1' && str[c + 2] == '~') { #endif + c += 3; + for (int j = 0; j < outLen; j++) + *(outstr++) = wNumStr[j++]; + + i++; switch (i) { case 0: sprintf(numStr, "%d", n1); break; case 1: sprintf(numStr, "%d", n2); break; @@ -393,14 +399,8 @@ CMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 case 4: sprintf(numStr, "%d", n5); break; case 5: sprintf(numStr, "%d", n6); break; } - i++; + outLen = strlen(numStr); AsciiToUnicode(numStr, wNumStr); - - int j = 0; - while (wNumStr[j] != '\0') - *(outstr++) = wNumStr[j++]; - - c += 3; } else { *(outstr++) = str[c++]; } @@ -466,10 +466,12 @@ CMessages::InsertPlayerControlKeysInString(wchar *str) if (str[i] == '~' && str[i + 1] == 'k' && str[i + 2] == '~') { #endif i += 4; - for (int32 cont = 0; cont < MAX_CONTROLLERACTIONS; cont++) { + bool done = false; + for (int32 cont = 0; cont < MAX_CONTROLLERACTIONS && !done; cont++) { uint16 contSize = GetWideStringLength(ControlsManager.m_aActionNames[cont]); if (contSize != 0) { if (WideStringCompare(&str[i], ControlsManager.m_aActionNames[cont], contSize)) { + done = true; ControlsManager.GetWideStringOfCommandKeys(cont, keybuf, 256); uint16 keybuf_size = GetWideStringLength(keybuf); for (uint16 j = 0; j < keybuf_size; j++) { @@ -751,7 +753,7 @@ CMessages::ClearThisPrint(wchar *str) } BriefMessages[i].m_pText = nil; BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds(); - if (BriefMessages[0].m_pText == nil) + if (BriefMessages[0].m_pText != nil) AddToPreviousBriefArray( BriefMessages[0].m_pText, BriefMessages[0].m_nNumber[0], -- cgit v1.2.3 From 632569cff3e109d2de69e5cd5df2c25d3a657a8d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 21 Oct 2020 19:48:13 +0300 Subject: Pickup fixes --- src/control/Pickups.cpp | 54 ++++++++++++++++++++++++++++++------------------- src/control/Pickups.h | 5 ++--- 2 files changed, 35 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 78084624..6fea43fb 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -54,20 +54,15 @@ uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 25 uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 }; float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f }; -void -CPickup::RemoveKeepType() + +inline void +CPickup::Remove() { CWorld::Remove(m_pObject); delete m_pObject; m_bRemoved = true; m_pObject = nil; -} - -void -CPickup::Remove() -{ - RemoveKeepType(); m_eType = PICKUP_NONE; } @@ -131,7 +126,6 @@ CPickup::GiveUsAPickUpObject(int32 handle) bool CPickup::CanBePickedUp(CPlayerPed *player) { - assert(m_pObject != nil); bool cannotBePickedUp = (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f) || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f) @@ -144,6 +138,7 @@ bool CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) { float waterLevel; + bool result = false; if (m_bRemoved) { if (CTimer::GetTimeInMilliseconds() > m_nTimer) { @@ -204,9 +199,12 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE); } - RemoveKeepType(); + result = true; + CWorld::Remove(m_pObject); + delete m_pObject; + m_pObject = nil; m_nTimer = CTimer::GetTimeInMilliseconds() + 5000; - return true; + m_bRemoved = true; } break; case PICKUP_ON_STREET: @@ -235,8 +233,12 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) m_nTimer = CTimer::GetTimeInMilliseconds() + 720000; } - RemoveKeepType(); - return true; + result = true; + CWorld::Remove(m_pObject); + delete m_pObject; + m_pObject = nil; + m_bRemoved = true; + break; case PICKUP_ONCE: case PICKUP_ONCE_TIMEOUT: if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { @@ -247,8 +249,9 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) } DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); } + result = true; Remove(); - return true; + break; case PICKUP_COLLECTABLE1: CWorld::Players[playerId].m_nCollectedPackages++; CWorld::Players[playerId].m_nMoney += 1000; @@ -260,18 +263,20 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) } else CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); + result = true; Remove(); DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0); - return true; + break; case PICKUP_MONEY: CWorld::Players[playerId].m_nMoney += m_nQuantity; sprintf(gString, "$%d", m_nQuantity); #ifdef MONEY_MESSAGES CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f); #endif + result = true; Remove(); DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0); - return true; + break; default: break; } @@ -298,7 +303,9 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { touched = true; - break; // added break here +#ifdef FIX_BUGS + break; +#endif } } @@ -320,12 +327,17 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) bool explode = false; if (CTimer::GetTimeInMilliseconds() > m_nTimer) explode = true; - else {// added else here since vehicle lookup is useless +#ifdef FIX_BUGS + else// added else here since vehicle lookup is useless +#endif + { for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { explode = true; - break; // added break here +#ifdef FIX_BUGS + break; +#endif } } } @@ -352,8 +364,8 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) m_pObject->UpdateRwFrame(); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { Remove(); + result = true; DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0); - return true; } break; default: break; @@ -361,7 +373,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) } if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer) Remove(); - return false; + return result; } void diff --git a/src/control/Pickups.h b/src/control/Pickups.h index b05f5db7..95eb6fbf 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -41,10 +41,9 @@ public: CObject *GiveUsAPickUpObject(int32 handle); bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId); private: - bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; } + inline bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; } inline bool CanBePickedUp(CPlayerPed *player); - void RemoveKeepType(); - void Remove(); + inline void Remove(); }; VALIDATE_SIZE(CPickup, 0x1C); -- cgit v1.2.3 From bd8d8b53a3c724daf2e4bd2be24243aebd6b9e35 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 21 Oct 2020 21:26:10 +0300 Subject: CTempColModels small fix --- src/core/TempColModels.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index ab73631d..f6796909 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -21,7 +21,11 @@ CColModel CTempColModels::ms_colModelBonnet1; CColSphere s_aPedSpheres[3]; CColSphere s_aPed2Spheres[3]; CColSphere s_aPedGSpheres[4]; +#ifdef FIX_BUGS +CColSphere s_aDoorSpheres[3]; +#else CColSphere s_aDoorSpheres[4]; +#endif CColSphere s_aBumperSpheres[4]; CColSphere s_aPanelSpheres[4]; CColSphere s_aBonnetSpheres[4]; @@ -129,7 +133,11 @@ CTempColModels::Initialise(void) s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f); s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f); +#ifdef FIX_BUGS for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) { +#else + for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { +#endif s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL; s_aDoorSpheres[i].piece = 0; } -- cgit v1.2.3 From 70f625d2116ac43615647e103dc5d000e276e4c8 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 21 Oct 2020 21:39:57 +0300 Subject: Message fix --- src/text/Messages.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index 2e0323eb..e6216f5b 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -387,12 +387,11 @@ CMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 if (str[c] == '~' && str[c + 1] == '1' && str[c + 2] == '~') { #endif c += 3; - for (int j = 0; j < outLen; j++) + for (int j = 0; j < outLen; ) *(outstr++) = wNumStr[j++]; i++; switch (i) { - case 0: sprintf(numStr, "%d", n1); break; case 1: sprintf(numStr, "%d", n2); break; case 2: sprintf(numStr, "%d", n3); break; case 3: sprintf(numStr, "%d", n4); break; -- cgit v1.2.3 From 94f0ecfa21ed4d260552b2717bff481f539422cb Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 22 Oct 2020 12:35:38 +0300 Subject: Police Radio fixes --- src/audio/AudioManager.h | 2 +- src/audio/DMAudio.cpp | 2 +- src/audio/PoliceRadio.cpp | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index a1aa96f5..46c099c4 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -432,7 +432,7 @@ public: void ReleaseDigitalHandle() const; void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, float intensity2); - void ReportCrime(int32 crime, const CVector *pos); + void ReportCrime(eCrimeType crime, const CVector &pos); void ResetAudioLogicTimers(uint32 timer); void ResetPoliceRadio(); void ResetTimers(uint32 time); diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 17963cc9..74968e0d 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -203,7 +203,7 @@ cDMAudio::IsAudioInitialised(void) void cDMAudio::ReportCrime(eCrimeType crime, const CVector &pos) { - AudioManager.ReportCrime(crime, &pos); + AudioManager.ReportCrime(crime, pos); } int32 diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp index 4d0f8909..673a3fcd 100644 --- a/src/audio/PoliceRadio.cpp +++ b/src/audio/PoliceRadio.cpp @@ -91,7 +91,7 @@ cAudioManager::InitialisePoliceRadio() m_sPoliceRadioQueue.policeChannelTimerSeconds = 0; m_sPoliceRadioQueue.policeChannelCounterSeconds = 0; for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) - m_sPoliceRadioQueue.crimes[i].type = 0; + m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE; SampleManager.SetChannelReverbFlag(policeChannel, 0); gSpecialSuspectLastSeenReport = false; @@ -154,7 +154,7 @@ cAudioManager::ServicePoliceRadio() if(!m_bIsInitialised) return; - if(!m_nUserPause) { + if(m_nUserPause == 0) { bool crimeReport = SetupCrimeReport(); #ifdef FIX_BUGS // Crash at 0x5fe6ef if(CReplay::IsPlayingBack() || !FindPlayerPed() || !FindPlayerPed()->m_pWanted) @@ -162,8 +162,8 @@ cAudioManager::ServicePoliceRadio() #endif wantedLevel = FindPlayerPed()->m_pWanted->m_nWantedLevel; if(!crimeReport) { - if(wantedLevel) { - if(nLastSeen) { + if(wantedLevel != 0) { + if(nLastSeen != 0) { --nLastSeen; } else { nLastSeen = m_anRandomTable[1] % 1000 + 2000; @@ -189,7 +189,7 @@ cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel) if (!m_bIsInitialised) return; - if (m_nUserPause) { + if (m_nUserPause != 0) { if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel); if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && bMissionAudioPhysicalPlayingStatus == 1 && SampleManager.IsStreamPlaying(1)) { @@ -241,7 +241,7 @@ cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel) } else { sample = TOTAL_AUDIO_SAMPLES; } - if (!wantedLevel) { + if (wantedLevel == 0) { if (gSpecialSuspectLastSeenReport) { gSpecialSuspectLastSeenReport = 0; } else if (((sample >= SFX_POLICE_RADIO_MESSAGE_NOISE_1) && (sample <= SFX_POLICE_RADIO_MESSAGE_NOISE_3)) || sample == TOTAL_AUDIO_SAMPLES) { @@ -675,7 +675,7 @@ cAudioManager::SetupSuspectLastSeenReport() void -cAudioManager::ReportCrime(int32 type, const CVector *pos) +cAudioManager::ReportCrime(eCrimeType type, const CVector &pos) { int32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes); if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && @@ -683,7 +683,7 @@ cAudioManager::ReportCrime(int32 type, const CVector *pos) for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) { if (m_sPoliceRadioQueue.crimes[i].type) { if (m_sPoliceRadioQueue.crimes[i].type == type) { - m_sPoliceRadioQueue.crimes[i].position = *pos; + m_sPoliceRadioQueue.crimes[i].position = pos; m_sPoliceRadioQueue.crimes[i].timer = 0; return; } @@ -694,7 +694,7 @@ cAudioManager::ReportCrime(int32 type, const CVector *pos) if (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) { m_sPoliceRadioQueue.crimes[lastCrime].type = type; - m_sPoliceRadioQueue.crimes[lastCrime].position = *pos; + m_sPoliceRadioQueue.crimes[lastCrime].position = pos; m_sPoliceRadioQueue.crimes[lastCrime].timer = 0; gMinTimeToNextReport[type] = m_FrameCounter + 500; } -- cgit v1.2.3 From 86a7d4415bfa1467d11f2d9ad62d846366a9bc39 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 22 Oct 2020 22:03:27 +0300 Subject: Fix argument type --- src/audio/AudioManager.h | 2 +- src/audio/PoliceRadio.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 46c099c4..40a2d056 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -440,7 +440,7 @@ public: void Service(); void ServiceCollisions(); void ServicePoliceRadio(); - void ServicePoliceRadioChannel(int32 wantedLevel); + void ServicePoliceRadioChannel(uint8 wantedLevel); void ServiceSoundEffects(); int8 SetCurrent3DProvider(uint8 which); void SetDynamicAcousticModelingStatus(uint8 status); diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp index 673a3fcd..665494a3 100644 --- a/src/audio/PoliceRadio.cpp +++ b/src/audio/PoliceRadio.cpp @@ -176,7 +176,7 @@ cAudioManager::ServicePoliceRadio() } void -cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel) +cAudioManager::ServicePoliceRadioChannel(uint8 wantedLevel) { bool processed = false; uint32 sample; -- cgit v1.2.3 From bedc066cfd888226100c431886ef3c923a9a9950 Mon Sep 17 00:00:00 2001 From: erorcun Date: Fri, 23 Oct 2020 01:56:32 +0300 Subject: mr.casepath --- src/skel/crossplatform.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 626403f8..65cfde45 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -27,23 +27,24 @@ void GetLocalTime_CP(SYSTEMTIME *out) { #ifndef _WIN32 HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) { char pathCopy[32]; + char constructedPath[32]; strncpy(pathCopy, pathname, 32); char* folder = strtok(pathCopy, "*"); - + // Case-sensitivity and backslashes... char *realFolder = casepath(folder); char *extension = nil; if (realFolder) { - realFolder[strlen(realFolder)] = '*'; + sprintf(constructedPath, "%s*", realFolder); extension = strtok(NULL, "*"); if (extension) { - strcat(realFolder, extension); + strcat(constructedPath, extension); } - - strncpy(pathCopy, realFolder, 32); + free(realFolder); - folder = strtok(pathCopy, "*"); + folder = strtok(constructedPath, "*"); + extension = strtok(NULL, "*"); } else { // Wildcard (*) if (strlen(folder) + 1 != strlen(pathname)) -- cgit v1.2.3 From 067200dd7eae890d6b0bfa98fc90fa80ca494a74 Mon Sep 17 00:00:00 2001 From: erorcun Date: Fri, 23 Oct 2020 04:37:01 +0300 Subject: mr.casepath 2 --- src/skel/crossplatform.cpp | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 65cfde45..f2f9d5ee 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -26,31 +26,23 @@ void GetLocalTime_CP(SYSTEMTIME *out) { // Compatible with Linux/POSIX and MinGW on Windows #ifndef _WIN32 HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) { - char pathCopy[32]; - char constructedPath[32]; - - strncpy(pathCopy, pathname, 32); - char* folder = strtok(pathCopy, "*"); + char pathCopy[MAX_PATH]; + strcpy(pathCopy, pathname); + + char *folder = strtok(pathCopy, "*"); + char *extension = strtok(NULL, "*"); + // because strtok doesn't return NULL for last delimiter + if (extension - folder == strlen(pathname)) + extension = nil; + // Case-sensitivity and backslashes... + // Will be freed at the bottom char *realFolder = casepath(folder); - char *extension = nil; if (realFolder) { - sprintf(constructedPath, "%s*", realFolder); - extension = strtok(NULL, "*"); - if (extension) { - strcat(constructedPath, extension); - } - - free(realFolder); - folder = strtok(constructedPath, "*"); - extension = strtok(NULL, "*"); - } else { - // Wildcard (*) - if (strlen(folder) + 1 != strlen(pathname)) - extension = strtok(NULL, "*"); + folder = realFolder; } - + strncpy(firstfile->folder, folder, sizeof(firstfile->folder)); if (extension) @@ -58,8 +50,11 @@ HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) { else firstfile->extension[0] = '\0'; + if (realFolder) + free(realFolder); + HANDLE d; - if ((d = (HANDLE)opendir(folder)) == NULL || !FindNextFile(d, firstfile)) + if ((d = (HANDLE)opendir(firstfile->folder)) == NULL || !FindNextFile(d, firstfile)) return NULL; return d; -- cgit v1.2.3 From f8a7f47fdeb4c99b745567dbe1d1cc37c4dd6bda Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 23 Oct 2020 13:06:40 +0300 Subject: Small CPedModelInfo fixes --- src/modelinfo/PedModelInfo.cpp | 46 +++++++++++++----------------------------- 1 file changed, 14 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index 117fd378..b77cccda 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -218,7 +218,6 @@ CPedModelInfo::CreateHitColModel(void) { RwObjectNameAssociation nameAssoc; RwObjectIdAssociation idAssoc; - CVector center; RwFrame *nodeFrame; CColModel *colmodel = new CColModel; CColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere)); @@ -251,23 +250,17 @@ CPedModelInfo::CreateHitColModel(void) if(RwFrameGetParent(nodeFrame) == root) break; } - center.x = mat->pos.x + m_pColNodeInfos[i].x; - center.y = mat->pos.y + 0.0f; - center.z = mat->pos.z + m_pColNodeInfos[i].z; - spheres[i].Set(radius, center, SURFACE_PED, m_pColNodeInfos[i].pieceType); + spheres[i].center = mat->pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z); + spheres[i].radius = radius; + spheres[i].surface = SURFACE_PED; + spheres[i].piece = m_pColNodeInfos[i].pieceType; } } RwMatrixDestroy(mat); colmodel->spheres = spheres; colmodel->numSpheres = NUMPEDINFONODES; - center.x = center.y = center.z = 0.0f; - colmodel->boundingSphere.Set(2.0f, center, 0, 0); - CVector min, max; - min.x = min.y = -0.5f; - min.z = -1.2f; - max.x = max.y = 0.5f; - max.z = 1.2f; - colmodel->boundingBox.Set(min, max, 0, 0); + colmodel->boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); + colmodel->boundingBox.Set(CVector(-0.5f, -0.5f, -1.2f), CVector(0.5f, 0.5f, 1.2f), SURFACE_DEFAULT, 0); colmodel->level = LEVEL_GENERIC; m_hitColModel = colmodel; } @@ -303,9 +296,7 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame) break; } - spheres[i].center.x = mat->pos.x + m_pColNodeInfos[i].x; - spheres[i].center.y = mat->pos.y + 0.0f; - spheres[i].center.z = mat->pos.z + m_pColNodeInfos[i].z; + spheres[i].center = mat->pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z); } } @@ -316,7 +307,6 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame) void CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) { - CVector center; RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump); CColModel *colmodel = new CColModel; CColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere)); @@ -335,23 +325,17 @@ CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) RwV3d pos = { 0.0f, 0.0f, 0.0f }; RwV3dTransformPoints(&pos, &pos, 1, mat); - center.x = pos.x + m_pColNodeInfos[i].x; - center.y = pos.y + 0.0f; - center.z = pos.z + m_pColNodeInfos[i].z; - spheres[i].Set(m_pColNodeInfos[i].radius, center, SURFACE_PED, m_pColNodeInfos[i].pieceType); + spheres[i].center = pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z); + spheres[i].radius = m_pColNodeInfos[i].radius; + spheres[i].surface = SURFACE_PED; + spheres[i].piece = m_pColNodeInfos[i].pieceType; } RwMatrixDestroy(invmat); RwMatrixDestroy(mat); colmodel->spheres = spheres; colmodel->numSpheres = NUMPEDINFONODES; - center.x = center.y = center.z = 0.0f; - colmodel->boundingSphere.Set(2.0f, center, 0, 0); - CVector min, max; - min.x = min.y = -0.5f; - min.z = -1.2f; - max.x = max.y = 0.5f; - max.z = 1.2f; - colmodel->boundingBox.Set(min, max, 0, 0); + colmodel->boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); + colmodel->boundingBox.Set(CVector(-0.5f, -0.5f, -1.2f), CVector(0.5f, 0.5f, 1.2f), SURFACE_DEFAULT, 0); colmodel->level = LEVEL_GENERIC; m_hitColModel = colmodel; } @@ -379,9 +363,7 @@ CPedModelInfo::AnimatePedColModelSkinned(RpClump *clump) RwV3d pos = { 0.0f, 0.0f, 0.0f }; RwV3dTransformPoints(&pos, &pos, 1, mat); - spheres[i].center.x = pos.x + m_pColNodeInfos[i].x; - spheres[i].center.y = pos.y + 0.0f; - spheres[i].center.z = pos.z + m_pColNodeInfos[i].z; + spheres[i].center = pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z); } RwMatrixDestroy(invmat); RwMatrixDestroy(mat); -- cgit v1.2.3 From 9f692ea3abd325495c084d1d3a5618987b7be401 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 23 Oct 2020 13:23:05 +0300 Subject: Missed nil --- src/text/Messages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index e6216f5b..c446a770 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -802,7 +802,7 @@ CMessages::ClearThisBigPrint(wchar *str) } BIGMessages[style].m_Stack[i].m_pText = nil; } else { - BIGMessages[style].m_Stack[0].m_pText = 0; + BIGMessages[style].m_Stack[0].m_pText = nil; i = 0; while (i < 3) { if (BIGMessages[style].m_Stack[i + 1].m_pText == nil) -- cgit v1.2.3 From d7b9884f9d4f6e516c9b72360414fede04884e95 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 23 Oct 2020 16:18:46 +0300 Subject: Use audio enum --- src/control/Script.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 50e89ecc..6bde6b87 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8333,11 +8333,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) } case COMMAND_INDUSTRIAL_PASSED: CStats::IndustrialPassed = true; - DMAudio.PlayRadioAnnouncement(13); //TODO: enum? + DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_COMMERCIAL_OPEN); return 0; case COMMAND_COMMERCIAL_PASSED: CStats::CommercialPassed = true; - DMAudio.PlayRadioAnnouncement(14); //TODO: enum? + DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_SUBURBAN_OPEN); return 0; case COMMAND_SUBURBAN_PASSED: CStats::SuburbanPassed = true; -- cgit v1.2.3 From a492f8ba0d7bf4a740ed91ccd7820a3afd9a111b Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 24 Oct 2020 16:37:14 +0300 Subject: Fix playback of vanilla opus --- src/audio/oal/stream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 3af50ea8..3adb702a 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -195,7 +195,7 @@ public: if (m_FileH) { m_nChannels = op_head(m_FileH, 0)->channel_count; - m_nRate = op_head(m_FileH, 0)->input_sample_rate; + m_nRate = 48000; const OpusTags *tags = op_tags(m_FileH, 0); for (int i = 0; i < tags->comments; i++) { if (strncmp(tags->user_comments[i], "SAMPLERATE", sizeof("SAMPLERATE")-1) == 0) -- cgit v1.2.3 From a32c390a954287e5918e5ea6297f6df7b75c1752 Mon Sep 17 00:00:00 2001 From: Adrian Graber Date: Sat, 24 Oct 2020 16:12:10 +0200 Subject: Join CdStream threads to wait for them to exit --- src/core/CdStreamPosix.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index fdc63a05..5c8d1b16 100644 --- a/src/core/CdStreamPosix.cpp +++ b/src/core/CdStreamPosix.cpp @@ -216,10 +216,12 @@ CdStreamShutdown(void) #ifndef ONE_THREAD_PER_CHANNEL gCdStreamThreadStatus = 2; sem_post(gCdStreamSema); + pthread_join(_gCdStreamThread, nil); #else for ( int32 i = 0; i < gNumChannels; i++ ) { gpReadInfo[i].nThreadStatus = 2; sem_post(gpReadInfo[i].pStartSemaphore); + pthread_join(gpReadInfo[i].pChannelThread, nil); } #endif } -- cgit v1.2.3 From 92ae468e008438d4563c0ee005bba1977099abd6 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sat, 24 Oct 2020 21:56:04 +0300 Subject: Messages and CameraSize fix --- src/rw/RwHelper.cpp | 6 ++++-- src/text/Messages.cpp | 33 +++++++++------------------------ 2 files changed, 13 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index fca5b4a4..1c6c434c 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -437,7 +437,7 @@ CameraSize(RwCamera * camera, RwRect * rect, RwRaster *zRaster; // BUG: game just changes camera raster's sizes, but this is a hack -#ifdef FIX_BUGS +#if 0//def FIX_BUGS /* * Destroy rasters... */ @@ -446,12 +446,14 @@ CameraSize(RwCamera * camera, RwRect * rect, if( raster ) { RwRasterDestroy(raster); + camera->frameBuffer = nil; } zRaster = RwCameraGetZRaster(camera); if( zRaster ) { RwRasterDestroy(zRaster); + camera->zBuffer = nil; } /* @@ -657,4 +659,4 @@ RestoreAlphaTest() RwD3D8SetRenderState(D3DRS_ALPHAREF, saved_alpharef); #endif } -#endif \ No newline at end of file +#endif diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index c446a770..b68f918d 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -69,7 +69,7 @@ CMessages::WideStringCompare(wchar *str1, wchar *str2, uint16 size) if (len1 != len2 && (len1 < size || len2 < size)) return false; - for (int32 i = 0; FixupChar(str1[i]) != '\0' && i < size; i++) { + for (int32 i = 0; i < size && FixupChar(str1[i]) != '\0'; i++) { if (FixupChar(str1[i]) != FixupChar(str2[i])) return false; } @@ -97,13 +97,9 @@ CMessages::Process() if (BriefMessages[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BriefMessages[0].m_nTime + BriefMessages[0].m_nStartTime) { BriefMessages[0].m_pText = nil; - int32 i = 0; - while (i < NUMBRIEFMESSAGES-1) { - if (BriefMessages[i + 1].m_pText == nil) - break; - + int32 i; + for (i = 0; i < NUMBRIEFMESSAGES-1 && BriefMessages[i + 1].m_pText != nil; i++) { BriefMessages[i] = BriefMessages[i + 1]; - i++; } CMessages::BriefMessages[i].m_pText = nil; CMessages::BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds(); @@ -325,7 +321,7 @@ void CMessages::AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string) { int32 i = 0; - for (i = 0; PreviousBriefs[i].m_pText && i < NUMPREVIOUSBRIEFS; i++) { + for (i = 0; i < NUMPREVIOUSBRIEFS && PreviousBriefs[i].m_pText != nil; i++) { if (PreviousBriefs[i].m_nNumber[0] == n1 && PreviousBriefs[i].m_nNumber[1] == n2 && PreviousBriefs[i].m_nNumber[2] == n3 @@ -503,7 +499,7 @@ CMessages::AddMessageWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, GetWideStringLength(outstr); uint16 i = 0; - while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText) + while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil) i++; if (i >= NUMBRIEFMESSAGES) return; @@ -720,35 +716,24 @@ CMessages::ClearThisPrint(wchar *str) do { equal = false; - uint16 i = 0; - while (i < NUMBRIEFMESSAGES) { - if (BriefMessages[i].m_pText == nil) - break; - + uint16 i; + for (i = 0; i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil; i++) { equal = FastWideStringComparison(str, BriefMessages[i].m_pText); if (equal) break; - i++; } if (equal) { if (i != 0) { BriefMessages[i].m_pText = nil; - while (i < NUMBRIEFMESSAGES-1) { - if (BriefMessages[i + 1].m_pText == nil) - break; - + for (; i < NUMBRIEFMESSAGES-1 && BriefMessages[i+1].m_pText != nil; i++) { BriefMessages[i] = BriefMessages[i + 1]; - i++; } BriefMessages[i].m_pText = nil; } else { BriefMessages[0].m_pText = nil; - while (i < NUMBRIEFMESSAGES-1) { - if (BriefMessages[i + 1].m_pText == nil) - break; + for (; i < NUMBRIEFMESSAGES-1 && BriefMessages[i+1].m_pText != nil; i++) { BriefMessages[i] = BriefMessages[i + 1]; - i++; } BriefMessages[i].m_pText = nil; BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds(); -- cgit v1.2.3 From d0e80e8c97e14ef73d3acaf7ac992fe71b4e0fc9 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sat, 24 Oct 2020 23:56:21 +0300 Subject: librw update --- src/rw/RwHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 1c6c434c..4b598e9b 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -437,7 +437,7 @@ CameraSize(RwCamera * camera, RwRect * rect, RwRaster *zRaster; // BUG: game just changes camera raster's sizes, but this is a hack -#if 0//def FIX_BUGS +#ifdef FIX_BUGS /* * Destroy rasters... */ -- cgit v1.2.3 From 5e5854b914d3b72855f872575adb13f7decca8b8 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sun, 25 Oct 2020 01:05:07 +0300 Subject: Fix bindings not loaded on Linux --- src/core/re3.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 069320ec..98201d5a 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -32,6 +32,8 @@ #include "MBlur.h" #include "postfx.h" #include "custompipes.h" +#include "FileMgr.h" +#include "ControllerConfig.h" #ifndef _WIN32 #include "assert.h" @@ -275,7 +277,7 @@ wchar* DetectJoystickDraw(bool* disabled, bool userHovering) { const char *joyname; if (userHovering) { for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { - if (joyname = glfwGetJoystickName(i)) { + if ((joyname = glfwGetJoystickName(i))) { const uint8* buttons = glfwGetJoystickButtons(i, &numButtons); for (int j = 0; j < numButtons; j++) { if (buttons[j]) { @@ -455,8 +457,34 @@ void LoadINISettings() char defaultStr[4]; #ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + // Written by assuming the codes below will run after _InputInitialiseJoys(). strcpy(gSelectedJoystickName, cfg.get("DetectJoystick", "JoystickName", "").c_str()); - _InputInitialiseJoys(); + + if(gSelectedJoystickName[0] != '\0') { + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { + if (glfwJoystickPresent(i) && strncmp(gSelectedJoystickName, glfwGetJoystickName(i), strlen(gSelectedJoystickName)) == 0) { + if (PSGLOBAL(joy1id) != -1) { + PSGLOBAL(joy2id) = PSGLOBAL(joy1id); + } + PSGLOBAL(joy1id) = i; + int count; + glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + + // We need to init and reload bindings, because; + // 1-joypad button number may differ with saved/prvly connected one + // 2-bindings are not init'ed if there is no joypad at the start + ControlsManager.InitDefaultControlConfigJoyPad(count); + CFileMgr::SetDirMyDocuments(); + int32 gta3set = CFileMgr::OpenFile("gta3.set", "r"); + if (gta3set) { + ControlsManager.LoadSettings(gta3set); + CFileMgr::CloseFile(gta3set); + } + CFileMgr::SetDir(""); + break; + } + } + } #endif #ifdef CUSTOM_FRONTEND_OPTIONS -- cgit v1.2.3 From aac0c3fb679401eab584cf91c07bd4353022c91c Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 25 Oct 2020 09:39:04 +0200 Subject: DMAudio fixes --- src/audio/DMAudio.cpp | 29 +---------------------------- src/audio/DMAudio.h | 4 +--- src/core/Game.cpp | 29 ++++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 74968e0d..b0d5745c 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -113,33 +113,6 @@ cDMAudio::Get3DProviderName(uint8 id) return AudioManager.Get3DProviderName(id); } -int8 cDMAudio::AutoDetect3DProviders(void) -{ - for ( int32 i = 0; i < GetNum3DProvidersAvailable(); i++ ) - { - wchar buff[64]; - -#ifdef AUDIO_OAL - if (defaultProvider >= 0 && defaultProvider < GetNum3DProvidersAvailable()) { - return i; - } -#endif - char *name = Get3DProviderName(i); - AsciiToUnicode(name, buff); - char *providername = UnicodeToAscii(buff); - strupr(providername); -#if defined(AUDIO_MSS) - if ( !strcmp(providername, "MILES FAST 2D POSITIONAL AUDIO") ) - return i; -#elif defined(AUDIO_OAL) - if ( !strcmp(providername, "OPENAL SOFT") ) - return i; -#endif - } - - return -1; -} - int8 cDMAudio::GetCurrent3DProviderIndex(void) { @@ -350,7 +323,7 @@ cDMAudio::SetRadioInCar(uint32 radio) } void -cDMAudio::SetRadioChannel(int8 radio, int32 pos) +cDMAudio::SetRadioChannel(uint8 radio, int32 pos) { MusicManager.SetRadioChannelByScript(radio, pos); } diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index bb95f303..3e6d5603 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -35,8 +35,6 @@ public: uint8 GetNum3DProvidersAvailable(void); char *Get3DProviderName(uint8 id); - int8 AutoDetect3DProviders(void); - int8 GetCurrent3DProviderIndex(void); int8 SetCurrent3DProvider(uint8 which); @@ -86,6 +84,6 @@ public: uint8 GetRadioInCar(void); void SetRadioInCar(uint32 radio); - void SetRadioChannel(int8 radio, int32 pos); + void SetRadioChannel(uint8 radio, int32 pos); }; extern cDMAudio DMAudio; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 93f0d1b0..1be62611 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -277,12 +277,31 @@ bool CGame::InitialiseOnceAfterRW(void) if ( DMAudio.GetNum3DProvidersAvailable() == 0 ) FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = -1; - if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -99 || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) - { + if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -99 || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) { CMenuManager::m_PrefsSpeakers = 0; - int8 provider = DMAudio.AutoDetect3DProviders(); - if ( provider != -1 ) - FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = provider; + int32 i; + for (i = 0; i < DMAudio.GetNum3DProvidersAvailable(); i++) { + wchar buff[64]; + +#ifdef AUDIO_OAL + extern int defaultProvider; + if (defaultProvider >= 0 && defaultProvider < DMAudio.GetNum3DProvidersAvailable()) + break; +#endif + char *name = DMAudio.Get3DProviderName(i); + AsciiToUnicode(name, buff); + char *providername = UnicodeToAscii(buff); + strupr(providername); +#if defined(AUDIO_MSS) + if (strcmp(providername, "MILES FAST 2D POSITIONAL AUDIO") == 0) + break; +#elif defined(AUDIO_OAL) + if (strcmp(providername, "OPENAL SOFT") == 0) + break; +#endif + } + + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = i; } DMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); -- cgit v1.2.3 From 6634410aee114e125a9c0564b2c7dd67619df5fc Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 25 Oct 2020 09:50:17 +0200 Subject: Fix build --- src/core/re3.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 98201d5a..d5a8099d 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -32,8 +32,11 @@ #include "MBlur.h" #include "postfx.h" #include "custompipes.h" + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS #include "FileMgr.h" #include "ControllerConfig.h" +#endif #ifndef _WIN32 #include "assert.h" -- cgit v1.2.3 From e0394e6e69f90c87e57c4d6ba3451dd085e06bcf Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 25 Oct 2020 12:38:08 +0200 Subject: Possible fix of linux build --- src/audio/DMAudio.cpp | 1 - src/core/Game.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index b0d5745c..44c22610 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -7,7 +7,6 @@ #include "sampman.h" #include "Font.h" #include "Text.h" -#include "crossplatform.h" cDMAudio DMAudio; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 1be62611..e47543b3 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -89,6 +89,7 @@ #include "frontendoption.h" #include "postfx.h" #include "custompipes.h" +#include "crossplatform.h" eLevelName CGame::currLevel; bool CGame::bDemoMode = true; -- cgit v1.2.3 From 83947e6958bf822f01e7b9de48021ab8ea776182 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 25 Oct 2020 13:07:44 +0200 Subject: Remove redundant includes --- src/audio/DMAudio.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 44c22610..1027a084 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -5,8 +5,6 @@ #include "AudioManager.h" #include "AudioScriptObject.h" #include "sampman.h" -#include "Font.h" -#include "Text.h" cDMAudio DMAudio; -- cgit v1.2.3 From e3a1041a471aaaa3d906caeb23d1d334071978b2 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 25 Oct 2020 16:17:30 +0100 Subject: clean up timebar ifdefs --- src/core/main.cpp | 51 ++++++++------------------------------------------- src/core/main.h | 2 ++ src/core/timebars.h | 9 ++++++++- 3 files changed, 18 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/core/main.cpp b/src/core/main.cpp index 5fea9c4b..b6a32b55 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1008,9 +1008,7 @@ Idle(void *arg) CTimer::Update(); -#ifdef TIMEBARS tbInit(); -#endif CSprite2d::InitPerFrame(); CFont::InitPerFrame(); @@ -1026,39 +1024,27 @@ Idle(void *arg) FrontEndMenuManager.Process(); } else { CPointLights::InitPerFrame(); -#ifdef TIMEBARS tbStartTimer(0, "CGame::Process"); -#endif CGame::Process(); -#ifdef TIMEBARS tbEndTimer("CGame::Process"); tbStartTimer(0, "DMAudio.Service"); -#endif DMAudio.Service(); -#ifdef TIMEBARS tbEndTimer("DMAudio.Service"); -#endif } if (RsGlobal.quit) return; #else CPointLights::InitPerFrame(); -#ifdef TIMEBARS + tbStartTimer(0, "CGame::Process"); -#endif CGame::Process(); -#ifdef TIMEBARS tbEndTimer("CGame::Process"); - tbStartTimer(0, "DMAudio.Service"); -#endif + tbStartTimer(0, "DMAudio.Service"); DMAudio.Service(); - -#ifdef TIMEBARS tbEndTimer("DMAudio.Service"); -#endif #endif if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){ @@ -1098,18 +1084,13 @@ Idle(void *arg) RsMouseSetPos(&pos); } #endif -#ifdef TIMEBARS tbStartTimer(0, "CnstrRenderList"); -#endif CRenderer::ConstructRenderList(); -#ifdef TIMEBARS tbEndTimer("CnstrRenderList"); + tbStartTimer(0, "PreRender"); -#endif CRenderer::PreRender(); -#ifdef TIMEBARS tbEndTimer("PreRender"); -#endif #ifdef FIX_BUGS RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); // TODO: temp? this fixes OpenGL render but there should be a better place for this @@ -1135,13 +1116,9 @@ Idle(void *arg) RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart()); #endif -#ifdef TIMEBARS tbStartTimer(0, "RenderScene"); -#endif RenderScene(); -#ifdef TIMEBARS tbEndTimer("RenderScene"); -#endif #ifdef EXTENDED_PIPELINES CustomPipes::EnvMapRender(); @@ -1150,21 +1127,16 @@ Idle(void *arg) RenderDebugShit(); RenderEffects(); -#ifdef TIMEBARS tbStartTimer(0, "RenderMotionBlur"); -#endif if((TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) && TheCamera.m_ScreenReductionPercentage > 0.0f) TheCamera.SetMotionBlurAlpha(150); TheCamera.RenderMotionBlur(); -#ifdef TIMEBARS tbEndTimer("RenderMotionBlur"); + tbStartTimer(0, "Render2dStuff"); -#endif Render2dStuff(); -#ifdef TIMEBARS tbEndTimer("Render2dStuff"); -#endif }else{ #ifdef ASPECT_RATIO_SCALE CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); @@ -1181,35 +1153,28 @@ Idle(void *arg) if (FrontEndMenuManager.m_bMenuActive) DefinedState(); #endif -#ifdef TIMEBARS tbStartTimer(0, "RenderMenus"); -#endif RenderMenus(); -#ifdef TIMEBARS tbEndTimer("RenderMenus"); - tbStartTimer(0, "DoFade"); -#endif #ifdef PS2_MENU if ( TheMemoryCard.m_bWantToLoad ) return; #endif + + tbStartTimer(0, "DoFade"); DoFade(); -#ifdef TIMEBARS tbEndTimer("DoFade"); + tbStartTimer(0, "Render2dStuff-Fade"); -#endif Render2dStuffAfterFade(); -#ifdef TIMEBARS tbEndTimer("Render2dStuff-Fade"); -#endif + CCredits::Render(); -#ifdef TIMEBARS if (gbShowTimebars) tbDisplay(); -#endif DoRWStuffEndOfFrame(); diff --git a/src/core/main.h b/src/core/main.h index 7eb080cb..13fff447 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -16,6 +16,8 @@ extern bool gbPrintShite; extern bool gbModelViewer; #ifdef TIMEBARS extern bool gbShowTimebars; +#else +#define gbShowTimebars false #endif class CSprite2d; diff --git a/src/core/timebars.h b/src/core/timebars.h index 3871b61c..c4939802 100644 --- a/src/core/timebars.h +++ b/src/core/timebars.h @@ -1,6 +1,13 @@ #pragma once +#ifdef TIMEBARS void tbInit(); void tbStartTimer(int32, Const char*); void tbEndTimer(Const char*); -void tbDisplay(); \ No newline at end of file +void tbDisplay(); +#else +#define tbInit() +#define tbStartTimer(a, b) +#define tbEndTimer(a) +#define tbDisplay() +#endif -- cgit v1.2.3 From 6729de49b16da9a1be3c95b146ba053bf214c91c Mon Sep 17 00:00:00 2001 From: erorcun Date: Sun, 25 Oct 2020 20:51:27 +0300 Subject: Font: Fix text dimensions --- src/audio/MusicManager.cpp | 2 +- src/control/Darkel.cpp | 4 ++-- src/control/Garages.cpp | 2 +- src/core/Frontend.cpp | 10 +++++----- src/core/Game.cpp | 8 ++++---- src/core/Pad.cpp | 4 ++-- src/core/main.cpp | 2 +- src/render/Credits.cpp | 4 ++-- src/render/Hud.cpp | 24 ++++++++++++------------ src/render/SpecialFX.cpp | 2 +- 10 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index 5519d899..10862cdc 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -161,7 +161,7 @@ cMusicManager::DisplayRadioStationName() CFont::SetPropOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation); diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index 793bec36..afdfcb82 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -72,7 +72,7 @@ CDarkel::DrawMessages() { CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(30.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(610.0f)); CFont::SetCentreOn(); CFont::SetPropOn(); uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; @@ -132,7 +132,7 @@ CDarkel::DrawMessages() uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; if (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart < 5000) { CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); CFont::SetCentreOn(); CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); CFont::SetJustifyOff(); diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 61c1a850..5a04285f 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1400,7 +1400,7 @@ void CGarages::PrintMessages() CFont::SetPropOn(); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(590.0f)); CFont::SetCentreOn(); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index db3774a7..89b5ba3d 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -787,7 +787,7 @@ CMenuManager::Draw() CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); - CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); CFont::SetRightJustifyWrap(0.0f); strcpy(gString, "V1.1"); AsciiToUnicode(gString, gUString); @@ -873,7 +873,7 @@ CMenuManager::Draw() #endif } - CFont::SetCentreSize(SCREEN_WIDTH); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); #ifdef PS2_LIKE_MENU bool itemsAreSelectable = !bottomBarActive; @@ -3575,11 +3575,11 @@ CMenuManager::MessageScreen(const char *text) CFont::SetPropOn(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); - CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); + CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // not used + CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // not used CSprite2d::DrawRect(CRect(StretchX(120.0f), StretchY(150.0f), SCREEN_WIDTH - StretchX(120.0f), SCREEN_HEIGHT - StretchY(220.0f)), CRGBA(50, 50, 50, 210)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetCentreSize(SCREEN_STRETCH_X(380.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(380.0f)); CFont::SetCentreOn(); CFont::SetColor(CRGBA(255, 217, 106, 255)); CFont::SetScale(SCREEN_SCALE_X(SMALLTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLTEXT_Y_SCALE)); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index e47543b3..ef4800c5 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -129,10 +129,10 @@ void MessageScreen(char *msg) CFont::SetFontStyle(FONT_BANK); CFont::SetBackgroundOff(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f // unused CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f + CFont::SetCentreSize(SCREEN_SCALE_X(450.0f)); // 450.0f CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetDropColor(CRGBA(32, 32, 32, 255)); @@ -745,10 +745,10 @@ void CGame::InitialiseWhenRestarting(void) //CFont::SetFontStyle(?); CFont::SetBackgroundOff(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f // unused CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f + CFont::SetCentreSize(SCREEN_SCALE_X(480.0f)); // 480.0f CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetBackGroundOnlyTextOff(); diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index e2f90a7c..0e2f06a6 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -2593,7 +2593,7 @@ void CPad::PrintErrorMessage(void) CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_WIDTH - 20); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); @@ -2610,7 +2610,7 @@ void CPad::PrintErrorMessage(void) CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_WIDTH - 20); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); diff --git a/src/core/main.cpp b/src/core/main.cpp index b6a32b55..18ee2dc5 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -841,7 +841,7 @@ DisplayGameDebugText() CFont::SetRightJustifyOff(); CFont::SetJustifyOff(); CFont::SetBackGroundOnlyTextOff(); - CFont::SetWrapx(640.0f); + CFont::SetWrapx(SCREEN_WIDTH); CFont::SetFontStyle(FONT_HEADING); CFont::SetColor(CRGBA(0, 0, 0, 255)); diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index 6b28ff04..2c8a9952 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -62,7 +62,7 @@ CCredits::Render(void) scrolloffset = (CTimer::GetTimeInMilliseconds() - CreditsStartTime) / 24.0f; CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - 20)); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(220, 220, 220, 220)); @@ -496,4 +496,4 @@ CCredits::Render(void) bool CCredits::AreCreditsDone(void) { return !bCreditsGoing; -} \ No newline at end of file +} diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index a6e6bccf..83c493bb 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -336,7 +336,7 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f)); CFont::SetJustifyOff(); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_WIDTH); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); CFont::SetPropOn(); CFont::SetFontStyle(FONT_BANK); @@ -740,7 +740,7 @@ void CHud::Draw() CFont::SetRightJustifyWrap(0.0f); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetColor(CRGBA(244, 20, 20, 255)); - CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); CFont::SetPropOff(); CFont::SetBackGroundOnlyTextOn(); @@ -869,8 +869,8 @@ void CHud::Draw() else CFont::SetCentreOff(); - CFont::SetWrapx(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fWrapX)); - CFont::SetCentreSize(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fCenterSize)); + CFont::SetWrapx(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fWrapX)); + CFont::SetCentreSize(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fCenterSize)); if (CTheScripts::IntroTextLines[i].m_bBackground) CFont::SetBackgroundOn(); @@ -957,12 +957,12 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f)); CFont::SetPropOn(); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(25.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(590.0f)); CFont::SetFontStyle(FONT_HEADING); // Appearently sliding text in here was abandoned very early, since this text is centered now. - if (BigMessageX[0] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { + if (BigMessageX[0] >= SCALE_AND_CENTER_X(620.0f)) { BigMessageInUse[0] += CTimer::GetTimeStep(); if (BigMessageInUse[0] >= 120.0f) { @@ -997,7 +997,7 @@ void CHud::Draw() } else { BigMessageAlpha[0] = 0.0f; - BigMessageX[0] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f); + BigMessageX[0] = SCALE_AND_CENTER_X(-60.0f); BigMessageInUse[0] = 1.0f; } } @@ -1166,8 +1166,8 @@ void CHud::DrawAfterFade() else CFont::SetCentreOff(); - CFont::SetWrapx(SCALE_AND_CENTER_X(line.m_fWrapX)); - CFont::SetCentreSize(SCALE_AND_CENTER_X(line.m_fCenterSize)); + CFont::SetWrapx(SCREEN_SCALE_X(line.m_fWrapX)); + CFont::SetCentreSize(SCREEN_SCALE_X(line.m_fCenterSize)); if (line.m_bBackground) CFont::SetBackgroundOn(); else @@ -1213,7 +1213,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(40.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(600.0f)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); @@ -1229,7 +1229,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); @@ -1286,7 +1286,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.2f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 34423d83..89043752 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -1058,7 +1058,7 @@ CMoneyMessage::Render() CFont::SetScale(fScaleX, fScaleY); // maybe use SCREEN_SCALE_X and SCREEN_SCALE_Y here? CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_WIDTH); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); CFont::SetJustifyOff(); CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity)); CFont::SetBackGroundOnlyTextOff(); -- cgit v1.2.3 From 19cc6fafe04b3a0b80c76f857eb68f2390525ea0 Mon Sep 17 00:00:00 2001 From: erorcun Date: Mon, 26 Oct 2020 12:35:24 +0300 Subject: (TEST) Try to fix OAL audio problems --- src/audio/oal/stream.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 3adb702a..6c6abf1a 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -67,13 +67,13 @@ public: void Seek(uint32 milliseconds) { if ( !IsOpened() ) return; - sf_seek(m_pfSound, ms2samples(milliseconds), SF_SEEK_SET); + sf_seek(m_pfSound, ms2samples(milliseconds) * (float)GetChannels(), SF_SEEK_SET); } uint32 Tell() { if ( !IsOpened() ) return 0; - return samples2ms(sf_seek(m_pfSound, 0, SF_SEEK_CUR)); + return samples2ms(sf_seek(m_pfSound, 0, SF_SEEK_CUR)) / (float)GetChannels(); } uint32 Decode(void *buffer) -- cgit v1.2.3 From d94b36c20261851105e0745134b1fb7f2b6558aa Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 26 Oct 2020 20:13:50 +0200 Subject: Fixes to OpenAL --- src/audio/sampman_oal.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index 720849f8..ad6961b0 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -109,9 +109,9 @@ ALuint ALStreamBuffers[MAX_STREAMS][NUM_STREAMBUFFERS]; struct { ALuint buffer; - ALuint timer; + ALint timer; - bool IsEmpty() { return timer == 0; } + bool IsEmpty() { return buffer == 0; } void Set(ALuint buf) { buffer = buf; } void Wait() { timer = 10000; } void Init() @@ -121,19 +121,32 @@ struct } void Term() { - if ( buffer != 0 && alIsBuffer(buffer) ) + if (buffer != 0 && alIsBuffer(buffer)) { alDeleteBuffers(1, &buffer); + assert(alGetError() == AL_NO_ERROR); + } timer = 0; + buffer = 0; } void Update() { if ( !(timer > 0) ) return; - timer -= ALuint(CTimer::GetTimeStepInMilliseconds()); + timer -= ALint(CTimer::GetTimeStepInMilliseconds()); if ( timer > 0 ) return; - if ( buffer != 0 && alIsBuffer(buffer) ) + timer = 0; + if ( buffer != 0 ) { + if (!alIsBuffer(buffer)) + { + buffer = 0; + return; + } alDeleteBuffers(1, &buffer); - timer = ( alGetError() == AL_NO_ERROR ) ? 0 : 10000; + ALenum error = alGetError(); + if (error != AL_NO_ERROR) + timer = 10000; + else + buffer = 0; } } }ALBuffers[SAMPLEBANK_MAX]; -- cgit v1.2.3 From ba0c96c39ca0711a574b19d437548fcf6303e785 Mon Sep 17 00:00:00 2001 From: erorcun Date: Tue, 27 Oct 2020 00:40:12 +0300 Subject: Revert "(TEST) Try to fix OAL audio problems" This reverts commit 19cc6fafe04b3a0b80c76f857eb68f2390525ea0. --- src/audio/oal/stream.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 6c6abf1a..3adb702a 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -67,13 +67,13 @@ public: void Seek(uint32 milliseconds) { if ( !IsOpened() ) return; - sf_seek(m_pfSound, ms2samples(milliseconds) * (float)GetChannels(), SF_SEEK_SET); + sf_seek(m_pfSound, ms2samples(milliseconds), SF_SEEK_SET); } uint32 Tell() { if ( !IsOpened() ) return 0; - return samples2ms(sf_seek(m_pfSound, 0, SF_SEEK_CUR)) / (float)GetChannels(); + return samples2ms(sf_seek(m_pfSound, 0, SF_SEEK_CUR)); } uint32 Decode(void *buffer) -- cgit v1.2.3 From 4cfb3b0984c1de2820691b4b5f1c63cd19c498fb Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 27 Oct 2020 09:35:09 +0200 Subject: OpenAL channels now use their own sound buffers --- src/audio/oal/channel.cpp | 134 +++++++++++++++++++++++++--------------------- src/audio/oal/channel.h | 18 +++---- src/audio/sampman.h | 6 +-- src/audio/sampman_oal.cpp | 117 +++++----------------------------------- 4 files changed, 96 insertions(+), 179 deletions(-) (limited to 'src') diff --git a/src/audio/oal/channel.cpp b/src/audio/oal/channel.cpp index 731e3581..673a4aed 100644 --- a/src/audio/oal/channel.cpp +++ b/src/audio/oal/channel.cpp @@ -10,17 +10,49 @@ extern bool IsFXSupported(); +ALuint alSources[MAXCHANNELS+MAX2DCHANNELS]; +ALuint alFilters[MAXCHANNELS+MAX2DCHANNELS]; +ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS]; +bool bChannelsCreated = false; + +void +CChannel::InitChannels() +{ + alGenSources(MAXCHANNELS+MAX2DCHANNELS, alSources); + alGenBuffers(MAXCHANNELS+MAX2DCHANNELS, alBuffers); + if (IsFXSupported()) + alGenFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters); + bChannelsCreated = true; +} + +void +CChannel::DestroyChannels() +{ + if (bChannelsCreated) + { + alDeleteSources(MAXCHANNELS + MAX2DCHANNELS, alSources); + memset(alSources, 0, sizeof(alSources)); + alDeleteBuffers(MAXCHANNELS + MAX2DCHANNELS, alBuffers); + memset(alBuffers, 0, sizeof(alBuffers)); + if (IsFXSupported()) + { + alDeleteFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters); + memset(alFilters, 0, sizeof(alFilters)); + } + bChannelsCreated = false; + } +} + + CChannel::CChannel() { - alSource = AL_NONE; - alFilter = AL_FILTER_NULL; + Data = nil; + DataSize = 0; SetDefault(); } void CChannel::SetDefault() { - alBuffer = AL_NONE; - Pitch = 1.0f; Gain = 1.0f; Mix = 0.0f; @@ -39,25 +71,19 @@ void CChannel::Reset() SetDefault(); } -void CChannel::Init(bool Is2D) +void CChannel::Init(uint32 _id, bool Is2D) { - ASSERT(!HasSource()); - alGenSources(1, &alSource); + id = _id; if ( HasSource() ) { - alSourcei(alSource, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcei(alSources[id], AL_SOURCE_RELATIVE, AL_TRUE); if ( IsFXSupported() ) - alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); + alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); if ( Is2D ) { - alSource3f(alSource, AL_POSITION, 0.0f, 0.0f, 0.0f); - alSourcef (alSource, AL_GAIN, 1.0f); - } - else - { - if ( IsFXSupported() ) - alGenFilters(1,&alFilter); + alSource3f(alSources[id], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSourcef(alSources[id], AL_GAIN, 1.0f); } } } @@ -69,39 +95,34 @@ void CChannel::Term() { if ( IsFXSupported() ) { - alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); - - if(alFilter != AL_FILTER_NULL) - alDeleteFilters(1,&alFilter); + alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); } - - alDeleteSources(1, &alSource); } - alSource = AL_NONE; - alFilter = AL_FILTER_NULL; } void CChannel::Start() { if ( !HasSource() ) return; - + if ( !Data ) return; + + alBufferData(alBuffers[id], AL_FORMAT_MONO16, Data, DataSize, Frequency); if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 ) - alBufferiv(alBuffer, AL_LOOP_POINTS_SOFT, LoopPoints); - alSourcei (alSource, AL_BUFFER, alBuffer); - alSourcePlay(alSource); + alBufferiv(alBuffers[id], AL_LOOP_POINTS_SOFT, LoopPoints); + alSourcei(alSources[id], AL_BUFFER, alBuffers[id]); + alSourcePlay(alSources[id]); } void CChannel::Stop() { if ( HasSource() ) - alSourceStop(alSource); + alSourceStop(alSources[id]); Reset(); } bool CChannel::HasSource() { - return alSource != AL_NONE; + return alSources[id] != AL_NONE; } bool CChannel::IsUsed() @@ -109,7 +130,7 @@ bool CChannel::IsUsed() if ( HasSource() ) { ALint sourceState; - alGetSourcei(alSource, AL_SOURCE_STATE, &sourceState); + alGetSourcei(alSources[id], AL_SOURCE_STATE, &sourceState); return sourceState == AL_PLAYING; } return false; @@ -118,27 +139,24 @@ bool CChannel::IsUsed() void CChannel::SetPitch(float pitch) { if ( !HasSource() ) return; - alSourcef(alSource, AL_PITCH, pitch); + alSourcef(alSources[id], AL_PITCH, pitch); } void CChannel::SetGain(float gain) { if ( !HasSource() ) return; - alSourcef(alSource, AL_GAIN, gain); + alSourcef(alSources[id], AL_GAIN, gain); } void CChannel::SetVolume(int32 vol) { SetGain(ALfloat(vol) / MAX_VOLUME); } - -void CChannel::SetSampleID(uint32 nSfx) -{ - Sample = nSfx; -} - -void CChannel::SetFreq(int32 freq) + +void CChannel::SetSampleData(void *_data, size_t _DataSize, int32 freq) { + Data = _data; + DataSize = _DataSize; Frequency = freq; } @@ -150,7 +168,7 @@ void CChannel::SetCurrentFreq(uint32 freq) void CChannel::SetLoopCount(int32 loopCount) // fake. TODO: { if ( !HasSource() ) return; - alSourcei(alSource, AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE); + alSourcei(alSources[id], AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE); } void CChannel::SetLoopPoints(ALint start, ALint end) @@ -162,53 +180,49 @@ void CChannel::SetLoopPoints(ALint start, ALint end) void CChannel::SetPosition(float x, float y, float z) { if ( !HasSource() ) return; - alSource3f(alSource, AL_POSITION, x, y, z); + alSource3f(alSources[id], AL_POSITION, x, y, z); } void CChannel::SetDistances(float max, float min) { if ( !HasSource() ) return; - alSourcef (alSource, AL_MAX_DISTANCE, max); - alSourcef (alSource, AL_REFERENCE_DISTANCE, min); - alSourcef (alSource, AL_MAX_GAIN, 1.0f); - alSourcef (alSource, AL_ROLLOFF_FACTOR, 1.0f); + alSourcef (alSources[id], AL_MAX_DISTANCE, max); + alSourcef (alSources[id], AL_REFERENCE_DISTANCE, min); + alSourcef (alSources[id], AL_MAX_GAIN, 1.0f); + alSourcef (alSources[id], AL_ROLLOFF_FACTOR, 1.0f); } -void CChannel::SetPan(uint32 pan) +void CChannel::SetPan(int32 pan) { SetPosition((pan-63)/64.0f, 0.0f, Sqrt(1.0f-SQR((pan-63)/64.0f))); } -void CChannel::SetBuffer(ALuint buffer) -{ - alBuffer = buffer; -} - void CChannel::ClearBuffer() { if ( !HasSource() ) return; - SetBuffer(AL_NONE); - alSourcei(alSource, AL_BUFFER, AL_NONE); + alSourcei(alSources[id], AL_BUFFER, AL_NONE); + Data = nil; + DataSize = 0; } void CChannel::SetReverbMix(ALuint slot, float mix) { if ( !IsFXSupported() ) return; if ( !HasSource() ) return; - if ( alFilter == AL_FILTER_NULL ) return; + if ( alFilters[id] == AL_FILTER_NULL ) return; Mix = mix; - EAX3_SetReverbMix(alFilter, mix); - alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter); + EAX3_SetReverbMix(alFilters[id], mix); + alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]); } void CChannel::UpdateReverb(ALuint slot) { if ( !IsFXSupported() ) return; if ( !HasSource() ) return; - if ( alFilter == AL_FILTER_NULL ) return; - EAX3_SetReverbMix(alFilter, Mix); - alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter); + if ( alFilters[id] == AL_FILTER_NULL ) return; + EAX3_SetReverbMix(alFilters[id], Mix); + alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]); } #endif diff --git a/src/audio/oal/channel.h b/src/audio/oal/channel.h index 0c86bdc6..81817a32 100644 --- a/src/audio/oal/channel.h +++ b/src/audio/oal/channel.h @@ -9,22 +9,24 @@ class CChannel { - ALuint alSource; - ALuint alFilter; - ALuint alBuffer; + uint32 id; float Pitch, Gain; float Mix; + void *Data; + size_t DataSize; int32 Frequency; float Position[3]; float Distances[2]; int32 LoopCount; ALint LoopPoints[2]; - uint32 Sample; public: + static void InitChannels(); + static void DestroyChannels(); + CChannel(); void SetDefault(); void Reset(); - void Init(bool Is2D = false); + void Init(uint32 _id, bool Is2D = false); void Term(); void Start(); void Stop(); @@ -33,15 +35,13 @@ public: void SetPitch(float pitch); void SetGain(float gain); void SetVolume(int32 vol); - void SetSampleID(uint32 nSfx); - void SetFreq(int32 freq); + void SetSampleData(void *_data, size_t _DataSize, int32 freq); void SetCurrentFreq(uint32 freq); void SetLoopCount(int32 loopCount); // fake void SetLoopPoints(ALint start, ALint end); void SetPosition(float x, float y, float z); void SetDistances(float max, float min); - void SetPan(uint32 pan); - void SetBuffer(ALuint buffer); + void SetPan(int32 pan); void ClearBuffer(); void SetReverbMix(ALuint slot, float mix); void UpdateReverb(ALuint slot); diff --git a/src/audio/sampman.h b/src/audio/sampman.h index aec61144..2284d385 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -153,11 +153,7 @@ public: bool Initialise(void); void Terminate (void); - -#ifdef AUDIO_OAL - void UpdateSoundBuffers(void); -#endif - + bool CheckForAnAudioFileOnCD(void); char GetCDAudioDriveLetter (void); diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index ad6961b0..eec5ca5f 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -98,58 +98,12 @@ int32 nPedSlotSfx [MAX_PEDSFX]; int32 nPedSlotSfxAddr[MAX_PEDSFX]; uint8 nCurrentPedSlot; -ALuint pedBuffers[MAX_PEDSFX]; - CChannel aChannel[MAXCHANNELS+MAX2DCHANNELS]; uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS]; uint32 nStreamLength[TOTAL_STREAMED_SOUNDS]; ALuint ALStreamSources[MAX_STREAMS]; ALuint ALStreamBuffers[MAX_STREAMS][NUM_STREAMBUFFERS]; -struct -{ - ALuint buffer; - ALint timer; - - bool IsEmpty() { return buffer == 0; } - void Set(ALuint buf) { buffer = buf; } - void Wait() { timer = 10000; } - void Init() - { - buffer = 0; - timer = 0; - } - void Term() - { - if (buffer != 0 && alIsBuffer(buffer)) { - alDeleteBuffers(1, &buffer); - assert(alGetError() == AL_NO_ERROR); - } - timer = 0; - buffer = 0; - } - void Update() - { - if ( !(timer > 0) ) return; - timer -= ALint(CTimer::GetTimeStepInMilliseconds()); - if ( timer > 0 ) return; - timer = 0; - if ( buffer != 0 ) - { - if (!alIsBuffer(buffer)) - { - buffer = 0; - return; - } - alDeleteBuffers(1, &buffer); - ALenum error = alGetError(); - if (error != AL_NO_ERROR) - timer = 10000; - else - buffer = 0; - } - } -}ALBuffers[SAMPLEBANK_MAX]; struct tMP3Entry { @@ -295,12 +249,7 @@ release_existing() alDeleteBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]); } - alDeleteBuffers(MAX_PEDSFX, pedBuffers); - - for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ ) - { - ALBuffers[i].Term(); - } + CChannel::DestroyChannels(); if ( ALContext ) { @@ -381,13 +330,6 @@ set_new_provider(int index) stream->ProviderInit(); } - for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ ) - { - ALBuffers[i].Init(); - } - - alGenBuffers(MAX_PEDSFX, pedBuffers); - usingEAX = 0; usingEAX3 = 0; _usingEFX = false; @@ -419,10 +361,12 @@ set_new_provider(int index) } //SampleManager.SetSpeakerConfig(speaker_type); - + + CChannel::InitChannels(); + for ( int32 i = 0; i < MAXCHANNELS; i++ ) - aChannel[i].Init(); - aChannel[CHANNEL2D].Init(true); + aChannel[i].Init(i); + aChannel[CHANNEL2D].Init(CHANNEL2D, true); if ( IsFXSupported() ) { @@ -1166,7 +1110,7 @@ cSampleManager::Terminate(void) _DeleteMP3Entries(); CStream::Terminate(); - + if ( nSampleBankMemoryStartAddress[SFX_BANK_0] != 0 ) { free((void *)nSampleBankMemoryStartAddress[SFX_BANK_0]); @@ -1182,15 +1126,6 @@ cSampleManager::Terminate(void) _bSampmanInitialised = false; } -void -cSampleManager::UpdateSoundBuffers(void) -{ - for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ ) - { - ALBuffers[i].Update(); - } -} - bool cSampleManager::CheckForAnAudioFileOnCD(void) { return true; @@ -1399,13 +1334,7 @@ cSampleManager::LoadPedComment(uint32 nComment) #endif nPedSlotSfx[nCurrentPedSlot] = nComment; - - alBufferData(pedBuffers[nCurrentPedSlot], - AL_FORMAT_MONO16, - (void *)(nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE*nCurrentPedSlot), - m_aSamples[nComment].nSize, - m_aSamples[nComment].nFrequency); - + if ( ++nCurrentPedSlot >= MAX_PEDSFX ) nCurrentPedSlot = 0; @@ -1541,25 +1470,14 @@ cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) { ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); - ALuint buffer; + uintptr addr; if ( nSfx < SAMPLEBANK_MAX ) { if ( !IsSampleBankLoaded(nBank) ) return false; - uintptr addr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset; - - if ( ALBuffers[nSfx].IsEmpty() ) - { - ALuint buf; - alGenBuffers(1, &buf); - alBufferData(buf, AL_FORMAT_MONO16, (void *)addr, m_aSamples[nSfx].nSize, m_aSamples[nSfx].nFrequency); - ALBuffers[nSfx].Set(buf); - } - ALBuffers[nSfx].Wait(); - - buffer = ALBuffers[nSfx].buffer; + addr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset; } else { @@ -1567,14 +1485,7 @@ cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) return false; int32 slot = _GetPedCommentSlot(nSfx); - - buffer = pedBuffers[slot]; - } - - if ( buffer == 0 ) - { - TRACE("No buffer to play id %d", nSfx); - return false; + addr = (nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE * slot); } if ( GetChannelUsedFlag(nChannel) ) @@ -1586,10 +1497,8 @@ cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) aChannel[nChannel].Reset(); if ( aChannel[nChannel].HasSource() ) { - aChannel[nChannel].SetSampleID (nSfx); - aChannel[nChannel].SetFreq (m_aSamples[nSfx].nFrequency); + aChannel[nChannel].SetSampleData ((void*)addr, m_aSamples[nSfx].nSize, m_aSamples[nSfx].nFrequency); aChannel[nChannel].SetLoopPoints (0, -1); - aChannel[nChannel].SetBuffer (buffer); aChannel[nChannel].SetPitch (1.0f); return true; } @@ -2040,8 +1949,6 @@ cSampleManager::Service(void) if ( stream ) stream->Update(); } - - UpdateSoundBuffers(); } bool -- cgit v1.2.3 From 78ac22ee2cfa12c1e8c93cca956f1aa1f93c76dc Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 27 Oct 2020 15:55:07 +0100 Subject: boolean for extended pipelines --- src/core/re3.cpp | 9 ++++++--- src/extras/custompipes.cpp | 3 +++ src/extras/custompipes.h | 3 +++ src/extras/custompipes_d3d9.cpp | 18 ++++++++++++++++++ src/extras/custompipes_gl.cpp | 17 +++++++++++++++++ 5 files changed, 47 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/re3.cpp b/src/core/re3.cpp index d5a8099d..a06762f5 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -849,9 +849,12 @@ DebugMenuPopulate(void) DebugMenuEntrySetWrap(e, true); DebugMenuAddVar("Render", "Neo Vehicle Shininess", &CustomPipes::VehicleShininess, nil, 0.1f, 0, 1.0f); DebugMenuAddVar("Render", "Neo Vehicle Specularity", &CustomPipes::VehicleSpecularity, nil, 0.1f, 0, 1.0f); - DebugMenuAddVar("Render", "Neo Ped Rim light", &CustomPipes::RimlightMult, nil, 0.1f, 0, 1.0f); - DebugMenuAddVar("Render", "Neo World Lightmaps", &CustomPipes::LightmapMult, nil, 0.1f, 0, 1.0f); - DebugMenuAddVar("Render", "Neo Road Gloss", &CustomPipes::GlossMult, nil, 0.1f, 0, 1.0f); + DebugMenuAddVarBool8("Render", "Neo Ped Rim light enable", &CustomPipes::RimlightEnable, nil); + DebugMenuAddVar("Render", "Mult", &CustomPipes::RimlightMult, nil, 0.1f, 0, 1.0f); + DebugMenuAddVarBool8("Render", "Neo World Lightmaps enable", &CustomPipes::LightmapEnable, nil); + DebugMenuAddVar("Render", "Mult", &CustomPipes::LightmapMult, nil, 0.1f, 0, 1.0f); + DebugMenuAddVarBool8("Render", "Neo Road Gloss enable", &CustomPipes::GlossEnable, nil); + DebugMenuAddVar("Render", "Mult", &CustomPipes::GlossMult, nil, 0.1f, 0, 1.0f); #endif DebugMenuAddVarBool8("Render", "Show Ped Paths", &gbShowPedPaths, nil); DebugMenuAddVarBool8("Render", "Show Car Paths", &gbShowCarPaths, nil); diff --git a/src/extras/custompipes.cpp b/src/extras/custompipes.cpp index 79254eb4..b545b4d8 100644 --- a/src/extras/custompipes.cpp +++ b/src/extras/custompipes.cpp @@ -365,6 +365,7 @@ AttachVehiclePipe(rw::Clump *clump) * Neo World pipe */ +bool LightmapEnable; float LightmapMult = 1.0f; InterpolatedFloat WorldLightmapBlend(1.0f); rw::ObjPipeline *worldPipe; @@ -389,6 +390,7 @@ AttachWorldPipe(rw::Clump *clump) * Neo Gloss pipe */ +bool GlossEnable; float GlossMult = 1.0f; rw::ObjPipeline *glossPipe; @@ -427,6 +429,7 @@ AttachGlossPipe(rw::Clump *clump) * Neo Rim pipes */ +bool RimlightEnable; float RimlightMult = 1.0f; InterpolatedColor RampStart(Color(0.0f, 0.0f, 0.0f, 1.0f)); InterpolatedColor RampEnd(Color(1.0f, 1.0f, 1.0f, 1.0f)); diff --git a/src/extras/custompipes.h b/src/extras/custompipes.h index 4ebe586f..6e9c6517 100644 --- a/src/extras/custompipes.h +++ b/src/extras/custompipes.h @@ -98,6 +98,7 @@ void DestroyVehiclePipe(void); void AttachVehiclePipe(rw::Atomic *atomic); void AttachVehiclePipe(rw::Clump *clump); +extern bool LightmapEnable; extern float LightmapMult; extern InterpolatedFloat WorldLightmapBlend; extern rw::ObjPipeline *worldPipe; @@ -106,6 +107,7 @@ void DestroyWorldPipe(void); void AttachWorldPipe(rw::Atomic *atomic); void AttachWorldPipe(rw::Clump *clump); +extern bool GlossEnable; extern float GlossMult; extern rw::ObjPipeline *glossPipe; void CreateGlossPipe(void); @@ -114,6 +116,7 @@ void AttachGlossPipe(rw::Atomic *atomic); void AttachGlossPipe(rw::Clump *clump); rw::Texture *GetGlossTex(rw::Material *mat); +extern bool RimlightEnable; extern float RimlightMult; extern InterpolatedColor RampStart; extern InterpolatedColor RampEnd; diff --git a/src/extras/custompipes_d3d9.cpp b/src/extras/custompipes_d3d9.cpp index bfc744a3..852f2df8 100644 --- a/src/extras/custompipes_d3d9.cpp +++ b/src/extras/custompipes_d3d9.cpp @@ -190,6 +190,11 @@ worldRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header) using namespace rw::d3d; using namespace rw::d3d9; + if(!LightmapEnable){ + defaultRenderCB_Shader(atomic, header); + return; + } + int vsBits; setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); setIndices(header->indexBuffer); @@ -297,6 +302,9 @@ glossRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header) using namespace rw::d3d; using namespace rw::d3d9; + if(!GlossEnable) + return; + setVertexShader(neoGloss_VS); setPixelShader(neoGloss_PS); @@ -395,6 +403,11 @@ rimRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header) using namespace rw::d3d; using namespace rw::d3d9; + if(!RimlightEnable){ + defaultRenderCB_Shader(atomic, header); + return; + } + int vsBits; setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); setIndices(header->indexBuffer); @@ -433,6 +446,11 @@ rimSkinRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header) using namespace rw::d3d; using namespace rw::d3d9; + if(!RimlightEnable){ + rimSkinRenderCB(atomic, header); + return; + } + int vsBits; setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, diff --git a/src/extras/custompipes_gl.cpp b/src/extras/custompipes_gl.cpp index 5717c83b..01663df5 100644 --- a/src/extras/custompipes_gl.cpp +++ b/src/extras/custompipes_gl.cpp @@ -203,6 +203,11 @@ worldRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header) using namespace rw; using namespace rw::gl3; + if(!LightmapEnable){ + gl3::defaultRenderCB(atomic, header); + return; + } + Material *m; setWorldMatrix(atomic->getFrame()->getLTM()); @@ -315,6 +320,8 @@ glossRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header) using namespace rw::gl3; worldRenderCB(atomic, header); + if(!GlossEnable) + return; Material *m; @@ -442,6 +449,11 @@ rimSkinRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header) using namespace rw; using namespace rw::gl3; + if(!RimlightEnable){ + gl3::skinRenderCB(atomic, header); + return; + } + Material *m; setWorldMatrix(atomic->getFrame()->getLTM()); @@ -487,6 +499,11 @@ rimRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header) using namespace rw; using namespace rw::gl3; + if(!RimlightEnable){ + gl3::defaultRenderCB(atomic, header); + return; + } + Material *m; setWorldMatrix(atomic->getFrame()->getLTM()); -- cgit v1.2.3 From ee222d03849b1ccac92c54378a74535b2bd68609 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 27 Oct 2020 16:15:30 +0100 Subject: stupid bug; update librw --- src/extras/custompipes_d3d9.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extras/custompipes_d3d9.cpp b/src/extras/custompipes_d3d9.cpp index 852f2df8..93973fec 100644 --- a/src/extras/custompipes_d3d9.cpp +++ b/src/extras/custompipes_d3d9.cpp @@ -447,7 +447,7 @@ rimSkinRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header) using namespace rw::d3d9; if(!RimlightEnable){ - rimSkinRenderCB(atomic, header); + skinRenderCB(atomic, header); return; } -- cgit v1.2.3 From e2dc1ba10242dfd94faab1a59d27862de92bcf37 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Tue, 27 Oct 2020 18:55:28 +0300 Subject: fix rainraindrop --- src/render/Weather.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index 2c0b27d2..f16467b6 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -346,7 +346,7 @@ void CWeather::AddRain() pos.y = CGeneral::GetRandomNumberInRange(DROPLETS_TOP_OFFSET, screen_height - DROPLETS_TOP_OFFSET); pos.z = 0.0f; CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, CVector(0.0f, 0.0f, 0.0f), nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f), - colour, CGeneral::GetRandomNumberInRange(-10, 10), 360 - rain_angle + CGeneral::GetRandomNumberInRange(-30, 30), cur_frame, 0); + colour, CGeneral::GetRandomNumberInRange(-10, 10), 360 - rain_angle + CGeneral::GetRandomNumberInRange(-30, 30), cur_frame, 50); } int num_splash_attempts = (int)(3 * Rain) + 1; int num_splashes = (int)(3 * Rain) + 4; -- cgit v1.2.3 From f7b1ba4049006fa772d9e16db96ce326dbde4aa8 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 28 Oct 2020 03:10:53 +0300 Subject: fix FireShotgun missing normalise --- src/weapons/Weapon.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 85f0bc15..9494c745 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -108,10 +108,17 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) CVector fireOffset(0.0f, 0.0f, 0.6f); CVector *source = fireSource; - if (!fireSource) { + if (!fireSource) + { + fireOffset = shooter->GetMatrix() * fireOffset; +#ifdef FIX_BUGS static CVector tmp; - tmp = shooter->GetMatrix() * fireOffset; + tmp = fireOffset; source = &tmp; +#else + source = &fireOffset; +#endif + } if ( m_bAddRotOffset ) { @@ -1166,6 +1173,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { float shootAngle = DEGTORAD(7.5f*i + shooterAngle - 15.0f); CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); + shootRot.Normalise(); CVector source, target; CColPoint point; -- cgit v1.2.3 From a5447306c4e53da45f389967e2f43fd6ca80d215 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 28 Oct 2020 10:33:27 +0100 Subject: fixed skin on player head --- src/modelinfo/ClumpModelInfo.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/modelinfo/ClumpModelInfo.cpp b/src/modelinfo/ClumpModelInfo.cpp index 49198437..1ae936a7 100644 --- a/src/modelinfo/ClumpModelInfo.cpp +++ b/src/modelinfo/ClumpModelInfo.cpp @@ -5,6 +5,7 @@ #include "NodeName.h" #include "VisibilityPlugins.h" #include "ModelInfo.h" +#include "ModelIndices.h" void CClumpModelInfo::DeleteRwObject(void) @@ -110,12 +111,18 @@ CClumpModelInfo::SetClump(RpClump *clump) weights->w3 /= sum; } RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS)); - }else -#endif - // do not set on skinned clip because cutscene head is not compatible with player head - if(strncmp(GetName(), "playerh", 8) == 0) + } + if(strncmp(GetName(), "playerh", 8) == 0){ + // playerh is incompatible with the xbox player skin + // so check if player model is skinned and only apply skin to head if it isn't + CPedModelInfo *body = (CPedModelInfo*)CModelInfo::GetModelInfo(MI_PLAYER); + if(!(body->m_clump && IsClumpSkinned(body->m_clump))) RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); - + } +#else + if(strncmp(GetName(), "playerh", 8) == 0){ + RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); +#endif } void -- cgit v1.2.3 From 922d06ab1fb1c2222b2738bd12cbc7549dc52ded Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 28 Oct 2020 05:11:34 +0300 Subject: rewrite CFO + postfx/pipeline options --- src/core/Frontend.cpp | 300 ++++++--------- src/core/Frontend.h | 115 +++++- src/core/Game.cpp | 11 - src/core/MenuScreens.cpp | 15 +- src/core/MenuScreensCustom.cpp | 804 +++++++++++++++++++++++++++++++++++++++++ src/core/config.h | 4 +- src/core/main.cpp | 8 + src/core/re3.cpp | 442 +++------------------- src/extras/frontendoption.cpp | 238 +++--------- src/extras/frontendoption.h | 121 ++----- 10 files changed, 1173 insertions(+), 885 deletions(-) create mode 100644 src/core/MenuScreensCustom.cpp (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 89b5ba3d..8f1204e3 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -435,29 +435,17 @@ CMenuManager::ThingsToDoBeforeGoingBack() } #ifdef CUSTOM_FRONTEND_OPTIONS - for (int i = 0; i < numCustomFrontendOptions; i++) { - FrontendOption &option = customFrontendOptions[i]; - if (option.type != FEOPTION_REDIRECT && option.type != FEOPTION_GOBACK && m_nCurrScreen == option.screen) { - if (option.returnPrevPageFunc) - option.returnPrevPageFunc(); - - if (m_nCurrOption == option.screenOptionOrder && (option.type == FEOPTION_DYNAMIC || option.type == FEOPTION_BUILTIN_ACTION)) - if(option.buttonPressFunc) - option.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); - - if (option.type == FEOPTION_SELECT && option.onlyApplyOnEnter && option.lastSavedValue != option.displayedValue) - option.displayedValue = *option.value = option.lastSavedValue; - } - } + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; - if (m_nCurrScreen > lastOgScreen) { - for (int i = 0; i < numCustomFrontendScreens; i++) { - FrontendScreen& screen = customFrontendScreens[i]; - if (m_nCurrScreen == screen.id && screen.returnPrevPageFunc) { - screen.returnPrevPageFunc(); - break; - } - } + if (option.m_Action == MENUACTION_CFO_DYNAMIC) + if(option.m_CFODynamic->buttonPressFunc) + option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + + if (option.m_Action == MENUACTION_CFO_SELECT && option.m_CFOSelect->onlyApplyOnEnter && option.m_CFOSelect->lastSavedValue != option.m_CFOSelect->displayedValue) + option.m_CFOSelect->displayedValue = *option.m_CFO->value = option.m_CFOSelect->lastSavedValue; + + if (aScreens[m_nCurrScreen].returnPrevPageFunc) { + aScreens[m_nCurrScreen].returnPrevPageFunc(); } #endif } @@ -476,18 +464,15 @@ CMenuManager::GetPreviousPageOption() prevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage; for (int i = 0; i < NUM_MENUROWS; i++) { - if (aScreens[prevPage].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) { - FrontendOption &option = customFrontendOptions[aScreens[prevPage].m_aEntries[i].m_TargetMenu]; - if(option.type == FEOPTION_REDIRECT && option.to == m_nCurrScreen) { + if (aScreens[prevPage].m_aEntries[i].m_Action >= MENUACTION_NOTHING) { // CFO check + if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) { return i; } - } else if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) { - return i; } } - - // Couldn't find current screen option on previous page, use default behaviour (maybe save-related screen?) - return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; + + // This shouldn't happen + return 0; #endif } @@ -854,13 +839,6 @@ CMenuManager::Draw() str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); break; default: -#ifdef CUSTOM_FRONTEND_OPTIONS - if (aScreens[m_nCurrScreen].m_aEntries[0].m_SaveSlot == SAVESLOT_CFO) { - FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[0].m_TargetMenu]; - str = (wchar*)option.leftText; - } - else -#endif str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); break; } @@ -959,30 +937,22 @@ CMenuManager::Draw() #endif default: #ifdef CUSTOM_FRONTEND_OPTIONS - bool custom = m_nCurrScreen > lastOgScreen; + CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout; if (custom) { - for (int i = 0; i < numCustomFrontendScreens; i++) { - FrontendScreen& screen = customFrontendScreens[i]; - if (m_nCurrScreen == screen.id) { - columnWidth = screen.columnWidth; - headerHeight = screen.headerHeight; - lineHeight = screen.lineHeight; - CFont::SetFontStyle(FONT_LOCALE(screen.font)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = screen.fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = screen.fontScaleY)); - if (screen.alignment == FESCREEN_LEFT_ALIGN) { - CFont::SetCentreOff(); - CFont::SetRightJustifyOff(); - } else if (screen.alignment == FESCREEN_RIGHT_ALIGN) { - CFont::SetCentreOff(); - CFont::SetRightJustifyOn(); - } else { - CFont::SetRightJustifyOff(); - CFont::SetCentreOn(); - } - break; - } - if (i == numCustomFrontendScreens - 1) - custom = false; + columnWidth = custom->columnWidth; + headerHeight = custom->headerHeight; + lineHeight = custom->lineHeight; + CFont::SetFontStyle(FONT_LOCALE(custom->font)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = custom->fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = custom->fontScaleY)); + if (custom->alignment == FESCREEN_LEFT_ALIGN) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + } else if (custom->alignment == FESCREEN_RIGHT_ALIGN) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + } else { + CFont::SetRightJustifyOff(); + CFont::SetCentreOn(); } } if (!custom) @@ -1066,28 +1036,22 @@ CMenuManager::Draw() leftText = TheText.Get(gString); } } else { -#ifdef CUSTOM_FRONTEND_OPTIONS - if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO){ - FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; - leftText = (wchar*)option.leftText; - } else -#endif leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } #ifdef CUSTOM_FRONTEND_OPTIONS - if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) { - FrontendOption &option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; - if (option.type == FEOPTION_SELECT) { - if (option.onlyApplyOnEnter){ + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action < MENUACTION_NOTHING) { // CFO check + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + if (option.m_CFOSelect->onlyApplyOnEnter){ if (m_nCurrOption != i) { - if (option.displayedValue != option.lastSavedValue) + if (option.m_CFOSelect->displayedValue != option.m_CFOSelect->lastSavedValue) SetHelperText(3); // Restored original value -// option.displayedValue = option.lastSavedValue = *option.value; +// option.displayedValue = option.lastSavedValue = *option.m_CFO->value; } else { - if (option.displayedValue != *option.value) + if (option.m_CFOSelect->displayedValue != *option.m_CFO->value) SetHelperText(1); // Enter to apply else if (m_nHelperTextMsgId == 1) ResetHelperText(); // Applied @@ -1096,13 +1060,13 @@ CMenuManager::Draw() } if (m_nCurrOption != lastOption && lastOption == i) { - FrontendOption &oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu]; - if (oldOption.type == FEOPTION_DYNAMIC || oldOption.type == FEOPTION_BUILTIN_ACTION) - if(oldOption.buttonPressFunc) - oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + CMenuScreenCustom::CMenuEntry &oldOption = aScreens[m_nCurrScreen].m_aEntries[lastOption]; + if (oldOption.m_Action == MENUACTION_CFO_DYNAMIC) + if(oldOption.m_CFODynamic->buttonPressFunc) + oldOption.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); - if (oldOption.onlyApplyOnEnter && oldOption.type == FEOPTION_SELECT) - oldOption.displayedValue = oldOption.lastSavedValue = *oldOption.value; + if (oldOption.m_Action == MENUACTION_CFO_SELECT && oldOption.m_CFOSelect->onlyApplyOnEnter) + oldOption.m_CFOSelect->displayedValue = oldOption.m_CFOSelect->lastSavedValue = *oldOption.m_CFO->value; } } #endif @@ -1336,29 +1300,24 @@ CMenuManager::Draw() rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON"); break; #ifdef CUSTOM_FRONTEND_OPTIONS - case MENUACTION_TRIGGERFUNC: - FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; - if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) { - if (option.type == FEOPTION_SELECT) { - // To whom manipulate option.value of static options externally (like RestoreDef functions) - if (*option.value != option.lastSavedValue) - option.displayedValue = option.lastSavedValue = *option.value; - - if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) - option.displayedValue = 0; - - rightText = (wchar*)option.rightTexts[option.displayedValue]; - - } else if (option.type == FEOPTION_DYNAMIC) { - if (option.drawFunc) { - rightText = option.drawFunc(&isOptionDisabled, m_nCurrOption == i); - } + case MENUACTION_CFO_DYNAMIC: + case MENUACTION_CFO_SELECT: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + // 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; + + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = 0; + + rightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]); + + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { + if (option.m_CFODynamic->drawFunc) { + rightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i); } - } else { - debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); - assert(0 && "Custom frontend options is borked"); } - break; #endif } @@ -1573,13 +1532,9 @@ CMenuManager::Draw() break; #ifdef CUSTOM_FRONTEND_OPTIONS default: - if (m_nCurrScreen > lastOgScreen) { - for (int i = 0; i < numCustomFrontendScreens; i++) { - FrontendScreen& screen = customFrontendScreens[i]; - if (m_nCurrScreen == screen.id && screen.showLeftRightHelper) { - DisplayHelperText(); - break; - } + if (aScreens[m_nCurrScreen].layout) { + if (aScreens[m_nCurrScreen].layout->showLeftRightHelper) { + DisplayHelperText(); } } break; @@ -2612,17 +2567,10 @@ CMenuManager::DrawFrontEndNormal() break; default: #ifdef CUSTOM_FRONTEND_OPTIONS - bool custom = m_nPrevScreen > lastOgScreen; + CCustomScreenLayout *custom = aScreens[m_nPrevScreen].layout; if (custom) { - for (int i = 0; i < numCustomFrontendScreens; i++) { - FrontendScreen& screen = customFrontendScreens[i]; - if (m_nPrevScreen == screen.id) { - previousSprite = screen.sprite; - break; - } - if (i == numCustomFrontendScreens - 1) - custom = false; - } + previousSprite = custom->sprite; + break; } if (!custom) #endif @@ -2678,15 +2626,9 @@ CMenuManager::DrawFrontEndNormal() break; #ifdef CUSTOM_FRONTEND_OPTIONS default: - bool custom = m_nCurrScreen > lastOgScreen; + CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout; if (custom) { - for (int i = 0; i < numCustomFrontendScreens; i++) { - FrontendScreen& screen = customFrontendScreens[i]; - if (m_nCurrScreen == screen.id) { - currentSprite = screen.sprite; - break; - } - } + previousSprite = custom->sprite; } break; #endif @@ -3301,10 +3243,6 @@ CMenuManager::InitialiseChangedLanguageSettings() default: break; } - -#ifdef CUSTOM_FRONTEND_OPTIONS - CustomFrontendOptionsPopulate(); -#endif } } @@ -3494,6 +3432,9 @@ CMenuManager::LoadSettings() strcpy(m_PrefsSkinFile, DEFAULT_SKIN_NAME); strcpy(m_aSkinName, DEFAULT_SKIN_NAME); } +#ifdef LOAD_INI_SETTINGS + LoadINISettings(); // needs frontend options to be loaded +#endif } void @@ -5086,29 +5027,28 @@ CMenuManager::ProcessButtonPresses(void) return; #endif #ifdef CUSTOM_FRONTEND_OPTIONS - case MENUACTION_TRIGGERFUNC: - FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; - if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) { - if (option.type == FEOPTION_SELECT) { - if (!option.onlyApplyOnEnter) { - option.displayedValue++; - if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) - option.displayedValue = 0; - } - option.changeFunc(option.displayedValue); - *option.value = option.lastSavedValue = option.displayedValue; - - } else if (option.type == FEOPTION_DYNAMIC) { - if (option.buttonPressFunc) - option.buttonPressFunc(FEOPTION_ACTION_SELECT); - } else if (option.type == FEOPTION_REDIRECT) { - ChangeScreen(option.to, option.option, true, option.fadeIn); - } else if (option.type == FEOPTION_GOBACK) { - goBack = true; + case MENUACTION_CFO_SELECT: + 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->onlyApplyOnEnter) { + option.m_CFOSelect->displayedValue++; + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = 0; } - } else { - debug("B- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); - assert(0 && "Custom frontend options are borked"); + int8 oldValue = *option.m_CFO->value; + + *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; + + if (option.m_CFOSelect->save) + SaveSettings(); + + if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc) + option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue); + + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { + if (option.m_CFODynamic->buttonPressFunc) + option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_SELECT); } break; @@ -5116,14 +5056,6 @@ CMenuManager::ProcessButtonPresses(void) } } ProcessOnOffMenuOptions(); -#ifdef CUSTOM_FRONTEND_OPTIONS - if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot == SAVESLOT_CFO) { - FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; - if (option.type == FEOPTION_BUILTIN_ACTION && option.buttonPressFunc) { - option.buttonPressFunc(FEOPTION_ACTION_SELECT); - } - } -#endif } if (goBack) { @@ -5326,32 +5258,34 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; #ifdef CUSTOM_FRONTEND_OPTIONS - case MENUACTION_TRIGGERFUNC: - FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; - if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) { - if (option.type == FEOPTION_SELECT) { - if (changeValueBy > 0) { - option.displayedValue++; - if (option.displayedValue >= option.numRightTexts) - option.displayedValue = 0; - } else { - option.displayedValue--; - if (option.displayedValue < 0) - option.displayedValue = option.numRightTexts - 1; - } - if (!option.onlyApplyOnEnter) { - option.changeFunc(option.displayedValue); - *option.value = option.lastSavedValue = option.displayedValue; - } - } else if (option.type == FEOPTION_DYNAMIC && option.buttonPressFunc) { - option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); + case MENUACTION_CFO_SELECT: + case MENUACTION_CFO_DYNAMIC: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + if (changeValueBy > 0) { + option.m_CFOSelect->displayedValue++; + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts) + option.m_CFOSelect->displayedValue = 0; + } else { + option.m_CFOSelect->displayedValue--; + if (option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = option.m_CFOSelect->numRightTexts - 1; } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - } - else { - debug("C- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); - assert(0 && "Custom frontend options are borked"); + if (!option.m_CFOSelect->onlyApplyOnEnter) { + int8 oldValue = *option.m_CFO->value; + + *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; + + if (option.m_CFOSelect->save) + SaveSettings(); + + if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc) + option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue); + } + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC && option.m_CFODynamic->buttonPressFunc) { + option.m_CFODynamic->buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); break; #endif diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 848148e7..70b4cd31 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -156,9 +156,6 @@ enum eSaveSlot SAVESLOT_7, SAVESLOT_8, SAVESLOT_LABEL = 36, -#ifdef CUSTOM_FRONTEND_OPTIONS - SAVESLOT_CFO -#endif }; #ifdef MENU_MAP @@ -238,19 +235,32 @@ enum eMenuScreen MENUPAGE_KEYBOARD_CONTROLS = 55, MENUPAGE_MOUSE_CONTROLS = 56, MENUPAGE_MISSION_RETRY = 57, +#ifdef CUSTOM_FRONTEND_OPTIONS + #ifdef MENU_MAP MENUPAGE_MAP, #endif - MENUPAGE_UNK, // 58 in game. Map page is added above, because last screen in CMenuScreens should always be empty to make CFO work -#ifdef CUSTOM_FRONTEND_OPTIONS - MENUPAGES = 65 // for some room to add more screen +#ifdef GRAPHICS_MENU_OPTIONS + MENUPAGE_GRAPHICS_SETTINGS, #else - MENUPAGES + MENUPAGE_ADVANCED_DISPLAY_SETTINGS, +#endif +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + MENUPAGE_DETECT_JOYSTICK, #endif + +#endif + MENUPAGE_UNK, // originally 58. Custom screens are inserted above, because last screen in CMenuScreens should always be empty to make CFO work + MENUPAGES + }; enum eMenuAction { +#ifdef CUSTOM_FRONTEND_OPTIONS + MENUACTION_CFO_SELECT = -2, + MENUACTION_CFO_DYNAMIC = -1, +#endif MENUACTION_NOTHING, MENUACTION_LABEL, MENUACTION_CHANGEMENU, @@ -373,9 +383,6 @@ enum eMenuAction //#ifdef NO_ISLAND_LOADING // MENUACTION_ISLANDLOADING, //#endif -#ifdef CUSTOM_FRONTEND_OPTIONS - MENUACTION_TRIGGERFUNC -#endif }; enum eCheckHover @@ -458,6 +465,7 @@ struct BottomBarOption int32 screenId; }; +#ifndef CUSTOM_FRONTEND_OPTIONS struct CMenuScreen { char m_ScreenName[8]; @@ -470,9 +478,91 @@ struct CMenuScreen int32 m_Action; // eMenuAction char m_EntryName[8]; int32 m_SaveSlot; // eSaveSlot - int32 m_TargetMenu; // eMenuScreen // FrontendOption ID if it's a custom option + int32 m_TargetMenu; // eMenuScreen + } m_aEntries[NUM_MENUROWS]; +}; +extern CMenuScreen aScreens[MENUPAGES]; +#else +#include "frontendoption.h" +struct CCustomScreenLayout { + eMenuSprites sprite; + int columnWidth; + int headerHeight; + int lineHeight; + int8 font; + int8 alignment; + bool showLeftRightHelper; + float fontScaleX; + float fontScaleY; +}; + +struct CCFO +{ + int8 *value; + const char *save; +}; + +struct CCFOSelect : CCFO +{ + char** rightTexts; + int8 numRightTexts; + bool onlyApplyOnEnter; + int8 displayedValue; // only if onlyApplyOnEnter enabled for now + int8 lastSavedValue; // only if onlyApplyOnEnter enabled + ChangeFunc changeFunc; + + CCFOSelect() {}; + CCFOSelect(int8* value, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc){ + this->value = value; + if (value) + this->lastSavedValue = this->displayedValue = *value; + + this->save = save; + this->rightTexts = (char**)rightTexts; + this->numRightTexts = numRightTexts; + this->onlyApplyOnEnter = onlyApplyOnEnter; + this->changeFunc = changeFunc; + } +}; + +struct CCFODynamic : CCFO +{ + DrawFunc drawFunc; + ButtonPressFunc buttonPressFunc; + + CCFODynamic() {}; + CCFODynamic(int8* value, const char* save, DrawFunc drawFunc, ButtonPressFunc buttonPressFunc){ + this->value = value; + this->save = save; + this->drawFunc = drawFunc; + this->buttonPressFunc = buttonPressFunc; + } +}; + +struct CMenuScreenCustom +{ + char m_ScreenName[8]; + int32 m_PreviousPage[2]; // eMenuScreen + CCustomScreenLayout *layout; + ReturnPrevPageFunc returnPrevPageFunc; + + struct CMenuEntry + { + int32 m_Action; // eMenuAction - below zero is CFO + char m_EntryName[8]; + struct { + union { + CCFO *m_CFO; // for initializing + CCFOSelect *m_CFOSelect; + CCFODynamic *m_CFODynamic; + }; + int32 m_SaveSlot; // eSaveSlot + int32 m_TargetMenu; // eMenuScreen + }; } m_aEntries[NUM_MENUROWS]; }; +extern CMenuScreenCustom aScreens[MENUPAGES]; +#endif class CMenuManager { @@ -703,6 +793,5 @@ VALIDATE_SIZE(CMenuManager, 0x564); #endif extern CMenuManager FrontEndMenuManager; -extern CMenuScreen aScreens[MENUPAGES]; -#endif \ No newline at end of file +#endif diff --git a/src/core/Game.cpp b/src/core/Game.cpp index ef4800c5..83c75d91 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -86,7 +86,6 @@ #include "ZoneCull.h" #include "Zones.h" #include "debugmenu.h" -#include "frontendoption.h" #include "postfx.h" #include "custompipes.h" #include "crossplatform.h" @@ -314,16 +313,6 @@ bool CGame::InitialiseOnceAfterRW(void) DMAudio.SetMusicFadeVol(127); CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile); -#ifdef CUSTOM_FRONTEND_OPTIONS - // Apparently this func. can be run multiple times at the start. - if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) { - // needs stored language and TheText to be loaded, and last TheText reload is at the start of here - CustomFrontendOptionsPopulate(); - } -#endif -#ifdef LOAD_INI_SETTINGS - LoadINISettings(); // needs frontend options to be loaded -#endif return true; } diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp index 533fc755..c2eadb3b 100644 --- a/src/core/MenuScreens.cpp +++ b/src/core/MenuScreens.cpp @@ -2,8 +2,10 @@ #include "Frontend.h" #ifdef PC_MENU -// If you want to add new options, please don't do that here and see CustomFrontendOptionsPopulate in re3.cpp. +// Please don't touch this file, except for bug fixing or ports. +// Check MenuScreensCustom.cpp +#ifndef CUSTOM_FRONTEND_OPTIONS CMenuScreen aScreens[MENUPAGES] = { // MENUPAGE_NONE = 0 { "", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, }, @@ -434,14 +436,6 @@ CMenuScreen aScreens[MENUPAGES] = { }, #endif -#ifdef MENU_MAP - // MENUPAGE_MAP - { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2, - MENUACTION_UNK110, "", SAVESLOT_NONE, MENUPAGE_NONE, // to prevent cross/enter to go back - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, -#endif - // MENUPAGE_UNK { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0, @@ -449,4 +443,5 @@ CMenuScreen aScreens[MENUPAGES] = { }; -#endif \ No newline at end of file +#endif +#endif diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp new file mode 100644 index 00000000..e2516140 --- /dev/null +++ b/src/core/MenuScreensCustom.cpp @@ -0,0 +1,804 @@ +#include "common.h" +#include "platform.h" +#include "crossplatform.h" +#include "Renderer.h" +#include "Frontend.h" +#include "Font.h" +#include "Camera.h" +#include "main.h" +#include "MBlur.h" +#include "postfx.h" +#include "custompipes.h" +#include "RwHelper.h" + +// Menu screens array is at the bottom of the file. + +#ifdef PC_MENU + +#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) }, +#else + #define VIDEOMODE_SELECTOR +#endif + +#ifdef MULTISAMPLING + #define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) }, +#else + #define MULTISAMPLING_SELECTOR +#endif + +#ifdef CUTSCENE_BORDERS_SWITCH + #define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&CMenuManager::m_PrefsCutsceneBorders, "CutsceneBorders", off_on, 2, false, nil) }, +#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) }, +#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) }, +#else + #define DUALPASS_SELECTOR +#endif + +#ifdef EXTENDED_COLOURFILTER + #define POSTFX_SELECTORS \ + MENUACTION_CFO_SELECT, "VEHPIPE", { new CCFOSelect((int8*)&CustomPipes::VehiclePipeSwitch, "VehiclePipeline", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), false, nil) }, \ + MENUACTION_CFO_SELECT, "RIM", { new CCFOSelect((int8*)&CustomPipes::RimlightEnable, "NeoRimLight", off_on, 2, false, nil) }, \ + MENUACTION_CFO_SELECT, "LGTMAPS", { new CCFOSelect((int8*)&CustomPipes::LightmapEnable, "NeoLightMaps", off_on, 2, false, nil) }, \ + MENUACTION_CFO_SELECT, "GLOSS", { new CCFOSelect((int8*)&CustomPipes::GlossEnable, "NeoRoadGloss", off_on, 2, false, nil) }, +#else + #define POSTFX_SELECTORS +#endif + +#ifdef EXTENDED_PIPELINES + #define PIPELINES_SELECTOR \ + MENUACTION_CFO_SELECT, "CLRFLTR", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \ + MENUACTION_CFO_SELECT, "MBLUR", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) }, +#else + #define PIPELINES_SELECTOR +#endif + +const char *filterNames[] = { "None", "Simple", "Normal", "Mobile" }; +const char *vehPipelineNames[] = { "MatFX", "Neo" }; +const char *off_on[] = { "FEM_OFF", "FEM_ON" }; + +void RestoreDefGraphics(int8 action) { + if (action != FEOPTION_ACTION_SELECT) + return; + + #ifdef PS2_ALPHA_TEST + gPS2alphaTest = false; + #endif + #ifdef MULTISAMPLING + FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0; + #endif + #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those + CMenuManager::m_PrefsFrameLimiter = true; + CMenuManager::m_PrefsVsyncDisp = true; + CMenuManager::m_PrefsVsync = true; + CMenuManager::m_PrefsUseWideScreen = false; + FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode; + #ifdef GTA3_1_1_PATCH + if (_dwOperatingSystemVersion == OS_WIN98) { + CMBlur::BlurOn = false; + CMBlur::MotionBlurClose(); + } else { + CMBlur::BlurOn = true; + CMBlur::MotionBlurOpen(Scene.camera); + } + #else + CMBlur::BlurOn = true; + #endif + FrontEndMenuManager.SaveSettings(); + #endif +} + +void RestoreDefDisplay(int8 action) { + if (action != FEOPTION_ACTION_SELECT) + return; + + #ifdef CUTSCENE_BORDERS_SWITCH + CMenuManager::m_PrefsCutsceneBorders = true; + #endif + #ifdef FREE_CAM + TheCamera.bFreeCam = false; + #endif + #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those + CMenuManager::m_PrefsBrightness = 256; + CMenuManager::m_PrefsLOD = 1.2f; + CRenderer::ms_lodDistScale = 1.2f; + CMenuManager::m_PrefsShowSubtitles = true; + FrontEndMenuManager.SaveSettings(); + #endif +} + +#ifdef MORE_LANGUAGES +void LangPolSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} + +void LangRusSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} + +void LangJapSelect(int8 action) +{ + if (action == FEOPTION_ACTION_SELECT) { + FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE; + FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; + FrontEndMenuManager.InitialiseChangedLanguageSettings(); + FrontEndMenuManager.SaveSettings(); + } +} +#endif + +#ifndef MULTISAMPLING +void GraphicsGoBack() { +} +#else +void GraphicsGoBack() { + FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; +} + +void MultiSamplingButtonPress(int8 action) { + if (action == FEOPTION_ACTION_SELECT) { + if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { + FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel; + _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); + FrontEndMenuManager.SetHelperText(0); + FrontEndMenuManager.SaveSettings(); + } + } else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) { + if (FrontEndMenuManager.m_bGameNotLoaded) { + FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1); + + int i = 0; + int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels(); + while (maxAA != 1) { + i++; + maxAA >>= 1; + } + + if (FrontEndMenuManager.m_nDisplayMSAALevel < 0) + FrontEndMenuManager.m_nDisplayMSAALevel = i; + else if (FrontEndMenuManager.m_nDisplayMSAALevel > i) + FrontEndMenuManager.m_nDisplayMSAALevel = 0; + } + } else if (action == FEOPTION_ACTION_FOCUSLOSS) { + if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { + FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; + FrontEndMenuManager.SetHelperText(3); + } + } +} + +wchar* MultiSamplingDraw(bool *disabled, bool userHovering) { + static wchar unicodeTemp[64]; + if (userHovering) { + if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) { + if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply + FrontEndMenuManager.ResetHelperText(); + } else { + FrontEndMenuManager.SetHelperText(1); + } + } else { + if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { + FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; + } + } + + if (!FrontEndMenuManager.m_bGameNotLoaded) + *disabled = true; + + switch (FrontEndMenuManager.m_nDisplayMSAALevel) { + case 0: + return TheText.Get("FEM_OFF"); + default: + sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel)); + AsciiToUnicode(gString, unicodeTemp); + return unicodeTemp; + } +} +#endif + +#ifdef IMPROVED_VIDEOMODE +const char* screenModes[] = { "FED_FLS", "FED_WND" }; +void ScreenModeAfterChange(int8 before, int8 after) +{ + _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution + FrontEndMenuManager.SetHelperText(0); +} + +#endif + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +wchar selectedJoystickUnicode[128]; + +wchar* DetectJoystickDraw(bool* disabled, bool userHovering) { + int numButtons; + int found = -1; + const char *joyname; + if (userHovering) { + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { + if ((joyname = glfwGetJoystickName(i))) { + const uint8* buttons = glfwGetJoystickButtons(i, &numButtons); + for (int j = 0; j < numButtons; j++) { + if (buttons[j]) { + found = i; + break; + } + } + if (found != -1) + break; + } + } + + if (found != -1 && PSGLOBAL(joy1id) != found) { + if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found) + PSGLOBAL(joy2id) = PSGLOBAL(joy1id); + else + PSGLOBAL(joy2id) = -1; + + strcpy(gSelectedJoystickName, joyname); + PSGLOBAL(joy1id) = found; + } + } + if (PSGLOBAL(joy1id) == -1) + AsciiToUnicode("Not found", selectedJoystickUnicode); + else + AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode); + + return selectedJoystickUnicode; +} +#endif + +CMenuScreenCustom aScreens[MENUPAGES] = { + // MENUPAGE_NONE = 0 + { "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, }, + + // MENUPAGE_STATS = 1 + { "FET_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_NEW_GAME = 2 + { "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_CHANGEMENU, "FES_SNG", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD }, + MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT }, + MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_BRIEFS = 3 + { "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_CONTROLLER_SETTINGS = 4 + { "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, + MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, + MENUACTION_CTRLVIBRATION, "FEC_VIB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_SOUND_SETTINGS = 5 + { "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + MENUACTION_MUSICVOLUME, "FEA_MUS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_SFXVOLUME, "FEA_SFX", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_AUDIOHW, "FEA_3DH", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_SPEAKERCONF, "FEA_SPK", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_DYNAMICACOUSTIC, "FET_DAM", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_RADIO, "FEA_RSS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + +#ifndef GRAPHICS_MENU_OPTIONS + // MENUPAGE_DISPLAY_SETTINGS = 6 + { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, +#ifndef EXTENDED_COLOURFILTER + MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, +#endif + MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + VIDEOMODE_SELECTOR + MULTISAMPLING_SELECTOR + MENUACTION_CHANGEMENU, "FET_ADV", { nil, SAVESLOT_NONE, MENUPAGE_ADVANCED_DISPLAY_SETTINGS }, + MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#else + // MENUPAGE_DISPLAY_SETTINGS = 6 + { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + CUTSCENE_BORDERS_TOGGLE + FREE_CAM_TOGGLE + MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefDisplay) }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#endif + + // MENUPAGE_LANGUAGE_SETTINGS = 7 + { "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + MENUACTION_LANG_ENG, "FEL_ENG", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, + MENUACTION_LANG_FRE, "FEL_FRE", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, + MENUACTION_LANG_GER, "FEL_GER", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, + MENUACTION_LANG_ITA, "FEL_ITA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, + MENUACTION_LANG_SPA, "FEL_SPA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, +#ifdef MORE_LANGUAGES + MENUACTION_CFO_DYNAMIC, "FEL_POL", { new CCFODynamic(nil, nil, nil, LangPolSelect) }, + MENUACTION_CFO_DYNAMIC, "FEL_RUS", { new CCFODynamic(nil, nil, nil, LangRusSelect) }, + MENUACTION_CFO_DYNAMIC, "FEL_JAP", { new CCFODynamic(nil, nil, nil, LangJapSelect) }, +#endif + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_CHOOSE_LOAD_SLOT = 8 + { "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, + MENUACTION_CHECKSAVE, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM }, + MENUACTION_CHECKSAVE, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM }, + MENUACTION_CHECKSAVE, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_LOAD_SLOT_CONFIRM }, + MENUACTION_CHECKSAVE, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_LOAD_SLOT_CONFIRM }, + MENUACTION_CHECKSAVE, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_LOAD_SLOT_CONFIRM }, + MENUACTION_CHECKSAVE, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_LOAD_SLOT_CONFIRM }, + MENUACTION_CHECKSAVE, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_LOAD_SLOT_CONFIRM }, + MENUACTION_CHECKSAVE, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_LOAD_SLOT_CONFIRM }, + }, + + // MENUPAGE_CHOOSE_DELETE_SLOT = 9 + { "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, + MENUACTION_CHANGEMENU, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_DELETE_SLOT_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_DELETE_SLOT_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_DELETE_SLOT_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_DELETE_SLOT_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_DELETE_SLOT_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_DELETE_SLOT_CONFIRM }, + }, + + // MENUPAGE_NEW_GAME_RELOAD = 10 + { "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_LABEL, "FESZ_QR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, + MENUACTION_NEWGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD }, + }, + + // MENUPAGE_LOAD_SLOT_CONFIRM = 11 + { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil, + MENUACTION_LABEL, "FESZ_QL", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT }, + MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS }, + }, + + // MENUPAGE_DELETE_SLOT_CONFIRM = 12 + { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, + MENUACTION_LABEL, "FESZ_QD", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, + MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_DELETING }, + }, + + // MENUPAGE_NO_MEMORY_CARD = 13 + { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + // hud adjustment page in mobile + }, + + // MENUPAGE_LOADING_IN_PROGRESS = 14 + { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_LABEL, "FED_LDW", { nil, SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM }, + }, + + // MENUPAGE_DELETING_IN_PROGRESS = 15 + { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_LABEL, "FEDL_WR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_PS2_LOAD_FAILED = 16 + { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_LABEL, "FES_LOE", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_DELETE_FAILED = 17 + { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_LABEL, "FES_DEE", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, + }, + + // MENUPAGE_DEBUG_MENU = 18 + { "FED_DBG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_RELOADIDE, "FED_RID", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_RELOADIPL, "FED_RIP", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_SETDBGFLAG, "FED_DFL", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_PEDROADGROUPS, "FED_SPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CARROADGROUPS, "FED_SCR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_COLLISIONPOLYS, "FED_SCP", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_PARSEHEAP, "FED_PAH", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_SHOWCULL, "FED_SCZ", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_DEBUGSTREAM, "FED_DSR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_MEMORY_CARD_DEBUG = 19 + { "FEM_MCM", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_REGMEMCARD1, "FEM_RMC", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_TESTFORMATMEMCARD1, "FEM_TFM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_TESTUNFORMATMEMCARD1, "FEM_TUM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CREATEROOTDIR, "FEM_CRD", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CREATELOADICONS, "FEM_CLI", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_FILLWITHGUFF, "FEM_FFF", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_SAVEONLYTHEGAME, "FEM_SOG", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_SAVEGAME, "FEM_STG", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_SAVEGAMEUNDERGTA, "FEM_STS", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CREATECOPYPROTECTED, "FEM_CPD", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_MEMORY_CARD_TEST = 20 + { "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_MULTIPLAYER_MAIN = 21 + { "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_PS2_SAVE_FAILED = 22 + { "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_PS2_SAVE_FAILED_2 = 23 + { "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // Unused in PC but anyway + // MENUPAGE_SAVE = 24 +#ifdef PS2_SAVE_DIALOG + { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_CHANGEMENU, "FESZ_SA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, + MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#else + { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_LABEL, "FES_SCG", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, + MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#endif + + // MENUPAGE_NO_MEMORY_CARD_2 = 25 + { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_CHOOSE_SAVE_SLOT = 26 + { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + MENUACTION_CHANGEMENU, "FEM_SL8", { nil, SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + }, + + // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FESZ_QO", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS }, + MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, + }, + + // MENUPAGE_MULTIPLAYER_MAP = 28 + { "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_MULTIPLAYER_CONNECTION = 29 + { "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_MULTIPLAYER_FIND_GAME = 30 + { "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_MULTIPLAYER_MODE = 31 + { "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_MULTIPLAYER_CREATE = 32 + { "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_MULTIPLAYER_START = 33 + { "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_SKIN_SELECT_OLD = 34 + { "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_CONTROLLER_PC = 35 + { "FET_CTL", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + MENUACTION_CTRLMETHOD, "FET_CME", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, + MENUACTION_KEYBOARDCTRLS,"FET_RDK", { nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS }, +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + MENUACTION_CHANGEMENU, "FEC_JOD", { nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK }, +#endif + MENUACTION_CHANGEMENU, "FET_AMS", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, + MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_CONTROLLER_PC_OLD1 = 36 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_GETKEY, "FEC_PLB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_CWL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_CWR", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_LKT", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_PJP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_PSP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_TLF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_TRG", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_GETKEY, "FEC_CCM", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_CONTROLLER_PC_OLD2 = 37 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, + + }, + + // MENUPAGE_CONTROLLER_PC_OLD3 = 38 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_GETKEY, "FEC_LUP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, + MENUACTION_GETKEY, "FEC_LDN", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, + MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, + MENUACTION_SHOWHEADBOB, "FEC_GSL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_CONTROLLER_PC_OLD4 = 39 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, + + }, + + // MENUPAGE_CONTROLLER_DEBUG = 40 + { "FEC_DBG", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_GETKEY, "FEC_TGD", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, + MENUACTION_GETKEY, "FEC_TDO", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, + MENUACTION_GETKEY, "FEC_TSS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, + MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_OPTIONS = 41 + { "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_CHANGEMENU, "FET_CTL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, + MENUACTION_LOADRADIO, "FET_AUD", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, + MENUACTION_CHANGEMENU, "FET_DIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, +#ifdef GRAPHICS_MENU_OPTIONS + MENUACTION_CHANGEMENU, "FET_GRA", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, +#endif + MENUACTION_CHANGEMENU, "FET_LAN", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, + MENUACTION_PLAYERSETUP, "FET_PSU", { nil, SAVESLOT_NONE, MENUPAGE_SKIN_SELECT }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_EXIT = 42 + { "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_LABEL, "FEQ_SRE", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_DONTCANCEL, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CANCELGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_SAVING_IN_PROGRESS = 43 + { "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FES_WAR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_SAVE_SUCCESSFUL = 44 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FES_SSC", { nil, SAVESLOT_LABEL, MENUPAGE_NONE }, + MENUACTION_RESUME_FROM_SAVEZONE, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, + }, + + // MENUPAGE_DELETING = 45 + { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, + MENUACTION_LABEL, "FED_DLW", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_DELETE_SUCCESS = 46 + { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, + MENUACTION_LABEL, "DEL_FNM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, + }, + + // MENUPAGE_SAVE_FAILED = 47 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, + }, + + // MENUPAGE_LOAD_FAILED = 48 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_LOAD_FAILED_2 = 49 + { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FEC_LUN", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT }, + }, + + // MENUPAGE_FILTER_GAME = 50 + { "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + + }, + + // MENUPAGE_START_MENU = 51 + { "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, + MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS }, + MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT }, + }, + + // MENUPAGE_PAUSE_MENU = 52 + { "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_RESUME, "FEM_RES", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, +#ifdef MENU_MAP + MENUACTION_CHANGEMENU, "FEG_MAP", { nil, SAVESLOT_NONE, MENUPAGE_MAP }, +#endif + MENUACTION_CHANGEMENU, "FEP_STA", { nil, SAVESLOT_NONE, MENUPAGE_STATS }, + MENUACTION_CHANGEMENU, "FEP_BRI", { nil, SAVESLOT_NONE, MENUPAGE_BRIEFS }, + MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS }, + MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT }, + }, + + // MENUPAGE_CHOOSE_MODE = 53 + { "FEN_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_CHANGEMENU, "FET_SP", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, + MENUACTION_INITMP, "FET_MP", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + + // MENUPAGE_SKIN_SELECT = 54 + { "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN }, + }, + + // MENUPAGE_KEYBOARD_CONTROLS = 55 + { "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, + }, + + // MENUPAGE_MOUSE_CONTROLS = 56 + { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_MOUSESENS, "FEC_MSH", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, + MENUACTION_INVVERT, "FEC_IVV", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, + MENUACTION_MOUSESTEER, "FET_MST", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, + // MENUPAGE_MISSION_RETRY = 57 +#ifdef MISSION_REPLAY + + { "M_FAIL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, + MENUACTION_LABEL, "FESZ_RM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS }, + MENUACTION_REJECT_RETRY, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#else + { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + // mission failed, wanna restart page in mobile + }, +#endif + +#ifdef MENU_MAP + // MENUPAGE_MAP + { "FEG_MAP", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + MENUACTION_UNK110, "", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, // to prevent cross/enter to go back + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#endif + +#ifdef GRAPHICS_MENU_OPTIONS + // MENUPAGE_GRAPHICS_SETTINGS + { "FET_GRA", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, + new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), GraphicsGoBack, + + MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, + MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, + VIDEOMODE_SELECTOR + MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + MULTISAMPLING_SELECTOR +#ifdef EXTENDED_COLOURFILTER + POSTFX_SELECTORS +#else + MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, +#endif +#ifdef EXTENDED_PIPELINES + PIPELINES_SELECTOR +#endif + DUALPASS_SELECTOR + MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefGraphics) }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#else + // MENUPAGE_ADVANCED_DISPLAY_SETTINGS + { "FET_ADV", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, + new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil, + + DUALPASS_SELECTOR + CUTSCENE_BORDERS_TOGGLE + FREE_CAM_TOGGLE +#ifdef EXTENDED_COLOURFILTER + POSTFX_SELECTORS +#endif +#ifdef EXTENDED_PIPELINES + PIPELINES_SELECTOR +#endif + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#endif + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + // MENUPAGE_DETECT_JOYSTICK + { "FEC_JOD", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, + new CCustomScreenLayout({MENUSPRITE_MAINMENU, 40, 60, 20, FONT_BANK, FESCREEN_LEFT_ALIGN, false, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil, + + MENUACTION_LABEL, "FEC_JPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CFO_DYNAMIC, "FEC_JDE", { new CCFODynamic(nil, nil, DetectJoystickDraw, nil) }, + MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + }, +#endif + + // MENUPAGE_UNK + { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + + }, + +}; + +#endif +#endif diff --git a/src/core/config.h b/src/core/config.h index 171c6be9..efb09222 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -210,8 +210,8 @@ enum Config { #define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL #define CUTSCENE_BORDERS_SWITCH -//#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) -//#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) +#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) +#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) #define MULTISAMPLING // adds MSAA option #ifdef LIBRW diff --git a/src/core/main.cpp b/src/core/main.cpp index 18ee2dc5..fa82d1e1 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -64,6 +64,7 @@ #include "debugmenu.h" #include "Clock.h" #include "custompipes.h" +#include "frontendoption.h" GlobalScene Scene; @@ -404,6 +405,13 @@ Initialise3D(void *param) DebugMenuInit(); DebugMenuPopulate(); #endif // !DEBUGMENU +#ifdef CUSTOM_FRONTEND_OPTIONS + // Apparently this func. can be run multiple times at the start. + if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) { + // needs stored language and TheText to be loaded, and last TheText reload is at the start of here + CustomFrontendOptionsPopulate(); + } +#endif bool ret = CGame::InitialiseRenderWare(); #ifdef EXTENDED_PIPELINES CustomPipes::CustomPipeInit(); // need Scene.world for this diff --git a/src/core/re3.cpp b/src/core/re3.cpp index a06762f5..aa13ba29 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -1,7 +1,6 @@ #include #define WITHWINDOWS #include "common.h" -#include "platform.h" #include "crossplatform.h" #include "Renderer.h" #include "Credits.h" @@ -16,7 +15,6 @@ #include "Boat.h" #include "Heli.h" #include "Automobile.h" -#include "Ped.h" #include "Console.h" #include "Debug.h" #include "Hud.h" @@ -26,10 +24,8 @@ #include "Radar.h" #include "debugmenu.h" #include "Frontend.h" -#include "Text.h" #include "WaterLevel.h" #include "main.h" -#include "MBlur.h" #include "postfx.h" #include "custompipes.h" @@ -76,388 +72,39 @@ mysrand(unsigned int seed) #ifdef CUSTOM_FRONTEND_OPTIONS #include "frontendoption.h" -#include "Font.h" -void ReloadFrontendOptions(void) -{ - CustomFrontendOptionsPopulate(); -} - -void RestoreDefGraphics(int8 action) { - if (action != FEOPTION_ACTION_SELECT) - return; - - #ifdef PS2_ALPHA_TEST - gPS2alphaTest = false; - #endif - #ifdef MULTISAMPLING - FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0; - #endif - #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those - CMenuManager::m_PrefsFrameLimiter = true; - CMenuManager::m_PrefsVsyncDisp = true; - CMenuManager::m_PrefsVsync = true; - CMenuManager::m_PrefsUseWideScreen = false; - FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode; - #ifdef GTA3_1_1_PATCH - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } - #else - CMBlur::BlurOn = true; - #endif - FrontEndMenuManager.SaveSettings(); - #endif -} - -void RestoreDefDisplay(int8 action) { - if (action != FEOPTION_ACTION_SELECT) - return; - - #ifdef CUTSCENE_BORDERS_SWITCH - CMenuManager::m_PrefsCutsceneBorders = true; - #endif - #ifdef FREE_CAM - TheCamera.bFreeCam = false; - #endif - #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those - CMenuManager::m_PrefsBrightness = 256; - CMenuManager::m_PrefsLOD = 1.2f; - CRenderer::ms_lodDistScale = 1.2f; - CMenuManager::m_PrefsShowSubtitles = true; - FrontEndMenuManager.SaveSettings(); - #endif -} - -#ifdef MULTISAMPLING -void MultiSamplingGoBack() { - FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; -} - -void MultiSamplingButtonPress(int8 action) { - if (action == FEOPTION_ACTION_SELECT) { - if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { - FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel; - _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); - FrontEndMenuManager.SetHelperText(0); - FrontEndMenuManager.SaveSettings(); - } - } else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) { - if (FrontEndMenuManager.m_bGameNotLoaded) { - FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1); - - int i = 0; - int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels(); - while (maxAA != 1) { - i++; - maxAA >>= 1; - } - - if (FrontEndMenuManager.m_nDisplayMSAALevel < 0) - FrontEndMenuManager.m_nDisplayMSAALevel = i; - else if (FrontEndMenuManager.m_nDisplayMSAALevel > i) - FrontEndMenuManager.m_nDisplayMSAALevel = 0; - } - } else if (action == FEOPTION_ACTION_FOCUSLOSS) { - if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { - FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; - FrontEndMenuManager.SetHelperText(3); - } - } -} - -wchar* MultiSamplingDraw(bool *disabled, bool userHovering) { - static wchar unicodeTemp[64]; - if (userHovering) { - if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) { - if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply - FrontEndMenuManager.ResetHelperText(); - } else { - FrontEndMenuManager.SetHelperText(1); - } - } else { - if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { - FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel; - } - } - - if (!FrontEndMenuManager.m_bGameNotLoaded) - *disabled = true; - - switch (FrontEndMenuManager.m_nDisplayMSAALevel) { - case 0: - return TheText.Get("FEM_OFF"); - default: - sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel)); - AsciiToUnicode(gString, unicodeTemp); - return unicodeTemp; - } -} -const char* multisamplingKey = "MultiSampling"; -#endif - -#ifdef MORE_LANGUAGES -void LangPolSelect(int8 action) -{ - if (action == FEOPTION_ACTION_SELECT) { - FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH; - FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; - FrontEndMenuManager.InitialiseChangedLanguageSettings(); - FrontEndMenuManager.SaveSettings(); - } -} - -void LangRusSelect(int8 action) -{ - if (action == FEOPTION_ACTION_SELECT) { - FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN; - FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; - FrontEndMenuManager.InitialiseChangedLanguageSettings(); - FrontEndMenuManager.SaveSettings(); - } -} - -void LangJapSelect(int8 action) -{ - if (action == FEOPTION_ACTION_SELECT) { - FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE; - FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true; - FrontEndMenuManager.InitialiseChangedLanguageSettings(); - FrontEndMenuManager.SaveSettings(); - } -} -#endif - -#ifdef IMPROVED_VIDEOMODE -void ScreenModeChange(int8 displayedValue) -{ - if (displayedValue != FrontEndMenuManager.m_nPrefsWindowed) { - FrontEndMenuManager.m_nPrefsWindowed = displayedValue; - _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution - FrontEndMenuManager.SetHelperText(0); - FrontEndMenuManager.SaveSettings(); - } -} -#endif - -#ifdef FREE_CAM -void FreeCamChange(int8 displayedValue) +void +CustomFrontendOptionsPopulate(void) { - TheCamera.bFreeCam = !!displayedValue; - FrontEndMenuManager.SaveSettings(); + // Moved to an array in MenuScreensCustom.cpp, but APIs are still available. see frontendoption.h } -const char* freeCamKey = "FreeCam"; #endif -#ifdef CUTSCENE_BORDERS_SWITCH -void BorderModeChange(int8 displayedValue) -{ - CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; - FrontEndMenuManager.SaveSettings(); -} -const char* cutsceneBordersKey = "CutsceneBorders"; -#endif +#ifdef LOAD_INI_SETTINGS +#include "ini_parser.hpp" -#ifdef PS2_ALPHA_TEST -void PS2AlphaTestChange(int8 displayedValue) +linb::ini cfg; +int CheckAndReadIniInt(const char *cat, const char *key, int original) { - gPS2alphaTest = !!displayedValue; - FrontEndMenuManager.SaveSettings(); -} -const char* ps2alphaKey = "PS2AlphaTest"; -#endif - -#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS -wchar selectedJoystickUnicode[128]; - -wchar* DetectJoystickDraw(bool* disabled, bool userHovering) { - int numButtons; - int found = -1; - const char *joyname; - if (userHovering) { - for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { - if ((joyname = glfwGetJoystickName(i))) { - const uint8* buttons = glfwGetJoystickButtons(i, &numButtons); - for (int j = 0; j < numButtons; j++) { - if (buttons[j]) { - found = i; - break; - } - } - if (found != -1) - break; - } - } - - if (found != -1 && PSGLOBAL(joy1id) != found) { - if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found) - PSGLOBAL(joy2id) = PSGLOBAL(joy1id); - else - PSGLOBAL(joy2id) = -1; - - strcpy(gSelectedJoystickName, joyname); - PSGLOBAL(joy1id) = found; - } - } - if (PSGLOBAL(joy1id) == -1) - AsciiToUnicode("Not found", selectedJoystickUnicode); - else - AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode); + const char *value = (cfg.get(cat, key, "").c_str()); + if (value && value[0] != '\0') + return atoi(value); - return selectedJoystickUnicode; + return original; } -#endif -// Important: Make sure to read the warnings/informations in frontendoption.h!! -// If you will hardcode any text, please use AllocUnicode! wchar_t size differs between platforms -void -CustomFrontendOptionsPopulate(void) +float CheckAndReadIniFloat(const char *cat, const char *key, float original) { - RemoveCustomFrontendOptions(); // if exist - - // -- Graphics/display seperation preperation starts - don't add options in here! -#ifdef GRAPHICS_MENU_OPTIONS - int graphicsMenu = FrontendScreenAdd("FET_GRA", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20, - FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true); - - int newDisplayMenu = FrontendScreenAdd("FET_DIS", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20, - FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true); - - FrontendOptionSetCursor(MENUPAGE_OPTIONS, 2, true); - FrontendOptionAddRedirect(TheText.Get("FET_DIS"), newDisplayMenu, 0); - FrontendOptionSetCursor(MENUPAGE_OPTIONS, 3); - FrontendOptionAddRedirect(TheText.Get("FET_GRA"), graphicsMenu, 0); - -#define SWITCH_TO_GRAPHICS_MENU FrontendOptionSetCursor(graphicsMenu, -1); -#define SWITCH_TO_DISPLAY_MENU FrontendOptionSetCursor(newDisplayMenu, -1); -#define CLONE_OPTION(a, b, c, d) FrontendOptionAddBuiltinAction(a, b, c, d); -#define ADD_BACK FrontendOptionAddBackButton(TheText.Get("FEDS_TB")); -#define ADD_RESTORE_DEFAULTS(a) FrontendOptionAddDynamic(TheText.Get("FET_DEF"), nil, nil, a, nil); -#else - int advancedDisplayMenu = FrontendScreenAdd("FET_ADV", MENUSPRITE_MAINMENU, MENUPAGE_DISPLAY_SETTINGS, 50, 0, 20, - FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true); - bool movedToAdvMenu = false; - -#define SWITCH_TO_GRAPHICS_MENU \ - if (GetNumberOfMenuOptions(MENUPAGE_DISPLAY_SETTINGS) >= 12) { \ - FrontendOptionSetCursor(advancedDisplayMenu, -1); \ - movedToAdvMenu = true; \ - } else { \ - FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3); \ - } - -#define SWITCH_TO_DISPLAY_MENU SWITCH_TO_GRAPHICS_MENU -#define CLONE_OPTION(a, b, c, d) -#define ADD_BACK -#define ADD_RESTORE_DEFAULTS(a) -#endif - // -- Graphics/display seperation preperation end - - const wchar* off_on[] = { TheText.Get("FEM_OFF"), TheText.Get("FEM_ON") }; + const char *value = (cfg.get(cat, key, "").c_str()); + if (value && value[0] != '\0') + return atof(value); -#ifdef MORE_LANGUAGES - FrontendOptionSetCursor(MENUPAGE_LANGUAGE_SETTINGS, -2); - FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, nil, LangPolSelect, nil); - FrontendOptionAddDynamic(TheText.Get("FEL_RUS"), nil, nil, LangRusSelect, nil); - FrontendOptionAddDynamic(TheText.Get("FEL_JAP"), nil, nil, LangJapSelect, nil); -#endif - -#ifdef MENU_MAP - FrontendOptionSetCursor(MENUPAGE_PAUSE_MENU, 2); - FrontendOptionAddRedirect(TheText.Get("FEG_MAP"), MENUPAGE_MAP); -#endif - - // -- Start of graphics menu - add options in display order! - - SWITCH_TO_GRAPHICS_MENU - CLONE_OPTION(TheText.Get("FED_RES"), MENUACTION_SCREENRES, nil, nil); - CLONE_OPTION(TheText.Get("FED_WIS"), MENUACTION_WIDESCREEN, nil, nil) - -#ifdef IMPROVED_VIDEOMODE - const wchar* screenModes[] = { TheText.Get("FED_FLS"), TheText.Get("FED_WND") }; - // Storing isn't enabled because it's handled in Frontend - FrontendOptionAddSelect(TheText.Get("FEM_SCF"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil); -#endif - - CLONE_OPTION(TheText.Get("FEM_VSC"), MENUACTION_FRAMESYNC, nil, nil); - CLONE_OPTION(TheText.Get("FEM_FRM"), MENUACTION_FRAMELIMIT, nil, nil); - -#ifdef MULTISAMPLING - SWITCH_TO_GRAPHICS_MENU - FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, multisamplingKey); -#endif - - CLONE_OPTION(TheText.Get("FED_TRA"), MENUACTION_TRAILS, nil, nil); - -#ifdef PS2_ALPHA_TEST - SWITCH_TO_GRAPHICS_MENU - FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, ps2alphaKey); -#endif - - ADD_RESTORE_DEFAULTS(RestoreDefGraphics) - ADD_BACK - - // ---- End of Graphics Menu ---- - - // -- Start of Display menu - add options in display order! - - SWITCH_TO_DISPLAY_MENU - CLONE_OPTION(TheText.Get("FED_BRI"), MENUACTION_BRIGHTNESS, nil, nil); - CLONE_OPTION(TheText.Get("FEM_LOD"), MENUACTION_DRAWDIST, nil, nil); - -#ifdef CUTSCENE_BORDERS_SWITCH - SWITCH_TO_DISPLAY_MENU - FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, cutsceneBordersKey); -#endif - -#ifdef FREE_CAM - SWITCH_TO_DISPLAY_MENU - FrontendOptionAddSelect(TheText.Get("FEC_FRC"), off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, freeCamKey); -#endif - - CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil); - - // Add link to advanced graphics menu if it's filled. -#ifndef GRAPHICS_MENU_OPTIONS - if (movedToAdvMenu) { - FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3); - FrontendOptionAddRedirect(TheText.Get("FET_ADV"), advancedDisplayMenu, 0); - - FrontendOptionSetCursor(advancedDisplayMenu, -1); - FrontendOptionAddBackButton(TheText.Get("FEDS_TB")); - } -#endif - - ADD_RESTORE_DEFAULTS(RestoreDefDisplay) - ADD_BACK - -#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS - int detectJoystickMenu = FrontendScreenAdd("FEC_JOD", MENUSPRITE_MAINMENU, MENUPAGE_CONTROLLER_PC, 40, 60, 20, - FONT_BANK, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, false); - - FrontendOptionSetCursor(detectJoystickMenu, 0); - - FrontendOptionAddBuiltinAction(TheText.Get("FEC_JPR"), MENUACTION_LABEL, nil, nil); - FrontendOptionAddDynamic(TheText.Get("FEC_JDE"), DetectJoystickDraw, nil, nil, nil); - FrontendOptionAddBackButton(TheText.Get("FEDS_TB")); - - FrontendOptionSetCursor(MENUPAGE_CONTROLLER_PC, 2); - FrontendOptionAddRedirect(TheText.Get("FEC_JOD"), detectJoystickMenu, 1); -#endif + return original; } -#endif -#ifdef LOAD_INI_SETTINGS -#include "ini_parser.hpp" void LoadINISettings() { - linb::ini cfg; cfg.load_file("re3.ini"); - char defaultStr[4]; #ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS // Written by assuming the codes below will run after _InputInitialiseJoys(). @@ -491,28 +138,43 @@ void LoadINISettings() #endif #ifdef CUSTOM_FRONTEND_OPTIONS - for (int i = 0; i < numCustomFrontendOptions; i++) { - FrontendOption& option = customFrontendOptions[i]; - if (option.save) { - // CFO only supports saving uint8 right now - sprintf(defaultStr, "%u", *option.value); - option.lastSavedValue = option.displayedValue = *option.value = atoi(cfg.get("FrontendOptions", option.save, defaultStr).c_str()); + for (int i = 0; i < MENUPAGES; i++) { + for (int j = 0; j < NUM_MENUROWS; j++) { + CMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j]; + if (option.m_Action == MENUACTION_NOTHING) + break; + + // CFO check + if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) { + // CFO only supports saving uint8 right now + *option.m_CFO->value = CheckAndReadIniInt("FrontendOptions", option.m_CFO->save, *option.m_CFO->value); + if (option.m_Action == MENUACTION_CFO_SELECT) { + option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue = *option.m_CFO->value; + } + } } } #endif #ifdef NO_ISLAND_LOADING - sprintf(defaultStr, "%u", CMenuManager::m_PrefsIslandLoading); - CMenuManager::m_PrefsIslandLoading = atoi(cfg.get("FrontendOptions", "NoIslandLoading", defaultStr).c_str()); + CMenuManager::m_PrefsIslandLoading = CheckAndReadIniInt("FrontendOptions", "NoIslandLoading", CMenuManager::m_PrefsIslandLoading); CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading; #endif +#ifdef EXTENDED_COLOURFILTER + CPostFX::Intensity = CheckAndReadIniFloat("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity); +#endif +#ifdef EXTENDED_PIPELINES + CustomPipes::VehicleShininess = CheckAndReadIniFloat("CustomPipesValues", "NeoVehicleShininess", CustomPipes::VehicleShininess); + CustomPipes::VehicleSpecularity = CheckAndReadIniFloat("CustomPipesValues", "NeoVehicleSpecularity", CustomPipes::VehicleSpecularity); + CustomPipes::RimlightMult = CheckAndReadIniFloat("CustomPipesValues", "RimlightMult", CustomPipes::RimlightMult); + CustomPipes::LightmapMult = CheckAndReadIniFloat("CustomPipesValues", "LightmapMult", CustomPipes::LightmapMult); + CustomPipes::GlossMult = CheckAndReadIniFloat("CustomPipesValues", "GlossMult", CustomPipes::GlossMult); +#endif } void SaveINISettings() { - linb::ini cfg; - cfg.load_file("re3.ini"); bool changed = false; char temp[4]; @@ -523,13 +185,18 @@ void SaveINISettings() } #endif #ifdef CUSTOM_FRONTEND_OPTIONS - for (int i = 0; i < numCustomFrontendOptions; i++) { - FrontendOption &option = customFrontendOptions[i]; - if (option.save) { - if (atoi(cfg.get("FrontendOptions", option.save, "xxx").c_str()) != *option.value) { // if .ini doesn't have that key compare with xxx, so we can add it - changed = true; - sprintf(temp, "%u", *option.value); - cfg.set("FrontendOptions", option.save, temp); + for (int i = 0; i < MENUPAGES; i++) { + for (int j = 0; j < NUM_MENUROWS; j++) { + CMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j]; + if (option.m_Action == MENUACTION_NOTHING) + break; + + if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) { + if (atoi(cfg.get("FrontendOptions", option.m_CFO->save, "xxx").c_str()) != *option.m_CFO->value) { // if .ini doesn't have that key compare with xxx, so we can add it + changed = true; + sprintf(temp, "%u", *option.m_CFO->value); + cfg.set("FrontendOptions", option.m_CFO->save, temp); + } } } } @@ -888,9 +555,6 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); DebugMenuAddVarBool8("Debug", "Script Heli On", &CHeli::ScriptHeliOn, nil); -#ifdef CUSTOM_FRONTEND_OPTIONS - DebugMenuAddCmd("Debug", "Reload custom frontend options", ReloadFrontendOptions); -#endif DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp index 88a930a9..a3c4b9e3 100644 --- a/src/extras/frontendoption.cpp +++ b/src/extras/frontendoption.cpp @@ -1,19 +1,13 @@ #include "common.h" #ifdef CUSTOM_FRONTEND_OPTIONS -#include "frontendoption.h" +#include "Frontend.h" #include "Text.h" -int numCustomFrontendOptions = 0; -FrontendOption *customFrontendOptions; +int lastOgScreen = MENUPAGES; // means no new pages +int numCustomFrontendOptions = 0; int numCustomFrontendScreens = 0; -FrontendScreen* customFrontendScreens; - -int numFrontendOptionReplacements = 0; -CMenuScreen::CMenuEntry* frontendOptionReplacements; - -int lastOgScreen = MENUPAGES; // means no new pages int optionCursor = -2; int currentMenu; @@ -32,8 +26,7 @@ void GoBack(bool fadeIn) { int screen = !FrontEndMenuManager.m_bGameNotLoaded ? aScreens[FrontEndMenuManager.m_nCurrScreen].m_PreviousPage[1] : aScreens[FrontEndMenuManager.m_nCurrScreen].m_PreviousPage[0]; - int option = !FrontEndMenuManager.m_bGameNotLoaded ? - aScreens[FrontEndMenuManager.m_nCurrScreen].m_ParentEntry[1] : aScreens[FrontEndMenuManager.m_nCurrScreen].m_ParentEntry[0]; + int option = FrontEndMenuManager.GetPreviousPageOption(); FrontEndMenuManager.ThingsToDoBeforeGoingBack(); @@ -58,7 +51,7 @@ GetLastMenuScreen() { int8 page = -1; for (int i = 0; i < MENUPAGES; i++) { - if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].unk == 0) + if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].m_PreviousPage[0] == MENUPAGE_NONE) break; ++page; @@ -66,89 +59,23 @@ GetLastMenuScreen() return page; } -// Used before populating options, but effective in InitialiseChangedLanguageSettings and debugmenu -void -RemoveCustomFrontendOptions() -{ - if (numCustomFrontendOptions != 0) { - - for (int i = 0; i < MENUPAGES; i++) { - for (int j = 0; j < NUM_MENUROWS; j++) { - if (aScreens[i].m_aEntries[j].m_SaveSlot == SAVESLOT_CFO) { - int ogOptionId = customFrontendOptions[aScreens[i].m_aEntries[j].m_TargetMenu].ogOptionId; - - if (customFrontendOptions[aScreens[i].m_aEntries[j].m_TargetMenu].type == FEOPTION_SELECT) - free(customFrontendOptions[aScreens[i].m_aEntries[j].m_TargetMenu].rightTexts); - - if (ogOptionId == -1) { - int k; - for (k = j; k < NUM_MENUROWS - 1; k++) { - memcpy(&aScreens[i].m_aEntries[k], &aScreens[i].m_aEntries[k + 1], sizeof(CMenuScreen::CMenuEntry)); - } - aScreens[i].m_aEntries[k].m_Action = MENUACTION_NOTHING; - aScreens[i].m_aEntries[k].m_SaveSlot = SAVESLOT_NONE; - aScreens[i].m_aEntries[k].m_EntryName[0] = '\0'; - j--; - } else { - memcpy(&aScreens[i].m_aEntries[j], &frontendOptionReplacements[ogOptionId], sizeof(CMenuScreen::CMenuEntry)); - } - } - } - } - free(customFrontendOptions); - numCustomFrontendOptions = 0; - - if (numFrontendOptionReplacements != 0) { - free(frontendOptionReplacements); - numFrontendOptionReplacements = 0; - } - } - - if (numCustomFrontendScreens == 0) - return; - - for (int i = 0; i < MENUPAGES; i++) { - if (i > lastOgScreen) { - aScreens[i].m_ScreenName[0] = '\0'; - aScreens[i].unk = 0; - } - } - free(customFrontendScreens); - numCustomFrontendScreens = 0; - lastOgScreen = MENUPAGES; -} - -int8 RegisterNewScreen(const char *name, int prevPage) +int8 RegisterNewScreen(const char *name, int prevPage, ReturnPrevPageFunc returnPrevPageFunc) { if (lastOgScreen == MENUPAGES) lastOgScreen = GetLastMenuScreen(); numCustomFrontendScreens++; - if (numCustomFrontendScreens == 1) - customFrontendScreens = (FrontendScreen*)malloc(5 * sizeof(FrontendScreen)); - else if (numCustomFrontendScreens % 5 == 1) - customFrontendScreens = (FrontendScreen*)realloc(customFrontendScreens, (numCustomFrontendScreens + 4) * sizeof(FrontendScreen)); - - assert(customFrontendScreens != nil && "Custom frontend screens can't be allocated"); - int id = lastOgScreen + numCustomFrontendScreens; assert(id < MENUPAGES && "No room for new custom frontend screens! Increase MENUPAGES"); strncpy(aScreens[id].m_ScreenName, name, 8); aScreens[id].m_PreviousPage[0] = aScreens[id].m_PreviousPage[1] = prevPage; - aScreens[id].unk = 1; + aScreens[id].returnPrevPageFunc = returnPrevPageFunc; return id; } int8 RegisterNewOption() { numCustomFrontendOptions++; - if (numCustomFrontendOptions == 1) - customFrontendOptions = (FrontendOption*)malloc(5 * sizeof(FrontendOption)); - else if (numCustomFrontendOptions % 5 == 1) - customFrontendOptions = (FrontendOption*)realloc(customFrontendOptions, (numCustomFrontendOptions + 4) * sizeof(FrontendOption)); - - assert(customFrontendOptions != nil && "Custom frontend options can't be allocated"); - uint8 numOptions = GetNumberOfMenuOptions(currentMenu); uint8 curIdx; if (optionCursor < 0) { @@ -159,30 +86,11 @@ int8 RegisterNewOption() if (!optionOverwrite) { if (aScreens[currentMenu].m_aEntries[curIdx].m_Action != MENUACTION_NOTHING) { for (int i = numOptions - 1; i >= curIdx; i--) { - memcpy(&aScreens[currentMenu].m_aEntries[i + 1], &aScreens[currentMenu].m_aEntries[i], sizeof(CMenuScreen::CMenuEntry)); + memcpy(&aScreens[currentMenu].m_aEntries[i + 1], &aScreens[currentMenu].m_aEntries[i], sizeof(CMenuScreenCustom::CMenuEntry)); } } } optionCursor++; - - if (optionOverwrite) { - numFrontendOptionReplacements++; - if (numFrontendOptionReplacements == 1) - frontendOptionReplacements = (CMenuScreen::CMenuEntry*)malloc(5 * sizeof(CMenuScreen::CMenuEntry)); - else if (numFrontendOptionReplacements % 5 == 1) - frontendOptionReplacements = (CMenuScreen::CMenuEntry*)realloc(frontendOptionReplacements, (numFrontendOptionReplacements + 4) * sizeof(CMenuScreen::CMenuEntry)); - - memcpy(&frontendOptionReplacements[numFrontendOptionReplacements - 1], &aScreens[currentMenu].m_aEntries[curIdx], sizeof(CMenuScreen::CMenuEntry)); - customFrontendOptions[numCustomFrontendOptions - 1].ogOptionId = numFrontendOptionReplacements - 1; - } else { - customFrontendOptions[numCustomFrontendOptions - 1].ogOptionId = -1; - } - customFrontendOptions[numCustomFrontendOptions - 1].screen = currentMenu; - - aScreens[currentMenu].m_aEntries[curIdx].m_Action = MENUACTION_TRIGGERFUNC; - aScreens[currentMenu].m_aEntries[curIdx].m_SaveSlot = SAVESLOT_CFO; - aScreens[currentMenu].m_aEntries[curIdx].m_TargetMenu = numCustomFrontendOptions - 1; - aScreens[currentMenu].m_aEntries[curIdx].m_EntryName[0] = 1; // just something to fool it return curIdx; } @@ -193,110 +101,78 @@ void FrontendOptionSetCursor(int screen, int8 option, bool overwrite) optionOverwrite = overwrite; } -void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc) { +void FrontendOptionAddBuiltinAction(const char* gxtKey, int action, int targetMenu, int saveSlot) { int8 screenOptionOrder = RegisterNewOption(); - FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; + CMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder]; - // To fool the Frontend, we will still display the text passed via first param. + // We can't use custom text on those :shrug: switch (action) { case MENUACTION_SCREENRES: - strcpy(aScreens[currentMenu].m_aEntries[screenOptionOrder].m_EntryName, "FED_RES"); + strcpy(option.m_EntryName, "FED_RES"); break; case MENUACTION_AUDIOHW: - strcpy(aScreens[currentMenu].m_aEntries[screenOptionOrder].m_EntryName, "FEA_3DH"); + strcpy(option.m_EntryName, "FEA_3DH"); + break; + default: + strncpy(option.m_EntryName, gxtKey, 8); break; } - aScreens[currentMenu].m_aEntries[screenOptionOrder].m_Action = action; - option.type = FEOPTION_BUILTIN_ACTION; - option.buttonPressFunc = buttonPressFunc; - TextCopy(option.leftText, leftText); - option.screenOptionOrder = screenOptionOrder; - option.returnPrevPageFunc = returnPrevPageFunc; - option.save = nil; -} - -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName) -{ - int8 screenOptionOrder = RegisterNewOption(); - - FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; - option.type = FEOPTION_SELECT; - TextCopy(option.leftText, leftText); - option.rightTexts = (wchar**)malloc(numRightTexts * sizeof(wchar*)); - memcpy(option.rightTexts, rightTexts, numRightTexts * sizeof(wchar*)); - option.numRightTexts = numRightTexts; - option.value = var; - option.displayedValue = *var; - option.lastSavedValue = *var; - option.save = saveName; - option.onlyApplyOnEnter = onlyApplyOnEnter; - option.changeFunc = changeFunc; - option.screenOptionOrder = screenOptionOrder; - option.returnPrevPageFunc = returnPrevPageFunc; + option.m_Action = action; + option.m_SaveSlot = saveSlot; + option.m_TargetMenu = targetMenu; } -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName) -{ +void FrontendOptionAddSelect(const char* gxtKey, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName) +{ int8 screenOptionOrder = RegisterNewOption(); - FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; - option.type = FEOPTION_DYNAMIC; - option.drawFunc = drawFunc; - option.buttonPressFunc = buttonPressFunc; - TextCopy(option.leftText, leftText); - option.value = var; - option.save = saveName; - option.screenOptionOrder = screenOptionOrder; - option.returnPrevPageFunc = returnPrevPageFunc; -} - -void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption, bool fadeIn) -{ - int8 screenOptionOrder = RegisterNewOption(); - - FrontendOption &option = customFrontendOptions[numCustomFrontendOptions - 1]; - option.type = FEOPTION_REDIRECT; - option.to = to; - option.option = selectedOption; - option.fadeIn = fadeIn; - TextCopy(option.leftText, text); - option.screenOptionOrder = screenOptionOrder; - option.returnPrevPageFunc = nil; - option.save = nil; + CMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder]; + option.m_Action = MENUACTION_CFO_SELECT; + strncpy(option.m_EntryName, gxtKey, 8); + option.m_CFOSelect = new CCFOSelect(); + option.m_CFOSelect->rightTexts = (char**)malloc(numRightTexts * sizeof(char*)); + memcpy(option.m_CFOSelect->rightTexts, rightTexts, numRightTexts * sizeof(char*)); + option.m_CFOSelect->numRightTexts = numRightTexts; + option.m_CFOSelect->value = var; + if (var) { + option.m_CFOSelect->displayedValue = *var; + option.m_CFOSelect->lastSavedValue = *var; + } + option.m_CFOSelect->save = saveName; + option.m_CFOSelect->onlyApplyOnEnter = onlyApplyOnEnter; + option.m_CFOSelect->changeFunc = changeFunc; } -void FrontendOptionAddBackButton(const wchar* text, bool fadeIn) +void FrontendOptionAddDynamic(const char* gxtKey, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName) { int8 screenOptionOrder = RegisterNewOption(); - FrontendOption& option = customFrontendOptions[numCustomFrontendOptions - 1]; - option.type = FEOPTION_GOBACK; - option.fadeIn = fadeIn; - TextCopy(option.leftText, text); - option.screenOptionOrder = screenOptionOrder; - option.returnPrevPageFunc = nil; - option.save = nil; + CMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder]; + option.m_Action = MENUACTION_CFO_DYNAMIC; + strncpy(option.m_EntryName, gxtKey, 8); + option.m_CFODynamic = new CCFODynamic(); + option.m_CFODynamic->drawFunc = drawFunc; + option.m_CFODynamic->buttonPressFunc = buttonPressFunc; + option.m_CFODynamic->value = var; + option.m_CFODynamic->save = saveName; } uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, int8 font, float fontScaleX, float fontScaleY, int8 alignment, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc) { - uint8 screenOrder = RegisterNewScreen(gxtKey, prevPage); - - FrontendScreen &screen = customFrontendScreens[numCustomFrontendScreens - 1]; - screen.id = screenOrder; - screen.sprite = sprite; - screen.prevPage = prevPage; - strncpy(screen.name, gxtKey, 8); - screen.columnWidth = columnWidth; - screen.headerHeight = headerHeight; - screen.lineHeight = lineHeight; - screen.font = font; - screen.fontScaleX = fontScaleX; - screen.fontScaleY = fontScaleY; - screen.alignment = alignment; - screen.returnPrevPageFunc = returnPrevPageFunc; + uint8 screenOrder = RegisterNewScreen(gxtKey, prevPage, returnPrevPageFunc); + + CCustomScreenLayout *screen = new CCustomScreenLayout(); + aScreens[screenOrder].layout = screen; + screen->sprite = sprite; + screen->columnWidth = columnWidth; + screen->headerHeight = headerHeight; + screen->lineHeight = lineHeight; + screen->font = font; + screen->fontScaleX = fontScaleX; + screen->fontScaleY = fontScaleY; + screen->alignment = alignment; return screenOrder; } diff --git a/src/extras/frontendoption.h b/src/extras/frontendoption.h index dac6be62..19340b20 100644 --- a/src/extras/frontendoption.h +++ b/src/extras/frontendoption.h @@ -2,47 +2,23 @@ #include "common.h" #ifdef CUSTOM_FRONTEND_OPTIONS -#include "Frontend.h" - -// Warning: -// All of the code relies on that you won't use more then NUM_MENUROWS(18) options on one page. -// Also congrats if you can make 18 options visible at once. - -// About texts: -// All text parameters accept wchar(including hardcoded wchar* and TheText.Get) -// except FrontendScreenAdd(it's char[8] GXT key by the design of Frontend). -// All texts reload if custom options reloaded too, which includes language changes and via live reload feature in debug menu! - -// Execute direction: -// All of the calls below eventually manipulate the aScreens array, so keep in mind to add/replace options in order, -// i.e. don't set cursor to 8 first and then 3. - -// Live reload: -// You can add/change/undo the new options in-game if you use VS. Change what you want, build the changed bits via "Edit and Continue", -// and hit the "Reload custom frontend options" from debug menu. Or call CustomFrontendOptionsPopulate() from somewhere else. +// ! There are 2 ways to use CFO, +// 1st; by adding a new option to the array in MenuScreensCustom.cpp and passing attributes/CBs to it +// 2nd; by calling the functions listed at the bottom of this file. // -- Option types // // Static/select: You allocate the variable, pass it to function and game sets it from user input among the strings given to function, -// then you can handle ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately) -// and ReturnPrevPageFunc optionally. You can store the option in an INI file if you pass the key(as a char array) to corresponding parameter. +// optionally you can add post-change event via ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately) +// You can store the option in an INI file if you pass the key(as a char array) to corresponding parameter. // // Dynamic: Passing variable to function is only needed if you want to store it, otherwise you should do // all the operations with ButtonPressFunc, this includes allocating the variable. // Left-side text is passed while creating and static, but ofc right-side text is dynamic - -// you should return it in DrawFunc, which is called on every draw. ReturnPrevPageFunc is also here if needed. -// -// Redirect: Redirection to another screen. selectedOption parameter is the highlighted option user will see after the redirection. +// you should return it in DrawFunc, which is called on every draw. // // Built-in action: As the name suggests, any action that game has built-in. But as an extra you can set the option text, -// and can be informed on button press/focus loss via buttonPressFunc. ReturnPrevPageFunc is also here. - -#define FEOPTION_SELECT 0 -#define FEOPTION_DYNAMIC 1 -#define FEOPTION_REDIRECT 2 -#define FEOPTION_GOBACK 3 -#define FEOPTION_BUILTIN_ACTION 4 // -- Returned via ButtonPressFunc() action param. #define FEOPTION_ACTION_LEFT 0 @@ -61,7 +37,7 @@ typedef void (*ReturnPrevPageFunc)(); // for static options -typedef void (*ChangeFunc)(int8 displayedValue); // called before updating the value. +typedef void (*ChangeFunc)(int8 before, int8 after); // called after updating the value. // only called on enter if onlyApplyOnEnter set, otherwise called on every value change // for dynamic options @@ -69,71 +45,11 @@ typedef wchar* (*DrawFunc)(bool* disabled, bool userHovering); // you must retur // you can also set *disabled if you want to gray it out. typedef void (*ButtonPressFunc)(int8 action); // see FEOPTION_ACTIONs above -struct FrontendScreen -{ - int id; - char name[8]; - eMenuSprites sprite; - int prevPage; - int columnWidth; - int headerHeight; - int lineHeight; - int8 font; - float fontScaleX; - float fontScaleY; - int8 alignment; - bool showLeftRightHelper; - ReturnPrevPageFunc returnPrevPageFunc; -}; - -struct FrontendOption -{ - int8 type; - int8 screenOptionOrder; - int32 screen; - wchar leftText[128]; - ReturnPrevPageFunc returnPrevPageFunc; - int8* value; - int8 displayedValue; // only if onlyApplyOnEnter enabled for now - const char* save; - int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor - - union { - // Only for dynamic / built-in action - struct { - DrawFunc drawFunc; - ButtonPressFunc buttonPressFunc; - }; - - // Only for static/select - struct { - wchar** rightTexts; - int8 numRightTexts; - bool onlyApplyOnEnter; - ChangeFunc changeFunc; - int8 lastSavedValue; // only if onlyApplyOnEnter enabled - }; - - // Only for redirect - struct { - int to; - int8 option; - bool fadeIn; - }; - }; -}; - // -- Internal things -void RemoveCustomFrontendOptions(); void CustomFrontendOptionsPopulate(); - extern int lastOgScreen; // for reloading - extern int numCustomFrontendOptions; -extern FrontendOption* customFrontendOptions; - extern int numCustomFrontendScreens; -extern FrontendScreen* customFrontendScreens; // -- To be used in ButtonPressFunc / ChangeFunc(this one would be weird): void ChangeScreen(int screen, int option = 0, bool fadeIn = true); @@ -141,6 +57,21 @@ void GoBack(bool fadeIn = true); uint8 GetNumberOfMenuOptions(int screen); +// !!! We're now moved to MenuScreensCustom.cpp, which houses an array that keeps all original+custom options. +// But you can still use the APIs below, and manipulate aScreens while in game. + +// Limits: +// The code relies on that you won't use more then NUM_MENUROWS(18) options on one page, and won't exceed the MENUPAGES of pages. +// Also congrats if you can make 18 options visible at once. + +// Texts: +// All text parameters accept char[8] GXT key. + +// Execute direction: +// All of the calls below eventually manipulate the aScreens array, so keep in mind to add/replace options in order, +// i.e. don't set cursor to 8 first and then 3. + + // -- Placing the cursor to append/overwrite option // // Done via FrontendOptionSetCursor(screen, position, overwrite = false), parameters explained below: @@ -152,11 +83,9 @@ uint8 GetNumberOfMenuOptions(int screen); 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 wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc); -void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName = nil); -void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, const char* saveName = nil); -void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true); -void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true); +void FrontendOptionAddBuiltinAction(const char* gxtKey, int action, int targetMenu = MENUPAGE_NONE, int saveSlot = SAVESLOT_NONE); +void FrontendOptionAddSelect(const char* gxtKey, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveName = nil); +void FrontendOptionAddDynamic(const char* gxtKey, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveName = nil); uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, int8 font, float fontScaleX, float fontScaleY, int8 alignment, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc = nil); #endif -- cgit v1.2.3 From e97366c023ee81d0feefa131ed38c77131d29f40 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 29 Oct 2020 19:11:47 +0100 Subject: implemented extra model flags for backface culling and alpha test from mobile --- src/core/FileLoader.cpp | 344 ++++++++++++++++++++++++++++++++++++++++++ src/core/config.h | 3 + src/extras/custompipes.cpp | 2 +- src/modelinfo/BaseModelInfo.h | 8 + src/render/Renderer.cpp | 29 ++++ src/rw/RwHelper.cpp | 24 ++- src/rw/RwHelper.h | 2 + src/rw/VisibilityPlugins.cpp | 9 ++ 8 files changed, 418 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index ff50575f..aadafc29 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "main.h" +#include "General.h" #include "Quaternion.h" #include "ModelInfo.h" #include "ModelIndices.h" @@ -449,6 +450,334 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id) return true; } +#ifdef HARDCODED_MODEL_FLAGS +char *DoubleSidedNames[] = { + "chnabankdoor", + "Security_Hut", + "Hospital_Sub", + "phonebooth1", + "trafficlight1", + "sub_roadbarrier", + "redlightbuild09", + "doublestreetlght1", + "doc_shedbig31", + "com_land_128", + "garage7", + "proj_garage01", + "buildingground2", + "buildingground3", + "ch_roof_kb", + "overpassind", + "casino", + "ind_land100", + "fuckedup_skewlbus", + "Police_Station_ind", + "flagsitaly", + "sidebarrier_gaz1", + "bar_barrier12", + "bar_barrier10b", + "sidebarrier_gaz2", + "doc_shedbig3", + "doc_shedbig4", + "verticalift_bridge", + "verticalift_bridg2", + "usdcrdlrbuild01", + "apairporthanger", + "apairporthangerA", + "porthangerclosed", + "redlightbuild13", + "doc_rave", + "const_woodfence", + "const_woodfence2", + "const_woodfence3", + "subfraightback01", + "subfraightback02", + "subfraightback03", + "subfraightback04", + "subind_build03", + "chinabanner1", + "chinabanner2", + "chinabanner3", + "chinabanner4", + "Pumpfirescape", + "Pumphouse", + "amcounder", + "barrel1", + "barrel2", + "barrel3", + "barrel4", + "com_1way50", + "com_1way20", + "overpasscom01", + "overpasscom02", + "overpasscom03", + "overpasscom04", + "overpass_comse", + "newdockbuilding", + "newdockbuilding2", + "newdockbuilding", + "policeballhall", + "fuzballdoor", + "ind_land106", + "PoliceBallSigns", + "amcoudet", + "rustship_structure", + "impexpgrgesub", + "ind_land128", + "fshfctry_dstryd", + "railtrax_bentl", + "railtrax_lo4b", + "railtrax_straight", + "railtrax_bentrb", + "railtrax_skew", + "newtrackaaa", + "railtrax_skew5", + // these they forgot: + "railtrax_skewp", + "railtrax_ske2b", + "railtrax_strtshort", + "railtrax_2b", + "railtrax_straightss", + "railtrax_bentr", + "" +}; +char *TreeNames[] = { + "coast_treepatch", + "comparknewtrees", + "comtreepatchprk", + "condotree01", + "condotree1", + "indatree03", + "indtreepatch5", + "indtreepatch06f", + "new_carprktrees", + "new_carprktrees4", + "newcoasttrees1", + "newcoasttrees2", + "newcoasttrees3", + "newtreepatch_sub", + "newtrees1_sub", + "newunitrepatch", + "pinetree_narrow", + "pinetree_wide", + "treencom2", + "treepatch", + "treepatch01_sub", + "treepatch02_sub", + "treepatch2", + "treepatch2b", + "treepatch03", + "treepatch03_sub", + "treepatch04_sub", + "treepatch05_sub", + "treepatch06_sub", + "treepatch07_sub", + "treepatch08_sub", + "treepatch09_sub", + "treepatch10_sub", + "treepatch11_sub", + "treepatch12_sub", + "treepatch13_sub", + "treepatch14_sub", + "treepatch15_sub", + "treepatch16_sub", + "treepatch17_sub", + "treepatch18_sub", + "treepatch19_sub", + "treepatch20_sub", + "treepatch21_sub", + "treepatch22_sub", + "treepatch23_sub", + "treepatch24_sub", + "treepatch25_sub", + "treepatch26_sub", + "treepatch27_sub", + "treepatch28_sub", + "treepatch29_sub", + "treepatch30_sub", + "treepatch31_sub", + "treepatch32_sub", + "treepatch33_sub", + "treepatch34_sub", + "treepatch35_sub", + "treepatch69", + "treepatch152_sub", + "treepatch153_sub", + "treepatch171_sub", + "treepatch172_sub", + "treepatch173_sub", + "treepatch212_sub", + "treepatch213_sub", + "treepatch214_sub", + "treepatcha", + "treepatchb", + "treepatchcomtop1", + "treepatchd", + "treepatche", + "treepatchh", + "treepatchindaa2", + "treepatchindnew", + "treepatchindnew2", + "treepatchk", + "treepatchkb4", + "treepatchkb5", + "treepatchkb6", + "treepatchkb7", + "treepatchkb9", + "treepatchl", + "treepatchm", + "treepatchnew_sub", + "treepatchttwrs", + "treesuni1", + "trepatchindaa1", + "veg_bush2", + "veg_bush14", + "veg_tree1", + "veg_tree3", + "veg_treea1", + "veg_treea3", + "veg_treeb1", + "veg_treenew01", + "veg_treenew03", + "veg_treenew05", + "veg_treenew06", + "veg_treenew08", + "veg_treenew09", + "veg_treenew10", + "veg_treenew16", + "veg_treenew17", + "vegclubtree01", + "vegclubtree02", + "vegclubtree03", + "vegpathtree", + "" +}; +char *OptimizedNames[] = { + "coast_treepatch", + "comparknewtrees", + "comtreepatchprk", + "indtreepatch5", + "indtreepatch06f", + "new_carprktrees", + "new_carprktrees4", + "newcoasttrees1", + "newcoasttrees2", + "newcoasttrees3", + "newtreepatch_sub", + "newtrees1_sub", + "newunitrepatch", + "treepatch", + "treepatch01_sub", + "treepatch02_sub", + "treepatch2", + "treepatch2b", + "treepatch03", + "treepatch03_sub", + "treepatch04_sub", + "treepatch05_sub", + "treepatch06_sub", + "treepatch07_sub", + "treepatch08_sub", + "treepatch09_sub", + "treepatch10_sub", + "treepatch11_sub", + "treepatch12_sub", + "treepatch13_sub", + "treepatch14_sub", + "treepatch15_sub", + "treepatch16_sub", + "treepatch17_sub", + "treepatch18_sub", + "treepatch19_sub", + "treepatch20_sub", + "treepatch21_sub", + "treepatch22_sub", + "treepatch23_sub", + "treepatch24_sub", + "treepatch25_sub", + "treepatch26_sub", + "treepatch27_sub", + "treepatch28_sub", + "treepatch29_sub", + "treepatch30_sub", + "treepatch31_sub", + "treepatch32_sub", + "treepatch33_sub", + "treepatch34_sub", + "treepatch35_sub", + "treepatch69", + "treepatch152_sub", + "treepatch153_sub", + "treepatch171_sub", + "treepatch172_sub", + "treepatch173_sub", + "treepatch212_sub", + "treepatch213_sub", + "treepatch214_sub", + "treepatcha", + "treepatchb", + "treepatchcomtop1", + "treepatchd", + "treepatche", + "treepatchh", + "treepatchindaa2", + "treepatchindnew", + "treepatchindnew2", + "treepatchk", + "treepatchkb4", + "treepatchkb5", + "treepatchkb6", + "treepatchkb7", + "treepatchkb9", + "treepatchl", + "treepatchm", + "treepatchnew_sub", + "treepatchttwrs", + "treesuni1", + "trepatchindaa1", + "combtm_treeshad01", + "combtm_treeshad02", + "combtm_treeshad03", + "combtm_treeshad04", + "combtm_treeshad05", + "combtm_treeshad06", + "comtop_tshad", + "comtop_tshad2", + "comtop_tshad3", + "comtop_tshad4", + "comtop_tshad5", + "comtop_tshad6", + "se_treeshad01", + "se_treeshad02", + "se_treeshad03", + "se_treeshad04", + "se_treeshad05", + "se_treeshad06", + "treeshads01", + "treeshads02", + "treeshads03", + "treeshads04", + "treeshads05", + "" +}; +// not from mobile +static bool +MatchModelName(char *name, char **list) +{ + int i; + char *s; + for(i = 0; *list[i] != '\0'; i++) + if(strncmp(name, "LOD", 3) == 0){ + if(!CGeneral::faststricmp(name+3, list[i]+3)) + return true; + }else{ + if(!CGeneral::faststricmp(name, list[i])) + return true; + } + return false; +} +#endif + RpAtomic* CFileLoader::SetRelatedModelInfoCB(RpAtomic *atomic, void *data) { @@ -600,6 +929,21 @@ SetModelInfoFlags(CSimpleModelInfo *mi, uint32 flags) mi->m_isSubway = !!(flags & 0x10); mi->m_ignoreLight = !!(flags & 0x20); mi->m_noZwrite = !!(flags & 0x40); +#ifdef EXTRA_MODEL_FLAGS + // same flag values as SA + mi->m_bIsTree = !!(flags & 0x2000); + mi->m_bIsDoubleSided = !!(flags & 0x200000); + // new value otherwise unused + mi->m_bCanBeIgnored = !!(flags & 0x10000); + +#ifdef HARDCODED_MODEL_FLAGS + // mobile sets these flags in CFileLoader::SetRelatedModelInfoCB, but that's stupid + if(MatchModelName(mi->GetName(), DoubleSidedNames)) mi->m_bIsDoubleSided = true; + if(MatchModelName(mi->GetName(), TreeNames)) mi->m_bIsTree = true; + if(MatchModelName(mi->GetName(), OptimizedNames)) mi->m_bCanBeIgnored = true; +#endif + +#endif } void diff --git a/src/core/config.h b/src/core/config.h index 171c6be9..fd89391b 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -201,6 +201,9 @@ enum Config { #define LOAD_INI_SETTINGS // Rendering/display +#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering +# define HARDCODED_MODEL_FLAGS // sets the flags enabled above from hardcoded model names. + // NB: keep this enabled unless your map IDEs have these flags baked in #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) #define USE_TXD_CDIMAGE // generate and load textures from txd.img diff --git a/src/extras/custompipes.cpp b/src/extras/custompipes.cpp index b545b4d8..8c2b6916 100644 --- a/src/extras/custompipes.cpp +++ b/src/extras/custompipes.cpp @@ -337,7 +337,7 @@ ReadTweakValueTable(char *fp, InterpolatedValue &interp) * Neo Vehicle pipe */ -int32 VehiclePipeSwitch = VEHICLEPIPE_NEO; +int32 VehiclePipeSwitch = VEHICLEPIPE_MATFX; float VehicleShininess = 0.7f; // the default is a bit extreme float VehicleSpecularity = 1.0f; InterpolatedFloat Fresnel(0.4f); diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h index 783f871f..2505967b 100644 --- a/src/modelinfo/BaseModelInfo.h +++ b/src/modelinfo/BaseModelInfo.h @@ -31,6 +31,14 @@ protected: ModelInfoType m_type; uint8 m_num2dEffects; bool m_bOwnsColModel; +#ifdef EXTRA_MODEL_FLAGS +public: + // from mobile + bool m_bIsDoubleSided; + bool m_bIsTree; + bool m_bCanBeIgnored; // for low-end devices + bool RenderDoubleSided(void) { return m_bIsDoubleSided || m_bIsTree; } +#endif public: CBaseModelInfo(ModelInfoType type); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 8c194067..4ad1d3b9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -53,6 +53,14 @@ CVehicle *CRenderer::m_pFirstPersonVehicle; bool CRenderer::m_loadingPriority; float CRenderer::ms_lodDistScale = 1.2f; +#ifdef EXTRA_MODEL_FLAGS +#define BACKFACE_CULLING_ON SetCullMode(rwCULLMODECULLBACK) +#define BACKFACE_CULLING_OFF SetCullMode(rwCULLMODECULLNONE) +#else +#define BACKFACE_CULLING_ON +#define BACKFACE_CULLING_OFF +#endif + void CRenderer::Init(void) { @@ -101,6 +109,13 @@ CRenderer::RenderOneRoad(CEntity *e) else{ #ifdef EXTENDED_PIPELINES CustomPipes::AttachGlossPipe(e->GetAtomic()); +#endif +#ifdef EXTRA_MODEL_FLAGS + if(CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ + BACKFACE_CULLING_OFF; + e->Render(); + BACKFACE_CULLING_ON; + }else #endif e->Render(); } @@ -163,13 +178,22 @@ CRenderer::RenderOneNonRoad(CEntity *e) for(i = 0; i < 8; i++) if(veh->pPassengers[i] && veh->pPassengers[i]->m_nPedState == PED_DRIVING) veh->pPassengers[i]->Render(); + BACKFACE_CULLING_OFF; } +#ifdef EXTRA_MODEL_FLAGS + if(CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ + BACKFACE_CULLING_OFF; + e->Render(); + BACKFACE_CULLING_ON; + }else +#endif e->Render(); if(e->IsVehicle()){ e->bImBeingRendered = true; CVisibilityPlugins::RenderAlphaAtomics(); e->bImBeingRendered = false; + BACKFACE_CULLING_ON; } e->RemoveLighting(resetLights); @@ -197,6 +221,7 @@ CRenderer::RenderRoads(void) CTreadable *t; RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + BACKFACE_CULLING_ON; DeActivateDirectional(); SetAmbientColours(); @@ -230,6 +255,7 @@ CRenderer::RenderEverythingBarRoads(void) CVector dist; EntityInfo ei; + BACKFACE_CULLING_ON; gSortedVehiclesAndPeds.Clear(); for(i = 0; i < ms_nNoOfVisibleEntities; i++){ @@ -284,6 +310,8 @@ CRenderer::RenderBoats(void) { CLink *node; + BACKFACE_CULLING_ON; + for(node = gSortedVehiclesAndPeds.tail.prev; node != &gSortedVehiclesAndPeds.head; node = node->prev){ @@ -298,6 +326,7 @@ void CRenderer::RenderFadingInEntities(void) { RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + BACKFACE_CULLING_ON; DeActivateDirectional(); SetAmbientColours(); CVisibilityPlugins::RenderFadingEntities(); diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 4b598e9b..6a7010e2 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -3,6 +3,7 @@ #endif #include "common.h" +#include "RwHelper.h" #include "Timecycle.h" #include "skeleton.h" #include "Debug.h" @@ -16,6 +17,7 @@ bool gPS2alphaTest = true; #else bool gPS2alphaTest = false; #endif +bool gBackfaceCulling = true; #ifndef FINAL static bool charsetOpen; @@ -121,14 +123,32 @@ DefinedState(void) #ifdef LIBRW rw::SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL); - rw::SetRenderState(rw::ALPHATESTREF, 3); rw::SetRenderState(rw::GSALPHATEST, gPS2alphaTest); #else // D3D stuff RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); - RwD3D8SetRenderState(D3DRS_ALPHAREF, 2); #endif + SetAlphaRef(2); +} + +void +SetAlphaRef(int ref) +{ +#ifdef LIBRW + rw::SetRenderState(rw::ALPHATESTREF, ref+1); +#else + RwD3D8SetRenderState(D3DRS_ALPHAREF, ref); +#endif +} + +void +SetCullMode(uint32 mode) +{ + if(gBackfaceCulling) + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)mode); + else + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); } RwFrame* diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index eceaee07..130eb636 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -11,6 +11,8 @@ void DestroyDebugFont(); void ObrsPrintfString(const char *str, short x, short y); void FlushObrsPrintfs(); void DefinedState(void); +void SetAlphaRef(int ref); +void SetCullMode(uint32 mode); RwFrame *GetFirstChild(RwFrame *frame); RwObject *GetFirstObject(RwFrame *frame); RpAtomic *GetFirstAtomic(RpClump *clump); diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index b2e252a0..c47cedca 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -1,5 +1,6 @@ #include "common.h" +#include "RwHelper.h" #include "templates.h" #include "Entity.h" #include "ModelInfo.h" @@ -158,6 +159,10 @@ CVisibilityPlugins::RenderFadingEntities(void) if(mi->m_noZwrite) #endif RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); +#ifdef EXTRA_MODEL_FLAGS + if(mi->m_bIsTree) + SetAlphaRef(128); +#endif if(e->bDistanceFade){ DeActivateDirectional(); @@ -168,6 +173,10 @@ CVisibilityPlugins::RenderFadingEntities(void) }else CRenderer::RenderOneNonRoad(e); +#ifdef EXTRA_MODEL_FLAGS + if(mi->m_bIsTree) + SetAlphaRef(2); +#endif #ifdef FIX_BUGS if(mi->GetModelType() == MITYPE_SIMPLE && mi->m_noZwrite) #else -- cgit v1.2.3 From e95516032f4e44ea35b7358f60c464c0faa1df91 Mon Sep 17 00:00:00 2001 From: withmorten Date: Thu, 29 Oct 2020 19:01:09 +0100 Subject: fix FINAL build, add DEBUGMENU and other simple qol defines to FINAL, add extra defines for menu and game version text --- src/core/Frontend.cpp | 2 ++ src/core/config.h | 24 ++++++++++++++++++++---- src/core/main.cpp | 3 +++ src/rw/RwHelper.cpp | 6 ++++-- 4 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 89b5ba3d..5c65aed5 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -789,9 +789,11 @@ CMenuManager::Draw() CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); CFont::SetRightJustifyWrap(0.0f); +#ifdef DRAW_MENU_VERSION_TEXT strcpy(gString, "V1.1"); AsciiToUnicode(gString, gUString); CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); +#endif #endif CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); diff --git a/src/core/config.h b/src/core/config.h index 171c6be9..92c0511f 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -156,6 +156,25 @@ enum Config { // any debug stuff that is only left in mobile, is not in MASTER //#define MASTER +// once and for all: +// pc: FINAL & MASTER +// mobile: FINAL + +// MASTER builds must be FINAL +#ifdef MASTER +#define FINAL +#endif + +// quality of life fixes that should also be in FINAL +#define NASTY_GAME // nasty game for all languages +#define NO_MOVIES // disable intro videos +#define NO_CDCHECK +#define DEBUGMENU + +// those infamous texts +#define DRAW_GAME_VERSION_TEXT +#define DRAW_MENU_VERSION_TEXT + #if defined GTA_PS2 # define GTA_PS2_STUFF # define RANDOMSPLASH @@ -177,6 +196,7 @@ enum Config { #ifdef MASTER // only in master builds + #undef DRAW_GAME_VERSION_TEXT #else // not in master builds #define VALIDATE_SAVE_SIZE @@ -187,11 +207,7 @@ enum Config { # define USE_MY_DOCUMENTS // use my documents directory for user files #else // not in any game -# define NASTY_GAME // nasty game for all languages -# define NO_MOVIES // disable intro videos -# define NO_CDCHECK # define CHATTYSPLASH // print what the game is loading -# define DEBUGMENU # define TIMEBARS // print debug timers #endif diff --git a/src/core/main.cpp b/src/core/main.cpp index 18ee2dc5..1aa0a953 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -768,6 +768,8 @@ DisplayGameDebugText() char str[200]; wchar ustr[200]; + +#ifdef DRAW_GAME_VERSION_TEXT wchar ver[200]; AsciiToUnicode(version_name, ver); @@ -783,6 +785,7 @@ DisplayGameDebugText() CFont::SetBackGroundOnlyTextOff(); CFont::SetColor(CRGBA(255, 108, 0, 255)); CFont::PrintString(SCREEN_SCALE_X(10.0f), SCREEN_SCALE_Y(10.0f), ver); +#endif FrameSamples++; FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f); diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 4b598e9b..dbadae6a 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -6,8 +6,10 @@ #include "Timecycle.h" #include "skeleton.h" #include "Debug.h" -#ifndef FINAL +#if !defined(FINAL) || defined(DEBUGMENU) #include "rtcharse.h" +#endif +#ifndef FINAL RtCharset *debugCharset; #endif @@ -17,7 +19,7 @@ bool gPS2alphaTest = true; bool gPS2alphaTest = false; #endif -#ifndef FINAL +#if !defined(FINAL) || defined(DEBUGMENU) static bool charsetOpen; void OpenCharsetSafe() { -- cgit v1.2.3 From 317393d763097af07bb56b1eeac2b70e91cceb98 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 29 Oct 2020 19:21:16 +0100 Subject: few more fixes to last commit --- src/core/config.h | 4 ++-- src/rw/VisibilityPlugins.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index fd89391b..a7de3a8a 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -201,8 +201,8 @@ enum Config { #define LOAD_INI_SETTINGS // Rendering/display -#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering -# define HARDCODED_MODEL_FLAGS // sets the flags enabled above from hardcoded model names. +//#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering +//# define HARDCODED_MODEL_FLAGS // sets the flags enabled above from hardcoded model names. // NB: keep this enabled unless your map IDEs have these flags baked in #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index c47cedca..8878a26a 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -160,7 +160,7 @@ CVisibilityPlugins::RenderFadingEntities(void) #endif RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); #ifdef EXTRA_MODEL_FLAGS - if(mi->m_bIsTree) + else if(mi->m_bIsTree) SetAlphaRef(128); #endif -- cgit v1.2.3 From 57b01ac4769b0ac83150f2284f5bad87f2f166a3 Mon Sep 17 00:00:00 2001 From: withmorten Date: Thu, 29 Oct 2020 19:23:59 +0100 Subject: NO_MOVIES and DEBUGMENU not for MASTER --- src/core/config.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index 92c0511f..019ff659 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -167,9 +167,7 @@ enum Config { // quality of life fixes that should also be in FINAL #define NASTY_GAME // nasty game for all languages -#define NO_MOVIES // disable intro videos #define NO_CDCHECK -#define DEBUGMENU // those infamous texts #define DRAW_GAME_VERSION_TEXT @@ -200,6 +198,9 @@ enum Config { #else // not in master builds #define VALIDATE_SAVE_SIZE + + #define NO_MOVIES // disable intro videos + #define DEBUGMENU #endif #ifdef FINAL -- cgit v1.2.3 From d34d591ed36557d88d2d0485965e7f7337ed25de Mon Sep 17 00:00:00 2001 From: withmorten Date: Thu, 29 Oct 2020 19:53:23 +0100 Subject: fix draw menu version text ifdef location --- src/core/Frontend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 5c65aed5..dca9685e 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -783,13 +783,13 @@ CMenuManager::Draw() CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); #ifdef GTA3_1_1_PATCH +#ifdef DRAW_MENU_VERSION_TEXT CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); CFont::SetRightJustifyWrap(0.0f); -#ifdef DRAW_MENU_VERSION_TEXT strcpy(gString, "V1.1"); AsciiToUnicode(gString, gUString); CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); -- cgit v1.2.3 From 7784ba052e3c5ea4aced693695e38caab825e053 Mon Sep 17 00:00:00 2001 From: erorcun Date: Fri, 30 Oct 2020 17:24:20 +0300 Subject: Update config.h --- src/core/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index efb09222..171c6be9 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -210,8 +210,8 @@ enum Config { #define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL #define CUTSCENE_BORDERS_SWITCH -#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) -#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) +//#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) +//#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) #define MULTISAMPLING // adds MSAA option #ifdef LIBRW -- cgit v1.2.3 From ded7c8960201b3df2a5682a5347fefa9af851f49 Mon Sep 17 00:00:00 2001 From: erorcun Date: Fri, 30 Oct 2020 17:36:13 +0300 Subject: Update MenuScreensCustom.cpp --- src/core/MenuScreensCustom.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index e2516140..25831486 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -49,24 +49,24 @@ #ifdef EXTENDED_COLOURFILTER #define POSTFX_SELECTORS \ - MENUACTION_CFO_SELECT, "VEHPIPE", { new CCFOSelect((int8*)&CustomPipes::VehiclePipeSwitch, "VehiclePipeline", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), false, nil) }, \ - MENUACTION_CFO_SELECT, "RIM", { new CCFOSelect((int8*)&CustomPipes::RimlightEnable, "NeoRimLight", off_on, 2, false, nil) }, \ - MENUACTION_CFO_SELECT, "LGTMAPS", { new CCFOSelect((int8*)&CustomPipes::LightmapEnable, "NeoLightMaps", off_on, 2, false, nil) }, \ - MENUACTION_CFO_SELECT, "GLOSS", { new CCFOSelect((int8*)&CustomPipes::GlossEnable, "NeoRoadGloss", off_on, 2, false, nil) }, + MENUACTION_CFO_SELECT, "FED_VPL", { new CCFOSelect((int8*)&CustomPipes::VehiclePipeSwitch, "VehiclePipeline", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_PRM", { new CCFOSelect((int8*)&CustomPipes::RimlightEnable, "NeoRimLight", off_on, 2, false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_WLM", { new CCFOSelect((int8*)&CustomPipes::LightmapEnable, "NeoLightMaps", off_on, 2, false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_RGL", { new CCFOSelect((int8*)&CustomPipes::GlossEnable, "NeoRoadGloss", off_on, 2, false, nil) }, #else #define POSTFX_SELECTORS #endif #ifdef EXTENDED_PIPELINES #define PIPELINES_SELECTOR \ - MENUACTION_CFO_SELECT, "CLRFLTR", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \ - MENUACTION_CFO_SELECT, "MBLUR", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) }, + MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) }, #else #define PIPELINES_SELECTOR #endif -const char *filterNames[] = { "None", "Simple", "Normal", "Mobile" }; -const char *vehPipelineNames[] = { "MatFX", "Neo" }; +const char *filterNames[] = { "FEM_NON", "FEM_SIM", "FEM_NRM", "FEM_MOB" }; +const char *vehPipelineNames[] = { "FED_MFX", "FED_NEO" }; const char *off_on[] = { "FEM_OFF", "FEM_ON" }; void RestoreDefGraphics(int8 action) { -- cgit v1.2.3 From 30c0f26f171b96443b9f897c816450a281cf216c Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 31 Oct 2020 22:09:43 +0100 Subject: fix sniper crosshair --- src/render/Hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 83c493bb..3d6e59f6 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -247,7 +247,7 @@ void CHud::Draw() rect.right = SCREEN_WIDTH/2 + SCREEN_SCALE_X(210.0f); rect.bottom = SCREEN_HEIGHT/2 + SCREEN_SCALE_Y(210.0f); Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), - 0.99f, 0.99f, 0.01f, 0.99f, 0.99f, 0.01f, 0.1f, 0.01f); + 0.99f, 0.99f, 0.01f, 0.99f, 0.99f, 0.01f, 0.01f, 0.01f); } } RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); -- cgit v1.2.3 From e9735f928f2c7c0675ef8ac2881da380f390576e Mon Sep 17 00:00:00 2001 From: withmorten Date: Sun, 1 Nov 2020 01:09:46 +0100 Subject: add ifdef LIBRW guard for pipelines and colourfilter --- src/core/config.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index 019ff659..7022fcc9 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -227,8 +227,10 @@ enum Config { #define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL #define CUTSCENE_BORDERS_SWITCH +#ifdef LIBRW //#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) //#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) +#endif #define MULTISAMPLING // adds MSAA option #ifdef LIBRW -- cgit v1.2.3 From 3c4f166a82d5760849e0f8a02c28a46d734a6c6d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 1 Nov 2020 09:20:37 +0200 Subject: Fix virtual SetModelIndex call in CBoat ctor --- src/vehicles/Boat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index dfe9d1d9..a33b9770 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -48,7 +48,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fSteeringLeftRight = 0.0f; m_nPadID = 0; m_fMovingRotation = 0.0f; - SetModelIndex(mi); + CBoat::SetModelIndex(mi); pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)minfo->m_handlingId); minfo->ChooseVehicleColour(m_currentColour1, m_currentColour2); -- cgit v1.2.3 From 5711251b0fcf3333c2f96b48dd784fe4c6e1ba25 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 1 Nov 2020 09:46:02 +0200 Subject: Also fix SetModelIndex in CAutomobile and CTrain ctors --- src/vehicles/Automobile.cpp | 2 +- src/vehicles/Train.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 95a68769..a1c38d21 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -73,7 +73,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) bBigWheels = false; bWaterTight = false; - SetModelIndex(id); + CAutomobile::SetModelIndex(id); pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp index 26d0dee7..98d522a7 100644 --- a/src/vehicles/Train.cpp +++ b/src/vehicles/Train.cpp @@ -44,7 +44,7 @@ CTrain::CTrain(int32 id, uint8 CreatedBy) CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); m_vehType = VEHICLE_TYPE_TRAIN; pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); - SetModelIndex(id); + CTrain::SetModelIndex(id); Doors[0].Init(0.8f, 0.0f, 1, 0); Doors[1].Init(-0.8f, 0.0f, 0, 0); -- cgit v1.2.3 From f21cfef8fb92a0923c6ddfa26124cf6da1fa883c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 1 Nov 2020 12:33:16 +0300 Subject: remove autosave at end of mission under MISSION_REPLAY --- src/control/Script.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 6bde6b87..86595bbd 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -2696,8 +2696,10 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) #ifdef MISSION_REPLAY if (m_bMissionFlag) { CPlayerInfo* pPlayerInfo = &CWorld::Players[CWorld::PlayerInFocus]; +#if 0 // makeing autosave is pointless and is a bit buggy if (pPlayerInfo->m_pPed->GetPedState() != PED_DEAD && pPlayerInfo->m_WBState == WBSTATE_PLAYING && !m_bDeatharrestExecuted) SaveGameForPause(1); +#endif oldTargetX = oldTargetY = 0.0f; if (AllowMissionReplay == 1) AllowMissionReplay = 2; -- cgit v1.2.3 From 1f5a6dab67d37af7e3686e29fc81d0f8e5bb5597 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 1 Nov 2020 12:30:23 +0200 Subject: Revert --- src/vehicles/Automobile.cpp | 2 +- src/vehicles/Boat.cpp | 2 +- src/vehicles/Train.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index a1c38d21..95a68769 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -73,7 +73,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) bBigWheels = false; bWaterTight = false; - CAutomobile::SetModelIndex(id); + SetModelIndex(id); pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index a33b9770..dfe9d1d9 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -48,7 +48,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fSteeringLeftRight = 0.0f; m_nPadID = 0; m_fMovingRotation = 0.0f; - CBoat::SetModelIndex(mi); + SetModelIndex(mi); pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)minfo->m_handlingId); minfo->ChooseVehicleColour(m_currentColour1, m_currentColour2); diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp index 98d522a7..26d0dee7 100644 --- a/src/vehicles/Train.cpp +++ b/src/vehicles/Train.cpp @@ -44,7 +44,7 @@ CTrain::CTrain(int32 id, uint8 CreatedBy) CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); m_vehType = VEHICLE_TYPE_TRAIN; pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); - CTrain::SetModelIndex(id); + SetModelIndex(id); Doors[0].Init(0.8f, 0.0f, 1, 0); Doors[1].Init(-0.8f, 0.0f, 0, 0); -- cgit v1.2.3 From 37943a87cbafcc0a0ad0a4a5b05a20e48ddf72de Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 1 Nov 2020 13:42:02 +0200 Subject: Show Xbox buttons when playing with a controller --- src/core/ControllerConfig.cpp | 408 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 408 insertions(+) (limited to 'src') diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 576a58b1..1af29a85 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -2316,8 +2316,416 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act return num; } +const char *XboxButtons[][MAX_CONTROLLERACTIONS] = +{ + { + "B", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "X", // PED_SNIPER_ZOOM_IN + "A", // PED_SNIPER_ZOOM_OUT + "Y", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "A", // PED_SPRINT + "RS", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + "B", // VEHICLE_FIREWEAPON +#endif + "A", // VEHICLE_ACCELERATE + "X", // VEHICLE_BRAKE + "LB", // VEHICLE_CHANGE_RADIO_STATION + "LS", // VEHICLE_HORN + "RS", // TOGGLE_SUBMISSIONS + "RB", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "LT", // VEHICLE_LOOKLEFT + "RT", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "LT", // PED_CYCLE_TARGET_LEFT + "RT", // PED_CYCLE_TARGET_RIGHT + "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER + "RB", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + }, + { + "B", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "X", // PED_SNIPER_ZOOM_IN + "A", // PED_SNIPER_ZOOM_OUT + "Y", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "A", // PED_SPRINT + "RS", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + "B", // VEHICLE_FIREWEAPON +#endif + "A", // VEHICLE_ACCELERATE + "X", // VEHICLE_BRAKE + "BACK", // VEHICLE_CHANGE_RADIO_STATION + "LB", // VEHICLE_HORN + "RS", // TOGGLE_SUBMISSIONS + "RB", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "LT", // VEHICLE_LOOKLEFT + "RT", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "LT", // PED_CYCLE_TARGET_LEFT + "RT", // PED_CYCLE_TARGET_RIGHT + "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER + "RB", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + }, + { + "A", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "Y", // PED_SNIPER_ZOOM_IN + "X", // PED_SNIPER_ZOOM_OUT + "LB", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "B", // PED_SPRINT + "RS", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + "B", // VEHICLE_FIREWEAPON +#endif + "A", // VEHICLE_ACCELERATE + "X", // VEHICLE_BRAKE + "LS", // VEHICLE_CHANGE_RADIO_STATION + "RB", // VEHICLE_HORN + "RS", // TOGGLE_SUBMISSIONS + "Y", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "LT", // VEHICLE_LOOKLEFT + "RT", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "LT", // PED_CYCLE_TARGET_LEFT + "RT", // PED_CYCLE_TARGET_RIGHT + "Y", // PED_CENTER_CAMERA_BEHIND_PLAYER + "RB", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + }, + { + "RB", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "X", // PED_SNIPER_ZOOM_IN + "A", // PED_SNIPER_ZOOM_OUT + "Y", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "A", // PED_SPRINT + "RS", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + "RB", // VEHICLE_FIREWEAPON +#endif + nil, // VEHICLE_ACCELERATE + nil, // VEHICLE_BRAKE + "B", // VEHICLE_CHANGE_RADIO_STATION + "LS", // VEHICLE_HORN + "X", // TOGGLE_SUBMISSIONS + "LB", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "LT", // VEHICLE_LOOKLEFT + "RT", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "LT", // PED_CYCLE_TARGET_LEFT + "RT", // PED_CYCLE_TARGET_RIGHT + "B", // PED_CENTER_CAMERA_BEHIND_PLAYER + "LB", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + } +}; + +#if 0 // set 1 for ps2 fonts +#define PS2_TRIANGLE "\"" +#define PS2_CIRCLE "|" +#define PS2_CROSS "/" +#define PS2_SQUARE "^" +#else +#define PS2_TRIANGLE "TRIANGLE" +#define PS2_CIRCLE "CIRCLE" +#define PS2_CROSS "CROSS" +#define PS2_SQUARE "SQUARE" +#endif + +const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] = +{ + { + PS2_CIRCLE, // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_SQUARE, // PED_SNIPER_ZOOM_IN + PS2_CROSS, // PED_SNIPER_ZOOM_OUT + PS2_TRIANGLE, // VEHICLE_ENTER_EXIT + "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CROSS, // PED_SPRINT + "R3", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + PS2_CIRCLE, // VEHICLE_FIREWEAPON +#endif + PS2_CROSS, // VEHICLE_ACCELERATE + PS2_SQUARE, // VEHICLE_BRAKE + "L1", // VEHICLE_CHANGE_RADIO_STATION + "L3", // VEHICLE_HORN + "R3", // TOGGLE_SUBMISSIONS + "R1", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "L2", // VEHICLE_LOOKLEFT + "R2", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "L2", // PED_CYCLE_TARGET_LEFT + "R2", // PED_CYCLE_TARGET_RIGHT + "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER + "R1", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + }, + { + PS2_CIRCLE, // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_SQUARE, // PED_SNIPER_ZOOM_IN + PS2_CROSS, // PED_SNIPER_ZOOM_OUT + PS2_TRIANGLE, // VEHICLE_ENTER_EXIT + "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CROSS, // PED_SPRINT + "R3", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + PS2_CIRCLE, // VEHICLE_FIREWEAPON +#endif + PS2_CROSS, // VEHICLE_ACCELERATE + PS2_SQUARE, // VEHICLE_BRAKE + "BACK", // VEHICLE_CHANGE_RADIO_STATION + "L1", // VEHICLE_HORN + "R3", // TOGGLE_SUBMISSIONS + "R1", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "L2", // VEHICLE_LOOKLEFT + "R2", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "L2", // PED_CYCLE_TARGET_LEFT + "R2", // PED_CYCLE_TARGET_RIGHT + "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER + "R1", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + }, + { + PS2_CROSS, // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_TRIANGLE, // PED_SNIPER_ZOOM_IN + PS2_SQUARE, // PED_SNIPER_ZOOM_OUT + "L1", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CIRCLE, // PED_SPRINT + "R3", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + PS2_CIRCLE, // VEHICLE_FIREWEAPON +#endif + PS2_CROSS, // VEHICLE_ACCELERATE + PS2_SQUARE, // VEHICLE_BRAKE + "L3", // VEHICLE_CHANGE_RADIO_STATION + "R1", // VEHICLE_HORN + "R3", // TOGGLE_SUBMISSIONS + PS2_TRIANGLE, // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "L2", // VEHICLE_LOOKLEFT + "R2", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "L2", // PED_CYCLE_TARGET_LEFT + "R2", // PED_CYCLE_TARGET_RIGHT + PS2_TRIANGLE, // PED_CENTER_CAMERA_BEHIND_PLAYER + "R1", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + }, + { + "R1", // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_SQUARE, // PED_SNIPER_ZOOM_IN + PS2_CROSS, // PED_SNIPER_ZOOM_OUT + PS2_TRIANGLE, // VEHICLE_ENTER_EXIT + "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CROSS, // PED_SPRINT + "R3", // PED_LOOKBEHIND +#ifdef BIND_VEHICLE_FIREWEAPON + "R1", // VEHICLE_FIREWEAPON +#endif + nil, // VEHICLE_ACCELERATE + nil, // VEHICLE_BRAKE + PS2_CIRCLE, // VEHICLE_CHANGE_RADIO_STATION + "L3", // VEHICLE_HORN + PS2_SQUARE, // TOGGLE_SUBMISSIONS + "L1", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "L2", // VEHICLE_LOOKLEFT + "R2", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "L2", // PED_CYCLE_TARGET_LEFT + "R2", // PED_CYCLE_TARGET_RIGHT + PS2_CIRCLE, // PED_CENTER_CAMERA_BEHIND_PLAYER + "L1", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE + } +}; + +#undef PS2_TRIANGLE +#undef PS2_CIRCLE +#undef PS2_CROSS +#undef PS2_SQUARE + void CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar *text, uint16 leight) { +#ifdef DETECT_PAD_INPUT_SWITCH + if (CPad::GetPad(0)->IsAffectedByController) { + wchar wstr[16]; + + // TODO: INI and/or menu setting for Xbox/PS switch + const char *(*Buttons)[MAX_CONTROLLERACTIONS] = XboxButtons; + + assert(Buttons[CPad::GetPad(0)->Mode][action] != nil); // we cannot use these + AsciiToUnicode(Buttons[CPad::GetPad(0)->Mode][action], wstr); + + CMessages::WideStringCopy(text, wstr, leight); + return; + } +#endif + int32 nums = GetNumOfSettingsForAction((e_ControllerAction)action); int32 sets = 0; -- cgit v1.2.3 From 30d1cbfecd6e9fb477a0b5672d830b871be9722d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 1 Nov 2020 13:46:12 +0200 Subject: Fix the goddamn spaces for tabs master race --- src/core/ControllerConfig.cpp | 568 +++++++++++++++++++++--------------------- 1 file changed, 284 insertions(+), 284 deletions(-) (limited to 'src') diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 1af29a85..dcc294c8 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -2318,161 +2318,161 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act const char *XboxButtons[][MAX_CONTROLLERACTIONS] = { - { - "B", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "X", // PED_SNIPER_ZOOM_IN - "A", // PED_SNIPER_ZOOM_OUT - "Y", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "A", // PED_SPRINT - "RS", // PED_LOOKBEHIND + { + "B", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "X", // PED_SNIPER_ZOOM_IN + "A", // PED_SNIPER_ZOOM_OUT + "Y", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "A", // PED_SPRINT + "RS", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - "B", // VEHICLE_FIREWEAPON + "B", // VEHICLE_FIREWEAPON #endif - "A", // VEHICLE_ACCELERATE - "X", // VEHICLE_BRAKE - "LB", // VEHICLE_CHANGE_RADIO_STATION - "LS", // VEHICLE_HORN - "RS", // TOGGLE_SUBMISSIONS - "RB", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "LT", // VEHICLE_LOOKLEFT - "RT", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "LT", // PED_CYCLE_TARGET_LEFT - "RT", // PED_CYCLE_TARGET_RIGHT - "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER - "RB", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE + "A", // VEHICLE_ACCELERATE + "X", // VEHICLE_BRAKE + "LB", // VEHICLE_CHANGE_RADIO_STATION + "LS", // VEHICLE_HORN + "RS", // TOGGLE_SUBMISSIONS + "RB", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "LT", // VEHICLE_LOOKLEFT + "RT", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "LT", // PED_CYCLE_TARGET_LEFT + "RT", // PED_CYCLE_TARGET_RIGHT + "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER + "RB", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE }, { - "B", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "X", // PED_SNIPER_ZOOM_IN - "A", // PED_SNIPER_ZOOM_OUT - "Y", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "A", // PED_SPRINT - "RS", // PED_LOOKBEHIND + "B", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "X", // PED_SNIPER_ZOOM_IN + "A", // PED_SNIPER_ZOOM_OUT + "Y", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "A", // PED_SPRINT + "RS", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - "B", // VEHICLE_FIREWEAPON + "B", // VEHICLE_FIREWEAPON #endif - "A", // VEHICLE_ACCELERATE - "X", // VEHICLE_BRAKE - "BACK", // VEHICLE_CHANGE_RADIO_STATION - "LB", // VEHICLE_HORN - "RS", // TOGGLE_SUBMISSIONS - "RB", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "LT", // VEHICLE_LOOKLEFT - "RT", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "LT", // PED_CYCLE_TARGET_LEFT - "RT", // PED_CYCLE_TARGET_RIGHT - "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER - "RB", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE + "A", // VEHICLE_ACCELERATE + "X", // VEHICLE_BRAKE + "BACK", // VEHICLE_CHANGE_RADIO_STATION + "LB", // VEHICLE_HORN + "RS", // TOGGLE_SUBMISSIONS + "RB", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "LT", // VEHICLE_LOOKLEFT + "RT", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "LT", // PED_CYCLE_TARGET_LEFT + "RT", // PED_CYCLE_TARGET_RIGHT + "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER + "RB", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE }, { - "A", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "Y", // PED_SNIPER_ZOOM_IN - "X", // PED_SNIPER_ZOOM_OUT - "LB", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "B", // PED_SPRINT - "RS", // PED_LOOKBEHIND + "A", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "Y", // PED_SNIPER_ZOOM_IN + "X", // PED_SNIPER_ZOOM_OUT + "LB", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "B", // PED_SPRINT + "RS", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - "B", // VEHICLE_FIREWEAPON + "B", // VEHICLE_FIREWEAPON #endif - "A", // VEHICLE_ACCELERATE - "X", // VEHICLE_BRAKE - "LS", // VEHICLE_CHANGE_RADIO_STATION - "RB", // VEHICLE_HORN - "RS", // TOGGLE_SUBMISSIONS - "Y", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "LT", // VEHICLE_LOOKLEFT - "RT", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "LT", // PED_CYCLE_TARGET_LEFT - "RT", // PED_CYCLE_TARGET_RIGHT - "Y", // PED_CENTER_CAMERA_BEHIND_PLAYER - "RB", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE + "A", // VEHICLE_ACCELERATE + "X", // VEHICLE_BRAKE + "LS", // VEHICLE_CHANGE_RADIO_STATION + "RB", // VEHICLE_HORN + "RS", // TOGGLE_SUBMISSIONS + "Y", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "LT", // VEHICLE_LOOKLEFT + "RT", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "LT", // PED_CYCLE_TARGET_LEFT + "RT", // PED_CYCLE_TARGET_RIGHT + "Y", // PED_CENTER_CAMERA_BEHIND_PLAYER + "RB", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE }, { - "RB", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "X", // PED_SNIPER_ZOOM_IN - "A", // PED_SNIPER_ZOOM_OUT - "Y", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "A", // PED_SPRINT - "RS", // PED_LOOKBEHIND + "RB", // PED_FIREWEAPON + "RT", // PED_CYCLE_WEAPON_RIGHT + "LT", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + "X", // PED_SNIPER_ZOOM_IN + "A", // PED_SNIPER_ZOOM_OUT + "Y", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + "X", // PED_JUMPING + "A", // PED_SPRINT + "RS", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - "RB", // VEHICLE_FIREWEAPON + "RB", // VEHICLE_FIREWEAPON #endif nil, // VEHICLE_ACCELERATE nil, // VEHICLE_BRAKE @@ -2518,161 +2518,161 @@ const char *XboxButtons[][MAX_CONTROLLERACTIONS] = const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] = { - { - PS2_CIRCLE, // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_SQUARE, // PED_SNIPER_ZOOM_IN - PS2_CROSS, // PED_SNIPER_ZOOM_OUT - PS2_TRIANGLE, // VEHICLE_ENTER_EXIT - "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CROSS, // PED_SPRINT - "R3", // PED_LOOKBEHIND + { + PS2_CIRCLE, // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_SQUARE, // PED_SNIPER_ZOOM_IN + PS2_CROSS, // PED_SNIPER_ZOOM_OUT + PS2_TRIANGLE, // VEHICLE_ENTER_EXIT + "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CROSS, // PED_SPRINT + "R3", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - PS2_CIRCLE, // VEHICLE_FIREWEAPON + PS2_CIRCLE, // VEHICLE_FIREWEAPON #endif - PS2_CROSS, // VEHICLE_ACCELERATE - PS2_SQUARE, // VEHICLE_BRAKE - "L1", // VEHICLE_CHANGE_RADIO_STATION - "L3", // VEHICLE_HORN - "R3", // TOGGLE_SUBMISSIONS - "R1", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "L2", // VEHICLE_LOOKLEFT - "R2", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "L2", // PED_CYCLE_TARGET_LEFT - "R2", // PED_CYCLE_TARGET_RIGHT - "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER - "R1", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE + PS2_CROSS, // VEHICLE_ACCELERATE + PS2_SQUARE, // VEHICLE_BRAKE + "L1", // VEHICLE_CHANGE_RADIO_STATION + "L3", // VEHICLE_HORN + "R3", // TOGGLE_SUBMISSIONS + "R1", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "L2", // VEHICLE_LOOKLEFT + "R2", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "L2", // PED_CYCLE_TARGET_LEFT + "R2", // PED_CYCLE_TARGET_RIGHT + "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER + "R1", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE }, { - PS2_CIRCLE, // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_SQUARE, // PED_SNIPER_ZOOM_IN - PS2_CROSS, // PED_SNIPER_ZOOM_OUT - PS2_TRIANGLE, // VEHICLE_ENTER_EXIT - "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CROSS, // PED_SPRINT - "R3", // PED_LOOKBEHIND + PS2_CIRCLE, // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_SQUARE, // PED_SNIPER_ZOOM_IN + PS2_CROSS, // PED_SNIPER_ZOOM_OUT + PS2_TRIANGLE, // VEHICLE_ENTER_EXIT + "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CROSS, // PED_SPRINT + "R3", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - PS2_CIRCLE, // VEHICLE_FIREWEAPON + PS2_CIRCLE, // VEHICLE_FIREWEAPON #endif - PS2_CROSS, // VEHICLE_ACCELERATE - PS2_SQUARE, // VEHICLE_BRAKE - "BACK", // VEHICLE_CHANGE_RADIO_STATION - "L1", // VEHICLE_HORN - "R3", // TOGGLE_SUBMISSIONS - "R1", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "L2", // VEHICLE_LOOKLEFT - "R2", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "L2", // PED_CYCLE_TARGET_LEFT - "R2", // PED_CYCLE_TARGET_RIGHT - "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER - "R1", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE + PS2_CROSS, // VEHICLE_ACCELERATE + PS2_SQUARE, // VEHICLE_BRAKE + "BACK", // VEHICLE_CHANGE_RADIO_STATION + "L1", // VEHICLE_HORN + "R3", // TOGGLE_SUBMISSIONS + "R1", // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "L2", // VEHICLE_LOOKLEFT + "R2", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "L2", // PED_CYCLE_TARGET_LEFT + "R2", // PED_CYCLE_TARGET_RIGHT + "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER + "R1", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE }, { - PS2_CROSS, // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_TRIANGLE, // PED_SNIPER_ZOOM_IN - PS2_SQUARE, // PED_SNIPER_ZOOM_OUT - "L1", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CIRCLE, // PED_SPRINT - "R3", // PED_LOOKBEHIND + PS2_CROSS, // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_TRIANGLE, // PED_SNIPER_ZOOM_IN + PS2_SQUARE, // PED_SNIPER_ZOOM_OUT + "L1", // VEHICLE_ENTER_EXIT + "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CIRCLE, // PED_SPRINT + "R3", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - PS2_CIRCLE, // VEHICLE_FIREWEAPON + PS2_CIRCLE, // VEHICLE_FIREWEAPON #endif - PS2_CROSS, // VEHICLE_ACCELERATE - PS2_SQUARE, // VEHICLE_BRAKE - "L3", // VEHICLE_CHANGE_RADIO_STATION - "R1", // VEHICLE_HORN - "R3", // TOGGLE_SUBMISSIONS - PS2_TRIANGLE, // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "L2", // VEHICLE_LOOKLEFT - "R2", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "L2", // PED_CYCLE_TARGET_LEFT - "R2", // PED_CYCLE_TARGET_RIGHT - PS2_TRIANGLE, // PED_CENTER_CAMERA_BEHIND_PLAYER - "R1", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE + PS2_CROSS, // VEHICLE_ACCELERATE + PS2_SQUARE, // VEHICLE_BRAKE + "L3", // VEHICLE_CHANGE_RADIO_STATION + "R1", // VEHICLE_HORN + "R3", // TOGGLE_SUBMISSIONS + PS2_TRIANGLE, // VEHICLE_HANDBRAKE + nil, // PED_1RST_PERSON_LOOK_LEFT + nil, // PED_1RST_PERSON_LOOK_RIGHT + "L2", // VEHICLE_LOOKLEFT + "R2", // VEHICLE_LOOKRIGHT + nil, // VEHICLE_LOOKBEHIND + nil, // VEHICLE_TURRETLEFT + nil, // VEHICLE_TURRETRIGHT + nil, // VEHICLE_TURRETUP + nil, // VEHICLE_TURRETDOWN + "L2", // PED_CYCLE_TARGET_LEFT + "R2", // PED_CYCLE_TARGET_RIGHT + PS2_TRIANGLE, // PED_CENTER_CAMERA_BEHIND_PLAYER + "R1", // PED_LOCK_TARGET + nil, // NETWORK_TALK + nil, // PED_1RST_PERSON_LOOK_UP + nil, // PED_1RST_PERSON_LOOK_DOWN + nil, // _CONTROLLERACTION_36 + nil, // TOGGLE_DPAD + nil, // SWITCH_DEBUG_CAM_ON + nil, // TAKE_SCREEN_SHOT + nil, // SHOW_MOUSE_POINTER_TOGGLE }, { - "R1", // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_SQUARE, // PED_SNIPER_ZOOM_IN - PS2_CROSS, // PED_SNIPER_ZOOM_OUT - PS2_TRIANGLE, // VEHICLE_ENTER_EXIT - "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CROSS, // PED_SPRINT - "R3", // PED_LOOKBEHIND + "R1", // PED_FIREWEAPON + "R2", // PED_CYCLE_WEAPON_RIGHT + "L2", // PED_CYCLE_WEAPON_LEFT + nil, // GO_FORWARD + nil, // GO_BACK + nil, // GO_LEFT + nil, // GO_RIGHT + PS2_SQUARE, // PED_SNIPER_ZOOM_IN + PS2_CROSS, // PED_SNIPER_ZOOM_OUT + PS2_TRIANGLE, // VEHICLE_ENTER_EXIT + "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS + PS2_SQUARE, // PED_JUMPING + PS2_CROSS, // PED_SPRINT + "R3", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - "R1", // VEHICLE_FIREWEAPON + "R1", // VEHICLE_FIREWEAPON #endif nil, // VEHICLE_ACCELERATE nil, // VEHICLE_BRAKE -- cgit v1.2.3 From fad0a9507d4a4eb63fc5a658c2886fe07f7dadee Mon Sep 17 00:00:00 2001 From: Roman Masanin <36927roma@gmail.com> Date: Sun, 1 Nov 2020 23:48:03 +0300 Subject: some "optimizations". same like I did in VC --- src/audio/AudioLogic.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 3fc9334f..1e8a8194 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -1930,7 +1930,6 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_CLOSE; break; case NEW_DOOR: - default: m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE; break; case TRUCK_DOOR: @@ -1939,9 +1938,12 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) case BUS_DOOR: m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; break; + default: + m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE; + break; } m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22; + m_sQueueSample.m_nCounter = event + 22; //originaly used m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i], which is same m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -1975,7 +1977,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) break; } m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10; + m_sQueueSample.m_nCounter = event + 10; //also used m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; -- cgit v1.2.3 From e587974759bd98a1f56dd752537b8ffe184b747b Mon Sep 17 00:00:00 2001 From: shfil Date: Mon, 2 Nov 2020 13:31:25 +0100 Subject: Fix include in Frontend_PS2.cpp --- src/core/Frontend_PS2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/Frontend_PS2.cpp b/src/core/Frontend_PS2.cpp index d474ee65..a1d802f2 100644 --- a/src/core/Frontend_PS2.cpp +++ b/src/core/Frontend_PS2.cpp @@ -22,7 +22,7 @@ #include "Game.h" #include "World.h" #include "PlayerInfo.h" -#include "FrontendControls.h" +#include "FrontEndControls.h" #include "MemoryCard.h" #define CRect_SZ(x, y, w, h) CRect(x, y, x+w, y+h) @@ -3044,4 +3044,4 @@ CMenuManager::FilterOutColorMarkersFromString(wchar *string, CRGBA &color) *dst = '\0'; } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 1df6dda546aa658d456846900880ac380d0ab677 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Sat, 31 Oct 2020 23:14:28 +0100 Subject: Add basic support for cmake on linux --- src/CMakeLists.txt | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/CMakeLists.txt (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..eca69d30 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,112 @@ +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + +if(${RE3_AUDIO} STREQUAL "OAL") + find_package(OpenAL REQUIRED) + find_package(MPG123 REQUIRED) + find_package(SndFile REQUIRED) +endif() + +file(GLOB_RECURSE Sources "*.cpp" "*.h") + +MACRO(HEADER_DIRECTORIES return_list) + FILE(GLOB_RECURSE new_list *.cpp) + SET(dir_list "animation" + "audio" + "control" + "core" + "entities" + "extras" + "fakerw" + "math" + "modelinfo" + "objects" + "peds" + "render" + "rw" + "save" + "skel" + "text" + "vehicles" + "weapons") + FOREACH(file_path ${new_list}) + GET_FILENAME_COMPONENT(dir_path ${file_path} PATH) + SET(dir_list ${dir_list} ${dir_path}) + ENDFOREACH() + LIST(REMOVE_DUPLICATES dir_list) + SET(${return_list} ${dir_list}) +ENDMACRO() + +HEADER_DIRECTORIES(header_list) +include_directories(${header_list}) + + +add_executable(re3 ${Sources}) +target_link_libraries(re3 librw) +target_link_libraries(re3 Threads::Threads) + +if(${RE3_AUDIO} STREQUAL "OAL") + target_link_libraries(re3 ${OPENAL_LIBRARY}) + target_link_libraries(re3 ${MPG123_LIBRARIES}) + target_link_libraries(re3 ${SNDFILE_LIBRARIES}) +endif() + +target_include_directories(re3 + INTERFACE + $ + ) + +target_compile_definitions(re3 + PRIVATE + "$,DEBUG,NDEBUG>" + PUBLIC + "RW_${RE3_PLATFORM}" + ) + +target_compile_definitions(re3 PRIVATE LIBRW=1 AUDIO_OAL=1) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + target_compile_options(re3 + PRIVATE + "-Wall" + ) + if (NOT RE3_PLATFORM_PS2) + target_compile_options(re3 + PRIVATE + "-Wextra" + "-Wdouble-promotion" + "-Wpedantic" + ) + endif() +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_options(re3 + PUBLIC + /wd4996 /wd4244 + ) +endif() + +set_target_properties(re3 + PROPERTIES + C_STANDARD 11 + C_EXTENSIONS OFF + C_STANDARD_REQUIRED ON + CXX_STANDARD 11 + CXX_EXTENSIONS OFF + CXX_STANDARD_REQUIRED ON + PREFIX "" + ) + +if(RE3_INSTALL) + target_include_directories(re3 + INTERFACE + $ + ) + + install( + TARGETS re3 + EXPORT re3-targets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ) +endif() -- cgit v1.2.3 From d4c26396c7c447de00470a0ba2153ee43bc00532 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 2 Nov 2020 18:17:37 +0200 Subject: Fix MemoryCard.cpp --- src/save/MemoryCard.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/save/MemoryCard.cpp b/src/save/MemoryCard.cpp index a24b754c..c8ebcd86 100644 --- a/src/save/MemoryCard.cpp +++ b/src/save/MemoryCard.cpp @@ -11,6 +11,7 @@ #include "Clock.h" #include "MBlur.h" #include "Date.h" +#include "Font.h" #include "FileMgr.h" #include "Game.h" #include "GameLogic.h" -- cgit v1.2.3 From f08b9cf0338c448d182c7561cacb4a755153834d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 3 Nov 2020 15:00:48 +0200 Subject: fix build --- src/core/MenuScreensCustom.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index 25831486..abb93a3c 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -10,6 +10,7 @@ #include "postfx.h" #include "custompipes.h" #include "RwHelper.h" +#include "Text.h" // Menu screens array is at the bottom of the file. -- cgit v1.2.3 From ebddb7956c44d6d5862b6bddfc0be54d55f4a813 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 3 Nov 2020 14:37:00 +0100 Subject: fix mistake in custom menu; update librw --- src/core/MenuScreensCustom.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index abb93a3c..fb0888fc 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -50,18 +50,18 @@ #ifdef EXTENDED_COLOURFILTER #define POSTFX_SELECTORS \ - MENUACTION_CFO_SELECT, "FED_VPL", { new CCFOSelect((int8*)&CustomPipes::VehiclePipeSwitch, "VehiclePipeline", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), false, nil) }, \ - MENUACTION_CFO_SELECT, "FED_PRM", { new CCFOSelect((int8*)&CustomPipes::RimlightEnable, "NeoRimLight", off_on, 2, false, nil) }, \ - MENUACTION_CFO_SELECT, "FED_WLM", { new CCFOSelect((int8*)&CustomPipes::LightmapEnable, "NeoLightMaps", off_on, 2, false, nil) }, \ - MENUACTION_CFO_SELECT, "FED_RGL", { new CCFOSelect((int8*)&CustomPipes::GlossEnable, "NeoRoadGloss", off_on, 2, false, nil) }, + MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) }, #else #define POSTFX_SELECTORS #endif #ifdef EXTENDED_PIPELINES #define PIPELINES_SELECTOR \ - MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \ - MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) }, + MENUACTION_CFO_SELECT, "FED_VPL", { new CCFOSelect((int8*)&CustomPipes::VehiclePipeSwitch, "VehiclePipeline", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_PRM", { new CCFOSelect((int8*)&CustomPipes::RimlightEnable, "NeoRimLight", off_on, 2, false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_WLM", { new CCFOSelect((int8*)&CustomPipes::LightmapEnable, "NeoLightMaps", off_on, 2, false, nil) }, \ + MENUACTION_CFO_SELECT, "FED_RGL", { new CCFOSelect((int8*)&CustomPipes::GlossEnable, "NeoRoadGloss", off_on, 2, false, nil) }, #else #define PIPELINES_SELECTOR #endif -- cgit v1.2.3 From b3da518ae02eb9c9a9cc3e0343438f07d6d28251 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 3 Nov 2020 16:59:37 +0100 Subject: only do backface culling on buildings --- src/render/Renderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 4ad1d3b9..92bbdd45 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -111,7 +111,7 @@ CRenderer::RenderOneRoad(CEntity *e) CustomPipes::AttachGlossPipe(e->GetAtomic()); #endif #ifdef EXTRA_MODEL_FLAGS - if(CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ + if(!e->IsBuilding() || CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ BACKFACE_CULLING_OFF; e->Render(); BACKFACE_CULLING_ON; @@ -181,7 +181,7 @@ CRenderer::RenderOneNonRoad(CEntity *e) BACKFACE_CULLING_OFF; } #ifdef EXTRA_MODEL_FLAGS - if(CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ + if(!e->IsBuilding() || CModelInfo::GetModelInfo(e->GetModelIndex())->RenderDoubleSided()){ BACKFACE_CULLING_OFF; e->Render(); BACKFACE_CULLING_ON; -- cgit v1.2.3 From 8224a6a38156ccba7c69b66fab3388463fc727b1 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 5 Nov 2020 17:05:16 +0200 Subject: Button icons --- src/core/ControllerConfig.cpp | 569 +++++++++++++++--------------------------- src/core/config.h | 1 + src/render/Font.cpp | 172 ++++++++++++- src/render/Font.h | 33 +++ 4 files changed, 403 insertions(+), 372 deletions(-) (limited to 'src') diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index dcc294c8..504b832c 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -2316,199 +2316,207 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act return num; } -const char *XboxButtons[][MAX_CONTROLLERACTIONS] = -{ - { - "B", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "X", // PED_SNIPER_ZOOM_IN - "A", // PED_SNIPER_ZOOM_OUT - "Y", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "A", // PED_SPRINT - "RS", // PED_LOOKBEHIND -#ifdef BIND_VEHICLE_FIREWEAPON - "B", // VEHICLE_FIREWEAPON -#endif - "A", // VEHICLE_ACCELERATE - "X", // VEHICLE_BRAKE - "LB", // VEHICLE_CHANGE_RADIO_STATION - "LS", // VEHICLE_HORN - "RS", // TOGGLE_SUBMISSIONS - "RB", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "LT", // VEHICLE_LOOKLEFT - "RT", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "LT", // PED_CYCLE_TARGET_LEFT - "RT", // PED_CYCLE_TARGET_RIGHT - "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER - "RB", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - }, - { - "B", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "X", // PED_SNIPER_ZOOM_IN - "A", // PED_SNIPER_ZOOM_OUT - "Y", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "A", // PED_SPRINT - "RS", // PED_LOOKBEHIND -#ifdef BIND_VEHICLE_FIREWEAPON - "B", // VEHICLE_FIREWEAPON -#endif - "A", // VEHICLE_ACCELERATE - "X", // VEHICLE_BRAKE - "BACK", // VEHICLE_CHANGE_RADIO_STATION - "LB", // VEHICLE_HORN - "RS", // TOGGLE_SUBMISSIONS - "RB", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "LT", // VEHICLE_LOOKLEFT - "RT", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "LT", // PED_CYCLE_TARGET_LEFT - "RT", // PED_CYCLE_TARGET_RIGHT - "LB", // PED_CENTER_CAMERA_BEHIND_PLAYER - "RB", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - }, - { - "A", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "Y", // PED_SNIPER_ZOOM_IN - "X", // PED_SNIPER_ZOOM_OUT - "LB", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "B", // PED_SPRINT - "RS", // PED_LOOKBEHIND #ifdef BIND_VEHICLE_FIREWEAPON - "B", // VEHICLE_FIREWEAPON +#define VFB(b) b, +#else +#define VFB(b) #endif - "A", // VEHICLE_ACCELERATE - "X", // VEHICLE_BRAKE - "LS", // VEHICLE_CHANGE_RADIO_STATION - "RB", // VEHICLE_HORN - "RS", // TOGGLE_SUBMISSIONS - "Y", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "LT", // VEHICLE_LOOKLEFT - "RT", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "LT", // PED_CYCLE_TARGET_LEFT - "RT", // PED_CYCLE_TARGET_RIGHT - "Y", // PED_CENTER_CAMERA_BEHIND_PLAYER - "RB", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - }, - { - "RB", // PED_FIREWEAPON - "RT", // PED_CYCLE_WEAPON_RIGHT - "LT", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - "X", // PED_SNIPER_ZOOM_IN - "A", // PED_SNIPER_ZOOM_OUT - "Y", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - "X", // PED_JUMPING - "A", // PED_SPRINT - "RS", // PED_LOOKBEHIND -#ifdef BIND_VEHICLE_FIREWEAPON - "RB", // VEHICLE_FIREWEAPON + +#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT) \ + {{ \ + 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 */ \ + Q, /* PED_SNIPER_ZOOM_IN */ \ + X, /* PED_SNIPER_ZOOM_OUT */ \ + T, /* VEHICLE_ENTER_EXIT */ \ + SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \ + Q, /* PED_JUMPING */ \ + X, /* PED_SPRINT */ \ + R3, /* PED_LOOKBEHIND */ \ + VFB(O) /* VEHICLE_FIREWEAPON */ \ + X, /* VEHICLE_ACCELERATE */ \ + Q, /* VEHICLE_BRAKE */ \ + L1, /* VEHICLE_CHANGE_RADIO_STATION */ \ + L3, /* VEHICLE_HORN */ \ + R3, /* TOGGLE_SUBMISSIONS */ \ + R1, /* VEHICLE_HANDBRAKE */ \ + nil, /* PED_1RST_PERSON_LOOK_LEFT */ \ + nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \ + L2, /* VEHICLE_LOOKLEFT */ \ + R2, /* VEHICLE_LOOKRIGHT */ \ + nil, /* VEHICLE_LOOKBEHIND */ \ + nil, /* VEHICLE_TURRETLEFT */ \ + nil, /* VEHICLE_TURRETRIGHT */ \ + nil, /* VEHICLE_TURRETUP */ \ + nil, /* VEHICLE_TURRETDOWN */ \ + L2, /* PED_CYCLE_TARGET_LEFT */ \ + R2, /* PED_CYCLE_TARGET_RIGHT */ \ + L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ + R1, /* PED_LOCK_TARGET */ \ + nil, /* NETWORK_TALK */ \ + nil, /* PED_1RST_PERSON_LOOK_UP */ \ + nil, /* PED_1RST_PERSON_LOOK_DOWN */ \ + nil, /* _CONTROLLERACTION_36 */ \ + nil, /* TOGGLE_DPAD */ \ + nil, /* SWITCH_DEBUG_CAM_ON */ \ + nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ + }, \ + { \ + 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 */ \ + Q, /* PED_SNIPER_ZOOM_IN */ \ + X, /* PED_SNIPER_ZOOM_OUT */ \ + T, /* VEHICLE_ENTER_EXIT */ \ + SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \ + Q, /* PED_JUMPING */ \ + X, /* PED_SPRINT */ \ + R3, /* PED_LOOKBEHIND */ \ + VFB(O) /* VEHICLE_FIREWEAPON */ \ + X, /* VEHICLE_ACCELERATE */ \ + Q, /* VEHICLE_BRAKE */ \ + SELECT, /* VEHICLE_CHANGE_RADIO_STATION */ \ + L1, /* VEHICLE_HORN */ \ + R3, /* TOGGLE_SUBMISSIONS */ \ + R1, /* VEHICLE_HANDBRAKE */ \ + nil, /* PED_1RST_PERSON_LOOK_LEFT */ \ + nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \ + L2, /* VEHICLE_LOOKLEFT */ \ + R2, /* VEHICLE_LOOKRIGHT */ \ + nil, /* VEHICLE_LOOKBEHIND */ \ + nil, /* VEHICLE_TURRETLEFT */ \ + nil, /* VEHICLE_TURRETRIGHT */ \ + nil, /* VEHICLE_TURRETUP */ \ + nil, /* VEHICLE_TURRETDOWN */ \ + L2, /* PED_CYCLE_TARGET_LEFT */ \ + R2, /* PED_CYCLE_TARGET_RIGHT */ \ + L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ + R1, /* PED_LOCK_TARGET */ \ + nil, /* NETWORK_TALK */ \ + nil, /* PED_1RST_PERSON_LOOK_UP */ \ + nil, /* PED_1RST_PERSON_LOOK_DOWN */ \ + nil, /* _CONTROLLERACTION_36 */ \ + nil, /* TOGGLE_DPAD */ \ + nil, /* SWITCH_DEBUG_CAM_ON */ \ + nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ + }, \ + { \ + X, /* PED_FIREWEAPON */ \ + R2, /* PED_CYCLE_WEAPON_RIGHT */ \ + L2, /* PED_CYCLE_WEAPON_LEFT */ \ + nil, /* GO_FORWARD */ \ + nil, /* GO_BACK */ \ + nil, /* GO_LEFT */ \ + nil, /* GO_RIGHT */ \ + T, /* PED_SNIPER_ZOOM_IN */ \ + Q, /* PED_SNIPER_ZOOM_OUT */ \ + L1, /* VEHICLE_ENTER_EXIT */ \ + SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \ + Q, /* PED_JUMPING */ \ + O, /* PED_SPRINT */ \ + R3, /* PED_LOOKBEHIND */ \ + VFB(O) /* VEHICLE_FIREWEAPON */ \ + X, /* VEHICLE_ACCELERATE */ \ + Q, /* VEHICLE_BRAKE */ \ + L3, /* VEHICLE_CHANGE_RADIO_STATION */ \ + R1, /* VEHICLE_HORN */ \ + R3, /* TOGGLE_SUBMISSIONS */ \ + T, /* VEHICLE_HANDBRAKE */ \ + nil, /* PED_1RST_PERSON_LOOK_LEFT */ \ + nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \ + L2, /* VEHICLE_LOOKLEFT */ \ + R2, /* VEHICLE_LOOKRIGHT */ \ + nil, /* VEHICLE_LOOKBEHIND */ \ + nil, /* VEHICLE_TURRETLEFT */ \ + nil, /* VEHICLE_TURRETRIGHT */ \ + nil, /* VEHICLE_TURRETUP */ \ + nil, /* VEHICLE_TURRETDOWN */ \ + L2, /* PED_CYCLE_TARGET_LEFT */ \ + R2, /* PED_CYCLE_TARGET_RIGHT */ \ + T, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ + R1, /* PED_LOCK_TARGET */ \ + nil, /* NETWORK_TALK */ \ + nil, /* PED_1RST_PERSON_LOOK_UP */ \ + nil, /* PED_1RST_PERSON_LOOK_DOWN */ \ + nil, /* _CONTROLLERACTION_36 */ \ + nil, /* TOGGLE_DPAD */ \ + nil, /* SWITCH_DEBUG_CAM_ON */ \ + nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ + }, \ + { \ + R1, /* PED_FIREWEAPON */ \ + R2, /* PED_CYCLE_WEAPON_RIGHT */ \ + L2, /* PED_CYCLE_WEAPON_LEFT */ \ + nil, /* GO_FORWARD */ \ + nil, /* GO_BACK */ \ + nil, /* GO_LEFT */ \ + nil, /* GO_RIGHT */ \ + Q, /* PED_SNIPER_ZOOM_IN */ \ + X, /* PED_SNIPER_ZOOM_OUT */ \ + T, /* VEHICLE_ENTER_EXIT */ \ + SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \ + Q, /* PED_JUMPING */ \ + X, /* PED_SPRINT */ \ + R3, /* PED_LOOKBEHIND */ \ + VFB(R1) /* VEHICLE_FIREWEAPON */ \ + nil, /* VEHICLE_ACCELERATE */ \ + nil, /* VEHICLE_BRAKE */ \ + O, /* VEHICLE_CHANGE_RADIO_STATION */ \ + L3, /* VEHICLE_HORN */ \ + Q, /* TOGGLE_SUBMISSIONS */ \ + L1, /* VEHICLE_HANDBRAKE */ \ + nil, /* PED_1RST_PERSON_LOOK_LEFT */ \ + nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \ + L2, /* VEHICLE_LOOKLEFT */ \ + R2, /* VEHICLE_LOOKRIGHT */ \ + nil, /* VEHICLE_LOOKBEHIND */ \ + nil, /* VEHICLE_TURRETLEFT */ \ + nil, /* VEHICLE_TURRETRIGHT */ \ + nil, /* VEHICLE_TURRETUP */ \ + nil, /* VEHICLE_TURRETDOWN */ \ + L2, /* PED_CYCLE_TARGET_LEFT */ \ + R2, /* PED_CYCLE_TARGET_RIGHT */ \ + O, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ + L1, /* PED_LOCK_TARGET */ \ + nil, /* NETWORK_TALK */ \ + nil, /* PED_1RST_PERSON_LOOK_UP */ \ + nil, /* PED_1RST_PERSON_LOOK_DOWN */ \ + nil, /* _CONTROLLERACTION_36 */ \ + nil, /* TOGGLE_DPAD */ \ + nil, /* SWITCH_DEBUG_CAM_ON */ \ + nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ + }} + +#ifdef BUTTON_ICONS +const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK"); +#else +const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK"); #endif - nil, // VEHICLE_ACCELERATE - nil, // VEHICLE_BRAKE - "B", // VEHICLE_CHANGE_RADIO_STATION - "LS", // VEHICLE_HORN - "X", // TOGGLE_SUBMISSIONS - "LB", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "LT", // VEHICLE_LOOKLEFT - "RT", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "LT", // PED_CYCLE_TARGET_LEFT - "RT", // PED_CYCLE_TARGET_RIGHT - "B", // PED_CENTER_CAMERA_BEHIND_PLAYER - "LB", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - } -}; + #if 0 // set 1 for ps2 fonts #define PS2_TRIANGLE "\"" #define PS2_CIRCLE "|" #define PS2_CROSS "/" #define PS2_SQUARE "^" +#elif defined(BUTTON_ICONS) +#define PS2_TRIANGLE "~T~" +#define PS2_CIRCLE "~O~" +#define PS2_CROSS "~X~" +#define PS2_SQUARE "~Q~" #else #define PS2_TRIANGLE "TRIANGLE" #define PS2_CIRCLE "CIRCLE" @@ -2516,199 +2524,22 @@ const char *XboxButtons[][MAX_CONTROLLERACTIONS] = #define PS2_SQUARE "SQUARE" #endif +#ifdef BUTTON_ICONS const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] = -{ - { - PS2_CIRCLE, // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_SQUARE, // PED_SNIPER_ZOOM_IN - PS2_CROSS, // PED_SNIPER_ZOOM_OUT - PS2_TRIANGLE, // VEHICLE_ENTER_EXIT - "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CROSS, // PED_SPRINT - "R3", // PED_LOOKBEHIND -#ifdef BIND_VEHICLE_FIREWEAPON - PS2_CIRCLE, // VEHICLE_FIREWEAPON -#endif - PS2_CROSS, // VEHICLE_ACCELERATE - PS2_SQUARE, // VEHICLE_BRAKE - "L1", // VEHICLE_CHANGE_RADIO_STATION - "L3", // VEHICLE_HORN - "R3", // TOGGLE_SUBMISSIONS - "R1", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "L2", // VEHICLE_LOOKLEFT - "R2", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "L2", // PED_CYCLE_TARGET_LEFT - "R2", // PED_CYCLE_TARGET_RIGHT - "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER - "R1", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - }, - { - PS2_CIRCLE, // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_SQUARE, // PED_SNIPER_ZOOM_IN - PS2_CROSS, // PED_SNIPER_ZOOM_OUT - PS2_TRIANGLE, // VEHICLE_ENTER_EXIT - "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CROSS, // PED_SPRINT - "R3", // PED_LOOKBEHIND -#ifdef BIND_VEHICLE_FIREWEAPON - PS2_CIRCLE, // VEHICLE_FIREWEAPON -#endif - PS2_CROSS, // VEHICLE_ACCELERATE - PS2_SQUARE, // VEHICLE_BRAKE - "BACK", // VEHICLE_CHANGE_RADIO_STATION - "L1", // VEHICLE_HORN - "R3", // TOGGLE_SUBMISSIONS - "R1", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "L2", // VEHICLE_LOOKLEFT - "R2", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "L2", // PED_CYCLE_TARGET_LEFT - "R2", // PED_CYCLE_TARGET_RIGHT - "L1", // PED_CENTER_CAMERA_BEHIND_PLAYER - "R1", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - }, - { - PS2_CROSS, // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_TRIANGLE, // PED_SNIPER_ZOOM_IN - PS2_SQUARE, // PED_SNIPER_ZOOM_OUT - "L1", // VEHICLE_ENTER_EXIT - "BACK", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CIRCLE, // PED_SPRINT - "R3", // PED_LOOKBEHIND -#ifdef BIND_VEHICLE_FIREWEAPON - PS2_CIRCLE, // VEHICLE_FIREWEAPON -#endif - PS2_CROSS, // VEHICLE_ACCELERATE - PS2_SQUARE, // VEHICLE_BRAKE - "L3", // VEHICLE_CHANGE_RADIO_STATION - "R1", // VEHICLE_HORN - "R3", // TOGGLE_SUBMISSIONS - PS2_TRIANGLE, // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "L2", // VEHICLE_LOOKLEFT - "R2", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "L2", // PED_CYCLE_TARGET_LEFT - "R2", // PED_CYCLE_TARGET_RIGHT - PS2_TRIANGLE, // PED_CENTER_CAMERA_BEHIND_PLAYER - "R1", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - }, - { - "R1", // PED_FIREWEAPON - "R2", // PED_CYCLE_WEAPON_RIGHT - "L2", // PED_CYCLE_WEAPON_LEFT - nil, // GO_FORWARD - nil, // GO_BACK - nil, // GO_LEFT - nil, // GO_RIGHT - PS2_SQUARE, // PED_SNIPER_ZOOM_IN - PS2_CROSS, // PED_SNIPER_ZOOM_OUT - PS2_TRIANGLE, // VEHICLE_ENTER_EXIT - "SELECT", // CAMERA_CHANGE_VIEW_ALL_SITUATIONS - PS2_SQUARE, // PED_JUMPING - PS2_CROSS, // PED_SPRINT - "R3", // PED_LOOKBEHIND -#ifdef BIND_VEHICLE_FIREWEAPON - "R1", // VEHICLE_FIREWEAPON + CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT"); +#else +const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] = + CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT"); #endif - nil, // VEHICLE_ACCELERATE - nil, // VEHICLE_BRAKE - PS2_CIRCLE, // VEHICLE_CHANGE_RADIO_STATION - "L3", // VEHICLE_HORN - PS2_SQUARE, // TOGGLE_SUBMISSIONS - "L1", // VEHICLE_HANDBRAKE - nil, // PED_1RST_PERSON_LOOK_LEFT - nil, // PED_1RST_PERSON_LOOK_RIGHT - "L2", // VEHICLE_LOOKLEFT - "R2", // VEHICLE_LOOKRIGHT - nil, // VEHICLE_LOOKBEHIND - nil, // VEHICLE_TURRETLEFT - nil, // VEHICLE_TURRETRIGHT - nil, // VEHICLE_TURRETUP - nil, // VEHICLE_TURRETDOWN - "L2", // PED_CYCLE_TARGET_LEFT - "R2", // PED_CYCLE_TARGET_RIGHT - PS2_CIRCLE, // PED_CENTER_CAMERA_BEHIND_PLAYER - "L1", // PED_LOCK_TARGET - nil, // NETWORK_TALK - nil, // PED_1RST_PERSON_LOOK_UP - nil, // PED_1RST_PERSON_LOOK_DOWN - nil, // _CONTROLLERACTION_36 - nil, // TOGGLE_DPAD - nil, // SWITCH_DEBUG_CAM_ON - nil, // TAKE_SCREEN_SHOT - nil, // SHOW_MOUSE_POINTER_TOGGLE - } -}; #undef PS2_TRIANGLE #undef PS2_CIRCLE #undef PS2_CROSS #undef PS2_SQUARE +#undef CONTROLLER_BUTTONS +#undef VFB + void CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar *text, uint16 leight) { #ifdef DETECT_PAD_INPUT_SWITCH diff --git a/src/core/config.h b/src/core/config.h index 9af75405..bdc5cd54 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -258,6 +258,7 @@ enum Config { #define ALT_DODO_CHEAT #define REGISTER_START_BUTTON //#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls +#define BUTTON_ICONS // use textures to show controller buttons // Hud, frontend and radar #define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. diff --git a/src/render/Font.cpp b/src/render/Font.cpp index d0b554dd..6aceaf4b 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -224,6 +224,11 @@ wchar foreign_table[128] = { 0, 174, 165, 166, 167, 0, 168, 0, 0, 169, 170, 171, 172, 0, 0, 0, }; +#ifdef BUTTON_ICONS +CSprite2d CFont::ButtonSprite[MAX_BUTTON_ICONS]; +int CFont::PS2Symbol = BUTTON_NONE; +#endif // BUTTON_ICONS + void CFont::Initialise(void) { @@ -281,6 +286,31 @@ CFont::Initialise(void) SetAlphaFade(255.0f); SetDropShadowPosition(0); CTxdStore::PopCurrentTxd(); + +#ifdef BUTTON_ICONS + slot = CTxdStore::AddTxdSlot("buttons"); + CTxdStore::LoadTxd(slot, "MODELS/X360BTNS.TXD"); + CTxdStore::AddRef(slot); + CTxdStore::PushCurrentTxd(); + CTxdStore::SetCurrentTxd(slot); +#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_CROSS].SetTexture("cross"); + ButtonSprite[BUTTON_CIRCLE].SetTexture("circle"); + ButtonSprite[BUTTON_SQUARE].SetTexture("square"); + ButtonSprite[BUTTON_TRIANGLE].SetTexture("triangle"); + ButtonSprite[BUTTON_L1].SetTexture("l1"); + ButtonSprite[BUTTON_L2].SetTexture("l2"); + ButtonSprite[BUTTON_L3].SetTexture("l3"); + ButtonSprite[BUTTON_R1].SetTexture("r1"); + ButtonSprite[BUTTON_R2].SetTexture("r2"); + ButtonSprite[BUTTON_R3].SetTexture("r3"); + CTxdStore::PopCurrentTxd(); +#endif // BUTTON_ICONS } #ifdef MORE_LANGUAGES @@ -329,6 +359,11 @@ CFont::ReloadFonts(uint8 set) void CFont::Shutdown(void) { +#ifdef BUTTON_ICONS + for (int i = 0; i < MAX_BUTTON_ICONS; i++) + ButtonSprite[i].Delete(); + CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("buttons")); +#endif Sprite[0].Delete(); Sprite[1].Delete(); Sprite[2].Delete(); @@ -354,7 +389,33 @@ CFont::InitPerFrame(void) #endif SetDropShadowPosition(0); NewLine = 0; +#ifdef BUTTON_ICONS + PS2Symbol = BUTTON_NONE; +#endif +} + +#ifdef BUTTON_ICONS +void +CFont::DrawButton(float x, float y) +{ + if (x <= 0.0f || x > SCREEN_WIDTH || y <= 0.0f || y > SCREEN_HEIGHT) + return; + + if (PS2Symbol != BUTTON_NONE) { + CRect rect; + rect.left = x; + rect.top = Details.scaleY + Details.scaleY + y; + rect.right = Details.scaleY * 17.0f + x; + rect.bottom = Details.scaleY * 19.0f + y; + + int vertexAlphaState; + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, Details.color.a)); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState); + } } +#endif void CFont::PrintChar(float x, float y, wchar c) @@ -822,6 +883,15 @@ CFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, f c = *s - ' '; 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 @@ -953,6 +1023,30 @@ CFont::GetStringWidth(wchar *s, bool spaces) do { while (*s == '~' || *s == JAP_TERMINATION) { s++; +#ifdef BUTTON_ICONS + switch (*s) { +#if 0 // unused + case 'U': + case 'D': + case '<': + case '>': +#endif + case 'X': + case 'O': + case 'Q': + case 'T': + case 'K': + case 'M': + case 'A': + case 'J': + case 'V': + case 'C': + w += 17.0f * Details.scaleY; + break; + default: + break; + } +#endif while (!(*s == '~' || *s == JAP_TERMINATION)) s++; s++; } @@ -967,12 +1061,40 @@ CFont::GetStringWidth(wchar *s, bool spaces) for (; (*s != ' ' || spaces) && *s != '\0'; s++) { if (*s == '~') { s++; +#ifdef BUTTON_ICONS + switch (*s) { +#if 0 // unused + case 'U': + case 'D': + case '<': + case '>': +#endif + case 'X': + case 'O': + case 'Q': + case 'T': + case 'K': + case 'M': + case 'A': + case 'J': + case 'V': + case 'C': + w += 17.0f * Details.scaleY; + break; + default: + break; + } +#endif while (*s != '~') s++; +#ifndef FIX_BUGS s++; if (*s == ' ' && !spaces) break; - } - w += GetCharacterSize(*s - ' '); + } +#else + } else +#endif + w += GetCharacterSize(*s - ' '); } } return w; @@ -1026,9 +1148,11 @@ CFont::GetNextSpace(wchar *s) if(*s == '~'){ s++; while(*s != '~') s++; +#ifndef FIX_BUGS s++; if(*s == ' ') break; +#endif } } return s; @@ -1036,7 +1160,7 @@ CFont::GetNextSpace(wchar *s) #ifdef MORE_LANGUAGES wchar* -CFont::ParseToken(wchar *s, wchar*, bool japShit) +CFont::ParseToken(wchar *s, wchar* ss, bool japShit) { s++; if ((Details.color.r || Details.color.g || Details.color.b) && !japShit) { @@ -1056,13 +1180,37 @@ CFont::ParseToken(wchar *s, wchar*, bool japShit) case 'r': SetColor(CRGBA(113, 43, 73, 255)); break; 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; + 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; +#endif } } else if (IsJapanese()) { if ((*s & 0x7FFF) == 'N' || (*s & 0x7FFF) == 'n') NewLine = true; } while ((!IsJapanese() || (*s != JAP_TERMINATION)) && *s != '~') s++; +#ifdef FIX_BUGS + if (*(++s) == '~') + s = ParseToken(s, ss, japShit); + return s; +#else return s + 1; +#endif } #else wchar* @@ -1083,6 +1231,24 @@ CFont::ParseToken(wchar *s, wchar*) case 'r': SetColor(CRGBA(0x71, 0x2B, 0x49, 0xFF)); break; case 'w': SetColor(CRGBA(0xAF, 0xAF, 0xAF, 0xFF)); break; case 'y': SetColor(CRGBA(0xD2, 0xC4, 0x6A, 0xFF)); break; +#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; + 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; +#endif } while(*s != '~') s++; return s+1; diff --git a/src/render/Font.h b/src/render/Font.h index 51035601..be1eabed 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -63,6 +63,31 @@ enum #define FONT_LOCALE(style) (style) #endif +#ifdef BUTTON_ICONS +enum +{ + BUTTON_NONE = -1, +#if 0 // unused + BUTTON_UP, + BUTTON_DOWN, + BUTTON_LEFT, + BUTTON_RIGHT, +#endif + BUTTON_CROSS, + BUTTON_CIRCLE, + BUTTON_SQUARE, + BUTTON_TRIANGLE, + BUTTON_L1, + BUTTON_L2, + BUTTON_L3, + BUTTON_R1, + BUTTON_R2, + BUTTON_R3, + MAX_BUTTON_ICONS +}; +#endif // BUTTON_ICONS + + class CFont { #ifdef MORE_LANGUAGES @@ -77,6 +102,14 @@ public: static CSprite2d Sprite[MAX_FONTS]; static CFontDetails Details; +#ifdef BUTTON_ICONS + static CSprite2d ButtonSprite[MAX_BUTTON_ICONS]; + static int PS2Symbol; + + static void DrawButton(float x, float y); +#endif // BUTTON_ICONS + + static void Initialise(void); static void Shutdown(void); static void InitPerFrame(void); -- cgit v1.2.3 From 8614f6862050d5e13c7a351cb4fafb4b983a8390 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 5 Nov 2020 16:42:42 +0100 Subject: RwRenderStateGet --- src/fakerw/fake.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'src') diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index b9ff0144..58b3277a 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -462,6 +462,53 @@ RwBool RwIm3DRenderPrimitive(RwPrimitiveType primType); +RwBool RwRenderStateGet(RwRenderState state, void *value) +{ + uint32 *uival = (uint32*)value; + uint32 fog; + switch(state){ + case rwRENDERSTATETEXTURERASTER: *(void**)value = GetRenderStatePtr(TEXTURERASTER); return true; + case rwRENDERSTATETEXTUREADDRESS: *uival = GetRenderState(TEXTUREADDRESS); return true; + case rwRENDERSTATETEXTUREADDRESSU: *uival = GetRenderState(TEXTUREADDRESSU); return true; + case rwRENDERSTATETEXTUREADDRESSV: *uival = GetRenderState(TEXTUREADDRESSV); return true; + case rwRENDERSTATETEXTUREPERSPECTIVE: *uival = 1; return true; + case rwRENDERSTATEZTESTENABLE: *uival = GetRenderState(ZTESTENABLE); return true; + case rwRENDERSTATESHADEMODE: *uival = rwSHADEMODEGOURAUD; return true; + case rwRENDERSTATEZWRITEENABLE: *uival = GetRenderState(ZWRITEENABLE); return true; + case rwRENDERSTATETEXTUREFILTER: *uival = GetRenderState(TEXTUREFILTER); return true; + case rwRENDERSTATESRCBLEND: *uival = GetRenderState(SRCBLEND); return true; + case rwRENDERSTATEDESTBLEND: *uival = GetRenderState(DESTBLEND); return true; + case rwRENDERSTATEVERTEXALPHAENABLE: *uival = GetRenderState(VERTEXALPHA); return true; + case rwRENDERSTATEBORDERCOLOR: *uival = 0; return true; + case rwRENDERSTATEFOGENABLE: *uival = GetRenderState(FOGENABLE); return true; + case rwRENDERSTATEFOGCOLOR: + // have to swap R and B here + fog = GetRenderState(FOGCOLOR); + *uival = (fog>>16)&0xFF; + *uival |= (fog&0xFF)<<16; + *uival |= fog&0xFF00; + *uival |= fog&0xFF000000; + return true; + case rwRENDERSTATEFOGTYPE: *uival = rwFOGTYPELINEAR; return true; + case rwRENDERSTATEFOGDENSITY: *(float*)value = 1.0f; return true; + case rwRENDERSTATECULLMODE: *uival = GetRenderState(CULLMODE); return true; + + // all unsupported + case rwRENDERSTATEFOGTABLE: + case rwRENDERSTATEALPHAPRIMITIVEBUFFER: + + case rwRENDERSTATESTENCILENABLE: + case rwRENDERSTATESTENCILFAIL: + case rwRENDERSTATESTENCILZFAIL: + case rwRENDERSTATESTENCILPASS: + case rwRENDERSTATESTENCILFUNCTION: + case rwRENDERSTATESTENCILFUNCTIONREF: + case rwRENDERSTATESTENCILFUNCTIONMASK: + case rwRENDERSTATESTENCILFUNCTIONWRITEMASK: + default: + return false; + } +} RwBool RwRenderStateSet(RwRenderState state, void *value) { uint32 uival = (uintptr)value; -- cgit v1.2.3 From bd78b5ff4e4d909c7d290b2a1bc823397ca3f930 Mon Sep 17 00:00:00 2001 From: withmorten Date: Thu, 5 Nov 2020 19:57:13 +0100 Subject: add bInvertLook4Pad from VC (doesn't get saved yet) --- src/core/Frontend.cpp | 5 +++++ src/core/Frontend.h | 3 +++ src/core/Pad.cpp | 19 ++++++++++++++++++- src/core/Pad.h | 3 +++ src/core/config.h | 1 + 5 files changed, 30 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index cf25e1b9..879bcb29 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5404,6 +5404,11 @@ CMenuManager::ProcessOnOffMenuOptions() DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; +#ifdef INVERT_LOOK_FOR_PAD + case MENUACTION_INVERTPADY: + CPad::bInvertLook4Pad = !CPad::bInvertLook4Pad; + break; +#endif } } diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 70b4cd31..947311b6 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -383,6 +383,9 @@ enum eMenuAction //#ifdef NO_ISLAND_LOADING // MENUACTION_ISLANDLOADING, //#endif +#ifdef INVERT_LOOK_FOR_PAD + MENUACTION_INVERTPADY, +#endif }; enum eCheckHover diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 0e2f06a6..104c8b40 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -59,6 +59,9 @@ bool CPad::bDisplayNoControllerMessage; bool CPad::bObsoleteControllerMessage; bool CPad::bOldDisplayNoControllerMessage; bool CPad::m_bMapPadOneToPadTwo; +#ifdef INVERT_LOOK_FOR_PAD +bool CPad::bInvertLook4Pad; +#endif #ifdef GTA_PS2 unsigned char act_direct[6]; unsigned char act_align[6]; @@ -2534,10 +2537,20 @@ int16 CPad::SniperModeLookLeftRight(void) int16 CPad::SniperModeLookUpDown(void) { int16 axis = NewState.LeftStickY; + int16 dpad; #ifdef FIX_BUGS axis = -axis; #endif - int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; +#ifndef INVERT_LOOK_FOR_PAD + dpad = (NewState.DPadUp - NewState.DPadDown) / 2; +#else + if (CPad::bInvertLook4Pad) { + axis = -axis; + dpad = (NewState.DPadDown - NewState.DPadUp) / 2; + } else { + dpad = (NewState.DPadUp - NewState.DPadDown) / 2; + } +#endif if ( Abs(axis) > Abs(dpad) ) return axis; @@ -2567,6 +2580,10 @@ int16 CPad::LookAroundUpDown(void) #ifdef FIX_BUGS axis = -axis; #endif +#ifdef INVERT_LOOK_FOR_PAD + if (CPad::bInvertLook4Pad) + axis = -axis; +#endif if ( Abs(axis) > 85 && !GetLookBehindForPed() ) return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) ) diff --git a/src/core/Pad.h b/src/core/Pad.h index 8c5d7ba3..20a676ef 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -170,6 +170,9 @@ public: static bool bObsoleteControllerMessage; static bool bOldDisplayNoControllerMessage; static bool m_bMapPadOneToPadTwo; +#ifdef INVERT_LOOK_FOR_PAD + static bool bInvertLook4Pad; +#endif static CKeyboardState OldKeyState; static CKeyboardState NewKeyState; diff --git a/src/core/config.h b/src/core/config.h index bdc5cd54..e604699d 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -259,6 +259,7 @@ enum Config { #define REGISTER_START_BUTTON //#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls #define BUTTON_ICONS // use textures to show controller buttons +#define INVERT_LOOK_FOR_PAD // add bInvertLook4Pad from VC // Hud, frontend and radar #define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. -- cgit v1.2.3 From f442793d201bd905c38c4861c564ba2896b8cd88 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Tue, 3 Nov 2020 18:00:10 +0100 Subject: Allow to handle larger files via 64bit variables --- src/core/CdStream.cpp | 9 ++++++++- src/core/CdStreamPosix.cpp | 2 +- src/core/config.h | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp index c11fb72a..1d39aa52 100644 --- a/src/core/CdStream.cpp +++ b/src/core/CdStream.cpp @@ -242,8 +242,15 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size) else return STREAM_SUCCESS; } - + +#ifdef BIG_IMG + LARGE_INTEGER liDistanceToMove; + liDistanceToMove.QuadPart = _GET_OFFSET(offset); + liDistanceToMove.QuadPart *= CDSTREAM_SECTOR_SIZE; + SetFilePointerEx(hImage, liDistanceToMove, nil, FILE_BEGIN); +#else SetFilePointer(hImage, _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE, nil, FILE_BEGIN); +#endif DWORD NumberOfBytesRead; diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index 5c8d1b16..35a90a74 100644 --- a/src/core/CdStreamPosix.cpp +++ b/src/core/CdStreamPosix.cpp @@ -429,7 +429,7 @@ void *CdStreamThread(void *param) ASSERT(pChannel->hFile >= 0); ASSERT(pChannel->pBuffer != nil ); - lseek(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, SEEK_SET); + lseek(pChannel->hFile, (size_t)pChannel->nSectorOffset * (size_t)CDSTREAM_SECTOR_SIZE, SEEK_SET); if (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) { // pChannel->nSectorsToRead == 0 at this point means we wanted to flush channel // STREAM_WAITING is a little hack to make CStreaming not process this data diff --git a/src/core/config.h b/src/core/config.h index bdc5cd54..48e616bd 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -326,6 +326,8 @@ enum Config { #endif //#define PS2_AUDIO // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS +// IMG +#define BIG_IMG // allows to read larger img files //#define SQUEEZE_PERFORMANCE #ifdef SQUEEZE_PERFORMANCE -- cgit v1.2.3 From 3b81eaa2d74b6f820f2651b6e468588b514ea5c9 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 7 Nov 2020 12:59:53 +0200 Subject: Fix cAudioManager::GetPhrase --- src/audio/AudioLogic.cpp | 796 +++++++++++++++++++++++------------------------ src/audio/AudioManager.h | 2 +- 2 files changed, 399 insertions(+), 399 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 3fc9334f..6bfe3cde 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -3992,15 +3992,15 @@ cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) } void -cAudioManager::GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const +cAudioManager::GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const { - *phrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset; + phrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset; // check if the same sfx like last time, if yes, then try use next one, // if exceeded range, then choose first available sample - if (*phrase == *prevPhrase && ++*phrase >= sample + maxOffset) - *phrase = sample; - *prevPhrase = *phrase; + if (phrase == prevPhrase && ++phrase >= sample + maxOffset) + phrase = sample; + prevPhrase = phrase; } #pragma region PED_COMMENTS @@ -4013,13 +4013,13 @@ cAudioManager::GetPlayerTalkSfx(int16 sound) switch (sound) { case SOUND_PED_DAMAGE: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIGH_DAMAGE_GRUNT_1, 11); + GetPhrase(sfx, lastSfx, SFX_CLAUDE_HIGH_DAMAGE_GRUNT_1, 11); break; case SOUND_PED_HIT: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_LOW_DAMAGE_GRUNT_1, 10); + GetPhrase(sfx, lastSfx, SFX_CLAUDE_LOW_DAMAGE_GRUNT_1, 10); break; case SOUND_PED_LAND: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIT_GROUND_GRUNT_1, 6); + GetPhrase(sfx, lastSfx, SFX_CLAUDE_HIT_GROUND_GRUNT_1, 6); break; default: sfx = NO_SAMPLE; @@ -4037,13 +4037,13 @@ cAudioManager::GetCopTalkSfx(int16 sound) switch (sound) { case SOUND_PED_ARREST_COP: - GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_ARREST_1, 6); + GetPhrase(sfx, lastSfx, SFX_COP_VOICE_1_ARREST_1, 6); break; case SOUND_PED_PURSUIT_COP: pedState = FindPlayerPed()->m_nPedState; if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_CHASE_1, 7); + GetPhrase(sfx, lastSfx, SFX_COP_VOICE_1_CHASE_1, 7); break; default: return GetGenericMaleTalkSfx(sound); @@ -4061,13 +4061,13 @@ cAudioManager::GetSwatTalkSfx(int16 sound) switch (sound) { case SOUND_PED_ARREST_SWAT: - GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); + GetPhrase(sfx, lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); break; case SOUND_PED_PURSUIT_SWAT: pedState = FindPlayerPed()->m_nPedState; if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); + GetPhrase(sfx, lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -4085,13 +4085,13 @@ cAudioManager::GetFBITalkSfx(int16 sound) switch (sound) { case SOUND_PED_ARREST_FBI: - GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); + GetPhrase(sfx, lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); break; case SOUND_PED_PURSUIT_FBI: pedState = FindPlayerPed()->m_nPedState; if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); + GetPhrase(sfx, lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -4111,7 +4111,7 @@ cAudioManager::GetArmyTalkSfx(int16 sound) case SOUND_PED_PURSUIT_ARMY: pedState = FindPlayerPed()->m_nPedState; if(pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15); + GetPhrase(sfx, lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15); break; default: return GetGenericMaleTalkSfx(sound); } @@ -4127,19 +4127,19 @@ cAudioManager::GetMedicTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GUN_PANIC_1, 5); + GetPhrase(sfx, lastSfx, SFX_MEDIC_VOICE_1_GUN_PANIC_1, 5); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_CARJACKED_1, 5); + GetPhrase(sfx, lastSfx, SFX_MEDIC_VOICE_1_CARJACKED_1, 5); break; case SOUND_PED_HEALING: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_AT_VICTIM_1, 12); + GetPhrase(sfx, lastSfx, SFX_MEDIC_VOICE_1_AT_VICTIM_1, 12); break; case SOUND_PED_LEAVE_VEHICLE: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GET_OUT_VAN_CHAT_1, 9); + GetPhrase(sfx, lastSfx, SFX_MEDIC_VOICE_1_GET_OUT_VAN_CHAT_1, 9); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_RUN_FROM_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_MEDIC_VOICE_1_RUN_FROM_FIGHT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -4161,28 +4161,28 @@ cAudioManager::GetNormalMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DODGE_1, 9); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_DODGE_1, 9); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_EYING_1, 8); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_EYING_1, 8); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CHAT_1, 25); + GetPhrase(sfx, lastSfx, SFX_NORMAL_MALE_CHAT_1, 25); break; default: return GetGenericMaleTalkSfx(sound); @@ -4198,10 +4198,10 @@ cAudioManager::GetTaxiDriverTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); + GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -4218,25 +4218,25 @@ cAudioManager::GetPimpTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_GUN_COOL_1, 7); + GetPhrase(sfx, lastSfx, SFX_PIMP_GUN_COOL_1, 7); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_CARJACKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_PIMP_CARJACKED_1, 4); break; case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_FIGHT_1, 9); + GetPhrase(sfx, lastSfx, SFX_PIMP_FIGHT_1, 9); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_PIMP_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_SHOCKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_PIMP_SHOCKED_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_CHAT_1, 17); + GetPhrase(sfx, lastSfx, SFX_PIMP_CHAT_1, 17); break; default: return GetGenericMaleTalkSfx(sound); @@ -4252,25 +4252,25 @@ cAudioManager::GetMafiaTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKING_1, 2); + GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKING_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_MAFIA_MALE_VOICE_1_CHAT_1, 7); break; default: return GetGenericMaleTalkSfx(sound); @@ -4286,28 +4286,28 @@ cAudioManager::GetTriadTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_GUN_COOL_1, 3); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_GUN_COOL_1, 3); break; case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKING_1, 2); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKING_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CHAT_1, 8); + GetPhrase(sfx, lastSfx, SFX_TRIAD_MALE_VOICE_1_CHAT_1, 8); break; default: return GetGenericMaleTalkSfx(sound); @@ -4323,32 +4323,32 @@ cAudioManager::GetDiabloTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_GUN_COOL_1, 4); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_GUN_COOL_1, 4); break; case SOUND_PED_HANDS_COWER: sound = SOUND_PED_FLEE_SPRINT; return GetGenericMaleTalkSfx(sound); break; case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKING_1, 2); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKING_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_EYING_1, 4); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_EYING_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_DIABLO_MALE_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -4364,22 +4364,22 @@ cAudioManager::GetYakuzaTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKING_1, 2); + GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKING_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_YAKUZA_MALE_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -4398,25 +4398,25 @@ cAudioManager::GetYardieTalkSfx(int16 sound) sfx = SFX_YARDIE_MALE_VOICE_1_GUN_COOL_1; break; case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CARJACKING_1, 2); + GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_CARJACKING_1, 2); break; case SOUND_PED_CAR_JACKED: sfx = SFX_YARDIE_MALE_VOICE_1_CARJACKED_1; break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_FIGHT_1, 6); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_EYING_1, 2); + GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_EYING_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CHAT_1, 8); + GetPhrase(sfx, lastSfx, SFX_YARDIE_MALE_VOICE_1_CHAT_1, 8); break; default: return GetGenericMaleTalkSfx(sound); @@ -4432,25 +4432,25 @@ cAudioManager::GetColumbianTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKING_1, 2); + GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKING_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_EYING_1, 2); + GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_EYING_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -4466,28 +4466,28 @@ cAudioManager::GetHoodTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_GUN_COOL_1, 5); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_GUN_COOL_1, 5); break; case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKING_1, 2); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKING_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_FIGHT_1, 6); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_EYING_1, 2); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_EYING_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_HOOD_MALE_VOICE_1_CHAT_1, 6); break; default: @@ -4505,22 +4505,22 @@ cAudioManager::GetBlackCriminalTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_GUN_COOL_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_GUN_COOL_1, 4); break; case SOUND_PED_CAR_JACKING: sfx = SFX_BLACK_CRIMINAL_VOICE_1_CARJACKING_1; break; case SOUND_PED_MUGGING: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_MUGGING_1, 2); + GetPhrase(sfx, lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_MUGGING_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -4537,22 +4537,22 @@ cAudioManager::GetWhiteCriminalTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_GUN_COOL_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_GUN_COOL_1, 3); break; case SOUND_PED_CAR_JACKING: sfx = SFX_WHITE_CRIMINAL_VOICE_1_CARJACKING_1; break; case SOUND_PED_MUGGING: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_MUGGING_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_MUGGING_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4); break; default: return GetGenericMaleTalkSfx(sound); @@ -4569,25 +4569,25 @@ cAudioManager::GetMaleNo2TalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CARJACKED_1, 3); + GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CARJACKED_1, 3); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_MUGGED_1, 4); + GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_MUGGED_1, 4); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_EYING_1, 5); + GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_EYING_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CHAT_1, 7); break; default: return GetGenericMaleTalkSfx(sound); @@ -4602,14 +4602,14 @@ cAudioManager::GetBlackProjectMaleTalkSfx(int16 sound, int32 model) static uint32 lastSfx = NO_SAMPLE; switch(sound) { - case SOUND_PED_HANDS_UP: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3); break; - case SOUND_PED_CAR_JACKED: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2); break; - case SOUND_PED_ROBBED: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2); break; - case SOUND_PED_ATTACK: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6); break; - case SOUND_PED_EVADE: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5); break; - case SOUND_PED_ANNOYED_DRIVER: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7); break; - case SOUND_PED_CHAT_SEXY: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3); break; - case SOUND_PED_CHAT: GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6); break; + case SOUND_PED_HANDS_UP: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3); break; + case SOUND_PED_CAR_JACKED: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2); break; + case SOUND_PED_ROBBED: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2); break; + case SOUND_PED_ATTACK: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6); break; + case SOUND_PED_EVADE: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5); break; + case SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7); break; + case SOUND_PED_CHAT_SEXY: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3); break; + case SOUND_PED_CHAT: GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); } @@ -4625,12 +4625,12 @@ cAudioManager::GetWhiteFatMaleTalkSfx(int16 sound) static uint32 lastSfx = NO_SAMPLE; switch(sound) { - case SOUND_PED_CAR_JACKED: GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3); break; - case SOUND_PED_ROBBED: GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3); break; - case SOUND_PED_EVADE: GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9); break; - case SOUND_PED_ANNOYED_DRIVER: GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9); break; - case SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2); break; - case SOUND_PED_CHAT: GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9); break; + case SOUND_PED_CAR_JACKED: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3); break; + case SOUND_PED_ROBBED: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3); break; + case SOUND_PED_EVADE: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9); break; + case SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9); break; + case SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2); break; + case SOUND_PED_CHAT: GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9); break; default: return GetGenericMaleTalkSfx(sound); } return sfx; @@ -4644,22 +4644,22 @@ cAudioManager::GetBlackFatMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8); break; default: return GetGenericMaleTalkSfx(sound); @@ -4675,28 +4675,28 @@ cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_GUN_PANIC_1, 2); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_GUN_PANIC_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_MUGGED_1, 3); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_MUGGED_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_DODGE_1, 6); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_RUN_FROM_FIGHT_1, 2); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_RUN_FROM_FIGHT_1, 2); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CHAT_1, 8); + GetPhrase(sfx, lastSfx, SFX_FEMALE_1_VOICE_1_CHAT_1, 8); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4712,28 +4712,28 @@ cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_GUN_PANIC_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_GUN_PANIC_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: sfx = SFX_WHITE_CASUAL_FEMALE_VOICE_1_MUGGED_1; break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DODGE_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DODGE_1, 3); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 2); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); + GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_SHOCKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_SHOCKED_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CHAT_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CHAT_1, 4); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4749,28 +4749,28 @@ cAudioManager::GetFemaleNo3TalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_GUN_PANIC_1, 5); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_GUN_PANIC_1, 5); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CARJACKED_1, 3); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_CARJACKED_1, 3); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_MUGGED_1, 3); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_MUGGED_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_DODGE_1, 6); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_RUN_FROM_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_RUN_FROM_FIGHT_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_FEMALE_3_VOICE_1_CHAT_1, 5); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4786,25 +4786,25 @@ cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_SHOCKED_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_SHOCKED_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CHAT_1, 7); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4820,25 +4820,25 @@ cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); + GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); break; case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_LOST_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_LOST_1, 2); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CHAT_1, 8); + GetPhrase(sfx, lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CHAT_1, 8); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4854,25 +4854,25 @@ cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_GUN_COOL_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_GUN_COOL_1, 4); break; case SOUND_PED_ROBBED: sfx = SFX_BLACK_PROSTITUTE_VOICE_1_MUGGED_1; break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DODGE_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DODGE_1, 3); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); break; case SOUND_PED_SOLICIT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_SOLICIT_1, 8); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_SOLICIT_1, 8); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1, 4); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4888,22 +4888,22 @@ cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound) switch (sound) { case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DODGE_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DODGE_1, 3); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); break; case SOUND_PED_SOLICIT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_SOLICIT_1, 8); + GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_SOLICIT_1, 8); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1, 4); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4919,25 +4919,25 @@ cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CARJACKED_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CARJACKED_1, 6); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DODGE_1, 10); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DODGE_1, 10); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_RUN_FROM_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_RUN_FROM_FIGHT_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_SHOCKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_SHOCKED_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CHAT_1, 10); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CHAT_1, 10); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4953,25 +4953,25 @@ cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_CAR_JACKED: sfx = SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CARJACKED_1; break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_SHOCKED_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_SHOCKED_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CHAT_1, 7); break; default: return GetGenericFemaleTalkSfx(sound); @@ -4987,25 +4987,25 @@ cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CHAT_1, 7); break; default: return GetGenericMaleTalkSfx(sound); @@ -5021,25 +5021,25 @@ cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 2); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 2); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_FIGHT_1, 6); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -5055,22 +5055,22 @@ cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT_EVENT: sfx = SFX_CHINATOWN_OLD_FEMALE_VOICE_1_SHOCKED_1; break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5086,22 +5086,22 @@ cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CHAT_1, 7); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5117,25 +5117,25 @@ cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -5151,22 +5151,22 @@ cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CHAT_1, 7); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5182,22 +5182,22 @@ cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DODGE_1, 7); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DODGE_1, 7); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5213,22 +5213,22 @@ cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_GUN_PANIC_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_GUN_PANIC_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_FIGHT_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_FIGHT_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -5244,22 +5244,22 @@ cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_DOCKER_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -5275,28 +5275,28 @@ cAudioManager::GetScumMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_GUN_PANIC_1, 5); + GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_GUN_PANIC_1, 5); break; case SOUND_PED_ROBBED: sfx = SFX_SCUM_MALE_VOICE_1_MUGGED_1; break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_FIGHT_1, 10); + GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_FIGHT_1, 10); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_LOST_1, 3); + GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_LOST_1, 3); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_EYING_1, 5); + GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_EYING_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_CHAT_1, 9); + GetPhrase(sfx, lastSfx, SFX_SCUM_MALE_VOICE_1_CHAT_1, 9); break; default: return GetGenericMaleTalkSfx(sound); @@ -5312,22 +5312,22 @@ cAudioManager::GetScumFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DODGE_1, 8); + GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_DODGE_1, 8); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_CHAT_1, 13); + GetPhrase(sfx, lastSfx, SFX_SCUM_FEMALE_VOICE_1_CHAT_1, 13); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5343,22 +5343,22 @@ cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_FIGHT_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_FIGHT_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_EYING_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_EYING_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -5374,22 +5374,22 @@ cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_FIGHT_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_FIGHT_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DODGE_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DODGE_1, 3); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_CHAT_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_CHAT_1, 4); break; default: return GetGenericMaleTalkSfx(sound); @@ -5405,28 +5405,28 @@ cAudioManager::GetBusinessMaleYoungTalkSfx(int16 sound, int32 model) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -5445,28 +5445,28 @@ cAudioManager::GetBusinessMaleOldTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -5482,28 +5482,28 @@ cAudioManager::GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5522,28 +5522,28 @@ cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 5); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CARAJACKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CARAJACKED_1, 4); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); break; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5559,25 +5559,25 @@ cAudioManager::GetSupermodelMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_MODEL_MALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -5593,22 +5593,22 @@ cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_MUGGED_1, 3); + GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_MUGGED_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_SHOCKED_1, 5); + GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_SHOCKED_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_CHAT_1, 8); + GetPhrase(sfx, lastSfx, SFX_MODEL_FEMALE_VOICE_1_CHAT_1, 8); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5624,19 +5624,19 @@ cAudioManager::GetStewardMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_STEWARD_MALE_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_STEWARD_MALE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DODGE_1, 3); + GetPhrase(sfx, lastSfx, SFX_STEWARD_MALE_VOICE_1_DODGE_1, 3); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_STEWARD_MALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_CHAT_1, 4); + GetPhrase(sfx, lastSfx, SFX_STEWARD_MALE_VOICE_1_CHAT_1, 4); break; default: return GetGenericMaleTalkSfx(sound); @@ -5652,16 +5652,16 @@ cAudioManager::GetStewardFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_STEWARD_FEMALE_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_STEWARD_FEMALE_VOICE_1_CHAT_1, 5); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5677,19 +5677,19 @@ cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model) switch (sound) { case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_FIGHT_1, 3); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_MALE_VOICE_1_FIGHT_1, 3); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_SHOCKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_MALE_VOICE_1_SHOCKED_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_MALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericMaleTalkSfx(sound); @@ -5711,16 +5711,16 @@ cAudioManager::GetFanFemaleTalkSfx(int16 sound) sfx = SFX_FOOTBALL_FEMALE_VOICE_1_MUGGED_1; break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_SHOCKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_SHOCKED_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5736,19 +5736,19 @@ cAudioManager::GetHospitalMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_MALE_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_MALE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_MALE_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -5764,13 +5764,13 @@ cAudioManager::GetHospitalFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_CHAT_1, 6); + GetPhrase(sfx, lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_CHAT_1, 6); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5786,25 +5786,25 @@ cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: sfx = SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CARJACKED_1; break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DRIVER_ABUSE_1, 4); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_EYING_1, 3); + GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_EYING_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CHAT_1, 7); break; default: return GetGenericMaleTalkSfx(sound); @@ -5820,25 +5820,25 @@ cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_GUN_PANIC_1, 3); + GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_GUN_PANIC_1, 3); break; case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_FIGHT_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_FIGHT_1, 5); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DODGE_1, 5); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DRIVER_ABUSE_1, 5); break; case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_EYING_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_EYING_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CHAT_1, 4); + GetPhrase(sfx, lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CHAT_1, 4); break; default: return GetGenericMaleTalkSfx(sound); @@ -5854,22 +5854,22 @@ cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model) switch (sound) { case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CARJACKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_CARJACKED_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DODGE_1, 6); + GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_DODGE_1, 6); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1, 7); + GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1, 7); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_SHOCKED_1, 4); + GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_SHOCKED_1, 4); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CHAT_1, 7); + GetPhrase(sfx, lastSfx, SFX_SHOPPER_VOICE_1_CHAT_1, 7); break; default: return GetGenericFemaleTalkSfx(sound); @@ -5891,25 +5891,25 @@ cAudioManager::GetStudentMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_GUN_PANIC_1, 2); + GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_GUN_PANIC_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_DRIVER_ABUSE_1, 4); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_SHOCKED_1, 3); + GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_SHOCKED_1, 3); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_CHAT_1, 5); + GetPhrase(sfx, lastSfx, SFX_STUDENT_MALE_VOICE_1_CHAT_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -5925,25 +5925,25 @@ cAudioManager::GetStudentFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_GUN_PANIC_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_GUN_PANIC_1, 4); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DODGE_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DODGE_1, 4); break; case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 4); break; case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_SHOCKED_1, 2); + GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_SHOCKED_1, 2); break; case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_CHAT_1, 4); + GetPhrase(sfx, lastSfx, SFX_STUDENT_FEMALE_VOICE_1_CHAT_1, 4); break; default: return GetGenericFemaleTalkSfx(sound); @@ -6002,16 +6002,16 @@ cAudioManager::GetEightTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_GUN_COOL_1, 2); + GetPhrase(sfx, lastSfx, SFX_8BALL_GUN_COOL_1, 2); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_8BALL_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_8BALL_FIGHT_1, 6); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_DODGE_1, 7); + GetPhrase(sfx, lastSfx, SFX_8BALL_DODGE_1, 7); break; default: return GetGenericMaleTalkSfx(sound); @@ -6027,16 +6027,16 @@ cAudioManager::GetFrankieTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_GUN_COOL_1, 4); + GetPhrase(sfx, lastSfx, SFX_SALVATORE_GUN_COOL_1, 4); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_SALVATORE_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_FIGHT_1, 6); + GetPhrase(sfx, lastSfx, SFX_SALVATORE_FIGHT_1, 6); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_DODGE_1, 3); + GetPhrase(sfx, lastSfx, SFX_SALVATORE_DODGE_1, 3); break; default: return GetGenericMaleTalkSfx(sound); @@ -6052,19 +6052,19 @@ cAudioManager::GetMistyTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_GUN_COOL_1, 5); + GetPhrase(sfx, lastSfx, SFX_MISTY_GUN_COOL_1, 5); break; case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_MUGGED_1, 2); + GetPhrase(sfx, lastSfx, SFX_MISTY_MUGGED_1, 2); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_FIGHT_1, 4); + GetPhrase(sfx, lastSfx, SFX_MISTY_FIGHT_1, 4); break; case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_DODGE_1, 5); + GetPhrase(sfx, lastSfx, SFX_MISTY_DODGE_1, 5); break; case SOUND_PED_TAXI_CALL: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_HERE_1, 4); + GetPhrase(sfx, lastSfx, SFX_MISTY_HERE_1, 4); break; default: return GetGenericFemaleTalkSfx(sound); @@ -6094,7 +6094,7 @@ cAudioManager::GetBomberTalkSfx(int16 sound) switch (sound) { case SOUND_PED_BOMBER: - GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7); + GetPhrase(sfx, lastSfx, SFX_BOMBERMAN_1, 7); break; default: return GetGenericMaleTalkSfx(sound); @@ -6110,23 +6110,23 @@ cAudioManager::GetSecurityGuardTalkSfx(int16 sound) switch (sound) { case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_GUN_COOL_1, 2); + GetPhrase(sfx, lastSfx, SFX_SECURITY_GUARD_VOICE_1_GUN_COOL_1, 2); break; case SOUND_PED_HANDS_COWER: sfx = SFX_SECURITY_GUARD_VOICE_1_GUN_PANIC_1; break; case SOUND_PED_CAR_JACKED: case SOUND_PED_ANNOYED_DRIVER: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 6); + GetPhrase(sfx, lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 6); break; case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_FIGHT_1, 2); + GetPhrase(sfx, lastSfx, SFX_SECURITY_GUARD_VOICE_1_FIGHT_1, 2); break; case SOUND_PED_FLEE_RUN: #ifdef FIX_BUGS sfx = SFX_SECURITY_GUARD_VOICE_1_RUN_FROM_FIGHT_1; #else - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 12); + GetPhrase(sfx, lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 12); #endif break; default: @@ -6146,7 +6146,7 @@ cAudioManager::GetChunkyTalkSfx(int16 sound) case SOUND_PED_DEATH: return SFX_CHUNKY_DEATH; case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5); + GetPhrase(sfx, lastSfx, SFX_CHUNKY_RUN_1, 5); break; default: return GetGenericMaleTalkSfx(sound); @@ -6163,17 +6163,17 @@ cAudioManager::GetGenericMaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_DEATH: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_DEATH_1, 8); + GetPhrase(sfx, lastSfx, SFX_GENERIC_MALE_DEATH_1, 8); break; case SOUND_PED_BULLET_HIT: case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_GRUNT_1, 15); + GetPhrase(sfx, lastSfx, SFX_GENERIC_MALE_GRUNT_1, 15); break; case SOUND_PED_BURNING: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_FIRE_1, 8); + GetPhrase(sfx, lastSfx, SFX_GENERIC_MALE_FIRE_1, 8); break; case SOUND_PED_FLEE_SPRINT: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_PANIC_1, 6); + GetPhrase(sfx, lastSfx, SFX_GENERIC_MALE_PANIC_1, 6); break; default: return NO_SAMPLE; @@ -6189,17 +6189,17 @@ cAudioManager::GetGenericFemaleTalkSfx(int16 sound) switch (sound) { case SOUND_PED_DEATH: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_DEATH_1, 10); + GetPhrase(sfx, lastSfx, SFX_GENERIC_FEMALE_DEATH_1, 10); break; case SOUND_PED_BULLET_HIT: case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_GRUNT_1, 11); + GetPhrase(sfx, lastSfx, SFX_GENERIC_FEMALE_GRUNT_1, 11); break; case SOUND_PED_BURNING: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9); + GetPhrase(sfx, lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9); break; case SOUND_PED_FLEE_SPRINT: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8); + GetPhrase(sfx, lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8); break; default: return NO_SAMPLE; diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 40a2d056..cf6363bc 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -332,7 +332,7 @@ public: int8 GetMissionScriptPoliceAudioPlayingStatus() const; uint8 GetNum3DProvidersAvailable() const; int32 GetPedCommentSfx(CPed *ped, int32 sound); - void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const; + void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const; float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange); float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, -- cgit v1.2.3 From 7f4498e0f09a51bce527760c8f3ec1b94dde1e77 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 7 Nov 2020 20:54:38 +0200 Subject: Check if buttons txd exsist --- src/core/ControllerConfig.cpp | 17 ++++++++----- src/render/Font.cpp | 55 +++++++++++++++++++++++++------------------ src/render/Font.h | 1 + 3 files changed, 44 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 504b832c..cadba7f2 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -2500,10 +2500,11 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ }} + +const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK"); + #ifdef BUTTON_ICONS const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK"); -#else -const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK"); #endif @@ -2524,12 +2525,12 @@ const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", #define PS2_SQUARE "SQUARE" #endif +const char *PlayStationButtons_noIcons[][MAX_CONTROLLERACTIONS] = + CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT"); + #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"); -#else -const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] = - CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT"); #endif #undef PS2_TRIANGLE @@ -2547,7 +2548,11 @@ void CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar * wchar wstr[16]; // TODO: INI and/or menu setting for Xbox/PS switch - const char *(*Buttons)[MAX_CONTROLLERACTIONS] = XboxButtons; +#ifdef BUTTON_ICONS + const char *(*Buttons)[MAX_CONTROLLERACTIONS] = CFont::ButtonsSlot != -1 ? XboxButtons : XboxButtons_noIcons; +#else + const char *(*Buttons)[MAX_CONTROLLERACTIONS] = XboxButtons_noIcons; +#endif assert(Buttons[CPad::GetPad(0)->Mode][action] != nil); // we cannot use these AsciiToUnicode(Buttons[CPad::GetPad(0)->Mode][action], wstr); diff --git a/src/render/Font.cpp b/src/render/Font.cpp index 6aceaf4b..719dffce 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -3,6 +3,9 @@ #include "Sprite2d.h" #include "TxdStore.h" #include "Font.h" +#ifdef BUTTON_ICONS +#include "FileMgr.h" +#endif void AsciiToUnicode(const char *src, wchar *dst) @@ -227,6 +230,7 @@ wchar foreign_table[128] = { #ifdef BUTTON_ICONS CSprite2d CFont::ButtonSprite[MAX_BUTTON_ICONS]; int CFont::PS2Symbol = BUTTON_NONE; +int CFont::ButtonsSlot = -1; #endif // BUTTON_ICONS void @@ -288,28 +292,31 @@ CFont::Initialise(void) CTxdStore::PopCurrentTxd(); #ifdef BUTTON_ICONS - slot = CTxdStore::AddTxdSlot("buttons"); - CTxdStore::LoadTxd(slot, "MODELS/X360BTNS.TXD"); - CTxdStore::AddRef(slot); - CTxdStore::PushCurrentTxd(); - CTxdStore::SetCurrentTxd(slot); + if (int file = CFileMgr::OpenFile("MODELS/X360BTNS.TXD")) { + CFileMgr::CloseFile(file); + ButtonsSlot = CTxdStore::AddTxdSlot("buttons"); + CTxdStore::LoadTxd(ButtonsSlot, "MODELS/X360BTNS.TXD"); + 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"); + ButtonSprite[BUTTON_UP].SetTexture("up"); + ButtonSprite[BUTTON_DOWN].SetTexture("down"); + ButtonSprite[BUTTON_LEFT].SetTexture("left"); + ButtonSprite[BUTTON_RIGHT].SetTexture("right"); #endif - ButtonSprite[BUTTON_CROSS].SetTexture("cross"); - ButtonSprite[BUTTON_CIRCLE].SetTexture("circle"); - ButtonSprite[BUTTON_SQUARE].SetTexture("square"); - ButtonSprite[BUTTON_TRIANGLE].SetTexture("triangle"); - ButtonSprite[BUTTON_L1].SetTexture("l1"); - ButtonSprite[BUTTON_L2].SetTexture("l2"); - ButtonSprite[BUTTON_L3].SetTexture("l3"); - ButtonSprite[BUTTON_R1].SetTexture("r1"); - ButtonSprite[BUTTON_R2].SetTexture("r2"); - ButtonSprite[BUTTON_R3].SetTexture("r3"); - CTxdStore::PopCurrentTxd(); + ButtonSprite[BUTTON_CROSS].SetTexture("cross"); + ButtonSprite[BUTTON_CIRCLE].SetTexture("circle"); + ButtonSprite[BUTTON_SQUARE].SetTexture("square"); + ButtonSprite[BUTTON_TRIANGLE].SetTexture("triangle"); + ButtonSprite[BUTTON_L1].SetTexture("l1"); + ButtonSprite[BUTTON_L2].SetTexture("l2"); + ButtonSprite[BUTTON_L3].SetTexture("l3"); + ButtonSprite[BUTTON_R1].SetTexture("r1"); + ButtonSprite[BUTTON_R2].SetTexture("r2"); + ButtonSprite[BUTTON_R3].SetTexture("r3"); + CTxdStore::PopCurrentTxd(); + } #endif // BUTTON_ICONS } @@ -360,9 +367,11 @@ void CFont::Shutdown(void) { #ifdef BUTTON_ICONS - for (int i = 0; i < MAX_BUTTON_ICONS; i++) - ButtonSprite[i].Delete(); - CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("buttons")); + if (ButtonsSlot != -1) { + for (int i = 0; i < MAX_BUTTON_ICONS; i++) + ButtonSprite[i].Delete(); + CTxdStore::RemoveTxdSlot(ButtonsSlot); + } #endif Sprite[0].Delete(); Sprite[1].Delete(); diff --git a/src/render/Font.h b/src/render/Font.h index be1eabed..bf747859 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -103,6 +103,7 @@ public: static CFontDetails Details; #ifdef BUTTON_ICONS + static int32 ButtonsSlot; static CSprite2d ButtonSprite[MAX_BUTTON_ICONS]; static int PS2Symbol; -- cgit v1.2.3 From 163c12608fa972e6bed225ac6cb56d0a68279f06 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sat, 7 Nov 2020 18:04:01 +0300 Subject: Fix build without CFO, NO_ISLAND_LOADING, save postfx/pipeline mults --- src/core/Frontend.cpp | 110 ----------------------------------------- src/core/Frontend.h | 10 ++-- src/core/Frontend_PS2.cpp | 14 ------ src/core/Frontend_PS2.h | 22 --------- src/core/MenuScreens.cpp | 11 +++++ src/core/MenuScreensCustom.cpp | 65 ++++++++++++++++++++++++ src/core/config.h | 25 +++++----- src/core/re3.cpp | 48 ++++++++++++------ 8 files changed, 125 insertions(+), 180 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index cf25e1b9..8221ad4f 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -122,7 +122,6 @@ int8 CMenuManager::m_nDisplayMSAALevel = 0; #endif #ifdef NO_ISLAND_LOADING -int8 CMenuManager::m_DisplayIslandLoading = ISLAND_LOADING_LOW; int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW; #endif @@ -1236,21 +1235,6 @@ CMenuManager::Draw() AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp); rightText = unicodeTemp; break; -//#ifdef NO_ISLAND_LOADING -// case MENUACTION_ISLANDLOADING: -// switch (m_DisplayIslandLoading) { -// case ISLAND_LOADING_LOW: -// rightText = TheText.Get("FEM_LOW"); -// break; -// case ISLAND_LOADING_MEDIUM: -// rightText = TheText.Get("FEM_MED"); -// break; -// case ISLAND_LOADING_HIGH: -// rightText = TheText.Get("FEM_HIG"); -// break; -// } -// break; -//#endif case MENUACTION_AUDIOHW: if (m_nPrefsAudio3DProviderIndex == -1) rightText = TheText.Get("FEA_NAH"); @@ -1430,12 +1414,6 @@ CMenuManager::Draw() if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") && m_nHelperTextMsgId == 1) ResetHelperText(); } -//#ifdef NO_ISLAND_LOADING -// if (m_DisplayIslandLoading == m_PrefsIslandLoading) { -// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL") && m_nHelperTextMsgId == 1) -// ResetHelperText(); -// } -//#endif if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH")) SetHelperText(1); @@ -1444,12 +1422,6 @@ CMenuManager::Draw() if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES")) SetHelperText(1); } -//#ifdef NO_ISLAND_LOADING -// if (m_DisplayIslandLoading != m_PrefsIslandLoading) { -// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL")) -// SetHelperText(1); -// } -//#endif if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 // To make assigning built-in actions to new custom options possible. @@ -4822,45 +4794,6 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); } break; -//#ifdef NO_ISLAND_LOADING -// case MENUACTION_ISLANDLOADING: -// if (m_DisplayIslandLoading != m_PrefsIslandLoading) { -// if (!m_bGameNotLoaded) { -// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) { -// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH) -// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); -// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) { -// if (CGame::currLevel != LEVEL_INDUSTRIAL) -// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); -// if (CGame::currLevel != LEVEL_COMMERCIAL) -// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); -// if (CGame::currLevel != LEVEL_SUBURBAN) -// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); -// CCollision::bAlreadyLoaded = true; -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// CStreaming::RequestBigBuildings(CGame::currLevel); -// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) { -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// CStreaming::RequestIslands(CGame::currLevel); -// } else -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// } else { // low -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// CCollision::bAlreadyLoaded = false; -// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); -// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); -// CStreaming::RemoveUnusedBuildings(CGame::currLevel); -// CStreaming::RequestIslands(CGame::currLevel); -// } -// -// CStreaming::LoadAllRequestedModels(true); -// } else -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// SetHelperText(0); -// SaveSettings(); -// } -// break; -//#endif case MENUACTION_AUDIOHW: { int selectedProvider = m_nPrefsAudio3DProviderIndex; @@ -4935,40 +4868,6 @@ CMenuManager::ProcessButtonPresses(void) RestoreDefGraphics(FEOPTION_ACTION_SELECT); RestoreDefDisplay(FEOPTION_ACTION_SELECT); #endif -//#ifdef NO_ISLAND_LOADING -// m_DisplayIslandLoading = ISLAND_LOADING_LOW; -// if (!m_bGameNotLoaded) { -// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) { -// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH) -// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); -// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) { -// if (CGame::currLevel != LEVEL_INDUSTRIAL) -// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); -// if (CGame::currLevel != LEVEL_COMMERCIAL) -// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); -// if (CGame::currLevel != LEVEL_SUBURBAN) -// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); -// CCollision::bAlreadyLoaded = true; -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// CStreaming::RequestBigBuildings(CGame::currLevel); -// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) { -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// CStreaming::RequestIslands(CGame::currLevel); -// } else -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// } else { // low -// m_PrefsIslandLoading = m_DisplayIslandLoading; -// CCollision::bAlreadyLoaded = false; -// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); -// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); -// CStreaming::RemoveUnusedBuildings(CGame::currLevel); -// CStreaming::RequestIslands(CGame::currLevel); -// } -// -// CStreaming::LoadAllRequestedModels(true); -// } else -// m_PrefsIslandLoading = m_DisplayIslandLoading; -//#endif // NO_ISLAND_LOADING SaveSettings(); } else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { ControlsManager.MakeControllerActionsBlank(); @@ -5228,15 +5127,6 @@ CMenuManager::ProcessButtonPresses(void) } } break; -//#ifdef NO_ISLAND_LOADING -// case MENUACTION_ISLANDLOADING: -// m_DisplayIslandLoading += changeValueBy; -// if (m_DisplayIslandLoading > ISLAND_LOADING_HIGH) -// m_DisplayIslandLoading = ISLAND_LOADING_LOW; -// else if (m_DisplayIslandLoading < ISLAND_LOADING_LOW) -// m_DisplayIslandLoading = ISLAND_LOADING_HIGH; -// break; -//#endif case MENUACTION_AUDIOHW: if (m_nPrefsAudio3DProviderIndex != -1) { m_nPrefsAudio3DProviderIndex += changeValueBy; diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 70b4cd31..fba98690 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -235,11 +235,11 @@ enum eMenuScreen MENUPAGE_KEYBOARD_CONTROLS = 55, MENUPAGE_MOUSE_CONTROLS = 56, MENUPAGE_MISSION_RETRY = 57, -#ifdef CUSTOM_FRONTEND_OPTIONS - #ifdef MENU_MAP - MENUPAGE_MAP, + MENUPAGE_MAP = 58, #endif +#ifdef CUSTOM_FRONTEND_OPTIONS + #ifdef GRAPHICS_MENU_OPTIONS MENUPAGE_GRAPHICS_SETTINGS, #else @@ -380,9 +380,6 @@ enum eMenuAction // MENUACTION_MIPMAPS, // MENUACTION_TEXTURE_FILTERING, //#endif -//#ifdef NO_ISLAND_LOADING -// MENUACTION_ISLANDLOADING, -//#endif }; enum eCheckHover @@ -718,7 +715,6 @@ public: ISLAND_LOADING_HIGH }; - static int8 m_DisplayIslandLoading; static int8 m_PrefsIslandLoading; #define ISLAND_LOADING_IS(p) if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p) diff --git a/src/core/Frontend_PS2.cpp b/src/core/Frontend_PS2.cpp index a1d802f2..824f342b 100644 --- a/src/core/Frontend_PS2.cpp +++ b/src/core/Frontend_PS2.cpp @@ -203,20 +203,6 @@ static const char* FrontendFilenames[][2] = {"fe_radio9", "" }, }; -#ifdef CUTSCENE_BORDERS_SWITCH -bool CMenuManager::m_PrefsCutsceneBorders = true; -#endif - -#ifdef MULTISAMPLING -int8 CMenuManager::m_nPrefsMSAALevel = 0; -int8 CMenuManager::m_nDisplayMSAALevel = 0; -#endif - -#ifdef NO_ISLAND_LOADING -int8 CMenuManager::m_DisplayIslandLoading = ISLAND_LOADING_LOW; -int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW; -#endif - int32 CMenuManager::m_PrefsSfxVolume = 102; int32 CMenuManager::m_PrefsMusicVolume = 102; int32 CMenuManager::m_PrefsBrightness = 256; diff --git a/src/core/Frontend_PS2.h b/src/core/Frontend_PS2.h index c1e42291..4bab7df9 100644 --- a/src/core/Frontend_PS2.h +++ b/src/core/Frontend_PS2.h @@ -160,31 +160,9 @@ public: static int32 m_PrefsLanguage; static CONTRCONFIG m_PrefsControllerConfig; static bool m_PrefsUseVibration; -#ifdef NO_ISLAND_LOADING - enum - { - ISLAND_LOADING_LOW = 0, - ISLAND_LOADING_MEDIUM, - ISLAND_LOADING_HIGH - }; - - static int8 m_DisplayIslandLoading; - static int8 m_PrefsIslandLoading; -#define ISLAND_LOADING_IS(p) if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p) -#define ISLAND_LOADING_ISNT(p) if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_##p) -#else #define ISLAND_LOADING_IS(p) #define ISLAND_LOADING_ISNT(p) -#endif -#ifdef CUTSCENE_BORDERS_SWITCH - static bool m_PrefsCutsceneBorders; -#endif -#ifdef MULTISAMPLING - static int8 m_nPrefsMSAALevel; - static int8 m_nDisplayMSAALevel; -#endif - #ifdef GTA_PC bool m_bQuitGameNoCD; diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp index c2eadb3b..9eff09e6 100644 --- a/src/core/MenuScreens.cpp +++ b/src/core/MenuScreens.cpp @@ -392,6 +392,9 @@ CMenuScreen aScreens[MENUPAGES] = { { "FET_PAU", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, +#ifdef MENU_MAP + MENUACTION_CHANGEMENU, "FEG_MAP", SAVESLOT_NONE, MENUPAGE_MAP, +#endif MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS, MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS, MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, @@ -436,6 +439,14 @@ CMenuScreen aScreens[MENUPAGES] = { }, #endif +#ifdef MENU_MAP + // MENUPAGE_MAP + { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 2, + MENUACTION_UNK110, "", SAVESLOT_NONE, MENUPAGE_NONE, // to prevent cross/enter to go back + MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + }, +#endif + // MENUPAGE_UNK { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0, diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index fb0888fc..b92d5325 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -11,6 +11,10 @@ #include "custompipes.h" #include "RwHelper.h" #include "Text.h" +#include "Streaming.h" +#include "FileLoader.h" +#include "Collision.h" +#include "ModelInfo.h" // Menu screens array is at the bottom of the file. @@ -48,6 +52,12 @@ #define DUALPASS_SELECTOR #endif +#ifdef NO_ISLAND_LOADING + #define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, "FEM_ISL", { new CCFOSelect((int8*)&CMenuManager::m_PrefsIslandLoading, "IslandLoading", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) }, +#else + #define ISLAND_LOADING_SELECTOR +#endif + #ifdef EXTENDED_COLOURFILTER #define POSTFX_SELECTORS \ MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \ @@ -80,6 +90,18 @@ void RestoreDefGraphics(int8 action) { #ifdef MULTISAMPLING FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0; #endif + #ifdef NO_ISLAND_LOADING + if (FrontEndMenuManager.m_bGameNotLoaded) { + FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW; + CCollision::bAlreadyLoaded = false; + CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); + CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); + CStreaming::RemoveUnusedBuildings(CGame::currLevel); + CStreaming::RequestIslands(CGame::currLevel); + CStreaming::LoadAllRequestedModels(true); + } else + FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW; + #endif #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those CMenuManager::m_PrefsFrameLimiter = true; CMenuManager::m_PrefsVsyncDisp = true; @@ -120,6 +142,47 @@ void RestoreDefDisplay(int8 action) { #endif } +#ifdef NO_ISLAND_LOADING +const char *islandLoadingOpts[] = { "FEM_LOW", "FEM_MED", "FEM_HIG" }; +void IslandLoadingAfterChange(int8 before, int8 after) { + if (!FrontEndMenuManager.m_bGameNotLoaded) { + if (after > FrontEndMenuManager.ISLAND_LOADING_LOW) { + FrontEndMenuManager.m_PrefsIslandLoading = before; // calls below needs previous mode :shrug: + + if (after == FrontEndMenuManager.ISLAND_LOADING_HIGH) + CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); + if (before == FrontEndMenuManager.ISLAND_LOADING_LOW) { + if (CGame::currLevel != LEVEL_INDUSTRIAL) + CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); + if (CGame::currLevel != LEVEL_COMMERCIAL) + CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); + if (CGame::currLevel != LEVEL_SUBURBAN) + CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); + CCollision::bAlreadyLoaded = true; + FrontEndMenuManager.m_PrefsIslandLoading = after; + CStreaming::RequestBigBuildings(CGame::currLevel); + + } else if (before == FrontEndMenuManager.ISLAND_LOADING_HIGH) { + FrontEndMenuManager.m_PrefsIslandLoading = after; + CStreaming::RequestIslands(CGame::currLevel); + } else + FrontEndMenuManager.m_PrefsIslandLoading = after; + + } else { // low + CCollision::bAlreadyLoaded = false; + CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); + CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); + CStreaming::RemoveUnusedBuildings(CGame::currLevel); + CStreaming::RequestIslands(CGame::currLevel); + } + + CStreaming::LoadAllRequestedModels(true); + } + + FrontEndMenuManager.SetHelperText(0); +} +#endif + #ifdef MORE_LANGUAGES void LangPolSelect(int8 action) { @@ -761,6 +824,7 @@ CMenuScreenCustom aScreens[MENUPAGES] = { #ifdef EXTENDED_PIPELINES PIPELINES_SELECTOR #endif + ISLAND_LOADING_SELECTOR DUALPASS_SELECTOR MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefGraphics) }, MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, @@ -770,6 +834,7 @@ CMenuScreenCustom aScreens[MENUPAGES] = { { "FET_ADV", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil, + ISLAND_LOADING_SELECTOR DUALPASS_SELECTOR CUTSCENE_BORDERS_TOGGLE FREE_CAM_TOGGLE diff --git a/src/core/config.h b/src/core/config.h index 48e616bd..a55b018e 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -212,10 +212,10 @@ enum Config { # define TIMEBARS // print debug timers #endif -#define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more +#define FIX_BUGS // fixes bugs that we've came across during reversing #define MORE_LANGUAGES // Add more translations to the game #define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible -#define LOAD_INI_SETTINGS +#define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS // Rendering/display //#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering @@ -227,19 +227,11 @@ enum Config { #define PS2_ALPHA_TEST // emulate ps2 alpha test #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number #define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time -#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL -#define CUTSCENE_BORDERS_SWITCH #ifdef LIBRW //#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) //#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) #endif -#define MULTISAMPLING // adds MSAA option - -#ifdef LIBRW -// these are not supported with librw yet -# undef MULTISAMPLING -#endif // Particle //#define PC_PARTICLE @@ -277,7 +269,13 @@ enum Config { //# define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc. //# define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box # define CUSTOM_FRONTEND_OPTIONS -# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full + +# ifdef CUSTOM_FRONTEND_OPTIONS +# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full +# define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU +# define CUTSCENE_BORDERS_SWITCH +# define MULTISAMPLING // adds MSAA option +# endif #endif // Script @@ -336,3 +334,8 @@ enum Config { #define PC_PARTICLE #define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial #endif + +#ifdef LIBRW +// these are not supported with librw yet +# undef MULTISAMPLING +#endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index aa13ba29..6bf5573e 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -102,6 +102,26 @@ float CheckAndReadIniFloat(const char *cat, const char *key, float original) return original; } +void CheckAndSaveIniInt(const char *cat, const char *key, int val, bool &changed) +{ + char temp[10]; + if (atoi(cfg.get(cat, key, "xxx").c_str()) != val) { // if .ini doesn't have our key, compare with xxx and forcefully add it + changed = true; + sprintf(temp, "%u", val); + cfg.set(cat, key, temp); + } +} + +void CheckAndSaveIniFloat(const char *cat, const char *key, float val, bool &changed) +{ + char temp[10]; + if (atof(cfg.get(cat, key, "xxx").c_str()) != val) { // if .ini doesn't have our key, compare with xxx and forcefully add it + changed = true; + sprintf(temp, "%f", val); + cfg.set(cat, key, temp); + } +} + void LoadINISettings() { cfg.load_file("re3.ini"); @@ -156,11 +176,6 @@ void LoadINISettings() } #endif -#ifdef NO_ISLAND_LOADING - CMenuManager::m_PrefsIslandLoading = CheckAndReadIniInt("FrontendOptions", "NoIslandLoading", CMenuManager::m_PrefsIslandLoading); - CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading; -#endif - #ifdef EXTENDED_COLOURFILTER CPostFX::Intensity = CheckAndReadIniFloat("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity); #endif @@ -192,21 +207,22 @@ void SaveINISettings() break; if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) { - if (atoi(cfg.get("FrontendOptions", option.m_CFO->save, "xxx").c_str()) != *option.m_CFO->value) { // if .ini doesn't have that key compare with xxx, so we can add it - changed = true; - sprintf(temp, "%u", *option.m_CFO->value); - cfg.set("FrontendOptions", option.m_CFO->save, temp); - } + // Beware: CFO only supports saving uint8 right now + CheckAndSaveIniInt("FrontendOptions", option.m_CFO->save, *option.m_CFO->value, changed); } } } #endif -#ifdef NO_ISLAND_LOADING - if (atoi(cfg.get("FrontendOptions", "NoIslandLoading", "xxx").c_str()) != CMenuManager::m_PrefsIslandLoading) { - changed = true; - sprintf(temp, "%u", CMenuManager::m_PrefsIslandLoading); - cfg.set("FrontendOptions", "NoIslandLoading", temp); - } + +#ifdef EXTENDED_COLOURFILTER + CheckAndSaveIniFloat("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity, changed); +#endif +#ifdef EXTENDED_PIPELINES + CheckAndSaveIniFloat("CustomPipesValues", "NeoVehicleShininess", CustomPipes::VehicleShininess, changed); + CheckAndSaveIniFloat("CustomPipesValues", "NeoVehicleSpecularity", CustomPipes::VehicleSpecularity, changed); + CheckAndSaveIniFloat("CustomPipesValues", "RimlightMult", CustomPipes::RimlightMult, changed); + CheckAndSaveIniFloat("CustomPipesValues", "LightmapMult", CustomPipes::LightmapMult, changed); + CheckAndSaveIniFloat("CustomPipesValues", "GlossMult", CustomPipes::GlossMult, changed); #endif if (changed) -- cgit v1.2.3 From 279acfae593dae000cf7aacd27c8e21a6c60415b Mon Sep 17 00:00:00 2001 From: Roman Masanin <36927roma@gmail.com> Date: Sun, 8 Nov 2020 20:50:46 +0300 Subject: pointers to referencies too --- src/audio/AudioLogic.cpp | 390 +++++++++++++++++++++++------------------------ src/audio/AudioManager.h | 46 +++--- 2 files changed, 218 insertions(+), 218 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index b0827885..95e6094f 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -599,78 +599,78 @@ cAudioManager::ProcessVehicle(CVehicle *veh) case VEHICLE_TYPE_CAR: UpdateGasPedalAudio((CAutomobile *)veh); if (params.m_nIndex == RCBANDIT) { - ProcessModelCarEngine(¶ms); - ProcessVehicleOneShots(¶ms); + ProcessModelCarEngine(params); + ProcessVehicleOneShots(params); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; break; } if (params.m_nIndex == DODO) { - if (!ProcessVehicleRoadNoise(¶ms)) { - ProcessVehicleOneShots(¶ms); + if (!ProcessVehicleRoadNoise(params)) { + ProcessVehicleOneShots(params); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; break; } if (CWeather::WetRoads > 0.f) - ProcessWetRoadNoise(¶ms); - ProcessVehicleSkidding(¶ms); + ProcessWetRoadNoise(params); + ProcessVehicleSkidding(params); } else { - if (!ProcessVehicleRoadNoise(¶ms)) { - ProcessVehicleOneShots(¶ms); + if (!ProcessVehicleRoadNoise(params)) { + ProcessVehicleOneShots(params); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; break; } - ProcessReverseGear(¶ms); + ProcessReverseGear(params); if (CWeather::WetRoads > 0.f) - ProcessWetRoadNoise(¶ms); - ProcessVehicleSkidding(¶ms); - ProcessVehicleHorn(¶ms); - ProcessVehicleSirenOrAlarm(¶ms); + ProcessWetRoadNoise(params); + ProcessVehicleSkidding(params); + ProcessVehicleHorn(params); + ProcessVehicleSirenOrAlarm(params); if (UsesReverseWarning(params.m_nIndex)) - ProcessVehicleReverseWarning(¶ms); + ProcessVehicleReverseWarning(params); if (HasAirBrakes(params.m_nIndex)) - ProcessAirBrakes(¶ms); + ProcessAirBrakes(params); } - ProcessCarBombTick(¶ms); - ProcessVehicleEngine(¶ms); - ProcessEngineDamage(¶ms); - ProcessVehicleDoors(¶ms); + ProcessCarBombTick(params); + ProcessVehicleEngine(params); + ProcessEngineDamage(params); + ProcessVehicleDoors(params); - ProcessVehicleOneShots(¶ms); + ProcessVehicleOneShots(params); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; break; case VEHICLE_TYPE_BOAT: - ProcessBoatEngine(¶ms); - ProcessBoatMovingOverWater(¶ms); - ProcessVehicleOneShots(¶ms); + ProcessBoatEngine(params); + ProcessBoatMovingOverWater(params); + ProcessVehicleOneShots(params); break; case VEHICLE_TYPE_TRAIN: - ProcessTrainNoise(¶ms); - ProcessVehicleOneShots(¶ms); + ProcessTrainNoise(params); + ProcessVehicleOneShots(params); break; case VEHICLE_TYPE_HELI: - ProcessHelicopter(¶ms); - ProcessVehicleOneShots(¶ms); + ProcessHelicopter(params); + ProcessVehicleOneShots(params); break; case VEHICLE_TYPE_PLANE: - ProcessPlane(¶ms); - ProcessVehicleOneShots(¶ms); + ProcessPlane(params); + ProcessVehicleOneShots(params); break; default: break; } - ProcessRainOnVehicle(¶ms); + ProcessRainOnVehicle(params); } void -cAudioManager::ProcessRainOnVehicle(cVehicleParams *params) +cAudioManager::ProcessRainOnVehicle(cVehicleParams& params) { const int rainOnVehicleIntensity = 22; - if (params->m_fDistance < SQR(rainOnVehicleIntensity) && CWeather::Rain > 0.01f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) { - CVehicle *veh = params->m_pVehicle; + if (params.m_fDistance < SQR(rainOnVehicleIntensity) && CWeather::Rain > 0.01f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) { + CVehicle *veh = params.m_pVehicle; ++veh->m_bRainAudioCounter; if (veh->m_bRainAudioCounter >= 2) { veh->m_bRainAudioCounter = 0; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); float emittingVol = 30.f * CWeather::Rain; m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, rainOnVehicleIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { @@ -698,7 +698,7 @@ cAudioManager::ProcessRainOnVehicle(cVehicleParams *params) } bool -cAudioManager::ProcessReverseGear(cVehicleParams *params) +cAudioManager::ProcessReverseGear(cVehicleParams& params) { const int reverseGearIntensity = 30; @@ -707,14 +707,14 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params) int32 emittingVol; float modificator; - if (params->m_fDistance >= SQR(reverseGearIntensity)) + if (params.m_fDistance >= SQR(reverseGearIntensity)) return false; - veh = params->m_pVehicle; + veh = params.m_pVehicle; if (veh->bEngineOn && (veh->m_fGasPedal < 0.0f || veh->m_nCurrentGear == 0)) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - automobile = (CAutomobile *)params->m_pVehicle; + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); + automobile = (CAutomobile *)params.m_pVehicle; if (automobile->m_nWheelsOnGround != 0) { - modificator = params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity; + modificator = params.m_fVelocityChange / params.m_pTransmission->fMaxReverseVelocity; } else { if (automobile->m_nDriveWheelsOnGround != 0) automobile->m_fGasPedalAudio *= 0.4f; @@ -724,7 +724,7 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params) emittingVol = (24.f * modificator); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, reverseGearIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { - if (params->m_pVehicle->m_fGasPedal >= 0.0f) { + if (params.m_pVehicle->m_fGasPedal >= 0.0f) { m_sQueueSample.m_nCounter = 62; m_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR_2; } else { @@ -752,7 +752,7 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params) } void -cAudioManager::ProcessModelCarEngine(cVehicleParams *params) +cAudioManager::ProcessModelCarEngine(cVehicleParams& params) { const float SOUND_INTENSITY = 30.0f; CAutomobile *automobile; @@ -760,24 +760,24 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params) int32 emittingVol; float velocityChange; - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { - automobile = (CAutomobile *)params->m_pVehicle; + if (params.m_fDistance < SQR(SOUND_INTENSITY)) { + automobile = (CAutomobile *)params.m_pVehicle; if (automobile->bEngineOn) { if (automobile->m_nWheelsOnGround == 0) { if (automobile->m_nDriveWheelsOnGround != 0) automobile->m_fGasPedalAudio *= 0.4f; - velocityChange = automobile->m_fGasPedalAudio * params->m_pTransmission->fMaxVelocity; + velocityChange = automobile->m_fGasPedalAudio * params.m_pTransmission->fMaxVelocity; } else { - velocityChange = Abs(params->m_fVelocityChange); + velocityChange = Abs(params.m_fVelocityChange); } if (velocityChange > 0.001f) { - allowedVelocity = 0.5f * params->m_pTransmission->fMaxVelocity; + allowedVelocity = 0.5f * params.m_pTransmission->fMaxVelocity; if (velocityChange < allowedVelocity) emittingVol = (90.f * velocityChange / allowedVelocity); else emittingVol = 90; if (emittingVol) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 30.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 2; @@ -785,7 +785,7 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params) m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = (11025.f * velocityChange / params->m_pTransmission->fMaxVelocity + 11025.f); + m_sQueueSample.m_nFrequency = (11025.f * velocityChange / params.m_pTransmission->fMaxVelocity + 11025.f); m_sQueueSample.m_nLoopCount = 0; m_sQueueSample.m_nEmittingVolume = emittingVol; m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); @@ -807,7 +807,7 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params) bool -cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) +cAudioManager::ProcessVehicleRoadNoise(cVehicleParams& params) { const float SOUND_INTENSITY = 95.0f; @@ -817,21 +817,21 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) int sampleFreq; float velocity; - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + if (params.m_fDistance >= SQR(SOUND_INTENSITY)) return false; - if (params->m_pTransmission != nil) { - if (((CAutomobile*)params->m_pVehicle)->m_nDriveWheelsOnGround != 0) { - velocity = Abs(params->m_fVelocityChange); + if (params.m_pTransmission != nil) { + if (((CAutomobile*)params.m_pVehicle)->m_nDriveWheelsOnGround != 0) { + velocity = Abs(params.m_fVelocityChange); if (velocity > 0.0f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - emittingVol = 30.f * Min(1.f, velocity / (0.5f * params->m_pTransmission->fMaxVelocity)); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); + emittingVol = 30.f * Min(1.f, velocity / (0.5f * params.m_pTransmission->fMaxVelocity)); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 0; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nReleasingVolumeModificator = 3; - if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_WATER) { + if (params.m_pVehicle->m_nSurfaceTouched == SURFACE_WATER) { m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; freq = 6050 * emittingVol / 30 + 16000; } else { @@ -860,7 +860,7 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) } bool -cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) +cAudioManager::ProcessWetRoadNoise(cVehicleParams& params) { const float SOUND_INTENSITY = 30.0f; @@ -870,14 +870,14 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) int freq; float velChange; - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + if (params.m_fDistance >= SQR(SOUND_INTENSITY)) return false; - if (params->m_pTransmission != nil) { - if (((CAutomobile *)params->m_pVehicle)->m_nDriveWheelsOnGround != 0) { - velChange = Abs(params->m_fVelocityChange); + if (params.m_pTransmission != nil) { + if (((CAutomobile *)params.m_pVehicle)->m_nDriveWheelsOnGround != 0) { + velChange = Abs(params.m_fVelocityChange); if (velChange > 0.f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - relativeVelocity = Min(1.0f, velChange / (0.5f * params->m_pTransmission->fMaxVelocity)); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); + relativeVelocity = Min(1.0f, velChange / (0.5f * params.m_pTransmission->fMaxVelocity)); emittingVol = 23.0f * relativeVelocity * CWeather::WetRoads; m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { @@ -912,7 +912,7 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) } void -cAudioManager::ProcessVehicleEngine(cVehicleParams *params) +cAudioManager::ProcessVehicleEngine(cVehicleParams& params) { const float SOUND_INTENSITY = 50.0f; @@ -929,17 +929,17 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) float modificator; float traction = 0.f; - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { + if (params.m_fDistance < SQR(SOUND_INTENSITY)) { playerVeh = FindPlayerVehicle(); - veh = params->m_pVehicle; + veh = params.m_pVehicle; if (playerVeh == veh && veh->GetStatus() == STATUS_WRECKED) { SampleManager.StopChannel(m_nActiveSamples); return; } if (veh->bEngineOn) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - automobile = (CAutomobile *)params->m_pVehicle; - if (params->m_nIndex == DODO) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); + automobile = (CAutomobile *)params.m_pVehicle; + if (params.m_nIndex == DODO) { ProcessCesna(params); return; } @@ -947,14 +947,14 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) ProcessPlayersVehicleEngine(params, automobile); return; } - transmission = params->m_pTransmission; + transmission = params.m_pTransmission; if (transmission != nil) { - currentGear = params->m_pVehicle->m_nCurrentGear; + currentGear = params.m_pVehicle->m_nCurrentGear; if (automobile->m_nWheelsOnGround != 0) { if (automobile->bIsHandbrakeOn) { - if (params->m_fVelocityChange == 0.0f) + if (params.m_fVelocityChange == 0.0f) traction = 0.9f; - } else if (params->m_pVehicle->GetStatus() == STATUS_SIMPLE) { + } else if (params.m_pVehicle->GetStatus() == STATUS_SIMPLE) { traction = 0.0f; } else { switch (transmission->nDriveType) { @@ -982,15 +982,15 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) relativeChange = 0.f; } else if (currentGear != 0) { relativeGearChange = - Min(1.0f, (params->m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f); + Min(1.0f, (params.m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f); if (traction == 0.0f && automobile->GetStatus() != STATUS_SIMPLE && - params->m_fVelocityChange < transmission->Gears[1].fShiftUpVelocity) { + params.m_fVelocityChange < transmission->Gears[1].fShiftUpVelocity) { traction = 0.7f; } relativeChange = traction * automobile->m_fGasPedalAudio * 0.95f + (1.0f - traction) * relativeGearChange; } else relativeChange = - Min(1.0f, 1.0f - Abs((params->m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity)); + Min(1.0f, 1.0f - Abs((params.m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity)); } else { if (automobile->m_nDriveWheelsOnGround != 0) automobile->m_fGasPedalAudio *= 0.4f; @@ -1017,20 +1017,20 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) if (m_sQueueSample.m_nVolume != 0) { if (automobile->GetStatus() == STATUS_SIMPLE) { if (modificator < 0.02f) { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1; freq = modificator * 10000 + 22050; m_sQueueSample.m_nCounter = 52; } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nAccelerationSampleIndex; m_sQueueSample.m_nCounter = 2; } } else { if (automobile->m_fGasPedal < 0.05f) { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1; freq = modificator * 10000 + 22050; m_sQueueSample.m_nCounter = 52; } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nAccelerationSampleIndex; m_sQueueSample.m_nCounter = 2; } } @@ -1115,14 +1115,14 @@ cAudioManager::AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sampl } void -cAudioManager::ProcessCesna(cVehicleParams *params) +cAudioManager::ProcessCesna(cVehicleParams& params) { static uint8 nAccel = 0; - //((CAutomobile *)params->m_pVehicle)->Damage.GetEngineStatus(); + //((CAutomobile *)params.m_pVehicle)->Damage.GetEngineStatus(); - if (FindPlayerVehicle() == params->m_pVehicle) { - if (params->m_nIndex == DODO) { + if (FindPlayerVehicle() == params.m_pVehicle) { + if (params.m_nIndex == DODO) { if (Pads[0].GetAccelerate() <= 0) { if (nAccel != 0) --nAccel; @@ -1132,10 +1132,10 @@ cAudioManager::ProcessCesna(cVehicleParams *params) AddPlayerCarSample(85 * (60 - nAccel) / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_IDLE, SFX_BANK_0, 52, true); AddPlayerCarSample(85 * nAccel / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_REV, SFX_BANK_0, 2, true); } - } else if (params->m_nIndex == DODO) { + } else if (params.m_nIndex == DODO) { AddPlayerCarSample(105, 17000, SFX_CESNA_IDLE, SFX_BANK_0, 52, true); - } else if (params->m_fDistance < SQR(200)) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + } else if (params.m_fDistance < SQR(200)) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, 200.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 52; @@ -1156,7 +1156,7 @@ cAudioManager::ProcessCesna(cVehicleParams *params) m_sQueueSample.m_bRequireReflection = false; AddSampleToRequestedQueue(); } - if (params->m_fDistance < SQR(90)) { + if (params.m_fDistance < SQR(90)) { m_sQueueSample.m_nVolume = ComputeVolume(80, 90.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 2; @@ -1182,7 +1182,7 @@ cAudioManager::ProcessCesna(cVehicleParams *params) } void -cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile) +cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams& params, CAutomobile *automobile) { static int32 GearFreqAdj[] = {6000, 6000, 3400, 1200, 0, -1000}; @@ -1234,13 +1234,13 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * accelerateState = Pads[0].GetAccelerate(); channelUsed = SampleManager.GetChannelUsedFlag(m_nActiveSamples); - transmission = params->m_pTransmission; - velocityChange = params->m_fVelocityChange; + transmission = params.m_pTransmission; + velocityChange = params.m_fVelocityChange; relativeVelocityChange = 2.0f * velocityChange / transmission->fMaxVelocity; accelerationMultipler = clamp(relativeVelocityChange, 0.0f, 1.0f); gasPedalAudio = accelerationMultipler; - currentGear = params->m_pVehicle->m_nCurrentGear; + currentGear = params.m_pVehicle->m_nCurrentGear; switch (transmission->nDriveType) { @@ -1265,20 +1265,20 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * } if (velocityChange != 0.0f) { - time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange; + time = params.m_pVehicle->m_vecMoveSpeed.z / velocityChange; if (time > 0.0f) freqModifier = -(Min(0.2f, time) * 3000.0f * 5.0f); else freqModifier = -(Max(-0.2f, time) * 3000.0f * 5.0f); - if (params->m_fVelocityChange < -0.001f) + if (params.m_fVelocityChange < -0.001f) freqModifier = -freqModifier; } else freqModifier = 0; - engineSoundType = aVehicleSettings[params->m_nIndex].m_nBank; + engineSoundType = aVehicleSettings[params.m_nIndex].m_nBank; soundOffset = 3 * (engineSoundType - CAR_SFX_BANKS_OFFSET); if (accelerateState <= 0) { - if (params->m_fVelocityChange < -0.001f) { + if (params.m_fVelocityChange < -0.001f) { if (channelUsed) { SampleManager.StopChannel(m_nActiveSamples); bAccelSampleStopped = true; @@ -1286,7 +1286,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * if (automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction) gasPedalAudio = automobile->m_fGasPedalAudio; else - gasPedalAudio = Min(1.0f, params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity); + gasPedalAudio = Min(1.0f, params.m_fVelocityChange / params.m_pTransmission->fMaxReverseVelocity); gasPedalAudio = Max(0.0f, gasPedalAudio); automobile->m_fGasPedalAudio = gasPedalAudio; @@ -1297,7 +1297,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * } nCruising = 0; if (automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction || - params->m_fVelocityChange < 0.01f && automobile->m_fGasPedalAudio > 0.2f) { + params.m_fVelocityChange < 0.01f && automobile->m_fGasPedalAudio > 0.2f) { automobile->m_fGasPedalAudio *= 0.6f; gasPedalAudio = automobile->m_fGasPedalAudio; } @@ -1355,7 +1355,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * if (!channelUsed) { if (!processedAccelSampleStopped) { - if (CurrentPretendGear < params->m_pTransmission->nNumberOfGears - 1) + if (CurrentPretendGear < params.m_pTransmission->nNumberOfGears - 1) ++CurrentPretendGear; else { nCruising = 1; @@ -1386,10 +1386,10 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * if (nCruising != 0) { bAccelSampleStopped = true; if (accelerateState < 150 || automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction || - currentGear < params->m_pTransmission->nNumberOfGears - 1) { + currentGear < params.m_pTransmission->nNumberOfGears - 1) { nCruising = 0; } else { - if (accelerateState >= 220 && params->m_fVelocityChange + 0.001f < automobile->m_fVelocityChangeForAudio) { + if (accelerateState >= 220 && params.m_fVelocityChange + 0.001f < automobile->m_fVelocityChangeForAudio) { if (nCruising < 800) ++nCruising; } else if (nCruising > 3) { @@ -1409,7 +1409,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * } bool -cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) +cAudioManager::ProcessVehicleSkidding(cVehicleParams& params) { const float SOUND_INTENSITY = 40.0f; @@ -1419,31 +1419,31 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) float newSkidVal = 0.0f; float skidVal = 0.0f; - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + if (params.m_fDistance >= SQR(SOUND_INTENSITY)) return false; - automobile = (CAutomobile *)params->m_pVehicle; + automobile = (CAutomobile *)params.m_pVehicle; if (automobile->m_nWheelsOnGround == 0) return true; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); for (int32 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { if (automobile->m_aWheelState[i] == WHEEL_STATE_NORMAL || automobile->Damage.GetWheelStatus(i) == WHEEL_STATUS_MISSING) continue; - transmission = params->m_pTransmission; + transmission = params.m_pTransmission; switch (transmission->nDriveType) { case '4': - newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange); break; case 'F': if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT) - newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange); else - newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange); break; case 'R': if (i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT) - newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange); else - newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params.m_fVelocityChange); break; default: break; @@ -1456,7 +1456,7 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 3; - switch (params->m_pVehicle->m_nSurfaceTouched) { + switch (params.m_pVehicle->m_nSurfaceTouched) { case SURFACE_GRASS: case SURFACE_HEDGE: m_sQueueSample.m_nSampleIndex = SFX_RAIN; @@ -1547,17 +1547,17 @@ cAudioManager::GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automo } void -cAudioManager::ProcessVehicleHorn(cVehicleParams *params) +cAudioManager::ProcessVehicleHorn(cVehicleParams& params) { const float SOUND_INTENSITY = 40.0f; CAutomobile *automobile; - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { - automobile = (CAutomobile *)params->m_pVehicle; - if ((!automobile->m_bSirenOrAlarm || !UsesSirenSwitching(params->m_nIndex)) && automobile->GetModelIndex() != MI_MRWHOOP) { + if (params.m_fDistance < SQR(SOUND_INTENSITY)) { + automobile = (CAutomobile *)params.m_pVehicle; + if ((!automobile->m_bSirenOrAlarm || !UsesSirenSwitching(params.m_nIndex)) && automobile->GetModelIndex() != MI_MRWHOOP) { if (automobile->m_nCarHornTimer) { - if (params->m_pVehicle->GetStatus() != STATUS_PLAYER) { + if (params.m_pVehicle->GetStatus() != STATUS_PLAYER) { automobile->m_nCarHornTimer = Min(44, automobile->m_nCarHornTimer); if (automobile->m_nCarHornTimer == 44) automobile->m_nCarHornPattern = (m_FrameCounter + m_sQueueSample.m_nEntityIndex) & 7; @@ -1565,15 +1565,15 @@ cAudioManager::ProcessVehicleHorn(cVehicleParams *params) return; } - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 4; - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nHornSample; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nHornSample; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nHornFrequency; + m_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nHornFrequency; m_sQueueSample.m_nLoopCount = 0; m_sQueueSample.m_nEmittingVolume = 80; m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); @@ -1622,36 +1622,36 @@ cAudioManager::UsesSirenSwitching(int32 model) const } bool -cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params) +cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams& params) { const float SOUND_INTENSITY = 110.0f; - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { - CVehicle *veh = params->m_pVehicle; + if (params.m_fDistance < SQR(SOUND_INTENSITY)) { + CVehicle *veh = params.m_pVehicle; if (veh->m_bSirenOrAlarm == false && !veh->IsAlarmOn()) return true; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 5; - if (UsesSiren(params->m_nIndex)) { - if (params->m_pVehicle->GetStatus() == STATUS_ABANDONED) + if (UsesSiren(params.m_nIndex)) { + if (params.m_pVehicle->GetStatus() == STATUS_ABANDONED) return true; - if (veh->m_nCarHornTimer && params->m_nIndex != FIRETRUK) { + if (veh->m_nCarHornTimer && params.m_nIndex != FIRETRUK) { m_sQueueSample.m_nSampleIndex = SFX_SIREN_FAST; - if (params->m_nIndex == FBICAR) + if (params.m_nIndex == FBICAR) m_sQueueSample.m_nFrequency = 16113; else m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SIREN_FAST); m_sQueueSample.m_nCounter = 60; } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample; - m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmSample; + m_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmFrequency; } } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample; - m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmSample; + m_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmFrequency; } m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_bIs2D = false; @@ -1681,17 +1681,17 @@ cAudioManager::UsesReverseWarning(int32 model) const } bool -cAudioManager::ProcessVehicleReverseWarning(cVehicleParams *params) +cAudioManager::ProcessVehicleReverseWarning(cVehicleParams& params) { const float SOUND_INTENSITY = 50.0f; - CVehicle *veh = params->m_pVehicle; + CVehicle *veh = params.m_pVehicle; - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + if (params.m_fDistance >= SQR(SOUND_INTENSITY)) return false; if (veh->bEngineOn && veh->m_fGasPedal < 0.0f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 12; @@ -1717,7 +1717,7 @@ cAudioManager::ProcessVehicleReverseWarning(cVehicleParams *params) } bool -cAudioManager::ProcessVehicleDoors(cVehicleParams *params) +cAudioManager::ProcessVehicleDoors(cVehicleParams& params) { const float SOUND_INTENSITY = 40.0f; @@ -1726,11 +1726,11 @@ cAudioManager::ProcessVehicleDoors(cVehicleParams *params) int32 emittingVol; float velocity; - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + if (params.m_fDistance >= SQR(SOUND_INTENSITY)) return false; - automobile = (CAutomobile *)params->m_pVehicle; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + automobile = (CAutomobile *)params.m_pVehicle; + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); for (int32 i = 0; i < ARRAY_SIZE(automobile->Doors); i++) { if (automobile->Damage.GetDoorStatus(i) == DOOR_STATUS_SWINGING) { doorState = automobile->Doors[i].m_nDoorState; @@ -1765,22 +1765,22 @@ cAudioManager::ProcessVehicleDoors(cVehicleParams *params) } bool -cAudioManager::ProcessAirBrakes(cVehicleParams *params) +cAudioManager::ProcessAirBrakes(cVehicleParams& params) { CAutomobile *automobile; uint8 rand; - if (params->m_fDistance > SQR(30)) + if (params.m_fDistance > SQR(30)) return false; - automobile = (CAutomobile *)params->m_pVehicle; + automobile = (CAutomobile *)params.m_pVehicle; if (!automobile->bEngineOn) return true; - if ((automobile->m_fVelocityChangeForAudio < 0.025f || params->m_fVelocityChange >= 0.025f) && - (automobile->m_fVelocityChangeForAudio > -0.025f || params->m_fVelocityChange <= 0.025f)) + if ((automobile->m_fVelocityChangeForAudio < 0.025f || params.m_fVelocityChange >= 0.025f) && + (automobile->m_fVelocityChangeForAudio > -0.025f || params.m_fVelocityChange <= 0.025f)) return true; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); rand = m_anRandomTable[0] % 10 + 70; m_sQueueSample.m_nVolume = ComputeVolume(rand, 30.0f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { @@ -1813,7 +1813,7 @@ cAudioManager::HasAirBrakes(int32 model) const } bool -cAudioManager::ProcessEngineDamage(cVehicleParams *params) +cAudioManager::ProcessEngineDamage(cVehicleParams& params) { const int engineDamageIntensity = 40; @@ -1821,9 +1821,9 @@ cAudioManager::ProcessEngineDamage(cVehicleParams *params) uint8 engineStatus; uint8 emittingVolume; - if (params->m_fDistance >= SQR(engineDamageIntensity)) + if (params.m_fDistance >= SQR(engineDamageIntensity)) return false; - veh = (CAutomobile *)params->m_pVehicle; + veh = (CAutomobile *)params.m_pVehicle; if (veh->bEngineOn) { engineStatus = veh->Damage.GetEngineStatus(); if (engineStatus > 250 || engineStatus < 100) @@ -1839,7 +1839,7 @@ cAudioManager::ProcessEngineDamage(cVehicleParams *params) m_sQueueSample.m_nReleasingVolumeModificator = 7; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); } - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, engineDamageIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 28; @@ -1862,15 +1862,15 @@ cAudioManager::ProcessEngineDamage(cVehicleParams *params) } bool -cAudioManager::ProcessCarBombTick(cVehicleParams *params) +cAudioManager::ProcessCarBombTick(cVehicleParams& params) { CAutomobile *automobile; - if (params->m_fDistance >= SQR(40.f)) + if (params.m_fDistance >= SQR(40.f)) return false; - automobile = (CAutomobile *)params->m_pVehicle; + automobile = (CAutomobile *)params.m_pVehicle; if (automobile->bEngineOn && automobile->m_bombType == CARBOMB_TIMEDACTIVE) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(60, 40.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 35; @@ -1896,7 +1896,7 @@ cAudioManager::ProcessCarBombTick(cVehicleParams *params) } void -cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) +cAudioManager::ProcessVehicleOneShots(cVehicleParams& params) { int16 event; uint8 emittingVol; @@ -1925,7 +1925,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) const float SOUND_INTENSITY = 50.0f; maxDist = SQR(SOUND_INTENSITY); emittingVol = m_anRandomTable[2] % 5 + 122; - switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { + switch (aVehicleSettings[params.m_nIndex].m_bDoorType) { case OLD_DOOR: m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_CLOSE; break; @@ -1961,7 +1961,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) const float SOUND_INTENSITY = 50.0f; maxDist = SQR(SOUND_INTENSITY); emittingVol = m_anRandomTable[1] % 10 + 117; - switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { + switch (aVehicleSettings[params.m_nIndex].m_bDoorType) { case OLD_DOOR: m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_OPEN; break; @@ -2009,7 +2009,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) iWheelIndex = 82; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TYRE_BUMP); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - if (params->m_nIndex == RCBANDIT) { + if (params.m_nIndex == RCBANDIT) { m_sQueueSample.m_nFrequency *= 2; emittingVol /= 2; } @@ -2238,16 +2238,16 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) pedParams.m_pPed = nil; pedParams.m_bDistanceCalculated = false; pedParams.m_fDistance = 0.0f; - pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated; - pedParams.m_fDistance = params->m_fDistance; + pedParams.m_bDistanceCalculated = params.m_bDistanceCalculated; + pedParams.m_fDistance = params.m_fDistance; SetupPedComments(&pedParams, SOUND_PED_HELI_PLAYER_FOUND); continue; case SOUND_PED_BODYCAST_HIT: pedParams.m_pPed = nil; pedParams.m_bDistanceCalculated = false; pedParams.m_fDistance = 0.0f; - pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated; - pedParams.m_fDistance = params->m_fDistance; + pedParams.m_bDistanceCalculated = params.m_bDistanceCalculated; + pedParams.m_fDistance = params.m_fDistance; SetupPedComments(&pedParams, SOUND_PED_BODYCAST_HIT); continue; case SOUND_WATER_FALL: { @@ -2300,8 +2300,8 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) default: continue; } - if (params->m_fDistance < maxDist) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + if (params.m_fDistance < maxDist) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { if (noReflections) { @@ -2323,7 +2323,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) } bool -cAudioManager::ProcessTrainNoise(cVehicleParams *params) +cAudioManager::ProcessTrainNoise(cVehicleParams& params) { const float SOUND_INTENSITY = 300.0f; @@ -2331,12 +2331,12 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params) uint8 emittingVol; float speedMultipler; - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + if (params.m_fDistance >= SQR(SOUND_INTENSITY)) return false; - if (params->m_fVelocityChange > 0.0f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - train = (CTrain *)params->m_pVehicle; + if (params.m_fVelocityChange > 0.0f) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); + train = (CTrain *)params.m_pVehicle; speedMultipler = Min(1.0f, train->m_fSpeed * 250.f / 51.f); emittingVol = (75.f * speedMultipler); if (train->m_fWagonPosition == 0.0f) { @@ -2362,7 +2362,7 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params) } } const float SOUND_INTENSITY = 70.0f; - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { + if (params.m_fDistance < SQR(SOUND_INTENSITY)) { m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 33; @@ -2389,7 +2389,7 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params) } bool -cAudioManager::ProcessBoatEngine(cVehicleParams *params) +cAudioManager::ProcessBoatEngine(cVehicleParams& params) { CBoat *boat; float padRelativeAccerate; @@ -2403,10 +2403,10 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) static const int intensity = 50; - if (params->m_fDistance < SQR(intensity)) { - boat = (CBoat *)params->m_pVehicle; - if (params->m_nIndex == REEFER) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + if (params.m_fDistance < SQR(intensity)) { + boat = (CBoat *)params.m_pVehicle; + if (params.m_nIndex == REEFER) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, 50.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 39; @@ -2428,7 +2428,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) m_sQueueSample.m_bRequireReflection = false; AddSampleToRequestedQueue(); } - if (FindPlayerVehicle() == params->m_pVehicle) { + if (FindPlayerVehicle() == params.m_pVehicle) { padAccelerate = Max(Pads[0].GetAccelerate(), Pads[0].GetBrake()); padRelativeAccerate = padAccelerate / 255; emittingVol = (100.f * padRelativeAccerate) + 15; @@ -2467,7 +2467,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) m_sQueueSample.m_bReverbFlag = true; m_sQueueSample.m_bRequireReflection = false; } else { - if (FindPlayerVehicle() == params->m_pVehicle) { + if (FindPlayerVehicle() == params.m_pVehicle) { padAccelerate = Max(Pads[0].GetAccelerate(), Pads[0].GetBrake()); if (padAccelerate <= 20) { emittingVol = 45 - 45 * padAccelerate / 40; @@ -2504,7 +2504,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL; } } - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 50.f, m_sQueueSample.m_fDistance); if (!m_sQueueSample.m_nVolume) return true; @@ -2530,22 +2530,22 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) } bool -cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) +cAudioManager::ProcessBoatMovingOverWater(cVehicleParams& params) { float velocityChange; int32 vol; float multiplier; - if (params->m_fDistance > SQR(50)) + if (params.m_fDistance > SQR(50)) return false; - velocityChange = Abs(params->m_fVelocityChange); - if (velocityChange <= 0.0005f && ((CBoat*)params->m_pVehicle)->bBoatInWater) + velocityChange = Abs(params.m_fVelocityChange); + if (velocityChange <= 0.0005f && ((CBoat*)params.m_pVehicle)->bBoatInWater) return true; velocityChange = Min(0.75f, velocityChange); multiplier = (velocityChange - 0.0005f) / (1499.0f / 2000.0f); - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); vol = (30.f * multiplier); m_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { @@ -2578,7 +2578,7 @@ struct tHelicopterSampleData { }; bool -cAudioManager::ProcessHelicopter(cVehicleParams *params) +cAudioManager::ProcessHelicopter(cVehicleParams& params) { CHeli *heli; float MaxDist; @@ -2587,11 +2587,11 @@ cAudioManager::ProcessHelicopter(cVehicleParams *params) int32 emittingVol; static const tHelicopterSampleData gHeliSfxRanges[3] = {{400.f, 380.f, 100}, {100.f, 70.f, MAX_VOLUME}, {60.f, 30.f, MAX_VOLUME}}; - if (SQR(gHeliSfxRanges[0].m_fMaxDistance) <= params->m_fDistance) + if (SQR(gHeliSfxRanges[0].m_fMaxDistance) <= params.m_fDistance) return false; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - heli = (CHeli *)params->m_pVehicle; + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); + heli = (CHeli *)params.m_pVehicle; for (uint32 i = 0; i < ARRAY_SIZE(gHeliSfxRanges); i++) { MaxDist = gHeliSfxRanges[i].m_fMaxDistance; dist = m_sQueueSample.m_fDistance; @@ -2628,9 +2628,9 @@ cAudioManager::ProcessHelicopter(cVehicleParams *params) } void -cAudioManager::ProcessPlane(cVehicleParams *params) +cAudioManager::ProcessPlane(cVehicleParams& params) { - switch (params->m_nIndex) { + switch (params.m_nIndex) { case AIRTRAIN: ProcessJumbo(params); break; @@ -2638,7 +2638,7 @@ cAudioManager::ProcessPlane(cVehicleParams *params) ProcessCesna(params); break; default: - debug("Plane Model Id is %d\n, ", params->m_pVehicle->GetModelIndex()); + debug("Plane Model Id is %d\n, ", params.m_pVehicle->GetModelIndex()); break; } } @@ -2654,14 +2654,14 @@ DoJumboVolOffset() } void -cAudioManager::ProcessJumbo(cVehicleParams *params) +cAudioManager::ProcessJumbo(cVehicleParams& params) { CPlane *plane; float position; - if (params->m_fDistance < SQR(440)) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - plane = (CPlane *)params->m_pVehicle; + if (params.m_fDistance < SQR(440)) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); + plane = (CPlane *)params.m_pVehicle; DoJumboVolOffset(); position = PlanePathPosition[plane->m_nPlaneId]; if (position <= TakeOffPoint) { diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index cf6363bc..2d971ac9 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -362,29 +362,29 @@ public: void PreTerminateGameSpecificShutdown(); /// processX - main logic of adding new sounds void ProcessActiveQueues(); - bool ProcessAirBrakes(cVehicleParams *params); + bool ProcessAirBrakes(cVehicleParams& params); void ProcessAirportScriptObject(uint8 sound); - bool ProcessBoatEngine(cVehicleParams *params); - bool ProcessBoatMovingOverWater(cVehicleParams *params); + bool ProcessBoatEngine(cVehicleParams& params); + bool ProcessBoatMovingOverWater(cVehicleParams& params); void ProcessBridge(); void ProcessBridgeMotor(); void ProcessBridgeOneShots(); void ProcessBridgeWarning(); - bool ProcessCarBombTick(cVehicleParams *params); - void ProcessCesna(cVehicleParams *params); + bool ProcessCarBombTick(cVehicleParams& params); + void ProcessCesna(cVehicleParams& params); void ProcessCinemaScriptObject(uint8 sound); void ProcessCrane(); void ProcessDocksScriptObject(uint8 sound); - bool ProcessEngineDamage(cVehicleParams *params); + bool ProcessEngineDamage(cVehicleParams& params); void ProcessEntity(int32 sound); void ProcessExplosions(int32 explosion); void ProcessFireHydrant(); void ProcessFires(int32 entity); void ProcessFrontEnd(); void ProcessGarages(); - bool ProcessHelicopter(cVehicleParams *params); + bool ProcessHelicopter(cVehicleParams& params); void ProcessHomeScriptObject(uint8 sound); - void ProcessJumbo(cVehicleParams *); + void ProcessJumbo(cVehicleParams& params); void ProcessJumboAccel(CPlane *plane); void ProcessJumboDecel(CPlane *plane); void ProcessJumboFlying(); @@ -394,37 +394,37 @@ public: void ProcessLaunderetteScriptObject(uint8 sound); void ProcessLoopingScriptObject(uint8 sound); void ProcessMissionAudio(); - void ProcessModelCarEngine(cVehicleParams *params); + void ProcessModelCarEngine(cVehicleParams& params); void ProcessOneShotScriptObject(uint8 sound); void ProcessPed(CPhysical *ped); void ProcessPedHeadphones(cPedParams *params); void ProcessPedOneShots(cPedParams *params); void ProcessPhysical(int32 id); - void ProcessPlane(cVehicleParams *params); - void ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile); + void ProcessPlane(cVehicleParams& params); + void ProcessPlayersVehicleEngine(cVehicleParams& params, CAutomobile *automobile); void ProcessPoliceCellBeatingScriptObject(uint8 sound); void ProcessPornCinema(uint8 sound); void ProcessProjectiles(); - void ProcessRainOnVehicle(cVehicleParams *params); + void ProcessRainOnVehicle(cVehicleParams& params); void ProcessReverb() const; - bool ProcessReverseGear(cVehicleParams *params); + bool ProcessReverseGear(cVehicleParams& params); void ProcessSawMillScriptObject(uint8 sound); void ProcessScriptObject(int32 id); void ProcessShopScriptObject(uint8 sound); void ProcessSpecial(); - bool ProcessTrainNoise(cVehicleParams *params); + bool ProcessTrainNoise(cVehicleParams& params); void ProcessVehicle(CVehicle *vehicle); - bool ProcessVehicleDoors(cVehicleParams *params); - void ProcessVehicleEngine(cVehicleParams *params); - void ProcessVehicleHorn(cVehicleParams *params); - void ProcessVehicleOneShots(cVehicleParams *params); - bool ProcessVehicleReverseWarning(cVehicleParams *params); - bool ProcessVehicleRoadNoise(cVehicleParams *params); - bool ProcessVehicleSirenOrAlarm(cVehicleParams *params); - bool ProcessVehicleSkidding(cVehicleParams *params); + bool ProcessVehicleDoors(cVehicleParams& params); + void ProcessVehicleEngine(cVehicleParams& params); + void ProcessVehicleHorn(cVehicleParams& params); + void ProcessVehicleOneShots(cVehicleParams& params); + bool ProcessVehicleReverseWarning(cVehicleParams& params); + bool ProcessVehicleRoadNoise(cVehicleParams& params); + bool ProcessVehicleSirenOrAlarm(cVehicleParams& params); + bool ProcessVehicleSkidding(cVehicleParams& params); void ProcessWaterCannon(int32); void ProcessWeather(int32 id); - bool ProcessWetRoadNoise(cVehicleParams *params); + bool ProcessWetRoadNoise(cVehicleParams& params); void ProcessWorkShopScriptObject(uint8 sound); int32 RandomDisplacement(uint32 seed) const; -- cgit v1.2.3 From f8367ebdef6d15d1b1892a3418ea8a1ed4df46b2 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sun, 8 Nov 2020 21:11:55 +0300 Subject: Revert "Font: Fix text dimensions" This reverts commit 6729de49b16da9a1be3c95b146ba053bf214c91c. --- src/audio/MusicManager.cpp | 2 +- src/control/Darkel.cpp | 4 ++-- src/control/Garages.cpp | 2 +- src/core/Frontend.cpp | 10 +++++----- src/core/Game.cpp | 8 ++++---- src/core/Pad.cpp | 4 ++-- src/core/main.cpp | 2 +- src/render/Credits.cpp | 4 ++-- src/render/Hud.cpp | 24 ++++++++++++------------ src/render/SpecialFX.cpp | 2 +- 10 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index 10862cdc..5519d899 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -161,7 +161,7 @@ cMusicManager::DisplayRadioStationName() CFont::SetPropOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation); diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index afdfcb82..793bec36 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -72,7 +72,7 @@ CDarkel::DrawMessages() { CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_X(610.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(30.0f)); CFont::SetCentreOn(); CFont::SetPropOn(); uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; @@ -132,7 +132,7 @@ CDarkel::DrawMessages() uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; if (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart < 5000) { CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); CFont::SetCentreOn(); CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); CFont::SetJustifyOff(); diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 5a04285f..61c1a850 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1400,7 +1400,7 @@ void CGarages::PrintMessages() CFont::SetPropOn(); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_X(590.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f)); CFont::SetCentreOn(); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 8221ad4f..1718218d 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -772,7 +772,7 @@ CMenuManager::Draw() CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); - CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetWrapx(SCREEN_WIDTH); CFont::SetRightJustifyWrap(0.0f); strcpy(gString, "V1.1"); AsciiToUnicode(gString, gUString); @@ -852,7 +852,7 @@ CMenuManager::Draw() #endif } - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetCentreSize(SCREEN_WIDTH); #ifdef PS2_LIKE_MENU bool itemsAreSelectable = !bottomBarActive; @@ -3490,11 +3490,11 @@ CMenuManager::MessageScreen(const char *text) CFont::SetPropOn(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // not used - CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // not used + CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); + CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); CSprite2d::DrawRect(CRect(StretchX(120.0f), StretchY(150.0f), SCREEN_WIDTH - StretchX(120.0f), SCREEN_HEIGHT - StretchY(220.0f)), CRGBA(50, 50, 50, 210)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetCentreSize(SCREEN_SCALE_X(380.0f)); + CFont::SetCentreSize(SCREEN_STRETCH_X(380.0f)); CFont::SetCentreOn(); CFont::SetColor(CRGBA(255, 217, 106, 255)); CFont::SetScale(SCREEN_SCALE_X(SMALLTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLTEXT_Y_SCALE)); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 83c75d91..3507b3b3 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -128,10 +128,10 @@ void MessageScreen(char *msg) CFont::SetFontStyle(FONT_BANK); CFont::SetBackgroundOff(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f // unused + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(450.0f)); // 450.0f + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetDropColor(CRGBA(32, 32, 32, 255)); @@ -734,10 +734,10 @@ void CGame::InitialiseWhenRestarting(void) //CFont::SetFontStyle(?); CFont::SetBackgroundOff(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f // unused + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(480.0f)); // 480.0f + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetBackGroundOnlyTextOff(); diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 0e2f06a6..e2f90a7c 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -2593,7 +2593,7 @@ void CPad::PrintErrorMessage(void) CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); + CFont::SetCentreSize(SCREEN_WIDTH - 20); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); @@ -2610,7 +2610,7 @@ void CPad::PrintErrorMessage(void) CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); + CFont::SetCentreSize(SCREEN_WIDTH - 20); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); diff --git a/src/core/main.cpp b/src/core/main.cpp index 36c94043..80feddb7 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -852,7 +852,7 @@ DisplayGameDebugText() CFont::SetRightJustifyOff(); CFont::SetJustifyOff(); CFont::SetBackGroundOnlyTextOff(); - CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetWrapx(640.0f); CFont::SetFontStyle(FONT_HEADING); CFont::SetColor(CRGBA(0, 0, 0, 255)); diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index 2c8a9952..6b28ff04 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -62,7 +62,7 @@ CCredits::Render(void) scrolloffset = (CTimer::GetTimeInMilliseconds() - CreditsStartTime) / 24.0f; CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); + CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - 20)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(220, 220, 220, 220)); @@ -496,4 +496,4 @@ CCredits::Render(void) bool CCredits::AreCreditsDone(void) { return !bCreditsGoing; -} +} \ No newline at end of file diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 3d6e59f6..4c8b6657 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -336,7 +336,7 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f)); CFont::SetJustifyOff(); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetPropOn(); CFont::SetFontStyle(FONT_BANK); @@ -740,7 +740,7 @@ void CHud::Draw() CFont::SetRightJustifyWrap(0.0f); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetColor(CRGBA(244, 20, 20, 255)); - CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); CFont::SetPropOff(); CFont::SetBackGroundOnlyTextOn(); @@ -869,8 +869,8 @@ void CHud::Draw() else CFont::SetCentreOff(); - CFont::SetWrapx(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fWrapX)); - CFont::SetCentreSize(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fCenterSize)); + CFont::SetWrapx(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fWrapX)); + CFont::SetCentreSize(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fCenterSize)); if (CTheScripts::IntroTextLines[i].m_bBackground) CFont::SetBackgroundOn(); @@ -957,12 +957,12 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f)); CFont::SetPropOn(); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(590.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(25.0f)); CFont::SetFontStyle(FONT_HEADING); // Appearently sliding text in here was abandoned very early, since this text is centered now. - if (BigMessageX[0] >= SCALE_AND_CENTER_X(620.0f)) { + if (BigMessageX[0] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { BigMessageInUse[0] += CTimer::GetTimeStep(); if (BigMessageInUse[0] >= 120.0f) { @@ -997,7 +997,7 @@ void CHud::Draw() } else { BigMessageAlpha[0] = 0.0f; - BigMessageX[0] = SCALE_AND_CENTER_X(-60.0f); + BigMessageX[0] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f); BigMessageInUse[0] = 1.0f; } } @@ -1166,8 +1166,8 @@ void CHud::DrawAfterFade() else CFont::SetCentreOff(); - CFont::SetWrapx(SCREEN_SCALE_X(line.m_fWrapX)); - CFont::SetCentreSize(SCREEN_SCALE_X(line.m_fCenterSize)); + CFont::SetWrapx(SCALE_AND_CENTER_X(line.m_fWrapX)); + CFont::SetCentreSize(SCALE_AND_CENTER_X(line.m_fCenterSize)); if (line.m_bBackground) CFont::SetBackgroundOn(); else @@ -1213,7 +1213,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(600.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(40.0f)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); @@ -1229,7 +1229,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); @@ -1286,7 +1286,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.2f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 89043752..34423d83 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -1058,7 +1058,7 @@ CMoneyMessage::Render() CFont::SetScale(fScaleX, fScaleY); // maybe use SCREEN_SCALE_X and SCREEN_SCALE_Y here? CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetJustifyOff(); CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity)); CFont::SetBackGroundOnlyTextOff(); -- cgit v1.2.3 From 612bd98039fe1516951994721298e05f34fb13b5 Mon Sep 17 00:00:00 2001 From: Roman Masanin <36927roma@gmail.com> Date: Sun, 8 Nov 2020 21:30:03 +0300 Subject: return bad code, becouse no one knows what to do with it --- src/audio/AudioLogic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 95e6094f..a27d3351 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -1943,7 +1943,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams& params) break; } m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = event + 22; //originaly used m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i], which is same + m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -1977,7 +1977,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams& params) break; } m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = event + 10; //also used m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; -- cgit v1.2.3 From c91d5a90a1d796ad18f438e7f980fe773762631c Mon Sep 17 00:00:00 2001 From: Roman Masanin <36927roma@gmail.com> Date: Sun, 8 Nov 2020 23:29:57 +0300 Subject: easy way to safe few petaseconds --- src/audio/AudioLogic.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index a27d3351..fc828042 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -1943,7 +1943,11 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams& params) break; } m_sQueueSample.m_nBankIndex = SFX_BANK_0; +#ifdef THIS_IS_STUPID m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22; +#else + m_sQueueSample.m_nCounter = event + 22; +#endif m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -1977,7 +1981,11 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams& params) break; } m_sQueueSample.m_nBankIndex = SFX_BANK_0; +#ifdef THIS_IS_STUPID m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10; +#else + m_sQueueSample.m_nCounter = event + 10; +#endif m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; -- cgit v1.2.3 From 59f9c009efd3e149b83621c61716fa8da1ee1309 Mon Sep 17 00:00:00 2001 From: erorcun Date: Tue, 10 Nov 2020 01:41:21 +0300 Subject: Font: Hud: Use orig. text dimensions, fix right-align calculations --- src/control/Darkel.cpp | 4 ++-- src/control/Garages.cpp | 2 +- src/core/Frontend.cpp | 26 ++++++++++++++++++-------- src/core/Frontend.h | 1 - src/core/Game.cpp | 4 ++-- src/core/Pad.cpp | 4 ++-- src/core/main.cpp | 12 ++++++------ src/render/Credits.cpp | 4 ++-- src/render/Font.cpp | 20 +++++++++++++++++--- src/render/Hud.cpp | 26 +++++++++++++------------- 10 files changed, 63 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index 793bec36..afdfcb82 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -72,7 +72,7 @@ CDarkel::DrawMessages() { CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(30.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(610.0f)); CFont::SetCentreOn(); CFont::SetPropOn(); uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; @@ -132,7 +132,7 @@ CDarkel::DrawMessages() uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; if (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart < 5000) { CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); CFont::SetCentreOn(); CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); CFont::SetJustifyOff(); diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 61c1a850..5a04285f 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1400,7 +1400,7 @@ void CGarages::PrintMessages() CFont::SetPropOn(); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(590.0f)); CFont::SetCentreOn(); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 1718218d..0831cc79 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -780,7 +780,7 @@ CMenuManager::Draw() #endif #endif CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); switch (m_nCurrScreen) { case MENUPAGE_STATS: @@ -852,7 +852,11 @@ CMenuManager::Draw() #endif } +#ifdef ASPECT_RATIO_SCALE + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); +#else CFont::SetCentreSize(SCREEN_WIDTH); +#endif #ifdef PS2_LIKE_MENU bool itemsAreSelectable = !bottomBarActive; @@ -1468,6 +1472,12 @@ CMenuManager::Draw() break; } + // Needed after the bug fix in Font.cpp +#ifdef FIX_BUGS + if (!CFont::Details.centre) + CFont::SetRightJustifyOff(); +#endif + // 60.0 is silly nextYToUse += lineHeight * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText); @@ -1976,7 +1986,7 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetRightJustifyOff(); CFont::SetBackGroundOnlyTextOn(); CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); PREPARE_MENU_HEADER @@ -2392,7 +2402,7 @@ CMenuManager::DrawFrontEndNormal() CFont::SetJustifyOn(); CFont::SetRightJustifyOff(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(40.0f)); // 600.0f + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); // 600.0f CFont::SetColor(CRGBA(16, 16, 16, 255)); switch (m_nCurrScreen) { @@ -2710,7 +2720,7 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetRightJustifyOff(); CFont::SetBackGroundOnlyTextOn(); CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); PREPARE_MENU_HEADER @@ -3490,11 +3500,11 @@ CMenuManager::MessageScreen(const char *text) CFont::SetPropOn(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); - CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); + CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // unused + CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // unused CSprite2d::DrawRect(CRect(StretchX(120.0f), StretchY(150.0f), SCREEN_WIDTH - StretchX(120.0f), SCREEN_HEIGHT - StretchY(220.0f)), CRGBA(50, 50, 50, 210)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetCentreSize(SCREEN_STRETCH_X(380.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(380.0f)); CFont::SetCentreOn(); CFont::SetColor(CRGBA(255, 217, 106, 255)); CFont::SetScale(SCREEN_SCALE_X(SMALLTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLTEXT_Y_SCALE)); @@ -3585,7 +3595,7 @@ CMenuManager::PrintErrorMessage() CFont::SetJustifyOn(); CFont::SetRightJustifyOff(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f)); + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(MENU_X_MARGIN)); #ifdef FIX_BUGS CFont::PrintString(SCREEN_SCALE_X(50.0f), SCREEN_SCALE_Y(180.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT")); #else diff --git a/src/core/Frontend.h b/src/core/Frontend.h index fba98690..72288f98 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -18,7 +18,6 @@ #define MENU_X_MARGIN 40.0f #define MENUACTION_POS_Y 60.0f -#define MENUACTION_WIDTH 38.0f #define MENUACTION_SCALE_MULT 0.9f #define MENURADIO_ICON_SCALE 60.0f diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 3507b3b3..f7589d2b 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -131,7 +131,7 @@ void MessageScreen(char *msg) CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f + CFont::SetCentreSize(SCREEN_SCALE_X(450.0f)); // 450.0f CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetDropColor(CRGBA(32, 32, 32, 255)); @@ -737,7 +737,7 @@ void CGame::InitialiseWhenRestarting(void) CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f + CFont::SetCentreSize(SCREEN_SCALE_X(480.0f)); CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetBackGroundOnlyTextOff(); diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index e2f90a7c..928ae826 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -2593,7 +2593,7 @@ void CPad::PrintErrorMessage(void) CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_WIDTH - 20); + CFont::SetCentreSize(SCREEN_SCALE_X(SCREEN_WIDTH - 20)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); @@ -2610,7 +2610,7 @@ void CPad::PrintErrorMessage(void) CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCREEN_WIDTH - 20); + CFont::SetCentreSize(SCREEN_SCALE_X(SCREEN_WIDTH - 20)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); diff --git a/src/core/main.cpp b/src/core/main.cpp index 80feddb7..2e4b839a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -625,20 +625,20 @@ LoadingIslandScreen(const char *levelName) CFont::SetScale(1.5f, 1.5f); CFont::SetPropOn(); CFont::SetRightJustifyOn(); - CFont::SetRightJustifyWrap(150.0f); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(150.0f)); CFont::SetFontStyle(FONT_HEADING); sprintf(str, "WELCOME TO"); AsciiToUnicode(str, wstr); CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetDropShadowPosition(3); CFont::SetColor(CRGBA(243, 237, 71, 255)); - CFont::SetScale(SCREEN_STRETCH_X(1.2f), SCREEN_STRETCH_Y(1.2f)); - CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME")); + CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME")); TextCopy(wstr, name); TheText.UpperCase(wstr); CFont::SetColor(CRGBA(243, 237, 71, 255)); - CFont::SetScale(SCREEN_STRETCH_X(1.2f), SCREEN_STRETCH_Y(1.2f)); - CFont::PrintString(SCREEN_WIDTH-20, SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr); + CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr); CFont::DrawFonts(); DoRWStuffEndOfFrame(); } @@ -852,7 +852,7 @@ DisplayGameDebugText() CFont::SetRightJustifyOff(); CFont::SetJustifyOff(); CFont::SetBackGroundOnlyTextOff(); - CFont::SetWrapx(640.0f); + CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); CFont::SetFontStyle(FONT_HEADING); CFont::SetColor(CRGBA(0, 0, 0, 255)); diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index 6b28ff04..2c8a9952 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -62,7 +62,7 @@ CCredits::Render(void) scrolloffset = (CTimer::GetTimeInMilliseconds() - CreditsStartTime) / 24.0f; CFont::SetJustifyOff(); CFont::SetBackgroundOff(); - CFont::SetCentreSize(SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - 20)); + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(220, 220, 220, 220)); @@ -496,4 +496,4 @@ CCredits::Render(void) bool CCredits::AreCreditsDone(void) { return !bCreditsGoing; -} \ No newline at end of file +} diff --git a/src/render/Font.cpp b/src/render/Font.cpp index 719dffce..fbcc38e4 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -279,8 +279,8 @@ CFont::Initialise(void) SetColor(CRGBA(0xFF, 0xFF, 0xFF, 0)); SetJustifyOff(); SetCentreOff(); - SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); - SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + SetWrapx(SCREEN_WIDTH); + SetCentreSize(SCREEN_WIDTH); SetBackgroundOff(); SetBackgroundColor(CRGBA(0x80, 0x80, 0x80, 0x80)); SetBackGroundOnlyTextOff(); @@ -701,7 +701,14 @@ CFont::GetNumberLines(float xstart, float ystart, wchar *s) y = ystart; while(*s){ +#ifdef FIX_BUGS + float f = Details.centre ? Details.centreSize : + Details.rightJustify ? xstart - Details.rightJustifyWrap : + Details.wrapX; +#else float f = (Details.centre ? Details.centreSize : Details.wrapX); +#endif + #ifdef MORE_LANGUAGES if (IsJapaneseFont()) f -= SCREEN_SCALE_X(21.0f * 2.0f); @@ -781,8 +788,15 @@ CFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s) x = xstart; y = ystart; +#ifdef FIX_BUGS + float xEnd = Details.centre ? Details.centreSize : + Details.rightJustify ? xstart - Details.rightJustifyWrap : + Details.wrapX; +#else + float xEnd = (Details.centre ? Details.centreSize : Details.wrapX); +#endif while(*s){ - if(x + GetStringWidth(s) > (Details.centre ? Details.centreSize : Details.wrapX)){ + if(x + GetStringWidth(s) > xEnd){ // reached end of line if(x > maxlength) maxlength = x; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 4c8b6657..de3128ce 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -870,7 +870,7 @@ void CHud::Draw() CFont::SetCentreOff(); CFont::SetWrapx(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fWrapX)); - CFont::SetCentreSize(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fCenterSize)); + CFont::SetCentreSize(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fCenterSize)); if (CTheScripts::IntroTextLines[i].m_bBackground) CFont::SetBackgroundOn(); @@ -931,9 +931,9 @@ void CHud::Draw() CFont::SetPropOn(); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - float offsetX = SCREEN_SCALE_X(40.0f) + SCREEN_SCALE_X(8.0f); - float center = SCREEN_SCALE_FROM_RIGHT(50.0f) - SCREEN_SCALE_X(8.0f) - offsetX; - CFont::SetCentreSize(center); + float radarBulge = SCREEN_SCALE_X(40.0f) + SCREEN_SCALE_X(8.0f); + float rectWidth = SCREEN_WIDTH - SCREEN_SCALE_X(50.0f) - SCREEN_SCALE_X(8.0f) - radarBulge; + CFont::SetCentreSize(rectWidth); const int16 shadow = 1; CFont::SetDropShadowPosition(shadow); @@ -941,7 +941,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(235, 235, 235, 255)); // I'm not sure shadow substaction was intentional here, might be a leftover if CFont::PrintString was used for a shadow draw call - CFont::PrintString(center / 2.0f + offsetX - SCREEN_SCALE_X(shadow), SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(68.0f) - SCREEN_SCALE_Y(shadow), m_Message); + CFont::PrintString(rectWidth / 2.0f + radarBulge - SCREEN_SCALE_X(shadow), SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(68.0f) - SCREEN_SCALE_Y(shadow), m_Message); CFont::SetDropShadowPosition(0); } @@ -957,12 +957,12 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f)); CFont::SetPropOn(); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(25.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(615.0f)); CFont::SetFontStyle(FONT_HEADING); // Appearently sliding text in here was abandoned very early, since this text is centered now. - if (BigMessageX[0] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { + if (BigMessageX[0] >= SCALE_AND_CENTER_X(620.0f)) { BigMessageInUse[0] += CTimer::GetTimeStep(); if (BigMessageInUse[0] >= 120.0f) { @@ -997,7 +997,7 @@ void CHud::Draw() } else { BigMessageAlpha[0] = 0.0f; - BigMessageX[0] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f); + BigMessageX[0] = SCALE_AND_CENTER_X(-60.0f); BigMessageInUse[0] = 1.0f; } } @@ -1167,7 +1167,7 @@ void CHud::DrawAfterFade() CFont::SetCentreOff(); CFont::SetWrapx(SCALE_AND_CENTER_X(line.m_fWrapX)); - CFont::SetCentreSize(SCALE_AND_CENTER_X(line.m_fCenterSize)); + CFont::SetCentreSize(SCREEN_SCALE_X(line.m_fCenterSize)); if (line.m_bBackground) CFont::SetBackgroundOn(); else @@ -1213,7 +1213,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(40.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(600.0f)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); @@ -1229,7 +1229,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); @@ -1286,7 +1286,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.2f)); CFont::SetCentreOn(); CFont::SetPropOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); @@ -1318,7 +1318,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f)); CFont::SetPropOn(); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(-500.0f)); + CFont::SetRightJustifyWrap(SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 500.0f)); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); if (BigMessageX[1] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { -- cgit v1.2.3 From 460f3cea447296cb5757c04108b9ac6becd6c968 Mon Sep 17 00:00:00 2001 From: erorcun Date: Tue, 10 Nov 2020 02:06:59 +0300 Subject: Frontend: Scroll for All, some care for PS2-like menu Don't show Back button on PS2-like menu Removed PS2-style reversed fade-in, because it was a hack and taking too much space --- src/core/Frontend.cpp | 800 +++++++++++++++++++++++++++----------------------- src/core/Frontend.h | 1 + 2 files changed, 436 insertions(+), 365 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 0831cc79..4be23b77 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -41,14 +41,7 @@ #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 #define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result - -#ifdef USE_PRECISE_MEASUREMENT_CONVERTION -#define MILES_IN_METER 0.000621371192f -#define FEET_IN_METER 3.28084f -#else -#define MILES_IN_METER 0.00059880241f -#define FEET_IN_METER 3.33f -#endif +#define SCROLLABLE_PAGES #ifdef SCROLLABLE_STATS_PAGE #define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS) @@ -56,6 +49,34 @@ #define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS) #endif +#define hasNativeList(screen) (screen == MENUPAGE_MULTIPLAYER_FIND_GAME || screen == MENUPAGE_SKIN_SELECT \ + || screen == MENUPAGE_KEYBOARD_CONTROLS) + +#ifdef SCROLLABLE_PAGES +#define MAX_VISIBLE_OPTION 12 +#define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION) + +int GetOptionCount(int screen) +{ + int i = 0; + for (; i < NUM_MENUROWS && aScreens[screen].m_aEntries[i].m_Action != MENUACTION_NOTHING; i++); + return i; +} + +#define SETUP_SCROLLING(screen) \ + if (!hasNativeList(screen)) { \ + m_nTotalListRow = GetOptionCount(screen); \ + if (m_nTotalListRow > MAX_VISIBLE_OPTION) { \ + m_nSelectedListRow = 0; \ + m_nFirstVisibleRowOnList = 0; \ + m_nScrollbarTopMargin = 0; \ + } \ + } +#else +#define MAX_VISIBLE_OPTION_ON_SCREEN MAX_VISIBLE_LIST_ROW +#define SETUP_SCROLLING(screen) +#endif + #ifdef TRIANGLE_BACK_BUTTON #define GetBackJustUp GetTriangleJustUp #define GetBackJustDown GetTriangleJustDown @@ -80,13 +101,40 @@ float CMenuManager::fMapCenterX; BottomBarOption bbNames[8]; int bbTabCount = 0; bool bottomBarActive = false; -bool reverseAlpha = false; int pendingScreen = -1; int pendingOption = -1; int curBottomBarOption = -1; int hoveredBottomBarOption = -1; #endif +#ifdef CUTSCENE_BORDERS_SWITCH +bool CMenuManager::m_PrefsCutsceneBorders = true; +#endif + +#ifdef MULTISAMPLING +int8 CMenuManager::m_nPrefsMSAALevel = 0; +int8 CMenuManager::m_nDisplayMSAALevel = 0; +#endif + +#ifdef NO_ISLAND_LOADING +int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW; +#endif + +// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) +#ifdef PS2_LIKE_MENU +const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); +#else +const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color +#endif + +#ifdef USE_PRECISE_MEASUREMENT_CONVERTION +#define MILES_IN_METER 0.000621371192f +#define FEET_IN_METER 3.28084f +#else +#define MILES_IN_METER 0.00059880241f +#define FEET_IN_METER 3.33f +#endif + int32 CMenuManager::OS_Language = LANG_ENGLISH; int8 CMenuManager::m_PrefsUseVibration; int8 CMenuManager::m_DisplayControllerOnFoot; @@ -112,30 +160,11 @@ int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; int32 CMenuManager::m_PrefsMusicVolume = 102; int32 CMenuManager::m_PrefsSfxVolume = 102; -#ifdef CUTSCENE_BORDERS_SWITCH -bool CMenuManager::m_PrefsCutsceneBorders = true; -#endif - -#ifdef MULTISAMPLING -int8 CMenuManager::m_nPrefsMSAALevel = 0; -int8 CMenuManager::m_nDisplayMSAALevel = 0; -#endif - -#ifdef NO_ISLAND_LOADING -int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW; -#endif char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME; int32 CMenuManager::m_KeyPressedCode = -1; -// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) -#ifdef PS2_LIKE_MENU -const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); -#else -const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color -#endif - float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; @@ -253,35 +282,12 @@ const char* MenuFilenames[][2] = { #define PAGE_NAME_X SCREEN_SCALE_FROM_RIGHT #endif -#ifdef PS2_LIKE_MENU -#define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \ - do { \ - if (reverseAlpha) { \ - m_nPrevScreen = m_nCurrScreen; \ - m_nCurrScreen = pendingScreen; \ - m_nCurrOption = pendingOption; \ - reverseAlpha = false; \ - if (updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ - } \ - if (withReverseAlpha && !m_bRenderGameInMenu) { \ - pendingOption = option; \ - pendingScreen = screen; \ - reverseAlpha = true; \ - } else { \ - m_nPrevScreen = m_nCurrScreen; \ - m_nCurrScreen = screen; \ - m_nCurrOption = option; \ - if (updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ - } \ - m_nMenuFadeAlpha = 255; \ - } while(0) -#else +// Seperate func. in VC #define ChangeScreen(screen, option, updateDelay, clearAlpha) \ do { \ m_nPrevScreen = m_nCurrScreen; \ int newOpt = option; \ + SETUP_SCROLLING(screen) \ m_nCurrScreen = screen; \ m_nCurrOption = newOpt; \ if(updateDelay) \ @@ -289,7 +295,6 @@ const char* MenuFilenames[][2] = { if(clearAlpha) \ m_nMenuFadeAlpha = 0; \ } while(0) -#endif #define PREPARE_MENU_HEADER \ CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \ @@ -340,8 +345,8 @@ CMenuManager::ScrollUpListByOne() void CMenuManager::ScrollDownListByOne() { - if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) { - if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { + if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1) { + if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) { m_nSelectedListRow++; m_nFirstVisibleRowOnList++; m_nScrollbarTopMargin += SCROLLBAR_MAX_HEIGHT / m_nTotalListRow; @@ -356,13 +361,13 @@ CMenuManager::ScrollDownListByOne() void CMenuManager::PageUpList(bool playSoundOnSuccess) { - if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { + if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) { if (m_nFirstVisibleRowOnList > 0) { if(playSoundOnSuccess) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); - m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); + m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_OPTION_ON_SCREEN); + m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1); } else { m_nFirstVisibleRowOnList = 0; m_nSelectedListRow = 0; @@ -374,15 +379,15 @@ CMenuManager::PageUpList(bool playSoundOnSuccess) void CMenuManager::PageDownList(bool playSoundOnSuccess) { - if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { - if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { + if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) { + if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) { if(playSoundOnSuccess) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); + m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN, m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN); m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList); } else { - m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; + m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN; m_nSelectedListRow = m_nTotalListRow - 1; } m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; @@ -433,6 +438,14 @@ CMenuManager::ThingsToDoBeforeGoingBack() m_nTotalListRow = 0; } +#ifdef SCROLLABLE_PAGES + if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) { + m_nSelectedListRow = 0; + m_nFirstVisibleRowOnList = 0; + m_nScrollbarTopMargin = 0; + } +#endif + #ifdef CUSTOM_FRONTEND_OPTIONS CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; @@ -475,6 +488,236 @@ CMenuManager::GetPreviousPageOption() #endif } +void +CMenuManager::ProcessList(bool &goBack, bool &optionSelected) +{ + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + m_nTotalListRow = m_nSkinsTotal; + } + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25; + if (m_nSelectedListRow > m_nTotalListRow) + m_nSelectedListRow = m_nTotalListRow - 1; + } + +#ifndef TIDY_UP_PBP + if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { + m_bShowMouse = 0; + optionSelected = true; + } +#endif + if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) { + if (m_nCurrExLayer == HOVEROPTION_LIST) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + m_bKeyChangeNotProcessed = true; + pControlEdit = &m_KeyPressedCode; + } + } else { + field_535 = false; + } + + static uint32 lastTimeClickedScrollButton = 0; + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) { + m_bPressedPgUpOnList = false; + m_bPressedPgDnOnList = false; + m_bPressedUpOnList = false; + m_bPressedDownOnList = false; + m_bPressedScrollButton = false; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + } + + if (CPad::GetPad(0)->GetTabJustDown()) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + m_bShowMouse = false; + switch (m_nCurrExLayer) { + case HOVEROPTION_BACK: + default: + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case HOVEROPTION_LIST: + m_nCurrExLayer = HOVEROPTION_USESKIN; + break; + case HOVEROPTION_USESKIN: + m_nCurrExLayer = HOVEROPTION_BACK; + } + if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) { + m_nCurrExLayer = HOVEROPTION_BACK; + } + if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) { + m_nCurrExLayer = HOVEROPTION_BACK; + } + } + + bool pressed = false; + if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { + m_bShowMouse = false; + pressed = true; + } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { + m_bShowMouse = true; + pressed = true; + } + + // Up + if (pressed) { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedUpOnList) { + m_bPressedUpOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + ScrollUpListByOne(); + } + } else { + m_bPressedUpOnList = false; + } + + pressed = false; + if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { + m_bShowMouse = false; + pressed = true; + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + m_bShowMouse = true; + pressed = true; + } + + // Down + if (pressed) { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedDownOnList) { + m_bPressedDownOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + ScrollDownListByOne(); + } + } else { + m_bPressedDownOnList = false; + } + + if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { + if (!CPad::GetPad(0)->GetPageUp()) { + m_bPressedPgUpOnList = false; + } else { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedPgUpOnList) { + m_bPressedPgUpOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + PageUpList(false); + } + } + if (!CPad::GetPad(0)->GetPageDown()) { + m_bPressedPgDnOnList = false; + } else { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedPgDnOnList) { + m_bPressedPgDnOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + PageDownList(false); + } + } + if (CPad::GetPad(0)->GetHome()) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { + m_nFirstVisibleRowOnList = 0; + } + m_nSelectedListRow = 0; + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } + if (CPad::GetPad(0)->GetEnd()) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { + m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN; + } + m_nSelectedListRow = m_nTotalListRow - 1; + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } + } + +#ifndef TIDY_UP_PBP + if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) { + m_bShowMouse = false; + goBack = true; + } +#endif + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + switch (m_nHoverOption) { + case HOVEROPTION_BACK: + goBack = true; + break; + case HOVEROPTION_PAGEUP: + PageUpList(true); + break; + case HOVEROPTION_PAGEDOWN: + PageDownList(true); + break; + case HOVEROPTION_USESKIN: + if (m_nSkinsTotal > 0) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); + m_pSelectedSkin = m_pSkinListHead.nextSkin; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + SaveSettings(); + } + } + } + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + switch (m_nHoverOption) { + case HOVEROPTION_OVER_SCROLL_UP: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; + break; + case HOVEROPTION_LIST: + m_nHoverOption = HOVEROPTION_SKIN; + } + } else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) + && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } + + if (!CPad::GetPad(0)->GetLeftMouse()) { + holdingScrollBar = false; + } else { + if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) { + holdingScrollBar = true; + // TODO: This part is a bit hard to reverse. Not much code tho + assert(0 && "Holding scrollbar isn't done yet"); + } else { + switch (m_nHoverOption) { + case HOVEROPTION_OVER_SCROLL_UP: + case HOVEROPTION_CLICKED_SCROLL_UP: + if (!m_bPressedScrollButton) { + m_bPressedScrollButton = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + ScrollUpListByOne(); + } + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + case HOVEROPTION_CLICKED_SCROLL_DOWN: + if (!m_bPressedScrollButton) { + m_bPressedScrollButton = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + ScrollDownListByOne(); + } + break; + default: + m_bPressedScrollButton = false; + } + } + } +} // ------ Functions not in the game/inlined ends void @@ -1018,12 +1261,23 @@ CMenuManager::Draw() #endif #ifdef CUSTOM_FRONTEND_OPTIONS - static int lastOption = m_nCurrOption; + static int lastSelectedOpt = m_nCurrOption; #endif +#ifdef SCROLLABLE_PAGES + int firstOption = m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen) ? m_nFirstVisibleRowOnList : 0; + for (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) { +#else for (int i = 0; i < NUM_MENUROWS; ++i) { +#endif + #ifdef CUSTOM_FRONTEND_OPTIONS bool isOptionDisabled = false; +#endif + // Hide back button +#ifdef PS2_LIKE_MENU + if ((i == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[i+1].m_EntryName[0] == '\0') && strncmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEDS_TB", 8) == 0) + break; #endif if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { wchar *rightText = nil; @@ -1064,8 +1318,8 @@ CMenuManager::Draw() } } - if (m_nCurrOption != lastOption && lastOption == i) { - CMenuScreenCustom::CMenuEntry &oldOption = aScreens[m_nCurrScreen].m_aEntries[lastOption]; + if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) { + CMenuScreenCustom::CMenuEntry &oldOption = aScreens[m_nCurrScreen].m_aEntries[lastSelectedOpt]; if (oldOption.m_Action == MENUACTION_CFO_DYNAMIC) if(oldOption.m_CFODynamic->buttonPressFunc) oldOption.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); @@ -1317,9 +1571,20 @@ CMenuManager::Draw() int nextYToCheck = bitAboveNextItemY; if (!foundTheHoveringItem) { +#ifdef SCROLLABLE_PAGES + for (int rowToCheck = firstOption + (aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Action == MENUACTION_LABEL); rowToCheck < firstOption + MAX_VISIBLE_OPTION && rowToCheck < NUM_MENUROWS; ++rowToCheck) { +#else for (int rowToCheck = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; rowToCheck < NUM_MENUROWS; ++rowToCheck) { +#endif if(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING) break; + + // Hide back button +#ifdef PS2_LIKE_MENU + if ((rowToCheck == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[rowToCheck+1].m_EntryName[0] == '\0') && + strncmp(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_EntryName, "FEDS_TB", 8) == 0) + break; +#endif int extraOffset = 0; if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_RADIO) @@ -1502,7 +1767,36 @@ CMenuManager::Draw() } #ifdef CUSTOM_FRONTEND_OPTIONS - lastOption = m_nCurrOption; + lastSelectedOpt = m_nCurrOption; +#endif + +#ifdef SCROLLABLE_PAGES + #define SCROLLBAR_BOTTOM_X 125.0f // only for background, scrollbar's itself is calculated + #define SCROLLBAR_RIGHT_X 36.0f + #define SCROLLBAR_WIDTH 9.5f + #define SCROLLBAR_TOP_X 64 + + if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) { + // Scrollbar background + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_X), + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_X)), CRGBA(100, 100, 66, FadeIn(205))); + + float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nTotalListRow / (float) MAX_VISIBLE_OPTION); + float scrollbarBottom, scrollbarTop; + + scrollbarBottom = MENU_Y(SCROLLBAR_TOP_X - 8 + m_nScrollbarTopMargin + scrollbarHeight); + scrollbarTop = MENU_Y(SCROLLBAR_TOP_X + m_nScrollbarTopMargin); + // Scrollbar shadow + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop, + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 1 - SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), + CRGBA(50, 50, 50, FadeIn(255))); + + // Scrollbar + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop, + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - SCROLLBAR_WIDTH), scrollbarBottom), + CRGBA(235, 170, 50, FadeIn(255))); + + } #endif switch (m_nCurrScreen) { @@ -2175,27 +2469,28 @@ CMenuManager::DrawFrontEnd() CFont::SetAlphaFade(255.0f); #ifdef PS2_LIKE_MENU + #define setBbItem(a, b, c) strcpy(a.name, b); a.screenId = c; if (m_nCurrScreen == MENUPAGE_NONE) { if (m_bGameNotLoaded) { if (bbTabCount != 6) { - bbNames[0] = { "FEB_SAV",MENUPAGE_NEW_GAME }; - bbNames[1] = { "FEB_CON",MENUPAGE_CONTROLLER_PC }; - bbNames[2] = { "FEB_AUD",MENUPAGE_SOUND_SETTINGS }; - bbNames[3] = { "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS }; - bbNames[4] = { "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS }; - bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT }; + setBbItem(bbNames[0], "FEB_SAV",MENUPAGE_NEW_GAME) + setBbItem(bbNames[1], "FEB_CON",MENUPAGE_CONTROLLER_PC) + setBbItem(bbNames[2], "FEB_AUD",MENUPAGE_SOUND_SETTINGS) + setBbItem(bbNames[3], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS) + setBbItem(bbNames[4], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS) + setBbItem(bbNames[5], "FESZ_QU",MENUPAGE_EXIT) bbTabCount = 6; } } else { if (bbTabCount != 8) { - bbNames[0] = { "FEB_STA",MENUPAGE_STATS }; - bbNames[1] = { "FEB_SAV",MENUPAGE_NEW_GAME }; - bbNames[2] = { "FEB_BRI",MENUPAGE_BRIEFS }; - bbNames[3] = { "FEB_CON",MENUPAGE_CONTROLLER_PC }; - bbNames[4] = { "FEB_AUD",MENUPAGE_SOUND_SETTINGS }; - bbNames[5] = { "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS }; - bbNames[6] = { "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS }; - bbNames[7] = { "FESZ_QU",MENUPAGE_EXIT }; + setBbItem(bbNames[0], "FEB_STA",MENUPAGE_STATS) + setBbItem(bbNames[1], "FEB_SAV",MENUPAGE_NEW_GAME) + setBbItem(bbNames[2], "FEB_BRI",MENUPAGE_BRIEFS) + setBbItem(bbNames[3], "FEB_CON",MENUPAGE_CONTROLLER_PC) + setBbItem(bbNames[4], "FEB_AUD",MENUPAGE_SOUND_SETTINGS) + setBbItem(bbNames[5], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS) + setBbItem(bbNames[6], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS) + setBbItem(bbNames[7], "FESZ_QU",MENUPAGE_EXIT) bbTabCount = 8; } } @@ -2203,6 +2498,7 @@ CMenuManager::DrawFrontEnd() bottomBarActive = true; curBottomBarOption = 0; } + #undef setBbItem #else if (m_nCurrScreen == MENUPAGE_NONE) { if (m_bGameNotLoaded) { @@ -2293,7 +2589,7 @@ CMenuManager::DrawFrontEndNormal() m_aFrontEndSprites[FE2_MAINPANEL_UR].Draw(CRect(SCREEN_WIDTH / 2, 0.0f, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT / 2), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE2_MAINPANEL_DL].Draw(CRect(MENU_X_LEFT_ALIGNED(0.0f), SCREEN_HEIGHT / 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE2_MAINPANEL_DR].Draw(CRect(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); eFrontendSprites currentSprite; switch (m_nCurrScreen) { @@ -2333,39 +2629,15 @@ CMenuManager::DrawFrontEndNormal() break; } - m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha)); - static float fadeAlpha = 0.0f; - static int lastState = 0; - // reverseAlpha = PS2 fading (wait for 255->0, then change screen) if (m_nMenuFadeAlpha < 255) { - if (lastState == 1 && !reverseAlpha) - fadeAlpha = 0.f; - - if (m_nMenuFadeAlpha <= 0 && reverseAlpha) { - reverseAlpha = false; - ChangeScreen(pendingScreen, pendingOption, true, false); - } else { - // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) - if (!reverseAlpha) - fadeAlpha += (frameTime) * 20.f / 33.f; - else - fadeAlpha = max(0.0f, fadeAlpha - (frameTime) * 30.f / 33.f); - - m_nMenuFadeAlpha = fadeAlpha; - } - lastState = 0; + if (m_nMenuFadeAlpha == 0 && fadeAlpha > 1.0f) fadeAlpha = 0.0f; + + // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) + fadeAlpha += (frameTime) * 20.f / 33.f; + m_nMenuFadeAlpha = fadeAlpha; } else { - if (lastState == 0) fadeAlpha = 255.f; - - if (reverseAlpha) { - fadeAlpha -= (frameTime) * 30.f / 33.f; - - m_nMenuFadeAlpha = fadeAlpha; - } - lastState = 1; - // TODO: what is this? waiting mouse? if(field_518 == 4){ if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || @@ -2377,6 +2649,8 @@ CMenuManager::DrawFrontEndNormal() } } + m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha)); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); @@ -2912,14 +3186,13 @@ CMenuManager::DrawPlayerSetupScreen() CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205))); - // Scrollbar - float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal * (float) MAX_VISIBLE_LIST_ROW; + float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nSkinsTotal / (float) MAX_VISIBLE_LIST_ROW); float scrollbarBottom, scrollbarTop; if (m_nSkinsTotal <= MAX_VISIBLE_LIST_ROW) { scrollbarBottom = SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 4.0f); scrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP); - // Shadow + // Scrollbar shadow CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255))); } else { @@ -2930,12 +3203,13 @@ CMenuManager::DrawPlayerSetupScreen() scrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 4 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal); scrollbarTop = MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin); #endif - // Shadow + // Scrollbar shadow CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255))); } + // Scrollbar CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom), CRGBA(235, 170, 50, FadeIn(255))); @@ -3907,235 +4181,10 @@ CMenuManager::ProcessButtonPresses(void) if (m_nMousePosY < 0) m_nMousePosY = 0; if (m_nMousePosY > SCREEN_HEIGHT) m_nMousePosY = SCREEN_HEIGHT; - if (m_nCurrScreen == MENUPAGE_MULTIPLAYER_FIND_GAME || m_nCurrScreen == MENUPAGE_SKIN_SELECT - || m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - - if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { - m_nTotalListRow = m_nSkinsTotal; - } - if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25; - if (m_nSelectedListRow > m_nTotalListRow) - m_nSelectedListRow = m_nTotalListRow - 1; - } - -#ifndef TIDY_UP_PBP - if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - m_bShowMouse = 0; - optionSelected = true; - } -#endif - if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) { - if (m_nCurrExLayer == HOVEROPTION_LIST) { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - m_bKeyChangeNotProcessed = true; - pControlEdit = &m_KeyPressedCode; - } - } else { - field_535 = false; - } - - static uint32 lastTimeClickedScrollButton = 0; - - if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) { - m_bPressedPgUpOnList = false; - m_bPressedPgDnOnList = false; - m_bPressedUpOnList = false; - m_bPressedDownOnList = false; - m_bPressedScrollButton = false; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - } - - if (CPad::GetPad(0)->GetTabJustDown()) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - m_bShowMouse = false; - switch (m_nCurrExLayer) { - case HOVEROPTION_BACK: - default: - m_nCurrExLayer = HOVEROPTION_LIST; - break; - case HOVEROPTION_LIST: - m_nCurrExLayer = HOVEROPTION_USESKIN; - break; - case HOVEROPTION_USESKIN: - m_nCurrExLayer = HOVEROPTION_BACK; - } - if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) { - m_nCurrExLayer = HOVEROPTION_BACK; - } - if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) { - m_nCurrExLayer = HOVEROPTION_BACK; - } - } - - bool pressed = false; - if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { - m_bShowMouse = false; - pressed = true; - } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { - m_bShowMouse = true; - pressed = true; - } - - // Up - if (pressed) { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedUpOnList) { - m_bPressedUpOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - ScrollUpListByOne(); - } - } else { - m_bPressedUpOnList = false; - } - - pressed = false; - if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { - m_bShowMouse = false; - pressed = true; - } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { - m_bShowMouse = true; - pressed = true; - } - - // Down - if (pressed) { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedDownOnList) { - m_bPressedDownOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - ScrollDownListByOne(); - } - } else { - m_bPressedDownOnList = false; - } - - if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { - if (!CPad::GetPad(0)->GetPageUp()) { - m_bPressedPgUpOnList = false; - } else { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedPgUpOnList) { - m_bPressedPgUpOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - PageUpList(false); - } - } - if (!CPad::GetPad(0)->GetPageDown()) { - m_bPressedPgDnOnList = false; - } else { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedPgDnOnList) { - m_bPressedPgDnOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - PageDownList(false); - } - } - if (CPad::GetPad(0)->GetHome()) { - m_nCurrExLayer = HOVEROPTION_LIST; - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) { - m_nFirstVisibleRowOnList = 0; - } - m_nSelectedListRow = 0; - m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; - } - if (CPad::GetPad(0)->GetEnd()) { - m_nCurrExLayer = HOVEROPTION_LIST; - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) { - m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; - } - m_nSelectedListRow = m_nTotalListRow - 1; - m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; - } - } - -#ifndef TIDY_UP_PBP - if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) { - m_bShowMouse = false; - goBack = true; - } -#endif + if (hasNativeList(m_nCurrScreen)) { + // Not split to seperate function in III as in VC, but we need it for scrollable pages :) + ProcessList(goBack, optionSelected); - if (CPad::GetPad(0)->GetLeftMouseJustDown()) { - switch (m_nHoverOption) { - case HOVEROPTION_BACK: - goBack = true; - break; - case HOVEROPTION_PAGEUP: - PageUpList(true); - break; - case HOVEROPTION_PAGEDOWN: - PageDownList(true); - break; - case HOVEROPTION_USESKIN: - if (m_nSkinsTotal > 0) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_pSelectedSkin = m_pSkinListHead.nextSkin; - strcpy(m_PrefsSkinFile, m_aSkinName); - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - SaveSettings(); - } - } - } - - if (CPad::GetPad(0)->GetLeftMouseJustDown()) { - switch (m_nHoverOption) { - case HOVEROPTION_OVER_SCROLL_UP: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; - break; - case HOVEROPTION_OVER_SCROLL_DOWN: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; - break; - case HOVEROPTION_LIST: - m_nHoverOption = HOVEROPTION_SKIN; - } - } else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) - && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - } - - if (!CPad::GetPad(0)->GetLeftMouse()) { - holdingScrollBar = false; - } else { - if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) { - holdingScrollBar = true; - // TODO: This part is a bit hard to reverse. Not much code tho - assert(0 && "Holding scrollbar isn't done yet"); - } else { - switch (m_nHoverOption) { - case HOVEROPTION_OVER_SCROLL_UP: - case HOVEROPTION_CLICKED_SCROLL_UP: - if (!m_bPressedScrollButton) { - m_bPressedScrollButton = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - ScrollUpListByOne(); - } - break; - case HOVEROPTION_OVER_SCROLL_DOWN: - case HOVEROPTION_CLICKED_SCROLL_DOWN: - if (!m_bPressedScrollButton) { - m_bPressedScrollButton = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - ScrollDownListByOne(); - } - break; - default: - m_bPressedScrollButton = false; - } - } - } } else if (isPlainTextScreen(m_nCurrScreen)) { #ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) { @@ -4374,7 +4423,7 @@ CMenuManager::ProcessButtonPresses(void) TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; SaveSettings(); break; - } + } #else switch (m_nHoverOption) { case HOVEROPTION_INCREASE_BRIGHTNESS: @@ -4393,7 +4442,26 @@ CMenuManager::ProcessButtonPresses(void) break; } #endif - } + } + +#ifdef SCROLLABLE_PAGES + if (m_nTotalListRow > MAX_VISIBLE_OPTION) { + bool temp = false; + + m_nSelectedListRow = m_nCurrOption; + + // ignore detected back/select states, it's our screen's job + ProcessList(temp, temp); + + // and ignore our screen's goUp/Down, now it's ProcessList's job + goUp = false; + goDown = false; + m_nCurrOption = m_nSelectedListRow; + } + + // Prevent sound on scroll. Mouse wheel is now belongs to us! + if (!(m_nTotalListRow > MAX_VISIBLE_OPTION && (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown()))) +#endif if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp() || CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp() @@ -4408,6 +4476,7 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); } + #ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetBackJustDown()) { if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU) { @@ -4427,7 +4496,7 @@ CMenuManager::ProcessButtonPresses(void) goBack = false; } #endif - } + } // Centralized enter/back (except some conditions) #ifdef TIDY_UP_PBP @@ -4480,16 +4549,10 @@ CMenuManager::ProcessButtonPresses(void) if (bbNames[curBottomBarOption].screenId == MENUPAGE_SOUND_SETTINGS) DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - // If there's a menu change with fade ongoing, finish it now - if (reverseAlpha) - m_nMenuFadeAlpha = 0; return; } else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown() || CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { - if (reverseAlpha && m_nMenuFadeAlpha > 30) - return; - m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); curBottomBarOption = ((curBottomBarOption + bbTabCount) - 1) % bbTabCount; @@ -4498,9 +4561,6 @@ CMenuManager::ProcessButtonPresses(void) } else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown() || CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { - if (reverseAlpha && m_nMenuFadeAlpha > 30) - return; - m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); curBottomBarOption = ((curBottomBarOption + bbTabCount) + 1) % bbTabCount; @@ -4531,6 +4591,12 @@ CMenuManager::ProcessButtonPresses(void) } } + // Hide back button +#ifdef PS2_LIKE_MENU + if ((goUp || goDown) && m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME && strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0) + m_nCurrOption = goUp ? m_nCurrOption - 1 : (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL); +#endif + if (optionSelected) { int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; if ((option == MENUACTION_CHANGEMENU) || (option == MENUACTION_POPULATESLOTS_CHANGEMENU)) { @@ -5056,23 +5122,27 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) { m_bShowMouse = false; increase = true; - } else if (CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { + } else if ( +#ifdef SCROLLABLE_PAGES + !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) && +#endif + CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { increase = true; CheckSliderMovement(1); m_bShowMouse = true; } - if (!CPad::GetPad(0)->GetLeftJustDown() && !CPad::GetPad(0)->GetAnaloguePadLeft() && !CPad::GetPad(0)->GetDPadLeftJustDown()) { - if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { - if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { - decrease = true; - CheckSliderMovement(-1); - m_bShowMouse = true; - } - } - } else { + if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()) { m_bShowMouse = false; decrease = true; + } else if ( +#ifdef SCROLLABLE_PAGES + !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) && +#endif + CPad::GetPad(0)->GetMouseWheelDownJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { + decrease = true; + CheckSliderMovement(-1); + m_bShowMouse = true; } if (increase) diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 72288f98..21124fdb 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -781,6 +781,7 @@ public: void PageUpList(bool); void PageDownList(bool); int8 GetPreviousPageOption(); + void ProcessList(bool &goBack, bool &optionSelected); }; #ifndef IMPROVED_VIDEOMODE -- cgit v1.2.3 From 546ed0ff07cad63cb07612d8aff8d63213f71ecd Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 11 Nov 2020 09:42:30 +0100 Subject: changes to RW layer so loading foreign files works --- src/core/FileLoader.cpp | 17 ++++++++++ src/core/Streaming.cpp | 1 + src/core/main.cpp | 4 +++ src/fakerw/fake.cpp | 25 +++----------- src/objects/CutsceneHead.cpp | 37 +++++++++++++++++++++ src/rw/RwHelper.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++ src/rw/RwHelper.h | 2 ++ 7 files changed, 142 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index aadafc29..3f731658 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -332,6 +332,16 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data) return atomic; } +#ifdef LIBRW +void +InitClump(RpClump *clump) +{ + RpClumpForAllAtomics(clump, ConvertPlatformAtomic, nil); +} +#else +#define InitClump(clump) +#endif + void CFileLoader::LoadModelFile(const char *filename) { @@ -343,6 +353,7 @@ CFileLoader::LoadModelFile(const char *filename) if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ clump = RpClumpStreamRead(stream); if(clump){ + InitClump(clump); RpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump); RpClumpDestroy(clump); } @@ -368,6 +379,7 @@ CFileLoader::LoadClumpFile(const char *filename) GetNameAndLOD(nodename, name, &n); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, nil); if(mi){ + InitClump(clump); assert(mi->IsClump()); mi->SetClump(clump); }else @@ -393,6 +405,7 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id) if (mi->GetModelType() == MITYPE_PED && id != 0 && RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) { // Read LOD ped clump = RpClumpStreamRead(stream); + InitClump(clump); if(clump){ ((CPedModelInfo*)mi)->SetLowDetailClump(clump); RpClumpDestroy(clump); @@ -423,6 +436,7 @@ CFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id) clump = RpClumpGtaStreamRead2(stream); if(clump){ + InitClump(clump); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); mi->SetClump(clump); return true; @@ -443,6 +457,7 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id) clump = RpClumpStreamRead(stream); if(clump == nil) return false; + InitClump(clump); gpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); RpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump); RpClumpDestroy(clump); @@ -806,6 +821,8 @@ CFileLoader::LoadAtomicFile2Return(const char *filename) stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) clump = RpClumpStreamRead(stream); + if(clump) + InitClump(clump); RwStreamClose(stream, nil); return clump; } diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 3c5689fd..4f721f17 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -390,6 +390,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) assert(sizeof(direntry) == 32); while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){ dot = strchr(direntry.name, '.'); + assert(dot); if(dot) *dot = '\0'; if(direntry.size > (uint32)ms_streamingBufferSize) ms_streamingBufferSize = direntry.size; diff --git a/src/core/main.cpp b/src/core/main.cpp index 2e4b839a..cd234588 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -89,7 +89,11 @@ RwRGBA gColourTop; bool gameAlreadyInitialised; float NumberOfChunksLoaded; +#ifdef GTA_PS2 +#define TOTALNUMCHUNKS 48.0f +#else #define TOTALNUMCHUNKS 73.0f +#endif bool g_SlowMode = false; char version_name[64]; diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 58b3277a..64e59375 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -294,32 +294,12 @@ RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture); // TODO void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { } -static rw::Raster* -ConvertTexRaster(rw::Raster *ras) -{ - using namespace rw; - - if(ras->platform == rw::platform) - return ras; - // compatible platforms - if(ras->platform == PLATFORM_D3D8 && rw::platform == PLATFORM_D3D9 || - ras->platform == PLATFORM_D3D9 && rw::platform == PLATFORM_D3D8) - return ras; - - Image *img = ras->toImage(); - ras->destroy(); - img->unpalettize(); - ras = Raster::createFromImage(img); - img->destroy(); - return ras; -} - // hack for reading native textures RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size) { *tex = Texture::streamReadNative(stream); #ifdef LIBRW - (*tex)->raster = ConvertTexRaster((*tex)->raster); + (*tex)->raster = rw::Raster::convertTexToCurrentPlatform((*tex)->raster); #endif return *tex != nil; } @@ -796,6 +776,9 @@ RwBool RpWorldPluginAttach(void) { registerNativeDataPlugin(); registerAtomicRightsPlugin(); registerMaterialRightsPlugin(); + + // not sure if this goes here + rw::xbox::registerVertexFormatPlugin(); return true; } diff --git a/src/objects/CutsceneHead.cpp b/src/objects/CutsceneHead.cpp index 55e75807..15611c29 100644 --- a/src/objects/CutsceneHead.cpp +++ b/src/objects/CutsceneHead.cpp @@ -12,6 +12,10 @@ #include "CutsceneHead.h" #include "CdStream.h" +#ifdef GTA_PS2_STUFF +// this is a total hack to switch between PC and PS2 code +static bool lastLoadedSKA; +#endif CCutsceneHead::CCutsceneHead(CObject *obj) { @@ -87,6 +91,10 @@ CCutsceneHead::ProcessControl(void) assert(RwObjectGetType(m_rwObject) == rpCLUMP); atm = GetFirstAtomic((RpClump*)m_rwObject); hier = RpSkinAtomicGetHAnimHierarchy(atm); +#ifdef GTA_PS2_STUFF + // PS2 only plays anims in cutscene, PC always plays anims + if(!lastLoadedSKA || CCutsceneMgr::IsRunning()) +#endif RpHAnimHierarchyAddAnimTime(hier, CTimer::GetTimeStepNonClipped()/50.0f); } @@ -168,6 +176,10 @@ CCutsceneHead::PlayAnimation(const char *animName) uint32 offset, size; RwStream *stream; +#ifdef GTA_PS2_STUFF + lastLoadedSKA = false; +#endif + assert(RwObjectGetType(m_rwObject) == rpCLUMP); atm = GetFirstAtomic((RpClump*)m_rwObject); hier = RpSkinAtomicGetHAnimHierarchy(atm); @@ -191,4 +203,29 @@ CCutsceneHead::PlayAnimation(const char *animName) RwStreamClose(stream, nil); } +#ifdef GTA_PS2_STUFF +#ifdef LIBRW + else{ + sprintf(gString, "%s.ska", animName); + + if(CCutsceneMgr::ms_pCutsceneDir->FindItem(gString, offset, size)){ + stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG"); + assert(stream); + + CStreaming::MakeSpaceFor(size * CDSTREAM_SECTOR_SIZE); + CStreaming::ImGonnaUseStreamingMemory(); + + RwStreamSkip(stream, offset*2048); + anim = rw::Animation::streamReadLegacy(stream); + RpHAnimHierarchySetCurrentAnim(hier, anim); + + CStreaming::IHaveUsedStreamingMemory(); + + RwStreamClose(stream, nil); + + lastLoadedSKA = true; + } + } +#endif +#endif } diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 35af1ebd..0069934f 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -649,6 +649,83 @@ WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); } WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); } #endif +#ifdef LIBRW +#include +#include "VehicleModelInfo.h" + +int32 +findPlatform(rw::Atomic *a) +{ + rw::Geometry *g = a->geometry; + if(g->instData) + return g->instData->platform; + return 0; +} + +// in CVehicleModelInfo in VC +static RpMaterial* +GetMatFXEffectMaterialCB(RpMaterial *material, void *data) +{ + if(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTNULL) + return material; + *(int*)data = RpMatFXMaterialGetEffects(material); + return nil; +} + +// Game doesn't read atomic extensions so we never get any other than the default pipe, +// but we need it for uninstancing +void +attachPipe(rw::Atomic *atomic) +{ + if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))) + atomic->pipeline = rw::skinGlobals.pipelines[rw::platform]; + else{ + int fx = rpMATFXEFFECTNULL; + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), GetMatFXEffectMaterialCB, &fx); + if(fx != rpMATFXEFFECTNULL) + RpMatFXAtomicEnableEffects(atomic); + } +} + +// Attach pipes for the platform we have native data for so we can uninstance +void +switchPipes(rw::Atomic *a, int32 platform) +{ + if(a->pipeline && a->pipeline->platform != platform){ + uint32 plgid = a->pipeline->pluginID; + switch(plgid){ + // assume default pipe won't be attached explicitly + case rw::ID_SKIN: + a->pipeline = rw::skinGlobals.pipelines[platform]; + break; + case rw::ID_MATFX: + a->pipeline = rw::matFXGlobals.pipelines[platform]; + break; + } + } +} + +RpAtomic* +ConvertPlatformAtomic(RpAtomic *atomic, void *data) +{ + int32 driver = rw::platform; + int32 platform = findPlatform(atomic); + if(platform != 0 && platform != driver){ + attachPipe(atomic); // kludge + rw::ObjPipeline *origPipe = atomic->pipeline; + rw::platform = platform; + switchPipes(atomic, rw::platform); + if(atomic->geometry->flags & rw::Geometry::NATIVE) + atomic->uninstance(); + // no ADC in this game + //rw::ps2::unconvertADC(atomic->geometry); + rw::platform = driver; + atomic->pipeline = origPipe; + } + return atomic; +} +#endif + #if defined(FIX_BUGS) && defined(GTA_PC) RwUInt32 saved_alphafunc, saved_alpharef; diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 130eb636..523a7732 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -56,6 +56,8 @@ RwCamera *CameraCreate(RwInt32 width, void _TexturePoolsInitialise(); void _TexturePoolsShutdown(); +RpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data); + #if defined(FIX_BUGS) && defined (GTA_PC) void SetAlphaTest(RwUInt32 alpharef); void RestoreAlphaTest(); -- cgit v1.2.3 From 67e57d136862ea7823ca3c7b256214b92d738af6 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 11 Nov 2020 13:08:22 +0300 Subject: Fix RestoreDef crash --- src/core/MenuScreensCustom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index b92d5325..d3d7474d 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -91,7 +91,7 @@ void RestoreDefGraphics(int8 action) { FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0; #endif #ifdef NO_ISLAND_LOADING - if (FrontEndMenuManager.m_bGameNotLoaded) { + if (!FrontEndMenuManager.m_bGameNotLoaded) { FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW; CCollision::bAlreadyLoaded = false; CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); -- cgit v1.2.3 From feeab0b74afa63376e51b1869f6e4a17fec9a420 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 11 Nov 2020 20:57:44 +0200 Subject: Fix ini reader --- src/core/re3.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 6bf5573e..4783e513 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -86,7 +86,8 @@ CustomFrontendOptionsPopulate(void) linb::ini cfg; int CheckAndReadIniInt(const char *cat, const char *key, int original) { - const char *value = (cfg.get(cat, key, "").c_str()); + std::string strval = cfg.get(cat, key, ""); + const char *value = strval.c_str(); if (value && value[0] != '\0') return atoi(value); @@ -95,7 +96,8 @@ int CheckAndReadIniInt(const char *cat, const char *key, int original) float CheckAndReadIniFloat(const char *cat, const char *key, float original) { - const char *value = (cfg.get(cat, key, "").c_str()); + std::string strval = cfg.get(cat, key, ""); + const char *value = strval.c_str(); if (value && value[0] != '\0') return atof(value); -- cgit v1.2.3 From 8374a346e52b99552228e80726305376c1853952 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 13 Nov 2020 18:28:15 +0200 Subject: Fix loading island LODs with big buildings --- src/core/Streaming.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 4f721f17..e9a7af88 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -742,7 +742,9 @@ CStreaming::RequestBigBuildings(eLevelName level) b = CPools::GetBuildingPool()->GetSlot(i); if(b && b->bIsBIGBuilding #ifdef NO_ISLAND_LOADING - && ((CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) || (b->m_level == level)) + && (((CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODindustEntity) && (b != pIslandLODcomIndEntity) && + (b != pIslandLODcomSubEntity) && (b != pIslandLODsubIndEntity) && (b != pIslandLODsubComEntity) + ) || (b->m_level == level)) #else && b->m_level == level #endif -- cgit v1.2.3 From a6f5f4634c63a515196a0f650682953356cb8e18 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 14 Nov 2020 22:13:32 +0200 Subject: Make collision code placement more like original (+ small fixes) --- src/CMakeLists.txt | 1 + src/collision/ColBox.cpp | 21 + src/collision/ColBox.h | 16 + src/collision/ColLine.cpp | 9 + src/collision/ColLine.h | 14 + src/collision/ColModel.cpp | 184 +++ src/collision/ColModel.h | 37 + src/collision/ColPoint.cpp | 16 + src/collision/ColPoint.h | 34 + src/collision/ColSphere.cpp | 11 + src/collision/ColSphere.h | 13 + src/collision/ColTriangle.cpp | 41 + src/collision/ColTriangle.h | 68 + src/collision/Collision.cpp | 2736 +++++++++++++++++++++++++++++++ src/collision/Collision.h | 70 + src/collision/CompressedVector.h | 36 + src/collision/TempColModels.cpp | 296 ++++ src/collision/TempColModels.h | 23 + src/collision/VuCollision.cpp | 282 ++++ src/collision/VuCollision.h | 32 + src/collision/vu0Collision.dsm | 21 + src/collision/vu0Collision_1.s | 610 +++++++ src/collision/vu0Collision_2.s | 191 +++ src/core/Collision.cpp | 3290 -------------------------------------- src/core/Collision.h | 254 --- src/core/TempColModels.cpp | 297 ---- src/core/TempColModels.h | 23 - src/core/vu0Collision.dsm | 21 - src/core/vu0Collision_1.s | 610 ------- src/core/vu0Collision_2.s | 191 --- src/entities/Physical.cpp | 24 +- 31 files changed, 4774 insertions(+), 4698 deletions(-) create mode 100644 src/collision/ColBox.cpp create mode 100644 src/collision/ColBox.h create mode 100644 src/collision/ColLine.cpp create mode 100644 src/collision/ColLine.h create mode 100644 src/collision/ColModel.cpp create mode 100644 src/collision/ColModel.h create mode 100644 src/collision/ColPoint.cpp create mode 100644 src/collision/ColPoint.h create mode 100644 src/collision/ColSphere.cpp create mode 100644 src/collision/ColSphere.h create mode 100644 src/collision/ColTriangle.cpp create mode 100644 src/collision/ColTriangle.h create mode 100644 src/collision/Collision.cpp create mode 100644 src/collision/Collision.h create mode 100644 src/collision/CompressedVector.h create mode 100644 src/collision/TempColModels.cpp create mode 100644 src/collision/TempColModels.h create mode 100644 src/collision/VuCollision.cpp create mode 100644 src/collision/VuCollision.h create mode 100644 src/collision/vu0Collision.dsm create mode 100644 src/collision/vu0Collision_1.s create mode 100644 src/collision/vu0Collision_2.s delete mode 100644 src/core/Collision.cpp delete mode 100644 src/core/Collision.h delete mode 100644 src/core/TempColModels.cpp delete mode 100644 src/core/TempColModels.h delete mode 100644 src/core/vu0Collision.dsm delete mode 100644 src/core/vu0Collision_1.s delete mode 100644 src/core/vu0Collision_2.s (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eca69d30..ef322a9a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ MACRO(HEADER_DIRECTORIES return_list) FILE(GLOB_RECURSE new_list *.cpp) SET(dir_list "animation" "audio" + "collision" "control" "core" "entities" diff --git a/src/collision/ColBox.cpp b/src/collision/ColBox.cpp new file mode 100644 index 00000000..53cba88b --- /dev/null +++ b/src/collision/ColBox.cpp @@ -0,0 +1,21 @@ +#include "common.h" +#include "ColBox.h" + +void +CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece) +{ + this->min = min; + this->max = max; + this->surface = surf; + this->piece = piece; +} + +CColBox& +CColBox::operator=(const CColBox& other) +{ + min = other.min; + max = other.max; + surface = other.surface; + piece = other.piece; + return *this; +} \ No newline at end of file diff --git a/src/collision/ColBox.h b/src/collision/ColBox.h new file mode 100644 index 00000000..ac2cd675 --- /dev/null +++ b/src/collision/ColBox.h @@ -0,0 +1,16 @@ +#pragma once + +#include "SurfaceTable.h" + +struct CColBox +{ + CVector min; + CVector max; + uint8 surface; + uint8 piece; + + void Set(const CVector &min, const CVector &max, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0); + CVector GetSize(void) { return max - min; } + + CColBox& operator=(const CColBox &other); +}; \ No newline at end of file diff --git a/src/collision/ColLine.cpp b/src/collision/ColLine.cpp new file mode 100644 index 00000000..c6247449 --- /dev/null +++ b/src/collision/ColLine.cpp @@ -0,0 +1,9 @@ +#include "common.h" +#include "ColLine.h" + +void +CColLine::Set(const CVector &p0, const CVector &p1) +{ + this->p0 = p0; + this->p1 = p1; +} \ No newline at end of file diff --git a/src/collision/ColLine.h b/src/collision/ColLine.h new file mode 100644 index 00000000..21587a06 --- /dev/null +++ b/src/collision/ColLine.h @@ -0,0 +1,14 @@ +#pragma once + +struct CColLine +{ + // NB: this has to be compatible with two CVuVectors + CVector p0; + int pad0; + CVector p1; + int pad1; + + CColLine(void) { }; + CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; }; + void Set(const CVector &p0, const CVector &p1); +}; \ No newline at end of file diff --git a/src/collision/ColModel.cpp b/src/collision/ColModel.cpp new file mode 100644 index 00000000..650e6958 --- /dev/null +++ b/src/collision/ColModel.cpp @@ -0,0 +1,184 @@ +#include "common.h" +#include "ColModel.h" +#include "Game.h" + +CColModel::CColModel(void) +{ + numSpheres = 0; + spheres = nil; + numLines = 0; + lines = nil; + numBoxes = 0; + boxes = nil; + numTriangles = 0; + vertices = nil; + triangles = nil; + trianglePlanes = nil; + level = CGame::currLevel; + ownsCollisionVolumes = true; +} + +CColModel::~CColModel(void) +{ + RemoveCollisionVolumes(); + RemoveTrianglePlanes(); +} + +void +CColModel::RemoveCollisionVolumes(void) +{ + if(ownsCollisionVolumes){ + RwFree(spheres); + RwFree(lines); + RwFree(boxes); + RwFree(vertices); + RwFree(triangles); + } + numSpheres = 0; + numLines = 0; + numBoxes = 0; + numTriangles = 0; + spheres = nil; + lines = nil; + boxes = nil; + vertices = nil; + triangles = nil; +} + +void +CColModel::CalculateTrianglePlanes(void) +{ + // HACK: allocate space for one more element to stuff the link pointer into + trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1)); + for(int i = 0; i < numTriangles; i++) + trianglePlanes[i].Set(vertices, triangles[i]); +} + +void +CColModel::RemoveTrianglePlanes(void) +{ + RwFree(trianglePlanes); + trianglePlanes = nil; +} + +void +CColModel::SetLinkPtr(CLink *lptr) +{ + assert(trianglePlanes); + *(CLink**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr; +} + +CLink* +CColModel::GetLinkPtr(void) +{ + assert(trianglePlanes); + return *(CLink**)ALIGNPTR(&trianglePlanes[numTriangles]); +} + +void +CColModel::GetTrianglePoint(CVector &v, int i) const +{ + v = vertices[i].Get(); +} + +CColModel& +CColModel::operator=(const CColModel &other) +{ + int i; + int numVerts; + + boundingSphere = other.boundingSphere; + boundingBox = other.boundingBox; + + // copy spheres + if(other.numSpheres){ + if(numSpheres != other.numSpheres){ + numSpheres = other.numSpheres; + if(spheres) + RwFree(spheres); + spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere)); + } + for(i = 0; i < numSpheres; i++) + spheres[i] = other.spheres[i]; + }else{ + numSpheres = 0; + if(spheres) + RwFree(spheres); + spheres = nil; + } + + // copy lines + if(other.numLines){ + if(numLines != other.numLines){ + numLines = other.numLines; + if(lines) + RwFree(lines); + lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine)); + } + for(i = 0; i < numLines; i++) + lines[i] = other.lines[i]; + }else{ + numLines = 0; + if(lines) + RwFree(lines); + lines = nil; + } + + // copy boxes + if(other.numBoxes){ + if(numBoxes != other.numBoxes){ + numBoxes = other.numBoxes; + if(boxes) + RwFree(boxes); + boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox)); + } + for(i = 0; i < numBoxes; i++) + boxes[i] = other.boxes[i]; + }else{ + numBoxes = 0; + if(boxes) + RwFree(boxes); + boxes = nil; + } + + // copy mesh + if(other.numTriangles){ + // copy vertices + numVerts = 0; + for(i = 0; i < other.numTriangles; i++){ + if(other.triangles[i].a > numVerts) + numVerts = other.triangles[i].a; + if(other.triangles[i].b > numVerts) + numVerts = other.triangles[i].b; + if(other.triangles[i].c > numVerts) + numVerts = other.triangles[i].c; + } + numVerts++; + if(vertices) + RwFree(vertices); + if(numVerts){ + vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector)); + for(i = 0; i < numVerts; i++) + vertices[i] = other.vertices[i]; + } + + // copy triangles + if(numTriangles != other.numTriangles){ + numTriangles = other.numTriangles; + if(triangles) + RwFree(triangles); + triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle)); + } + for(i = 0; i < numTriangles; i++) + triangles[i] = other.triangles[i]; + }else{ + numTriangles = 0; + if(triangles) + RwFree(triangles); + triangles = nil; + if(vertices) + RwFree(vertices); + vertices = nil; + } + return *this; +} diff --git a/src/collision/ColModel.h b/src/collision/ColModel.h new file mode 100644 index 00000000..7dcdfa4d --- /dev/null +++ b/src/collision/ColModel.h @@ -0,0 +1,37 @@ +#pragma once + +#include "templates.h" +#include "ColBox.h" +#include "ColSphere.h" +#include "ColLine.h" +#include "ColPoint.h" +#include "ColTriangle.h" + +struct CColModel +{ + CColSphere boundingSphere; + CColBox boundingBox; + int16 numSpheres; + int16 numLines; + int16 numBoxes; + int16 numTriangles; + int32 level; + bool ownsCollisionVolumes; // missing on PS2 + CColSphere *spheres; + CColLine *lines; + CColBox *boxes; + CompressedVector *vertices; + CColTriangle *triangles; + CColTrianglePlane *trianglePlanes; + + CColModel(void); + ~CColModel(void); + void RemoveCollisionVolumes(void); + void CalculateTrianglePlanes(void); + void RemoveTrianglePlanes(void); + CLink *GetLinkPtr(void); + void SetLinkPtr(CLink*); + void GetTrianglePoint(CVector &v, int i) const; + + CColModel& operator=(const CColModel& other); +}; \ No newline at end of file diff --git a/src/collision/ColPoint.cpp b/src/collision/ColPoint.cpp new file mode 100644 index 00000000..fbf9e8c3 --- /dev/null +++ b/src/collision/ColPoint.cpp @@ -0,0 +1,16 @@ +#include "common.h" +#include "ColPoint.h" + +CColPoint& +CColPoint::operator=(const CColPoint &other) +{ + point = other.point; + normal = other.normal; + surfaceA = other.surfaceA; + pieceA = other.pieceA; + surfaceB = other.surfaceB; + pieceB = other.pieceB; + + // no depth? + return *this; +} diff --git a/src/collision/ColPoint.h b/src/collision/ColPoint.h new file mode 100644 index 00000000..a15b2345 --- /dev/null +++ b/src/collision/ColPoint.h @@ -0,0 +1,34 @@ +#pragma once + +struct CColPoint +{ + CVector point; + int pad1; + // the surface normal on the surface of point + CVector normal; + int pad2; + uint8 surfaceA; + uint8 pieceA; + uint8 surfaceB; + uint8 pieceB; + float depth; + + const CVector &GetNormal() { return normal; } + float GetDepth() { return depth; } + void Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) { + this->depth = depth; + this->surfaceA = surfA; + this->pieceA = pieceA; + this->surfaceB = surfB; + this->pieceB = pieceB; + } + void Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) { + this->surfaceA = surfA; + this->pieceA = pieceA; + this->surfaceB = surfB; + this->pieceB = pieceB; + } + + CColPoint &operator=(const CColPoint &other); +}; + diff --git a/src/collision/ColSphere.cpp b/src/collision/ColSphere.cpp new file mode 100644 index 00000000..9aac01e0 --- /dev/null +++ b/src/collision/ColSphere.cpp @@ -0,0 +1,11 @@ +#include "common.h" +#include "ColSphere.h" + +void +CColSphere::Set(float radius, const CVector ¢er, uint8 surf, uint8 piece) +{ + this->radius = radius; + this->center = center; + this->surface = surf; + this->piece = piece; +} \ No newline at end of file diff --git a/src/collision/ColSphere.h b/src/collision/ColSphere.h new file mode 100644 index 00000000..70e29763 --- /dev/null +++ b/src/collision/ColSphere.h @@ -0,0 +1,13 @@ +#pragma once + +#include "SurfaceTable.h" + +struct CColSphere +{ + // NB: this has to be compatible with a CVuVector + CVector center; + float radius; + uint8 surface; + uint8 piece; + void Set(float radius, const CVector ¢er, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0); +}; \ No newline at end of file diff --git a/src/collision/ColTriangle.cpp b/src/collision/ColTriangle.cpp new file mode 100644 index 00000000..9120fcff --- /dev/null +++ b/src/collision/ColTriangle.cpp @@ -0,0 +1,41 @@ +#include "common.h" +#include "ColTriangle.h" + +void +CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece) +{ + this->a = a; + this->b = b; + this->c = c; + this->surface = surf; +} + +#ifdef VU_COLLISION +void +CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc) +{ + CVector norm = CrossProduct(vc-va, vb-va); + norm.Normalise(); + float d = DotProduct(norm, va); + normal.x = norm.x*4096.0f; + normal.y = norm.y*4096.0f; + normal.z = norm.z*4096.0f; + dist = d*128.0f; +} +#else +void +CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc) +{ + normal = CrossProduct(vc-va, vb-va); + normal.Normalise(); + dist = DotProduct(normal, va); + CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z)); + // find out largest component and its direction + if(an.x > an.y && an.x > an.z) + dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS; + else if(an.y > an.z) + dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS; + else + dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS; +} +#endif \ No newline at end of file diff --git a/src/collision/ColTriangle.h b/src/collision/ColTriangle.h new file mode 100644 index 00000000..9e918e38 --- /dev/null +++ b/src/collision/ColTriangle.h @@ -0,0 +1,68 @@ +#pragma once + +#include "CompressedVector.h" + +enum Direction { + DIR_X_POS, + DIR_X_NEG, + DIR_Y_POS, + DIR_Y_NEG, + DIR_Z_POS, + DIR_Z_NEG, +}; + +struct CColTriangle +{ + uint16 a; + uint16 b; + uint16 c; + uint8 surface; + + void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece); +}; + +struct CColTrianglePlane +{ +#ifdef VU_COLLISION + CompressedVector normal; + int16 dist; + + void Set(const CVector &va, const CVector &vb, const CVector &vc); + void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); } + void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; } + float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; }; +#ifdef GTA_PS2 + void Unpack(uint128 &qword) const { + __asm__ volatile ( + "lh $8, 0(%1)\n" + "lh $9, 2(%1)\n" + "lh $10, 4(%1)\n" + "lh $11, 6(%1)\n" + "pextlw $10, $8\n" + "pextlw $11, $9\n" + "pextlw $2, $11, $10\n" + "sq $2, %0\n" + : "=m" (qword) + : "r" (this) + : "$8", "$9", "$10", "$11", "$2" + ); + } +#else + void Unpack(int32 *qword) const { + qword[0] = normal.x; + qword[1] = normal.y; + qword[2] = normal.z; + qword[3] = dist; + } +#endif +#else + CVector normal; + float dist; + uint8 dir; + + void Set(const CVector &va, const CVector &vb, const CVector &vc); + void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); } + void GetNormal(CVector &n) const { n = normal; } + float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; }; +#endif +}; \ No newline at end of file diff --git a/src/collision/Collision.cpp b/src/collision/Collision.cpp new file mode 100644 index 00000000..41997e32 --- /dev/null +++ b/src/collision/Collision.cpp @@ -0,0 +1,2736 @@ +#include "common.h" + +#include "VuVector.h" +#include "main.h" +#include "Lists.h" +#include "Game.h" +#include "Zones.h" +#include "General.h" +#include "ZoneCull.h" +#include "World.h" +#include "Entity.h" +#include "Train.h" +#include "Streaming.h" +#include "Pad.h" +#include "DMAudio.h" +#include "Population.h" +#include "FileLoader.h" +#include "Replay.h" +#include "CutsceneMgr.h" +#include "RenderBuffer.h" +#include "SurfaceTable.h" +#include "Lines.h" +#include "Collision.h" +#include "Frontend.h" + +#ifdef VU_COLLISION +#include "VuCollision.h" + +inline int +GetVUresult(void) +{ +#ifdef GTA_PS2 + int ret; + __asm__ volatile ( + "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish + : "=r" (ret) + ); + return ret; +#else + return vi01; +#endif +} + +inline int +GetVUresult(CVuVector &point, CVuVector &normal, float &dist) +{ +#ifdef GTA_PS2 + int ret; + __asm__ volatile ( + "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish + "sqc2 vf01,(%1)\n" + "sqc2 vf02,(%2)\n" + "qmfc2 $12,vf03\n" + "sw $12,(%3)\n" + : "=r" (ret) + : "r" (&point), "r" (&normal), "r" (&dist) + : "$12" + ); + return ret; +#else + point = vf01; + normal = vf02; + dist = vf03.x; + return vi01; +#endif +} + +#endif + +eLevelName CCollision::ms_collisionInMemory; +CLinkList CCollision::ms_colModelCache; + +void +CCollision::Init(void) +{ + ms_colModelCache.Init(NUMCOLCACHELINKS); + ms_collisionInMemory = LEVEL_GENERIC; +} + +void +CCollision::Shutdown(void) +{ + ms_colModelCache.Shutdown(); +} + +void +CCollision::Update(void) +{ + CVector playerCoors; + playerCoors = FindPlayerCoors(); + eLevelName level = CTheZones::m_CurrLevel; + bool forceLevelChange = false; + + if(CTimer::GetTimeInMilliseconds() < 2000 || CCutsceneMgr::IsCutsceneProcessing()) + return; + + // hardcode a level if there are no zones + if(level == LEVEL_GENERIC){ + if(CGame::currLevel == LEVEL_INDUSTRIAL && + playerCoors.x < 400.0f){ + level = LEVEL_COMMERCIAL; + forceLevelChange = true; + }else if(CGame::currLevel == LEVEL_SUBURBAN && + playerCoors.x > -450.0f && playerCoors.y < -1400.0f){ + level = LEVEL_COMMERCIAL; + forceLevelChange = true; + }else{ + if(playerCoors.x > 800.0f){ + level = LEVEL_INDUSTRIAL; + forceLevelChange = true; + }else if(playerCoors.x < -800.0f){ + level = LEVEL_SUBURBAN; + forceLevelChange = true; + } + } + } + if(level != LEVEL_GENERIC && level != CGame::currLevel) + CGame::currLevel = level; + if(ms_collisionInMemory != CGame::currLevel) + LoadCollisionWhenINeedIt(forceLevelChange); + CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); +} + +eLevelName +GetCollisionInSectorList(CPtrList &list) +{ + CPtrNode *node; + CEntity *e; + int level; + + for(node = list.first; node; node = node->next){ + e = (CEntity*)node->item; + level = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel()->level; + if(level != LEVEL_GENERIC) + return (eLevelName)level; + } + return LEVEL_GENERIC; +} + +// Get a level this sector is in based on collision models +eLevelName +GetCollisionInSector(CSector §) +{ + int level; + + level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS]); + if(level == LEVEL_GENERIC) + level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS_OVERLAP]); + if(level == LEVEL_GENERIC) + level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS]); + if(level == LEVEL_GENERIC) + level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS_OVERLAP]); + if(level == LEVEL_GENERIC) + level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES]); + if(level == LEVEL_GENERIC) + level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES_OVERLAP]); + return (eLevelName)level; +} + +void +CCollision::LoadCollisionWhenINeedIt(bool forceChange) +{ + eLevelName level, l; + bool multipleLevels; + CVector playerCoors; + CVehicle *veh; + CEntryInfoNode *ei; + int sx, sy; + int xmin, xmax, ymin, ymax; + int x, y; + + level = LEVEL_GENERIC; + + playerCoors = FindPlayerCoors(); + sx = CWorld::GetSectorIndexX(playerCoors.x); + sy = CWorld::GetSectorIndexY(playerCoors.y); + multipleLevels = false; + + veh = FindPlayerVehicle(); + if(veh && veh->IsTrain()){ + if(((CTrain*)veh)->m_nDoorState != TRAIN_DOOR_OPEN) + return; + }else if(playerCoors.z < -4.0f && !CCullZones::DoINeedToLoadCollision()) + return; + + // Figure out whose level's collisions we're most likely to be interested in + if(!forceChange){ + if(veh && veh->IsBoat()){ + // on water we expect to be between levels + multipleLevels = true; + }else{ + xmin = Max(sx - 1, 0); + xmax = Min(sx + 1, NUMSECTORS_X-1); + ymin = Max(sy - 1, 0); + ymax = Min(sy + 1, NUMSECTORS_Y-1); + + for(x = xmin; x <= xmax; x++) + for(y = ymin; y <= ymax; y++){ + l = GetCollisionInSector(*CWorld::GetSector(x, y)); + if(l != LEVEL_GENERIC){ + if(level == LEVEL_GENERIC) + level = l; + if(level != l) + multipleLevels = true; + } + } + } + + if(multipleLevels && veh && veh->IsBoat()) + for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){ + level = GetCollisionInSector(*ei->sector); + if(level != LEVEL_GENERIC) + break; + } + } + + if (level == CGame::currLevel || forceChange) { +#ifdef FIX_BUGS + CTimer::Suspend(); +#else + CTimer::Stop(); +#endif + ISLAND_LOADING_IS(LOW) + { + DMAudio.SetEffectsFadeVol(0); + CPad::StopPadsShaking(); + LoadCollisionScreen(CGame::currLevel); + DMAudio.Service(); + } + + CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false); + + ISLAND_LOADING_ISNT(HIGH) + { + CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); + CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); + CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); + } + ISLAND_LOADING_IS(LOW) + { + CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL); + CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL); + CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN); + CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); + CStreaming::RemoveUnusedModelsInLoadedList(); + CGame::TidyUpMemory(true, true); + CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); + } + + ms_collisionInMemory = CGame::currLevel; + CReplay::EmptyReplayBuffer(); + ISLAND_LOADING_IS(LOW) + { + if (CGame::currLevel != LEVEL_GENERIC) + LoadSplash(GetLevelSplashScreen(CGame::currLevel)); + CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); + CStreaming::RemoveUnusedBuildings(CGame::currLevel); + CStreaming::RequestBigBuildings(CGame::currLevel); + } +#ifdef NO_ISLAND_LOADING + else if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM) + CStreaming::RequestIslands(CGame::currLevel); +#endif + CStreaming::LoadAllRequestedModels(true); + + ISLAND_LOADING_IS(LOW) + { + CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); + + CGame::TidyUpMemory(true, true); + } +#ifdef FIX_BUGS + CTimer::Resume(); +#else + CTimer::Update(); +#endif + ISLAND_LOADING_IS(LOW) + DMAudio.SetEffectsFadeVol(127); + } +} + +#ifdef NO_ISLAND_LOADING +bool CCollision::bAlreadyLoaded = false; +#endif +void +CCollision::SortOutCollisionAfterLoad(void) +{ + if(ms_collisionInMemory == CGame::currLevel) + return; + ISLAND_LOADING_IS(LOW) + CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); + + if (CGame::currLevel != LEVEL_GENERIC) { +#ifdef NO_ISLAND_LOADING + if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) { + if (bAlreadyLoaded) { + ms_collisionInMemory = CGame::currLevel; + return; + } + bAlreadyLoaded = true; + CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); + CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); + CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); + } else +#endif + CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); + if(!CGame::playingIntro) + LoadSplash(GetLevelSplashScreen(CGame::currLevel)); + } + ms_collisionInMemory = CGame::currLevel; + CGame::TidyUpMemory(true, false); +} + +void +CCollision::LoadCollisionScreen(eLevelName level) +{ + static Const char *levelNames[4] = { + "", + "IND_ZON", + "COM_ZON", + "SUB_ZON" + }; + + // Why twice? + LoadingIslandScreen(levelNames[level]); + LoadingIslandScreen(levelNames[level]); +} + +// +// Test +// + + +bool +CCollision::TestSphereSphere(const CColSphere &s1, const CColSphere &s2) +{ + float d = s1.radius + s2.radius; + return (s1.center - s2.center).MagnitudeSqr() < d*d; +} + +bool +CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box) +{ + if(sph.center.x + sph.radius < box.min.x) return false; + if(sph.center.x - sph.radius > box.max.x) return false; + if(sph.center.y + sph.radius < box.min.y) return false; + if(sph.center.y - sph.radius > box.max.y) return false; + if(sph.center.z + sph.radius < box.min.z) return false; + if(sph.center.z - sph.radius > box.max.z) return false; + return true; +} + +bool +CCollision::TestLineBox(const CColLine &line, const CColBox &box) +{ + float t, x, y, z; + // If either line point is in the box, we have a collision + if(line.p0.x > box.min.x && line.p0.x < box.max.x && + line.p0.y > box.min.y && line.p0.y < box.max.y && + line.p0.z > box.min.z && line.p0.z < box.max.z) + return true; + if(line.p1.x > box.min.x && line.p1.x < box.max.x && + line.p1.y > box.min.y && line.p1.y < box.max.y && + line.p1.z > box.min.z && line.p1.z < box.max.z) + return true; + + // check if points are on opposite sides of min x plane + if((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){ + // parameter along line where we intersect + t = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x); + // y of intersection + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y){ + // z of intersection + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + return true; + } + } + + // same test with max x plane + if((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){ + t = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x); + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y){ + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + return true; + } + } + + // min y plne + if((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){ + t = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + return true; + } + } + + // max y plane + if((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){ + t = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + return true; + } + } + + // min z plne + if((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){ + t = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y) + return true; + } + } + + // max z plane + if((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){ + t = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y) + return true; + } + } + return false; +} + +bool +CCollision::TestVerticalLineBox(const CColLine &line, const CColBox &box) +{ + if(line.p0.x <= box.min.x) return false; + if(line.p0.y <= box.min.y) return false; + if(line.p0.x >= box.max.x) return false; + if(line.p0.y >= box.max.y) return false; + if(line.p0.z < line.p1.z){ + if(line.p0.z > box.max.z) return false; + if(line.p1.z < box.min.z) return false; + }else{ + if(line.p1.z > box.max.z) return false; + if(line.p0.z < box.min.z) return false; + } + return true; +} + +bool +CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) +{ +#ifdef VU_COLLISION + // not used in favour of optimized loops + VuTriangle vutri; + verts[tri.a].Unpack(vutri.v0); + verts[tri.b].Unpack(vutri.v1); + verts[tri.c].Unpack(vutri.v2); + plane.Unpack(vutri.plane); + + LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri); + + if(GetVUresult()) + return true; + return false; +#else + float t; + CVector normal; + plane.GetNormal(normal); + + // if points are on the same side, no collision + if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f) + return false; + + // intersection parameter on line + t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal); + // find point of intersection + CVector p = line.p0 + (line.p1-line.p0)*t; + + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); + CVector2D vec1, vec2, vec3, vect; + + // We do the test in 2D. With the plane direction we + // can figure out how to project the vectors. + // normal = (c-a) x (b-a) + switch(plane.dir){ + case DIR_X_POS: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vc.y; vec2.y = vc.z; + vec3.x = vb.y; vec3.y = vb.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_X_NEG: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vb.y; vec2.y = vb.z; + vec3.x = vc.y; vec3.y = vc.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_Y_POS: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vc.z; vec2.y = vc.x; + vec3.x = vb.z; vec3.y = vb.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Y_NEG: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vb.z; vec2.y = vb.x; + vec3.x = vc.z; vec3.y = vc.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Z_POS: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vc.x; vec2.y = vc.y; + vec3.x = vb.x; vec3.y = vb.y; + vect.x = p.x; vect.y = p.y; + break; + case DIR_Z_NEG: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vb.x; vec2.y = vb.y; + vec3.x = vc.x; vec3.y = vc.y; + vect.x = p.x; vect.y = p.y; + break; + default: + assert(0); + } + // This is our triangle: + // 3-------2 + // \ P / + // \ / + // \ / + // 1 + // We can use the "2d cross product" to check on which side + // a vector is of another. Test is true if point is inside of all edges. + if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; + if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; + if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; + return true; +#endif +} + +// Test if line segment intersects with sphere. +// If the first point is inside the sphere this test does not register a collision! +// The code is reversed from the original code and rather ugly, see Process for a clear version. +// TODO: actually rewrite this mess +bool +CCollision::TestLineSphere(const CColLine &line, const CColSphere &sph) +{ + CVector v01 = line.p1 - line.p0; // vector from p0 to p1 + CVector v0c = sph.center - line.p0; // vector from p0 to center + float linesq = v01.MagnitudeSqr(); + // I leave in the strange -2 factors even though they serve no real purpose + float projline = -2.0f * DotProduct(v01, v0c); // project v0c onto line + // Square of tangent from p0 multiplied by line length so we can compare with projline. + // The length of the tangent would be this: Sqrt((c-p0)^2 - r^2). + // Negative if p0 is inside the sphere! This breaks the test! + float tansq = 4.0f * linesq * + (sph.center.MagnitudeSqr() - 2.0f*DotProduct(sph.center, line.p0) + line.p0.MagnitudeSqr() - sph.radius*sph.radius); + float diffsq = projline*projline - tansq; + // if diffsq < 0 that means the line is a passant, so no intersection + if(diffsq < 0.0f) + return false; + // projline (negative in GTA for some reason) is the point on the line + // in the middle of the two intersection points (startin from p0). + // Sqrt(diffsq) somehow works out to be the distance from that + // midpoint to the intersection points. + // So subtract that and get rid of the awkward scaling: + float f = (-projline - Sqrt(diffsq)) / (2.0f*linesq); + // f should now be in range [0, 1] for [p0, p1] + return f >= 0.0f && f <= 1.0f; +} + +bool +CCollision::TestSphereTriangle(const CColSphere &sphere, + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) +{ +#ifdef VU_COLLISION + // not used in favour of optimized loops + VuTriangle vutri; + verts[tri.a].Unpack(vutri.v0); + verts[tri.b].Unpack(vutri.v1); + verts[tri.c].Unpack(vutri.v2); + plane.Unpack(vutri.plane); + + SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri); + + if(GetVUresult()) + return true; + return false; +#else + // If sphere and plane don't intersect, no collision + float planedist = plane.CalcPoint(sphere.center); + if(Abs(planedist) > sphere.radius) + return false; + + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); + + // calculate two orthogonal basis vectors for the triangle + CVector vec2 = vb - va; + float len = vec2.Magnitude(); + vec2 = vec2 * (1.0f/len); + CVector normal; + plane.GetNormal(normal); + CVector vec1 = CrossProduct(vec2, normal); + + // We know A has local coordinate [0,0] and B has [0,len]. + // Now calculate coordinates on triangle for these two vectors: + CVector vac = vc - va; + CVector vas = sphere.center - va; + CVector2D b(0.0f, len); + CVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac)); + CVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas)); + + // The three triangle lines partition the space into 6 sectors, + // find out in which the center lies. + int insideAB = CrossProduct2D(s, b) >= 0.0f; + int insideAC = CrossProduct2D(c, s) >= 0.0f; + int insideBC = CrossProduct2D(s-b, c-b) >= 0.0f; + + int testcase = insideAB + insideAC + insideBC; + float dist = 0.0f; + switch(testcase){ + case 1: + // closest to a vertex + if(insideAB) dist = (sphere.center - vc).Magnitude(); + else if(insideAC) dist = (sphere.center - vb).Magnitude(); + else if(insideBC) dist = (sphere.center - va).Magnitude(); + else assert(0); + break; + case 2: + // closest to an edge + // looks like original game as DistToLine manually inlined + if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center); + else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center); + else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center); + else assert(0); + break; + case 3: + // center is in triangle + dist = Abs(planedist); + break; + default: + assert(0); + } + + return dist < sphere.radius; +#endif +} + +bool +CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough) +{ +#ifdef VU_COLLISION + CMatrix matTransform; + int i; + + // transform line to model space + Invert(matrix, matTransform); + CVuVector newline[2]; + TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); + + // If we don't intersect with the bounding box, no chance on the rest + if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) + return false; + + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(TestLineSphere(*(CColLine*)newline, model.spheres[i])) + return true; + } + + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(TestLineBox(*(CColLine*)newline, model.boxes[i])) + return true; + } + + CalculateTrianglePlanes(&model); + int lastTest = -1; + VuTriangle vutri; + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + + CColTriangle *tri = &model.triangles[i]; + model.vertices[tri->a].Unpack(vutri.v0); + model.vertices[tri->b].Unpack(vutri.v1); + model.vertices[tri->c].Unpack(vutri.v2); + model.trianglePlanes[i].Unpack(vutri.plane); + + LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); + lastTest = i; + break; + } +#ifdef FIX_BUGS + // no need to check first again + i++; +#endif + for(; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + + CColTriangle *tri = &model.triangles[i]; + model.vertices[tri->a].Unpack(vutri.v0); + model.vertices[tri->b].Unpack(vutri.v1); + model.vertices[tri->c].Unpack(vutri.v2); + model.trianglePlanes[i].Unpack(vutri.plane); + + if(GetVUresult()) + return true; + + LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); + lastTest = i; + + } + if(lastTest != -1 && GetVUresult()) + return true; + + return false; +#else + static CMatrix matTransform; + int i; + + // transform line to model space + Invert(matrix, matTransform); + CColLine newline(matTransform * line.p0, matTransform * line.p1); + + // If we don't intersect with the bounding box, no chance on the rest + if(!TestLineBox(newline, model.boundingBox)) + return false; + + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(TestLineSphere(newline, model.spheres[i])) + return true; + } + + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(TestLineBox(newline, model.boxes[i])) + return true; + } + + CalculateTrianglePlanes(&model); + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i])) + return true; + } + + return false; +#endif +} + + +// +// Process +// + +// For Spheres mindist is the squared distance to its center +// For Lines mindist is between [0,1] + +bool +CCollision::ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq) +{ + CVector dist = s1.center - s2.center; + float d = dist.Magnitude() - s2.radius; // distance from s1's center to s2 + float depth = s1.radius - d; // sphere overlap + if(d < 0.0f) d = 0.0f; // clamp to zero, i.e. if s1's center is inside s2 + // no collision if sphere is not close enough + if(d*d < mindistsq && d < s1.radius){ + dist.Normalise(); + point.point = s1.center - dist*d; + point.normal = dist; +#ifndef VU_COLLISION + point.surfaceA = s1.surface; + point.pieceA = s1.piece; + point.surfaceB = s2.surface; + point.pieceB = s2.piece; +#endif + point.depth = depth; + mindistsq = d*d; // collision radius + return true; + } + return false; +} + +bool +CCollision::ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq) +{ + CVector p; + CVector dist; + + // GTA's code is too complicated, uses a huge 3x3x3 if statement + // we can simplify the structure a lot + + // first make sure we have a collision at all + if(sph.center.x + sph.radius < box.min.x) return false; + if(sph.center.x - sph.radius > box.max.x) return false; + if(sph.center.y + sph.radius < box.min.y) return false; + if(sph.center.y - sph.radius > box.max.y) return false; + if(sph.center.z + sph.radius < box.min.z) return false; + if(sph.center.z - sph.radius > box.max.z) return false; + + // Now find out where the sphere center lies in relation to all the sides + int xpos = sph.center.x < box.min.x ? 1 : + sph.center.x > box.max.x ? 2 : + 0; + int ypos = sph.center.y < box.min.y ? 1 : + sph.center.y > box.max.y ? 2 : + 0; + int zpos = sph.center.z < box.min.z ? 1 : + sph.center.z > box.max.z ? 2 : + 0; + + if(xpos == 0 && ypos == 0 && zpos == 0){ + // sphere is inside the box + p = (box.min + box.max)*0.5f; + + dist = sph.center - p; + float lensq = dist.MagnitudeSqr(); + if(lensq < mindistsq){ + point.normal = dist * (1.0f/Sqrt(lensq)); + point.point = sph.center - point.normal; +#ifndef VU_COLLISION + point.surfaceA = sph.surface; + point.pieceA = sph.piece; + point.surfaceB = box.surface; + point.pieceB = box.piece; +#endif + + // find absolute distance to the closer side in each dimension + float dx = dist.x > 0.0f ? + box.max.x - sph.center.x : + sph.center.x - box.min.x; + float dy = dist.y > 0.0f ? + box.max.y - sph.center.y : + sph.center.y - box.min.y; + float dz = dist.z > 0.0f ? + box.max.z - sph.center.z : + sph.center.z - box.min.z; + // collision depth is maximum of that: + if(dx > dy && dx > dz) + point.depth = dx; + else if(dy > dz) + point.depth = dy; + else + point.depth = dz; + return true; + } + }else{ + // sphere is outside. + // closest point on box: + p.x = xpos == 1 ? box.min.x : + xpos == 2 ? box.max.x : + sph.center.x; + p.y = ypos == 1 ? box.min.y : + ypos == 2 ? box.max.y : + sph.center.y; + p.z = zpos == 1 ? box.min.z : + zpos == 2 ? box.max.z : + sph.center.z; + + dist = sph.center - p; + float lensq = dist.MagnitudeSqr(); + if(lensq < mindistsq){ + float len = Sqrt(lensq); + point.point = p; + point.normal = dist * (1.0f/len); +#ifndef VU_COLLISION + point.surfaceA = sph.surface; + point.pieceA = sph.piece; + point.surfaceB = box.surface; + point.pieceB = box.piece; +#endif + point.depth = sph.radius - len; + mindistsq = lensq; + return true; + } + } + return false; +} + +bool +CCollision::ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist) +{ + float mint, t, x, y, z; + CVector normal; + CVector p; + + mint = 1.0f; + // check if points are on opposite sides of min x plane + if((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){ + // parameter along line where we intersect + t = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x); + // y of intersection + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y){ + // z of intersection + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + if(t < mint){ + mint = t; + p = CVector(box.min.x, y, z); + normal = CVector(-1.0f, 0.0f, 0.0f); + } + } + } + + // max x plane + if((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){ + t = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x); + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y){ + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + if(t < mint){ + mint = t; + p = CVector(box.max.x, y, z); + normal = CVector(1.0f, 0.0f, 0.0f); + } + } + } + + // min y plne + if((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){ + t = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + if(t < mint){ + mint = t; + p = CVector(x, box.min.y, z); + normal = CVector(0.0f, -1.0f, 0.0f); + } + } + } + + // max y plane + if((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){ + t = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + z = line.p0.z + (line.p1.z - line.p0.z)*t; + if(z > box.min.z && z < box.max.z) + if(t < mint){ + mint = t; + p = CVector(x, box.max.y, z); + normal = CVector(0.0f, 1.0f, 0.0f); + } + } + } + + // min z plne + if((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){ + t = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y) + if(t < mint){ + mint = t; + p = CVector(x, y, box.min.z); + normal = CVector(0.0f, 0.0f, -1.0f); + } + } + } + + // max z plane + if((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){ + t = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z); + x = line.p0.x + (line.p1.x - line.p0.x)*t; + if(x > box.min.x && x < box.max.x){ + y = line.p0.y + (line.p1.y - line.p0.y)*t; + if(y > box.min.y && y < box.max.y) + if(t < mint){ + mint = t; + p = CVector(x, y, box.max.z); + normal = CVector(0.0f, 0.0f, 1.0f); + } + } + } + + if(mint >= mindist) + return false; + + point.point = p; + point.normal = normal; +#ifndef VU_COLLISION + point.surfaceA = 0; + point.pieceA = 0; + point.surfaceB = box.surface; + point.pieceB = box.piece; +#endif + mindist = mint; + + return true; +} + +// If line.p0 lies inside sphere, no collision is registered. +bool +CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist) +{ + CVector v01 = line.p1 - line.p0; + CVector v0c = sphere.center - line.p0; + float linesq = v01.MagnitudeSqr(); + // project v0c onto v01, scaled by |v01| this is the midpoint of the two intersections + float projline = DotProduct(v01, v0c); + // tangent of p0 to sphere, scaled by linesq just like projline^2 + float tansq = (v0c.MagnitudeSqr() - sphere.radius*sphere.radius) * linesq; + // this works out to be the square of the distance between the midpoint and the intersections + float diffsq = projline*projline - tansq; + // no intersection + if(diffsq < 0.0f) + return false; + // point of first intersection, in range [0,1] between p0 and p1 + float t = (projline - Sqrt(diffsq)) / linesq; + // if not on line or beyond mindist, no intersection + if(t < 0.0f || t > 1.0f || t >= mindist) + return false; + point.point = line.p0 + v01*t; + point.normal = point.point - sphere.center; + point.normal.Normalise(); +#ifndef VU_COLLISION + point.surfaceA = 0; + point.pieceA = 0; + point.surfaceB = sphere.surface; + point.pieceB = sphere.piece; +#endif + mindist = t; + return true; +} + +bool +CCollision::ProcessVerticalLineTriangle(const CColLine &line, + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, + CColPoint &point, float &mindist, CStoredCollPoly *poly) +{ +#ifdef VU_COLLISION + // not used in favour of optimized loops + bool res = ProcessLineTriangle(line, verts, tri, plane, point, mindist); + if(res && poly){ + poly->verts[0] = verts[tri.a].Get(); + poly->verts[1] = verts[tri.b].Get(); + poly->verts[2] = verts[tri.c].Get(); + poly->valid = true; + } + return res; +#else + float t; + CVector normal; + + const CVector &p0 = line.p0; + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); + + // early out bound rect test + if(p0.x < va.x && p0.x < vb.x && p0.x < vc.x) return false; + if(p0.x > va.x && p0.x > vb.x && p0.x > vc.x) return false; + if(p0.y < va.y && p0.y < vb.y && p0.y < vc.y) return false; + if(p0.y > va.y && p0.y > vb.y && p0.y > vc.y) return false; + + plane.GetNormal(normal); + // if points are on the same side, no collision + if(plane.CalcPoint(p0) * plane.CalcPoint(line.p1) > 0.0f) + return false; + + // intersection parameter on line + float h = (line.p1 - p0).z; + t = -plane.CalcPoint(p0) / (h * normal.z); + // early out if we're beyond the mindist + if(t >= mindist) + return false; + CVector p(p0.x, p0.y, p0.z + h*t); + + CVector2D vec1, vec2, vec3, vect; + switch(plane.dir){ + case DIR_X_POS: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vc.y; vec2.y = vc.z; + vec3.x = vb.y; vec3.y = vb.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_X_NEG: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vb.y; vec2.y = vb.z; + vec3.x = vc.y; vec3.y = vc.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_Y_POS: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vc.z; vec2.y = vc.x; + vec3.x = vb.z; vec3.y = vb.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Y_NEG: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vb.z; vec2.y = vb.x; + vec3.x = vc.z; vec3.y = vc.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Z_POS: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vc.x; vec2.y = vc.y; + vec3.x = vb.x; vec3.y = vb.y; + vect.x = p.x; vect.y = p.y; + break; + case DIR_Z_NEG: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vb.x; vec2.y = vb.y; + vec3.x = vc.x; vec3.y = vc.y; + vect.x = p.x; vect.y = p.y; + break; + default: + assert(0); + } + if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; + if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; + if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; + if(t >= mindist) return false; + point.point = p; + point.normal = normal; + point.surfaceA = 0; + point.pieceA = 0; + point.surfaceB = tri.surface; + point.pieceB = 0; + if(poly){ + poly->verts[0] = va; + poly->verts[1] = vb; + poly->verts[2] = vc; + poly->valid = true; + } + mindist = t; + return true; +#endif +} + +bool +CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly) +{ +#ifdef VU_COLLISION + if(!poly->valid) + return false; + + CVuVector p0 = pos; + CVuVector p1 = pos; + p1.z = z; + + CVector v01 = poly->verts[1] - poly->verts[0]; + CVector v02 = poly->verts[2] - poly->verts[0]; + CVuVector plane = CrossProduct(v02, v01); + plane.Normalise(); + plane.w = DotProduct(plane, poly->verts[0]); + + LineToTriangleCollision(p0, p1, poly->verts[0], poly->verts[1], poly->verts[2], plane); + + CVuVector pnt; + float dist; + if(!GetVUresult(pnt, plane, dist)) +#ifdef FIX_BUGS + // perhaps not needed but be safe + return poly->valid = false; +#else + return false; +#endif + point.point = pnt; + return true; +#else + float t; + + if(!poly->valid) + return false; + + // maybe inlined? + CColTrianglePlane plane; + plane.Set(poly->verts[0], poly->verts[1], poly->verts[2]); + + const CVector &va = poly->verts[0]; + const CVector &vb = poly->verts[1]; + const CVector &vc = poly->verts[2]; + CVector p0 = pos; + CVector p1(pos.x, pos.y, z); + + // The rest is pretty much CCollision::ProcessLineTriangle + + // if points are on the same side, no collision + if(plane.CalcPoint(p0) * plane.CalcPoint(p1) > 0.0f) + return poly->valid = false; + + // intersection parameter on line + CVector normal; + plane.GetNormal(normal); + t = -plane.CalcPoint(p0) / DotProduct(p1 - p0, normal); + // find point of intersection + CVector p = p0 + (p1-p0)*t; + + CVector2D vec1, vec2, vec3, vect; + switch(plane.dir){ + case DIR_X_POS: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vc.y; vec2.y = vc.z; + vec3.x = vb.y; vec3.y = vb.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_X_NEG: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vb.y; vec2.y = vb.z; + vec3.x = vc.y; vec3.y = vc.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_Y_POS: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vc.z; vec2.y = vc.x; + vec3.x = vb.z; vec3.y = vb.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Y_NEG: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vb.z; vec2.y = vb.x; + vec3.x = vc.z; vec3.y = vc.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Z_POS: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vc.x; vec2.y = vc.y; + vec3.x = vb.x; vec3.y = vb.y; + vect.x = p.x; vect.y = p.y; + break; + case DIR_Z_NEG: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vb.x; vec2.y = vb.y; + vec3.x = vc.x; vec3.y = vc.y; + vect.x = p.x; vect.y = p.y; + break; + default: + assert(0); + } + if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return poly->valid = false; + if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return poly->valid = false; + if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return poly->valid = false; + point.point = p; + return poly->valid = true; +#endif +} + +bool +CCollision::ProcessLineTriangle(const CColLine &line, + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, + CColPoint &point, float &mindist) +{ +#ifdef VU_COLLISION + // not used in favour of optimized loops + VuTriangle vutri; + verts[tri.a].Unpack(vutri.v0); + verts[tri.b].Unpack(vutri.v1); + verts[tri.c].Unpack(vutri.v2); + plane.Unpack(vutri.plane); + + LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri); + + CVuVector pnt, normal; + float dist; + if(GetVUresult(pnt, normal, dist)){ + if(dist < mindist){ + point.point = pnt; + point.normal = normal; + mindist = dist; + return true; + } + } + return false; +#else + float t; + CVector normal; + plane.GetNormal(normal); + + // if points are on the same side, no collision + if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f) + return false; + + // intersection parameter on line + t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal); + // early out if we're beyond the mindist + if(t >= mindist) + return false; + // find point of intersection + CVector p = line.p0 + (line.p1-line.p0)*t; + + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); + CVector2D vec1, vec2, vec3, vect; + + switch(plane.dir){ + case DIR_X_POS: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vc.y; vec2.y = vc.z; + vec3.x = vb.y; vec3.y = vb.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_X_NEG: + vec1.x = va.y; vec1.y = va.z; + vec2.x = vb.y; vec2.y = vb.z; + vec3.x = vc.y; vec3.y = vc.z; + vect.x = p.y; vect.y = p.z; + break; + case DIR_Y_POS: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vc.z; vec2.y = vc.x; + vec3.x = vb.z; vec3.y = vb.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Y_NEG: + vec1.x = va.z; vec1.y = va.x; + vec2.x = vb.z; vec2.y = vb.x; + vec3.x = vc.z; vec3.y = vc.x; + vect.x = p.z; vect.y = p.x; + break; + case DIR_Z_POS: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vc.x; vec2.y = vc.y; + vec3.x = vb.x; vec3.y = vb.y; + vect.x = p.x; vect.y = p.y; + break; + case DIR_Z_NEG: + vec1.x = va.x; vec1.y = va.y; + vec2.x = vb.x; vec2.y = vb.y; + vec3.x = vc.x; vec3.y = vc.y; + vect.x = p.x; vect.y = p.y; + break; + default: + assert(0); + } + if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; + if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; + if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; + if(t >= mindist) return false; + point.point = p; + point.normal = normal; + point.surfaceA = 0; + point.pieceA = 0; + point.surfaceB = tri.surface; + point.pieceB = 0; + mindist = t; + return true; +#endif +} + +bool +CCollision::ProcessSphereTriangle(const CColSphere &sphere, + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, + CColPoint &point, float &mindistsq) +{ +#ifdef VU_COLLISION + // not used in favour of optimized loops + VuTriangle vutri; + verts[tri.a].Unpack(vutri.v0); + verts[tri.b].Unpack(vutri.v1); + verts[tri.c].Unpack(vutri.v2); + plane.Unpack(vutri.plane); + + SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri); + + CVuVector pnt, normal; + float dist; + if(GetVUresult(pnt, normal, dist) && dist*dist < mindistsq){ + float depth = sphere.radius - dist; + if(depth > point.depth){ + point.point = pnt; + point.normal = normal; + point.depth = depth; + mindistsq = dist*dist; + return true; + } + } + return false; +#else + // If sphere and plane don't intersect, no collision + float planedist = plane.CalcPoint(sphere.center); + float distsq = planedist*planedist; + if(Abs(planedist) > sphere.radius || distsq > mindistsq) + return false; + + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); + + // calculate two orthogonal basis vectors for the triangle + CVector normal; + plane.GetNormal(normal); + CVector vec2 = vb - va; + float len = vec2.Magnitude(); + vec2 = vec2 * (1.0f/len); + CVector vec1 = CrossProduct(vec2, normal); + + // We know A has local coordinate [0,0] and B has [0,len]. + // Now calculate coordinates on triangle for these two vectors: + CVector vac = vc - va; + CVector vas = sphere.center - va; + CVector2D b(0.0f, len); + CVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac)); + CVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas)); + + // The three triangle lines partition the space into 6 sectors, + // find out in which the center lies. + int insideAB = CrossProduct2D(s, b) >= 0.0f; + int insideAC = CrossProduct2D(c, s) >= 0.0f; + int insideBC = CrossProduct2D(s-b, c-b) >= 0.0f; + + int testcase = insideAB + insideAC + insideBC; + float dist = 0.0f; + CVector p; + switch(testcase){ + case 1: + // closest to a vertex + if(insideAB) p = vc; + else if(insideAC) p = vb; + else if(insideBC) p = va; + else assert(0); + dist = (sphere.center - p).Magnitude(); + break; + case 2: + // closest to an edge + // looks like original game as DistToLine manually inlined + if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center, p); + else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center, p); + else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center, p); + else assert(0); + break; + case 3: + // center is in triangle + dist = Abs(planedist); + p = sphere.center - normal*planedist; + break; + default: + assert(0); + } + + if(dist >= sphere.radius || dist*dist >= mindistsq) + return false; + + point.point = p; + point.normal = sphere.center - p; + point.normal.Normalise(); +#ifndef VU_COLLISION + point.surfaceA = sphere.surface; + point.pieceA = sphere.piece; + point.surfaceB = tri.surface; + point.pieceB = 0; +#endif + point.depth = sphere.radius - dist; + mindistsq = dist*dist; + return true; +#endif +} + +bool +CCollision::ProcessLineOfSight(const CColLine &line, + const CMatrix &matrix, CColModel &model, + CColPoint &point, float &mindist, bool ignoreSeeThrough) +{ +#ifdef VU_COLLISION + CMatrix matTransform; + int i; + + // transform line to model space + Invert(matrix, matTransform); + CVuVector newline[2]; + TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); + + if(mindist < 1.0f) + newline[1] = newline[0] + (newline[1] - newline[0])*mindist; + + // If we don't intersect with the bounding box, no chance on the rest + if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) + return false; + + float coldist = 1.0f; + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist)) + point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece); + } + + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist)) + point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece); + } + + CalculateTrianglePlanes(&model); + VuTriangle vutri; + CColTriangle *lasttri = nil; + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + + CColTriangle *tri = &model.triangles[i]; + model.vertices[tri->a].Unpack(vutri.v0); + model.vertices[tri->b].Unpack(vutri.v1); + model.vertices[tri->c].Unpack(vutri.v2); + model.trianglePlanes[i].Unpack(vutri.plane); + + LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); + lasttri = tri; + break; + } +#ifdef FIX_BUGS + // no need to check first again + i++; +#endif + CVuVector pnt, normal; + float dist; + for(; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + + CColTriangle *tri = &model.triangles[i]; + model.vertices[tri->a].Unpack(vutri.v0); + model.vertices[tri->b].Unpack(vutri.v1); + model.vertices[tri->c].Unpack(vutri.v2); + model.trianglePlanes[i].Unpack(vutri.plane); + + if(GetVUresult(pnt, normal, dist)) + if(dist < coldist){ + point.point = pnt; + point.normal = normal; + point.Set(0, 0, lasttri->surface, 0); + coldist = dist; + } + + LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); + lasttri = tri; + } + if(lasttri && GetVUresult(pnt, normal, dist)) + if(dist < coldist){ + point.point = pnt; + point.normal = normal; + point.Set(0, 0, lasttri->surface, 0); + coldist = dist; + } + + + if(coldist < 1.0f){ + point.point = matrix * point.point; + point.normal = Multiply3x3(matrix, point.normal); + mindist *= coldist; + return true; + } + return false; +#else + static CMatrix matTransform; + int i; + + // transform line to model space + Invert(matrix, matTransform); + CColLine newline(matTransform * line.p0, matTransform * line.p1); + + // If we don't intersect with the bounding box, no chance on the rest + if(!TestLineBox(newline, model.boundingBox)) + return false; + + float coldist = mindist; + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + ProcessLineSphere(newline, model.spheres[i], point, coldist); + } + + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + ProcessLineBox(newline, model.boxes[i], point, coldist); + } + + CalculateTrianglePlanes(&model); + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist); + } + + if(coldist < mindist){ + point.point = matrix * point.point; + point.normal = Multiply3x3(matrix, point.normal); + mindist = coldist; + return true; + } + return false; +#endif +} + +bool +CCollision::ProcessVerticalLine(const CColLine &line, + const CMatrix &matrix, CColModel &model, + CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly) +{ +#ifdef VU_COLLISION + static CStoredCollPoly TempStoredPoly; + CMatrix matTransform; + int i; + + // transform line to model space + Invert(matrix, matTransform); + CVuVector newline[2]; + TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); + + if(mindist < 1.0f) + newline[1] = newline[0] + (newline[1] - newline[0])*mindist; + + if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) + return false; + + float coldist = 1.0f; + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist)) + point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece); + } + + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist)) + point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece); + } + + CalculateTrianglePlanes(&model); + TempStoredPoly.valid = false; + if(model.numTriangles){ + bool registeredCol; + CColTriangle *lasttri = nil; + VuTriangle vutri; + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + + CColTriangle *tri = &model.triangles[i]; + model.vertices[tri->a].Unpack(vutri.v0); + model.vertices[tri->b].Unpack(vutri.v1); + model.vertices[tri->c].Unpack(vutri.v2); + model.trianglePlanes[i].Unpack(vutri.plane); + + LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); + lasttri = tri; + break; + } +#ifdef FIX_BUGS + // no need to check first again + i++; +#endif + CVuVector pnt, normal; + float dist; + for(; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + + CColTriangle *tri = &model.triangles[i]; + model.vertices[tri->a].Unpack(vutri.v0); + model.vertices[tri->b].Unpack(vutri.v1); + model.vertices[tri->c].Unpack(vutri.v2); + model.trianglePlanes[i].Unpack(vutri.plane); + + if(GetVUresult(pnt, normal, dist)){ + if(dist < coldist){ + point.point = pnt; + point.normal = normal; + point.Set(0, 0, lasttri->surface, 0); + coldist = dist; + registeredCol = true; + }else + registeredCol = false; + }else + registeredCol = false; + + if(registeredCol){ + TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get(); + TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get(); + TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get(); + TempStoredPoly.valid = true; + } + + LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); + lasttri = tri; + } + if(lasttri && GetVUresult(pnt, normal, dist)){ + if(dist < coldist){ + point.point = pnt; + point.normal = normal; + point.Set(0, 0, lasttri->surface, 0); + coldist = dist; + registeredCol = true; + }else + registeredCol = false; + }else + registeredCol = false; + + if(registeredCol){ + TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get(); + TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get(); + TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get(); + TempStoredPoly.valid = true; + } + } + + if(coldist < 1.0f){ + point.point = matrix * point.point; + point.normal = Multiply3x3(matrix, point.normal); + if(TempStoredPoly.valid && poly){ + *poly = TempStoredPoly; + poly->verts[0] = matrix * CVector(poly->verts[0]); + poly->verts[1] = matrix * CVector(poly->verts[1]); + poly->verts[2] = matrix * CVector(poly->verts[2]); + } + mindist *= coldist; + return true; + } + return false; +#else + static CStoredCollPoly TempStoredPoly; + int i; + + // transform line to model space + // Why does the game seem to do this differently than above? + CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1)); + newline.p1.x = newline.p0.x; + newline.p1.y = newline.p0.y; + + if(!TestVerticalLineBox(newline, model.boundingBox)) + return false; + + float coldist = mindist; + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + ProcessLineSphere(newline, model.spheres[i], point, coldist); + } + + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + ProcessLineBox(newline, model.boxes[i], point, coldist); + } + + CalculateTrianglePlanes(&model); + TempStoredPoly.valid = false; + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); + } + + if(coldist < mindist){ + point.point = matrix * point.point; + point.normal = Multiply3x3(matrix, point.normal); + if(TempStoredPoly.valid && poly){ + *poly = TempStoredPoly; + poly->verts[0] = matrix * poly->verts[0]; + poly->verts[1] = matrix * poly->verts[1]; + poly->verts[2] = matrix * poly->verts[2]; + } + mindist = coldist; + return true; + } + return false; +#endif +} + +enum { + MAXNUMSPHERES = 128, + MAXNUMBOXES = 32, + MAXNUMLINES = 16, + MAXNUMTRIS = 600 +}; + +#ifdef VU_COLLISION +#ifdef GTA_PS2 +#define SPR(off) ((uint8*)(0x70000000 + (off))) +#else +static uint8 fakeSPR[16*1024]; +#define SPR(off) ((uint8*)(fakeSPR + (off))) +#endif +#endif + +// This checks model A's spheres and lines against model B's spheres, boxes and triangles. +// Returns the number of A's spheres that collide. +// Returned ColPoints are in world space. +// NB: only vehicles can have col models with lines, exactly 4, one for each wheel +int32 +CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA, + const CMatrix &matrixB, CColModel &modelB, + CColPoint *spherepoints, CColPoint *linepoints, float *linedists) +{ +#ifdef VU_COLLISION + CVuVector *aSpheresA = (CVuVector*)SPR(0x0000); + CVuVector *aSpheresB = (CVuVector*)SPR(0x0800); + CVuVector *aLinesA = (CVuVector*)SPR(0x1000); + int32 *aSphereIndicesA = (int32*)SPR(0x1200); + int32 *aSphereIndicesB = (int32*)SPR(0x1400); + int32 *aBoxIndicesB = (int32*)SPR(0x1600); + int32 *aTriangleIndicesB = (int32*)SPR(0x1680); + bool *aCollided = (bool*)SPR(0x1FE0); + CMatrix &matAB = *(CMatrix*)SPR(0x1FF0); + CMatrix &matBA = *(CMatrix*)SPR(0x2040); + int i, j, k; + + // From model A space to model B space + Invert(matrixB, matAB); + matAB *= matrixA; + + CVuVector bsphereAB; // bounding sphere of A in B space + TransformPoint(bsphereAB, matAB, *(RwV3d*)modelA.boundingSphere.center); // inlined + bsphereAB.w = modelA.boundingSphere.radius; + if(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox)) + return 0; + + // transform modelA's spheres and lines to B space + TransformPoints(aSpheresA, modelA.numSpheres, matAB, (RwV3d*)&modelA.spheres->center, sizeof(CColSphere)); + for(i = 0; i < modelA.numSpheres; i++) + aSpheresA[i].w = modelA.spheres[i].radius; + TransformPoints(aLinesA, modelA.numLines*2, matAB, (RwV3d*)&modelA.lines->p0, sizeof(CColLine)/2); + + // Test them against model B's bounding volumes + int numSpheresA = 0; + for(i = 0; i < modelA.numSpheres; i++) + if(TestSphereBox(*(CColSphere*)&aSpheresA[i], modelB.boundingBox)) + aSphereIndicesA[numSpheresA++] = i; + // No collision + if(numSpheresA == 0 && modelA.numLines == 0) + return 0; + + + // B to A space + Invert(matrixA, matBA); + matBA *= matrixB; + + // transform modelB's spheres to A space + TransformPoints(aSpheresB, modelB.numSpheres, matBA, (RwV3d*)&modelB.spheres->center, sizeof(CColSphere)); + for(i = 0; i < modelB.numSpheres; i++) + aSpheresB[i].w = modelB.spheres[i].radius; + + // Check model B against A's bounding volumes + int numSpheresB = 0; + int numBoxesB = 0; + int numTrianglesB = 0; + for(i = 0; i < modelB.numSpheres; i++) + if(TestSphereBox(*(CColSphere*)&aSpheresB[i], modelA.boundingBox)) + aSphereIndicesB[numSpheresB++] = i; + for(i = 0; i < modelB.numBoxes; i++) + if(TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boxes[i])) + aBoxIndicesB[numBoxesB++] = i; + CalculateTrianglePlanes(&modelB); + if(modelB.numTriangles){ + VuTriangle vutri; + // process the first triangle + CColTriangle *tri = &modelB.triangles[0]; + modelB.vertices[tri->a].Unpack(vutri.v0); + modelB.vertices[tri->b].Unpack(vutri.v1); + modelB.vertices[tri->c].Unpack(vutri.v2); + modelB.trianglePlanes[0].Unpack(vutri.plane); + + SphereToTriangleCollisionCompressed(bsphereAB, vutri); + + for(i = 1; i < modelB.numTriangles; i++){ + // set up the next triangle while VU0 is running + tri = &modelB.triangles[i]; + modelB.vertices[tri->a].Unpack(vutri.v0); + modelB.vertices[tri->b].Unpack(vutri.v1); + modelB.vertices[tri->c].Unpack(vutri.v2); + modelB.trianglePlanes[i].Unpack(vutri.plane); + + // check previous result + if(GetVUresult()) + aTriangleIndicesB[numTrianglesB++] = i-1; + + // kick off this one + SphereToTriangleCollisionCompressed(bsphereAB, vutri); + } + + // check last result + if(GetVUresult()) + aTriangleIndicesB[numTrianglesB++] = i-1; + } + // No collision + if(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0) + return 0; + + // We now have the collision volumes in A and B that are worth processing. + + // Process A's spheres against B's collision volumes + int numCollisions = 0; + spherepoints[numCollisions].depth = -1.0f; + for(i = 0; i < numSpheresA; i++){ + float coldist = 1.0e24f; + bool hasCollided = false; + CColSphere *sphA = &modelA.spheres[aSphereIndicesA[i]]; + CVuVector *vusphA = &aSpheresA[aSphereIndicesA[i]]; + + for(j = 0; j < numSpheresB; j++) + // This actually looks like something was inlined here + if(ProcessSphereSphere(*(CColSphere*)vusphA, modelB.spheres[aSphereIndicesB[j]], + spherepoints[numCollisions], coldist)){ + spherepoints[numCollisions].Set( + sphA->surface, sphA->piece, + modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece); + hasCollided = true; + } + for(j = 0; j < numBoxesB; j++) + if(ProcessSphereBox(*(CColSphere*)vusphA, modelB.boxes[aBoxIndicesB[j]], + spherepoints[numCollisions], coldist)){ + spherepoints[numCollisions].Set( + sphA->surface, sphA->piece, + modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece); + hasCollided = true; + } + if(numTrianglesB){ + CVuVector point, normal; + float depth; + bool registeredCol; + CColTriangle *lasttri; + + VuTriangle vutri; + // process the first triangle + k = aTriangleIndicesB[0]; + CColTriangle *tri = &modelB.triangles[k]; + modelB.vertices[tri->a].Unpack(vutri.v0); + modelB.vertices[tri->b].Unpack(vutri.v1); + modelB.vertices[tri->c].Unpack(vutri.v2); + modelB.trianglePlanes[k].Unpack(vutri.plane); + + SphereToTriangleCollisionCompressed(*vusphA, vutri); + lasttri = tri; + + for(j = 1; j < numTrianglesB; j++){ + k = aTriangleIndicesB[j]; + // set up the next triangle while VU0 is running + tri = &modelB.triangles[k]; + modelB.vertices[tri->a].Unpack(vutri.v0); + modelB.vertices[tri->b].Unpack(vutri.v1); + modelB.vertices[tri->c].Unpack(vutri.v2); + modelB.trianglePlanes[k].Unpack(vutri.plane); + + // check previous result + // TODO: this looks inlined but spherepoints[numCollisions] does not... + if(GetVUresult(point, normal, depth)){ + depth = sphA->radius - depth; + if(depth > spherepoints[numCollisions].depth){ + spherepoints[numCollisions].point = point; + spherepoints[numCollisions].normal = normal; + spherepoints[numCollisions].Set(depth, + sphA->surface, sphA->piece, lasttri->surface, 0); + registeredCol = true; + }else + registeredCol = false; + }else + registeredCol = false; + + if(registeredCol) + hasCollided = true; + + // kick off this one + SphereToTriangleCollisionCompressed(*vusphA, vutri); + lasttri = tri; + } + + // check last result + // TODO: this looks inlined but spherepoints[numCollisions] does not... + if(GetVUresult(point, normal, depth)){ + depth = sphA->radius - depth; + if(depth > spherepoints[numCollisions].depth){ + spherepoints[numCollisions].point = point; + spherepoints[numCollisions].normal = normal; + spherepoints[numCollisions].Set(depth, + sphA->surface, sphA->piece, lasttri->surface, 0); + registeredCol = true; + }else + registeredCol = false; + }else + registeredCol = false; + + if(registeredCol) + hasCollided = true; + } + + if(hasCollided){ + numCollisions++; + if(numCollisions == MAX_COLLISION_POINTS) + break; + spherepoints[numCollisions].depth = -1.0f; + } + } + for(i = 0; i < numCollisions; i++){ + // TODO: both VU0 macros + spherepoints[i].point = matrixB * spherepoints[i].point; + spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal); + } + + // And the same thing for the lines in A + for(i = 0; i < modelA.numLines; i++){ + aCollided[i] = false; + CVuVector *lineA = &aLinesA[i*2]; + + for(j = 0; j < numSpheresB; j++) + if(ProcessLineSphere(*(CColLine*)lineA, modelB.spheres[aSphereIndicesB[j]], + linepoints[i], linedists[i])){ + linepoints[i].Set(0, 0, +#ifdef FIX_BUGS + modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece); +#else + modelB.spheres[j].surface, modelB.spheres[j].piece); +#endif + aCollided[i] = true; + } + for(j = 0; j < numBoxesB; j++) + if(ProcessLineBox(*(CColLine*)lineA, modelB.boxes[aBoxIndicesB[j]], + linepoints[i], linedists[i])){ + linepoints[i].Set(0, 0, + modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece); + aCollided[i] = true; + } + if(numTrianglesB){ + CVuVector point, normal; + float dist; + bool registeredCol; + CColTriangle *lasttri; + + VuTriangle vutri; + // process the first triangle + k = aTriangleIndicesB[0]; + CColTriangle *tri = &modelB.triangles[k]; + modelB.vertices[tri->a].Unpack(vutri.v0); + modelB.vertices[tri->b].Unpack(vutri.v1); + modelB.vertices[tri->c].Unpack(vutri.v2); + modelB.trianglePlanes[k].Unpack(vutri.plane); + + LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri); + lasttri = tri; + + for(j = 1; j < numTrianglesB; j++){ + k = aTriangleIndicesB[j]; + // set up the next triangle while VU0 is running + CColTriangle *tri = &modelB.triangles[k]; + modelB.vertices[tri->a].Unpack(vutri.v0); + modelB.vertices[tri->b].Unpack(vutri.v1); + modelB.vertices[tri->c].Unpack(vutri.v2); + modelB.trianglePlanes[k].Unpack(vutri.plane); + + // check previous result + // TODO: this again somewhat looks inlined + if(GetVUresult(point, normal, dist)){ + if(dist < linedists[i]){ + linepoints[i].point = point; + linepoints[i].normal = normal; + linedists[i] = dist; + linepoints[i].Set(0, 0, lasttri->surface, 0); + registeredCol = true; + }else + registeredCol = false; + }else + registeredCol = false; + + if(registeredCol) + aCollided[i] = true; + + // kick of this one + LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri); + lasttri = tri; + } + + // check last result + if(GetVUresult(point, normal, dist)){ + if(dist < linedists[i]){ + linepoints[i].point = point; + linepoints[i].normal = normal; + linedists[i] = dist; + linepoints[i].Set(0, 0, lasttri->surface, 0); + registeredCol = true; + }else + registeredCol = false; + }else + registeredCol = false; + + if(registeredCol) + aCollided[i] = true; + } + + if(aCollided[i]){ + // TODO: both VU0 macros + linepoints[i].point = matrixB * linepoints[i].point; + linepoints[i].normal = Multiply3x3(matrixB, linepoints[i].normal); + } + } + + return numCollisions; // sphere collisions +#else + static int aSphereIndicesA[MAXNUMSPHERES]; + static int aLineIndicesA[MAXNUMLINES]; + static int aSphereIndicesB[MAXNUMSPHERES]; + static int aBoxIndicesB[MAXNUMBOXES]; + static int aTriangleIndicesB[MAXNUMTRIS]; + static bool aCollided[MAXNUMLINES]; + static CColSphere aSpheresA[MAXNUMSPHERES]; + static CColLine aLinesA[MAXNUMLINES]; + static CMatrix matAB, matBA; + CColSphere s; + int i, j; + + assert(modelA.numSpheres <= MAXNUMSPHERES); + assert(modelA.numLines <= MAXNUMLINES); + + // From model A space to model B space + matAB = Invert(matrixB, matAB); + matAB *= matrixA; + + CColSphere bsphereAB; // bounding sphere of A in B space + bsphereAB.radius = modelA.boundingSphere.radius; + bsphereAB.center = matAB * modelA.boundingSphere.center; + if(!TestSphereBox(bsphereAB, modelB.boundingBox)) + return 0; + // B to A space + matBA = Invert(matrixA, matBA); + matBA *= matrixB; + + // transform modelA's spheres and lines to B space + for(i = 0; i < modelA.numSpheres; i++){ + CColSphere &s = modelA.spheres[i]; + aSpheresA[i].Set(s.radius, matAB * s.center, s.surface, s.piece); + } + for(i = 0; i < modelA.numLines; i++) + aLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1); + + // Test them against model B's bounding volumes + int numSpheresA = 0; + int numLinesA = 0; + for(i = 0; i < modelA.numSpheres; i++) + if(TestSphereBox(aSpheresA[i], modelB.boundingBox)) + aSphereIndicesA[numSpheresA++] = i; + // no actual check??? + for(i = 0; i < modelA.numLines; i++) + aLineIndicesA[numLinesA++] = i; + // No collision + if(numSpheresA == 0 && numLinesA == 0) + return 0; + + // Check model B against A's bounding volumes + int numSpheresB = 0; + int numBoxesB = 0; + int numTrianglesB = 0; + for(i = 0; i < modelB.numSpheres; i++){ + s.radius = modelB.spheres[i].radius; + s.center = matBA * modelB.spheres[i].center; + if(TestSphereBox(s, modelA.boundingBox)) + aSphereIndicesB[numSpheresB++] = i; + } + for(i = 0; i < modelB.numBoxes; i++) + if(TestSphereBox(bsphereAB, modelB.boxes[i])) + aBoxIndicesB[numBoxesB++] = i; + CalculateTrianglePlanes(&modelB); + for(i = 0; i < modelB.numTriangles; i++) + if(TestSphereTriangle(bsphereAB, modelB.vertices, modelB.triangles[i], modelB.trianglePlanes[i])) + aTriangleIndicesB[numTrianglesB++] = i; + assert(numSpheresB <= MAXNUMSPHERES); + assert(numBoxesB <= MAXNUMBOXES); + assert(numTrianglesB <= MAXNUMTRIS); + // No collision + if(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0) + return 0; + + // We now have the collision volumes in A and B that are worth processing. + + // Process A's spheres against B's collision volumes + int numCollisions = 0; + for(i = 0; i < numSpheresA; i++){ + float coldist = 1.0e24f; + bool hasCollided = false; + + for(j = 0; j < numSpheresB; j++) + hasCollided |= ProcessSphereSphere( + aSpheresA[aSphereIndicesA[i]], + modelB.spheres[aSphereIndicesB[j]], + spherepoints[numCollisions], coldist); + for(j = 0; j < numBoxesB; j++) + hasCollided |= ProcessSphereBox( + aSpheresA[aSphereIndicesA[i]], + modelB.boxes[aBoxIndicesB[j]], + spherepoints[numCollisions], coldist); + for(j = 0; j < numTrianglesB; j++) + hasCollided |= ProcessSphereTriangle( + aSpheresA[aSphereIndicesA[i]], + modelB.vertices, + modelB.triangles[aTriangleIndicesB[j]], + modelB.trianglePlanes[aTriangleIndicesB[j]], + spherepoints[numCollisions], coldist); + + if(hasCollided) + numCollisions++; + } + for(i = 0; i < numCollisions; i++){ + spherepoints[i].point = matrixB * spherepoints[i].point; + spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal); + } + + // And the same thing for the lines in A + for(i = 0; i < numLinesA; i++){ + aCollided[i] = false; + + for(j = 0; j < numSpheresB; j++) + aCollided[i] |= ProcessLineSphere( + aLinesA[aLineIndicesA[i]], + modelB.spheres[aSphereIndicesB[j]], + linepoints[aLineIndicesA[i]], + linedists[aLineIndicesA[i]]); + for(j = 0; j < numBoxesB; j++) + aCollided[i] |= ProcessLineBox( + aLinesA[aLineIndicesA[i]], + modelB.boxes[aBoxIndicesB[j]], + linepoints[aLineIndicesA[i]], + linedists[aLineIndicesA[i]]); + for(j = 0; j < numTrianglesB; j++) + aCollided[i] |= ProcessLineTriangle( + aLinesA[aLineIndicesA[i]], + modelB.vertices, + modelB.triangles[aTriangleIndicesB[j]], + modelB.trianglePlanes[aTriangleIndicesB[j]], + linepoints[aLineIndicesA[i]], + linedists[aLineIndicesA[i]]); + } + for(i = 0; i < numLinesA; i++) + if(aCollided[i]){ + j = aLineIndicesA[i]; + linepoints[j].point = matrixB * linepoints[j].point; + linepoints[j].normal = Multiply3x3(matrixB, linepoints[j].normal); + } + + return numCollisions; // sphere collisions +#endif +} + + +// +// Misc +// + +float +CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point) +{ + float lensq = (*l1 - *l0).MagnitudeSqr(); + float dot = DotProduct(*point - *l0, *l1 - *l0); + // Between 0 and len we're above the line. + // if not, calculate distance to endpoint + if(dot <= 0.0f) + return (*point - *l0).Magnitude(); + if(dot >= lensq) + return (*point - *l1).Magnitude(); + // distance to line + return Sqrt((*point - *l0).MagnitudeSqr() - dot*dot/lensq); +} + +// same as above but also return the point on the line +float +CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest) +{ + float lensq = (*l1 - *l0).MagnitudeSqr(); + float dot = DotProduct(*point - *l0, *l1 - *l0); + // find out which point we're closest to + if(dot <= 0.0f) + closest = *l0; + else if(dot >= lensq) + closest = *l1; + else + closest = *l0 + (*l1 - *l0)*(dot/lensq); + // this is the distance + return (*point - closest).Magnitude(); +} + +void +CCollision::CalculateTrianglePlanes(CColModel *model) +{ + assert(model); + if(model->numTriangles == 0) + return; + + CLink *lptr; + if(model->trianglePlanes){ + // re-insert at front so it's not removed again soon + lptr = model->GetLinkPtr(); + lptr->Remove(); + ms_colModelCache.head.Insert(lptr); + }else{ + lptr = ms_colModelCache.Insert(model); + if(lptr == nil){ + // make room if we have to, remove last in list + lptr = ms_colModelCache.tail.prev; + assert(lptr); + assert(lptr->item); + lptr->item->RemoveTrianglePlanes(); + ms_colModelCache.Remove(lptr); + // now this cannot fail + lptr = ms_colModelCache.Insert(model); + assert(lptr); + } + model->CalculateTrianglePlanes(); + model->SetLinkPtr(lptr); + } +} + +void +CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel) +{ + int i; + CVector min, max; + CVector verts[8]; + CVector c; + float r; + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + min = colModel.boundingBox.min; + max = colModel.boundingBox.max; + + verts[0] = mat * CVector(min.x, min.y, min.z); + verts[1] = mat * CVector(min.x, min.y, max.z); + verts[2] = mat * CVector(min.x, max.y, min.z); + verts[3] = mat * CVector(min.x, max.y, max.z); + verts[4] = mat * CVector(max.x, min.y, min.z); + verts[5] = mat * CVector(max.x, min.y, max.z); + verts[6] = mat * CVector(max.x, max.y, min.z); + verts[7] = mat * CVector(max.x, max.y, max.z); + + CLines::RenderLineWithClipping( + verts[0].x, verts[0].y, verts[0].z, + verts[1].x, verts[1].y, verts[1].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[1].x, verts[1].y, verts[1].z, + verts[3].x, verts[3].y, verts[3].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[3].x, verts[3].y, verts[3].z, + verts[2].x, verts[2].y, verts[2].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[2].x, verts[2].y, verts[2].z, + verts[0].x, verts[0].y, verts[0].z, + 0xFF0000FF, 0xFF0000FF); + + CLines::RenderLineWithClipping( + verts[4].x, verts[4].y, verts[4].z, + verts[5].x, verts[5].y, verts[5].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[5].x, verts[5].y, verts[5].z, + verts[7].x, verts[7].y, verts[7].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[7].x, verts[7].y, verts[7].z, + verts[6].x, verts[6].y, verts[6].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[6].x, verts[6].y, verts[6].z, + verts[4].x, verts[4].y, verts[4].z, + 0xFF0000FF, 0xFF0000FF); + + CLines::RenderLineWithClipping( + verts[0].x, verts[0].y, verts[0].z, + verts[4].x, verts[4].y, verts[4].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[1].x, verts[1].y, verts[1].z, + verts[5].x, verts[5].y, verts[5].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[2].x, verts[2].y, verts[2].z, + verts[6].x, verts[6].y, verts[6].z, + 0xFF0000FF, 0xFF0000FF); + CLines::RenderLineWithClipping( + verts[3].x, verts[3].y, verts[3].z, + verts[7].x, verts[7].y, verts[7].z, + 0xFF0000FF, 0xFF0000FF); + + for(i = 0; i < colModel.numSpheres; i++){ + c = mat * colModel.spheres[i].center; + r = colModel.spheres[i].radius; + + CLines::RenderLineWithClipping( + c.x, c.y, c.z-r, + c.x-r, c.y-r, c.z, + 0xFF00FFFF, 0xFF00FFFF); + CLines::RenderLineWithClipping( + c.x, c.y, c.z-r, + c.x-r, c.y+r, c.z, + 0xFF00FFFF, 0xFF00FFFF); + CLines::RenderLineWithClipping( + c.x, c.y, c.z-r, + c.x+r, c.y-r, c.z, + 0xFF00FFFF, 0xFF00FFFF); + CLines::RenderLineWithClipping( + c.x, c.y, c.z-r, + c.x+r, c.y+r, c.z, + 0xFF00FFFF, 0xFF00FFFF); + CLines::RenderLineWithClipping( + c.x-r, c.y-r, c.z, + c.x, c.y, c.z+r, + 0xFF00FFFF, 0xFF00FFFF); + CLines::RenderLineWithClipping( + c.x-r, c.y+r, c.z, + c.x, c.y, c.z+r, + 0xFF00FFFF, 0xFF00FFFF); + CLines::RenderLineWithClipping( + c.x+r, c.y-r, c.z, + c.x, c.y, c.z+r, + 0xFF00FFFF, 0xFF00FFFF); + CLines::RenderLineWithClipping( + c.x+r, c.y+r, c.z, + c.x, c.y, c.z+r, + 0xFF00FFFF, 0xFF00FFFF); + } + + for(i = 0; i < colModel.numLines; i++){ + verts[0] = colModel.lines[i].p0; + verts[1] = colModel.lines[i].p1; + + verts[0] = mat * verts[0]; + verts[1] = mat * verts[1]; + + CLines::RenderLineWithClipping( + verts[0].x, verts[0].y, verts[0].z, + verts[1].x, verts[1].y, verts[1].z, + 0x00FFFFFF, 0x00FFFFFF); + } + + for(i = 0; i < colModel.numBoxes; i++){ + min = colModel.boxes[i].min; + max = colModel.boxes[i].max; + + verts[0] = mat * CVector(min.x, min.y, min.z); + verts[1] = mat * CVector(min.x, min.y, max.z); + verts[2] = mat * CVector(min.x, max.y, min.z); + verts[3] = mat * CVector(min.x, max.y, max.z); + verts[4] = mat * CVector(max.x, min.y, min.z); + verts[5] = mat * CVector(max.x, min.y, max.z); + verts[6] = mat * CVector(max.x, max.y, min.z); + verts[7] = mat * CVector(max.x, max.y, max.z); + + CLines::RenderLineWithClipping( + verts[0].x, verts[0].y, verts[0].z, + verts[1].x, verts[1].y, verts[1].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[1].x, verts[1].y, verts[1].z, + verts[3].x, verts[3].y, verts[3].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[3].x, verts[3].y, verts[3].z, + verts[2].x, verts[2].y, verts[2].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[2].x, verts[2].y, verts[2].z, + verts[0].x, verts[0].y, verts[0].z, + 0xFFFFFFFF, 0xFFFFFFFF); + + CLines::RenderLineWithClipping( + verts[4].x, verts[4].y, verts[4].z, + verts[5].x, verts[5].y, verts[5].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[5].x, verts[5].y, verts[5].z, + verts[7].x, verts[7].y, verts[7].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[7].x, verts[7].y, verts[7].z, + verts[6].x, verts[6].y, verts[6].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[6].x, verts[6].y, verts[6].z, + verts[4].x, verts[4].y, verts[4].z, + 0xFFFFFFFF, 0xFFFFFFFF); + + CLines::RenderLineWithClipping( + verts[0].x, verts[0].y, verts[0].z, + verts[4].x, verts[4].y, verts[4].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[1].x, verts[1].y, verts[1].z, + verts[5].x, verts[5].y, verts[5].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[2].x, verts[2].y, verts[2].z, + verts[6].x, verts[6].y, verts[6].z, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping( + verts[3].x, verts[3].y, verts[3].z, + verts[7].x, verts[7].y, verts[7].z, + 0xFFFFFFFF, 0xFFFFFFFF); + } + + for(i = 0; i < colModel.numTriangles; i++){ + colModel.GetTrianglePoint(verts[0], colModel.triangles[i].a); + colModel.GetTrianglePoint(verts[1], colModel.triangles[i].b); + colModel.GetTrianglePoint(verts[2], colModel.triangles[i].c); + verts[0] = mat * verts[0]; + verts[1] = mat * verts[1]; + verts[2] = mat * verts[2]; + CLines::RenderLineWithClipping( + verts[0].x, verts[0].y, verts[0].z, + verts[1].x, verts[1].y, verts[1].z, + 0x00FF00FF, 0x00FF00FF); + CLines::RenderLineWithClipping( + verts[0].x, verts[0].y, verts[0].z, + verts[2].x, verts[2].y, verts[2].z, + 0x00FF00FF, 0x00FF00FF); + CLines::RenderLineWithClipping( + verts[1].x, verts[1].y, verts[1].z, + verts[2].x, verts[2].y, verts[2].z, + 0x00FF00FF, 0x00FF00FF); + } + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); +} + +void +CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id) +{ + int i; + int s; + float f; + CVector verts[8]; + CVector min, max; + int r, g, b; + RwImVertexIndex *iptr; + RwIm3DVertex *vptr; + + RenderBuffer::ClearRenderBuffer(); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + for(i = 0; i < colModel.numTriangles; i++){ + colModel.GetTrianglePoint(verts[0], colModel.triangles[i].a); + colModel.GetTrianglePoint(verts[1], colModel.triangles[i].b); + colModel.GetTrianglePoint(verts[2], colModel.triangles[i].c); + verts[0] = mat * verts[0]; + verts[1] = mat * verts[1]; + verts[2] = mat * verts[2]; + + // game doesn't do this + r = 255; + g = 128; + b = 0; + + s = colModel.triangles[i].surface; + f = (s & 0xF)/32.0f + 0.5f; + switch(CSurfaceTable::GetAdhesionGroup(s)){ + case ADHESIVE_RUBBER: + r = f * 255.0f; + g = 0; + b = 0; + break; + case ADHESIVE_HARD: + r = f*255.0f; + g = f*255.0f; + b = f*128.0f; + break; + case ADHESIVE_ROAD: + r = f*128.0f; + g = f*128.0f; + b = f*128.0f; + break; + case ADHESIVE_LOOSE: + r = 0; + g = f * 255.0f; + b = 0; + break; + case ADHESIVE_WET: + r = 0; + g = 0; + b = f * 255.0f; + break; + default: + // this doesn't make much sense + r *= f; + g *= f; + b *= f; + } + + if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || + s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) + if(CTimer::GetFrameCounter() & 1){ + r = 0; + g = 0; + b = 0; + } + + if(s > SURFACE_METAL_GATE){ + r = CGeneral::GetRandomNumber(); + g = CGeneral::GetRandomNumber(); + b = CGeneral::GetRandomNumber(); + printf("Illegal surfacetype:%d on MI:%d\n", s, id); + } + + RenderBuffer::StartStoring(6, 3, &iptr, &vptr); + RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255); + RwIm3DVertexSetU(&vptr[0], 0.0f); + RwIm3DVertexSetV(&vptr[0], 0.0f); + RwIm3DVertexSetU(&vptr[1], 0.0f); + RwIm3DVertexSetV(&vptr[1], 1.0f); + RwIm3DVertexSetU(&vptr[2], 1.0f); + RwIm3DVertexSetV(&vptr[2], 1.0f); + RwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z); + RwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z); + RwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z); + iptr[0] = 0; iptr[1] = 1; iptr[2] = 2; + iptr[3] = 0; iptr[4] = 2; iptr[5] = 1; + RenderBuffer::StopStoring(); + } + + for(i = 0; i < colModel.numBoxes; i++){ + min = colModel.boxes[i].min; + max = colModel.boxes[i].max; + + verts[0] = mat * CVector(min.x, min.y, min.z); + verts[1] = mat * CVector(min.x, min.y, max.z); + verts[2] = mat * CVector(min.x, max.y, min.z); + verts[3] = mat * CVector(min.x, max.y, max.z); + verts[4] = mat * CVector(max.x, min.y, min.z); + verts[5] = mat * CVector(max.x, min.y, max.z); + verts[6] = mat * CVector(max.x, max.y, min.z); + verts[7] = mat * CVector(max.x, max.y, max.z); + + s = colModel.boxes[i].surface; + f = (s & 0xF)/32.0f + 0.5f; + switch(CSurfaceTable::GetAdhesionGroup(s)){ + case ADHESIVE_RUBBER: + r = f * 255.0f; + g = 0; + b = 0; + break; + case ADHESIVE_HARD: + r = f*255.0f; + g = f*255.0f; + b = f*128.0f; + break; + case ADHESIVE_ROAD: + r = f*128.0f; + g = f*128.0f; + b = f*128.0f; + break; + case ADHESIVE_LOOSE: + r = 0; + g = f * 255.0f; + b = 0; + break; + case ADHESIVE_WET: + r = 0; + g = 0; + b = f * 255.0f; + break; + default: + // this doesn't make much sense + r *= f; + g *= f; + b *= f; + } + + if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || + s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) + if(CTimer::GetFrameCounter() & 1){ + r = 0; + g = 0; + b = 0; + } + + RenderBuffer::StartStoring(36, 8, &iptr, &vptr); + RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[3], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[4], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[5], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[6], r, g, b, 255); + RwIm3DVertexSetRGBA(&vptr[7], r, g, b, 255); + RwIm3DVertexSetU(&vptr[0], 0.0f); + RwIm3DVertexSetV(&vptr[0], 0.0f); + RwIm3DVertexSetU(&vptr[1], 0.0f); + RwIm3DVertexSetV(&vptr[1], 1.0f); + RwIm3DVertexSetU(&vptr[2], 1.0f); + RwIm3DVertexSetV(&vptr[2], 1.0f); + RwIm3DVertexSetU(&vptr[3], 0.0f); + RwIm3DVertexSetV(&vptr[3], 0.0f); + RwIm3DVertexSetU(&vptr[4], 0.0f); + RwIm3DVertexSetV(&vptr[4], 1.0f); + RwIm3DVertexSetU(&vptr[5], 1.0f); + RwIm3DVertexSetV(&vptr[5], 1.0f); + RwIm3DVertexSetU(&vptr[6], 0.0f); + RwIm3DVertexSetV(&vptr[6], 1.0f); + RwIm3DVertexSetU(&vptr[7], 1.0f); + RwIm3DVertexSetV(&vptr[7], 1.0f); + RwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z); + RwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z); + RwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z); + RwIm3DVertexSetPos(&vptr[3], verts[3].x, verts[3].y, verts[3].z); + RwIm3DVertexSetPos(&vptr[4], verts[4].x, verts[4].y, verts[4].z); + RwIm3DVertexSetPos(&vptr[5], verts[5].x, verts[5].y, verts[5].z); + RwIm3DVertexSetPos(&vptr[6], verts[6].x, verts[6].y, verts[6].z); + RwIm3DVertexSetPos(&vptr[7], verts[7].x, verts[7].y, verts[7].z); + iptr[0] = 0; iptr[1] = 1; iptr[2] = 2; + iptr[3] = 1; iptr[4] = 3; iptr[5] = 2; + iptr[6] = 1; iptr[7] = 5; iptr[8] = 7; + iptr[9] = 1; iptr[10] = 7; iptr[11] = 3; + iptr[12] = 2; iptr[13] = 3; iptr[14] = 7; + iptr[15] = 2; iptr[16] = 7; iptr[17] = 6; + iptr[18] = 0; iptr[19] = 5; iptr[20] = 1; + iptr[21] = 0; iptr[22] = 4; iptr[23] = 5; + iptr[24] = 0; iptr[25] = 2; iptr[26] = 4; + iptr[27] = 2; iptr[28] = 6; iptr[29] = 4; + iptr[30] = 4; iptr[31] = 6; iptr[32] = 7; + iptr[33] = 4; iptr[34] = 7; iptr[35] = 5; + RenderBuffer::StopStoring(); + } + + RenderBuffer::RenderStuffInBuffer(); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); +} \ No newline at end of file diff --git a/src/collision/Collision.h b/src/collision/Collision.h new file mode 100644 index 00000000..f4270bc5 --- /dev/null +++ b/src/collision/Collision.h @@ -0,0 +1,70 @@ +#pragma once + +#include "ColModel.h" +#include "Game.h" // for eLevelName +#ifdef VU_COLLISION +#include "VuVector.h" +#endif + +struct CStoredCollPoly +{ +#ifdef VU_COLLISION + CVuVector verts[3]; +#else + CVector verts[3]; +#endif + bool valid; +}; + +// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32. +#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE) +#define MAX_COLLISION_POINTS 64 +#else +#define MAX_COLLISION_POINTS 32 +#endif + +class CCollision +{ +public: + static eLevelName ms_collisionInMemory; + static CLinkList ms_colModelCache; +#ifdef NO_ISLAND_LOADING + static bool bAlreadyLoaded; +#endif + + static void Init(void); + static void Shutdown(void); + static void Update(void); + static void LoadCollisionWhenINeedIt(bool changeLevel); + static void SortOutCollisionAfterLoad(void); + static void LoadCollisionScreen(eLevelName level); + static void DrawColModel(const CMatrix &mat, const CColModel &colModel); + static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id); + + static void CalculateTrianglePlanes(CColModel *model); + + // all these return true if there's a collision + static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2); + static bool TestSphereBox(const CColSphere &sph, const CColBox &box); + static bool TestLineBox(const CColLine &line, const CColBox &box); + static bool TestVerticalLineBox(const CColLine &line, const CColBox &box); + static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); + static bool TestLineSphere(const CColLine &line, const CColSphere &sph); + static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); + static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough); + + static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq); + static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq); + static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist); + static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly); + static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist); + static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist); + static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq); + static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough); + static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly); + static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists); + static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly); + + static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point); + static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest); +}; diff --git a/src/collision/CompressedVector.h b/src/collision/CompressedVector.h new file mode 100644 index 00000000..d54e49b1 --- /dev/null +++ b/src/collision/CompressedVector.h @@ -0,0 +1,36 @@ +#pragma once + +struct CompressedVector +{ +#ifdef COMPRESSED_COL_VECTORS + int16 x, y, z; + CVector Get(void) const { return CVector(x, y, z)/128.0f; }; + void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; }; +#ifdef GTA_PS2 + void Unpack(uint128 &qword) const { + __asm__ volatile ( + "lh $8, 0(%1)\n" + "lh $9, 2(%1)\n" + "lh $10, 4(%1)\n" + "pextlw $10, $8\n" + "pextlw $2, $9, $10\n" + "sq $2, %0\n" + : "=m" (qword) + : "r" (this) + : "$8", "$9", "$10", "$2" + ); + } +#else + void Unpack(int32 *qword) const { + qword[0] = x; + qword[1] = y; + qword[2] = z; + qword[3] = 0; // junk + } +#endif +#else + float x, y, z; + CVector Get(void) const { return CVector(x, y, z); }; + void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; }; +#endif +}; \ No newline at end of file diff --git a/src/collision/TempColModels.cpp b/src/collision/TempColModels.cpp new file mode 100644 index 00000000..849eb01e --- /dev/null +++ b/src/collision/TempColModels.cpp @@ -0,0 +1,296 @@ +#include "common.h" + +#include "TempColModels.h" + +CColModel CTempColModels::ms_colModelPed1; +CColModel CTempColModels::ms_colModelPed2; +CColModel CTempColModels::ms_colModelBBox; +CColModel CTempColModels::ms_colModelBumper1; +CColModel CTempColModels::ms_colModelWheel1; +CColModel CTempColModels::ms_colModelPanel1; +CColModel CTempColModels::ms_colModelBodyPart2; +CColModel CTempColModels::ms_colModelBodyPart1; +CColModel CTempColModels::ms_colModelCutObj[5]; +CColModel CTempColModels::ms_colModelPedGroundHit; +CColModel CTempColModels::ms_colModelBoot1; +CColModel CTempColModels::ms_colModelDoor1; +CColModel CTempColModels::ms_colModelBonnet1; + + +CColSphere s_aPedSpheres[3]; +CColSphere s_aPed2Spheres[3]; +CColSphere s_aPedGSpheres[4]; +#ifdef FIX_BUGS +CColSphere s_aDoorSpheres[3]; +#else +CColSphere s_aDoorSpheres[4]; +#endif +CColSphere s_aBumperSpheres[4]; +CColSphere s_aPanelSpheres[4]; +CColSphere s_aBonnetSpheres[4]; +CColSphere s_aBootSpheres[4]; +CColSphere s_aWheelSpheres[2]; +CColSphere s_aBodyPartSpheres1[2]; +CColSphere s_aBodyPartSpheres2[2]; + +void +CTempColModels::Initialise(void) +{ +#define SET_COLMODEL_SPHERES(colmodel, sphrs)\ + colmodel.numSpheres = ARRAY_SIZE(sphrs);\ + colmodel.spheres = sphrs;\ + colmodel.level = LEVEL_GENERIC;\ + colmodel.ownsCollisionVolumes = false;\ + + int i; + + ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f)); + ms_colModelBBox.level = LEVEL_GENERIC; + + for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) { + ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f)); + ms_colModelCutObj[i].level = LEVEL_GENERIC; + } + + // Ped Spheres + + for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) + s_aPedSpheres[i].radius = 0.35f; + + s_aPedSpheres[0].center = CVector(0.0f, 0.0f, -0.25f); + s_aPedSpheres[1].center = CVector(0.0f, 0.0f, 0.15f); + s_aPedSpheres[2].center = CVector(0.0f, 0.0f, 0.55f); + +#ifdef FIX_BUGS + for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) { +#else + for (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) { +#endif + s_aPedSpheres[i].surface = SURFACE_PED; + s_aPedSpheres[i].piece = 0; + } + + ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f)); + SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres); + + // Ped 2 Spheres + + s_aPed2Spheres[0].radius = 0.3f; + s_aPed2Spheres[1].radius = 0.4f; + s_aPed2Spheres[2].radius = 0.3f; + + s_aPed2Spheres[0].center = CVector(0.0f, 0.35f, -0.9f); + s_aPed2Spheres[1].center = CVector(0.0f, 0.0f, -0.9f); + s_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f); + + for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { + s_aPed2Spheres[i].surface = SURFACE_PED; + s_aPed2Spheres[i].piece = 0; + } + + ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f)); + + SET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres); + + // Ped ground collision + + s_aPedGSpheres[0].radius = 0.35f; + s_aPedGSpheres[1].radius = 0.35f; + s_aPedGSpheres[2].radius = 0.35f; + s_aPedGSpheres[3].radius = 0.3f; + + s_aPedGSpheres[0].center = CVector(0.0f, -0.4f, -0.9f); + s_aPedGSpheres[1].center = CVector(0.0f, -0.1f, -0.9f); + s_aPedGSpheres[2].center = CVector(0.0f, 0.25f, -0.9f); + s_aPedGSpheres[3].center = CVector(0.0f, 0.65f, -0.9f); + + s_aPedGSpheres[0].surface = SURFACE_PED; + s_aPedGSpheres[1].surface = SURFACE_PED; + s_aPedGSpheres[2].surface = SURFACE_PED; + s_aPedGSpheres[3].surface = SURFACE_PED; + s_aPedGSpheres[0].piece = 4; + s_aPedGSpheres[1].piece = 1; + s_aPedGSpheres[2].piece = 0; + s_aPedGSpheres[3].piece = 6; + + ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f)); + + SET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres); + + // Door Spheres + + s_aDoorSpheres[0].radius = 0.15f; + s_aDoorSpheres[1].radius = 0.15f; + s_aDoorSpheres[2].radius = 0.25f; + + s_aDoorSpheres[0].center = CVector(0.0f, -0.25f, -0.35f); + s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f); + s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f); + +#ifdef FIX_BUGS + for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) { +#else + for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { +#endif + s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL; + s_aDoorSpheres[i].piece = 0; + } + + ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f)); + ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f)); + + SET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres); + + // Bumper Spheres + + for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) + s_aBumperSpheres[i].radius = 0.15f; + + s_aBumperSpheres[0].center = CVector(0.85f, -0.05f, 0.0f); + s_aBumperSpheres[1].center = CVector(0.4f, 0.05f, 0.0f); + s_aBumperSpheres[2].center = CVector(-0.4f, 0.05f, 0.0f); + s_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f); + + for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) { + s_aBumperSpheres[i].surface = SURFACE_CAR_PANEL; + s_aBumperSpheres[i].piece = 0; + } + + ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f)); + ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f)); + + SET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres); + + // Panel Spheres + + for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) + s_aPanelSpheres[i].radius = 0.15f; + + s_aPanelSpheres[0].center = CVector(0.15f, 0.45f, 0.0f); + s_aPanelSpheres[1].center = CVector(0.15f, -0.45f, 0.0f); + s_aPanelSpheres[2].center = CVector(-0.15f, -0.45f, 0.0f); + s_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f); + + for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) { + s_aPanelSpheres[i].surface = SURFACE_CAR_PANEL; + s_aPanelSpheres[i].piece = 0; + } + + ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f)); + + SET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres); + + // Bonnet Spheres + + for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) + s_aBonnetSpheres[i].radius = 0.2f; + + s_aBonnetSpheres[0].center = CVector(-0.4f, 0.1f, 0.0f); + s_aBonnetSpheres[1].center = CVector(-0.4f, 0.9f, 0.0f); + s_aBonnetSpheres[2].center = CVector(0.4f, 0.1f, 0.0f); + s_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f); + + for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) { + s_aBonnetSpheres[i].surface = SURFACE_CAR_PANEL; + s_aBonnetSpheres[i].piece = 0; + } + + ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f)); + ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f)); + + SET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres); + + // Boot Spheres + + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) + s_aBootSpheres[i].radius = 0.2f; + + s_aBootSpheres[0].center = CVector(-0.4f, -0.1f, 0.0f); + s_aBootSpheres[1].center = CVector(-0.4f, -0.6f, 0.0f); + s_aBootSpheres[2].center = CVector(0.4f, -0.1f, 0.0f); + s_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f); + + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { + s_aBootSpheres[i].surface = SURFACE_CAR_PANEL; + s_aBootSpheres[i].piece = 0; + } + + ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f)); + ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f)); + + SET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres); + + // Wheel Spheres + + s_aWheelSpheres[0].radius = 0.35f; + s_aWheelSpheres[1].radius = 0.35f; + + s_aWheelSpheres[0].center = CVector(-0.3f, 0.0f, 0.0f); + s_aWheelSpheres[1].center = CVector(0.3f, 0.0f, 0.0f); + +#ifdef FIX_BUGS + for (i = 0; i < ARRAY_SIZE(s_aWheelSpheres); i++) { +#else + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { +#endif + s_aWheelSpheres[i].surface = SURFACE_WHEELBASE; + s_aWheelSpheres[i].piece = 0; + } + + ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f)); + + SET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres); + + // Body Part Spheres 1 + + s_aBodyPartSpheres1[0].radius = 0.2f; + s_aBodyPartSpheres1[1].radius = 0.2f; + + s_aBodyPartSpheres1[0].center = CVector(0.0f, 0.0f, 0.0f); + s_aBodyPartSpheres1[1].center = CVector(0.8f, 0.0f, 0.0f); + +#ifdef FIX_BUGS + for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres1); i++) { +#else + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { +#endif + s_aBodyPartSpheres1[i].surface = SURFACE_PED; + s_aBodyPartSpheres1[i].piece = 0; + } + + ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f)); + ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f)); + + SET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1); + + // Body Part Spheres 2 + + s_aBodyPartSpheres2[0].radius = 0.15f; + s_aBodyPartSpheres2[1].radius = 0.15f; + + s_aBodyPartSpheres2[0].center = CVector(0.0f, 0.0f, 0.0f); + s_aBodyPartSpheres2[1].center = CVector(0.5f, 0.0f, 0.0f); + +#ifdef FIX_BUGS + for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres2); i++) { +#else + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { +#endif + s_aBodyPartSpheres2[i].surface = SURFACE_PED; + s_aBodyPartSpheres2[i].piece = 0; + } + + ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f)); + ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f)); + + SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2); + +#undef SET_COLMODEL_SPHERES +} diff --git a/src/collision/TempColModels.h b/src/collision/TempColModels.h new file mode 100644 index 00000000..3e1dd5e1 --- /dev/null +++ b/src/collision/TempColModels.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Collision.h" + +class CTempColModels +{ +public: + static CColModel ms_colModelPed1; + static CColModel ms_colModelPed2; + static CColModel ms_colModelBBox; + static CColModel ms_colModelBumper1; + static CColModel ms_colModelWheel1; + static CColModel ms_colModelPanel1; + static CColModel ms_colModelBodyPart2; + static CColModel ms_colModelBodyPart1; + static CColModel ms_colModelCutObj[5]; + static CColModel ms_colModelPedGroundHit; + static CColModel ms_colModelBoot1; + static CColModel ms_colModelDoor1; + static CColModel ms_colModelBonnet1; + + static void Initialise(void); +}; diff --git a/src/collision/VuCollision.cpp b/src/collision/VuCollision.cpp new file mode 100644 index 00000000..8828d2e1 --- /dev/null +++ b/src/collision/VuCollision.cpp @@ -0,0 +1,282 @@ +#include "common.h" +#ifdef VU_COLLISION +#include "VuVector.h" +#include "VuCollision.h" + +#ifndef GTA_PS2 +int16 vi01; +CVuVector vf01; +CVuVector vf02; +CVuVector vf03; + +CVuVector +DistanceBetweenSphereAndLine(const CVuVector ¢er, const CVuVector &p0, const CVuVector &line) +{ + // center VF12 + // p0 VF14 + // line VF15 + CVuVector ret; // VF16 + CVuVector p1 = p0+line; + CVuVector dist0 = center - p0; // VF20 + CVuVector dist1 = center - p1; // VF25 + float lenSq = line.MagnitudeSqr(); // VF21 + float distSq0 = dist0.MagnitudeSqr(); // VF22 + float distSq1 = dist1.MagnitudeSqr(); + float dot = DotProduct(dist0, line); // VF23 + if(dot < 0.0f){ + // not above line, closest to p0 + ret = p0; + ret.w = distSq0; + return ret; + } + float t = dot/lenSq; // param of nearest point on infinite line + if(t > 1.0f){ + // not above line, closest to p1 + ret = p1; + ret.w = distSq1; + return ret; + } + // closest to line + ret = p0 + line*t; + ret.w = (ret - center).MagnitudeSqr(); + return ret; +} +inline int SignFlags(const CVector &v) +{ + int f = 0; + if(v.x < 0.0f) f |= 1; + if(v.y < 0.0f) f |= 2; + if(v.z < 0.0f) f |= 4; + return f; +} +#endif + +extern "C" void +LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1, + const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, + const CVuVector &plane) +{ +#ifdef GTA_PS2 + __asm__ volatile ( + ".set noreorder\n" + "lqc2 vf12, 0x0(%0)\n" + "lqc2 vf13, 0x0(%1)\n" + "lqc2 vf14, 0x0(%2)\n" + "lqc2 vf15, 0x0(%3)\n" + "lqc2 vf16, 0x0(%4)\n" + "lqc2 vf17, 0x0(%5)\n" + "vcallms Vu0LineToTriangleCollisionStart\n" + ".set reorder\n" + : + : "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane) + ); +#else + float dot0 = DotProduct(plane, p0); + float dot1 = DotProduct(plane, p1); + float dist0 = plane.w - dot0; + float dist1 = plane.w - dot1; + + // if points are on the same side, no collision + if(dist0 * dist1 > 0.0f){ + vi01 = 0; + return; + } + + CVuVector diff = p1 - p0; + float t = dist0/(dot1 - dot0); + CVuVector p = p0 + diff*t; + p.w = 0.0f; + vf01 = p; + vf03.x = t; + + // Check if point is inside + CVector cross1 = CrossProduct(p-v0, v1-v0); + CVector cross2 = CrossProduct(p-v1, v2-v1); + CVector cross3 = CrossProduct(p-v2, v0-v2); + // Only check relevant directions + int flagmask = 0; + if(Abs(plane.x) > 0.5f) flagmask |= 1; + if(Abs(plane.y) > 0.5f) flagmask |= 2; + if(Abs(plane.z) > 0.5f) flagmask |= 4; + int flags1 = SignFlags(cross1) & flagmask; + int flags2 = SignFlags(cross2) & flagmask; + int flags3 = SignFlags(cross3) & flagmask; + // inside if on the same side of all edges + if(flags1 != flags2 || flags1 != flags3){ + vi01 = 0; + return; + } + vi01 = 1; + vf02 = plane; + return; +#endif +} + +extern "C" void +LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri) +{ +#ifdef GTA_PS2 + __asm__ volatile ( + ".set noreorder\n" + "lqc2 vf12, 0x0(%0)\n" + "lqc2 vf13, 0x0(%1)\n" + "lqc2 vf14, 0x0(%2)\n" + "lqc2 vf15, 0x10(%2)\n" + "lqc2 vf16, 0x20(%2)\n" + "lqc2 vf17, 0x30(%2)\n" + "vcallms Vu0LineToTriangleCollisionCompressedStart\n" + ".set reorder\n" + : + : "r" (&p0), "r" (&p1), "r" (&tri) + ); +#else + CVuVector v0, v1, v2, plane; + v0.x = tri.v0[0]/128.0f; + v0.y = tri.v0[1]/128.0f; + v0.z = tri.v0[2]/128.0f; + v0.w = tri.v0[3]/128.0f; + v1.x = tri.v1[0]/128.0f; + v1.y = tri.v1[1]/128.0f; + v1.z = tri.v1[2]/128.0f; + v1.w = tri.v1[3]/128.0f; + v2.x = tri.v2[0]/128.0f; + v2.y = tri.v2[1]/128.0f; + v2.z = tri.v2[2]/128.0f; + v2.w = tri.v2[3]/128.0f; + plane.x = tri.plane[0]/4096.0f; + plane.y = tri.plane[1]/4096.0f; + plane.z = tri.plane[2]/4096.0f; + plane.w = tri.plane[3]/128.0f; + LineToTriangleCollision(p0, p1, v0, v1, v2, plane); +#endif +} + +extern "C" void +SphereToTriangleCollision(const CVuVector &sph, + const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, + const CVuVector &plane) +{ +#ifdef GTA_PS2 + __asm__ volatile ( + ".set noreorder\n" + "lqc2 vf12, 0x0(%0)\n" + "lqc2 vf14, 0x0(%1)\n" + "lqc2 vf15, 0x0(%2)\n" + "lqc2 vf16, 0x0(%3)\n" + "lqc2 vf17, 0x0(%4)\n" + "vcallms Vu0SphereToTriangleCollisionStart\n" + ".set reorder\n" + : + : "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane) + ); +#else + float planedist = DotProduct(plane, sph) - plane.w; // VF02 + if(Abs(planedist) > sph.w){ + vi01 = 0; + return; + } + // point on plane + CVuVector p = sph - planedist*plane; + p.w = 0.0f; + vf01 = p; + planedist = Abs(planedist); + // edges + CVuVector v01 = v1 - v0; + CVuVector v12 = v2 - v1; + CVuVector v20 = v0 - v2; + // VU code calculates normal again for some weird reason... + // Check sides of point + CVector cross1 = CrossProduct(p-v0, v01); + CVector cross2 = CrossProduct(p-v1, v12); + CVector cross3 = CrossProduct(p-v2, v20); + // Only check relevant directions + int flagmask = 0; + if(Abs(plane.x) > 0.1f) flagmask |= 1; + if(Abs(plane.y) > 0.1f) flagmask |= 2; + if(Abs(plane.z) > 0.1f) flagmask |= 4; + int nflags = SignFlags(plane) & flagmask; + int flags1 = SignFlags(cross1) & flagmask; + int flags2 = SignFlags(cross2) & flagmask; + int flags3 = SignFlags(cross3) & flagmask; + int testcase = 0; + CVuVector closest(0.0f, 0.0f, 0.0f); // VF04 + if(flags1 == nflags){ + closest += v2; + testcase++; + } + if(flags2 == nflags){ + closest += v0; + testcase++; + } + if(flags3 == nflags){ + closest += v1; + testcase++; + } + if(testcase == 3){ + // inside triangle - dist to plane already checked + vf02 = plane; + vf02.w = vf03.x = planedist; + vi01 = 1; + }else if(testcase == 1){ + // outside two sides - closest to point opposide inside edge + vf01 = closest; + vf02 = sph - closest; + float distSq = vf02.MagnitudeSqr(); + vi01 = sph.w*sph.w > distSq; + vf03.x = Sqrt(distSq); + vf02 *= 1.0f/vf03.x; + }else{ + // inside two sides - closest to third edge + if(flags1 != nflags) + closest = DistanceBetweenSphereAndLine(sph, v0, v01); + else if(flags2 != nflags) + closest = DistanceBetweenSphereAndLine(sph, v1, v12); + else + closest = DistanceBetweenSphereAndLine(sph, v2, v20); + vi01 = sph.w*sph.w > closest.w; + vf01 = closest; + vf02 = sph - closest; + vf03.x = Sqrt(closest.w); + vf02 *= 1.0f/vf03.x; + } +#endif +} + +extern "C" void +SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri) +{ +#ifdef GTA_PS2 + __asm__ volatile ( + ".set noreorder\n" + "lqc2 vf12, 0x0(%0)\n" + "lqc2 vf14, 0x0(%1)\n" + "lqc2 vf15, 0x10(%1)\n" + "lqc2 vf16, 0x20(%1)\n" + "lqc2 vf17, 0x30(%1)\n" + "vcallms Vu0SphereToTriangleCollisionCompressedStart\n" + ".set reorder\n" + : + : "r" (&sph), "r" (&tri) + ); +#else + CVuVector v0, v1, v2, plane; + v0.x = tri.v0[0]/128.0f; + v0.y = tri.v0[1]/128.0f; + v0.z = tri.v0[2]/128.0f; + v0.w = tri.v0[3]/128.0f; + v1.x = tri.v1[0]/128.0f; + v1.y = tri.v1[1]/128.0f; + v1.z = tri.v1[2]/128.0f; + v1.w = tri.v1[3]/128.0f; + v2.x = tri.v2[0]/128.0f; + v2.y = tri.v2[1]/128.0f; + v2.z = tri.v2[2]/128.0f; + v2.w = tri.v2[3]/128.0f; + plane.x = tri.plane[0]/4096.0f; + plane.y = tri.plane[1]/4096.0f; + plane.z = tri.plane[2]/4096.0f; + plane.w = tri.plane[3]/128.0f; + SphereToTriangleCollision(sph, v0, v1, v2, plane); +#endif +} +#endif \ No newline at end of file diff --git a/src/collision/VuCollision.h b/src/collision/VuCollision.h new file mode 100644 index 00000000..29ca4cbf --- /dev/null +++ b/src/collision/VuCollision.h @@ -0,0 +1,32 @@ +#pragma once + + +struct VuTriangle +{ + // Compressed int16 but unpacked +#ifdef GTA_PS2 + uint128 v0; + uint128 v1; + uint128 v2; + uint128 plane; +#else + int32 v0[4]; + int32 v1[4]; + int32 v2[4]; + int32 plane[4]; +#endif +}; + +#ifndef GTA_PS2 +extern int16 vi01; +extern CVuVector vf01; +extern CVuVector vf02; +extern CVuVector vf03; +#endif + +extern "C" { +void LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane); +void LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri); +void SphereToTriangleCollision(const CVuVector &sph, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane); +void SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri); +} diff --git a/src/collision/vu0Collision.dsm b/src/collision/vu0Collision.dsm new file mode 100644 index 00000000..657c8b81 --- /dev/null +++ b/src/collision/vu0Collision.dsm @@ -0,0 +1,21 @@ +.align 4 +.global Vu0CollisionDmaTag +Vu0CollisionDmaTag: +DMAcnt * +MPG 0, * +.vu +.include "vu0Collision_1.s" +.EndMPG +.EndDmaData +DMAend + +.global Vu0Collision2DmaTag +Vu0Collision2DmaTag: +DMAcnt * +MPG 0, * +.vu +.include "vu0Collision_2.s" +.EndMPG +.EndDmaData +DMAend +.end diff --git a/src/collision/vu0Collision_1.s b/src/collision/vu0Collision_1.s new file mode 100644 index 00000000..055c8640 --- /dev/null +++ b/src/collision/vu0Collision_1.s @@ -0,0 +1,610 @@ +QuitAndFail: + NOP[E] IADDIU VI01, VI00, 0 + NOP NOP + + +QuitAndSucceed: + NOP[E] IADDIU VI01, VI00, 1 + NOP NOP + + +; 20 -- unused +; VF12, VF13 xyz: sphere centers +; VF14, VF15 x: sphere radii +; out: +; VI01: set when collision +; VF01: supposed to be intersection point? +; VF02: normal (pointing towards s1, not normalized) +.globl Vu0SphereToSphereCollision +Vu0SphereToSphereCollision: + SUB.xyz VF02, VF13, VF12 NOP ; dist of centers + ADD.x VF04, VF14, VF15 NOP ; s = sum of radii + MUL.xyzw VF03, VF02, VF02 NOP ; + MUL.x VF04, VF04, VF04 DIV Q, VF14x, VF04x ; square s + NOP NOP ; + NOP NOP ; + MULAx.w ACC, VF00, VF03 NOP ; + MADDAy.w ACC, VF00, VF03 NOP ; + MADDz.w VF03, VF00, VF03 NOP ; d = DistSq of centers + NOP NOP ; + MULAw.xyz ACC, VF12, VF00 NOP ; + MADDq.xyz VF01, VF02, Q NOP ; intersection, but wrong + CLIPw.xyz VF04, VF03 NOP ; compare s and d + SUB.xyz VF02, VF00, VF02 NOP ; compute normal + NOP NOP ; + NOP NOP ; + NOP FCAND VI01, 0x3 ; 0x2 cannot be set here + NOP[E] NOP ; + NOP NOP ; + + +; B8 -- unused +; VF12: +; VF13: radius +; VF14: +; VF15: box dimensions (?) +.globl Vu0SphereToAABBCollision +Vu0SphereToAABBCollision: + SUB.xyz VF03, VF12, VF14 LOI 0.5 + MULi.xyz VF15, VF15, I NOP + MUL.x VF13, VF13, VF13 NOP + SUB.xyz VF04, VF03, VF15 NOP + ADD.xyz VF05, VF03, VF15 MR32.xyzw VF16, VF15 + CLIPw.xyz VF03, VF16 MR32.xyzw VF17, VF16 + MUL.xyz VF04, VF04, VF04 NOP + MUL.xyz VF05, VF05, VF05 NOP + CLIPw.xyz VF03, VF17 MR32.xyzw VF16, VF17 + NOP FCAND VI01, 0x1 + MINI.xyz VF04, VF04, VF05 MFIR.x VF09, VI01 + NOP NOP + CLIPw.xyz VF03, VF16 FCAND VI01, 0x4 + NOP MFIR.y VF09, VI01 + NOP NOP + MULAx.w ACC, VF00, VF00 NOP + ADD.xyz VF01, VF00, VF03 FCAND VI01, 0x10 + NOP MFIR.z VF09, VI01 + NOP LOI 2 + NOP FCAND VI01, 0x30 + SUBAw.xyz ACC, VF00, VF00 IADD VI04, VI00, VI01 + ITOF0.xyz VF09, VF09 FCAND VI01, 0x300 + NOP IADD VI03, VI00, VI01 + NOP FCAND VI01, 0x3000 + NOP IADD VI02, VI00, VI01 + MADDi.xyzw VF09, VF09, I NOP + NOP IBEQ VI04, VI00, IgnoreZValue + NOP NOP + MADDAz.w ACC, VF00, VF04 NOP + MUL.z VF01, VF09, VF15 NOP +IgnoreZValue: + NOP IBEQ VI03, VI00, IgnoreYValue + NOP NOP + MADDAy.w ACC, VF00, VF04 NOP + MUL.y VF01, VF09, VF15 NOP +IgnoreYValue: + NOP IBEQ VI02, VI00, IgnoreXValue + NOP NOP + MADDAx.w ACC, VF00, VF04 NOP + MUL.x VF01, VF09, VF15 NOP +IgnoreXValue: + MADDx.w VF06, VF00, VF00 NOP + SUB.xyz VF02, VF03, VF01 NOP + ADD.xyz VF01, VF01, VF14 NOP + MULx.w VF01, VF00, VF00 NOP + CLIPw.xyz VF13, VF06 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x1 +QuitMicrocode: + NOP[E] NOP + NOP NOP + + +; 240 +.globl Vu0LineToSphereCollision +Vu0LineToSphereCollision: + SUB.xyzw VF01, VF13, VF12 NOP + SUB.xyzw VF02, VF14, VF12 NOP + MUL.xyz VF03, VF01, VF02 NOP + MUL.xyz VF04, VF01, VF01 NOP + MUL.x VF15, VF15, VF15 NOP + MUL.xyz VF02, VF02, VF02 NOP + MULAx.w ACC, VF00, VF03 NOP + MADDAy.w ACC, VF00, VF03 NOP + MADDz.w VF03, VF00, VF03 NOP + MULAx.w ACC, VF00, VF04 NOP + MADDAy.w ACC, VF00, VF04 NOP + MADDz.w VF01, VF00, VF04 NOP + MULAx.w ACC, VF00, VF02 NOP + MADDAy.w ACC, VF00, VF02 NOP + MADDz.w VF02, VF00, VF02 NOP + MULA.w ACC, VF03, VF03 NOP + MADDAx.w ACC, VF01, VF15 NOP + MSUB.w VF05, VF01, VF02 NOP + NOP NOP + NOP NOP + NOP IADDIU VI02, VI00, 0x10 + NOP FMAND VI01, VI02 + NOP IBNE VI01, VI00, QuitAndFail + NOP NOP + CLIPw.xyz VF15, VF02 SQRT Q, VF05w + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x1 + NOP IBNE VI00, VI01, LineStartInsideSphere + NOP NOP + SUBq.w VF05, VF03, Q NOP + SUB.w VF05, VF05, VF01 DIV Q, VF05w, VF01w + NOP FMAND VI01, VI02 + NOP IBNE VI01, VI00, QuitAndFail + NOP NOP + NOP FMAND VI01, VI02 + NOP IBEQ VI01, VI00, QuitAndFail + NOP NOP + ADDA.xyz ACC, VF12, VF00 NOP + MADDq.xyz VF01, VF01, Q NOP + MULx.w VF01, VF00, VF00 NOP + SUB.xyz VF02, VF01, VF14 NOP + NOP[E] NOP + NOP NOP +LineStartInsideSphere: + NOP MOVE.xyzw VF01, VF12 + NOP[E] IADDIU VI01, VI00, 0x1 + NOP NOP + + +; 3C0 +.globl Vu0LineToAABBCollision +Vu0LineToAABBCollision: + SUB.xyzw VF08, VF13, VF12 LOI 0.5 + MULi.xyz VF15, VF15, I IADDIU VI08, VI00, 0x0 + SUB.xyzw VF12, VF12, VF14 NOP + SUB.xyzw VF13, VF13, VF14 NOP + NOP DIV Q, VF00w, VF08x + NOP MR32.xyzw VF03, VF15 + SUB.xyz VF06, VF15, VF12 NOP + ADD.xyz VF07, VF15, VF12 NOP + NOP NOP + CLIPw.xyz VF12, VF03 MR32.xyzw VF04, VF03 + NOP NOP + ADDq.x VF09, VF00, Q DIV Q, VF00w, VF08y + NOP NOP + CLIPw.xyz VF12, VF04 MR32.xyzw VF05, VF04 + SUB.xyz VF07, VF00, VF07 IADDIU VI06, VI00, 0xCC + NOP IADDIU VI07, VI00, 0x30 + NOP NOP + CLIPw.xyz VF12, VF05 FCGET VI02 + NOP IAND VI02, VI02, VI06 + ADDq.y VF09, VF00, Q DIV Q, VF00w, VF08z + SUB.xyz VF10, VF00, VF10 NOP + CLIPw.xyz VF13, VF03 FCGET VI03 + CLIPw.xyz VF13, VF04 IAND VI03, VI03, VI07 + CLIPw.xyz VF13, VF05 FCAND VI01, 0x3330 + NOP IBEQ VI01, VI00, StartPointInsideAABB + NOP NOP + ADDq.z VF09, VF00, Q FCGET VI04 + NOP FCGET VI05 + NOP IAND VI04, VI04, VI06 + NOP IAND VI05, VI05, VI07 + MULx.xyz VF17, VF08, VF09 NOP + MULy.xyz VF18, VF08, VF09 IADDIU VI07, VI00, 0x80 + MULz.xyz VF19, VF08, VF09 IAND VI06, VI02, VI07 + MUL.w VF10, VF00, VF00 IAND VI07, VI04, VI07 + NOP NOP + NOP IBEQ VI06, VI07, CheckMaxXSide + NOP NOP + MULAx.xyz ACC, VF17, VF07 NOP + MADDw.xyz VF16, VF12, VF00 NOP + MUL.x VF10, VF07, VF09 NOP + CLIPw.xyz VF16, VF04 NOP + CLIPw.xyz VF16, VF05 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x330 + NOP IBNE VI01, VI00, CheckMaxXSide + NOP NOP + MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 + ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 + SUBw.x VF02, VF00, VF00 NOP +CheckMaxXSide: + MULAx.xyz ACC, VF17, VF06 IADDIU VI07, VI00, 0x40 + MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07 + MUL.x VF10, VF06, VF09 IAND VI07, VI04, VI07 + NOP NOP + NOP IBEQ VI06, VI07, CheckMinYSide + NOP NOP + CLIPw.xyz VF16, VF04 NOP + CLIPw.xyz VF16, VF05 NOP + CLIPw.xyz VF10, VF10 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0xCC03 + NOP IBNE VI01, VI00, CheckMinYSide + NOP NOP + MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 + ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 + ADDw.x VF02, VF00, VF00 NOP +CheckMinYSide: + MULAy.xyz ACC, VF18, VF07 IADDIU VI07, VI00, 0x8 + MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07 + MUL.y VF10, VF07, VF09 IAND VI07, VI04, VI07 + NOP NOP + NOP IBEQ VI06, VI07, CheckMaxYSide + NOP NOP + CLIPw.xyz VF16, VF03 NOP + CLIPw.xyz VF16, VF05 NOP + CLIPw.xyz VF10, VF10 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x3C0C + NOP IBNE VI01, VI00, CheckMaxYSide + NOP NOP + MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 + ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 + SUBw.y VF02, VF00, VF00 NOP +CheckMaxYSide: + MULAy.xyz ACC, VF18, VF06 IADDIU VI07, VI00, 0x4 + MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07 + MUL.y VF10, VF06, VF09 IAND VI07, VI04, VI07 + NOP NOP + NOP IBEQ VI06, VI07, CheckMinZSide + NOP NOP + CLIPw.xyz VF16, VF03 NOP + CLIPw.xyz VF16, VF05 NOP + CLIPw.xyz VF10, VF10 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x3C0C + NOP IBNE VI01, VI00, CheckMinZSide + NOP NOP + MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 + ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 + ADDw.y VF02, VF00, VF00 NOP +CheckMinZSide: + MULAz.xyz ACC, VF19, VF07 IADDIU VI07, VI00, 0x20 + MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07 + MUL.z VF10, VF07, VF09 IAND VI07, VI05, VI07 + NOP NOP + NOP IBEQ VI06, VI07, CheckMaxZSide + NOP NOP + CLIPw.xyz VF16, VF03 NOP + CLIPw.xyz VF16, VF04 NOP + CLIPw.xyz VF10, VF10 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x3330 + NOP IBNE VI01, VI00, CheckMaxZSide + NOP NOP + MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 + ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16 + SUBw.z VF02, VF00, VF00 NOP +CheckMaxZSide: + MULAz.xyz ACC, VF19, VF06 IADDIU VI07, VI00, 0x10 + MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07 + MUL.z VF10, VF06, VF09 IAND VI07, VI05, VI07 + NOP NOP + NOP IBEQ VI06, VI07, DoneAllChecks + NOP NOP + CLIPw.xyz VF16, VF03 NOP + CLIPw.xyz VF16, VF04 NOP + CLIPw.xyz VF10, VF10 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x3330 + NOP IBNE VI01, VI00, DoneAllChecks + NOP NOP + MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 + ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16 + ADDw.z VF02, VF00, VF00 NOP +DoneAllChecks: + ADD.xyz VF01, VF01, VF14 IADD VI01, VI00, VI08 + NOP[E] NOP + NOP NOP +StartPointInsideAABB: + ADD.xyz VF01, VF12, VF14 WAITQ + NOP IADDIU VI01, VI00, 0x1 + NOP[E] NOP + NOP NOP + + +; 860 +.globl Vu0LineToTriangleCollisionCompressedStart +Vu0LineToTriangleCollisionCompressedStart: + ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0 + ITOF0.xyzw VF14, VF14 NOP + ITOF0.xyzw VF15, VF15 NOP + ITOF0.xyzw VF16, VF16 NOP + MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0 + MULi.w VF17, VF17, I NOP + MULi.xyzw VF14, VF14, I NOP + MULi.xyzw VF15, VF15, I NOP + MULi.xyzw VF16, VF16, I NOP +; fall through + +; 8A8 +; VF12: point0 +; VF13: point1 +; VF14-16: verts +; VF17: plane +; out: +; VF01: intersection point +; VF02: triangle normal +; VF03 x: intersection parameter +.globl Vu0LineToTriangleCollisionStart +Vu0LineToTriangleCollisionStart: + MUL.xyz VF10, VF17, VF12 LOI 0.5 + MUL.xyz VF11, VF17, VF13 NOP + SUB.xyz VF02, VF13, VF12 NOP ; line dist + ADD.xyz VF17, VF17, VF00 NOP + MULi.w VF03, VF00, I NOP + MULAx.w ACC, VF00, VF10 NOP + MADDAy.w ACC, VF00, VF10 IADDIU VI06, VI00, 0xE0 + MADDz.w VF10, VF00, VF10 FMAND VI05, VI06 ; -- normal sign flags, unused + MULAx.w ACC, VF00, VF11 NOP + MADDAy.w ACC, VF00, VF11 NOP + MADDz.w VF11, VF00, VF11 NOP + SUB.w VF09, VF17, VF10 NOP ; plane-pos 0 + CLIPw.xyz VF17, VF03 NOP ; compare normal against 0.5 to figure out which in which dimension to compare + NOP IADDIU VI02, VI00, 0x10 ; Sw flag + SUBA.w ACC, VF17, VF11 NOP ; plane-pos 1 + SUB.w VF08, VF11, VF10 FMAND VI01, VI02 + NOP NOP + NOP NOP + NOP FMAND VI02, VI02 + NOP IBEQ VI01, VI02, QuitAndFail ; if on same side, no collision + NOP NOP + NOP DIV Q, VF09w, VF08w ; parameter of intersection + NOP FCAND VI01, 0x3 ; check x direction + NOP IADDIU VI02, VI01, 0x7F + NOP IADDIU VI06, VI00, 0x80 + NOP IAND VI02, VI02, VI06 ; Sx flag + NOP FCAND VI01, 0xC ; check y direction + NOP IADDIU VI03, VI01, 0x3F + MULAw.xyz ACC, VF12, VF00 IADDIU VI06, VI00, 0x40 + MADDq.xyz VF01, VF02, Q IAND VI03, VI03, VI06 ; point of intersection -- Sy flag + MULx.w VF01, VF00, VF00 FCAND VI01, 0x30 ; -- check z direction + ADDq.x VF03, VF00, Q IADDIU VI04, VI01, 0x1F ; output parameter + SUB.xyz VF05, VF15, VF14 IADDIU VI06, VI00, 0x20 ; edge vectors + SUB.xyz VF08, VF01, VF14 IAND VI04, VI04, VI06 ; edge vectors -- Sz flag + SUB.xyz VF06, VF16, VF15 IADD VI06, VI02, VI03 ; edge vectors + SUB.xyz VF09, VF01, VF15 IADD VI06, VI06, VI04 ; edge vectors -- combine flags + SUB.xyz VF07, VF14, VF16 NOP ; edge vectors + SUB.xyz VF10, VF01, VF16 NOP ; edge vectors + OPMULA.xyz ACC, VF08, VF05 NOP + OPMSUB.xyz VF18, VF05, VF08 NOP ; cross1 + OPMULA.xyz ACC, VF09, VF06 NOP + OPMSUB.xyz VF19, VF06, VF09 NOP ; cross2 + OPMULA.xyz ACC, VF10, VF07 NOP + OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; cross3 + NOP NOP + NOP FMAND VI03, VI06 + NOP NOP + NOP FMAND VI04, VI06 + NOP NOP + NOP IBNE VI03, VI02, QuitAndFail ; point has to lie on the same side of all edges (i.e. inside) + NOP NOP + NOP IBNE VI04, VI02, QuitAndFail + NOP NOP + MULw.xyz VF02, VF17, VF00 IADDIU VI01, VI00, 0x1 ; success + NOP[E] NOP + NOP NOP + + +; A68 +; VF12: center +; VF14: line origin +; VF15: line vector to other point +; out: VF16 xyz: nearest point on line; w: distance to that point +DistanceBetweenSphereAndLine: + SUB.xyz VF20, VF12, VF14 NOP + MUL.xyz VF21, VF15, VF15 NOP + ADDA.xyz ACC, VF14, VF15 NOP + MSUBw.xyz VF25, VF12, VF00 NOP ; VF25 = VF12 - (VF14+VF15) + MUL.xyz VF22, VF20, VF20 NOP + MUL.xyz VF23, VF20, VF15 NOP + MULAx.w ACC, VF00, VF21 NOP + MADDAy.w ACC, VF00, VF21 NOP + MADDz.w VF21, VF00, VF21 NOP ; MagSq VF15 (line length) + MULAx.w ACC, VF00, VF23 NOP + MADDAy.w ACC, VF00, VF23 NOP + MADDz.w VF23, VF00, VF23 NOP ; dot(VF12-VF14, VF15) + MULAx.w ACC, VF00, VF22 NOP + MADDAy.w ACC, VF00, VF22 NOP + MADDz.w VF22, VF00, VF22 IADDIU VI08, VI00, 0x10 ; MagSq VF12-VF14 -- Sw bit + MUL.xyz VF25, VF25, VF25 FMAND VI08, VI08 + NOP DIV Q, VF23w, VF21w + NOP IBNE VI00, VI08, NegativeRatio + NOP NOP + ADDA.xyz ACC, VF00, VF14 NOP + MADDq.xyz VF16, VF15, Q WAITQ ; nearest point on infinte line + ADDq.x VF24, VF00, Q NOP ; ratio + NOP NOP + NOP NOP + SUB.xyz VF26, VF16, VF12 NOP + CLIPw.xyz VF24, VF00 NOP ; compare ratio to 1.0 + NOP NOP + NOP NOP + MUL.xyz VF26, VF26, VF26 NOP + NOP FCAND VI01, 0x1 + NOP IBNE VI00, VI01, RatioGreaterThanOne + NOP NOP + MULAx.w ACC, VF00, VF26 NOP + MADDAy.w ACC, VF00, VF26 NOP + MADDz.w VF16, VF00, VF26 NOP ; distance + NOP JR VI15 + NOP NOP +NegativeRatio: + ADD.xyz VF16, VF00, VF14 NOP ; return line origin + MUL.w VF16, VF00, VF22 NOP ; and DistSq to it + NOP JR VI15 + NOP NOP +RatioGreaterThanOne: + MULAx.w ACC, VF00, VF25 NOP + MADDAy.w ACC, VF00, VF25 NOP + MADDz.w VF16, VF00, VF25 NOP + ADD.xyz VF16, VF14, VF15 NOP ; return toerh line point + NOP JR VI15 + NOP NOP + + +; BE0 +.globl Vu0SphereToTriangleCollisionCompressedStart +Vu0SphereToTriangleCollisionCompressedStart: + ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0 + ITOF0.xyzw VF14, VF14 NOP + ITOF0.xyzw VF15, VF15 NOP + ITOF0.xyzw VF16, VF16 NOP + MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0 + MULi.w VF17, VF17, I NOP + MULi.xyzw VF14, VF14, I NOP + MULi.xyzw VF15, VF15, I NOP + MULi.xyzw VF16, VF16, I NOP +; fall through + +; C28 +; VF12: sphere +; VF14-16: verts +; VF17: plane +; out: +; VF01: intersection point +; VF02: triangle normal +; VF03 x: intersection parameter +.globl Vu0SphereToTriangleCollisionStart +Vu0SphereToTriangleCollisionStart: + MUL.xyz VF02, VF12, VF17 LOI 0.1 + ADD.xyz VF17, VF17, VF00 NOP + ADDw.x VF13, VF00, VF12 NOP + NOP NOP + MULAx.w ACC, VF00, VF02 IADDIU VI06, VI00, 0xE0 + MADDAy.w ACC, VF00, VF02 FMAND VI05, VI06 ; normal sign flags + MADDAz.w ACC, VF00, VF02 NOP + MSUB.w VF02, VF00, VF17 NOP ; center plane pos + MULi.w VF03, VF00, I MOVE.xyzw VF04, VF03 + NOP NOP + NOP NOP + CLIPw.xyz VF13, VF02 NOP ; compare dist and radius + CLIPw.xyz VF17, VF03 NOP + MULAw.xyz ACC, VF12, VF00 IADDIU VI07, VI00, 0x0 ; -- clear test case + MSUBw.xyz VF01, VF17, VF02 NOP + MULx.w VF01, VF00, VF00 FCAND VI01, 0x3 ; projected center on plane + ABS.w VF02, VF02 IBEQ VI00, VI01, QuitAndFail ; no intersection + NOP NOP + NOP FCAND VI01, 0x3 ; -- check x direction + SUB.xyz VF02, VF12, VF01 IADDIU VI02, VI01, 0x7F + NOP IADDIU VI06, VI00, 0x80 + SUB.xyz VF05, VF15, VF14 IAND VI02, VI02, VI06 + SUB.xyz VF08, VF01, VF14 FCAND VI01, 0xC ; -- check y direction + SUB.xyz VF06, VF16, VF15 IADDIU VI03, VI01, 0x3F + SUB.xyz VF09, VF01, VF15 IADDIU VI06, VI00, 0x40 + SUB.xyz VF07, VF14, VF16 IAND VI03, VI03, VI06 + SUB.xyz VF10, VF01, VF16 FCAND VI01, 0x30 ; -- check z direction + MUL.xyz VF03, VF02, VF02 IADDIU VI04, VI01, 0x1F + OPMULA.xyz ACC, VF08, VF05 IADDIU VI06, VI00, 0x20 + OPMSUB.xyz VF18, VF05, VF08 IAND VI04, VI04, VI06 + OPMULA.xyz ACC, VF09, VF06 NOP + OPMSUB.xyz VF19, VF06, VF09 IADD VI06, VI02, VI03 + OPMULA.xyz ACC, VF10, VF07 IADD VI06, VI06, VI04 ; -- combine flags + OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; -- cross 1 flags + MULAx.w ACC, VF00, VF03 IAND VI05, VI05, VI06 + MADDAy.w ACC, VF00, VF03 FMAND VI03, VI06 ; -- cross 2 flags + MADDz.w VF03, VF00, VF03 IADDIU VI08, VI00, 0x3 + NOP FMAND VI04, VI06 ; -- cross 3 flags + NOP NOP + NOP IBNE VI02, VI05, CheckSide2 + NOP RSQRT Q, VF00w, VF03w + ADD.xyz VF04, VF00, VF16 IADDIU VI07, VI07, 0x1 ; inside side 1 +CheckSide2: + NOP IBNE VI03, VI05, CheckSide3 + NOP NOP + ADD.xyz VF04, VF00, VF14 IADDIU VI07, VI07, 0x1 ; inside side 2 +CheckSide3: + NOP IBNE VI04, VI05, FinishCheckingSides + NOP NOP + ADD.xyz VF04, VF00, VF15 IADDIU VI07, VI07, 0x1 ; inside side 3 + NOP NOP + NOP IBEQ VI07, VI08, TotallyInsideTriangle + NOP NOP +FinishCheckingSides: + MUL.x VF13, VF13, VF13 IADDIU VI08, VI00, 0x2 + MULq.xyz VF02, VF02, Q WAITQ + NOP IBNE VI07, VI08, IntersectionOutsideTwoSides + NOP NOP + NOP IBEQ VI02, VI05, CheckDistanceSide2 + NOP NOP + NOP MOVE.xyzw VF15, VF05 + NOP BAL VI15, DistanceBetweenSphereAndLine + NOP NOP + NOP B ProcessLineResult + NOP NOP +CheckDistanceSide2: + NOP IBEQ VI03, VI05, CheckDistanceSide3 + NOP NOP + NOP MOVE.xyzw VF14, VF15 + NOP MOVE.xyzw VF15, VF06 + NOP BAL VI15, DistanceBetweenSphereAndLine + NOP NOP + NOP B ProcessLineResult + NOP NOP +CheckDistanceSide3: + NOP MOVE.xyzw VF14, VF16 + NOP MOVE.xyzw VF15, VF07 + NOP BAL VI15, DistanceBetweenSphereAndLine + NOP NOP + NOP B ProcessLineResult + NOP NOP +IntersectionOutsideTwoSides: + SUB.xyz VF05, VF04, VF12 NOP + ADD.xyz VF01, VF00, VF04 NOP ; col point + SUB.xyz VF02, VF12, VF04 NOP + NOP NOP + MUL.xyz VF05, VF05, VF05 NOP + NOP NOP + NOP NOP + NOP NOP + MULAx.w ACC, VF00, VF05 NOP + MADDAy.w ACC, VF00, VF05 NOP + MADDz.w VF05, VF00, VF05 NOP ; distSq to vertex + NOP NOP + NOP NOP + NOP NOP + CLIPw.xyz VF13, VF05 SQRT Q, VF05w ; compare radiusSq and distSq + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x1 + ADDq.x VF03, VF00, Q WAITQ ; dist to vertex + NOP IBEQ VI00, VI01, QuitAndFail ; too far + NOP NOP + NOP NOP + NOP DIV Q, VF00w, VF03x + MULq.xyz VF02, VF02, Q WAITQ ; col normal + NOP[E] NOP + NOP NOP +TotallyInsideTriangle: + ADDw.x VF03, VF00, VF02 WAITQ + MULq.xyz VF02, VF02, Q NOP + NOP[E] IADDIU VI01, VI00, 0x1 + NOP NOP +ProcessLineResult: + CLIPw.xyz VF13, VF16 SQRT Q, VF16w + ADD.xyz VF01, VF00, VF16 NOP + SUB.xyz VF02, VF12, VF16 NOP + NOP NOP + NOP FCAND VI01, 0x1 + ADDq.x VF03, VF00, Q WAITQ + NOP IBEQ VI00, VI01, QuitAndFail + NOP NOP + NOP NOP + NOP DIV Q, VF00w, VF03x + MULq.xyz VF02, VF02, Q WAITQ + NOP[E] NOP + NOP NOP + +EndOfMicrocode: diff --git a/src/collision/vu0Collision_2.s b/src/collision/vu0Collision_2.s new file mode 100644 index 00000000..716c29ac --- /dev/null +++ b/src/collision/vu0Collision_2.s @@ -0,0 +1,191 @@ +QuitAndFail2: + NOP[E] IADDIU VI01, VI00, 0x0 + NOP NOP + + +QuitAndSucceed2: + NOP[E] IADDIU VI01, VI00, 0x1 + NOP NOP + + +; 20 +GetBBVertices: + MULw.xy VF02, VF01, VF00 NOP + MUL.z VF02, VF01, VF11 NOP + MULw.xz VF03, VF01, VF00 NOP + MUL.y VF03, VF01, VF11 NOP + MULw.x VF04, VF01, VF00 NOP + MUL.yz VF04, VF01, VF11 NOP + NOP JR VI15 + NOP NOP + + +; 60 +Vu0OBBToOBBCollision: + SUBw.xyz VF11, VF00, VF00 LOI 0.5 + MULi.xyz VF12, VF12, I NOP + MULi.xyz VF13, VF13, I NOP + NOP NOP + NOP NOP + NOP MOVE.xyz VF01, VF12 + NOP BAL VI15, GetBBVertices + NOP NOP + MULAx.xyz ACC, VF14, VF01 NOP + MADDAy.xyz ACC, VF15, VF01 NOP + MADDz.xyz VF01, VF16, VF01 NOP + MULAx.xyz ACC, VF14, VF02 NOP + MADDAy.xyz ACC, VF15, VF02 NOP + MADDz.xyz VF02, VF16, VF02 NOP + MULAx.xyz ACC, VF14, VF03 NOP + MADDAy.xyz ACC, VF15, VF03 NOP + MADDz.xyz VF03, VF16, VF03 NOP + MULAx.xyz ACC, VF14, VF04 NOP + MADDAy.xyz ACC, VF15, VF04 NOP + MADDz.xyz VF04, VF16, VF04 NOP + ABS.xyz VF05, VF01 NOP + ABS.xyz VF06, VF02 NOP + ABS.xyz VF07, VF03 NOP + ABS.xyz VF08, VF04 NOP + NOP NOP + MAX.xyz VF05, VF05, VF06 NOP + NOP NOP + MAX.xyz VF07, VF07, VF08 NOP + NOP NOP + NOP NOP + NOP NOP + MAX.xyz VF05, VF05, VF07 NOP + NOP NOP + NOP NOP + NOP NOP + ADD.xyz VF09, VF05, VF13 NOP + NOP NOP + NOP NOP + NOP NOP + MULx.w VF05, VF00, VF09 NOP + MULy.w VF06, VF00, VF09 NOP + MULz.w VF07, VF00, VF09 NOP + CLIPw.xyz VF17, VF05 NOP + CLIPw.xyz VF17, VF06 NOP + CLIPw.xyz VF17, VF07 MOVE.xyz VF01, VF13 + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x3330 + NOP IBNE VI01, VI00, QuitAndFail2 + NOP NOP + NOP BAL VI15, GetBBVertices + NOP NOP + MULAx.xyz ACC, VF18, VF01 NOP + MADDAy.xyz ACC, VF19, VF01 NOP + MADDz.xyz VF01, VF20, VF01 NOP + MULAx.xyz ACC, VF18, VF02 NOP + MADDAy.xyz ACC, VF19, VF02 NOP + MADDz.xyz VF02, VF20, VF02 NOP + MULAx.xyz ACC, VF18, VF03 NOP + MADDAy.xyz ACC, VF19, VF03 NOP + MADDz.xyz VF03, VF20, VF03 NOP + MULAx.xyz ACC, VF18, VF04 NOP + MADDAy.xyz ACC, VF19, VF04 NOP + MADDz.xyz VF04, VF20, VF04 NOP + ABS.xyz VF05, VF01 NOP + ABS.xyz VF06, VF02 NOP + ABS.xyz VF07, VF03 NOP + ABS.xyz VF08, VF04 NOP + NOP NOP + MAX.xyz VF05, VF05, VF06 NOP + NOP NOP + MAX.xyz VF07, VF07, VF08 NOP + NOP NOP + NOP NOP + NOP NOP + MAX.xyz VF05, VF05, VF07 NOP + NOP NOP + NOP NOP + NOP NOP + ADD.xyz VF09, VF05, VF12 NOP + NOP NOP + NOP NOP + NOP NOP + MULx.w VF05, VF00, VF09 NOP + MULy.w VF06, VF00, VF09 NOP + MULz.w VF07, VF00, VF09 NOP + CLIPw.xyz VF21, VF05 NOP + CLIPw.xyz VF21, VF06 NOP + CLIPw.xyz VF21, VF07 NOP + NOP NOP + NOP NOP + NOP NOP + NOP FCAND VI01, 0x3330 + NOP IBNE VI01, VI00, QuitAndFail2 + NOP NOP + SUB.xyz VF06, VF02, VF01 NOP + SUB.xyz VF07, VF03, VF01 NOP + ADD.xyz VF08, VF04, VF01 NOP + ADD.x VF09, VF00, VF12 NOP + ADD.yz VF09, VF00, VF00 NOP + ADD.y VF10, VF00, VF12 NOP + ADD.xz VF10, VF00, VF00 NOP + ADD.z VF11, VF00, VF12 IADDI VI04, VI00, 0x0 + ADD.xy VF11, VF00, VF00 IADD VI02, VI00, VI00 + OPMULA.xyz ACC, VF06, VF09 NOP + OPMSUB.xyz VF01, VF09, VF06 NOP + OPMULA.xyz ACC, VF06, VF10 NOP + OPMSUB.xyz VF02, VF10, VF06 NOP + OPMULA.xyz ACC, VF06, VF11 NOP + OPMSUB.xyz VF03, VF11, VF06 SQI.xyzw VF01, (VI02++) + OPMULA.xyz ACC, VF07, VF09 NOP + OPMSUB.xyz VF01, VF09, VF07 SQI.xyzw VF02, (VI02++) + OPMULA.xyz ACC, VF07, VF10 NOP + OPMSUB.xyz VF02, VF10, VF07 SQI.xyzw VF03, (VI02++) + OPMULA.xyz ACC, VF07, VF11 NOP + OPMSUB.xyz VF03, VF11, VF07 SQI.xyzw VF01, (VI02++) + OPMULA.xyz ACC, VF08, VF09 NOP + OPMSUB.xyz VF01, VF09, VF08 SQI.xyzw VF02, (VI02++) + OPMULA.xyz ACC, VF08, VF10 NOP + OPMSUB.xyz VF02, VF10, VF08 SQI.xyzw VF03, (VI02++) + OPMULA.xyz ACC, VF08, VF11 LOI 0.5 + OPMSUB.xyz VF01, VF11, VF08 SQI.xyzw VF01, (VI02++) + MULi.xyz VF06, VF06, I NOP + MULi.xyz VF07, VF07, I SQI.xyzw VF02, (VI02++) + MULi.xyz VF08, VF08, I NOP + MUL.xyz VF02, VF21, VF01 NOP + MUL.xyz VF03, VF12, VF01 NOP + MUL.xyz VF09, VF06, VF01 NOP + MUL.xyz VF10, VF07, VF01 NOP + MUL.xyz VF11, VF08, VF01 NOP + ABS.xyz VF03, VF03 NOP + ADDy.x VF05, VF09, VF09 NOP + ADDx.y VF05, VF10, VF10 NOP + ADDx.z VF05, VF11, VF11 NOP + NOP NOP +EdgePairLoop: + ADDz.x VF05, VF05, VF09 NOP + ADDz.y VF05, VF05, VF10 NOP + ADDy.z VF05, VF05, VF11 NOP + MULAx.w ACC, VF00, VF02 IADD VI03, VI02, VI00 + MADDAy.w ACC, VF00, VF02 LQD.xyzw VF01, (--VI02) + MADDz.w VF02, VF00, VF02 NOP + ABS.xyz VF05, VF05 NOP + MULAx.w ACC, VF00, VF03 NOP + MADDAy.w ACC, VF00, VF03 NOP + MADDAz.w ACC, VF00, VF03 NOP + MADDAx.w ACC, VF00, VF05 NOP + MADDAy.w ACC, VF00, VF05 NOP + MADDz.w VF03, VF00, VF05 NOP + ADDw.x VF04, VF00, VF02 NOP + MUL.xyz VF02, VF21, VF01 NOP + MUL.xyz VF03, VF12, VF01 NOP + MUL.xyz VF09, VF06, VF01 NOP + CLIPw.xyz VF04, VF03 NOP + MUL.xyz VF10, VF07, VF01 NOP + MUL.xyz VF11, VF08, VF01 NOP + ABS.xyz VF03, VF03 NOP + ADDy.x VF05, VF09, VF09 FCAND VI01, 0x3 + ADDx.y VF05, VF10, VF10 IBNE VI01, VI00, QuitAndFail2 + ADDx.z VF05, VF11, VF11 NOP + NOP IBNE VI03, VI00, EdgePairLoop + NOP NOP + NOP[E] IADDIU VI01, VI00, 0x1 + NOP NOP + +EndOfMicrocode2: diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp deleted file mode 100644 index d8603cd8..00000000 --- a/src/core/Collision.cpp +++ /dev/null @@ -1,3290 +0,0 @@ -#include "common.h" - -#include "VuVector.h" -#include "main.h" -#include "Lists.h" -#include "Game.h" -#include "Zones.h" -#include "General.h" -#include "ZoneCull.h" -#include "World.h" -#include "Entity.h" -#include "Train.h" -#include "Streaming.h" -#include "Pad.h" -#include "DMAudio.h" -#include "Population.h" -#include "FileLoader.h" -#include "Replay.h" -#include "CutsceneMgr.h" -#include "RenderBuffer.h" -#include "SurfaceTable.h" -#include "Lines.h" -#include "Collision.h" -#include "Frontend.h" - - -// TODO: where do these go? - -#ifdef VU_COLLISION - -struct VuTriangle -{ - // Compressed int16 but unpacked -#ifdef GTA_PS2 - uint128 v0; - uint128 v1; - uint128 v2; - uint128 plane; -#else - int32 v0[4]; - int32 v1[4]; - int32 v2[4]; - int32 plane[4]; -#endif -}; - -#ifndef GTA_PS2 -static int16 vi01; -static CVuVector vf01; -static CVuVector vf02; -static CVuVector vf03; - -CVuVector -DistanceBetweenSphereAndLine(const CVuVector ¢er, const CVuVector &p0, const CVuVector &line) -{ - // center VF12 - // p0 VF14 - // line VF15 - CVuVector ret; // VF16 - CVuVector p1 = p0+line; - CVuVector dist0 = center - p0; // VF20 - CVuVector dist1 = center - p1; // VF25 - float lenSq = line.MagnitudeSqr(); // VF21 - float distSq0 = dist0.MagnitudeSqr(); // VF22 - float distSq1 = dist1.MagnitudeSqr(); - float dot = DotProduct(dist0, line); // VF23 - if(dot < 0.0f){ - // not above line, closest to p0 - ret = p0; - ret.w = distSq0; - return ret; - } - float t = dot/lenSq; // param of nearest point on infinite line - if(t > 1.0f){ - // not above line, closest to p1 - ret = p1; - ret.w = distSq1; - return ret; - } - // closest to line - ret = p0 + line*t; - ret.w = (ret - center).MagnitudeSqr(); - return ret; -} -inline int SignFlags(const CVector &v) -{ - int f = 0; - if(v.x < 0.0f) f |= 1; - if(v.y < 0.0f) f |= 2; - if(v.z < 0.0f) f |= 4; - return f; -} -#endif - -extern "C" void -LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1, - const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, - const CVuVector &plane) -{ -#ifdef GTA_PS2 - __asm__ volatile ( - ".set noreorder\n" - "lqc2 vf12, 0x0(%0)\n" - "lqc2 vf13, 0x0(%1)\n" - "lqc2 vf14, 0x0(%2)\n" - "lqc2 vf15, 0x0(%3)\n" - "lqc2 vf16, 0x0(%4)\n" - "lqc2 vf17, 0x0(%5)\n" - "vcallms Vu0LineToTriangleCollisionStart\n" - ".set reorder\n" - : - : "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane) - ); -#else - float dot0 = DotProduct(plane, p0); - float dot1 = DotProduct(plane, p1); - float dist0 = plane.w - dot0; - float dist1 = plane.w - dot1; - - // if points are on the same side, no collision - if(dist0 * dist1 > 0.0f){ - vi01 = 0; - return; - } - - CVuVector diff = p1 - p0; - float t = dist0/(dot1 - dot0); - CVuVector p = p0 + diff*t; - p.w = 0.0f; - vf01 = p; - vf03.x = t; - - // Check if point is inside - CVector cross1 = CrossProduct(p-v0, v1-v0); - CVector cross2 = CrossProduct(p-v1, v2-v1); - CVector cross3 = CrossProduct(p-v2, v0-v2); - // Only check relevant directions - int flagmask = 0; - if(Abs(plane.x) > 0.5f) flagmask |= 1; - if(Abs(plane.y) > 0.5f) flagmask |= 2; - if(Abs(plane.z) > 0.5f) flagmask |= 4; - int flags1 = SignFlags(cross1) & flagmask; - int flags2 = SignFlags(cross2) & flagmask; - int flags3 = SignFlags(cross3) & flagmask; - // inside if on the same side of all edges - if(flags1 != flags2 || flags1 != flags3){ - vi01 = 0; - return; - } - vi01 = 1; - vf02 = plane; - return; -#endif -} - -extern "C" void -LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri) -{ -#ifdef GTA_PS2 - __asm__ volatile ( - ".set noreorder\n" - "lqc2 vf12, 0x0(%0)\n" - "lqc2 vf13, 0x0(%1)\n" - "lqc2 vf14, 0x0(%2)\n" - "lqc2 vf15, 0x10(%2)\n" - "lqc2 vf16, 0x20(%2)\n" - "lqc2 vf17, 0x30(%2)\n" - "vcallms Vu0LineToTriangleCollisionCompressedStart\n" - ".set reorder\n" - : - : "r" (&p0), "r" (&p1), "r" (&tri) - ); -#else - CVuVector v0, v1, v2, plane; - v0.x = tri.v0[0]/128.0f; - v0.y = tri.v0[1]/128.0f; - v0.z = tri.v0[2]/128.0f; - v0.w = tri.v0[3]/128.0f; - v1.x = tri.v1[0]/128.0f; - v1.y = tri.v1[1]/128.0f; - v1.z = tri.v1[2]/128.0f; - v1.w = tri.v1[3]/128.0f; - v2.x = tri.v2[0]/128.0f; - v2.y = tri.v2[1]/128.0f; - v2.z = tri.v2[2]/128.0f; - v2.w = tri.v2[3]/128.0f; - plane.x = tri.plane[0]/4096.0f; - plane.y = tri.plane[1]/4096.0f; - plane.z = tri.plane[2]/4096.0f; - plane.w = tri.plane[3]/128.0f; - LineToTriangleCollision(p0, p1, v0, v1, v2, plane); -#endif -} - -extern "C" void -SphereToTriangleCollision(const CVuVector &sph, - const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, - const CVuVector &plane) -{ -#ifdef GTA_PS2 - __asm__ volatile ( - ".set noreorder\n" - "lqc2 vf12, 0x0(%0)\n" - "lqc2 vf14, 0x0(%1)\n" - "lqc2 vf15, 0x0(%2)\n" - "lqc2 vf16, 0x0(%3)\n" - "lqc2 vf17, 0x0(%4)\n" - "vcallms Vu0SphereToTriangleCollisionStart\n" - ".set reorder\n" - : - : "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane) - ); -#else - float planedist = DotProduct(plane, sph) - plane.w; // VF02 - if(Abs(planedist) > sph.w){ - vi01 = 0; - return; - } - // point on plane - CVuVector p = sph - planedist*plane; - p.w = 0.0f; - vf01 = p; - planedist = Abs(planedist); - // edges - CVuVector v01 = v1 - v0; - CVuVector v12 = v2 - v1; - CVuVector v20 = v0 - v2; - // VU code calculates normal again for some weird reason... - // Check sides of point - CVector cross1 = CrossProduct(p-v0, v01); - CVector cross2 = CrossProduct(p-v1, v12); - CVector cross3 = CrossProduct(p-v2, v20); - // Only check relevant directions - int flagmask = 0; - if(Abs(plane.x) > 0.1f) flagmask |= 1; - if(Abs(plane.y) > 0.1f) flagmask |= 2; - if(Abs(plane.z) > 0.1f) flagmask |= 4; - int nflags = SignFlags(plane) & flagmask; - int flags1 = SignFlags(cross1) & flagmask; - int flags2 = SignFlags(cross2) & flagmask; - int flags3 = SignFlags(cross3) & flagmask; - int testcase = 0; - CVuVector closest(0.0f, 0.0f, 0.0f); // VF04 - if(flags1 == nflags){ - closest += v2; - testcase++; - } - if(flags2 == nflags){ - closest += v0; - testcase++; - } - if(flags3 == nflags){ - closest += v1; - testcase++; - } - if(testcase == 3){ - // inside triangle - dist to plane already checked - vf02 = plane; - vf02.w = vf03.x = planedist; - vi01 = 1; - }else if(testcase == 1){ - // outside two sides - closest to point opposide inside edge - vf01 = closest; - vf02 = sph - closest; - float distSq = vf02.MagnitudeSqr(); - vi01 = sph.w*sph.w > distSq; - vf03.x = Sqrt(distSq); - vf02 *= 1.0f/vf03.x; - }else{ - // inside two sides - closest to third edge - if(flags1 != nflags) - closest = DistanceBetweenSphereAndLine(sph, v0, v01); - else if(flags2 != nflags) - closest = DistanceBetweenSphereAndLine(sph, v1, v12); - else - closest = DistanceBetweenSphereAndLine(sph, v2, v20); - vi01 = sph.w*sph.w > closest.w; - vf01 = closest; - vf02 = sph - closest; - vf03.x = Sqrt(closest.w); - vf02 *= 1.0f/vf03.x; - } -#endif -} - -extern "C" void -SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri) -{ -#ifdef GTA_PS2 - __asm__ volatile ( - ".set noreorder\n" - "lqc2 vf12, 0x0(%0)\n" - "lqc2 vf14, 0x0(%1)\n" - "lqc2 vf15, 0x10(%1)\n" - "lqc2 vf16, 0x20(%1)\n" - "lqc2 vf17, 0x30(%1)\n" - "vcallms Vu0SphereToTriangleCollisionCompressedStart\n" - ".set reorder\n" - : - : "r" (&sph), "r" (&tri) - ); -#else - CVuVector v0, v1, v2, plane; - v0.x = tri.v0[0]/128.0f; - v0.y = tri.v0[1]/128.0f; - v0.z = tri.v0[2]/128.0f; - v0.w = tri.v0[3]/128.0f; - v1.x = tri.v1[0]/128.0f; - v1.y = tri.v1[1]/128.0f; - v1.z = tri.v1[2]/128.0f; - v1.w = tri.v1[3]/128.0f; - v2.x = tri.v2[0]/128.0f; - v2.y = tri.v2[1]/128.0f; - v2.z = tri.v2[2]/128.0f; - v2.w = tri.v2[3]/128.0f; - plane.x = tri.plane[0]/4096.0f; - plane.y = tri.plane[1]/4096.0f; - plane.z = tri.plane[2]/4096.0f; - plane.w = tri.plane[3]/128.0f; - SphereToTriangleCollision(sph, v0, v1, v2, plane); -#endif -} - -inline int -GetVUresult(void) -{ -#ifdef GTA_PS2 - int ret; - __asm__ volatile ( - "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish - : "=r" (ret) - ); - return ret; -#else - return vi01; -#endif -} - -inline int -GetVUresult(CVuVector &point, CVuVector &normal, float &dist) -{ -#ifdef GTA_PS2 - int ret; - __asm__ volatile ( - "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish - "sqc2 vf01,(%1)\n" - "sqc2 vf02,(%2)\n" - "qmfc2 $12,vf03\n" - "sw $12,(%3)\n" - : "=r" (ret) - : "r" (&point), "r" (&normal), "r" (&dist) - : "$12" - ); - return ret; -#else - point = vf01; - normal = vf02; - dist = vf03.x; - return vi01; -#endif -} - -#endif - - -enum Direction -{ - DIR_X_POS, - DIR_X_NEG, - DIR_Y_POS, - DIR_Y_NEG, - DIR_Z_POS, - DIR_Z_NEG, -}; - -eLevelName CCollision::ms_collisionInMemory; -CLinkList CCollision::ms_colModelCache; - -void -CCollision::Init(void) -{ - ms_colModelCache.Init(NUMCOLCACHELINKS); - ms_collisionInMemory = LEVEL_GENERIC; -} - -void -CCollision::Shutdown(void) -{ - ms_colModelCache.Shutdown(); -} - -void -CCollision::Update(void) -{ - CVector playerCoors; - playerCoors = FindPlayerCoors(); - eLevelName level = CTheZones::m_CurrLevel; - bool forceLevelChange = false; - - if(CTimer::GetTimeInMilliseconds() < 2000 || CCutsceneMgr::IsCutsceneProcessing()) - return; - - // hardcode a level if there are no zones - if(level == LEVEL_GENERIC){ - if(CGame::currLevel == LEVEL_INDUSTRIAL && - playerCoors.x < 400.0f){ - level = LEVEL_COMMERCIAL; - forceLevelChange = true; - }else if(CGame::currLevel == LEVEL_SUBURBAN && - playerCoors.x > -450.0f && playerCoors.y < -1400.0f){ - level = LEVEL_COMMERCIAL; - forceLevelChange = true; - }else{ - if(playerCoors.x > 800.0f){ - level = LEVEL_INDUSTRIAL; - forceLevelChange = true; - }else if(playerCoors.x < -800.0f){ - level = LEVEL_SUBURBAN; - forceLevelChange = true; - } - } - } - if(level != LEVEL_GENERIC && level != CGame::currLevel) - CGame::currLevel = level; - if(ms_collisionInMemory != CGame::currLevel) - LoadCollisionWhenINeedIt(forceLevelChange); - CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); -} - -eLevelName -GetCollisionInSectorList(CPtrList &list) -{ - CPtrNode *node; - CEntity *e; - int level; - - for(node = list.first; node; node = node->next){ - e = (CEntity*)node->item; - level = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel()->level; - if(level != LEVEL_GENERIC) - return (eLevelName)level; - } - return LEVEL_GENERIC; -} - -// Get a level this sector is in based on collision models -eLevelName -GetCollisionInSector(CSector §) -{ - int level; - - level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS]); - if(level == LEVEL_GENERIC) - level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS_OVERLAP]); - if(level == LEVEL_GENERIC) - level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS]); - if(level == LEVEL_GENERIC) - level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS_OVERLAP]); - if(level == LEVEL_GENERIC) - level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES]); - if(level == LEVEL_GENERIC) - level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES_OVERLAP]); - return (eLevelName)level; -} - -void -CCollision::LoadCollisionWhenINeedIt(bool forceChange) -{ - eLevelName level, l; - bool multipleLevels; - CVector playerCoors; - CVehicle *veh; - CEntryInfoNode *ei; - int sx, sy; - int xmin, xmax, ymin, ymax; - int x, y; - - level = LEVEL_GENERIC; - - playerCoors = FindPlayerCoors(); - sx = CWorld::GetSectorIndexX(playerCoors.x); - sy = CWorld::GetSectorIndexY(playerCoors.y); - multipleLevels = false; - - veh = FindPlayerVehicle(); - if(veh && veh->IsTrain()){ - if(((CTrain*)veh)->m_nDoorState != TRAIN_DOOR_OPEN) - return; - }else if(playerCoors.z < -4.0f && !CCullZones::DoINeedToLoadCollision()) - return; - - // Figure out whose level's collisions we're most likely to be interested in - if(!forceChange){ - if(veh && veh->IsBoat()){ - // on water we expect to be between levels - multipleLevels = true; - }else{ - xmin = Max(sx - 1, 0); - xmax = Min(sx + 1, NUMSECTORS_X-1); - ymin = Max(sy - 1, 0); - ymax = Min(sy + 1, NUMSECTORS_Y-1); - - for(x = xmin; x <= xmax; x++) - for(y = ymin; y <= ymax; y++){ - l = GetCollisionInSector(*CWorld::GetSector(x, y)); - if(l != LEVEL_GENERIC){ - if(level == LEVEL_GENERIC) - level = l; - if(level != l) - multipleLevels = true; - } - } - } - - if(multipleLevels && veh && veh->IsBoat()) - for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){ - level = GetCollisionInSector(*ei->sector); - if(level != LEVEL_GENERIC) - break; - } - } - - if (level == CGame::currLevel || forceChange) { -#ifdef FIX_BUGS - CTimer::Suspend(); -#else - CTimer::Stop(); -#endif - ISLAND_LOADING_IS(LOW) - { - DMAudio.SetEffectsFadeVol(0); - CPad::StopPadsShaking(); - LoadCollisionScreen(CGame::currLevel); - DMAudio.Service(); - } - - CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false); - - ISLAND_LOADING_ISNT(HIGH) - { - CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); - CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); - CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); - } - ISLAND_LOADING_IS(LOW) - { - CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL); - CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL); - CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN); - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - CStreaming::RemoveUnusedModelsInLoadedList(); - CGame::TidyUpMemory(true, true); - CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); - } - - ms_collisionInMemory = CGame::currLevel; - CReplay::EmptyReplayBuffer(); - ISLAND_LOADING_IS(LOW) - { - if (CGame::currLevel != LEVEL_GENERIC) - LoadSplash(GetLevelSplashScreen(CGame::currLevel)); - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - CStreaming::RequestBigBuildings(CGame::currLevel); - } -#ifdef NO_ISLAND_LOADING - else if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM) - CStreaming::RequestIslands(CGame::currLevel); -#endif - CStreaming::LoadAllRequestedModels(true); - - ISLAND_LOADING_IS(LOW) - { - CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); - - CGame::TidyUpMemory(true, true); - } -#ifdef FIX_BUGS - CTimer::Resume(); -#else - CTimer::Update(); -#endif - ISLAND_LOADING_IS(LOW) - DMAudio.SetEffectsFadeVol(127); - } -} - -#ifdef NO_ISLAND_LOADING -bool CCollision::bAlreadyLoaded = false; -#endif -void -CCollision::SortOutCollisionAfterLoad(void) -{ - if(ms_collisionInMemory == CGame::currLevel) - return; - ISLAND_LOADING_IS(LOW) - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - - if (CGame::currLevel != LEVEL_GENERIC) { -#ifdef NO_ISLAND_LOADING - if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) { - if (bAlreadyLoaded) { - ms_collisionInMemory = CGame::currLevel; - return; - } - bAlreadyLoaded = true; - CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); - CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); - CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); - } else -#endif - CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); - if(!CGame::playingIntro) - LoadSplash(GetLevelSplashScreen(CGame::currLevel)); - } - ms_collisionInMemory = CGame::currLevel; - CGame::TidyUpMemory(true, false); -} - -void -CCollision::LoadCollisionScreen(eLevelName level) -{ - static Const char *levelNames[4] = { - "", - "IND_ZON", - "COM_ZON", - "SUB_ZON" - }; - - // Why twice? - LoadingIslandScreen(levelNames[level]); - LoadingIslandScreen(levelNames[level]); -} - -// -// Test -// - - -bool -CCollision::TestSphereSphere(const CColSphere &s1, const CColSphere &s2) -{ - float d = s1.radius + s2.radius; - return (s1.center - s2.center).MagnitudeSqr() < d*d; -} - -bool -CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box) -{ - if(sph.center.x + sph.radius < box.min.x) return false; - if(sph.center.x - sph.radius > box.max.x) return false; - if(sph.center.y + sph.radius < box.min.y) return false; - if(sph.center.y - sph.radius > box.max.y) return false; - if(sph.center.z + sph.radius < box.min.z) return false; - if(sph.center.z - sph.radius > box.max.z) return false; - return true; -} - -bool -CCollision::TestLineBox(const CColLine &line, const CColBox &box) -{ - float t, x, y, z; - // If either line point is in the box, we have a collision - if(line.p0.x > box.min.x && line.p0.x < box.max.x && - line.p0.y > box.min.y && line.p0.y < box.max.y && - line.p0.z > box.min.z && line.p0.z < box.max.z) - return true; - if(line.p1.x > box.min.x && line.p1.x < box.max.x && - line.p1.y > box.min.y && line.p1.y < box.max.y && - line.p1.z > box.min.z && line.p1.z < box.max.z) - return true; - - // check if points are on opposite sides of min x plane - if((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){ - // parameter along line where we intersect - t = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x); - // y of intersection - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y){ - // z of intersection - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - return true; - } - } - - // same test with max x plane - if((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){ - t = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x); - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y){ - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - return true; - } - } - - // min y plne - if((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){ - t = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - return true; - } - } - - // max y plane - if((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){ - t = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - return true; - } - } - - // min z plne - if((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){ - t = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y) - return true; - } - } - - // max z plane - if((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){ - t = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y) - return true; - } - } - return false; -} - -bool -CCollision::TestVerticalLineBox(const CColLine &line, const CColBox &box) -{ - if(line.p0.x <= box.min.x) return false; - if(line.p0.y <= box.min.y) return false; - if(line.p0.x >= box.max.x) return false; - if(line.p0.y >= box.max.y) return false; - if(line.p0.z < line.p1.z){ - if(line.p0.z > box.max.z) return false; - if(line.p1.z < box.min.z) return false; - }else{ - if(line.p1.z > box.max.z) return false; - if(line.p0.z < box.min.z) return false; - } - return true; -} - -bool -CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) -{ -#ifdef VU_COLLISION - // not used in favour of optimized loops - VuTriangle vutri; - verts[tri.a].Unpack(vutri.v0); - verts[tri.b].Unpack(vutri.v1); - verts[tri.c].Unpack(vutri.v2); - plane.Unpack(vutri.plane); - - LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri); - - if(GetVUresult()) - return true; - return false; -#else - float t; - CVector normal; - plane.GetNormal(normal); - - // if points are on the same side, no collision - if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f) - return false; - - // intersection parameter on line - t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal); - // find point of intersection - CVector p = line.p0 + (line.p1-line.p0)*t; - - const CVector &va = verts[tri.a].Get(); - const CVector &vb = verts[tri.b].Get(); - const CVector &vc = verts[tri.c].Get(); - CVector2D vec1, vec2, vec3, vect; - - // We do the test in 2D. With the plane direction we - // can figure out how to project the vectors. - // normal = (c-a) x (b-a) - switch(plane.dir){ - case DIR_X_POS: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vc.y; vec2.y = vc.z; - vec3.x = vb.y; vec3.y = vb.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_X_NEG: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vb.y; vec2.y = vb.z; - vec3.x = vc.y; vec3.y = vc.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_Y_POS: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vc.z; vec2.y = vc.x; - vec3.x = vb.z; vec3.y = vb.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Y_NEG: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vb.z; vec2.y = vb.x; - vec3.x = vc.z; vec3.y = vc.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Z_POS: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vc.x; vec2.y = vc.y; - vec3.x = vb.x; vec3.y = vb.y; - vect.x = p.x; vect.y = p.y; - break; - case DIR_Z_NEG: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vb.x; vec2.y = vb.y; - vec3.x = vc.x; vec3.y = vc.y; - vect.x = p.x; vect.y = p.y; - break; - default: - assert(0); - } - // This is our triangle: - // 3-------2 - // \ P / - // \ / - // \ / - // 1 - // We can use the "2d cross product" to check on which side - // a vector is of another. Test is true if point is inside of all edges. - if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; - if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; - if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; - return true; -#endif -} - -// Test if line segment intersects with sphere. -// If the first point is inside the sphere this test does not register a collision! -// The code is reversed from the original code and rather ugly, see Process for a clear version. -// TODO: actually rewrite this mess -bool -CCollision::TestLineSphere(const CColLine &line, const CColSphere &sph) -{ - CVector v01 = line.p1 - line.p0; // vector from p0 to p1 - CVector v0c = sph.center - line.p0; // vector from p0 to center - float linesq = v01.MagnitudeSqr(); - // I leave in the strange -2 factors even though they serve no real purpose - float projline = -2.0f * DotProduct(v01, v0c); // project v0c onto line - // Square of tangent from p0 multiplied by line length so we can compare with projline. - // The length of the tangent would be this: Sqrt((c-p0)^2 - r^2). - // Negative if p0 is inside the sphere! This breaks the test! - float tansq = 4.0f * linesq * - (sph.center.MagnitudeSqr() - 2.0f*DotProduct(sph.center, line.p0) + line.p0.MagnitudeSqr() - sph.radius*sph.radius); - float diffsq = projline*projline - tansq; - // if diffsq < 0 that means the line is a passant, so no intersection - if(diffsq < 0.0f) - return false; - // projline (negative in GTA for some reason) is the point on the line - // in the middle of the two intersection points (startin from p0). - // Sqrt(diffsq) somehow works out to be the distance from that - // midpoint to the intersection points. - // So subtract that and get rid of the awkward scaling: - float f = (-projline - Sqrt(diffsq)) / (2.0f*linesq); - // f should now be in range [0, 1] for [p0, p1] - return f >= 0.0f && f <= 1.0f; -} - -bool -CCollision::TestSphereTriangle(const CColSphere &sphere, - const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) -{ -#ifdef VU_COLLISION - // not used in favour of optimized loops - VuTriangle vutri; - verts[tri.a].Unpack(vutri.v0); - verts[tri.b].Unpack(vutri.v1); - verts[tri.c].Unpack(vutri.v2); - plane.Unpack(vutri.plane); - - SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri); - - if(GetVUresult()) - return true; - return false; -#else - // If sphere and plane don't intersect, no collision - float planedist = plane.CalcPoint(sphere.center); - if(Abs(planedist) > sphere.radius) - return false; - - const CVector &va = verts[tri.a].Get(); - const CVector &vb = verts[tri.b].Get(); - const CVector &vc = verts[tri.c].Get(); - - // calculate two orthogonal basis vectors for the triangle - CVector vec2 = vb - va; - float len = vec2.Magnitude(); - vec2 = vec2 * (1.0f/len); - CVector normal; - plane.GetNormal(normal); - CVector vec1 = CrossProduct(vec2, normal); - - // We know A has local coordinate [0,0] and B has [0,len]. - // Now calculate coordinates on triangle for these two vectors: - CVector vac = vc - va; - CVector vas = sphere.center - va; - CVector2D b(0.0f, len); - CVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac)); - CVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas)); - - // The three triangle lines partition the space into 6 sectors, - // find out in which the center lies. - int insideAB = CrossProduct2D(s, b) >= 0.0f; - int insideAC = CrossProduct2D(c, s) >= 0.0f; - int insideBC = CrossProduct2D(s-b, c-b) >= 0.0f; - - int testcase = insideAB + insideAC + insideBC; - float dist = 0.0f; - switch(testcase){ - case 1: - // closest to a vertex - if(insideAB) dist = (sphere.center - vc).Magnitude(); - else if(insideAC) dist = (sphere.center - vb).Magnitude(); - else if(insideBC) dist = (sphere.center - va).Magnitude(); - else assert(0); - break; - case 2: - // closest to an edge - // looks like original game as DistToLine manually inlined - if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center); - else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center); - else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center); - else assert(0); - break; - case 3: - // center is in triangle - dist = Abs(planedist); - break; - default: - assert(0); - } - - return dist < sphere.radius; -#endif -} - -bool -CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough) -{ -#ifdef VU_COLLISION - CMatrix matTransform; - int i; - - // transform line to model space - Invert(matrix, matTransform); - CVuVector newline[2]; - TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); - - // If we don't intersect with the bounding box, no chance on the rest - if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) - return false; - - for(i = 0; i < model.numSpheres; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; - if(TestLineSphere(*(CColLine*)newline, model.spheres[i])) - return true; - } - - for(i = 0; i < model.numBoxes; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; - if(TestLineBox(*(CColLine*)newline, model.boxes[i])) - return true; - } - - CalculateTrianglePlanes(&model); - int lastTest = -1; - VuTriangle vutri; - for(i = 0; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - - CColTriangle *tri = &model.triangles[i]; - model.vertices[tri->a].Unpack(vutri.v0); - model.vertices[tri->b].Unpack(vutri.v1); - model.vertices[tri->c].Unpack(vutri.v2); - model.trianglePlanes[i].Unpack(vutri.plane); - - LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); - lastTest = i; - break; - } -#ifdef FIX_BUGS - // no need to check first again - i++; -#endif - for(; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - - CColTriangle *tri = &model.triangles[i]; - model.vertices[tri->a].Unpack(vutri.v0); - model.vertices[tri->b].Unpack(vutri.v1); - model.vertices[tri->c].Unpack(vutri.v2); - model.trianglePlanes[i].Unpack(vutri.plane); - - if(GetVUresult()) - return true; - - LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); - lastTest = i; - - } - if(lastTest != -1 && GetVUresult()) - return true; - - return false; -#else - static CMatrix matTransform; - int i; - - // transform line to model space - Invert(matrix, matTransform); - CColLine newline(matTransform * line.p0, matTransform * line.p1); - - // If we don't intersect with the bounding box, no chance on the rest - if(!TestLineBox(newline, model.boundingBox)) - return false; - - for(i = 0; i < model.numSpheres; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; - if(TestLineSphere(newline, model.spheres[i])) - return true; - } - - for(i = 0; i < model.numBoxes; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; - if(TestLineBox(newline, model.boxes[i])) - return true; - } - - CalculateTrianglePlanes(&model); - for(i = 0; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i])) - return true; - } - - return false; -#endif -} - - -// -// Process -// - -// For Spheres mindist is the squared distance to its center -// For Lines mindist is between [0,1] - -bool -CCollision::ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq) -{ - CVector dist = s1.center - s2.center; - float d = dist.Magnitude() - s2.radius; // distance from s1's center to s2 - float depth = s1.radius - d; // sphere overlap - if(d < 0.0f) d = 0.0f; // clamp to zero, i.e. if s1's center is inside s2 - // no collision if sphere is not close enough - if(d*d < mindistsq && d < s1.radius){ - dist.Normalise(); - point.point = s1.center - dist*d; - point.normal = dist; -#ifndef VU_COLLISION - point.surfaceA = s1.surface; - point.pieceA = s1.piece; - point.surfaceB = s2.surface; - point.pieceB = s2.piece; -#endif - point.depth = depth; - mindistsq = d*d; // collision radius - return true; - } - return false; -} - -bool -CCollision::ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq) -{ - CVector p; - CVector dist; - - // GTA's code is too complicated, uses a huge 3x3x3 if statement - // we can simplify the structure a lot - - // first make sure we have a collision at all - if(sph.center.x + sph.radius < box.min.x) return false; - if(sph.center.x - sph.radius > box.max.x) return false; - if(sph.center.y + sph.radius < box.min.y) return false; - if(sph.center.y - sph.radius > box.max.y) return false; - if(sph.center.z + sph.radius < box.min.z) return false; - if(sph.center.z - sph.radius > box.max.z) return false; - - // Now find out where the sphere center lies in relation to all the sides - int xpos = sph.center.x < box.min.x ? 1 : - sph.center.x > box.max.x ? 2 : - 0; - int ypos = sph.center.y < box.min.y ? 1 : - sph.center.y > box.max.y ? 2 : - 0; - int zpos = sph.center.z < box.min.z ? 1 : - sph.center.z > box.max.z ? 2 : - 0; - - if(xpos == 0 && ypos == 0 && zpos == 0){ - // sphere is inside the box - p = (box.min + box.max)*0.5f; - - dist = sph.center - p; - float lensq = dist.MagnitudeSqr(); - if(lensq < mindistsq){ - point.normal = dist * (1.0f/Sqrt(lensq)); - point.point = sph.center - point.normal; -#ifndef VU_COLLISION - point.surfaceA = sph.surface; - point.pieceA = sph.piece; - point.surfaceB = box.surface; - point.pieceB = box.piece; -#endif - - // find absolute distance to the closer side in each dimension - float dx = dist.x > 0.0f ? - box.max.x - sph.center.x : - sph.center.x - box.min.x; - float dy = dist.y > 0.0f ? - box.max.y - sph.center.y : - sph.center.y - box.min.y; - float dz = dist.z > 0.0f ? - box.max.z - sph.center.z : - sph.center.z - box.min.z; - // collision depth is maximum of that: - if(dx > dy && dx > dz) - point.depth = dx; - else if(dy > dz) - point.depth = dy; - else - point.depth = dz; - return true; - } - }else{ - // sphere is outside. - // closest point on box: - p.x = xpos == 1 ? box.min.x : - xpos == 2 ? box.max.x : - sph.center.x; - p.y = ypos == 1 ? box.min.y : - ypos == 2 ? box.max.y : - sph.center.y; - p.z = zpos == 1 ? box.min.z : - zpos == 2 ? box.max.z : - sph.center.z; - - dist = sph.center - p; - float lensq = dist.MagnitudeSqr(); - if(lensq < mindistsq){ - float len = Sqrt(lensq); - point.point = p; - point.normal = dist * (1.0f/len); -#ifndef VU_COLLISION - point.surfaceA = sph.surface; - point.pieceA = sph.piece; - point.surfaceB = box.surface; - point.pieceB = box.piece; -#endif - point.depth = sph.radius - len; - mindistsq = lensq; - return true; - } - } - return false; -} - -bool -CCollision::ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist) -{ - float mint, t, x, y, z; - CVector normal; - CVector p; - - mint = 1.0f; - // check if points are on opposite sides of min x plane - if((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){ - // parameter along line where we intersect - t = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x); - // y of intersection - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y){ - // z of intersection - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - if(t < mint){ - mint = t; - p = CVector(box.min.x, y, z); - normal = CVector(-1.0f, 0.0f, 0.0f); - } - } - } - - // max x plane - if((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){ - t = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x); - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y){ - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - if(t < mint){ - mint = t; - p = CVector(box.max.x, y, z); - normal = CVector(1.0f, 0.0f, 0.0f); - } - } - } - - // min y plne - if((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){ - t = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - if(t < mint){ - mint = t; - p = CVector(x, box.min.y, z); - normal = CVector(0.0f, -1.0f, 0.0f); - } - } - } - - // max y plane - if((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){ - t = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - z = line.p0.z + (line.p1.z - line.p0.z)*t; - if(z > box.min.z && z < box.max.z) - if(t < mint){ - mint = t; - p = CVector(x, box.max.y, z); - normal = CVector(0.0f, 1.0f, 0.0f); - } - } - } - - // min z plne - if((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){ - t = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y) - if(t < mint){ - mint = t; - p = CVector(x, y, box.min.z); - normal = CVector(0.0f, 0.0f, -1.0f); - } - } - } - - // max z plane - if((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){ - t = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z); - x = line.p0.x + (line.p1.x - line.p0.x)*t; - if(x > box.min.x && x < box.max.x){ - y = line.p0.y + (line.p1.y - line.p0.y)*t; - if(y > box.min.y && y < box.max.y) - if(t < mint){ - mint = t; - p = CVector(x, y, box.max.z); - normal = CVector(0.0f, 0.0f, 1.0f); - } - } - } - - if(mint >= mindist) - return false; - - point.point = p; - point.normal = normal; -#ifndef VU_COLLISION - point.surfaceA = 0; - point.pieceA = 0; - point.surfaceB = box.surface; - point.pieceB = box.piece; -#endif - mindist = mint; - - return true; -} - -// If line.p0 lies inside sphere, no collision is registered. -bool -CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist) -{ - CVector v01 = line.p1 - line.p0; - CVector v0c = sphere.center - line.p0; - float linesq = v01.MagnitudeSqr(); - // project v0c onto v01, scaled by |v01| this is the midpoint of the two intersections - float projline = DotProduct(v01, v0c); - // tangent of p0 to sphere, scaled by linesq just like projline^2 - float tansq = (v0c.MagnitudeSqr() - sphere.radius*sphere.radius) * linesq; - // this works out to be the square of the distance between the midpoint and the intersections - float diffsq = projline*projline - tansq; - // no intersection - if(diffsq < 0.0f) - return false; - // point of first intersection, in range [0,1] between p0 and p1 - float t = (projline - Sqrt(diffsq)) / linesq; - // if not on line or beyond mindist, no intersection - if(t < 0.0f || t > 1.0f || t >= mindist) - return false; - point.point = line.p0 + v01*t; - point.normal = point.point - sphere.center; - point.normal.Normalise(); -#ifndef VU_COLLISION - point.surfaceA = 0; - point.pieceA = 0; - point.surfaceB = sphere.surface; - point.pieceB = sphere.piece; -#endif - mindist = t; - return true; -} - -bool -CCollision::ProcessVerticalLineTriangle(const CColLine &line, - const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, - CColPoint &point, float &mindist, CStoredCollPoly *poly) -{ -#ifdef VU_COLLISION - // not used in favour of optimized loops - bool res = ProcessLineTriangle(line, verts, tri, plane, point, mindist); - if(res && poly){ - poly->verts[0] = verts[tri.a].Get(); - poly->verts[1] = verts[tri.b].Get(); - poly->verts[2] = verts[tri.c].Get(); - poly->valid = true; - } - return res; -#else - float t; - CVector normal; - - const CVector &p0 = line.p0; - const CVector &va = verts[tri.a].Get(); - const CVector &vb = verts[tri.b].Get(); - const CVector &vc = verts[tri.c].Get(); - - // early out bound rect test - if(p0.x < va.x && p0.x < vb.x && p0.x < vc.x) return false; - if(p0.x > va.x && p0.x > vb.x && p0.x > vc.x) return false; - if(p0.y < va.y && p0.y < vb.y && p0.y < vc.y) return false; - if(p0.y > va.y && p0.y > vb.y && p0.y > vc.y) return false; - - plane.GetNormal(normal); - // if points are on the same side, no collision - if(plane.CalcPoint(p0) * plane.CalcPoint(line.p1) > 0.0f) - return false; - - // intersection parameter on line - float h = (line.p1 - p0).z; - t = -plane.CalcPoint(p0) / (h * normal.z); - // early out if we're beyond the mindist - if(t >= mindist) - return false; - CVector p(p0.x, p0.y, p0.z + h*t); - - CVector2D vec1, vec2, vec3, vect; - switch(plane.dir){ - case DIR_X_POS: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vc.y; vec2.y = vc.z; - vec3.x = vb.y; vec3.y = vb.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_X_NEG: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vb.y; vec2.y = vb.z; - vec3.x = vc.y; vec3.y = vc.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_Y_POS: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vc.z; vec2.y = vc.x; - vec3.x = vb.z; vec3.y = vb.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Y_NEG: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vb.z; vec2.y = vb.x; - vec3.x = vc.z; vec3.y = vc.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Z_POS: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vc.x; vec2.y = vc.y; - vec3.x = vb.x; vec3.y = vb.y; - vect.x = p.x; vect.y = p.y; - break; - case DIR_Z_NEG: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vb.x; vec2.y = vb.y; - vec3.x = vc.x; vec3.y = vc.y; - vect.x = p.x; vect.y = p.y; - break; - default: - assert(0); - } - if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; - if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; - if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; - if(t >= mindist) return false; - point.point = p; - point.normal = normal; - point.surfaceA = 0; - point.pieceA = 0; - point.surfaceB = tri.surface; - point.pieceB = 0; - if(poly){ - poly->verts[0] = va; - poly->verts[1] = vb; - poly->verts[2] = vc; - poly->valid = true; - } - mindist = t; - return true; -#endif -} - -bool -CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly) -{ -#ifdef VU_COLLISION - if(!poly->valid) - return false; - - CVuVector p0 = pos; - CVuVector p1 = pos; - p1.z = z; - - CVector v01 = poly->verts[1] - poly->verts[0]; - CVector v02 = poly->verts[2] - poly->verts[0]; - CVuVector plane = CrossProduct(v02, v01); - plane.Normalise(); - plane.w = DotProduct(plane, poly->verts[0]); - - LineToTriangleCollision(p0, p1, poly->verts[0], poly->verts[1], poly->verts[2], plane); - - CVuVector pnt; - float dist; - if(!GetVUresult(pnt, plane, dist)) -#ifdef FIX_BUGS - // perhaps not needed but be safe - return poly->valid = false; -#else - return false; -#endif - point.point = pnt; - return true; -#else - float t; - - if(!poly->valid) - return false; - - // maybe inlined? - CColTrianglePlane plane; - plane.Set(poly->verts[0], poly->verts[1], poly->verts[2]); - - const CVector &va = poly->verts[0]; - const CVector &vb = poly->verts[1]; - const CVector &vc = poly->verts[2]; - CVector p0 = pos; - CVector p1(pos.x, pos.y, z); - - // The rest is pretty much CCollision::ProcessLineTriangle - - // if points are on the same side, no collision - if(plane.CalcPoint(p0) * plane.CalcPoint(p1) > 0.0f) - return poly->valid = false; - - // intersection parameter on line - CVector normal; - plane.GetNormal(normal); - t = -plane.CalcPoint(p0) / DotProduct(p1 - p0, normal); - // find point of intersection - CVector p = p0 + (p1-p0)*t; - - CVector2D vec1, vec2, vec3, vect; - switch(plane.dir){ - case DIR_X_POS: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vc.y; vec2.y = vc.z; - vec3.x = vb.y; vec3.y = vb.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_X_NEG: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vb.y; vec2.y = vb.z; - vec3.x = vc.y; vec3.y = vc.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_Y_POS: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vc.z; vec2.y = vc.x; - vec3.x = vb.z; vec3.y = vb.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Y_NEG: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vb.z; vec2.y = vb.x; - vec3.x = vc.z; vec3.y = vc.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Z_POS: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vc.x; vec2.y = vc.y; - vec3.x = vb.x; vec3.y = vb.y; - vect.x = p.x; vect.y = p.y; - break; - case DIR_Z_NEG: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vb.x; vec2.y = vb.y; - vec3.x = vc.x; vec3.y = vc.y; - vect.x = p.x; vect.y = p.y; - break; - default: - assert(0); - } - if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return poly->valid = false; - if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return poly->valid = false; - if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return poly->valid = false; - point.point = p; - return poly->valid = true; -#endif -} - -bool -CCollision::ProcessLineTriangle(const CColLine &line, - const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, - CColPoint &point, float &mindist) -{ -#ifdef VU_COLLISION - // not used in favour of optimized loops - VuTriangle vutri; - verts[tri.a].Unpack(vutri.v0); - verts[tri.b].Unpack(vutri.v1); - verts[tri.c].Unpack(vutri.v2); - plane.Unpack(vutri.plane); - - LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri); - - CVuVector pnt, normal; - float dist; - if(GetVUresult(pnt, normal, dist)){ - if(dist < mindist){ - point.point = pnt; - point.normal = normal; - mindist = dist; - return true; - } - } - return false; -#else - float t; - CVector normal; - plane.GetNormal(normal); - - // if points are on the same side, no collision - if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f) - return false; - - // intersection parameter on line - t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal); - // early out if we're beyond the mindist - if(t >= mindist) - return false; - // find point of intersection - CVector p = line.p0 + (line.p1-line.p0)*t; - - const CVector &va = verts[tri.a].Get(); - const CVector &vb = verts[tri.b].Get(); - const CVector &vc = verts[tri.c].Get(); - CVector2D vec1, vec2, vec3, vect; - - switch(plane.dir){ - case DIR_X_POS: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vc.y; vec2.y = vc.z; - vec3.x = vb.y; vec3.y = vb.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_X_NEG: - vec1.x = va.y; vec1.y = va.z; - vec2.x = vb.y; vec2.y = vb.z; - vec3.x = vc.y; vec3.y = vc.z; - vect.x = p.y; vect.y = p.z; - break; - case DIR_Y_POS: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vc.z; vec2.y = vc.x; - vec3.x = vb.z; vec3.y = vb.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Y_NEG: - vec1.x = va.z; vec1.y = va.x; - vec2.x = vb.z; vec2.y = vb.x; - vec3.x = vc.z; vec3.y = vc.x; - vect.x = p.z; vect.y = p.x; - break; - case DIR_Z_POS: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vc.x; vec2.y = vc.y; - vec3.x = vb.x; vec3.y = vb.y; - vect.x = p.x; vect.y = p.y; - break; - case DIR_Z_NEG: - vec1.x = va.x; vec1.y = va.y; - vec2.x = vb.x; vec2.y = vb.y; - vec3.x = vc.x; vec3.y = vc.y; - vect.x = p.x; vect.y = p.y; - break; - default: - assert(0); - } - if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; - if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; - if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; - if(t >= mindist) return false; - point.point = p; - point.normal = normal; - point.surfaceA = 0; - point.pieceA = 0; - point.surfaceB = tri.surface; - point.pieceB = 0; - mindist = t; - return true; -#endif -} - -bool -CCollision::ProcessSphereTriangle(const CColSphere &sphere, - const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, - CColPoint &point, float &mindistsq) -{ -#ifdef VU_COLLISION - // not used in favour of optimized loops - VuTriangle vutri; - verts[tri.a].Unpack(vutri.v0); - verts[tri.b].Unpack(vutri.v1); - verts[tri.c].Unpack(vutri.v2); - plane.Unpack(vutri.plane); - - SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri); - - CVuVector pnt, normal; - float dist; - if(GetVUresult(pnt, normal, dist) && dist*dist < mindistsq){ - float depth = sphere.radius - dist; - if(depth > point.depth){ - point.point = pnt; - point.normal = normal; - point.depth = depth; - mindistsq = dist*dist; - return true; - } - } - return false; -#else - // If sphere and plane don't intersect, no collision - float planedist = plane.CalcPoint(sphere.center); - float distsq = planedist*planedist; - if(Abs(planedist) > sphere.radius || distsq > mindistsq) - return false; - - const CVector &va = verts[tri.a].Get(); - const CVector &vb = verts[tri.b].Get(); - const CVector &vc = verts[tri.c].Get(); - - // calculate two orthogonal basis vectors for the triangle - CVector normal; - plane.GetNormal(normal); - CVector vec2 = vb - va; - float len = vec2.Magnitude(); - vec2 = vec2 * (1.0f/len); - CVector vec1 = CrossProduct(vec2, normal); - - // We know A has local coordinate [0,0] and B has [0,len]. - // Now calculate coordinates on triangle for these two vectors: - CVector vac = vc - va; - CVector vas = sphere.center - va; - CVector2D b(0.0f, len); - CVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac)); - CVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas)); - - // The three triangle lines partition the space into 6 sectors, - // find out in which the center lies. - int insideAB = CrossProduct2D(s, b) >= 0.0f; - int insideAC = CrossProduct2D(c, s) >= 0.0f; - int insideBC = CrossProduct2D(s-b, c-b) >= 0.0f; - - int testcase = insideAB + insideAC + insideBC; - float dist = 0.0f; - CVector p; - switch(testcase){ - case 1: - // closest to a vertex - if(insideAB) p = vc; - else if(insideAC) p = vb; - else if(insideBC) p = va; - else assert(0); - dist = (sphere.center - p).Magnitude(); - break; - case 2: - // closest to an edge - // looks like original game as DistToLine manually inlined - if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center, p); - else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center, p); - else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center, p); - else assert(0); - break; - case 3: - // center is in triangle - dist = Abs(planedist); - p = sphere.center - normal*planedist; - break; - default: - assert(0); - } - - if(dist >= sphere.radius || dist*dist >= mindistsq) - return false; - - point.point = p; - point.normal = sphere.center - p; - point.normal.Normalise(); -#ifndef VU_COLLISION - point.surfaceA = sphere.surface; - point.pieceA = sphere.piece; - point.surfaceB = tri.surface; - point.pieceB = 0; -#endif - point.depth = sphere.radius - dist; - mindistsq = dist*dist; - return true; -#endif -} - -bool -CCollision::ProcessLineOfSight(const CColLine &line, - const CMatrix &matrix, CColModel &model, - CColPoint &point, float &mindist, bool ignoreSeeThrough) -{ -#ifdef VU_COLLISION - CMatrix matTransform; - int i; - - // transform line to model space - Invert(matrix, matTransform); - CVuVector newline[2]; - TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); - - if(mindist < 1.0f) - newline[1] = newline[0] + (newline[1] - newline[0])*mindist; - - // If we don't intersect with the bounding box, no chance on the rest - if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) - return false; - - float coldist = 1.0f; - for(i = 0; i < model.numSpheres; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; - if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist)) - point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece); - } - - for(i = 0; i < model.numBoxes; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; - if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist)) - point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece); - } - - CalculateTrianglePlanes(&model); - VuTriangle vutri; - CColTriangle *lasttri = nil; - for(i = 0; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - - CColTriangle *tri = &model.triangles[i]; - model.vertices[tri->a].Unpack(vutri.v0); - model.vertices[tri->b].Unpack(vutri.v1); - model.vertices[tri->c].Unpack(vutri.v2); - model.trianglePlanes[i].Unpack(vutri.plane); - - LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); - lasttri = tri; - break; - } -#ifdef FIX_BUGS - // no need to check first again - i++; -#endif - CVuVector pnt, normal; - float dist; - for(; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - - CColTriangle *tri = &model.triangles[i]; - model.vertices[tri->a].Unpack(vutri.v0); - model.vertices[tri->b].Unpack(vutri.v1); - model.vertices[tri->c].Unpack(vutri.v2); - model.trianglePlanes[i].Unpack(vutri.plane); - - if(GetVUresult(pnt, normal, dist)) - if(dist < coldist){ - point.point = pnt; - point.normal = normal; - point.Set(0, 0, lasttri->surface, 0); - coldist = dist; - } - - LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); - lasttri = tri; - } - if(lasttri && GetVUresult(pnt, normal, dist)) - if(dist < coldist){ - point.point = pnt; - point.normal = normal; - point.Set(0, 0, lasttri->surface, 0); - coldist = dist; - } - - - if(coldist < 1.0f){ - point.point = matrix * point.point; - point.normal = Multiply3x3(matrix, point.normal); - mindist *= coldist; - return true; - } - return false; -#else - static CMatrix matTransform; - int i; - - // transform line to model space - Invert(matrix, matTransform); - CColLine newline(matTransform * line.p0, matTransform * line.p1); - - // If we don't intersect with the bounding box, no chance on the rest - if(!TestLineBox(newline, model.boundingBox)) - return false; - - float coldist = mindist; - for(i = 0; i < model.numSpheres; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; - ProcessLineSphere(newline, model.spheres[i], point, coldist); - } - - for(i = 0; i < model.numBoxes; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; - ProcessLineBox(newline, model.boxes[i], point, coldist); - } - - CalculateTrianglePlanes(&model); - for(i = 0; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist); - } - - if(coldist < mindist){ - point.point = matrix * point.point; - point.normal = Multiply3x3(matrix, point.normal); - mindist = coldist; - return true; - } - return false; -#endif -} - -bool -CCollision::ProcessVerticalLine(const CColLine &line, - const CMatrix &matrix, CColModel &model, - CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly) -{ -#ifdef VU_COLLISION - static CStoredCollPoly TempStoredPoly; - CMatrix matTransform; - int i; - - // transform line to model space - Invert(matrix, matTransform); - CVuVector newline[2]; - TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); - - if(mindist < 1.0f) - newline[1] = newline[0] + (newline[1] - newline[0])*mindist; - - if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) - return false; - - float coldist = 1.0f; - for(i = 0; i < model.numSpheres; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; - if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist)) - point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece); - } - - for(i = 0; i < model.numBoxes; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; - if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist)) - point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece); - } - - CalculateTrianglePlanes(&model); - TempStoredPoly.valid = false; - if(model.numTriangles){ - bool registeredCol; - CColTriangle *lasttri = nil; - VuTriangle vutri; - for(i = 0; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - - CColTriangle *tri = &model.triangles[i]; - model.vertices[tri->a].Unpack(vutri.v0); - model.vertices[tri->b].Unpack(vutri.v1); - model.vertices[tri->c].Unpack(vutri.v2); - model.trianglePlanes[i].Unpack(vutri.plane); - - LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); - lasttri = tri; - break; - } -#ifdef FIX_BUGS - // no need to check first again - i++; -#endif - CVuVector pnt, normal; - float dist; - for(; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - - CColTriangle *tri = &model.triangles[i]; - model.vertices[tri->a].Unpack(vutri.v0); - model.vertices[tri->b].Unpack(vutri.v1); - model.vertices[tri->c].Unpack(vutri.v2); - model.trianglePlanes[i].Unpack(vutri.plane); - - if(GetVUresult(pnt, normal, dist)){ - if(dist < coldist){ - point.point = pnt; - point.normal = normal; - point.Set(0, 0, lasttri->surface, 0); - coldist = dist; - registeredCol = true; - }else - registeredCol = false; - }else - registeredCol = false; - - if(registeredCol){ - TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get(); - TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get(); - TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get(); - TempStoredPoly.valid = true; - } - - LineToTriangleCollisionCompressed(newline[0], newline[1], vutri); - lasttri = tri; - } - if(lasttri && GetVUresult(pnt, normal, dist)){ - if(dist < coldist){ - point.point = pnt; - point.normal = normal; - point.Set(0, 0, lasttri->surface, 0); - coldist = dist; - registeredCol = true; - }else - registeredCol = false; - }else - registeredCol = false; - - if(registeredCol){ - TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get(); - TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get(); - TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get(); - TempStoredPoly.valid = true; - } - } - - if(coldist < 1.0f){ - point.point = matrix * point.point; - point.normal = Multiply3x3(matrix, point.normal); - if(TempStoredPoly.valid && poly){ - *poly = TempStoredPoly; - poly->verts[0] = matrix * CVector(poly->verts[0]); - poly->verts[1] = matrix * CVector(poly->verts[1]); - poly->verts[2] = matrix * CVector(poly->verts[2]); - } - mindist *= coldist; - return true; - } - return false; -#else - static CStoredCollPoly TempStoredPoly; - int i; - - // transform line to model space - // Why does the game seem to do this differently than above? - CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1)); - newline.p1.x = newline.p0.x; - newline.p1.y = newline.p0.y; - - if(!TestVerticalLineBox(newline, model.boundingBox)) - return false; - - float coldist = mindist; - for(i = 0; i < model.numSpheres; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; - ProcessLineSphere(newline, model.spheres[i], point, coldist); - } - - for(i = 0; i < model.numBoxes; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; - ProcessLineBox(newline, model.boxes[i], point, coldist); - } - - CalculateTrianglePlanes(&model); - TempStoredPoly.valid = false; - for(i = 0; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); - } - - if(coldist < mindist){ - point.point = matrix * point.point; - point.normal = Multiply3x3(matrix, point.normal); - if(TempStoredPoly.valid && poly){ - *poly = TempStoredPoly; - poly->verts[0] = matrix * poly->verts[0]; - poly->verts[1] = matrix * poly->verts[1]; - poly->verts[2] = matrix * poly->verts[2]; - } - mindist = coldist; - return true; - } - return false; -#endif -} - -enum { - MAXNUMSPHERES = 128, - MAXNUMBOXES = 32, - MAXNUMLINES = 16, - MAXNUMTRIS = 600 -}; - -#ifdef VU_COLLISION -#ifdef GTA_PS2 -#define SPR(off) ((uint8*)(0x70000000 + (off))) -#else -static uint8 fakeSPR[16*1024]; -#define SPR(off) ((uint8*)(fakeSPR + (off))) -#endif -#endif - -// This checks model A's spheres and lines against model B's spheres, boxes and triangles. -// Returns the number of A's spheres that collide. -// Returned ColPoints are in world space. -// NB: only vehicles can have col models with lines, exactly 4, one for each wheel -int32 -CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA, - const CMatrix &matrixB, CColModel &modelB, - CColPoint *spherepoints, CColPoint *linepoints, float *linedists) -{ -#ifdef VU_COLLISION - CVuVector *aSpheresA = (CVuVector*)SPR(0x0000); - CVuVector *aSpheresB = (CVuVector*)SPR(0x0800); - CVuVector *aLinesA = (CVuVector*)SPR(0x1000); - int32 *aSphereIndicesA = (int32*)SPR(0x1200); - int32 *aSphereIndicesB = (int32*)SPR(0x1400); - int32 *aBoxIndicesB = (int32*)SPR(0x1600); - int32 *aTriangleIndicesB = (int32*)SPR(0x1680); - bool *aCollided = (bool*)SPR(0x1FE0); - CMatrix &matAB = *(CMatrix*)SPR(0x1FF0); - CMatrix &matBA = *(CMatrix*)SPR(0x2040); - int i, j, k; - - // From model A space to model B space - Invert(matrixB, matAB); - matAB *= matrixA; - - CVuVector bsphereAB; // bounding sphere of A in B space - TransformPoint(bsphereAB, matAB, *(RwV3d*)modelA.boundingSphere.center); // inlined - bsphereAB.w = modelA.boundingSphere.radius; - if(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox)) - return 0; - - // transform modelA's spheres and lines to B space - TransformPoints(aSpheresA, modelA.numSpheres, matAB, (RwV3d*)&modelA.spheres->center, sizeof(CColSphere)); - for(i = 0; i < modelA.numSpheres; i++) - aSpheresA[i].w = modelA.spheres[i].radius; - TransformPoints(aLinesA, modelA.numLines*2, matAB, (RwV3d*)&modelA.lines->p0, sizeof(CColLine)/2); - - // Test them against model B's bounding volumes - int numSpheresA = 0; - for(i = 0; i < modelA.numSpheres; i++) - if(TestSphereBox(*(CColSphere*)&aSpheresA[i], modelB.boundingBox)) - aSphereIndicesA[numSpheresA++] = i; - // No collision - if(numSpheresA == 0 && modelA.numLines == 0) - return 0; - - - // B to A space - Invert(matrixA, matBA); - matBA *= matrixB; - - // transform modelB's spheres to A space - TransformPoints(aSpheresB, modelB.numSpheres, matBA, (RwV3d*)&modelB.spheres->center, sizeof(CColSphere)); - for(i = 0; i < modelB.numSpheres; i++) - aSpheresB[i].w = modelB.spheres[i].radius; - - // Check model B against A's bounding volumes - int numSpheresB = 0; - int numBoxesB = 0; - int numTrianglesB = 0; - for(i = 0; i < modelB.numSpheres; i++) - if(TestSphereBox(*(CColSphere*)&aSpheresB[i], modelA.boundingBox)) - aSphereIndicesB[numSpheresB++] = i; - for(i = 0; i < modelB.numBoxes; i++) - if(TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boxes[i])) - aBoxIndicesB[numBoxesB++] = i; - CalculateTrianglePlanes(&modelB); - if(modelB.numTriangles){ - VuTriangle vutri; - // process the first triangle - CColTriangle *tri = &modelB.triangles[0]; - modelB.vertices[tri->a].Unpack(vutri.v0); - modelB.vertices[tri->b].Unpack(vutri.v1); - modelB.vertices[tri->c].Unpack(vutri.v2); - modelB.trianglePlanes[0].Unpack(vutri.plane); - - SphereToTriangleCollisionCompressed(bsphereAB, vutri); - - for(i = 1; i < modelB.numTriangles; i++){ - // set up the next triangle while VU0 is running - tri = &modelB.triangles[i]; - modelB.vertices[tri->a].Unpack(vutri.v0); - modelB.vertices[tri->b].Unpack(vutri.v1); - modelB.vertices[tri->c].Unpack(vutri.v2); - modelB.trianglePlanes[i].Unpack(vutri.plane); - - // check previous result - if(GetVUresult()) - aTriangleIndicesB[numTrianglesB++] = i-1; - - // kick off this one - SphereToTriangleCollisionCompressed(bsphereAB, vutri); - } - - // check last result - if(GetVUresult()) - aTriangleIndicesB[numTrianglesB++] = i-1; - } - // No collision - if(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0) - return 0; - - // We now have the collision volumes in A and B that are worth processing. - - // Process A's spheres against B's collision volumes - int numCollisions = 0; - spherepoints[numCollisions].depth = -1.0f; - for(i = 0; i < numSpheresA; i++){ - float coldist = 1.0e24f; - bool hasCollided = false; - CColSphere *sphA = &modelA.spheres[aSphereIndicesA[i]]; - CVuVector *vusphA = &aSpheresA[aSphereIndicesA[i]]; - - for(j = 0; j < numSpheresB; j++) - // This actually looks like something was inlined here - if(ProcessSphereSphere(*(CColSphere*)vusphA, modelB.spheres[aSphereIndicesB[j]], - spherepoints[numCollisions], coldist)){ - spherepoints[numCollisions].Set( - sphA->surface, sphA->piece, - modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece); - hasCollided = true; - } - for(j = 0; j < numBoxesB; j++) - if(ProcessSphereBox(*(CColSphere*)vusphA, modelB.boxes[aBoxIndicesB[j]], - spherepoints[numCollisions], coldist)){ - spherepoints[numCollisions].Set( - sphA->surface, sphA->piece, - modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece); - hasCollided = true; - } - if(numTrianglesB){ - CVuVector point, normal; - float depth; - bool registeredCol; - CColTriangle *lasttri; - - VuTriangle vutri; - // process the first triangle - k = aTriangleIndicesB[0]; - CColTriangle *tri = &modelB.triangles[k]; - modelB.vertices[tri->a].Unpack(vutri.v0); - modelB.vertices[tri->b].Unpack(vutri.v1); - modelB.vertices[tri->c].Unpack(vutri.v2); - modelB.trianglePlanes[k].Unpack(vutri.plane); - - SphereToTriangleCollisionCompressed(*vusphA, vutri); - lasttri = tri; - - for(j = 1; j < numTrianglesB; j++){ - k = aTriangleIndicesB[j]; - // set up the next triangle while VU0 is running - tri = &modelB.triangles[k]; - modelB.vertices[tri->a].Unpack(vutri.v0); - modelB.vertices[tri->b].Unpack(vutri.v1); - modelB.vertices[tri->c].Unpack(vutri.v2); - modelB.trianglePlanes[k].Unpack(vutri.plane); - - // check previous result - // TODO: this looks inlined but spherepoints[numCollisions] does not... - if(GetVUresult(point, normal, depth)){ - depth = sphA->radius - depth; - if(depth > spherepoints[numCollisions].depth){ - spherepoints[numCollisions].point = point; - spherepoints[numCollisions].normal = normal; - spherepoints[numCollisions].Set(depth, - sphA->surface, sphA->piece, lasttri->surface, 0); - registeredCol = true; - }else - registeredCol = false; - }else - registeredCol = false; - - if(registeredCol) - hasCollided = true; - - // kick off this one - SphereToTriangleCollisionCompressed(*vusphA, vutri); - lasttri = tri; - } - - // check last result - // TODO: this looks inlined but spherepoints[numCollisions] does not... - if(GetVUresult(point, normal, depth)){ - depth = sphA->radius - depth; - if(depth > spherepoints[numCollisions].depth){ - spherepoints[numCollisions].point = point; - spherepoints[numCollisions].normal = normal; - spherepoints[numCollisions].Set(depth, - sphA->surface, sphA->piece, lasttri->surface, 0); - registeredCol = true; - }else - registeredCol = false; - }else - registeredCol = false; - - if(registeredCol) - hasCollided = true; - } - - if(hasCollided){ - numCollisions++; - if(numCollisions == MAX_COLLISION_POINTS) - break; - spherepoints[numCollisions].depth = -1.0f; - } - } - for(i = 0; i < numCollisions; i++){ - // TODO: both VU0 macros - spherepoints[i].point = matrixB * spherepoints[i].point; - spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal); - } - - // And the same thing for the lines in A - for(i = 0; i < modelA.numLines; i++){ - aCollided[i] = false; - CVuVector *lineA = &aLinesA[i*2]; - - for(j = 0; j < numSpheresB; j++) - if(ProcessLineSphere(*(CColLine*)lineA, modelB.spheres[aSphereIndicesB[j]], - linepoints[i], linedists[i])){ - linepoints[i].Set(0, 0, -#ifdef FIX_BUGS - modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece); -#else - modelB.spheres[j].surface, modelB.spheres[j].piece); -#endif - aCollided[i] = true; - } - for(j = 0; j < numBoxesB; j++) - if(ProcessLineBox(*(CColLine*)lineA, modelB.boxes[aBoxIndicesB[j]], - linepoints[i], linedists[i])){ - linepoints[i].Set(0, 0, - modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece); - aCollided[i] = true; - } - if(numTrianglesB){ - CVuVector point, normal; - float dist; - bool registeredCol; - CColTriangle *lasttri; - - VuTriangle vutri; - // process the first triangle - k = aTriangleIndicesB[0]; - CColTriangle *tri = &modelB.triangles[k]; - modelB.vertices[tri->a].Unpack(vutri.v0); - modelB.vertices[tri->b].Unpack(vutri.v1); - modelB.vertices[tri->c].Unpack(vutri.v2); - modelB.trianglePlanes[k].Unpack(vutri.plane); - - LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri); - lasttri = tri; - - for(j = 1; j < numTrianglesB; j++){ - k = aTriangleIndicesB[j]; - // set up the next triangle while VU0 is running - CColTriangle *tri = &modelB.triangles[k]; - modelB.vertices[tri->a].Unpack(vutri.v0); - modelB.vertices[tri->b].Unpack(vutri.v1); - modelB.vertices[tri->c].Unpack(vutri.v2); - modelB.trianglePlanes[k].Unpack(vutri.plane); - - // check previous result - // TODO: this again somewhat looks inlined - if(GetVUresult(point, normal, dist)){ - if(dist < linedists[i]){ - linepoints[i].point = point; - linepoints[i].normal = normal; - linedists[i] = dist; - linepoints[i].Set(0, 0, lasttri->surface, 0); - registeredCol = true; - }else - registeredCol = false; - }else - registeredCol = false; - - if(registeredCol) - aCollided[i] = true; - - // kick of this one - LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri); - lasttri = tri; - } - - // check last result - if(GetVUresult(point, normal, dist)){ - if(dist < linedists[i]){ - linepoints[i].point = point; - linepoints[i].normal = normal; - linedists[i] = dist; - linepoints[i].Set(0, 0, lasttri->surface, 0); - registeredCol = true; - }else - registeredCol = false; - }else - registeredCol = false; - - if(registeredCol) - aCollided[i] = true; - } - - if(aCollided[i]){ - // TODO: both VU0 macros - linepoints[i].point = matrixB * linepoints[i].point; - linepoints[i].normal = Multiply3x3(matrixB, linepoints[i].normal); - } - } - - return numCollisions; // sphere collisions -#else - static int aSphereIndicesA[MAXNUMSPHERES]; - static int aLineIndicesA[MAXNUMLINES]; - static int aSphereIndicesB[MAXNUMSPHERES]; - static int aBoxIndicesB[MAXNUMBOXES]; - static int aTriangleIndicesB[MAXNUMTRIS]; - static bool aCollided[MAXNUMLINES]; - static CColSphere aSpheresA[MAXNUMSPHERES]; - static CColLine aLinesA[MAXNUMLINES]; - static CMatrix matAB, matBA; - CColSphere s; - int i, j; - - assert(modelA.numSpheres <= MAXNUMSPHERES); - assert(modelA.numLines <= MAXNUMLINES); - - // From model A space to model B space - Invert(matrixB, matAB); - matAB *= matrixA; - - CColSphere bsphereAB; // bounding sphere of A in B space - bsphereAB.Set(modelA.boundingSphere.radius, matAB * modelA.boundingSphere.center); - if(!TestSphereBox(bsphereAB, modelB.boundingBox)) - return 0; - // B to A space - matBA = Invert(matrixA, matBA); - matBA *= matrixB; - - // transform modelA's spheres and lines to B space - for(i = 0; i < modelA.numSpheres; i++){ - CColSphere &s = modelA.spheres[i]; - aSpheresA[i].Set(s.radius, matAB * s.center, s.surface, s.piece); - } - for(i = 0; i < modelA.numLines; i++) - aLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1); - - // Test them against model B's bounding volumes - int numSpheresA = 0; - int numLinesA = 0; - for(i = 0; i < modelA.numSpheres; i++) - if(TestSphereBox(aSpheresA[i], modelB.boundingBox)) - aSphereIndicesA[numSpheresA++] = i; - // no actual check??? - for(i = 0; i < modelA.numLines; i++) - aLineIndicesA[numLinesA++] = i; - // No collision - if(numSpheresA == 0 && numLinesA == 0) - return 0; - - // Check model B against A's bounding volumes - int numSpheresB = 0; - int numBoxesB = 0; - int numTrianglesB = 0; - for(i = 0; i < modelB.numSpheres; i++){ - s.Set(modelB.spheres[i].radius, matBA * modelB.spheres[i].center); - if(TestSphereBox(s, modelA.boundingBox)) - aSphereIndicesB[numSpheresB++] = i; - } - for(i = 0; i < modelB.numBoxes; i++) - if(TestSphereBox(bsphereAB, modelB.boxes[i])) - aBoxIndicesB[numBoxesB++] = i; - CalculateTrianglePlanes(&modelB); - for(i = 0; i < modelB.numTriangles; i++) - if(TestSphereTriangle(bsphereAB, modelB.vertices, modelB.triangles[i], modelB.trianglePlanes[i])) - aTriangleIndicesB[numTrianglesB++] = i; - assert(numSpheresB <= MAXNUMSPHERES); - assert(numBoxesB <= MAXNUMBOXES); - assert(numTrianglesB <= MAXNUMTRIS); - // No collision - if(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0) - return 0; - - // We now have the collision volumes in A and B that are worth processing. - - // Process A's spheres against B's collision volumes - int numCollisions = 0; - for(i = 0; i < numSpheresA; i++){ - float coldist = 1.0e24f; - bool hasCollided = false; - - for(j = 0; j < numSpheresB; j++) - hasCollided |= ProcessSphereSphere( - aSpheresA[aSphereIndicesA[i]], - modelB.spheres[aSphereIndicesB[j]], - spherepoints[numCollisions], coldist); - for(j = 0; j < numBoxesB; j++) - hasCollided |= ProcessSphereBox( - aSpheresA[aSphereIndicesA[i]], - modelB.boxes[aBoxIndicesB[j]], - spherepoints[numCollisions], coldist); - for(j = 0; j < numTrianglesB; j++) - hasCollided |= ProcessSphereTriangle( - aSpheresA[aSphereIndicesA[i]], - modelB.vertices, - modelB.triangles[aTriangleIndicesB[j]], - modelB.trianglePlanes[aTriangleIndicesB[j]], - spherepoints[numCollisions], coldist); - - if(hasCollided) - numCollisions++; - } - for(i = 0; i < numCollisions; i++){ - spherepoints[i].point = matrixB * spherepoints[i].point; - spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal); - } - - // And the same thing for the lines in A - for(i = 0; i < numLinesA; i++){ - aCollided[i] = false; - - for(j = 0; j < numSpheresB; j++) - aCollided[i] |= ProcessLineSphere( - aLinesA[aLineIndicesA[i]], - modelB.spheres[aSphereIndicesB[j]], - linepoints[aLineIndicesA[i]], - linedists[aLineIndicesA[i]]); - for(j = 0; j < numBoxesB; j++) - aCollided[i] |= ProcessLineBox( - aLinesA[aLineIndicesA[i]], - modelB.boxes[aBoxIndicesB[j]], - linepoints[aLineIndicesA[i]], - linedists[aLineIndicesA[i]]); - for(j = 0; j < numTrianglesB; j++) - aCollided[i] |= ProcessLineTriangle( - aLinesA[aLineIndicesA[i]], - modelB.vertices, - modelB.triangles[aTriangleIndicesB[j]], - modelB.trianglePlanes[aTriangleIndicesB[j]], - linepoints[aLineIndicesA[i]], - linedists[aLineIndicesA[i]]); - } - for(i = 0; i < numLinesA; i++) - if(aCollided[i]){ - j = aLineIndicesA[i]; - linepoints[j].point = matrixB * linepoints[j].point; - linepoints[j].normal = Multiply3x3(matrixB, linepoints[j].normal); - } - - return numCollisions; // sphere collisions -#endif -} - - -// -// Misc -// - -float -CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point) -{ - float lensq = (*l1 - *l0).MagnitudeSqr(); - float dot = DotProduct(*point - *l0, *l1 - *l0); - // Between 0 and len we're above the line. - // if not, calculate distance to endpoint - if(dot <= 0.0f) - return (*point - *l0).Magnitude(); - if(dot >= lensq) - return (*point - *l1).Magnitude(); - // distance to line - return Sqrt((*point - *l0).MagnitudeSqr() - dot*dot/lensq); -} - -// same as above but also return the point on the line -float -CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest) -{ - float lensq = (*l1 - *l0).MagnitudeSqr(); - float dot = DotProduct(*point - *l0, *l1 - *l0); - // find out which point we're closest to - if(dot <= 0.0f) - closest = *l0; - else if(dot >= lensq) - closest = *l1; - else - closest = *l0 + (*l1 - *l0)*(dot/lensq); - // this is the distance - return (*point - closest).Magnitude(); -} - -void -CCollision::CalculateTrianglePlanes(CColModel *model) -{ - assert(model); - if(model->numTriangles == 0) - return; - - CLink *lptr; - if(model->trianglePlanes){ - // re-insert at front so it's not removed again soon - lptr = model->GetLinkPtr(); - lptr->Remove(); - ms_colModelCache.head.Insert(lptr); - }else{ - lptr = ms_colModelCache.Insert(model); - if(lptr == nil){ - // make room if we have to, remove last in list - lptr = ms_colModelCache.tail.prev; - assert(lptr); - assert(lptr->item); - lptr->item->RemoveTrianglePlanes(); - ms_colModelCache.Remove(lptr); - // now this cannot fail - lptr = ms_colModelCache.Insert(model); - assert(lptr); - } - model->CalculateTrianglePlanes(); - model->SetLinkPtr(lptr); - } -} - -void -CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel) -{ - int i; - CVector min, max; - CVector verts[8]; - CVector c; - float r; - - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); - - min = colModel.boundingBox.min; - max = colModel.boundingBox.max; - - verts[0] = mat * CVector(min.x, min.y, min.z); - verts[1] = mat * CVector(min.x, min.y, max.z); - verts[2] = mat * CVector(min.x, max.y, min.z); - verts[3] = mat * CVector(min.x, max.y, max.z); - verts[4] = mat * CVector(max.x, min.y, min.z); - verts[5] = mat * CVector(max.x, min.y, max.z); - verts[6] = mat * CVector(max.x, max.y, min.z); - verts[7] = mat * CVector(max.x, max.y, max.z); - - CLines::RenderLineWithClipping( - verts[0].x, verts[0].y, verts[0].z, - verts[1].x, verts[1].y, verts[1].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[1].x, verts[1].y, verts[1].z, - verts[3].x, verts[3].y, verts[3].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[3].x, verts[3].y, verts[3].z, - verts[2].x, verts[2].y, verts[2].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[2].x, verts[2].y, verts[2].z, - verts[0].x, verts[0].y, verts[0].z, - 0xFF0000FF, 0xFF0000FF); - - CLines::RenderLineWithClipping( - verts[4].x, verts[4].y, verts[4].z, - verts[5].x, verts[5].y, verts[5].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[5].x, verts[5].y, verts[5].z, - verts[7].x, verts[7].y, verts[7].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[7].x, verts[7].y, verts[7].z, - verts[6].x, verts[6].y, verts[6].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[6].x, verts[6].y, verts[6].z, - verts[4].x, verts[4].y, verts[4].z, - 0xFF0000FF, 0xFF0000FF); - - CLines::RenderLineWithClipping( - verts[0].x, verts[0].y, verts[0].z, - verts[4].x, verts[4].y, verts[4].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[1].x, verts[1].y, verts[1].z, - verts[5].x, verts[5].y, verts[5].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[2].x, verts[2].y, verts[2].z, - verts[6].x, verts[6].y, verts[6].z, - 0xFF0000FF, 0xFF0000FF); - CLines::RenderLineWithClipping( - verts[3].x, verts[3].y, verts[3].z, - verts[7].x, verts[7].y, verts[7].z, - 0xFF0000FF, 0xFF0000FF); - - for(i = 0; i < colModel.numSpheres; i++){ - c = mat * colModel.spheres[i].center; - r = colModel.spheres[i].radius; - - CLines::RenderLineWithClipping( - c.x, c.y, c.z-r, - c.x-r, c.y-r, c.z, - 0xFF00FFFF, 0xFF00FFFF); - CLines::RenderLineWithClipping( - c.x, c.y, c.z-r, - c.x-r, c.y+r, c.z, - 0xFF00FFFF, 0xFF00FFFF); - CLines::RenderLineWithClipping( - c.x, c.y, c.z-r, - c.x+r, c.y-r, c.z, - 0xFF00FFFF, 0xFF00FFFF); - CLines::RenderLineWithClipping( - c.x, c.y, c.z-r, - c.x+r, c.y+r, c.z, - 0xFF00FFFF, 0xFF00FFFF); - CLines::RenderLineWithClipping( - c.x-r, c.y-r, c.z, - c.x, c.y, c.z+r, - 0xFF00FFFF, 0xFF00FFFF); - CLines::RenderLineWithClipping( - c.x-r, c.y+r, c.z, - c.x, c.y, c.z+r, - 0xFF00FFFF, 0xFF00FFFF); - CLines::RenderLineWithClipping( - c.x+r, c.y-r, c.z, - c.x, c.y, c.z+r, - 0xFF00FFFF, 0xFF00FFFF); - CLines::RenderLineWithClipping( - c.x+r, c.y+r, c.z, - c.x, c.y, c.z+r, - 0xFF00FFFF, 0xFF00FFFF); - } - - for(i = 0; i < colModel.numLines; i++){ - verts[0] = colModel.lines[i].p0; - verts[1] = colModel.lines[i].p1; - - verts[0] = mat * verts[0]; - verts[1] = mat * verts[1]; - - CLines::RenderLineWithClipping( - verts[0].x, verts[0].y, verts[0].z, - verts[1].x, verts[1].y, verts[1].z, - 0x00FFFFFF, 0x00FFFFFF); - } - - for(i = 0; i < colModel.numBoxes; i++){ - min = colModel.boxes[i].min; - max = colModel.boxes[i].max; - - verts[0] = mat * CVector(min.x, min.y, min.z); - verts[1] = mat * CVector(min.x, min.y, max.z); - verts[2] = mat * CVector(min.x, max.y, min.z); - verts[3] = mat * CVector(min.x, max.y, max.z); - verts[4] = mat * CVector(max.x, min.y, min.z); - verts[5] = mat * CVector(max.x, min.y, max.z); - verts[6] = mat * CVector(max.x, max.y, min.z); - verts[7] = mat * CVector(max.x, max.y, max.z); - - CLines::RenderLineWithClipping( - verts[0].x, verts[0].y, verts[0].z, - verts[1].x, verts[1].y, verts[1].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[1].x, verts[1].y, verts[1].z, - verts[3].x, verts[3].y, verts[3].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[3].x, verts[3].y, verts[3].z, - verts[2].x, verts[2].y, verts[2].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[2].x, verts[2].y, verts[2].z, - verts[0].x, verts[0].y, verts[0].z, - 0xFFFFFFFF, 0xFFFFFFFF); - - CLines::RenderLineWithClipping( - verts[4].x, verts[4].y, verts[4].z, - verts[5].x, verts[5].y, verts[5].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[5].x, verts[5].y, verts[5].z, - verts[7].x, verts[7].y, verts[7].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[7].x, verts[7].y, verts[7].z, - verts[6].x, verts[6].y, verts[6].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[6].x, verts[6].y, verts[6].z, - verts[4].x, verts[4].y, verts[4].z, - 0xFFFFFFFF, 0xFFFFFFFF); - - CLines::RenderLineWithClipping( - verts[0].x, verts[0].y, verts[0].z, - verts[4].x, verts[4].y, verts[4].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[1].x, verts[1].y, verts[1].z, - verts[5].x, verts[5].y, verts[5].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[2].x, verts[2].y, verts[2].z, - verts[6].x, verts[6].y, verts[6].z, - 0xFFFFFFFF, 0xFFFFFFFF); - CLines::RenderLineWithClipping( - verts[3].x, verts[3].y, verts[3].z, - verts[7].x, verts[7].y, verts[7].z, - 0xFFFFFFFF, 0xFFFFFFFF); - } - - for(i = 0; i < colModel.numTriangles; i++){ - colModel.GetTrianglePoint(verts[0], colModel.triangles[i].a); - colModel.GetTrianglePoint(verts[1], colModel.triangles[i].b); - colModel.GetTrianglePoint(verts[2], colModel.triangles[i].c); - verts[0] = mat * verts[0]; - verts[1] = mat * verts[1]; - verts[2] = mat * verts[2]; - CLines::RenderLineWithClipping( - verts[0].x, verts[0].y, verts[0].z, - verts[1].x, verts[1].y, verts[1].z, - 0x00FF00FF, 0x00FF00FF); - CLines::RenderLineWithClipping( - verts[0].x, verts[0].y, verts[0].z, - verts[2].x, verts[2].y, verts[2].z, - 0x00FF00FF, 0x00FF00FF); - CLines::RenderLineWithClipping( - verts[1].x, verts[1].y, verts[1].z, - verts[2].x, verts[2].y, verts[2].z, - 0x00FF00FF, 0x00FF00FF); - } - - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); -} - -void -CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id) -{ - int i; - int s; - float f; - CVector verts[8]; - CVector min, max; - int r, g, b; - RwImVertexIndex *iptr; - RwIm3DVertex *vptr; - - RenderBuffer::ClearRenderBuffer(); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); - - for(i = 0; i < colModel.numTriangles; i++){ - colModel.GetTrianglePoint(verts[0], colModel.triangles[i].a); - colModel.GetTrianglePoint(verts[1], colModel.triangles[i].b); - colModel.GetTrianglePoint(verts[2], colModel.triangles[i].c); - verts[0] = mat * verts[0]; - verts[1] = mat * verts[1]; - verts[2] = mat * verts[2]; - - // game doesn't do this - r = 255; - g = 128; - b = 0; - - s = colModel.triangles[i].surface; - f = (s & 0xF)/32.0f + 0.5f; - switch(CSurfaceTable::GetAdhesionGroup(s)){ - case ADHESIVE_RUBBER: - r = f * 255.0f; - g = 0; - b = 0; - break; - case ADHESIVE_HARD: - r = f*255.0f; - g = f*255.0f; - b = f*128.0f; - break; - case ADHESIVE_ROAD: - r = f*128.0f; - g = f*128.0f; - b = f*128.0f; - break; - case ADHESIVE_LOOSE: - r = 0; - g = f * 255.0f; - b = 0; - break; - case ADHESIVE_WET: - r = 0; - g = 0; - b = f * 255.0f; - break; - default: - // this doesn't make much sense - r *= f; - g *= f; - b *= f; - } - - if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || - s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) - if(CTimer::GetFrameCounter() & 1){ - r = 0; - g = 0; - b = 0; - } - - if(s > SURFACE_METAL_GATE){ - r = CGeneral::GetRandomNumber(); - g = CGeneral::GetRandomNumber(); - b = CGeneral::GetRandomNumber(); - printf("Illegal surfacetype:%d on MI:%d\n", s, id); - } - - RenderBuffer::StartStoring(6, 3, &iptr, &vptr); - RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255); - RwIm3DVertexSetU(&vptr[0], 0.0f); - RwIm3DVertexSetV(&vptr[0], 0.0f); - RwIm3DVertexSetU(&vptr[1], 0.0f); - RwIm3DVertexSetV(&vptr[1], 1.0f); - RwIm3DVertexSetU(&vptr[2], 1.0f); - RwIm3DVertexSetV(&vptr[2], 1.0f); - RwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z); - RwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z); - RwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z); - iptr[0] = 0; iptr[1] = 1; iptr[2] = 2; - iptr[3] = 0; iptr[4] = 2; iptr[5] = 1; - RenderBuffer::StopStoring(); - } - - for(i = 0; i < colModel.numBoxes; i++){ - min = colModel.boxes[i].min; - max = colModel.boxes[i].max; - - verts[0] = mat * CVector(min.x, min.y, min.z); - verts[1] = mat * CVector(min.x, min.y, max.z); - verts[2] = mat * CVector(min.x, max.y, min.z); - verts[3] = mat * CVector(min.x, max.y, max.z); - verts[4] = mat * CVector(max.x, min.y, min.z); - verts[5] = mat * CVector(max.x, min.y, max.z); - verts[6] = mat * CVector(max.x, max.y, min.z); - verts[7] = mat * CVector(max.x, max.y, max.z); - - s = colModel.boxes[i].surface; - f = (s & 0xF)/32.0f + 0.5f; - switch(CSurfaceTable::GetAdhesionGroup(s)){ - case ADHESIVE_RUBBER: - r = f * 255.0f; - g = 0; - b = 0; - break; - case ADHESIVE_HARD: - r = f*255.0f; - g = f*255.0f; - b = f*128.0f; - break; - case ADHESIVE_ROAD: - r = f*128.0f; - g = f*128.0f; - b = f*128.0f; - break; - case ADHESIVE_LOOSE: - r = 0; - g = f * 255.0f; - b = 0; - break; - case ADHESIVE_WET: - r = 0; - g = 0; - b = f * 255.0f; - break; - default: - // this doesn't make much sense - r *= f; - g *= f; - b *= f; - } - - if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || - s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) - if(CTimer::GetFrameCounter() & 1){ - r = 0; - g = 0; - b = 0; - } - - RenderBuffer::StartStoring(36, 8, &iptr, &vptr); - RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[3], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[4], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[5], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[6], r, g, b, 255); - RwIm3DVertexSetRGBA(&vptr[7], r, g, b, 255); - RwIm3DVertexSetU(&vptr[0], 0.0f); - RwIm3DVertexSetV(&vptr[0], 0.0f); - RwIm3DVertexSetU(&vptr[1], 0.0f); - RwIm3DVertexSetV(&vptr[1], 1.0f); - RwIm3DVertexSetU(&vptr[2], 1.0f); - RwIm3DVertexSetV(&vptr[2], 1.0f); - RwIm3DVertexSetU(&vptr[3], 0.0f); - RwIm3DVertexSetV(&vptr[3], 0.0f); - RwIm3DVertexSetU(&vptr[4], 0.0f); - RwIm3DVertexSetV(&vptr[4], 1.0f); - RwIm3DVertexSetU(&vptr[5], 1.0f); - RwIm3DVertexSetV(&vptr[5], 1.0f); - RwIm3DVertexSetU(&vptr[6], 0.0f); - RwIm3DVertexSetV(&vptr[6], 1.0f); - RwIm3DVertexSetU(&vptr[7], 1.0f); - RwIm3DVertexSetV(&vptr[7], 1.0f); - RwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z); - RwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z); - RwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z); - RwIm3DVertexSetPos(&vptr[3], verts[3].x, verts[3].y, verts[3].z); - RwIm3DVertexSetPos(&vptr[4], verts[4].x, verts[4].y, verts[4].z); - RwIm3DVertexSetPos(&vptr[5], verts[5].x, verts[5].y, verts[5].z); - RwIm3DVertexSetPos(&vptr[6], verts[6].x, verts[6].y, verts[6].z); - RwIm3DVertexSetPos(&vptr[7], verts[7].x, verts[7].y, verts[7].z); - iptr[0] = 0; iptr[1] = 1; iptr[2] = 2; - iptr[3] = 1; iptr[4] = 3; iptr[5] = 2; - iptr[6] = 1; iptr[7] = 5; iptr[8] = 7; - iptr[9] = 1; iptr[10] = 7; iptr[11] = 3; - iptr[12] = 2; iptr[13] = 3; iptr[14] = 7; - iptr[15] = 2; iptr[16] = 7; iptr[17] = 6; - iptr[18] = 0; iptr[19] = 5; iptr[20] = 1; - iptr[21] = 0; iptr[22] = 4; iptr[23] = 5; - iptr[24] = 0; iptr[25] = 2; iptr[26] = 4; - iptr[27] = 2; iptr[28] = 6; iptr[29] = 4; - iptr[30] = 4; iptr[31] = 6; iptr[32] = 7; - iptr[33] = 4; iptr[34] = 7; iptr[35] = 5; - RenderBuffer::StopStoring(); - } - - RenderBuffer::RenderStuffInBuffer(); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); -} - - -/* - * ColModel code - */ - -void -CColSphere::Set(float radius, const CVector ¢er, uint8 surf, uint8 piece) -{ - this->radius = radius; - this->center = center; - this->surface = surf; - this->piece = piece; -} - -void -CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece) -{ - this->min = min; - this->max = max; - this->surface = surf; - this->piece = piece; -} - -void -CColLine::Set(const CVector &p0, const CVector &p1) -{ - this->p0 = p0; - this->p1 = p1; -} - -void -CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece) -{ - this->a = a; - this->b = b; - this->c = c; - this->surface = surf; -} - -#ifdef VU_COLLISION -void -CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc) -{ - CVector norm = CrossProduct(vc-va, vb-va); - norm.Normalise(); - float d = DotProduct(norm, va); - normal.x = norm.x*4096.0f; - normal.y = norm.y*4096.0f; - normal.z = norm.z*4096.0f; - dist = d*128.0f; -} -#else -void -CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc) -{ - normal = CrossProduct(vc-va, vb-va); - normal.Normalise(); - dist = DotProduct(normal, va); - CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z)); - // find out largest component and its direction - if(an.x > an.y && an.x > an.z) - dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS; - else if(an.y > an.z) - dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS; - else - dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS; -} -#endif - -CColModel::CColModel(void) -{ - numSpheres = 0; - spheres = nil; - numLines = 0; - lines = nil; - numBoxes = 0; - boxes = nil; - numTriangles = 0; - vertices = nil; - triangles = nil; - trianglePlanes = nil; - level = CGame::currLevel; - ownsCollisionVolumes = true; -} - -CColModel::~CColModel(void) -{ - RemoveCollisionVolumes(); - RemoveTrianglePlanes(); -} - -void -CColModel::RemoveCollisionVolumes(void) -{ - if(ownsCollisionVolumes){ - RwFree(spheres); - RwFree(lines); - RwFree(boxes); - RwFree(vertices); - RwFree(triangles); - } - numSpheres = 0; - numLines = 0; - numBoxes = 0; - numTriangles = 0; - spheres = nil; - lines = nil; - boxes = nil; - vertices = nil; - triangles = nil; -} - -void -CColModel::CalculateTrianglePlanes(void) -{ - // HACK: allocate space for one more element to stuff the link pointer into - trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1)); - for(int i = 0; i < numTriangles; i++) - trianglePlanes[i].Set(vertices, triangles[i]); -} - -void -CColModel::RemoveTrianglePlanes(void) -{ - RwFree(trianglePlanes); - trianglePlanes = nil; -} - -void -CColModel::SetLinkPtr(CLink *lptr) -{ - assert(trianglePlanes); - *(CLink**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr; -} - -CLink* -CColModel::GetLinkPtr(void) -{ - assert(trianglePlanes); - return *(CLink**)ALIGNPTR(&trianglePlanes[numTriangles]); -} - -void -CColModel::GetTrianglePoint(CVector &v, int i) const -{ - v = vertices[i].Get(); -} - -CColModel& -CColModel::operator=(const CColModel &other) -{ - int i; - int numVerts; - - boundingSphere = other.boundingSphere; - boundingBox = other.boundingBox; - - // copy spheres - if(other.numSpheres){ - if(numSpheres != other.numSpheres){ - numSpheres = other.numSpheres; - if(spheres) - RwFree(spheres); - spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere)); - } - for(i = 0; i < numSpheres; i++) - spheres[i] = other.spheres[i]; - }else{ - numSpheres = 0; - if(spheres) - RwFree(spheres); - spheres = nil; - } - - // copy lines - if(other.numLines){ - if(numLines != other.numLines){ - numLines = other.numLines; - if(lines) - RwFree(lines); - lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine)); - } - for(i = 0; i < numLines; i++) - lines[i] = other.lines[i]; - }else{ - numLines = 0; - if(lines) - RwFree(lines); - lines = nil; - } - - // copy boxes - if(other.numBoxes){ - if(numBoxes != other.numBoxes){ - numBoxes = other.numBoxes; - if(boxes) - RwFree(boxes); - boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox)); - } - for(i = 0; i < numBoxes; i++) - boxes[i] = other.boxes[i]; - }else{ - numBoxes = 0; - if(boxes) - RwFree(boxes); - boxes = nil; - } - - // copy mesh - if(other.numTriangles){ - // copy vertices - numVerts = 0; - for(i = 0; i < other.numTriangles; i++){ - if(other.triangles[i].a > numVerts) - numVerts = other.triangles[i].a; - if(other.triangles[i].b > numVerts) - numVerts = other.triangles[i].b; - if(other.triangles[i].c > numVerts) - numVerts = other.triangles[i].c; - } - numVerts++; - if(vertices) - RwFree(vertices); - if(numVerts){ - vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector)); - for(i = 0; i < numVerts; i++) - vertices[i] = other.vertices[i]; - } - - // copy triangles - if(numTriangles != other.numTriangles){ - numTriangles = other.numTriangles; - if(triangles) - RwFree(triangles); - triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle)); - } - for(i = 0; i < numTriangles; i++) - triangles[i] = other.triangles[i]; - }else{ - numTriangles = 0; - if(triangles) - RwFree(triangles); - triangles = nil; - if(vertices) - RwFree(vertices); - vertices = nil; - } - return *this; -} diff --git a/src/core/Collision.h b/src/core/Collision.h deleted file mode 100644 index da94dd34..00000000 --- a/src/core/Collision.h +++ /dev/null @@ -1,254 +0,0 @@ -#pragma once - -#include "templates.h" -#include "Game.h" // for eLevelName -#ifdef VU_COLLISION -#include "VuVector.h" -#endif - -// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32. -#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE) -#define MAX_COLLISION_POINTS 64 -#else -#define MAX_COLLISION_POINTS 32 -#endif - -struct CompressedVector -{ -#ifdef COMPRESSED_COL_VECTORS - int16 x, y, z; - CVector Get(void) const { return CVector(x, y, z)/128.0f; }; - void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; }; -#ifdef GTA_PS2 - void Unpack(uint128 &qword) const { - __asm__ volatile ( - "lh $8, 0(%1)\n" - "lh $9, 2(%1)\n" - "lh $10, 4(%1)\n" - "pextlw $10, $8\n" - "pextlw $2, $9, $10\n" - "sq $2, %0\n" - : "=m" (qword) - : "r" (this) - : "$8", "$9", "$10", "$2" - ); - } -#else - void Unpack(int32 *qword) const { - qword[0] = x; - qword[1] = y; - qword[2] = z; - qword[3] = 0; // junk - } -#endif -#else - float x, y, z; - CVector Get(void) const { return CVector(x, y, z); }; - void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; }; -#endif -}; - -struct CColSphere -{ - // NB: this has to be compatible with a CVuVector - CVector center; - float radius; - uint8 surface; - uint8 piece; - - void Set(float radius, const CVector ¢er, uint8 surf, uint8 piece); - void Set(float radius, const CVector ¢er) { this->center = center; this->radius = radius; } -}; - -struct CColBox -{ - CVector min; - CVector max; - uint8 surface; - uint8 piece; - - void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece); - CVector GetSize(void) { return max - min; } -}; - -struct CColLine -{ - // NB: this has to be compatible with two CVuVectors - CVector p0; - int pad0; - CVector p1; - int pad1; - - CColLine(void) { }; - CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; }; - void Set(const CVector &p0, const CVector &p1); -}; - -struct CColTriangle -{ - uint16 a; - uint16 b; - uint16 c; - uint8 surface; - - void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece); -}; - -struct CColTrianglePlane -{ -#ifdef VU_COLLISION - CompressedVector normal; - int16 dist; - - void Set(const CVector &va, const CVector &vb, const CVector &vc); - void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); } - void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; } - float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; }; -#ifdef GTA_PS2 - void Unpack(uint128 &qword) const { - __asm__ volatile ( - "lh $8, 0(%1)\n" - "lh $9, 2(%1)\n" - "lh $10, 4(%1)\n" - "lh $11, 6(%1)\n" - "pextlw $10, $8\n" - "pextlw $11, $9\n" - "pextlw $2, $11, $10\n" - "sq $2, %0\n" - : "=m" (qword) - : "r" (this) - : "$8", "$9", "$10", "$11", "$2" - ); - } -#else - void Unpack(int32 *qword) const { - qword[0] = normal.x; - qword[1] = normal.y; - qword[2] = normal.z; - qword[3] = dist; - } -#endif -#else - CVector normal; - float dist; - uint8 dir; - - void Set(const CVector &va, const CVector &vb, const CVector &vc); - void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); } - void GetNormal(CVector &n) const { n = normal; } - float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; }; -#endif -}; - -struct CColPoint -{ - CVector point; - int pad1; - // the surface normal on the surface of point - CVector normal; - int pad2; - uint8 surfaceA; - uint8 pieceA; - uint8 surfaceB; - uint8 pieceB; - float depth; - - void Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) { - this->depth = depth; - this->surfaceA = surfA; - this->pieceA = pieceA; - this->surfaceB = surfB; - this->pieceB = pieceB; - } - void Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) { - this->surfaceA = surfA; - this->pieceA = pieceA; - this->surfaceB = surfB; - this->pieceB = pieceB; - } -}; - -struct CStoredCollPoly -{ -#ifdef VU_COLLISION - CVuVector verts[3]; -#else - CVector verts[3]; -#endif - bool valid; -}; - -struct CColModel -{ - CColSphere boundingSphere; - CColBox boundingBox; - int16 numSpheres; - int16 numLines; - int16 numBoxes; - int16 numTriangles; - int32 level; - bool ownsCollisionVolumes; // missing on PS2 - CColSphere *spheres; - CColLine *lines; - CColBox *boxes; - CompressedVector *vertices; - CColTriangle *triangles; - CColTrianglePlane *trianglePlanes; - - CColModel(void); - ~CColModel(void); - void RemoveCollisionVolumes(void); - void CalculateTrianglePlanes(void); - void RemoveTrianglePlanes(void); - CLink *GetLinkPtr(void); - void SetLinkPtr(CLink*); - void GetTrianglePoint(CVector &v, int i) const; - - CColModel& operator=(const CColModel& other); -}; - -class CCollision -{ -public: - static eLevelName ms_collisionInMemory; - static CLinkList ms_colModelCache; -#ifdef NO_ISLAND_LOADING - static bool bAlreadyLoaded; -#endif - - static void Init(void); - static void Shutdown(void); - static void Update(void); - static void LoadCollisionWhenINeedIt(bool changeLevel); - static void SortOutCollisionAfterLoad(void); - static void LoadCollisionScreen(eLevelName level); - static void DrawColModel(const CMatrix &mat, const CColModel &colModel); - static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id); - - static void CalculateTrianglePlanes(CColModel *model); - - // all these return true if there's a collision - static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2); - static bool TestSphereBox(const CColSphere &sph, const CColBox &box); - static bool TestLineBox(const CColLine &line, const CColBox &box); - static bool TestVerticalLineBox(const CColLine &line, const CColBox &box); - static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); - static bool TestLineSphere(const CColLine &line, const CColSphere &sph); - static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); - static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough); - - static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq); - static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq); - static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist); - static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly); - static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist); - static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist); - static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq); - static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough); - static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly); - static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists); - static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly); - - static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point); - static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest); -}; diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp deleted file mode 100644 index f6796909..00000000 --- a/src/core/TempColModels.cpp +++ /dev/null @@ -1,297 +0,0 @@ -#include "common.h" - -#include "TempColModels.h" -#include "SurfaceTable.h" - -CColModel CTempColModels::ms_colModelPed1; -CColModel CTempColModels::ms_colModelPed2; -CColModel CTempColModels::ms_colModelBBox; -CColModel CTempColModels::ms_colModelBumper1; -CColModel CTempColModels::ms_colModelWheel1; -CColModel CTempColModels::ms_colModelPanel1; -CColModel CTempColModels::ms_colModelBodyPart2; -CColModel CTempColModels::ms_colModelBodyPart1; -CColModel CTempColModels::ms_colModelCutObj[5]; -CColModel CTempColModels::ms_colModelPedGroundHit; -CColModel CTempColModels::ms_colModelBoot1; -CColModel CTempColModels::ms_colModelDoor1; -CColModel CTempColModels::ms_colModelBonnet1; - - -CColSphere s_aPedSpheres[3]; -CColSphere s_aPed2Spheres[3]; -CColSphere s_aPedGSpheres[4]; -#ifdef FIX_BUGS -CColSphere s_aDoorSpheres[3]; -#else -CColSphere s_aDoorSpheres[4]; -#endif -CColSphere s_aBumperSpheres[4]; -CColSphere s_aPanelSpheres[4]; -CColSphere s_aBonnetSpheres[4]; -CColSphere s_aBootSpheres[4]; -CColSphere s_aWheelSpheres[2]; -CColSphere s_aBodyPartSpheres1[2]; -CColSphere s_aBodyPartSpheres2[2]; - -void -CTempColModels::Initialise(void) -{ -#define SET_COLMODEL_SPHERES(colmodel, sphrs)\ - colmodel.numSpheres = ARRAY_SIZE(sphrs);\ - colmodel.spheres = sphrs;\ - colmodel.level = LEVEL_GENERIC;\ - colmodel.ownsCollisionVolumes = false;\ - - int i; - - ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); - ms_colModelBBox.level = LEVEL_GENERIC; - - for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) { - ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); - ms_colModelCutObj[i].level = LEVEL_GENERIC; - } - - // Ped Spheres - - for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) - s_aPedSpheres[i].radius = 0.35f; - - s_aPedSpheres[0].center = CVector(0.0f, 0.0f, -0.25f); - s_aPedSpheres[1].center = CVector(0.0f, 0.0f, 0.15f); - s_aPedSpheres[2].center = CVector(0.0f, 0.0f, 0.55f); - -#ifdef FIX_BUGS - for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) { -#else - for (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) { -#endif - s_aPedSpheres[i].surface = SURFACE_PED; - s_aPedSpheres[i].piece = 0; - } - - ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f), SURFACE_DEFAULT, 0); - SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres); - - // Ped 2 Spheres - - s_aPed2Spheres[0].radius = 0.3f; - s_aPed2Spheres[1].radius = 0.4f; - s_aPed2Spheres[2].radius = 0.3f; - - s_aPed2Spheres[0].center = CVector(0.0f, 0.35f, -0.9f); - s_aPed2Spheres[1].center = CVector(0.0f, 0.0f, -0.9f); - s_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f); - - for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { - s_aPed2Spheres[i].surface = SURFACE_PED; - s_aPed2Spheres[i].piece = 0; - } - - ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres); - - // Ped ground collision - - s_aPedGSpheres[0].radius = 0.35f; - s_aPedGSpheres[1].radius = 0.35f; - s_aPedGSpheres[2].radius = 0.35f; - s_aPedGSpheres[3].radius = 0.3f; - - s_aPedGSpheres[0].center = CVector(0.0f, -0.4f, -0.9f); - s_aPedGSpheres[1].center = CVector(0.0f, -0.1f, -0.9f); - s_aPedGSpheres[2].center = CVector(0.0f, 0.25f, -0.9f); - s_aPedGSpheres[3].center = CVector(0.0f, 0.65f, -0.9f); - - s_aPedGSpheres[0].surface = SURFACE_PED; - s_aPedGSpheres[1].surface = SURFACE_PED; - s_aPedGSpheres[2].surface = SURFACE_PED; - s_aPedGSpheres[3].surface = SURFACE_PED; - s_aPedGSpheres[0].piece = 4; - s_aPedGSpheres[1].piece = 1; - s_aPedGSpheres[2].piece = 0; - s_aPedGSpheres[3].piece = 6; - - ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres); - - // Door Spheres - - s_aDoorSpheres[0].radius = 0.15f; - s_aDoorSpheres[1].radius = 0.15f; - s_aDoorSpheres[2].radius = 0.25f; - - s_aDoorSpheres[0].center = CVector(0.0f, -0.25f, -0.35f); - s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f); - s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f); - -#ifdef FIX_BUGS - for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) { -#else - for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { -#endif - s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL; - s_aDoorSpheres[i].piece = 0; - } - - ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres); - - // Bumper Spheres - - for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) - s_aBumperSpheres[i].radius = 0.15f; - - s_aBumperSpheres[0].center = CVector(0.85f, -0.05f, 0.0f); - s_aBumperSpheres[1].center = CVector(0.4f, 0.05f, 0.0f); - s_aBumperSpheres[2].center = CVector(-0.4f, 0.05f, 0.0f); - s_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f); - - for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) { - s_aBumperSpheres[i].surface = SURFACE_CAR_PANEL; - s_aBumperSpheres[i].piece = 0; - } - - ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres); - - // Panel Spheres - - for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) - s_aPanelSpheres[i].radius = 0.15f; - - s_aPanelSpheres[0].center = CVector(0.15f, 0.45f, 0.0f); - s_aPanelSpheres[1].center = CVector(0.15f, -0.45f, 0.0f); - s_aPanelSpheres[2].center = CVector(-0.15f, -0.45f, 0.0f); - s_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f); - - for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) { - s_aPanelSpheres[i].surface = SURFACE_CAR_PANEL; - s_aPanelSpheres[i].piece = 0; - } - - ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres); - - // Bonnet Spheres - - for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) - s_aBonnetSpheres[i].radius = 0.2f; - - s_aBonnetSpheres[0].center = CVector(-0.4f, 0.1f, 0.0f); - s_aBonnetSpheres[1].center = CVector(-0.4f, 0.9f, 0.0f); - s_aBonnetSpheres[2].center = CVector(0.4f, 0.1f, 0.0f); - s_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f); - - for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) { - s_aBonnetSpheres[i].surface = SURFACE_CAR_PANEL; - s_aBonnetSpheres[i].piece = 0; - } - - ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres); - - // Boot Spheres - - for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) - s_aBootSpheres[i].radius = 0.2f; - - s_aBootSpheres[0].center = CVector(-0.4f, -0.1f, 0.0f); - s_aBootSpheres[1].center = CVector(-0.4f, -0.6f, 0.0f); - s_aBootSpheres[2].center = CVector(0.4f, -0.1f, 0.0f); - s_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f); - - for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { - s_aBootSpheres[i].surface = SURFACE_CAR_PANEL; - s_aBootSpheres[i].piece = 0; - } - - ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres); - - // Wheel Spheres - - s_aWheelSpheres[0].radius = 0.35f; - s_aWheelSpheres[1].radius = 0.35f; - - s_aWheelSpheres[0].center = CVector(-0.3f, 0.0f, 0.0f); - s_aWheelSpheres[1].center = CVector(0.3f, 0.0f, 0.0f); - -#ifdef FIX_BUGS - for (i = 0; i < ARRAY_SIZE(s_aWheelSpheres); i++) { -#else - for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { -#endif - s_aWheelSpheres[i].surface = SURFACE_WHEELBASE; - s_aWheelSpheres[i].piece = 0; - } - - ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres); - - // Body Part Spheres 1 - - s_aBodyPartSpheres1[0].radius = 0.2f; - s_aBodyPartSpheres1[1].radius = 0.2f; - - s_aBodyPartSpheres1[0].center = CVector(0.0f, 0.0f, 0.0f); - s_aBodyPartSpheres1[1].center = CVector(0.8f, 0.0f, 0.0f); - -#ifdef FIX_BUGS - for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres1); i++) { -#else - for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { -#endif - s_aBodyPartSpheres1[i].surface = SURFACE_PED; - s_aBodyPartSpheres1[i].piece = 0; - } - - ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1); - - // Body Part Spheres 2 - - s_aBodyPartSpheres2[0].radius = 0.15f; - s_aBodyPartSpheres2[1].radius = 0.15f; - - s_aBodyPartSpheres2[0].center = CVector(0.0f, 0.0f, 0.0f); - s_aBodyPartSpheres2[1].center = CVector(0.5f, 0.0f, 0.0f); - -#ifdef FIX_BUGS - for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres2); i++) { -#else - for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { -#endif - s_aBodyPartSpheres2[i].surface = SURFACE_PED; - s_aBodyPartSpheres2[i].piece = 0; - } - - ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f), SURFACE_DEFAULT, 0); - - SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2); - -#undef SET_COLMODEL_SPHERES -} diff --git a/src/core/TempColModels.h b/src/core/TempColModels.h deleted file mode 100644 index 3e1dd5e1..00000000 --- a/src/core/TempColModels.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "Collision.h" - -class CTempColModels -{ -public: - static CColModel ms_colModelPed1; - static CColModel ms_colModelPed2; - static CColModel ms_colModelBBox; - static CColModel ms_colModelBumper1; - static CColModel ms_colModelWheel1; - static CColModel ms_colModelPanel1; - static CColModel ms_colModelBodyPart2; - static CColModel ms_colModelBodyPart1; - static CColModel ms_colModelCutObj[5]; - static CColModel ms_colModelPedGroundHit; - static CColModel ms_colModelBoot1; - static CColModel ms_colModelDoor1; - static CColModel ms_colModelBonnet1; - - static void Initialise(void); -}; diff --git a/src/core/vu0Collision.dsm b/src/core/vu0Collision.dsm deleted file mode 100644 index 657c8b81..00000000 --- a/src/core/vu0Collision.dsm +++ /dev/null @@ -1,21 +0,0 @@ -.align 4 -.global Vu0CollisionDmaTag -Vu0CollisionDmaTag: -DMAcnt * -MPG 0, * -.vu -.include "vu0Collision_1.s" -.EndMPG -.EndDmaData -DMAend - -.global Vu0Collision2DmaTag -Vu0Collision2DmaTag: -DMAcnt * -MPG 0, * -.vu -.include "vu0Collision_2.s" -.EndMPG -.EndDmaData -DMAend -.end diff --git a/src/core/vu0Collision_1.s b/src/core/vu0Collision_1.s deleted file mode 100644 index 055c8640..00000000 --- a/src/core/vu0Collision_1.s +++ /dev/null @@ -1,610 +0,0 @@ -QuitAndFail: - NOP[E] IADDIU VI01, VI00, 0 - NOP NOP - - -QuitAndSucceed: - NOP[E] IADDIU VI01, VI00, 1 - NOP NOP - - -; 20 -- unused -; VF12, VF13 xyz: sphere centers -; VF14, VF15 x: sphere radii -; out: -; VI01: set when collision -; VF01: supposed to be intersection point? -; VF02: normal (pointing towards s1, not normalized) -.globl Vu0SphereToSphereCollision -Vu0SphereToSphereCollision: - SUB.xyz VF02, VF13, VF12 NOP ; dist of centers - ADD.x VF04, VF14, VF15 NOP ; s = sum of radii - MUL.xyzw VF03, VF02, VF02 NOP ; - MUL.x VF04, VF04, VF04 DIV Q, VF14x, VF04x ; square s - NOP NOP ; - NOP NOP ; - MULAx.w ACC, VF00, VF03 NOP ; - MADDAy.w ACC, VF00, VF03 NOP ; - MADDz.w VF03, VF00, VF03 NOP ; d = DistSq of centers - NOP NOP ; - MULAw.xyz ACC, VF12, VF00 NOP ; - MADDq.xyz VF01, VF02, Q NOP ; intersection, but wrong - CLIPw.xyz VF04, VF03 NOP ; compare s and d - SUB.xyz VF02, VF00, VF02 NOP ; compute normal - NOP NOP ; - NOP NOP ; - NOP FCAND VI01, 0x3 ; 0x2 cannot be set here - NOP[E] NOP ; - NOP NOP ; - - -; B8 -- unused -; VF12: -; VF13: radius -; VF14: -; VF15: box dimensions (?) -.globl Vu0SphereToAABBCollision -Vu0SphereToAABBCollision: - SUB.xyz VF03, VF12, VF14 LOI 0.5 - MULi.xyz VF15, VF15, I NOP - MUL.x VF13, VF13, VF13 NOP - SUB.xyz VF04, VF03, VF15 NOP - ADD.xyz VF05, VF03, VF15 MR32.xyzw VF16, VF15 - CLIPw.xyz VF03, VF16 MR32.xyzw VF17, VF16 - MUL.xyz VF04, VF04, VF04 NOP - MUL.xyz VF05, VF05, VF05 NOP - CLIPw.xyz VF03, VF17 MR32.xyzw VF16, VF17 - NOP FCAND VI01, 0x1 - MINI.xyz VF04, VF04, VF05 MFIR.x VF09, VI01 - NOP NOP - CLIPw.xyz VF03, VF16 FCAND VI01, 0x4 - NOP MFIR.y VF09, VI01 - NOP NOP - MULAx.w ACC, VF00, VF00 NOP - ADD.xyz VF01, VF00, VF03 FCAND VI01, 0x10 - NOP MFIR.z VF09, VI01 - NOP LOI 2 - NOP FCAND VI01, 0x30 - SUBAw.xyz ACC, VF00, VF00 IADD VI04, VI00, VI01 - ITOF0.xyz VF09, VF09 FCAND VI01, 0x300 - NOP IADD VI03, VI00, VI01 - NOP FCAND VI01, 0x3000 - NOP IADD VI02, VI00, VI01 - MADDi.xyzw VF09, VF09, I NOP - NOP IBEQ VI04, VI00, IgnoreZValue - NOP NOP - MADDAz.w ACC, VF00, VF04 NOP - MUL.z VF01, VF09, VF15 NOP -IgnoreZValue: - NOP IBEQ VI03, VI00, IgnoreYValue - NOP NOP - MADDAy.w ACC, VF00, VF04 NOP - MUL.y VF01, VF09, VF15 NOP -IgnoreYValue: - NOP IBEQ VI02, VI00, IgnoreXValue - NOP NOP - MADDAx.w ACC, VF00, VF04 NOP - MUL.x VF01, VF09, VF15 NOP -IgnoreXValue: - MADDx.w VF06, VF00, VF00 NOP - SUB.xyz VF02, VF03, VF01 NOP - ADD.xyz VF01, VF01, VF14 NOP - MULx.w VF01, VF00, VF00 NOP - CLIPw.xyz VF13, VF06 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x1 -QuitMicrocode: - NOP[E] NOP - NOP NOP - - -; 240 -.globl Vu0LineToSphereCollision -Vu0LineToSphereCollision: - SUB.xyzw VF01, VF13, VF12 NOP - SUB.xyzw VF02, VF14, VF12 NOP - MUL.xyz VF03, VF01, VF02 NOP - MUL.xyz VF04, VF01, VF01 NOP - MUL.x VF15, VF15, VF15 NOP - MUL.xyz VF02, VF02, VF02 NOP - MULAx.w ACC, VF00, VF03 NOP - MADDAy.w ACC, VF00, VF03 NOP - MADDz.w VF03, VF00, VF03 NOP - MULAx.w ACC, VF00, VF04 NOP - MADDAy.w ACC, VF00, VF04 NOP - MADDz.w VF01, VF00, VF04 NOP - MULAx.w ACC, VF00, VF02 NOP - MADDAy.w ACC, VF00, VF02 NOP - MADDz.w VF02, VF00, VF02 NOP - MULA.w ACC, VF03, VF03 NOP - MADDAx.w ACC, VF01, VF15 NOP - MSUB.w VF05, VF01, VF02 NOP - NOP NOP - NOP NOP - NOP IADDIU VI02, VI00, 0x10 - NOP FMAND VI01, VI02 - NOP IBNE VI01, VI00, QuitAndFail - NOP NOP - CLIPw.xyz VF15, VF02 SQRT Q, VF05w - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x1 - NOP IBNE VI00, VI01, LineStartInsideSphere - NOP NOP - SUBq.w VF05, VF03, Q NOP - SUB.w VF05, VF05, VF01 DIV Q, VF05w, VF01w - NOP FMAND VI01, VI02 - NOP IBNE VI01, VI00, QuitAndFail - NOP NOP - NOP FMAND VI01, VI02 - NOP IBEQ VI01, VI00, QuitAndFail - NOP NOP - ADDA.xyz ACC, VF12, VF00 NOP - MADDq.xyz VF01, VF01, Q NOP - MULx.w VF01, VF00, VF00 NOP - SUB.xyz VF02, VF01, VF14 NOP - NOP[E] NOP - NOP NOP -LineStartInsideSphere: - NOP MOVE.xyzw VF01, VF12 - NOP[E] IADDIU VI01, VI00, 0x1 - NOP NOP - - -; 3C0 -.globl Vu0LineToAABBCollision -Vu0LineToAABBCollision: - SUB.xyzw VF08, VF13, VF12 LOI 0.5 - MULi.xyz VF15, VF15, I IADDIU VI08, VI00, 0x0 - SUB.xyzw VF12, VF12, VF14 NOP - SUB.xyzw VF13, VF13, VF14 NOP - NOP DIV Q, VF00w, VF08x - NOP MR32.xyzw VF03, VF15 - SUB.xyz VF06, VF15, VF12 NOP - ADD.xyz VF07, VF15, VF12 NOP - NOP NOP - CLIPw.xyz VF12, VF03 MR32.xyzw VF04, VF03 - NOP NOP - ADDq.x VF09, VF00, Q DIV Q, VF00w, VF08y - NOP NOP - CLIPw.xyz VF12, VF04 MR32.xyzw VF05, VF04 - SUB.xyz VF07, VF00, VF07 IADDIU VI06, VI00, 0xCC - NOP IADDIU VI07, VI00, 0x30 - NOP NOP - CLIPw.xyz VF12, VF05 FCGET VI02 - NOP IAND VI02, VI02, VI06 - ADDq.y VF09, VF00, Q DIV Q, VF00w, VF08z - SUB.xyz VF10, VF00, VF10 NOP - CLIPw.xyz VF13, VF03 FCGET VI03 - CLIPw.xyz VF13, VF04 IAND VI03, VI03, VI07 - CLIPw.xyz VF13, VF05 FCAND VI01, 0x3330 - NOP IBEQ VI01, VI00, StartPointInsideAABB - NOP NOP - ADDq.z VF09, VF00, Q FCGET VI04 - NOP FCGET VI05 - NOP IAND VI04, VI04, VI06 - NOP IAND VI05, VI05, VI07 - MULx.xyz VF17, VF08, VF09 NOP - MULy.xyz VF18, VF08, VF09 IADDIU VI07, VI00, 0x80 - MULz.xyz VF19, VF08, VF09 IAND VI06, VI02, VI07 - MUL.w VF10, VF00, VF00 IAND VI07, VI04, VI07 - NOP NOP - NOP IBEQ VI06, VI07, CheckMaxXSide - NOP NOP - MULAx.xyz ACC, VF17, VF07 NOP - MADDw.xyz VF16, VF12, VF00 NOP - MUL.x VF10, VF07, VF09 NOP - CLIPw.xyz VF16, VF04 NOP - CLIPw.xyz VF16, VF05 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x330 - NOP IBNE VI01, VI00, CheckMaxXSide - NOP NOP - MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 - ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 - SUBw.x VF02, VF00, VF00 NOP -CheckMaxXSide: - MULAx.xyz ACC, VF17, VF06 IADDIU VI07, VI00, 0x40 - MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07 - MUL.x VF10, VF06, VF09 IAND VI07, VI04, VI07 - NOP NOP - NOP IBEQ VI06, VI07, CheckMinYSide - NOP NOP - CLIPw.xyz VF16, VF04 NOP - CLIPw.xyz VF16, VF05 NOP - CLIPw.xyz VF10, VF10 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0xCC03 - NOP IBNE VI01, VI00, CheckMinYSide - NOP NOP - MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 - ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 - ADDw.x VF02, VF00, VF00 NOP -CheckMinYSide: - MULAy.xyz ACC, VF18, VF07 IADDIU VI07, VI00, 0x8 - MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07 - MUL.y VF10, VF07, VF09 IAND VI07, VI04, VI07 - NOP NOP - NOP IBEQ VI06, VI07, CheckMaxYSide - NOP NOP - CLIPw.xyz VF16, VF03 NOP - CLIPw.xyz VF16, VF05 NOP - CLIPw.xyz VF10, VF10 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x3C0C - NOP IBNE VI01, VI00, CheckMaxYSide - NOP NOP - MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 - ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 - SUBw.y VF02, VF00, VF00 NOP -CheckMaxYSide: - MULAy.xyz ACC, VF18, VF06 IADDIU VI07, VI00, 0x4 - MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07 - MUL.y VF10, VF06, VF09 IAND VI07, VI04, VI07 - NOP NOP - NOP IBEQ VI06, VI07, CheckMinZSide - NOP NOP - CLIPw.xyz VF16, VF03 NOP - CLIPw.xyz VF16, VF05 NOP - CLIPw.xyz VF10, VF10 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x3C0C - NOP IBNE VI01, VI00, CheckMinZSide - NOP NOP - MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 - ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16 - ADDw.y VF02, VF00, VF00 NOP -CheckMinZSide: - MULAz.xyz ACC, VF19, VF07 IADDIU VI07, VI00, 0x20 - MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07 - MUL.z VF10, VF07, VF09 IAND VI07, VI05, VI07 - NOP NOP - NOP IBEQ VI06, VI07, CheckMaxZSide - NOP NOP - CLIPw.xyz VF16, VF03 NOP - CLIPw.xyz VF16, VF04 NOP - CLIPw.xyz VF10, VF10 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x3330 - NOP IBNE VI01, VI00, CheckMaxZSide - NOP NOP - MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 - ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16 - SUBw.z VF02, VF00, VF00 NOP -CheckMaxZSide: - MULAz.xyz ACC, VF19, VF06 IADDIU VI07, VI00, 0x10 - MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07 - MUL.z VF10, VF06, VF09 IAND VI07, VI05, VI07 - NOP NOP - NOP IBEQ VI06, VI07, DoneAllChecks - NOP NOP - CLIPw.xyz VF16, VF03 NOP - CLIPw.xyz VF16, VF04 NOP - CLIPw.xyz VF10, VF10 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x3330 - NOP IBNE VI01, VI00, DoneAllChecks - NOP NOP - MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1 - ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16 - ADDw.z VF02, VF00, VF00 NOP -DoneAllChecks: - ADD.xyz VF01, VF01, VF14 IADD VI01, VI00, VI08 - NOP[E] NOP - NOP NOP -StartPointInsideAABB: - ADD.xyz VF01, VF12, VF14 WAITQ - NOP IADDIU VI01, VI00, 0x1 - NOP[E] NOP - NOP NOP - - -; 860 -.globl Vu0LineToTriangleCollisionCompressedStart -Vu0LineToTriangleCollisionCompressedStart: - ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0 - ITOF0.xyzw VF14, VF14 NOP - ITOF0.xyzw VF15, VF15 NOP - ITOF0.xyzw VF16, VF16 NOP - MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0 - MULi.w VF17, VF17, I NOP - MULi.xyzw VF14, VF14, I NOP - MULi.xyzw VF15, VF15, I NOP - MULi.xyzw VF16, VF16, I NOP -; fall through - -; 8A8 -; VF12: point0 -; VF13: point1 -; VF14-16: verts -; VF17: plane -; out: -; VF01: intersection point -; VF02: triangle normal -; VF03 x: intersection parameter -.globl Vu0LineToTriangleCollisionStart -Vu0LineToTriangleCollisionStart: - MUL.xyz VF10, VF17, VF12 LOI 0.5 - MUL.xyz VF11, VF17, VF13 NOP - SUB.xyz VF02, VF13, VF12 NOP ; line dist - ADD.xyz VF17, VF17, VF00 NOP - MULi.w VF03, VF00, I NOP - MULAx.w ACC, VF00, VF10 NOP - MADDAy.w ACC, VF00, VF10 IADDIU VI06, VI00, 0xE0 - MADDz.w VF10, VF00, VF10 FMAND VI05, VI06 ; -- normal sign flags, unused - MULAx.w ACC, VF00, VF11 NOP - MADDAy.w ACC, VF00, VF11 NOP - MADDz.w VF11, VF00, VF11 NOP - SUB.w VF09, VF17, VF10 NOP ; plane-pos 0 - CLIPw.xyz VF17, VF03 NOP ; compare normal against 0.5 to figure out which in which dimension to compare - NOP IADDIU VI02, VI00, 0x10 ; Sw flag - SUBA.w ACC, VF17, VF11 NOP ; plane-pos 1 - SUB.w VF08, VF11, VF10 FMAND VI01, VI02 - NOP NOP - NOP NOP - NOP FMAND VI02, VI02 - NOP IBEQ VI01, VI02, QuitAndFail ; if on same side, no collision - NOP NOP - NOP DIV Q, VF09w, VF08w ; parameter of intersection - NOP FCAND VI01, 0x3 ; check x direction - NOP IADDIU VI02, VI01, 0x7F - NOP IADDIU VI06, VI00, 0x80 - NOP IAND VI02, VI02, VI06 ; Sx flag - NOP FCAND VI01, 0xC ; check y direction - NOP IADDIU VI03, VI01, 0x3F - MULAw.xyz ACC, VF12, VF00 IADDIU VI06, VI00, 0x40 - MADDq.xyz VF01, VF02, Q IAND VI03, VI03, VI06 ; point of intersection -- Sy flag - MULx.w VF01, VF00, VF00 FCAND VI01, 0x30 ; -- check z direction - ADDq.x VF03, VF00, Q IADDIU VI04, VI01, 0x1F ; output parameter - SUB.xyz VF05, VF15, VF14 IADDIU VI06, VI00, 0x20 ; edge vectors - SUB.xyz VF08, VF01, VF14 IAND VI04, VI04, VI06 ; edge vectors -- Sz flag - SUB.xyz VF06, VF16, VF15 IADD VI06, VI02, VI03 ; edge vectors - SUB.xyz VF09, VF01, VF15 IADD VI06, VI06, VI04 ; edge vectors -- combine flags - SUB.xyz VF07, VF14, VF16 NOP ; edge vectors - SUB.xyz VF10, VF01, VF16 NOP ; edge vectors - OPMULA.xyz ACC, VF08, VF05 NOP - OPMSUB.xyz VF18, VF05, VF08 NOP ; cross1 - OPMULA.xyz ACC, VF09, VF06 NOP - OPMSUB.xyz VF19, VF06, VF09 NOP ; cross2 - OPMULA.xyz ACC, VF10, VF07 NOP - OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; cross3 - NOP NOP - NOP FMAND VI03, VI06 - NOP NOP - NOP FMAND VI04, VI06 - NOP NOP - NOP IBNE VI03, VI02, QuitAndFail ; point has to lie on the same side of all edges (i.e. inside) - NOP NOP - NOP IBNE VI04, VI02, QuitAndFail - NOP NOP - MULw.xyz VF02, VF17, VF00 IADDIU VI01, VI00, 0x1 ; success - NOP[E] NOP - NOP NOP - - -; A68 -; VF12: center -; VF14: line origin -; VF15: line vector to other point -; out: VF16 xyz: nearest point on line; w: distance to that point -DistanceBetweenSphereAndLine: - SUB.xyz VF20, VF12, VF14 NOP - MUL.xyz VF21, VF15, VF15 NOP - ADDA.xyz ACC, VF14, VF15 NOP - MSUBw.xyz VF25, VF12, VF00 NOP ; VF25 = VF12 - (VF14+VF15) - MUL.xyz VF22, VF20, VF20 NOP - MUL.xyz VF23, VF20, VF15 NOP - MULAx.w ACC, VF00, VF21 NOP - MADDAy.w ACC, VF00, VF21 NOP - MADDz.w VF21, VF00, VF21 NOP ; MagSq VF15 (line length) - MULAx.w ACC, VF00, VF23 NOP - MADDAy.w ACC, VF00, VF23 NOP - MADDz.w VF23, VF00, VF23 NOP ; dot(VF12-VF14, VF15) - MULAx.w ACC, VF00, VF22 NOP - MADDAy.w ACC, VF00, VF22 NOP - MADDz.w VF22, VF00, VF22 IADDIU VI08, VI00, 0x10 ; MagSq VF12-VF14 -- Sw bit - MUL.xyz VF25, VF25, VF25 FMAND VI08, VI08 - NOP DIV Q, VF23w, VF21w - NOP IBNE VI00, VI08, NegativeRatio - NOP NOP - ADDA.xyz ACC, VF00, VF14 NOP - MADDq.xyz VF16, VF15, Q WAITQ ; nearest point on infinte line - ADDq.x VF24, VF00, Q NOP ; ratio - NOP NOP - NOP NOP - SUB.xyz VF26, VF16, VF12 NOP - CLIPw.xyz VF24, VF00 NOP ; compare ratio to 1.0 - NOP NOP - NOP NOP - MUL.xyz VF26, VF26, VF26 NOP - NOP FCAND VI01, 0x1 - NOP IBNE VI00, VI01, RatioGreaterThanOne - NOP NOP - MULAx.w ACC, VF00, VF26 NOP - MADDAy.w ACC, VF00, VF26 NOP - MADDz.w VF16, VF00, VF26 NOP ; distance - NOP JR VI15 - NOP NOP -NegativeRatio: - ADD.xyz VF16, VF00, VF14 NOP ; return line origin - MUL.w VF16, VF00, VF22 NOP ; and DistSq to it - NOP JR VI15 - NOP NOP -RatioGreaterThanOne: - MULAx.w ACC, VF00, VF25 NOP - MADDAy.w ACC, VF00, VF25 NOP - MADDz.w VF16, VF00, VF25 NOP - ADD.xyz VF16, VF14, VF15 NOP ; return toerh line point - NOP JR VI15 - NOP NOP - - -; BE0 -.globl Vu0SphereToTriangleCollisionCompressedStart -Vu0SphereToTriangleCollisionCompressedStart: - ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0 - ITOF0.xyzw VF14, VF14 NOP - ITOF0.xyzw VF15, VF15 NOP - ITOF0.xyzw VF16, VF16 NOP - MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0 - MULi.w VF17, VF17, I NOP - MULi.xyzw VF14, VF14, I NOP - MULi.xyzw VF15, VF15, I NOP - MULi.xyzw VF16, VF16, I NOP -; fall through - -; C28 -; VF12: sphere -; VF14-16: verts -; VF17: plane -; out: -; VF01: intersection point -; VF02: triangle normal -; VF03 x: intersection parameter -.globl Vu0SphereToTriangleCollisionStart -Vu0SphereToTriangleCollisionStart: - MUL.xyz VF02, VF12, VF17 LOI 0.1 - ADD.xyz VF17, VF17, VF00 NOP - ADDw.x VF13, VF00, VF12 NOP - NOP NOP - MULAx.w ACC, VF00, VF02 IADDIU VI06, VI00, 0xE0 - MADDAy.w ACC, VF00, VF02 FMAND VI05, VI06 ; normal sign flags - MADDAz.w ACC, VF00, VF02 NOP - MSUB.w VF02, VF00, VF17 NOP ; center plane pos - MULi.w VF03, VF00, I MOVE.xyzw VF04, VF03 - NOP NOP - NOP NOP - CLIPw.xyz VF13, VF02 NOP ; compare dist and radius - CLIPw.xyz VF17, VF03 NOP - MULAw.xyz ACC, VF12, VF00 IADDIU VI07, VI00, 0x0 ; -- clear test case - MSUBw.xyz VF01, VF17, VF02 NOP - MULx.w VF01, VF00, VF00 FCAND VI01, 0x3 ; projected center on plane - ABS.w VF02, VF02 IBEQ VI00, VI01, QuitAndFail ; no intersection - NOP NOP - NOP FCAND VI01, 0x3 ; -- check x direction - SUB.xyz VF02, VF12, VF01 IADDIU VI02, VI01, 0x7F - NOP IADDIU VI06, VI00, 0x80 - SUB.xyz VF05, VF15, VF14 IAND VI02, VI02, VI06 - SUB.xyz VF08, VF01, VF14 FCAND VI01, 0xC ; -- check y direction - SUB.xyz VF06, VF16, VF15 IADDIU VI03, VI01, 0x3F - SUB.xyz VF09, VF01, VF15 IADDIU VI06, VI00, 0x40 - SUB.xyz VF07, VF14, VF16 IAND VI03, VI03, VI06 - SUB.xyz VF10, VF01, VF16 FCAND VI01, 0x30 ; -- check z direction - MUL.xyz VF03, VF02, VF02 IADDIU VI04, VI01, 0x1F - OPMULA.xyz ACC, VF08, VF05 IADDIU VI06, VI00, 0x20 - OPMSUB.xyz VF18, VF05, VF08 IAND VI04, VI04, VI06 - OPMULA.xyz ACC, VF09, VF06 NOP - OPMSUB.xyz VF19, VF06, VF09 IADD VI06, VI02, VI03 - OPMULA.xyz ACC, VF10, VF07 IADD VI06, VI06, VI04 ; -- combine flags - OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; -- cross 1 flags - MULAx.w ACC, VF00, VF03 IAND VI05, VI05, VI06 - MADDAy.w ACC, VF00, VF03 FMAND VI03, VI06 ; -- cross 2 flags - MADDz.w VF03, VF00, VF03 IADDIU VI08, VI00, 0x3 - NOP FMAND VI04, VI06 ; -- cross 3 flags - NOP NOP - NOP IBNE VI02, VI05, CheckSide2 - NOP RSQRT Q, VF00w, VF03w - ADD.xyz VF04, VF00, VF16 IADDIU VI07, VI07, 0x1 ; inside side 1 -CheckSide2: - NOP IBNE VI03, VI05, CheckSide3 - NOP NOP - ADD.xyz VF04, VF00, VF14 IADDIU VI07, VI07, 0x1 ; inside side 2 -CheckSide3: - NOP IBNE VI04, VI05, FinishCheckingSides - NOP NOP - ADD.xyz VF04, VF00, VF15 IADDIU VI07, VI07, 0x1 ; inside side 3 - NOP NOP - NOP IBEQ VI07, VI08, TotallyInsideTriangle - NOP NOP -FinishCheckingSides: - MUL.x VF13, VF13, VF13 IADDIU VI08, VI00, 0x2 - MULq.xyz VF02, VF02, Q WAITQ - NOP IBNE VI07, VI08, IntersectionOutsideTwoSides - NOP NOP - NOP IBEQ VI02, VI05, CheckDistanceSide2 - NOP NOP - NOP MOVE.xyzw VF15, VF05 - NOP BAL VI15, DistanceBetweenSphereAndLine - NOP NOP - NOP B ProcessLineResult - NOP NOP -CheckDistanceSide2: - NOP IBEQ VI03, VI05, CheckDistanceSide3 - NOP NOP - NOP MOVE.xyzw VF14, VF15 - NOP MOVE.xyzw VF15, VF06 - NOP BAL VI15, DistanceBetweenSphereAndLine - NOP NOP - NOP B ProcessLineResult - NOP NOP -CheckDistanceSide3: - NOP MOVE.xyzw VF14, VF16 - NOP MOVE.xyzw VF15, VF07 - NOP BAL VI15, DistanceBetweenSphereAndLine - NOP NOP - NOP B ProcessLineResult - NOP NOP -IntersectionOutsideTwoSides: - SUB.xyz VF05, VF04, VF12 NOP - ADD.xyz VF01, VF00, VF04 NOP ; col point - SUB.xyz VF02, VF12, VF04 NOP - NOP NOP - MUL.xyz VF05, VF05, VF05 NOP - NOP NOP - NOP NOP - NOP NOP - MULAx.w ACC, VF00, VF05 NOP - MADDAy.w ACC, VF00, VF05 NOP - MADDz.w VF05, VF00, VF05 NOP ; distSq to vertex - NOP NOP - NOP NOP - NOP NOP - CLIPw.xyz VF13, VF05 SQRT Q, VF05w ; compare radiusSq and distSq - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x1 - ADDq.x VF03, VF00, Q WAITQ ; dist to vertex - NOP IBEQ VI00, VI01, QuitAndFail ; too far - NOP NOP - NOP NOP - NOP DIV Q, VF00w, VF03x - MULq.xyz VF02, VF02, Q WAITQ ; col normal - NOP[E] NOP - NOP NOP -TotallyInsideTriangle: - ADDw.x VF03, VF00, VF02 WAITQ - MULq.xyz VF02, VF02, Q NOP - NOP[E] IADDIU VI01, VI00, 0x1 - NOP NOP -ProcessLineResult: - CLIPw.xyz VF13, VF16 SQRT Q, VF16w - ADD.xyz VF01, VF00, VF16 NOP - SUB.xyz VF02, VF12, VF16 NOP - NOP NOP - NOP FCAND VI01, 0x1 - ADDq.x VF03, VF00, Q WAITQ - NOP IBEQ VI00, VI01, QuitAndFail - NOP NOP - NOP NOP - NOP DIV Q, VF00w, VF03x - MULq.xyz VF02, VF02, Q WAITQ - NOP[E] NOP - NOP NOP - -EndOfMicrocode: diff --git a/src/core/vu0Collision_2.s b/src/core/vu0Collision_2.s deleted file mode 100644 index 716c29ac..00000000 --- a/src/core/vu0Collision_2.s +++ /dev/null @@ -1,191 +0,0 @@ -QuitAndFail2: - NOP[E] IADDIU VI01, VI00, 0x0 - NOP NOP - - -QuitAndSucceed2: - NOP[E] IADDIU VI01, VI00, 0x1 - NOP NOP - - -; 20 -GetBBVertices: - MULw.xy VF02, VF01, VF00 NOP - MUL.z VF02, VF01, VF11 NOP - MULw.xz VF03, VF01, VF00 NOP - MUL.y VF03, VF01, VF11 NOP - MULw.x VF04, VF01, VF00 NOP - MUL.yz VF04, VF01, VF11 NOP - NOP JR VI15 - NOP NOP - - -; 60 -Vu0OBBToOBBCollision: - SUBw.xyz VF11, VF00, VF00 LOI 0.5 - MULi.xyz VF12, VF12, I NOP - MULi.xyz VF13, VF13, I NOP - NOP NOP - NOP NOP - NOP MOVE.xyz VF01, VF12 - NOP BAL VI15, GetBBVertices - NOP NOP - MULAx.xyz ACC, VF14, VF01 NOP - MADDAy.xyz ACC, VF15, VF01 NOP - MADDz.xyz VF01, VF16, VF01 NOP - MULAx.xyz ACC, VF14, VF02 NOP - MADDAy.xyz ACC, VF15, VF02 NOP - MADDz.xyz VF02, VF16, VF02 NOP - MULAx.xyz ACC, VF14, VF03 NOP - MADDAy.xyz ACC, VF15, VF03 NOP - MADDz.xyz VF03, VF16, VF03 NOP - MULAx.xyz ACC, VF14, VF04 NOP - MADDAy.xyz ACC, VF15, VF04 NOP - MADDz.xyz VF04, VF16, VF04 NOP - ABS.xyz VF05, VF01 NOP - ABS.xyz VF06, VF02 NOP - ABS.xyz VF07, VF03 NOP - ABS.xyz VF08, VF04 NOP - NOP NOP - MAX.xyz VF05, VF05, VF06 NOP - NOP NOP - MAX.xyz VF07, VF07, VF08 NOP - NOP NOP - NOP NOP - NOP NOP - MAX.xyz VF05, VF05, VF07 NOP - NOP NOP - NOP NOP - NOP NOP - ADD.xyz VF09, VF05, VF13 NOP - NOP NOP - NOP NOP - NOP NOP - MULx.w VF05, VF00, VF09 NOP - MULy.w VF06, VF00, VF09 NOP - MULz.w VF07, VF00, VF09 NOP - CLIPw.xyz VF17, VF05 NOP - CLIPw.xyz VF17, VF06 NOP - CLIPw.xyz VF17, VF07 MOVE.xyz VF01, VF13 - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x3330 - NOP IBNE VI01, VI00, QuitAndFail2 - NOP NOP - NOP BAL VI15, GetBBVertices - NOP NOP - MULAx.xyz ACC, VF18, VF01 NOP - MADDAy.xyz ACC, VF19, VF01 NOP - MADDz.xyz VF01, VF20, VF01 NOP - MULAx.xyz ACC, VF18, VF02 NOP - MADDAy.xyz ACC, VF19, VF02 NOP - MADDz.xyz VF02, VF20, VF02 NOP - MULAx.xyz ACC, VF18, VF03 NOP - MADDAy.xyz ACC, VF19, VF03 NOP - MADDz.xyz VF03, VF20, VF03 NOP - MULAx.xyz ACC, VF18, VF04 NOP - MADDAy.xyz ACC, VF19, VF04 NOP - MADDz.xyz VF04, VF20, VF04 NOP - ABS.xyz VF05, VF01 NOP - ABS.xyz VF06, VF02 NOP - ABS.xyz VF07, VF03 NOP - ABS.xyz VF08, VF04 NOP - NOP NOP - MAX.xyz VF05, VF05, VF06 NOP - NOP NOP - MAX.xyz VF07, VF07, VF08 NOP - NOP NOP - NOP NOP - NOP NOP - MAX.xyz VF05, VF05, VF07 NOP - NOP NOP - NOP NOP - NOP NOP - ADD.xyz VF09, VF05, VF12 NOP - NOP NOP - NOP NOP - NOP NOP - MULx.w VF05, VF00, VF09 NOP - MULy.w VF06, VF00, VF09 NOP - MULz.w VF07, VF00, VF09 NOP - CLIPw.xyz VF21, VF05 NOP - CLIPw.xyz VF21, VF06 NOP - CLIPw.xyz VF21, VF07 NOP - NOP NOP - NOP NOP - NOP NOP - NOP FCAND VI01, 0x3330 - NOP IBNE VI01, VI00, QuitAndFail2 - NOP NOP - SUB.xyz VF06, VF02, VF01 NOP - SUB.xyz VF07, VF03, VF01 NOP - ADD.xyz VF08, VF04, VF01 NOP - ADD.x VF09, VF00, VF12 NOP - ADD.yz VF09, VF00, VF00 NOP - ADD.y VF10, VF00, VF12 NOP - ADD.xz VF10, VF00, VF00 NOP - ADD.z VF11, VF00, VF12 IADDI VI04, VI00, 0x0 - ADD.xy VF11, VF00, VF00 IADD VI02, VI00, VI00 - OPMULA.xyz ACC, VF06, VF09 NOP - OPMSUB.xyz VF01, VF09, VF06 NOP - OPMULA.xyz ACC, VF06, VF10 NOP - OPMSUB.xyz VF02, VF10, VF06 NOP - OPMULA.xyz ACC, VF06, VF11 NOP - OPMSUB.xyz VF03, VF11, VF06 SQI.xyzw VF01, (VI02++) - OPMULA.xyz ACC, VF07, VF09 NOP - OPMSUB.xyz VF01, VF09, VF07 SQI.xyzw VF02, (VI02++) - OPMULA.xyz ACC, VF07, VF10 NOP - OPMSUB.xyz VF02, VF10, VF07 SQI.xyzw VF03, (VI02++) - OPMULA.xyz ACC, VF07, VF11 NOP - OPMSUB.xyz VF03, VF11, VF07 SQI.xyzw VF01, (VI02++) - OPMULA.xyz ACC, VF08, VF09 NOP - OPMSUB.xyz VF01, VF09, VF08 SQI.xyzw VF02, (VI02++) - OPMULA.xyz ACC, VF08, VF10 NOP - OPMSUB.xyz VF02, VF10, VF08 SQI.xyzw VF03, (VI02++) - OPMULA.xyz ACC, VF08, VF11 LOI 0.5 - OPMSUB.xyz VF01, VF11, VF08 SQI.xyzw VF01, (VI02++) - MULi.xyz VF06, VF06, I NOP - MULi.xyz VF07, VF07, I SQI.xyzw VF02, (VI02++) - MULi.xyz VF08, VF08, I NOP - MUL.xyz VF02, VF21, VF01 NOP - MUL.xyz VF03, VF12, VF01 NOP - MUL.xyz VF09, VF06, VF01 NOP - MUL.xyz VF10, VF07, VF01 NOP - MUL.xyz VF11, VF08, VF01 NOP - ABS.xyz VF03, VF03 NOP - ADDy.x VF05, VF09, VF09 NOP - ADDx.y VF05, VF10, VF10 NOP - ADDx.z VF05, VF11, VF11 NOP - NOP NOP -EdgePairLoop: - ADDz.x VF05, VF05, VF09 NOP - ADDz.y VF05, VF05, VF10 NOP - ADDy.z VF05, VF05, VF11 NOP - MULAx.w ACC, VF00, VF02 IADD VI03, VI02, VI00 - MADDAy.w ACC, VF00, VF02 LQD.xyzw VF01, (--VI02) - MADDz.w VF02, VF00, VF02 NOP - ABS.xyz VF05, VF05 NOP - MULAx.w ACC, VF00, VF03 NOP - MADDAy.w ACC, VF00, VF03 NOP - MADDAz.w ACC, VF00, VF03 NOP - MADDAx.w ACC, VF00, VF05 NOP - MADDAy.w ACC, VF00, VF05 NOP - MADDz.w VF03, VF00, VF05 NOP - ADDw.x VF04, VF00, VF02 NOP - MUL.xyz VF02, VF21, VF01 NOP - MUL.xyz VF03, VF12, VF01 NOP - MUL.xyz VF09, VF06, VF01 NOP - CLIPw.xyz VF04, VF03 NOP - MUL.xyz VF10, VF07, VF01 NOP - MUL.xyz VF11, VF08, VF01 NOP - ABS.xyz VF03, VF03 NOP - ADDy.x VF05, VF09, VF09 FCAND VI01, 0x3 - ADDx.y VF05, VF10, VF10 IBNE VI01, VI00, QuitAndFail2 - ADDx.z VF05, VF11, VF11 NOP - NOP IBNE VI03, VI00, EdgePairLoop - NOP NOP - NOP[E] IADDIU VI01, VI00, 0x1 - NOP NOP - -EndOfMicrocode2: diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index a08e68f8..172bae3f 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -572,7 +572,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(IsGlass(B->GetModelIndex())) CGlass::WindowRespondsToSoftCollision(B, impulseA); if(!A->bInfiniteMass) - A->ApplyMoveForce(colpoint.normal*(1.0f + A->m_fElasticity)*impulseA); + A->ApplyMoveForce(colpoint.GetNormal() * (1.0f + A->m_fElasticity) * impulseA); return true; } }else if(!B->bInfiniteMass) @@ -624,7 +624,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl }else{ if(IsGlass(B->GetModelIndex())) CGlass::WindowRespondsToSoftCollision(B, impulseA); - CVector f = colpoint.normal * impulseA; + CVector f = colpoint.GetNormal() * impulseA; if(A->IsVehicle() && colpoint.normal.z < 0.7f) f.z *= 0.3f; if(!A->bInfiniteMass){ @@ -1146,43 +1146,43 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) mostColliding = 0; for(j = 1; j < numCollisions; j++) - if(colpoints[j].depth > colpoints[mostColliding].depth) + if (colpoints[j].GetDepth() > colpoints[mostColliding].GetDepth()) mostColliding = j; if(CWorld::bSecondShift) for(j = 0; j < numCollisions; j++) - shift += colpoints[j].normal * colpoints[j].depth * 1.5f/numCollisions; + shift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.5f / numCollisions; else for(j = 0; j < numCollisions; j++) - shift += colpoints[j].normal * colpoints[j].depth * 1.2f/numCollisions; + shift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.2f / numCollisions; if(A->IsVehicle() && B->IsVehicle()){ CVector dir = A->GetPosition() - B->GetPosition(); dir.Normalise(); if(dir.z < 0.0f && dir.z < A->GetForward().z && dir.z < A->GetRight().z) dir.z = Min(0.0f, Min(A->GetForward().z, A->GetRight().z)); - shift += dir * colpoints[mostColliding].depth * 0.5f; + shift += dir * colpoints[mostColliding].GetDepth() * 0.5f; }else if(A->IsPed() && B->IsVehicle() && ((CVehicle*)B)->IsBoat()){ - CVector dir = colpoints[mostColliding].normal; + CVector dir = colpoints[mostColliding].GetNormal(); float f = Min(Abs(dir.z), 0.9f); dir.z = 0.0f; dir.Normalise(); - shift += dir * colpoints[mostColliding].depth / (1.0f - f); + shift += dir * colpoints[mostColliding].GetDepth() / (1.0f - f); boat = B; }else if(B->IsPed() && A->IsVehicle() && ((CVehicle*)A)->IsBoat()){ - CVector dir = colpoints[mostColliding].normal * -1.0f; + CVector dir = colpoints[mostColliding].GetNormal() * -1.0f; float f = Min(Abs(dir.z), 0.9f); dir.z = 0.0f; dir.Normalise(); - B->GetMatrix().Translate(dir * colpoints[mostColliding].depth / (1.0f - f)); + B->GetMatrix().Translate(dir * colpoints[mostColliding].GetDepth() / (1.0f - f)); // BUG? how can that ever happen? A is a Ped if(B->IsVehicle()) B->ProcessEntityCollision(A, colpoints); }else{ if(CWorld::bSecondShift) - shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.4f; + shift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.4f; else - shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.2f; + shift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.2f; } doShift = true; -- cgit v1.2.3 From ad10d3e64e317a60c4c7c481354ef9c2b39922f2 Mon Sep 17 00:00:00 2001 From: withmorten Date: Sun, 15 Nov 2020 22:07:44 +0100 Subject: revert frontend changes for invertlook4pad --- src/core/Frontend.cpp | 5 ----- src/core/Frontend.h | 3 --- 2 files changed, 8 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 879bcb29..cf25e1b9 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5404,11 +5404,6 @@ CMenuManager::ProcessOnOffMenuOptions() DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; -#ifdef INVERT_LOOK_FOR_PAD - case MENUACTION_INVERTPADY: - CPad::bInvertLook4Pad = !CPad::bInvertLook4Pad; - break; -#endif } } diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 947311b6..70b4cd31 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -383,9 +383,6 @@ enum eMenuAction //#ifdef NO_ISLAND_LOADING // MENUACTION_ISLANDLOADING, //#endif -#ifdef INVERT_LOOK_FOR_PAD - MENUACTION_INVERTPADY, -#endif }; enum eCheckHover -- cgit v1.2.3 From ac29ae6e23ac174adf03acb85749533e601ec5d0 Mon Sep 17 00:00:00 2001 From: withmorten Date: Sun, 15 Nov 2020 23:06:09 +0100 Subject: add CFO for invertlook4pad; update american.gxt --- src/core/MenuScreensCustom.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index d3d7474d..5fc44661 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -15,6 +15,7 @@ #include "FileLoader.h" #include "Collision.h" #include "ModelInfo.h" +#include "Pad.h" // Menu screens array is at the bottom of the file. @@ -76,6 +77,12 @@ #define PIPELINES_SELECTOR #endif +#ifdef INVERT_LOOK_FOR_PAD + #define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_IVP", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, "InvertPad", off_on, 2, false, nil) }, +#else + #define INVERT_PAD_SELECTOR +#endif + const char *filterNames[] = { "FEM_NON", "FEM_SIM", "FEM_NRM", "FEM_MOB" }; const char *vehPipelineNames[] = { "FED_MFX", "FED_NEO" }; const char *off_on[] = { "FEM_OFF", "FEM_ON" }; @@ -780,6 +787,9 @@ CMenuScreenCustom aScreens[MENUPAGES] = { { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, MENUACTION_MOUSESENS, "FEC_MSH", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, MENUACTION_INVVERT, "FEC_IVV", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, +#ifdef INVERT_LOOK_FOR_PAD + INVERT_PAD_SELECTOR +#endif MENUACTION_MOUSESTEER, "FET_MST", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, }, -- cgit v1.2.3 From f0071c094aeacdd5fc8dd4f45911ebbc719811e0 Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 16 Nov 2020 00:07:27 +0100 Subject: remove unneeded ifdef --- src/core/MenuScreensCustom.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index 5fc44661..f8ff3acf 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -787,9 +787,7 @@ CMenuScreenCustom aScreens[MENUPAGES] = { { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, MENUACTION_MOUSESENS, "FEC_MSH", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, MENUACTION_INVVERT, "FEC_IVV", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, -#ifdef INVERT_LOOK_FOR_PAD INVERT_PAD_SELECTOR -#endif MENUACTION_MOUSESTEER, "FET_MST", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, }, -- cgit v1.2.3 From 207f8576d83c54d80a05a983798ce1d4bcb34f91 Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 16 Nov 2020 00:21:04 +0100 Subject: move config.h define to CUSTOM_FRONTEND_OPTIONS --- src/core/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index 39c5d782..1d321175 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -251,7 +251,6 @@ enum Config { #define REGISTER_START_BUTTON //#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls #define BUTTON_ICONS // use textures to show controller buttons -#define INVERT_LOOK_FOR_PAD // add bInvertLook4Pad from VC // Hud, frontend and radar #define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. @@ -276,6 +275,7 @@ enum Config { # define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU # define CUTSCENE_BORDERS_SWITCH # define MULTISAMPLING // adds MSAA option +# define INVERT_LOOK_FOR_PAD // add bInvertLook4Pad from VC # endif #endif -- cgit v1.2.3 From abcda2ce29877cdd60fad383ec098b174fbcc11f Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 16 Nov 2020 00:41:03 +0100 Subject: add mission switcher from miami --- src/control/Script.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/control/Script.h | 7 +++++++ src/core/config.h | 5 +++++ src/core/re3.cpp | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) (limited to 'src') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 86595bbd..646bc3f7 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -13337,3 +13337,44 @@ void RetryMission(int type, int unk) } #endif + +#ifdef MISSION_SWITCHER +void +CTheScripts::SwitchToMission(int32 mission) +{ + for (CRunningScript* pScript = CTheScripts::pActiveScripts; pScript != nil; pScript = pScript->GetNext()) { + if (!pScript->m_bIsMissionScript || !pScript->m_bDeatharrestEnabled) { + continue; + } + while (pScript->m_nStackPointer > 0) + --pScript->m_nStackPointer; + + pScript->m_nIp = pScript->m_anStack[pScript->m_nStackPointer]; + *(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0; + pScript->m_nWakeTime = 0; + pScript->m_bDeatharrestExecuted = true; + + while (!pScript->ProcessOneCommand()); + + CMessages::ClearMessages(); + } + +#ifdef MISSION_REPLAY + missionRetryScriptIndex = mission; + if (missionRetryScriptIndex == 19) + CStats::LastMissionPassedName[0] = '\0'; +#endif + CTimer::Suspend(); + int offset = CTheScripts::MultiScriptArray[mission]; + CFileMgr::ChangeDir("\\"); + int handle = CFileMgr::OpenFile("data\\main.scm", "rb"); + CFileMgr::Seek(handle, offset, 0); + CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT); + CFileMgr::CloseFile(handle); + CRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT); + CTimer::Resume(); + pMissionScript->m_bIsMissionScript = true; + pMissionScript->m_bMissionFlag = true; + CTheScripts::bAlreadyRunningAMissionScript = true; +} +#endif diff --git a/src/control/Script.h b/src/control/Script.h index e0ed314e..c9e92129 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -376,6 +376,11 @@ private: #ifdef FIX_BUGS friend void RetryMission(int, int); #endif + +#ifdef MISSION_SWITCHER +public: + static void SwitchToMission(int32 mission); +#endif }; @@ -514,6 +519,8 @@ private: return false; } } + + friend class CTheScripts; }; #ifdef MISSION_REPLAY diff --git a/src/core/config.h b/src/core/config.h index a55b018e..ddbac185 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -217,6 +217,11 @@ enum Config { #define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible #define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS +// Just debug menu entries +#ifdef DEBUGMENU +#define MISSION_SWITCHER // from debug menu +#endif + // Rendering/display //#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering //# define HARDCODED_MODEL_FLAGS // sets the flags enabled above from hardcoded model names. diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 4783e513..194f75fa 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -26,6 +26,7 @@ #include "Frontend.h" #include "WaterLevel.h" #include "main.h" +#include "Script.h" #include "postfx.h" #include "custompipes.h" @@ -373,6 +374,15 @@ ResetCamStatics(void) TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true; } +#ifdef MISSION_SWITCHER +int8 nextMissionToSwitch = 0; +static void +SwitchToMission(void) +{ + CTheScripts::SwitchToMission(nextMissionToSwitch); +} +#endif + static const char *carnames[] = { "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony", "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer", @@ -581,6 +591,29 @@ DebugMenuPopulate(void) #ifdef TIMEBARS DebugMenuAddVarBool8("Debug", "Show Timebars", &gbShowTimebars, nil); #endif +#ifdef MISSION_SWITCHER + DebugMenuEntry *missionEntry; + static const char* missions[] = { + "Intro Movie", "Hospital Info Scene", "Police Station Info Scene", + "RC Diablo Destruction", "RC Mafia Massacre", "RC Rumpo Rampage", "RC Casino Calamity", + "Patriot Playground", "A Ride In The Park", "Gripped!", "Multistorey Mayhem", + "Paramedic", "Firefighter", "Vigilante", "Taxi Driver", + "The Crook", "The Thieves", "The Wife", "Her Lover", + "Give Me Liberty and Luigi's Girls", "Don't Spank My Bitch Up", "Drive Misty For Me", "Pump-Action Pimp", "The Fuzz Ball", + "Mike Lips Last Lunch", "Farewell 'Chunky' Lee Chong", "Van Heist", "Cipriani's Chauffeur", "Dead Skunk In The Trunk", "The Getaway", + "Taking Out The Laundry", "The Pick-Up", "Salvatore's Called A Meeting", "Triads And Tribulations", "Blow Fish", "Chaperone", "Cutting The Grass", + "Bomb Da Base: Act I", "Bomb Da Base: Act II", "Last Requests", "Turismo", "I Scream, You Scream", "Trial By Fire", "Big'N'Veiny", "Sayonara Salvatore", + "Under Surveillance", "Paparazzi Purge", "Payday For Ray", "Two-Faced Tanner", "Kanbu Bust-Out", "Grand Theft Auto", "Deal Steal", "Shima", "Smack Down", + "Silence The Sneak", "Arms Shortage", "Evidence Dash", "Gone Fishing", "Plaster Blaster", "Marked Man", + "Liberator", "Waka-Gashira Wipeout!", "A Drop In The Ocean", "Bling-Bling Scramble", "Uzi Rider", "Gangcar Round-Up", "Kingdom Come", + "Grand Theft Aero", "Escort Service", "Decoy", "Love's Disappearance", "Bait", "Espresso-2-Go!", "S.A.M.", + "Uzi Money", "Toyminator", "Rigged To Blow", "Bullion Run", "Rumble", "The Exchange" + }; + + missionEntry = DebugMenuAddVar("Debug", "Select mission", &nextMissionToSwitch, nil, 1, 0, 79, missions); + DebugMenuEntrySetWrap(missionEntry, true); + DebugMenuAddCmd("Debug", "Start selected mission ", SwitchToMission); +#endif extern bool PrintDebugCode; extern int16 DebugCamMode; -- cgit v1.2.3 From 2f9a905c613aacf12a3bc059eb1c8876d8c3bc86 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 16 Nov 2020 09:41:39 +0100 Subject: change gl caps.dat constants --- src/fakerw/fake.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 64e59375..460b8211 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -942,7 +942,9 @@ RwBool RtCharsetDestroy(RtCharset * charSet) { charSet->destroy(); return RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags) { #ifdef RW_GL3 - return '3LGO'; + if(flags & (rwRASTERFORMATPAL8 | rwRASTERFORMAT8888)) + return 'NOPE'; + return 'YUP'; #endif return flags & 0xF00; } -- cgit v1.2.3 From 5335b46cbb83e80e88d99f6963670050920e5f3e Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 16 Nov 2020 09:48:02 +0100 Subject: little fix to ps2 CPad --- src/core/Pad.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 44a347bd..9c6bdc98 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -1284,7 +1284,7 @@ void CPad::Update(int16 pad) { if ( ShakeDur ) { - ShakeDur = Max(ShakeDur - CTimer::GetTimeStepInMilliseconds(), 0); + ShakeDur = Max(ShakeDur - (int32)CTimer::GetTimeStepInMilliseconds(), 0); if ( ShakeDur == 0 ) { -- cgit v1.2.3 From b508458f372ba125c0d40d3f2aed27701b2cf7be Mon Sep 17 00:00:00 2001 From: Nikolay Date: Mon, 16 Nov 2020 15:13:30 +0300 Subject: small fix --- src/control/CarCtrl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 76ee47b0..627d7bad 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -2692,7 +2692,7 @@ void CCarCtrl::GenerateEmergencyServicesCar(void) float distance = 30.0f; CFire* pNearestFire = gFireManager.FindNearestFire(FindPlayerCoors(), &distance); if (pNearestFire) { - if (CountCarsOfType(MI_FIRETRUCK) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeFireTruckCreated + 30000){ + if (CountCarsOfType(MI_FIRETRUCK) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeFireTruckCreated + 35000){ CStreaming::RequestModel(MI_FIRETRUCK, STREAMFLAGS_DEPENDENCY); CStreaming::RequestModel(MI_FIREMAN, STREAMFLAGS_DONT_REMOVE); if (CStreaming::HasModelLoaded(MI_FIRETRUCK) && CStreaming::HasModelLoaded(MI_FIREMAN)){ -- cgit v1.2.3 From 3b1debaa0d5341bdb954654503424fb12b529894 Mon Sep 17 00:00:00 2001 From: erorcun Date: Mon, 16 Nov 2020 15:28:10 +0300 Subject: Fix mouse lock/high-dpi --- src/core/Frontend.cpp | 9 ++++++++- src/core/main.cpp | 4 ++-- src/skel/glfw/glfw.cpp | 20 +++++++++++++------- 3 files changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 4be23b77..ffcd8b30 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5529,8 +5529,15 @@ CMenuManager::SwitchMenuOnAndOff() gMusicPlaying = 0; } */ - if (m_bMenuActive != menuWasActive) + if (m_bMenuActive != menuWasActive) { m_bMenuStateChanged = true; + + // Keep mouse centered while in game. Done in main.cpp in other conditions. + // IMPROVED_VIDEOMODE because otherwise there is no way for windowed mode. +#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE) + glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, m_bMenuActive && m_nPrefsWindowed ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_DISABLED); +#endif + } m_bStartUpFrontEndRequested = false; m_bShutDownFrontEndRequested = false; diff --git a/src/core/main.cpp b/src/core/main.cpp index cd234588..157776e0 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1090,9 +1090,9 @@ Idle(void *arg) if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) && TheCamera.GetScreenFadeStatus() != FADE_2) { -#ifdef GTA_PC + // This is from SA, but it's nice for windowed mode +#if defined(GTA_PC) && !defined(RW_GL3) if (!FrontEndMenuManager.m_bRenderGameInMenu) { - // This is from SA, but it's nice for windowed mode RwV2d pos; pos.x = SCREEN_WIDTH / 2.0f; pos.y = SCREEN_HEIGHT / 2.0f; diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index d8d168c5..86abca64 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -885,7 +885,13 @@ void _InputInitialiseJoys() long _InputInitialiseMouse() { +#ifdef IMPROVED_VIDEOMODE + // May be windowed, transition will be handled in CMenuManager::SwitchMenuOnAndOff() glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); +#else + // Always fullscreen, disable mouse + glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_DISABLED); +#endif return 0; } @@ -1416,11 +1422,13 @@ _InputTranslateShiftKeyUpDown(RsKeyCodes *rs) { // TODO this only works in frontend(and luckily only frontend use this). Fun fact: if I get pos manually in game, glfw reports that it's > 32000 void cursorCB(GLFWwindow* window, double xpos, double ypos) { - int bufw, bufh, winw, winh; - glfwGetWindowSize(window, &winw, &winh); - glfwGetFramebufferSize(window, &bufw, &bufh); - FrontEndMenuManager.m_nMouseTempPosX = xpos * (bufw / winw); - FrontEndMenuManager.m_nMouseTempPosY = ypos * (bufh / winh); + if (!FrontEndMenuManager.m_bMenuActive) + return; + + int winw, winh; + glfwGetWindowSize(PSGLOBAL(window), &winw, &winh); + FrontEndMenuManager.m_nMouseTempPosX = xpos * (RsGlobal.maximumWidth / winw); + FrontEndMenuManager.m_nMouseTempPosY = ypos * (RsGlobal.maximumHeight / winh); } void @@ -1648,8 +1656,6 @@ main(int argc, char *argv[]) #endif { glfwPollEvents(); - glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, - (FrontEndMenuManager.m_bMenuActive && !PSGLOBAL(fullScreen)) ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_DISABLED); if( ForegroundApp ) { switch ( gGameState ) -- cgit v1.2.3 From f33ed2892a7a083d10c89b93b0122c6b4100a9a2 Mon Sep 17 00:00:00 2001 From: erorcun Date: Mon, 16 Nov 2020 15:49:00 +0300 Subject: Fix mouse lock/high-dpi 2 --- src/core/Frontend.cpp | 7 +++++-- src/skel/glfw/glfw.cpp | 6 ------ 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index ffcd8b30..b84b691d 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5433,6 +5433,10 @@ CMenuManager::SetHelperText(int text) void CMenuManager::ShutdownJustMenu() { + // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions. +#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE) + glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_DISABLED); +#endif m_bMenuActive = false; CTimer::EndUserPause(); } @@ -5532,8 +5536,7 @@ CMenuManager::SwitchMenuOnAndOff() if (m_bMenuActive != menuWasActive) { m_bMenuStateChanged = true; - // Keep mouse centered while in game. Done in main.cpp in other conditions. - // IMPROVED_VIDEOMODE because otherwise there is no way for windowed mode. + // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions. #if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE) glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, m_bMenuActive && m_nPrefsWindowed ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_DISABLED); #endif diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 86abca64..982e8641 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -885,13 +885,7 @@ void _InputInitialiseJoys() long _InputInitialiseMouse() { -#ifdef IMPROVED_VIDEOMODE - // May be windowed, transition will be handled in CMenuManager::SwitchMenuOnAndOff() glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); -#else - // Always fullscreen, disable mouse - glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_DISABLED); -#endif return 0; } -- cgit v1.2.3 From 6bc2ed74fec6e60d1d379dc36f271c457448d3e7 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 16 Nov 2020 14:56:07 +0200 Subject: Add debug code to CPathFind::PreparePathDataForType --- src/control/PathFind.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index fb60250c..ecd2d0cb 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -542,6 +542,22 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor int done, cont; int tileStart; +#ifndef MASTER + for (i = 0; i < m_numMapObjects-1; i++) + for (j = i+1; j < m_numMapObjects; j++) { + CTreadable *obj1 = m_mapObjects[i]; + CTreadable *obj2 = m_mapObjects[j]; + if (obj1->GetModelIndex() == obj2->GetModelIndex() && + obj1->GetPosition().x == obj2->GetPosition().x && obj1->GetPosition().y == obj2->GetPosition().y && obj1->GetPosition().z == obj2->GetPosition().z && + obj1->GetRight().x == obj2->GetRight().x && obj1->GetForward().x == obj2->GetForward().x && obj1->GetUp().x == obj2->GetUp().x && + obj1->GetRight().y == obj2->GetRight().y && obj1->GetForward().y == obj2->GetForward().y && obj1->GetUp().y == obj2->GetUp().y && + obj1->GetRight().z == obj2->GetRight().z && obj1->GetForward().z == obj2->GetForward().z && obj1->GetUp().z == obj2->GetUp().z) { + printf("THIS IS VERY BAD INDEED. FIX IMMEDIATELY!!!\n"); + printf("Double road objects at the following coors: %f %f %f\n", obj1->GetPosition().x, obj1->GetPosition().y, obj1->GetPosition().z); + } + } +#endif // !MASTER + oldNumPathNodes = m_numPathNodes; oldNumLinks = m_numConnections; -- cgit v1.2.3 From a802ad5c271f15fc9acaacdfa55fb6a318c1c893 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 16 Nov 2020 15:05:02 +0200 Subject: pragma twice --- src/objects/Projectile.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/objects/Projectile.h b/src/objects/Projectile.h index 2f2b541c..4b3eb4b8 100644 --- a/src/objects/Projectile.h +++ b/src/objects/Projectile.h @@ -1,7 +1,5 @@ #pragma once -#pragma once - #include "Object.h" class CProjectile : public CObject -- cgit v1.2.3 From 3564b85b4e354272cea8a8217f9e27827a043d7a Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 16 Nov 2020 22:43:15 +0100 Subject: animation compression from PS2 --- src/animation/AnimBlendAssociation.h | 2 +- src/animation/AnimBlendHierarchy.cpp | 18 ++++-- src/animation/AnimBlendSequence.cpp | 104 +++++++++++++++++++++++++++++++++++ src/animation/AnimBlendSequence.h | 16 ++++-- src/animation/AnimManager.cpp | 2 +- src/core/config.h | 1 + 6 files changed, 133 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h index 2dff4391..80927da2 100644 --- a/src/animation/AnimBlendAssociation.h +++ b/src/animation/AnimBlendAssociation.h @@ -13,7 +13,7 @@ enum { ASSOC_MOVEMENT = 0x20, // ??? ASSOC_HAS_TRANSLATION = 0x40, ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void) - ASSOC_FLAG_XPRESS = 0x100, // only used by xpress scratch, see CPed::Chat(void) + ASSOC_IDLE = 0x100, // only used by xpress scratch, see CPed::Chat(void) ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void) ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played ASSOC_FRONTAL = 0x800, // anims that we fall to front diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp index feeaca3d..67b19019 100644 --- a/src/animation/AnimBlendHierarchy.cpp +++ b/src/animation/AnimBlendHierarchy.cpp @@ -30,15 +30,14 @@ void CAnimBlendHierarchy::CalcTotalTime(void) { int i, j; - float totalTime = 0.0f; + totalLength = 0.0f; for(i = 0; i < numSequences; i++){ float seqTime = 0.0f; for(j = 0; j < sequences[i].numFrames; j++) seqTime += sequences[i].GetKeyFrame(j)->deltaTime; - totalTime = Max(totalTime, seqTime); + totalLength = Max(totalLength, seqTime); } - totalLength = totalTime; } void @@ -61,6 +60,12 @@ CAnimBlendHierarchy::RemoveAnimSequences(void) void CAnimBlendHierarchy::Uncompress(void) { +#ifdef ANIM_COMPRESSION + int i; + assert(compressed); + for(i = 0; i < numSequences; i++) + sequences[i].Uncompress(); +#endif if(totalLength == 0.0f) CalcTotalTime(); compressed = 0; @@ -69,6 +74,11 @@ CAnimBlendHierarchy::Uncompress(void) void CAnimBlendHierarchy::RemoveUncompressedData(void) { - // useless +#ifdef ANIM_COMPRESSION + int i; + assert(!compressed); + for(i = 0; i < numSequences; i++) + sequences[i].RemoveUncompressedData(); +#endif compressed = 1; } diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp index 4578ec50..d35fbc46 100644 --- a/src/animation/AnimBlendSequence.cpp +++ b/src/animation/AnimBlendSequence.cpp @@ -15,6 +15,7 @@ CAnimBlendSequence::CAnimBlendSequence(void) CAnimBlendSequence::~CAnimBlendSequence(void) { + assert(keyFramesCompressed == nil); if(keyFrames) RwFree(keyFrames); } @@ -60,3 +61,106 @@ CAnimBlendSequence::RemoveQuaternionFlips(void) last = frame->rotation; } } + +void +CAnimBlendSequence::Uncompress(void) +{ + int i; + + if(numFrames == 0) + return; + + float rotScale = 1.0f/4096.0f; + float timeScale = 1.0f/60.0f; + float transScale = 1.0f/128.0f; + if(type & KF_TRANS){ + void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTrans)); + KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)keyFramesCompressed; + KeyFrameTrans *kf = (KeyFrameTrans*)newKfs; + for(i = 0; i < numFrames; i++){ + kf->rotation.x = ckf->rot[0]*rotScale; + kf->rotation.y = ckf->rot[1]*rotScale; + kf->rotation.z = ckf->rot[2]*rotScale; + kf->rotation.w = ckf->rot[3]*rotScale; + kf->deltaTime = ckf->deltaTime*timeScale; + kf->translation.x = ckf->trans[0]*transScale; + kf->translation.y = ckf->trans[1]*transScale; + kf->translation.z = ckf->trans[2]*transScale; + kf++; + ckf++; + } + keyFrames = newKfs; + }else{ + void *newKfs = RwMalloc(numFrames * sizeof(KeyFrame)); + KeyFrameCompressed *ckf = (KeyFrameCompressed*)keyFramesCompressed; + KeyFrame *kf = (KeyFrame*)newKfs; + for(i = 0; i < numFrames; i++){ + kf->rotation.x = ckf->rot[0]*rotScale; + kf->rotation.y = ckf->rot[1]*rotScale; + kf->rotation.z = ckf->rot[2]*rotScale; + kf->rotation.w = ckf->rot[3]*rotScale; + kf->deltaTime = ckf->deltaTime*timeScale; + kf++; + ckf++; + } + keyFrames = newKfs; + } + RwFree(keyFramesCompressed); + keyFramesCompressed = nil; +} + +void +CAnimBlendSequence::CompressKeyframes(void) +{ + int i; + + if(numFrames == 0) + return; + + float rotScale = 4096.0f; + float timeScale = 60.0f; + float transScale = 128.0f; + if(type & KF_TRANS){ + void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTransCompressed)); + KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)newKfs; + KeyFrameTrans *kf = (KeyFrameTrans*)keyFrames; + for(i = 0; i < numFrames; i++){ + ckf->rot[0] = kf->rotation.x*rotScale; + ckf->rot[1] = kf->rotation.y*rotScale; + ckf->rot[2] = kf->rotation.z*rotScale; + ckf->rot[3] = kf->rotation.w*rotScale; + ckf->deltaTime = kf->deltaTime*timeScale + 0.5f; + ckf->trans[0] = kf->translation.x*transScale; + ckf->trans[1] = kf->translation.y*transScale; + ckf->trans[2] = kf->translation.z*transScale; + kf++; + ckf++; + } + keyFramesCompressed = newKfs; + }else{ + void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameCompressed)); + KeyFrameCompressed *ckf = (KeyFrameCompressed*)newKfs; + KeyFrame *kf = (KeyFrame*)keyFrames; + for(i = 0; i < numFrames; i++){ + ckf->rot[0] = kf->rotation.x*rotScale; + ckf->rot[1] = kf->rotation.y*rotScale; + ckf->rot[2] = kf->rotation.z*rotScale; + ckf->rot[3] = kf->rotation.w*rotScale; + ckf->deltaTime = kf->deltaTime*timeScale + 0.5f; + kf++; + ckf++; + } + keyFramesCompressed = newKfs; + } +} + +void +CAnimBlendSequence::RemoveUncompressedData(void) +{ + if(numFrames == 0) + return; + CompressKeyframes(); + RwFree(keyFrames); + keyFrames = nil; +} + diff --git a/src/animation/AnimBlendSequence.h b/src/animation/AnimBlendSequence.h index 44ac8886..e51e5aaa 100644 --- a/src/animation/AnimBlendSequence.h +++ b/src/animation/AnimBlendSequence.h @@ -12,6 +12,15 @@ struct KeyFrameTrans : KeyFrame { CVector translation; }; +struct KeyFrameCompressed { + int16 rot[4]; // 4096 + int16 deltaTime; // 60 +}; + +struct KeyFrameTransCompressed : KeyFrameCompressed { + int16 trans[3]; // 128 +}; + // The sequence of key frames of one animated node class CAnimBlendSequence @@ -41,10 +50,9 @@ public: &((KeyFrame*)keyFrames)[n]; } bool HasTranslation(void) { return !!(type & KF_TRANS); } - // TODO? these are unused -// void Uncompress(void); -// void CompressKeyframes(void); -// void RemoveUncompressedData(void); + void Uncompress(void); + void CompressKeyframes(void); + void RemoveUncompressedData(void); #ifdef PED_SKIN void SetBoneTag(int tag) { boneTag = tag; } diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index 444b6d45..877dcd76 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -176,7 +176,7 @@ AnimAssocDesc aStdAnimDescs[] = { { ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_EV_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, - { ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG_XPRESS }, + { ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_IDLE }, { ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, diff --git a/src/core/config.h b/src/core/config.h index 1d321175..11168039 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -177,6 +177,7 @@ enum Config { # define GTA_PS2_STUFF # define RANDOMSPLASH # define VU_COLLISION +# define ANIM_COMPRESSION #elif defined GTA_PC # define GTA3_1_1_PATCH //# define GTA3_STEAM_PATCH -- cgit v1.2.3 From 19d943031481f83d662c74ee3202a8fbaed22fa2 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 16 Nov 2020 22:57:37 +0100 Subject: fix flag --- src/peds/Ped.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index fcfd9bce..b3c5c57b 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -3023,7 +3023,7 @@ CPed::Chat(void) } else Say(SOUND_PED_CHAT); - } else if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG_XPRESS)) { + } else if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { if (CGeneral::GetRandomNumber() < 20) { CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); -- cgit v1.2.3 From 82b0103c6789041b721b1de30746ce21a556ab4d Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 18 Nov 2020 10:27:55 +0100 Subject: changes to librw layer, GLES now runtime choice --- src/extras/custompipes_gl.cpp | 47 ++++---------- src/extras/postfx.cpp | 18 ++---- src/extras/shaders/Makefile | 58 +++++++++--------- src/extras/shaders/colourfilterIII.frag | 11 ++-- src/extras/shaders/colourfilterIII_fs_gl.inc | 26 ++++++++ src/extras/shaders/contrast.frag | 11 ++-- src/extras/shaders/contrast_fs_gl.inc | 21 +++++++ src/extras/shaders/default_UV2.vert | 14 ++--- src/extras/shaders/default_UV2_gl.inc | 27 ++++++++ src/extras/shaders/im2d.vert | 10 ++- src/extras/shaders/im2d_gl.inc | 21 +++++++ src/extras/shaders/neoGloss.frag | 14 ++--- src/extras/shaders/neoGloss.vert | 14 ++--- src/extras/shaders/neoGloss_fs_gl.inc | 28 +++++++++ src/extras/shaders/neoGloss_vs_gl.inc | 27 ++++++++ src/extras/shaders/neoRim.vert | 13 ++-- src/extras/shaders/neoRimSkin.vert | 15 ++--- src/extras/shaders/neoRimSkin_gl.inc | 45 ++++++++++++++ src/extras/shaders/neoRim_gl.inc | 36 +++++++++++ src/extras/shaders/neoVehicle.frag | 15 ++--- src/extras/shaders/neoVehicle.vert | 17 +++-- src/extras/shaders/neoVehicle_fs_gl.inc | 31 ++++++++++ src/extras/shaders/neoVehicle_vs_gl.inc | 53 ++++++++++++++++ src/extras/shaders/neoWorldIII.frag | 14 ++--- src/extras/shaders/neoWorldIII_fs_gl.inc | 27 ++++++++ src/extras/shaders/simple.frag | 11 ++-- src/extras/shaders/simple_fs_gl.inc | 19 ++++++ src/fakerw/fake.cpp | 13 ---- src/rw/TexRead.cpp | 92 ++++++++++++++++++++++++++-- 29 files changed, 565 insertions(+), 183 deletions(-) create mode 100644 src/extras/shaders/colourfilterIII_fs_gl.inc create mode 100644 src/extras/shaders/contrast_fs_gl.inc create mode 100644 src/extras/shaders/default_UV2_gl.inc create mode 100644 src/extras/shaders/im2d_gl.inc create mode 100644 src/extras/shaders/neoGloss_fs_gl.inc create mode 100644 src/extras/shaders/neoGloss_vs_gl.inc create mode 100644 src/extras/shaders/neoRimSkin_gl.inc create mode 100644 src/extras/shaders/neoRim_gl.inc create mode 100644 src/extras/shaders/neoVehicle_fs_gl.inc create mode 100644 src/extras/shaders/neoVehicle_vs_gl.inc create mode 100644 src/extras/shaders/neoWorldIII_fs_gl.inc create mode 100644 src/extras/shaders/simple_fs_gl.inc (limited to 'src') diff --git a/src/extras/custompipes_gl.cpp b/src/extras/custompipes_gl.cpp index 01663df5..861a831e 100644 --- a/src/extras/custompipes_gl.cpp +++ b/src/extras/custompipes_gl.cpp @@ -134,6 +134,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header) } SetRenderState(SRCBLEND, BLENDSRCALPHA); + setTexture(1, nil); #ifndef RW_GL_USE_VAOS disableAttribPointers(header->attribDesc, header->numAttribs); @@ -158,13 +159,8 @@ CreateVehiclePipe(void) { -#ifdef RW_GLES2 -#include "gl2_shaders/neoVehicle_fs_gl2.inc" -#include "gl2_shaders/neoVehicle_vs_gl2.inc" -#else -#include "shaders/neoVehicle_fs_gl3.inc" -#include "shaders/neoVehicle_vs_gl3.inc" -#endif +#include "shaders/neoVehicle_fs_gl.inc" +#include "shaders/neoVehicle_vs_gl.inc" const char *vs[] = { shaderDecl, header_vert_src, neoVehicle_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, neoVehicle_frag_src, nil }; neoVehicleShader = Shader::create(vs, fs); @@ -256,6 +252,7 @@ worldRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header) drawInst(header, inst); inst++; } + setTexture(1, nil); #ifndef RW_GL_USE_VAOS disableAttribPointers(header->attribDesc, header->numAttribs); #endif @@ -273,13 +270,8 @@ CreateWorldPipe(void) ReadTweakValueTable((char*)work_buff, WorldLightmapBlend); { -#ifdef RW_GLES2 -#include "gl2_shaders/neoWorldIII_fs_gl2.inc" -#include "gl2_shaders/default_UV2_gl2.inc" -#else -#include "shaders/neoWorldIII_fs_gl3.inc" -#include "shaders/default_UV2_gl3.inc" -#endif +#include "shaders/neoWorldIII_fs_gl.inc" +#include "shaders/default_UV2_gl.inc" const char *vs[] = { shaderDecl, header_vert_src, default_UV2_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, neoWorldIII_frag_src, nil }; neoWorldShader = Shader::create(vs, fs); @@ -381,13 +373,8 @@ CreateGlossPipe(void) using namespace rw::gl3; { -#ifdef RW_GLES2 -#include "gl2_shaders/neoGloss_fs_gl2.inc" -#include "gl2_shaders/neoGloss_vs_gl2.inc" -#else -#include "shaders/neoGloss_fs_gl3.inc" -#include "shaders/neoGloss_vs_gl3.inc" -#endif +#include "shaders/neoGloss_fs_gl.inc" +#include "shaders/neoGloss_vs_gl.inc" const char *vs[] = { shaderDecl, header_vert_src, neoGloss_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, neoGloss_frag_src, nil }; neoGlossShader = Shader::create(vs, fs); @@ -558,13 +545,8 @@ CreateRimLightPipes(void) } { -#ifdef RW_GLES2 -#include "gl2_shaders/simple_fs_gl2.inc" -#include "gl2_shaders/neoRimSkin_gl2.inc" -#else -#include "shaders/simple_fs_gl3.inc" -#include "shaders/neoRimSkin_gl3.inc" -#endif +#include "shaders/simple_fs_gl.inc" +#include "shaders/neoRimSkin_gl.inc" const char *vs[] = { shaderDecl, header_vert_src, neoRimSkin_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil }; neoRimSkinShader = Shader::create(vs, fs); @@ -572,13 +554,8 @@ CreateRimLightPipes(void) } { -#ifdef RW_GLES2 -#include "gl2_shaders/simple_fs_gl2.inc" -#include "gl2_shaders/neoRim_gl2.inc" -#else -#include "shaders/simple_fs_gl3.inc" -#include "shaders/neoRim_gl3.inc" -#endif +#include "shaders/simple_fs_gl.inc" +#include "shaders/neoRim_gl.inc" const char *vs[] = { shaderDecl, header_vert_src, neoRim_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil }; neoRimShader = Shader::create(vs, fs); diff --git a/src/extras/postfx.cpp b/src/extras/postfx.cpp index 6355dfb1..fe481658 100644 --- a/src/extras/postfx.cpp +++ b/src/extras/postfx.cpp @@ -150,13 +150,8 @@ CPostFX::Open(RwCamera *cam) #ifdef RW_OPENGL using namespace rw::gl3; { -#ifdef RW_GLES2 -#include "gl2_shaders/im2d_gl2.inc" -#include "gl2_shaders/colourfilterIII_fs_gl2.inc" -#else -#include "shaders/im2d_gl3.inc" -#include "shaders/colourfilterIII_fs_gl3.inc" -#endif +#include "shaders/im2d_gl.inc" +#include "shaders/colourfilterIII_fs_gl.inc" const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, colourfilterIII_frag_src, nil }; colourFilterIII = Shader::create(vs, fs); @@ -164,17 +159,12 @@ CPostFX::Open(RwCamera *cam) } { -#ifdef RW_GLES2 -#include "gl2_shaders/im2d_gl2.inc" -#include "gl2_shaders/contrast_fs_gl2.inc" -#else -#include "shaders/im2d_gl3.inc" -#include "shaders/contrast_fs_gl3.inc" +#include "shaders/im2d_gl.inc" +#include "shaders/contrast_fs_gl.inc" const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil }; contrast = Shader::create(vs, fs); assert(contrast); -#endif } #endif diff --git a/src/extras/shaders/Makefile b/src/extras/shaders/Makefile index 6cbbf237..4b6027e2 100644 --- a/src/extras/shaders/Makefile +++ b/src/extras/shaders/Makefile @@ -1,68 +1,68 @@ -all: im2d_gl3.inc simple_fs_gl3.inc default_UV2_gl3.inc \ - colourfilterIII_fs_gl3.inc contrast_fs_gl3.inc \ - neoRim_gl3.inc neoRimSkin_gl3.inc \ - neoWorldIII_fs_gl3.inc neoGloss_vs_gl3.inc neoGloss_fs_gl3.inc \ - neoVehicle_vs_gl3.inc neoVehicle_fs_gl3.inc +all: im2d_gl.inc simple_fs_gl.inc default_UV2_gl.inc \ + colourfilterIII_fs_gl.inc contrast_fs_gl.inc \ + neoRim_gl.inc neoRimSkin_gl.inc \ + neoWorldIII_fs_gl.inc neoGloss_vs_gl.inc neoGloss_fs_gl.inc \ + neoVehicle_vs_gl.inc neoVehicle_fs_gl.inc -im2d_gl3.inc: im2d.vert +im2d_gl.inc: im2d.vert (echo 'const char *im2d_vert_src =';\ sed 's/..*/"&\\n"/' im2d.vert;\ - echo ';') >im2d_gl3.inc + echo ';') >im2d_gl.inc -simple_fs_gl3.inc: simple.frag +simple_fs_gl.inc: simple.frag (echo 'const char *simple_frag_src =';\ sed 's/..*/"&\\n"/' simple.frag;\ - echo ';') >simple_fs_gl3.inc + echo ';') >simple_fs_gl.inc -default_UV2_gl3.inc: default_UV2.vert +default_UV2_gl.inc: default_UV2.vert (echo 'const char *default_UV2_vert_src =';\ sed 's/..*/"&\\n"/' default_UV2.vert;\ - echo ';') >default_UV2_gl3.inc + echo ';') >default_UV2_gl.inc -colourfilterIII_fs_gl3.inc: colourfilterIII.frag +colourfilterIII_fs_gl.inc: colourfilterIII.frag (echo 'const char *colourfilterIII_frag_src =';\ sed 's/..*/"&\\n"/' colourfilterIII.frag;\ - echo ';') >colourfilterIII_fs_gl3.inc + echo ';') >colourfilterIII_fs_gl.inc -contrast_fs_gl3.inc: contrast.frag +contrast_fs_gl.inc: contrast.frag (echo 'const char *contrast_frag_src =';\ sed 's/..*/"&\\n"/' contrast.frag;\ - echo ';') >contrast_fs_gl3.inc + echo ';') >contrast_fs_gl.inc -neoRim_gl3.inc: neoRim.vert +neoRim_gl.inc: neoRim.vert (echo 'const char *neoRim_vert_src =';\ sed 's/..*/"&\\n"/' neoRim.vert;\ - echo ';') >neoRim_gl3.inc + echo ';') >neoRim_gl.inc -neoRimSkin_gl3.inc: neoRimSkin.vert +neoRimSkin_gl.inc: neoRimSkin.vert (echo 'const char *neoRimSkin_vert_src =';\ sed 's/..*/"&\\n"/' neoRimSkin.vert;\ - echo ';') >neoRimSkin_gl3.inc + echo ';') >neoRimSkin_gl.inc -neoWorldIII_fs_gl3.inc: neoWorldIII.frag +neoWorldIII_fs_gl.inc: neoWorldIII.frag (echo 'const char *neoWorldIII_frag_src =';\ sed 's/..*/"&\\n"/' neoWorldIII.frag;\ - echo ';') >neoWorldIII_fs_gl3.inc + echo ';') >neoWorldIII_fs_gl.inc -neoGloss_fs_gl3.inc: neoGloss.frag +neoGloss_fs_gl.inc: neoGloss.frag (echo 'const char *neoGloss_frag_src =';\ sed 's/..*/"&\\n"/' neoGloss.frag;\ - echo ';') >neoGloss_fs_gl3.inc + echo ';') >neoGloss_fs_gl.inc -neoGloss_vs_gl3.inc: neoGloss.vert +neoGloss_vs_gl.inc: neoGloss.vert (echo 'const char *neoGloss_vert_src =';\ sed 's/..*/"&\\n"/' neoGloss.vert;\ - echo ';') >neoGloss_vs_gl3.inc + echo ';') >neoGloss_vs_gl.inc -neoVehicle_vs_gl3.inc: neoVehicle.vert +neoVehicle_vs_gl.inc: neoVehicle.vert (echo 'const char *neoVehicle_vert_src =';\ sed 's/..*/"&\\n"/' neoVehicle.vert;\ - echo ';') >neoVehicle_vs_gl3.inc + echo ';') >neoVehicle_vs_gl.inc -neoVehicle_fs_gl3.inc: neoVehicle.frag +neoVehicle_fs_gl.inc: neoVehicle.frag (echo 'const char *neoVehicle_frag_src =';\ sed 's/..*/"&\\n"/' neoVehicle.frag;\ - echo ';') >neoVehicle_fs_gl3.inc + echo ';') >neoVehicle_fs_gl.inc diff --git a/src/extras/shaders/colourfilterIII.frag b/src/extras/shaders/colourfilterIII.frag index 4c9a8400..b41cb94a 100644 --- a/src/extras/shaders/colourfilterIII.frag +++ b/src/extras/shaders/colourfilterIII.frag @@ -1,11 +1,9 @@ uniform sampler2D tex0; uniform vec4 u_blurcolor; -in vec4 v_color; -in vec2 v_tex0; -in float v_fog; - -out vec4 color; +FSIN vec4 v_color; +FSIN vec2 v_tex0; +FSIN float v_fog; void main(void) @@ -17,7 +15,10 @@ main(void) vec4 tmp = dst*(1.0-a) + prev*u_blurcolor*a; prev = clamp(tmp, 0.0, 1.0); } + vec4 color; color.rgb = prev.rgb; color.a = 1.0f; + + FRAGCOLOR(color); } diff --git a/src/extras/shaders/colourfilterIII_fs_gl.inc b/src/extras/shaders/colourfilterIII_fs_gl.inc new file mode 100644 index 00000000..6fd1935b --- /dev/null +++ b/src/extras/shaders/colourfilterIII_fs_gl.inc @@ -0,0 +1,26 @@ +const char *colourfilterIII_frag_src = +"uniform sampler2D tex0;\n" +"uniform vec4 u_blurcolor;\n" + +"FSIN vec4 v_color;\n" +"FSIN vec2 v_tex0;\n" +"FSIN float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" float a = u_blurcolor.a;\n" +" vec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" vec4 prev = dst;\n" +" for(int i = 0; i < 5; i++){\n" +" vec4 tmp = dst*(1.0-a) + prev*u_blurcolor*a;\n" +" prev = clamp(tmp, 0.0, 1.0);\n" +" }\n" +" vec4 color;\n" +" color.rgb = prev.rgb;\n" +" color.a = 1.0f;\n" + +" FRAGCOLOR(color);\n" +"}\n" + +; diff --git a/src/extras/shaders/contrast.frag b/src/extras/shaders/contrast.frag index d6dec478..1b93f6fe 100644 --- a/src/extras/shaders/contrast.frag +++ b/src/extras/shaders/contrast.frag @@ -2,17 +2,18 @@ uniform sampler2D tex0; uniform vec3 u_contrastAdd; uniform vec3 u_contrastMult; -in vec4 v_color; -in vec2 v_tex0; -in float v_fog; - -out vec4 color; +FSIN vec4 v_color; +FSIN vec2 v_tex0; +FSIN float v_fog; void main(void) { vec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); + vec4 color; color.rgb = dst.rgb*u_contrastMult + u_contrastAdd; color.a = 1.0f; + + FRAGCOLOR(color); } diff --git a/src/extras/shaders/contrast_fs_gl.inc b/src/extras/shaders/contrast_fs_gl.inc new file mode 100644 index 00000000..97f78194 --- /dev/null +++ b/src/extras/shaders/contrast_fs_gl.inc @@ -0,0 +1,21 @@ +const char *contrast_frag_src = +"uniform sampler2D tex0;\n" +"uniform vec3 u_contrastAdd;\n" +"uniform vec3 u_contrastMult;\n" + +"FSIN vec4 v_color;\n" +"FSIN vec2 v_tex0;\n" +"FSIN float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" vec4 color;\n" +" color.rgb = dst.rgb*u_contrastMult + u_contrastAdd;\n" +" color.a = 1.0f;\n" + +" FRAGCOLOR(color);\n" +"}\n" + +; diff --git a/src/extras/shaders/default_UV2.vert b/src/extras/shaders/default_UV2.vert index 3dbad20f..694c012b 100644 --- a/src/extras/shaders/default_UV2.vert +++ b/src/extras/shaders/default_UV2.vert @@ -1,13 +1,9 @@ -layout(location = 0) in vec3 in_pos; -layout(location = 1) in vec3 in_normal; -layout(location = 2) in vec4 in_color; -layout(location = 3) in vec2 in_tex0; -layout(location = 4) in vec2 in_tex1; +VSIN(ATTRIB_POS) vec3 in_pos; -out vec4 v_color; -out vec2 v_tex0; -out vec2 v_tex1; -out float v_fog; +VSOUT vec4 v_color; +VSOUT vec2 v_tex0; +VSOUT vec2 v_tex1; +VSOUT float v_fog; void main(void) diff --git a/src/extras/shaders/default_UV2_gl.inc b/src/extras/shaders/default_UV2_gl.inc new file mode 100644 index 00000000..450f3d9a --- /dev/null +++ b/src/extras/shaders/default_UV2_gl.inc @@ -0,0 +1,27 @@ +const char *default_UV2_vert_src = +"VSIN(ATTRIB_POS) vec3 in_pos;\n" + +"VSOUT vec4 v_color;\n" +"VSOUT vec2 v_tex0;\n" +"VSOUT vec2 v_tex1;\n" +"VSOUT float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" +" gl_Position = u_proj * u_view * Vertex;\n" +" vec3 Normal = mat3(u_world) * in_normal;\n" + +" v_tex0 = in_tex0;\n" +" v_tex1 = in_tex1;\n" + +" v_color = in_color;\n" +" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" +" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n" +" v_color = clamp(v_color, 0.0, 1.0);\n" +" v_color *= u_matColor;\n" + +" v_fog = DoFog(gl_Position.w);\n" +"}\n" +; diff --git a/src/extras/shaders/im2d.vert b/src/extras/shaders/im2d.vert index 241593b1..fcd81c2c 100644 --- a/src/extras/shaders/im2d.vert +++ b/src/extras/shaders/im2d.vert @@ -1,12 +1,10 @@ uniform vec4 u_xform; -layout(location = 0) in vec4 in_pos; -layout(location = 2) in vec4 in_color; -layout(location = 3) in vec2 in_tex0; +VSIN(ATTRIB_POS) vec4 in_pos; -out vec4 v_color; -out vec2 v_tex0; -out float v_fog; +VSOUT vec4 v_color; +VSOUT vec2 v_tex0; +VSOUT float v_fog; void main(void) diff --git a/src/extras/shaders/im2d_gl.inc b/src/extras/shaders/im2d_gl.inc new file mode 100644 index 00000000..d11f5d33 --- /dev/null +++ b/src/extras/shaders/im2d_gl.inc @@ -0,0 +1,21 @@ +const char *im2d_vert_src = +"uniform vec4 u_xform;\n" + +"VSIN(ATTRIB_POS) vec4 in_pos;\n" + +"VSOUT vec4 v_color;\n" +"VSOUT vec2 v_tex0;\n" +"VSOUT float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" gl_Position = in_pos;\n" +" gl_Position.w = 1.0;\n" +" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n" +" v_fog = DoFog(gl_Position.z);\n" +" gl_Position.xyz *= gl_Position.w;\n" +" v_color = in_color;\n" +" v_tex0 = in_tex0;\n" +"}\n" +; diff --git a/src/extras/shaders/neoGloss.frag b/src/extras/shaders/neoGloss.frag index 14ef0e15..4f097b0b 100644 --- a/src/extras/shaders/neoGloss.frag +++ b/src/extras/shaders/neoGloss.frag @@ -4,17 +4,15 @@ uniform vec4 u_reflProps; #define glossMult (u_reflProps.x) -in vec3 v_normal; -in vec3 v_light; -in vec2 v_tex0; -in float v_fog; - -out vec4 color; +FSIN vec3 v_normal; +FSIN vec3 v_light; +FSIN vec2 v_tex0; +FSIN float v_fog; void main(void) { - color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); + vec4 color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); vec3 n = 2.0*v_normal-1.0; // unpack vec3 v = 2.0*v_light-1.0; // @@ -22,5 +20,7 @@ main(void) color = s*s*s*s*s*s*s*s*color*v_fog*glossMult; DoAlphaTest(color.a); + + FRAGCOLOR(color); } diff --git a/src/extras/shaders/neoGloss.vert b/src/extras/shaders/neoGloss.vert index 78dd1b33..41102f3f 100644 --- a/src/extras/shaders/neoGloss.vert +++ b/src/extras/shaders/neoGloss.vert @@ -1,15 +1,11 @@ uniform vec3 u_eye; +VSIN(ATTRIB_POS) vec3 in_pos; -layout(location = 0) in vec3 in_pos; -layout(location = 1) in vec3 in_normal; -layout(location = 2) in vec4 in_color; -layout(location = 3) in vec2 in_tex0; - -out vec3 v_normal; -out vec3 v_light; -out vec2 v_tex0; -out float v_fog; +VSOUT vec3 v_normal; +VSOUT vec3 v_light; +VSOUT vec2 v_tex0; +VSOUT float v_fog; void main(void) diff --git a/src/extras/shaders/neoGloss_fs_gl.inc b/src/extras/shaders/neoGloss_fs_gl.inc new file mode 100644 index 00000000..67e9724e --- /dev/null +++ b/src/extras/shaders/neoGloss_fs_gl.inc @@ -0,0 +1,28 @@ +const char *neoGloss_frag_src = +"uniform sampler2D tex0;\n" + +"uniform vec4 u_reflProps;\n" + +"#define glossMult (u_reflProps.x)\n" + +"FSIN vec3 v_normal;\n" +"FSIN vec3 v_light;\n" +"FSIN vec2 v_tex0;\n" +"FSIN float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" vec3 n = 2.0*v_normal-1.0; // unpack\n" +" vec3 v = 2.0*v_light-1.0; //\n" + +" float s = dot(n, v);\n" +" color = s*s*s*s*s*s*s*s*color*v_fog*glossMult;\n" + +" DoAlphaTest(color.a);\n" + +" FRAGCOLOR(color);\n" +"}\n" + +; diff --git a/src/extras/shaders/neoGloss_vs_gl.inc b/src/extras/shaders/neoGloss_vs_gl.inc new file mode 100644 index 00000000..dffb423f --- /dev/null +++ b/src/extras/shaders/neoGloss_vs_gl.inc @@ -0,0 +1,27 @@ +const char *neoGloss_vert_src = +"uniform vec3 u_eye;\n" + +"VSIN(ATTRIB_POS) vec3 in_pos;\n" + +"VSOUT vec3 v_normal;\n" +"VSOUT vec3 v_light;\n" +"VSOUT vec2 v_tex0;\n" +"VSOUT float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" +" gl_Position = u_proj * u_view * Vertex;\n" +" vec3 Normal = mat3(u_world) * in_normal;\n" + +" v_tex0 = in_tex0;\n" + +" vec3 viewVec = normalize(u_eye - Vertex.xyz);\n" +" vec3 Light = normalize(viewVec - u_lightDirection[0].xyz);\n" +" v_normal = 0.5*(1.0 + vec3(0.0, 0.0, 1.0)); // compress\n" +" v_light = 0.5*(1.0 + Light); //\n" + +" v_fog = DoFog(gl_Position.w);\n" +"}\n" +; diff --git a/src/extras/shaders/neoRim.vert b/src/extras/shaders/neoRim.vert index 4a2b545f..81ee1090 100644 --- a/src/extras/shaders/neoRim.vert +++ b/src/extras/shaders/neoRim.vert @@ -3,14 +3,11 @@ uniform vec4 u_rampStart; uniform vec4 u_rampEnd; uniform vec3 u_rimData; -layout(location = 0) in vec3 in_pos; -layout(location = 1) in vec3 in_normal; -layout(location = 2) in vec4 in_color; -layout(location = 3) in vec2 in_tex0; - -out vec4 v_color; -out vec2 v_tex0; -out float v_fog; +VSIN(ATTRIB_POS) vec3 in_pos; + +VSOUT vec4 v_color; +VSOUT vec2 v_tex0; +VSOUT float v_fog; void main(void) diff --git a/src/extras/shaders/neoRimSkin.vert b/src/extras/shaders/neoRimSkin.vert index f16f2310..1515ad71 100644 --- a/src/extras/shaders/neoRimSkin.vert +++ b/src/extras/shaders/neoRimSkin.vert @@ -5,16 +5,11 @@ uniform vec4 u_rampStart; uniform vec4 u_rampEnd; uniform vec3 u_rimData; -layout(location = 0) in vec3 in_pos; -layout(location = 1) in vec3 in_normal; -layout(location = 2) in vec4 in_color; -layout(location = 3) in vec2 in_tex0; -layout(location = 11) in vec4 in_weights; -layout(location = 12) in vec4 in_indices; - -out vec4 v_color; -out vec2 v_tex0; -out float v_fog; +VSIN(ATTRIB_POS) vec3 in_pos; + +VSOUT vec4 v_color; +VSOUT vec2 v_tex0; +VSOUT float v_fog; void main(void) diff --git a/src/extras/shaders/neoRimSkin_gl.inc b/src/extras/shaders/neoRimSkin_gl.inc new file mode 100644 index 00000000..01b739b2 --- /dev/null +++ b/src/extras/shaders/neoRimSkin_gl.inc @@ -0,0 +1,45 @@ +const char *neoRimSkin_vert_src = +"uniform mat4 u_boneMatrices[64];\n" + +"uniform vec3 u_viewVec;\n" +"uniform vec4 u_rampStart;\n" +"uniform vec4 u_rampEnd;\n" +"uniform vec3 u_rimData;\n" + +"VSIN(ATTRIB_POS) vec3 in_pos;\n" + +"VSOUT vec4 v_color;\n" +"VSOUT vec2 v_tex0;\n" +"VSOUT float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec3 SkinVertex = vec3(0.0, 0.0, 0.0);\n" +" vec3 SkinNormal = vec3(0.0, 0.0, 0.0);\n" +" for(int i = 0; i < 4; i++){\n" +" SkinVertex += (u_boneMatrices[int(in_indices[i])] * vec4(in_pos, 1.0)).xyz * in_weights[i];\n" +" SkinNormal += (mat3(u_boneMatrices[int(in_indices[i])]) * in_normal) * in_weights[i];\n" +" }\n" + +" vec4 Vertex = u_world * vec4(SkinVertex, 1.0);\n" +" gl_Position = u_proj * u_view * Vertex;\n" +" vec3 Normal = mat3(u_world) * SkinNormal;\n" + +" v_tex0 = in_tex0;\n" + +" v_color = in_color;\n" +" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" +" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n" + +" // rim light\n" +" float f = u_rimData.x - u_rimData.y*dot(Normal, u_viewVec);\n" +" vec4 rimlight = clamp(mix(u_rampEnd, u_rampStart, f)*u_rimData.z, 0.0, 1.0);\n" +" v_color.rgb += rimlight.rgb;\n" + +" v_color = clamp(v_color, 0.0, 1.0);\n" +" v_color *= u_matColor;\n" + +" v_fog = DoFog(gl_Position.z);\n" +"}\n" +; diff --git a/src/extras/shaders/neoRim_gl.inc b/src/extras/shaders/neoRim_gl.inc new file mode 100644 index 00000000..7cd199d0 --- /dev/null +++ b/src/extras/shaders/neoRim_gl.inc @@ -0,0 +1,36 @@ +const char *neoRim_vert_src = +"uniform vec3 u_viewVec;\n" +"uniform vec4 u_rampStart;\n" +"uniform vec4 u_rampEnd;\n" +"uniform vec3 u_rimData;\n" + +"VSIN(ATTRIB_POS) vec3 in_pos;\n" + +"VSOUT vec4 v_color;\n" +"VSOUT vec2 v_tex0;\n" +"VSOUT float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" +" gl_Position = u_proj * u_view * Vertex;\n" +" vec3 Normal = mat3(u_world) * in_normal;\n" + +" v_tex0 = in_tex0;\n" + +" v_color = in_color;\n" +" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" +" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n" + +" // rim light\n" +" float f = u_rimData.x - u_rimData.y*dot(Normal, u_viewVec);\n" +" vec4 rimlight = clamp(mix(u_rampEnd, u_rampStart, f)*u_rimData.z, 0.0, 1.0);\n" +" v_color.rgb += rimlight.rgb;\n" + +" v_color = clamp(v_color, 0.0, 1.0);\n" +" v_color *= u_matColor;\n" + +" v_fog = DoFog(gl_Position.w);\n" +"}\n" +; diff --git a/src/extras/shaders/neoVehicle.frag b/src/extras/shaders/neoVehicle.frag index 96d4a632..2ac24f70 100644 --- a/src/extras/shaders/neoVehicle.frag +++ b/src/extras/shaders/neoVehicle.frag @@ -1,13 +1,11 @@ uniform sampler2D tex0; uniform sampler2D tex1; -in vec4 v_color; -in vec4 v_reflcolor; -in vec2 v_tex0; -in vec2 v_tex1; -in float v_fog; - -out vec4 color; +FSIN vec4 v_color; +FSIN vec4 v_reflcolor; +FSIN vec2 v_tex0; +FSIN vec2 v_tex1; +FSIN float v_fog; void main(void) @@ -20,9 +18,12 @@ main(void) vec3 pass2 = v_reflcolor.rgb * v_fog; + vec4 color; color.rgb = pass1.rgb*pass1.a + pass2; color.a = pass1.a; // color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); DoAlphaTest(color.a); + + FRAGCOLOR(color); } diff --git a/src/extras/shaders/neoVehicle.vert b/src/extras/shaders/neoVehicle.vert index f2f54d6d..f0224ddb 100644 --- a/src/extras/shaders/neoVehicle.vert +++ b/src/extras/shaders/neoVehicle.vert @@ -8,16 +8,13 @@ uniform vec4 u_specColor[5]; #define shininess (u_reflProps.z) #define specularity (u_reflProps.w) -layout(location = 0) in vec3 in_pos; -layout(location = 1) in vec3 in_normal; -layout(location = 2) in vec4 in_color; -layout(location = 3) in vec2 in_tex0; - -out vec4 v_color; -out vec4 v_reflcolor; -out vec2 v_tex0; -out vec2 v_tex1; -out float v_fog; +VSIN(ATTRIB_POS) vec3 in_pos; + +VSOUT vec4 v_color; +VSOUT vec4 v_reflcolor; +VSOUT vec2 v_tex0; +VSOUT vec2 v_tex1; +VSOUT float v_fog; vec3 DoDirLightSpec(vec3 Ldir, vec3 Lcol, vec3 N, vec3 V, float power) { diff --git a/src/extras/shaders/neoVehicle_fs_gl.inc b/src/extras/shaders/neoVehicle_fs_gl.inc new file mode 100644 index 00000000..20537440 --- /dev/null +++ b/src/extras/shaders/neoVehicle_fs_gl.inc @@ -0,0 +1,31 @@ +const char *neoVehicle_frag_src = +"uniform sampler2D tex0;\n" +"uniform sampler2D tex1;\n" + +"FSIN vec4 v_color;\n" +"FSIN vec4 v_reflcolor;\n" +"FSIN vec2 v_tex0;\n" +"FSIN vec2 v_tex1;\n" +"FSIN float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 pass1 = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" vec3 envmap = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y)).rgb;\n" +" pass1.rgb = mix(pass1.rgb, envmap, v_reflcolor.a);\n" +" pass1.rgb = mix(u_fogColor.rgb, pass1.rgb, v_fog);\n" +"// pass1.rgb += v_reflcolor.rgb * v_fog;\n" + +" vec3 pass2 = v_reflcolor.rgb * v_fog;\n" + +" vec4 color;\n" +" color.rgb = pass1.rgb*pass1.a + pass2;\n" +" color.a = pass1.a;\n" + +"// color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" +" DoAlphaTest(color.a);\n" + +" FRAGCOLOR(color);\n" +"}\n" +; diff --git a/src/extras/shaders/neoVehicle_vs_gl.inc b/src/extras/shaders/neoVehicle_vs_gl.inc new file mode 100644 index 00000000..b7b42622 --- /dev/null +++ b/src/extras/shaders/neoVehicle_vs_gl.inc @@ -0,0 +1,53 @@ +const char *neoVehicle_vert_src = +"uniform vec3 u_eye;\n" +"uniform vec4 u_reflProps;\n" +"uniform vec4 u_specDir[5];\n" +"uniform vec4 u_specColor[5];\n" + +"#define fresnel (u_reflProps.x)\n" +"#define lightStrength (u_reflProps.y) // speclight alpha\n" +"#define shininess (u_reflProps.z)\n" +"#define specularity (u_reflProps.w)\n" + +"VSIN(ATTRIB_POS) vec3 in_pos;\n" + +"VSOUT vec4 v_color;\n" +"VSOUT vec4 v_reflcolor;\n" +"VSOUT vec2 v_tex0;\n" +"VSOUT vec2 v_tex1;\n" +"VSOUT float v_fog;\n" + +"vec3 DoDirLightSpec(vec3 Ldir, vec3 Lcol, vec3 N, vec3 V, float power)\n" +"{\n" +" return pow(clamp(dot(N, normalize(V + -Ldir)), 0.0, 1.0), power)*Lcol;\n" +"}\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" +" gl_Position = u_proj * u_view * Vertex;\n" +" vec3 Normal = mat3(u_world) * in_normal;\n" +" vec3 viewVec = normalize(u_eye - Vertex.xyz);\n" + +" v_tex0 = in_tex0;\n" + +" v_color = in_color;\n" +" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" +" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse*lightStrength;\n" +" v_color = clamp(v_color, 0.0, 1.0);\n" +" v_color *= u_matColor;\n" + +" // reflect V along Normal\n" +" vec3 uv2 = Normal*dot(viewVec, Normal)*2.0 - viewVec;\n" +" v_tex1 = uv2.xy*0.5 + 0.5;\n" +" float b = 1.0 - clamp(dot(viewVec, Normal), 0.0, 1.0);\n" +" v_reflcolor = vec4(0.0, 0.0, 0.0, 1.0);\n" +" v_reflcolor.a = mix(b*b*b*b*b, 1.0f, fresnel)*shininess;\n" + +" for(int i = 0; i < 5; i++)\n" +" v_reflcolor.rgb += DoDirLightSpec(u_specDir[i].xyz, u_specColor[i].rgb, Normal, viewVec, u_specDir[i].w)*specularity*lightStrength;\n" + +" v_fog = DoFog(gl_Position.w);\n" +"}\n" +; diff --git a/src/extras/shaders/neoWorldIII.frag b/src/extras/shaders/neoWorldIII.frag index 4c5571ee..d8bb7159 100644 --- a/src/extras/shaders/neoWorldIII.frag +++ b/src/extras/shaders/neoWorldIII.frag @@ -3,12 +3,10 @@ uniform sampler2D tex1; uniform vec4 u_lightMap; -in vec4 v_color; -in vec2 v_tex0; -in vec2 v_tex1; -in float v_fog; - -out vec4 color; +FSIN vec4 v_color; +FSIN vec2 v_tex0; +FSIN vec2 v_tex1; +FSIN float v_fog; void main(void) @@ -16,10 +14,12 @@ main(void) vec4 t0 = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); vec4 t1 = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y)); - color = t0*v_color*(1 + u_lightMap*(2*t1-1)); + vec4 color = t0*v_color*(1.0 + u_lightMap*(2.0*t1-1.0)); color.a = v_color.a*t0.a*u_lightMap.a; color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); DoAlphaTest(color.a); + + FRAGCOLOR(color); } diff --git a/src/extras/shaders/neoWorldIII_fs_gl.inc b/src/extras/shaders/neoWorldIII_fs_gl.inc new file mode 100644 index 00000000..afd75f57 --- /dev/null +++ b/src/extras/shaders/neoWorldIII_fs_gl.inc @@ -0,0 +1,27 @@ +const char *neoWorldIII_frag_src = +"uniform sampler2D tex0;\n" +"uniform sampler2D tex1;\n" + +"uniform vec4 u_lightMap;\n" + +"FSIN vec4 v_color;\n" +"FSIN vec2 v_tex0;\n" +"FSIN vec2 v_tex1;\n" +"FSIN float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 t0 = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" vec4 t1 = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n" + +" vec4 color = t0*v_color*(1.0 + u_lightMap*(2.0*t1-1.0));\n" +" color.a = v_color.a*t0.a*u_lightMap.a;\n" + +" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" +" DoAlphaTest(color.a);\n" + +" FRAGCOLOR(color);\n" +"}\n" + +; diff --git a/src/extras/shaders/simple.frag b/src/extras/shaders/simple.frag index 87157beb..c85bf089 100644 --- a/src/extras/shaders/simple.frag +++ b/src/extras/shaders/simple.frag @@ -1,16 +1,17 @@ uniform sampler2D tex0; -in vec4 v_color; -in vec2 v_tex0; -in float v_fog; - -out vec4 color; +FSIN vec4 v_color; +FSIN vec2 v_tex0; +FSIN float v_fog; void main(void) { + vec4 color; color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); DoAlphaTest(color.a); + + FRAGCOLOR(color); } diff --git a/src/extras/shaders/simple_fs_gl.inc b/src/extras/shaders/simple_fs_gl.inc new file mode 100644 index 00000000..614d79a0 --- /dev/null +++ b/src/extras/shaders/simple_fs_gl.inc @@ -0,0 +1,19 @@ +const char *simple_frag_src = +"uniform sampler2D tex0;\n" + +"FSIN vec4 v_color;\n" +"FSIN vec2 v_tex0;\n" +"FSIN float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 color;\n" +" color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" +" DoAlphaTest(color.a);\n" + +" FRAGCOLOR(color);\n" +"}\n" + +; diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 460b8211..64a37421 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -935,16 +935,3 @@ RtCharset *RtCharsetSetColors(RtCharset * charSet, const RwRGBA * foreGround, RtCharset *RtCharsetGetDesc(RtCharset * charset, RtCharsetDesc * desc) { *desc = charset->desc; return charset; } RtCharset *RtCharsetCreate(const RwRGBA * foreGround, const RwRGBA * backGround) { return Charset::create(foreGround, backGround); } RwBool RtCharsetDestroy(RtCharset * charSet) { charSet->destroy(); return true; } - - - -// fake shit -RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags) -{ -#ifdef RW_GL3 - if(flags & (rwRASTERFORMATPAL8 | rwRASTERFORMAT8888)) - return 'NOPE'; - return 'YUP'; -#endif - return flags & 0xF00; -} diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 33d9a4cb..0a0ed04b 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -150,11 +150,80 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict) } #ifdef GTA_PC -#ifdef RWLIBS -extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); -#else -RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); + +#ifdef LIBRW + +#define CAPSVERSION 0 + +struct GPUcaps +{ + uint32 version; // so we can force regeneration easily + uint32 platform; + uint32 subplatform; + uint32 dxtSupport; +}; + +static void +GetGPUcaps(GPUcaps *caps) +{ + caps->version = CAPSVERSION; + caps->platform = rw::platform; + caps->subplatform = 0; + caps->dxtSupport = 0; + // TODO: more later +#ifdef RW_GL3 + caps->subplatform = rw::gl3::gl3Caps.gles; + caps->dxtSupport = rw::gl3::gl3Caps.dxtSupported; +#endif +#ifdef RW_D3D9 + caps->dxtSupport = 1; // TODO, probably #endif +} + +void +ReadVideoCardCapsFile(GPUcaps *caps) +{ + memset(caps, 0, sizeof(GPUcaps)); + + int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "rb"); + if (file != 0) { + CFileMgr::Read(file, (char*)&caps->version, 4); + CFileMgr::Read(file, (char*)&caps->platform, 4); + CFileMgr::Read(file, (char*)&caps->subplatform, 4); + CFileMgr::Read(file, (char*)&caps->dxtSupport, 4); + CFileMgr::CloseFile(file); + } +} + +bool +CheckVideoCardCaps(void) +{ + GPUcaps caps, fcaps; + GetGPUcaps(&caps); + ReadVideoCardCapsFile(&fcaps); + return caps.version != fcaps.version || + caps.platform != fcaps.platform || + caps.subplatform != fcaps.subplatform || + caps.dxtSupport != fcaps.dxtSupport; +} + +void +WriteVideoCardCapsFile(void) +{ + GPUcaps caps; + GetGPUcaps(&caps); + int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "wb"); + if (file != 0) { + CFileMgr::Write(file, (char*)&caps.version, 4); + CFileMgr::Write(file, (char*)&caps.platform, 4); + CFileMgr::Write(file, (char*)&caps.subplatform, 4); + CFileMgr::Write(file, (char*)&caps.dxtSupport, 4); + CFileMgr::CloseFile(file); + } +} + +#else +extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); void ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8) { @@ -201,6 +270,7 @@ WriteVideoCardCapsFile(void) CFileMgr::CloseFile(file); } } +#endif void ConvertingTexturesScreen(uint32 num, uint32 count, const char *text) @@ -281,6 +351,13 @@ CreateTxdImageForVideoCard() return false; } +#ifdef LIBRW + // so we can read back DXT with GLES + // only works for textures that are not yet loaded + // so let's hope that is the case for all + rw::gl3::needToReadBackTextures = true; +#endif + int32 i; for (i = 0; i < TXDSTORESIZE; i++) { ConvertingTexturesScreen(i, TXDSTORESIZE, "CVT_MSG"); @@ -308,6 +385,9 @@ CreateTxdImageForVideoCard() delete []buf; delete pDir; CStreaming::RemoveTxd(i); +#ifdef LIBRW + rw::gl3::needToReadBackTextures = false; +#endif return false; } @@ -334,6 +414,10 @@ CreateTxdImageForVideoCard() RwStreamClose(img, nil); delete []buf; +#ifdef LIBRW + rw::gl3::needToReadBackTextures = false; +#endif + if (!pDir->WriteDirFile("models\\txd.dir")) { DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR"); delete pDir; -- cgit v1.2.3 From 9826fdf6d5a324b316e59a34feeb0da9ffca56cc Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 18 Nov 2020 11:16:02 +0100 Subject: more fixes to librw stuff --- src/extras/shaders/colourfilterIII_fs_gl3.inc | 25 ------------ src/extras/shaders/contrast_fs_gl3.inc | 20 ---------- src/extras/shaders/default_UV2_gl3.inc | 31 --------------- src/extras/shaders/im2d_gl3.inc | 23 ----------- src/extras/shaders/neoGloss_fs_gl3.inc | 28 -------------- src/extras/shaders/neoGloss_vs_gl3.inc | 31 --------------- src/extras/shaders/neoRimSkin_gl3.inc | 50 ------------------------ src/extras/shaders/neoRim_gl3.inc | 39 ------------------- src/extras/shaders/neoVehicle_fs_gl3.inc | 30 -------------- src/extras/shaders/neoVehicle_vs_gl3.inc | 56 --------------------------- src/extras/shaders/neoWorldIII_fs_gl3.inc | 27 ------------- src/extras/shaders/simple_fs_gl3.inc | 18 --------- src/rw/TexRead.cpp | 6 +-- 13 files changed, 3 insertions(+), 381 deletions(-) delete mode 100644 src/extras/shaders/colourfilterIII_fs_gl3.inc delete mode 100644 src/extras/shaders/contrast_fs_gl3.inc delete mode 100644 src/extras/shaders/default_UV2_gl3.inc delete mode 100644 src/extras/shaders/im2d_gl3.inc delete mode 100644 src/extras/shaders/neoGloss_fs_gl3.inc delete mode 100644 src/extras/shaders/neoGloss_vs_gl3.inc delete mode 100644 src/extras/shaders/neoRimSkin_gl3.inc delete mode 100644 src/extras/shaders/neoRim_gl3.inc delete mode 100644 src/extras/shaders/neoVehicle_fs_gl3.inc delete mode 100644 src/extras/shaders/neoVehicle_vs_gl3.inc delete mode 100644 src/extras/shaders/neoWorldIII_fs_gl3.inc delete mode 100644 src/extras/shaders/simple_fs_gl3.inc (limited to 'src') diff --git a/src/extras/shaders/colourfilterIII_fs_gl3.inc b/src/extras/shaders/colourfilterIII_fs_gl3.inc deleted file mode 100644 index 5530a4fa..00000000 --- a/src/extras/shaders/colourfilterIII_fs_gl3.inc +++ /dev/null @@ -1,25 +0,0 @@ -const char *colourfilterIII_frag_src = -"uniform sampler2D tex0;\n" -"uniform vec4 u_blurcolor;\n" - -"in vec4 v_color;\n" -"in vec2 v_tex0;\n" -"in float v_fog;\n" - -"out vec4 color;\n" - -"void\n" -"main(void)\n" -"{\n" -" float a = u_blurcolor.a;\n" -" vec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" -" vec4 prev = dst;\n" -" for(int i = 0; i < 5; i++){\n" -" vec4 tmp = dst*(1.0-a) + prev*u_blurcolor*a;\n" -" prev = clamp(tmp, 0.0, 1.0);\n" -" }\n" -" color.rgb = prev.rgb;\n" -" color.a = 1.0f;\n" -"}\n" - -; diff --git a/src/extras/shaders/contrast_fs_gl3.inc b/src/extras/shaders/contrast_fs_gl3.inc deleted file mode 100644 index 58aaf079..00000000 --- a/src/extras/shaders/contrast_fs_gl3.inc +++ /dev/null @@ -1,20 +0,0 @@ -const char *contrast_frag_src = -"uniform sampler2D tex0;\n" -"uniform vec3 u_contrastAdd;\n" -"uniform vec3 u_contrastMult;\n" - -"in vec4 v_color;\n" -"in vec2 v_tex0;\n" -"in float v_fog;\n" - -"out vec4 color;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" -" color.rgb = dst.rgb*u_contrastMult + u_contrastAdd;\n" -" color.a = 1.0f;\n" -"}\n" - -; diff --git a/src/extras/shaders/default_UV2_gl3.inc b/src/extras/shaders/default_UV2_gl3.inc deleted file mode 100644 index 14106b29..00000000 --- a/src/extras/shaders/default_UV2_gl3.inc +++ /dev/null @@ -1,31 +0,0 @@ -const char *default_UV2_vert_src = -"layout(location = 0) in vec3 in_pos;\n" -"layout(location = 1) in vec3 in_normal;\n" -"layout(location = 2) in vec4 in_color;\n" -"layout(location = 3) in vec2 in_tex0;\n" -"layout(location = 4) in vec2 in_tex1;\n" - -"out vec4 v_color;\n" -"out vec2 v_tex0;\n" -"out vec2 v_tex1;\n" -"out float v_fog;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" -" gl_Position = u_proj * u_view * Vertex;\n" -" vec3 Normal = mat3(u_world) * in_normal;\n" - -" v_tex0 = in_tex0;\n" -" v_tex1 = in_tex1;\n" - -" v_color = in_color;\n" -" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" -" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n" -" v_color = clamp(v_color, 0.0, 1.0);\n" -" v_color *= u_matColor;\n" - -" v_fog = DoFog(gl_Position.w);\n" -"}\n" -; diff --git a/src/extras/shaders/im2d_gl3.inc b/src/extras/shaders/im2d_gl3.inc deleted file mode 100644 index 68341b39..00000000 --- a/src/extras/shaders/im2d_gl3.inc +++ /dev/null @@ -1,23 +0,0 @@ -const char *im2d_vert_src = -"uniform vec4 u_xform;\n" - -"layout(location = 0) in vec4 in_pos;\n" -"layout(location = 2) in vec4 in_color;\n" -"layout(location = 3) in vec2 in_tex0;\n" - -"out vec4 v_color;\n" -"out vec2 v_tex0;\n" -"out float v_fog;\n" - -"void\n" -"main(void)\n" -"{\n" -" gl_Position = in_pos;\n" -" gl_Position.w = 1.0;\n" -" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n" -" v_fog = DoFog(gl_Position.z);\n" -" gl_Position.xyz *= gl_Position.w;\n" -" v_color = in_color;\n" -" v_tex0 = in_tex0;\n" -"}\n" -; diff --git a/src/extras/shaders/neoGloss_fs_gl3.inc b/src/extras/shaders/neoGloss_fs_gl3.inc deleted file mode 100644 index 736b0c5d..00000000 --- a/src/extras/shaders/neoGloss_fs_gl3.inc +++ /dev/null @@ -1,28 +0,0 @@ -const char *neoGloss_frag_src = -"uniform sampler2D tex0;\n" - -"uniform vec4 u_reflProps;\n" - -"#define glossMult (u_reflProps.x)\n" - -"in vec3 v_normal;\n" -"in vec3 v_light;\n" -"in vec2 v_tex0;\n" -"in float v_fog;\n" - -"out vec4 color;\n" - -"void\n" -"main(void)\n" -"{\n" -" color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" -" vec3 n = 2.0*v_normal-1.0; // unpack\n" -" vec3 v = 2.0*v_light-1.0; //\n" - -" float s = dot(n, v);\n" -" color = s*s*s*s*s*s*s*s*color*v_fog*glossMult;\n" - -" DoAlphaTest(color.a);\n" -"}\n" - -; diff --git a/src/extras/shaders/neoGloss_vs_gl3.inc b/src/extras/shaders/neoGloss_vs_gl3.inc deleted file mode 100644 index 4adc9cb2..00000000 --- a/src/extras/shaders/neoGloss_vs_gl3.inc +++ /dev/null @@ -1,31 +0,0 @@ -const char *neoGloss_vert_src = -"uniform vec3 u_eye;\n" - - -"layout(location = 0) in vec3 in_pos;\n" -"layout(location = 1) in vec3 in_normal;\n" -"layout(location = 2) in vec4 in_color;\n" -"layout(location = 3) in vec2 in_tex0;\n" - -"out vec3 v_normal;\n" -"out vec3 v_light;\n" -"out vec2 v_tex0;\n" -"out float v_fog;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" -" gl_Position = u_proj * u_view * Vertex;\n" -" vec3 Normal = mat3(u_world) * in_normal;\n" - -" v_tex0 = in_tex0;\n" - -" vec3 viewVec = normalize(u_eye - Vertex.xyz);\n" -" vec3 Light = normalize(viewVec - u_lightDirection[0].xyz);\n" -" v_normal = 0.5*(1.0 + vec3(0.0, 0.0, 1.0)); // compress\n" -" v_light = 0.5*(1.0 + Light); //\n" - -" v_fog = DoFog(gl_Position.w);\n" -"}\n" -; diff --git a/src/extras/shaders/neoRimSkin_gl3.inc b/src/extras/shaders/neoRimSkin_gl3.inc deleted file mode 100644 index 70948e1f..00000000 --- a/src/extras/shaders/neoRimSkin_gl3.inc +++ /dev/null @@ -1,50 +0,0 @@ -const char *neoRimSkin_vert_src = -"uniform mat4 u_boneMatrices[64];\n" - -"uniform vec3 u_viewVec;\n" -"uniform vec4 u_rampStart;\n" -"uniform vec4 u_rampEnd;\n" -"uniform vec3 u_rimData;\n" - -"layout(location = 0) in vec3 in_pos;\n" -"layout(location = 1) in vec3 in_normal;\n" -"layout(location = 2) in vec4 in_color;\n" -"layout(location = 3) in vec2 in_tex0;\n" -"layout(location = 11) in vec4 in_weights;\n" -"layout(location = 12) in vec4 in_indices;\n" - -"out vec4 v_color;\n" -"out vec2 v_tex0;\n" -"out float v_fog;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec3 SkinVertex = vec3(0.0, 0.0, 0.0);\n" -" vec3 SkinNormal = vec3(0.0, 0.0, 0.0);\n" -" for(int i = 0; i < 4; i++){\n" -" SkinVertex += (u_boneMatrices[int(in_indices[i])] * vec4(in_pos, 1.0)).xyz * in_weights[i];\n" -" SkinNormal += (mat3(u_boneMatrices[int(in_indices[i])]) * in_normal) * in_weights[i];\n" -" }\n" - -" vec4 Vertex = u_world * vec4(SkinVertex, 1.0);\n" -" gl_Position = u_proj * u_view * Vertex;\n" -" vec3 Normal = mat3(u_world) * SkinNormal;\n" - -" v_tex0 = in_tex0;\n" - -" v_color = in_color;\n" -" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" -" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n" - -" // rim light\n" -" float f = u_rimData.x - u_rimData.y*dot(Normal, u_viewVec);\n" -" vec4 rimlight = clamp(mix(u_rampEnd, u_rampStart, f)*u_rimData.z, 0.0, 1.0);\n" -" v_color.rgb += rimlight.rgb;\n" - -" v_color = clamp(v_color, 0.0, 1.0);\n" -" v_color *= u_matColor;\n" - -" v_fog = DoFog(gl_Position.z);\n" -"}\n" -; diff --git a/src/extras/shaders/neoRim_gl3.inc b/src/extras/shaders/neoRim_gl3.inc deleted file mode 100644 index 7e36e95a..00000000 --- a/src/extras/shaders/neoRim_gl3.inc +++ /dev/null @@ -1,39 +0,0 @@ -const char *neoRim_vert_src = -"uniform vec3 u_viewVec;\n" -"uniform vec4 u_rampStart;\n" -"uniform vec4 u_rampEnd;\n" -"uniform vec3 u_rimData;\n" - -"layout(location = 0) in vec3 in_pos;\n" -"layout(location = 1) in vec3 in_normal;\n" -"layout(location = 2) in vec4 in_color;\n" -"layout(location = 3) in vec2 in_tex0;\n" - -"out vec4 v_color;\n" -"out vec2 v_tex0;\n" -"out float v_fog;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" -" gl_Position = u_proj * u_view * Vertex;\n" -" vec3 Normal = mat3(u_world) * in_normal;\n" - -" v_tex0 = in_tex0;\n" - -" v_color = in_color;\n" -" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" -" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n" - -" // rim light\n" -" float f = u_rimData.x - u_rimData.y*dot(Normal, u_viewVec);\n" -" vec4 rimlight = clamp(mix(u_rampEnd, u_rampStart, f)*u_rimData.z, 0.0, 1.0);\n" -" v_color.rgb += rimlight.rgb;\n" - -" v_color = clamp(v_color, 0.0, 1.0);\n" -" v_color *= u_matColor;\n" - -" v_fog = DoFog(gl_Position.w);\n" -"}\n" -; diff --git a/src/extras/shaders/neoVehicle_fs_gl3.inc b/src/extras/shaders/neoVehicle_fs_gl3.inc deleted file mode 100644 index c75ba717..00000000 --- a/src/extras/shaders/neoVehicle_fs_gl3.inc +++ /dev/null @@ -1,30 +0,0 @@ -const char *neoVehicle_frag_src = -"uniform sampler2D tex0;\n" -"uniform sampler2D tex1;\n" - -"in vec4 v_color;\n" -"in vec4 v_reflcolor;\n" -"in vec2 v_tex0;\n" -"in vec2 v_tex1;\n" -"in float v_fog;\n" - -"out vec4 color;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec4 pass1 = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" -" vec3 envmap = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y)).rgb;\n" -" pass1.rgb = mix(pass1.rgb, envmap, v_reflcolor.a);\n" -" pass1.rgb = mix(u_fogColor.rgb, pass1.rgb, v_fog);\n" -"// pass1.rgb += v_reflcolor.rgb * v_fog;\n" - -" vec3 pass2 = v_reflcolor.rgb * v_fog;\n" - -" color.rgb = pass1.rgb*pass1.a + pass2;\n" -" color.a = pass1.a;\n" - -"// color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" -" DoAlphaTest(color.a);\n" -"}\n" -; diff --git a/src/extras/shaders/neoVehicle_vs_gl3.inc b/src/extras/shaders/neoVehicle_vs_gl3.inc deleted file mode 100644 index 268180e1..00000000 --- a/src/extras/shaders/neoVehicle_vs_gl3.inc +++ /dev/null @@ -1,56 +0,0 @@ -const char *neoVehicle_vert_src = -"uniform vec3 u_eye;\n" -"uniform vec4 u_reflProps;\n" -"uniform vec4 u_specDir[5];\n" -"uniform vec4 u_specColor[5];\n" - -"#define fresnel (u_reflProps.x)\n" -"#define lightStrength (u_reflProps.y) // speclight alpha\n" -"#define shininess (u_reflProps.z)\n" -"#define specularity (u_reflProps.w)\n" - -"layout(location = 0) in vec3 in_pos;\n" -"layout(location = 1) in vec3 in_normal;\n" -"layout(location = 2) in vec4 in_color;\n" -"layout(location = 3) in vec2 in_tex0;\n" - -"out vec4 v_color;\n" -"out vec4 v_reflcolor;\n" -"out vec2 v_tex0;\n" -"out vec2 v_tex1;\n" -"out float v_fog;\n" - -"vec3 DoDirLightSpec(vec3 Ldir, vec3 Lcol, vec3 N, vec3 V, float power)\n" -"{\n" -" return pow(clamp(dot(N, normalize(V + -Ldir)), 0.0, 1.0), power)*Lcol;\n" -"}\n" - -"void\n" -"main(void)\n" -"{\n" -" vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" -" gl_Position = u_proj * u_view * Vertex;\n" -" vec3 Normal = mat3(u_world) * in_normal;\n" -" vec3 viewVec = normalize(u_eye - Vertex.xyz);\n" - -" v_tex0 = in_tex0;\n" - -" v_color = in_color;\n" -" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" -" v_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse*lightStrength;\n" -" v_color = clamp(v_color, 0.0, 1.0);\n" -" v_color *= u_matColor;\n" - -" // reflect V along Normal\n" -" vec3 uv2 = Normal*dot(viewVec, Normal)*2.0 - viewVec;\n" -" v_tex1 = uv2.xy*0.5 + 0.5;\n" -" float b = 1.0 - clamp(dot(viewVec, Normal), 0.0, 1.0);\n" -" v_reflcolor = vec4(0.0, 0.0, 0.0, 1.0);\n" -" v_reflcolor.a = mix(b*b*b*b*b, 1.0f, fresnel)*shininess;\n" - -" for(int i = 0; i < 5; i++)\n" -" v_reflcolor.rgb += DoDirLightSpec(u_specDir[i].xyz, u_specColor[i].rgb, Normal, viewVec, u_specDir[i].w)*specularity*lightStrength;\n" - -" v_fog = DoFog(gl_Position.w);\n" -"}\n" -; diff --git a/src/extras/shaders/neoWorldIII_fs_gl3.inc b/src/extras/shaders/neoWorldIII_fs_gl3.inc deleted file mode 100644 index 5145f9cd..00000000 --- a/src/extras/shaders/neoWorldIII_fs_gl3.inc +++ /dev/null @@ -1,27 +0,0 @@ -const char *neoWorldIII_frag_src = -"uniform sampler2D tex0;\n" -"uniform sampler2D tex1;\n" - -"uniform vec4 u_lightMap;\n" - -"in vec4 v_color;\n" -"in vec2 v_tex0;\n" -"in vec2 v_tex1;\n" -"in float v_fog;\n" - -"out vec4 color;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec4 t0 = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" -" vec4 t1 = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n" - -" color = t0*v_color*(1 + u_lightMap*(2*t1-1));\n" -" color.a = v_color.a*t0.a*u_lightMap.a;\n" - -" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" -" DoAlphaTest(color.a);\n" -"}\n" - -; diff --git a/src/extras/shaders/simple_fs_gl3.inc b/src/extras/shaders/simple_fs_gl3.inc deleted file mode 100644 index 47d89971..00000000 --- a/src/extras/shaders/simple_fs_gl3.inc +++ /dev/null @@ -1,18 +0,0 @@ -const char *simple_frag_src = -"uniform sampler2D tex0;\n" - -"in vec4 v_color;\n" -"in vec2 v_tex0;\n" -"in float v_fog;\n" - -"out vec4 color;\n" - -"void\n" -"main(void)\n" -"{\n" -" color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" -" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" -" DoAlphaTest(color.a);\n" -"}\n" - -; diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 0a0ed04b..72d2ae17 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -351,7 +351,7 @@ CreateTxdImageForVideoCard() return false; } -#ifdef LIBRW +#ifdef RW_GL3 // so we can read back DXT with GLES // only works for textures that are not yet loaded // so let's hope that is the case for all @@ -385,7 +385,7 @@ CreateTxdImageForVideoCard() delete []buf; delete pDir; CStreaming::RemoveTxd(i); -#ifdef LIBRW +#ifdef RW_GL3 rw::gl3::needToReadBackTextures = false; #endif return false; @@ -414,7 +414,7 @@ CreateTxdImageForVideoCard() RwStreamClose(img, nil); delete []buf; -#ifdef LIBRW +#ifdef RW_GL3 rw::gl3::needToReadBackTextures = false; #endif -- cgit v1.2.3 From 91f9c7938ee3d2f68002cfc9ab9733f7e358c503 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 18 Nov 2020 12:38:47 +0100 Subject: CPed review part1,2 re3 --- src/peds/Ped.cpp | 624 ++++++++++++++++++++++++--------------------------- src/peds/PedChat.cpp | 53 +++-- 2 files changed, 316 insertions(+), 361 deletions(-) (limited to 'src') diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index b3c5c57b..05e00ec2 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -591,13 +591,11 @@ CPed::AddWeaponModel(int id) void CPed::AimGun(void) { - RwV3d pos; CVector vector; if (m_pSeekTarget) { if (m_pSeekTarget->IsPed()) { - ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(&pos, PED_MID); - vector = pos; + ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(vector, PED_MID); } else { vector = m_pSeekTarget->GetPosition(); } @@ -1987,8 +1985,8 @@ CPed::SortPeds(CPed **list, int min, int max) float middleDist = middleDiff.Magnitude(); int left = max; - int right; - for(right = min; right <= left; ){ + int right = min; + while(right <= left){ float rightDist, leftDist; do { rightDiff = GetPosition() - list[right]->GetPosition(); @@ -2015,31 +2013,7 @@ CPed::SortPeds(CPed **list, int min, int max) void CPed::BuildPedLists(void) { - if ((CTimer::GetFrameCounter() + m_randomSeed) % 16) { - - for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) { - bool removePed = false; - if (m_nearPeds[i]) { - if (m_nearPeds[i]->IsPointerValid()) { - float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D(); - if (distSqr > 900.0f) - removePed = true; - } else - removePed = true; - } - if (removePed) { - // If we arrive here, the ped we're checking isn't "near", so we should remove it. - for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) { - m_nearPeds[j] = m_nearPeds[j + 1]; - m_nearPeds[j + 1] = nil; - } - // Above loop won't work when it's 9, so we need to empty slot 9. - m_nearPeds[9] = nil; - m_numNearPeds--; - } else - i++; - } - } else { + if (((CTimer::GetFrameCounter() + m_randomSeed) % 16) == 0) { CVector centre = CEntity::GetBoundCentre(); CRect rect(centre.x - 20.0f, centre.y - 20.0f, @@ -2077,6 +2051,29 @@ CPed::BuildPedLists(void) } for (int pedToClear = m_numNearPeds; pedToClear < ARRAY_SIZE(m_nearPeds); pedToClear++) m_nearPeds[pedToClear] = nil; + } else { + for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) { + bool removePed = false; + if (m_nearPeds[i]) { + if (m_nearPeds[i]->IsPointerValid()) { + float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D(); + if (distSqr > 900.0f) + removePed = true; + } else + removePed = true; + } + if (removePed) { + // If we arrive here, the ped we're checking isn't "near", so we should remove it. + for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) { + m_nearPeds[j] = m_nearPeds[j + 1]; + m_nearPeds[j + 1] = nil; + } + // Above loop won't work on last slot, so we need to empty it. + m_nearPeds[ARRAY_SIZE(m_nearPeds) - 1] = nil; + m_numNearPeds--; + } else + i++; + } } } @@ -2337,13 +2334,13 @@ CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil) pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z; pos.z = pos.z + 0.05f; float collPower = damageNormal->Magnitude2D(); - if (damageNormal->z <= 0.5f) { - forwardOffset += collPower * ourCol->spheres->radius * forwardOffset; - } else { + if (damageNormal->z > 0.5f) { CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f); invDamageNormal *= 1.0f / collPower; CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius; forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f); + } else { + forwardOffset += collPower * ourCol->spheres->radius * forwardOffset; } } else { pos.z -= 0.15f; @@ -2574,7 +2571,9 @@ CPed::SetObjective(eObjective newObj, void *entity) ClearPointGunAt(); #endif bObjectiveCompleted = false; - if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) { + if (IsTemporaryObjective(m_objective) && !IsTemporaryObjective(newObj)) { + m_prevObjective = newObj; + } else { if (m_objective != newObj) { if (IsTemporaryObjective(newObj)) ForceStoredObjective(newObj); @@ -2582,8 +2581,6 @@ CPed::SetObjective(eObjective newObj, void *entity) SetStoredObjective(); } m_objective = newObj; - } else { - m_prevObjective = newObj; } switch (newObj) { @@ -2623,13 +2620,12 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_FLEE_CAR: m_carInObjective = (CVehicle*)entity; m_carInObjective->RegisterReference((CEntity **)&m_carInObjective); - if (!m_carInObjective->bIsBus || m_leaveCarTimer) - break; - - for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) { - if (m_carInObjective->pPassengers[i] == this) { - m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i; - break; + if (m_carInObjective->bIsBus && m_leaveCarTimer == 0) { + for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) { + if (m_carInObjective->pPassengers[i] == this) { + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i; + break; + } } } @@ -2836,10 +2832,9 @@ CPed::InformMyGangOfAttack(CEntity *attacker) void CPed::QuitEnteringCar(void) { - CAnimBlendAssociation *animAssoc = m_pVehicleAnim; CVehicle *veh = m_pMyVehicle; - if (animAssoc) - animAssoc->blendDelta = -1000.0f; + if (m_pVehicleAnim) + m_pVehicleAnim->blendDelta = -1000.0f; RestartNonPartialAnims(); @@ -2866,11 +2861,10 @@ CPed::QuitEnteringCar(void) ReplaceWeaponWhenExitingVehicle(); if (DyingOrDead()) { - animAssoc = m_pVehicleAnim; - if (animAssoc) { - animAssoc->blendDelta = -4.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->flags &= ~ASSOC_RUNNING; + if (m_pVehicleAnim) { + m_pVehicleAnim->blendDelta = -4.0f; + m_pVehicleAnim->flags |= ASSOC_DELETEFADEDOUT; + m_pVehicleAnim->flags &= ~ASSOC_RUNNING; } } else SetIdle(); @@ -2954,21 +2948,16 @@ CPed::ReactToAttack(CEntity *attacker) bool CPed::TurnBody(void) { - float lookDir; bool turnDone = true; - if (m_pLookTarget) { - const CVector &lookPos = m_pLookTarget->GetPosition(); - - lookDir = CGeneral::GetRadianAngleBetweenPoints( - lookPos.x, - lookPos.y, + if (m_pLookTarget) + m_fLookDirection = CGeneral::GetRadianAngleBetweenPoints( + m_pLookTarget->GetPosition().x, + m_pLookTarget->GetPosition().y, GetPosition().x, GetPosition().y); - } else - lookDir = m_fLookDirection; - float limitedLookDir = CGeneral::LimitRadianAngle(lookDir); + float limitedLookDir = CGeneral::LimitRadianAngle(m_fLookDirection); float currentRot = m_fRotationCur; if (currentRot - PI > limitedLookDir) @@ -3023,12 +3012,12 @@ CPed::Chat(void) } else Say(SOUND_PED_CHAT); - } else if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { + } else { - if (CGeneral::GetRandomNumber() < 20) { + if (CGeneral::GetRandomNumber() < 20 && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); } - if (!bIsTalking) { + if (!bIsTalking && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f); float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f); chatAssoc->SetCurrentTime(chatTime); @@ -4465,10 +4454,10 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) dangerZone = CGeneral::LimitRadianAngle(dangerZone); // So, add or subtract 90deg (jump to left/right) according to that - if (dangerZone <= 0.0f) - angleToFace = HALFPI + vehDirection; - else + if (dangerZone > 0.0f) angleToFace = vehDirection - HALFPI; + else + angleToFace = vehDirection + HALFPI; stepAnim = NUM_ANIMS; if (animType == 0 || animType == 1) @@ -4851,9 +4840,9 @@ CPed::LoadFightData(void) line[linelen] = '\0'; // skip white space - for (lp = 0; line[lp] <= ' '; lp++); + for (lp = 0; line[lp] <= ' ' && line[lp] != '\0'; lp++); - if (lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines + if (line[lp] == '\0' || line[lp] == '#') continue; @@ -4914,11 +4903,12 @@ CPed::LoadFightData(void) int CPed::GetLocalDirection(const CVector2D &posOffset) { - float direction; + int direction; + float angle; - for (direction = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); direction < 0.0f; direction += TWOPI); + for (angle = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); angle < 0.0f; angle += TWOPI); - for (direction = (int)RADTODEG(direction) / 90; direction > 3; direction -= 4); + for (direction = RADTODEG(angle)/90.0f; direction > 3; direction -= 4); // 0-forward, 1-left, 2-backward, 3-right. return direction; @@ -5636,8 +5626,9 @@ CPed::CreateDeadPedMoney(void) if (!CGame::nastyGame) return; - int skin = GetModelIndex(); - if ((skin >= MI_COP && skin <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle) + int mi = GetModelIndex(); + + if ((mi >= MI_COP && mi <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle) return; int money = CGeneral::GetRandomNumber() % 60; @@ -6103,10 +6094,8 @@ CPed::EnterCar(void) // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType); if (veh->CanPedOpenLocks(this)) { - if (m_vehEnterType) { - CAnimBlendAssociation *enterAssoc = m_pVehicleAnim; - if (enterAssoc) - veh->ProcessOpenDoor(m_vehEnterType, enterAssoc->animId, enterAssoc->currentTime); + if (m_vehEnterType && m_pVehicleAnim) { + veh->ProcessOpenDoor(m_vehEnterType, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime); } } bIsInTheAir = false; @@ -6258,10 +6247,10 @@ CPed::ExitCar(void) if (m_pSeekTarget) { // Car is upside down if (m_pMyVehicle->GetUp().z > -0.8f) { - if (exitAnim != ANIM_CAR_CLOSE_RHS && exitAnim != ANIM_CAR_CLOSE_LHS && animTime <= 0.3f) - LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START)); - else + if (exitAnim == ANIM_CAR_CLOSE_RHS || exitAnim == ANIM_CAR_CLOSE_LHS || animTime > 0.3f) LineUpPedWithCar(LINE_UP_TO_CAR_END); + else + LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START)); } else { LineUpPedWithCar(LINE_UP_TO_CAR_END); } @@ -6681,7 +6670,7 @@ CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords) CVector ourPos = GetPosition(); - int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f, false, false); + int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f); CVector seekObjPos = m_vecSeekPos; seekObjPos.z += 1.0f; @@ -7561,15 +7550,12 @@ CPed::FollowPath(void) CVector CPed::GetFormationPosition(void) { - CPed *referencePed = m_pedInObjective; - - if (referencePed->m_nPedState == PED_DEAD) { - CPed *referencePedOfReference = referencePed->m_pedInObjective; - if (!referencePedOfReference) { + if (m_pedInObjective->m_nPedState == PED_DEAD) { + if (!m_pedInObjective->m_pedInObjective) { m_pedInObjective = nil; return GetPosition(); } - m_pedInObjective = referencePed = referencePedOfReference; + m_pedInObjective = m_pedInObjective->m_pedInObjective; } CVector formationOffset; @@ -7602,7 +7588,7 @@ CPed::GetFormationPosition(void) formationOffset = CVector(0.0f, 0.0f, 0.0f); break; } - return formationOffset + referencePed->GetPosition(); + return formationOffset + m_pedInObjective->GetPosition(); } void @@ -7620,41 +7606,36 @@ CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen) CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF); CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); - // Right front door is closer - if ((lfPos - GetPosition()).MagnitudeSqr2D() >= (rfPos - GetPosition()).MagnitudeSqr2D()) { + // Left front door is closer + if ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) { + + if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; + } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { + m_vehEnterType = CAR_DOOR_RF; + posToOpen = rfPos; + } + } else { if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { CPed *rfPassenger = veh->pPassengers[0]; - if (!rfPassenger - || rfPassenger->m_leader != this && !rfPassenger->bDontDragMeOutCar && (veh->VehicleCreatedBy != MISSION_VEHICLE || m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) - || veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) == 0) { - - if ((veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) == 0 - || veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) == 0) { - m_vehEnterType = CAR_DOOR_RF; - posToOpen = rfPos; - return; - } + if (rfPassenger && (rfPassenger->m_leader == this || rfPassenger->bDontDragMeOutCar || + veh->VehicleCreatedBy == MISSION_VEHICLE && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) + || (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { + + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; + } else { + m_vehEnterType = CAR_DOOR_RF; + posToOpen = rfPos; } - } else { - if (!veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) - return; + } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; } - m_vehEnterType = CAR_DOOR_LF; - posToOpen = lfPos; - return; - } - - if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { - m_vehEnterType = CAR_DOOR_LF; - posToOpen = lfPos; - return; - } - - if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { - m_vehEnterType = CAR_DOOR_RF; - posToOpen = rfPos; } } @@ -8951,18 +8932,11 @@ CPed::MoveHeadToLook(void) } bShakeFist = false; return; - } - - if (999999.0f == m_fLookDirection) { + } else if (999999.0f == m_fLookDirection) { ClearLookFlag(); - return; - } - - if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) { - if (!bKeepTryingToLook) { + } else if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) { + if (!bKeepTryingToLook) ClearLookFlag(); - return; - } } } @@ -10525,7 +10499,7 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) default: assert(0); } - if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SMASHED) + if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING) veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK); if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus) { @@ -11125,9 +11099,7 @@ CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) default: break; } - bool closeDoor = false; - if (!veh->IsDoorMissing(door)) - closeDoor = true; + bool closeDoor = !veh->IsDoorMissing(door); int padNo; if (ped->IsPlayer()) { @@ -11148,10 +11120,7 @@ CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) break; } CPad* pad = CPad::GetPad(padNo); - bool engineIsIntact = false; - if (veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225) { - engineIsIntact = true; - } + bool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225; if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS && (pad->GetTarget() || pad->NewState.LeftStickX @@ -11215,10 +11184,9 @@ CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg) if (!animAssoc) { ped->ClearLookFlag(); - if (ped->m_nPedState != PED_DIVE_AWAY && ped->m_nPedState != PED_STEP_AWAY) - return; - - ped->RestorePreviousState(); + if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) + ped->RestorePreviousState(); + } else if (animAssoc->animId == ANIM_EV_DIVE) { ped->bUpdateAnimHeading = true; ped->ClearLookFlag(); @@ -11229,12 +11197,12 @@ CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg) } animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) { ped->ClearLookFlag(); - if (ped->m_nPedState != PED_DIVE_AWAY && ped->m_nPedState != PED_STEP_AWAY) - return; + if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) + ped->RestorePreviousState(); - ped->RestorePreviousState(); } else if (ped->m_nPedState != PED_ARRESTED) { animAssoc->flags |= ASSOC_DELETEFADEDOUT; if (animAssoc->blendDelta >= 0.0f) @@ -11798,12 +11766,14 @@ CPed::ReactToPointGun(CEntity *entWithGun) if (m_nPedType == PEDTYPE_COP) { if (pedWithGun->IsPlayer()) { ((CPlayerPed*)pedWithGun)->m_pWanted->SetWantedLevelNoDrop(2); + if (bCrouchWhenShooting || bKindaStayInSamePlace) { + SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000)); + return; + } } - if (bCrouchWhenShooting || bKindaStayInSamePlace) { - SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000)); - } + } - } else if (m_nPedType != PEDTYPE_COP + if (m_nPedType != PEDTYPE_COP && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee()) && (m_nPedState != PED_FLEE_ENTITY || pedWithGun->IsPlayer() && m_fleeFrom != pedWithGun) && m_nPedState != PED_AIM_GUN && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { @@ -11825,9 +11795,8 @@ CPed::ReactToPointGun(CEntity *entWithGun) int moneyPerPickup = money / pickupCount; for (int i = 0; i < pickupCount; i++) { - // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish. - float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x; - float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y; + float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x; + float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y; bool found = false; float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f; if (found) { @@ -12123,7 +12092,6 @@ CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void CVector finalPos; CVector draggedOutOffset; - CVector finalLocalPos; CMatrix pedMat(ped->GetMatrix()); ped->bUsesCollision = true; @@ -12132,8 +12100,7 @@ CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR) draggedOutOffset.x = -draggedOutOffset.x; - finalLocalPos = Multiply3x3(pedMat, draggedOutOffset); - finalPos = finalLocalPos + ped->GetPosition(); + finalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition(); CPedPlacement::FindZCoorForPed(&finalPos); ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); ped->SetPosition(finalPos); @@ -12178,36 +12145,32 @@ CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void ped->m_pNextPathNode = nil; ped->Say(SOUND_PED_FLEE_RUN); } - } else { - if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear - && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE - && veh->pDriver && veh->pDriver->IsPlayer() - && !CTheScripts::IsPlayerOnAMission()) { + } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear + && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE + && veh->pDriver && veh->pDriver->IsPlayer() + && !CTheScripts::IsPlayerOnAMission()) { #ifndef VC_PED_PORTS - if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) { - ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver); - } else + if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) { + ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver); + } else #endif - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); - } else { #ifdef VC_PED_PORTS - if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR - && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !veh->pDriver - && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission()) - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); - else + } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear + && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE + && !veh->pDriver && FindPlayerPed()->m_carInObjective == veh + && !CTheScripts::IsPlayerOnAMission()) { + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); #endif - { - ped->SetFindPathAndFlee(veh->GetPosition(), 10000); - if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) { - ped->SetMoveState(PEDMOVE_SPRINT); - ped->Say(SOUND_PED_FLEE_SPRINT); - } else { - ped->Say(SOUND_PED_FLEE_RUN); - } - } + } else { + ped->SetFindPathAndFlee(veh->GetPosition(), 10000); + if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) { + ped->SetMoveState(PEDMOVE_SPRINT); + ped->Say(SOUND_PED_FLEE_SPRINT); + } else { + ped->Say(SOUND_PED_FLEE_RUN); } } } @@ -12417,27 +12380,33 @@ CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh) void CPed::Render(void) { - if (!bInVehicle || m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR || - bRenderPedInCar && sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) { - CEntity::Render(); + if (bInVehicle && m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR) { + if (!bRenderPedInCar) + return; + + float camDistSq = (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr(); + if (camDistSq > SQR(25.0f * TheCamera.LODDistMultiplier)) + return; + } + + CEntity::Render(); #ifdef PED_SKIN - if(IsClumpSkinned(GetClump())){ - renderLimb(PED_HEAD); - renderLimb(PED_HANDL); - renderLimb(PED_HANDR); - } - if(m_pWeaponModel && IsClumpSkinned(GetClump())){ - RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); - int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID); - RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; - RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel); - *RwFrameGetMatrix(frame) = *mat; - RwFrameUpdateObjects(frame); - RpAtomicRender(m_pWeaponModel); - } -#endif + if(IsClumpSkinned(GetClump())){ + renderLimb(PED_HEAD); + renderLimb(PED_HANDL); + renderLimb(PED_HANDR); + } + if(m_pWeaponModel && IsClumpSkinned(GetClump())){ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel); + *RwFrameGetMatrix(frame) = *mat; + RwFrameUpdateObjects(frame); + RpAtomicRender(m_pWeaponModel); } +#endif } #ifdef PED_SKIN @@ -15520,31 +15489,7 @@ CPed::ScanForInterestingStuff(void) return; if (m_nPedType == PEDTYPE_CRIMINAL && m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) { - if (CGeneral::GetRandomNumber() % 100 >= 10) { - if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) { - CPed *charToMug = nil; - for (int i = 0; i < m_numNearPeds; ++i) { - CPed *nearPed = m_nearPeds[i]; - - if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f)) - break; - - if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE - || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1 - || nearPed->m_nPedType == PEDTYPE_PROSTITUTE) - && nearPed->CharCreatedBy != MISSION_CHAR - && nearPed->IsPedShootable() - && nearPed->m_objective != OBJECTIVE_MUG_CHAR) { - charToMug = nearPed; - break; - } - } - if (charToMug) - SetObjective(OBJECTIVE_MUG_CHAR, charToMug); - - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; - } - } else { + if (CGeneral::GetRandomNumber() % 100 < 10) { int mostExpensiveVehAround = -1; int bestMonetaryValue = 0; @@ -15570,6 +15515,28 @@ CPed::ScanForInterestingStuff(void) return; } m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; + } else if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) { + CPed *charToMug = nil; + for (int i = 0; i < m_numNearPeds; ++i) { + CPed *nearPed = m_nearPeds[i]; + + if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f)) + break; + + if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE + || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1 + || nearPed->m_nPedType == PEDTYPE_PROSTITUTE) + && nearPed->CharCreatedBy != MISSION_CHAR + && nearPed->IsPedShootable() + && nearPed->m_objective != OBJECTIVE_MUG_CHAR) { + charToMug = nearPed; + break; + } + } + if (charToMug) + SetObjective(OBJECTIVE_MUG_CHAR, charToMug); + + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; } } @@ -15596,9 +15563,7 @@ CPed::ScanForInterestingStuff(void) } } #else - if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) >= 0.5f) { - m_standardTimer = CTimer::GetTimeInMilliseconds() + 200; - } else { + if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.5f) { if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { for (int i = 0; i < m_numNearPeds; i ++) { if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) { @@ -15615,6 +15580,8 @@ CPed::ScanForInterestingStuff(void) } } } + } else { + m_standardTimer = CTimer::GetTimeInMilliseconds() + 200; } #endif } @@ -16308,94 +16275,92 @@ CPed::UpdateFromLeader(void) return; } } - if (bInVehicle || !m_leader->bInVehicle || m_leader->m_nPedState != PED_DRIVING) { - if (m_leader->m_objective != OBJECTIVE_NONE && (!m_leader->IsPlayer() || m_leader->m_objective != OBJECTIVE_WAIT_ON_FOOT) - && m_objective != m_leader->m_objective) { - - switch (m_leader->m_objective) { - case OBJECTIVE_WAIT_ON_FOOT: - case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: - case OBJECTIVE_WAIT_IN_CAR: - case OBJECTIVE_FOLLOW_ROUTE: - SetObjective(m_leader->m_objective); - m_objectiveTimer = m_leader->m_objectiveTimer; - break; - case OBJECTIVE_GUARD_SPOT: - SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx); - m_objectiveTimer = m_leader->m_objectiveTimer; - break; - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - if (m_leader->m_pedInObjective) { - SetObjective(m_leader->m_objective, m_leader->m_pedInObjective); - m_objectiveTimer = m_leader->m_objectiveTimer; - } - break; - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - if (m_leader->m_carInObjective) { - SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective); - return; - } - break; - case OBJECTIVE_GUARD_ATTACK: - return; - case OBJECTIVE_HAIL_TAXI: - m_leader = nil; - SetObjective(OBJECTIVE_NONE); - break; - default: - SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); - SetObjectiveTimer(0); - break; + if (!bInVehicle && m_leader->bInVehicle && m_leader->m_nPedState == PED_DRIVING) { + if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { + if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers) + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle); + } + } else if (m_leader->m_objective == OBJECTIVE_NONE || (m_leader->IsPlayer() && m_leader->m_objective == OBJECTIVE_WAIT_ON_FOOT) + || m_objective == m_leader->m_objective) { + + if (m_leader->m_nPedState == PED_ATTACK) { + CEntity *lookTargetOfLeader = m_leader->m_pLookTarget; + if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT + && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) { + + SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader); + SetObjectiveTimer(8000); + SetLookFlag(m_leader->m_pLookTarget, false); + SetLookTimer(500); } } else { - if (m_leader->m_nPedState == PED_ATTACK) { - CEntity *lookTargetOfLeader = m_leader->m_pLookTarget; - if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT - && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) { - - SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader); - SetObjectiveTimer(8000); - SetLookFlag(m_leader->m_pLookTarget, false); - SetLookTimer(500); - } - } else { - if (IsPedInControl() && m_nPedState != PED_ATTACK) { + if (IsPedInControl() && m_nPedState != PED_ATTACK) { #ifndef VC_PED_PORTS - SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); - SetObjectiveTimer(0); + SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); + SetObjectiveTimer(0); #else - if (m_leader->m_objective != OBJECTIVE_NONE || m_objective != OBJECTIVE_NONE - || m_leader->m_nPedState != PED_CHAT || m_nPedState != PED_CHAT) { + if (m_leader->m_objective == OBJECTIVE_NONE && m_objective == OBJECTIVE_NONE + && m_leader->m_nPedState == PED_CHAT && m_nPedState == PED_CHAT) { - SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); - SetObjectiveTimer(0); - } else { - SetObjective(OBJECTIVE_NONE); - } -#endif + SetObjective(OBJECTIVE_NONE); + } else { + SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); + SetObjectiveTimer(0); } - if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) { - if (ScanForThreats() && m_threatEntity) { - m_pLookTarget = m_threatEntity; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - TurnBody(); - if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) { - m_pPointGunAt = m_threatEntity; - if (m_threatEntity) - m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt); - SetAttack(m_threatEntity); - } +#endif + } + if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) { + if (ScanForThreats() && m_threatEntity) { + m_pLookTarget = m_threatEntity; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + TurnBody(); + if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) { + m_pPointGunAt = m_threatEntity; + if (m_threatEntity) + m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt); + SetAttack(m_threatEntity); } } } } } else { - if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { - if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers) - SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle); + switch (m_leader->m_objective) { + case OBJECTIVE_WAIT_ON_FOOT: + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: + case OBJECTIVE_WAIT_IN_CAR: + case OBJECTIVE_FOLLOW_ROUTE: + SetObjective(m_leader->m_objective); + m_objectiveTimer = m_leader->m_objectiveTimer; + break; + case OBJECTIVE_GUARD_SPOT: + SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx); + m_objectiveTimer = m_leader->m_objectiveTimer; + break; + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + if (m_leader->m_pedInObjective) { + SetObjective(m_leader->m_objective, m_leader->m_pedInObjective); + m_objectiveTimer = m_leader->m_objectiveTimer; + } + break; + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + if (m_leader->m_carInObjective) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective); + return; + } + break; + case OBJECTIVE_GUARD_ATTACK: + return; + case OBJECTIVE_HAIL_TAXI: + m_leader = nil; + SetObjective(OBJECTIVE_NONE); + break; + default: + SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); + SetObjectiveTimer(0); + break; } } } else if (bInVehicle) { @@ -16433,34 +16398,32 @@ CPed::UpdatePosition(void) SetHeading(m_fRotationCur); if (m_pCurrentPhysSurface) { CVector2D velocityOfSurface; - CPhysical *curSurface = m_pCurrentPhysSurface; if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) { // It seems R* didn't like m_vecOffsetFromPhysSurface for boats - CVector offsetToSurface = GetPosition() - curSurface->GetPosition(); + CVector offsetToSurface = GetPosition() - m_pCurrentPhysSurface->GetPosition(); offsetToSurface.z -= FEET_OFFSET; - CVector surfaceMoveVelocity = curSurface->m_vecMoveSpeed; - CVector surfaceTurnVelocity = CrossProduct(curSurface->m_vecTurnSpeed, offsetToSurface); + CVector surfaceMoveVelocity = m_pCurrentPhysSurface->m_vecMoveSpeed; + CVector surfaceTurnVelocity = CrossProduct(m_pCurrentPhysSurface->m_vecTurnSpeed, offsetToSurface); // Also we use that weird formula instead of friction if it's boat - float slideMult = -curSurface->m_vecTurnSpeed.MagnitudeSqr(); + float slideMult = -m_pCurrentPhysSurface->m_vecTurnSpeed.MagnitudeSqr(); velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity); m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z); } else { - velocityOfSurface = curSurface->GetSpeed(m_vecOffsetFromPhysSurface); + velocityOfSurface = m_pCurrentPhysSurface->GetSpeed(m_vecOffsetFromPhysSurface); } // Reminder: m_moved is displacement from walking/running. velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed; - m_fRotationCur += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); - m_fRotationDest += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); - } else if (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) { - velocityChange = m_moved - m_vecMoveSpeed; - } else { + m_fRotationCur += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); + m_fRotationDest += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); + } else if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF && (m_vecDamageNormal.x != 0.0f || m_vecDamageNormal.y != 0.0f)) { // Ped got damaged by steep slope m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f); // some kind of - CVector2D reactionForce = m_vecDamageNormal * (1.0f / m_vecDamageNormal.Magnitude2D()); + CVector2D reactionForce = m_vecDamageNormal; + reactionForce.Normalise(); velocityChange = 0.02f * reactionForce + m_moved; @@ -16469,17 +16432,18 @@ CPed::UpdatePosition(void) if (reactionAndVelocityDotProd < 0.0f) { velocityChange -= reactionAndVelocityDotProd * reactionForce; } + } else { + velocityChange = m_moved - m_vecMoveSpeed; } // Take time step into account if (m_pCurrentPhysSurface) { float speedChange = velocityChange.Magnitude(); float changeMult = speedChange; - if (m_nPedState != PED_DIE || !m_pCurrentPhysSurface->IsVehicle()) { - if (!m_pCurrentPhysSurface->IsVehicle() || !((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) - changeMult = 0.01f * CTimer::GetTimeStep(); - } else { + if (m_nPedState == PED_DIE && m_pCurrentPhysSurface->IsVehicle()) { changeMult = 0.002f * CTimer::GetTimeStep(); + } else if (!(m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())) { + changeMult = 0.01f * CTimer::GetTimeStep(); } if (speedChange > changeMult) { @@ -16551,7 +16515,7 @@ CPed::SetPedPositionInCar(void) tempMat.RotateZ(-HALFPI); newMat = newMat * tempMat; } else if (m_pMyVehicle->pPassengers[2] == this) { - m_fRotationCur = HALFPI + m_pMyVehicle->GetForward().Heading(); + m_fRotationCur = m_pMyVehicle->GetForward().Heading() + HALFPI; tempMat.SetTranslate(0.0f, 0.0f, 0.0f); tempMat.RotateZ(HALFPI); newMat = newMat * tempMat; @@ -17202,18 +17166,10 @@ CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z); bUsesCollision = false; - if (zDiff > 4.4f) { - if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f); - - } else { - if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f); - } + if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f); + else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f); m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this); } @@ -17307,11 +17263,11 @@ CPed::SetCarJack(CVehicle* car) if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO))) - if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING) - if (m_nPedState != PED_CARJACK && !m_pVehicleAnim) - if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door))) - if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags)) - SetCarJack_AllClear(car, m_vehEnterType, doorFlag); + if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING) + if (m_nPedState != PED_CARJACK && !m_pVehicleAnim) + if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door))) + if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags)) + SetCarJack_AllClear(car, m_vehEnterType, doorFlag); } void diff --git a/src/peds/PedChat.cpp b/src/peds/PedChat.cpp index 65ed67a5..81e295c6 100644 --- a/src/peds/PedChat.cpp +++ b/src/peds/PedChat.cpp @@ -56,26 +56,27 @@ CPed::ServiceTalkingWhenDead(void) void CPed::ServiceTalking(void) { - if (!bBodyPartJustCameOff || m_bodyPartBleeding != PED_HEAD) { - if (!CGeneral::faststricmp(CModelInfo::GetModelInfo(GetModelIndex())->GetName(), "bomber")) - m_queuedSound = SOUND_PED_BOMBER; - else if (m_nPedState == PED_ON_FIRE) - m_queuedSound = SOUND_PED_BURNING; + if (bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD) + return; - if (m_queuedSound != SOUND_NO_SOUND) { - if (m_queuedSound == SOUND_PED_DEATH) - m_soundStart = CTimer::GetTimeInMilliseconds() - 1; + if (!CGeneral::faststricmp(CModelInfo::GetModelInfo(GetModelIndex())->GetName(), "bomber")) + m_queuedSound = SOUND_PED_BOMBER; + else if (m_nPedState == PED_ON_FIRE) + m_queuedSound = SOUND_PED_BURNING; - if (CTimer::GetTimeInMilliseconds() > m_soundStart) { - DMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f); - m_lastSoundStart = CTimer::GetTimeInMilliseconds(); - m_soundStart = - CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime - + CTimer::GetTimeInMilliseconds() - + CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime); - m_lastQueuedSound = m_queuedSound; - m_queuedSound = SOUND_NO_SOUND; - } + if (m_queuedSound != SOUND_NO_SOUND) { + if (m_queuedSound == SOUND_PED_DEATH) + m_soundStart = CTimer::GetTimeInMilliseconds() - 1; + + if (CTimer::GetTimeInMilliseconds() > m_soundStart) { + DMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f); + m_lastSoundStart = CTimer::GetTimeInMilliseconds(); + m_soundStart = + CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime + + CTimer::GetTimeInMilliseconds() + + CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime); + m_lastQueuedSound = m_queuedSound; + m_queuedSound = SOUND_NO_SOUND; } } } @@ -83,14 +84,12 @@ CPed::ServiceTalking(void) void CPed::Say(uint16 audio) { - uint16 audioToPlay = audio; - if (IsPlayer()) { // Ofc this part isn't in VC. switch (audio) { case SOUND_PED_DEATH: - audioToPlay = SOUND_PED_DAMAGE; + audio = SOUND_PED_DAMAGE; break; case SOUND_PED_DAMAGE: case SOUND_PED_HIT: @@ -99,7 +98,7 @@ CPed::Say(uint16 audio) case SOUND_PED_BULLET_HIT: case SOUND_PED_CAR_JACKED: case SOUND_PED_DEFEND: - audioToPlay = SOUND_PED_HIT; + audio = SOUND_PED_HIT; break; default: return; @@ -142,12 +141,12 @@ CPed::Say(uint16 audio) } } - if (audioToPlay < m_queuedSound) { - if (audioToPlay != m_lastQueuedSound || audioToPlay == SOUND_PED_DEATH - || CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime + if (audio < m_queuedSound) { + if (audio != m_lastQueuedSound || audio == SOUND_PED_DEATH + || CommentWaitTime[audio - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime + m_lastSoundStart - + (uint32) CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nMaxRandomDelayTime) <= CTimer::GetTimeInMilliseconds()) { - m_queuedSound = audioToPlay; + + (uint32) CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audio - SOUND_PED_DEATH].m_nMaxRandomDelayTime) <= CTimer::GetTimeInMilliseconds()) { + m_queuedSound = audio; } } } \ No newline at end of file -- cgit v1.2.3 From 808f7c46f1df9acaf8d00ebde7cb1925e1d27f94 Mon Sep 17 00:00:00 2001 From: erorcun Date: Thu, 19 Nov 2020 02:09:04 +0300 Subject: Infamous XBOX subtitle outline --- src/core/config.h | 1 + src/render/Font.cpp | 34 ++++++++++++++++++++++++++++++++++ src/render/Font.h | 4 ++++ src/render/Hud.cpp | 12 +++++++++++- 4 files changed, 50 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index 3da9bcb1..db6e5490 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -262,6 +262,7 @@ enum Config { #define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. // #define BETA_SLIDING_TEXT #define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC +// #define XBOX_SUBTITLES // the infamous outlines #define PC_MENU #ifndef PC_MENU diff --git a/src/render/Font.cpp b/src/render/Font.cpp index fbcc38e4..42ddd0fb 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -942,6 +942,40 @@ CFont::PrintString(float x, float y, wchar *start, wchar *end, float spwidth) } #endif +#ifdef XBOX_SUBTITLES +void +CFont::PrintStringFromBottom(float x, float y, wchar *str) +{ +#ifdef MORE_LANGUAGES + if (IsJapaneseFont()) + y -= (32.0f * CFont::Details.scaleY / 2.75f + 2.0f * CFont::Details.scaleY) * GetNumberLines(x, y, str); + else +#endif + y -= (32.0f * CFont::Details.scaleY * 0.5f + 2.0f * CFont::Details.scaleY) * GetNumberLines(x, y, str); + PrintString(x, y, str); +} + +void +CFont::PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor) +{ + CRGBA textColor = Details.color; + SetColor(outlineColor); + CVector2D offsets[] = { {1.f, 1.f}, {1.f, -1.f}, {-1.f, 1.f}, {-1.f, -1.f} }; + for(int i = 0; i < ARRAY_SIZE(offsets); i++){ + if (fromBottom) + PrintStringFromBottom(x + SCREEN_SCALE_X(offsets[i].x * outlineStrength), y + SCREEN_SCALE_Y(offsets[i].y * outlineStrength), str); + else + PrintString(x + SCREEN_SCALE_X(offsets[i].x * outlineStrength), y + SCREEN_SCALE_Y(offsets[i].y * outlineStrength), str); + } + SetColor(textColor); + + if (fromBottom) + PrintStringFromBottom(x, y, str); + else + PrintString(x, y, str); +} +#endif + float CFont::GetCharacterWidth(wchar c) { diff --git a/src/render/Font.h b/src/render/Font.h index bf747859..7b67e310 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -116,6 +116,10 @@ public: static void InitPerFrame(void); static void PrintChar(float x, float y, wchar c); static void PrintString(float x, float y, wchar *s); +#ifdef XBOX_SUBTITLES + static void PrintStringFromBottom(float x, float y, wchar *str); + static void PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor); +#endif static int GetNumberLines(float xstart, float ystart, wchar *s); static void GetTextRect(CRect *rect, float xstart, float ystart, wchar *s); #ifdef MORE_LANGUAGES diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index de3128ce..1a39e1c7 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -926,11 +926,20 @@ void CHud::Draw() CFont::SetJustifyOff(); CFont::SetBackgroundOff(); CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128)); - CFont::SetScale(SCREEN_SCALE_X(0.48f), SCREEN_SCALE_Y(1.120f)); + CFont::SetScale(SCREEN_SCALE_X(0.48f), SCREEN_SCALE_Y(1.12f)); CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); +#ifdef XBOX_SUBTITLES + float radarBulge = SCREEN_SCALE_X(45.0f) + SCREEN_SCALE_X(16.0f); + float rectWidth = SCREEN_WIDTH - SCREEN_SCALE_X(45.0f) - SCREEN_SCALE_X(16.0f) - radarBulge; + CFont::SetCentreSize(rectWidth); + CFont::SetColor(CRGBA(180, 180, 180, 255)); + + CFont::PrintOutlinedString(rectWidth / 2.0f + radarBulge, SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(48.0f) - SCREEN_SCALE_Y(1), m_Message, + 2.0f, true, CRGBA(0, 0, 0, 255)); +#else float radarBulge = SCREEN_SCALE_X(40.0f) + SCREEN_SCALE_X(8.0f); float rectWidth = SCREEN_WIDTH - SCREEN_SCALE_X(50.0f) - SCREEN_SCALE_X(8.0f) - radarBulge; CFont::SetCentreSize(rectWidth); @@ -943,6 +952,7 @@ void CHud::Draw() // I'm not sure shadow substaction was intentional here, might be a leftover if CFont::PrintString was used for a shadow draw call CFont::PrintString(rectWidth / 2.0f + radarBulge - SCREEN_SCALE_X(shadow), SCREEN_SCALE_Y(4.0f) + SCREEN_SCALE_FROM_BOTTOM(68.0f) - SCREEN_SCALE_Y(shadow), m_Message); CFont::SetDropShadowPosition(0); +#endif } /* -- cgit v1.2.3 From 02c7f8381b81732645ed92fda0c5a66d0f1db265 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 19 Nov 2020 16:23:52 +0100 Subject: neo screen droplets --- src/control/GameLogic.cpp | 10 + src/core/Game.cpp | 7 + src/core/config.h | 8 + src/core/main.cpp | 17 +- src/extras/custompipes.cpp | 2 +- src/extras/custompipes.h | 1 + src/extras/custompipes_d3d9.cpp | 1 + src/extras/postfx.cpp | 15 +- src/extras/postfx.h | 1 + src/extras/screendroplets.cpp | 791 +++++++++++++++++++++++++++++ src/extras/screendroplets.h | 78 +++ src/extras/shaders/Makefile | 13 +- src/extras/shaders/im2d_UV2.vert | 21 + src/extras/shaders/im2d_UV2_gl.inc | 23 + src/extras/shaders/screenDroplet.frag | 18 + src/extras/shaders/screenDroplet_PS.cso | Bin 0 -> 324 bytes src/extras/shaders/screenDroplet_PS.hlsl | 17 + src/extras/shaders/screenDroplet_PS.inc | 29 ++ src/extras/shaders/screenDroplet_fs_gl.inc | 20 + src/objects/ParticleObject.cpp | 6 + src/objects/ParticleObject.h | 2 + 21 files changed, 1072 insertions(+), 8 deletions(-) create mode 100644 src/extras/screendroplets.cpp create mode 100644 src/extras/screendroplets.h create mode 100644 src/extras/shaders/im2d_UV2.vert create mode 100644 src/extras/shaders/im2d_UV2_gl.inc create mode 100644 src/extras/shaders/screenDroplet.frag create mode 100644 src/extras/shaders/screenDroplet_PS.cso create mode 100644 src/extras/shaders/screenDroplet_PS.hlsl create mode 100644 src/extras/shaders/screenDroplet_PS.inc create mode 100644 src/extras/shaders/screenDroplet_fs_gl.inc (limited to 'src') diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index 47b4586b..59c75dd4 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -19,6 +19,7 @@ #include "Fire.h" #include "Script.h" #include "Garages.h" +#include "screendroplets.h" uint8 CGameLogic::ActivePlayers; @@ -117,6 +118,9 @@ CGameLogic::Update() } } CEventList::Initialise(); +#ifdef SCREEN_DROPLETS + ScreenDroplets::Initialise(); +#endif CMessages::ClearMessages(); CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); @@ -196,6 +200,9 @@ CGameLogic::Update() } } CEventList::Initialise(); +#ifdef SCREEN_DROPLETS + ScreenDroplets::Initialise(); +#endif CMessages::ClearMessages(); CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); @@ -245,6 +252,9 @@ CGameLogic::Update() } } CEventList::Initialise(); +#ifdef SCREEN_DROPLETS + ScreenDroplets::Initialise(); +#endif CMessages::ClearMessages(); CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index f7589d2b..1283ecd1 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -88,6 +88,7 @@ #include "debugmenu.h" #include "postfx.h" #include "custompipes.h" +#include "screendroplets.h" #include "crossplatform.h" eLevelName CGame::currLevel; @@ -408,6 +409,9 @@ bool CGame::Initialise(const char* datFile) CPed::Initialise(); CRouteNode::Initialise(); CEventList::Initialise(); +#ifdef SCREEN_DROPLETS + ScreenDroplets::Initialise(); +#endif LoadingScreen("Loading the Game", "Find big buildings", nil); CRenderer::Init(); LoadingScreen("Loading the Game", "Setup game variables", nil); @@ -559,6 +563,9 @@ void CGame::ReInitGameObjectVariables(void) CStreaming::LoadAllRequestedModels(false); CPed::Initialise(); CEventList::Initialise(); +#ifdef SCREEN_DROPLETS + ScreenDroplets::Initialise(); +#endif CWeapon::InitialiseWeapons(); CPopulation::Initialise(); diff --git a/src/core/config.h b/src/core/config.h index db6e5490..8b4356ce 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -237,6 +237,14 @@ enum Config { #ifdef LIBRW //#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) //#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) +//#define SCREEN_DROPLETS // neo water droplets +#endif + +#ifndef EXTENDED_COLOURFILTER +#undef SCREEN_DROPLETS // we need the frontbuffer for this effect +#endif +#ifndef EXTENDED_PIPELINES +#undef SCREEN_DROPLETS // we need neo.txd #endif // Particle diff --git a/src/core/main.cpp b/src/core/main.cpp index 157776e0..843f0671 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -63,7 +63,9 @@ #include "SceneEdit.h" #include "debugmenu.h" #include "Clock.h" +#include "postfx.h" #include "custompipes.h" +#include "screendroplets.h" #include "frontendoption.h" GlobalScene Scene; @@ -419,6 +421,9 @@ Initialise3D(void *param) bool ret = CGame::InitialiseRenderWare(); #ifdef EXTENDED_PIPELINES CustomPipes::CustomPipeInit(); // need Scene.world for this +#endif +#ifdef SCREEN_DROPLETS + ScreenDroplets::InitDraw(); #endif return ret; } @@ -429,6 +434,9 @@ Initialise3D(void *param) static void Terminate3D(void) { +#ifdef SCREEN_DROPLETS + ScreenDroplets::Shutdown(); +#endif #ifdef EXTENDED_PIPELINES CustomPipes::CustomPipeShutdown(); #endif @@ -1142,10 +1150,17 @@ Idle(void *arg) RenderDebugShit(); RenderEffects(); - tbStartTimer(0, "RenderMotionBlur"); if((TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) && TheCamera.m_ScreenReductionPercentage > 0.0f) TheCamera.SetMotionBlurAlpha(150); + +#ifdef SCREEN_DROPLETS + CPostFX::GetBackBuffer(Scene.camera); + ScreenDroplets::Process(); + ScreenDroplets::Render(); +#endif + + tbStartTimer(0, "RenderMotionBlur"); TheCamera.RenderMotionBlur(); tbEndTimer("RenderMotionBlur"); diff --git a/src/extras/custompipes.cpp b/src/extras/custompipes.cpp index 8c2b6916..bb3ebd2e 100644 --- a/src/extras/custompipes.cpp +++ b/src/extras/custompipes.cpp @@ -44,7 +44,7 @@ CustomMatCopy(void *dst, void *src, int32, int32) -static rw::TexDictionary *neoTxd; +rw::TexDictionary *neoTxd; bool bRenderingEnvMap; int32 EnvMapSize = 128; diff --git a/src/extras/custompipes.h b/src/extras/custompipes.h index 6e9c6517..ca3f0fb4 100644 --- a/src/extras/custompipes.h +++ b/src/extras/custompipes.h @@ -6,6 +6,7 @@ namespace CustomPipes { +extern rw::TexDictionary *neoTxd; struct CustomMatExt { diff --git a/src/extras/custompipes_d3d9.cpp b/src/extras/custompipes_d3d9.cpp index 93973fec..b39efd47 100644 --- a/src/extras/custompipes_d3d9.cpp +++ b/src/extras/custompipes_d3d9.cpp @@ -131,6 +131,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header) drawInst(header, inst); inst++; } + d3d::setTexture(1, nil); SetRenderState(SRCBLEND, BLENDSRCALPHA); } diff --git a/src/extras/postfx.cpp b/src/extras/postfx.cpp index fe481658..d3b8b8ac 100644 --- a/src/extras/postfx.cpp +++ b/src/extras/postfx.cpp @@ -363,6 +363,14 @@ CPostFX::NeedFrontBuffer(int32 type) return false; } +void +CPostFX::GetBackBuffer(RwCamera *cam) +{ + RwRasterPushContext(pBackBuffer); + RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0); + RwRasterPopContext(); +} + void CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha) { @@ -405,11 +413,8 @@ CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blu assert(pFrontBuffer); assert(pBackBuffer); - if(NeedBackBuffer()){ - RwRasterPushContext(pBackBuffer); - RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0); - RwRasterPopContext(); - } + if(NeedBackBuffer()) + GetBackBuffer(cam); DefinedState(); diff --git a/src/extras/postfx.h b/src/extras/postfx.h index 658c2d88..f8779a6d 100644 --- a/src/extras/postfx.h +++ b/src/extras/postfx.h @@ -29,6 +29,7 @@ public: static void Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha); static bool NeedBackBuffer(void); static bool NeedFrontBuffer(int32 type); + static void GetBackBuffer(RwCamera *cam); static bool UseBlurColours(void) { return EffectSwitch != POSTFX_SIMPLE; } }; diff --git a/src/extras/screendroplets.cpp b/src/extras/screendroplets.cpp new file mode 100644 index 00000000..2d34cdcb --- /dev/null +++ b/src/extras/screendroplets.cpp @@ -0,0 +1,791 @@ +#define WITH_D3D +#include "common.h" + +#ifdef SCREEN_DROPLETS + +#ifndef LIBRW +#error "Need librw for SCREEN_DROPLETS" +#endif + +#include "General.h" +#include "Main.h" +#include "RwHelper.h" +#include "Main.h" +#include "Timer.h" +#include "Camera.h" +#include "ZoneCull.h" +#include "Weather.h" +#include "ParticleObject.h" + #include "Pad.h" +#include "RenderBuffer.h" +#include "custompipes.h" +#include "postfx.h" +#include "screendroplets.h" + +// for 640 +#define MAXSIZE 15 +#define MINSIZE 4 + +int ScreenDroplets::ms_initialised; +RwTexture *ScreenDroplets::ms_maskTex; +RwTexture *ScreenDroplets::ms_screenTex; + +bool ScreenDroplets::ms_enabled = true; +bool ScreenDroplets::ms_movingEnabled = true; + +ScreenDroplets::ScreenDrop ScreenDroplets::ms_drops[ScreenDroplets::MAXDROPS]; +int ScreenDroplets::ms_numDrops; +ScreenDroplets::ScreenDropMoving ScreenDroplets::ms_dropsMoving[ScreenDroplets::MAXDROPSMOVING]; +int ScreenDroplets::ms_numDropsMoving; + +CVector ScreenDroplets::ms_prevCamUp; +CVector ScreenDroplets::ms_prevCamPos; +CVector ScreenDroplets::ms_camMoveDelta; +float ScreenDroplets::ms_camMoveDist; +CVector ScreenDroplets::ms_screenMoveDelta; +float ScreenDroplets::ms_screenMoveDist; +float ScreenDroplets::ms_camUpAngle; + +int ScreenDroplets::ms_splashDuration; +CParticleObject *ScreenDroplets::ms_splashObject; + +struct Im2DVertexUV2 : rw::RWDEVICE::Im2DVertex +{ + rw::float32 u2, v2; +}; + +#ifdef RW_D3D9 +static void *screenDroplet_PS; +#endif +#ifdef RW_GL3 +static rw::gl3::Shader *screenDroplet; +#endif + +// platform specific +static void openim2d_uv2(void); +static void closeim2d_uv2(void); +static void RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices); + +static Im2DVertexUV2 VertexBuffer[TEMPBUFFERVERTSIZE]; + +void +ScreenDroplets::Initialise(void) +{ + Clear(); + ms_splashDuration = -1; + ms_splashObject = nil; +} + +void +ScreenDroplets::InitDraw(void) +{ + if(CustomPipes::neoTxd) + ms_maskTex = CustomPipes::neoTxd->find("dropmask"); + + ms_screenTex = RwTextureCreate(nil); + RwTextureSetFilterMode(ms_screenTex, rwFILTERLINEAR); + + openim2d_uv2(); +#ifdef RW_D3D9 +#include "shaders/screenDroplet_PS.inc" + screenDroplet_PS = rw::d3d::createPixelShader(screenDroplet_PS_cso); +#endif +#ifdef RW_GL3 + using namespace rw::gl3; + { +#include "shaders/im2d_UV2_gl.inc" +#include "shaders/screenDroplet_fs_gl.inc" + const char *vs[] = { shaderDecl, header_vert_src, im2d_UV2_vert_src, nil }; + const char *fs[] = { shaderDecl, header_frag_src, screenDroplet_frag_src, nil }; + screenDroplet = Shader::create(vs, fs); + assert(screenDroplet); + } +#endif + + ms_initialised = 1; +} + +void +ScreenDroplets::Shutdown(void) +{ + if(ms_maskTex){ + RwTextureDestroy(ms_maskTex); + ms_maskTex = nil; + } + if(ms_screenTex){ + RwTextureSetRaster(ms_screenTex, nil); + RwTextureDestroy(ms_screenTex); + ms_screenTex = nil; + } +#ifdef RW_D3D9 + if(screenDroplet_PS){ + rw::d3d::destroyPixelShader(screenDroplet_PS); + screenDroplet_PS = nil; + } +#endif +#ifdef RW_GL3 + if(screenDroplet){ + screenDroplet->destroy(); + screenDroplet = nil; + } +#endif + + closeim2d_uv2(); +} + +void +ScreenDroplets::Process(void) +{ + ProcessCameraMovement(); + SprayDrops(); + ProcessMoving(); + Fade(); +} + +static void +FlushBuffer(void) +{ + if(TempBufferIndicesStored){ + RenderIndexedPrimitive_UV2(rwPRIMTYPETRILIST, + VertexBuffer, TempBufferVerticesStored, + TempBufferRenderIndexList, TempBufferIndicesStored); + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + } +} + +static int +StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, Im2DVertexUV2 **vertexStart) +{ + if(TempBufferIndicesStored + numIndices >= TEMPBUFFERINDEXSIZE || + TempBufferVerticesStored + numVertices >= TEMPBUFFERVERTSIZE) + FlushBuffer(); + *indexStart = &TempBufferRenderIndexList[TempBufferIndicesStored]; + *vertexStart = &VertexBuffer[TempBufferVerticesStored]; + int vertOffset = TempBufferVerticesStored; + TempBufferIndicesStored += numIndices; + TempBufferVerticesStored += numVertices; + return vertOffset; +} + +void +ScreenDroplets::Render(void) +{ + ScreenDrop *drop; + + DefinedState(); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(ms_maskTex)); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + + RwTextureSetRaster(ms_screenTex, CPostFX::pBackBuffer); +#ifdef RW_D3D9 + rw::d3d::im2dOverridePS = screenDroplet_PS; + rw::d3d::setTexture(1, ms_screenTex); +#endif +#ifdef RW_GL3 + rw::gl3::im2dOverrideShader = screenDroplet; + rw::gl3::setTexture(1, ms_screenTex); +#endif + + RenderBuffer::ClearRenderBuffer(); + for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++) + if(drop->active) + AddToRenderList(drop); + FlushBuffer(); + +#ifdef RW_D3D9 + rw::d3d::im2dOverridePS = nil; + rw::d3d::setTexture(1, nil); +#endif +#ifdef RW_GL3 + rw::gl3::im2dOverrideShader = nil; + rw::gl3::setTexture(1, nil); +#endif + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE); +} + +void +ScreenDroplets::AddToRenderList(ScreenDroplets::ScreenDrop *drop) +{ + static float xy[] = { + -1.0f, -1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f + }; + static float uv[] = { + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f + }; + + int i; + RwImVertexIndex *indices; + Im2DVertexUV2 *verts; + int first = StartStoring(6, 4, &indices, &verts); + + float scale = 0.5f*SCREEN_SCALE_X(drop->size); + + float screenz = RwIm2DGetNearScreenZ(); + float z = RwCameraGetNearClipPlane(Scene.camera); + float recipz = 1.0f/z; + + float magSize = SCREEN_SCALE_Y(drop->magnification*(300.0f-40.0f) + 40.0f); + float ul = drop->x - magSize; + float vt = drop->y - magSize; + float ur = drop->x + magSize; + float vb = drop->y + magSize; + ul = Max(ul, 0.0f)/RwRasterGetWidth(CPostFX::pBackBuffer); + vt = Max(vt, 0.0f)/RwRasterGetHeight(CPostFX::pBackBuffer); + ur = Min(ur, SCREEN_WIDTH)/RwRasterGetWidth(CPostFX::pBackBuffer); + vb = Min(vb, SCREEN_HEIGHT)/RwRasterGetHeight(CPostFX::pBackBuffer); + + for(i = 0; i < 4; i++){ + RwIm2DVertexSetScreenX(&verts[i], drop->x + xy[i*2]*scale); + RwIm2DVertexSetScreenY(&verts[i], drop->y + xy[i*2+1]*scale); + RwIm2DVertexSetScreenZ(&verts[i], screenz); + RwIm2DVertexSetCameraZ(&verts[i], z); + RwIm2DVertexSetRecipCameraZ(&verts[i], recipz); + RwIm2DVertexSetIntRGBA(&verts[i], drop->color.r, drop->color.g, drop->color.b, drop->color.a); + RwIm2DVertexSetU(&verts[i], uv[i*2], recipz); + RwIm2DVertexSetV(&verts[i], uv[i*2+1], recipz); + + verts[i].u2 = i < 2 ? ul : ur; + verts[i].v2 = i % 3 ? vt : vb; + } + indices[0] = first + 0; + indices[1] = first + 1; + indices[2] = first + 2; + indices[3] = first + 2; + indices[4] = first + 3; + indices[5] = first + 0; +} + +void +ScreenDroplets::Clear(void) +{ + ScreenDrop *drop; + for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++) + drop->active = false; + ms_numDrops = 0; +} + +ScreenDroplets::ScreenDrop* +ScreenDroplets::NewDrop(float x, float y, float size, float lifetime, bool fades, int r, int g, int b) +{ + ScreenDrop *drop; + int i; + + for(i = 0, drop = ms_drops; i < MAXDROPS; i++, drop++) + if(!ms_drops[i].active) + goto found; + return nil; +found: + ms_numDrops++; + drop->x = x; + drop->y = y; + drop->size = size; + drop->magnification = (MAXSIZE - size + 1.0f) / (MAXSIZE - MINSIZE + 1.0f); + drop->fades = fades; + drop->active = true; + drop->color.r = r; + drop->color.g = g; + drop->color.b = b; + drop->color.a = 255; + drop->time = 0.0f; + drop->lifetime = lifetime; + return drop; +} + +void +ScreenDroplets::SetMoving(ScreenDroplets::ScreenDrop *drop) +{ + ScreenDropMoving *moving; + for(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++) + if(moving->drop == nil) + goto found; + return; +found: + ms_numDropsMoving++; + moving->drop = drop; + moving->dist = 0.0f; +} + +void +ScreenDroplets::FillScreen(int n) +{ + float x, y, size; + ScreenDrop *drop; + + if(!ms_initialised) + return; + ms_numDrops = 0; + for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++){ + drop->active = false; + if(drop < &ms_drops[n]){ + x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH; + y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT; + size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE); + NewDrop(x, y, size, 2000.0f, true); + } + } +} + +void +ScreenDroplets::FillScreenMoving(float amount, bool isBlood) +{ + int n = (ms_screenMoveDelta.z > 5.0f ? 1.5f : 1.0f)*amount*20.0f; + float x, y, size; + ScreenDrop *drop; + + while(n--) + if(ms_numDrops < MAXDROPS && ms_numDropsMoving < MAXDROPSMOVING){ + x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH; + y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT; + size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE); + drop = nil; + if(isBlood) + drop = NewDrop(x, y, size, 2000.0f, true, 255, 0, 0); + else + drop = NewDrop(x, y, size, 2000.0f, true); + if(drop) + SetMoving(drop); + } +} + +void +ScreenDroplets::RegisterSplash(CParticleObject *pobj) +{ + CVector dist = pobj->GetPosition() - ms_prevCamPos; + if(dist.MagnitudeSqr() < 20.0f){ + ms_splashDuration = 14; + ms_splashObject = pobj; + } +} + +void +ScreenDroplets::ProcessCameraMovement(void) +{ + RwMatrix *camMat = RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)); + CVector camPos = camMat->pos; + CVector camUp = camMat->at; + ms_camMoveDelta = camPos - ms_prevCamPos; + ms_camMoveDist = ms_camMoveDelta.Magnitude(); + + ms_prevCamUp = camUp; + ms_prevCamPos = camPos; + + ms_screenMoveDelta.x = -RwV3dDotProduct(&camMat->right, (RwV3d*)&ms_camMoveDelta); + ms_screenMoveDelta.y = RwV3dDotProduct(&camMat->up, (RwV3d*)&ms_camMoveDelta); + ms_screenMoveDelta.z = RwV3dDotProduct(&camMat->at, (RwV3d*)&ms_camMoveDelta); + ms_screenMoveDelta *= 10.0f; + ms_screenMoveDist = ms_screenMoveDelta.Magnitude2D(); + + uint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + bool isTopDown = mode == CCam::MODE_TOPDOWN || mode == CCam::MODE_GTACLASSIC || mode == CCam::MODE_TOP_DOWN_PED; + bool isLookingInDirection = CPad::GetPad(0)->GetLookBehindForCar() || CPad::GetPad(0)->GetLookLeft() || CPad::GetPad(0)->GetLookRight(); + ms_enabled = !isTopDown && !isLookingInDirection; + ms_movingEnabled = !isTopDown && !isLookingInDirection; + + // 0 when looking stright up, 180 when looking up or down + ms_camUpAngle = RADTODEG(Acos(clamp(camUp.z, -1.0f, 1.0f))); +} + +void +ScreenDroplets::SprayDrops(void) +{ + bool noRain = CCullZones::PlayerNoRain() || CCullZones::CamNoRain(); + if(!noRain && CWeather::Rain > 0.0f && ms_enabled){ + // 180 when looking stright up, 0 when looking up or down + float angle = 180.0f - ms_camUpAngle; + angle = Max(angle, 40.0f); // want at least some rain + FillScreenMoving((angle - 40.0f) / 150.0f * CWeather::Rain * 0.5f); + } + + int i; + for(i = 0; i < MAX_AUDIOHYDRANTS; i++){ + CAudioHydrant *hyd = CAudioHydrant::Get(i); + if (hyd->pParticleObject){ + CVector dist = hyd->pParticleObject->GetPosition() - ms_prevCamPos; + if(dist.MagnitudeSqr() > 40.0f || + DotProduct(dist, ms_prevCamUp) < 0.0f) continue; + + FillScreenMoving(1.0f); + } + } + + static int ndrops[] = { + 125, 250, 500, 1000, 1000, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if(ms_splashDuration >= 0){ + if(ms_numDrops < MAXDROPS) { + float numDropMult = 1.0f; + if(ms_splashObject){ + float dist = (ms_splashObject->GetPosition() - ms_prevCamPos).Magnitude(); + numDropMult = 1.0f - (dist - 5.0f)/15.0f; + if(numDropMult < 0) numDropMult = 0.0f; // fix + } + int n = ndrops[ms_splashDuration] * numDropMult; + while(n--) + if(ms_numDrops < MAXDROPS){ + float x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH; + float y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT; + float size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE); + NewDrop(x, y, size, 10000.0f, false); + } + } + ms_splashDuration--; + } +} + +void +ScreenDroplets::NewTrace(ScreenDroplets::ScreenDropMoving *moving) +{ + if(ms_numDrops < MAXDROPS){ + moving->dist = 0.0f; + NewDrop(moving->drop->x, moving->drop->y, MINSIZE, 500.0f, true, + moving->drop->color.r, moving->drop->color.g, moving->drop->color.b); + } +} + +void +ScreenDroplets::MoveDrop(ScreenDroplets::ScreenDropMoving *moving) +{ + ScreenDrop *drop = moving->drop; + if(!ms_movingEnabled) + return; + if(!drop->active){ + moving->drop = nil; + ms_numDropsMoving--; + return; + } + if(ms_screenMoveDelta.z > 0.0f && ms_camMoveDist > 0.3f){ + if(ms_screenMoveDist > 0.5f && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){ + // movement when camera turns + moving->dist += ms_screenMoveDist; + if(moving->dist > 20.0f && drop->color.a > 100) + NewTrace(moving); + + drop->x -= ms_screenMoveDelta.x; + drop->y += ms_screenMoveDelta.y; + }else{ + // movement out of center + float d = ms_screenMoveDelta.z*0.2f; + float dx, dy, sum; + dx = drop->x - SCREEN_WIDTH*0.5f + ms_screenMoveDelta.x; + if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) + dy = drop->y - SCREEN_HEIGHT*1.2f - ms_screenMoveDelta.y; + else + dy = drop->y - SCREEN_HEIGHT*0.5f - ms_screenMoveDelta.y; + sum = fabs(dx) + fabs(dy); + if(sum > 0.001f){ + dx /= sum; + dy /= sum; + } + moving->dist += d; + if(moving->dist > 20.0f && drop->color.a > 100) + NewTrace(moving); + drop->x += dx * d; + drop->y += dy * d; + } + + if(drop->x < 0.0f || drop->y < 0.0f || + drop->x > SCREEN_WIDTH || drop->y > SCREEN_HEIGHT){ + moving->drop = nil; + ms_numDropsMoving--; + } + } +} + +void +ScreenDroplets::ProcessMoving(void) +{ + ScreenDropMoving *moving; + if(!ms_movingEnabled) + return; + for(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++) + if(moving->drop) + MoveDrop(moving); +} + +void +ScreenDroplets::Fade(void) +{ + ScreenDrop *drop; + for(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++) + if(drop->active) + drop->Fade(); +} + +void +ScreenDroplets::ScreenDrop::Fade(void) +{ + int delta = CTimer::GetTimeStepInMilliseconds(); + time += delta; + if(time < lifetime){ + color.a = 255 - time/lifetime*255; + }else if(fades){ + ScreenDroplets::ms_numDrops--; + active = false; + } +} + + +/* + * Im2D with two uv coors + */ + +#ifdef RW_D3D9 +// stolen from RW, not in a public header +namespace rw { +namespace d3d { +void addDynamicVB(uint32 length, uint32 fvf, IDirect3DVertexBuffer9 **buf); // NB: don't share this pointer +void removeDynamicVB(IDirect3DVertexBuffer9 **buf); +void addDynamicIB(uint32 length, IDirect3DIndexBuffer9 **buf); // NB: don't share this pointer +void removeDynamicIB(IDirect3DIndexBuffer9 **buf); +} +} +// different than im2d +#define NUMINDICES 1024 +#define NUMVERTICES 1024 + +static int primTypeMap[] = { + D3DPT_POINTLIST, // invalid + D3DPT_LINELIST, + D3DPT_LINESTRIP, + D3DPT_TRIANGLELIST, + D3DPT_TRIANGLESTRIP, + D3DPT_TRIANGLEFAN, + D3DPT_POINTLIST, // actually not supported! +}; +// end of stolen stuff + + +static IDirect3DVertexDeclaration9 *im2ddecl_uv2; +static IDirect3DVertexBuffer9 *im2dvertbuf_uv2; +static IDirect3DIndexBuffer9 *im2dindbuf_uv2; + +void +openim2d_uv2(void) +{ + using namespace rw; + using namespace d3d; + D3DVERTEXELEMENT9 elements[5] = { + { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 }, + { 0, offsetof(Im2DVertexUV2, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, + { 0, offsetof(Im2DVertexUV2, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + { 0, offsetof(Im2DVertexUV2, u2), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, + D3DDECL_END() + }; + assert(im2ddecl_uv2 == nil); + im2ddecl_uv2 = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements); + assert(im2ddecl_uv2); + + assert(im2dvertbuf_uv2 == nil); + im2dvertbuf_uv2 = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertexUV2), 0, true); + assert(im2dvertbuf_uv2); + addDynamicVB(NUMVERTICES*sizeof(Im2DVertexUV2), 0, &im2dvertbuf_uv2); + + assert(im2dindbuf_uv2 == nil); + im2dindbuf_uv2 = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(rw::uint16), true); + assert(im2dindbuf_uv2); + addDynamicIB(NUMINDICES*sizeof(rw::uint16), &im2dindbuf_uv2); +} + +void +closeim2d_uv2(void) +{ + using namespace rw; + using namespace d3d; + + d3d9::destroyVertexDeclaration(im2ddecl_uv2); + im2ddecl_uv2 = nil; + + removeDynamicVB(&im2dvertbuf_uv2); + destroyVertexBuffer(im2dvertbuf_uv2); + im2dvertbuf_uv2 = nil; + + removeDynamicIB(&im2dindbuf_uv2); + destroyIndexBuffer(im2dindbuf_uv2); + im2dindbuf_uv2 = nil; +} + +void +RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices) +{ + using namespace rw; + using namespace d3d; + + if(numVertices > NUMVERTICES || + numIndices > NUMINDICES){ + // TODO: error + return; + } + rw::uint16 *lockedindices = lockIndices(im2dindbuf_uv2, 0, numIndices*sizeof(rw::uint16), D3DLOCK_DISCARD); + memcpy(lockedindices, indices, numIndices*sizeof(rw::uint16)); + unlockIndices(im2dindbuf_uv2); + + rw::uint8 *lockedvertices = lockVertices(im2dvertbuf_uv2, 0, numVertices*sizeof(Im2DVertexUV2), D3DLOCK_DISCARD); + memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertexUV2)); + unlockVertices(im2dvertbuf_uv2); + + setStreamSource(0, im2dvertbuf_uv2, 0, sizeof(Im2DVertexUV2)); + setIndices(im2dindbuf_uv2); + setVertexDeclaration(im2ddecl_uv2); + + if(im2dOverridePS) + setPixelShader(im2dOverridePS); + else if(engine->device.getRenderState(TEXTURERASTER)) + setPixelShader(im2d_tex_PS); + else + setPixelShader(im2d_PS); + + d3d::flushCache(); + + rw::uint32 primCount = 0; + switch(primType){ + case PRIMTYPELINELIST: + primCount = numIndices/2; + break; + case PRIMTYPEPOLYLINE: + primCount = numIndices-1; + break; + case PRIMTYPETRILIST: + primCount = numIndices/3; + break; + case PRIMTYPETRISTRIP: + primCount = numIndices-2; + break; + case PRIMTYPETRIFAN: + primCount = numIndices-2; + break; + case PRIMTYPEPOINTLIST: + primCount = numIndices; + break; + } + d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0, + 0, numVertices, + 0, primCount); +} +#endif + +#ifdef RW_GL3 +// different than im2d +#define NUMINDICES 1024 +#define NUMVERTICES 1024 + +static rw::gl3::AttribDesc im2d_UV2_attribDesc[4] = { + { rw::gl3::ATTRIB_POS, GL_FLOAT, GL_FALSE, 4, + sizeof(Im2DVertexUV2), 0 }, + { rw::gl3::ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4, + sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, r) }, + { rw::gl3::ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2, + sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u) }, + { rw::gl3::ATTRIB_TEXCOORDS1, GL_FLOAT, GL_FALSE, 2, + sizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u2) } +}; + +static int primTypeMap[] = { + GL_POINTS, // invalid + GL_LINES, + GL_LINE_STRIP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + GL_POINTS +}; + +static int32 u_xform; + +uint32 im2D_UV2_Vbo, im2D_UV2_Ibo; +#ifdef RW_GL_USE_VAOS +uint32 im2D_UV2_Vao; +#endif + +void +openim2d_uv2(void) +{ + u_xform = rw::gl3::registerUniform("u_xform"); // this doesn't add a new one, so it's safe + + glGenBuffers(1, &im2D_UV2_Ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW); + + glGenBuffers(1, &im2D_UV2_Vbo); + glBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo); + glBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW); + +#ifdef RW_GL_USE_VAOS + glGenVertexArrays(1, &im2D_UV2_Vao); + glBindVertexArray(im2D_UV2_Vao); + setAttribPointers(im2d_UV2_attribDesc, 4); +#endif +} + +void +closeim2d_uv2(void) +{ + glDeleteBuffers(1, &im2D_UV2_Ibo); + glDeleteBuffers(1, &im2D_UV2_Vbo); +#ifdef RW_GL_USE_VAOS + glDeleteVertexArrays(1, &im2D_UV2_Vao); +#endif +} + +void +RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices) +{ + using namespace rw; + using namespace gl3; + + GLfloat xform[4]; + Camera *cam; + cam = (Camera*)engine->currentCamera; + +#ifdef RW_GL_USE_VAOS + glBindVertexArray(im2D_UV2_Vao); +#endif + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices); + + glBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo); + glBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertexUV2), vertices); + + xform[0] = 2.0f/cam->frameBuffer->width; + xform[1] = -2.0f/cam->frameBuffer->height; + xform[2] = -1.0f; + xform[3] = 1.0f; + + if(im2dOverrideShader) + im2dOverrideShader->use(); + else + assert(0);//im2dShader->use(); +#ifndef RW_GL_USE_VAOS + setAttribPointers(im2d_UV2_attribDesc, 4); +#endif + + glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform); + + flushCache(); + glDrawElements(primTypeMap[primType], numIndices, + GL_UNSIGNED_SHORT, nil); +#ifndef RW_GL_USE_VAOS + disableAttribPointers(im2d_UV2_attribDesc, 4); +#endif +} +#endif + +#endif diff --git a/src/extras/screendroplets.h b/src/extras/screendroplets.h new file mode 100644 index 00000000..090b1923 --- /dev/null +++ b/src/extras/screendroplets.h @@ -0,0 +1,78 @@ +#pragma once + +#ifdef SCREEN_DROPLETS + +class CParticleObject; + +class ScreenDroplets +{ +public: + enum { + MAXDROPS = 2000, + MAXDROPSMOVING = 700 + }; + + class ScreenDrop + { + public: + float x, y, time; // shorts on xbox (short float?) + float size, magnification, lifetime; // " + CRGBA color; + bool active; + bool fades; + + void Fade(void); + }; + + struct ScreenDropMoving + { + ScreenDrop *drop; + float dist; + }; + + static int ms_initialised; + static RwTexture *ms_maskTex; + static RwTexture *ms_screenTex; + + static bool ms_enabled; + static bool ms_movingEnabled; + + static ScreenDrop ms_drops[MAXDROPS]; + static int ms_numDrops; + static ScreenDropMoving ms_dropsMoving[MAXDROPSMOVING]; + static int ms_numDropsMoving; + + static CVector ms_prevCamUp; + static CVector ms_prevCamPos; + static CVector ms_camMoveDelta; + static float ms_camMoveDist; + static CVector ms_screenMoveDelta; + static float ms_screenMoveDist; + static float ms_camUpAngle; + + static int ms_splashDuration; + static CParticleObject *ms_splashObject; + + static void Initialise(void); + static void InitDraw(void); + static void Shutdown(void); + static void Process(void); + static void Render(void); + static void AddToRenderList(ScreenDrop *drop); + + static void Clear(void); + static ScreenDrop *NewDrop(float x, float y, float size, float lifetime, bool fades, int r = 255, int g = 255, int b = 255); + static void SetMoving(ScreenDroplets::ScreenDrop *drop); + static void FillScreen(int n); + static void FillScreenMoving(float amount, bool isBlood = false); + static void RegisterSplash(CParticleObject *pobj); + + static void ProcessCameraMovement(void); + static void SprayDrops(void); + static void NewTrace(ScreenDroplets::ScreenDropMoving *moving); + static void MoveDrop(ScreenDropMoving *moving); + static void ProcessMoving(void); + static void Fade(void); +}; + +#endif diff --git a/src/extras/shaders/Makefile b/src/extras/shaders/Makefile index 4b6027e2..51e009d6 100644 --- a/src/extras/shaders/Makefile +++ b/src/extras/shaders/Makefile @@ -2,7 +2,8 @@ all: im2d_gl.inc simple_fs_gl.inc default_UV2_gl.inc \ colourfilterIII_fs_gl.inc contrast_fs_gl.inc \ neoRim_gl.inc neoRimSkin_gl.inc \ neoWorldIII_fs_gl.inc neoGloss_vs_gl.inc neoGloss_fs_gl.inc \ - neoVehicle_vs_gl.inc neoVehicle_fs_gl.inc + neoVehicle_vs_gl.inc neoVehicle_fs_gl.inc \ + im2d_UV2_gl.inc screenDroplet_fs_gl.inc im2d_gl.inc: im2d.vert (echo 'const char *im2d_vert_src =';\ @@ -66,3 +67,13 @@ neoVehicle_fs_gl.inc: neoVehicle.frag (echo 'const char *neoVehicle_frag_src =';\ sed 's/..*/"&\\n"/' neoVehicle.frag;\ echo ';') >neoVehicle_fs_gl.inc + +im2d_UV2_gl.inc: im2d_UV2.vert + (echo 'const char *im2d_UV2_vert_src =';\ + sed 's/..*/"&\\n"/' im2d_UV2.vert;\ + echo ';') >im2d_UV2_gl.inc + +screenDroplet_fs_gl.inc: screenDroplet.frag + (echo 'const char *screenDroplet_frag_src =';\ + sed 's/..*/"&\\n"/' screenDroplet.frag;\ + echo ';') >screenDroplet_fs_gl.inc diff --git a/src/extras/shaders/im2d_UV2.vert b/src/extras/shaders/im2d_UV2.vert new file mode 100644 index 00000000..e5fd4d08 --- /dev/null +++ b/src/extras/shaders/im2d_UV2.vert @@ -0,0 +1,21 @@ +uniform vec4 u_xform; + +VSIN(ATTRIB_POS) vec4 in_pos; + +VSOUT vec4 v_color; +VSOUT vec2 v_tex0; +VSOUT vec2 v_tex1; +VSOUT float v_fog; + +void +main(void) +{ + gl_Position = in_pos; + gl_Position.w = 1.0; + gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw; + v_fog = DoFog(gl_Position.z); + gl_Position.xyz *= gl_Position.w; + v_color = in_color; + v_tex0 = in_tex0; + v_tex1 = in_tex1; +} diff --git a/src/extras/shaders/im2d_UV2_gl.inc b/src/extras/shaders/im2d_UV2_gl.inc new file mode 100644 index 00000000..3feb2bc1 --- /dev/null +++ b/src/extras/shaders/im2d_UV2_gl.inc @@ -0,0 +1,23 @@ +const char *im2d_UV2_vert_src = +"uniform vec4 u_xform;\n" + +"VSIN(ATTRIB_POS) vec4 in_pos;\n" + +"VSOUT vec4 v_color;\n" +"VSOUT vec2 v_tex0;\n" +"VSOUT vec2 v_tex1;\n" +"VSOUT float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" gl_Position = in_pos;\n" +" gl_Position.w = 1.0;\n" +" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n" +" v_fog = DoFog(gl_Position.z);\n" +" gl_Position.xyz *= gl_Position.w;\n" +" v_color = in_color;\n" +" v_tex0 = in_tex0;\n" +" v_tex1 = in_tex1;\n" +"}\n" +; diff --git a/src/extras/shaders/screenDroplet.frag b/src/extras/shaders/screenDroplet.frag new file mode 100644 index 00000000..84d30bd5 --- /dev/null +++ b/src/extras/shaders/screenDroplet.frag @@ -0,0 +1,18 @@ +uniform sampler2D tex0; +uniform sampler2D tex1; + +FSIN vec4 v_color; +FSIN vec2 v_tex0; +FSIN vec2 v_tex1; +FSIN float v_fog; + +void +main(void) +{ + vec4 color; + color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); + color *= texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y)); + + FRAGCOLOR(color); +} + diff --git a/src/extras/shaders/screenDroplet_PS.cso b/src/extras/shaders/screenDroplet_PS.cso new file mode 100644 index 00000000..5508096b Binary files /dev/null and b/src/extras/shaders/screenDroplet_PS.cso differ diff --git a/src/extras/shaders/screenDroplet_PS.hlsl b/src/extras/shaders/screenDroplet_PS.hlsl new file mode 100644 index 00000000..4d41da68 --- /dev/null +++ b/src/extras/shaders/screenDroplet_PS.hlsl @@ -0,0 +1,17 @@ +struct VS_out { + float4 Position : POSITION; + float2 TexCoord0 : TEXCOORD0; + float2 TexCoord1 : TEXCOORD1; + float4 Color : COLOR0; +}; + +sampler2D tex0 : register(s0); +sampler2D tex1 : register(s1); + +float4 main(VS_out input) : COLOR +{ + float4 color = input.Color; + color *= tex2D(tex0, input.TexCoord0.xy); + color *= tex2D(tex1, input.TexCoord1.xy); + return color; +} diff --git a/src/extras/shaders/screenDroplet_PS.inc b/src/extras/shaders/screenDroplet_PS.inc new file mode 100644 index 00000000..c2055188 --- /dev/null +++ b/src/extras/shaders/screenDroplet_PS.inc @@ -0,0 +1,29 @@ +static unsigned char screenDroplet_PS_cso[] = { + 0x00, 0x02, 0xff, 0xff, 0xfe, 0xff, 0x2c, 0x00, 0x43, 0x54, 0x41, 0x42, + 0x1c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, + 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x06, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x30, + 0x00, 0xab, 0xab, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x31, + 0x00, 0xab, 0xab, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x32, + 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, + 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, + 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, + 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, + 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x03, 0xb0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x03, 0xb0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, + 0x00, 0x08, 0x0f, 0xa0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, + 0x01, 0x08, 0x0f, 0xa0, 0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, + 0x00, 0x00, 0xe4, 0xb0, 0x00, 0x08, 0xe4, 0xa0, 0x42, 0x00, 0x00, 0x03, + 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0xb0, 0x01, 0x08, 0xe4, 0xa0, + 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0x80, + 0x00, 0x00, 0xe4, 0x90, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, + 0x01, 0x00, 0xe4, 0x80, 0x00, 0x00, 0xe4, 0x80, 0x01, 0x00, 0x00, 0x02, + 0x00, 0x08, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0x80, 0xff, 0xff, 0x00, 0x00 +}; diff --git a/src/extras/shaders/screenDroplet_fs_gl.inc b/src/extras/shaders/screenDroplet_fs_gl.inc new file mode 100644 index 00000000..dd393b02 --- /dev/null +++ b/src/extras/shaders/screenDroplet_fs_gl.inc @@ -0,0 +1,20 @@ +const char *screenDroplet_frag_src = +"uniform sampler2D tex0;\n" +"uniform sampler2D tex1;\n" + +"FSIN vec4 v_color;\n" +"FSIN vec2 v_tex0;\n" +"FSIN vec2 v_tex1;\n" +"FSIN float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 color;\n" +" color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" color *= texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n" + +" FRAGCOLOR(color);\n" +"}\n" + +; diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index a8afaf6c..71f223d7 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -8,6 +8,7 @@ #include "Camera.h" #include "Game.h" #include "DMAudio.h" +#include "screendroplets.h" CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS]; @@ -18,6 +19,8 @@ CParticleObject *CParticleObject::pUnusedListHead; CAudioHydrant List[MAX_AUDIOHYDRANTS]; +CAudioHydrant *CAudioHydrant::Get(int n) { return &List[n]; } + bool CAudioHydrant::Add(CParticleObject *particleobject) { @@ -247,6 +250,9 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe pobj->m_nSkipFrames = 3; #endif pobj->m_nCreationChance = 0; +#ifdef SCREEN_DROPLETS + ScreenDroplets::RegisterSplash(pobj); +#endif break; } diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index 34a672bb..e4e7fcd2 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -103,4 +103,6 @@ public: static bool Add (CParticleObject *particleobject); static void Remove(CParticleObject *particleobject); + + static CAudioHydrant *Get(int n); // for neo screen droplets }; \ No newline at end of file -- cgit v1.2.3 From 9e45feb4fa0a841b1d059bcab8507fd80708d6e7 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 19 Nov 2020 21:12:20 +0200 Subject: Reorganize CPed functions into their original cpp files --- src/control/Pickups.cpp | 82 + src/core/FileLoader.cpp | 1 - src/modelinfo/PedModelInfo.h | 1 - src/peds/CivilianPed.cpp | 42 + src/peds/Ped.cpp | 22640 +++++++++++++---------------------------- src/peds/Ped.h | 48 +- src/peds/PedAI.cpp | 5413 ++++++++++ src/peds/PedFight.cpp | 3250 ++++++ src/peds/PedStats.cpp | 118 - src/peds/PedStats.h | 80 - src/peds/PedType.cpp | 113 + src/peds/PedType.h | 79 + src/render/Renderer.cpp | 31 + src/vehicles/Automobile.cpp | 87 + src/weapons/Weapon.cpp | 10 + 15 files changed, 16002 insertions(+), 15993 deletions(-) create mode 100644 src/peds/PedAI.cpp create mode 100644 src/peds/PedFight.cpp delete mode 100644 src/peds/PedStats.cpp delete mode 100644 src/peds/PedStats.h (limited to 'src') diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 6fea43fb..8951ed82 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1432,3 +1432,85 @@ CPacManPickups::ResetPowerPillsCarriedByPlayer() FindPlayerVehicle()->m_fForceMultiplier = 1.0f; } } + +void +CPed::CreateDeadPedMoney(void) +{ + if (!CGame::nastyGame) + return; + + int mi = GetModelIndex(); + + if ((mi >= MI_COP && mi <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle) + return; + + int money = CGeneral::GetRandomNumber() % 60; + if (money < 10) + return; + + if (money == 43) + money = 700; + + int pickupCount = money / 40 + 1; + int moneyPerPickup = money / pickupCount; + + for(int i = 0; i < pickupCount; i++) { + // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish. + float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x; + float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y; + bool found = false; + float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f; + if (found) { + CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7)); + } + } +} + +void +CPed::CreateDeadPedWeaponPickups(void) +{ + bool found = false; + float angleToPed; + CVector pickupPos; + + if (bInVehicle) + return; + + for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { + + eWeaponType weapon = GetWeapon(i).m_eWeaponType; + int weaponAmmo = GetWeapon(i).m_nAmmoTotal; + if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || weaponAmmo == 0) + continue; + + angleToPed = i * 1.75f; + pickupPos = GetPosition(); + pickupPos.x += 1.5f * Sin(angleToPed); + pickupPos.y += 1.5f * Cos(angleToPed); + pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; + + CVector pedPos = GetPosition(); + pedPos.z += 0.3f; + + CVector pedToPickup = pickupPos - pedPos; + float distance = pedToPickup.Magnitude(); + + // outer edge of pickup + distance = (distance + 0.3f) / distance; + CVector pickupPos2 = pedPos; + pickupPos2 += distance * pedToPickup; + + // pickup must be on ground and line to its edge must be clear + if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) { + // otherwise try another position (but disregard second check apparently) + angleToPed += 3.14f; + pickupPos = GetPosition(); + pickupPos.x += 1.5f * Sin(angleToPed); + pickupPos.y += 1.5f * Cos(angleToPed); + pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; + } + if (found) + CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon])); + } + ClearWeapons(); +} \ No newline at end of file diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 3f731658..f46b6134 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -11,7 +11,6 @@ #include "HandlingMgr.h" #include "CarCtrl.h" #include "PedType.h" -#include "PedStats.h" #include "AnimManager.h" #include "Game.h" #include "RwHelper.h" diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h index d73d3646..f467fe8a 100644 --- a/src/modelinfo/PedModelInfo.h +++ b/src/modelinfo/PedModelInfo.h @@ -2,7 +2,6 @@ #include "ClumpModelInfo.h" #include "PedType.h" -#include "PedStats.h" enum PedNode { PED_TORSO, diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 2d782a73..401d2e67 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -424,3 +424,45 @@ CCivilianPed::ProcessControl(void) if (m_moved.Magnitude() > 0.0f) Avoid(); } + +// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB but that's not true, someone made it up. +bool +CPed::RunToReportCrime(eCrimeType crimeToReport) +{ +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + if (bRunningToPhone) { + if (!isPhoneAvailable(m_phoneId)) { + m_phoneId = -1; + bIsRunning = false; + ClearSeek(); // clears bRunningToPhone + return false; + } + + return true; + } +#else + // They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it. + if (m_nPedState == PED_SEEK_POS) + return false; +#endif + + CVector pos = GetPosition(); + int phoneId = gPhoneInfo.FindNearestFreePhone(&pos); + + if (phoneId == -1) + return false; + + CPhone *phone = &gPhoneInfo.m_aPhones[phoneId]; +#ifndef PEDS_REPORT_CRIMES_ON_PHONE + if (phone->m_nState != PHONE_STATE_FREE) + return false; +#endif + + bRunningToPhone = true; + SetSeek(phone->m_pEntity->GetMatrix() * -phone->m_pEntity->GetForward(), 1.0f); // original: phone.m_vecPos, 0.3f + SetMoveState(PEDMOVE_RUN); + bIsRunning = true; // not there in original + m_phoneId = phoneId; + m_crimeToReportOnPhone = crimeToReport; + return true; +} \ No newline at end of file diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 05e00ec2..c41c1f0c 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -3,111 +3,44 @@ #include "main.h" #include "Pools.h" #include "Particle.h" -#include "Stats.h" -#include "World.h" #include "RpAnimBlend.h" #include "Bones.h" #include "Ped.h" -#include "Wanted.h" -#include "PlayerPed.h" -#include "PedType.h" -#include "AnimBlendClumpData.h" #include "AnimBlendAssociation.h" #include "Fire.h" #include "DMAudio.h" #include "General.h" -#include "SurfaceTable.h" #include "VisibilityPlugins.h" -#include "AudioManager.h" #include "HandlingMgr.h" #include "Replay.h" -#include "Camera.h" #include "Radar.h" #include "PedPlacement.h" #include "Shadows.h" #include "Weather.h" #include "ZoneCull.h" #include "Population.h" -#include "Renderer.h" -#include "Lights.h" -#include "PointLights.h" #include "Pad.h" #include "Phones.h" -#include "Darkel.h" -#include "PathFind.h" -#include "ModelIndices.h" -#include "FileMgr.h" -#include "TempColModels.h" -#include "Pickups.h" -#include "Train.h" #include "TrafficLights.h" -#include "PedRoutes.h" -#include "Sprite.h" -#include "RwHelper.h" -#include "Font.h" -#include "Text.h" #include "CopPed.h" #include "Script.h" #include "CarCtrl.h" #include "Garages.h" #include "WaterLevel.h" -#include "CarAI.h" -#include "Zones.h" -#include "Cranes.h" #include "Timecycle.h" #include "ParticleObject.h" #include "Floater.h" #include "Range2D.h" -#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) - CPed *gapTempPedList[50]; uint16 gnNumTempPedList; static CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; -uint16 nPlayerInComboMove; - -RpClump *flyingClumpTemp; - -// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat. -FightMove tFightMoves[NUM_FIGHTMOVES] = { - {NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_PUNCH_R, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0}, - {ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0}, - {ANIM_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0}, - {ANIM_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0}, - {ANIM_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0}, - {ANIM_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0}, - {ANIM_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0}, - {ANIM_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0}, - {ANIM_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0}, - {ANIM_KICK_FLOOR, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0}, - {ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, -}; uint16 CPed::nThreatReactionRangeMultiplier = 1; uint16 CPed::nEnterCarRangeMultiplier = 1; -CVector vecPedCarDoorAnimOffset; -CVector vecPedCarDoorLoAnimOffset; -CVector vecPedVanRearDoorAnimOffset; -CVector vecPedQuickDraggedOutCarAnimOffset; -CVector vecPedDraggedOutCarAnimOffset; -CVector vecPedTrainDoorAnimOffset; - bool CPed::bNastyLimbsCheat; bool CPed::bPedCheat2; bool CPed::bPedCheat3; @@ -122,53 +55,6 @@ void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete(( bool CPed::bPopHeadsOnHeadshot = false; #endif -CPed::~CPed(void) -{ - CWorld::Remove(this); - CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); - if (InVehicle()){ - uint8 door_flag = GetCarDoorFlag(m_vehEnterType); - if (m_pMyVehicle->pDriver == this) - m_pMyVehicle->pDriver = nil; - else { - // FIX: Passenger counter now decreasing after removing ourself from vehicle. - m_pMyVehicle->RemovePassenger(this); - } - if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) - m_pMyVehicle->m_nGettingOutFlags &= ~door_flag; - bInVehicle = false; - m_pMyVehicle = nil; - } else if (EnteringCar()) { - QuitEnteringCar(); - } - if (m_pFire) - m_pFire->Extinguish(); - CPopulation::UpdatePedCount((ePedType)m_nPedType, true); - DMAudio.DestroyEntity(m_audioEntityId); -} - -void -CPed::FlagToDestroyWhenNextProcessed(void) -{ - bRemoveFromWorld = true; - if (!InVehicle()) - return; - if (m_pMyVehicle->pDriver == this){ - m_pMyVehicle->pDriver = nil; - if (IsPlayer() && m_pMyVehicle->GetStatus() != STATUS_WRECKED) - m_pMyVehicle->SetStatus(STATUS_ABANDONED); - }else{ - m_pMyVehicle->RemovePassenger(this); - } - bInVehicle = false; - m_pMyVehicle = nil; - if (CharCreatedBy == MISSION_CHAR) - m_nPedState = PED_DEAD; - else - m_nPedState = PED_NONE; - m_pVehicleAnim = nil; -} - CPed::CPed(uint32 pedType) : m_pedIK(this) { m_type = ENTITY_TYPE_PED; @@ -397,11416 +283,3884 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) CPopulation::UpdatePedCount((ePedType)m_nPedType, false); } -uint32 -CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo) +CPed::~CPed(void) { - CWeapon &weapon = GetWeapon(weaponType); - - if (HasWeapon(weaponType)) { - if (weapon.m_nAmmoTotal + ammo > 99999) - weapon.m_nAmmoTotal = 99999; - else - weapon.m_nAmmoTotal += ammo; - - weapon.Reload(); - } else { - weapon.Initialise(weaponType, ammo); - // TODO: It seems game uses this as both weapon count and max WeaponType we have, which is ofcourse erroneous. - m_maxWeaponTypeAllowed++; + CWorld::Remove(this); + CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); + if (InVehicle()){ + uint8 door_flag = GetCarDoorFlag(m_vehEnterType); + if (m_pMyVehicle->pDriver == this) + m_pMyVehicle->pDriver = nil; + else { + // FIX: Passenger counter now decreasing after removing ourself from vehicle. + m_pMyVehicle->RemovePassenger(this); + } + if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) + m_pMyVehicle->m_nGettingOutFlags &= ~door_flag; + bInVehicle = false; + m_pMyVehicle = nil; + } else if (EnteringCar()) { + QuitEnteringCar(); } - if (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO) - weapon.m_eWeaponState = WEAPONSTATE_READY; - - return weaponType; + if (m_pFire) + m_pFire->Extinguish(); + CPopulation::UpdatePedCount((ePedType)m_nPedType, true); + DMAudio.DestroyEntity(m_audioEntityId); } -static RwObject* -RemoveAllModelCB(RwObject *object, void *data) +void +CPed::Initialise(void) { - RpAtomic *atomic = (RpAtomic*)object; - if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) { - RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic); - RpAtomicDestroy(atomic); - } - return object; + debug("Initialising CPed...\n"); + CPedType::Initialise(); + LoadFightData(); + SetAnimOffsetForEnterOrExitVehicle(); + debug("CPed ready\n"); } -static PedOnGroundState -CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround) +void +CPed::SetModelIndex(uint32 mi) { - PedOnGroundState stateToReturn; - float angleToFace; - CPed *currentPed = nil; - PedState currentPedState; - CPed *pedOnTheFloor = nil; - CPed *deadPed = nil; - CPed *pedBelow = nil; - bool foundDead = false; - bool foundOnTheFloor = false; - bool foundBelow = false; - float angleDiff; - float distance; - - if (!CGame::nastyGame) - return NO_PED; - - for (int currentPedId = 0; currentPedId < attacker->m_numNearPeds; currentPedId++) { - - currentPed = attacker->m_nearPeds[currentPedId]; - - CVector posDifference = currentPed->GetPosition() - attacker->GetPosition(); - distance = posDifference.Magnitude(); - - if (distance < 2.0f) { - angleToFace = CGeneral::GetRadianAngleBetweenPoints( - currentPed->GetPosition().x, currentPed->GetPosition().y, - attacker->GetPosition().x, attacker->GetPosition().y); + CEntity::SetModelIndex(mi); + RpAnimBlendClumpInit(GetClump()); + RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames); + CPedModelInfo *modelInfo = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()); + SetPedStats(modelInfo->m_pedStatType); + m_headingRate = m_pedStats->m_headingChangeRate; + m_animGroup = (AssocGroupId) modelInfo->m_animGroup; + CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE); - angleToFace = CGeneral::LimitRadianAngle(angleToFace); - attacker->m_fRotationCur = CGeneral::LimitRadianAngle(attacker->m_fRotationCur); + // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D. + (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta; - angleDiff = Abs(angleToFace - attacker->m_fRotationCur); +#ifdef PED_SKIN + if(modelInfo->GetHitColModel() == nil) + modelInfo->CreateHitColModelSkinned(GetClump()); +#endif +} - if (angleDiff > PI) - angleDiff = 2 * PI - angleDiff; +void +CPed::SetPedStats(ePedStats pedStat) +{ + m_pedStats = CPedStats::ms_apPedStats[pedStat]; +} - currentPedState = currentPed->m_nPedState; +void +CPed::BuildPedLists(void) +{ + if (((CTimer::GetFrameCounter() + m_randomSeed) % 16) == 0) { + CVector centre = CEntity::GetBoundCentre(); + CRect rect(centre.x - 20.0f, + centre.y - 20.0f, + centre.x + 20.0f, + centre.y + 20.0f); + int xstart = CWorld::GetSectorIndexX(rect.left); + int ystart = CWorld::GetSectorIndexY(rect.top); + int xend = CWorld::GetSectorIndexX(rect.right); + int yend = CWorld::GetSectorIndexY(rect.bottom); + gnNumTempPedList = 0; - if (currentPed->OnGroundOrGettingUp()) { - if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) { - if (currentPedState == PED_DEAD) { - foundDead = 1; - if (!deadPed) - deadPed = currentPed; - } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) { - foundOnTheFloor = 1; - if (!pedOnTheFloor) - pedOnTheFloor = currentPed; + for(int y = ystart; y <= yend; y++) { + for(int x = xstart; x <= xend; x++) { + for (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) { + CPed *ped = (CPed*)pedPtrNode->item; + if (ped != this && !ped->bInVehicle) { + float dist = (ped->GetPosition() - GetPosition()).Magnitude2D(); + if (nThreatReactionRangeMultiplier * 30.0f > dist) { + gapTempPedList[gnNumTempPedList] = ped; + gnNumTempPedList++; + assert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList)); + } } } - } else if ((distance < 0.8f && angleDiff < DEGTORAD(75.0f)) - || (distance < 1.3f && angleDiff < DEGTORAD(55.0f)) - || (distance < 1.7f && angleDiff < DEGTORAD(35.0f)) - || (distance < 2.0f && angleDiff < DEGTORAD(30.0f))) { - - // Either this condition or below one was probably returning 4 early in development. See Fight(). - foundBelow = 1; - pedBelow = currentPed; - break; - } else { - if (angleDiff < DEGTORAD(75.0f)) { - foundBelow = 1; - if (!pedBelow) - pedBelow = currentPed; - } } } - } + gapTempPedList[gnNumTempPedList] = nil; + SortPeds(gapTempPedList, 0, gnNumTempPedList - 1); + for (m_numNearPeds = 0; m_numNearPeds < ARRAY_SIZE(m_nearPeds); m_numNearPeds++) { + CPed *ped = gapTempPedList[m_numNearPeds]; + if (!ped) + break; - if (foundOnTheFloor) { - currentPed = pedOnTheFloor; - stateToReturn = PED_ON_THE_FLOOR; - } else if (foundDead) { - currentPed = deadPed; - stateToReturn = PED_DEAD_ON_THE_FLOOR; - } else if (foundBelow) { - currentPed = pedBelow; - stateToReturn = PED_IN_FRONT_OF_ATTACKER; + m_nearPeds[m_numNearPeds] = ped; + } + for (int pedToClear = m_numNearPeds; pedToClear < ARRAY_SIZE(m_nearPeds); pedToClear++) + m_nearPeds[pedToClear] = nil; } else { - currentPed = nil; - stateToReturn = NO_PED; + for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) { + bool removePed = false; + if (m_nearPeds[i]) { + if (m_nearPeds[i]->IsPointerValid()) { + float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D(); + if (distSqr > 900.0f) + removePed = true; + } else + removePed = true; + } + if (removePed) { + // If we arrive here, the ped we're checking isn't "near", so we should remove it. + for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) { + m_nearPeds[j] = m_nearPeds[j + 1]; + m_nearPeds[j + 1] = nil; + } + // Above loop won't work on last slot, so we need to empty it. + m_nearPeds[ARRAY_SIZE(m_nearPeds) - 1] = nil; + m_numNearPeds--; + } else + i++; + } } - - if (pedOnGround) - *pedOnGround = currentPed; - - return stateToReturn; -} - -bool -CPed::IsPlayer(void) -{ - return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 || - m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4; } bool -CPed::UseGroundColModel(void) +CPed::OurPedCanSeeThisOne(CEntity *target) { - return m_nPedState == PED_FALL || - m_nPedState == PED_DIVE_AWAY || - m_nPedState == PED_DIE || - m_nPedState == PED_DEAD; -} + CColPoint colpoint; + CEntity *ent; -bool -CPed::CanSetPedState(void) -{ - return !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR; -} + CVector2D dist = CVector2D(target->GetPosition()) - CVector2D(GetPosition()); -bool -CPed::IsPedInControl(void) -{ - return m_nPedState <= PED_STATES_NO_AI - && !bIsInTheAir && !bIsLanding - && m_fHealth > 0.0f; -} + // Check if target is behind ped + if (DotProduct2D(dist, CVector2D(GetForward())) < 0.0f) + return false; -bool -CPed::CanStrafeOrMouseControl(void) -{ -#ifdef FREE_CAM - if (CCamera::bFreeCam) + // Check if target is too far away + if (dist.Magnitude() >= 40.0f) return false; -#endif - return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY || - m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP; + + // Check line of sight from head + CVector headPos = this->GetPosition(); + headPos.z += 1.0f; + return !CWorld::ProcessLineOfSight(headPos, target->GetPosition(), colpoint, ent, true, false, false, false, false, false); } +// Some kind of binary sort void -CPed::AddWeaponModel(int id) +CPed::SortPeds(CPed **list, int min, int max) { - RpAtomic *atm; + if (min >= max) + return; - if (id != -1) { -#ifdef PED_SKIN - if (IsClumpSkinned(GetClump())) { - if (m_pWeaponModel) - RemoveWeaponModel(-1); + CVector leftDiff, rightDiff; + CVector middleDiff = GetPosition() - list[(max + min) / 2]->GetPosition(); + float middleDist = middleDiff.Magnitude(); - m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); - } else -#endif - { - atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); - RwFrameDestroy(RpAtomicGetFrame(atm)); - RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame); - RpClumpAddAtomic(GetClump(), atm); + int left = max; + int right = min; + while(right <= left){ + float rightDist, leftDist; + do { + rightDiff = GetPosition() - list[right]->GetPosition(); + rightDist = rightDiff.Magnitude(); + } while (middleDist > rightDist && ++right); + + do { + leftDiff = GetPosition() - list[left]->GetPosition(); + leftDist = leftDiff.Magnitude(); + } while (middleDist < leftDist && left--); + + if (right <= left) { + CPed *ped = list[right]; + list[right] = list[left]; + list[left] = ped; + right++; + left--; } - m_wepModelID = id; } + SortPeds(list, min, left); + SortPeds(list, right, max); } void -CPed::AimGun(void) +CPed::SetMoveState(eMoveState state) { - CVector vector; - - if (m_pSeekTarget) { - if (m_pSeekTarget->IsPed()) { - ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(vector, PED_MID); - } else { - vector = m_pSeekTarget->GetPosition(); - } - Say(SOUND_PED_ATTACK); - - bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(vector); - if (m_pLookTarget != m_pSeekTarget) { - SetLookFlag(m_pSeekTarget, true); - } - - } else { - if (IsPlayer()) { - bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading); - } else { - bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f); - } - } + m_nMoveState = state; } void -CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer) +CPed::SetMoveAnim(void) { - CVector pos2 = CVector( - pos.x, - pos.y, - pos.z + 0.1f - ); - - if (!IsPlayer() || evenOnPlayer) { - ++CStats::HeadsPopped; + if (m_nStoredMoveState == m_nMoveState || !IsPedInControl()) + return; - // BUG: This condition will always return true. Even fixing it won't work, because these states are unused. - // if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) { - SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - // } + if (m_nMoveState == PEDMOVE_NONE) { + m_nStoredMoveState = PEDMOVE_NONE; + return; + } - bBodyPartJustCameOff = true; - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150; + AssocGroupId animGroupToUse; + if (m_leader && m_leader->IsPlayer()) + animGroupToUse = ASSOCGRP_PLAYER; + else + animGroupToUse = m_animGroup; - CParticle::AddParticle(PARTICLE_TEST, pos2, - CVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0); + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK); + if (!animAssoc) { + CAnimBlendAssociation *fightIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); + animAssoc = fightIdleAssoc; + if (fightIdleAssoc && m_nPedState == PED_FIGHT) + return; - if (CEntity::GetIsOnScreen()) { - for(int i=0; i < 32; i++) { - CParticle::AddParticle(PARTICLE_BLOOD_SMALL, - pos2, CVector(0.0f, 0.0f, 0.03f), - nil, 0.0f, 0, 0, 0, 0); + if (fightIdleAssoc) { + CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); + if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 8.0f); } + } + } + if (!animAssoc) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); + if (animAssoc) + if (m_nWaitState == WAITSTATE_STUCK || m_nWaitState == WAITSTATE_FINISH_FLEE) + return; - for (int i = 0; i < 16; i++) { - CParticle::AddParticle(PARTICLE_DEBRIS2, - pos2, - CVector(0.0f, 0.0f, 0.01f), - nil, 0.0f, 0, 0, 0, 0); + if (animAssoc) { + CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); + if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f); } } } -} + if (!animAssoc) { + m_nStoredMoveState = m_nMoveState; + if (m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT) { + for (CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL); + assoc; assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_PARTIAL)) { -static RwObject* -SetPedAtomicVisibilityCB(RwObject* object, void* data) -{ - if (data == nil) - RpAtomicSetFlags((RpAtomic*)object, 0); - return object; -} + if (!(assoc->flags & ASSOC_FADEOUTWHENDONE)) { + assoc->blendDelta = -2.0f; + assoc->flags |= ASSOC_DELETEFADEDOUT; + } + } -static RwFrame* -RecurseFrameChildrenVisibilityCB(RwFrame* frame, void* data) -{ - RwFrameForAllObjects(frame, SetPedAtomicVisibilityCB, data); - RwFrameForAllChildren(frame, RecurseFrameChildrenVisibilityCB, nil); - return frame; -} + ClearAimFlag(); + ClearLookFlag(); + } -void -CPed::RemoveBodyPart(PedNode nodeId, int8 direction) -{ - RwFrame *frame; - CVector pos; + switch (m_nMoveState) { + case PEDMOVE_STILL: + animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f); + break; + case PEDMOVE_WALK: + animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_WALK, 1.0f); + break; + case PEDMOVE_RUN: + if (m_nPedState == PED_FLEE_ENTITY) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 3.0f); + } else { + animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 1.0f); + } + break; + case PEDMOVE_SPRINT: + animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_SPRINT, 1.0f); + break; + default: + break; + } - frame = m_pFrames[nodeId]->frame; - if (frame) { - if (CGame::nastyGame) { -#ifdef PED_SKIN - if(!IsClumpSkinned(GetClump())) -#endif - { -#ifdef DEBUGMENU - if (bPopHeadsOnHeadshot || nodeId != PED_HEAD) -#else - if (nodeId != PED_HEAD) -#endif - SpawnFlyingComponent(nodeId, direction); + if (animAssoc) { + if (m_leader) { + CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_WALK); + if (!walkAssoc) + walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_RUN); - RecurseFrameChildrenVisibilityCB(frame, nil); - } - pos.x = 0.0f; - pos.y = 0.0f; - pos.z = 0.0f; - TransformToNode(pos, PED_HEAD); - - if (CEntity::GetIsOnScreen()) { - CParticle::AddParticle(PARTICLE_TEST, pos, - CVector(0.0f, 0.0f, 0.0f), - nil, 0.1f, 0, 0, 0, 0); - - for (int i = 0; i < 16; i++) { - CParticle::AddParticle(PARTICLE_BLOOD_SMALL, - pos, - CVector(0.0f, 0.0f, 0.03f), - nil, 0.0f, 0, 0, 0, 0); + if (!walkAssoc) + walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_SPRINT); + + if (walkAssoc) { + animAssoc->speed = walkAssoc->speed; + } else { + if (CharCreatedBy == MISSION_CHAR) + animAssoc->speed = 1.0f; + else + animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX; + } + } else { + if (CharCreatedBy == MISSION_CHAR) + animAssoc->speed = 1.0f; + else + animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX; } - bBodyPartJustCameOff = true; - m_bodyPartBleeding = nodeId; } - } else { - printf("Trying to remove ped component"); } } void -CPed::SetLookFlag(CEntity *target, bool keepTryingToLook) +CPed::StopNonPartialAnims(void) { - if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { - bIsLooking = true; - bIsRestoringLook = false; - m_pLookTarget = target; - m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget); - m_fLookDirection = 999999.0f; - m_lookTimer = 0; - bKeepTryingToLook = keepTryingToLook; - if (m_nPedState != PED_DRIVING) { - m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; - } - } -} + CAnimBlendAssociation *assoc; -void -CPed::SetLookFlag(float direction, bool keepTryingToLook) -{ - if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { - bIsLooking = true; - bIsRestoringLook = false; - m_pLookTarget = nil; - m_fLookDirection = direction; - m_lookTimer = 0; - bKeepTryingToLook = keepTryingToLook; - if (m_nPedState != PED_DRIVING) { - m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; - } + for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + if (!assoc->IsPartial()) + assoc->flags &= ~ASSOC_RUNNING; } } void -CPed::SetLookTimer(int time) +CPed::RestartNonPartialAnims(void) { - if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { - m_lookTimer = CTimer::GetTimeInMilliseconds() + time; + CAnimBlendAssociation *assoc; + + for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + if (!assoc->IsPartial()) + assoc->SetRun(); } } -bool -CPed::OurPedCanSeeThisOne(CEntity *target) +void +CPed::SetStoredState(void) { - CColPoint colpoint; - CEntity *ent; - - CVector2D dist = CVector2D(target->GetPosition()) - CVector2D(GetPosition()); - - // Check if target is behind ped - if (DotProduct2D(dist, CVector2D(GetForward())) < 0.0f) - return false; - - // Check if target is too far away - if (dist.Magnitude() >= 40.0f) - return false; + if (m_nLastPedState != PED_NONE || !CanPedReturnToState()) + return; - // Check line of sight from head - CVector headPos = this->GetPosition(); - headPos.z += 1.0f; - return !CWorld::ProcessLineOfSight(headPos, target->GetPosition(), colpoint, ent, true, false, false, false, false, false); + if (m_nPedState == PED_WANDER_PATH) { + bFindNewNodeAfterStateRestore = true; + if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) + m_nMoveState = PEDMOVE_WALK; + } +#ifdef VC_PED_PORTS + if (m_nPedState != PED_IDLE) +#endif + { + m_nLastPedState = m_nPedState; + if (m_nMoveState >= m_nPrevMoveState) + m_nPrevMoveState = m_nMoveState; + } } void -CPed::Avoid(void) +CPed::RestorePreviousState(void) { - CPed *nearestPed; - - if(m_pedStats->m_temper > m_pedStats->m_fear && m_pedStats->m_temper > 50) + if(!CanSetPedState() || m_nPedState == PED_FALL) return; - if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { - - if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) { - nearestPed = m_nearPeds[0]; - - if (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_pedInObjective) { + if (m_nPedState == PED_GETUP && !bGetUpAnimStarted) + return; - // Check if this ped wants to avoid the nearest one - if (CPedType::GetAvoid(m_nPedType) & CPedType::GetFlag(nearestPed->m_nPedType)) { - - // Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters. - // If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else. - - // Game converts from radians to degress and back again here, doesn't make much sense - CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur)); - forward.Normalise(); // this is kinda pointless - - // Move forward 1.25 meters - CVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f; - - // Get distance to ped we want to avoid - CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition; - - if (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) { - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() - + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter()) - % 1000 / 5; + if (InVehicle()) { + m_nPedState = PED_DRIVING; + m_nLastPedState = PED_NONE; + } else { + if (m_nLastPedState == PED_NONE) { + if (!IsPlayer() && CharCreatedBy != MISSION_CHAR && m_objective == OBJECTIVE_NONE) { + if (SetWanderPath(CGeneral::GetRandomNumber() & 7) != 0) + return; + } + SetIdle(); + return; + } - m_fRotationDest += DEGTORAD(45.0f); - if (!bIsLooking) { - SetLookFlag(nearestPed, false); - SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800)); + switch (m_nLastPedState) { + case PED_IDLE: + SetIdle(); + break; + case PED_WANDER_PATH: + m_nPedState = PED_WANDER_PATH; + bIsRunning = false; + if (bFindNewNodeAfterStateRestore) { + if (m_pNextPathNode) { + CVector diff = m_pNextPathNode->GetPosition() - GetPosition(); + if (diff.MagnitudeSqr() < sq(7.0f)) { + SetMoveState(PEDMOVE_WALK); + break; } } } - } + SetWanderPath(CGeneral::GetRandomNumber() & 7); + break; + default: + m_nPedState = m_nLastPedState; + SetMoveState((eMoveState) m_nPrevMoveState); + break; } + m_nLastPedState = PED_NONE; } } -void -CPed::ClearAimFlag(void) +uint32 +CPed::ScanForThreats(void) { - if (bIsAimingGun) { - bIsAimingGun = false; - bIsRestoringGun = true; - m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; -#if defined VC_PED_PORTS || defined FIX_BUGS - m_lookTimer = 0; -#endif + int fearFlags = m_fearFlags; + CVector ourPos = GetPosition(); + float closestPedDist = 60.0f; + CVector2D explosionPos = GetPosition(); + if (fearFlags & PED_FLAG_EXPLOSION && CheckForExplosions(explosionPos)) { + m_eventOrThreat = explosionPos; + return PED_FLAG_EXPLOSION; } + + CPed *shooter = nil; + if ((fearFlags & PED_FLAG_GUN) && (shooter = CheckForGunShots()) && (m_nPedType != shooter->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE)) { + if (!IsGangMember()) { + m_threatEntity = shooter; + m_threatEntity->RegisterReference((CEntity **) &m_threatEntity); + return PED_FLAG_GUN; + } - if (IsPlayer()) - ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f; -} - -void -CPed::ClearLookFlag(void) { - if (bIsLooking) { - bIsLooking = false; - bIsRestoringLook = true; - bShakeFist = false; - - m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; - if (IsPlayer()) - m_lookTimer = CTimer::GetTimeInMilliseconds() + 2000; - else - m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000; - - if (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) { - ClearLook(); + if (CPedType::GetFlag(shooter->m_nPedType) & fearFlags) { + m_threatEntity = shooter; + m_threatEntity->RegisterReference((CEntity **) &m_threatEntity); + return CPedType::GetFlag(shooter->m_nPedType); } } -} - -bool -CPed::IsPedHeadAbovePos(float zOffset) -{ - return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z; -} - -void -CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) -{ - CWeaponInfo *currentWeapon; - CAnimBlendAssociation *newAnim; - CPed *ped = (CPed*)arg; - if (attackAssoc) { - switch (attackAssoc->animId) { - case ANIM_WEAPON_START_THROW: - // what?! - if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) { - attackAssoc->blendDelta = -1000.0f; - newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU); - } else { - attackAssoc->blendDelta = -1000.0f; - newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROW); - } + CPed *deadPed = nil; + if (fearFlags & PED_FLAG_DEADPEDS && CharCreatedBy != MISSION_CHAR + && (deadPed = CheckForDeadPeds()) != nil && (deadPed->GetPosition() - ourPos).MagnitudeSqr() < sq(20.0f)) { + m_pEventEntity = deadPed; + m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity); + return PED_FLAG_DEADPEDS; + } else { + uint32 flagsOfSomePed = 0; - newAnim->SetFinishCallback(FinishedAttackCB, ped); - return; + CPed *pedToFearFrom = nil; +#ifndef VC_PED_PORTS + for (int i = 0; i < m_numNearPeds; i++) { + if (CharCreatedBy != RANDOM_CHAR || m_nearPeds[i]->CharCreatedBy != MISSION_CHAR || m_nearPeds[i]->IsPlayer()) { + CPed *nearPed = m_nearPeds[i]; - case ANIM_FIGHT_PPUNCH: - attackAssoc->blendDelta = -8.0f; - attackAssoc->flags |= ASSOC_DELETEFADEDOUT; - ped->ClearAttack(); - return; + // BUG: WTF Rockstar?! Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance. + // Fixed at the bottom of the function. + flagsOfSomePed = CPedType::GetFlag(nearPed->m_nPedType); - case ANIM_WEAPON_THROW: - case ANIM_WEAPON_THROWU: - if (ped->GetWeapon()->m_nAmmoTotal > 0) { - currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType); - ped->AddWeaponModel(currentWeapon->m_nModelId); + if (CPedType::GetFlag(nearPed->m_nPedType) & fearFlags) { + if (nearPed->m_fHealth > 0.0f && OurPedCanSeeThisOne(m_nearPeds[i])) { + // FIX: Taken from VC +#ifdef FIX_BUGS + float nearPedDistSqr = (nearPed->GetPosition() - ourPos).MagnitudeSqr2D(); +#else + float nearPedDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr(); +#endif + if (sq(closestPedDist) > nearPedDistSqr) { + closestPedDist = Sqrt(nearPedDistSqr); + pedToFearFrom = m_nearPeds[i]; + } + } } - break; - default: - break; + } } - } - - if (!ped->bIsAttacking) - ped->ClearAttack(); -} +#else + bool weSawOurEnemy = false; + bool weMaySeeOurEnemy = false; + float closestEnemyDist = 60.0f; + if ((CTimer::GetFrameCounter() + (uint8)m_randomSeed + 16) & 4) { -void -CPed::Attack(void) -{ - CAnimBlendAssociation *weaponAnimAssoc; - int32 weaponAnim; - float animStart; - eWeaponType ourWeaponType; - float weaponAnimTime; - eWeaponFire ourWeaponFire; - float animLoopEnd; - CWeaponInfo *ourWeapon; - bool attackShouldContinue; - AnimationId reloadAnim; - CAnimBlendAssociation *reloadAnimAssoc; - float delayBetweenAnimAndFire; - CVector firePos; - - ourWeaponType = GetWeapon()->m_eWeaponType; - ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType); - ourWeaponFire = ourWeapon->m_eWeaponFire; - weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay); - attackShouldContinue = bIsAttacking; - reloadAnimAssoc = nil; - reloadAnim = NUM_ANIMS; - delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire; - weaponAnim = ourWeapon->m_AnimToPlay; - - if (weaponAnim == ANIM_WEAPON_HGUN_BODY) - reloadAnim = ANIM_HGUN_RELOAD; - else if (weaponAnim == ANIM_WEAPON_AK_BODY) - reloadAnim = ANIM_AK_RELOAD; - - if (reloadAnim != NUM_ANIMS) - reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim); - - if (bIsDucking) - return; + for (int i = 0; i < m_numNearPeds; ++i) { + if (CharCreatedBy == RANDOM_CHAR && m_nearPeds[i]->CharCreatedBy == MISSION_CHAR && !m_nearPeds[i]->IsPlayer()) { + continue; + } - if (reloadAnimAssoc) { - if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) - ClearAttack(); + // BUG: Explained at the same occurence of this bug above. Fixed at the bottom of the function. + flagsOfSomePed = CPedType::GetFlag(m_nearPeds[i]->m_nPedType); - return; - } + if (flagsOfSomePed & fearFlags) { + if (m_nearPeds[i]->m_fHealth > 0.0f) { - if (CTimer::GetTimeInMilliseconds() < m_shootTimer) - attackShouldContinue = true; + // VC also has ability to include objects to line of sight check here (via last bit of flagsL) + if (OurPedCanSeeThisOne(m_nearPeds[i])) { + if (m_nearPeds[i]->m_nPedState == PED_ATTACK) { + if (m_nearPeds[i]->m_pedInObjective == this) { - if (!weaponAnimAssoc) { - weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay); - delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire; + float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); + if (sq(closestEnemyDist) > enemyDistSqr) { + float enemyDist = Sqrt(enemyDistSqr); + weSawOurEnemy = true; + closestPedDist = enemyDist; + closestEnemyDist = enemyDist; + pedToFearFrom = m_nearPeds[i]; + } + } + } else { + float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); + if (sq(closestPedDist) > nearPedDistSqr && !weSawOurEnemy) { + closestPedDist = Sqrt(nearPedDistSqr); + pedToFearFrom = m_nearPeds[i]; + } + } + } else if (!weSawOurEnemy) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed->m_nPedState == PED_ATTACK) { + CColPoint foundCol; + CEntity *foundEnt; - // Long throw granade, molotov - if (!weaponAnimAssoc && ourWeapon->m_bThrow) { - weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU); - delayBetweenAnimAndFire = 0.2f; - } + // We don't see him yet but he's behind a ped, vehicle or object + // VC also has ability to include objects to line of sight check here (via last bit of flagsL) + if (!CWorld::ProcessLineOfSight(ourPos, nearPed->GetPosition(), foundCol, foundEnt, + true, false, false, false, false, false, false)) { - if (!weaponAnimAssoc) { - if (attackShouldContinue) { - if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) { - if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { - weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); - } - else { - weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); + if (nearPed->m_pedInObjective == this) { + float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); + if (sq(closestEnemyDist) > enemyDistSqr) { + float enemyDist = Sqrt(enemyDistSqr); + weMaySeeOurEnemy = true; + closestPedDist = enemyDist; + closestEnemyDist = enemyDist; + pedToFearFrom = m_nearPeds[i]; + } + } else if (!nearPed->GetWeapon()->IsTypeMelee() && !weMaySeeOurEnemy) { + float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); + if (sq(closestPedDist) > nearPedDistSqr) { + weMaySeeOurEnemy = true; + closestPedDist = Sqrt(nearPedDistSqr); + pedToFearFrom = m_nearPeds[i]; + } + } + } + } + } } + } + } + } +#endif + int16 lastVehicle; + CEntity* vehicles[8]; + CWorld::FindObjectsInRange(ourPos, 20.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + CVehicle* foundVeh = nil; + for (int i = 0; i < lastVehicle; i++) { + CVehicle* nearVeh = (CVehicle*)vehicles[i]; - weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this); - weaponAnimAssoc->SetRun(); - - if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength) - weaponAnimAssoc->SetCurrentTime(0.0f); + CPed *driver = nearVeh->pDriver; + if (driver) { - if (IsPlayer()) { - ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f; - ((CPlayerPed*)this)->m_bHaveTargetSelected = false; + // BUG: Same bug as above. Fixed at the bottom of function. + flagsOfSomePed = CPedType::GetFlag(driver->m_nPedType); + if (CPedType::GetFlag(driver->m_nPedType) & fearFlags) { + if (driver->m_fHealth > 0.0f && OurPedCanSeeThisOne(nearVeh->pDriver)) { + // FIX: Taken from VC +#ifdef FIX_BUGS + float driverDistSqr = (driver->GetPosition() - ourPos).MagnitudeSqr2D(); +#else + float driverDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr(); +#endif + if (sq(closestPedDist) > driverDistSqr) { + closestPedDist = Sqrt(driverDistSqr); + pedToFearFrom = nearVeh->pDriver; + } } } - } else - FinishedAttackCB(nil, this); - - return; + } } - } + m_threatEntity = pedToFearFrom; + if (m_threatEntity) + m_threatEntity->RegisterReference((CEntity **) &m_threatEntity); - animStart = ourWeapon->m_fAnimLoopStart; - weaponAnimTime = weaponAnimAssoc->currentTime; - if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) { - if (ourWeapon->m_bCanAimWithArm) - m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM; +#ifdef FIX_BUGS + if (pedToFearFrom) + flagsOfSomePed = CPedType::GetFlag(((CPed*)m_threatEntity)->m_nPedType); else - m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; - } + flagsOfSomePed = 0; +#endif - if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) { - if (weaponAnimAssoc->speed < 1.0f) - weaponAnimAssoc->speed = 1.0f; + return flagsOfSomePed; + } +} - } else { - firePos = ourWeapon->m_vecFireOffset; - if (ourWeaponType == WEAPONTYPE_BASEBALLBAT) { - if (weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay) - firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f; - - firePos = GetMatrix() * firePos; - } else if (ourWeaponType != WEAPONTYPE_UNARMED) { - TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR); - } else { - firePos = GetMatrix() * firePos; +void +CPed::SetLookFlag(float direction, bool keepTryingToLook) +{ + if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { + bIsLooking = true; + bIsRestoringLook = false; + m_pLookTarget = nil; + m_fLookDirection = direction; + m_lookTimer = 0; + bKeepTryingToLook = keepTryingToLook; + if (m_nPedState != PED_DRIVING) { + m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; } - - GetWeapon()->Fire(this, &firePos); + } +} - if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) { - RemoveWeaponModel(ourWeapon->m_nModelId); - } - if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) { - SelectGunIfArmed(); +void +CPed::SetLookFlag(CEntity *target, bool keepTryingToLook) +{ + if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { + bIsLooking = true; + bIsRestoringLook = false; + m_pLookTarget = target; + m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget); + m_fLookDirection = 999999.0f; + m_lookTimer = 0; + bKeepTryingToLook = keepTryingToLook; + if (m_nPedState != PED_DRIVING) { + m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; } + } +} - if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) { - // If reloading just began, start the animation - // Last condition will always return true, even IDA hides it - if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS /* && !reloadAnimAssoc*/) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f); - ClearLookFlag(); - ClearAimFlag(); - bIsAttacking = false; - bIsPointingGunAt = false; - m_shootTimer = CTimer::GetTimeInMilliseconds(); - return; - } - } else { - if (weaponAnimAssoc->animId == ANIM_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_WEAPON_BAT_H) { - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f); - } else if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH) { - DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); - } +void +CPed::ClearLookFlag(void) { + if (bIsLooking) { + bIsLooking = false; + bIsRestoringLook = true; + bShakeFist = false; - weaponAnimAssoc->speed = 0.5f; + m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; + if (IsPlayer()) + m_lookTimer = CTimer::GetTimeInMilliseconds() + 2000; + else + m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000; - if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) { - weaponAnimAssoc->callbackType = 0; - } + if (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) { + ClearLook(); } + } +} + +void +FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; + + if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) + ped->RemoveWeaponModel(0); +} + +void +CPed::MoveHeadToLook(void) +{ + CVector lookPos; - attackShouldContinue = false; + if (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) { + ClearLookFlag(); + } else if (m_nPedState == PED_DRIVING) { + m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY; } - if (ourWeaponType == WEAPONTYPE_SHOTGUN) { - weaponAnimTime = weaponAnimAssoc->currentTime; - firePos = ourWeapon->m_vecFireOffset; + if (m_pLookTarget) { + + if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { + + CAnimBlendAssociation *fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU); + if (fuckUAssoc) { + + float animTime = fuckUAssoc->currentTime; + if (animTime > 4.0f / 30.0f && animTime - fuckUAssoc->timeStep > 4.0f / 30.0f) { + + bool lookingToCop = false; + if (m_pLookTarget->GetModelIndex() == MI_POLICE + || m_pLookTarget->IsPed() && ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP) { - if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) { - TransformToNode(firePos, PED_HANDR); + lookingToCop = true; + } - CVector gunshellPos( - firePos.x - 0.6f * GetForward().x, - firePos.y - 0.6f * GetForward().y, - firePos.z - 0.15f * GetUp().z - ); + if (IsPlayer() && (m_pedStats->m_temper >= 52 || lookingToCop)) { + AddWeaponModel(MI_FINGERS); + ((CPlayerPed*)this)->AnnoyPlayerPed(true); - CVector2D gunshellRot( - GetRight().x, - GetRight().y - ); + } else if ((CGeneral::GetRandomNumber() & 3) == 0) { + AddWeaponModel(MI_FINGERS); + } + } + } + } - gunshellRot.Normalise(); - GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f); + if (m_pLookTarget->IsPed()) { + ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID); + } else { + lookPos = m_pLookTarget->GetPosition(); } - } -#ifdef VC_PED_PORTS - if (IsPlayer()) { - if (CPad::GetPad(0)->GetSprint()) { - // animBreakout is a member of WeaponInfo in VC, so it's me that added the below line. - float animBreakOut = ((ourWeaponType == WEAPONTYPE_FLAMETHROWER || ourWeaponType == WEAPONTYPE_UZI || ourWeaponType == WEAPONTYPE_SHOTGUN) ? 25 / 30.0f : 99 / 30.0f); - if (!attackShouldContinue && weaponAnimAssoc->currentTime > animBreakOut) { - weaponAnimAssoc->blendDelta = -4.0f; - FinishedAttackCB(nil, this); - return; + + if (!m_pedIK.LookAtPosition(lookPos)) { + if (!bKeepTryingToLook) { + ClearLookFlag(); } + return; } - } -#endif - animLoopEnd = ourWeapon->m_fAnimLoopEnd; - if (ourWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay) - animLoopEnd = 3.4f/6.0f; - weaponAnimTime = weaponAnimAssoc->currentTime; + if (!bShakeFist || bIsAimingGun || bIsRestoringGun) + return; + + if (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000) + return; + + bool notRocketLauncher = false; + bool notTwoHanded = false; + AnimationId animToPlay = NUM_ANIMS; + + if (!GetWeapon()->IsType2Handed()) + notTwoHanded = true; + + if (notTwoHanded && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER) + notRocketLauncher = true; + + if (IsPlayer() && notRocketLauncher) { - // Anim loop end, either start the loop again or finish the attack - if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeaponFire != WEAPON_FIRE_PROJECTILE) { + if (m_pLookTarget->IsPed()) { - if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd - && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) - && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) { + if (m_pedStats->m_temper >= 49 && ((CPed*)m_pLookTarget)->m_nPedType != PEDTYPE_COP) { - weaponAnim = weaponAnimAssoc->animId; - if (ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { - if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_RBLOCK_CSHOOT) { - weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart); + // FIX: Unreachable and meaningless condition +#ifndef FIX_BUGS + if (m_pedStats->m_temper < 47) +#endif + animToPlay = ANIM_FIGHT_PPUNCH; } else { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); + animToPlay = ANIM_FUCKU; } - } else { - if (weaponAnim == ourWeapon->m_Anim2ToPlay) - weaponAnimAssoc->SetCurrentTime(0.1f); - else - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); + } else if (m_pedStats->m_temper > 49 || m_pLookTarget->GetModelIndex() == MI_POLICE) { + animToPlay = ANIM_FUCKU; } -#ifdef VC_PED_PORTS - } else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) { - weaponAnimAssoc->SetCurrentTime(ourWeapon->m_fAnimLoopEnd); - weaponAnimAssoc->flags &= ~ASSOC_RUNNING; - SetPointGunAt(m_pPointGunAt); -#endif - } else { - ClearAimFlag(); + } else if (notRocketLauncher && (CGeneral::GetRandomNumber() & 1)) { + animToPlay = ANIM_FUCKU; + } - // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading) - if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) { - switch (ourWeaponType) { - case WEAPONTYPE_UZI: - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); - break; - case WEAPONTYPE_AK47: - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); - break; - case WEAPONTYPE_M16: - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); - break; - default: - break; - } - } + if (animToPlay != NUM_ANIMS) { + CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); - // Fun fact: removing this part leds to reloading flamethrower - if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) { - weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT; - weaponAnimAssoc->flags &= ~ASSOC_RUNNING; - weaponAnimAssoc->blendDelta = -4.0f; + if (newAssoc) { + newAssoc->flags |= ASSOC_FADEOUTWHENDONE; + newAssoc->flags |= ASSOC_DELETEFADEDOUT; + if (newAssoc->animId == ANIM_FUCKU) + newAssoc->SetDeleteCallback(FinishFuckUCB, this); } } + bShakeFist = false; + return; + } else if (999999.0f == m_fLookDirection) { + ClearLookFlag(); + } else if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) { + if (!bKeepTryingToLook) + ClearLookFlag(); } - if (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire) - attackShouldContinue = false; - - bIsAttacking = attackShouldContinue; -} - -void -CPed::RemoveWeaponModel(int modelId) -{ - // modelId is not used!! This function just removes the current weapon. -#ifdef PED_SKIN - if(IsClumpSkinned(GetClump())){ - if(m_pWeaponModel){ - RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel); - RpAtomicDestroy(m_pWeaponModel); - RwFrameDestroy(frm); - m_pWeaponModel = nil; - } - }else -#endif - RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil); - m_wepModelID = -1; } void -CPed::SetCurrentWeapon(uint32 weaponType) +CPed::RestoreHeadPosition(void) { - CWeaponInfo *weaponInfo; - if (HasWeapon(weaponType)) { - weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - RemoveWeaponModel(weaponInfo->m_nModelId); - - m_currentWeapon = weaponType; - - weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - AddWeaponModel(weaponInfo->m_nModelId); + if (m_pedIK.RestoreLookAt()) { + bIsRestoringLook = false; } } -// Only used while deciding which gun ped should switch to, if no ammo left. -bool -CPed::SelectGunIfArmed(void) +void +CPed::SetAimFlag(float angle) { - for (int i = 0; i < m_maxWeaponTypeAllowed; i++) { - if (GetWeapon(i).m_nAmmoTotal > 0) { - eWeaponType weaponType = GetWeapon(i).m_eWeaponType; - if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) { - SetCurrentWeapon(i); - return true; - } - } - } - SetCurrentWeapon(WEAPONTYPE_UNARMED); - return false; + bIsAimingGun = true; + bIsRestoringGun = false; + m_fLookDirection = angle; + m_lookTimer = 0; + m_pLookTarget = nil; + m_pSeekTarget = nil; + if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm) + m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM; + else + m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; } void -CPed::Duck(void) +CPed::SetAimFlag(CEntity *to) { - if (CTimer::GetTimeInMilliseconds() > m_duckTimer) - ClearDuck(); + bIsAimingGun = true; + bIsRestoringGun = false; + m_pLookTarget = to; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + m_pSeekTarget = to; + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + m_lookTimer = 0; } void -CPed::ClearDuck(void) +CPed::ClearAimFlag(void) { - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (!animAssoc) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); - - if (!animAssoc) { - bIsDucking = false; - return; - } + if (bIsAimingGun) { + bIsAimingGun = false; + bIsRestoringGun = true; + m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; +#if defined VC_PED_PORTS || defined FIX_BUGS + m_lookTimer = 0; +#endif } - if (!bCrouchWhenShooting) - return; - - if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN) - return; - - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT); - if (!animAssoc || animAssoc->blendDelta < 0.0f) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); - } + if (IsPlayer()) + ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f; } void -CPed::ClearPointGunAt(void) +CPed::AimGun(void) { - CAnimBlendAssociation *animAssoc; - CWeaponInfo *weaponInfo; + CVector vector; - ClearLookFlag(); - ClearAimFlag(); - bIsPointingGunAt = false; -#ifndef VC_PED_PORTS - if (m_nPedState == PED_AIM_GUN) { - RestorePreviousState(); -#else - if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) { - m_nPedState = PED_IDLE; - RestorePreviousState(); - } -#endif - weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay); - if (!animAssoc || animAssoc->blendDelta < 0.0f) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay); - } - if (animAssoc) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->blendDelta = -4.0f; + if (m_pSeekTarget) { + if (m_pSeekTarget->IsPed()) { + ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(vector, PED_MID); + } else { + vector = m_pSeekTarget->GetPosition(); } -#ifndef VC_PED_PORTS - } -#endif -} + Say(SOUND_PED_ATTACK); -void -CPed::BeingDraggedFromCar(void) -{ - CAnimBlendAssociation *animAssoc; - AnimationId enterAnim; - bool dontRunAnim = false; - PedLineUpPhase lineUpType; - - if (!m_pVehicleAnim) { - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT); - if (!animAssoc) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT); - if (!animAssoc) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO); - } + bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(vector); + if (m_pLookTarget != m_pSeekTarget) { + SetLookFlag(m_pSeekTarget, true); } - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { - if (bWillBeQuickJacked) { - enterAnim = ANIM_CAR_QJACKED; - } else if (m_pMyVehicle->bLowVehicle) { - enterAnim = ANIM_CAR_LJACKED_LHS; - } else { - enterAnim = ANIM_CAR_JACKED_LHS; - } - } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) { - if (m_pMyVehicle->bLowVehicle) - enterAnim = ANIM_CAR_LJACKED_RHS; - else - enterAnim = ANIM_CAR_JACKED_RHS; - } else - dontRunAnim = true; - - if (!dontRunAnim) - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim); - - m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this); - lineUpType = LINE_UP_TO_CAR_START; - } else if (m_pVehicleAnim->currentTime <= 1.4f) { - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - lineUpType = LINE_UP_TO_CAR_START; } else { - lineUpType = LINE_UP_TO_CAR_2; - } - - LineUpPedWithCar(lineUpType); -#ifdef VC_PED_PORTS - if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { - if (m_pMyVehicle) { - m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f); + if (IsPlayer()) { + bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading); + } else { + bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f); } } -#endif } void -CPed::RestartNonPartialAnims(void) +CPed::RestoreGunPosition(void) { - CAnimBlendAssociation *assoc; - - for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { - if (!assoc->IsPartial()) - assoc->SetRun(); + if (bIsLooking) { + m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; + bIsRestoringGun = false; + } else if (m_pedIK.RestoreGunPosn()) { + bIsRestoringGun = false; + } else { + if (IsPlayer()) + ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f; } } void -CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) +CPed::ScanForInterestingStuff(void) { - CAnimBlendAssociation *quickJackedAssoc; - CVehicle *vehicle; - CPed *ped = (CPed*)arg; + if (!IsPedInControl()) + return; - quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED); - if (ped->m_nPedState != PED_ARRESTED) { - ped->m_nLastPedState = PED_NONE; - if (dragAssoc) - dragAssoc->blendDelta = -1000.0f; - } - ped->RestartNonPartialAnims(); - ped->m_pVehicleAnim = nil; - ped->m_pSeekTarget = nil; - vehicle = ped->m_pMyVehicle; + if (m_objective != OBJECTIVE_NONE) + return; - if (vehicle) { - vehicle->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType); + if (CharCreatedBy == MISSION_CHAR) + return; - if (vehicle->pDriver == ped) { - vehicle->RemoveDriver(); - if (vehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) - vehicle->m_nDoorLock = CARLOCK_UNLOCKED; + LookForSexyPeds(); + LookForSexyCars(); + if (LookForInterestingNodes()) + return; - if (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle()) - vehicle->ChangeLawEnforcerState(false); - } else { - vehicle->RemovePassenger(ped); - } - } - ped->bInVehicle = false; - if (ped->IsPlayer()) - AudioManager.PlayerJustLeftCar(); + if (m_nPedType == PEDTYPE_CRIMINAL && m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) { + if (CGeneral::GetRandomNumber() % 100 < 10) { + int mostExpensiveVehAround = -1; + int bestMonetaryValue = 0; -#ifdef VC_PED_PORTS - if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { - dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped); - ped->m_fHealth = 0.0f; - ped->SetDie(ANIM_FLOOR_HIT, 1000.0f, 0.5f); - return; - } -#endif + CVector pos = GetPosition(); + int16 lastVehicle; + CEntity *vehicles[8]; + CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - if (quickJackedAssoc) { - dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped); - } else { - dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped); - if (ped->CanSetPedState()) - CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); - } + for (int i = 0; i < lastVehicle; i++) { + CVehicle* veh = (CVehicle*)vehicles[i]; - ped->ReplaceWeaponWhenExitingVehicle(); + if (veh->VehicleCreatedBy != MISSION_VEHICLE) { + if (veh->m_vecMoveSpeed.Magnitude() <= 0.1f && veh->IsVehicleNormal() + && veh->IsCar() && bestMonetaryValue < veh->pHandling->nMonetaryValue) { + mostExpensiveVehAround = i; + bestMonetaryValue = veh->pHandling->nMonetaryValue; + } + } + } + if (bestMonetaryValue > 2000 && mostExpensiveVehAround != -1 && vehicles[mostExpensiveVehAround]) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, vehicles[mostExpensiveVehAround]); + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; + return; + } + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; + } else if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) { + CPed *charToMug = nil; + for (int i = 0; i < m_numNearPeds; ++i) { + CPed *nearPed = m_nearPeds[i]; - ped->m_nStoredMoveState = PEDMOVE_NONE; - ped->bVehExitWillBeInstant = false; -} + if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f)) + break; -CVector -CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult) -{ - CVehicleModelInfo *vehModel; - CVector vehDoorPos; - CVector vehDoorOffset; - float seatOffset; - - vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex()); - if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) { - seatOffset = 0.0f; - vehDoorOffset = vecPedVanRearDoorAnimOffset; - } else { - seatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult; - if (veh->bLowVehicle) { - vehDoorOffset = vecPedCarDoorLoAnimOffset; - } else { - vehDoorOffset = vecPedCarDoorAnimOffset; + if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE + || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1 + || nearPed->m_nPedType == PEDTYPE_PROSTITUTE) + && nearPed->CharCreatedBy != MISSION_CHAR + && nearPed->IsPedShootable() + && nearPed->m_objective != OBJECTIVE_MUG_CHAR) { + charToMug = nearPed; + break; + } + } + if (charToMug) + SetObjective(OBJECTIVE_MUG_CHAR, charToMug); + + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; } } - switch (component) { - case CAR_DOOR_RF: - vehDoorPos = vehModel->GetFrontSeatPosn(); - vehDoorPos.x += seatOffset; - vehDoorOffset.x = -vehDoorOffset.x; - break; - - case CAR_DOOR_RR: - vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT]; - vehDoorPos.x += seatOffset; - vehDoorOffset.x = -vehDoorOffset.x; - break; - - case CAR_DOOR_LF: - vehDoorPos = vehModel->GetFrontSeatPosn(); - vehDoorPos.x = -(vehDoorPos.x + seatOffset); - break; + if (m_nPedState == PED_WANDER_PATH) { +#ifndef VC_PED_PORTS + if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { - case CAR_DOOR_LR: - vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT]; - vehDoorPos.x = -(vehDoorPos.x + seatOffset); - break; + // += 2 is weird + for (int i = 0; i < m_numNearPeds; i += 2) { + if (m_nearPeds[i]->m_nPedState == PED_WANDER_PATH && WillChat(m_nearPeds[i])) { + if (CGeneral::GetRandomNumberInRange(0, 100) >= 100) + m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; + else { + if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) { + m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; + } else if (CanSeeEntity(m_nearPeds[i])) { + int time = CGeneral::GetRandomNumber() % 4000 + 10000; + SetChat(m_nearPeds[i], time); + m_nearPeds[i]->SetChat(this, time); + return; + } + } + } + } + } +#else + if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.5f) { + if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { + for (int i = 0; i < m_numNearPeds; i ++) { + if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) { + if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f + && CanSeeEntity(m_nearPeds[i]) + && m_nearPeds[i]->CanSeeEntity(this) + && WillChat(m_nearPeds[i])) { - default: - vehDoorPos = vehModel->GetFrontSeatPosn(); - vehDoorOffset = CVector(0.0f, 0.0f, 0.0f); + int time = CGeneral::GetRandomNumber() % 4000 + 10000; + SetChat(m_nearPeds[i], time); + m_nearPeds[i]->SetChat(this, time); + return; + } + } + } + } + } else { + m_standardTimer = CTimer::GetTimeInMilliseconds() + 200; + } +#endif } - return vehDoorPos - vehDoorOffset; -} -// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it. -CVector -CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component) -{ - CVector localPos; - CVector vehDoorPos; + // Parts below aren't there in VC, they're in somewhere else. + if (!CGame::noProstitutes && m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy != MISSION_CHAR + && m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) { - localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f); - vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition(); + CVector pos = GetPosition(); + int16 lastVehicle; + CEntity* vehicles[8]; + CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); -/* - // Not used. - CVector localVehDoorOffset; + for (int i = 0; i < lastVehicle; i++) { + CVehicle* veh = (CVehicle*)vehicles[i]; - if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) { - localVehDoorOffset = vecPedVanRearDoorAnimOffset; - } else { - if (veh->bIsLow) { - localVehDoorOffset = vecPedCarDoorLoAnimOffset; - } else { - localVehDoorOffset = vecPedCarDoorAnimOffset; + if (veh->IsVehicleNormal()) { + if (veh->IsCar()) { + if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil)) { + SetObjective(OBJECTIVE_SOLICIT_VEHICLE, veh); + Say(SOUND_PED_SOLICIT); + return; + } + } + } } } + if (m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) { + CVector pos = GetPosition(); + int16 lastVehicle; + CEntity* vehicles[8]; + CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition(); -*/ - return vehDoorPos; -} + for (int i = 0; i < lastVehicle; i++) { + CVehicle* veh = (CVehicle*)vehicles[i]; -CVector -CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset) -{ - CVector doorPos; - CMatrix vehMat(veh->GetMatrix()); - - doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset)); - - return veh->GetPosition() + doorPos; + if (veh->GetModelIndex() == MI_MRWHOOP) { + if (veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED) { + if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f) { + SetObjective(OBJECTIVE_BUY_ICE_CREAM, veh); + return; + } + } + } + } + } } -void -CPed::LineUpPedWithCar(PedLineUpPhase phase) +bool +CPed::WillChat(CPed *stranger) { - bool vehIsUpsideDown = false; - int vehAnim; - float seatPosMult = 0.0f; - float currentZ; - float adjustedTimeStep; - - if (CReplay::IsPlayingBack()) - return; - - if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) { - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) { - SetPedPositionInCar(); - return; - } - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) { - SetPedPositionInCar(); - return; - } - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) { - SetPedPositionInCar(); - return; - } - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) { - SetPedPositionInCar(); - return; + if (m_pNextPathNode && m_pLastPathNode) { + if (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) { + return false; } - bChangedSeat = true; } - if (phase == LINE_UP_TO_CAR_START) { - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - } - CVehicle *veh = m_pMyVehicle; + if (m_nSurfaceTouched == SURFACE_TARMAC) + return false; + if (stranger == this) + return false; + if (m_nPedType == stranger->m_nPedType) + return true; + if (m_nPedType == PEDTYPE_CRIMINAL) + return false; + if ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType) + return false; + return true; +} - // Not quite right, IsUpsideDown func. checks for <= -0.9f. - if (veh->GetUp().z <= -0.8f) - vehIsUpsideDown = true; +void +CPed::CalculateNewVelocity(void) +{ + if (IsPedInControl()) { + float headAmount = DEGTORAD(m_headingRate) * CTimer::GetTimeStep(); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + float limitedRotDest = CGeneral::LimitRadianAngle(m_fRotationDest); - if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) { - if (vehIsUpsideDown) { - m_fRotationDest = -PI + veh->GetForward().Heading(); - } else if (veh->bIsBus) { - m_fRotationDest = 0.5f * PI + veh->GetForward().Heading(); - } else { - m_fRotationDest = veh->GetForward().Heading(); - } - } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { - if (vehIsUpsideDown) { - m_fRotationDest = veh->GetForward().Heading(); - } else if (veh->bIsBus) { - m_fRotationDest = -0.5f * PI + veh->GetForward().Heading(); - } else { - m_fRotationDest = veh->GetForward().Heading(); + if (m_fRotationCur - PI > limitedRotDest) { + limitedRotDest += 2 * PI; + } else if(PI + m_fRotationCur < limitedRotDest) { + limitedRotDest -= 2 * PI; } - } else { - // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional. - if (vehIsUpsideDown) { - m_fRotationDest = veh->GetForward().Heading(); - } else if (veh->bIsBus) { - m_fRotationDest = 0.5f * PI + veh->GetForward().Heading(); + if (IsPlayer() && m_nPedState == PED_ATTACK) + headAmount /= 4.0f; + + float neededTurn = limitedRotDest - m_fRotationCur; + if (neededTurn <= headAmount) { + if (neededTurn > (-headAmount)) + m_fRotationCur += neededTurn; + else + m_fRotationCur -= headAmount; } else { - m_fRotationDest = veh->GetForward().Heading(); + m_fRotationCur += headAmount; } } - if (!bInVehicle) - seatPosMult = 1.0f; - -#ifdef VC_PED_PORTS - bool multExtractedFromAnim = false; - bool multExtractedFromAnimBus = false; - float zBlend; -#endif - if (m_pVehicleAnim) { - vehAnim = m_pVehicleAnim->animId; - - switch (vehAnim) { - case ANIM_CAR_JACKED_RHS: - case ANIM_CAR_LJACKED_RHS: - case ANIM_CAR_JACKED_LHS: - case ANIM_CAR_LJACKED_LHS: - case ANIM_VAN_GETIN_L: - case ANIM_VAN_GETIN: -#ifdef VC_PED_PORTS - multExtractedFromAnim = true; - zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f); - // fall through -#endif - case ANIM_CAR_QJACKED: - case ANIM_CAR_GETOUT_LHS: - case ANIM_CAR_GETOUT_LOW_LHS: - case ANIM_CAR_GETOUT_RHS: - case ANIM_CAR_GETOUT_LOW_RHS: -#ifdef VC_PED_PORTS - if (!multExtractedFromAnim) { - multExtractedFromAnim = true; - zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f); - } - // fall through -#endif - case ANIM_CAR_CRAWLOUT_RHS: - case ANIM_CAR_CRAWLOUT_RHS2: - case ANIM_VAN_GETOUT_L: - case ANIM_VAN_GETOUT: - seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength; - break; - case ANIM_CAR_GETIN_RHS: - case ANIM_CAR_GETIN_LHS: -#ifdef VC_PED_PORTS - if (veh && veh->IsCar() && veh->bIsBus) { - multExtractedFromAnimBus = true; - zBlend = Min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f; - } - // fall through -#endif - case ANIM_CAR_QJACK: - case ANIM_CAR_GETIN_LOW_LHS: - case ANIM_CAR_GETIN_LOW_RHS: - case ANIM_DRIVE_BOAT: - seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength; - break; - case ANIM_CAR_CLOSEDOOR_LHS: - case ANIM_CAR_CLOSEDOOR_LOW_LHS: - case ANIM_CAR_CLOSEDOOR_RHS: - case ANIM_CAR_CLOSEDOOR_LOW_RHS: - case ANIM_CAR_SHUFFLE_RHS: - case ANIM_CAR_LSHUFFLE_RHS: - seatPosMult = 0.0f; - break; - case ANIM_CAR_CLOSE_LHS: - case ANIM_CAR_CLOSE_RHS: - case ANIM_COACH_OPEN_L: - case ANIM_COACH_OPEN_R: - case ANIM_COACH_IN_L: - case ANIM_COACH_IN_R: - case ANIM_COACH_OUT_L: - seatPosMult = 1.0f; - break; - default: - break; - } - } + CVector2D forward(Sin(m_fRotationCur), Cos(m_fRotationCur)); - CVector neededPos; + m_moved.x = CrossProduct2D(m_vecAnimMoveDelta, forward); // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y; + m_moved.y = DotProduct2D(m_vecAnimMoveDelta, forward); // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur)); - if (phase == LINE_UP_TO_CAR_2) { - neededPos = GetPosition(); + if (CTimer::GetTimeStep() >= 0.01f) { + m_moved = m_moved * (1 / CTimer::GetTimeStep()); } else { - neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult); + m_moved = m_moved * (1 / 100.0f); } - CVector autoZPos = neededPos; - - if (veh->bIsInWater) { - if (veh->m_vehType == VEHICLE_TYPE_BOAT && veh->IsUpsideDown()) - autoZPos.z += 1.0f; - } else { - CPedPlacement::FindZCoorForPed(&autoZPos); - } + if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam()) + || FindPlayerPed() != this || !CanStrafeOrMouseControl()) + return; - if (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) { - neededPos.z = GetPosition().z; + float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur); + float pedSpeed = m_moved.Magnitude(); + float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur); - // Getting out - if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) { - float nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep(); + if (localWalkAngle < -0.5f * PI) { + localWalkAngle += PI; + } else if (localWalkAngle > 0.5f * PI) { + localWalkAngle -= PI; + } - // If we're not in ground at next step, apply animation - if (neededPos.z + nextZSpeed >= autoZPos.z) { - m_vecMoveSpeed.z = nextZSpeed; - ApplyMoveSpeed(); - // Removing below line breaks the animation - neededPos.z = GetPosition().z; - } else { - neededPos.z = autoZPos.z; - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - } - } + // Interestingly this part is responsible for diagonal walking. + if (localWalkAngle > -DEGTORAD(50.0f) && localWalkAngle < DEGTORAD(50.0f)) { + TheCamera.Cams[TheCamera.ActiveCam].m_fPlayerVelocity = pedSpeed; + m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed; } - if (autoZPos.z > neededPos.z) { + CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); + CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); #ifdef VC_PED_PORTS - if (multExtractedFromAnim) { - neededPos.z += (autoZPos.z - neededPos.z) * zBlend; - } else { + if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) { +#else + if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) { #endif - currentZ = GetPosition().z; - if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) { - neededPos.z = autoZPos.z; - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) { - adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f); - - // Smoothly change ped position - neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep); - } -#ifdef VC_PED_PORTS + LimbOrientation newUpperLegs; + newUpperLegs.yaw = localWalkAngle; + + if (newUpperLegs.yaw < -DEGTORAD(100.0f)) { + newUpperLegs.yaw += PI; + } else if (newUpperLegs.yaw > DEGTORAD(100.0f)) { + newUpperLegs.yaw -= PI; } -#endif - } else { - // We may need to raise up the ped - if (phase == LINE_UP_TO_CAR_START) { - currentZ = GetPosition().z; - if (neededPos.z > currentZ) { -#ifdef VC_PED_PORTS - if (multExtractedFromAnimBus) { - neededPos.z = (neededPos.z - currentZ) * zBlend + currentZ; - } else { -#endif - if (m_pVehicleAnim && - (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS - || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) { - adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f); - - // Smoothly change ped position - neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ; - } else if (EnteringCar()) { - neededPos.z = Max(currentZ, autoZPos.z); - } -#ifdef VC_PED_PORTS - } + if (newUpperLegs.yaw > -DEGTORAD(50.0f) && newUpperLegs.yaw < DEGTORAD(50.0f)) { +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ +/* + // this looks shit + newUpperLegs.pitch = 0.0f; + RwV3d axis = { -1.0f, 0.0f, 0.0f }; + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT); +*/ + newUpperLegs.pitch = 0.1f; + RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; + RwV3d Zaxis = { 0.0f, 0.0f, 1.0f }; + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT); + + bDontAcceptIKLookAts = true; + }else #endif + { + newUpperLegs.pitch = 0.0f; + m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false); + m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false); } } } +} + +float +CPed::WorkOutHeadingForMovingFirstPerson(float offset) +{ + if (!IsPlayer()) + return 0.0f; - bool stillGettingInOut = false; - if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) - stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat; + CPad *pad0 = CPad::GetPad(0); + float leftRight = pad0->GetPedWalkLeftRight(); + float upDown = pad0->GetPedWalkUpDown(); + float &angle = ((CPlayerPed*)this)->m_fWalkAngle; - if (!stillGettingInOut) { - m_fRotationCur = m_fRotationDest; + if (upDown != 0.0f) { + angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown); } else { - float limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest); - float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f; + if (leftRight < 0.0f) + angle = 0.5f * PI; + else if (leftRight > 0.0f) + angle = -0.5f * PI; + } + + return CGeneral::LimitRadianAngle(offset + angle); +} + +void +CPed::UpdatePosition(void) +{ + if (CReplay::IsPlayingBack() || !bIsStanding) + return; + + CVector2D velocityChange; - if (timeUntilStateChange <= 0.0f) { - m_vecOffsetSeek.x = 0.0f; - m_vecOffsetSeek.y = 0.0f; + SetHeading(m_fRotationCur); + if (m_pCurrentPhysSurface) { + CVector2D velocityOfSurface; + if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) { + + // It seems R* didn't like m_vecOffsetFromPhysSurface for boats + CVector offsetToSurface = GetPosition() - m_pCurrentPhysSurface->GetPosition(); + offsetToSurface.z -= FEET_OFFSET; + + CVector surfaceMoveVelocity = m_pCurrentPhysSurface->m_vecMoveSpeed; + CVector surfaceTurnVelocity = CrossProduct(m_pCurrentPhysSurface->m_vecTurnSpeed, offsetToSurface); + + // Also we use that weird formula instead of friction if it's boat + float slideMult = -m_pCurrentPhysSurface->m_vecTurnSpeed.MagnitudeSqr(); + velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity); + m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z); + } else { + velocityOfSurface = m_pCurrentPhysSurface->GetSpeed(m_vecOffsetFromPhysSurface); } - m_vecOffsetSeek.z = 0.0f; + // Reminder: m_moved is displacement from walking/running. + velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed; + m_fRotationCur += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); + m_fRotationDest += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); + } else if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF && (m_vecDamageNormal.x != 0.0f || m_vecDamageNormal.y != 0.0f)) { + // Ped got damaged by steep slope + m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f); + // some kind of + CVector2D reactionForce = m_vecDamageNormal; + reactionForce.Normalise(); - neededPos -= timeUntilStateChange * m_vecOffsetSeek; + velocityChange = 0.02f * reactionForce + m_moved; - if (PI + m_fRotationCur < limitedDest) { - limitedDest -= 2 * PI; - } else if (m_fRotationCur - PI > limitedDest) { - limitedDest += 2 * PI; + float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange); + // they're in same direction + if (reactionAndVelocityDotProd < 0.0f) { + velocityChange -= reactionAndVelocityDotProd * reactionForce; } - m_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange); + } else { + velocityChange = m_moved - m_vecMoveSpeed; } + + // Take time step into account + if (m_pCurrentPhysSurface) { + float speedChange = velocityChange.Magnitude(); + float changeMult = speedChange; + if (m_nPedState == PED_DIE && m_pCurrentPhysSurface->IsVehicle()) { + changeMult = 0.002f * CTimer::GetTimeStep(); + } else if (!(m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())) { + changeMult = 0.01f * CTimer::GetTimeStep(); + } - if (seatPosMult > 0.2f || vehIsUpsideDown) { - SetPosition(neededPos); - SetHeading(m_fRotationCur); - } else { - CMatrix vehDoorMat(veh->GetMatrix()); - vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f)); - // VC couch anims are inverted, so they're fixing it here. - GetMatrix() = vehDoorMat; + if (speedChange > changeMult) { + velocityChange = velocityChange * (changeMult / speedChange); + } } + m_vecMoveSpeed.x += velocityChange.x; + m_vecMoveSpeed.y += velocityChange.y; +} + +void +CPed::CalculateNewOrientation(void) +{ + if (CReplay::IsPlayingBack() || !IsPedInControl()) + return; + SetHeading(m_fRotationCur); } -static void -particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) +void +CPed::ClearAll(void) { - switch (ped->m_nSurfaceTouched) - { - case SURFACE_TARMAC: - case SURFACE_GRAVEL: - case SURFACE_PAVEMENT: - case SURFACE_SAND: - for (int i = 0; i < times; ++i) { - CVector adjustedPos = pos; - adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0); - } - break; - default: - break; - } -} - -static void -particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times) -{ -#ifdef PC_PARTICLE - for (int i = 0; i < times; i++) { - CVector adjustedPos = pos; - adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + if (!IsPedInControl() && m_nPedState != PED_DEAD) + return; - CVector direction = ped->GetForward() * -0.05f; - CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200); - } + m_nPedState = PED_NONE; + m_nMoveState = PEDMOVE_NONE; + m_pSeekTarget = nil; + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); + m_fleeFromPosX = 0.0f; + m_fleeFromPosY = 0.0f; + m_fleeFrom = nil; + m_fleeTimer = 0; + bUsesCollision = true; +#ifdef VC_PED_PORTS + ClearPointGunAt(); #else - for ( int32 i = 0; i < times; i++ ) - { - CVector adjustedPos = pos; - adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - - CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200); - } + ClearAimFlag(); + ClearLookFlag(); #endif + bIsPointingGunAt = false; + bRenderPedInCar = true; + bKnockedUpIntoAir = false; + m_pCollidingEntity = nil; } void -CPed::PlayFootSteps(void) +CPed::ProcessBuoyancy(void) { - if (bDoBloodyFootprints) { - if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) { - m_bloodyFootprintCountOrDeathTime--; - - if (m_bloodyFootprintCountOrDeathTime == 0) - bDoBloodyFootprints = false; - } - } + static uint32 nGenerateRaindrops = 0; + static uint32 nGenerateWaterCircles = 0; + CRGBA color(((0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f), + ((0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f), + ((0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f), + (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48); - if (!bIsStanding) + if (bInVehicle) return; - CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); - CAnimBlendAssociation *walkRunAssoc = nil; - float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f; + CVector buoyancyPoint; + CVector buoyancyImpulse; - for (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { - if (assoc->flags & ASSOC_WALK) { - walkRunAssoc = assoc; - walkRunAssocBlend += assoc->blendAmount; - } else if ((assoc->flags & ASSOC_NOWALK) == 0) { - idleAssocBlend += assoc->blendAmount; - } - } +#ifndef VC_PED_PORTS + float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.5f : 1.3f); +#else + float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f); +#endif -#ifdef GTA_PS2_STUFF - CAnimBlendAssociation *runStopAsoc = NULL; - - if ( IsPlayer() ) - { - runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); - - if ( runStopAsoc == NULL ) - runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); - } - - if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f ) - { - { - CVector pos(0.0f, 0.0f, 0.0f); - TransformToNode(pos, PED_FOOTL); - - pos.z -= 0.1f; - pos += GetForward()*0.2f; - particleProduceFootDust(this, pos, 0.02f, 1); + if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) { + bTouchingWater = true; + CEntity *entity; + CColPoint point; + if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil) + && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) { + bIsInWater = false; + return; } + bIsInWater = true; + ApplyMoveForce(buoyancyImpulse); + if (!DyingOrDead()) { + if (bTryingToReachDryLand) { + if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) { + bTryingToReachDryLand = false; + CVector pos = GetPosition(); + if (PlacePedOnDryLand()) { + if (m_fHealth > 20.0f) + InflictDamage(nil, WEAPONTYPE_DROWNING, 15.0f, PEDPIECE_TORSO, false); - { - CVector pos(0.0f, 0.0f, 0.0f); - TransformToNode(pos, PED_FOOTR); - - pos.z -= 0.1f; - pos += GetForward()*0.2f; - particleProduceFootDust(this, pos, 0.02f, 1); - } - } + if (bIsInTheAir) { + RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); + bIsInTheAir = false; + } + pos.z = pos.z - 0.8f; +#ifdef PC_PARTICLE + CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true); +#else + CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true); #endif - - - if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) { - float stepStart = 1 / 15.0f; - float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart; - float currentTime = walkRunAssoc->currentTime; - int stepPart = 0; - - if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart) - stepPart = 1; - else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd) - stepPart = 2; - - if (stepPart != 0) { - DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f); - CVector footPos(0.0f, 0.0f, 0.0f); - TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR); - - CVector forward = GetForward(); - - footPos.z -= 0.1f; - footPos += 0.2f * forward; - - if (bDoBloodyFootprints) { - CVector2D top(forward * 0.26f); - CVector2D right(GetRight() * 0.14f); - - CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &footPos, - top.x, top.y, - right.x, right.y, - 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f); - - if (m_bloodyFootprintCountOrDeathTime <= 20) { - m_bloodyFootprintCountOrDeathTime = 0; - bDoBloodyFootprints = false; - } else { - m_bloodyFootprintCountOrDeathTime -= 20; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + m_nPedState = PED_IDLE; + return; + } } } - if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) { - if(IsPlayer()) - particleProduceFootDust(this, footPos, 0.0f, 4); + float speedMult = 0.0f; + if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.75f * CTimer::GetTimeStep() + || mod_Buoyancy.m_waterlevel > GetPosition().z) { + speedMult = pow(0.9f, CTimer::GetTimeStep()); + m_vecMoveSpeed.x *= speedMult; + m_vecMoveSpeed.y *= speedMult; + m_vecMoveSpeed.z *= speedMult; + bIsStanding = false; + InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); } + if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) { + if (speedMult == 0.0f) { + speedMult = pow(0.9f, CTimer::GetTimeStep()); + } + m_vecMoveSpeed.x *= speedMult; + m_vecMoveSpeed.y *= speedMult; + if (m_vecMoveSpeed.z >= -0.1f) { + if (m_vecMoveSpeed.z < -0.04f) + m_vecMoveSpeed.z = -0.02f; + } else { + m_vecMoveSpeed.z = -0.01f; + DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f); #ifdef PC_PARTICLE - else if(stepPart == 2) + CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition(); + float level = 0.0f; + if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) + aBitForward.z = level; + + CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true); + nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80; + nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100; #else - else + CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition(); + float level = 0.0f; + if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) + aBitForward.z = level + 0.5f; + + CVector vel = m_vecMoveSpeed * 0.1f; + vel.z = 0.18f; + CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true); + nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300; + nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60; #endif - { - particleProduceFootSplash(this, footPos, 0.15f, 4); + } } - } - } - - if (m_nSurfaceTouched == SURFACE_WATER) { - float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude(); - if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) { -#ifdef PC_PARTICLE - float particleSize = pedSpeed * 2.0f; + } else + return; + } else + bTouchingWater = false; - if (particleSize < 0.25f) - particleSize = 0.25f; + if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) { + CVector pos = GetPosition(); + float level = 0.0f; + if (CWaterLevel::GetWaterLevel(pos, &level, false)) + pos.z = level; - if (particleSize > 0.75f) - particleSize = 0.75f; - - CVector particlePos = GetPosition() + GetForward() * 0.3f; - particlePos.z -= 1.2f; - - CVector particleDir = m_vecMoveSpeed * -0.75f; - - particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f); - CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0); - - particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); - CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0); + if (pos.z != 0.0f) { + nGenerateWaterCircles = 0; + for(int i = 0; i < 4; i++) { +#ifdef PC_PARTICLE + pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); + pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); + CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0); #else - CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f; - CVector particleDir = m_vecMoveSpeed * 0.45f; - particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); - CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255)); + pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); + pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); + CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f)); #endif + } } } -} - -bool -CPed::IsPointerValid(void) -{ - int pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8; - if (pedIndex < 0 || pedIndex >= NUMPEDS) - return false; - if (m_entryInfoList.first || FindPlayerPed() == this) - return true; + if (nGenerateRaindrops && CTimer::GetTimeInMilliseconds() >= nGenerateRaindrops) { + CVector pos = GetPosition(); + float level = 0.0f; + if (CWaterLevel::GetWaterLevel(pos, &level, false)) + pos.z = level; - return false; + if (pos.z >= 0.0f) { +#ifdef PC_PARTICLE + pos.z += 0.25f; +#else + pos.z += 0.5f; +#endif + nGenerateRaindrops = 0; +#ifdef PC_PARTICLE + CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true); +#else + CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true); +#endif + } + } } -// Some kind of binary sort void -CPed::SortPeds(CPed **list, int min, int max) +CPed::ProcessControl(void) { - if (min >= max) + CColPoint foundCol; + CEntity *foundEnt = nil; + + if (m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory) return; - CVector leftDiff, rightDiff; - CVector middleDiff = GetPosition() - list[(max + min) / 2]->GetPosition(); - float middleDist = middleDiff.Magnitude(); + int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); + if (!bFadeOut) { + if (alpha < 255) { + alpha += 16; + if (alpha > 255) + alpha = 255; + } + } else { + alpha -= 8; + if (alpha < 0) + alpha = 0; + } - int left = max; - int right = min; - while(right <= left){ - float rightDist, leftDist; - do { - rightDiff = GetPosition() - list[right]->GetPosition(); - rightDist = rightDiff.Magnitude(); - } while (middleDist > rightDist && ++right); + CVisibilityPlugins::SetClumpAlpha(GetClump(), alpha); + bIsShooting = false; + BuildPedLists(); + bIsInWater = false; + ProcessBuoyancy(); - do { - leftDiff = GetPosition() - list[left]->GetPosition(); - leftDist = leftDiff.Magnitude(); - } while (middleDist < leftDist && left--); + if (m_nPedState != PED_ARRESTED) { + if (m_nPedState == PED_DEAD) { + DeadPedMakesTyresBloody(); +#ifndef VC_PED_PORTS + if (CGame::nastyGame) { +#else + if (CGame::nastyGame && !bIsInWater) { +#endif + uint32 remainingBloodyFpTime = CTimer::GetTimeInMilliseconds() - m_bloodyFootprintCountOrDeathTime; + float timeDependentDist; + if (remainingBloodyFpTime >= 2000) { + if (remainingBloodyFpTime <= 7000) + timeDependentDist = (remainingBloodyFpTime - 2000) / 5000.0f * 0.75f; + else + timeDependentDist = 0.75f; + } else { + timeDependentDist = 0.0f; + } - if (right <= left) { - CPed *ped = list[right]; - list[right] = list[left]; - list[left] = ped; - right++; - left--; - } - } - SortPeds(list, min, left); - SortPeds(list, right, max); -} + for (int i = 0; i < m_numNearPeds; ++i) { + CPed *nearPed = m_nearPeds[i]; + if (!nearPed->DyingOrDead()) { + CVector dist = nearPed->GetPosition() - GetPosition(); + if (dist.MagnitudeSqr() < sq(timeDependentDist)) { + nearPed->m_bloodyFootprintCountOrDeathTime = 200; + nearPed->bDoBloodyFootprints = true; + if (nearPed->IsPlayer()) { + if (!nearPed->bIsLooking && nearPed->m_nPedState != PED_ATTACK) { + int16 camMode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (camMode != CCam::MODE_SNIPER + && camMode != CCam::MODE_ROCKETLAUNCHER + && camMode != CCam::MODE_M16_1STPERSON + && camMode != CCam::MODE_1STPERSON + && camMode != CCam::MODE_HELICANNON_1STPERSON + && !TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn()) { -void -CPed::BuildPedLists(void) -{ - if (((CTimer::GetFrameCounter() + m_randomSeed) % 16) == 0) { - CVector centre = CEntity::GetBoundCentre(); - CRect rect(centre.x - 20.0f, - centre.y - 20.0f, - centre.x + 20.0f, - centre.y + 20.0f); - int xstart = CWorld::GetSectorIndexX(rect.left); - int ystart = CWorld::GetSectorIndexY(rect.top); - int xend = CWorld::GetSectorIndexX(rect.right); - int yend = CWorld::GetSectorIndexY(rect.bottom); - gnNumTempPedList = 0; + nearPed->SetLookFlag(this, true); + nearPed->SetLookTimer(500); + } + } + } + } + } + } - for(int y = ystart; y <= yend; y++) { - for(int x = xstart; x <= xend; x++) { - for (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) { - CPed *ped = (CPed*)pedPtrNode->item; - if (ped != this && !ped->bInVehicle) { - float dist = (ped->GetPosition() - GetPosition()).Magnitude2D(); - if (nThreatReactionRangeMultiplier * 30.0f > dist) { - gapTempPedList[gnNumTempPedList] = ped; - gnNumTempPedList++; - assert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList)); + if (remainingBloodyFpTime > 2000) { + CVector bloodPos = GetPosition(); + if (remainingBloodyFpTime - 2000 >= 5000) { + if (!m_deadBleeding) { + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, + 0.75f, 0.0f, 0.0f, -0.75f, 255, 255, 0, 0, 4.0f, 40000, 1.0f); + m_deadBleeding = true; } + } else { + CShadows::StoreStaticShadow( + (uintptr)this + 17, SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, + (remainingBloodyFpTime - 2000) / 5000.0f * 0.75f, 0.0f, + 0.0f, (remainingBloodyFpTime - 2000) / 5000.0f * -0.75f, + 255, 255, 0, 0, 4.0f, 1.0f, 40.0f, false, 0.0f); } } } - } - gapTempPedList[gnNumTempPedList] = nil; - SortPeds(gapTempPedList, 0, gnNumTempPedList - 1); - for (m_numNearPeds = 0; m_numNearPeds < ARRAY_SIZE(m_nearPeds); m_numNearPeds++) { - CPed *ped = gapTempPedList[m_numNearPeds]; - if (!ped) - break; + if (ServiceTalkingWhenDead()) + ServiceTalking(); - m_nearPeds[m_numNearPeds] = ped; - } - for (int pedToClear = m_numNearPeds; pedToClear < ARRAY_SIZE(m_nearPeds); pedToClear++) - m_nearPeds[pedToClear] = nil; - } else { - for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) { - bool removePed = false; - if (m_nearPeds[i]) { - if (m_nearPeds[i]->IsPointerValid()) { - float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D(); - if (distSqr > 900.0f) - removePed = true; - } else - removePed = true; +#ifdef VC_PED_PORTS + if (bIsInWater) { + bIsStanding = false; + bWasStanding = false; + CPhysical::ProcessControl(); } - if (removePed) { - // If we arrive here, the ped we're checking isn't "near", so we should remove it. - for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) { - m_nearPeds[j] = m_nearPeds[j + 1]; - m_nearPeds[j + 1] = nil; +#endif + return; + } + + bWasStanding = false; + if (bIsStanding) { + if (!CWorld::bForceProcessControl) { + if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->bIsInSafePosition) { + bWasPostponed = true; + return; } - // Above loop won't work on last slot, so we need to empty it. - m_nearPeds[ARRAY_SIZE(m_nearPeds) - 1] = nil; - m_numNearPeds--; - } else - i++; + } } - } -} -void -CPed::SetPedStats(ePedStats pedStat) -{ - m_pedStats = CPedStats::ms_apPedStats[pedStat]; -} + if (!IsPedInControl() || m_nWaitState != WAITSTATE_FALSE || 0.01f * CTimer::GetTimeStep() <= m_fDistanceTravelled + || (m_nStoredMoveState != PEDMOVE_WALK && m_nStoredMoveState != PEDMOVE_RUN && m_nStoredMoveState != PEDMOVE_SPRINT)) + m_panicCounter = 0; + else if (m_panicCounter < 50) + ++m_panicCounter; -void -CPed::SetModelIndex(uint32 mi) -{ - CEntity::SetModelIndex(mi); - RpAnimBlendClumpInit(GetClump()); - RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames); - CPedModelInfo *modelInfo = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()); - SetPedStats(modelInfo->m_pedStatType); - m_headingRate = m_pedStats->m_headingChangeRate; - m_animGroup = (AssocGroupId) modelInfo->m_animGroup; - CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE); + if (m_fHealth <= 1.0f && m_nPedState <= PED_STATES_NO_AI && !bIsInTheAir && !bIsLanding) + SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D. - (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta; + bCollidedWithMyVehicle = false; -#ifdef PED_SKIN - if(modelInfo->GetHitColModel() == nil) - modelInfo->CreateHitColModelSkinned(GetClump()); + CEntity *collidingEnt = m_pDamageEntity; +#ifndef VC_PED_PORTS + if (!bUsesCollision || m_fDamageImpulse <= 0.0f || m_nPedState == PED_DIE || !collidingEnt) { +#else + if (!bUsesCollision || ((!collidingEnt || m_fDamageImpulse <= 0.0f) && (!IsPlayer() || !bIsStuck)) || m_nPedState == PED_DIE) { #endif -} - -void -CPed::RemoveLighting(bool reset) -{ - CRenderer::RemoveVehiclePedLights(this, reset); -} + bHitSomethingLastFrame = false; + if (m_nPedStateTimer <= 500 && bIsInTheAir) { + if (m_nPedStateTimer) + m_nPedStateTimer--; + } else if (m_nPedStateTimer < 1001) { + m_nPedStateTimer = 0; + } + } else { + if (m_panicCounter == 50 && IsPedInControl()) { + SetWaitState(WAITSTATE_STUCK, nil); + // Leftover + /* + if (m_nPedType < PEDTYPE_COP) { -bool -CPed::SetupLighting(void) -{ - ActivateDirectional(); - SetAmbientColoursForPedsCarsAndObjects(); + } else { -#ifndef MASTER - // Originally this was being called through iteration of Sectors, but putting it here is better. - if (GetDebugDisplay() != 0 && !IsPlayer()) - DebugRenderOnePedText(); + } + */ +#ifndef VC_PED_PORTS + } else { +#else + } else if (collidingEnt) { #endif + switch (collidingEnt->GetType()) + { + case ENTITY_TYPE_BUILDING: + case ENTITY_TYPE_OBJECT: + { + CBaseModelInfo *collidingModel = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex()); + CColModel *collidingCol = collidingModel->GetColModel(); + if (collidingEnt->IsObject() && ((CObject*)collidingEnt)->m_nSpecialCollisionResponseCases != COLLRESPONSE_FENCEPART + || collidingCol->boundingBox.max.x < 3.0f + && collidingCol->boundingBox.max.y < 3.0f) { - if (bRenderScorched) { - WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f); - } else { - // Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0. - float lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition()); - if (!bHasBlip && lightMult != 1.0f) { - SetAmbientAndDirectionalColours(lightMult); - return true; - } - } - return false; -} - -void -CPed::Teleport(CVector pos) -{ - CWorld::Remove(this); - SetPosition(pos); - bIsStanding = false; - m_nPedStateTimer = 0; - m_actionX = 0.0f; - m_actionY = 0.0f; - m_pDamageEntity = nil; - CWorld::Add(this); -} + if (!IsPlayer()) { + SetDirectionToWalkAroundObject(collidingEnt); + break; + } + } + if (IsPlayer()) { + bHitSomethingLastFrame = true; + break; + } -void -CPed::CalculateNewOrientation(void) -{ - if (CReplay::IsPlayingBack() || !IsPedInControl()) - return; + float angleToFaceWhenHit = CGeneral::GetRadianAngleBetweenPoints( + GetPosition().x, + GetPosition().y, + m_vecDamageNormal.x + GetPosition().x, + m_vecDamageNormal.y + GetPosition().y); - SetHeading(m_fRotationCur); -} + float neededTurn = Abs(m_fRotationCur - angleToFaceWhenHit); -float -CPed::WorkOutHeadingForMovingFirstPerson(float offset) -{ - if (!IsPlayer()) - return 0.0f; + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; - CPad *pad0 = CPad::GetPad(0); - float leftRight = pad0->GetPedWalkLeftRight(); - float upDown = pad0->GetPedWalkUpDown(); - float &angle = ((CPlayerPed*)this)->m_fWalkAngle; + float oldDestRot = CGeneral::LimitRadianAngle(m_fRotationDest); - if (upDown != 0.0f) { - angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown); - } else { - if (leftRight < 0.0f) - angle = 0.5f * PI; - else if (leftRight > 0.0f) - angle = -0.5f * PI; - } + if (m_pedInObjective && + (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT)) { - return CGeneral::LimitRadianAngle(offset + angle); -} + if (m_pedInObjective->IsPlayer() + && (neededTurn < DEGTORAD(20.0f) || m_panicCounter > 10)) { + if (CanPedJumpThis(collidingEnt)) { + SetJump(); + } else if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { + SetWaitState(WAITSTATE_LOOK_ABOUT, nil); + } else { + SetWaitState(WAITSTATE_PLAYANIM_TAXI, nil); + m_headingRate = 0.0f; + SetLookFlag(m_pedInObjective, true); + SetLookTimer(3000); + Say(SOUND_PED_TAXI_CALL); + } + } else { + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + TurnBody(); + } + } else { + if (m_nPedType != PEDTYPE_COP && neededTurn < DEGTORAD(15.0f) && m_nWaitState == WAITSTATE_FALSE) { + if ((m_nStoredMoveState == PEDMOVE_RUN || m_nStoredMoveState == PEDMOVE_SPRINT) && m_vecDamageNormal.z < 0.3f) { + CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN); + if (!runAssoc) + runAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT); -void -CPed::CalculateNewVelocity(void) -{ - if (IsPedInControl()) { - float headAmount = DEGTORAD(m_headingRate) * CTimer::GetTimeStep(); - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - float limitedRotDest = CGeneral::LimitRadianAngle(m_fRotationDest); + if (runAssoc && runAssoc->blendAmount > 0.9f && runAssoc->IsRunning()) { + SetWaitState(WAITSTATE_HITWALL, nil); + } + } + } + if (m_nPedState == PED_FLEE_POS) { + CVector2D fleePos = collidingEnt->GetPosition(); + uint32 oldFleeTimer = m_fleeTimer; + SetFlee(fleePos, 5000); + if (oldFleeTimer != m_fleeTimer) + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500; - if (m_fRotationCur - PI > limitedRotDest) { - limitedRotDest += 2 * PI; - } else if(PI + m_fRotationCur < limitedRotDest) { - limitedRotDest -= 2 * PI; - } + } else { + if (m_nPedState == PED_FLEE_ENTITY && (neededTurn < DEGTORAD(25.0f) || m_panicCounter > 10)) { + m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; + m_collidingEntityWhileFleeing = collidingEnt; + m_collidingEntityWhileFleeing->RegisterReference((CEntity **) &m_collidingEntityWhileFleeing); - if (IsPlayer() && m_nPedState == PED_ATTACK) - headAmount /= 4.0f; + uint8 currentDir = Floor((PI + m_fRotationCur) / DEGTORAD(45.0f)); + uint8 nextDir; + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, currentDir, &nextDir); - float neededTurn = limitedRotDest - m_fRotationCur; - if (neededTurn <= headAmount) { - if (neededTurn > (-headAmount)) - m_fRotationCur += neededTurn; - else - m_fRotationCur -= headAmount; - } else { - m_fRotationCur += headAmount; - } - } + } else { + if (neededTurn < DEGTORAD(60.0f)) { + CVector posToHead = m_vecDamageNormal * 4.0f; + posToHead.z = 0.0f; + posToHead += GetPosition(); + int closestNodeId = ThePaths.FindNodeClosestToCoors(posToHead, PATH_PED, + 999999.9f, false, false); + float angleToFace; - CVector2D forward(Sin(m_fRotationCur), Cos(m_fRotationCur)); + if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) { + if (m_nPedState != PED_SEEK_POS && m_nPedState != PED_SEEK_CAR) { + if (m_nPedState == PED_WANDER_PATH) { + m_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId]; + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + m_pNextPathNode->GetX(), m_pNextPathNode->GetY(), + GetPosition().x, GetPosition().y); + } else { + if (ThePaths.m_pathNodes[closestNodeId].GetX() == 0.0f + || ThePaths.m_pathNodes[closestNodeId].GetY() == 0.0f) { + posToHead = (3.0f * m_vecDamageNormal) + GetPosition(); + posToHead.x += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f; + posToHead.y += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f; + } else { + posToHead.x = ThePaths.m_pathNodes[closestNodeId].GetX(); + posToHead.y = ThePaths.m_pathNodes[closestNodeId].GetY(); + } + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + posToHead.x, posToHead.y, + GetPosition().x, GetPosition().y); - m_moved.x = CrossProduct2D(m_vecAnimMoveDelta, forward); // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y; - m_moved.y = DotProduct2D(m_vecAnimMoveDelta, forward); // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur)); + if (m_nPedState != PED_FOLLOW_PATH) + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500; + } + } else { + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + ThePaths.m_pathNodes[closestNodeId].GetX(), + ThePaths.m_pathNodes[closestNodeId].GetY(), + GetPosition().x, + GetPosition().y); - if (CTimer::GetTimeStep() >= 0.01f) { - m_moved = m_moved * (1 / CTimer::GetTimeStep()); - } else { - m_moved = m_moved * (1 / 100.0f); - } + CVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].GetPosition() - GetPosition(); + CVector2D distToSeekPos = m_vecSeekPos - GetPosition(); - if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam()) - || FindPlayerPed() != this || !CanStrafeOrMouseControl()) - return; + if (DotProduct2D(distToNode, distToSeekPos) < 0.0f) { + m_fRotationCur = m_fRotationDest; + break; + } + } + } else { + float angleToFaceAwayDamage = CGeneral::GetRadianAngleBetweenPoints( + m_vecDamageNormal.x, + m_vecDamageNormal.y, + 0.0f, + 0.0f); - float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur); - float pedSpeed = m_moved.Magnitude(); - float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur); + if (angleToFaceAwayDamage < m_fRotationCur) + angleToFaceAwayDamage += TWOPI; - if (localWalkAngle < -0.5f * PI) { - localWalkAngle += PI; - } else if (localWalkAngle > 0.5f * PI) { - localWalkAngle -= PI; - } + float neededTurn = angleToFaceAwayDamage - m_fRotationCur; - // Interestingly this part is responsible for diagonal walking. - if (localWalkAngle > -DEGTORAD(50.0f) && localWalkAngle < DEGTORAD(50.0f)) { - TheCamera.Cams[TheCamera.ActiveCam].m_fPlayerVelocity = pedSpeed; - m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed; - } + if (neededTurn <= PI) { + angleToFace = 0.5f * neededTurn + m_fRotationCur; + m_fRotationCur += DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f; + } else { + angleToFace = m_fRotationCur - (TWOPI - neededTurn) * 0.5f; + m_fRotationCur -= DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f; + } - CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); - CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); -#ifdef VC_PED_PORTS - if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) { -#else - if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) { -#endif - LimbOrientation newUpperLegs; - newUpperLegs.yaw = localWalkAngle; + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200; + if (m_nPedType == PEDTYPE_COP) { + if (m_pedInObjective) { + float angleToLookCriminal = CGeneral::GetRadianAngleBetweenPoints( + m_pedInObjective->GetPosition().x, + m_pedInObjective->GetPosition().y, + GetPosition().x, + GetPosition().y); - if (newUpperLegs.yaw < -DEGTORAD(100.0f)) { - newUpperLegs.yaw += PI; - } else if (newUpperLegs.yaw > DEGTORAD(100.0f)) { - newUpperLegs.yaw -= PI; - } + angleToLookCriminal = CGeneral::LimitRadianAngle(angleToLookCriminal); + angleToFace = CGeneral::LimitRadianAngle(angleToFace); - if (newUpperLegs.yaw > -DEGTORAD(50.0f) && newUpperLegs.yaw < DEGTORAD(50.0f)) { -#ifdef PED_SKIN - if(IsClumpSkinned(GetClump())){ -/* - // this looks shit - newUpperLegs.pitch = 0.0f; - RwV3d axis = { -1.0f, 0.0f, 0.0f }; - RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT); -*/ - newUpperLegs.pitch = 0.1f; - RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; - RwV3d Zaxis = { 0.0f, 0.0f, 1.0f }; - RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT); + if (angleToLookCriminal < angleToFace) + angleToLookCriminal += TWOPI; - bDontAcceptIKLookAts = true; - }else -#endif - { - newUpperLegs.pitch = 0.0f; - m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false); - m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false); - } - } - } -} + float neededTurnToCriminal = angleToLookCriminal - angleToFace; -bool -CPed::CanBeDeleted(void) -{ - if (bInVehicle) - return false; + if (neededTurnToCriminal > DEGTORAD(150.0f) && neededTurnToCriminal < DEGTORAD(210.0f)) { + ((CCopPed*)this)->m_bStopAndShootDisabledZone = true; + } + } + } + } + m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace); - switch (CharCreatedBy) { - case RANDOM_CHAR: - return true; - case MISSION_CHAR: - return false; - default: - return true; - } -} + if (m_fRotationCur - PI > m_fRotationDest) { + m_fRotationDest += TWOPI; + } else if (PI + m_fRotationCur < m_fRotationDest) { + m_fRotationDest -= TWOPI; + } -bool -CPed::CanPedDriveOff(void) -{ - if (m_nPedState != PED_DRIVING || m_lookTimer > CTimer::GetTimeInMilliseconds()) - return false; + if (oldDestRot == m_fRotationDest && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200; + m_fRotationDest += HALFPI; + } + } + } + } + } - for (int i = 0; i < m_numNearPeds; i++) { - CPed *nearPed = m_nearPeds[i]; - if (nearPed->m_nPedType == m_nPedType && nearPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && nearPed->m_carInObjective == m_carInObjective) { - m_lookTimer = CTimer::GetTimeInMilliseconds() + 1000; - return false; - } - } - return true; -} + if (m_nPedState != PED_WANDER_PATH && m_nPedState != PED_FLEE_ENTITY) + m_pNextPathNode = nil; + + bHitSomethingLastFrame = true; + break; + } + case ENTITY_TYPE_VEHICLE: + { + CVehicle* collidingVeh = ((CVehicle*)collidingEnt); + float collidingVehSpeedSqr = collidingVeh->m_vecMoveSpeed.MagnitudeSqr(); + if (collidingVeh == m_pMyVehicle) + bCollidedWithMyVehicle = true; #ifdef VC_PED_PORTS -bool -CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil) -{ - if (m_nSurfaceTouched == SURFACE_WATER) - return true; + float oldHealth = m_fHealth; + bool playerSufferSound = false; - CVector pos = GetPosition(); - CVector forwardOffset = GetForward(); - if (damageNormal && damageNormal->z > 0.17f) { - if (damageNormal->z > 0.9f) - return false; + if (collidingVehSpeedSqr <= 1.0f / 400.0f) { + if (IsPedInControl() + && (!IsPlayer() + || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT + || m_objective == OBJECTIVE_RUN_TO_AREA + || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)) { - CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); - pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z; - pos.z = pos.z + 0.05f; - float collPower = damageNormal->Magnitude2D(); - if (damageNormal->z > 0.5f) { - CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f); - invDamageNormal *= 1.0f / collPower; - CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius; - forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f); - } else { - forwardOffset += collPower * ourCol->spheres->radius * forwardOffset; - } - } else { - pos.z -= 0.15f; - } + if (collidingVeh != m_pCurrentPhysSurface || IsPlayer()) { + if (!bVehEnterDoorIsBlocked) { + if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) { - CVector forwardPos = pos + forwardOffset; - return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false); -} -#else -bool -CPed::CanPedJumpThis(CEntity *unused) -{ - CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur)); - CVector pos = GetPosition(); - CVector forwardPos( - forward.x + pos.x, - forward.y + pos.y, - pos.z); + // VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR. + SetDirectionToWalkAroundObject(collidingVeh); + CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; + } else { + if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer + || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) { - return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false); -} -#endif + // VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR. + SetDirectionToWalkAroundObject(collidingVeh); + CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; -bool -CPed::CanPedReturnToState(void) -{ - return m_nPedState <= PED_STATES_NO_AI && m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK && - m_nPedState != PED_FIGHT && m_nPedState != PED_STEP_AWAY && m_nPedState != PED_SNIPER_MODE && m_nPedState != PED_LOOK_ENTITY; -} + } else if (m_fleeFrom != collidingVeh) { + SetFlee(collidingVeh, 4000); + bUsePedNodeSeek = false; + SetMoveState(PEDMOVE_WALK); + } + } + } + } else { + float angleLeftToCompleteTurn = Abs(m_fRotationCur - m_fRotationDest); + if (angleLeftToCompleteTurn < 0.01f && CanPedJumpThis(collidingVeh)) { + SetJump(); + } + } + } else if (IsPlayer() && !bIsInTheAir) { -bool -CPed::CanSeeEntity(CEntity *entity, float threshold = CAN_SEE_ENTITY_ANGLE_THRESHOLD) -{ - float neededAngle = CGeneral::GetRadianAngleBetweenPoints( - entity->GetPosition().x, - entity->GetPosition().y, - GetPosition().x, - GetPosition().y); + if (IsPedInControl() && ((CPlayerPed*)this)->m_fMoveSpeed == 0.0f + && !bIsLooking && CTimer::GetTimeInMilliseconds() > m_lookTimer && collidingVeh->pDriver) { - if (neededAngle < 0.0f) - neededAngle += TWOPI; - else if (neededAngle > TWOPI) - neededAngle -= TWOPI; + ((CPlayerPed*)this)->AnnoyPlayerPed(false); + SetLookFlag(collidingVeh, true); + SetLookTimer(1300); - float ourAngle = m_fRotationCur; - if (ourAngle < 0.0f) - ourAngle += TWOPI; - else if (ourAngle > TWOPI) - ourAngle -= TWOPI; + eWeaponType weaponType = GetWeapon()->m_eWeaponType; + if (weaponType == WEAPONTYPE_UNARMED + || weaponType == WEAPONTYPE_BASEBALLBAT + || weaponType == WEAPONTYPE_COLT45 + || weaponType == WEAPONTYPE_UZI) { + bShakeFist = true; + } + } else { + SetLookFlag(collidingVeh, true); + SetLookTimer(500); + } + } + } else { + float adjustedImpulse = m_fDamageImpulse; + if (IsPlayer()) { + if (bIsStanding) { + float forwardVecAndDamageDirDotProd = DotProduct(m_vecAnimMoveDelta.y * GetForward(), m_vecDamageNormal); + if (forwardVecAndDamageDirDotProd < 0.0f) { + adjustedImpulse = forwardVecAndDamageDirDotProd * m_fMass + m_fDamageImpulse; + if (adjustedImpulse < 0.0f) + adjustedImpulse = 0.0f; + } + } + } + if (m_fMass / 20.0f < adjustedImpulse) + DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, adjustedImpulse); - float neededTurn = Abs(neededAngle - ourAngle); + if (IsPlayer()) { + if (adjustedImpulse > 20.0f) + adjustedImpulse = 20.0f; - return neededTurn < threshold || TWOPI - threshold < neededTurn; -} + if (adjustedImpulse > 5.0f) { + if (adjustedImpulse <= 13.0f) + playerSufferSound = true; + else + Say(SOUND_PED_DAMAGE); + } -bool -CPed::IsTemporaryObjective(eObjective objective) -{ - return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER || -#ifdef VC_PED_PORTS - objective == OBJECTIVE_LEAVE_CAR_AND_DIE || -#endif - objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER; -} + CColModel* collidingCol = CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(); + CVector colMinVec = collidingCol->boundingBox.min; + CVector colMaxVec = collidingCol->boundingBox.max; -void -CPed::SetMoveState(eMoveState state) -{ - m_nMoveState = state; -} + CVector vehColCenterDist = collidingVeh->GetMatrix() * ((colMinVec + colMaxVec) * 0.5f) - GetPosition(); -void -CPed::SetObjectiveTimer(int time) -{ - if (time == 0) { - m_objectiveTimer = 0; - } else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { - m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time; - } -} + // TLVC = To look vehicle center -void -CPed::ForceStoredObjective(eObjective objective) -{ - if (objective != OBJECTIVE_ENTER_CAR_AS_DRIVER && objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) { - m_prevObjective = m_objective; - return; - } + float angleToVehFront = collidingVeh->GetForward().Heading(); + float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading(); + angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC); - switch (m_objective) - { - case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - case OBJECTIVE_GOTO_AREA_ON_FOOT: - case OBJECTIVE_RUN_TO_AREA: - return; - default: - m_prevObjective = m_objective; - } -} + // I don't know why do we use that + float vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); -void -CPed::SetStoredObjective(void) -{ - if (m_objective == m_prevObjective) - return; + CVector vehDist = GetPosition() - collidingVeh->GetPosition(); + vehDist.Normalise(); - switch (m_objective) - { - case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: - case OBJECTIVE_LEAVE_CAR: - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - case OBJECTIVE_GOTO_AREA_ON_FOOT: - case OBJECTIVE_RUN_TO_AREA: - return; - default: - m_prevObjective = m_objective; - } -} + float vehRightVecAndSpeedDotProd; -void -CPed::RestorePreviousObjective(void) -{ - if (m_objective == OBJECTIVE_NONE) - return; + if (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) { + if (angleDiffFromLookingFrontTLVC <= 0.0f) { + vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - if (m_objective != OBJECTIVE_LEAVE_CAR && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER -#if defined VC_PED_PORTS || defined FIX_BUGS - && m_nPedState != PED_CARJACK -#endif - ) - m_pedInObjective = nil; + // vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right? + if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - if (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) { - m_objective = OBJECTIVE_NONE; - if (m_pMyVehicle) - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + // Car's right faces towards us and isn't coming directly to us + if (DotProduct(collidingVeh->GetRight(), GetForward()) < 0.0f + && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { + SetEvasiveStep(collidingVeh, 1); + } + } + } else { + vehRightVecAndSpeedDotProd = DotProduct(-1.0f * collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - } else { - m_objective = m_prevObjective; - m_prevObjective = OBJECTIVE_NONE; - } - bObjectiveCompleted = false; -} + if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { + if (DotProduct(collidingVeh->GetRight(), GetForward()) > 0.0f + && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { + SetEvasiveStep(collidingVeh, 1); + } + } + } + } else { + vehRightVecAndSpeedDotProd = DotProduct(vehDist, collidingVeh->m_vecMoveSpeed); + } -void -CPed::SetLeader(CEntity *leader) -{ - m_leader = (CPed*)leader; + if (vehRightVecAndSpeedDotProd <= 0.1f) { + if (m_nPedState != PED_FIGHT) { + SetLookFlag(collidingVeh, true); + SetLookTimer(700); + } + } else { + bIsStanding = false; + CVector2D collidingEntMoveDir = -collidingVeh->m_vecMoveSpeed; + int dir = GetLocalDirection(collidingEntMoveDir); + SetFall(1000, (AnimationId)(dir + ANIM_KO_SKID_FRONT), false); - if(m_leader) - m_leader->RegisterReference((CEntity **)&m_leader); -} + float damage; + if (collidingVeh->m_modelIndex == MI_TRAIN) { + damage = 50.0f; + } else { + damage = 20.0f; + } -void -CPed::SetObjective(eObjective newObj, void *entity) -{ - if (DyingOrDead()) - return; + InflictDamage(collidingVeh, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, dir); + Say(SOUND_PED_DAMAGE); + } + } else { + KillPedWithCar(collidingVeh, m_fDamageImpulse); + } + + /* VC specific + if (m_pCollidingEntity != collidingEnt) + bPushedAlongByCar = true; + */ + } + if (m_fHealth < oldHealth && playerSufferSound) + Say(SOUND_PED_HIT); +#else + if (collidingVehSpeedSqr <= 1.0f / 400.0f) { + if (!IsPedInControl() + || IsPlayer() + && m_objective != OBJECTIVE_GOTO_AREA_ON_FOOT + && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER + && m_objective != OBJECTIVE_RUN_TO_AREA) { - if (m_prevObjective == newObj) { - // Why? - if (m_prevObjective != OBJECTIVE_NONE) - return; - } + if (IsPlayer() && !bIsInTheAir) { - if (entity == this) - return; + if (IsPedInControl() + && ((CPlayerPed*)this)->m_fMoveSpeed == 0.0f + && !bIsLooking + && CTimer::GetTimeInMilliseconds() > m_lookTimer + && collidingVeh->pDriver) { - SetObjectiveTimer(0); - if (m_objective == newObj) { - switch (newObj) { - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: - case OBJECTIVE_GOTO_AREA_ANY_MEANS: - case OBJECTIVE_GUARD_ATTACK: - if (m_pedInObjective == entity) - return; + ((CPlayerPed*)this)->AnnoyPlayerPed(false); + SetLookFlag(collidingVeh, true); + SetLookTimer(1300); - break; - case OBJECTIVE_LEAVE_CAR: - case OBJECTIVE_FLEE_CAR: -#ifdef VC_PED_PORTS - case OBJECTIVE_LEAVE_CAR_AND_DIE: -#endif - return; - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - case OBJECTIVE_DESTROY_CAR: - case OBJECTIVE_SOLICIT_VEHICLE: - case OBJECTIVE_BUY_ICE_CREAM: - if (m_carInObjective == entity) - return; + eWeaponType weaponType = GetWeapon()->m_eWeaponType; + if (weaponType == WEAPONTYPE_UNARMED + || weaponType == WEAPONTYPE_BASEBALLBAT + || weaponType == WEAPONTYPE_COLT45 + || weaponType == WEAPONTYPE_UZI) { + bShakeFist = true; + } + } else { + SetLookFlag(collidingVeh, true); + SetLookTimer(500); + } + } - break; - case OBJECTIVE_SET_LEADER: - if (m_leader == entity) - return; + } else if (!bVehEnterDoorIsBlocked) { + if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) { - break; - default: - break; - } - } else { - if ((newObj == OBJECTIVE_LEAVE_CAR -#ifdef VC_PED_PORTS - || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE -#endif - ) && !bInVehicle) - return; - } + SetDirectionToWalkAroundObject(collidingVeh); -#ifdef VC_PED_PORTS - ClearPointGunAt(); -#endif - bObjectiveCompleted = false; - if (IsTemporaryObjective(m_objective) && !IsTemporaryObjective(newObj)) { - m_prevObjective = newObj; - } else { - if (m_objective != newObj) { - if (IsTemporaryObjective(newObj)) - ForceStoredObjective(newObj); - else - SetStoredObjective(); - } - m_objective = newObj; - } + } else if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer + || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) { - switch (newObj) { - case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: + SetDirectionToWalkAroundObject(collidingVeh); + CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; - // In this special case, entity parameter isn't CEntity, but int. - SetObjectiveTimer((uintptr)entity); - break; - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_MUG_CHAR: - m_pNextPathNode = nil; - bUsePedNodeSeek = false; - m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); - m_pedInObjective = (CPed*)entity; - m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); - m_pLookTarget = (CEntity*)entity; - m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget); - break; - case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_GUARD_ATTACK: - m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); - m_pedInObjective = (CPed*)entity; - m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); - break; - case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: - m_pedInObjective = (CPed*)entity; - m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); - m_pedFormation = FORMATION_REAR; - break; - case OBJECTIVE_LEAVE_CAR: -#ifdef VC_PED_PORTS - case OBJECTIVE_LEAVE_CAR_AND_DIE: -#endif - case OBJECTIVE_FLEE_CAR: - m_carInObjective = (CVehicle*)entity; - m_carInObjective->RegisterReference((CEntity **)&m_carInObjective); - if (m_carInObjective->bIsBus && m_leaveCarTimer == 0) { - for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) { - if (m_carInObjective->pPassengers[i] == this) { - m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i; - break; - } - } - } + } else if (m_fleeFrom != collidingVeh) { + SetFlee(collidingVeh, 4000); + bUsePedNodeSeek = false; + SetMoveState(PEDMOVE_WALK); + } + } + } else { + DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, m_fDamageImpulse); + if (IsPlayer()) { + CColModel *collidingCol = CModelInfo::GetModelInfo(collidingVeh->GetModelIndex())->GetColModel(); + CVector colMinVec = collidingCol->boundingBox.min; + CVector colMaxVec = collidingCol->boundingBox.max; - break; - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - if (m_nMoveState == PEDMOVE_STILL) - SetMoveState(PEDMOVE_RUN); + CVector vehColCenterDist = collidingVeh->GetMatrix() * ((colMinVec + colMaxVec) * 0.5f) - GetPosition(); - if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer()) { - RestorePreviousObjective(); - break; - } - // fall through - case OBJECTIVE_DESTROY_CAR: - case OBJECTIVE_SOLICIT_VEHICLE: - case OBJECTIVE_BUY_ICE_CREAM: - m_carInObjective = (CVehicle*)entity; - m_carInObjective->RegisterReference((CEntity**)&m_carInObjective); - m_pSeekTarget = m_carInObjective; - m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget); - m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); - if (newObj == OBJECTIVE_SOLICIT_VEHICLE) { - m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; - } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR && - (m_carInObjective->GetStatus() == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->ArePlayerControlsDisabled())) { - SetObjectiveTimer(14000); - } else { - m_objectiveTimer = 0; - } - break; - case OBJECTIVE_SET_LEADER: - SetLeader((CEntity*)entity); - RestorePreviousObjective(); - break; - default: - break; - } -} + // TLVC = To look vehicle center -void -CPed::SetIdle(void) -{ - if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) { -#ifdef VC_PED_PORTS - if (m_nPedState == PED_AIM_GUN) - ClearPointGunAt(); + float angleToVehFront = collidingVeh->GetForward().Heading(); + float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading(); + angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC); - m_nLastPedState = PED_NONE; -#endif - m_nPedState = PED_IDLE; - SetMoveState(PEDMOVE_STILL); - } - if (m_nWaitState == WAITSTATE_FALSE) { - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000); - } -} + // I don't know why do we use that + float vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); -void -CPed::SetObjective(eObjective newObj) -{ - if (DyingOrDead()) - return; + CVector vehDist = GetPosition() - collidingVeh->GetPosition(); + vehDist.Normalise(); - if (newObj == OBJECTIVE_NONE) { - if ((m_objective == OBJECTIVE_LEAVE_CAR || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER -#ifdef VC_PED_PORTS - || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) - && !IsPlayer() -#else - ) -#endif - && !IsPedInControl()) { - - bStartWanderPathOnFoot = true; - return; - } - // Unused code from assembly... - /* - else if(m_objective == OBJECTIVE_FLEE_CAR) { - - } else { - - } - */ - m_objective = OBJECTIVE_NONE; - m_prevObjective = OBJECTIVE_NONE; - } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) { - SetObjectiveTimer(0); - - if (m_objective == newObj) - return; - - if (IsTemporaryObjective(m_objective)) { - m_prevObjective = newObj; - } else { - if (m_objective != newObj) - SetStoredObjective(); - - m_objective = newObj; - } - bObjectiveCompleted = false; - - switch (newObj) { - case OBJECTIVE_NONE: - m_prevObjective = OBJECTIVE_NONE; - break; - case OBJECTIVE_HAIL_TAXI: - m_nWaitTimer = 0; - SetIdle(); - SetMoveState(PEDMOVE_STILL); - break; - default: - break; - } - } -} - -// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode -// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call... -void -CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType) -{ - if (DyingOrDead()) - return; - - if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE) - return; - - SetObjectiveTimer(0); - - if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType) - return; - - bObjectiveCompleted = false; - if (IsTemporaryObjective(m_objective)) { - m_prevObjective = newObj; - } else { - if (m_objective != newObj) - SetStoredObjective(); - - m_objective = newObj; - } - - if (newObj == OBJECTIVE_FOLLOW_ROUTE) { - SetFollowRoute(routePoint, routeType); - } -} - -void -CPed::ClearChat(void) -{ - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - bIsTalking = false; - ClearLookFlag(); - RestorePreviousState(); -} + float vehRightVecAndSpeedDotProd; -bool -CPed::IsGangMember(void) -{ - return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9; -} + if (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) { + if (angleDiffFromLookingFrontTLVC <= 0.0f) { + vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); -void -CPed::InformMyGangOfAttack(CEntity *attacker) -{ - CPed *attackerPed; + // vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right? + if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) - return; + // Car's right faces towards us and isn't coming directly to us + if (DotProduct(collidingVeh->GetRight(), GetForward()) < 0.0f + && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { + SetEvasiveStep(collidingVeh, 1); + } + } + } else { + vehRightVecAndSpeedDotProd = DotProduct(-1.0f * collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - if (attacker->IsPed()) { - attackerPed = (CPed*)attacker; - } else { - if (!attacker->IsVehicle()) - return; + if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { + if (DotProduct(collidingVeh->GetRight(), GetForward()) > 0.0f + && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { + SetEvasiveStep(collidingVeh, 1); + } + } + } + } else { + vehRightVecAndSpeedDotProd = DotProduct(vehDist, collidingVeh->m_vecMoveSpeed); + } - attackerPed = ((CVehicle*)attacker)->pDriver; - if (!attackerPed) - return; - } + if (vehRightVecAndSpeedDotProd <= 0.1f) { + if (m_nPedState != PED_FIGHT) { + SetLookFlag(collidingVeh, true); + SetLookTimer(700); + } + } else { + bIsStanding = false; + CVector2D collidingEntMoveDir = -collidingVeh->m_vecMoveSpeed; + int dir = GetLocalDirection(collidingEntMoveDir); + SetFall(1000, (AnimationId)(dir + ANIM_KO_SKID_FRONT), false); + CPed *driver = collidingVeh->pDriver; - if (attackerPed->m_nPedType == PEDTYPE_COP) - return; + float damage; + if (driver && driver->IsPlayer()) { + damage = vehRightVecAndSpeedDotProd * 1000.0f; + } else if (collidingVeh->GetModelIndex() == MI_TRAIN) { + damage = 50.0f; + } else { + damage = 20.0f; + } - for (int i = 0; i < m_numNearPeds; i++) { - CPed *nearPed = m_nearPeds[i]; - if (nearPed && nearPed != this) { - CPed *leader = nearPed->m_leader; - if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper) - { - nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed); - nearPed->SetObjectiveTimer(30000); + InflictDamage(collidingVeh, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, dir); + Say(SOUND_PED_DAMAGE); + } + } else { + KillPedWithCar(collidingVeh, m_fDamageImpulse); + } + } +#endif + break; + } + case ENTITY_TYPE_PED: + { + CollideWithPed((CPed*)collidingEnt); + if (((CPed*)collidingEnt)->IsPlayer()) { + CPlayerPed *player = ((CPlayerPed*)collidingEnt); + Say(SOUND_PED_CHAT); + if (m_nMoveState > PEDMOVE_STILL && player->IsPedInControl()) { + if (player->m_fMoveSpeed < 1.0f) { + if (!player->bIsLooking) { + if (CTimer::GetTimeInMilliseconds() > player->m_lookTimer) { + player->AnnoyPlayerPed(false); + player->SetLookFlag(this, true); + player->SetLookTimer(1300); + eWeaponType weapon = player->GetWeapon()->m_eWeaponType; + if (weapon == WEAPONTYPE_UNARMED + || weapon == WEAPONTYPE_BASEBALLBAT + || weapon == WEAPONTYPE_COLT45 + || weapon == WEAPONTYPE_UZI) { + player->bShakeFist = true; + } + } + } + } + } + } + break; + } + default: + break; + } } - } - } -} - -void -CPed::QuitEnteringCar(void) -{ - CVehicle *veh = m_pMyVehicle; - if (m_pVehicleAnim) - m_pVehicleAnim->blendDelta = -1000.0f; - - RestartNonPartialAnims(); - - if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE)) - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); - - if (veh) { - if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK) - veh->bIsBeingCarJacked = false; - - if (veh->m_nNumGettingIn != 0) - veh->m_nNumGettingIn--; - + CVector forceDir; + if (!bIsInTheAir && m_nPedState != PED_JUMP #ifdef VC_PED_PORTS - if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) - RestorePreviousObjective(); + && m_fDamageImpulse > 0.0f #endif + ) { - veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType); - } + forceDir = m_vecDamageNormal; + forceDir.z = 0.0f; + if (!bIsStanding) { + forceDir *= 4.0f; + } else { + forceDir *= 0.5f; + } - bUsesCollision = true; + ApplyMoveForce(forceDir); + } + if ((bIsInTheAir && !DyingOrDead()) +#ifdef VC_PED_PORTS + || (!bIsStanding && !bWasStanding && m_nPedState == PED_FALL) +#endif + ) { + if (m_nPedStateTimer > 0 && m_nPedStateTimer <= 1000) { + forceDir = GetPosition() - m_vecHitLastPos; + } else { + m_nPedStateTimer = 0; + m_vecHitLastPos = GetPosition(); + forceDir = CVector(0.0f, 0.0f, 0.0f); + } - ReplaceWeaponWhenExitingVehicle(); + CVector offsetToCheck; + m_nPedStateTimer++; - if (DyingOrDead()) { - if (m_pVehicleAnim) { - m_pVehicleAnim->blendDelta = -4.0f; - m_pVehicleAnim->flags |= ASSOC_DELETEFADEDOUT; - m_pVehicleAnim->flags &= ~ASSOC_RUNNING; - } - } else - SetIdle(); + float adjustedTs = Max(CTimer::GetTimeStep(), 0.01f); - m_pVehicleAnim = nil; - - if (veh) { + CPad *pad0 = CPad::GetPad(0); + if ((m_nPedStateTimer <= 50.0f / (4.0f * adjustedTs) || m_nPedStateTimer * 0.01f <= forceDir.MagnitudeSqr()) + && (m_nCollisionRecords <= 1 || m_nPedStateTimer <= 50.0f / (2.0f * adjustedTs) || m_nPedStateTimer * 1.0f / 250.0f <= Abs(forceDir.z))) { + + if (m_nCollisionRecords == 1 && m_aCollisionRecords[0] != nil && m_aCollisionRecords[0]->IsBuilding() + && m_nPedStateTimer > 50.0f / (2.0f * adjustedTs) && m_nPedStateTimer * 1.0f / 250.0f > Abs(forceDir.z)) { + offsetToCheck.x = -forceDir.y; #ifdef VC_PED_PORTS - if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE) + offsetToCheck.z = 1.0f; #else - if (veh->AutoPilot.m_nCruiseSpeed == 0) + offsetToCheck.z = 0.0f; #endif - veh->AutoPilot.m_nCruiseSpeed = 17; - } -} + offsetToCheck.y = forceDir.x; + offsetToCheck.Normalise(); -void -CPed::ReactToAttack(CEntity *attacker) -{ - if (IsPlayer() && attacker->IsPed()) { - InformMyGangOfAttack(attacker); - SetLookFlag(attacker, true); - SetLookTimer(700); - return; - } + CVector posToCheck = GetPosition() + offsetToCheck; -#ifdef VC_PED_PORTS - if (m_nPedState == PED_DRIVING && InVehicle() - && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) { + // These are either obstacle or ground to land, I don't know which one. + float obstacleForFlyingZ, obstacleForFlyingOtherDirZ; + CColPoint obstacleForFlying, obstacleForFlyingOtherDir; - if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE - && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS) - && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) { + // Check is there any room for being knocked up in reverse direction of force + if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlying, foundEnt, true, false, false, false, false, false, nil)) { + obstacleForFlyingZ = obstacleForFlying.point.z; + } else { + obstacleForFlyingZ = 500.0f; + } + + posToCheck = GetPosition() - offsetToCheck; - 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->SetStatus(STATUS_PHYSICS); - } - } else -#endif - if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) { - CPed *ourLeader = m_leader; - if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader) - && attacker->IsPed()) { - - CPed *attackerPed = (CPed*)attacker; - if (bNotAllowedToDuck) { - if (!attackerPed->GetWeapon()->IsTypeMelee()) { - m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds(); - return; - } - } else if (bCrouchWhenShooting || bKindaStayInSamePlace) { - SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000)); - return; - } + // Now check for direction of force this time + if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlyingOtherDir, foundEnt, true, false, false, false, false, false, nil)) { + obstacleForFlyingOtherDirZ = obstacleForFlyingOtherDir.point.z; + } else { + obstacleForFlyingOtherDirZ = 501.0f; + } +#ifdef VC_PED_PORTS + uint8 flyDir = 0; + float feetZ = GetPosition().z - FEET_OFFSET; + if ((obstacleForFlyingZ <= feetZ || obstacleForFlyingOtherDirZ >= 500.0f) && (obstacleForFlyingZ <= feetZ || obstacleForFlyingOtherDirZ <= feetZ)) { + if (obstacleForFlyingOtherDirZ > feetZ && obstacleForFlyingZ < 499.0f) + flyDir = 2; + } else { + flyDir = 1; + } - if (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) { - if (m_pedStats != attackerPed->m_pedStats) { - if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) { - RegisterThreatWithGangPeds(attackerPed); - } - if (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) { - SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker); - SetMoveState(PEDMOVE_RUN); - } else { - SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker); - SetObjectiveTimer(20000); - } - } - } else { - SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed); - SetMoveState(PEDMOVE_RUN); - if (attackerPed->GetWeapon()->IsTypeMelee()) - Say(SOUND_PED_FLEE_RUN); - } - } - } -} - -bool -CPed::TurnBody(void) -{ - bool turnDone = true; - - if (m_pLookTarget) - m_fLookDirection = CGeneral::GetRadianAngleBetweenPoints( - m_pLookTarget->GetPosition().x, - m_pLookTarget->GetPosition().y, - GetPosition().x, - GetPosition().y); + if (flyDir != 0 && !bSomeVCflag1) { + SetPosition((flyDir == 2 ? obstacleForFlyingOtherDir.point : obstacleForFlying.point)); + GetMatrix().GetPosition().z += FEET_OFFSET; + GetMatrix().UpdateRW(); + SetLanding(); + bIsStanding = true; + } +#endif + if (obstacleForFlyingZ < obstacleForFlyingOtherDirZ) { + offsetToCheck *= -1.0f; + } + offsetToCheck.z = 1.0f; + forceDir = 4.0f * offsetToCheck; + forceDir.z = 4.0f; + ApplyMoveForce(forceDir); - float limitedLookDir = CGeneral::LimitRadianAngle(m_fLookDirection); - float currentRot = m_fRotationCur; + GetMatrix().GetPosition() += 0.25f * offsetToCheck; - if (currentRot - PI > limitedLookDir) - limitedLookDir += 2 * PI; - else if (PI + currentRot < limitedLookDir) - limitedLookDir -= 2 * PI; + m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints(offsetToCheck.x, offsetToCheck.y, 0.0f, 0.0f); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + m_fRotationDest = m_fRotationCur; + SetHeading(m_fRotationCur); - float neededTurn = currentRot - limitedLookDir; - m_fRotationDest = limitedLookDir; + if (m_nPedState != PED_FALL && !bIsPedDieAnimPlaying) { + SetFall(1000, ANIM_KO_SKID_BACK, true); + } + bIsInTheAir = false; + } else if (m_vecDamageNormal.z > 0.4f) { +#ifndef VC_PED_PORTS + forceDir = m_vecDamageNormal; + forceDir.z = 0.0f; + forceDir.Normalise(); + ApplyMoveForce(2.0f * forceDir); +#else + if (m_nPedState == PED_JUMP) { + if (m_nWaitTimer <= 2000) { + if (m_nWaitTimer < 1000) + m_nWaitTimer += CTimer::GetTimeStep() * 0.02f * 1000.0f; + } else { + m_nWaitTimer = 0; + } + } + forceDir = m_vecDamageNormal; + forceDir.z = 0.0f; + forceDir.Normalise(); + if (m_nPedState != PED_JUMP || m_nWaitTimer >= 300) { + ApplyMoveForce(2.0f * forceDir); + } else { + ApplyMoveForce(-4.0f * forceDir); + } +#endif + } + } else if ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 3) & 7) { + if (IsPlayer() && m_nPedState != PED_JUMP && pad0->JumpJustDown()) { + int16 padWalkX = pad0->GetPedWalkLeftRight(); + int16 padWalkY = pad0->GetPedWalkUpDown(); + if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY); + m_fRotationDest -= TheCamera.Orientation; + m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); + m_fRotationCur = m_fRotationDest; + SetHeading(m_fRotationCur); + } + SetJump(); + m_nPedStateTimer = 0; + m_vecHitLastPos = GetPosition(); - if (Abs(neededTurn) > 0.05f) { - turnDone = false; - currentRot -= neededTurn * 0.2f; - } + // Why? forceDir is unused after this point. + forceDir = CVector(0.0f, 0.0f, 0.0f); + } else if (IsPlayer()) { + int16 padWalkX = pad0->GetPedWalkLeftRight(); + int16 padWalkY = pad0->GetPedWalkUpDown(); + if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY); + m_fRotationDest -= TheCamera.Orientation; + m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); + m_fRotationCur = m_fRotationDest; + SetHeading(m_fRotationCur); + } + CAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_GLIDE); - m_fRotationCur = currentRot; - m_fLookDirection = limitedLookDir; - return turnDone; -} + if (!jumpAssoc) + jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_GLIDE); -void -CPed::Chat(void) -{ - // We're already looking to our partner - if (bIsLooking && TurnBody()) - ClearLookFlag(); + if (jumpAssoc) { + jumpAssoc->blendDelta = -3.0f; + jumpAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + if (m_nPedState == PED_JUMP) + m_nPedState = PED_IDLE; + } else { + CAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_GLIDE); - if (!m_pLookTarget || !m_pLookTarget->IsPed()) { - ClearChat(); - return; - } + if (!jumpAssoc) + jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_GLIDE); - CPed *partner = (CPed*) m_pLookTarget; + if (jumpAssoc) { + jumpAssoc->blendDelta = -3.0f; + jumpAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + } + } else { + offsetToCheck = GetPosition(); + offsetToCheck.z += 0.5f; - if (partner->m_nPedState != PED_CHAT) { - ClearChat(); - if (partner->m_pedInObjective) { - if (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || - partner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE) - ReactToAttack(partner->m_pedInObjective); - } - return; - } - if (bIsTalking) { - if (CGeneral::GetRandomNumber() < 512) { - CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); - if (chatAssoc) { - chatAssoc->blendDelta = -4.0f; - chatAssoc->flags |= ASSOC_DELETEFADEDOUT; + if (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - FEET_OFFSET, foundCol, foundEnt, true, true, false, true, false, false, nil)) { +#ifdef VC_PED_PORTS + if (!bSomeVCflag1 || FEET_OFFSET + foundCol.point.z < GetPosition().z) { + GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z; + GetMatrix().UpdateRW(); + if (bSomeVCflag1) + bSomeVCflag1 = false; + } +#else + GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z; + GetMatrix().UpdateRW(); +#endif + SetLanding(); + bIsStanding = true; + } + } + } else if (m_nPedStateTimer < 1001) { + m_nPedStateTimer = 0; } - bIsTalking = false; - } else - Say(SOUND_PED_CHAT); - - } else { - - if (CGeneral::GetRandomNumber() < 20 && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); - } - if (!bIsTalking && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { - CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f); - float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f); - chatAssoc->SetCurrentTime(chatTime); - - bIsTalking = true; - Say(SOUND_PED_CHAT); } - } - if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) { - ClearChat(); - m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; - } -} - -void -CPed::CheckAroundForPossibleCollisions(void) -{ - CVector ourCentre, objCentre; - CEntity *objects[8]; - int16 maxObject; - - if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) - return; - GetBoundCentre(ourCentre); + if (bIsDucking) + Duck(); - CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false); - for (int i = 0; i < maxObject; i++) { - CEntity *object = objects[i]; - if (bRunningToPhone) { - if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition())) - break; + if (bStartWanderPathOnFoot) { + if (IsPedInControl()) { + ClearAll(); + SetWanderPath(m_nPathDir); + bStartWanderPathOnFoot = false; + } else if (m_nPedState == PED_DRIVING) { + bWanderPathAfterExitingCar = true; + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } } - object->GetBoundCentre(objCentre); - float radius = object->GetBoundRadius(); - if (radius > 4.5f || radius < 1.0f) - radius = 1.0f; - - // Developers gave up calculating Z diff. later according to asm. - float diff = CVector(ourCentre - objCentre).MagnitudeSqr2D(); - if (sq(radius + 1.0f) > diff) - m_fRotationDest += DEGTORAD(22.5f); - } -} + if (!bIsStanding && m_vecMoveSpeed.z > 0.25f) { + float airResistance = Pow(0.95f, CTimer::GetTimeStep()); -#ifdef PEDS_REPORT_CRIMES_ON_PHONE -void -ReportPhonePickUpCB(CAnimBlendAssociation* assoc, void* arg) -{ - CPed* ped = (CPed*)arg; - ped->m_nMoveState = PEDMOVE_STILL; - CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f); + m_vecMoveSpeed *= airResistance; + } +#ifdef VC_PED_PORTS + if (IsPlayer() || !bIsStanding || m_vecMoveSpeed.x != 0.0f || m_vecMoveSpeed.y != 0.0f || m_vecMoveSpeed.z != 0.0f + || (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) + || m_vecAnimMoveDelta.x != 0.0f || m_vecAnimMoveDelta.y != 0.0f + || m_nPedState == PED_JUMP + || bIsInTheAir + || m_pCurrentPhysSurface) { - if (assoc->blendAmount > 0.5f && ped) { - CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f); - } -} - -void -ReportPhonePutDownCB(CAnimBlendAssociation* assoc, void* arg) -{ - assoc->flags |= ASSOC_DELETEFADEDOUT; - assoc->blendDelta = -1000.0f; - CPed* ped = (CPed*)arg; - - if (ped->m_phoneId != -1 && crimeReporters[ped->m_phoneId] == ped) { - crimeReporters[ped->m_phoneId] = nil; - gPhoneInfo.m_aPhones[ped->m_phoneId].m_nState = PHONE_STATE_FREE; - ped->m_phoneId = -1; - } - - if (assoc->blendAmount > 0.5f) - ped->bUpdateAnimHeading = true; - - ped->SetWanderPath(CGeneral::GetRandomNumber() & 7); -} -#endif - -bool -CPed::MakePhonecall(void) -{ -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) { - - FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(), - (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)m_victimOfPlayerCrime), false); - - if (m_crimeToReportOnPhone != CRIME_POSSESSION_GUN) - FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1); - - bRunningToPhone = false; - } + CPhysical::ProcessControl(); + } else { + bHasContacted = false; + bIsInSafePosition = false; + bWasPostponed = false; + bHasHitWall = false; + m_nCollisionRecords = 0; + bHasCollided = false; + m_nDamagePieceType = 0; + m_fDamageImpulse = 0.0f; + m_pDamageEntity = nil; + m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f); + m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f); + } +#else + CPhysical::ProcessControl(); #endif - if (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer) - return false; - -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - CAnimBlendAssociation* talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_TALK); - if (talkAssoc && talkAssoc->blendAmount > 0.5f) { - CAnimBlendAssociation* endAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f); - endAssoc->flags &= ~ASSOC_DELETEFADEDOUT; - endAssoc->SetFinishCallback(ReportPhonePutDownCB, this); - } + if (m_nPedState != PED_DIE || bIsPedDieAnimPlaying) { + if (m_nPedState != PED_DEAD) { + CalculateNewVelocity(); + CalculateNewOrientation(); + } + UpdatePosition(); + PlayFootSteps(); + if (IsPedInControl() && !bIsStanding && !m_pDamageEntity && CheckIfInTheAir()) { + SetInTheAir(); +#ifdef VC_PED_PORTS + bSomeVCflag1 = false; #endif - SetIdle(); - - gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE; -#ifndef PEDS_REPORT_CRIMES_ON_PHONE - m_phoneId = -1; + } +#ifdef VC_PED_PORTS + if (bSomeVCflag1) { + CVector posToCheck = GetPosition(); + posToCheck.z += 0.9f; + if (!CWorld::TestSphereAgainstWorld(posToCheck, 0.2f, this, true, true, false, true, false, false)) + bSomeVCflag1 = false; + } #endif + ProcessObjective(); + if (!bIsAimingGun) { + if (bIsRestoringGun) + RestoreGunPosition(); + } else { + AimGun(); + } - // Because SetWanderPath is now done async in ReportPhonePutDownCB -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - return false; -#else - return true; -#endif -} + if (bIsLooking) { + MoveHeadToLook(); + } else if (bIsRestoringLook) { + RestoreHeadPosition(); + } -bool -CPed::FacePhone(void) -{ - // This function was broken since it's left unused early in development. -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - float phoneDir = CGeneral::GetRadianAngleBetweenPoints( - gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y, - GetPosition().x, GetPosition().y); + if (bIsInTheAir) + InTheAir(); - if (m_facePhoneStart) { - m_lookTimer = 0; - SetLookFlag(phoneDir, true); - m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000; - m_facePhoneStart = false; - } + if (bUpdateAnimHeading) { + if (m_nPedState != PED_GETUP && m_nPedState != PED_FALL) { + m_fRotationCur -= HALFPI; + m_fRotationDest = m_fRotationCur; + bUpdateAnimHeading = false; + } + } - if (bIsLooking && TurnBody()) { - ClearLookFlag(); - SetIdle(); - m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000; - CAnimBlendAssociation* assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f); - assoc->SetFinishCallback(ReportPhonePickUpCB, this); - return true; - } + if (m_nWaitState != WAITSTATE_FALSE) + Wait(); - return false; -#else - float currentRot = RADTODEG(m_fRotationCur); - float phoneDir = CGeneral::GetRadianAngleBetweenPoints( - gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, - gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y, - GetPosition().x, - GetPosition().y); + if (m_nPedState != PED_IDLE) { + CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED); + if(idleAssoc) { + idleAssoc->blendDelta = -8.0f; + idleAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + } - SetLookFlag(phoneDir, false); - phoneDir = CGeneral::LimitAngle(phoneDir); - m_moved = CVector2D(0.0f, 0.0f); + switch (m_nPedState) { + case PED_IDLE: + Idle(); + break; + case PED_LOOK_ENTITY: + case PED_LOOK_HEADING: + Look(); + break; + case PED_WANDER_RANGE: + WanderRange(); + CheckAroundForPossibleCollisions(); + break; + case PED_WANDER_PATH: + WanderPath(); + break; + case PED_SEEK_POS: + case PED_SEEK_ENTITY: + case PED_PURSUE: + case PED_SNIPER_MODE: + case PED_ROCKET_MODE: + case PED_DUMMY: + case PED_FACE_PHONE: + case PED_MAKE_CALL: + case PED_MUG: + case PED_AI_CONTROL: + case PED_FOLLOW_ROUTE: + case PED_CPR: + case PED_SOLICIT: + case PED_BUY_ICECREAM: + case PED_STEP_AWAY: + case PED_UNKNOWN: + case PED_STATES_NO_AI: + case PED_JUMP: + case PED_STAGGER: + case PED_DIVE_AWAY: + case PED_STATES_NO_ST: + case PED_ARREST_PLAYER: + case PED_PASSENGER: + case PED_TAXI_PASSENGER: + case PED_OPEN_DOOR: + case PED_DEAD: + case PED_DRAG_FROM_CAR: + case PED_EXIT_CAR: + case PED_STEAL_CAR: + break; + case PED_ENTER_CAR: + case PED_CARJACK: + { +#ifdef CANCELLABLE_CAR_ENTER + if (!IsPlayer() || !m_pVehicleAnim) + break; - if (currentRot - 180.0f > phoneDir) - phoneDir += 2 * 180.0f; - else if (180.0f + currentRot < phoneDir) - phoneDir -= 2 * 180.0f; + CPad *pad = CPad::GetPad(0); - float neededTurn = currentRot - phoneDir; + if (pad->ArePlayerControlsDisabled()) + break; - if (Abs(neededTurn) <= 0.75f) { - SetIdle(); - ClearLookFlag(); - m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000; - return true; - } else { - m_fRotationCur = DEGTORAD(currentRot - neededTurn * 0.2f); - return false; - } -#endif -} + int vehAnim = m_pVehicleAnim->animId; -CPed * -CPed::CheckForDeadPeds(void) -{ - int event; - if (CEventList::FindClosestEvent(EVENT_DEAD_PED, GetPosition(), &event)) { - int pedHandle = gaEvent[event].entityRef; - if (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) { - bGonnaInvestigateEvent = true; - return CPools::GetPed(pedHandle); - } - } - bGonnaInvestigateEvent = false; - return nil; -} + static bool cancelJack = false; + int16 padWalkX = pad->GetPedWalkLeftRight(); + int16 padWalkY = pad->GetPedWalkUpDown(); + if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { + if (vehAnim == ANIM_CAR_OPEN_LHS || vehAnim == ANIM_CAR_OPEN_RHS || vehAnim == ANIM_COACH_OPEN_L || vehAnim == ANIM_COACH_OPEN_R || + vehAnim == ANIM_VAN_OPEN_L || vehAnim == ANIM_VAN_OPEN) { -#ifdef PEDS_REPORT_CRIMES_ON_PHONE -// returns event id, parameter is optional -int32 -CPed::CheckForPlayerCrimes(CPed *victim) -{ - int i; - float dist; - float mindist = 60.0f; - CPlayerPed *player = FindPlayerPed(); - int32 victimRef = (victim ? CPools::GetPedRef(victim) : 0); - int event = -1; + if (!m_pMyVehicle->pDriver) { + cancelJack = false; + bCancelEnteringCar = true; + } else + cancelJack = true; + } else if (vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f) { + cancelJack = true; + } else if (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS) { + bCancelEnteringCar = true; + cancelJack = false; + } + } + if (cancelJack && vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f && m_pVehicleAnim->GetTimeLeft() < 0.78f) { + cancelJack = false; + QuitEnteringCar(); + RestorePreviousObjective(); + } + if (cancelJack && (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS)) { + cancelJack = false; + bCancelEnteringCar = true; + } +#endif + break; + } + case PED_FLEE_POS: + ms_vec2DFleePosition.x = m_fleeFromPosX; + ms_vec2DFleePosition.y = m_fleeFromPosY; + Flee(); + break; + case PED_FLEE_ENTITY: + if (!m_fleeFrom) { + SetIdle(); + break; + } - for (i = 0; i < NUMEVENTS; i++) { - if (gaEvent[i].type == EVENT_NULL || gaEvent[i].type > EVENT_CAR_SET_ON_FIRE) - continue; + if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) + break; - // those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc. - if (gaEvent[i].type == EVENT_DEAD_PED || gaEvent[i].type == EVENT_GUNSHOT || gaEvent[i].type == EVENT_EXPLOSION) - continue; + ms_vec2DFleePosition = m_fleeFrom->GetPosition(); + Flee(); + break; + case PED_FOLLOW_PATH: + FollowPath(); + break; + case PED_PAUSE: + Pause(); + break; + case PED_ATTACK: + Attack(); + break; + case PED_FIGHT: + Fight(); + break; + case PED_CHAT: + Chat(); + break; + case PED_AIM_GUN: + if (m_pPointGunAt && m_pPointGunAt->IsPed() +#ifdef FIX_BUGS + && !GetWeapon()->IsTypeMelee() +#endif + && ((CPed*)m_pPointGunAt)->CanSeeEntity(this, CAN_SEE_ENTITY_ANGLE_THRESHOLD * 2)) { + ((CPed*)m_pPointGunAt)->ReactToPointGun(this); + } + PointGunAt(); + break; + case PED_SEEK_CAR: + SeekCar(); + break; + case PED_SEEK_IN_BOAT: + SeekBoatPosition(); + break; + case PED_INVESTIGATE: + InvestigateEvent(); + break; + case PED_ON_FIRE: + if (IsPlayer()) + break; - if (victim && gaEvent[i].entityRef != victimRef) - continue; + if (CTimer::GetTimeInMilliseconds() <= m_fleeTimer) { + if (m_fleeFrom) { + ms_vec2DFleePosition = m_fleeFrom->GetPosition(); + } else { + ms_vec2DFleePosition.x = m_fleeFromPosX; + ms_vec2DFleePosition.y = m_fleeFromPosY; + } + Flee(); + } else { + if (m_pFire) + m_pFire->Extinguish(); + } + break; + case PED_FALL: + Fall(); + break; + case PED_GETUP: + SetGetUp(); + break; + case PED_ENTER_TRAIN: + EnterTrain(); + break; + case PED_EXIT_TRAIN: + ExitTrain(); + break; + case PED_DRIVING: + { + if (!m_pMyVehicle) { + bInVehicle = false; + FlagToDestroyWhenNextProcessed(); + return; + } - if (gaEvent[i].criminal != player) - continue; + if (m_pMyVehicle->pDriver != this || m_pMyVehicle->IsBoat()) { + LookForSexyPeds(); + LookForSexyCars(); + break; + } - dist = (GetPosition() - gaEvent[i].posn).Magnitude(); - if (dist < mindist) { - mindist = dist; - event = i; - } - } + if (m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE || !m_pMyVehicle->pDriver->IsPlayer()) { + break; + } - if (event != -1) { - if (victim) { - m_victimOfPlayerCrime = victim; - } else { - switch (gaEvent[event].entityType) { - case EVENT_ENTITY_PED: - m_victimOfPlayerCrime = CPools::GetPed(gaEvent[event].entityRef); - break; - case EVENT_ENTITY_VEHICLE: - m_victimOfPlayerCrime = CPools::GetVehicle(gaEvent[event].entityRef); - break; - case EVENT_ENTITY_OBJECT: - m_victimOfPlayerCrime = CPools::GetObject(gaEvent[event].entityRef); - break; - default: - break; - } - } - } + CPad* pad = CPad::GetPad(0); - return event; -} +#ifdef CAR_AIRBREAK + if (!pad->ArePlayerControlsDisabled()) { + if (pad->GetHorn()) { + float c = Cos(m_fRotationCur); + float s = Sin(m_fRotationCur); + m_pMyVehicle->GetRight() = CVector(1.0f, 0.0f, 0.0f); + m_pMyVehicle->GetForward() = CVector(0.0f, 1.0f, 0.0f); + m_pMyVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); + if (pad->GetAccelerate()) { + m_pMyVehicle->ApplyMoveForce(GetForward() * 30.0f); + } else if (pad->GetBrake()) { + m_pMyVehicle->ApplyMoveForce(-GetForward() * 30.0f); + } else { + int16 lr = pad->GetSteeringLeftRight(); + if (lr < 0) { + //m_pMyVehicle->ApplyTurnForce(20.0f * -GetRight(), GetForward()); + m_pMyVehicle->ApplyMoveForce(-GetRight() * 30.0f); + } else if (lr > 0) { + m_pMyVehicle->ApplyMoveForce(GetRight() * 30.0f); + } else { + m_pMyVehicle->ApplyMoveForce(0.0f, 0.0f, 50.0f); + } + } + } + } #endif + float steerAngle = m_pMyVehicle->m_fSteerAngle; + CAnimBlendAssociation *lDriveAssoc; + CAnimBlendAssociation *rDriveAssoc; + CAnimBlendAssociation *lbAssoc; + CAnimBlendAssociation *sitAssoc; + if (m_pMyVehicle->bLowVehicle) { + sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT); -bool -CPed::CheckForExplosions(CVector2D &area) -{ - int event = 0; - if (CEventList::FindClosestEvent(EVENT_EXPLOSION, GetPosition(), &event)) { - area.x = gaEvent[event].posn.x; - area.y = gaEvent[event].posn.y; - CEntity *actualEntity = nil; + if (!sitAssoc || sitAssoc->blendAmount < 1.0f) { + break; + } - switch (gaEvent[event].entityType) { - case EVENT_ENTITY_PED: - actualEntity = CPools::GetPed(gaEvent[event].entityRef); - break; - case EVENT_ENTITY_VEHICLE: - actualEntity = CPools::GetVehicle(gaEvent[event].entityRef); - break; - case EVENT_ENTITY_OBJECT: - actualEntity = CPools::GetObject(gaEvent[event].entityRef); - break; - default: - break; - } + lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L); + lbAssoc = nil; + rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R); + } else { + sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT); - if (actualEntity) { - m_pEventEntity = actualEntity; - m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity); - bGonnaInvestigateEvent = true; - } else - bGonnaInvestigateEvent = false; + if (!sitAssoc || sitAssoc->blendAmount < 1.0f) { + break; + } - CEventList::ClearEvent(event); - return true; - } else if (CEventList::FindClosestEvent(EVENT_FIRE, GetPosition(), &event)) { - area.x = gaEvent[event].posn.x; - area.y = gaEvent[event].posn.y; - CEventList::ClearEvent(event); - bGonnaInvestigateEvent = false; - return true; - } + lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L); + rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R); + lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB); - bGonnaInvestigateEvent = false; - return false; -} + if (lbAssoc && + TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON + && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) { + lbAssoc->blendDelta = -1000.0f; + } + } -CPed * -CPed::CheckForGunShots(void) -{ - int event; - if (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) { - if (gaEvent[event].entityType == EVENT_ENTITY_PED) { - // Probably due to we don't want peds to go gunshot area? (same on VC) - bGonnaInvestigateEvent = false; - return CPools::GetPed(gaEvent[event].entityRef); - } - } - bGonnaInvestigateEvent = false; - return nil; -} + CAnimBlendAssociation *driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L); -PointBlankNecessity -CPed::CheckForPointBlankPeds(CPed *pedToVerify) -{ - float pbDistance = 1.1f; - if (GetWeapon()->IsType2Handed()) - pbDistance = 1.6f; + if (!driveByAssoc) + driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R); - for (int i = 0; i < m_numNearPeds; i++) { - CPed *nearPed = m_nearPeds[i]; + if (m_pMyVehicle->bLowVehicle || m_pMyVehicle->m_fGasPedal >= 0.0f || driveByAssoc) { + if (steerAngle == 0.0f || driveByAssoc) { + if (lDriveAssoc) + lDriveAssoc->blendAmount = 0.0f; + if (rDriveAssoc) + rDriveAssoc->blendAmount = 0.0f; - if (!pedToVerify || pedToVerify == nearPed) { + } else if (steerAngle <= 0.0f) { + if (lDriveAssoc) + lDriveAssoc->blendAmount = 0.0f; - CVector diff = nearPed->GetPosition() - GetPosition(); - if (diff.Magnitude() < pbDistance) { + if (rDriveAssoc) + rDriveAssoc->blendAmount = clamp(steerAngle * -100.0f / 61.0f, 0.0f, 1.0f); + else if (m_pMyVehicle->bLowVehicle) + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_R); + else + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_R); - float neededAngle = CGeneral::GetRadianAngleBetweenPoints( - nearPed->GetPosition().x, nearPed->GetPosition().y, - GetPosition().x, GetPosition().y); - neededAngle = CGeneral::LimitRadianAngle(neededAngle); - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + } else { + if (rDriveAssoc) + rDriveAssoc->blendAmount = 0.0f; - float neededTurn = Abs(neededAngle - m_fRotationCur); + if (lDriveAssoc) + lDriveAssoc->blendAmount = clamp(steerAngle * 100.0f / 61.0f, 0.0f, 1.0f); + else if (m_pMyVehicle->bLowVehicle) + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_L); + else + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_L); + } - if (neededTurn > PI) - neededTurn = 2*PI - neededTurn; + if (lbAssoc) + lbAssoc->blendDelta = -4.0f; + } else { + + if ((TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON + || TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking != LOOKING_LEFT) + && (!lbAssoc || lbAssoc->blendAmount < 1.0f)) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LB, 4.0f); + } + } + break; + } + case PED_DIE: + Die(); + break; + case PED_HANDS_UP: + if (m_pedStats->m_temper <= 50) { + if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSCOWER)) { + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER); + Say(SOUND_PED_HANDS_COWER); + } + } else if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP)) { + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP); + Say(SOUND_PED_HANDS_UP); + } + break; + default: break; + } + SetMoveAnim(); + if (bPedIsBleeding) { + if (CGame::nastyGame) { + if (!(CTimer::GetFrameCounter() & 3)) { + CVector cameraDist = GetPosition() - TheCamera.GetPosition(); + if (cameraDist.MagnitudeSqr() < sq(50.0f)) { - if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY) - return NO_POINT_BLANK_PED; + float length = (CGeneral::GetRandomNumber() & 127) * 0.0015f + 0.15f; + CVector bloodPos( + ((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f, + ((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f, + 1.0f); + bloodPos += GetPosition(); - if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) { - if (pedToVerify == nearPed) - return POINT_BLANK_FOR_WANTED_PED; - else - return POINT_BLANK_FOR_SOMEONE_ELSE; + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, length, 0.0f, + 0.0f, -length, 255, 255, 0, 0, 4.0f, (CGeneral::GetRandomNumber() & 4095) + 2000, 1.0f); + } + } } } + ServiceTalking(); + if (bInVehicle && !m_pMyVehicle) + bInVehicle = false; +#ifndef VC_PED_PORTS + m_pCurrentPhysSurface = nil; +#endif + } else { + if (bIsStanding && (!m_pCurrentPhysSurface || IsPlayer()) + || bIsInWater || !bUsesCollision) { + SetDead(); + } + m_pCurrentPhysSurface = nil; } } - return NO_POINT_BLANK_PED; } -bool -CPed::CheckIfInTheAir(void) +int32 +CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) { - if (bInVehicle) - return false; + bool collidedWithBoat = false; + bool belowTorsoCollided = false; + float gravityEffect = -0.15f * CTimer::GetTimeStep(); + CColPoint intersectionPoint; + CColLine ourLine; - CVector pos = GetPosition(); - CColPoint foundColPoint; - CEntity *foundEntity; + CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel(); + CColModel *hisCol = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex())->GetColModel(); - float startZ = pos.z - 1.54f; - bool foundGround = CWorld::ProcessVerticalLine(pos, startZ, foundColPoint, foundEntity, true, true, false, true, false, false, nil); - if (!foundGround && m_nPedState != PED_JUMP) - { - pos.z -= FEET_OFFSET; - if (CWorld::TestSphereAgainstWorld(pos, 0.15f, this, true, false, false, false, false, false)) - foundGround = true; - } - return !foundGround; -} + if (!bUsesCollision) + return false; -void -CPed::ClearAll(void) -{ - if (!IsPedInControl() && m_nPedState != PED_DEAD) - return; + if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) + collidedWithBoat = true; - m_nPedState = PED_NONE; - m_nMoveState = PEDMOVE_NONE; - m_pSeekTarget = nil; - m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); - m_fleeFromPosX = 0.0f; - m_fleeFromPosY = 0.0f; - m_fleeFrom = nil; - m_fleeTimer = 0; - bUsesCollision = true; + // ofc we're not vehicle + if (!m_bIsVehicleBeingShifted && !bSkipLineCol #ifdef VC_PED_PORTS - ClearPointGunAt(); -#else - ClearAimFlag(); - ClearLookFlag(); + && !collidingEnt->IsPed() #endif - bIsPointingGunAt = false; - bRenderPedInCar = true; - bKnockedUpIntoAir = false; - m_pCollidingEntity = nil; -} - -void -CPed::ClearAttack(void) -{ - if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK) - return; - + ) { + if (!bCollisionProcessed) { #ifdef VC_PED_PORTS - // VC uses CCamera::Using1stPersonWeaponMode - if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER || - TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) { - SetPointGunAt(nil); - } else + m_pCurrentPhysSurface = nil; +#endif + if (bIsStanding) { + bIsStanding = false; + bWasStanding = true; + } + bCollisionProcessed = true; + m_fCollisionSpeed += m_vecMoveSpeed.Magnitude2D() * CTimer::GetTimeStep(); + bStillOnValidPoly = false; + if (IsPlayer() || m_fCollisionSpeed >= 1.0f + && (m_fCollisionSpeed >= 2.0f || m_nPedState != PED_WANDER_PATH)) { + m_collPoly.valid = false; + m_fCollisionSpeed = 0.0f; + bHitSteepSlope = false; + } else { + CVector pos = GetPosition(); + float potentialGroundZ = GetPosition().z - FEET_OFFSET; + if (bWasStanding) { + pos.z += -0.25f; + potentialGroundZ += gravityEffect; + } + if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) { + bStillOnValidPoly = true; +#ifdef VC_PED_PORTS + if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { + GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; + if (bSomeVCflag1) + bSomeVCflag1 = false; + } +#else + GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; #endif - if (bIsPointingGunAt) { - if (m_pLookTarget) - SetPointGunAt(m_pLookTarget); - else - ClearPointGunAt(); - } else if (m_objective != OBJECTIVE_NONE) { - SetIdle(); - } else { - RestorePreviousState(); - } -} - -void -CPed::ClearAttackByRemovingAnim(void) -{ - if (m_nPedState != PED_ATTACK || bIsDucking) - return; - - CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay); - if (!weaponAssoc) { - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay); - - if (!weaponAssoc && weapon->m_bThrow) - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU); - if (!weaponAssoc) { - ClearAttack(); - return; + m_vecMoveSpeed.z = 0.0f; + bIsStanding = true; + } else { + m_collPoly.valid = false; + m_fCollisionSpeed = 0.0f; + bHitSteepSlope = false; + } + } } - } - weaponAssoc->blendDelta = -8.0f; - weaponAssoc->flags &= ~ASSOC_RUNNING; - weaponAssoc->flags |= ASSOC_DELETEFADEDOUT; - weaponAssoc->SetDeleteCallback(FinishedAttackCB, this); -} - -void -CPed::StopNonPartialAnims(void) -{ - CAnimBlendAssociation *assoc; - for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { - if (!assoc->IsPartial()) - assoc->flags &= ~ASSOC_RUNNING; - } -} + if (!bStillOnValidPoly) { + CVector potentialCenter = GetPosition(); + potentialCenter.z = GetPosition().z - 0.52f; -void -CPed::SetStoredState(void) -{ - if (m_nLastPedState != PED_NONE || !CanPedReturnToState()) - return; + // 0.52f should be a ped's approx. radius + float totalRadiusWhenCollided = collidingEnt->GetBoundRadius() + 0.52f - gravityEffect; + if (bWasStanding) { + if (collidedWithBoat) { + potentialCenter.z += 2.0f * gravityEffect; + totalRadiusWhenCollided += Abs(gravityEffect); + } else { + potentialCenter.z += gravityEffect; + } + } + if (sq(totalRadiusWhenCollided) > (potentialCenter - collidingEnt->GetBoundCentre()).MagnitudeSqr()) { + ourLine.p0 = GetPosition(); + ourLine.p1 = GetPosition(); + ourLine.p1.z = GetPosition().z - FEET_OFFSET; + if (bWasStanding) { + ourLine.p1.z = ourLine.p1.z + gravityEffect; + ourLine.p0.z = ourLine.p0.z + -0.25f; + } + float minDist = 1.0f; + belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol, + intersectionPoint, minDist, false, &m_collPoly); - if (m_nPedState == PED_WANDER_PATH) { - bFindNewNodeAfterStateRestore = true; - if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) - m_nMoveState = PEDMOVE_WALK; - } + if (collidedWithBoat && bWasStanding && !belowTorsoCollided) { + ourLine.p0.z = ourLine.p1.z; + ourLine.p1.z = ourLine.p1.z + gravityEffect; + belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol, + intersectionPoint, minDist, false, &m_collPoly); + } + if (belowTorsoCollided) { +#ifndef VC_PED_PORTS + if (!collidingEnt->IsPed()) { +#endif + if (!bIsStanding + || FEET_OFFSET + intersectionPoint.point.z > GetPosition().z + || collidedWithBoat && 3.12f + intersectionPoint.point.z > GetPosition().z) { + + if (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) { + m_pCurSurface = collidingEnt; + collidingEnt->RegisterReference((CEntity**)&m_pCurSurface); + bTryingToReachDryLand = false; + bOnBoat = false; + } else { + m_pCurrentPhysSurface = (CPhysical*)collidingEnt; + collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface); + m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition(); + m_pCurSurface = collidingEnt; + collidingEnt->RegisterReference((CEntity**)&m_pCurSurface); + m_collPoly.valid = false; + if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) { + bOnBoat = true; + } else { + bOnBoat = false; + } + } #ifdef VC_PED_PORTS - if (m_nPedState != PED_IDLE) + if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { + GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; + if (bSomeVCflag1) + bSomeVCflag1 = false; + } +#else + GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; #endif - { - m_nLastPedState = m_nPedState; - if (m_nMoveState >= m_nPrevMoveState) - m_nPrevMoveState = m_nMoveState; - } -} + m_nSurfaceTouched = intersectionPoint.surfaceB; + if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) { + bHitSteepSlope = true; + m_vecDamageNormal = intersectionPoint.normal; + } + } +#ifdef VC_PED_PORTS + float upperSpeedLimit = 0.33f; + float lowerSpeedLimit = -0.25f; + float speed = m_vecMoveSpeed.Magnitude2D(); + if (m_nPedState == PED_IDLE) { + upperSpeedLimit *= 2.0f; + lowerSpeedLimit *= 1.5f; + } + CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL); + if (!bWasStanding && speed > upperSpeedLimit && (/*!bPushedAlongByCar ||*/ m_vecMoveSpeed.z < lowerSpeedLimit) + && m_pCollidingEntity != collidingEnt) { -void -CPed::SetDie(AnimationId animId, float delta, float speed) -{ - CPlayerPed *player = FindPlayerPed(); - if (player == this) { - if (!player->m_bCanBeDamaged) - return; - } + float damage = 100.0f * Max(speed - 0.25f, 0.0f); + float damage2 = damage; + if (m_vecMoveSpeed.z < -0.25f) + damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f; - m_threatEntity = nil; - if (DyingOrDead()) - return; + uint8 dir = 2; // from backward + if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) { + CVector2D offset = -m_vecMoveSpeed; + dir = GetLocalDirection(offset); + } - if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) - delta *= 0.5f; + InflictDamage(collidingEnt, WEAPONTYPE_FALL, damage, PEDPIECE_TORSO, dir); + if (IsPlayer() && damage2 > 5.0f) + Say(SOUND_PED_LAND); - SetStoredState(); - ClearAll(); - m_fHealth = 0.0f; - if (m_nPedState == PED_DRIVING) { - if (!IsPlayer()) - FlagToDestroyWhenNextProcessed(); - } else if (bInVehicle) { - if (m_pVehicleAnim) - m_pVehicleAnim->blendDelta = -1000.0f; - } else if (EnteringCar()) { - QuitEnteringCar(); - } + } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) { + InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2); + } +#else + float speedSqr = 0.0f; + CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL); + if (!bWasStanding && (m_vecMoveSpeed.z < -0.25f || (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) > sq(0.5f))) { + if (speedSqr == 0.0f) + speedSqr = sq(m_vecMoveSpeed.z); - m_nPedState = PED_DIE; - if (animId == NUM_ANIMS) { - bIsPedDieAnimPlaying = false; - } else { - CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta); - if (speed > 0.0f) - dieAssoc->speed = speed; + uint8 dir = 2; // from backward + if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) { + CVector2D offset = -m_vecMoveSpeed; + dir = GetLocalDirection(offset); + } + InflictDamage(collidingEnt, WEAPONTYPE_FALL, 350.0f * sq(speedSqr), PEDPIECE_TORSO, dir); - dieAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; - if (dieAssoc->IsRunning()) { - dieAssoc->SetFinishCallback(FinishDieAnimCB, this); - bIsPedDieAnimPlaying = true; + } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) { + InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2); + } +#endif + m_vecMoveSpeed.z = 0.0f; + bIsStanding = true; +#ifndef VC_PED_PORTS + } else { + bOnBoat = false; + } +#endif + } else { + bOnBoat = false; + } + } } } - Say(SOUND_PED_DEATH); - if (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK) - QuitEnteringCar(); - if (!bInVehicle) - StopNonPartialAnims(); + int ourCollidedSpheres = CCollision::ProcessColModels(GetMatrix(), *ourCol, collidingEnt->GetMatrix(), *hisCol, collidingPoints, nil, nil); + if (ourCollidedSpheres > 0 || belowTorsoCollided) { + AddCollisionRecord(collidingEnt); + if (!collidingEnt->IsBuilding()) + ((CPhysical*)collidingEnt)->AddCollisionRecord(this); - m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds(); + if (ourCollidedSpheres > 0 && (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic())) { + bHasHitWall = true; + } + } + if (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic()) { + + if (bWasStanding) { + CVector sphereNormal; + float normalLength; + for(int sphere = 0; sphere < ourCollidedSpheres; sphere++) { + sphereNormal = collidingPoints[sphere].normal; +#ifdef VC_PED_PORTS + if (sphereNormal.z >= -1.0f || !IsPlayer()) { +#endif + normalLength = sphereNormal.Magnitude2D(); + if (normalLength != 0.0f) { + sphereNormal.x = sphereNormal.x / normalLength; + sphereNormal.y = sphereNormal.y / normalLength; + } +#ifdef VC_PED_PORTS + } else { + float speed = m_vecMoveSpeed.Magnitude2D(); + sphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed); + sphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed); + GetMatrix().GetPosition().z -= 0.05f; + bSomeVCflag1 = true; + } +#endif + sphereNormal.Normalise(); + collidingPoints[sphere].normal = sphereNormal; + if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF) + bHitSteepSlope = true; + } + } + } + return ourCollidedSpheres; } -bool -CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction) +static void +particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times) { - CPlayerPed *player = FindPlayerPed(); - float dieDelta = 4.0f; - float dieSpeed = 0.0f; - AnimationId dieAnim = ANIM_KO_SHOT_FRONT1; - bool headShot = false; - bool willLinger = false; - int random; - - if (player == this) { - if (!player->m_bCanBeDamaged) - return false; +#ifdef PC_PARTICLE + for (int i = 0; i < times; i++) { + CVector adjustedPos = pos; + adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - player->AnnoyPlayerPed(false); + CVector direction = ped->GetForward() * -0.05f; + CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200); } +#else + for ( int32 i = 0; i < times; i++ ) + { + CVector adjustedPos = pos; + adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + + CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200); + } +#endif +} - if (DyingOrDead()) - return false; - - if (!bUsesCollision && method != WEAPONTYPE_DROWNING) - return false; - - if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() && - method != WEAPONTYPE_DROWNING && method != WEAPONTYPE_EXPLOSION) - return false; +static void +particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) +{ + switch (ped->m_nSurfaceTouched) + { + case SURFACE_TARMAC: + case SURFACE_GRAVEL: + case SURFACE_PAVEMENT: + case SURFACE_SAND: + for (int i = 0; i < times; ++i) { + CVector adjustedPos = pos; + adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0); + } + break; + default: + break; + } +} - float healthImpact; - if (IsPlayer()) - healthImpact = damage * 0.33f; - else - healthImpact = damage * m_pedStats->m_defendWeakness; +void +CPed::PlayFootSteps(void) +{ + if (bDoBloodyFootprints) { + if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) { + m_bloodyFootprintCountOrDeathTime--; - bool detectDieAnim = true; - if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) { - if (!IsPedHeadAbovePos(-0.3f)) { - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) - dieAnim = ANIM_FLOOR_HIT_F; - else - dieAnim = ANIM_FLOOR_HIT; - dieDelta *= 2.0f; - dieSpeed = 0.5f; - detectDieAnim = false; - } else if (m_nPedState == PED_FALL) { - dieAnim = NUM_ANIMS; - detectDieAnim = false; + if (m_bloodyFootprintCountOrDeathTime == 0) + bDoBloodyFootprints = false; } } - if (detectDieAnim) { - switch (method) { - case WEAPONTYPE_UNARMED: - if (bMeleeProof) - return false; - - if (m_nPedState == PED_FALL) { - if (IsPedHeadAbovePos(-0.3f)) { - dieAnim = NUM_ANIMS; - } else { - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) - dieAnim = ANIM_FLOOR_HIT_F; - else - dieAnim = ANIM_FLOOR_HIT; - dieDelta = dieDelta * 2.0f; - dieSpeed = 0.5f; - } - } else { - switch (direction) { - case 0: - dieAnim = ANIM_KO_SKID_FRONT; - break; - case 1: - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - dieAnim = ANIM_KO_SKID_BACK; - break; - case 3: - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - } - break; - case WEAPONTYPE_BASEBALLBAT: - if (bMeleeProof) - return false; - - if (m_nPedState == PED_FALL) { - if (IsPedHeadAbovePos(-0.3f)) { - dieAnim = NUM_ANIMS; - } else { - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) - dieAnim = ANIM_FLOOR_HIT_F; - else - dieAnim = ANIM_FLOOR_HIT; - dieDelta = dieDelta * 2.0f; - dieSpeed = 0.5f; - } - } else { - switch (direction) { - case 0: - dieAnim = ANIM_KO_SKID_FRONT; - break; - case 1: - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - dieAnim = ANIM_KO_SKID_BACK; - break; - case 3: - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - } - break; - case WEAPONTYPE_COLT45: - case WEAPONTYPE_UZI: - case WEAPONTYPE_SHOTGUN: - case WEAPONTYPE_AK47: - case WEAPONTYPE_M16: - case WEAPONTYPE_SNIPERRIFLE: - if (bBulletProof) - return false; - - bool dontRemoveLimb; - if (IsPlayer() || bNoCriticalHits) - dontRemoveLimb = true; - else { - switch (method) { - case WEAPONTYPE_SNIPERRIFLE: - dontRemoveLimb = false; - break; - case WEAPONTYPE_M16: - dontRemoveLimb = false; - break; - case WEAPONTYPE_SHOTGUN: - dontRemoveLimb = CGeneral::GetRandomNumber() & 7; - break; - default: - dontRemoveLimb = CGeneral::GetRandomNumber() & 15; - break; - } - } - - if (dontRemoveLimb) { - if (method == WEAPONTYPE_SHOTGUN) { - switch (direction) { - case 0: - dieAnim = ANIM_KO_SKID_FRONT; - break; - case 1: - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - dieAnim = ANIM_KO_SKID_BACK; - break; - case 3: - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - } else - dieAnim = ANIM_KO_SHOT_FRONT1; - - willLinger = false; - } else { - switch (pedPiece) { - case PEDPIECE_TORSO: - willLinger = false; - dieAnim = ANIM_KO_SHOT_FRONT1; - break; - case PEDPIECE_MID: - willLinger = false; - dieAnim = ANIM_KO_SHOT_STOM; - break; - case PEDPIECE_LEFTARM: - dieAnim = ANIM_KO_SHOT_ARML; - RemoveBodyPart(PED_UPPERARML, direction); - willLinger = true; - break; - case PEDPIECE_RIGHTARM: - dieAnim = ANIM_KO_SHOT_ARMR; - RemoveBodyPart(PED_UPPERARMR, direction); - willLinger = true; - break; - case PEDPIECE_LEFTLEG: - dieAnim = ANIM_KO_SHOT_LEGL; - RemoveBodyPart(PED_UPPERLEGL, direction); - willLinger = true; - break; - case PEDPIECE_RIGHTLEG: - dieAnim = ANIM_KO_SHOT_LEGR; - RemoveBodyPart(PED_UPPERLEGR, direction); - willLinger = true; - break; - case PEDPIECE_HEAD: - dieAnim = ANIM_KO_SHOT_FACE; - RemoveBodyPart(PED_HEAD, direction); - headShot = true; - willLinger = true; - break; - default: - break; - } - } - break; - case WEAPONTYPE_ROCKETLAUNCHER: - case WEAPONTYPE_GRENADE: - case WEAPONTYPE_EXPLOSION: - if (bExplosionProof) - return false; - - if (CGame::nastyGame && !IsPlayer() && !bInVehicle && - 1.0f + healthImpact > m_fArmour + m_fHealth) { - - random = CGeneral::GetRandomNumber(); - if (random & 1) - RemoveBodyPart(PED_UPPERARML, direction); - if (random & 2) - RemoveBodyPart(PED_UPPERLEGR, direction); - if (random & 4) - RemoveBodyPart(PED_HEAD, direction); - if (random & 8) - RemoveBodyPart(PED_UPPERARMR, direction); - if (random & 0x10) - RemoveBodyPart(PED_UPPERLEGL, direction); - if (bBodyPartJustCameOff) - willLinger = true; - } - // fall through - case WEAPONTYPE_MOLOTOV: - if (bExplosionProof) - return false; - - switch (direction) { - case 0: - dieAnim = ANIM_KO_SKID_FRONT; - break; - case 1: - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - dieAnim = ANIM_KO_SKID_BACK; - break; - case 3: - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - break; - case WEAPONTYPE_FLAMETHROWER: - if (bFireProof) - return false; - - dieAnim = ANIM_KO_SHOT_FRONT1; - break; - case WEAPONTYPE_RAMMEDBYCAR: - case WEAPONTYPE_RUNOVERBYCAR: - if (bCollisionProof) - return false; - random = CGeneral::GetRandomNumber() & 3; - switch (random) { - case 0: - if ((pedPiece != PEDPIECE_LEFTARM || random <= 1) - && (pedPiece != PEDPIECE_MID || random != 1)) { - if (pedPiece == PEDPIECE_RIGHTARM && random > 1 - || pedPiece == PEDPIECE_MID && random == 2) - - dieAnim = ANIM_KO_SPIN_L; - else - dieAnim = ANIM_KO_SKID_FRONT; - } else - dieAnim = ANIM_KO_SPIN_R; + if (!bIsStanding) + return; - break; - case 1: - if (m_nPedState == PED_DIVE_AWAY) - dieAnim = ANIM_KD_LEFT; - else - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - if ((pedPiece != PEDPIECE_LEFTARM || random <= 1) - && (pedPiece != PEDPIECE_MID || random != 1)) { - if ((pedPiece != PEDPIECE_RIGHTARM || random <= 1) - && (pedPiece != PEDPIECE_MID || random != 2)) { - dieAnim = ANIM_KO_SKID_BACK; - } else { - dieAnim = ANIM_KD_RIGHT; - } - } else - dieAnim = ANIM_KD_LEFT; - break; - case 3: - if (m_nPedState == PED_DIVE_AWAY) - dieAnim = ANIM_KD_RIGHT; - else - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - if (damagedBy) { - CVehicle *vehicle = (CVehicle*)damagedBy; - if (method == WEAPONTYPE_RAMMEDBYCAR) { - float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude(); - dieDelta = 8.0f * vehSpeed + 4.0f; - } else { - float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude(); - dieDelta = 12.0f * vehSpeed + 4.0f; - dieSpeed = 16.0f * vehSpeed + 1.0f; - } - } - break; - case WEAPONTYPE_DROWNING: - dieAnim = ANIM_DROWN; - break; - case WEAPONTYPE_FALL: - if (bCollisionProof) - return false; + CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); + CAnimBlendAssociation *walkRunAssoc = nil; + float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f; - switch (direction) { - case 0: - dieAnim = ANIM_KO_SKID_FRONT; - break; - case 1: - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - dieAnim = ANIM_KO_SKID_BACK; - break; - case 3: - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - break; - default: - break; + for (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + if (assoc->flags & ASSOC_WALK) { + walkRunAssoc = assoc; + walkRunAssocBlend += assoc->blendAmount; + } else if ((assoc->flags & ASSOC_NOWALK) == 0) { + idleAssocBlend += assoc->blendAmount; } } - if (m_fArmour != 0.0f && method != WEAPONTYPE_DROWNING) { - if (player == this) - CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss = CTimer::GetTimeInMilliseconds(); +#ifdef GTA_PS2_STUFF + CAnimBlendAssociation *runStopAsoc = NULL; + + if ( IsPlayer() ) + { + runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); + + if ( runStopAsoc == NULL ) + runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); + } + + if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f ) + { + { + CVector pos(0.0f, 0.0f, 0.0f); + TransformToNode(pos, PED_FOOTL); + + pos.z -= 0.1f; + pos += GetForward()*0.2f; + particleProduceFootDust(this, pos, 0.02f, 1); + } - if (healthImpact < m_fArmour) { - m_fArmour = m_fArmour - healthImpact; - healthImpact = 0.0f; - } else { - healthImpact = healthImpact - m_fArmour; - m_fArmour = 0.0f; + { + CVector pos(0.0f, 0.0f, 0.0f); + TransformToNode(pos, PED_FOOTR); + + pos.z -= 0.1f; + pos += GetForward()*0.2f; + particleProduceFootDust(this, pos, 0.02f, 1); } } +#endif + - if (healthImpact != 0.0f) { - if (player == this) - CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds(); + if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) { + float stepStart = 1 / 15.0f; + float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart; + float currentTime = walkRunAssoc->currentTime; + int stepPart = 0; - m_lastWepDam = method; - } + if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart) + stepPart = 1; + else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd) + stepPart = 2; - if (m_fHealth - healthImpact >= 1.0f && !willLinger) { - m_fHealth -= healthImpact; - return false; - } + if (stepPart != 0) { + DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f); + CVector footPos(0.0f, 0.0f, 0.0f); + TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR); - if (bInVehicle) { - if (method != WEAPONTYPE_DROWNING) { -#ifdef VC_PED_PORTS - if (m_pMyVehicle) { - if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) { - if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) { - m_pMyVehicle->SetStatus(STATUS_PHYSICS); - CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle); - } - m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT; - m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; - } - if (m_pMyVehicle->CanPedExitCar()) { - SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle); - } else { - m_fHealth = 0.0f; - if (m_pMyVehicle && m_pMyVehicle->pDriver == this) { - SetRadioStation(); - m_pMyVehicle->SetStatus(STATUS_ABANDONED); - } - SetDie(dieAnim, dieDelta, dieSpeed); - /* - if (damagedBy == FindPlayerPed() && damagedBy != this) { - // PlayerInfo stuff - } - */ - } - for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) { - CPed* passenger = m_pMyVehicle->pPassengers[i]; - if (passenger && passenger != this && damagedBy) - passenger->ReactToAttack(damagedBy); - } + CVector forward = GetForward(); + + footPos.z -= 0.1f; + footPos += 0.2f * forward; + + if (bDoBloodyFootprints) { + CVector2D top(forward * 0.26f); + CVector2D right(GetRight() * 0.14f); - CPed *driverOfVeh = m_pMyVehicle->pDriver; - if (driverOfVeh && driverOfVeh != this && damagedBy) - driverOfVeh->ReactToAttack(damagedBy); + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &footPos, + top.x, top.y, + right.x, right.y, + 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f); - if (damagedBy == FindPlayerPed() || damagedBy && damagedBy == FindPlayerVehicle()) { - CDarkel::RegisterKillByPlayer(this, method, headShot); - m_threatEntity = FindPlayerPed(); + if (m_bloodyFootprintCountOrDeathTime <= 20) { + m_bloodyFootprintCountOrDeathTime = 0; + bDoBloodyFootprints = false; } else { - CDarkel::RegisterKillNotByPlayer(this, method); + m_bloodyFootprintCountOrDeathTime -= 20; } } + if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) { + if(IsPlayer()) + particleProduceFootDust(this, footPos, 0.0f, 4); + } +#ifdef PC_PARTICLE + else if(stepPart == 2) +#else + else #endif - m_fHealth = 1.0f; - return false; + { + particleProduceFootSplash(this, footPos, 0.15f, 4); + } } - m_fHealth = 0.0f; - if (player == this) - m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED); + } - SetDie(NUM_ANIMS, 4.0f, 0.0f); - return true; - } else { - m_fHealth = 0.0f; - SetDie(dieAnim, dieDelta, dieSpeed); + if (m_nSurfaceTouched == SURFACE_WATER) { + float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude(); + if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) { +#ifdef PC_PARTICLE + float particleSize = pedSpeed * 2.0f; - if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) { + if (particleSize < 0.25f) + particleSize = 0.25f; - // There are PlayerInfo stuff here in VC - CDarkel::RegisterKillByPlayer(this, method, headShot); - m_threatEntity = player; - } else { - CDarkel::RegisterKillNotByPlayer(this, method); - } - if (method == WEAPONTYPE_DROWNING) - bIsInTheAir = false; + if (particleSize > 0.75f) + particleSize = 0.75f; - return true; - } -} + CVector particlePos = GetPosition() + GetForward() * 0.3f; + particlePos.z -= 1.2f; -void -CPed::ClearFlee(void) -{ - RestorePreviousState(); - bUsePedNodeSeek = false; - m_standardTimer = 0; - m_fleeTimer = 0; -} + CVector particleDir = m_vecMoveSpeed * -0.75f; -void -CPed::ClearFall(void) -{ - SetGetUp(); + particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f); + CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0); + + particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0); +#else + CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f; + CVector particleDir = m_vecMoveSpeed * 0.45f; + particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); + CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255)); +#endif + } + } } -void -CPed::SetGetUp(void) +// Actually GetLocalDirectionTo(Turn/Look) +int +CPed::GetLocalDirection(const CVector2D &posOffset) { - if (m_nPedState == PED_GETUP && bGetUpAnimStarted) - return; + int direction; + float angle; - if (!CanSetPedState()) - return; + for (angle = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); angle < 0.0f; angle += TWOPI); - if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) { - if (bUpdateAnimHeading) { - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - m_fRotationCur -= HALFPI; - bUpdateAnimHeading = false; - } - if (m_nPedState != PED_GETUP) { - SetStoredState(); - m_nPedState = PED_GETUP; - } - - CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity; - CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition()); - if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE || - collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE - && ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 || - CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(), - aTempPedColPts, nil, nil) > 0)) { + for (direction = RADTODEG(angle)/90.0f; direction > 3; direction -= 4); - bGetUpAnimStarted = false; - if (IsPlayer()) - InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); - else { - if (!CPad::GetPad(0)->ArePlayerControlsDisabled()) - return; + // 0-forward, 1-left, 2-backward, 3-right. + return direction; +} - InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, 0); - } - return; - } - bGetUpAnimStarted = true; - m_pCollidingEntity = nil; - bKnockedUpIntoAir = false; - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT); - if (animAssoc) { - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) { - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f); - } else { - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f); - } - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } +#ifdef NEW_WALK_AROUND_ALGORITHM +CVector +LocalPosForWalkAround(CVector2D colMin, CVector2D colMax, int walkAround, uint32 enterDoorNode, bool itsVan) { + switch (walkAround) { + case 0: + if (enterDoorNode == CAR_DOOR_LF) + return CVector(colMin.x, colMax.y - 1.0f, 0.0f); + case 1: + return CVector(colMin.x, colMax.y, 0.0f); + case 2: + case 3: + if (walkAround == 3 && enterDoorNode == CAR_DOOR_RF) + return CVector(colMax.x, colMax.y - 1.0f, 0.0f); - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f); - else - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + return CVector(colMax.x, colMax.y, 0.0f); + case 4: + if (enterDoorNode == CAR_DOOR_RR && !itsVan) + return CVector(colMax.x, colMin.y + 1.0f, 0.0f); + case 5: + return CVector(colMax.x, colMin.y, 0.0f); + case 6: + case 7: + if (walkAround == 7 && enterDoorNode == CAR_DOOR_LR && !itsVan) + return CVector(colMin.x, colMin.y + 1.0f, 0.0f); - animAssoc->SetFinishCallback(PedGetupCB,this); - } else { - m_fHealth = 0.0f; - SetDie(NUM_ANIMS, 4.0f, 0.0f); + return CVector(colMin.x, colMin.y, 0.0f); + default: + return CVector(0.0f, 0.0f, 0.0f); } } -void -CPed::ClearInvestigateEvent(void) +bool +CanWeSeeTheCorner(CVector2D dist, CVector2D fwdOffset) { - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - if (m_eventType > EVENT_EXPLOSION) - m_standardTimer = CTimer::GetTimeInMilliseconds() + 15000; + // because fov isn't important if dist is more then 5 unit, we want shortest way + if (dist.Magnitude() > 5.0f) + return true; - bGonnaInvestigateEvent = false; - m_pEventEntity = nil; - ClearLookFlag(); - RestorePreviousState(); - if(m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) - SetMoveState(PEDMOVE_WALK); + if (DotProduct2D(dist, fwdOffset) < 0.0f) + return false; + + return true; } +#endif +// This function looks completely same on VC. void -CPed::ClearLeader(void) +CPed::SetDirectionToWalkAroundObject(CEntity *obj) { - if (!m_leader) + float distLimitForTimer = 8.0f; + CColModel *objCol = CModelInfo::GetModelInfo(obj->GetModelIndex())->GetColModel(); + CVector objColMin = objCol->boundingBox.min; + CVector objColMax = objCol->boundingBox.max; + CVector objColCenter = (objColMin + objColMax) / 2.0f; + CMatrix objMat(obj->GetMatrix()); + float dirToSet = obj->GetForward().Heading(); + bool goingToEnterCarAndItsVan = false; + bool goingToEnterCar = false; + bool objUpsideDown = false; + + float checkIntervalInDist = (objColMax.y - objColMin.y) * 0.1f; + float checkIntervalInTime; + + if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) return; - m_leader = nil; - if (IsPedInControl()) { - SetObjective(OBJECTIVE_NONE); - if (CharCreatedBy == MISSION_CHAR) { - SetIdle(); - } else { - SetWanderPath(CGeneral::GetRandomNumberInRange(0,8)); - } - } else if (m_objective != OBJECTIVE_NONE) { - bClearObjective = true; +#ifndef PEDS_REPORT_CRIMES_ON_PHONE + if (CharCreatedBy != MISSION_CHAR && obj->GetModelIndex() == MI_PHONEBOOTH1) { + bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; + SetFindPathAndFlee(obj, 5000, !isRunning); + return; } -} +#endif -void -CPed::ClearLook(void) -{ - RestorePreviousState(); - ClearLookFlag(); -} + CVector2D adjustedColMin(objColMin.x - 0.35f, objColMin.y - 0.35f); + CVector2D adjustedColMax(objColMax.x + 0.35f, objColMax.y + 0.35f); -void -CPed::ClearObjective(void) -{ - if (IsPedInControl() || m_nPedState == PED_DRIVING) { - m_objective = OBJECTIVE_NONE; -#ifdef VC_PED_PORTS - m_pedInObjective = nil; - m_carInObjective = nil; -#endif - if (m_nPedState == PED_DRIVING && m_pMyVehicle) { + checkIntervalInDist = Max(checkIntervalInDist, 0.5f); + checkIntervalInDist = Min(checkIntervalInDist, (objColMax.z - objColMin.z) / 2.0f); + checkIntervalInDist = Min(checkIntervalInDist, (adjustedColMax.x - adjustedColMin.x) / 2.0f); - if (m_pMyVehicle->pDriver != this) { -#if defined VC_PED_PORTS || defined FIX_BUGS - if(!IsPlayer()) -#endif - bWanderPathAfterExitingCar = true; + if (objMat.GetUp().z < 0.0f) + objUpsideDown = true; - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } -#ifdef VC_PED_PORTS - m_nLastPedState = PED_NONE; -#endif + if (obj->GetModelIndex() != MI_TRAFFICLIGHTS && obj->GetModelIndex() != MI_SINGLESTREETLIGHTS1 && obj->GetModelIndex() != MI_SINGLESTREETLIGHTS2) { + objColCenter = obj->GetMatrix() * objColCenter; + } else { + checkIntervalInDist = 0.4f; + if (objMat.GetUp().z <= 0.57f) { + + // Specific calculations for traffic lights, didn't get a bit. + adjustedColMin.x = 1.2f * (adjustedColMin.x < adjustedColMin.y ? adjustedColMin.x : adjustedColMin.y); + adjustedColMax.x = 1.2f * (adjustedColMax.x > adjustedColMax.y ? adjustedColMax.x : adjustedColMax.y); + adjustedColMin.y = 1.2f * objColMin.z; + adjustedColMax.y = 1.2f * objColMax.z; + dirToSet = objMat.GetUp().Heading(); + objMat.SetUnity(); + objMat.RotateZ(dirToSet); + objMat.GetPosition() += obj->GetPosition(); + objColCenter = obj->GetPosition(); } else { - SetIdle(); - SetMoveState(PEDMOVE_STILL); + objColCenter.x = adjustedColMax.x - 0.25f; + objColCenter = obj->GetMatrix() * objColCenter; + distLimitForTimer = 0.75f; } - } else { - bClearObjective = true; + objUpsideDown = false; } -} + float oldRotDest = m_fRotationDest; +#ifndef NEW_WALK_AROUND_ALGORITHM + float angleToFaceObjCenter = (objColCenter - GetPosition()).Heading(); + float angleDiffBtwObjCenterAndForward = CGeneral::LimitRadianAngle(dirToSet - angleToFaceObjCenter); + float objTopRightHeading = Atan2(adjustedColMax.x - adjustedColMin.x, adjustedColMax.y - adjustedColMin.y); +#endif -void -CPed::ClearPause(void) -{ - RestorePreviousState(); -} + if (IsPlayer()) { + if (FindPlayerPed()->m_fMoveSpeed <= 0.0f) + checkIntervalInTime = 0.0f; + else + checkIntervalInTime = 2.0f / FindPlayerPed()->m_fMoveSpeed; + } else { + switch (m_nMoveState) { + case PEDMOVE_WALK: + checkIntervalInTime = 2.0f; + break; + case PEDMOVE_RUN: + checkIntervalInTime = 0.5f; + break; + case PEDMOVE_SPRINT: + checkIntervalInTime = 0.5f; + break; + default: + checkIntervalInTime = 0.0f; + break; + } + } + if (m_pSeekTarget == obj && obj->IsVehicle()) { + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER + || m_objective == OBJECTIVE_SOLICIT_VEHICLE) { + goingToEnterCar = true; + if (IsPlayer()) + checkIntervalInTime = 0.0f; -void -CPed::ClearSeek(void) -{ - SetIdle(); - bRunningToPhone = false; -} + if (((CVehicle*)obj)->bIsVan) + goingToEnterCarAndItsVan = true; + } + } -bool -CPed::SetWanderPath(int8 pathStateDest) -{ - uint8 nextPathState; + int entityOnTopLeftOfObj = 0; + int entityOnBottomLeftOfObj = 0; + int entityOnTopRightOfObj = 0; + int entityOnBottomRightOfObj = 0; - if (IsPedInControl()) { - if (bKindaStayInSamePlace) { - SetIdle(); - return false; - } else { - m_nPathDir = pathStateDest; - if (pathStateDest == 0) - pathStateDest = CGeneral::GetRandomNumberInRange(1, 7); + if (CTimer::GetTimeInMilliseconds() > m_collidingThingTimer || m_collidingEntityWhileFleeing != obj) { + bool collidingThingChanged = true; + CEntity *obstacle; - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, - m_nPathDir, &nextPathState); +#ifndef NEW_WALK_AROUND_ALGORITHM + if (!obj->IsVehicle() || objUpsideDown) { + collidingThingChanged = false; + } else { +#else + CVector cornerToGo = CVector(10.0f, 10.0f, 10.0f); + int dirToGo; + m_walkAroundType = 0; + int iWouldPreferGoingBack = 0; // 1:left 2:right +#endif + float adjustedCheckInterval = 0.7f * checkIntervalInDist; + CVector posToCheck; - // Circular loop until we find a node for current m_nPathDir - while (!m_pNextPathNode) { - m_nPathDir = (m_nPathDir+1) % 8; - - // We're at where we started and couldn't find any node - if (m_nPathDir == pathStateDest) { - ClearAll(); - SetIdle(); - return false; + // Top left of obj + posToCheck.x = adjustedColMin.x + adjustedCheckInterval; + posToCheck.y = adjustedColMax.y - adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnTopLeftOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnTopLeftOfObj = 2; + } else { + entityOnTopLeftOfObj = 3; } - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, - m_nPathDir, &nextPathState); } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector tl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMax.y, 0.0f) - GetPosition(); + if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { + cornerToGo = tl; + m_walkAroundType = 1; - // We did it, save next path state and return true - m_nPathDir = nextPathState; - m_nPedState = PED_WANDER_PATH; - SetMoveState(PEDMOVE_WALK); - bIsRunning = false; - return true; - } - } else { - m_nPathDir = pathStateDest; - bStartWanderPathOnFoot = true; - return false; - } -} - -void -CPed::ClearWeapons(void) -{ - CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - RemoveWeaponModel(currentWeapon->m_nModelId); - - m_maxWeaponTypeAllowed = WEAPONTYPE_BASEBALLBAT; - m_currentWeapon = WEAPONTYPE_UNARMED; - - currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - AddWeaponModel(currentWeapon->m_nModelId); - for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { - CWeapon &weapon = GetWeapon(i); - weapon.m_eWeaponType = WEAPONTYPE_UNARMED; - weapon.m_eWeaponState = WEAPONSTATE_READY; - weapon.m_nAmmoInClip = 0; - weapon.m_nAmmoTotal = 0; - weapon.m_nTimer = 0; - } -} - -void -CPed::RestoreGunPosition(void) -{ - if (bIsLooking) { - m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; - bIsRestoringGun = false; - } else if (m_pedIK.RestoreGunPosn()) { - bIsRestoringGun = false; - } else { - if (IsPlayer()) - ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f; - } -} - -void -CPed::RestoreHeadingRate(void) -{ - m_headingRate = m_pedStats->m_headingChangeRate; -} - -void -CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) -{ - ((CPed*)arg)->m_headingRate = ((CPed*)arg)->m_pedStats->m_headingChangeRate; -} + if (m_vehEnterType == CAR_DOOR_LR) + iWouldPreferGoingBack = 1; + } else if(CanWeSeeTheCorner(tl, GetForward())){ + cornerToGo = tl; + dirToGo = GetLocalDirection(tl); + if (dirToGo == 1) + m_walkAroundType = 0; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 1; // ALL of the next turns will be left turn + } + } +#endif -void -CPed::RestorePreviousState(void) -{ - if(!CanSetPedState() || m_nPedState == PED_FALL) - return; + // Top right of obj + posToCheck.x = adjustedColMax.x - adjustedCheckInterval; + posToCheck.y = adjustedColMax.y - adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnTopRightOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnTopRightOfObj = 2; + } else { + entityOnTopRightOfObj = 3; + } + } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector tr = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMax.y, 0.0f) - GetPosition(); + if (tr.Magnitude2D() < cornerToGo.Magnitude2D()) { + if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { + cornerToGo = tr; + m_walkAroundType = 2; - if (m_nPedState == PED_GETUP && !bGetUpAnimStarted) - return; + if (m_vehEnterType == CAR_DOOR_RR) + iWouldPreferGoingBack = 2; + } else if (CanWeSeeTheCorner(tr, GetForward())) { + cornerToGo = tr; + dirToGo = GetLocalDirection(tr); + if (dirToGo == 1) + m_walkAroundType = 2; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 3; // ALL of the next turns will be left turn + } + } + } +#endif - if (InVehicle()) { - m_nPedState = PED_DRIVING; - m_nLastPedState = PED_NONE; - } else { - if (m_nLastPedState == PED_NONE) { - if (!IsPlayer() && CharCreatedBy != MISSION_CHAR && m_objective == OBJECTIVE_NONE) { - if (SetWanderPath(CGeneral::GetRandomNumber() & 7) != 0) - return; + // Bottom right of obj + posToCheck.x = adjustedColMax.x - adjustedCheckInterval; + posToCheck.y = adjustedColMin.y + adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnBottomRightOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnBottomRightOfObj = 2; + } else { + entityOnBottomRightOfObj = 3; + } } - SetIdle(); - return; - } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector br = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMin.y, 0.0f) - GetPosition(); + if (iWouldPreferGoingBack == 2) + m_walkAroundType = 4; + else if (br.Magnitude2D() < cornerToGo.Magnitude2D()) { + if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { + cornerToGo = br; + m_walkAroundType = 5; + } else if (CanWeSeeTheCorner(br, GetForward())) { + cornerToGo = br; + dirToGo = GetLocalDirection(br); + if (dirToGo == 1) + m_walkAroundType = 4; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 5; // ALL of the next turns will be left turn + } + } + } +#endif - switch (m_nLastPedState) { - case PED_IDLE: - SetIdle(); - break; - case PED_WANDER_PATH: - m_nPedState = PED_WANDER_PATH; - bIsRunning = false; - if (bFindNewNodeAfterStateRestore) { - if (m_pNextPathNode) { - CVector diff = m_pNextPathNode->GetPosition() - GetPosition(); - if (diff.MagnitudeSqr() < sq(7.0f)) { - SetMoveState(PEDMOVE_WALK); - break; - } + // Bottom left of obj + posToCheck.x = adjustedColMin.x + adjustedCheckInterval; + posToCheck.y = adjustedColMin.y + adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnBottomLeftOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnBottomLeftOfObj = 2; + } else { + entityOnBottomLeftOfObj = 3; + } + } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector bl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMin.y, 0.0f) - GetPosition(); + if (iWouldPreferGoingBack == 1) + m_walkAroundType = 7; + else if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) { + if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { + cornerToGo = bl; + m_walkAroundType = 6; + } else if (CanWeSeeTheCorner(bl, GetForward())) { + cornerToGo = bl; + dirToGo = GetLocalDirection(bl); + if (dirToGo == 1) + m_walkAroundType = 6; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 7; // ALL of the next turns will be left turn } } - SetWanderPath(CGeneral::GetRandomNumber() & 7); - break; - default: - m_nPedState = m_nLastPedState; - SetMoveState((eMoveState) m_nPrevMoveState); - break; + } +#else } - m_nLastPedState = PED_NONE; - } -} -void -CPed::SetAimFlag(CEntity *to) -{ - bIsAimingGun = true; - bIsRestoringGun = false; - m_pLookTarget = to; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - m_pSeekTarget = to; - m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); - m_lookTimer = 0; -} - -void -CPed::SetAimFlag(float angle) -{ - bIsAimingGun = true; - bIsRestoringGun = false; - m_fLookDirection = angle; - m_lookTimer = 0; - m_pLookTarget = nil; - m_pSeekTarget = nil; - if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm) - m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM; - else - m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; -} - -void -CPed::SetPointGunAt(CEntity *to) -{ - if (to) { - SetLookFlag(to, true); - SetAimFlag(to); -#ifdef VC_PED_PORTS - SetLookTimer(INT32_MAX); -#endif - } - - if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK) - return; - - if (m_nPedState != PED_ATTACK) - SetStoredState(); - - m_nPedState = PED_AIM_GUN; - bIsPointingGunAt = true; - CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - SetMoveState(PEDMOVE_NONE); - - CAnimBlendAssociation *aimAssoc; - - if (bCrouchWhenShooting) - aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay); - else - aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay); - - if (!aimAssoc || aimAssoc->blendDelta < 0.0f) { - if (bCrouchWhenShooting) - aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f); - else - aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay); - - aimAssoc->blendAmount = 0.0f; - aimAssoc->blendDelta = 8.0f; - } - if (to) - Say(SOUND_PED_ATTACK); -} - -void -CPed::SetAmmo(eWeaponType weaponType, uint32 ammo) -{ - if (HasWeapon(weaponType)) { - GetWeapon(weaponType).m_nAmmoTotal = ammo; - } else { - GetWeapon(weaponType).Initialise(weaponType, ammo); - m_maxWeaponTypeAllowed++; - } -} - -void -CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo) -{ - if (HasWeapon(weaponType)) { - GetWeapon(weaponType).m_nAmmoTotal += ammo; - } else { - GetWeapon(weaponType).Initialise(weaponType, ammo); - m_maxWeaponTypeAllowed++; - } -} - -void -CPed::SetEvasiveStep(CEntity *reason, uint8 animType) -{ - AnimationId stepAnim; - - if (m_nPedState == PED_STEP_AWAY || !IsPedInControl() || ((IsPlayer() || !bRespondsToThreats) && animType == 0)) - return; - - float angleToFace = CGeneral::GetRadianAngleBetweenPoints( - reason->GetPosition().x, reason->GetPosition().y, - GetPosition().x, GetPosition().y); - angleToFace = CGeneral::LimitRadianAngle(angleToFace); - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - float neededTurn = Abs(angleToFace - m_fRotationCur); - bool vehPressedHorn = false; - - if (neededTurn > PI) - neededTurn = TWOPI - neededTurn; - - CVehicle *veh = (CVehicle*)reason; - if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR) { - if (veh->m_nCarHornTimer != 0) { - vehPressedHorn = true; - if (!IsPlayer()) - animType = 1; - } - } - if (neededTurn <= DEGTORAD(90.0f) || veh->GetModelIndex() == MI_RCBANDIT || vehPressedHorn || animType != 0) { - SetLookFlag(veh, true); - if ((CGeneral::GetRandomNumber() & 1) && veh->GetModelIndex() != MI_RCBANDIT && animType == 0) { - stepAnim = ANIM_IDLE_TAXI; - } else { - - float vehDirection = CGeneral::GetRadianAngleBetweenPoints( - veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, - 0.0f, 0.0f); - - // Let's turn our back to the "reason" - angleToFace += PI; - - if (angleToFace > PI) - angleToFace -= TWOPI; - - // We don't want to run towards car's direction - float dangerZone = angleToFace - vehDirection; - dangerZone = CGeneral::LimitRadianAngle(dangerZone); - - // So, add or subtract 90deg (jump to left/right) according to that - if (dangerZone > 0.0f) - angleToFace = vehDirection - HALFPI; - else - angleToFace = vehDirection + HALFPI; - - stepAnim = NUM_ANIMS; - if (animType == 0 || animType == 1) - stepAnim = ANIM_EV_STEP; - else if (animType == 2) - stepAnim = ANIM_HANDSCOWER; - } - if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) { - CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f); - stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT; - stepAssoc->SetFinishCallback(PedEvadeCB, this); - - if (animType == 0) - Say(SOUND_PED_EVADE); - - m_fRotationCur = CGeneral::LimitRadianAngle(angleToFace); - ClearAimFlag(); - SetStoredState(); - m_nPedState = PED_STEP_AWAY; - } - } -} - -void -CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump) -{ - if (!IsPedInControl() || !bRespondsToThreats) - return; - - CAnimBlendAssociation *animAssoc; - float angleToFace, neededTurn; - bool handsUp = false; - - angleToFace = m_fRotationCur; - CVehicle *veh = (CVehicle*) reason; - if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) { - onlyRandomJump = true; - } - - if (onlyRandomJump) { - if (reason) { - // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly. - // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots. - - float vehDirection = CGeneral::GetRadianAngleBetweenPoints( - veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, - 0.0f, 0.0f); - angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection; - angleToFace = CGeneral::LimitRadianAngle(angleToFace); - } - } else { - if (IsPlayer()) { - ((CPlayerPed*)this)->m_nEvadeAmount = 5; - ((CPlayerPed*)this)->m_pEvadingFrom = reason; - reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom); - return; - } - - angleToFace = CGeneral::GetRadianAngleBetweenPoints( - reason->GetPosition().x, reason->GetPosition().y, - GetPosition().x, GetPosition().y); - angleToFace = CGeneral::LimitRadianAngle(angleToFace); - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - - // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted -#ifdef FIX_BUGS - float vehDirection = CGeneral::GetRadianAngleBetweenPoints( - veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, - 0.0f, 0.0f); - - // Let's turn our back to the "reason" - angleToFace += PI; - - if (angleToFace > PI) - angleToFace -= 2 * PI; - - // We don't want to dive towards car's direction - float dangerZone = angleToFace - vehDirection; - dangerZone = CGeneral::LimitRadianAngle(dangerZone); - - // So, add or subtract 90deg (jump to left/right) according to that - if (dangerZone > 0.0f) - angleToFace = 0.5f * PI + vehDirection; - else - angleToFace = vehDirection - 0.5f * PI; -#endif - - neededTurn = Abs(angleToFace - m_fRotationCur); - - if (neededTurn > PI) - neededTurn = 2 * PI - neededTurn; - - if (neededTurn <= 0.5f*PI) { - if (CGeneral::GetRandomNumber() & 1) - handsUp = true; - } else { - if (CGeneral::GetRandomNumber() & 7) - return; - } - Say(SOUND_PED_EVADE); - } - - if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) { - m_fRotationCur = angleToFace; - ClearLookFlag(); - ClearAimFlag(); - SetLookFlag(reason, true); - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP); - if (animAssoc) - return; - - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f); - animAssoc->flags &= ~ASSOC_DELETEFADEDOUT; - animAssoc->SetFinishCallback(PedEvadeCB, this); - SetStoredState(); - m_nPedState = PED_STEP_AWAY; - } else { - m_fRotationCur = angleToFace; - ClearLookFlag(); - ClearAimFlag(); - SetStoredState(); - m_nPedState = PED_DIVE_AWAY; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f); - animAssoc->SetFinishCallback(PedEvadeCB, this); - } - - if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) { - if (veh->pDriver && veh->pDriver->IsPlayer()) { - CWanted *wanted = FindPlayerPed()->m_pWanted; - wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false); - wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false); - } - } -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - else if (reason->IsVehicle()) { - if (veh->pDriver && veh->pDriver->IsPlayer()) { - CWanted* wanted = FindPlayerPed()->m_pWanted; - wanted->RegisterCrime(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false); - } - } -#endif -} - -void -CPed::SetAttack(CEntity *victim) -{ - CPed *victimPed = nil; - if (victim && victim->IsPed()) - victimPed = (CPed*)victim; - - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED); - if (animAssoc) { - animAssoc->blendDelta = -1000.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - - if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE) - return; - - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HGUN_RELOAD)) { - bIsAttacking = false; - return; - } - - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) { - if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected) - bIsAttacking = false; - else - bIsAttacking = true; - - return; - } - - CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - if (curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && !IsPlayer()) { - if (GetWeapon()->HitsGround(this, nil, victim)) - return; - } - - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { - if (IsPlayer() || - (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) { - - if (m_nPedState != PED_ATTACK) { - m_nPedState = PED_ATTACK; - bIsAttacking = false; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f); - animAssoc->SetRun(); - if (animAssoc->currentTime == animAssoc->hierarchy->totalLength) - animAssoc->SetCurrentTime(0.0f); - - animAssoc->SetFinishCallback(FinishedAttackCB, this); - } - } else { - StartFightAttack(CGeneral::GetRandomNumber() % 256); - } - return; - } - - m_pSeekTarget = victim; - if (m_pSeekTarget) - m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); - - if (curWeapon->m_bCanAim) { - CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition(); - CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false); - if (obstacle) - return; - - m_pLookTarget = victim; - if (victim) { - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); - } - if (m_pLookTarget) { - SetAimFlag(m_pLookTarget); - } else { - SetAimFlag(m_fRotationCur); - - if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam()) - ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch(); - } - } - if (m_nPedState == PED_ATTACK) { - bIsAttacking = true; - return; - } - - if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) { - if (IsPlayer()) - CPad::GetPad(0)->ResetAverageWeapon(); - - PointBlankNecessity pointBlankStatus; - if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER) - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER - && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT - && (pointBlankStatus = CheckForPointBlankPeds(victimPed)) != NO_POINT_BLANK_PED) { - ClearAimFlag(); - - // This condition is pointless - if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed) - StartFightAttack(200); - } else { - if (!curWeapon->m_bCanAim) - m_pSeekTarget = nil; - - if (m_nPedState != PED_AIM_GUN) - SetStoredState(); - - m_nPedState = PED_ATTACK; - SetMoveState(PEDMOVE_NONE); - if (bCrouchWhenShooting) { - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); - } else { - float animDelta = 8.0f; - if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE) - animDelta = 1000.0f; - - if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT - || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta); - } else { - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta); - } - } - - animAssoc->SetRun(); - if (animAssoc->currentTime == animAssoc->hierarchy->totalLength) - animAssoc->SetCurrentTime(0.0f); - - animAssoc->SetFinishCallback(FinishedAttackCB, this); - } - return; - } - - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP) - SetWaitState(WAITSTATE_SURPRISE, nil); - - SetLookFlag(victim, false); - SetLookTimer(100); -} - -void -CPed::StartFightAttack(uint8 buttonPressure) -{ - if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds()) - return; - - if (m_nPedState == PED_FIGHT) { - m_fightButtonPressure = buttonPressure; - return; - } - - if (m_nPedState != PED_AIM_GUN) - SetStoredState(); - - if (m_nWaitState != WAITSTATE_FALSE) { - m_nWaitState = WAITSTATE_FALSE; - RestoreHeadingRate(); - } - - m_nPedState = PED_FIGHT; - m_fightButtonPressure = 0; - RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); - - if (animAssoc) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->blendDelta = -1000.0f; - } - - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); - - if (animAssoc) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->blendDelta = -1000.0f; - RestoreHeadingRate(); - } - - SetMoveState(PEDMOVE_NONE); - m_nStoredMoveState = PEDMOVE_NONE; - - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f; - - CPed *pedOnGround = nil; - if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) { - m_curFightMove = FIGHTMOVE_GROUNDKICK; - } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) { - m_curFightMove = FIGHTMOVE_ROUNDHOUSE; - } else { - m_curFightMove = FIGHTMOVE_STDPUNCH; - } - - if (pedOnGround && IsPlayer()) { - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - pedOnGround->GetPosition().x, pedOnGround->GetPosition().y, - GetPosition().x, GetPosition().y); - - m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); - m_fRotationCur = m_fRotationDest; - m_lookTimer = 0; - SetLookFlag(pedOnGround, true); - SetLookTimer(1500); - } - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); - animAssoc->SetFinishCallback(FinishFightMoveCB, this); - m_fightState = FIGHTSTATE_NO_MOVE; - m_takeAStepAfterAttack = false; - bIsAttacking = true; - - if (IsPlayer()) - nPlayerInComboMove = 0; -} - -void -CPed::LoadFightData(void) -{ - float startFireTime, endFireTime, comboFollowOnTime, strikeRadius; - int damage, flags; - char line[256], moveName[32], animName[32], hitLevel; - int moveId = 0; - - CAnimBlendAssociation *animAssoc; - - size_t bp, buflen; - int lp, linelen; - - buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r"); - - for (bp = 0; bp < buflen; ) { - // read file line by line - for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) { - line[linelen++] = work_buff[bp]; - } - bp++; - line[linelen] = '\0'; - - // skip white space - for (lp = 0; line[lp] <= ' ' && line[lp] != '\0'; lp++); - - if (line[lp] == '\0' || - line[lp] == '#') - continue; - - sscanf( - &line[lp], - "%s %f %f %f %f %c %s %d %d", - moveName, - &startFireTime, - &endFireTime, - &comboFollowOnTime, - &strikeRadius, - &hitLevel, - animName, - &damage, - &flags); - - if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0) - return; - - tFightMoves[moveId].startFireTime = startFireTime / 30.0f; - tFightMoves[moveId].endFireTime = endFireTime / 30.0f; - tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f; - tFightMoves[moveId].strikeRadius = strikeRadius; - tFightMoves[moveId].damage = damage; - tFightMoves[moveId].flags = flags; - - switch (hitLevel) { - case 'G': - tFightMoves[moveId].hitLevel = HITLEVEL_GROUND; - break; - case 'H': - tFightMoves[moveId].hitLevel = HITLEVEL_HIGH; - break; - case 'L': - tFightMoves[moveId].hitLevel = HITLEVEL_LOW; - break; - case 'M': - tFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM; - break; - case 'N': - tFightMoves[moveId].hitLevel = HITLEVEL_NULL; - break; - default: - break; - } - - if (strncmp(animName, "null", 4) != 0) { - animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName); - tFightMoves[moveId].animId = (AnimationId)animAssoc->animId; - } else { - tFightMoves[moveId].animId = ANIM_WALK; - } - moveId++; - } -} - -// Actually GetLocalDirectionTo(Turn/Look) -int -CPed::GetLocalDirection(const CVector2D &posOffset) -{ - int direction; - float angle; - - for (angle = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); angle < 0.0f; angle += TWOPI); - - for (direction = RADTODEG(angle)/90.0f; direction > 3; direction -= 4); - - // 0-forward, 1-left, 2-backward, 3-right. - return direction; -} - -bool -CPed::FightStrike(CVector &touchedNodePos) -{ - CColModel *ourCol; - CVector attackDistance; - ePedPieceTypes closestPedPiece = PEDPIECE_TORSO; - float maxDistanceToBeBeaten; - CPed *nearPed; - int state = m_fightState; - bool pedFound = false; - - if (state == FIGHTSTATE_JUST_ATTACKED) - return false; - - // Pointless code - if (state > FIGHTSTATE_NO_MOVE) - attackDistance = touchedNodePos - m_vecHitLastPos; - - for (int i = 0; i < m_numNearPeds; i++) { - nearPed = m_nearPeds[i]; - if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) - maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f; - else - maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius; - - if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) { - CVector nearPedCentre; - nearPed->GetBoundCentre(nearPedCentre); - CVector potentialAttackDistance = nearPedCentre - touchedNodePos; - - // He can beat us - if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) { - -#ifdef PED_SKIN - // Have to animate a skinned clump because the initial col model is useless - if(IsClumpSkinned(GetClump())) - ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump()); - else -#endif - if (nearPed->OnGround() || !nearPed->IsPedHeadAbovePos(-0.3f)) { - ourCol = &CTempColModels::ms_colModelPedGroundHit; - } else { -#ifdef ANIMATE_PED_COL_MODEL - ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->GetHitColModel(), - RpClumpGetFrame(GetClump())); -#else - ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel(); -#endif - } - - for (int j = 0; j < ourCol->numSpheres; j++) { - attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center; - attackDistance -= touchedNodePos; - CColSphere *ourPieces = ourCol->spheres; - float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius; - - // We can beat him too - if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) { - pedFound = true; - closestPedPiece = (ePedPieceTypes) ourPieces[j].piece; - break; - } - } - } - } - if (pedFound) - break; - } - - if (pedFound) { - if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP) - return false; - - float oldVictimHealth = nearPed->m_fHealth; - CVector bloodPos = 0.5f * attackDistance + touchedNodePos; - int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1; - - CVector2D diff (GetPosition() - nearPed->GetPosition()); - int direction = nearPed->GetLocalDirection(diff); - if (IsPlayer()) { - if (((CPlayerPed*)this)->m_bAdrenalineActive) - damageMult = 20; - } else { - damageMult *= m_pedStats->m_attackStrength; - } - - // Change direction if we used kick. - if (m_curFightMove == FIGHTMOVE_KICK) { - if (CGeneral::GetRandomNumber() & 1) { - direction++; - if (direction > 3) - direction -= 4; - } - } - nearPed->ReactToAttack(this); - - // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it. - int unk2; - if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer()) - unk2 = 101; - else - unk2 = damageMult; - - nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2); - PlayHitSound(nearPed); - m_fightState = FIGHTSTATE_JUST_ATTACKED; - RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f; - if (!nearPed->DyingOrDead()) { - nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction); - } - - if (CGame::nastyGame - && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM - && nearPed->m_nPedState == PED_DIE - && nearPed->GetIsOnScreen()) { - - // Just for blood particle. We will restore it below. - attackDistance /= (10.0f * attackDistance.Magnitude()); - for(int i=0; i<4; i++) { - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0); - } - } - if (!nearPed->OnGround()) { - float curVictimHealth = nearPed->m_fHealth; - if (curVictimHealth > 0.0f - && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer() - || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f - || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer() - || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) { - - nearPed->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0); - if (nearPed->m_nPedState == PED_FALL) - nearPed->bIsStanding = false; - } - } - if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) { - attackDistance = nearPed->GetPosition() - GetPosition(); - attackDistance.Normalise(); - attackDistance.z = 1.0f; - nearPed->bIsStanding = false; - - float moveMult; - if (m_curFightMove == FIGHTMOVE_GROUNDKICK) { - moveMult = Min(damageMult * 0.6f, 4.0f); - } else { - if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) { - moveMult = damageMult; - } else { - moveMult = Min(damageMult * 2.0f, 14.0f); - } - } - - nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance); - } - CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000); - } - - if (m_fightState == FIGHTSTATE_NO_MOVE) - m_fightState = FIGHTSTATE_1; - - m_vecHitLastPos = *touchedNodePos; - return false; -} - -void -CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl) -{ - if (!IsPedInControl() && (!evenIfNotInControl || DyingOrDead())) - return; - - ClearLookFlag(); - ClearAimFlag(); - SetStoredState(); - m_nPedState = PED_FALL; - CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId); - - if (fallAssoc) { - fallAssoc->SetCurrentTime(0.0f); - fallAssoc->blendAmount = 0.0f; - fallAssoc->blendDelta = 8.0f; - fallAssoc->SetRun(); - } else { - fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f); - } - - if (extraTime == -1) { - m_getUpTimer = UINT32_MAX; - } else if (fallAssoc) { - if (IsPlayer()) { - m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength - + CTimer::GetTimeInMilliseconds() - + 500.0f; - } else { - m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength - + CTimer::GetTimeInMilliseconds() - + extraTime - + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000); - } - } else { - m_getUpTimer = extraTime - + CTimer::GetTimeInMilliseconds() - + 1000 - + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000); - } - bFallenDown = true; -} - -void -CPed::SetFlee(CEntity *fleeFrom, int time) -{ - if (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom) - return; - - SetStoredState(); - m_nPedState = PED_FLEE_ENTITY; - bUsePedNodeSeek = true; - SetMoveState(PEDMOVE_RUN); - m_fleeFrom = fleeFrom; - m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom); - - if (time <= 0) - m_fleeTimer = 0; - else - m_fleeTimer = CTimer::GetTimeInMilliseconds() + time; - - float angleToFace = CGeneral::GetRadianAngleBetweenPoints( - GetPosition().x, GetPosition().y, - fleeFrom->GetPosition().x, fleeFrom->GetPosition().y); - - m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace); - if (m_fRotationCur - PI > m_fRotationDest) { - m_fRotationDest += 2 * PI; - } else if (PI + m_fRotationCur < m_fRotationDest) { - m_fRotationDest -= 2 * PI; - } -} - -void -CPed::SetFlee(CVector2D const &from, int time) -{ - if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace) - return; - - if (m_nPedState != PED_FLEE_ENTITY) { - SetStoredState(); - m_nPedState = PED_FLEE_POS; - SetMoveState(PEDMOVE_RUN); - m_fleeFromPosX = from.x; - m_fleeFromPosY = from.y; - } - - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - m_fleeTimer = CTimer::GetTimeInMilliseconds() + time; - - float angleToFace = CGeneral::GetRadianAngleBetweenPoints( - GetPosition().x, GetPosition().y, - from.x, from.y); - - m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace); - if (m_fRotationCur - PI > m_fRotationDest) { - m_fRotationDest += 2 * PI; - } else if (PI + m_fRotationCur < m_fRotationDest) { - m_fRotationDest -= 2 * PI; - } -} - -void -CPed::SetWaitState(eWaitState state, void *time) -{ - AnimationId waitAnim = NUM_ANIMS; - CAnimBlendAssociation *animAssoc; - - if (!IsPedInControl()) - return; - - if (state != m_nWaitState) - FinishedWaitCB(nil, this); - - switch (state) { - case WAITSTATE_TRAFFIC_LIGHTS: - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500; - SetMoveState(PEDMOVE_STILL); - break; - case WAITSTATE_CROSS_ROAD: - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 1000; - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f); - break; - case WAITSTATE_CROSS_ROAD_LOOK: - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 8.0f); - - if (time) - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; - else - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000,5000); - - break; - case WAITSTATE_LOOK_PED: - case WAITSTATE_LOOK_SHOP: - case WAITSTATE_LOOK_ACCIDENT: - case WAITSTATE_FACEOFF_GANG: - break; - case WAITSTATE_DOUBLEBACK: - m_headingRate = 0.0f; - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3500; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f); -#ifdef FIX_BUGS - animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); -#endif - break; - case WAITSTATE_HITWALL: - m_headingRate = 2.0f; - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 16.0f); - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->flags |= ASSOC_FADEOUTWHENDONE; - animAssoc->SetDeleteCallback(FinishedWaitCB, this); - - if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) { - ClearObjective(); - RestorePreviousState(); - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000; - } - break; - case WAITSTATE_TURN180: - m_headingRate = 0.0f; - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TURN_180, 4.0f); - animAssoc->SetFinishCallback(FinishedWaitCB, this); - animAssoc->SetDeleteCallback(RestoreHeadingRateCB, this); - break; - case WAITSTATE_SURPRISE: - m_headingRate = 0.0f; - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 4.0f); - animAssoc->SetFinishCallback(FinishedWaitCB, this); - break; - case WAITSTATE_STUCK: - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); - m_headingRate = 0.0f; - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f); -#ifdef FIX_BUGS - animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); -#endif - - if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) { - ClearObjective(); - RestorePreviousState(); - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000; - } - break; - case WAITSTATE_LOOK_ABOUT: - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); - m_headingRate = 0.0f; - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f); -#ifdef FIX_BUGS - animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); -#endif - - break; - case WAITSTATE_PLAYANIM_COWER: - waitAnim = ANIM_HANDSCOWER; - case WAITSTATE_PLAYANIM_HANDSUP: - if (waitAnim == NUM_ANIMS) - waitAnim = ANIM_HANDSUP; - case WAITSTATE_PLAYANIM_HANDSCOWER: - if (waitAnim == NUM_ANIMS) - waitAnim = ANIM_HANDSCOWER; - m_headingRate = 0.0f; - if (time) - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; - else - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000; - - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f); - animAssoc->SetDeleteCallback(FinishedWaitCB, this); - break; - case WAITSTATE_PLAYANIM_DUCK: - waitAnim = ANIM_DUCK_DOWN; - case WAITSTATE_PLAYANIM_TAXI: - if (waitAnim == NUM_ANIMS) - waitAnim = ANIM_IDLE_TAXI; - case WAITSTATE_PLAYANIM_CHAT: - if (waitAnim == NUM_ANIMS) - waitAnim = ANIM_IDLE_CHAT; - if (time) - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; - else - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000; - - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f); - animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->SetDeleteCallback(FinishedWaitCB, this); - break; - case WAITSTATE_FINISH_FLEE: - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); - m_headingRate = 0.0f; - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f); -#ifdef FIX_BUGS - animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); -#endif - break; - default: - m_nWaitState = WAITSTATE_FALSE; - RestoreHeadingRate(); - return; - } - m_nWaitState = state; -} - - -void -CPed::PlayHitSound(CPed *hitTo) -{ - // That was very complicated to reverse for me... - // First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10). - enum { - S33 = SOUND_FIGHT_PUNCH_33, - S34 = SOUND_FIGHT_KICK_34, - S35 = SOUND_FIGHT_HEADBUTT_35, - S36 = SOUND_FIGHT_PUNCH_36, - S37 = SOUND_FIGHT_PUNCH_37, - S38 = SOUND_FIGHT_CLOSE_PUNCH_38, - S39 = SOUND_FIGHT_PUNCH_39, - S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 , - S41 = SOUND_FIGHT_PUNCH_41, - S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42, - S43 = SOUND_FIGHT_KNEE_OR_KICK_43, - S44 = SOUND_FIGHT_KICK_44, - NO_SND = SOUND_NO_SOUND - }; - uint16 hitSoundsByFightMoves[12][10] = { - {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42}, - {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND}, - {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND}, - {S39,S39,S39,S39,S33,S43,S39,S39,S39,S39}, - {S39,S39,S39,S39,S35,S39,S38,S38,S39,S39}, - {S39,S39,S39,S39,S33,S39,S41,S36,S39,S39}, - {S39,S39,S39,S39,S37,S40,S38,S38,S39,S39}, - {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39}, - {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39}, - {S39,S39,S39,S39,S34,S43,S44,S37,S39,S40}, - {S39,S39,S39,S39,S33,S39,S41,S37,S39,S40}, - {S39,S39,S39,S39,S39,S39,S39,S39,S33,S33} - }; - - // This is why first dimension is between FightMove 1 and 12. - if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT) - return; - - uint16 soundId; - - // And this is why second dimension is between 13 and 22. - if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) { - soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT]; - - } else { - if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) { - soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT]; - } else { - soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT]; - } - } - - if (soundId != NO_SND) - DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f); -} - -void -CPed::CollideWithPed(CPed *collideWith) -{ - CAnimBlendAssociation *animAssoc; - AnimationId animToPlay; - - bool weAreMissionChar = CharCreatedBy == MISSION_CHAR; - bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR; - CVector posDiff = collideWith->GetPosition() - GetPosition(); - int waitTime = 0; - - if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) { - bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f; - bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f; - - if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) { - - if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f) - && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT -#ifdef VC_PED_PORTS - || m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith - || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this -#endif - )) { - - if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) { - - if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { - - if (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) { - - if (weAreMissionChar && (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY)) { - - if (collideWith->m_nMoveState != PEDMOVE_STILL - && (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) { - float seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D(); - float heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D(); - - if (seekPosDist <= heAndSeekPosDist) { - waitTime = 1000; - collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime); - collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime; - } else { - waitTime = 500; - SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime; - } - } else if (collideWith->m_nMoveState == PEDMOVE_STILL) { - SetDirectionToWalkAroundObject(collideWith); - } - } else { - if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper - || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) && - (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) { - SetDirectionToWalkAroundObject(collideWith); - if (!weAreMissionChar) - Say(SOUND_PED_CHAT); - } else { - SetEvasiveStep(collideWith, 2); - } - } - } else { - if (m_pedStats->m_temper <= m_pedStats->m_fear - || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED - || weAreMissionChar - || collideWith->m_nPedType == PEDTYPE_CIVFEMALE - || collideWith->m_nPedType == m_nPedType - || collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { - SetDirectionToWalkAroundObject(collideWith); - Say(SOUND_PED_CHAT); - } else { - TurnBody(); - SetAttack(collideWith); -#ifdef VC_PED_PORTS - m_fRotationCur = 0.3f + m_fRotationCur; - m_fRotationDest = m_fRotationCur; -#endif - } - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450); - } - } - } else { -#ifdef VC_PED_PORTS - if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { -#else - if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { -#endif - if (heLooksToUs) { - SetEvasiveStep(collideWith, 1); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; - } - } else if (weDontLookToHim && IsPedInControl()) { - - if (m_pedStats != collideWith->m_pedStats) { - - if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper -#ifdef VC_PED_PORTS - || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer -#endif - ) { - - if (collideWith->IsPlayer()) { - // He's on our right side - if (DotProduct(posDiff,GetRight()) <= 0.0f) - m_fRotationCur -= m_headingRate; - else - m_fRotationCur += m_headingRate; - } else { - // He's on our right side - if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) - collideWith->m_fRotationCur -= collideWith->m_headingRate; - else - collideWith->m_fRotationCur += collideWith->m_headingRate; - } - } else { - SetLookFlag(collideWith, false); - TurnBody(); - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); - animAssoc->flags |= ASSOC_FADEOUTWHENDONE; -#ifdef VC_PED_PORTS - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000; -#endif - if (!heIsMissionChar) { - CVector2D posDiff2D(posDiff); - int direction = collideWith->GetLocalDirection(posDiff2D); - collideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5); - } - } - } - } - } - } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar -#ifdef VC_PED_PORTS - || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness -#endif - ) { - // He looks us and we're not at his right side - if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) { - CVector moveForce = GetRight(); - moveForce.z += 0.1f; - ApplyMoveForce(moveForce); - if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) - animToPlay = ANIM_HIT_LEFT; - else - animToPlay = ANIM_SHOT_LEFT_PARTIAL; - } else if (heLooksToUs) { - CVector moveForce = GetRight() * -1.0f; - moveForce.z += 0.1f; - ApplyMoveForce(moveForce); - if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) - animToPlay = ANIM_HIT_RIGHT; - else - animToPlay = ANIM_SHOT_RIGHT_PARTIAL; - } else { - if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) - animToPlay = ANIM_HIT_BACK; - else - animToPlay = ANIM_SHOT_BACK_PARTIAL; - } - - if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) { - animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f); - animAssoc->flags |= ASSOC_FADEOUTWHENDONE; - collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000; - if (m_nPedState == PED_ATTACK) - DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); - } - } else { - // We're at his right side - if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) { - CVector moveForce = GetRight() * -1.0f; - moveForce.z += 0.1f; - ApplyMoveForce(moveForce); - if (heLooksToUs) - animToPlay = ANIM_KO_SPIN_L; - else - animToPlay = ANIM_KD_RIGHT; - } else { - CVector moveForce = GetRight(); - moveForce.z += 0.1f; - ApplyMoveForce(moveForce); - if (heLooksToUs) - animToPlay = ANIM_KO_SPIN_R; - else - animToPlay = ANIM_KD_LEFT; - } - - if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl()) - DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); - - collideWith->SetFall(3000, animToPlay, 0); - } - } else { - if (!IsPedInControl()) - return; - - if (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) - return; - - if (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) { - - if (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) { - - if (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){ - SetEvasiveStep(collideWith, 2); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; - } else if (collideWith->m_nMoveState > PEDMOVE_WALK) { - waitTime = 2000; - SetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime); - } - } - } else if (heLooksToUs - && collideWith->m_nPedState != PED_STEP_AWAY - && m_nPedState != PED_STEP_AWAY - && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { - - SetEvasiveStep(collideWith, 1); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; - } - } - - if (IsPlayer()) { - SetLookFlag(collideWith, true); - SetLookTimer(800); - } - } else { - bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; - SetFindPathAndFlee(collideWith, 5000, !isRunning); - } -} - -void -CPed::CreateDeadPedMoney(void) -{ - if (!CGame::nastyGame) - return; - - int mi = GetModelIndex(); - - if ((mi >= MI_COP && mi <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle) - return; - - int money = CGeneral::GetRandomNumber() % 60; - if (money < 10) - return; - - if (money == 43) - money = 700; - - int pickupCount = money / 40 + 1; - int moneyPerPickup = money / pickupCount; - - for(int i = 0; i < pickupCount; i++) { - // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish. - float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x; - float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y; - bool found = false; - float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f; - if (found) { - CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7)); - } - } -} - -void -CPed::CreateDeadPedWeaponPickups(void) -{ - bool found = false; - float angleToPed; - CVector pickupPos; - - if (bInVehicle) - return; - - for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { - - eWeaponType weapon = GetWeapon(i).m_eWeaponType; - int weaponAmmo = GetWeapon(i).m_nAmmoTotal; - if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || weaponAmmo == 0) - continue; - - angleToPed = i * 1.75f; - pickupPos = GetPosition(); - pickupPos.x += 1.5f * Sin(angleToPed); - pickupPos.y += 1.5f * Cos(angleToPed); - pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; - - CVector pedPos = GetPosition(); - pedPos.z += 0.3f; - - CVector pedToPickup = pickupPos - pedPos; - float distance = pedToPickup.Magnitude(); - - // outer edge of pickup - distance = (distance + 0.3f) / distance; - CVector pickupPos2 = pedPos; - pickupPos2 += distance * pedToPickup; - - // pickup must be on ground and line to its edge must be clear - if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) { - // otherwise try another position (but disregard second check apparently) - angleToPed += 3.14f; - pickupPos = GetPosition(); - pickupPos.x += 1.5f * Sin(angleToPed); - pickupPos.y += 1.5f * Cos(angleToPed); - pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; - } - if (found) - CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon])); - } - ClearWeapons(); -} - -void -CPed::SetAttackTimer(uint32 time) -{ - if (CTimer::GetTimeInMilliseconds() > m_attackTimer) - m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time; -} - -void -CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack) -{ - if (m_nPedState == PED_DRAG_FROM_CAR) - return; - - bUsesCollision = false; - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - m_nLastPedState = PED_IDLE; - SetMoveState(PEDMOVE_STILL); - m_pSeekTarget = veh; - m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); - m_vehEnterType = vehEnterType; - if (m_vehEnterType == CAR_DOOR_LF) { - if (veh->pDriver && veh->pDriver->IsPlayer()) - veh->SetStatus(STATUS_PLAYER_DISABLED); - else - veh->SetStatus(STATUS_ABANDONED); - } - RemoveInCarAnims(); - SetMoveState(PEDMOVE_NONE); - LineUpPedWithCar(LINE_UP_TO_CAR_START); - m_pVehicleAnim = nil; - m_nPedState = PED_DRAG_FROM_CAR; - bChangedSeat = false; - bWillBeQuickJacked = quickJack; - - SetHeading(m_fRotationCur); - - Say(SOUND_PED_CAR_JACKED); - SetRadioStation(); - veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType); -} - -void -CPed::SetBuyIceCream(void) -{ - if (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl()) - return; - - if (!m_carInObjective) - return; - -#ifdef FIX_ICECREAM - - // Simulating BuyIceCream - CPed* driver = m_carInObjective->pDriver; - if (driver) { - m_nPedState = PED_BUY_ICECREAM; - bFindNewNodeAfterStateRestore = true; - SetObjectiveTimer(8000); - SetChat(driver, 8000); - driver->SetChat(this, 8000); - return; - } -#endif - - // Side of the Ice Cream van - m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI; - - if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) { - m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000; - m_nPedState = PED_BUY_ICECREAM; - } -} - -void -CPed::SetChat(CEntity *chatWith, uint32 time) -{ - if(m_nPedState != PED_CHAT) - SetStoredState(); - - m_nPedState = PED_CHAT; - SetMoveState(PEDMOVE_STILL); -#if defined VC_PED_PORTS || defined FIX_BUGS - m_lookTimer = 0; -#endif - SetLookFlag(chatWith, true); - m_standardTimer = CTimer::GetTimeInMilliseconds() + time; - m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000; -} - -void -CPed::SetDead(void) -{ - bUsesCollision = false; - - m_fHealth = 0.0f; - if (m_nPedState == PED_DRIVING) - bIsVisible = false; - - m_nPedState = PED_DEAD; - m_pVehicleAnim = nil; - m_pCollidingEntity = nil; - - CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - RemoveWeaponModel(weapon->m_nModelId); - - m_currentWeapon = WEAPONTYPE_UNARMED; - CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250); - if (this != FindPlayerPed()) { - CreateDeadPedWeaponPickups(); - CreateDeadPedMoney(); - } - - m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds(); - m_deadBleeding = false; - bDoBloodyFootprints = false; - bVehExitWillBeInstant = false; - CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000); -} - -void -CPed::SetSeek(CEntity *seeking, float distanceToCountDone) -{ - if (!IsPedInControl()) - return; - - if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking) - return; - - if (!seeking) - return; - - if (m_nPedState != PED_SEEK_ENTITY) - SetStoredState(); - - m_nPedState = PED_SEEK_ENTITY; - m_distanceToCountSeekDone = distanceToCountDone; - m_pSeekTarget = seeking; - m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); - SetMoveState(PEDMOVE_STILL); -} - -void -CPed::SetSeek(CVector pos, float distanceToCountDone) -{ - if (!IsPedInControl() - || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y)) - return; - - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 - || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47 - || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE - || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER - || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) { - ClearPointGunAt(); - } - - if (m_nPedState != PED_SEEK_POS) - SetStoredState(); - - m_nPedState = PED_SEEK_POS; - m_distanceToCountSeekDone = distanceToCountDone; - m_vecSeekPos = pos; -} - -void -CPed::DeadPedMakesTyresBloody(void) -{ - int minX = CWorld::GetSectorIndexX(GetPosition().x - 2.0f); - if (minX < 0) minX = 0; - int minY = CWorld::GetSectorIndexY(GetPosition().y - 2.0f); - if (minY < 0) minY = 0; - int maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f); - if (maxX > NUMSECTORS_X-1) maxX = NUMSECTORS_X-1; - int maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f); - if (maxY > NUMSECTORS_Y-1) maxY = NUMSECTORS_Y-1; - - CWorld::AdvanceCurrentScanCode(); - - for (int curY = minY; curY <= maxY; curY++) { - for (int curX = minX; curX <= maxX; curX++) { - CSector *sector = CWorld::GetSector(curX, curY); - MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]); - MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]); - } - } -} - -void -CPed::Die(void) -{ - // UNUSED: This is a perfectly empty function. -} - -uint8 -CPed::DoesLOSBulletHitPed(CColPoint &colPoint) -{ -#ifdef FIX_BUGS - return 1; -#else - uint8 retVal = 2; - - float headZ = GetNodePosition(PED_HEAD).z; - - if (m_nPedState == PED_FALL) - retVal = 1; - - float colZ = colPoint.point.z; - if (colZ < headZ) - retVal = 1; - - if (headZ + 0.2f <= colZ) - retVal = 0; - - return retVal; -#endif -} - -bool -CPed::DuckAndCover(void) -{ - if (!m_pedInObjective || CTimer::GetTimeInMilliseconds() <= m_duckAndCoverTimer) - return false; - - if (bKindaStayInSamePlace){ - - if (CTimer::GetTimeInMilliseconds() <= m_leaveCarTimer) { - if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) { - m_pLookTarget = m_pedInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - } - if (!bIsAimingGun) - SetAimFlag(m_pedInObjective); - - } else { - bCrouchWhenShooting = false; - bKindaStayInSamePlace = false; - bIsDucking = false; - bDuckAndCover = false; - m_headingRate = 10.0f; - m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000); - if (m_pSeekTarget && m_pSeekTarget->IsVehicle()) - ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover--; - } - return false; - } - - bool justDucked = false; - CVehicle *foundVeh = nil; - float maxDist = 225.0f; - bIsDucking = false; - bCrouchWhenShooting = false; - if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - CVector pos = GetPosition(); - int16 lastVehicle; - CEntity *vehicles[8]; - CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - - for (int i = 0; i < lastVehicle; i++) { - CVehicle *veh = (CVehicle*) vehicles[i]; - if (veh->m_vecMoveSpeed.Magnitude() <= 0.02f - && !veh->bIsBus - && !veh->bIsVan - && !veh->bIsBig - && veh->m_numPedsUseItAsCover < 3) { - float dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr(); - if (dist < maxDist) { - maxDist = dist; - foundVeh = veh; - } - } - } - if (foundVeh) { - // Unused. - // CVector lfWheelPos, rfWheelPos; - // foundVeh->GetComponentWorldPosition(CAR_WHEEL_RF, rfWheelPos); - // foundVeh->GetComponentWorldPosition(CAR_WHEEL_LF, lfWheelPos); - CVector rightSide, leftSide; - - // 3 persons can use the car as cover. Found the correct position for us. - if (foundVeh->m_numPedsUseItAsCover == 2) { - rightSide = CVector(1.5f, -0.5f, 0.0f); - leftSide = CVector(-1.5f, -0.5f, 0.0f); - } else if (foundVeh->m_numPedsUseItAsCover == 1) { - rightSide = CVector(1.5f, 0.5f, 0.0f); - leftSide = CVector(-1.5f, 0.5f, 0.0f); - } else if (foundVeh->m_numPedsUseItAsCover == 0) { - rightSide = CVector(1.5f, 0.0f, 0.0f); - leftSide = CVector(-1.5f, 0.0f, 0.0f); - } - - CMatrix vehMatrix(foundVeh->GetMatrix()); - CVector duckAtRightSide = Multiply3x3(vehMatrix, rightSide) + foundVeh->GetPosition(); - - CVector duckAtLeftSide = Multiply3x3(vehMatrix, leftSide) + foundVeh->GetPosition(); - - CVector distWithPedRightSide = m_pedInObjective->GetPosition() - duckAtRightSide; - CVector distWithPedLeftSide = m_pedInObjective->GetPosition() - duckAtLeftSide; - - CVector duckPos; - if (distWithPedRightSide.MagnitudeSqr() <= distWithPedLeftSide.MagnitudeSqr()) - duckPos = duckAtLeftSide; - else - duckPos = duckAtRightSide; - - if (CWorld::TestSphereAgainstWorld(duckPos, 0.5f, nil, true, true, true, false, false, false) - && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) { - SetSeek(duckPos, 1.0f); - m_headingRate = 15.0f; - bIsRunning = true; - bDuckAndCover = true; - justDucked = true; - m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500; - if (foundVeh->bIsLawEnforcer) - m_carInObjective = foundVeh; - - // BUG? Shouldn't we register the reference? - m_pSeekTarget = foundVeh; - ClearPointGunAt(); - } else { - m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000); - bDuckAndCover = false; - } - } else { - bDuckAndCover = false; - } - } - - if (!justDucked && !bDuckAndCover) - return false; - - if (!Seek()) - return true; - - bKindaStayInSamePlace = true; - bDuckAndCover = false; - m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); - if (m_pSeekTarget && m_pSeekTarget->IsVehicle()) - ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++; - - SetIdle(); - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); - if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) { - m_pLookTarget = m_pedInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - } - - m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 6000); - return false; -} - -void -CPed::EndFight(uint8 endType) -{ - if (m_nPedState != PED_FIGHT) - return; - - m_curFightMove = FIGHTMOVE_NULL; - RestorePreviousState(); - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); - if (animAssoc) - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - - switch (endType) { - case ENDFIGHT_NORMAL: - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f); - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f); - break; - case ENDFIGHT_WITH_A_STEP: - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 1.0f); - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WALK_START, 8.0f); - break; - case ENDFIGHT_FAST: - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f); - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f)->speed = 2.0f; - break; - default: - break; - } - m_nWaitTimer = 0; -} - -void -CPed::EnterCar(void) -{ - if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) { - CVehicle *veh = (CVehicle*)m_pSeekTarget; - - // Not used. - // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType); - - if (veh->CanPedOpenLocks(this)) { - if (m_vehEnterType && m_pVehicleAnim) { - veh->ProcessOpenDoor(m_vehEnterType, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime); - } - } - bIsInTheAir = false; - LineUpPedWithCar(LINE_UP_TO_CAR_START); - } else { - QuitEnteringCar(); - SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } -} - -uint8 -CPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos) -{ - CVector enterStepOffset; - CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(train->GetModelIndex()); - CMatrix trainMat = CMatrix(train->GetMatrix()); - CVector leftEntryPos, rightEntryPos, midEntryPos; - float distLeftEntry, distRightEntry, distMidEntry; - - // enterStepOffset = vecPedCarDoorAnimOffset; - enterStepOffset = CVector(1.5f, 0.0f, 0.0f); - - if (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) { - distLeftEntry = 999.0f; - } else { - leftEntryPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterStepOffset; - leftEntryPos = Multiply3x3(trainMat, leftEntryPos); - leftEntryPos += train->GetPosition(); - distLeftEntry = (leftEntryPos - GetPosition()).Magnitude(); - } - - if (train->pPassengers[TRAIN_POS_MID_ENTRY]) { - distMidEntry = 999.0f; - } else { - midEntryPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterStepOffset; - midEntryPos = Multiply3x3(trainMat, midEntryPos); - midEntryPos += train->GetPosition(); - distMidEntry = (midEntryPos - GetPosition()).Magnitude(); - } - - if (train->pPassengers[TRAIN_POS_RIGHT_ENTRY]) { - distRightEntry = 999.0f; - } else { - rightEntryPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterStepOffset; - rightEntryPos = Multiply3x3(trainMat, rightEntryPos); - rightEntryPos += train->GetPosition(); - distRightEntry = (rightEntryPos - GetPosition()).Magnitude(); - } - - if (distMidEntry < distLeftEntry) { - if (distMidEntry < distRightEntry) { - enterPos = midEntryPos; - m_vehEnterType = TRAIN_POS_MID_ENTRY; - } else { - enterPos = rightEntryPos; - m_vehEnterType = TRAIN_POS_RIGHT_ENTRY; - } - } else if (distRightEntry < distLeftEntry) { - enterPos = rightEntryPos; - m_vehEnterType = TRAIN_POS_RIGHT_ENTRY; - } else { - enterPos = leftEntryPos; - m_vehEnterType = TRAIN_POS_LEFT_ENTRY; - } - - return 1; -} - -uint8 -CPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos) -{ - GetNearestTrainPedPosition(train, doorPos); -/* - // Not used. - CVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(train->m_modelIndex); - CMatrix trainMat = CMatrix(train->GetMatrix()); - - doorPos = trainModel->m_positions[m_vehEnterType]; - doorPos.x -= 1.5f; - doorPos = Multiply3x3(trainMat, doorPos); - doorPos += train->GetPosition(); -*/ - return 1; -} - -void -CPed::LineUpPedWithTrain(void) -{ - CVector lineUpPos; - CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex()); - CVector enterOffset(1.5f, 0.0f, -0.2f); - - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI; - m_fRotationDest = m_fRotationCur; - - if (!bInVehicle) { - GetNearestTrainDoor(m_pMyVehicle, lineUpPos); - lineUpPos.z += 0.2f; - } else { - if (m_pMyVehicle->pPassengers[TRAIN_POS_LEFT_ENTRY] == this) { - - lineUpPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterOffset; - - } else if (m_pMyVehicle->pPassengers[TRAIN_POS_MID_ENTRY] == this) { - - lineUpPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterOffset; - - } else if (m_pMyVehicle->pPassengers[TRAIN_POS_RIGHT_ENTRY] == this) { - - lineUpPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterOffset; - } - lineUpPos = Multiply3x3(m_pMyVehicle->GetMatrix(), lineUpPos); - lineUpPos += m_pMyVehicle->GetPosition(); - } - - if (m_pVehicleAnim) { - float percentageLeft = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength; - lineUpPos += (GetPosition() - lineUpPos) * percentageLeft; - } - - SetPosition(lineUpPos); - SetHeading(m_fRotationCur); -} - -void -CPed::EnterTrain(void) -{ - LineUpPedWithTrain(); -} - -void -CPed::ExitTrain(void) -{ - LineUpPedWithTrain(); -} - -void -CPed::ExitCar(void) -{ - if (!m_pVehicleAnim) - return; - - AnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId; - float animTime = m_pVehicleAnim->currentTime; - - m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, exitAnim, animTime); - - if (m_pSeekTarget) { - // Car is upside down - if (m_pMyVehicle->GetUp().z > -0.8f) { - if (exitAnim == ANIM_CAR_CLOSE_RHS || exitAnim == ANIM_CAR_CLOSE_LHS || animTime > 0.3f) - LineUpPedWithCar(LINE_UP_TO_CAR_END); - else - LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START)); - } else { - LineUpPedWithCar(LINE_UP_TO_CAR_END); - } - } - - // If there is someone in front of the door, make him fall while we exit. - if (m_nPedState == PED_EXIT_CAR) { - CPed *foundPed = nil; - for (int i = 0; i < m_numNearPeds; i++) { - if ((m_nearPeds[i]->GetPosition() - GetPosition()).MagnitudeSqr2D() < 0.04f) { - foundPed = m_nearPeds[i]; - break; - } - } - if (foundPed && animTime > 0.4f && foundPed->IsPedInControl()) - foundPed->SetFall(1000, ANIM_KO_SKID_FRONT, 1); - } -} - -void -CPed::Fall(void) -{ - if (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer -#ifdef VC_PED_PORTS - && bIsStanding -#endif - ) - ClearFall(); - - // VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III. -} - -void -CPed::Fight(void) -{ - CAnimBlendAssociation *currentAssoc, *animAssoc; - bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse; - float angleToFace, nextAngle; - bool goForward = false; - int nextFightMove; - - switch (m_curFightMove) { - case FIGHTMOVE_NULL: - return; - case FIGHTMOVE_IDLE2NORM: - m_curFightMove = FIGHTMOVE_NULL; - RestorePreviousState(); - - // FIX: Uninitialized - currentAssoc = nil; - break; - case FIGHTMOVE_IDLE: - currentAssoc = nil; - break; - default: - currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); - break; - } - - if (!bIsAttacking && IsPlayer()) { - if (currentAssoc) { - currentAssoc->blendDelta = -1000.0f; - currentAssoc->flags |= ASSOC_DELETEFADEDOUT; - currentAssoc->flags &= ~ASSOC_RUNNING; - } - if (m_takeAStepAfterAttack) - EndFight(ENDFIGHT_WITH_A_STEP); - else - EndFight(ENDFIGHT_FAST); - - } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) { - float animTime = currentAssoc->currentTime; - FightMove &curMove = tFightMoves[m_curFightMove]; - if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) { - - CVector touchingNodePos(0.0f, 0.0f, 0.0f); - - switch (m_curFightMove) { - case FIGHTMOVE_STDPUNCH: - case FIGHTMOVE_PUNCHHOOK: - case FIGHTMOVE_BODYBLOW: - TransformToNode(touchingNodePos, PED_HANDR); - break; - case FIGHTMOVE_IDLE: - case FIGHTMOVE_SHUFFLE_F: - break; - case FIGHTMOVE_KNEE: - TransformToNode(touchingNodePos, PED_LOWERLEGR); - break; - case FIGHTMOVE_HEADBUTT: - TransformToNode(touchingNodePos, PED_HEAD); - break; - case FIGHTMOVE_PUNCHJAB: - TransformToNode(touchingNodePos, PED_HANDL); - break; - case FIGHTMOVE_KICK: - case FIGHTMOVE_LONGKICK: - case FIGHTMOVE_ROUNDHOUSE: - case FIGHTMOVE_GROUNDKICK: - TransformToNode(touchingNodePos, PED_FOOTR); - break; - } - - if (m_curFightMove == FIGHTMOVE_PUNCHJAB) { - touchingNodePos += 0.1f * GetForward(); - } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) { - touchingNodePos += 0.22f * GetForward(); - } - FightStrike(touchingNodePos); - m_fightButtonPressure = 0; - return; - } - - if (curMove.hitLevel != HITLEVEL_NULL) { - if (animTime > curMove.endFireTime) { - if (IsPlayer()) - currentAssoc->speed = 1.0f; - else - currentAssoc->speed = 0.8f; - } - - if (IsPlayer() && !nPlayerInComboMove) { - if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) { - - // Notice that it increases fight move index, because we're in combo! - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f); - animAssoc->SetFinishCallback(FinishFightMoveCB, this); - animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength); - m_fightButtonPressure = 0; - nPlayerInComboMove = 1; - } - } - } else { - if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) { - if (IsPlayer()) - currentAssoc->speed = 1.3f; - else - currentAssoc->speed = 0.8f; - } - } - } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { - EndFight(ENDFIGHT_FAST); - - } else if (m_fightButtonPressure != 0) { - bool canAffectMultiplePeople = true; - nextAngle = m_fRotationCur; - bool kickGround = false; - float angleForGroundKick = 0.0f; - CPed *pedOnGround = nil; - - Say(SOUND_PED_ATTACK); - - if (IsPlayer()) { - canRoundhouse = false; - punchOnly = false; - canKick = true; - nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE); - hasShoppingBags = false; - canKneeHead = true; - nPlayerInComboMove = 0; - } else { - nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE); - uint16 pedFeatures = m_pedStats->m_flags; - punchOnly = pedFeatures & STAT_PUNCH_ONLY; - canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE; - canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD; - canKick = pedFeatures & STAT_CAN_KICK; - hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS; - } - - // Attack isn't scripted, find the victim - if (IsPlayer() || !m_pedInObjective) { - - for (int i = 0; i < m_numNearPeds; i++) { - - CPed *nearPed = m_nearPeds[i]; - float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude(); - if (nearPedDist < 3.0f) { - float angleToFace = CGeneral::GetRadianAngleBetweenPoints( - nearPed->GetPosition().x, nearPed->GetPosition().y, - GetPosition().x, GetPosition().y); - - nextAngle = CGeneral::LimitRadianAngle(angleToFace); - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - - float neededTurn = Abs(nextAngle - m_fRotationCur); - if (neededTurn > PI) - neededTurn = TWOPI - neededTurn; - - if (!nearPed->OnGroundOrGettingUp()) { - - if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) { - canAffectMultiplePeople = false; - } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) { - - if (nearPedDist < 1.7f - && neededTurn < DEGTORAD(35.0f) - && (canKick || hasShoppingBags)) { - - nextFightMove = FIGHTMOVE_KICK; - if (hasShoppingBags) { - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) { - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - } - canAffectMultiplePeople = false; - } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) { - canAffectMultiplePeople = false; - nextFightMove = FIGHTMOVE_LONGKICK; - } else if (neededTurn < DEGTORAD(30.0f)) { - goForward = true; - } - } else { - nextFightMove += 2; // Makes it 6 or 7 - if (punchOnly) - nextFightMove = FIGHTMOVE_PUNCHJAB; - - canAffectMultiplePeople = false; - } - } else if (!CGame::nastyGame - || nearPedDist >= 1.3f - || neededTurn >= DEGTORAD(55.0f) - || punchOnly) { - - if (nearPedDist > 0.8f - && nearPedDist < 3.0f - && neededTurn < DEGTORAD(30.0f)) { - goForward = true; - } - - } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) { - if (!nearPed->IsPedHeadAbovePos(-0.3f)) { - canAffectMultiplePeople = false; - nextFightMove = FIGHTMOVE_GROUNDKICK; - } - - } else { - pedOnGround = nearPed; - kickGround = true; - angleForGroundKick = nextAngle; - } - } - - if (!canAffectMultiplePeople) { - m_fRotationDest = nextAngle; - if (IsPlayer()) { - m_fRotationCur = m_fRotationDest; - m_lookTimer = 0; - SetLookFlag(nearPed, true); - SetLookTimer(1500); - } - break; - } - } - } else { - // Because we're in a scripted fight with some particular ped. - canAffectMultiplePeople = false; - - float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude(); - if (hasShoppingBags) { - if (fightingPedDist >= 1.7f) - nextFightMove = FIGHTMOVE_SHUFFLE_F; - else - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - - } else if (punchOnly) { - if (fightingPedDist >= 1.3f) - nextFightMove = FIGHTMOVE_SHUFFLE_F; - else - nextFightMove = FIGHTMOVE_PUNCHJAB; - - } else if (fightingPedDist >= 3.0f) { - nextFightMove = FIGHTMOVE_STDPUNCH; - - } else { - angleToFace = CGeneral::GetRadianAngleBetweenPoints( - m_pedInObjective->GetPosition().x, - m_pedInObjective->GetPosition().y, - GetPosition().x, - GetPosition().y); - - nextAngle = CGeneral::LimitRadianAngle(angleToFace); - m_fRotationDest = nextAngle; - m_fRotationCur = m_fRotationDest; - if (!m_pedInObjective->OnGroundOrGettingUp()) { - - if (fightingPedDist >= 0.8f || !canKneeHead) { - - if (fightingPedDist >= 1.3f) { - - if (fightingPedDist < 1.7f && canKick) { - nextFightMove = FIGHTMOVE_KICK; - if (canRoundhouse && CGeneral::GetRandomNumber() & 1) - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - - } else if (fightingPedDist < 2.0f && canKick) { - nextFightMove += 5; // Makes it 9 or 10 - - } else { - nextFightMove = FIGHTMOVE_SHUFFLE_F; - - } - } else { - nextFightMove += 2; // Makes it 6 or 7 - } - } - } else if (!CGame::nastyGame - || fightingPedDist >= 1.3f - || m_pedInObjective->IsPlayer() - || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) { - nextFightMove = FIGHTMOVE_IDLE; - } else { - nextFightMove = FIGHTMOVE_GROUNDKICK; - } - } - } - - if (canAffectMultiplePeople) { - if (kickGround && IsPlayer()) { - m_fRotationDest = angleForGroundKick; - nextFightMove = FIGHTMOVE_GROUNDKICK; - m_fRotationCur = m_fRotationDest; - m_lookTimer = 0; - SetLookFlag(pedOnGround, true); - SetLookTimer(1500); - } else if (goForward) { - nextFightMove = FIGHTMOVE_SHUFFLE_F; - } else { - nextFightMove = FIGHTMOVE_STDPUNCH; - } - } - - if (nextFightMove != FIGHTMOVE_IDLE) { - m_curFightMove = nextFightMove; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); - - animAssoc->SetFinishCallback(FinishFightMoveCB, this); - if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) { - animAssoc->SetCurrentTime(0.0f); - animAssoc->SetRun(); - } - m_fightButtonPressure = 0; - } - m_fightState = FIGHTSTATE_NO_MOVE; - } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F -#ifndef FIX_BUGS - && CheckForPedsOnGroundToAttack(this, nil) == 4) { -#else - && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) { -#endif - m_curFightMove = FIGHTMOVE_SHUFFLE_F; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); - - if (animAssoc) { - animAssoc->SetCurrentTime(0.0f); - animAssoc->blendDelta = 4.0f; - animAssoc->SetRun(); - } else { - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f); - } - animAssoc->SetFinishCallback(FinishFightMoveCB, this); - m_fightState = FIGHTSTATE_NO_MOVE; - m_fightButtonPressure = 0; - m_takeAStepAfterAttack = false; - - } else if (m_takeAStepAfterAttack) { - EndFight(ENDFIGHT_FAST); - - } else if (m_curFightMove == FIGHTMOVE_IDLE) { - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - EndFight(ENDFIGHT_NORMAL); - } - - } else { - m_curFightMove = FIGHTMOVE_IDLE; - if (IsPlayer()) - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500; - else - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000; - } -} - -// Some helper function which doesn't exist in og game. -inline void -SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVector2D farDist, CPathNode *closeNode, CPathNode *closeNode2, int runCount = 3) -{ - for (int i = 0; i < node->numLinks; i++) { - - CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)]; - - if (testNode && testNode != closeNode && testNode != closeNode2) { - CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition()); - float dist = posDiff.MagnitudeSqr(); - - if (farDist.MagnitudeSqr() > dist) { - - if (closeDist.MagnitudeSqr() <= dist) { - ped->m_pNextPathNode = closeNode; - closeDist = posDiff; - } else { - ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode); - farDist = posDiff; - } - } - - if (--runCount > 0) - SelectClosestNodeForSeek(ped, testNode, closeDist, farDist, closeNode, (closeNode2 ? closeNode2 : testNode), runCount); - } - } -} - -bool -CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords) -{ - if (m_pNextPathNode || !bUsePedNodeSeek) - return false; - - CVector ourPos = GetPosition(); - - int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f); - - CVector seekObjPos = m_vecSeekPos; - seekObjPos.z += 1.0f; - - if (CWorld::GetIsLineOfSightClear(ourPos, seekObjPos, true, false, false, true, false, false, false)) - return false; - - m_pNextPathNode = nil; - - CVector2D seekPosDist (m_vecSeekPos - ourPos); - - CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId]; - CVector2D closeDist(m_vecSeekPos - closestNode->GetPosition()); - - SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil); - - // Above function decided that going to the next node is more logical than seeking the object. - if (m_pNextPathNode) { - - CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos; - if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) { - *bestCoords = m_pNextPathNode->GetPosition(); - return true; - } - m_pNextPathNode = nil; - } - - return false; -} - -void -CPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - if (ped->bIsPedDieAnimPlaying) - ped->bIsPedDieAnimPlaying = false; -} - -void -CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) { - ped->m_fightState = FIGHTSTATE_MOVE_FINISHED; - animAssoc->blendDelta = -1000.0f; - } -} - -void -CPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - if (animAssoc) { - animAssoc->blendDelta = -4.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - - if (ped->m_nPedState == PED_JUMP) - ped->RestorePreviousState(); - - ped->bIsLanding = false; -} - -void -CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - ped->bResetWalkAnims = true; - ped->bIsLanding = false; - - animAssoc->blendDelta = -1000.0f; -} - -void -CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - if (ped->m_nPedState != PED_JUMP) - return; - - CVector forward(0.15f * ped->GetForward() + ped->GetPosition()); - forward.z += CModelInfo::GetModelInfo(ped->GetModelIndex())->GetColModel()->spheres->center.z + 0.25f; - - CEntity *obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false); - if (!obstacle) { - // Forward of forward - forward += 0.15f * ped->GetForward(); - forward.z += 0.15f; - obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false); - } - - if (obstacle) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - - // ANIM_HIT_WALL in VC (which makes more sense) - CAnimBlendAssociation *handsCoverAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 8.0f); - handsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; - handsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped); - ped->bIsLanding = true; - return; - } - - float velocityFromAnim = 0.1f; - CAnimBlendAssociation *sprintAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_SPRINT); - - if (sprintAssoc) { - velocityFromAnim = 0.05f * sprintAssoc->blendAmount + 0.17f; - } else { - CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_RUN); - if (runAssoc) { - velocityFromAnim = 0.07f * runAssoc->blendAmount + 0.1f; - } - } - - if (ped->IsPlayer() -#ifdef VC_PED_PORTS - || ped->m_pedInObjective && ped->m_pedInObjective->IsPlayer() -#endif - ) - ped->ApplyMoveForce(0.0f, 0.0f, 8.5f); - else - ped->ApplyMoveForce(0.0f, 0.0f, 4.5f); - - if (sq(velocityFromAnim) > ped->m_vecMoveSpeed.MagnitudeSqr2D() -#ifdef VC_PED_PORTS - || ped->m_pCurrentPhysSurface -#endif - ) { - -#ifdef FREE_CAM - if (TheCamera.Cams[0].Using3rdPersonMouseCam() && !CCamera::bFreeCam) { -#else - if (TheCamera.Cams[0].Using3rdPersonMouseCam()) { -#endif - float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur); - ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle); - ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle); - } else { - ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur); - ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur); - } -#ifdef VC_PED_PORTS - if (ped->m_pCurrentPhysSurface) { - ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x; - ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y; - } -#endif - } - - ped->bIsStanding = false; - ped->bIsInTheAir = true; - animAssoc->blendDelta = -1000.0f; - CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_JUMP_GLIDE); - - if (ped->bDoBloodyFootprints) { - CVector bloodPos(0.0f, 0.0f, 0.0f); - ped->TransformToNode(bloodPos, PED_FOOTL); - - bloodPos.z -= 0.1f; - bloodPos += 0.2f * ped->GetForward(); - - CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, - 0.26f * ped->GetForward().x, - 0.26f * ped->GetForward().y, - 0.14f * ped->GetRight().x, - 0.14f * ped->GetRight().y, - 255, 255, 0, 0, 4.0f, 3000, 1.0f); - - bloodPos = CVector(0.0f, 0.0f, 0.0f); - ped->TransformToNode(bloodPos, PED_FOOTR); - - bloodPos.z -= 0.1f; - bloodPos += 0.2f * ped->GetForward(); - CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, - 0.26f * ped->GetForward().x, - 0.26f * ped->GetForward().y, - 0.14f * ped->GetRight().x, - 0.14f * ped->GetRight().y, - 255, 255, 0, 0, 4.0f, 3000, 1.0f); - - if (ped->m_bloodyFootprintCountOrDeathTime <= 40) { - ped->m_bloodyFootprintCountOrDeathTime = 0; - ped->bDoBloodyFootprints = false; - } else { - ped->m_bloodyFootprintCountOrDeathTime -= 40; - } - } -} - -void -CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - ped->m_nWaitTimer = 0; - ped->RestoreHeadingRate(); - ped->Wait(); -} - -void -CPed::Wait(void) -{ - AnimationId mustHaveAnim = NUM_ANIMS; - CAnimBlendAssociation *animAssoc; - CPed *pedWeLook; - - if (DyingOrDead()) { - m_nWaitState = WAITSTATE_FALSE; - RestoreHeadingRate(); - return; - } - - switch (m_nWaitState) { - - case WAITSTATE_TRAFFIC_LIGHTS: - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) { - m_nWaitState = WAITSTATE_FALSE; - SetMoveState(PEDMOVE_WALK); - } - } - break; - - case WAITSTATE_CROSS_ROAD: - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer) - m_nWaitState = WAITSTATE_FALSE; - else - SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil); - - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - } - break; - - case WAITSTATE_CROSS_ROAD_LOOK: - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - m_nWaitState = WAITSTATE_FALSE; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - } - break; - - case WAITSTATE_DOUBLEBACK: - if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { - uint32 timeLeft = m_nWaitTimer - CTimer::GetTimeInMilliseconds(); - if (timeLeft < 2500 && timeLeft > 2000) { - m_nWaitTimer -= 500; - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); - } - } else { - m_nWaitState = WAITSTATE_FALSE; - SetMoveState(PEDMOVE_WALK); - } - break; - - case WAITSTATE_HITWALL: - if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { - if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) { - m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; - } - } else { - m_nWaitState = WAITSTATE_FALSE; - } - break; - - case WAITSTATE_TURN180: - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - m_nWaitState = WAITSTATE_FALSE; - SetMoveState(PEDMOVE_WALK); - m_fRotationCur = m_fRotationCur + PI; - if (m_nPedState == PED_INVESTIGATE) - ClearInvestigateEvent(); - } - - if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) { - m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; - } - break; - - case WAITSTATE_SURPRISE: - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HIT_WALL)) { - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); - animAssoc->SetFinishCallback(FinishedWaitCB, this); - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; - } else { - m_nWaitState = WAITSTATE_FALSE; - } - } - break; - - case WAITSTATE_STUCK: - if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) - break; - - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); - - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_TURN_180); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); - - if (animAssoc) { - if (animAssoc->IsPartial()) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } else { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); - } - - if (animAssoc->animId == ANIM_TURN_180) { - m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur); - m_nWaitState = WAITSTATE_FALSE; - SetMoveState(PEDMOVE_WALK); - m_nStoredMoveState = PEDMOVE_NONE; - m_panicCounter = 0; - return; - } - } - - AnimationId animToPlay; - - switch (CGeneral::GetRandomNumber() & 3) { - case 0: - animToPlay = ANIM_ROAD_CROSS; - break; - case 1: - animToPlay = ANIM_IDLE_TIRED; - break; - case 2: - animToPlay = ANIM_XPRESS_SCRATCH; - break; - case 3: - animToPlay = ANIM_TURN_180; - break; - default: - break; - } - - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); - - if (animToPlay == ANIM_TURN_180) - animAssoc->SetFinishCallback(FinishedWaitCB, this); - - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000); - break; - - case WAITSTATE_LOOK_ABOUT: - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - m_nWaitState = WAITSTATE_FALSE; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - } - break; - - case WAITSTATE_PLAYANIM_HANDSUP: - mustHaveAnim = ANIM_HANDSUP; - - case WAITSTATE_PLAYANIM_HANDSCOWER: - if (mustHaveAnim == NUM_ANIMS) - mustHaveAnim = ANIM_HANDSCOWER; - - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim); - pedWeLook = (CPed*) m_pLookTarget; - - if ((!m_pLookTarget || !m_pLookTarget->IsPed() || pedWeLook->m_pPointGunAt) - && m_nPedState != PED_FLEE_ENTITY - && m_nPedState != PED_ATTACK - && CTimer::GetTimeInMilliseconds() <= m_nWaitTimer - && animAssoc) { - - TurnBody(); - } else { - m_nWaitState = WAITSTATE_FALSE; - m_nWaitTimer = 0; - if (m_pLookTarget && m_pLookTarget->IsPed()) { - - if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_ATTACK) { - - if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) { - - if (GetWeapon()->IsTypeMelee()) { -#ifdef VC_PED_PORTS - if(m_pedStats->m_flags & STAT_GUN_PANIC) { -#endif - SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); - if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { - - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - } - if (m_nMoveState != PEDMOVE_RUN) - SetMoveState(PEDMOVE_WALK); - - if (m_nPedType != PEDTYPE_COP) { - ProcessObjective(); - SetMoveState(PEDMOVE_WALK); - } -#ifdef VC_PED_PORTS - } else { - SetObjective(OBJECTIVE_NONE); - SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); - } -#endif - } else { - SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget); - SetObjectiveTimer(20000); - } - } else { - SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); - if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) - { - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - } - SetMoveState(PEDMOVE_RUN); - Say(SOUND_PED_FLEE_RUN); - } - } - } - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim); - if (animAssoc) { - animAssoc->blendDelta = -4.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - } - break; - case WAITSTATE_PLAYANIM_COWER: - mustHaveAnim = ANIM_HANDSCOWER; - - case WAITSTATE_PLAYANIM_DUCK: - if (mustHaveAnim == NUM_ANIMS) - mustHaveAnim = ANIM_DUCK_DOWN; - - case WAITSTATE_PLAYANIM_TAXI: - if (mustHaveAnim == NUM_ANIMS) - mustHaveAnim = ANIM_IDLE_TAXI; - - case WAITSTATE_PLAYANIM_CHAT: - if (mustHaveAnim == NUM_ANIMS) - mustHaveAnim = ANIM_IDLE_CHAT; - - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim); - if (animAssoc) { - animAssoc->blendDelta = -4.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - m_nWaitState = WAITSTATE_FALSE; - } -#ifdef VC_PED_PORTS - else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) { - if (m_pedInObjective) { - if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { - - // VC also calls CleanUpOldReference here for old LookTarget. - m_pLookTarget = m_pedInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - TurnBody(); - } - } - } -#endif - break; - - case WAITSTATE_FINISH_FLEE: - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); - if (animAssoc) { - if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); - int timer = 2000; - m_nWaitState = WAITSTATE_FALSE; - SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer); - } - } else { - m_nWaitState = WAITSTATE_FALSE; - } - break; - default: - break; - } - - if(!m_nWaitState) - RestoreHeadingRate(); -} - -bool -CPed::Seek(void) -{ - float distanceToCountItDone = m_distanceToCountSeekDone; - eMoveState nextMove = PEDMOVE_NONE; - - if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { - - if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT && - m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) { - - if ((!m_pedInObjective || !m_pedInObjective->bInVehicle) - && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) { - - CEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil, - false, true, false, false, false, false); - - if (obstacle) { - if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) { - distanceToCountItDone = 2.5f; - } else { - CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex()); - float yLength = vehModel->GetColModel()->boundingBox.max.y - - vehModel->GetColModel()->boundingBox.min.y; - distanceToCountItDone = yLength * 0.55f; - } - } - } - } - } - - if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY) - ClearSeek(); - - float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D(); - if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) { - - if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { - - if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) - nextMove = m_pedInObjective->m_nMoveState; - } else - nextMove = PEDMOVE_WALK; - - } else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { - - if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning) - nextMove = PEDMOVE_RUN; - else - nextMove = PEDMOVE_WALK; - - } else if (seekPosDist <= 2.0f) { - - if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) - nextMove = m_pedInObjective->m_nMoveState; - - } else { - nextMove = PEDMOVE_RUN; - } - - if (m_nPedState == PED_SEEK_ENTITY) { - if (m_pSeekTarget->IsPed()) { - if (((CPed*)m_pSeekTarget)->bInVehicle) - distanceToCountItDone += 2.0f; - } - } - - if (seekPosDist >= distanceToCountItDone) { - if (bIsRunning) - nextMove = PEDMOVE_RUN; - - if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) { - - if (m_actionX != 0.0f && m_actionY != 0.0f) { - - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - m_actionX, m_actionY, - GetPosition().x, GetPosition().y); - - float neededTurn = Abs(m_fRotationDest - m_fRotationCur); - - if (neededTurn > PI) - neededTurn = TWOPI - neededTurn; - - if (neededTurn > HALFPI) { - if (seekPosDist >= 1.0f) { - if (seekPosDist < 2.0f) { - if (bIsRunning) - nextMove = PEDMOVE_RUN; - else - nextMove = PEDMOVE_WALK; - } - } else { - nextMove = PEDMOVE_STILL; - } - } - - CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY); - if (moveDist.Magnitude() < 0.5f) { - m_nPedStateTimer = 0; - m_actionX = 0; - m_actionY = 0; - } - } - } else { - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - m_vecSeekPos.x, m_vecSeekPos.y, - GetPosition().x, GetPosition().y); - - float neededTurn = Abs(m_fRotationDest - m_fRotationCur); - - if (neededTurn > PI) - neededTurn = TWOPI - neededTurn; - - if (neededTurn > HALFPI) { - if (seekPosDist >= 1.0 && neededTurn <= DEGTORAD(135.0f)) { - if (seekPosDist < 2.0f) - nextMove = PEDMOVE_WALK; - } else { - nextMove = PEDMOVE_STILL; - } - } - } - - if (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove) - || (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) { - - SetMoveState(nextMove); - } - - SetMoveAnim(); - return false; - } - - if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) { - m_nPedStateTimer = 0; - m_actionX = 0; - m_actionY = 0; - } - - if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) { - if (m_pNextPathNode) - m_pNextPathNode = nil; - else - bScriptObjectiveCompleted = true; - - bUsePedNodeSeek = true; - } - - if (SeekFollowingPath(nil)) - m_nCurPathNode++; - - return true; -} - -bool -CPed::SeekFollowingPath(CVector *unused) -{ - return m_nCurPathNode <= m_nPathNodes && m_nPathNodes; -} - -void -CPed::Flee(void) -{ - if (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) { - bool mayFinishFleeing = true; - if (m_nPedState == PED_FLEE_ENTITY) { - if ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < sq(30.0f)) - mayFinishFleeing = false; - } - - if (mayFinishFleeing) { - eMoveState moveState = m_nMoveState; - ClearFlee(); - - if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) - RestorePreviousObjective(); - - if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) { - SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil); - } - return; - } - m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000; - } - - if (bUsePedNodeSeek) { - CPathNode *realLastNode = nil; - uint8 nextDirection = 0; - uint8 curDirectionShouldBe = 9; // means not defined yet - - if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds() - && m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) { - - if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) { - - curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y); - if (m_nPathDir < curDirectionShouldBe) - m_nPathDir += 8; - - int dirDiff = m_nPathDir - curDirectionShouldBe; - if (dirDiff > 2 && dirDiff < 6) { - realLastNode = nil; - m_pLastPathNode = m_pNextPathNode; - m_pNextPathNode = nil; - } - } - - if (m_pNextPathNode) { - m_vecSeekPos = m_pNextPathNode->GetPosition(); - if (m_nMoveState == PEDMOVE_RUN) - bIsRunning = true; - - eMoveState moveState = m_nMoveState; - if (Seek()) { - realLastNode = m_pLastPathNode; - m_pLastPathNode = m_pNextPathNode; - m_pNextPathNode = nil; - } - bIsRunning = false; - SetMoveState(moveState); - } - } - - if (!m_pNextPathNode) { - if (curDirectionShouldBe == 9) { - curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y); - } - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, - curDirectionShouldBe, - &nextDirection); - - if (curDirectionShouldBe < nextDirection) - curDirectionShouldBe += 8; - - if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) { - m_nPathDir = nextDirection; - m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000; - } else { - bUsePedNodeSeek = false; - SetMoveState(PEDMOVE_RUN); - Flee(); - } - } - return; - } - - if ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) { - - float angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints( - GetPosition().x, - GetPosition().y, - ms_vec2DFleePosition.x, - ms_vec2DFleePosition.y); - - m_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos); - - if (m_fRotationCur - PI > m_fRotationDest) - m_fRotationDest += TWOPI; - else if (PI + m_fRotationCur < m_fRotationDest) - m_fRotationDest -= TWOPI; - } - - if (CTimer::GetTimeInMilliseconds() & 0x20) { - //CVector forwardPos = GetPosition(); - CMatrix forwardMat(GetMatrix()); - forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f)); - CVector forwardPos = forwardMat.GetPosition(); - - CEntity *foundEnt; - CColPoint foundCol; - bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0); - - if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) { - m_fRotationDest += DEGTORAD(112.5f); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000; - } - } - - if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer) - return; - - if (!m_collidingEntityWhileFleeing) - return; - - double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500; - - if (collidingThingPriorityMult <= 1.5) { - - double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints( - GetPosition().x, - GetPosition().y, - m_collidingEntityWhileFleeing->GetPosition().x, - m_collidingEntityWhileFleeing->GetPosition().y); - angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity); - - double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints( - m_vecDamageNormal.x, - m_vecDamageNormal.y, - 0.0f, - 0.0f); - angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing); - - if (angleToFleeEntity - PI > angleToFleeCollidingThing) - angleToFleeCollidingThing += TWOPI; - else if (PI + angleToFleeEntity < angleToFleeCollidingThing) - angleToFleeCollidingThing -= TWOPI; - - if (collidingThingPriorityMult <= 1.0f) { - // Range [0.0, 1.0] - - float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f; - - if (m_fRotationDest - PI > angleToFleeBoth) - angleToFleeBoth += TWOPI; - else if (PI + m_fRotationDest < angleToFleeBoth) - angleToFleeBoth -= TWOPI; - - m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth; - } else { - // Range (1.0, 1.5] - - double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f; - m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing; - } - } else { - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - m_vecDamageNormal.x, - m_vecDamageNormal.y, - 0.0f, - 0.0f); - m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); - } - - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - - if (m_fRotationCur - PI > m_fRotationDest) - m_fRotationDest += TWOPI; - else if (PI + m_fRotationCur < m_fRotationDest) - m_fRotationDest -= TWOPI; - -} - -void -CPed::FollowPath(void) -{ - m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x; - m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y; - m_vecSeekPos.z = GetPosition().z; - - // Mysterious code -/* int v4 = 0; - int maxNodeIndex = m_nPathNodes - 1; - if (maxNodeIndex > 0) { - if (maxNodeIndex > 8) { - while (v4 < maxNodeIndex - 8) - v4 += 8; - } - - while (v4 < maxNodeIndex) - v4++; - - } -*/ - if (Seek()) { - m_nCurPathNode++; - if (m_nCurPathNode == m_nPathNodes) - RestorePreviousState(); - } -} - -CVector -CPed::GetFormationPosition(void) -{ - if (m_pedInObjective->m_nPedState == PED_DEAD) { - if (!m_pedInObjective->m_pedInObjective) { - m_pedInObjective = nil; - return GetPosition(); - } - m_pedInObjective = m_pedInObjective->m_pedInObjective; - } - - CVector formationOffset; - switch (m_pedFormation) { - case FORMATION_REAR: - formationOffset = CVector(0.0f, -1.5f, 0.0f); - break; - case FORMATION_REAR_LEFT: - formationOffset = CVector(-1.5f, -1.5f, 0.0f); - break; - case FORMATION_REAR_RIGHT: - formationOffset = CVector(1.5f, -1.5f, 0.0f); - break; - case FORMATION_FRONT_LEFT: - formationOffset = CVector(-1.5f, 1.5f, 0.0f); - break; - case FORMATION_FRONT_RIGHT: - formationOffset = CVector(1.5f, 1.5f, 0.0f); - break; - case FORMATION_LEFT: - formationOffset = CVector(-1.5f, 0.0f, 0.0f); - break; - case FORMATION_RIGHT: - formationOffset = CVector(1.5f, 0.0f, 0.0f); - break; - case FORMATION_FRONT: - formationOffset = CVector(0.0f, 1.5f, 0.0f); - break; - default: - formationOffset = CVector(0.0f, 0.0f, 0.0f); - break; - } - return formationOffset + m_pedInObjective->GetPosition(); -} - -void -CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen) -{ - CVector *enterOffset = nil; - if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver - || m_vehEnterType == CAR_DOOR_RF && veh->pPassengers[0] - || m_vehEnterType == CAR_DOOR_LR && veh->pPassengers[1] - || m_vehEnterType == CAR_DOOR_RR && veh->pPassengers[2]) - { - enterOffset = &vecPedQuickDraggedOutCarAnimOffset; - } - - CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF); - CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); - - // Left front door is closer - if ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) { - - if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { - m_vehEnterType = CAR_DOOR_LF; - posToOpen = lfPos; - } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { - m_vehEnterType = CAR_DOOR_RF; - posToOpen = rfPos; - } - } else { - - if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { - - CPed *rfPassenger = veh->pPassengers[0]; - if (rfPassenger && (rfPassenger->m_leader == this || rfPassenger->bDontDragMeOutCar || - veh->VehicleCreatedBy == MISSION_VEHICLE && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) - && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) - || (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { - - m_vehEnterType = CAR_DOOR_LF; - posToOpen = lfPos; - } else { - m_vehEnterType = CAR_DOOR_RF; - posToOpen = rfPos; - } - } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { - m_vehEnterType = CAR_DOOR_LF; - posToOpen = lfPos; - } - } -} - -bool -CPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen) -{ - CVector rfPos, lrPos, rrPos; - bool canEnter = false; - - CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex()); - - switch (veh->GetModelIndex()) { - case MI_BUS: - m_vehEnterType = CAR_DOOR_RF; - posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); - return true; - case MI_RHINO: - default: - break; - } - - CVector2D rfPosDist(999.0f, 999.0f); - CVector2D lrPosDist(999.0f, 999.0f); - CVector2D rrPosDist(999.0f, 999.0f); - - if (!veh->pPassengers[0] - && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) - && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) { - - rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); - canEnter = true; - rfPosDist = rfPos - GetPosition(); - } - if (vehModel->m_numDoors == 4) { - if (!veh->pPassengers[1] - && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) - && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) { - lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR); - canEnter = true; - lrPosDist = lrPos - GetPosition(); - } - if (!veh->pPassengers[2] - && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) - && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) { - rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR); - canEnter = true; - rrPosDist = rrPos - GetPosition(); - } - - // When the door we should enter is blocked by some object. - if (!canEnter) - veh->ShufflePassengersToMakeSpace(); - } - - CVector2D nextToCompare = rfPosDist; - posToOpen = rfPos; - m_vehEnterType = CAR_DOOR_RF; - if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { - m_vehEnterType = CAR_DOOR_LR; - posToOpen = lrPos; - nextToCompare = lrPosDist; - } - - if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { - m_vehEnterType = CAR_DOOR_RR; - posToOpen = rrPos; - } - return canEnter; -} - -int -CPed::GetNextPointOnRoute(void) -{ - int16 nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint; - - // Route is complete - if (nextPoint < 0 || nextPoint > NUMPEDROUTES || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) { - - switch (m_routeType) { - case PEDROUTE_STOP_WHEN_DONE: - nextPoint = -1; - break; - case PEDROUTE_GO_BACKWARD_WHEN_DONE: - m_routePointsBeingPassed = -m_routePointsBeingPassed; - nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint; - break; - case PEDROUTE_GO_TO_START_WHEN_DONE: - m_routePointsPassed = -1; - nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint; - break; - default: - break; - } - } - return nextPoint; -} - -// These categories are purely random, most of ped models have no correlation. So I don't think making an enum. -uint8 -CPed::GetPedRadioCategory(uint32 modelIndex) -{ - switch (modelIndex) { - case MI_MALE01: - case MI_FEMALE03: - case MI_PROSTITUTE2: - case MI_WORKER1: - case MI_MOD_MAN: - case MI_MOD_WOM: - case MI_ST_WOM: - case MI_FAN_WOM: - return 3; - case MI_TAXI_D: - case MI_PIMP: - case MI_MALE02: - case MI_FEMALE02: - case MI_FATFEMALE01: - case MI_FATFEMALE02: - case MI_DOCKER1: - case MI_WORKER2: - case MI_FAN_MAN2: - return 9; - case MI_GANG01: - case MI_GANG02: - case MI_SCUM_MAN: - case MI_SCUM_WOM: - case MI_HOS_WOM: - case MI_CONST1: - return 1; - case MI_GANG03: - case MI_GANG04: - case MI_GANG07: - case MI_GANG08: - case MI_CT_MAN2: - case MI_CT_WOM2: - case MI_B_MAN3: - case MI_SHOPPER3: - return 4; - case MI_GANG05: - case MI_GANG06: - case MI_GANG11: - case MI_GANG12: - case MI_CRIMINAL02: - case MI_B_WOM2: - case MI_ST_MAN: - case MI_HOS_MAN: - return 5; - case MI_FATMALE01: - case MI_LI_MAN2: - case MI_SHOPPER1: - case MI_CAS_MAN: - return 6; - case MI_PROSTITUTE: - case MI_P_WOM2: - case MI_LI_WOM2: - case MI_B_WOM3: - case MI_CAS_WOM: - return 2; - case MI_P_WOM1: - case MI_DOCKER2: - case MI_STUD_MAN: - return 7; - case MI_CT_MAN1: - case MI_CT_WOM1: - case MI_LI_MAN1: - case MI_LI_WOM1: - case MI_B_MAN1: - case MI_B_MAN2: - case MI_B_WOM1: - case MI_SHOPPER2: - case MI_STUD_WOM: - return 8; - default: - return 0; - } -} - -// Some kind of VC leftover I think -int -CPed::GetWeaponSlot(eWeaponType weaponType) -{ - if (HasWeapon(weaponType)) - return weaponType; - else - return -1; -} - -void -CPed::GoToNearestDoor(CVehicle *veh) -{ - CVector posToOpen; - GetNearestDoor(veh, posToOpen); - SetSeek(posToOpen, 0.5f); - SetMoveState(PEDMOVE_RUN); -} - -bool -CPed::HaveReachedNextPointOnRoute(float distToCountReached) -{ - if ((m_nextRoutePointPos - GetPosition()).Magnitude2D() >= distToCountReached) - return false; - - m_routePointsPassed += m_routePointsBeingPassed; - return true; -} - -void -CPed::Idle(void) -{ - CVehicle *veh = m_pMyVehicle; - if (veh && veh->m_nGettingOutFlags && m_vehEnterType) { - - if (veh->m_nGettingOutFlags & GetCarDoorFlag(m_vehEnterType)) { - - if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { - - CVector doorPos = GetPositionToOpenCarDoor(veh, m_vehEnterType); - CVector doorDist = GetPosition() - doorPos; - - if (doorDist.MagnitudeSqr() < sq(0.5f)) { - SetMoveState(PEDMOVE_WALK); - return; - } - } - } - } - - CAnimBlendAssociation *armedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED); - CAnimBlendAssociation *unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); - int waitTime; - - if (m_nMoveState == PEDMOVE_STILL) { - - eWeaponType curWeapon = GetWeapon()->m_eWeaponType; - if (!armedIdleAssoc || - CTimer::GetTimeInMilliseconds() <= m_nWaitTimer && curWeapon != WEAPONTYPE_UNARMED && curWeapon != WEAPONTYPE_MOLOTOV && curWeapon != WEAPONTYPE_GRENADE) { - - if ((!GetWeapon()->IsType2Handed() || curWeapon == WEAPONTYPE_SHOTGUN) && curWeapon != WEAPONTYPE_BASEBALLBAT - || !unarmedIdleAssoc || unarmedIdleAssoc->blendAmount <= 0.95f || m_nWaitState != WAITSTATE_FALSE || CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { - - m_moved = CVector2D(0.0f, 0.0f); - return; - } - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_ARMED, 3.0f); - waitTime = CGeneral::GetRandomNumberInRange(4000, 7500); - } else { - armedIdleAssoc->blendDelta = -2.0f; - armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT; - waitTime = CGeneral::GetRandomNumberInRange(3000, 8500); - } - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + waitTime; - } else { - if (armedIdleAssoc) { - armedIdleAssoc->blendDelta = -8.0f; - armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT; - m_nWaitTimer = 0; - } - if (!IsPlayer()) - SetMoveState(PEDMOVE_STILL); - } - m_moved = CVector2D(0.0f, 0.0f); -} - -void -CPed::InTheAir(void) -{ - CColPoint foundCol; - CEntity *foundEnt; - - CVector ourPos = GetPosition(); - CVector bitBelow = GetPosition(); - bitBelow.z -= 4.04f; - - if (m_vecMoveSpeed.z < 0.0f && !bIsPedDieAnimPlaying) { - if (!DyingOrDead()) { - if (CWorld::ProcessLineOfSight(ourPos, bitBelow, foundCol, foundEnt, true, true, false, true, false, false, false)) { - if (GetPosition().z - foundCol.point.z < 1.3f -#ifdef VC_PED_PORTS - || bIsStanding -#endif - ) - SetLanding(); - } else { - if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)) { - if (m_vecMoveSpeed.z < -0.1f) - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_FALL, 4.0f); - } - } - } - } -} - -void -CPed::SetLanding(void) -{ - if (DyingOrDead()) - return; - - CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL); - CAnimBlendAssociation *landAssoc; - - RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); - if (fallAssoc) { - landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_COLLAPSE); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f); - - if (IsPlayer()) - Say(SOUND_PED_LAND); - - } else { - landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f); - } - - landAssoc->SetFinishCallback(PedLandCB, this); - bIsInTheAir = false; - bIsLanding = true; -} - -void -CPed::Initialise(void) -{ - debug("Initialising CPed...\n"); - CPedType::Initialise(); - LoadFightData(); - SetAnimOffsetForEnterOrExitVehicle(); - debug("CPed ready\n"); -} - -void -CPed::SetAnimOffsetForEnterOrExitVehicle(void) -{ - // FIX: If there were no translations on enter anims, there were overflows all over this function. - - CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy; - CAnimBlendSequence *seq = enterAssoc->sequences; - CAnimManager::UncompressAnimation(enterAssoc); - if (seq->numFrames > 0) { - if (!seq->HasTranslation()) - vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f); - else { - KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); - vecPedDraggedOutCarAnimOffset = lastFrame->translation; - } - } - - enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LHS)->hierarchy; - seq = enterAssoc->sequences; - CAnimManager::UncompressAnimation(enterAssoc); - if (seq->numFrames > 0) { - if (!seq->HasTranslation()) - vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f); - else { - KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); - vecPedCarDoorAnimOffset = lastFrame->translation; - } - } - - enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS)->hierarchy; - seq = enterAssoc->sequences; - CAnimManager::UncompressAnimation(enterAssoc); - if (seq->numFrames > 0) { - if (!seq->HasTranslation()) - vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f); - else { - KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); - vecPedCarDoorLoAnimOffset = lastFrame->translation; - } - } - - enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_QJACKED)->hierarchy; - seq = enterAssoc->sequences; - CAnimManager::UncompressAnimation(enterAssoc); - if (seq->numFrames > 0) { - if (!seq->HasTranslation()) - vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f); - else { - KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); - vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation; - } - } - - enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_VAN_GETIN_L)->hierarchy; - seq = enterAssoc->sequences; - CAnimManager::UncompressAnimation(enterAssoc); - if (seq->numFrames > 0) { - if (!seq->HasTranslation()) - vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f); - else { - KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); - vecPedVanRearDoorAnimOffset = lastFrame->translation; - } - } - - enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_TRAIN_GETOUT)->hierarchy; - seq = enterAssoc->sequences; - CAnimManager::UncompressAnimation(enterAssoc); - if (seq->numFrames > 0) { - if (!seq->HasTranslation()) - vecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f); - else { - KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); - vecPedTrainDoorAnimOffset = lastFrame->translation; - } - } -} - -void -CPed::InvestigateEvent(void) -{ - CAnimBlendAssociation *animAssoc; - AnimationId animToPlay; - AssocGroupId animGroup; - - if (m_nWaitState == WAITSTATE_TURN180) - return; - - if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { - - if (m_standardTimer) { - if (m_eventType < EVENT_ASSAULT_NASTYWEAPON) - SetWaitState(WAITSTATE_TURN180, nil); - - m_standardTimer = 0; - } else { - ClearInvestigateEvent(); - } - return; - } - - CVector2D vecDist = m_eventOrThreat - GetPosition(); - float distSqr = vecDist.MagnitudeSqr(); - if (sq(m_distanceToCountSeekDone) >= distSqr) { - - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f); - SetMoveState(PEDMOVE_STILL); - - switch (m_eventType) { - case EVENT_DEAD_PED: - case EVENT_HIT_AND_RUN: - case EVENT_HIT_AND_RUN_COP: - - if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); - - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - if (m_pEventEntity) - SetLookFlag(m_pEventEntity, true); - - SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000)); - - } else if (CGeneral::GetRandomNumber() & 3) { - ClearLookFlag(); - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f); - - SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); - Say(SOUND_PED_CHAT_EVENT); - - } else { - ClearInvestigateEvent(); - } - } - break; - case EVENT_FIRE: - case EVENT_EXPLOSION: - - if (bHasACamera && CTimer::GetTimeInMilliseconds() > m_lookTimer) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CAM); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); - - if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) { - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); - - } else if (CGeneral::GetRandomNumber() & 3) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CAM, 4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000)); - Say(SOUND_PED_CHAT_EVENT); - - } else { - m_standardTimer = 0; - } - - } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); - - if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); - - if (animAssoc && animAssoc->animId == ANIM_IDLE_STANCE) { - if (CGeneral::GetRandomNumber() & 1) - animToPlay = ANIM_IDLE_HBHB; - else - animToPlay = ANIM_XPRESS_SCRATCH; - - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000)); - - } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - if (CGeneral::GetRandomNumber() & 1) { - animToPlay = ANIM_IDLE_STANCE; - animGroup = m_animGroup; - } else { - animToPlay = ANIM_XPRESS_SCRATCH; - animGroup = ASSOCGRP_STD; - } - - CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); - - } else { - if (CGeneral::GetRandomNumber() & 1) { - animToPlay = ANIM_IDLE_STANCE; - animGroup = m_animGroup; - } else { - animToPlay = ANIM_IDLE_HBHB; - animGroup = ASSOCGRP_STD; - } - - CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); - } - Say(SOUND_PED_CHAT_EVENT); - } - break; - case EVENT_ICECREAM: - case EVENT_SHOPSTALL: - - m_fRotationDest = m_fAngleToEvent; - if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { - - if (m_lookTimer) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); - - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - if (m_eventType == EVENT_ICECREAM) - animToPlay = ANIM_IDLE_CHAT; - else - animToPlay = ANIM_XPRESS_SCRATCH; - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); - - } else { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - ClearInvestigateEvent(); - } else { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); - if (animAssoc) { - animAssoc->blendDelta = -8.0f; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - ClearInvestigateEvent(); - } - } - } else { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); - } - } - break; - default: - return; - } - } else { - m_vecSeekPos.x = m_eventOrThreat.x; - m_vecSeekPos.y = m_eventOrThreat.y; - m_vecSeekPos.z = GetPosition().z; - Seek(); - - if (m_eventType < EVENT_ICECREAM) { - if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) { - SetMoveState(PEDMOVE_RUN); - return; - } - } - if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) { - SetMoveState(PEDMOVE_WALK); - return; - } - if (distSqr > sq(1.2f)) { - SetMoveState(PEDMOVE_WALK); - return; - } - - for (int i = 0; i < m_numNearPeds; i++) { - if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) { - SetMoveState(PEDMOVE_STILL); - return; - } - } - - SetMoveState(PEDMOVE_WALK); - } -} - -bool -CPed::IsPedDoingDriveByShooting(void) -{ - if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) { - if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight) - return true; - } - return false; -} - -bool -CPed::IsPedShootable(void) -{ - return m_nPedState <= PED_STATES_NO_ST; -} - -bool -CPed::IsRoomToBeCarJacked(void) -{ - if (!m_pMyVehicle) - return false; - - CVector offset; - if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) { - offset = vecPedDraggedOutCarAnimOffset; - } else { - offset = vecPedQuickDraggedOutCarAnimOffset; - } - - offset.z = 0.0f; - if (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &offset)) { - return true; - } - - return false; -} - -void -CPed::KillPedWithCar(CVehicle *car, float impulse) -{ - CVehicleModelInfo *vehModel; - CColModel *vehColModel; - uint8 damageDir; - PedNode nodeToDamage; - eWeaponType killMethod; - - if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) { - if (!this->m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER) - this->m_pCollidingEntity = car; - return; - } - - if (m_nPedState == PED_DEAD) - return; - - if (m_pCurSurface) { - if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer())) - return; - } - - CVector distVec = GetPosition() - car->GetPosition(); - - if ((impulse > 12.0f || car->GetModelIndex() == MI_TRAIN) && !IsPlayer()) { - nodeToDamage = PED_TORSO; - killMethod = WEAPONTYPE_RAMMEDBYCAR; - uint8 randVal = CGeneral::GetRandomNumber() & 3; - - if (car == FindPlayerVehicle()) { - float carSpeed = car->m_vecMoveSpeed.Magnitude(); - uint8 shakeFreq; - if (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) { - shakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f; - } else { - shakeFreq = 250.0f; - } - CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq); - } - bIsStanding = false; - damageDir = GetLocalDirection(-m_vecMoveSpeed); - vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex()); - vehColModel = vehModel->GetColModel(); - float carRightAndDistDotProd = DotProduct(distVec, car->GetRight()); - - if (car->GetModelIndex() == MI_TRAIN) { - killMethod = WEAPONTYPE_RUNOVERBYCAR; - nodeToDamage = PED_HEAD; - m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed; - m_vecMoveSpeed.z = 0.0f; - if (damageDir == 1 || damageDir == 3) - damageDir = 2; - if (CGame::nastyGame) - DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f); - - // Car doesn't look to us - } else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){ - - if (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) { - - // We're at the right of the car - if (carRightAndDistDotProd <= 0.0f) - nodeToDamage = PED_UPPERARML; - else - nodeToDamage = PED_UPPERARMR; - - if (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) { - killMethod = WEAPONTYPE_RUNOVERBYCAR; - m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed; - m_vecMoveSpeed.z = 0.0f; - if (damageDir == 1 || damageDir == 3) - damageDir = 2; - if (CGame::nastyGame) - DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f); - - } - } else { - float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward()); - - // carFrontAndDistDotProd <= 0.0 car looks to us - if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) { - killMethod = WEAPONTYPE_RUNOVERBYCAR; - nodeToDamage = PED_HEAD; - m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed; - m_vecMoveSpeed.z = 0.0f; - if (damageDir == 1 || damageDir == 3) - damageDir = 2; - - if (CGame::nastyGame) - DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f); - - } else { - nodeToDamage = PED_MID; - float vehColMaxY = vehColModel->boundingBox.max.y; - float vehColMinY = vehColModel->boundingBox.min.y; - float vehColMaxZ = vehColModel->boundingBox.max.z; - float carFrontZ = car->GetForward().z; - float carHighestZ, carLength; - - if (carFrontZ < -0.2f) { - // Highest point of car's back - carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z; - carLength = vehColMaxY - vehColMinY; - - } else if (carFrontZ > 0.1f) { - // Highest point of car's front - carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z; - float highestZDist = carHighestZ - GetPosition().z; - if (highestZDist > 0.0f) { - GetMatrix().GetPosition().z += 0.5f * highestZDist; - carHighestZ += highestZDist * 0.25f; - } - carLength = vehColMaxY; - - } else { - // Highest point of car's front - carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z; - carLength = vehColMaxY; - } - - float pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude()); - - // TODO: What are we doing down here? - float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ; - - // After this point, distVec isn't distVec anymore. - distVec = car->m_vecMoveSpeed; - distVec.Normalise(); - distVec *= 0.2 * unknown; - - if (damageDir != 1 && damageDir != 3) - distVec.z += unknown; - else - distVec.z += 1.5f * unknown; - - m_vecMoveSpeed = distVec; - damageDir += 2; - if (damageDir > 3) - damageDir = damageDir - 4; - - if (car->m_vehType == VEHICLE_TYPE_CAR) { - CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision(); - - if (bonnet) { - if (CGeneral::GetRandomNumber() & 1) { - bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f)); - } else { - bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f)); - } - CVector forceDir = car->GetUp() * 10.0f; - bonnet->ApplyTurnForce(forceDir, car->GetForward()); - } - } - } - } - } - - if (car->pDriver) { - CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000); - } - - ePedPieceTypes pieceToDamage; - switch (nodeToDamage) { - case PED_HEAD: - pieceToDamage = PEDPIECE_HEAD; - break; - case PED_UPPERARML: - pieceToDamage = PEDPIECE_LEFTARM; - break; - case PED_UPPERARMR: - pieceToDamage = PEDPIECE_RIGHTARM; - break; - default: - pieceToDamage = PEDPIECE_MID; - break; - } - InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir); - - if (DyingOrDead() - && bIsPedDieAnimPlaying && !m_pCollidingEntity) { - m_pCollidingEntity = car; - } - if (nodeToDamage == PED_MID) - bKnockedUpIntoAir = true; - else - bKnockedUpIntoAir = false; - - distVec.Normalise(); - -#ifdef VC_PED_PORTS - distVec *= Min(car->m_fMass / 1400.0f, 1.0f); -#endif - car->ApplyMoveForce(distVec * -100.0f); - Say(SOUND_PED_DEFEND); - - } else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f - || impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) { - - bIsStanding = false; - uint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed); - float damage; - if (IsPlayer() && car->GetModelIndex() == MI_TRAIN) - damage = 150.0f; - else - damage = 30.0f; - - InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection); - SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true); - - if (OnGround() && !m_pCollidingEntity && - (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) { - - m_pCollidingEntity = car; - } - - bKnockedUpIntoAir = false; - if (car->GetModelIndex() != MI_TRAIN && !bHasHitWall) { - m_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f; - } - m_vecMoveSpeed.z = 0.0f; - distVec.Normalise(); -#ifdef VC_PED_PORTS - distVec *= Min(car->m_fMass / 1400.0f, 1.0f); -#endif - car->ApplyMoveForce(distVec * -60.0f); - Say(SOUND_PED_DEFEND); - } - -#ifdef VC_PED_PORTS - // Killing gang members with car wasn't triggering a fight, until now... Taken from VC. - if (IsGangMember()) { - CPed *driver = car->pDriver; - if (driver && driver->IsPlayer() -#ifdef FIX_BUGS - && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats) && (!m_leader || m_leader != driver) -#endif - ) { - RegisterThreatWithGangPeds(driver); - } - } -#endif -} - -void -CPed::Look(void) -{ - // UNUSED: This is a perfectly empty function. -} - -bool -CPed::LookForInterestingNodes(void) -{ - CBaseModelInfo *model; - CPtrNode *ptrNode; - CVector effectDist; - C2dEffect *effect; - CMatrix *objMat; - - if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_standardTimer) { - return false; - } - bool found = false; - uint8 randVal = CGeneral::GetRandomNumber() % 256; - - int minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST); - if (minX < 0) minX = 0; - int minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST); - if (minY < 0) minY = 0; - int maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST); -#ifdef FIX_BUGS - if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; -#else - if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; -#endif - - int maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST); -#ifdef FIX_BUGS - if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; -#else - if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; -#endif - - for (int curY = minY; curY <= maxY && !found; curY++) { - for (int curX = minX; curX <= maxX && !found; curX++) { - CSector *sector = CWorld::GetSector(curX, curY); - - for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) { - CVehicle *veh = (CVehicle*)ptrNode->item; - model = veh->GetModelInfo(); - if (model->GetNum2dEffects() != 0) { - for (int e = 0; e < model->GetNum2dEffects(); e++) { - effect = model->Get2dEffect(e); - if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { - objMat = &veh->GetMatrix(); - CVector effectPos = veh->GetMatrix() * effect->pos; - effectDist = effectPos - GetPosition(); - if (effectDist.MagnitudeSqr() < sq(8.0f)) { - found = true; - break; - } - } - } - } - } - for (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) { - CObject *obj = (CObject*)ptrNode->item; - model = CModelInfo::GetModelInfo(obj->GetModelIndex()); - if (model->GetNum2dEffects() != 0) { - for (int e = 0; e < model->GetNum2dEffects(); e++) { - effect = model->Get2dEffect(e); - if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { - objMat = &obj->GetMatrix(); - CVector effectPos = obj->GetMatrix() * effect->pos; - effectDist = effectPos - GetPosition(); - if (effectDist.MagnitudeSqr() < sq(8.0f)) { - found = true; - break; - } - } - } - } - } - for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) { - CBuilding *building = (CBuilding*)ptrNode->item; - model = CModelInfo::GetModelInfo(building->GetModelIndex()); - if (model->GetNum2dEffects() != 0) { - for (int e = 0; e < model->GetNum2dEffects(); e++) { - effect = model->Get2dEffect(e); - if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { - objMat = &building->GetMatrix(); - CVector effectPos = building->GetMatrix() * effect->pos; - effectDist = effectPos - GetPosition(); - if (effectDist.MagnitudeSqr() < sq(8.0f)) { - found = true; - break; - } - } - } - } - } - for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) { - CBuilding *building = (CBuilding*)ptrNode->item; - model = CModelInfo::GetModelInfo(building->GetModelIndex()); - if (model->GetNum2dEffects() != 0) { - for (int e = 0; e < model->GetNum2dEffects(); e++) { - effect = model->Get2dEffect(e); - if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { - objMat = &building->GetMatrix(); - CVector effectPos = building->GetMatrix() * effect->pos; - effectDist = effectPos - GetPosition(); - if (effectDist.MagnitudeSqr() < sq(8.0f)) { - found = true; - break; - } - } - } - } - } - } - } - - if (!found) - return false; - - CVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir); - float angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f); - randVal = CGeneral::GetRandomNumber() % 256; - if (randVal <= m_randomSeed % 256) { - m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000; - SetLookFlag(angleToFace, true); - SetLookTimer(1000); - return false; - } - - CVector2D effectPos = *objMat * effect->pos; - switch (effect->attractor.type) { - case ATTRACTORTYPE_ICECREAM: - SetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace); - break; - case ATTRACTORTYPE_STARE: - SetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f, - CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500), - angleToFace); - break; - default: - return true; - } - return true; -} - -void -CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle) -{ - if (!IsPedInControl() || CharCreatedBy == MISSION_CHAR) - return; - - SetStoredState(); - bFindNewNodeAfterStateRestore = false; - m_nPedState = PED_INVESTIGATE; - m_standardTimer = CTimer::GetTimeInMilliseconds() + time; - m_eventType = event; - m_eventOrThreat = pos; - m_distanceToCountSeekDone = distanceToCountDone; - m_fAngleToEvent = angle; - - if (m_eventType >= EVENT_ICECREAM) - m_lookTimer = 0; - else - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 4.0f); - -} - -void -CPed::LookForSexyCars(void) -{ - CEntity *vehicles[8]; - CVehicle *veh; - int foundVehId = 0; - int bestPriceYet = 0; - int16 lastVehicle; - - if (!IsPedInControl() && m_nPedState != PED_DRIVING) - return; - - if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { - CWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - - for (int vehId = 0; vehId < lastVehicle; vehId++) { - veh = (CVehicle*)vehicles[vehId]; - if (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) { - foundVehId = vehId; - bestPriceYet = veh->pHandling->nMonetaryValue; - } - } - if (lastVehicle > 0 && bestPriceYet > 40000) - SetLookFlag(vehicles[foundVehId], false); - - m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000; - } -} - -void -CPed::LookForSexyPeds(void) -{ - if ((!IsPedInControl() && m_nPedState != PED_DRIVING) - || m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE) - return; - - for (int i = 0; i < m_numNearPeds; i++) { - if (CanSeeEntity(m_nearPeds[i])) { - if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) { - CPed *nearPed = m_nearPeds[i]; - if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness) - && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) { - - SetLookFlag(nearPed, true); - m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000; - Say(SOUND_PED_CHAT_SEXY); - return; - } - } - } - } - m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000; -} - -void -CPed::MakeTyresMuddySectorList(CPtrList &list) -{ - for (CPtrNode *node = list.first; node; node = node->next) { - CVehicle *veh = (CVehicle*)node->item; - if (veh->IsCar() && veh->m_scanCode != CWorld::GetCurrentScanCode()) { - veh->m_scanCode = CWorld::GetCurrentScanCode(); - - if (Abs(GetPosition().x - veh->GetPosition().x) < 10.0f) { - - if (Abs(GetPosition().y - veh->GetPosition().y) < 10.0f - && veh->m_vecMoveSpeed.MagnitudeSqr2D() > 0.05f) { - - for(int wheel = 0; wheel < 4; wheel++) { - - if (!((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] - && ((CAutomobile*)veh)->m_aSuspensionSpringRatio[wheel] < 1.0f) { - - CColModel *vehCol = veh->GetModelInfo()->GetColModel(); - CVector approxWheelOffset; - switch (wheel) { - case 0: - approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f); - break; - case 1: - approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f); - break; - case 2: - approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f); - break; - case 3: - approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f); - break; - default: - break; - } - - // I hope so - CVector wheelPos = veh->GetMatrix() * approxWheelOffset; - if (Abs(wheelPos.z - GetPosition().z) < 2.0f) { - - if ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) { - if (CGame::nastyGame) { - ((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] = true; - DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_SPLATTER, 0.0f); - } - veh->ApplyMoveForce(CVector(0.0f, 0.0f, 50.0f)); - - CVector vehAndWheelDist = wheelPos - veh->GetPosition(); - veh->ApplyTurnForce(CVector(0.0f, 0.0f, 50.0f), vehAndWheelDist); - - if (veh == FindPlayerVehicle()) { - CPad::GetPad(0)->StartShake(300, 70); - } - } - } - } - } - } - } - } - } -} - -void -CPed::Mug(void) -{ - if (m_pSeekTarget && m_pSeekTarget->IsPed()) { - - if (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) { - if ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f) - m_wepSkills = 50; - - Say(SOUND_PED_MUGGING); - ((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED); - } else { - SetWanderPath(CGeneral::GetRandomNumber() & 7); - SetFlee(m_pSeekTarget, 20000); - } - - } else { - SetIdle(); - } -} - -void -CPed::MoveHeadToLook(void) -{ - CVector lookPos; - - if (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) { - ClearLookFlag(); - } else if (m_nPedState == PED_DRIVING) { - m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY; - } - - if (m_pLookTarget) { - - if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { - - CAnimBlendAssociation *fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU); - if (fuckUAssoc) { - - float animTime = fuckUAssoc->currentTime; - if (animTime > 4.0f / 30.0f && animTime - fuckUAssoc->timeStep > 4.0f / 30.0f) { - - bool lookingToCop = false; - if (m_pLookTarget->GetModelIndex() == MI_POLICE - || m_pLookTarget->IsPed() && ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP) { - - lookingToCop = true; - } - - if (IsPlayer() && (m_pedStats->m_temper >= 52 || lookingToCop)) { - AddWeaponModel(MI_FINGERS); - ((CPlayerPed*)this)->AnnoyPlayerPed(true); - - } else if ((CGeneral::GetRandomNumber() & 3) == 0) { - AddWeaponModel(MI_FINGERS); - } - } - } - } - - if (m_pLookTarget->IsPed()) { - ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID); - } else { - lookPos = m_pLookTarget->GetPosition(); - } - - if (!m_pedIK.LookAtPosition(lookPos)) { - if (!bKeepTryingToLook) { - ClearLookFlag(); - } - return; - } - - if (!bShakeFist || bIsAimingGun || bIsRestoringGun) - return; - - if (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000) - return; - - bool notRocketLauncher = false; - bool notTwoHanded = false; - AnimationId animToPlay = NUM_ANIMS; - - if (!GetWeapon()->IsType2Handed()) - notTwoHanded = true; - - if (notTwoHanded && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER) - notRocketLauncher = true; - - if (IsPlayer() && notRocketLauncher) { - - if (m_pLookTarget->IsPed()) { - - if (m_pedStats->m_temper >= 49 && ((CPed*)m_pLookTarget)->m_nPedType != PEDTYPE_COP) { - - // FIX: Unreachable and meaningless condition -#ifndef FIX_BUGS - if (m_pedStats->m_temper < 47) -#endif - animToPlay = ANIM_FIGHT_PPUNCH; - } else { - animToPlay = ANIM_FUCKU; - } - } else if (m_pedStats->m_temper > 49 || m_pLookTarget->GetModelIndex() == MI_POLICE) { - animToPlay = ANIM_FUCKU; - } - } else if (notRocketLauncher && (CGeneral::GetRandomNumber() & 1)) { - animToPlay = ANIM_FUCKU; - } - - if (animToPlay != NUM_ANIMS) { - CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); - - if (newAssoc) { - newAssoc->flags |= ASSOC_FADEOUTWHENDONE; - newAssoc->flags |= ASSOC_DELETEFADEDOUT; - if (newAssoc->animId == ANIM_FUCKU) - newAssoc->SetDeleteCallback(FinishFuckUCB, this); - } - } - bShakeFist = false; - return; - } else if (999999.0f == m_fLookDirection) { - ClearLookFlag(); - } else if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) { - if (!bKeepTryingToLook) - ClearLookFlag(); - } -} - -void -FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) - ped->RemoveWeaponModel(0); -} - -void -CPed::Pause(void) -{ - m_moved = CVector2D(0.0f, 0.0f); - if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) - ClearPause(); -} - -void -CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - CVehicle *veh = ped->m_pMyVehicle; - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (!ped->IsNotInWreckedVehicle()) - return; - - if (!ped->EnteringCar()) { -#ifdef VC_PED_PORTS - if (ped->m_nPedState != PED_DRIVING) -#endif - ped->QuitEnteringCar(); - - return; - } - if (ped->m_fHealth == 0.0f) { - ped->QuitEnteringCar(); - return; - } - bool itsVan = !!veh->bIsVan; - bool itsBus = !!veh->bIsBus; -#ifdef FIX_BUGS - bool itsLow = !!veh->bLowVehicle; -#endif - eDoors enterDoor; - AnimationId enterAnim; - - switch (ped->m_vehEnterType) { - case CAR_DOOR_RF: - itsVan = false; - enterDoor = DOOR_FRONT_RIGHT; - break; - case CAR_DOOR_RR: - enterDoor = DOOR_REAR_RIGHT; - break; - case CAR_DOOR_LF: - itsVan = false; - enterDoor = DOOR_FRONT_LEFT; - break; - case CAR_DOOR_LR: - enterDoor = DOOR_REAR_LEFT; - break; - default: - break; - } - - if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) { - - veh->AutoPilot.m_nCruiseSpeed = 0; - if (ped->m_nPedState == PED_CARJACK) { - ped->PedAnimDoorOpenCB(nil, ped); - return; - } - if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) { - if (itsVan) { - enterAnim = ANIM_VAN_GETIN; - } else if (itsBus) { - enterAnim = ANIM_COACH_IN_R; -#ifdef FIX_BUGS - } else if (itsLow) { - enterAnim = ANIM_CAR_GETIN_LOW_RHS; -#endif - } else { - enterAnim = ANIM_CAR_GETIN_RHS; - } - } else if (itsVan) { - enterAnim = ANIM_VAN_GETIN_L; - } else if (itsBus) { - enterAnim = ANIM_COACH_IN_L; -#ifdef FIX_BUGS - } else if (itsLow) { - enterAnim = ANIM_CAR_GETIN_LOW_LHS; -#endif - } else { - enterAnim = ANIM_CAR_GETIN_LHS; - } - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterAnim); - ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); - - } else if (veh->CanPedOpenLocks(ped)) { - - veh->AutoPilot.m_nCruiseSpeed = 0; - if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) { - if (itsVan) { - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN); - } else if (itsBus) { - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_R); - } else { - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_RHS); - } - } else if (itsVan) { - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN_L); - } else if (itsBus) { - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L); - } else { - - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) { - - if (!veh->bLowVehicle - && veh->pDriver->CharCreatedBy != MISSION_CHAR - && veh->pDriver->m_nPedState == PED_DRIVING) { - - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_QJACK); - ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); - veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true); - - if (veh->pDriver->IsGangMember()) - veh->pDriver->RegisterThreatWithGangPeds(ped); - return; - } - } - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS); - } - ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped); - - } else { - if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_RHS); - else - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_LHS); - - ped->bCancelEnteringCar = true; - ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped); - } -} - -void -CPed::ProcessControl(void) -{ - CColPoint foundCol; - CEntity *foundEnt = nil; - - if (m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory) - return; - - int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); - if (!bFadeOut) { - if (alpha < 255) { - alpha += 16; - if (alpha > 255) - alpha = 255; - } - } else { - alpha -= 8; - if (alpha < 0) - alpha = 0; - } - - CVisibilityPlugins::SetClumpAlpha(GetClump(), alpha); - bIsShooting = false; - BuildPedLists(); - bIsInWater = false; - ProcessBuoyancy(); - - if (m_nPedState != PED_ARRESTED) { - if (m_nPedState == PED_DEAD) { - DeadPedMakesTyresBloody(); -#ifndef VC_PED_PORTS - if (CGame::nastyGame) { -#else - if (CGame::nastyGame && !bIsInWater) { -#endif - uint32 remainingBloodyFpTime = CTimer::GetTimeInMilliseconds() - m_bloodyFootprintCountOrDeathTime; - float timeDependentDist; - if (remainingBloodyFpTime >= 2000) { - if (remainingBloodyFpTime <= 7000) - timeDependentDist = (remainingBloodyFpTime - 2000) / 5000.0f * 0.75f; - else - timeDependentDist = 0.75f; - } else { - timeDependentDist = 0.0f; - } - - for (int i = 0; i < m_numNearPeds; ++i) { - CPed *nearPed = m_nearPeds[i]; - if (!nearPed->DyingOrDead()) { - CVector dist = nearPed->GetPosition() - GetPosition(); - if (dist.MagnitudeSqr() < sq(timeDependentDist)) { - nearPed->m_bloodyFootprintCountOrDeathTime = 200; - nearPed->bDoBloodyFootprints = true; - if (nearPed->IsPlayer()) { - if (!nearPed->bIsLooking && nearPed->m_nPedState != PED_ATTACK) { - int16 camMode = TheCamera.Cams[TheCamera.ActiveCam].Mode; - if (camMode != CCam::MODE_SNIPER - && camMode != CCam::MODE_ROCKETLAUNCHER - && camMode != CCam::MODE_M16_1STPERSON - && camMode != CCam::MODE_1STPERSON - && camMode != CCam::MODE_HELICANNON_1STPERSON - && !TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn()) { - - nearPed->SetLookFlag(this, true); - nearPed->SetLookTimer(500); - } - } - } - } - } - } - - if (remainingBloodyFpTime > 2000) { - CVector bloodPos = GetPosition(); - if (remainingBloodyFpTime - 2000 >= 5000) { - if (!m_deadBleeding) { - CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, - 0.75f, 0.0f, 0.0f, -0.75f, 255, 255, 0, 0, 4.0f, 40000, 1.0f); - m_deadBleeding = true; - } - } else { - CShadows::StoreStaticShadow( - (uintptr)this + 17, SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, - (remainingBloodyFpTime - 2000) / 5000.0f * 0.75f, 0.0f, - 0.0f, (remainingBloodyFpTime - 2000) / 5000.0f * -0.75f, - 255, 255, 0, 0, 4.0f, 1.0f, 40.0f, false, 0.0f); - } - } - } - if (ServiceTalkingWhenDead()) - ServiceTalking(); - -#ifdef VC_PED_PORTS - if (bIsInWater) { - bIsStanding = false; - bWasStanding = false; - CPhysical::ProcessControl(); - } -#endif - return; - } - - bWasStanding = false; - if (bIsStanding) { - if (!CWorld::bForceProcessControl) { - if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->bIsInSafePosition) { - bWasPostponed = true; - return; - } - } - } - - if (!IsPedInControl() || m_nWaitState != WAITSTATE_FALSE || 0.01f * CTimer::GetTimeStep() <= m_fDistanceTravelled - || (m_nStoredMoveState != PEDMOVE_WALK && m_nStoredMoveState != PEDMOVE_RUN && m_nStoredMoveState != PEDMOVE_SPRINT)) - m_panicCounter = 0; - else if (m_panicCounter < 50) - ++m_panicCounter; - - if (m_fHealth <= 1.0f && m_nPedState <= PED_STATES_NO_AI && !bIsInTheAir && !bIsLanding) - SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - - bCollidedWithMyVehicle = false; - - CEntity *collidingEnt = m_pDamageEntity; -#ifndef VC_PED_PORTS - if (!bUsesCollision || m_fDamageImpulse <= 0.0f || m_nPedState == PED_DIE || !collidingEnt) { -#else - if (!bUsesCollision || ((!collidingEnt || m_fDamageImpulse <= 0.0f) && (!IsPlayer() || !bIsStuck)) || m_nPedState == PED_DIE) { -#endif - bHitSomethingLastFrame = false; - if (m_nPedStateTimer <= 500 && bIsInTheAir) { - if (m_nPedStateTimer) - m_nPedStateTimer--; - } else if (m_nPedStateTimer < 1001) { - m_nPedStateTimer = 0; - } - } else { - if (m_panicCounter == 50 && IsPedInControl()) { - SetWaitState(WAITSTATE_STUCK, nil); - // Leftover - /* - if (m_nPedType < PEDTYPE_COP) { - - } else { - - } - */ -#ifndef VC_PED_PORTS - } else { -#else - } else if (collidingEnt) { -#endif - switch (collidingEnt->GetType()) - { - case ENTITY_TYPE_BUILDING: - case ENTITY_TYPE_OBJECT: - { - CBaseModelInfo *collidingModel = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex()); - CColModel *collidingCol = collidingModel->GetColModel(); - if (collidingEnt->IsObject() && ((CObject*)collidingEnt)->m_nSpecialCollisionResponseCases != COLLRESPONSE_FENCEPART - || collidingCol->boundingBox.max.x < 3.0f - && collidingCol->boundingBox.max.y < 3.0f) { - - if (!IsPlayer()) { - SetDirectionToWalkAroundObject(collidingEnt); - break; - } - } - if (IsPlayer()) { - bHitSomethingLastFrame = true; - break; - } - - float angleToFaceWhenHit = CGeneral::GetRadianAngleBetweenPoints( - GetPosition().x, - GetPosition().y, - m_vecDamageNormal.x + GetPosition().x, - m_vecDamageNormal.y + GetPosition().y); - - float neededTurn = Abs(m_fRotationCur - angleToFaceWhenHit); - - if (neededTurn > PI) - neededTurn = TWOPI - neededTurn; - - float oldDestRot = CGeneral::LimitRadianAngle(m_fRotationDest); - - if (m_pedInObjective && - (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT)) { - - if (m_pedInObjective->IsPlayer() - && (neededTurn < DEGTORAD(20.0f) || m_panicCounter > 10)) { - if (CanPedJumpThis(collidingEnt)) { - SetJump(); - } else if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { - SetWaitState(WAITSTATE_LOOK_ABOUT, nil); - } else { - SetWaitState(WAITSTATE_PLAYANIM_TAXI, nil); - m_headingRate = 0.0f; - SetLookFlag(m_pedInObjective, true); - SetLookTimer(3000); - Say(SOUND_PED_TAXI_CALL); - } - } else { - m_pLookTarget = m_pedInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - TurnBody(); - } - } else { - if (m_nPedType != PEDTYPE_COP && neededTurn < DEGTORAD(15.0f) && m_nWaitState == WAITSTATE_FALSE) { - if ((m_nStoredMoveState == PEDMOVE_RUN || m_nStoredMoveState == PEDMOVE_SPRINT) && m_vecDamageNormal.z < 0.3f) { - CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN); - if (!runAssoc) - runAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT); - - if (runAssoc && runAssoc->blendAmount > 0.9f && runAssoc->IsRunning()) { - SetWaitState(WAITSTATE_HITWALL, nil); - } - } - } - if (m_nPedState == PED_FLEE_POS) { - CVector2D fleePos = collidingEnt->GetPosition(); - uint32 oldFleeTimer = m_fleeTimer; - SetFlee(fleePos, 5000); - if (oldFleeTimer != m_fleeTimer) - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500; - - } else { - if (m_nPedState == PED_FLEE_ENTITY && (neededTurn < DEGTORAD(25.0f) || m_panicCounter > 10)) { - m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; - m_collidingEntityWhileFleeing = collidingEnt; - m_collidingEntityWhileFleeing->RegisterReference((CEntity **) &m_collidingEntityWhileFleeing); - - uint8 currentDir = Floor((PI + m_fRotationCur) / DEGTORAD(45.0f)); - uint8 nextDir; - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, currentDir, &nextDir); - - } else { - if (neededTurn < DEGTORAD(60.0f)) { - CVector posToHead = m_vecDamageNormal * 4.0f; - posToHead.z = 0.0f; - posToHead += GetPosition(); - int closestNodeId = ThePaths.FindNodeClosestToCoors(posToHead, PATH_PED, - 999999.9f, false, false); - float angleToFace; - - if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) { - if (m_nPedState != PED_SEEK_POS && m_nPedState != PED_SEEK_CAR) { - if (m_nPedState == PED_WANDER_PATH) { - m_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId]; - angleToFace = CGeneral::GetRadianAngleBetweenPoints( - m_pNextPathNode->GetX(), m_pNextPathNode->GetY(), - GetPosition().x, GetPosition().y); - } else { - if (ThePaths.m_pathNodes[closestNodeId].GetX() == 0.0f - || ThePaths.m_pathNodes[closestNodeId].GetY() == 0.0f) { - posToHead = (3.0f * m_vecDamageNormal) + GetPosition(); - posToHead.x += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f; - posToHead.y += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f; - } else { - posToHead.x = ThePaths.m_pathNodes[closestNodeId].GetX(); - posToHead.y = ThePaths.m_pathNodes[closestNodeId].GetY(); - } - angleToFace = CGeneral::GetRadianAngleBetweenPoints( - posToHead.x, posToHead.y, - GetPosition().x, GetPosition().y); - - if (m_nPedState != PED_FOLLOW_PATH) - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500; - } - } else { - angleToFace = CGeneral::GetRadianAngleBetweenPoints( - ThePaths.m_pathNodes[closestNodeId].GetX(), - ThePaths.m_pathNodes[closestNodeId].GetY(), - GetPosition().x, - GetPosition().y); - - CVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].GetPosition() - GetPosition(); - CVector2D distToSeekPos = m_vecSeekPos - GetPosition(); - - if (DotProduct2D(distToNode, distToSeekPos) < 0.0f) { - m_fRotationCur = m_fRotationDest; - break; - } - } - } else { - float angleToFaceAwayDamage = CGeneral::GetRadianAngleBetweenPoints( - m_vecDamageNormal.x, - m_vecDamageNormal.y, - 0.0f, - 0.0f); - - if (angleToFaceAwayDamage < m_fRotationCur) - angleToFaceAwayDamage += TWOPI; - - float neededTurn = angleToFaceAwayDamage - m_fRotationCur; - - if (neededTurn <= PI) { - angleToFace = 0.5f * neededTurn + m_fRotationCur; - m_fRotationCur += DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f; - } else { - angleToFace = m_fRotationCur - (TWOPI - neededTurn) * 0.5f; - m_fRotationCur -= DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f; - } - - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200; - if (m_nPedType == PEDTYPE_COP) { - if (m_pedInObjective) { - float angleToLookCriminal = CGeneral::GetRadianAngleBetweenPoints( - m_pedInObjective->GetPosition().x, - m_pedInObjective->GetPosition().y, - GetPosition().x, - GetPosition().y); - - angleToLookCriminal = CGeneral::LimitRadianAngle(angleToLookCriminal); - angleToFace = CGeneral::LimitRadianAngle(angleToFace); - - if (angleToLookCriminal < angleToFace) - angleToLookCriminal += TWOPI; - - float neededTurnToCriminal = angleToLookCriminal - angleToFace; - - if (neededTurnToCriminal > DEGTORAD(150.0f) && neededTurnToCriminal < DEGTORAD(210.0f)) { - ((CCopPed*)this)->m_bStopAndShootDisabledZone = true; - } - } - } - } - m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace); - - if (m_fRotationCur - PI > m_fRotationDest) { - m_fRotationDest += TWOPI; - } else if (PI + m_fRotationCur < m_fRotationDest) { - m_fRotationDest -= TWOPI; - } - - if (oldDestRot == m_fRotationDest && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200; - m_fRotationDest += HALFPI; - } - } - } - } - } - - if (m_nPedState != PED_WANDER_PATH && m_nPedState != PED_FLEE_ENTITY) - m_pNextPathNode = nil; - - bHitSomethingLastFrame = true; - break; - } - case ENTITY_TYPE_VEHICLE: - { - CVehicle* collidingVeh = ((CVehicle*)collidingEnt); - float collidingVehSpeedSqr = collidingVeh->m_vecMoveSpeed.MagnitudeSqr(); - - if (collidingVeh == m_pMyVehicle) - bCollidedWithMyVehicle = true; -#ifdef VC_PED_PORTS - float oldHealth = m_fHealth; - bool playerSufferSound = false; - - if (collidingVehSpeedSqr <= 1.0f / 400.0f) { - if (IsPedInControl() - && (!IsPlayer() - || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT - || m_objective == OBJECTIVE_RUN_TO_AREA - || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)) { - - if (collidingVeh != m_pCurrentPhysSurface || IsPlayer()) { - if (!bVehEnterDoorIsBlocked) { - if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) { - - // VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR. - SetDirectionToWalkAroundObject(collidingVeh); - CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; - } else { - if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer - || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) { - - // VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR. - SetDirectionToWalkAroundObject(collidingVeh); - CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; - - } else if (m_fleeFrom != collidingVeh) { - SetFlee(collidingVeh, 4000); - bUsePedNodeSeek = false; - SetMoveState(PEDMOVE_WALK); - } - } - } - } else { - float angleLeftToCompleteTurn = Abs(m_fRotationCur - m_fRotationDest); - if (angleLeftToCompleteTurn < 0.01f && CanPedJumpThis(collidingVeh)) { - SetJump(); - } - } - } else if (IsPlayer() && !bIsInTheAir) { - - if (IsPedInControl() && ((CPlayerPed*)this)->m_fMoveSpeed == 0.0f - && !bIsLooking && CTimer::GetTimeInMilliseconds() > m_lookTimer && collidingVeh->pDriver) { - - ((CPlayerPed*)this)->AnnoyPlayerPed(false); - SetLookFlag(collidingVeh, true); - SetLookTimer(1300); - - eWeaponType weaponType = GetWeapon()->m_eWeaponType; - if (weaponType == WEAPONTYPE_UNARMED - || weaponType == WEAPONTYPE_BASEBALLBAT - || weaponType == WEAPONTYPE_COLT45 - || weaponType == WEAPONTYPE_UZI) { - bShakeFist = true; - } - } else { - SetLookFlag(collidingVeh, true); - SetLookTimer(500); - } - } - } else { - float adjustedImpulse = m_fDamageImpulse; - if (IsPlayer()) { - if (bIsStanding) { - float forwardVecAndDamageDirDotProd = DotProduct(m_vecAnimMoveDelta.y * GetForward(), m_vecDamageNormal); - if (forwardVecAndDamageDirDotProd < 0.0f) { - adjustedImpulse = forwardVecAndDamageDirDotProd * m_fMass + m_fDamageImpulse; - if (adjustedImpulse < 0.0f) - adjustedImpulse = 0.0f; - } - } - } - if (m_fMass / 20.0f < adjustedImpulse) - DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, adjustedImpulse); - - if (IsPlayer()) { - if (adjustedImpulse > 20.0f) - adjustedImpulse = 20.0f; - - if (adjustedImpulse > 5.0f) { - if (adjustedImpulse <= 13.0f) - playerSufferSound = true; - else - Say(SOUND_PED_DAMAGE); - } - - CColModel* collidingCol = CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(); - CVector colMinVec = collidingCol->boundingBox.min; - CVector colMaxVec = collidingCol->boundingBox.max; - - CVector vehColCenterDist = collidingVeh->GetMatrix() * ((colMinVec + colMaxVec) * 0.5f) - GetPosition(); - - // TLVC = To look vehicle center - - float angleToVehFront = collidingVeh->GetForward().Heading(); - float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading(); - angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC); - - // I don't know why do we use that - float vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); - - CVector vehDist = GetPosition() - collidingVeh->GetPosition(); - vehDist.Normalise(); - - float vehRightVecAndSpeedDotProd; - - if (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) { - if (angleDiffFromLookingFrontTLVC <= 0.0f) { - vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - - // vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right? - if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - - // Car's right faces towards us and isn't coming directly to us - if (DotProduct(collidingVeh->GetRight(), GetForward()) < 0.0f - && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { - SetEvasiveStep(collidingVeh, 1); - } - } - } else { - vehRightVecAndSpeedDotProd = DotProduct(-1.0f * collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - - if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - if (DotProduct(collidingVeh->GetRight(), GetForward()) > 0.0f - && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { - SetEvasiveStep(collidingVeh, 1); - } - } - } - } else { - vehRightVecAndSpeedDotProd = DotProduct(vehDist, collidingVeh->m_vecMoveSpeed); - } - - if (vehRightVecAndSpeedDotProd <= 0.1f) { - if (m_nPedState != PED_FIGHT) { - SetLookFlag(collidingVeh, true); - SetLookTimer(700); - } - } else { - bIsStanding = false; - CVector2D collidingEntMoveDir = -collidingVeh->m_vecMoveSpeed; - int dir = GetLocalDirection(collidingEntMoveDir); - SetFall(1000, (AnimationId)(dir + ANIM_KO_SKID_FRONT), false); - - float damage; - if (collidingVeh->m_modelIndex == MI_TRAIN) { - damage = 50.0f; - } else { - damage = 20.0f; - } - - InflictDamage(collidingVeh, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, dir); - Say(SOUND_PED_DAMAGE); - } - } else { - KillPedWithCar(collidingVeh, m_fDamageImpulse); - } - - /* VC specific - if (m_pCollidingEntity != collidingEnt) - bPushedAlongByCar = true; - */ - } - if (m_fHealth < oldHealth && playerSufferSound) - Say(SOUND_PED_HIT); -#else - if (collidingVehSpeedSqr <= 1.0f / 400.0f) { - if (!IsPedInControl() - || IsPlayer() - && m_objective != OBJECTIVE_GOTO_AREA_ON_FOOT - && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER - && m_objective != OBJECTIVE_RUN_TO_AREA) { - - if (IsPlayer() && !bIsInTheAir) { - - if (IsPedInControl() - && ((CPlayerPed*)this)->m_fMoveSpeed == 0.0f - && !bIsLooking - && CTimer::GetTimeInMilliseconds() > m_lookTimer - && collidingVeh->pDriver) { - - ((CPlayerPed*)this)->AnnoyPlayerPed(false); - SetLookFlag(collidingVeh, true); - SetLookTimer(1300); - - eWeaponType weaponType = GetWeapon()->m_eWeaponType; - if (weaponType == WEAPONTYPE_UNARMED - || weaponType == WEAPONTYPE_BASEBALLBAT - || weaponType == WEAPONTYPE_COLT45 - || weaponType == WEAPONTYPE_UZI) { - bShakeFist = true; - } - } else { - SetLookFlag(collidingVeh, true); - SetLookTimer(500); - } - } - - } else if (!bVehEnterDoorIsBlocked) { - if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) { - - SetDirectionToWalkAroundObject(collidingVeh); - - } else if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer - || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) { - - SetDirectionToWalkAroundObject(collidingVeh); - CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; - - } else if (m_fleeFrom != collidingVeh) { - SetFlee(collidingVeh, 4000); - bUsePedNodeSeek = false; - SetMoveState(PEDMOVE_WALK); - } - } - } else { - DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, m_fDamageImpulse); - if (IsPlayer()) { - CColModel *collidingCol = CModelInfo::GetModelInfo(collidingVeh->GetModelIndex())->GetColModel(); - CVector colMinVec = collidingCol->boundingBox.min; - CVector colMaxVec = collidingCol->boundingBox.max; - - CVector vehColCenterDist = collidingVeh->GetMatrix() * ((colMinVec + colMaxVec) * 0.5f) - GetPosition(); - - // TLVC = To look vehicle center - - float angleToVehFront = collidingVeh->GetForward().Heading(); - float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading(); - angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC); - - // I don't know why do we use that - float vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); - - CVector vehDist = GetPosition() - collidingVeh->GetPosition(); - vehDist.Normalise(); - - float vehRightVecAndSpeedDotProd; - - if (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) { - if (angleDiffFromLookingFrontTLVC <= 0.0f) { - vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - - // vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right? - if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - - // Car's right faces towards us and isn't coming directly to us - if (DotProduct(collidingVeh->GetRight(), GetForward()) < 0.0f - && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { - SetEvasiveStep(collidingVeh, 1); - } - } - } else { - vehRightVecAndSpeedDotProd = DotProduct(-1.0f * collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - - if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - if (DotProduct(collidingVeh->GetRight(), GetForward()) > 0.0f - && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { - SetEvasiveStep(collidingVeh, 1); - } - } - } - } else { - vehRightVecAndSpeedDotProd = DotProduct(vehDist, collidingVeh->m_vecMoveSpeed); - } - - if (vehRightVecAndSpeedDotProd <= 0.1f) { - if (m_nPedState != PED_FIGHT) { - SetLookFlag(collidingVeh, true); - SetLookTimer(700); - } - } else { - bIsStanding = false; - CVector2D collidingEntMoveDir = -collidingVeh->m_vecMoveSpeed; - int dir = GetLocalDirection(collidingEntMoveDir); - SetFall(1000, (AnimationId)(dir + ANIM_KO_SKID_FRONT), false); - CPed *driver = collidingVeh->pDriver; - - float damage; - if (driver && driver->IsPlayer()) { - damage = vehRightVecAndSpeedDotProd * 1000.0f; - } else if (collidingVeh->GetModelIndex() == MI_TRAIN) { - damage = 50.0f; - } else { - damage = 20.0f; - } - - InflictDamage(collidingVeh, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, dir); - Say(SOUND_PED_DAMAGE); - } - } else { - KillPedWithCar(collidingVeh, m_fDamageImpulse); - } - } -#endif - break; - } - case ENTITY_TYPE_PED: - { - CollideWithPed((CPed*)collidingEnt); - if (((CPed*)collidingEnt)->IsPlayer()) { - CPlayerPed *player = ((CPlayerPed*)collidingEnt); - Say(SOUND_PED_CHAT); - if (m_nMoveState > PEDMOVE_STILL && player->IsPedInControl()) { - if (player->m_fMoveSpeed < 1.0f) { - if (!player->bIsLooking) { - if (CTimer::GetTimeInMilliseconds() > player->m_lookTimer) { - player->AnnoyPlayerPed(false); - player->SetLookFlag(this, true); - player->SetLookTimer(1300); - eWeaponType weapon = player->GetWeapon()->m_eWeaponType; - if (weapon == WEAPONTYPE_UNARMED - || weapon == WEAPONTYPE_BASEBALLBAT - || weapon == WEAPONTYPE_COLT45 - || weapon == WEAPONTYPE_UZI) { - player->bShakeFist = true; - } - } - } - } - } - } - break; - } - default: - break; - } - } - CVector forceDir; - if (!bIsInTheAir && m_nPedState != PED_JUMP -#ifdef VC_PED_PORTS - && m_fDamageImpulse > 0.0f -#endif - ) { - - forceDir = m_vecDamageNormal; - forceDir.z = 0.0f; - if (!bIsStanding) { - forceDir *= 4.0f; - } else { - forceDir *= 0.5f; - } - - ApplyMoveForce(forceDir); - } - if ((bIsInTheAir && !DyingOrDead()) -#ifdef VC_PED_PORTS - || (!bIsStanding && !bWasStanding && m_nPedState == PED_FALL) -#endif - ) { - if (m_nPedStateTimer > 0 && m_nPedStateTimer <= 1000) { - forceDir = GetPosition() - m_vecHitLastPos; - } else { - m_nPedStateTimer = 0; - m_vecHitLastPos = GetPosition(); - forceDir = CVector(0.0f, 0.0f, 0.0f); - } - - CVector offsetToCheck; - m_nPedStateTimer++; - - float adjustedTs = Max(CTimer::GetTimeStep(), 0.01f); - - CPad *pad0 = CPad::GetPad(0); - if ((m_nPedStateTimer <= 50.0f / (4.0f * adjustedTs) || m_nPedStateTimer * 0.01f <= forceDir.MagnitudeSqr()) - && (m_nCollisionRecords <= 1 || m_nPedStateTimer <= 50.0f / (2.0f * adjustedTs) || m_nPedStateTimer * 1.0f / 250.0f <= Abs(forceDir.z))) { - - if (m_nCollisionRecords == 1 && m_aCollisionRecords[0] != nil && m_aCollisionRecords[0]->IsBuilding() - && m_nPedStateTimer > 50.0f / (2.0f * adjustedTs) && m_nPedStateTimer * 1.0f / 250.0f > Abs(forceDir.z)) { - offsetToCheck.x = -forceDir.y; -#ifdef VC_PED_PORTS - offsetToCheck.z = 1.0f; -#else - offsetToCheck.z = 0.0f; -#endif - offsetToCheck.y = forceDir.x; - offsetToCheck.Normalise(); - - CVector posToCheck = GetPosition() + offsetToCheck; - - // These are either obstacle or ground to land, I don't know which one. - float obstacleForFlyingZ, obstacleForFlyingOtherDirZ; - CColPoint obstacleForFlying, obstacleForFlyingOtherDir; - - // Check is there any room for being knocked up in reverse direction of force - if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlying, foundEnt, true, false, false, false, false, false, nil)) { - obstacleForFlyingZ = obstacleForFlying.point.z; - } else { - obstacleForFlyingZ = 500.0f; - } - - posToCheck = GetPosition() - offsetToCheck; - - // Now check for direction of force this time - if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlyingOtherDir, foundEnt, true, false, false, false, false, false, nil)) { - obstacleForFlyingOtherDirZ = obstacleForFlyingOtherDir.point.z; - } else { - obstacleForFlyingOtherDirZ = 501.0f; - } -#ifdef VC_PED_PORTS - uint8 flyDir = 0; - float feetZ = GetPosition().z - FEET_OFFSET; - if ((obstacleForFlyingZ <= feetZ || obstacleForFlyingOtherDirZ >= 500.0f) && (obstacleForFlyingZ <= feetZ || obstacleForFlyingOtherDirZ <= feetZ)) { - if (obstacleForFlyingOtherDirZ > feetZ && obstacleForFlyingZ < 499.0f) - flyDir = 2; - } else { - flyDir = 1; - } - - if (flyDir != 0 && !bSomeVCflag1) { - SetPosition((flyDir == 2 ? obstacleForFlyingOtherDir.point : obstacleForFlying.point)); - GetMatrix().GetPosition().z += FEET_OFFSET; - GetMatrix().UpdateRW(); - SetLanding(); - bIsStanding = true; - } -#endif - if (obstacleForFlyingZ < obstacleForFlyingOtherDirZ) { - offsetToCheck *= -1.0f; - } - offsetToCheck.z = 1.0f; - forceDir = 4.0f * offsetToCheck; - forceDir.z = 4.0f; - ApplyMoveForce(forceDir); - - GetMatrix().GetPosition() += 0.25f * offsetToCheck; - - m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints(offsetToCheck.x, offsetToCheck.y, 0.0f, 0.0f); - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - m_fRotationDest = m_fRotationCur; - SetHeading(m_fRotationCur); - - if (m_nPedState != PED_FALL && !bIsPedDieAnimPlaying) { - SetFall(1000, ANIM_KO_SKID_BACK, true); - } - bIsInTheAir = false; - } else if (m_vecDamageNormal.z > 0.4f) { -#ifndef VC_PED_PORTS - forceDir = m_vecDamageNormal; - forceDir.z = 0.0f; - forceDir.Normalise(); - ApplyMoveForce(2.0f * forceDir); -#else - if (m_nPedState == PED_JUMP) { - if (m_nWaitTimer <= 2000) { - if (m_nWaitTimer < 1000) - m_nWaitTimer += CTimer::GetTimeStep() * 0.02f * 1000.0f; - } else { - m_nWaitTimer = 0; - } - } - forceDir = m_vecDamageNormal; - forceDir.z = 0.0f; - forceDir.Normalise(); - if (m_nPedState != PED_JUMP || m_nWaitTimer >= 300) { - ApplyMoveForce(2.0f * forceDir); - } else { - ApplyMoveForce(-4.0f * forceDir); - } -#endif - } - } else if ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 3) & 7) { - if (IsPlayer() && m_nPedState != PED_JUMP && pad0->JumpJustDown()) { - int16 padWalkX = pad0->GetPedWalkLeftRight(); - int16 padWalkY = pad0->GetPedWalkUpDown(); - if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY); - m_fRotationDest -= TheCamera.Orientation; - m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); - m_fRotationCur = m_fRotationDest; - SetHeading(m_fRotationCur); - } - SetJump(); - m_nPedStateTimer = 0; - m_vecHitLastPos = GetPosition(); - - // Why? forceDir is unused after this point. - forceDir = CVector(0.0f, 0.0f, 0.0f); - } else if (IsPlayer()) { - int16 padWalkX = pad0->GetPedWalkLeftRight(); - int16 padWalkY = pad0->GetPedWalkUpDown(); - if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY); - m_fRotationDest -= TheCamera.Orientation; - m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); - m_fRotationCur = m_fRotationDest; - SetHeading(m_fRotationCur); - } - CAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_GLIDE); - - if (!jumpAssoc) - jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_GLIDE); - - if (jumpAssoc) { - jumpAssoc->blendDelta = -3.0f; - jumpAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - if (m_nPedState == PED_JUMP) - m_nPedState = PED_IDLE; - } else { - CAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_GLIDE); - - if (!jumpAssoc) - jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_GLIDE); - - if (jumpAssoc) { - jumpAssoc->blendDelta = -3.0f; - jumpAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - } - } else { - offsetToCheck = GetPosition(); - offsetToCheck.z += 0.5f; - - if (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - FEET_OFFSET, foundCol, foundEnt, true, true, false, true, false, false, nil)) { -#ifdef VC_PED_PORTS - if (!bSomeVCflag1 || FEET_OFFSET + foundCol.point.z < GetPosition().z) { - GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z; - GetMatrix().UpdateRW(); - if (bSomeVCflag1) - bSomeVCflag1 = false; - } -#else - GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z; - GetMatrix().UpdateRW(); -#endif - SetLanding(); - bIsStanding = true; - } - } - } else if (m_nPedStateTimer < 1001) { - m_nPedStateTimer = 0; - } - } - - if (bIsDucking) - Duck(); - - if (bStartWanderPathOnFoot) { - if (IsPedInControl()) { - ClearAll(); - SetWanderPath(m_nPathDir); - bStartWanderPathOnFoot = false; - } else if (m_nPedState == PED_DRIVING) { - bWanderPathAfterExitingCar = true; - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } - } - - if (!bIsStanding && m_vecMoveSpeed.z > 0.25f) { - float airResistance = Pow(0.95f, CTimer::GetTimeStep()); - - m_vecMoveSpeed *= airResistance; - } -#ifdef VC_PED_PORTS - if (IsPlayer() || !bIsStanding || m_vecMoveSpeed.x != 0.0f || m_vecMoveSpeed.y != 0.0f || m_vecMoveSpeed.z != 0.0f - || (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) - || m_vecAnimMoveDelta.x != 0.0f || m_vecAnimMoveDelta.y != 0.0f - || m_nPedState == PED_JUMP - || bIsInTheAir - || m_pCurrentPhysSurface) { - - CPhysical::ProcessControl(); - } else { - bHasContacted = false; - bIsInSafePosition = false; - bWasPostponed = false; - bHasHitWall = false; - m_nCollisionRecords = 0; - bHasCollided = false; - m_nDamagePieceType = 0; - m_fDamageImpulse = 0.0f; - m_pDamageEntity = nil; - m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f); - m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f); - } -#else - CPhysical::ProcessControl(); -#endif - if (m_nPedState != PED_DIE || bIsPedDieAnimPlaying) { - if (m_nPedState != PED_DEAD) { - CalculateNewVelocity(); - CalculateNewOrientation(); - } - UpdatePosition(); - PlayFootSteps(); - if (IsPedInControl() && !bIsStanding && !m_pDamageEntity && CheckIfInTheAir()) { - SetInTheAir(); -#ifdef VC_PED_PORTS - bSomeVCflag1 = false; -#endif - } -#ifdef VC_PED_PORTS - if (bSomeVCflag1) { - CVector posToCheck = GetPosition(); - posToCheck.z += 0.9f; - if (!CWorld::TestSphereAgainstWorld(posToCheck, 0.2f, this, true, true, false, true, false, false)) - bSomeVCflag1 = false; - } -#endif - ProcessObjective(); - if (!bIsAimingGun) { - if (bIsRestoringGun) - RestoreGunPosition(); - } else { - AimGun(); - } - - if (bIsLooking) { - MoveHeadToLook(); - } else if (bIsRestoringLook) { - RestoreHeadPosition(); - } - - if (bIsInTheAir) - InTheAir(); - - if (bUpdateAnimHeading) { - if (m_nPedState != PED_GETUP && m_nPedState != PED_FALL) { - m_fRotationCur -= HALFPI; - m_fRotationDest = m_fRotationCur; - bUpdateAnimHeading = false; - } - } - - if (m_nWaitState != WAITSTATE_FALSE) - Wait(); - - if (m_nPedState != PED_IDLE) { - CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED); - if(idleAssoc) { - idleAssoc->blendDelta = -8.0f; - idleAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - } - - switch (m_nPedState) { - case PED_IDLE: - Idle(); - break; - case PED_LOOK_ENTITY: - case PED_LOOK_HEADING: - Look(); - break; - case PED_WANDER_RANGE: - WanderRange(); - CheckAroundForPossibleCollisions(); - break; - case PED_WANDER_PATH: - WanderPath(); - break; - case PED_SEEK_POS: - case PED_SEEK_ENTITY: - case PED_PURSUE: - case PED_SNIPER_MODE: - case PED_ROCKET_MODE: - case PED_DUMMY: - case PED_FACE_PHONE: - case PED_MAKE_CALL: - case PED_MUG: - case PED_AI_CONTROL: - case PED_FOLLOW_ROUTE: - case PED_CPR: - case PED_SOLICIT: - case PED_BUY_ICECREAM: - case PED_STEP_AWAY: - case PED_UNKNOWN: - case PED_STATES_NO_AI: - case PED_JUMP: - case PED_STAGGER: - case PED_DIVE_AWAY: - case PED_STATES_NO_ST: - case PED_ARREST_PLAYER: - case PED_PASSENGER: - case PED_TAXI_PASSENGER: - case PED_OPEN_DOOR: - case PED_DEAD: - case PED_DRAG_FROM_CAR: - case PED_EXIT_CAR: - case PED_STEAL_CAR: - break; - case PED_ENTER_CAR: - case PED_CARJACK: - { -#ifdef CANCELLABLE_CAR_ENTER - if (!IsPlayer() || !m_pVehicleAnim) - break; - - CPad *pad = CPad::GetPad(0); - - if (pad->ArePlayerControlsDisabled()) - break; - - int vehAnim = m_pVehicleAnim->animId; - - static bool cancelJack = false; - int16 padWalkX = pad->GetPedWalkLeftRight(); - int16 padWalkY = pad->GetPedWalkUpDown(); - if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { - if (vehAnim == ANIM_CAR_OPEN_LHS || vehAnim == ANIM_CAR_OPEN_RHS || vehAnim == ANIM_COACH_OPEN_L || vehAnim == ANIM_COACH_OPEN_R || - vehAnim == ANIM_VAN_OPEN_L || vehAnim == ANIM_VAN_OPEN) { - - if (!m_pMyVehicle->pDriver) { - cancelJack = false; - bCancelEnteringCar = true; - } else - cancelJack = true; - } else if (vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f) { - cancelJack = true; - } else if (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS) { - bCancelEnteringCar = true; - cancelJack = false; - } - } - if (cancelJack && vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f && m_pVehicleAnim->GetTimeLeft() < 0.78f) { - cancelJack = false; - QuitEnteringCar(); - RestorePreviousObjective(); - } - if (cancelJack && (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS)) { - cancelJack = false; - bCancelEnteringCar = true; - } -#endif - break; - } - case PED_FLEE_POS: - ms_vec2DFleePosition.x = m_fleeFromPosX; - ms_vec2DFleePosition.y = m_fleeFromPosY; - Flee(); - break; - case PED_FLEE_ENTITY: - if (!m_fleeFrom) { - SetIdle(); - break; - } - - if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) - break; - - ms_vec2DFleePosition = m_fleeFrom->GetPosition(); - Flee(); - break; - case PED_FOLLOW_PATH: - FollowPath(); - break; - case PED_PAUSE: - Pause(); - break; - case PED_ATTACK: - Attack(); - break; - case PED_FIGHT: - Fight(); - break; - case PED_CHAT: - Chat(); - break; - case PED_AIM_GUN: - if (m_pPointGunAt && m_pPointGunAt->IsPed() -#ifdef FIX_BUGS - && !GetWeapon()->IsTypeMelee() -#endif - && ((CPed*)m_pPointGunAt)->CanSeeEntity(this, CAN_SEE_ENTITY_ANGLE_THRESHOLD * 2)) { - ((CPed*)m_pPointGunAt)->ReactToPointGun(this); - } - PointGunAt(); - break; - case PED_SEEK_CAR: - SeekCar(); - break; - case PED_SEEK_IN_BOAT: - SeekBoatPosition(); - break; - case PED_INVESTIGATE: - InvestigateEvent(); - break; - case PED_ON_FIRE: - if (IsPlayer()) - break; - - if (CTimer::GetTimeInMilliseconds() <= m_fleeTimer) { - if (m_fleeFrom) { - ms_vec2DFleePosition = m_fleeFrom->GetPosition(); - } else { - ms_vec2DFleePosition.x = m_fleeFromPosX; - ms_vec2DFleePosition.y = m_fleeFromPosY; - } - Flee(); - } else { - if (m_pFire) - m_pFire->Extinguish(); - } - break; - case PED_FALL: - Fall(); - break; - case PED_GETUP: - SetGetUp(); - break; - case PED_ENTER_TRAIN: - EnterTrain(); - break; - case PED_EXIT_TRAIN: - ExitTrain(); - break; - case PED_DRIVING: - { - if (!m_pMyVehicle) { - bInVehicle = false; - FlagToDestroyWhenNextProcessed(); - return; - } - - if (m_pMyVehicle->pDriver != this || m_pMyVehicle->IsBoat()) { - LookForSexyPeds(); - LookForSexyCars(); - break; - } - - if (m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE || !m_pMyVehicle->pDriver->IsPlayer()) { - break; - } - - CPad* pad = CPad::GetPad(0); - -#ifdef CAR_AIRBREAK - if (!pad->ArePlayerControlsDisabled()) { - if (pad->GetHorn()) { - float c = Cos(m_fRotationCur); - float s = Sin(m_fRotationCur); - m_pMyVehicle->GetRight() = CVector(1.0f, 0.0f, 0.0f); - m_pMyVehicle->GetForward() = CVector(0.0f, 1.0f, 0.0f); - m_pMyVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); - if (pad->GetAccelerate()) { - m_pMyVehicle->ApplyMoveForce(GetForward() * 30.0f); - } else if (pad->GetBrake()) { - m_pMyVehicle->ApplyMoveForce(-GetForward() * 30.0f); - } else { - int16 lr = pad->GetSteeringLeftRight(); - if (lr < 0) { - //m_pMyVehicle->ApplyTurnForce(20.0f * -GetRight(), GetForward()); - m_pMyVehicle->ApplyMoveForce(-GetRight() * 30.0f); - } else if (lr > 0) { - m_pMyVehicle->ApplyMoveForce(GetRight() * 30.0f); - } else { - m_pMyVehicle->ApplyMoveForce(0.0f, 0.0f, 50.0f); - } - } - } - } -#endif - float steerAngle = m_pMyVehicle->m_fSteerAngle; - CAnimBlendAssociation *lDriveAssoc; - CAnimBlendAssociation *rDriveAssoc; - CAnimBlendAssociation *lbAssoc; - CAnimBlendAssociation *sitAssoc; - if (m_pMyVehicle->bLowVehicle) { - sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT); - - if (!sitAssoc || sitAssoc->blendAmount < 1.0f) { - break; - } - - lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L); - lbAssoc = nil; - rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R); - } else { - sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT); - - if (!sitAssoc || sitAssoc->blendAmount < 1.0f) { - break; - } - - lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L); - rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R); - lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB); - - if (lbAssoc && - TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON - && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) { - lbAssoc->blendDelta = -1000.0f; - } - } - - CAnimBlendAssociation *driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L); - - if (!driveByAssoc) - driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R); - - if (m_pMyVehicle->bLowVehicle || m_pMyVehicle->m_fGasPedal >= 0.0f || driveByAssoc) { - if (steerAngle == 0.0f || driveByAssoc) { - if (lDriveAssoc) - lDriveAssoc->blendAmount = 0.0f; - if (rDriveAssoc) - rDriveAssoc->blendAmount = 0.0f; - - } else if (steerAngle <= 0.0f) { - if (lDriveAssoc) - lDriveAssoc->blendAmount = 0.0f; - - if (rDriveAssoc) - rDriveAssoc->blendAmount = clamp(steerAngle * -100.0f / 61.0f, 0.0f, 1.0f); - else if (m_pMyVehicle->bLowVehicle) - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_R); - else - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_R); - - } else { - if (rDriveAssoc) - rDriveAssoc->blendAmount = 0.0f; - - if (lDriveAssoc) - lDriveAssoc->blendAmount = clamp(steerAngle * 100.0f / 61.0f, 0.0f, 1.0f); - else if (m_pMyVehicle->bLowVehicle) - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_L); - else - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_L); - } - - if (lbAssoc) - lbAssoc->blendDelta = -4.0f; - } else { - - if ((TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON - || TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking != LOOKING_LEFT) - && (!lbAssoc || lbAssoc->blendAmount < 1.0f)) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LB, 4.0f); - } - } - break; - } - case PED_DIE: - Die(); - break; - case PED_HANDS_UP: - if (m_pedStats->m_temper <= 50) { - if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSCOWER)) { - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER); - Say(SOUND_PED_HANDS_COWER); - } - } else if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP)) { - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP); - Say(SOUND_PED_HANDS_UP); - } - break; - default: break; - } - SetMoveAnim(); - if (bPedIsBleeding) { - if (CGame::nastyGame) { - if (!(CTimer::GetFrameCounter() & 3)) { - CVector cameraDist = GetPosition() - TheCamera.GetPosition(); - if (cameraDist.MagnitudeSqr() < sq(50.0f)) { - - float length = (CGeneral::GetRandomNumber() & 127) * 0.0015f + 0.15f; - CVector bloodPos( - ((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f, - ((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f, - 1.0f); - bloodPos += GetPosition(); - - CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, length, 0.0f, - 0.0f, -length, 255, 255, 0, 0, 4.0f, (CGeneral::GetRandomNumber() & 4095) + 2000, 1.0f); - } - } - } - } - ServiceTalking(); - if (bInVehicle && !m_pMyVehicle) - bInVehicle = false; -#ifndef VC_PED_PORTS - m_pCurrentPhysSurface = nil; -#endif - } else { - if (bIsStanding && (!m_pCurrentPhysSurface || IsPlayer()) - || bIsInWater || !bUsesCollision) { - SetDead(); - } - m_pCurrentPhysSurface = nil; - } - } -} - -void -CPed::SetInTheAir(void) -{ - if (bIsInTheAir) - return; - - bIsInTheAir = true; - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_GLIDE, 4.0f); - - if (m_nPedState == PED_ATTACK) { - ClearAttack(); - ClearPointGunAt(); - } else if (m_nPedState == PED_FIGHT) { - EndFight(ENDFIGHT_FAST); - } - -} - -void -CPed::RestoreHeadPosition(void) -{ - if (m_pedIK.RestoreLookAt()) { - bIsRestoringLook = false; - } -} - -void -CPed::PointGunAt(void) -{ - CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay); - if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f) - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay); - - if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) { - weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart); - weaponAssoc->flags &= ~ASSOC_RUNNING; - - if (weaponInfo->m_bCanAimWithArm) - m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM; - else - m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; - } -} - -void -CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - CAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle); - - if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) - return; - - if (ped->EnteringCar()) { - bool isLow = !!veh->bLowVehicle; - - if (!veh->bIsBus) - veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f); - - eDoors door; - switch (ped->m_vehEnterType) { - case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break; - case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break; - case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break; - case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break; - default: assert(0); - } - - if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING) - veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK); - - if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus) { - PedSetInCarCB(nil, ped); - } else if (ped->m_vehEnterType == CAR_DOOR_RF - && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF || - (veh->pDriver != nil && - (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR -#ifdef VC_PED_PORTS - && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE -#endif - || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) { - - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER -#if defined VC_PED_PORTS || defined FIX_BUGS - || ped->m_nPedState == PED_CARJACK -#endif - ) - veh->bIsBeingCarJacked = false; - - ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER; - PedSetInCarCB(nil, ped); - - ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); - if (!ped->IsPlayer()) - ped->bFleeAfterExitingCar = true; - - ped->bUsePedNodeSeek = true; - ped->m_pNextPathNode = nil; - - } else { - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (isLow) - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSHUFFLE_RHS); - else - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SHUFFLE_RHS); - - ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped); - } - } else { -#ifdef VC_PED_PORTS - if (ped->m_nPedState != PED_DRIVING) -#endif - ped->QuitEnteringCar(); - } -} - -void -CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed* ped = (CPed*)arg; - - CAutomobile* veh = (CAutomobile*)(ped->m_pMyVehicle); - - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (veh->bLowVehicle) { - veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR_LOW, 1.0f); - } else { - veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, 1.0f); - } - - veh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF; - - if (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) - veh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK); -} - -void -CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed* ped = (CPed*)arg; - - CVehicle* veh = ped->m_pMyVehicle; - - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (!ped->IsNotInWreckedVehicle()) - return; - - if (!ped->EnteringCar()) { -#ifdef VC_PED_PORTS - if (ped->m_nPedState != PED_DRIVING) -#endif - ped->QuitEnteringCar(); - - return; - } - - eDoors door; - CPed *pedInSeat = nil; - switch (ped->m_vehEnterType) { - case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; pedInSeat = veh->pPassengers[0]; break; - case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; pedInSeat = veh->pPassengers[2]; break; - case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; pedInSeat = veh->pDriver; break; - case CAR_DOOR_LR: door = DOOR_REAR_LEFT; pedInSeat = veh->pPassengers[1]; break; - default: assert(0); - } - - if (ped->m_fHealth == 0.0f || CPad::GetPad(0)->ArePlayerControlsDisabled() && pedInSeat && pedInSeat->IsPlayer()) { - ped->QuitEnteringCar(); - return; - } - - bool isVan = veh->bIsVan; - bool isBus = veh->bIsBus; - bool isLow = veh->bLowVehicle; - bool vehUpsideDown = veh->IsUpsideDown(); - if (ped->bCancelEnteringCar) { - if (ped->IsPlayer()) { - if (veh->pDriver) { - if (veh->pDriver->m_nPedType == PEDTYPE_COP) { - FindPlayerPed()->SetWantedLevelNoDrop(1); - } - } - } -#ifdef CANCELLABLE_CAR_ENTER - if (!veh->IsDoorMissing(door) && veh->CanPedOpenLocks(ped) && veh->IsCar()) { - ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); - } -#endif - ped->QuitEnteringCar(); - ped->RestorePreviousObjective(); - ped->bCancelEnteringCar = false; - return; - } - if (!veh->IsDoorMissing(door) && veh->IsCar()) { - ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); - } - - if (veh->m_vecMoveSpeed.Magnitude() > 0.2f) { - ped->QuitEnteringCar(); - if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) - ped->SetFall(1000, ANIM_KO_SPIN_R, false); - else - ped->SetFall(1000, ANIM_KO_SPIN_L, false); - - return; - } - veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f); - - if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF) - isVan = false; - - if (ped->m_nPedState != PED_CARJACK || isBus) { - AnimationId animToPlay; - if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) { - - if (isVan) { - animToPlay = ANIM_VAN_GETIN; - } else if (isBus) { - animToPlay = ANIM_COACH_IN_R; - } else if (isLow) { - animToPlay = ANIM_CAR_GETIN_LOW_RHS; - } else { - animToPlay = ANIM_CAR_GETIN_RHS; - } - } else if (isVan) { - animToPlay = ANIM_VAN_GETIN_L; - } else if (isBus) { - animToPlay = ANIM_COACH_IN_L; - } else if (isLow) { - animToPlay = ANIM_CAR_GETIN_LOW_LHS; - } else { - animToPlay = ANIM_CAR_GETIN_LHS; - } - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay); - ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); - } else { - CPed *pedToDragOut = nil; - switch (ped->m_vehEnterType) { - case CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break; - case CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break; - case CAR_DOOR_LF: pedToDragOut = veh->pDriver; break; - case CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break; - default: assert(0); - } - - if (vehUpsideDown) { - ped->QuitEnteringCar(); - if (ped->m_nPedType == PEDTYPE_COP) - ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective); - } - - if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) { - if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) { - if (pedToDragOut->m_nPedState != PED_DRIVING) { - ped->QuitEnteringCar(); - pedToDragOut = nil; - } else { - if (isLow) - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_RHS); - else - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_RHS); - - ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped); - } - } else if (ped->m_nPedType == PEDTYPE_COP) { - ped->QuitEnteringCar(); - if (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) { - veh->SetStatus(STATUS_PLAYER_DISABLED); - ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective); - } else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) { - ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING); - } - } else { - // BUG: Probably we will sit on top of the passenger if his m_ped_flagF4 is true. - if (isLow) - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS); - else - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS); - - ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); - } - } else { - if (pedToDragOut) { - if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) { - - // BUG: Player freezes in that condition due to its objective isn't restored. It's an unfinished feature, used in VC. - ped->QuitEnteringCar(); - pedToDragOut = nil; - } else { - if (isLow) - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_LHS); - else - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LHS); - - ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped); - } - } else { - if (isLow) - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS); - else - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS); - - ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); - } - } - - if (pedToDragOut) { - pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false); - if (pedToDragOut->IsGangMember()) - pedToDragOut->RegisterThreatWithGangPeds(ped); - } - } - - if (veh->pDriver && ped) { - veh->pDriver->SetLookFlag(ped, true); - veh->pDriver->SetLookTimer(1000); - } - return; -} - -void -CPed::SetJump(void) -{ - if (!bInVehicle && -#if defined VC_PED_PORTS || defined FIX_BUGS - m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) && -#endif - (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { - SetStoredState(); - m_nPedState = PED_JUMP; - CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f); - jumpAssoc->SetFinishCallback(FinishLaunchCB, this); - m_fRotationDest = m_fRotationCur; - } -} - -void -CPed::RemoveInCarAnims(void) -{ - if (!IsPlayer()) - return; - - CAnimBlendAssociation *animAssoc; - - if (m_pMyVehicle && m_pMyVehicle->bLowVehicle) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - } else { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - } - -#ifdef VC_PED_PORTS - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; -#endif - - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB); - if (animAssoc) - animAssoc->blendDelta = -1000.0f; -} - -void -CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*) arg; - - CVehicle *veh = ped->m_pMyVehicle; - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) - return; - - if (!ped->EnteringCar()) { -#ifdef VC_PED_PORTS - if(ped->m_nPedState != PED_DRIVING) -#endif - ped->QuitEnteringCar(); - return; - } - - if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) { - PedSetInCarCB(nil, ped); - ped->m_nLastPedState = ped->m_nPedState; - ped->m_nPedState = PED_ARRESTED; - ped->bGonnaKillTheCarJacker = false; - if (veh) { - veh->m_nNumGettingIn = 0; - veh->m_nGettingInFlags = 0; - veh->bIsHandbrakeOn = true; - veh->SetStatus(STATUS_PLAYER_DISABLED); - } - return; - } - if (ped->IsPlayer() && ped->m_vehEnterType == CAR_DOOR_LF - && (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f) - && veh->IsCar()) { - if (((CAutomobile*)veh)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING) - ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING); - - PedSetInCarCB(nil, ped); - return; - } - bool isVan = !!veh->bIsVan; - bool isBus = !!veh->bIsBus; - bool isLow = !!veh->bLowVehicle; - eDoors enterDoor; - switch (ped->m_vehEnterType) { - case CAR_DOOR_RF: - isVan = false; - enterDoor = DOOR_FRONT_RIGHT; - break; - case CAR_DOOR_RR: - enterDoor = DOOR_REAR_RIGHT; - break; - case CAR_DOOR_LF: - isVan = false; - enterDoor = DOOR_FRONT_LEFT; - break; - case CAR_DOOR_LR: - enterDoor = DOOR_REAR_LEFT; - break; - default: - break; - } - if (!veh->IsDoorMissing(enterDoor)) { - if (veh->IsCar()) - ((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING); - } - CPed *driver = veh->pDriver; - if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) { - if (veh->bIsBus) { - driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh); - if (driver->IsPlayer()) { - veh->bIsHandbrakeOn = true; - veh->SetStatus(STATUS_PLAYER_DISABLED); - } - driver->bBusJacked = true; - veh->bIsBeingCarJacked = false; - PedSetInCarCB(nil, ped); - if (ped->m_nPedType == PEDTYPE_COP - || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT - || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { - ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); - } - ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400; - return; - } - if (driver != ped && ped->m_vehEnterType != CAR_DOOR_LF) { - if (!driver->IsPlayer()) { - driver->bUsePedNodeSeek = true; - driver->m_pLastPathNode = nil; - if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear - || driver->CharCreatedBy == MISSION_CHAR - || veh->VehicleCreatedBy == MISSION_VEHICLE) { - driver->bFleeAfterExitingCar = true; - } else { - driver->bGonnaKillTheCarJacker = true; - veh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped); - - if (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) { - FindPlayerPed()->SetWantedLevelNoDrop(1); - } - } - } - if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY) - && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) { - veh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh); - veh->pDriver->Say(SOUND_PED_CAR_JACKED); -#ifdef VC_PED_PORTS - veh->pDriver->SetRadioStation(); -#endif - } else { - ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER; - } - } - } - if (veh->IsDoorMissing(enterDoor) || isBus) { - PedAnimDoorCloseCB(nil, ped); - } else { - AnimationId animToPlay; - if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) { - if (isVan) { - animToPlay = ANIM_VAN_CLOSE; - } else if (isLow) { - animToPlay = ANIM_CAR_CLOSEDOOR_LOW_RHS; - } else { - animToPlay = ANIM_CAR_CLOSEDOOR_RHS; - } - } else if (isVan) { - animToPlay = ANIM_VAN_CLOSE_L; - } else if (isLow) { - animToPlay = ANIM_CAR_CLOSEDOOR_LOW_LHS; - } else { - animToPlay = ANIM_CAR_CLOSEDOOR_LHS; - } - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay); - ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped); - } -} - -void -CPed::SetPedPositionInTrain(void) -{ - LineUpPedWithTrain(); -} - -void -CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed* ped = (CPed*)arg; - - CVehicle* veh = ped->m_pMyVehicle; - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (ped->EnteringCar()) { - if (!ped->IsNotInWreckedVehicle()) - return; - -#ifdef CANCELLABLE_CAR_ENTER - if (ped->bCancelEnteringCar) { - ped->QuitEnteringCar(); - ped->RestorePreviousObjective(); - ped->bCancelEnteringCar = false; - return; - } -#endif - - bool isLow = !!veh->bLowVehicle; - - int padNo; - if (ped->IsPlayer()) { - - // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads - switch (ped->m_nPedType) { - case PEDTYPE_PLAYER1: - padNo = 0; - break; - case PEDTYPE_PLAYER2: - padNo = 1; - break; - case PEDTYPE_PLAYER3: - padNo = 2; - break; - case PEDTYPE_PLAYER4: - padNo = 3; - break; - } - CPad *pad = CPad::GetPad(padNo); - - if (!pad->ArePlayerControlsDisabled()) { - - if (pad->GetTarget() - || pad->NewState.LeftStickX - || pad->NewState.LeftStickY - || pad->NewState.DPadUp - || pad->NewState.DPadDown - || pad->NewState.DPadLeft - || pad->NewState.DPadRight) { - ped->QuitEnteringCar(); - ped->RestorePreviousObjective(); - return; - } - } + if (entityOnTopLeftOfObj && entityOnTopRightOfObj && entityOnBottomRightOfObj && entityOnBottomLeftOfObj) { + collidingThingChanged = false; + entityOnTopLeftOfObj = 0; + entityOnBottomLeftOfObj = 0; + entityOnTopRightOfObj = 0; + entityOnBottomRightOfObj = 0; } - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { - AnimationId animToPlay; - if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) { - if (isLow) - animToPlay = ANIM_CAR_GETIN_LOW_RHS; - else - animToPlay = ANIM_CAR_GETIN_RHS; - } else if (isLow) { - animToPlay = ANIM_CAR_GETIN_LOW_LHS; - } else { - animToPlay = ANIM_CAR_GETIN_LHS; - } - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay); - ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + if (!collidingThingChanged) { + m_walkAroundType = 0; } else { - ped->QuitEnteringCar(); - } - } else { - ped->QuitEnteringCar(); - } -} - -void -CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed* ped = (CPed*)arg; - - CVehicle* veh = ped->m_pMyVehicle; - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - if (!veh) { - PedSetOutCarCB(nil, ped); - return; - } -#ifdef VC_PED_PORTS - CVector posForZ = ped->GetPosition(); - CPedPlacement::FindZCoorForPed(&posForZ); - if (ped->GetPosition().z - 0.5f > posForZ.z) { - PedSetOutCarCB(nil, ped); - return; - } -#endif - veh->m_nStaticFrames = 0; - veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f); - veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f); - if (!veh->bIsBus) - veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f); - - /* - // Duplicate and only in PC for some reason - if (!veh) { - PedSetOutCarCB(nil, ped); - return; - } - */ - eDoors door; - switch (ped->m_vehEnterType) { - case CAR_DOOR_RF: - door = DOOR_FRONT_RIGHT; - break; - case CAR_DOOR_RR: - door = DOOR_REAR_RIGHT; - break; - case CAR_DOOR_LF: - door = DOOR_FRONT_LEFT; - break; - case CAR_DOOR_LR: - door = DOOR_REAR_LEFT; - break; - default: - break; - } - bool closeDoor = !veh->IsDoorMissing(door); - - int padNo; - if (ped->IsPlayer()) { - - // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads - switch (ped->m_nPedType) { - case PEDTYPE_PLAYER1: - padNo = 0; - break; - case PEDTYPE_PLAYER2: - padNo = 1; - break; - case PEDTYPE_PLAYER3: - padNo = 2; - break; - case PEDTYPE_PLAYER4: - padNo = 3; - break; - } - CPad* pad = CPad::GetPad(padNo); - bool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225; - if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS - && (pad->GetTarget() - || pad->NewState.LeftStickX - || pad->NewState.LeftStickY - || pad->NewState.DPadUp - || pad->NewState.DPadDown - || pad->NewState.DPadLeft - || pad->NewState.DPadRight) - || veh->bIsBus - || veh->m_pCarFire - || engineIsIntact) { - closeDoor = false; - } - } - -#ifdef VC_PED_PORTS - if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) - closeDoor = false; -#endif - - if (!closeDoor) { - if (!veh->IsDoorMissing(door) && !veh->bIsBus) { - ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); - } - PedSetOutCarCB(nil, ped); - return; - } - - if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) { - // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa? - if (!veh->IsDoorMissing(door)) - ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING); - } else { - switch (door) { - case DOOR_FRONT_LEFT: - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS); - break; - case DOOR_FRONT_RIGHT: - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS); - break; - case DOOR_REAR_LEFT: - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS); - break; - case DOOR_REAR_RIGHT: - ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS); - break; - default: - break; - } - } - - if (ped->m_pVehicleAnim) - ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped); - return; -} - -void -CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed* ped = (CPed*)arg; - - if (!animAssoc) { - ped->ClearLookFlag(); - if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) - ped->RestorePreviousState(); - - } else if (animAssoc->animId == ANIM_EV_DIVE) { - ped->bUpdateAnimHeading = true; - ped->ClearLookFlag(); - if (ped->m_nPedState == PED_DIVE_AWAY) - { - ped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1; - ped->m_nPedState = PED_FALL; - } - animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - - } else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) { - ped->ClearLookFlag(); - if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) - ped->RestorePreviousState(); - - } else if (ped->m_nPedState != PED_ARRESTED) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - if (animAssoc->blendDelta >= 0.0f) - animAssoc->blendDelta = -4.0f; - - ped->ClearLookFlag(); - if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) { - ped->RestorePreviousState(); - } - } -} - -void -CPed::PedGetupCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed* ped = (CPed*)arg; - - if (ped->m_nPedState == PED_GETUP) - RpAnimBlendClumpSetBlendDeltas(ped->GetClump(), ASSOC_PARTIAL, -1000.0f); - - ped->bFallenDown = false; - animAssoc->blendDelta = -1000.0f; - if (ped->m_nPedState == PED_GETUP) - ped->RestorePreviousState(); - - if (ped->m_nPedState != PED_FLEE_POS && ped->m_nPedState != PED_FLEE_ENTITY) - ped->SetMoveState(PEDMOVE_STILL); - else - ped->SetMoveState(PEDMOVE_RUN); - - ped->SetMoveAnim(); - ped->bGetUpAnimStarted = false; -} - -void -CPed::PedLandCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed* ped = (CPed*)arg; - - animAssoc->blendDelta = -1000.0f; - ped->bIsLanding = false; - - if (ped->m_nPedState == PED_JUMP) - ped->RestorePreviousState(); -} - -void -CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg) -{ - CPed *ped = (CPed*)arg; - - ped->bUsesCollision = true; - ped->RestartNonPartialAnims(); - bool itsRearDoor = false; - - if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR) - itsRearDoor = true; - - CMatrix pedMat(ped->GetMatrix()); - CVector posAfterBeingDragged = Multiply3x3(pedMat, (itsRearDoor ? -vecPedDraggedOutCarAnimOffset : vecPedDraggedOutCarAnimOffset)); - posAfterBeingDragged += ped->GetPosition(); -#ifndef VC_PED_PORTS - posAfterBeingDragged.z += 1.0f; -#endif - CPedPlacement::FindZCoorForPed(&posAfterBeingDragged); - ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - ped->SetPosition(posAfterBeingDragged); - - if (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedDraggedOutCarAnimOffset)) { - ped->PositionPedOutOfCollision(); - } - - if (!ped->CanSetPedState()) - return; - - if (!ped->m_pMyVehicle) { - ped->SetIdle(); - ped->SetGetUp(); - return; - } - - CPed *driver = ped->m_pMyVehicle->pDriver; - - if (ped->IsPlayer()) { - ped->SetIdle(); - - } else if (ped->bFleeAfterExitingCar) { - ped->bFleeAfterExitingCar = false; - ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000); - - } else if (ped->bWanderPathAfterExitingCar) { - ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); - ped->bWanderPathAfterExitingCar = false; - - } else if (ped->bGonnaKillTheCarJacker) { - // Kill objective is already set at this point. - - ped->bGonnaKillTheCarJacker = false; - if (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) { - if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) { - ped->m_nPedState = PED_NONE; - ped->m_nLastPedState = PED_NONE; - ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000); - } else { - ped->ClearObjective(); - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); - } - } - - } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR - && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && driver - && driver->IsPlayer() && !CTheScripts::IsPlayerOnAMission()) { - -#ifndef VC_PED_PORTS - if (CGeneral::GetRandomNumber() & 1) - ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver); - else -#endif - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); - - } else { -#ifdef VC_PED_PORTS - if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR - && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !driver - && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission()) - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); - else -#endif - { - ped->m_nPedState = PED_NONE; - ped->m_nLastPedState = PED_NONE; - ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000); - } - } - ped->SetGetUp(); -} - -void -CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; - - CVehicle *veh = ped->m_pMyVehicle; - - // Pointless code - if (!veh) - return; - -#ifdef VC_PED_PORTS - // Situation of entering car as a driver while there is already a driver exiting atm. - CPed *driver = veh->pDriver; - if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR - && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) { - - if (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) { - ped->QuitEnteringCar(); - return; - } - if (driver->CharCreatedBy == MISSION_CHAR) { - PedSetOutCarCB(nil, veh->pDriver); - if (driver->m_pMyVehicle) { - driver->PositionPedOutOfCollision(); + if (Abs(angleDiffBtwObjCenterAndForward) >= objTopRightHeading) { + if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) { + if ((angleDiffBtwObjCenterAndForward <= 0.0f || objUpsideDown) && (angleDiffBtwObjCenterAndForward < 0.0f || !objUpsideDown)) { + if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { + m_walkAroundType = 0; + } else { + if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) >= 0.0f) { + if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 1; + } else if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 1; + } + } else { + if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 4; + } else if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 4; + } + } + } + } else { + if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { + m_walkAroundType = 0; + } else { + if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f) { + if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 2; + } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 2; + } + } else { + if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 3; + } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 3; + } + } + } + } + } else if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) + || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) < 0.0f) { + if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) { + m_walkAroundType = 3; + } + } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 4; + } + } else if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) + || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) { + m_walkAroundType = 2; + } + } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 1; } else { - driver->m_pMyVehicle = veh; - driver->PositionPedOutOfCollision(); - driver->m_pMyVehicle = nil; + m_walkAroundType = 0; } - veh->pDriver = nil; - } else { - driver->SetDead(); - driver->FlagToDestroyWhenNextProcessed(); - veh->pDriver = nil; } - } #endif - - if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) - return; - - ped->bInVehicle = true; - if (ped->m_nPedType == PEDTYPE_PROSTITUTE) { - if (veh->pDriver) { - if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) { - CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1000; - CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000; - CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; - CWorld::Players[CWorld::PlayerInFocus].m_pHooker = (CCivilianPed*)ped; - } - } } - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER -#if defined VC_PED_PORTS || defined FIX_BUGS - || ped->m_nPedState == PED_CARJACK -#endif - ) - veh->bIsBeingCarJacked = false; - - if (veh->m_nNumGettingIn) - --veh->m_nNumGettingIn; + m_collidingEntityWhileFleeing = obj; + m_collidingEntityWhileFleeing->RegisterReference((CEntity**) &m_collidingEntityWhileFleeing); - if (ped->IsPlayer() && ((CPlayerPed*)ped)->m_bAdrenalineActive) - ((CPlayerPed*)ped)->ClearAdrenaline(); + // TODO: This random may need to be changed. + m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 512 + CGeneral::GetRandomNumber(); - if (veh->IsBoat()) { - if (ped->IsPlayer()) { -#if defined VC_PED_PORTS || defined FIX_BUGS - CCarCtrl::RegisterVehicleOfInterest(veh); -#endif - if (veh->GetStatus() == STATUS_SIMPLE) { - veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.00001f); - veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - } - veh->SetStatus(STATUS_PLAYER); - AudioManager.PlayerJustGotInCar(); - } - veh->SetDriver(ped); - if (!veh->bEngineOn) - veh->bEngineOn = true; + CVector localPosToHead; - ped->m_nPedState = PED_DRIVING; - ped->StopNonPartialAnims(); - return; +#ifdef NEW_WALK_AROUND_ALGORITHM + int nextWalkAround = m_walkAroundType; + if (m_walkAroundType % 2 == 0) { + nextWalkAround += 2; + if (nextWalkAround > 6) + nextWalkAround = 0; + } else { + nextWalkAround -= 2; + if (nextWalkAround < 0) + nextWalkAround = 7; } - if (ped->m_pVehicleAnim) - ped->m_pVehicleAnim->blendDelta = -1000.0f; + CVector nextPosToHead = objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, nextWalkAround, goingToEnterCar ? m_vehEnterType : 0, goingToEnterCarAndItsVan); + bool nextRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), nextPosToHead, true, true, true, true, true, true, false); - ped->bDoBloodyFootprints = false; - if (veh->m_nAlarmState == -1) - veh->m_nAlarmState = 15000; + if(nextRouteIsClear) + m_walkAroundType = nextWalkAround; + else { + CVector posToHead = objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType, goingToEnterCar ? m_vehEnterType : 0, goingToEnterCarAndItsVan); + bool currentRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), posToHead, + true, true, true, true, true, true, false); - if (ped->IsPlayer()) { - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { - if (veh->GetStatus() == STATUS_SIMPLE) { - veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - } - veh->SetStatus(STATUS_PLAYER); - } - AudioManager.PlayerJustGotInCar(); - } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { - if (veh->GetStatus() == STATUS_SIMPLE) { - veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - } - veh->SetStatus(STATUS_PHYSICS); - } - - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { - for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) { - CPed *passenger = veh->pPassengers[i]; - if (passenger && passenger->CharCreatedBy == RANDOM_CHAR) { - passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh); -#ifdef VC_PED_PORTS - passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds(); -#endif + /* Either; + * - Some obstacle came in and it's impossible to reach current destination + * - We reached to the destination, but since next route is not clear, we're turning around us + */ + if (!currentRouteIsClear || + ((posToHead - GetPosition()).Magnitude2D() < 0.8f && + !CWorld::GetIsLineOfSightClear(GetPosition() + GetForward(), nextPosToHead, + true, true, true, true, true, true, false))) { + + // Change both target and direction (involves changing even/oddness) + if (m_walkAroundType % 2 == 0) { + m_walkAroundType -= 2; + if (m_walkAroundType < 0) + m_walkAroundType = 7; + else + m_walkAroundType += 1; + } else { + m_walkAroundType += 2; + if (m_walkAroundType > 7) + m_walkAroundType = 0; + else + m_walkAroundType -= 1; } } } - // This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below. -#if !defined VC_PED_PORTS && !defined FIX_BUGS - else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { - if (ped->m_nPedState == PED_CARJACK) { - veh->AddPassenger(ped, 0); - ped->m_nPedState = PED_DRIVING; - ped->RestorePreviousObjective(); - ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); - } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) { - veh->AutoPilot.m_nCruiseSpeed = 17; - } - } -#endif - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK) { - veh->SetDriver(ped); - if (veh->VehicleCreatedBy == PARKED_VEHICLE) { - veh->VehicleCreatedBy = RANDOM_VEHICLE; - ++CCarCtrl::NumRandomCars; - --CCarCtrl::NumParkedCars; - } - if (veh->bIsAmbulanceOnDuty) { - veh->bIsAmbulanceOnDuty = false; - --CCarCtrl::NumAmbulancesOnDuty; - } - if (veh->bIsFireTruckOnDuty) { - veh->bIsFireTruckOnDuty = false; - --CCarCtrl::NumFiretrucksOnDuty; - } - if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle()) - veh->ChangeLawEnforcerState(true); + localPosToHead = LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType, goingToEnterCar ? m_vehEnterType : 0, goingToEnterCarAndItsVan); +#else + if (Abs(angleDiffBtwObjCenterAndForward) < objTopRightHeading) { + if (goingToEnterCar) { + if (goingToEnterCarAndItsVan) { + if (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR) + return; + } + if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnBottomRightOfObj || entityOnBottomLeftOfObj)) { + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } + } else { + if (m_walkAroundType != 1 && m_walkAroundType != 4 + && (m_walkAroundType || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f)) { - if (!veh->bEngineOn) { - veh->bEngineOn = true; - DMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f); + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } } - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && ped->CharCreatedBy == RANDOM_CHAR - && ped != FindPlayerPed() && ped->m_nPedType != PEDTYPE_EMERGENCY) { + } else { + if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) { + if (angleDiffBtwObjCenterAndForward <= 0.0f) { + if (!goingToEnterCar || !goingToEnterCarAndItsVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR) { + if (goingToEnterCar) { + if (m_vehEnterType == CAR_DOOR_RF || (m_vehEnterType == CAR_DOOR_RR && !goingToEnterCarAndItsVan)) + return; + } + if (m_walkAroundType == 4 || m_walkAroundType == 3 + || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { - CCarCtrl::JoinCarWithRoadSystem(veh); - veh->AutoPilot.m_nCarMission = MISSION_CRUISE; - veh->AutoPilot.m_nTempAction = TEMPACT_NONE; - veh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; - veh->AutoPilot.m_nCruiseSpeed = 25; - } - ped->m_nPedState = PED_DRIVING; - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + m_fRotationDest = dirToSet; + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } + } else if (goingToEnterCar && goingToEnterCarAndItsVan && (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR)) { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + if (goingToEnterCar) { + if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR && !goingToEnterCarAndItsVan) + return; + } + if (m_walkAroundType == 1 || m_walkAroundType == 2 + || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { - if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT) - ped->m_prevObjective = OBJECTIVE_NONE; + m_fRotationDest = dirToSet; + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } + } + } else { + if (goingToEnterCar && (!goingToEnterCarAndItsVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR)) { + if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnTopRightOfObj || entityOnTopLeftOfObj)) { - ped->RestorePreviousObjective(); - } + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } + } else { + if (m_walkAroundType == 2 || m_walkAroundType == 3 + || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { - } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { - if (veh->bIsBus) { - veh->AddPassenger(ped); - } else { - switch (ped->m_vehEnterType) { - case CAR_DOOR_RF: - veh->AddPassenger(ped, 0); - break; - case CAR_DOOR_RR: - veh->AddPassenger(ped, 2); - break; - case CAR_DOOR_LR: - veh->AddPassenger(ped, 1); - break; - default: - veh->AddPassenger(ped); - break; + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } } } - ped->m_nPedState = PED_DRIVING; - if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT) - ped->m_prevObjective = OBJECTIVE_NONE; - - ped->RestorePreviousObjective(); -#ifdef VC_PED_PORTS - if(veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) - veh->AutoPilot.m_nCruiseSpeed = 17; -#endif } +#endif + if (objUpsideDown) + localPosToHead.x = localPosToHead.x * -1.0f; - veh->m_nGettingInFlags &= ~GetCarDoorFlag(ped->m_vehEnterType); - - if (veh->bIsBus && !veh->m_nGettingInFlags) - ((CAutomobile*)veh)->SetBusDoorTimer(1000, 1); - - switch (ped->m_objective) { - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_LEAVE_CAR: - case OBJECTIVE_FOLLOW_CAR_IN_CAR: - case OBJECTIVE_GOTO_AREA_ANY_MEANS: - case OBJECTIVE_GOTO_AREA_ON_FOOT: - case OBJECTIVE_RUN_TO_AREA: - break; - default: - ped->SetObjective(OBJECTIVE_NONE); - } + localPosToHead = objMat * localPosToHead; + m_actionX = localPosToHead.x; + m_actionY = localPosToHead.y; + localPosToHead -= GetPosition(); + m_fRotationDest = CGeneral::LimitRadianAngle(localPosToHead.Heading()); - if (veh->pDriver == ped) { - if (veh->bLowVehicle) { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f); + if (m_fRotationDest != m_fRotationCur && bHitSomethingLastFrame) { + if (m_fRotationDest == oldRotDest) { + m_fRotationDest = oldRotDest; } else { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); } - } else if (veh->bLowVehicle) { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITPLO, 100.0f); - } else { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITP, 100.0f); } - - ped->StopNonPartialAnims(); - if (veh->bIsBus) - ped->bRenderPedInCar = false; - - // FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check. -#ifndef FIX_BUGS - if (ped->IsPlayer() && !CCarCtrl::IsThisVehicleInteresting(veh) && veh->VehicleCreatedBy != MISSION_VEHICLE) { -#else - if (ped->IsPlayer() && veh->VehicleCreatedBy != MISSION_VEHICLE) { -#endif - CCarCtrl::RegisterVehicleOfInterest(veh); - if (!veh->bHasBeenOwnedByPlayer && veh->VehicleCreatedBy != MISSION_VEHICLE) - CEventList::RegisterEvent(EVENT_STEAL_CAR, EVENT_ENTITY_VEHICLE, veh, ped, 1500); + float dist = localPosToHead.Magnitude2D(); + if (dist < 0.5f) + dist = 0.5f; - veh->bHasBeenOwnedByPlayer = true; - } - ped->bChangedSeat = true; + if (dist > distLimitForTimer) + dist = distLimitForTimer; + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 280.0f * dist * checkIntervalInTime; } -void -CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg) +bool +CPed::IsPedInControl(void) { - CPed *ped = (CPed*)arg; - CTrain *veh = (CTrain*)ped->m_pMyVehicle; - - if (!veh) - return; - - ped->bInVehicle = true; - ped->m_nPedState = PED_DRIVING; - ped->RestorePreviousObjective(); - ped->SetMoveState(PEDMOVE_STILL); - veh->AddPassenger(ped); + return m_nPedState <= PED_STATES_NO_AI + && !bIsInTheAir && !bIsLanding + && m_fHealth > 0.0f; } -void -CPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg) +bool +CPed::IsPedShootable(void) { - /* - CPed *ped = (CPed*)arg; - - if (ped->m_nPedState == PED_STAGGER) - // nothing - */ + return m_nPedState <= PED_STATES_NO_ST; } -// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB but that's not true, someone made it up. bool -CPed::RunToReportCrime(eCrimeType crimeToReport) +CPed::UseGroundColModel(void) { -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - if (bRunningToPhone) { - if (!isPhoneAvailable(m_phoneId)) { - m_phoneId = -1; - bIsRunning = false; - ClearSeek(); // clears bRunningToPhone - return false; - } - - return true; - } -#else - // They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it. - if (m_nPedState == PED_SEEK_POS) - return false; -#endif + return m_nPedState == PED_FALL || + m_nPedState == PED_DIVE_AWAY || + m_nPedState == PED_DIE || + m_nPedState == PED_DEAD; +} - CVector pos = GetPosition(); - int phoneId = gPhoneInfo.FindNearestFreePhone(&pos); +bool +CPed::CanPedReturnToState(void) +{ + return m_nPedState <= PED_STATES_NO_AI && m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK && + m_nPedState != PED_FIGHT && m_nPedState != PED_STEP_AWAY && m_nPedState != PED_SNIPER_MODE && m_nPedState != PED_LOOK_ENTITY; +} - if (phoneId == -1) - return false; +bool +CPed::CanSetPedState(void) +{ + return !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR; +} - CPhone *phone = &gPhoneInfo.m_aPhones[phoneId]; -#ifndef PEDS_REPORT_CRIMES_ON_PHONE - if (phone->m_nState != PHONE_STATE_FREE) +bool +CPed::CanStrafeOrMouseControl(void) +{ +#ifdef FREE_CAM + if (CCamera::bFreeCam) return false; #endif - - bRunningToPhone = true; - SetSeek(phone->m_pEntity->GetMatrix() * -phone->m_pEntity->GetForward(), 1.0f); // original: phone.m_vecPos, 0.3f - SetMoveState(PEDMOVE_RUN); - bIsRunning = true; // not there in original - m_phoneId = phoneId; - m_crimeToReportOnPhone = crimeToReport; - return true; + return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY || + m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP; } void -CPed::RegisterThreatWithGangPeds(CEntity *attacker) +CPed::PedGetupCB(CAnimBlendAssociation* animAssoc, void* arg) { - CPed *attackerPed = nil; - if (attacker) { - if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) { - if (attacker->IsPed()) { - attackerPed = (CPed*)attacker; - } else { - if (!attacker->IsVehicle()) - return; - - attackerPed = ((CVehicle*)attacker)->pDriver; - if (!attackerPed) - return; - } - - if (attackerPed && (attackerPed->IsPlayer() || attackerPed->IsGangMember())) { - for (int i = 0; i < m_numNearPeds; ++i) { - CPed *nearPed = m_nearPeds[i]; - if (nearPed->IsPointerValid()) { - if (nearPed != this && nearPed->m_nPedType == m_nPedType) - nearPed->m_fearFlags |= CPedType::GetFlag(attackerPed->m_nPedType); - } - } - } - } - } - - if (attackerPed && attackerPed->IsPlayer() && (attackerPed->m_nPedState == PED_CARJACK || attackerPed->bInVehicle)) { - if (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOYZ) { - int16 lastVehicle; - CEntity *vehicles[8]; - CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - - if (lastVehicle > 8) - lastVehicle = 8; + CPed* ped = (CPed*)arg; - for (int j = 0; j < lastVehicle; ++j) { - CVehicle *nearVeh = (CVehicle*) vehicles[j]; + if (ped->m_nPedState == PED_GETUP) + RpAnimBlendClumpSetBlendDeltas(ped->GetClump(), ASSOC_PARTIAL, -1000.0f); - if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) { - CPed *nearVehDriver = nearVeh->pDriver; + ped->bFallenDown = false; + animAssoc->blendDelta = -1000.0f; + if (ped->m_nPedState == PED_GETUP) + ped->RestorePreviousState(); - if (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType) { + if (ped->m_nPedState != PED_FLEE_POS && ped->m_nPedState != PED_FLEE_ENTITY) + ped->SetMoveState(PEDMOVE_STILL); + else + ped->SetMoveState(PEDMOVE_RUN); - if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) { - nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f; - nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY; - nearVeh->SetStatus(STATUS_PHYSICS); - nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE; - nearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; - } - } - } - } - } - } + ped->SetMoveAnim(); + ped->bGetUpAnimStarted = false; } void -CPed::ReactToPointGun(CEntity *entWithGun) +CPed::PedLandCB(CAnimBlendAssociation* animAssoc, void* arg) { - CPed *pedWithGun = (CPed*)entWithGun; - int waitTime; - - if (IsPlayer() || !IsPedInControl() || CharCreatedBy == MISSION_CHAR) - return; - - if (m_leader == pedWithGun) - return; - - if (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER || - (GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f) - return; - - if (m_leader) { - if (FindPlayerPed() == m_leader) - return; + CPed* ped = (CPed*)arg; - ClearLeader(); - } - if (m_pedStats->m_flags & STAT_GUN_PANIC - && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee()) - && m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_AIM_GUN) { - - waitTime = CGeneral::GetRandomNumberInRange(3000, 6000); - SetWaitState(WAITSTATE_PLAYANIM_HANDSCOWER, &waitTime); - Say(SOUND_PED_HANDS_COWER); - m_pLookTarget = pedWithGun; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - SetMoveState(PEDMOVE_NONE); - - } else if (m_nPedType != pedWithGun->m_nPedType) { - if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) { - RegisterThreatWithGangPeds(pedWithGun); - } + animAssoc->blendDelta = -1000.0f; + ped->bIsLanding = false; - if (m_nPedType == PEDTYPE_COP) { - if (pedWithGun->IsPlayer()) { - ((CPlayerPed*)pedWithGun)->m_pWanted->SetWantedLevelNoDrop(2); - if (bCrouchWhenShooting || bKindaStayInSamePlace) { - SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000)); - return; - } - } - } + if (ped->m_nPedState == PED_JUMP) + ped->RestorePreviousState(); +} - if (m_nPedType != PEDTYPE_COP - && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee()) - && (m_nPedState != PED_FLEE_ENTITY || pedWithGun->IsPlayer() && m_fleeFrom != pedWithGun) - && m_nPedState != PED_AIM_GUN && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { - - waitTime = CGeneral::GetRandomNumberInRange(3000, 6000); - SetWaitState(WAITSTATE_PLAYANIM_HANDSUP, &waitTime); - Say(SOUND_PED_HANDS_UP); - m_pLookTarget = pedWithGun; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - SetMoveState(PEDMOVE_NONE); - if (m_nPedState == PED_FLEE_ENTITY) { - m_fleeFrom = pedWithGun; - m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom); - } +void +CPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + /* + CPed *ped = (CPed*)arg; - if (FindPlayerPed() == pedWithGun && bRichFromMugging) { - int money = CGeneral::GetRandomNumberInRange(100, 300); - int pickupCount = money / 40 + 1; - int moneyPerPickup = money / pickupCount; - - for (int i = 0; i < pickupCount; i++) { - float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x; - float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y; - bool found = false; - float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f; - if (found) { - CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7)); - } - } - bRichFromMugging = false; - } - } - } + if (ped->m_nPedState == PED_STAGGER) + // nothing + */ } void @@ -11857,1850 +4211,1098 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) ped->SetMoveState(PEDMOVE_RUN); ped->Say(SOUND_PED_FLEE_RUN); } - startedToRun = true; + startedToRun = true; + + // This is not a good way to do this... + ped->m_nLastPedState = PED_WANDER_PATH; + + } else if (ped->bWanderPathAfterExitingCar) { + ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); + ped->bWanderPathAfterExitingCar = false; + if (ped->m_nPedType == PEDTYPE_PROSTITUTE) + ped->SetObjectiveTimer(30000); + ped->m_nLastPedState = PED_NONE; + + } else if (ped->bGonnaKillTheCarJacker) { + + // Kill objective is already given at this point. + ped->bGonnaKillTheCarJacker = false; + if (ped->m_pedInObjective) { + if (!(CGeneral::GetRandomNumber() & 1) + && ped->m_nPedType != PEDTYPE_COP + && (!ped->m_pedInObjective->IsPlayer() || !CTheScripts::IsPlayerOnAMission())) { + ped->ClearObjective(); + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + } + ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1500; + } + int waitTime = 1500; + ped->SetWaitState(WAITSTATE_PLAYANIM_COWER, &waitTime); + ped->SetMoveState(PEDMOVE_RUN); + startedToRun = true; + } else if (ped->m_objective == OBJECTIVE_NONE && ped->CharCreatedBy != MISSION_CHAR && ped->m_nPedState == PED_IDLE && !ped->IsPlayer()) { + ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); + } + } +#ifdef VC_PED_PORTS + else { + ped->m_nPedState = PED_IDLE; + } +#endif + + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + ped->RestartNonPartialAnims(); + ped->m_pVehicleAnim = nil; + CVector posFromZ = ped->GetPosition(); + CPedPlacement::FindZCoorForPed(&posFromZ); + ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + ped->SetPosition(posFromZ); + veh = ped->m_pMyVehicle; + if (veh) { + if (ped->m_nPedType == PEDTYPE_PROSTITUTE) { + if (veh->pDriver) { + if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) { + CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = 0; + CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = 0; + CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; + CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= 100; + if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney < 0) + CWorld::Players[CWorld::PlayerInFocus].m_nMoney = 0; + } + } + } + veh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType); + if (veh->pDriver == ped) { + veh->RemoveDriver(); + veh->SetStatus(STATUS_ABANDONED); + if (veh->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) + veh->m_nDoorLock = CARLOCK_UNLOCKED; + if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle()) + veh->ChangeLawEnforcerState(false); + } else { + veh->RemovePassenger(ped); + } + + if (veh->bIsBus && !veh->IsUpsideDown() && !veh->IsOnItsSide()) { + float angleAfterExit; + if (ped->m_vehEnterType == CAR_DOOR_LF) { + angleAfterExit = HALFPI + veh->GetForward().Heading(); + } else { + angleAfterExit = veh->GetForward().Heading() - HALFPI; + } + ped->SetHeading(angleAfterExit); + ped->m_fRotationDest = angleAfterExit; + ped->m_fRotationCur = angleAfterExit; + if (!ped->bBusJacked) + ped->SetMoveState(PEDMOVE_WALK); + } + if (CGarages::IsPointWithinAnyGarage(ped->GetPosition())) + veh->bLightsOn = false; + } + + if (ped->IsPlayer()) + AudioManager.PlayerJustLeftCar(); + + ped->ReplaceWeaponWhenExitingVehicle(); + + ped->bOnBoat = false; + if (ped->bBusJacked) { + ped->SetFall(1500, ANIM_KO_SKID_BACK, false); + ped->bBusJacked = false; + } + ped->m_nStoredMoveState = PEDMOVE_NONE; + if (!ped->IsPlayer()) { + // It's a shame... +#ifdef FIX_BUGS + int createdBy = ped->CharCreatedBy; +#else + int createdBy = !ped->CharCreatedBy; +#endif + + if (createdBy == MISSION_CHAR && !startedToRun) + ped->SetMoveState(PEDMOVE_WALK); + } +} + +void +CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) +{ + CAnimBlendAssociation *quickJackedAssoc; + CVehicle *vehicle; + CPed *ped = (CPed*)arg; + + quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED); + if (ped->m_nPedState != PED_ARRESTED) { + ped->m_nLastPedState = PED_NONE; + if (dragAssoc) + dragAssoc->blendDelta = -1000.0f; + } + ped->RestartNonPartialAnims(); + ped->m_pVehicleAnim = nil; + ped->m_pSeekTarget = nil; + vehicle = ped->m_pMyVehicle; + + if (vehicle) { + vehicle->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType); + + if (vehicle->pDriver == ped) { + vehicle->RemoveDriver(); + if (vehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) + vehicle->m_nDoorLock = CARLOCK_UNLOCKED; + + if (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle()) + vehicle->ChangeLawEnforcerState(false); + } else { + vehicle->RemovePassenger(ped); + } + } + ped->bInVehicle = false; + if (ped->IsPlayer()) + AudioManager.PlayerJustLeftCar(); + +#ifdef VC_PED_PORTS + if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { + dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped); + ped->m_fHealth = 0.0f; + ped->SetDie(ANIM_FLOOR_HIT, 1000.0f, 0.5f); + return; + } +#endif + + if (quickJackedAssoc) { + dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped); + } else { + dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped); + if (ped->CanSetPedState()) + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + } + + ped->ReplaceWeaponWhenExitingVehicle(); + + ped->m_nStoredMoveState = PEDMOVE_NONE; + ped->bVehExitWillBeInstant = false; +} + +void +CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; + + CVehicle *veh = ped->m_pMyVehicle; + + // Pointless code + if (!veh) + return; + +#ifdef VC_PED_PORTS + // Situation of entering car as a driver while there is already a driver exiting atm. + CPed *driver = veh->pDriver; + if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR + && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) { + + if (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) { + ped->QuitEnteringCar(); + return; + } + if (driver->CharCreatedBy == MISSION_CHAR) { + PedSetOutCarCB(nil, veh->pDriver); + if (driver->m_pMyVehicle) { + driver->PositionPedOutOfCollision(); + } else { + driver->m_pMyVehicle = veh; + driver->PositionPedOutOfCollision(); + driver->m_pMyVehicle = nil; + } + veh->pDriver = nil; + } else { + driver->SetDead(); + driver->FlagToDestroyWhenNextProcessed(); + veh->pDriver = nil; + } + } +#endif + + if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) + return; + + ped->bInVehicle = true; + if (ped->m_nPedType == PEDTYPE_PROSTITUTE) { + if (veh->pDriver) { + if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) { + CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1000; + CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000; + CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; + CWorld::Players[CWorld::PlayerInFocus].m_pHooker = (CCivilianPed*)ped; + } + } + } + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER +#if defined VC_PED_PORTS || defined FIX_BUGS + || ped->m_nPedState == PED_CARJACK +#endif + ) + veh->bIsBeingCarJacked = false; + + if (veh->m_nNumGettingIn) + --veh->m_nNumGettingIn; + + if (ped->IsPlayer() && ((CPlayerPed*)ped)->m_bAdrenalineActive) + ((CPlayerPed*)ped)->ClearAdrenaline(); + + if (veh->IsBoat()) { + if (ped->IsPlayer()) { +#if defined VC_PED_PORTS || defined FIX_BUGS + CCarCtrl::RegisterVehicleOfInterest(veh); +#endif + if (veh->GetStatus() == STATUS_SIMPLE) { + veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.00001f); + veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + } + veh->SetStatus(STATUS_PLAYER); + AudioManager.PlayerJustGotInCar(); + } + veh->SetDriver(ped); + if (!veh->bEngineOn) + veh->bEngineOn = true; - // This is not a good way to do this... - ped->m_nLastPedState = PED_WANDER_PATH; + ped->m_nPedState = PED_DRIVING; + ped->StopNonPartialAnims(); + return; + } - } else if (ped->bWanderPathAfterExitingCar) { - ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); - ped->bWanderPathAfterExitingCar = false; - if (ped->m_nPedType == PEDTYPE_PROSTITUTE) - ped->SetObjectiveTimer(30000); - ped->m_nLastPedState = PED_NONE; + if (ped->m_pVehicleAnim) + ped->m_pVehicleAnim->blendDelta = -1000.0f; - } else if (ped->bGonnaKillTheCarJacker) { + ped->bDoBloodyFootprints = false; + if (veh->m_nAlarmState == -1) + veh->m_nAlarmState = 15000; - // Kill objective is already given at this point. - ped->bGonnaKillTheCarJacker = false; - if (ped->m_pedInObjective) { - if (!(CGeneral::GetRandomNumber() & 1) - && ped->m_nPedType != PEDTYPE_COP - && (!ped->m_pedInObjective->IsPlayer() || !CTheScripts::IsPlayerOnAMission())) { - ped->ClearObjective(); - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); - } - ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1500; + if (ped->IsPlayer()) { + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + if (veh->GetStatus() == STATUS_SIMPLE) { + veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); } - int waitTime = 1500; - ped->SetWaitState(WAITSTATE_PLAYANIM_COWER, &waitTime); - ped->SetMoveState(PEDMOVE_RUN); - startedToRun = true; - } else if (ped->m_objective == OBJECTIVE_NONE && ped->CharCreatedBy != MISSION_CHAR && ped->m_nPedState == PED_IDLE && !ped->IsPlayer()) { - ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); + veh->SetStatus(STATUS_PLAYER); + } + AudioManager.PlayerJustGotInCar(); + } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + if (veh->GetStatus() == STATUS_SIMPLE) { + veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); } + veh->SetStatus(STATUS_PHYSICS); } + + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) { + CPed *passenger = veh->pPassengers[i]; + if (passenger && passenger->CharCreatedBy == RANDOM_CHAR) { + passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh); #ifdef VC_PED_PORTS - else { - ped->m_nPedState = PED_IDLE; + passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds(); +#endif + } + } + } + // This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below. +#if !defined VC_PED_PORTS && !defined FIX_BUGS + else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { + if (ped->m_nPedState == PED_CARJACK) { + veh->AddPassenger(ped, 0); + ped->m_nPedState = PED_DRIVING; + ped->RestorePreviousObjective(); + ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); + } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) { + veh->AutoPilot.m_nCruiseSpeed = 17; + } } #endif - if (animAssoc) - animAssoc->blendDelta = -1000.0f; - - ped->RestartNonPartialAnims(); - ped->m_pVehicleAnim = nil; - CVector posFromZ = ped->GetPosition(); - CPedPlacement::FindZCoorForPed(&posFromZ); - ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - ped->SetPosition(posFromZ); - veh = ped->m_pMyVehicle; - if (veh) { - if (ped->m_nPedType == PEDTYPE_PROSTITUTE) { - if (veh->pDriver) { - if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) { - CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = 0; - CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = 0; - CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; - CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= 100; - if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney < 0) - CWorld::Players[CWorld::PlayerInFocus].m_nMoney = 0; - } - } + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK) { + veh->SetDriver(ped); + if (veh->VehicleCreatedBy == PARKED_VEHICLE) { + veh->VehicleCreatedBy = RANDOM_VEHICLE; + ++CCarCtrl::NumRandomCars; + --CCarCtrl::NumParkedCars; } - veh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType); - if (veh->pDriver == ped) { - veh->RemoveDriver(); - veh->SetStatus(STATUS_ABANDONED); - if (veh->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) - veh->m_nDoorLock = CARLOCK_UNLOCKED; - if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle()) - veh->ChangeLawEnforcerState(false); - } else { - veh->RemovePassenger(ped); + if (veh->bIsAmbulanceOnDuty) { + veh->bIsAmbulanceOnDuty = false; + --CCarCtrl::NumAmbulancesOnDuty; + } + if (veh->bIsFireTruckOnDuty) { + veh->bIsFireTruckOnDuty = false; + --CCarCtrl::NumFiretrucksOnDuty; } + if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle()) + veh->ChangeLawEnforcerState(true); - if (veh->bIsBus && !veh->IsUpsideDown() && !veh->IsOnItsSide()) { - float angleAfterExit; - if (ped->m_vehEnterType == CAR_DOOR_LF) { - angleAfterExit = HALFPI + veh->GetForward().Heading(); - } else { - angleAfterExit = veh->GetForward().Heading() - HALFPI; - } - ped->SetHeading(angleAfterExit); - ped->m_fRotationDest = angleAfterExit; - ped->m_fRotationCur = angleAfterExit; - if (!ped->bBusJacked) - ped->SetMoveState(PEDMOVE_WALK); + if (!veh->bEngineOn) { + veh->bEngineOn = true; + DMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f); } - if (CGarages::IsPointWithinAnyGarage(ped->GetPosition())) - veh->bLightsOn = false; - } + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && ped->CharCreatedBy == RANDOM_CHAR + && ped != FindPlayerPed() && ped->m_nPedType != PEDTYPE_EMERGENCY) { - if (ped->IsPlayer()) - AudioManager.PlayerJustLeftCar(); + CCarCtrl::JoinCarWithRoadSystem(veh); + veh->AutoPilot.m_nCarMission = MISSION_CRUISE; + veh->AutoPilot.m_nTempAction = TEMPACT_NONE; + veh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + veh->AutoPilot.m_nCruiseSpeed = 25; + } + ped->m_nPedState = PED_DRIVING; + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { - ped->ReplaceWeaponWhenExitingVehicle(); + if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT) + ped->m_prevObjective = OBJECTIVE_NONE; - ped->bOnBoat = false; - if (ped->bBusJacked) { - ped->SetFall(1500, ANIM_KO_SKID_BACK, false); - ped->bBusJacked = false; - } - ped->m_nStoredMoveState = PEDMOVE_NONE; - if (!ped->IsPlayer()) { - // It's a shame... -#ifdef FIX_BUGS - int createdBy = ped->CharCreatedBy; -#else - int createdBy = !ped->CharCreatedBy; -#endif + ped->RestorePreviousObjective(); + } - if (createdBy == MISSION_CHAR && !startedToRun) - ped->SetMoveState(PEDMOVE_WALK); + } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { + if (veh->bIsBus) { + veh->AddPassenger(ped); + } else { + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: + veh->AddPassenger(ped, 0); + break; + case CAR_DOOR_RR: + veh->AddPassenger(ped, 2); + break; + case CAR_DOOR_LR: + veh->AddPassenger(ped, 1); + break; + default: + veh->AddPassenger(ped); + break; + } + } + ped->m_nPedState = PED_DRIVING; + if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT) + ped->m_prevObjective = OBJECTIVE_NONE; + + ped->RestorePreviousObjective(); +#ifdef VC_PED_PORTS + if(veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) + veh->AutoPilot.m_nCruiseSpeed = 17; +#endif } -} -// It was inlined in III but not in VC. -inline void -CPed::ReplaceWeaponWhenExitingVehicle(void) -{ - eWeaponType weaponType = GetWeapon()->m_eWeaponType; + veh->m_nGettingInFlags &= ~GetCarDoorFlag(ped->m_vehEnterType); - // If it's Uzi, we may have stored weapon. Uzi is the only gun we can use in car. - if (IsPlayer() && weaponType == WEAPONTYPE_UZI) { - if (/*IsPlayer() && */ m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) { - SetCurrentWeapon(m_storedWeapon); - m_storedWeapon = WEAPONTYPE_UNIDENTIFIED; - } - } else { - AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId); - } -} + if (veh->bIsBus && !veh->m_nGettingInFlags) + ((CAutomobile*)veh)->SetBusDoorTimer(1000, 1); -// Same, it's inlined in III. -inline void -CPed::RemoveWeaponWhenEnteringVehicle(void) -{ - if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) { - if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED) - m_storedWeapon = GetWeapon()->m_eWeaponType; - SetCurrentWeapon(WEAPONTYPE_UZI); - } else { - CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - RemoveWeaponModel(ourWeapon->m_nModelId); + switch (ped->m_objective) { + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + case OBJECTIVE_LEAVE_CAR: + case OBJECTIVE_FOLLOW_CAR_IN_CAR: + case OBJECTIVE_GOTO_AREA_ANY_MEANS: + case OBJECTIVE_GOTO_AREA_ON_FOOT: + case OBJECTIVE_RUN_TO_AREA: + break; + default: + ped->SetObjective(OBJECTIVE_NONE); } -} -void -CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg) -{ - CPed *ped = (CPed*)arg; + if (veh->pDriver == ped) { + if (veh->bLowVehicle) { + ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f); + } else { + ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); + } + } else if (veh->bLowVehicle) { + ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITPLO, 100.0f); + } else { + ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITP, 100.0f); + } + + ped->StopNonPartialAnims(); + if (veh->bIsBus) + ped->bRenderPedInCar = false; - CVehicle *veh = ped->m_pMyVehicle; + // FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check. +#ifndef FIX_BUGS + if (ped->IsPlayer() && !CCarCtrl::IsThisVehicleInteresting(veh) && veh->VehicleCreatedBy != MISSION_VEHICLE) { +#else + if (ped->IsPlayer() && veh->VehicleCreatedBy != MISSION_VEHICLE) { +#endif + CCarCtrl::RegisterVehicleOfInterest(veh); - if (ped->m_pVehicleAnim) - ped->m_pVehicleAnim->blendDelta = -1000.0f; + if (!veh->bHasBeenOwnedByPlayer && veh->VehicleCreatedBy != MISSION_VEHICLE) + CEventList::RegisterEvent(EVENT_STEAL_CAR, EVENT_ENTITY_VEHICLE, veh, ped, 1500); - ped->bUsesCollision = true; - ped->m_pVehicleAnim = nil; - ped->bInVehicle = false; - ped->m_nPedState = PED_IDLE; - ped->RestorePreviousObjective(); - ped->SetMoveState(PEDMOVE_STILL); - - CMatrix pedMat(ped->GetMatrix()); - ped->m_fRotationCur = HALFPI + veh->GetForward().Heading(); - ped->m_fRotationDest = ped->m_fRotationCur; - CVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset); - posAfterExit += ped->GetPosition(); - CPedPlacement::FindZCoorForPed(&posAfterExit); - ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - ped->SetPosition(posAfterExit); - ped->SetHeading(ped->m_fRotationCur); - veh->RemovePassenger(ped); + veh->bHasBeenOwnedByPlayer = true; + } + ped->bChangedSeat = true; } bool -CPed::PlacePedOnDryLand(void) +CPed::CanBeDeleted(void) { - float waterLevel = 0.0f; - CEntity *foundEnt = nil; - CColPoint foundCol; - float foundColZ; - - CWaterLevel::GetWaterLevelNoWaves(GetPosition().x, GetPosition().y, GetPosition().z, &waterLevel); - - CVector potentialGround = GetPosition(); - potentialGround.z = waterLevel; - - if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false)) + if (bInVehicle) return false; - CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition(); - potentialGroundDist.z = 0.0f; - potentialGroundDist.Normalise(); - - CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point; - posToCheck.z = 3.0f + waterLevel; - - if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) { - foundColZ = foundCol.point.z; - if (foundColZ >= waterLevel) { - posToCheck.z = 0.8f + foundColZ; - SetPosition(posToCheck); - bIsStanding = true; - bWasStanding = true; + switch (CharCreatedBy) { + case RANDOM_CHAR: + return true; + case MISSION_CHAR: + return false; + default: return true; - } } - - posToCheck = 5.0f * potentialGroundDist + GetPosition(); - posToCheck.z = 3.0f + waterLevel; - - if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) - return false; - - foundColZ = foundCol.point.z; - if (foundColZ < waterLevel) - return false; - - posToCheck.z = 0.8f + foundColZ; - SetPosition(posToCheck); - bIsStanding = true; - bWasStanding = true; - return true; } void -CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg) +CPed::AddWeaponModel(int id) { - CPed *ped = (CPed*)arg; - - CVehicle *veh = ped->m_pMyVehicle; - - CVector finalPos; - CVector draggedOutOffset; - - CMatrix pedMat(ped->GetMatrix()); - ped->bUsesCollision = true; - ped->RestartNonPartialAnims(); - draggedOutOffset = vecPedQuickDraggedOutCarAnimOffset; - if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR) - draggedOutOffset.x = -draggedOutOffset.x; - - finalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition(); - CPedPlacement::FindZCoorForPed(&finalPos); - ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - ped->SetPosition(finalPos); - - if (veh) { - ped->m_fRotationDest = veh->GetForward().Heading() - HALFPI; - ped->m_fRotationCur = ped->m_fRotationDest; - ped->CalculateNewOrientation(); - - if (!veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedQuickDraggedOutCarAnimOffset)) - ped->PositionPedOutOfCollision(); - } - - if (!ped->CanSetPedState()) - return; - - ped->SetIdle(); - if (veh) { - if (ped->bFleeAfterExitingCar) { - ped->bFleeAfterExitingCar = false; - ped->SetFlee(veh->GetPosition(), 14000); - - } else if (ped->bWanderPathAfterExitingCar) { - ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); - ped->bWanderPathAfterExitingCar = false; - - } else if (ped->bGonnaKillTheCarJacker) { - ped->bGonnaKillTheCarJacker = false; - if (ped->m_pedInObjective && CGeneral::GetRandomNumber() & 1) { - if (ped->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) - ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped->m_pedInObjective); - - } else { - CPed *driver = veh->pDriver; - if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) { - ped->SetFlee(veh->GetPosition(), 14000); - } else { - ped->ClearObjective(); - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); - } - ped->bUsePedNodeSeek = true; - ped->m_pNextPathNode = nil; - ped->Say(SOUND_PED_FLEE_RUN); - } - } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear - && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE - && veh->pDriver && veh->pDriver->IsPlayer() - && !CTheScripts::IsPlayerOnAMission()) { + RpAtomic *atm; -#ifndef VC_PED_PORTS - if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) { - ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver); - } else -#endif - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + if (id != -1) { +#ifdef PED_SKIN + if (IsClumpSkinned(GetClump())) { + if (m_pWeaponModel) + RemoveWeaponModel(-1); -#ifdef VC_PED_PORTS - } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear - && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE - && !veh->pDriver && FindPlayerPed()->m_carInObjective == veh - && !CTheScripts::IsPlayerOnAMission()) { - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); + } else #endif - } else { - ped->SetFindPathAndFlee(veh->GetPosition(), 10000); - if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) { - ped->SetMoveState(PEDMOVE_SPRINT); - ped->Say(SOUND_PED_FLEE_SPRINT); - } else { - ped->Say(SOUND_PED_FLEE_RUN); - } + { + atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); + RwFrameDestroy(RpAtomicGetFrame(atm)); + RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame); + RpClumpAddAtomic(GetClump(), atm); } + m_wepModelID = id; } - if (ped->m_nLastPedState == PED_IDLE) - ped->m_nLastPedState = PED_WANDER_PATH; } -bool -CPed::PositionPedOutOfCollision(void) +static RwObject* +RemoveAllModelCB(RwObject *object, void *data) { - CVehicle *veh; - CVector posNearVeh; - CVector posSomewhereClose; - bool putNearVeh = false; - bool putSomewhereClose = false; - int smallestDistNearVeh = 999; - int smallestDistSomewhereClose = 999; - - if (!m_pMyVehicle) - return false; - - CVector vehPos = m_pMyVehicle->GetPosition(); - CVector potentialPos; - potentialPos.y = GetPosition().y - 3.5f; - potentialPos.z = GetPosition().z; - - for (int yTry = 0; yTry < 15; yTry++) { - potentialPos.x = GetPosition().x - 3.5f; - - for (int xTry = 0; xTry < 15; xTry++) { - CPedPlacement::FindZCoorForPed(&potentialPos); - CVector distVec = potentialPos - vehPos; - float dist = distVec.Magnitude(); - - // Makes close distances bigger for some reason. - float mult = (0.6f + dist) / dist; - CVector adjustedPotentialPos = distVec * mult + vehPos; - if (CWorld::GetIsLineOfSightClear(vehPos, adjustedPotentialPos, true, false, false, true, false, false, false) - && !CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) { - - float potentialChangeSqr = (potentialPos - GetPosition()).MagnitudeSqr(); - veh = (CVehicle*)CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, false, true, false, false, false, false); - if (veh) { - if (potentialChangeSqr < smallestDistNearVeh) { - posNearVeh = potentialPos; - putNearVeh = true; - smallestDistNearVeh = potentialChangeSqr; - } - } else if (potentialChangeSqr < smallestDistSomewhereClose) { - smallestDistSomewhereClose = potentialChangeSqr; - posSomewhereClose = potentialPos; - putSomewhereClose = true; - } - } - potentialPos.x += 0.5f; - } - potentialPos.y += 0.5f; - } - - if (!putSomewhereClose && !putNearVeh) - return false; - - // We refrain from using posNearVeh, probably because of it may be top of the vehicle. - if (putSomewhereClose) { - SetPosition(posSomewhereClose); - } else { - CVector vehSize = veh->GetModelInfo()->GetColModel()->boundingBox.max; - posNearVeh.z += vehSize.z; - SetPosition(posNearVeh); + RpAtomic *atomic = (RpAtomic*)object; + if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) { + RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic); + RpAtomicDestroy(atomic); } - return true; + return object; } -bool -CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh) +void +CPed::RemoveWeaponModel(int modelId) { - bool foundIt = false; - - CVector helperPos = GetPosition(); - helperPos.z = pos->z - 0.5f; - - CVector foundPos = *pos; - foundPos.z -= 0.5f; - - // If there is another car between target car and us. - if (CWorld::TestSphereAgainstWorld((foundPos + helperPos) / 2.0f, 0.25f, veh, false, true, false, false, false, false)) { - - CColModel *vehCol = veh->GetModelInfo()->GetColModel(); - CVector *colMin = &vehCol->boundingBox.min; - CVector *colMax = &vehCol->boundingBox.max; - - CVector leftRearPos = CVector(colMin->x - 0.5f, colMin->y - 0.5f, 0.0f); - CVector rightRearPos = CVector(0.5f + colMax->x, colMin->y - 0.5f, 0.0f); - CVector leftFrontPos = CVector(colMin->x - 0.5f, 0.5f + colMax->y, 0.0f); - CVector rightFrontPos = CVector(0.5f + colMax->x, 0.5f + colMax->y, 0.0f); - - leftRearPos = veh->GetMatrix() * leftRearPos; - rightRearPos = veh->GetMatrix() * rightRearPos; - leftFrontPos = veh->GetMatrix() * leftFrontPos; - rightFrontPos = veh->GetMatrix() * rightFrontPos; - - // Makes helperPos veh-ped distance vector. - helperPos -= veh->GetPosition(); - - // ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour. - // On every run it returns another pos. for ped, with same distance to the veh. - // Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't) - helperPos = veh->GetMatrix() * helperPos; - - float vehForwardHeading = veh->GetForward().Heading(); - - // I'm absolutely not sure about these namings. - // NTVF = needed turn if we're looking to vehicle front and wanna look to... - - float potentialLrHeading = Atan2(leftRearPos.x - helperPos.x, leftRearPos.y - helperPos.y); - float NTVF_LR = CGeneral::LimitRadianAngle(potentialLrHeading - vehForwardHeading); - - float potentialRrHeading = Atan2(rightRearPos.x - helperPos.x, rightRearPos.y - helperPos.y); - float NTVF_RR = CGeneral::LimitRadianAngle(potentialRrHeading - vehForwardHeading); - - float potentialLfHeading = Atan2(leftFrontPos.x - helperPos.x, leftFrontPos.y - helperPos.y); - float NTVF_LF = CGeneral::LimitRadianAngle(potentialLfHeading - vehForwardHeading); - - float potentialRfHeading = Atan2(rightFrontPos.x - helperPos.x, rightFrontPos.y - helperPos.y); - float NTVF_RF = CGeneral::LimitRadianAngle(potentialRfHeading - vehForwardHeading); - - bool canHeadToLr = NTVF_LR <= -PI || NTVF_LR >= -HALFPI; - - bool canHeadToRr = NTVF_RR <= HALFPI || NTVF_RR >= PI; - - bool canHeadToLf = NTVF_LF >= 0.0f || NTVF_LF <= -HALFPI; - - bool canHeadToRf = NTVF_RF <= 0.0f || NTVF_RF >= HALFPI; - - // Only order of conditions are different among enterTypes. - if (m_vehEnterType == CAR_DOOR_RR) { - if (canHeadToRr) { - foundPos = rightRearPos; - foundIt = true; - } else if (canHeadToRf) { - foundPos = rightFrontPos; - foundIt = true; - } else if (canHeadToLr) { - foundPos = leftRearPos; - foundIt = true; - } else if (canHeadToLf) { - foundPos = leftFrontPos; - foundIt = true; - } - } else if(m_vehEnterType == CAR_DOOR_RF) { - if (canHeadToRf) { - foundPos = rightFrontPos; - foundIt = true; - } else if (canHeadToRr) { - foundPos = rightRearPos; - foundIt = true; - } else if (canHeadToLf) { - foundPos = leftFrontPos; - foundIt = true; - } else if (canHeadToLr) { - foundPos = leftRearPos; - foundIt = true; - } - } else if (m_vehEnterType == CAR_DOOR_LF) { - if (canHeadToLf) { - foundPos = leftFrontPos; - foundIt = true; - } else if (canHeadToLr) { - foundPos = leftRearPos; - foundIt = true; - } else if (canHeadToRf) { - foundPos = rightFrontPos; - foundIt = true; - } else if (canHeadToRr) { - foundPos = rightRearPos; - foundIt = true; - } - } else if (m_vehEnterType == CAR_DOOR_LR) { - if (canHeadToLr) { - foundPos = leftRearPos; - foundIt = true; - } else if (canHeadToLf) { - foundPos = leftFrontPos; - foundIt = true; - } else if (canHeadToRr) { - foundPos = rightRearPos; - foundIt = true; - } else if (canHeadToRf) { - foundPos = rightFrontPos; - foundIt = true; - } + // modelId is not used!! This function just removes the current weapon. +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + if(m_pWeaponModel){ + RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel); + RpAtomicDestroy(m_pWeaponModel); + RwFrameDestroy(frm); + m_pWeaponModel = nil; } + }else +#endif + RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil); + m_wepModelID = -1; +} + +uint32 +CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo) +{ + CWeapon &weapon = GetWeapon(weaponType); + + if (HasWeapon(weaponType)) { + if (weapon.m_nAmmoTotal + ammo > 99999) + weapon.m_nAmmoTotal = 99999; + else + weapon.m_nAmmoTotal += ammo; + + weapon.Reload(); + } else { + weapon.Initialise(weaponType, ammo); + // TODO: It seems game uses this as both weapon count and max WeaponType we have, which is ofcourse erroneous. + m_maxWeaponTypeAllowed++; } - if (!foundIt) - return false; + if (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO) + weapon.m_eWeaponState = WEAPONSTATE_READY; - helperPos = GetPosition() - foundPos; - helperPos.z = 0.0f; - if (helperPos.MagnitudeSqr() <= sq(0.5f)) - return false; + return weaponType; +} - pos->x = foundPos.x; - pos->y = foundPos.y; - return true; +// Some kind of VC leftover I think +int +CPed::GetWeaponSlot(eWeaponType weaponType) +{ + if (HasWeapon(weaponType)) + return weaponType; + else + return -1; } void -CPed::Render(void) +CPed::SetCurrentWeapon(uint32 weaponType) { - if (bInVehicle && m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR) { - if (!bRenderPedInCar) - return; - - float camDistSq = (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr(); - if (camDistSq > SQR(25.0f * TheCamera.LODDistMultiplier)) - return; - } + CWeaponInfo *weaponInfo; + if (HasWeapon(weaponType)) { + weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + RemoveWeaponModel(weaponInfo->m_nModelId); - CEntity::Render(); + m_currentWeapon = weaponType; -#ifdef PED_SKIN - if(IsClumpSkinned(GetClump())){ - renderLimb(PED_HEAD); - renderLimb(PED_HANDL); - renderLimb(PED_HANDR); - } - if(m_pWeaponModel && IsClumpSkinned(GetClump())){ - RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); - int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID); - RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; - RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel); - *RwFrameGetMatrix(frame) = *mat; - RwFrameUpdateObjects(frame); - RpAtomicRender(m_pWeaponModel); + weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + AddWeaponModel(weaponInfo->m_nModelId); } -#endif } -#ifdef PED_SKIN -static RpMaterial* -SetLimbAlphaCB(RpMaterial *material, void *data) +void +CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo) { - ((RwRGBA*)RpMaterialGetColor(material))->alpha = *(uint8*)data; - return material; + if (HasWeapon(weaponType)) { + GetWeapon(weaponType).m_nAmmoTotal += ammo; + } else { + GetWeapon(weaponType).Initialise(weaponType, ammo); + m_maxWeaponTypeAllowed++; + } } void -CPed::renderLimb(int node) +CPed::SetAmmo(eWeaponType weaponType, uint32 ammo) { - RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); - int idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID); - RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; - CPedModelInfo *mi = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()); - RpAtomic *atomic; - switch(node){ - case PED_HEAD: - atomic = mi->getHead(); - break; - case PED_HANDL: - atomic = mi->getLeftHand(); - break; - case PED_HANDR: - atomic = mi->getRightHand(); - break; - default: - return; + if (HasWeapon(weaponType)) { + GetWeapon(weaponType).m_nAmmoTotal = ammo; + } else { + GetWeapon(weaponType).Initialise(weaponType, ammo); + m_maxWeaponTypeAllowed++; } - if(atomic == nil) - return; - - RwFrame *frame = RpAtomicGetFrame(atomic); - *RwFrameGetMatrix(frame) = *mat; - RwFrameUpdateObjects(frame); - int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); - RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha); - RpAtomicRender(atomic); } -#endif void -CPed::ProcessObjective(void) +CPed::ClearWeapons(void) { - if (bClearObjective && (IsPedInControl() || m_nPedState == PED_DRIVING)) { - ClearObjective(); - bClearObjective = false; - } - UpdateFromLeader(); - - CVector carOrOurPos; - CVector targetCarOrHisPos; - CVector distWithTarget; - - if (m_objective != OBJECTIVE_NONE && (IsPedInControl() || m_nPedState == PED_DRIVING)) { - if (bInVehicle) { - if (!m_pMyVehicle) { - bInVehicle = false; - return; - } - carOrOurPos = m_pMyVehicle->GetPosition(); - } else { - carOrOurPos = GetPosition(); - } - - if (m_pedInObjective) { - if (m_pedInObjective->InVehicle() && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { - targetCarOrHisPos = m_pedInObjective->m_pMyVehicle->GetPosition(); - } else { - targetCarOrHisPos = m_pedInObjective->GetPosition(); - } - distWithTarget = targetCarOrHisPos - carOrOurPos; - } else if (m_carInObjective) { - targetCarOrHisPos = m_carInObjective->GetPosition(); - distWithTarget = targetCarOrHisPos - carOrOurPos; - } + CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + RemoveWeaponModel(currentWeapon->m_nModelId); - switch (m_objective) { - case OBJECTIVE_NONE: - case OBJECTIVE_GUARD_AREA: - case OBJECTIVE_FOLLOW_CAR_IN_CAR: - case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE: - case OBJECTIVE_DESTROY_OBJECT: - case OBJECTIVE_GOTO_AREA_IN_CAR: - case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: - case OBJECTIVE_SET_LEADER: - break; - case OBJECTIVE_WAIT_ON_FOOT: - SetIdle(); - m_objective = OBJECTIVE_NONE; - SetMoveState(PEDMOVE_STILL); - break; - case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: - if (InVehicle()) { - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - bFleeAfterExitingCar = true; - } else if (m_nPedState != PED_FLEE_POS) { - CVector2D fleePos = GetPosition(); - SetFlee(fleePos, 10000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - } - break; - case OBJECTIVE_GUARD_SPOT: - { - distWithTarget = m_vecSeekPosEx - GetPosition(); - if (m_pedInObjective) { - SetLookFlag(m_pedInObjective, true); - m_pLookTarget = m_pedInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - TurnBody(); - } - float distWithTargetSc = distWithTarget.Magnitude(); - if (2.0f * m_distanceToCountSeekDoneEx >= distWithTargetSc) { - if (m_pedInObjective) { - if (distWithTargetSc <= m_distanceToCountSeekDoneEx) - SetIdle(); - else - SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx); - } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { - int threatType = ScanForThreats(); - SetLookTimer(CGeneral::GetRandomNumberInRange(500, 1500)); - - // Second condition is pointless and isn't there in Mobile. - if (threatType == PED_FLAG_GUN || (threatType == PED_FLAG_EXPLOSION && m_threatEntity) || m_threatEntity) { - if (m_threatEntity->IsPed()) - SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity); - } - } - } else { - SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx); - } - break; - } - case OBJECTIVE_WAIT_IN_CAR: - m_nPedState = PED_DRIVING; - break; - case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: - m_nPedState = PED_DRIVING; - break; - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - { - if (m_pedInObjective) { - if (m_pedInObjective->IsPlayer() && CharCreatedBy != MISSION_CHAR - && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops != 0 - && !bKindaStayInSamePlace) { + m_maxWeaponTypeAllowed = WEAPONTYPE_BASEBALLBAT; + m_currentWeapon = WEAPONTYPE_UNARMED; - SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); - break; - } - if (InVehicle()) { - if (distWithTarget.Magnitude() >= 20.0f - || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() >= sq(0.02f)) { - if (m_pMyVehicle->pDriver == this - && !m_pMyVehicle->m_nGettingInFlags) { - 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_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_nCarMission = MISSION_RAMPLAYER_FARAWAY; - } - m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; - } - } else { - bool targetHasVeh = m_pedInObjective->bInVehicle; - if (!targetHasVeh - || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) { - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } - } - break; - } - if (distWithTarget.Magnitude() > 30.0f && !bKindaStayInSamePlace) { - if (m_pMyVehicle) { - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); - } else { - float closestVehDist = 60.0f; - int16 lastVehicle; - CEntity* vehicles[8]; - CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - CVehicle *foundVeh = nil; - for(int i = 0; i < lastVehicle; i++) { - CVehicle *nearVeh = (CVehicle*)vehicles[i]; - /* - Not used. - CVector vehSpeed = nearVeh->GetSpeed(); - CVector ourSpeed = GetSpeed(); - */ - CVector vehDistVec = nearVeh->GetPosition() - GetPosition(); - if (vehDistVec.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh - && nearVeh->CanPedOpenLocks(this)) { - - foundVeh = nearVeh; - closestVehDist = vehDistVec.Magnitude(); - } - } - m_pMyVehicle = foundVeh; - if (m_pMyVehicle) { - m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); - } else if (!GetIsOnScreen()) { - CVector ourPos = GetPosition(); - int closestNode = ThePaths.FindNodeClosestToCoors(ourPos, PATH_CAR, 20.0f); - if (closestNode >= 0) { - int16 colliding; - CWorld::FindObjectsKindaColliding( - ThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false); - if (!colliding) { - CZoneInfo zoneInfo; - int chosenCarClass; - CTheZones::GetZoneInfoForTimeOfDay(&ourPos, &zoneInfo); - int chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &ourPos, &chosenCarClass); - CAutomobile *newVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE); - if (newVeh) { - newVeh->GetMatrix().GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition(); - newVeh->GetMatrix().GetPosition().z += 4.0f; - newVeh->SetHeading(DEGTORAD(200.0f)); - newVeh->SetStatus(STATUS_ABANDONED); - newVeh->m_nDoorLock = CARLOCK_UNLOCKED; - CWorld::Add(newVeh); - m_pMyVehicle = newVeh; - if (m_pMyVehicle) { - m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); - } - } - } - } - } - } - break; - } - } else { - ClearLookFlag(); - bObjectiveCompleted = true; - } - } - case OBJECTIVE_KILL_CHAR_ON_FOOT: - { - bool killPlayerInNoPoliceZone = false; - if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) { - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - break; - } - if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) { - ClearLookFlag(); - bObjectiveCompleted = true; - SetMoveAnim(); - break; - } - if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice()) - killPlayerInNoPoliceZone = true; + currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + AddWeaponModel(currentWeapon->m_nModelId); + for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { + CWeapon &weapon = GetWeapon(i); + weapon.m_eWeaponType = WEAPONTYPE_UNARMED; + weapon.m_eWeaponState = WEAPONSTATE_READY; + weapon.m_nAmmoInClip = 0; + weapon.m_nAmmoTotal = 0; + weapon.m_nTimer = 0; + } +} - if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) { - if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee() && !GetWeapon()->IsTypeMelee()) - bNotAllowedToDuck = true; - } else { - if (!m_pedInObjective->bInVehicle) { - if (m_pedInObjective->GetWeapon()->IsTypeMelee() || GetWeapon()->IsTypeMelee()) { - bNotAllowedToDuck = false; - bCrouchWhenShooting = false; - } else if (DuckAndCover()) { - break; - } - } else { - bNotAllowedToDuck = false; - bCrouchWhenShooting = false; - } - } - if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) { - SetMoveState(PEDMOVE_STILL); - break; - } - if (m_pedInObjective->IsPlayer()) { - CPlayerPed *player = FindPlayerPed(); - if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops - || player->m_pWanted->m_bIgnoredByEveryone - || m_pedInObjective->bIsInWater - || m_pedInObjective->m_nPedState == PED_ARRESTED) { +void +CPed::PreRender(void) +{ + CShadows::StoreShadowForPed(this, + CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue], + CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]); - if (m_nPedState != PED_ARREST_PLAYER) - SetIdle(); +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + UpdateRpHAnim(); - break; - } - } - CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - float wepRange = wepInfo->m_fRange; - float wepRangeAdjusted; - if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { - wepRangeAdjusted = wepRange / 3.0f; - } else { - if (m_nPedState == PED_FIGHT) { - if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK)) - wepRange = 2.0f; - } else { - wepRange = 1.3f; - } - wepRangeAdjusted = wepRange; - } - if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) { - wepRangeAdjusted = 2.5f; - } - if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP - && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) { - SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); - break; - } - if (m_pedInObjective->m_fHealth <= 0.0f) { - bObjectiveCompleted = true; - bScriptObjectiveCompleted = true; - SetMoveAnim(); - break; - } - float distWithTargetSc = distWithTarget.Magnitude(); - if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { - CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle; - if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED - || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) { - SetIdle(); - return; - } - SetLookFlag(vehOfTarget, false); - if (m_nPedState != PED_CARJACK) { - if (m_pedInObjective->m_nPedState != PED_ARRESTED) { - if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE - && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) { - - // I hope so - CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); - CVector maxShotPos = vehOfTarget->GetPosition() - ourHead; - maxShotPos.Normalise(); - maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead; - - CWorld::bIncludeDeadPeds = true; - CColPoint foundCol; - CEntity *foundEnt; - CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, - true, true, true, true, false, true, false); - CWorld::bIncludeDeadPeds = false; - if (foundEnt == vehOfTarget) { - SetAttack(vehOfTarget); - m_pPointGunAt = vehOfTarget; - if (vehOfTarget) - vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt); - - SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); - if (distWithTargetSc <= m_distanceToCountSeekDone) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500)); - SetMoveState(PEDMOVE_STILL); - } else { - SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); - } - } - } - else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) { - if (vehOfTarget) { - if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) { - GoToNearestDoor(vehOfTarget); - } else { - m_vehEnterType = 0; - if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) { - m_vehEnterType = CAR_DOOR_LF; - } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) { - m_vehEnterType = CAR_DOOR_RF; - } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) { - m_vehEnterType = CAR_DOOR_LR; - } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) { - m_vehEnterType = CAR_DOOR_RR; - } - // Unused - // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType); - SetSeekCar(vehOfTarget, m_vehEnterType); - SetMoveState(PEDMOVE_RUN); - } - } - } - } - } - SetMoveAnim(); - break; - } - if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) { - SetLookFlag(m_pedInObjective, false); - TurnBody(); - } - if (m_nPedType == PEDTYPE_COP && distWithTargetSc < 1.5f && m_pedInObjective->IsPlayer()) { - if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() - || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) { + if(bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD){ + // scale head to 0 if shot off + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD)); + RwMatrix *head = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwV3d zero = { 0.0f, 0.0f, 0.0f }; + RwMatrixScale(head, &zero, rwCOMBINEPRECONCAT); + } + } +#endif - ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective); - return; - } - } - if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) { - if (distWithTargetSc > wepRange - || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() - || m_pedInObjective->m_nPedState == PED_ARRESTED - || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f - || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) { + if (bBodyPartJustCameOff && bIsPedDieAnimPlaying && m_bodyPartBleeding != -1 && (CTimer::GetFrameCounter() & 7) > 3) { + CVector bloodDir(0.0f, 0.0f, 0.0f); + CVector bloodPos(0.0f, 0.0f, 0.0f); - if (m_pedInObjective->EnteringCar()) - wepRangeAdjusted = 2.0f; + TransformToNode(bloodPos, m_bodyPartBleeding); - if (bUsePedNodeSeek) { - CVector bestCoords(0.0f, 0.0f, 0.0f); - m_vecSeekPos = m_pedInObjective->GetPosition(); + switch (m_bodyPartBleeding) { + case PED_HEAD: + bloodDir = 0.1f * GetUp(); + break; + case PED_UPPERARML: + bloodDir = 0.04f * GetUp() - 0.04f * GetRight(); + break; + case PED_UPPERARMR: + bloodDir = 0.04f * GetUp() - 0.04f * GetRight(); + break; + case PED_UPPERLEGL: + bloodDir = 0.04f * GetUp() + 0.05f * GetForward(); + break; + case PED_UPPERLEGR: + bloodDir = 0.04f * GetUp() + 0.05f * GetForward(); + break; + default: + bloodDir = CVector(0.0f, 0.0f, 0.0f); + break; + } - if (!m_pNextPathNode) - FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); + for(int i = 0; i < 4; i++) + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0); + } + if (CWeather::Rain > 0.3f && TheCamera.SoundDistUp > 15.0f) { + if ((TheCamera.GetPosition() - GetPosition()).Magnitude() < 25.0f) { + bool doSplashUp = true; + CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel(); + CVector speed = FindPlayerSpeed(); - if (m_pNextPathNode) - m_vecSeekPos = m_pNextPathNode->GetPosition(); + if (Abs(speed.x) <= 0.05f && Abs(speed.y) <= 0.05f) { + if (!OnGround() && m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { + if (!IsPedHeadAbovePos(0.3f) || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED)) { + doSplashUp = false; + } + } else + doSplashUp = false; + } else + doSplashUp = false; - SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); - } else { - SetSeek(m_pedInObjective, wepRangeAdjusted); - } - bCrouchWhenShooting = false; - if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) { - if (wepRange <= 5.0f) { - if (m_pedInObjective->IsPlayer() - && FindPlayerPed()->m_bSpeedTimerFlag - && (IsGangMember() || m_nPedType == PEDTYPE_COP) - && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { - GiveWeapon(WEAPONTYPE_COLT45, 1000); - SetCurrentWeapon(WEAPONTYPE_COLT45); - } - } else { - bStopAndShoot = true; - } - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); + if (doSplashUp && ourCol->numSpheres > 0) { + for(int i = 0; i < ourCol->numSpheres; i++) { + CColSphere *sphere = &ourCol->spheres[i]; + CVector splashPos; + switch (sphere->piece) { + case PEDPIECE_LEFTARM: + case PEDPIECE_RIGHTARM: + case PEDPIECE_HEAD: + splashPos = GetMatrix() * ourCol->spheres[i].center; + splashPos.z += 0.7f * sphere->radius; + splashPos.x += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f); + splashPos.y += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f); + CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, splashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 1, 0); + break; + default: break; - } - bStopAndShoot = false; - SetMoveAnim(); - break; } } - if (m_attackTimer < CTimer::GetTimeInMilliseconds() - && distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { - if (bIsDucking) { - CAnimBlendAssociation *duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (duckAnim) { - duckAnim->blendDelta = -2.0f; - break; - } - bIsDucking = false; - } else if (wepRange <= 5.0f) { - SetMoveState(PEDMOVE_STILL); - SetAttack(m_pedInObjective); - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, - GetPosition().x, GetPosition().y); - SetShootTimer(CGeneral::GetRandomNumberInRange(0.0f, 500.0f)); - SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f)); - bObstacleShowedUpDuringKillObjective = false; + } + } + } +} - } else { - CVector target; - CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); - if (m_pedInObjective->IsPed()) - m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID); - else - target = m_pedInObjective->GetPosition(); - - target -= ourHead; - target.Normalise(); - target = target * wepInfo->m_fRange + ourHead; - - CWorld::bIncludeDeadPeds = true; - CEntity *foundEnt = nil; - CColPoint foundCol; - - CWorld::ProcessLineOfSight( - ourHead, target, foundCol, foundEnt, - true, true, true, false, true, false); - CWorld::bIncludeDeadPeds = 0; - if (foundEnt == m_pedInObjective) { - SetAttack(m_pedInObjective); - m_pPointGunAt = m_pedInObjective; - if (m_pedInObjective) - m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt); - - SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f)); - - int time; - if (distWithTargetSc <= wepRangeAdjusted) - time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f); - else - time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f); +void +CPed::Render(void) +{ + if (bInVehicle && m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR) { + if (!bRenderPedInCar) + return; - SetAttackTimer(time); - bObstacleShowedUpDuringKillObjective = false; + float camDistSq = (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr(); + if (camDistSq > SQR(25.0f * TheCamera.LODDistMultiplier)) + return; + } - } else if (foundEnt) { - if (foundEnt->IsPed()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); - bObstacleShowedUpDuringKillObjective = false; - } else { - if (foundEnt->IsObject()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f)); - bObstacleShowedUpDuringKillObjective = true; - } else if (foundEnt->IsVehicle()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f)); - bObstacleShowedUpDuringKillObjective = true; - } else { - SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f)); - bObstacleShowedUpDuringKillObjective = true; - } - } + CEntity::Render(); - m_fleeFrom = foundEnt; - m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom); - SetPointGunAt(m_pedInObjective); - } - } - } else { - if (!m_pedInObjective->m_pCurrentPhysSurface) - bStopAndShoot = false; - - if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { - - // This is weird... - if (bNotAllowedToDuck && bKindaStayInSamePlace) { - if (!bIsDucking) { - CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (!duckAnim || duckAnim->blendDelta < 0.0f) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f); - bIsDucking = true; - } - break; - } else { - CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (!duckAnim || duckAnim->blendDelta < 0.0f) { - bIsDucking = false; - } else { - break; - } - } - } - if (bObstacleShowedUpDuringKillObjective) { - if (m_nPedType == PEDTYPE_COP) { - if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45 - || m_fleeFrom && m_fleeFrom->IsObject()) { - wepRangeAdjusted = 6.0f; - } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) { - wepRangeAdjusted = 4.0f; - } else { - wepRangeAdjusted = 2.0f; - } - } else { - wepRangeAdjusted = 2.0f; - } - } - if (distWithTargetSc <= wepRangeAdjusted) { - SetMoveState(PEDMOVE_STILL); - bIsPointingGunAt = true; - if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) { - m_attackTimer = CTimer::GetTimeInMilliseconds(); - SetIdle(); - } - } else { - if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS - && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) { - Say(SOUND_PED_ATTACK); - SetSeek(m_pedInObjective, wepRangeAdjusted); - bIsRunning = true; - } - } - } - } +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + renderLimb(PED_HEAD); + renderLimb(PED_HANDL); + renderLimb(PED_HANDR); + } + if(m_pWeaponModel && IsClumpSkinned(GetClump())){ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel); + *RwFrameGetMatrix(frame) = *mat; + RwFrameUpdateObjects(frame); + RpAtomicRender(m_pWeaponModel); + } +#endif +} - if (distWithTargetSc < 2.5f && wepRange > 5.0f - && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE) { +void +CPed::CheckAroundForPossibleCollisions(void) +{ + CVector ourCentre, objCentre; + CEntity *objects[8]; + int16 maxObject; - SetAttack(m_pedInObjective); - if (m_attackTimer < CTimer::GetTimeInMilliseconds()) { - int time = CGeneral::GetRandomNumberInRange(500.0f, 1000.0f); - SetAttackTimer(time); - SetShootTimer(time - 500); - } - SetMoveState(PEDMOVE_STILL); - } - if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y); - - SetMoveAnim(); - break; - } - case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: - { - if (InVehicle()) { - if (m_nPedState == PED_DRIVING) - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } else if (m_nPedState != PED_FLEE_ENTITY) { - int time; - if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) - time = 0; - else - time = 6000; + if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) + return; - SetFindPathAndFlee(m_pedInObjective, time); - } - break; - } - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - { - if (m_pedInObjective) { - float safeDistance = 2.0f; - if (m_pedInObjective->bInVehicle) - safeDistance = 3.0f; - - float distWithTargetSc = distWithTarget.Magnitude(); - if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) { - if (distWithTargetSc <= safeDistance) { - bScriptObjectiveCompleted = true; - if (m_nPedState != PED_ATTACK) { - SetIdle(); - m_pLookTarget = m_pedInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - TurnBody(); - } - if (distWithTargetSc > 2.0f) - SetMoveState(m_pedInObjective->m_nMoveState); - else - SetMoveState(PEDMOVE_STILL); - } else { - SetSeek(m_pedInObjective, safeDistance); - if (distWithTargetSc >= 5.0f) { - if (m_leader && m_leader->m_nMoveState == PEDMOVE_SPRINT) - SetMoveState(PEDMOVE_SPRINT); - else - SetMoveState(PEDMOVE_RUN); - } else { - if (m_leader && m_leader->m_nMoveState != PEDMOVE_STILL - && m_leader->m_nMoveState != PEDMOVE_NONE) { - if (m_leader->IsPlayer()) { - if (distWithTargetSc >= 3.0f && FindPlayerPed()->m_fMoveSpeed >= 1.3f) - SetMoveState(PEDMOVE_RUN); - else - SetMoveState(PEDMOVE_WALK); - } else { - SetMoveState(m_leader->m_nMoveState); - } - } else if (distWithTargetSc <= 3.0f) { - SetMoveState(PEDMOVE_WALK); - } else { - SetMoveState(PEDMOVE_RUN); - } - } - } - } - } else { - SetObjective(OBJECTIVE_NONE); - } - break; - } - case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: - { - if (m_pedInObjective) { - CVector posToGo = GetFormationPosition(); - distWithTarget = posToGo - carOrOurPos; - SetSeek(posToGo, 1.0f); - if (distWithTarget.Magnitude() <= 3.0f) { - SetSeek(posToGo, 1.0f); - if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) - SetMoveState(m_pedInObjective->m_nMoveState); - } else { - SetSeek(posToGo, 1.0f); - SetMoveState(PEDMOVE_RUN); - } - } else { - SetObjective(OBJECTIVE_NONE); - } + GetBoundCentre(ourCentre); + + CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false); + for (int i = 0; i < maxObject; i++) { + CEntity *object = objects[i]; + if (bRunningToPhone) { + if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition())) break; - } - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - { - if (m_carInObjective) { - if (!bInVehicle && m_carInObjective->m_nNumPassengers >= m_carInObjective->m_nNumMaxPassengers) { - RestorePreviousObjective(); - RestorePreviousState(); - if (IsPedInControl()) - m_pMyVehicle = nil; + } + object->GetBoundCentre(objCentre); + float radius = object->GetBoundRadius(); + if (radius > 4.5f || radius < 1.0f) + radius = 1.0f; - break; - } + // Developers gave up calculating Z diff. later according to asm. + float diff = CVector(ourCentre - objCentre).MagnitudeSqr2D(); - if (m_prevObjective == OBJECTIVE_HAIL_TAXI && !((CAutomobile*)m_carInObjective)->bTaxiLight) { - RestorePreviousObjective(); - ClearObjective(); - SetWanderPath(CGeneral::GetRandomNumber() & 7); - bIsRunning = false; - break; - } - if (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) { - if (!EnteringCar()) { - bool foundSeat = false; - if (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) { - if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) { - if (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) { - foundSeat = false; - } else { - m_vehEnterType = CAR_DOOR_RR; - foundSeat = true; - } - } else { - m_vehEnterType = CAR_DOOR_LR; - foundSeat = true; - } - } else { - m_vehEnterType = CAR_DOOR_RF; - foundSeat = true; - } - for (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) { - if (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) { - m_vehEnterType = CAR_DOOR_RF; - foundSeat = true; - } - } - if (foundSeat) { - SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType)); - SetEnterCar(m_carInObjective, m_vehEnterType); - } - } - m_objectiveTimer = 0; - } - } - // fall through - } - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - { - if (!m_carInObjective || bInVehicle) { -#ifdef VC_PED_PORTS - if (bInVehicle && m_pMyVehicle != m_carInObjective) { - SetExitCar(m_pMyVehicle, 0); - } else -#endif - { - bObjectiveCompleted = true; - bScriptObjectiveCompleted = true; - RestorePreviousState(); - } - } else { - if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) { - SetMoveState(PEDMOVE_STILL); - break; - } - if (IsPedInControl()) { - if (m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { - if (distWithTarget.Magnitude() < 20.0f) { - RestorePreviousObjective(); - RestorePreviousState(); - return; - } - if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { - if (m_carInObjective->pDriver -#ifdef VC_PED_PORTS - && !IsPlayer() -#endif - ) { - if (m_carInObjective->pDriver->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS && m_carInObjective->pDriver != m_pedInObjective) { - SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective); - m_carInObjective->bIsBeingCarJacked = false; - } - } - } - } else if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) { - if (m_carInObjective->pDriver + if (sq(radius + 1.0f) > diff) + m_fRotationDest += DEGTORAD(22.5f); + } +} + +void +CPed::SetIdle(void) +{ + if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) { #ifdef VC_PED_PORTS - && (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR) + if (m_nPedState == PED_AIM_GUN) + ClearPointGunAt(); + + m_nLastPedState = PED_NONE; #endif - ) { - if (m_carInObjective->pDriver->m_nPedType == m_nPedType) { - SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective); - m_carInObjective->bIsBeingCarJacked = false; - } - } - } - if (m_carInObjective->IsUpsideDown() && m_carInObjective->m_vehType != VEHICLE_TYPE_BIKE) { - RestorePreviousObjective(); - RestorePreviousState(); - return; - } - if (!m_carInObjective->IsBoat() || m_nPedState == PED_SEEK_IN_BOAT) { - if (m_nPedState != PED_SEEK_CAR) - SetSeekCar(m_carInObjective, 0); - } else { - SetSeekBoatPosition(m_carInObjective); - } - if (m_nMoveState == PEDMOVE_STILL && !bVehEnterDoorIsBlocked) - SetMoveState(PEDMOVE_RUN); + m_nPedState = PED_IDLE; + SetMoveState(PEDMOVE_STILL); + } + if (m_nWaitState == WAITSTATE_FALSE) { + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000); + } +} + +void +CPed::Idle(void) +{ + CVehicle *veh = m_pMyVehicle; + if (veh && veh->m_nGettingOutFlags && m_vehEnterType) { - if (m_carInObjective && m_carInObjective->m_fHealth > 0.0f) { - distWithTarget = m_carInObjective->GetPosition() - GetPosition(); - if (!bInVehicle) { - if (nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST < distWithTarget.Magnitude()) { - if (!m_carInObjective->pDriver && !m_carInObjective->GetIsOnScreen() && !GetIsOnScreen()) - WarpPedToNearEntityOffScreen(m_carInObjective); + if (veh->m_nGettingOutFlags & GetCarDoorFlag(m_vehEnterType)) { - if (CharCreatedBy != MISSION_CHAR || m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS -#ifdef VC_PED_PORTS - || IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled() -#endif - ) { - RestorePreviousObjective(); - RestorePreviousState(); - if (IsPedInControl()) - m_pMyVehicle = nil; - } else { - SetIdle(); - SetMoveState(PEDMOVE_STILL); - } - } - } - } else if (!bInVehicle) { - RestorePreviousObjective(); - RestorePreviousState(); - if (IsPedInControl()) - m_pMyVehicle = nil; - } - } + if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { + + CVector doorPos = GetPositionToOpenCarDoor(veh, m_vehEnterType); + CVector doorDist = GetPosition() - doorPos; + + if (doorDist.MagnitudeSqr() < sq(0.5f)) { + SetMoveState(PEDMOVE_WALK); + return; } - break; } - case OBJECTIVE_DESTROY_CAR: - { - if (!m_carInObjective) { - ClearLookFlag(); - bObjectiveCompleted = true; - break; - } - float distWithTargetSc = distWithTarget.Magnitude(); - CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - float wepRange = wepInfo->m_fRange; - m_pLookTarget = m_carInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + } + } - m_pSeekTarget = m_carInObjective; - m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); + CAnimBlendAssociation *armedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED); + CAnimBlendAssociation *unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); + int waitTime; - TurnBody(); - if (m_carInObjective->m_fHealth <= 0.0f) { - ClearLookFlag(); - bScriptObjectiveCompleted = true; - break; - } + if (m_nMoveState == PEDMOVE_STILL) { - if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE - && distWithTargetSc < wepRange) { - - // I hope so - CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); - CVector maxShotPos = m_carInObjective->GetPosition() - ourHead; - maxShotPos.Normalise(); - maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead; - - CWorld::bIncludeDeadPeds = true; - CColPoint foundCol; - CEntity *foundEnt; - CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, - true, true, true, true, false, true, false); - CWorld::bIncludeDeadPeds = false; - if (foundEnt == m_carInObjective) { - SetAttack(m_carInObjective); - m_pPointGunAt = m_carInObjective; - if (m_pPointGunAt) - m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt); - - SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); - if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); - } else { - SetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300)); - SetMoveState(PEDMOVE_STILL); - } - } - } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) { + eWeaponType curWeapon = GetWeapon()->m_eWeaponType; + if (!armedIdleAssoc || + CTimer::GetTimeInMilliseconds() <= m_nWaitTimer && curWeapon != WEAPONTYPE_UNARMED && curWeapon != WEAPONTYPE_MOLOTOV && curWeapon != WEAPONTYPE_GRENADE) { - float safeDistance; - if (wepRange <= 5.0f) - safeDistance = 3.0f; - else - safeDistance = wepRange * 0.25f; + if ((!GetWeapon()->IsType2Handed() || curWeapon == WEAPONTYPE_SHOTGUN) && curWeapon != WEAPONTYPE_BASEBALLBAT + || !unarmedIdleAssoc || unarmedIdleAssoc->blendAmount <= 0.95f || m_nWaitState != WAITSTATE_FALSE || CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { - SetSeek(m_carInObjective, safeDistance); - SetMoveState(PEDMOVE_RUN); - } - SetLookFlag(m_carInObjective, false); - TurnBody(); - break; - } - case OBJECTIVE_GOTO_AREA_ANY_MEANS: - { - distWithTarget = m_nextRoutePointPos - GetPosition(); - distWithTarget.z = 0.0f; - if (InVehicle()) { - CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos); - CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle); - if (distWithTarget.MagnitudeSqr() < sq(20.0f)) { - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS); - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } - break; - } - if (distWithTarget.Magnitude() > 30.0f) { - if (m_pMyVehicle) { - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - } else { - float closestVehDist = SQR(60.0f); - int16 lastVehicle; - CEntity* vehicles[8]; - CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - CVehicle* foundVeh = nil; - for (int i = 0; i < lastVehicle; i++) { - CVehicle* nearVeh = (CVehicle*)vehicles[i]; - /* - Not used. - CVector vehSpeed = nearVeh->GetSpeed(); - CVector ourSpeed = GetSpeed(); - */ - CVector vehDistVec = nearVeh->GetPosition() - GetPosition(); - if (vehDistVec.MagnitudeSqr() < closestVehDist - && m_pedInObjective->m_pMyVehicle != nearVeh) - { - foundVeh = nearVeh; - closestVehDist = vehDistVec.MagnitudeSqr(); - } - } - m_pMyVehicle = foundVeh; - if (m_pMyVehicle) { - m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); - } - } - break; - } - // fall through + m_moved = CVector2D(0.0f, 0.0f); + return; } - case OBJECTIVE_GOTO_AREA_ON_FOOT: - case OBJECTIVE_RUN_TO_AREA: - { - if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) - && InVehicle()) { - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } else { - distWithTarget = m_nextRoutePointPos - GetPosition(); - distWithTarget.z = 0.0f; - if (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) { - bObjectiveCompleted = true; - bScriptObjectiveCompleted = true; - SetMoveState(PEDMOVE_STILL); - } else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) { - if (bUsePedNodeSeek) { - CVector bestCoords(0.0f, 0.0f, 0.0f); - m_vecSeekPos = m_nextRoutePointPos; + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_ARMED, 3.0f); + waitTime = CGeneral::GetRandomNumberInRange(4000, 7500); + } else { + armedIdleAssoc->blendDelta = -2.0f; + armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT; + waitTime = CGeneral::GetRandomNumberInRange(3000, 8500); + } + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + waitTime; + } else { + if (armedIdleAssoc) { + armedIdleAssoc->blendDelta = -8.0f; + armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT; + m_nWaitTimer = 0; + } + if (!IsPlayer()) + SetMoveState(PEDMOVE_STILL); + } + m_moved = CVector2D(0.0f, 0.0f); +} - if (!m_pNextPathNode) - FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); +void +CPed::ClearPause(void) +{ + RestorePreviousState(); +} - if (m_pNextPathNode) - m_vecSeekPos = m_pNextPathNode->GetPosition(); - } - SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); - } - } +void +CPed::Pause(void) +{ + m_moved = CVector2D(0.0f, 0.0f); + if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) + ClearPause(); +} - break; - } - case OBJECTIVE_GUARD_ATTACK: - { - if (m_pedInObjective) { - SetLookFlag(m_pedInObjective, true); - m_pLookTarget = m_pedInObjective; - m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); - m_lookTimer = m_attackTimer; - TurnBody(); - float distWithTargetSc = distWithTarget.Magnitude(); - if (distWithTargetSc >= 20.0f) { - RestorePreviousObjective(); - } else if (m_attackTimer < CTimer::GetTimeInMilliseconds()) { - if (m_nPedState != PED_SEEK_ENTITY && distWithTargetSc >= 2.0f) { - SetSeek(m_pedInObjective, 1.0f); - } else { - SetAttack(m_pedInObjective); - SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1500.0f)); - } - SetAttackTimer(1000); - } - } else { - RestorePreviousObjective(); - } - break; - } - case OBJECTIVE_FOLLOW_ROUTE: - if (HaveReachedNextPointOnRoute(1.0f)) { - int nextPoint = GetNextPointOnRoute(); - m_nextRoutePointPos = CRouteNode::GetPointPosition(nextPoint); - } else { - SetSeek(m_nextRoutePointPos, 0.8f); - } - break; - case OBJECTIVE_SOLICIT_VEHICLE: - if (m_carInObjective) { - if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) { - if (!bInVehicle) { - SetObjective(OBJECTIVE_NONE); - SetWanderPath(CGeneral::GetRandomNumber() & 7); - m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; - if (IsPedInControl()) - m_pMyVehicle = nil; - } - } else { - if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT) - SetSeekCar(m_carInObjective, 0); - } - } else { - RestorePreviousObjective(); - RestorePreviousState(); - if (IsPedInControl()) - m_pMyVehicle = nil; - } - break; - case OBJECTIVE_HAIL_TAXI: - if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - Say(SOUND_PED_TAXI_WAIT); - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TAXI, 4.0f); - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000; - } - break; - case OBJECTIVE_CATCH_TRAIN: - { - if (m_carInObjective) { - SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective); - } else { - CVehicle* trainToEnter = nil; - float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST; - CVector pos = GetPosition(); - int16 lastVehicle; - CEntity* vehicles[8]; - - CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - for (int i = 0; i < lastVehicle; i++) { - CVehicle* nearVeh = (CVehicle*)vehicles[i]; - if (nearVeh->IsTrain()) { - CVector vehDistVec = GetPosition() - nearVeh->GetPosition(); - float vehDist = vehDistVec.Magnitude(); - if (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh) - { - trainToEnter = nearVeh; - closestCarDist = vehDist; - } - } - } - if (trainToEnter) { - m_carInObjective = trainToEnter; - m_carInObjective->RegisterReference((CEntity **) &m_carInObjective); - } - } - break; - } - case OBJECTIVE_BUY_ICE_CREAM: - if (m_carInObjective) { - if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM) - SetSeekCar(m_carInObjective, 0); - } else { - RestorePreviousObjective(); - RestorePreviousState(); - if (IsPedInControl()) - m_pMyVehicle = nil; - } - break; - case OBJECTIVE_STEAL_ANY_CAR: - { - if (bInVehicle) { - bScriptObjectiveCompleted = true; - RestorePreviousObjective(); - } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) { - CVehicle *carToSteal = nil; - float closestCarDist = ENTER_CAR_MAX_DIST; - CVector pos = GetPosition(); - int16 lastVehicle; - CEntity *vehicles[8]; - - // NB: This should've been ENTER_CAR_MAX_DIST actually, and is fixed in VC. - CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - for(int i = 0; i < lastVehicle; i++) { - CVehicle *nearVeh = (CVehicle*)vehicles[i]; - if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) { - if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) { - if (nearVeh->CanPedOpenLocks(this)) { - CVector vehDistVec = GetPosition() - nearVeh->GetPosition(); - float vehDist = vehDistVec.Magnitude(); - if (vehDist < closestCarDist) { - carToSteal = nearVeh; - closestCarDist = vehDist; - } - } - } - } - } - if (carToSteal) { - SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal); - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; - } else { - RestorePreviousObjective(); - RestorePreviousState(); - } - } - break; - } - case OBJECTIVE_MUG_CHAR: - { - if (m_pedInObjective) { - if (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) { - ClearObjective(); - return; - } - if (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) { - ClearObjective(); - return; - } - if (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) { - SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective); - SetMoveState(PEDMOVE_SPRINT); - return; - } - if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this - || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) { - ClearObjective(); - SetFindPathAndFlee(m_pedInObjective, 15000, true); - return; - } - float distWithTargetScSqr = distWithTarget.MagnitudeSqr(); - if (distWithTargetScSqr <= sq(10.0f)) { - if (distWithTargetScSqr <= sq(1.4f)) { - CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD); - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, - GetPosition().x, GetPosition().y); - - if (reloadAssoc || !m_pedInObjective->IsPedShootable()) { - if (reloadAssoc && - (!reloadAssoc->IsRunning() || reloadAssoc->currentTime / reloadAssoc->hierarchy->totalLength > 0.8f)) { - CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); - punchAssoc->flags |= ASSOC_DELETEFADEDOUT; - punchAssoc->flags |= ASSOC_FADEOUTWHENDONE; - CVector2D offset(distWithTarget.x, distWithTarget.y); - int dir = m_pedInObjective->GetLocalDirection(offset); - m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5); - m_pedInObjective->ReactToAttack(this); - m_pedInObjective->Say(SOUND_PED_ROBBED); - Say(SOUND_PED_MUGGING); - bRichFromMugging = true; - - // VC FIX: ClearObjective() clears m_pedInObjective in VC (also same with VC_PED_PORTS), so get it before call - CPed *victim = m_pedInObjective; - ClearObjective(); - if (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT - || victim->m_pedInObjective != this) { - SetFindPathAndFlee(victim, 15000, true); - m_nLastPedState = PED_WANDER_PATH; - } else { - SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim); - SetMoveState(PEDMOVE_SPRINT); - m_nLastPedState = PED_WANDER_PATH; - } - } - } else { - eWeaponType weaponType = GetWeapon()->m_eWeaponType; - if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT) - SetCurrentWeapon(WEAPONTYPE_UNARMED); +void +CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl) +{ + if (!IsPedInControl() && (!evenIfNotInControl || DyingOrDead())) + return; + + ClearLookFlag(); + ClearAimFlag(); + SetStoredState(); + m_nPedState = PED_FALL; + CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId); + + if (fallAssoc) { + fallAssoc->SetCurrentTime(0.0f); + fallAssoc->blendAmount = 0.0f; + fallAssoc->blendDelta = 8.0f; + fallAssoc->SetRun(); + } else { + fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f); + } + + if (extraTime == -1) { + m_getUpTimer = UINT32_MAX; + } else if (fallAssoc) { + if (IsPlayer()) { + m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength + + CTimer::GetTimeInMilliseconds() + + 500.0f; + } else { + m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength + + CTimer::GetTimeInMilliseconds() + + extraTime + + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000); + } + } else { + m_getUpTimer = extraTime + + CTimer::GetTimeInMilliseconds() + + 1000 + + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000); + } + bFallenDown = true; +} + +void +CPed::ClearFall(void) +{ + SetGetUp(); +} + +void +CPed::Fall(void) +{ + if (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer +#ifdef VC_PED_PORTS + && bIsStanding +#endif + ) + ClearFall(); + + // VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III. +} + +bool +CPed::CheckIfInTheAir(void) +{ + if (bInVehicle) + return false; + + CVector pos = GetPosition(); + CColPoint foundColPoint; + CEntity *foundEntity; + + float startZ = pos.z - 1.54f; + bool foundGround = CWorld::ProcessVerticalLine(pos, startZ, foundColPoint, foundEntity, true, true, false, true, false, false, nil); + if (!foundGround && m_nPedState != PED_JUMP) + { + pos.z -= FEET_OFFSET; + if (CWorld::TestSphereAgainstWorld(pos, 0.15f, this, true, false, false, false, false, false)) + foundGround = true; + } + return !foundGround; +} + +void +CPed::SetInTheAir(void) +{ + if (bIsInTheAir) + return; - CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_AK_RELOAD, 8.0f); - newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT; - newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE; - } - } else { - SetSeek(m_pedInObjective, 1.0f); - CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK); + bIsInTheAir = true; + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_GLIDE, 4.0f); - if (walkAssoc) - walkAssoc->speed = 1.3f; - } - } else { - ClearObjective(); - SetWanderPath(CGeneral::GetRandomNumber() & 7); - } - } else { + if (m_nPedState == PED_ATTACK) { + ClearAttack(); + ClearPointGunAt(); + } else if (m_nPedState == PED_FIGHT) { + EndFight(ENDFIGHT_FAST); + } + +} + +void +CPed::InTheAir(void) +{ + CColPoint foundCol; + CEntity *foundEnt; + + CVector ourPos = GetPosition(); + CVector bitBelow = GetPosition(); + bitBelow.z -= 4.04f; + + if (m_vecMoveSpeed.z < 0.0f && !bIsPedDieAnimPlaying) { + if (!DyingOrDead()) { + if (CWorld::ProcessLineOfSight(ourPos, bitBelow, foundCol, foundEnt, true, true, false, true, false, false, false)) { + if (GetPosition().z - foundCol.point.z < 1.3f #ifdef VC_PED_PORTS - m_objective = OBJECTIVE_NONE; + || bIsStanding #endif - ClearObjective(); + ) + SetLanding(); + } else { + if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)) { + if (m_vecMoveSpeed.z < -0.1f) + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_FALL, 4.0f); } - break; } - case OBJECTIVE_FLEE_CAR: - if (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) { - RestorePreviousObjective(); - SetFlee(m_pMyVehicle, 6000); - break; - } - // fall through - case OBJECTIVE_LEAVE_CAR: - if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - if (InVehicle() -#ifdef VC_PED_PORTS - && (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() - || bBusJacked) -#endif - ) { - if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN - && (m_nPedType != PEDTYPE_COP -#ifdef VC_PED_PORTS - || m_pMyVehicle->IsBoat() -#endif - || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) { - if (m_pMyVehicle->IsTrain()) - SetExitTrain(m_pMyVehicle); -#ifdef VC_PED_PORTS - else if (m_pMyVehicle->IsBoat()) - SetExitBoat(m_pMyVehicle); -#endif - else - SetExitCar(m_pMyVehicle, 0); - } - } else { - RestorePreviousObjective(); - } - } - break; -#ifdef VC_PED_PORTS - case OBJECTIVE_LEAVE_CAR_AND_DIE: - { - if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - if (InVehicle()) { - if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN) { - if (m_pMyVehicle->IsBoat()) - SetExitBoat(m_pMyVehicle); - else if (m_pMyVehicle->bIsBus) - SetExitCar(m_pMyVehicle, 0); - else { - eCarNodes doorNode = CAR_DOOR_LF; - if (m_pMyVehicle->pDriver != this) { - if (m_pMyVehicle->pPassengers[0] == this) { - doorNode = CAR_DOOR_RF; - } else if (m_pMyVehicle->pPassengers[1] == this) { - doorNode = CAR_DOOR_LR; - } else if (m_pMyVehicle->pPassengers[2] == this) { - doorNode = CAR_DOOR_RR; - } - } - SetBeingDraggedFromCar(m_pMyVehicle, doorNode, false); - } - } - } - } - break; + } + } +} + +void +CPed::SetLanding(void) +{ + if (DyingOrDead()) + return; + + CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL); + CAnimBlendAssociation *landAssoc; + + RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); + if (fallAssoc) { + landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_COLLAPSE); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f); + + if (IsPlayer()) + Say(SOUND_PED_LAND); + + } else { + landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f); + } + + landAssoc->SetFinishCallback(PedLandCB, this); + bIsInTheAir = false; + bIsLanding = true; +} + +void +CPed::SetGetUp(void) +{ + if (m_nPedState == PED_GETUP && bGetUpAnimStarted) + return; + + if (!CanSetPedState()) + return; + + if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) { + if (bUpdateAnimHeading) { + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + m_fRotationCur -= HALFPI; + bUpdateAnimHeading = false; + } + if (m_nPedState != PED_GETUP) { + SetStoredState(); + m_nPedState = PED_GETUP; + } + + CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity; + CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition()); + if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE || + collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE + && ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 || + CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(), + aTempPedColPts, nil, nil) > 0)) { + + bGetUpAnimStarted = false; + if (IsPlayer()) + InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); + else { + if (!CPad::GetPad(0)->ArePlayerControlsDisabled()) + return; + + InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, 0); } -#endif + return; } - if (bObjectiveCompleted - || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { - RestorePreviousObjective(); - if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer) - m_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1; - - if (CharCreatedBy != RANDOM_CHAR || bInVehicle) { - if (IsPedInControl()) - RestorePreviousState(); + bGetUpAnimStarted = true; + m_pCollidingEntity = nil; + bKnockedUpIntoAir = false; + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT); + if (animAssoc) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) { + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f); } else { - SetWanderPath(CGeneral::GetRandomNumber() & 7); + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f); } - ClearAimFlag(); - ClearLookFlag(); + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f); + else + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + + animAssoc->SetFinishCallback(PedGetupCB,this); + } else { + m_fHealth = 0.0f; + SetDie(NUM_ANIMS, 4.0f, 0.0f); + } +} + +void +CPed::Mug(void) +{ + if (m_pSeekTarget && m_pSeekTarget->IsPed()) { + + if (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) { + if ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f) + m_wepSkills = 50; + + Say(SOUND_PED_MUGGING); + ((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED); + } else { + SetWanderPath(CGeneral::GetRandomNumber() & 7); + SetFlee(m_pSeekTarget, 20000); } + + } else { + SetIdle(); + } +} + +void +CPed::SetLookTimer(int time) +{ + if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { + m_lookTimer = CTimer::GetTimeInMilliseconds() + time; } } +void +CPed::SetAttackTimer(uint32 time) +{ + if (CTimer::GetTimeInMilliseconds() > m_attackTimer) + m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time; +} + void CPed::SetShootTimer(uint32 time) { @@ -13710,3688 +5312,3156 @@ CPed::SetShootTimer(uint32 time) } void -CPed::SetSeekCar(CVehicle *car, uint32 doorNode) +CPed::ClearLook(void) +{ + RestorePreviousState(); + ClearLookFlag(); +} + +void +CPed::Look(void) +{ + // UNUSED: This is a perfectly empty function. +} + +bool +CPed::TurnBody(void) +{ + bool turnDone = true; + + if (m_pLookTarget) + m_fLookDirection = CGeneral::GetRadianAngleBetweenPoints( + m_pLookTarget->GetPosition().x, + m_pLookTarget->GetPosition().y, + GetPosition().x, + GetPosition().y); + + float limitedLookDir = CGeneral::LimitRadianAngle(m_fLookDirection); + float currentRot = m_fRotationCur; + + if (currentRot - PI > limitedLookDir) + limitedLookDir += 2 * PI; + else if (PI + currentRot < limitedLookDir) + limitedLookDir -= 2 * PI; + + float neededTurn = currentRot - limitedLookDir; + m_fRotationDest = limitedLookDir; + + if (Abs(neededTurn) > 0.05f) { + turnDone = false; + currentRot -= neededTurn * 0.2f; + } + + m_fRotationCur = currentRot; + m_fLookDirection = limitedLookDir; + return turnDone; +} + +void +CPed::SetSeek(CVector pos, float distanceToCountDone) +{ + if (!IsPedInControl() + || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y)) + return; + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 + || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47 + || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE + || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER + || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) { + ClearPointGunAt(); + } + + if (m_nPedState != PED_SEEK_POS) + SetStoredState(); + + m_nPedState = PED_SEEK_POS; + m_distanceToCountSeekDone = distanceToCountDone; + m_vecSeekPos = pos; +} + +void +CPed::SetSeek(CEntity *seeking, float distanceToCountDone) { - if (m_nPedState == PED_SEEK_CAR) + if (!IsPedInControl()) return; -#ifdef VC_PED_PORTS - if (!CanSetPedState() || m_nPedState == PED_DRIVING) + if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking) return; -#endif - SetStoredState(); - m_pSeekTarget = car; - m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); - m_carInObjective = car; - m_carInObjective->RegisterReference((CEntity**) &m_carInObjective); - m_pMyVehicle = car; - m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle); - // m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); - m_vehEnterType = doorNode; - m_distanceToCountSeekDone = 0.5f; - m_nPedState = PED_SEEK_CAR; + if (!seeking) + return; + + if (m_nPedState != PED_SEEK_ENTITY) + SetStoredState(); + m_nPedState = PED_SEEK_ENTITY; + m_distanceToCountSeekDone = distanceToCountDone; + m_pSeekTarget = seeking; + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + SetMoveState(PEDMOVE_STILL); } void -CPed::SetSeekBoatPosition(CVehicle *boat) +CPed::ClearSeek(void) { - if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver -#if defined VC_PED_PORTS || defined FIX_BUGS - || !IsPedInControl() -#endif - ) - return; - - SetStoredState(); - m_carInObjective = boat; - m_carInObjective->RegisterReference((CEntity **) &m_carInObjective); - m_pMyVehicle = boat; - m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); - m_distanceToCountSeekDone = 0.5f; - m_nPedState = PED_SEEK_IN_BOAT; + SetIdle(); + bRunningToPhone = false; } -void -CPed::SetExitTrain(CVehicle* train) +bool +CPed::Seek(void) { - if (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen()) - return; + float distanceToCountItDone = m_distanceToCountSeekDone; + eMoveState nextMove = PEDMOVE_NONE; - /* - // Not used - CVector exitPos; - GetNearestTrainPedPosition(train, exitPos); - */ - m_nPedState = PED_EXIT_TRAIN; - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f); - m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this); - bUsesCollision = false; - LineUpPedWithTrain(); -} + if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { -#ifdef NEW_WALK_AROUND_ALGORITHM -CVector -LocalPosForWalkAround(CVector2D colMin, CVector2D colMax, int walkAround, uint32 enterDoorNode, bool itsVan) { - switch (walkAround) { - case 0: - if (enterDoorNode == CAR_DOOR_LF) - return CVector(colMin.x, colMax.y - 1.0f, 0.0f); - case 1: - return CVector(colMin.x, colMax.y, 0.0f); - case 2: - case 3: - if (walkAround == 3 && enterDoorNode == CAR_DOOR_RF) - return CVector(colMax.x, colMax.y - 1.0f, 0.0f); + if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT && + m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) { + + if ((!m_pedInObjective || !m_pedInObjective->bInVehicle) + && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) { - return CVector(colMax.x, colMax.y, 0.0f); - case 4: - if (enterDoorNode == CAR_DOOR_RR && !itsVan) - return CVector(colMax.x, colMin.y + 1.0f, 0.0f); - case 5: - return CVector(colMax.x, colMin.y, 0.0f); - case 6: - case 7: - if (walkAround == 7 && enterDoorNode == CAR_DOOR_LR && !itsVan) - return CVector(colMin.x, colMin.y + 1.0f, 0.0f); + CEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil, + false, true, false, false, false, false); - return CVector(colMin.x, colMin.y, 0.0f); - default: - return CVector(0.0f, 0.0f, 0.0f); + if (obstacle) { + if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) { + distanceToCountItDone = 2.5f; + } else { + CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex()); + float yLength = vehModel->GetColModel()->boundingBox.max.y + - vehModel->GetColModel()->boundingBox.min.y; + distanceToCountItDone = yLength * 0.55f; + } + } + } + } } -} -bool -CanWeSeeTheCorner(CVector2D dist, CVector2D fwdOffset) -{ - // because fov isn't important if dist is more then 5 unit, we want shortest way - if (dist.Magnitude() > 5.0f) - return true; + if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY) + ClearSeek(); - if (DotProduct2D(dist, fwdOffset) < 0.0f) + float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D(); + if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) { + + if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { + + if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) + nextMove = m_pedInObjective->m_nMoveState; + } else + nextMove = PEDMOVE_WALK; + + } else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { + + if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning) + nextMove = PEDMOVE_RUN; + else + nextMove = PEDMOVE_WALK; + + } else if (seekPosDist <= 2.0f) { + + if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) + nextMove = m_pedInObjective->m_nMoveState; + + } else { + nextMove = PEDMOVE_RUN; + } + + if (m_nPedState == PED_SEEK_ENTITY) { + if (m_pSeekTarget->IsPed()) { + if (((CPed*)m_pSeekTarget)->bInVehicle) + distanceToCountItDone += 2.0f; + } + } + + if (seekPosDist >= distanceToCountItDone) { + if (bIsRunning) + nextMove = PEDMOVE_RUN; + + if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) { + + if (m_actionX != 0.0f && m_actionY != 0.0f) { + + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_actionX, m_actionY, + GetPosition().x, GetPosition().y); + + float neededTurn = Abs(m_fRotationDest - m_fRotationCur); + + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; + + if (neededTurn > HALFPI) { + if (seekPosDist >= 1.0f) { + if (seekPosDist < 2.0f) { + if (bIsRunning) + nextMove = PEDMOVE_RUN; + else + nextMove = PEDMOVE_WALK; + } + } else { + nextMove = PEDMOVE_STILL; + } + } + + CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY); + if (moveDist.Magnitude() < 0.5f) { + m_nPedStateTimer = 0; + m_actionX = 0; + m_actionY = 0; + } + } + } else { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_vecSeekPos.x, m_vecSeekPos.y, + GetPosition().x, GetPosition().y); + + float neededTurn = Abs(m_fRotationDest - m_fRotationCur); + + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; + + if (neededTurn > HALFPI) { + if (seekPosDist >= 1.0 && neededTurn <= DEGTORAD(135.0f)) { + if (seekPosDist < 2.0f) + nextMove = PEDMOVE_WALK; + } else { + nextMove = PEDMOVE_STILL; + } + } + } + + if (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove) + || (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) { + + SetMoveState(nextMove); + } + + SetMoveAnim(); return false; + } + + if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) { + m_nPedStateTimer = 0; + m_actionX = 0; + m_actionY = 0; + } + + if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) { + if (m_pNextPathNode) + m_pNextPathNode = nil; + else + bScriptObjectiveCompleted = true; + + bUsePedNodeSeek = true; + } + + if (SeekFollowingPath(nil)) + m_nCurPathNode++; return true; } -#endif -// This function looks completely same on VC. void -CPed::SetDirectionToWalkAroundObject(CEntity *obj) +CPed::SetFlee(CVector2D const &from, int time) { - float distLimitForTimer = 8.0f; - CColModel *objCol = CModelInfo::GetModelInfo(obj->GetModelIndex())->GetColModel(); - CVector objColMin = objCol->boundingBox.min; - CVector objColMax = objCol->boundingBox.max; - CVector objColCenter = (objColMin + objColMax) / 2.0f; - CMatrix objMat(obj->GetMatrix()); - float dirToSet = obj->GetForward().Heading(); - bool goingToEnterCarAndItsVan = false; - bool goingToEnterCar = false; - bool objUpsideDown = false; + if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace) + return; - float checkIntervalInDist = (objColMax.y - objColMin.y) * 0.1f; - float checkIntervalInTime; + if (m_nPedState != PED_FLEE_ENTITY) { + SetStoredState(); + m_nPedState = PED_FLEE_POS; + SetMoveState(PEDMOVE_RUN); + m_fleeFromPosX = from.x; + m_fleeFromPosY = from.y; + } - if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) - return; + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + m_fleeTimer = CTimer::GetTimeInMilliseconds() + time; -#ifndef PEDS_REPORT_CRIMES_ON_PHONE - if (CharCreatedBy != MISSION_CHAR && obj->GetModelIndex() == MI_PHONEBOOTH1) { - bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; - SetFindPathAndFlee(obj, 5000, !isRunning); - return; + float angleToFace = CGeneral::GetRadianAngleBetweenPoints( + GetPosition().x, GetPosition().y, + from.x, from.y); + + m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace); + if (m_fRotationCur - PI > m_fRotationDest) { + m_fRotationDest += 2 * PI; + } else if (PI + m_fRotationCur < m_fRotationDest) { + m_fRotationDest -= 2 * PI; } -#endif +} - CVector2D adjustedColMin(objColMin.x - 0.35f, objColMin.y - 0.35f); - CVector2D adjustedColMax(objColMax.x + 0.35f, objColMax.y + 0.35f); +void +CPed::SetFlee(CEntity *fleeFrom, int time) +{ + if (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom) + return; - checkIntervalInDist = Max(checkIntervalInDist, 0.5f); - checkIntervalInDist = Min(checkIntervalInDist, (objColMax.z - objColMin.z) / 2.0f); - checkIntervalInDist = Min(checkIntervalInDist, (adjustedColMax.x - adjustedColMin.x) / 2.0f); + SetStoredState(); + m_nPedState = PED_FLEE_ENTITY; + bUsePedNodeSeek = true; + SetMoveState(PEDMOVE_RUN); + m_fleeFrom = fleeFrom; + m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom); - if (objMat.GetUp().z < 0.0f) - objUpsideDown = true; + if (time <= 0) + m_fleeTimer = 0; + else + m_fleeTimer = CTimer::GetTimeInMilliseconds() + time; - if (obj->GetModelIndex() != MI_TRAFFICLIGHTS && obj->GetModelIndex() != MI_SINGLESTREETLIGHTS1 && obj->GetModelIndex() != MI_SINGLESTREETLIGHTS2) { - objColCenter = obj->GetMatrix() * objColCenter; - } else { - checkIntervalInDist = 0.4f; - if (objMat.GetUp().z <= 0.57f) { + float angleToFace = CGeneral::GetRadianAngleBetweenPoints( + GetPosition().x, GetPosition().y, + fleeFrom->GetPosition().x, fleeFrom->GetPosition().y); - // Specific calculations for traffic lights, didn't get a bit. - adjustedColMin.x = 1.2f * (adjustedColMin.x < adjustedColMin.y ? adjustedColMin.x : adjustedColMin.y); - adjustedColMax.x = 1.2f * (adjustedColMax.x > adjustedColMax.y ? adjustedColMax.x : adjustedColMax.y); - adjustedColMin.y = 1.2f * objColMin.z; - adjustedColMax.y = 1.2f * objColMax.z; - dirToSet = objMat.GetUp().Heading(); - objMat.SetUnity(); - objMat.RotateZ(dirToSet); - objMat.GetPosition() += obj->GetPosition(); - objColCenter = obj->GetPosition(); - } else { - objColCenter.x = adjustedColMax.x - 0.25f; - objColCenter = obj->GetMatrix() * objColCenter; - distLimitForTimer = 0.75f; - } - objUpsideDown = false; + m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace); + if (m_fRotationCur - PI > m_fRotationDest) { + m_fRotationDest += 2 * PI; + } else if (PI + m_fRotationCur < m_fRotationDest) { + m_fRotationDest -= 2 * PI; } - float oldRotDest = m_fRotationDest; -#ifndef NEW_WALK_AROUND_ALGORITHM - float angleToFaceObjCenter = (objColCenter - GetPosition()).Heading(); - float angleDiffBtwObjCenterAndForward = CGeneral::LimitRadianAngle(dirToSet - angleToFaceObjCenter); - float objTopRightHeading = Atan2(adjustedColMax.x - adjustedColMin.x, adjustedColMax.y - adjustedColMin.y); -#endif +} - if (IsPlayer()) { - if (FindPlayerPed()->m_fMoveSpeed <= 0.0f) - checkIntervalInTime = 0.0f; - else - checkIntervalInTime = 2.0f / FindPlayerPed()->m_fMoveSpeed; - } else { - switch (m_nMoveState) { - case PEDMOVE_WALK: - checkIntervalInTime = 2.0f; - break; - case PEDMOVE_RUN: - checkIntervalInTime = 0.5f; - break; - case PEDMOVE_SPRINT: - checkIntervalInTime = 0.5f; - break; - default: - checkIntervalInTime = 0.0f; - break; - } - } - if (m_pSeekTarget == obj && obj->IsVehicle()) { - if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER - || m_objective == OBJECTIVE_SOLICIT_VEHICLE) { - goingToEnterCar = true; - if (IsPlayer()) - checkIntervalInTime = 0.0f; +void +CPed::ClearFlee(void) +{ + RestorePreviousState(); + bUsePedNodeSeek = false; + m_standardTimer = 0; + m_fleeTimer = 0; +} - if (((CVehicle*)obj)->bIsVan) - goingToEnterCarAndItsVan = true; +void +CPed::Flee(void) +{ + if (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) { + bool mayFinishFleeing = true; + if (m_nPedState == PED_FLEE_ENTITY) { + if ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < sq(30.0f)) + mayFinishFleeing = false; } - } - - int entityOnTopLeftOfObj = 0; - int entityOnBottomLeftOfObj = 0; - int entityOnTopRightOfObj = 0; - int entityOnBottomRightOfObj = 0; - if (CTimer::GetTimeInMilliseconds() > m_collidingThingTimer || m_collidingEntityWhileFleeing != obj) { - bool collidingThingChanged = true; - CEntity *obstacle; + if (mayFinishFleeing) { + eMoveState moveState = m_nMoveState; + ClearFlee(); -#ifndef NEW_WALK_AROUND_ALGORITHM - if (!obj->IsVehicle() || objUpsideDown) { - collidingThingChanged = false; - } else { -#else - CVector cornerToGo = CVector(10.0f, 10.0f, 10.0f); - int dirToGo; - m_walkAroundType = 0; - int iWouldPreferGoingBack = 0; // 1:left 2:right -#endif - float adjustedCheckInterval = 0.7f * checkIntervalInDist; - CVector posToCheck; + if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) + RestorePreviousObjective(); - // Top left of obj - posToCheck.x = adjustedColMin.x + adjustedCheckInterval; - posToCheck.y = adjustedColMax.y - adjustedCheckInterval; - posToCheck.z = 0.0f; - posToCheck = objMat * posToCheck; - posToCheck.z += 0.6f; - obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, - true, true, false, true, false, false); - if (obstacle) { - if (obstacle->IsBuilding()) { - entityOnTopLeftOfObj = 1; - } else if (obstacle->IsVehicle()) { - entityOnTopLeftOfObj = 2; - } else { - entityOnTopLeftOfObj = 3; - } + if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) { + SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil); } -#ifdef NEW_WALK_AROUND_ALGORITHM - else { - CVector tl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMax.y, 0.0f) - GetPosition(); - if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { - cornerToGo = tl; - m_walkAroundType = 1; + return; + } + m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000; + } - if (m_vehEnterType == CAR_DOOR_LR) - iWouldPreferGoingBack = 1; - } else if(CanWeSeeTheCorner(tl, GetForward())){ - cornerToGo = tl; - dirToGo = GetLocalDirection(tl); - if (dirToGo == 1) - m_walkAroundType = 0; // ALL of the next turns will be right turn - else if (dirToGo == 3) - m_walkAroundType = 1; // ALL of the next turns will be left turn - } - } -#endif + if (bUsePedNodeSeek) { + CPathNode *realLastNode = nil; + uint8 nextDirection = 0; + uint8 curDirectionShouldBe = 9; // means not defined yet - // Top right of obj - posToCheck.x = adjustedColMax.x - adjustedCheckInterval; - posToCheck.y = adjustedColMax.y - adjustedCheckInterval; - posToCheck.z = 0.0f; - posToCheck = objMat * posToCheck; - posToCheck.z += 0.6f; - obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, - true, true, false, true, false, false); - if (obstacle) { - if (obstacle->IsBuilding()) { - entityOnTopRightOfObj = 1; - } else if (obstacle->IsVehicle()) { - entityOnTopRightOfObj = 2; - } else { - entityOnTopRightOfObj = 3; - } - } -#ifdef NEW_WALK_AROUND_ALGORITHM - else { - CVector tr = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMax.y, 0.0f) - GetPosition(); - if (tr.Magnitude2D() < cornerToGo.Magnitude2D()) { - if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { - cornerToGo = tr; - m_walkAroundType = 2; + if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds() + && m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) { - if (m_vehEnterType == CAR_DOOR_RR) - iWouldPreferGoingBack = 2; - } else if (CanWeSeeTheCorner(tr, GetForward())) { - cornerToGo = tr; - dirToGo = GetLocalDirection(tr); - if (dirToGo == 1) - m_walkAroundType = 2; // ALL of the next turns will be right turn - else if (dirToGo == 3) - m_walkAroundType = 3; // ALL of the next turns will be left turn - } - } - } -#endif + if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) { - // Bottom right of obj - posToCheck.x = adjustedColMax.x - adjustedCheckInterval; - posToCheck.y = adjustedColMin.y + adjustedCheckInterval; - posToCheck.z = 0.0f; - posToCheck = objMat * posToCheck; - posToCheck.z += 0.6f; - obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, - true, true, false, true, false, false); - if (obstacle) { - if (obstacle->IsBuilding()) { - entityOnBottomRightOfObj = 1; - } else if (obstacle->IsVehicle()) { - entityOnBottomRightOfObj = 2; - } else { - entityOnBottomRightOfObj = 3; + curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y); + if (m_nPathDir < curDirectionShouldBe) + m_nPathDir += 8; + + int dirDiff = m_nPathDir - curDirectionShouldBe; + if (dirDiff > 2 && dirDiff < 6) { + realLastNode = nil; + m_pLastPathNode = m_pNextPathNode; + m_pNextPathNode = nil; } } -#ifdef NEW_WALK_AROUND_ALGORITHM - else { - CVector br = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMin.y, 0.0f) - GetPosition(); - if (iWouldPreferGoingBack == 2) - m_walkAroundType = 4; - else if (br.Magnitude2D() < cornerToGo.Magnitude2D()) { - if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { - cornerToGo = br; - m_walkAroundType = 5; - } else if (CanWeSeeTheCorner(br, GetForward())) { - cornerToGo = br; - dirToGo = GetLocalDirection(br); - if (dirToGo == 1) - m_walkAroundType = 4; // ALL of the next turns will be right turn - else if (dirToGo == 3) - m_walkAroundType = 5; // ALL of the next turns will be left turn - } + + if (m_pNextPathNode) { + m_vecSeekPos = m_pNextPathNode->GetPosition(); + if (m_nMoveState == PEDMOVE_RUN) + bIsRunning = true; + + eMoveState moveState = m_nMoveState; + if (Seek()) { + realLastNode = m_pLastPathNode; + m_pLastPathNode = m_pNextPathNode; + m_pNextPathNode = nil; } + bIsRunning = false; + SetMoveState(moveState); } -#endif + } - // Bottom left of obj - posToCheck.x = adjustedColMin.x + adjustedCheckInterval; - posToCheck.y = adjustedColMin.y + adjustedCheckInterval; - posToCheck.z = 0.0f; - posToCheck = objMat * posToCheck; - posToCheck.z += 0.6f; - obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, - true, true, false, true, false, false); - if (obstacle) { - if (obstacle->IsBuilding()) { - entityOnBottomLeftOfObj = 1; - } else if (obstacle->IsVehicle()) { - entityOnBottomLeftOfObj = 2; - } else { - entityOnBottomLeftOfObj = 3; - } + if (!m_pNextPathNode) { + if (curDirectionShouldBe == 9) { + curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y); } -#ifdef NEW_WALK_AROUND_ALGORITHM - else { - CVector bl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMin.y, 0.0f) - GetPosition(); - if (iWouldPreferGoingBack == 1) - m_walkAroundType = 7; - else if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) { - if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { - cornerToGo = bl; - m_walkAroundType = 6; - } else if (CanWeSeeTheCorner(bl, GetForward())) { - cornerToGo = bl; - dirToGo = GetLocalDirection(bl); - if (dirToGo == 1) - m_walkAroundType = 6; // ALL of the next turns will be right turn - else if (dirToGo == 3) - m_walkAroundType = 7; // ALL of the next turns will be left turn - } - } + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, + curDirectionShouldBe, + &nextDirection); + + if (curDirectionShouldBe < nextDirection) + curDirectionShouldBe += 8; + + if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) { + m_nPathDir = nextDirection; + m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000; + } else { + bUsePedNodeSeek = false; + SetMoveState(PEDMOVE_RUN); + Flee(); } -#else } + return; + } - if (entityOnTopLeftOfObj && entityOnTopRightOfObj && entityOnBottomRightOfObj && entityOnBottomLeftOfObj) { - collidingThingChanged = false; - entityOnTopLeftOfObj = 0; - entityOnBottomLeftOfObj = 0; - entityOnTopRightOfObj = 0; - entityOnBottomRightOfObj = 0; + if ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) { + + float angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints( + GetPosition().x, + GetPosition().y, + ms_vec2DFleePosition.x, + ms_vec2DFleePosition.y); + + m_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos); + + if (m_fRotationCur - PI > m_fRotationDest) + m_fRotationDest += TWOPI; + else if (PI + m_fRotationCur < m_fRotationDest) + m_fRotationDest -= TWOPI; + } + + if (CTimer::GetTimeInMilliseconds() & 0x20) { + //CVector forwardPos = GetPosition(); + CMatrix forwardMat(GetMatrix()); + forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f)); + CVector forwardPos = forwardMat.GetPosition(); + + CEntity *foundEnt; + CColPoint foundCol; + bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0); + + if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) { + m_fRotationDest += DEGTORAD(112.5f); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000; } + } - if (!collidingThingChanged) { - m_walkAroundType = 0; + if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer) + return; + + if (!m_collidingEntityWhileFleeing) + return; + + double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500; + + if (collidingThingPriorityMult <= 1.5) { + + double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints( + GetPosition().x, + GetPosition().y, + m_collidingEntityWhileFleeing->GetPosition().x, + m_collidingEntityWhileFleeing->GetPosition().y); + angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity); + + double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints( + m_vecDamageNormal.x, + m_vecDamageNormal.y, + 0.0f, + 0.0f); + angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing); + + if (angleToFleeEntity - PI > angleToFleeCollidingThing) + angleToFleeCollidingThing += TWOPI; + else if (PI + angleToFleeEntity < angleToFleeCollidingThing) + angleToFleeCollidingThing -= TWOPI; + + if (collidingThingPriorityMult <= 1.0f) { + // Range [0.0, 1.0] + + float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f; + + if (m_fRotationDest - PI > angleToFleeBoth) + angleToFleeBoth += TWOPI; + else if (PI + m_fRotationDest < angleToFleeBoth) + angleToFleeBoth -= TWOPI; + + m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth; } else { - if (Abs(angleDiffBtwObjCenterAndForward) >= objTopRightHeading) { - if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) { - if ((angleDiffBtwObjCenterAndForward <= 0.0f || objUpsideDown) && (angleDiffBtwObjCenterAndForward < 0.0f || !objUpsideDown)) { - if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { - m_walkAroundType = 0; - } else { - if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) >= 0.0f) { - if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { - m_walkAroundType = 1; - } else if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { - m_walkAroundType = 1; - } - } else { - if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { - m_walkAroundType = 4; - } else if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { - m_walkAroundType = 4; - } - } - } - } else { - if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { - m_walkAroundType = 0; - } else { - if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f) { - if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { - m_walkAroundType = 2; - } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { - m_walkAroundType = 2; - } - } else { - if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { - m_walkAroundType = 3; - } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { - m_walkAroundType = 3; - } - } - } - } - } else if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) - || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) < 0.0f) { - if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) { - m_walkAroundType = 3; - } - } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) { - m_walkAroundType = 4; - } - } else if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) - || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { - if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) { - m_walkAroundType = 2; - } - } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) { - m_walkAroundType = 1; - } else { - m_walkAroundType = 0; - } + // Range (1.0, 1.5] + + double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f; + m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing; + } + } else { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_vecDamageNormal.x, + m_vecDamageNormal.y, + 0.0f, + 0.0f); + m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); + } + + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + + if (m_fRotationCur - PI > m_fRotationDest) + m_fRotationDest += TWOPI; + else if (PI + m_fRotationCur < m_fRotationDest) + m_fRotationDest -= TWOPI; + +} + +// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway +void +CPed::WanderRange(void) +{ + bool arrived = Seek(); + if (arrived) { + Idle(); + if ((m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 > 997) { + CVector2D newCoords2D = m_wanderRangeBounds->GetRandomPointInRange(); + SetSeek(CVector(newCoords2D.x, newCoords2D.y, GetPosition().z), 2.5f); } -#endif } - m_collidingEntityWhileFleeing = obj; - m_collidingEntityWhileFleeing->RegisterReference((CEntity**) &m_collidingEntityWhileFleeing); +} - // TODO: This random may need to be changed. - m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 512 + CGeneral::GetRandomNumber(); +bool +CPed::SetWanderPath(int8 pathStateDest) +{ + uint8 nextPathState; - CVector localPosToHead; + if (IsPedInControl()) { + if (bKindaStayInSamePlace) { + SetIdle(); + return false; + } else { + m_nPathDir = pathStateDest; + if (pathStateDest == 0) + pathStateDest = CGeneral::GetRandomNumberInRange(1, 7); -#ifdef NEW_WALK_AROUND_ALGORITHM - int nextWalkAround = m_walkAroundType; - if (m_walkAroundType % 2 == 0) { - nextWalkAround += 2; - if (nextWalkAround > 6) - nextWalkAround = 0; + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, + m_nPathDir, &nextPathState); + + // Circular loop until we find a node for current m_nPathDir + while (!m_pNextPathNode) { + m_nPathDir = (m_nPathDir+1) % 8; + + // We're at where we started and couldn't find any node + if (m_nPathDir == pathStateDest) { + ClearAll(); + SetIdle(); + return false; + } + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, + m_nPathDir, &nextPathState); + } + + // We did it, save next path state and return true + m_nPathDir = nextPathState; + m_nPedState = PED_WANDER_PATH; + SetMoveState(PEDMOVE_WALK); + bIsRunning = false; + return true; + } } else { - nextWalkAround -= 2; - if (nextWalkAround < 0) - nextWalkAround = 7; + m_nPathDir = pathStateDest; + bStartWanderPathOnFoot = true; + return false; } +} - CVector nextPosToHead = objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, nextWalkAround, goingToEnterCar ? m_vehEnterType : 0, goingToEnterCarAndItsVan); - bool nextRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), nextPosToHead, true, true, true, true, true, true, false); +void +CPed::WanderPath(void) +{ + if (!m_pNextPathNode) { + printf("THIS SHOULDN@T HAPPEN TOO OFTEN\n"); + SetIdle(); + return; + } + if (m_nWaitState == WAITSTATE_FALSE) { + if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE) + SetMoveState(PEDMOVE_WALK); + } + m_vecSeekPos = m_pNextPathNode->GetPosition(); + m_vecSeekPos.z += 1.0f; - if(nextRouteIsClear) - m_walkAroundType = nextWalkAround; - else { - CVector posToHead = objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType, goingToEnterCar ? m_vehEnterType : 0, goingToEnterCarAndItsVan); - bool currentRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), posToHead, - true, true, true, true, true, true, false); + // Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him. + if (!Seek()) + return; - /* Either; - * - Some obstacle came in and it's impossible to reach current destination - * - We reached to the destination, but since next route is not clear, we're turning around us - */ - if (!currentRouteIsClear || - ((posToHead - GetPosition()).Magnitude2D() < 0.8f && - !CWorld::GetIsLineOfSightClear(GetPosition() + GetForward(), nextPosToHead, - true, true, true, true, true, true, false))) { + CPathNode *previousLastNode = m_pLastPathNode; + uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100; - // Change both target and direction (involves changing even/oddness) - if (m_walkAroundType % 2 == 0) { - m_walkAroundType -= 2; - if (m_walkAroundType < 0) - m_walkAroundType = 7; - else - m_walkAroundType += 1; - } else { - m_walkAroundType += 2; - if (m_walkAroundType > 7) - m_walkAroundType = 0; - else - m_walkAroundType -= 1; - } + // We don't prefer 180-degree turns in normal situations + uint8 dirWeWouldntPrefer = m_nPathDir; + if (dirWeWouldntPrefer <= 3) + dirWeWouldntPrefer += 4; + else + dirWeWouldntPrefer -= 4; + + CPathNode *nodeWeWouldntPrefer = nil; + uint8 dirToSet = 9; // means undefined + uint8 dirWeWouldntPrefer2 = 9; // means undefined + if (randVal <= 90) { + if (randVal > 80) { + m_nPathDir += 2; + m_nPathDir %= 8; } + } else { + m_nPathDir -= 2; + if (m_nPathDir < 0) + m_nPathDir += 8; } - localPosToHead = LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType, goingToEnterCar ? m_vehEnterType : 0, goingToEnterCarAndItsVan); -#else - if (Abs(angleDiffBtwObjCenterAndForward) < objTopRightHeading) { - if (goingToEnterCar) { - if (goingToEnterCarAndItsVan) { - if (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR) - return; - } - if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnBottomRightOfObj || entityOnBottomLeftOfObj)) { - m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); - localPosToHead.x = adjustedColMax.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; - } else { - m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); - localPosToHead.x = adjustedColMin.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; + m_pLastPathNode = m_pNextPathNode; + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, + m_nPathDir, &dirToSet); + + uint8 tryCount = 0; + + // NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7 + while (!m_pNextPathNode) { + tryCount++; + m_nPathDir = (m_nPathDir + 1) % 8; + + // We're at where we started and couldn't find any node + if (tryCount > 7) { + if (!nodeWeWouldntPrefer) { + ClearAll(); + SetIdle(); + // Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath. + Error("Can't find valid path node, SetWanderPath, Ped.cpp"); + return; } + m_pNextPathNode = nodeWeWouldntPrefer; + dirToSet = dirWeWouldntPrefer2; } else { - if (m_walkAroundType != 1 && m_walkAroundType != 4 - && (m_walkAroundType || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f)) { - - m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); - localPosToHead.x = adjustedColMax.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; - } else { - m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); - localPosToHead.x = adjustedColMin.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, + m_nPathDir, &dirToSet); + if (m_pNextPathNode) { + if (dirToSet == dirWeWouldntPrefer) { + nodeWeWouldntPrefer = m_pNextPathNode; + dirWeWouldntPrefer2 = dirToSet; + m_pNextPathNode = nil; + } } } - } else { - if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) { - if (angleDiffBtwObjCenterAndForward <= 0.0f) { - if (!goingToEnterCar || !goingToEnterCarAndItsVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR) { - if (goingToEnterCar) { - if (m_vehEnterType == CAR_DOOR_RF || (m_vehEnterType == CAR_DOOR_RR && !goingToEnterCarAndItsVan)) - return; - } - if (m_walkAroundType == 4 || m_walkAroundType == 3 - || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + } - m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); - localPosToHead.x = adjustedColMax.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; - } else { - m_fRotationDest = dirToSet; - localPosToHead.x = adjustedColMax.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMax.y; - } - } else { - m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); - localPosToHead.x = adjustedColMax.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; - } - } else if (goingToEnterCar && goingToEnterCarAndItsVan && (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR)) { - m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); - localPosToHead.x = adjustedColMin.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; - } else { - if (goingToEnterCar) { - if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR && !goingToEnterCarAndItsVan) - return; - } - if (m_walkAroundType == 1 || m_walkAroundType == 2 - || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + m_nPathDir = dirToSet; + if (m_pLastPathNode == m_pNextPathNode) { + m_pNextPathNode = previousLastNode; + SetWaitState(WAITSTATE_DOUBLEBACK, nil); + Say(SOUND_PED_WAIT_DOUBLEBACK); + } else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) { + SetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil); + } else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) { + SetWaitState(WAITSTATE_CROSS_ROAD, nil); + } else if (m_pNextPathNode == previousLastNode) { + SetWaitState(WAITSTATE_DOUBLEBACK, nil); + Say(SOUND_PED_WAIT_DOUBLEBACK); + } +} + +void +CPed::Avoid(void) +{ + CPed *nearestPed; + + if(m_pedStats->m_temper > m_pedStats->m_fear && m_pedStats->m_temper > 50) + return; + + if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { + + if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) { + nearestPed = m_nearPeds[0]; + + if (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_pedInObjective) { + + // Check if this ped wants to avoid the nearest one + if (CPedType::GetAvoid(m_nPedType) & CPedType::GetFlag(nearestPed->m_nPedType)) { + + // Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters. + // If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else. - m_fRotationDest = dirToSet; - localPosToHead.x = adjustedColMin.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMax.y; - } else { - m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); - localPosToHead.x = adjustedColMin.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMin.y; - } - } - } else { - if (goingToEnterCar && (!goingToEnterCarAndItsVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR)) { - if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnTopRightOfObj || entityOnTopLeftOfObj)) { + // Game converts from radians to degress and back again here, doesn't make much sense + CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur)); + forward.Normalise(); // this is kinda pointless - m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); - localPosToHead.x = adjustedColMax.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMax.y; - } else { - m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); - localPosToHead.x = adjustedColMin.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMax.y; - } - } else { - if (m_walkAroundType == 2 || m_walkAroundType == 3 - || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + // Move forward 1.25 meters + CVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f; - m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); - localPosToHead.x = adjustedColMax.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMax.y; - } else { - m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); - localPosToHead.x = adjustedColMin.x; - localPosToHead.z = 0.0f; - localPosToHead.y = adjustedColMax.y; + // Get distance to ped we want to avoid + CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition; + + if (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) { + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter()) + % 1000 / 5; + + m_fRotationDest += DEGTORAD(45.0f); + if (!bIsLooking) { + SetLookFlag(nearestPed, false); + SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800)); + } + } } } } } -#endif - if (objUpsideDown) - localPosToHead.x = localPosToHead.x * -1.0f; +} - localPosToHead = objMat * localPosToHead; - m_actionX = localPosToHead.x; - m_actionY = localPosToHead.y; - localPosToHead -= GetPosition(); - m_fRotationDest = CGeneral::LimitRadianAngle(localPosToHead.Heading()); +bool +CPed::SeekFollowingPath(CVector *unused) +{ + return m_nCurPathNode <= m_nPathNodes && m_nPathNodes; +} - if (m_fRotationDest != m_fRotationCur && bHitSomethingLastFrame) { - if (m_fRotationDest == oldRotDest) { - m_fRotationDest = oldRotDest; - } else { - m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); - } +bool +CPed::SetFollowPath(CVector dest) +{ + if (m_nPedState == PED_FOLLOW_PATH) + return false; + + if (FindPlayerPed() != this) + return false; + + if ((dest - GetPosition()).Magnitude() <= 2.0f) + return false; + + CVector pointPoses[7]; + int16 pointsFound; + CPedPath::CalcPedRoute(0, GetPosition(), dest, pointPoses, &pointsFound, 7); + for(int i = 0; i < pointsFound; i++) { + m_stPathNodeStates[i].x = pointPoses[i].x; + m_stPathNodeStates[i].y = pointPoses[i].y; } - float dist = localPosToHead.Magnitude2D(); - if (dist < 0.5f) - dist = 0.5f; + m_nCurPathNode = 0; + m_nPathNodes = pointsFound; + if (m_nPathNodes < 1) + return false; - if (dist > distLimitForTimer) - dist = distLimitForTimer; - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 280.0f * dist * checkIntervalInTime; + SetStoredState(); + m_nPedState = PED_FOLLOW_PATH; + SetMoveState(PEDMOVE_WALK); + return true; } -int32 -CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) +void +CPed::FollowPath(void) { - bool collidedWithBoat = false; - bool belowTorsoCollided = false; - float gravityEffect = -0.15f * CTimer::GetTimeStep(); - CColPoint intersectionPoint; - CColLine ourLine; + m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x; + m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y; + m_vecSeekPos.z = GetPosition().z; + + // Mysterious code +/* int v4 = 0; + int maxNodeIndex = m_nPathNodes - 1; + if (maxNodeIndex > 0) { + if (maxNodeIndex > 8) { + while (v4 < maxNodeIndex - 8) + v4 += 8; + } - CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel(); - CColModel *hisCol = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex())->GetColModel(); + while (v4 < maxNodeIndex) + v4++; - if (!bUsesCollision) - return false; + } +*/ + if (Seek()) { + m_nCurPathNode++; + if (m_nCurPathNode == m_nPathNodes) + RestorePreviousState(); + } +} - if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) - collidedWithBoat = true; +void +CPed::SetEvasiveStep(CEntity *reason, uint8 animType) +{ + AnimationId stepAnim; - // ofc we're not vehicle - if (!m_bIsVehicleBeingShifted && !bSkipLineCol -#ifdef VC_PED_PORTS - && !collidingEnt->IsPed() -#endif - ) { - if (!bCollisionProcessed) { -#ifdef VC_PED_PORTS - m_pCurrentPhysSurface = nil; -#endif - if (bIsStanding) { - bIsStanding = false; - bWasStanding = true; - } - bCollisionProcessed = true; - m_fCollisionSpeed += m_vecMoveSpeed.Magnitude2D() * CTimer::GetTimeStep(); - bStillOnValidPoly = false; - if (IsPlayer() || m_fCollisionSpeed >= 1.0f - && (m_fCollisionSpeed >= 2.0f || m_nPedState != PED_WANDER_PATH)) { - m_collPoly.valid = false; - m_fCollisionSpeed = 0.0f; - bHitSteepSlope = false; - } else { - CVector pos = GetPosition(); - float potentialGroundZ = GetPosition().z - FEET_OFFSET; - if (bWasStanding) { - pos.z += -0.25f; - potentialGroundZ += gravityEffect; - } - if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) { - bStillOnValidPoly = true; -#ifdef VC_PED_PORTS - if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { - GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; - if (bSomeVCflag1) - bSomeVCflag1 = false; - } -#else - GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; -#endif + if (m_nPedState == PED_STEP_AWAY || !IsPedInControl() || ((IsPlayer() || !bRespondsToThreats) && animType == 0)) + return; - m_vecMoveSpeed.z = 0.0f; - bIsStanding = true; - } else { - m_collPoly.valid = false; - m_fCollisionSpeed = 0.0f; - bHitSteepSlope = false; - } - } + float angleToFace = CGeneral::GetRadianAngleBetweenPoints( + reason->GetPosition().x, reason->GetPosition().y, + GetPosition().x, GetPosition().y); + angleToFace = CGeneral::LimitRadianAngle(angleToFace); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + float neededTurn = Abs(angleToFace - m_fRotationCur); + bool vehPressedHorn = false; + + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; + + CVehicle *veh = (CVehicle*)reason; + if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR) { + if (veh->m_nCarHornTimer != 0) { + vehPressedHorn = true; + if (!IsPlayer()) + animType = 1; + } + } + if (neededTurn <= DEGTORAD(90.0f) || veh->GetModelIndex() == MI_RCBANDIT || vehPressedHorn || animType != 0) { + SetLookFlag(veh, true); + if ((CGeneral::GetRandomNumber() & 1) && veh->GetModelIndex() != MI_RCBANDIT && animType == 0) { + stepAnim = ANIM_IDLE_TAXI; + } else { + + float vehDirection = CGeneral::GetRadianAngleBetweenPoints( + veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, + 0.0f, 0.0f); + + // Let's turn our back to the "reason" + angleToFace += PI; + + if (angleToFace > PI) + angleToFace -= TWOPI; + + // We don't want to run towards car's direction + float dangerZone = angleToFace - vehDirection; + dangerZone = CGeneral::LimitRadianAngle(dangerZone); + + // So, add or subtract 90deg (jump to left/right) according to that + if (dangerZone > 0.0f) + angleToFace = vehDirection - HALFPI; + else + angleToFace = vehDirection + HALFPI; + + stepAnim = NUM_ANIMS; + if (animType == 0 || animType == 1) + stepAnim = ANIM_EV_STEP; + else if (animType == 2) + stepAnim = ANIM_HANDSCOWER; + } + if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) { + CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f); + stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + stepAssoc->SetFinishCallback(PedEvadeCB, this); + + if (animType == 0) + Say(SOUND_PED_EVADE); + + m_fRotationCur = CGeneral::LimitRadianAngle(angleToFace); + ClearAimFlag(); + SetStoredState(); + m_nPedState = PED_STEP_AWAY; } + } +} - if (!bStillOnValidPoly) { - CVector potentialCenter = GetPosition(); - potentialCenter.z = GetPosition().z - 0.52f; +void +CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump) +{ + if (!IsPedInControl() || !bRespondsToThreats) + return; - // 0.52f should be a ped's approx. radius - float totalRadiusWhenCollided = collidingEnt->GetBoundRadius() + 0.52f - gravityEffect; - if (bWasStanding) { - if (collidedWithBoat) { - potentialCenter.z += 2.0f * gravityEffect; - totalRadiusWhenCollided += Abs(gravityEffect); - } else { - potentialCenter.z += gravityEffect; - } - } - if (sq(totalRadiusWhenCollided) > (potentialCenter - collidingEnt->GetBoundCentre()).MagnitudeSqr()) { - ourLine.p0 = GetPosition(); - ourLine.p1 = GetPosition(); - ourLine.p1.z = GetPosition().z - FEET_OFFSET; - if (bWasStanding) { - ourLine.p1.z = ourLine.p1.z + gravityEffect; - ourLine.p0.z = ourLine.p0.z + -0.25f; - } - float minDist = 1.0f; - belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol, - intersectionPoint, minDist, false, &m_collPoly); + CAnimBlendAssociation *animAssoc; + float angleToFace, neededTurn; + bool handsUp = false; - if (collidedWithBoat && bWasStanding && !belowTorsoCollided) { - ourLine.p0.z = ourLine.p1.z; - ourLine.p1.z = ourLine.p1.z + gravityEffect; - belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol, - intersectionPoint, minDist, false, &m_collPoly); - } - if (belowTorsoCollided) { -#ifndef VC_PED_PORTS - if (!collidingEnt->IsPed()) { -#endif - if (!bIsStanding - || FEET_OFFSET + intersectionPoint.point.z > GetPosition().z - || collidedWithBoat && 3.12f + intersectionPoint.point.z > GetPosition().z) { + angleToFace = m_fRotationCur; + CVehicle *veh = (CVehicle*) reason; + if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) { + onlyRandomJump = true; + } - if (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) { - m_pCurSurface = collidingEnt; - collidingEnt->RegisterReference((CEntity**)&m_pCurSurface); - bTryingToReachDryLand = false; - bOnBoat = false; - } else { - m_pCurrentPhysSurface = (CPhysical*)collidingEnt; - collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface); - m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition(); - m_pCurSurface = collidingEnt; - collidingEnt->RegisterReference((CEntity**)&m_pCurSurface); - m_collPoly.valid = false; - if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) { - bOnBoat = true; - } else { - bOnBoat = false; - } - } -#ifdef VC_PED_PORTS - if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { - GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; - if (bSomeVCflag1) - bSomeVCflag1 = false; - } -#else - GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; -#endif - m_nSurfaceTouched = intersectionPoint.surfaceB; - if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) { - bHitSteepSlope = true; - m_vecDamageNormal = intersectionPoint.normal; - } - } -#ifdef VC_PED_PORTS - float upperSpeedLimit = 0.33f; - float lowerSpeedLimit = -0.25f; - float speed = m_vecMoveSpeed.Magnitude2D(); - if (m_nPedState == PED_IDLE) { - upperSpeedLimit *= 2.0f; - lowerSpeedLimit *= 1.5f; - } - CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL); - if (!bWasStanding && speed > upperSpeedLimit && (/*!bPushedAlongByCar ||*/ m_vecMoveSpeed.z < lowerSpeedLimit) - && m_pCollidingEntity != collidingEnt) { + if (onlyRandomJump) { + if (reason) { + // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly. + // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots. - float damage = 100.0f * Max(speed - 0.25f, 0.0f); - float damage2 = damage; - if (m_vecMoveSpeed.z < -0.25f) - damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f; + float vehDirection = CGeneral::GetRadianAngleBetweenPoints( + veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, + 0.0f, 0.0f); + angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection; + angleToFace = CGeneral::LimitRadianAngle(angleToFace); + } + } else { + if (IsPlayer()) { + ((CPlayerPed*)this)->m_nEvadeAmount = 5; + ((CPlayerPed*)this)->m_pEvadingFrom = reason; + reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom); + return; + } - uint8 dir = 2; // from backward - if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) { - CVector2D offset = -m_vecMoveSpeed; - dir = GetLocalDirection(offset); - } + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + reason->GetPosition().x, reason->GetPosition().y, + GetPosition().x, GetPosition().y); + angleToFace = CGeneral::LimitRadianAngle(angleToFace); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - InflictDamage(collidingEnt, WEAPONTYPE_FALL, damage, PEDPIECE_TORSO, dir); - if (IsPlayer() && damage2 > 5.0f) - Say(SOUND_PED_LAND); + // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted +#ifdef FIX_BUGS + float vehDirection = CGeneral::GetRadianAngleBetweenPoints( + veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, + 0.0f, 0.0f); - } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) { - InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2); - } -#else - float speedSqr = 0.0f; - CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL); - if (!bWasStanding && (m_vecMoveSpeed.z < -0.25f || (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) > sq(0.5f))) { - if (speedSqr == 0.0f) - speedSqr = sq(m_vecMoveSpeed.z); + // Let's turn our back to the "reason" + angleToFace += PI; - uint8 dir = 2; // from backward - if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) { - CVector2D offset = -m_vecMoveSpeed; - dir = GetLocalDirection(offset); - } - InflictDamage(collidingEnt, WEAPONTYPE_FALL, 350.0f * sq(speedSqr), PEDPIECE_TORSO, dir); + if (angleToFace > PI) + angleToFace -= 2 * PI; - } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) { - InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2); - } -#endif - m_vecMoveSpeed.z = 0.0f; - bIsStanding = true; -#ifndef VC_PED_PORTS - } else { - bOnBoat = false; - } + // We don't want to dive towards car's direction + float dangerZone = angleToFace - vehDirection; + dangerZone = CGeneral::LimitRadianAngle(dangerZone); + + // So, add or subtract 90deg (jump to left/right) according to that + if (dangerZone > 0.0f) + angleToFace = 0.5f * PI + vehDirection; + else + angleToFace = vehDirection - 0.5f * PI; #endif - } else { - bOnBoat = false; - } - } + + neededTurn = Abs(angleToFace - m_fRotationCur); + + if (neededTurn > PI) + neededTurn = 2 * PI - neededTurn; + + if (neededTurn <= 0.5f*PI) { + if (CGeneral::GetRandomNumber() & 1) + handsUp = true; + } else { + if (CGeneral::GetRandomNumber() & 7) + return; } + Say(SOUND_PED_EVADE); } - int ourCollidedSpheres = CCollision::ProcessColModels(GetMatrix(), *ourCol, collidingEnt->GetMatrix(), *hisCol, collidingPoints, nil, nil); - if (ourCollidedSpheres > 0 || belowTorsoCollided) { - AddCollisionRecord(collidingEnt); - if (!collidingEnt->IsBuilding()) - ((CPhysical*)collidingEnt)->AddCollisionRecord(this); + if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) { + m_fRotationCur = angleToFace; + ClearLookFlag(); + ClearAimFlag(); + SetLookFlag(reason, true); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP); + if (animAssoc) + return; - if (ourCollidedSpheres > 0 && (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic())) { - bHasHitWall = true; - } + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f); + animAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + animAssoc->SetFinishCallback(PedEvadeCB, this); + SetStoredState(); + m_nPedState = PED_STEP_AWAY; + } else { + m_fRotationCur = angleToFace; + ClearLookFlag(); + ClearAimFlag(); + SetStoredState(); + m_nPedState = PED_DIVE_AWAY; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f); + animAssoc->SetFinishCallback(PedEvadeCB, this); } - if (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic()) { - if (bWasStanding) { - CVector sphereNormal; - float normalLength; - for(int sphere = 0; sphere < ourCollidedSpheres; sphere++) { - sphereNormal = collidingPoints[sphere].normal; -#ifdef VC_PED_PORTS - if (sphereNormal.z >= -1.0f || !IsPlayer()) { -#endif - normalLength = sphereNormal.Magnitude2D(); - if (normalLength != 0.0f) { - sphereNormal.x = sphereNormal.x / normalLength; - sphereNormal.y = sphereNormal.y / normalLength; - } -#ifdef VC_PED_PORTS - } else { - float speed = m_vecMoveSpeed.Magnitude2D(); - sphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed); - sphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed); - GetMatrix().GetPosition().z -= 0.05f; - bSomeVCflag1 = true; - } -#endif - sphereNormal.Normalise(); - collidingPoints[sphere].normal = sphereNormal; - if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF) - bHitSteepSlope = true; - } + if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) { + if (veh->pDriver && veh->pDriver->IsPlayer()) { + CWanted *wanted = FindPlayerPed()->m_pWanted; + wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false); + wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false); } } - return ourCollidedSpheres; +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + else if (reason->IsVehicle()) { + if (veh->pDriver && veh->pDriver->IsPlayer()) { + CWanted* wanted = FindPlayerPed()->m_pWanted; + wanted->RegisterCrime(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false); + } + } +#endif } void -CPed::SetFormation(eFormation type) +CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg) { - // FIX: Formations in GetFormationPosition were in range 1-8, whereas in here it's 0-7. - // To not change the behaviour, range in here tweaked by 1 with the use of enum. - - switch (m_pedFormation) { - case FORMATION_REAR: - case FORMATION_REAR_LEFT: - case FORMATION_REAR_RIGHT: - case FORMATION_FRONT_LEFT: - case FORMATION_FRONT_RIGHT: - case FORMATION_LEFT: - case FORMATION_RIGHT: - case FORMATION_FRONT: - break; - default: - Error("Unknown formation type, PedAI.cpp"); - break; + CPed* ped = (CPed*)arg; + + if (!animAssoc) { + ped->ClearLookFlag(); + if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) + ped->RestorePreviousState(); + + } else if (animAssoc->animId == ANIM_EV_DIVE) { + ped->bUpdateAnimHeading = true; + ped->ClearLookFlag(); + if (ped->m_nPedState == PED_DIVE_AWAY) + { + ped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1; + ped->m_nPedState = PED_FALL; + } + animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + + } else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) { + ped->ClearLookFlag(); + if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) + ped->RestorePreviousState(); + + } else if (ped->m_nPedState != PED_ARRESTED) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + if (animAssoc->blendDelta >= 0.0f) + animAssoc->blendDelta = -4.0f; + + ped->ClearLookFlag(); + if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) { + ped->RestorePreviousState(); + } } - m_pedFormation = type; } void -CPed::SetFollowRoute(int16 currentPoint, int16 routeType) +CPed::SetDie(AnimationId animId, float delta, float speed) { - m_routeLastPoint = currentPoint; - m_routeStartPoint = CRouteNode::GetRouteStart(currentPoint); - m_routePointsPassed = 0; - m_routeType = routeType; - m_routePointsBeingPassed = 1; - m_objective = OBJECTIVE_FOLLOW_ROUTE; - m_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute()); -} + CPlayerPed *player = FindPlayerPed(); + if (player == this) { + if (!player->m_bCanBeDamaged) + return; + } -// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway -void -CPed::WanderRange(void) -{ - bool arrived = Seek(); - if (arrived) { - Idle(); - if ((m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 > 997) { - CVector2D newCoords2D = m_wanderRangeBounds->GetRandomPointInRange(); - SetSeek(CVector(newCoords2D.x, newCoords2D.y, GetPosition().z), 2.5f); - } + m_threatEntity = nil; + if (DyingOrDead()) + return; + + if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) + delta *= 0.5f; + + SetStoredState(); + ClearAll(); + m_fHealth = 0.0f; + if (m_nPedState == PED_DRIVING) { + if (!IsPlayer()) + FlagToDestroyWhenNextProcessed(); + } else if (bInVehicle) { + if (m_pVehicleAnim) + m_pVehicleAnim->blendDelta = -1000.0f; + } else if (EnteringCar()) { + QuitEnteringCar(); } -} -bool -CPed::WillChat(CPed *stranger) -{ - if (m_pNextPathNode && m_pLastPathNode) { - if (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) { - return false; + m_nPedState = PED_DIE; + if (animId == NUM_ANIMS) { + bIsPedDieAnimPlaying = false; + } else { + CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta); + if (speed > 0.0f) + dieAssoc->speed = speed; + + dieAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + if (dieAssoc->IsRunning()) { + dieAssoc->SetFinishCallback(FinishDieAnimCB, this); + bIsPedDieAnimPlaying = true; } } - if (m_nSurfaceTouched == SURFACE_TARMAC) - return false; - if (stranger == this) - return false; - if (m_nPedType == stranger->m_nPedType) - return true; - if (m_nPedType == PEDTYPE_CRIMINAL) - return false; - if ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType) - return false; - return true; + + Say(SOUND_PED_DEATH); + if (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK) + QuitEnteringCar(); + if (!bInVehicle) + StopNonPartialAnims(); + + m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds(); } void -CPed::SetEnterTrain(CVehicle *train, uint32 unused) +CPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg) { - if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen()) - return; - - /* - // Not used - CVector enterPos; - GetNearestTrainPedPosition(train, enterPos); - */ - m_fRotationCur = train->GetForward().Heading() - HALFPI; - m_pMyVehicle = train; - m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + CPed *ped = (CPed*)arg; - m_nPedState = PED_ENTER_TRAIN; - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f); - m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this); - bUsesCollision = false; - LineUpPedWithTrain(); - if (IsPlayer()) { - if (((CPlayerPed*)this)->m_bAdrenalineActive) - ((CPlayerPed*)this)->ClearAdrenaline(); - } + if (ped->bIsPedDieAnimPlaying) + ped->bIsPedDieAnimPlaying = false; } void -CPed::SetDuck(uint32 time) +CPed::SetDead(void) { - if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer) - return; + bUsesCollision = false; - if (bCrouchWhenShooting && (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN)) { - CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); - if (!duckAssoc || duckAssoc->blendDelta < 0.0f) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_LOW, 4.0f); - bIsDucking = true; - m_duckTimer = CTimer::GetTimeInMilliseconds() + time; - } - } else { - CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (!duckAssoc || duckAssoc->blendDelta < 0.0f) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f); - bIsDucking = true; - m_duckTimer = CTimer::GetTimeInMilliseconds() + time; - } + m_fHealth = 0.0f; + if (m_nPedState == PED_DRIVING) + bIsVisible = false; + + m_nPedState = PED_DEAD; + m_pVehicleAnim = nil; + m_pCollidingEntity = nil; + + CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + RemoveWeaponModel(weapon->m_nModelId); + + m_currentWeapon = WEAPONTYPE_UNARMED; + CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250); + if (this != FindPlayerPed()) { + CreateDeadPedWeaponPickups(); + CreateDeadPedMoney(); } + + m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds(); + m_deadBleeding = false; + bDoBloodyFootprints = false; + bVehExitWillBeInstant = false; + CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000); } void -CPed::SeekBoatPosition(void) +CPed::Die(void) { - if (m_carInObjective && !m_carInObjective->pDriver) { - CVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo(); - - CVector enterOffset; - enterOffset = boatModel->GetFrontSeatPosn(); - enterOffset.x = 0.0f; - CMatrix boatMat(m_carInObjective->GetMatrix()); - SetMoveState(PEDMOVE_WALK); - m_vecSeekPos = boatMat * enterOffset; - if (Seek()) { - // We arrived to the boat - m_vehEnterType = 0; - SetEnterCar(m_carInObjective, 0); - } - } else - RestorePreviousState(); + // UNUSED: This is a perfectly empty function. } void -CPed::SetEnterCar(CVehicle *car, uint32 unused) +CPed::SetChat(CEntity *chatWith, uint32 time) { - if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) { - RestorePreviousState(); - RestorePreviousObjective(); - } else { - uint8 doorFlag; - eDoors door; - switch (m_vehEnterType) { - case CAR_DOOR_RF: - doorFlag = CAR_DOOR_FLAG_RF; - door = DOOR_FRONT_RIGHT; - break; - case CAR_DOOR_RR: - doorFlag = CAR_DOOR_FLAG_RR; - door = DOOR_REAR_RIGHT; - break; - case CAR_DOOR_LF: - doorFlag = CAR_DOOR_FLAG_LF; - door = DOOR_FRONT_LEFT; - break; - case CAR_DOOR_LR: - doorFlag = CAR_DOOR_FLAG_LR; - door = DOOR_REAR_LEFT; - break; - default: - doorFlag = CAR_DOOR_FLAG_UNKNOWN; - break; - } - if (!IsPedInControl() || m_fHealth <= 0.0f - || doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags - || car->bIsBeingCarJacked || m_pVehicleAnim - || doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door)) - SetMoveState(PEDMOVE_STILL); - else - SetEnterCar_AllClear(car, m_vehEnterType, doorFlag); - } + if(m_nPedState != PED_CHAT) + SetStoredState(); + + m_nPedState = PED_CHAT; + SetMoveState(PEDMOVE_STILL); +#if defined VC_PED_PORTS || defined FIX_BUGS + m_lookTimer = 0; +#endif + SetLookFlag(chatWith, true); + m_standardTimer = CTimer::GetTimeInMilliseconds() + time; + m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000; } void -CPed::SetRadioStation(void) +CPed::Chat(void) { - static const uint8 radiosPerRadioCategories[10][4] = { - {JAH_RADIO, RISE_FM, GAME_FM, MSX_FM}, - {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK}, - {RISE_FM, GAME_FM, MSX_FM, FLASHBACK}, - {HEAD_RADIO, RISE_FM, LIPS_106, MSX_FM}, - {HEAD_RADIO, RISE_FM, MSX_FM, FLASHBACK}, - {JAH_RADIO, RISE_FM, LIPS_106, FLASHBACK}, - {HEAD_RADIO, RISE_FM, LIPS_106, FLASHBACK}, - {HEAD_RADIO, JAH_RADIO, LIPS_106, FLASHBACK}, - {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK}, - {CHATTERBOX, HEAD_RADIO, LIPS_106, GAME_FM} - }; - uint8 orderInCat = 0; // BUG: this wasn't initialized + // We're already looking to our partner + if (bIsLooking && TurnBody()) + ClearLookFlag(); - if (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this) + if (!m_pLookTarget || !m_pLookTarget->IsPed()) { + ClearChat(); return; + } - uint8 category = GetPedRadioCategory(GetModelIndex()); - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (CGeneral::GetRandomNumber() & 15) { - for (orderInCat = 0; orderInCat < 4; orderInCat++) { - if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat]) - break; - } - } else { - m_pMyVehicle->m_nRadioStation = USERTRACK; + CPed *partner = (CPed*) m_pLookTarget; + + if (partner->m_nPedState != PED_CHAT) { + ClearChat(); + if (partner->m_pedInObjective) { + if (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || + partner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE) + ReactToAttack(partner->m_pedInObjective); } + return; + } + if (bIsTalking) { + if (CGeneral::GetRandomNumber() < 512) { + CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); + if (chatAssoc) { + chatAssoc->blendDelta = -4.0f; + chatAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + bIsTalking = false; + } else + Say(SOUND_PED_CHAT); + } else { - for (orderInCat = 0; orderInCat < 4; orderInCat++) { - if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat]) - break; + + if (CGeneral::GetRandomNumber() < 20 && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); + } + if (!bIsTalking && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) { + CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f); + float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f); + chatAssoc->SetCurrentTime(chatTime); + + bIsTalking = true; + Say(SOUND_PED_CHAT); } } - if (orderInCat == 4) { - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (CGeneral::GetRandomNumber() & 15) - m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3]; - else - m_pMyVehicle->m_nRadioStation = USERTRACK; - } else { - m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3]; - } + if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) { + ClearChat(); + m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; } } -inline bool -CPed::IsNotInWreckedVehicle() +void +CPed::ClearChat(void) { - return m_pMyVehicle != nil && m_pMyVehicle->GetStatus() != STATUS_WRECKED; + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + bIsTalking = false; + ClearLookFlag(); + RestorePreviousState(); } +#ifdef PEDS_REPORT_CRIMES_ON_PHONE void -CPed::PreRender(void) +ReportPhonePickUpCB(CAnimBlendAssociation* assoc, void* arg) { - CShadows::StoreShadowForPed(this, - CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue], - CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue], - CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]); + CPed* ped = (CPed*)arg; + ped->m_nMoveState = PEDMOVE_STILL; + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f); -#ifdef PED_SKIN - if(IsClumpSkinned(GetClump())){ - UpdateRpHAnim(); + if (assoc->blendAmount > 0.5f && ped) { + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f); + } +} - if(bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD){ - // scale head to 0 if shot off - RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); - int32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD)); - RwMatrix *head = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; - RwV3d zero = { 0.0f, 0.0f, 0.0f }; - RwMatrixScale(head, &zero, rwCOMBINEPRECONCAT); - } +void +ReportPhonePutDownCB(CAnimBlendAssociation* assoc, void* arg) +{ + assoc->flags |= ASSOC_DELETEFADEDOUT; + assoc->blendDelta = -1000.0f; + CPed* ped = (CPed*)arg; + + if (ped->m_phoneId != -1 && crimeReporters[ped->m_phoneId] == ped) { + crimeReporters[ped->m_phoneId] = nil; + gPhoneInfo.m_aPhones[ped->m_phoneId].m_nState = PHONE_STATE_FREE; + ped->m_phoneId = -1; } + + if (assoc->blendAmount > 0.5f) + ped->bUpdateAnimHeading = true; + + ped->SetWanderPath(CGeneral::GetRandomNumber() & 7); +} #endif - if (bBodyPartJustCameOff && bIsPedDieAnimPlaying && m_bodyPartBleeding != -1 && (CTimer::GetFrameCounter() & 7) > 3) { - CVector bloodDir(0.0f, 0.0f, 0.0f); - CVector bloodPos(0.0f, 0.0f, 0.0f); +bool +CPed::FacePhone(void) +{ + // This function was broken since it's left unused early in development. +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + float phoneDir = CGeneral::GetRadianAngleBetweenPoints( + gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y, + GetPosition().x, GetPosition().y); - TransformToNode(bloodPos, m_bodyPartBleeding); + if (m_facePhoneStart) { + m_lookTimer = 0; + SetLookFlag(phoneDir, true); + m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000; + m_facePhoneStart = false; + } - switch (m_bodyPartBleeding) { - case PED_HEAD: - bloodDir = 0.1f * GetUp(); - break; - case PED_UPPERARML: - bloodDir = 0.04f * GetUp() - 0.04f * GetRight(); - break; - case PED_UPPERARMR: - bloodDir = 0.04f * GetUp() - 0.04f * GetRight(); - break; - case PED_UPPERLEGL: - bloodDir = 0.04f * GetUp() + 0.05f * GetForward(); - break; - case PED_UPPERLEGR: - bloodDir = 0.04f * GetUp() + 0.05f * GetForward(); - break; - default: - bloodDir = CVector(0.0f, 0.0f, 0.0f); - break; - } + if (bIsLooking && TurnBody()) { + ClearLookFlag(); + SetIdle(); + m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000; + CAnimBlendAssociation* assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f); + assoc->SetFinishCallback(ReportPhonePickUpCB, this); + return true; + } - for(int i = 0; i < 4; i++) - CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0); + return false; +#else + float currentRot = RADTODEG(m_fRotationCur); + float phoneDir = CGeneral::GetRadianAngleBetweenPoints( + gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, + gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y, + GetPosition().x, + GetPosition().y); + + SetLookFlag(phoneDir, false); + phoneDir = CGeneral::LimitAngle(phoneDir); + m_moved = CVector2D(0.0f, 0.0f); + + if (currentRot - 180.0f > phoneDir) + phoneDir += 2 * 180.0f; + else if (180.0f + currentRot < phoneDir) + phoneDir -= 2 * 180.0f; + + float neededTurn = currentRot - phoneDir; + + if (Abs(neededTurn) <= 0.75f) { + SetIdle(); + ClearLookFlag(); + m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000; + return true; + } else { + m_fRotationCur = DEGTORAD(currentRot - neededTurn * 0.2f); + return false; } - if (CWeather::Rain > 0.3f && TheCamera.SoundDistUp > 15.0f) { - if ((TheCamera.GetPosition() - GetPosition()).Magnitude() < 25.0f) { - bool doSplashUp = true; - CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel(); - CVector speed = FindPlayerSpeed(); +#endif +} +bool +CPed::MakePhonecall(void) +{ +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) { - if (Abs(speed.x) <= 0.05f && Abs(speed.y) <= 0.05f) { - if (!OnGround() && m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { - if (!IsPedHeadAbovePos(0.3f) || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED)) { - doSplashUp = false; - } - } else - doSplashUp = false; - } else - doSplashUp = false; + FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(), + (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)m_victimOfPlayerCrime), false); - if (doSplashUp && ourCol->numSpheres > 0) { - for(int i = 0; i < ourCol->numSpheres; i++) { - CColSphere *sphere = &ourCol->spheres[i]; - CVector splashPos; - switch (sphere->piece) { - case PEDPIECE_LEFTARM: - case PEDPIECE_RIGHTARM: - case PEDPIECE_HEAD: - splashPos = GetMatrix() * ourCol->spheres[i].center; - splashPos.z += 0.7f * sphere->radius; - splashPos.x += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f); - splashPos.y += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f); - CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, splashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 1, 0); - break; - default: - break; - } - } - } - } + if (m_crimeToReportOnPhone != CRIME_POSSESSION_GUN) + FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1); + + bRunningToPhone = false; + } +#endif + if (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer) + return false; + +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + CAnimBlendAssociation* talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_TALK); + if (talkAssoc && talkAssoc->blendAmount > 0.5f) { + CAnimBlendAssociation* endAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f); + endAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + endAssoc->SetFinishCallback(ReportPhonePutDownCB, this); } +#endif + SetIdle(); + + gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE; +#ifndef PEDS_REPORT_CRIMES_ON_PHONE + m_phoneId = -1; +#endif + + // Because SetWanderPath is now done async in ReportPhonePutDownCB +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + return false; +#else + return true; +#endif } void -CPed::ProcessBuoyancy(void) +CPed::Teleport(CVector pos) { - static uint32 nGenerateRaindrops = 0; - static uint32 nGenerateWaterCircles = 0; - CRGBA color(((0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f), - ((0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f), - ((0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f), - (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48); + CWorld::Remove(this); + SetPosition(pos); + bIsStanding = false; + m_nPedStateTimer = 0; + m_actionX = 0.0f; + m_actionY = 0.0f; + m_pDamageEntity = nil; + CWorld::Add(this); +} - if (bInVehicle) +void +CPed::SetSeekCar(CVehicle *car, uint32 doorNode) +{ + if (m_nPedState == PED_SEEK_CAR) return; - CVector buoyancyPoint; - CVector buoyancyImpulse; +#ifdef VC_PED_PORTS + if (!CanSetPedState() || m_nPedState == PED_DRIVING) + return; +#endif + + SetStoredState(); + m_pSeekTarget = car; + m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); + m_carInObjective = car; + m_carInObjective->RegisterReference((CEntity**) &m_carInObjective); + m_pMyVehicle = car; + m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle); + // m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); + m_vehEnterType = doorNode; + m_distanceToCountSeekDone = 0.5f; + m_nPedState = PED_SEEK_CAR; + +} -#ifndef VC_PED_PORTS - float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.5f : 1.3f); -#else - float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f); -#endif +void +CPed::SeekCar(void) +{ + CVehicle *vehToSeek = m_carInObjective; + CVector dest(0.0f, 0.0f, 0.0f); + if (!vehToSeek) { + RestorePreviousState(); + return; + } - if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) { - bTouchingWater = true; - CEntity *entity; - CColPoint point; - if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil) - && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) { - bIsInWater = false; + if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) { + if (m_vehEnterType && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { + if (IsRoomToBeCarJacked()) { + dest = GetPositionToOpenCarDoor(vehToSeek, m_vehEnterType); + } else if (m_nPedType == PEDTYPE_COP) { + dest = GetPositionToOpenCarDoor(vehToSeek, CAR_DOOR_RF); + } else { + SetMoveState(PEDMOVE_STILL); + } + } else + GetNearestDoor(vehToSeek, dest); + } else { + if (m_hitRecoverTimer > CTimer::GetTimeInMilliseconds()) { + SetMoveState(PEDMOVE_STILL); return; } - bIsInWater = true; - ApplyMoveForce(buoyancyImpulse); - if (!DyingOrDead()) { - if (bTryingToReachDryLand) { - if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) { - bTryingToReachDryLand = false; - CVector pos = GetPosition(); - if (PlacePedOnDryLand()) { - if (m_fHealth > 20.0f) - InflictDamage(nil, WEAPONTYPE_DROWNING, 15.0f, PEDPIECE_TORSO, false); - - if (bIsInTheAir) { - RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); - bIsInTheAir = false; - } - pos.z = pos.z - 0.8f; -#ifdef PC_PARTICLE - CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true); -#else - CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true); -#endif - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - m_nPedState = PED_IDLE; - return; - } + if (vehToSeek->GetModelIndex() == MI_COACH) { + GetNearestDoor(vehToSeek, dest); + } else { + if (vehToSeek->IsTrain()) { + if (vehToSeek->GetStatus() != STATUS_TRAIN_NOT_MOVING) { + RestorePreviousObjective(); + RestorePreviousState(); + return; } - } - float speedMult = 0.0f; - if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.75f * CTimer::GetTimeStep() - || mod_Buoyancy.m_waterlevel > GetPosition().z) { - speedMult = pow(0.9f, CTimer::GetTimeStep()); - m_vecMoveSpeed.x *= speedMult; - m_vecMoveSpeed.y *= speedMult; - m_vecMoveSpeed.z *= speedMult; - bIsStanding = false; - InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); - } - if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) { - if (speedMult == 0.0f) { - speedMult = pow(0.9f, CTimer::GetTimeStep()); + if (!GetNearestTrainDoor(vehToSeek, dest)) { + RestorePreviousObjective(); + RestorePreviousState(); + return; } - m_vecMoveSpeed.x *= speedMult; - m_vecMoveSpeed.y *= speedMult; - if (m_vecMoveSpeed.z >= -0.1f) { - if (m_vecMoveSpeed.z < -0.04f) - m_vecMoveSpeed.z = -0.02f; - } else { - m_vecMoveSpeed.z = -0.01f; - DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f); -#ifdef PC_PARTICLE - CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition(); - float level = 0.0f; - if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) - aBitForward.z = level; - - CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true); - nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80; - nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100; -#else - CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition(); - float level = 0.0f; - if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) - aBitForward.z = level + 0.5f; - - CVector vel = m_vecMoveSpeed * 0.1f; - vel.z = 0.18f; - CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true); - nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300; - nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60; -#endif + } else { + if (!GetNearestPassengerDoor(vehToSeek, dest)) { + if (vehToSeek->m_nNumPassengers == vehToSeek->m_nNumMaxPassengers) { + RestorePreviousObjective(); + RestorePreviousState(); + } else { + SetMoveState(PEDMOVE_STILL); + } + bVehEnterDoorIsBlocked = true; + return; } + bVehEnterDoorIsBlocked = false; } - } else - return; - } else - bTouchingWater = false; - - if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) { - CVector pos = GetPosition(); - float level = 0.0f; - if (CWaterLevel::GetWaterLevel(pos, &level, false)) - pos.z = level; + } + } - if (pos.z != 0.0f) { - nGenerateWaterCircles = 0; - for(int i = 0; i < 4; i++) { -#ifdef PC_PARTICLE - pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); - pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); - CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0); + if (dest.x == 0.0f && dest.y == 0.0f) { +#ifdef FIX_BUGS + if ((!IsPlayer() && CharCreatedBy != MISSION_CHAR) || vehToSeek->VehicleCreatedBy != MISSION_VEHICLE || vehToSeek->pDriver || !vehToSeek->CanPedOpenLocks(this)) { #else - pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); - pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); - CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f)); + if ((!IsPlayer() && CharCreatedBy != MISSION_CHAR) || vehToSeek->VehicleCreatedBy != MISSION_VEHICLE || vehToSeek->pDriver) { #endif + RestorePreviousState(); + if (IsPlayer()) { + ClearObjective(); + } else if (CharCreatedBy == RANDOM_CHAR) { + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000; } + SetMoveState(PEDMOVE_STILL); + TheCamera.ClearPlayerWeaponMode(); + CCarCtrl::RemoveFromInterestingVehicleList(vehToSeek); + return; + } + dest = vehToSeek->GetPosition(); + if (bCollidedWithMyVehicle) { + WarpPedIntoCar(m_pMyVehicle); + return; } } - - if (nGenerateRaindrops && CTimer::GetTimeInMilliseconds() >= nGenerateRaindrops) { - CVector pos = GetPosition(); - float level = 0.0f; - if (CWaterLevel::GetWaterLevel(pos, &level, false)) - pos.z = level; - - if (pos.z >= 0.0f) { -#ifdef PC_PARTICLE - pos.z += 0.25f; -#else - pos.z += 0.5f; -#endif - nGenerateRaindrops = 0; -#ifdef PC_PARTICLE - CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true); + bool foundBetterPosToSeek = PossiblyFindBetterPosToSeekCar(&dest, vehToSeek); + m_vecSeekPos = dest; + float distToDestSqr = (m_vecSeekPos - GetPosition()).MagnitudeSqr(); +#ifndef VC_PED_PORTS + if (bIsRunning) + SetMoveState(PEDMOVE_RUN); #else - CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true); + if (bIsRunning || + vehToSeek->pDriver && distToDestSqr > sq(2.0f) && (Abs(vehToSeek->m_vecMoveSpeed.x) > 0.01f || Abs(vehToSeek->m_vecMoveSpeed.y) > 0.01f)) + SetMoveState(PEDMOVE_RUN); #endif + else if (distToDestSqr < sq(2.0f)) + SetMoveState(PEDMOVE_WALK); + + if (distToDestSqr >= 1.0f) + bCanPedEnterSeekedCar = false; + else if (2.0f * vehToSeek->GetColModel()->boundingBox.max.x > distToDestSqr) + bCanPedEnterSeekedCar = true; + + if (vehToSeek->m_nGettingInFlags & GetCarDoorFlag(m_vehEnterType)) + bVehEnterDoorIsBlocked = true; + else + bVehEnterDoorIsBlocked = false; + + // Arrived to the car + if (Seek()) { + if (!foundBetterPosToSeek) { + if (1.5f + GetPosition().z > dest.z && GetPosition().z - 0.5f < dest.z) { + if (vehToSeek->IsTrain()) { + SetEnterTrain(vehToSeek, m_vehEnterType); + } else { + m_fRotationCur = m_fRotationDest; + if (!bVehEnterDoorIsBlocked) { + vehToSeek->SetIsStatic(false); + if (m_objective == OBJECTIVE_SOLICIT_VEHICLE) { + SetSolicit(1000); + } else if (m_objective == OBJECTIVE_BUY_ICE_CREAM) { + SetBuyIceCream(); + } else if (vehToSeek->m_nNumGettingIn < vehToSeek->m_nNumMaxPassengers + 1 + && vehToSeek->CanPedEnterCar()) { + + switch (vehToSeek->GetStatus()) { + case STATUS_PLAYER: + case STATUS_SIMPLE: + case STATUS_PHYSICS: + case STATUS_PLAYER_DISABLED: + if (!vehToSeek->bIsBus && (!m_leader || m_leader != vehToSeek->pDriver) && + (m_vehEnterType == CAR_DOOR_LF && vehToSeek->pDriver || m_vehEnterType == CAR_DOOR_RF && vehToSeek->pPassengers[0] || m_vehEnterType == CAR_DOOR_LR && vehToSeek->pPassengers[1] || m_vehEnterType == CAR_DOOR_RR && vehToSeek->pPassengers[2])) { + SetCarJack(vehToSeek); + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && m_vehEnterType != CAR_DOOR_LF) + vehToSeek->pDriver->bFleeAfterExitingCar = true; + } else { + SetEnterCar(vehToSeek, m_vehEnterType); + } + break; + case STATUS_ABANDONED: + if (m_vehEnterType == CAR_DOOR_RF && vehToSeek->pPassengers[0]) { + if (vehToSeek->pPassengers[0]->bDontDragMeOutCar) { + if (IsPlayer()) + SetEnterCar(vehToSeek, m_vehEnterType); + } else { + SetCarJack(vehToSeek); + } + } else { + SetEnterCar(vehToSeek, m_vehEnterType); + } + break; + case STATUS_WRECKED: + SetIdle(); + break; + default: + return; + } + } else { + RestorePreviousState(); + } + } else { + SetMoveState(PEDMOVE_STILL); + } + } + } } } } -void -CPed::SetSolicit(uint32 time) +bool +CPed::CheckForExplosions(CVector2D &area) { - if (m_nPedState == PED_SOLICIT || !IsPedInControl() || !m_carInObjective) - return; + int event = 0; + if (CEventList::FindClosestEvent(EVENT_EXPLOSION, GetPosition(), &event)) { + area.x = gaEvent[event].posn.x; + area.y = gaEvent[event].posn.y; + CEntity *actualEntity = nil; - if (CharCreatedBy != MISSION_CHAR && m_carInObjective->m_nNumGettingIn == 0 - && CTimer::GetTimeInMilliseconds() < m_objectiveTimer) { - if (m_vehEnterType == CAR_DOOR_LF) { - m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI; - } else { - m_fRotationDest = m_carInObjective->GetForward().Heading() + HALFPI; + switch (gaEvent[event].entityType) { + case EVENT_ENTITY_PED: + actualEntity = CPools::GetPed(gaEvent[event].entityRef); + break; + case EVENT_ENTITY_VEHICLE: + actualEntity = CPools::GetVehicle(gaEvent[event].entityRef); + break; + case EVENT_ENTITY_OBJECT: + actualEntity = CPools::GetObject(gaEvent[event].entityRef); + break; + default: + break; } - if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) { - m_standardTimer = CTimer::GetTimeInMilliseconds() + time; + if (actualEntity) { + m_pEventEntity = actualEntity; + m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity); + bGonnaInvestigateEvent = true; + } else + bGonnaInvestigateEvent = false; - if(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_HOOKERTALK, 4.0f); + CEventList::ClearEvent(event); + return true; + } else if (CEventList::FindClosestEvent(EVENT_FIRE, GetPosition(), &event)) { + area.x = gaEvent[event].posn.x; + area.y = gaEvent[event].posn.y; + CEventList::ClearEvent(event); + bGonnaInvestigateEvent = false; + return true; + } - m_nPedState = PED_SOLICIT; + bGonnaInvestigateEvent = false; + return false; +} + +CPed * +CPed::CheckForGunShots(void) +{ + int event; + if (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) { + if (gaEvent[event].entityType == EVENT_ENTITY_PED) { + // Probably due to we don't want peds to go gunshot area? (same on VC) + bGonnaInvestigateEvent = false; + return CPools::GetPed(gaEvent[event].entityRef); } } + bGonnaInvestigateEvent = false; + return nil; } -bool -CPed::SetFollowPath(CVector dest) +CPed * +CPed::CheckForDeadPeds(void) { - if (m_nPedState == PED_FOLLOW_PATH) - return false; - - if (FindPlayerPed() != this) - return false; - - if ((dest - GetPosition()).Magnitude() <= 2.0f) - return false; - - CVector pointPoses[7]; - int16 pointsFound; - CPedPath::CalcPedRoute(0, GetPosition(), dest, pointPoses, &pointsFound, 7); - for(int i = 0; i < pointsFound; i++) { - m_stPathNodeStates[i].x = pointPoses[i].x; - m_stPathNodeStates[i].y = pointPoses[i].y; + int event; + if (CEventList::FindClosestEvent(EVENT_DEAD_PED, GetPosition(), &event)) { + int pedHandle = gaEvent[event].entityRef; + if (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) { + bGonnaInvestigateEvent = true; + return CPools::GetPed(pedHandle); + } } + bGonnaInvestigateEvent = false; + return nil; +} - m_nCurPathNode = 0; - m_nPathNodes = pointsFound; - if (m_nPathNodes < 1) - return false; +bool +CPed::IsPlayer(void) const +{ + return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 || + m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4; +} - SetStoredState(); - m_nPedState = PED_FOLLOW_PATH; - SetMoveState(PEDMOVE_WALK); - return true; +bool +CPed::IsGangMember(void) const +{ + return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9; } -void -AddYardieDoorSmoke(CVehicle *veh, uint32 doorNode) +bool +CPed::IsPointerValid(void) { - eDoors door; - switch (doorNode) { - case CAR_DOOR_RF: - door = DOOR_FRONT_RIGHT; - break; - case CAR_DOOR_LF: - door = DOOR_FRONT_LEFT; - break; - default: - break; - } + int pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8; + if (pedIndex < 0 || pedIndex >= NUMPEDS) + return false; - if (!veh->IsDoorMissing(door) && veh->IsComponentPresent(doorNode)) { - CVector pos; -#ifdef FIX_BUGS - veh->GetComponentWorldPosition(doorNode, pos); -#else - veh->GetComponentWorldPosition(CAR_DOOR_LF, pos); -#endif - CParticle::AddYardieDoorSmoke(pos, veh->GetMatrix()); - } + if (m_entryInfoList.first || FindPlayerPed() == this) + return true; + + return false; } -// wantedDoorNode = 0 means that func. will determine it void -CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) +CPed::SetPedPositionInCar(void) { - uint32 optedDoorNode = wantedDoorNode; - bool teleportNeeded = false; - bool isLow = !!veh->bLowVehicle; - if (!veh->CanPedExitCar()) { - if (veh->pDriver && !veh->pDriver->IsPlayer()) { - veh->AutoPilot.m_nCruiseSpeed = 0; - veh->AutoPilot.m_nCarMission = MISSION_NONE; - } - return; - } - - if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) + if (CReplay::IsPlayingBack()) return; - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - if (wantedDoorNode == 0) { - optedDoorNode = CAR_DOOR_LF; - if (!veh->bIsBus) { - if (veh->pDriver == this) { - optedDoorNode = CAR_DOOR_LF; - } else if (veh->pPassengers[0] == this) { - optedDoorNode = CAR_DOOR_RF; - } else if (veh->pPassengers[1] == this) { - optedDoorNode = CAR_DOOR_LR; - } else if (veh->pPassengers[2] == this) { - optedDoorNode = CAR_DOOR_RR; - } else { - for (int i = 3; i < veh->m_nNumMaxPassengers; ++i) { - if (veh->pPassengers[i] == this) { - if (i & 1) - optedDoorNode = CAR_DOOR_RR; - else - optedDoorNode = CAR_DOOR_LR; - - break; - } - } - } + if (bChangedSeat) { + bool notYet = false; + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_GETIN_LHS) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_GETIN_LOW_LHS) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_CLOSEDOOR_LHS) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_CLOSEDOOR_LOW_LHS) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SHUFFLE_RHS) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSHUFFLE_RHS) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_CLOSE_L) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_CLOSE) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_GETIN_L) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_GETIN) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_COACH_IN_L) + || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_COACH_IN_R)) { + notYet = true; + } + if (notYet) { + LineUpPedWithCar(LINE_UP_TO_CAR_START); + bChangedSeat = false; + return; } } - bool someoneExitsFromOurExitDoor = false; - bool someoneEntersFromOurExitDoor = false; - switch (optedDoorNode) { - case CAR_DOOR_RF: - if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) - someoneEntersFromOurExitDoor = true; - if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RF) - someoneExitsFromOurExitDoor = true; - break; - case CAR_DOOR_RR: - if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) - someoneEntersFromOurExitDoor = true; - if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RR) - someoneExitsFromOurExitDoor = true; - break; - case CAR_DOOR_LF: - if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) - someoneEntersFromOurExitDoor = true; - if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LF) - someoneExitsFromOurExitDoor = true; - break; - case CAR_DOOR_LR: - if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) - someoneEntersFromOurExitDoor = true; - if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LR) - someoneExitsFromOurExitDoor = true; - break; - default: - break; - } - if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) { - RestorePreviousObjective(); - return; - } - if (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) { - // Again, unused... - // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode); - bool thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil); - if (veh->IsOnItsSide()) { - teleportNeeded = true; - } else if (!thereIsRoom) { - bool trySideSeat = false; - CPed *pedOnSideSeat = nil; - switch (optedDoorNode) { - case CAR_DOOR_RF: - if (veh->pDriver || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) { - pedOnSideSeat = veh->pDriver; - trySideSeat = true; - } else - optedDoorNode = CAR_DOOR_LF; - - break; - case CAR_DOOR_RR: - if (veh->pPassengers[1] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) { - pedOnSideSeat = veh->pPassengers[1]; - trySideSeat = true; - } else - optedDoorNode = CAR_DOOR_LR; - - break; - case CAR_DOOR_LF: - if (veh->pPassengers[0] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) { - pedOnSideSeat = veh->pPassengers[0]; - trySideSeat = true; - } else - optedDoorNode = CAR_DOOR_RF; - - break; - case CAR_DOOR_LR: - if (veh->pPassengers[2] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) { - pedOnSideSeat = (CPed*)veh->pPassengers[2]; - trySideSeat = true; - } else - optedDoorNode = CAR_DOOR_RR; - - break; - default: - break; - } - if (trySideSeat) { - if (!pedOnSideSeat || !IsPlayer() && CharCreatedBy != MISSION_CHAR) - return; - - switch (optedDoorNode) { - case CAR_DOOR_RF: - optedDoorNode = CAR_DOOR_LF; - break; - case CAR_DOOR_RR: - optedDoorNode = CAR_DOOR_LR; - break; - case CAR_DOOR_LF: - optedDoorNode = CAR_DOOR_RF; - break; - case CAR_DOOR_LR: - optedDoorNode = CAR_DOOR_RR; - break; - default: - break; - } - } - // ... - // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode); - if (!veh->IsRoomForPedToLeaveCar(optedDoorNode, nil)) { - if (!IsPlayer() && CharCreatedBy != MISSION_CHAR) - return; + CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex()); + CMatrix newMat(m_pMyVehicle->GetMatrix()); + CVector seatPos; + if (m_pMyVehicle->pDriver == this) { + seatPos = vehModel->GetFrontSeatPosn(); + if (!m_pMyVehicle->IsBoat() && m_pMyVehicle->m_vehType != VEHICLE_TYPE_BIKE) + seatPos.x = -seatPos.x; - teleportNeeded = true; - } - } - if (m_nPedState == PED_FLEE_POS) { - m_nLastPedState = PED_FLEE_POS; - m_nPrevMoveState = PEDMOVE_RUN; - SetMoveState(PEDMOVE_SPRINT); + } else if (m_pMyVehicle->pPassengers[0] == this) { + seatPos = vehModel->GetFrontSeatPosn(); + } else if (m_pMyVehicle->pPassengers[1] == this) { + seatPos = vehModel->m_positions[CAR_POS_BACKSEAT]; + seatPos.x = -seatPos.x; + } else { + if (m_pMyVehicle->pPassengers[2] == this) { + seatPos = vehModel->m_positions[CAR_POS_BACKSEAT]; } else { - m_nLastPedState = PED_IDLE; - m_nPrevMoveState = PEDMOVE_STILL; - SetMoveState(PEDMOVE_STILL); + seatPos = vehModel->GetFrontSeatPosn(); } + } + newMat.GetPosition() += Multiply3x3(newMat, seatPos); + // Already done below (SetTranslate(0.0f, 0.0f, 0.0f)) + // tempMat.SetUnity(); - ReplaceWeaponWhenExitingVehicle(); - bUsesCollision = false; - m_pSeekTarget = veh; - m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); - m_vehEnterType = optedDoorNode; - m_nPedState = PED_EXIT_CAR; - if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL) - m_pVehicleAnim->blendDelta = -1000.0f; - SetMoveState(PEDMOVE_NONE); - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); - RemoveInCarAnims(); - veh->AutoPilot.m_nCruiseSpeed = 0; - if (teleportNeeded) { - PedSetOutCarCB(nil, this); - - // This is same code with CPedPlacement::FindZCoorForPed, except we start from z + 1.5 and also check vehicles. - float zForPed; - float startZ = GetPosition().z - 100.0f; - float foundColZ = -100.0f; - float foundColZ2 = -100.0f; - CColPoint foundCol; - CEntity* foundEnt; - - CVector vec = GetPosition(); - vec.z += 1.5f; - - if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil)) - foundColZ = foundCol.point.z; - - // Adjust coords and do a second test - vec.x += 0.1f; - vec.y += 0.1f; - - if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil)) - foundColZ2 = foundCol.point.z; - - zForPed = Max(foundColZ, foundColZ2); - - if (zForPed > -99.0f) - GetMatrix().GetPosition().z = FEET_OFFSET + zForPed; + // Rear seats on vans don't face to front, so rotate them HALFPI. + if (m_pMyVehicle->bIsVan) { + CMatrix tempMat; + if (m_pMyVehicle->pPassengers[1] == this) { + m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI; + tempMat.SetTranslate(0.0f, 0.0f, 0.0f); + tempMat.RotateZ(-HALFPI); + newMat = newMat * tempMat; + } else if (m_pMyVehicle->pPassengers[2] == this) { + m_fRotationCur = m_pMyVehicle->GetForward().Heading() + HALFPI; + tempMat.SetTranslate(0.0f, 0.0f, 0.0f); + tempMat.RotateZ(HALFPI); + newMat = newMat * tempMat; } else { - if (veh->GetUp().z > -0.8f) { - bool addDoorSmoke = false; - if (veh->GetModelIndex() == MI_YARDIE) - addDoorSmoke = true; - - switch (m_vehEnterType) { - case CAR_DOOR_RF: - if (veh->bIsBus) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L); - } else { - if (isLow) - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS); - else - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS); + m_fRotationCur = m_pMyVehicle->GetForward().Heading(); + } + } else { + m_fRotationCur = m_pMyVehicle->GetForward().Heading(); + } + GetMatrix() = newMat; +} - if (addDoorSmoke) - AddYardieDoorSmoke(veh, CAR_DOOR_RF); - } - break; - case CAR_DOOR_RR: - if (veh->bIsVan) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT); - } else if (isLow) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS); - } else { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS); - } - break; - case CAR_DOOR_LF: - if (veh->bIsBus) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L); - } else { - if (isLow) - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS); - else - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS); +void +CPed::LookForSexyPeds(void) +{ + if ((!IsPedInControl() && m_nPedState != PED_DRIVING) + || m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE) + return; - if (addDoorSmoke) - AddYardieDoorSmoke(veh, CAR_DOOR_LF); - } - break; - case CAR_DOOR_LR: - if (veh->bIsVan) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT_L); - } else if (isLow) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS); - } else { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS); - } - break; - default: - break; - } - if (!bBusJacked) { - switch (m_vehEnterType) { - case CAR_DOOR_RF: - veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RF; - break; - case CAR_DOOR_RR: - veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RR; - break; - case CAR_DOOR_LF: - veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF; - break; - case CAR_DOOR_LR: - veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LR; - break; - default: - break; - } - } - m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this); - } else { - if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS2); - } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { - m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS); + for (int i = 0; i < m_numNearPeds; i++) { + if (CanSeeEntity(m_nearPeds[i])) { + if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) { + CPed *nearPed = m_nearPeds[i]; + if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness) + && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) { + + SetLookFlag(nearPed, true); + m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000; + Say(SOUND_PED_CHAT_SEXY); + return; } - m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this); } } - bChangedSeat = false; - if (veh->bIsBus) - bRenderPedInCar = true; - - SetRadioStation(); - if (veh->pDriver == this) { - if (IsPlayer()) - veh->SetStatus(STATUS_PLAYER_DISABLED); - else - veh->SetStatus(STATUS_ABANDONED); - } } + m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000; } void -CPed::ScanForInterestingStuff(void) +CPed::LookForSexyCars(void) { - if (!IsPedInControl()) - return; + CEntity *vehicles[8]; + CVehicle *veh; + int foundVehId = 0; + int bestPriceYet = 0; + int16 lastVehicle; - if (m_objective != OBJECTIVE_NONE) + if (!IsPedInControl() && m_nPedState != PED_DRIVING) return; - if (CharCreatedBy == MISSION_CHAR) - return; + if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { + CWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - LookForSexyPeds(); - LookForSexyCars(); - if (LookForInterestingNodes()) - return; + for (int vehId = 0; vehId < lastVehicle; vehId++) { + veh = (CVehicle*)vehicles[vehId]; + if (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) { + foundVehId = vehId; + bestPriceYet = veh->pHandling->nMonetaryValue; + } + } + if (lastVehicle > 0 && bestPriceYet > 40000) + SetLookFlag(vehicles[foundVehId], false); - if (m_nPedType == PEDTYPE_CRIMINAL && m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) { - if (CGeneral::GetRandomNumber() % 100 < 10) { - int mostExpensiveVehAround = -1; - int bestMonetaryValue = 0; + m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000; + } +} - CVector pos = GetPosition(); - int16 lastVehicle; - CEntity *vehicles[8]; - CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); +bool +CPed::LookForInterestingNodes(void) +{ + CBaseModelInfo *model; + CPtrNode *ptrNode; + CVector effectDist; + C2dEffect *effect; + CMatrix *objMat; - for (int i = 0; i < lastVehicle; i++) { - CVehicle* veh = (CVehicle*)vehicles[i]; + if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_standardTimer) { + return false; + } + bool found = false; + uint8 randVal = CGeneral::GetRandomNumber() % 256; - if (veh->VehicleCreatedBy != MISSION_VEHICLE) { - if (veh->m_vecMoveSpeed.Magnitude() <= 0.1f && veh->IsVehicleNormal() - && veh->IsCar() && bestMonetaryValue < veh->pHandling->nMonetaryValue) { - mostExpensiveVehAround = i; - bestMonetaryValue = veh->pHandling->nMonetaryValue; - } - } - } - if (bestMonetaryValue > 2000 && mostExpensiveVehAround != -1 && vehicles[mostExpensiveVehAround]) { - SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, vehicles[mostExpensiveVehAround]); - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; - return; - } - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; - } else if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) { - CPed *charToMug = nil; - for (int i = 0; i < m_numNearPeds; ++i) { - CPed *nearPed = m_nearPeds[i]; + int minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST); + if (minX < 0) minX = 0; + int minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST); + if (minY < 0) minY = 0; + int maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST); +#ifdef FIX_BUGS + if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; +#else + if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; +#endif - if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f)) - break; + int maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST); +#ifdef FIX_BUGS + if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; +#else + if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; +#endif - if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE - || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1 - || nearPed->m_nPedType == PEDTYPE_PROSTITUTE) - && nearPed->CharCreatedBy != MISSION_CHAR - && nearPed->IsPedShootable() - && nearPed->m_objective != OBJECTIVE_MUG_CHAR) { - charToMug = nearPed; - break; + for (int curY = minY; curY <= maxY && !found; curY++) { + for (int curX = minX; curX <= maxX && !found; curX++) { + CSector *sector = CWorld::GetSector(curX, curY); + + for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) { + CVehicle *veh = (CVehicle*)ptrNode->item; + model = veh->GetModelInfo(); + if (model->GetNum2dEffects() != 0) { + for (int e = 0; e < model->GetNum2dEffects(); e++) { + effect = model->Get2dEffect(e); + if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { + objMat = &veh->GetMatrix(); + CVector effectPos = veh->GetMatrix() * effect->pos; + effectDist = effectPos - GetPosition(); + if (effectDist.MagnitudeSqr() < sq(8.0f)) { + found = true; + break; + } + } + } } } - if (charToMug) - SetObjective(OBJECTIVE_MUG_CHAR, charToMug); - - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; - } - } - - if (m_nPedState == PED_WANDER_PATH) { -#ifndef VC_PED_PORTS - if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { - - // += 2 is weird - for (int i = 0; i < m_numNearPeds; i += 2) { - if (m_nearPeds[i]->m_nPedState == PED_WANDER_PATH && WillChat(m_nearPeds[i])) { - if (CGeneral::GetRandomNumberInRange(0, 100) >= 100) - m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; - else { - if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) { - m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; - } else if (CanSeeEntity(m_nearPeds[i])) { - int time = CGeneral::GetRandomNumber() % 4000 + 10000; - SetChat(m_nearPeds[i], time); - m_nearPeds[i]->SetChat(this, time); - return; + for (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) { + CObject *obj = (CObject*)ptrNode->item; + model = CModelInfo::GetModelInfo(obj->GetModelIndex()); + if (model->GetNum2dEffects() != 0) { + for (int e = 0; e < model->GetNum2dEffects(); e++) { + effect = model->Get2dEffect(e); + if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { + objMat = &obj->GetMatrix(); + CVector effectPos = obj->GetMatrix() * effect->pos; + effectDist = effectPos - GetPosition(); + if (effectDist.MagnitudeSqr() < sq(8.0f)) { + found = true; + break; + } } } } } - } -#else - if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.5f) { - if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { - for (int i = 0; i < m_numNearPeds; i ++) { - if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) { - if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f - && CanSeeEntity(m_nearPeds[i]) - && m_nearPeds[i]->CanSeeEntity(this) - && WillChat(m_nearPeds[i])) { - - int time = CGeneral::GetRandomNumber() % 4000 + 10000; - SetChat(m_nearPeds[i], time); - m_nearPeds[i]->SetChat(this, time); - return; + for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) { + CBuilding *building = (CBuilding*)ptrNode->item; + model = CModelInfo::GetModelInfo(building->GetModelIndex()); + if (model->GetNum2dEffects() != 0) { + for (int e = 0; e < model->GetNum2dEffects(); e++) { + effect = model->Get2dEffect(e); + if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { + objMat = &building->GetMatrix(); + CVector effectPos = building->GetMatrix() * effect->pos; + effectDist = effectPos - GetPosition(); + if (effectDist.MagnitudeSqr() < sq(8.0f)) { + found = true; + break; + } } } } } - } else { - m_standardTimer = CTimer::GetTimeInMilliseconds() + 200; - } -#endif - } - - // Parts below aren't there in VC, they're in somewhere else. - if (!CGame::noProstitutes && m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy != MISSION_CHAR - && m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) { - - CVector pos = GetPosition(); - int16 lastVehicle; - CEntity* vehicles[8]; - CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - - for (int i = 0; i < lastVehicle; i++) { - CVehicle* veh = (CVehicle*)vehicles[i]; - - if (veh->IsVehicleNormal()) { - if (veh->IsCar()) { - if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil)) { - SetObjective(OBJECTIVE_SOLICIT_VEHICLE, veh); - Say(SOUND_PED_SOLICIT); - return; + for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) { + CBuilding *building = (CBuilding*)ptrNode->item; + model = CModelInfo::GetModelInfo(building->GetModelIndex()); + if (model->GetNum2dEffects() != 0) { + for (int e = 0; e < model->GetNum2dEffects(); e++) { + effect = model->Get2dEffect(e); + if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { + objMat = &building->GetMatrix(); + CVector effectPos = building->GetMatrix() * effect->pos; + effectDist = effectPos - GetPosition(); + if (effectDist.MagnitudeSqr() < sq(8.0f)) { + found = true; + break; + } + } } } } } } - if (m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) { - CVector pos = GetPosition(); - int16 lastVehicle; - CEntity* vehicles[8]; - CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - for (int i = 0; i < lastVehicle; i++) { - CVehicle* veh = (CVehicle*)vehicles[i]; + if (!found) + return false; - if (veh->GetModelIndex() == MI_MRWHOOP) { - if (veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED) { - if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f) { - SetObjective(OBJECTIVE_BUY_ICE_CREAM, veh); - return; - } - } - } - } + CVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir); + float angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f); + randVal = CGeneral::GetRandomNumber() % 256; + if (randVal <= m_randomSeed % 256) { + m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000; + SetLookFlag(angleToFace, true); + SetLookTimer(1000); + return false; + } + + CVector2D effectPos = *objMat * effect->pos; + switch (effect->attractor.type) { + case ATTRACTORTYPE_ICECREAM: + SetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace); + break; + case ATTRACTORTYPE_STARE: + SetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f, + CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500), + angleToFace); + break; + default: + return true; } + return true; } -uint32 -CPed::ScanForThreats(void) +void +CPed::SetWaitState(eWaitState state, void *time) { - int fearFlags = m_fearFlags; - CVector ourPos = GetPosition(); - float closestPedDist = 60.0f; - CVector2D explosionPos = GetPosition(); - if (fearFlags & PED_FLAG_EXPLOSION && CheckForExplosions(explosionPos)) { - m_eventOrThreat = explosionPos; - return PED_FLAG_EXPLOSION; - } - - CPed *shooter = nil; - if ((fearFlags & PED_FLAG_GUN) && (shooter = CheckForGunShots()) && (m_nPedType != shooter->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE)) { - if (!IsGangMember()) { - m_threatEntity = shooter; - m_threatEntity->RegisterReference((CEntity **) &m_threatEntity); - return PED_FLAG_GUN; - } + AnimationId waitAnim = NUM_ANIMS; + CAnimBlendAssociation *animAssoc; - if (CPedType::GetFlag(shooter->m_nPedType) & fearFlags) { - m_threatEntity = shooter; - m_threatEntity->RegisterReference((CEntity **) &m_threatEntity); - return CPedType::GetFlag(shooter->m_nPedType); - } - } + if (!IsPedInControl()) + return; - CPed *deadPed = nil; - if (fearFlags & PED_FLAG_DEADPEDS && CharCreatedBy != MISSION_CHAR - && (deadPed = CheckForDeadPeds()) != nil && (deadPed->GetPosition() - ourPos).MagnitudeSqr() < sq(20.0f)) { - m_pEventEntity = deadPed; - m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity); - return PED_FLAG_DEADPEDS; - } else { - uint32 flagsOfSomePed = 0; + if (state != m_nWaitState) + FinishedWaitCB(nil, this); - CPed *pedToFearFrom = nil; -#ifndef VC_PED_PORTS - for (int i = 0; i < m_numNearPeds; i++) { - if (CharCreatedBy != RANDOM_CHAR || m_nearPeds[i]->CharCreatedBy != MISSION_CHAR || m_nearPeds[i]->IsPlayer()) { - CPed *nearPed = m_nearPeds[i]; + switch (state) { + case WAITSTATE_TRAFFIC_LIGHTS: + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500; + SetMoveState(PEDMOVE_STILL); + break; + case WAITSTATE_CROSS_ROAD: + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 1000; + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f); + break; + case WAITSTATE_CROSS_ROAD_LOOK: + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 8.0f); - // BUG: WTF Rockstar?! Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance. - // Fixed at the bottom of the function. - flagsOfSomePed = CPedType::GetFlag(nearPed->m_nPedType); + if (time) + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; + else + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000,5000); - if (CPedType::GetFlag(nearPed->m_nPedType) & fearFlags) { - if (nearPed->m_fHealth > 0.0f && OurPedCanSeeThisOne(m_nearPeds[i])) { - // FIX: Taken from VC + break; + case WAITSTATE_LOOK_PED: + case WAITSTATE_LOOK_SHOP: + case WAITSTATE_LOOK_ACCIDENT: + case WAITSTATE_FACEOFF_GANG: + break; + case WAITSTATE_DOUBLEBACK: + m_headingRate = 0.0f; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3500; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f); #ifdef FIX_BUGS - float nearPedDistSqr = (nearPed->GetPosition() - ourPos).MagnitudeSqr2D(); -#else - float nearPedDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr(); + animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); #endif - if (sq(closestPedDist) > nearPedDistSqr) { - closestPedDist = Sqrt(nearPedDistSqr); - pedToFearFrom = m_nearPeds[i]; - } - } - } - } - } -#else - bool weSawOurEnemy = false; - bool weMaySeeOurEnemy = false; - float closestEnemyDist = 60.0f; - if ((CTimer::GetFrameCounter() + (uint8)m_randomSeed + 16) & 4) { - - for (int i = 0; i < m_numNearPeds; ++i) { - if (CharCreatedBy == RANDOM_CHAR && m_nearPeds[i]->CharCreatedBy == MISSION_CHAR && !m_nearPeds[i]->IsPlayer()) { - continue; - } - - // BUG: Explained at the same occurence of this bug above. Fixed at the bottom of the function. - flagsOfSomePed = CPedType::GetFlag(m_nearPeds[i]->m_nPedType); - - if (flagsOfSomePed & fearFlags) { - if (m_nearPeds[i]->m_fHealth > 0.0f) { - - // VC also has ability to include objects to line of sight check here (via last bit of flagsL) - if (OurPedCanSeeThisOne(m_nearPeds[i])) { - if (m_nearPeds[i]->m_nPedState == PED_ATTACK) { - if (m_nearPeds[i]->m_pedInObjective == this) { - - float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); - if (sq(closestEnemyDist) > enemyDistSqr) { - float enemyDist = Sqrt(enemyDistSqr); - weSawOurEnemy = true; - closestPedDist = enemyDist; - closestEnemyDist = enemyDist; - pedToFearFrom = m_nearPeds[i]; - } - } - } else { - float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); - if (sq(closestPedDist) > nearPedDistSqr && !weSawOurEnemy) { - closestPedDist = Sqrt(nearPedDistSqr); - pedToFearFrom = m_nearPeds[i]; - } - } - } else if (!weSawOurEnemy) { - CPed *nearPed = m_nearPeds[i]; - if (nearPed->m_nPedState == PED_ATTACK) { - CColPoint foundCol; - CEntity *foundEnt; - - // We don't see him yet but he's behind a ped, vehicle or object - // VC also has ability to include objects to line of sight check here (via last bit of flagsL) - if (!CWorld::ProcessLineOfSight(ourPos, nearPed->GetPosition(), foundCol, foundEnt, - true, false, false, false, false, false, false)) { + break; + case WAITSTATE_HITWALL: + m_headingRate = 2.0f; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 16.0f); + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->flags |= ASSOC_FADEOUTWHENDONE; + animAssoc->SetDeleteCallback(FinishedWaitCB, this); - if (nearPed->m_pedInObjective == this) { - float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); - if (sq(closestEnemyDist) > enemyDistSqr) { - float enemyDist = Sqrt(enemyDistSqr); - weMaySeeOurEnemy = true; - closestPedDist = enemyDist; - closestEnemyDist = enemyDist; - pedToFearFrom = m_nearPeds[i]; - } - } else if (!nearPed->GetWeapon()->IsTypeMelee() && !weMaySeeOurEnemy) { - float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D(); - if (sq(closestPedDist) > nearPedDistSqr) { - weMaySeeOurEnemy = true; - closestPedDist = Sqrt(nearPedDistSqr); - pedToFearFrom = m_nearPeds[i]; - } - } - } - } - } - } - } + if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) { + ClearObjective(); + RestorePreviousState(); + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000; } - } + break; + case WAITSTATE_TURN180: + m_headingRate = 0.0f; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TURN_180, 4.0f); + animAssoc->SetFinishCallback(FinishedWaitCB, this); + animAssoc->SetDeleteCallback(RestoreHeadingRateCB, this); + break; + case WAITSTATE_SURPRISE: + m_headingRate = 0.0f; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 4.0f); + animAssoc->SetFinishCallback(FinishedWaitCB, this); + break; + case WAITSTATE_STUCK: + SetMoveState(PEDMOVE_STILL); + SetMoveAnim(); + m_headingRate = 0.0f; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f); +#ifdef FIX_BUGS + animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); #endif - int16 lastVehicle; - CEntity* vehicles[8]; - CWorld::FindObjectsInRange(ourPos, 20.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - CVehicle* foundVeh = nil; - for (int i = 0; i < lastVehicle; i++) { - CVehicle* nearVeh = (CVehicle*)vehicles[i]; - CPed *driver = nearVeh->pDriver; - if (driver) { - - // BUG: Same bug as above. Fixed at the bottom of function. - flagsOfSomePed = CPedType::GetFlag(driver->m_nPedType); - if (CPedType::GetFlag(driver->m_nPedType) & fearFlags) { - if (driver->m_fHealth > 0.0f && OurPedCanSeeThisOne(nearVeh->pDriver)) { - // FIX: Taken from VC + if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) { + ClearObjective(); + RestorePreviousState(); + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000; + } + break; + case WAITSTATE_LOOK_ABOUT: + SetMoveState(PEDMOVE_STILL); + SetMoveAnim(); + m_headingRate = 0.0f; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f); #ifdef FIX_BUGS - float driverDistSqr = (driver->GetPosition() - ourPos).MagnitudeSqr2D(); -#else - float driverDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr(); + animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); #endif - if (sq(closestPedDist) > driverDistSqr) { - closestPedDist = Sqrt(driverDistSqr); - pedToFearFrom = nearVeh->pDriver; - } - } - } - } - } - m_threatEntity = pedToFearFrom; - if (m_threatEntity) - m_threatEntity->RegisterReference((CEntity **) &m_threatEntity); + break; + case WAITSTATE_PLAYANIM_COWER: + waitAnim = ANIM_HANDSCOWER; + case WAITSTATE_PLAYANIM_HANDSUP: + if (waitAnim == NUM_ANIMS) + waitAnim = ANIM_HANDSUP; + case WAITSTATE_PLAYANIM_HANDSCOWER: + if (waitAnim == NUM_ANIMS) + waitAnim = ANIM_HANDSCOWER; + m_headingRate = 0.0f; + if (time) + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; + else + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000; + + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f); + animAssoc->SetDeleteCallback(FinishedWaitCB, this); + break; + case WAITSTATE_PLAYANIM_DUCK: + waitAnim = ANIM_DUCK_DOWN; + case WAITSTATE_PLAYANIM_TAXI: + if (waitAnim == NUM_ANIMS) + waitAnim = ANIM_IDLE_TAXI; + case WAITSTATE_PLAYANIM_CHAT: + if (waitAnim == NUM_ANIMS) + waitAnim = ANIM_IDLE_CHAT; + if (time) + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; + else + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000; + + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f); + animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->SetDeleteCallback(FinishedWaitCB, this); + break; + case WAITSTATE_FINISH_FLEE: + SetMoveState(PEDMOVE_STILL); + SetMoveAnim(); + m_headingRate = 0.0f; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f); #ifdef FIX_BUGS - if (pedToFearFrom) - flagsOfSomePed = CPedType::GetFlag(((CPed*)m_threatEntity)->m_nPedType); - else - flagsOfSomePed = 0; + animAssoc->SetFinishCallback(RestoreHeadingRateCB, this); #endif - - return flagsOfSomePed; + break; + default: + m_nWaitState = WAITSTATE_FALSE; + RestoreHeadingRate(); + return; } + m_nWaitState = state; } void -CPed::SeekCar(void) +CPed::Wait(void) { - CVehicle *vehToSeek = m_carInObjective; - CVector dest(0.0f, 0.0f, 0.0f); - if (!vehToSeek) { - RestorePreviousState(); + AnimationId mustHaveAnim = NUM_ANIMS; + CAnimBlendAssociation *animAssoc; + CPed *pedWeLook; + + if (DyingOrDead()) { + m_nWaitState = WAITSTATE_FALSE; + RestoreHeadingRate(); return; } - if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) { - if (m_vehEnterType && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { - if (IsRoomToBeCarJacked()) { - dest = GetPositionToOpenCarDoor(vehToSeek, m_vehEnterType); - } else if (m_nPedType == PEDTYPE_COP) { - dest = GetPositionToOpenCarDoor(vehToSeek, CAR_DOOR_RF); - } else { - SetMoveState(PEDMOVE_STILL); - } - } else - GetNearestDoor(vehToSeek, dest); - } else { - if (m_hitRecoverTimer > CTimer::GetTimeInMilliseconds()) { - SetMoveState(PEDMOVE_STILL); - return; - } - if (vehToSeek->GetModelIndex() == MI_COACH) { - GetNearestDoor(vehToSeek, dest); - } else { - if (vehToSeek->IsTrain()) { - if (vehToSeek->GetStatus() != STATUS_TRAIN_NOT_MOVING) { - RestorePreviousObjective(); - RestorePreviousState(); - return; - } - if (!GetNearestTrainDoor(vehToSeek, dest)) { - RestorePreviousObjective(); - RestorePreviousState(); - return; - } - } else { - if (!GetNearestPassengerDoor(vehToSeek, dest)) { - if (vehToSeek->m_nNumPassengers == vehToSeek->m_nNumMaxPassengers) { - RestorePreviousObjective(); - RestorePreviousState(); - } else { - SetMoveState(PEDMOVE_STILL); - } - bVehEnterDoorIsBlocked = true; - return; - } - bVehEnterDoorIsBlocked = false; - } - } - } + switch (m_nWaitState) { - if (dest.x == 0.0f && dest.y == 0.0f) { -#ifdef FIX_BUGS - if ((!IsPlayer() && CharCreatedBy != MISSION_CHAR) || vehToSeek->VehicleCreatedBy != MISSION_VEHICLE || vehToSeek->pDriver || !vehToSeek->CanPedOpenLocks(this)) { -#else - if ((!IsPlayer() && CharCreatedBy != MISSION_CHAR) || vehToSeek->VehicleCreatedBy != MISSION_VEHICLE || vehToSeek->pDriver) { -#endif - RestorePreviousState(); - if (IsPlayer()) { - ClearObjective(); - } else if (CharCreatedBy == RANDOM_CHAR) { - m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000; + case WAITSTATE_TRAFFIC_LIGHTS: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) { + m_nWaitState = WAITSTATE_FALSE; + SetMoveState(PEDMOVE_WALK); + } } - SetMoveState(PEDMOVE_STILL); - TheCamera.ClearPlayerWeaponMode(); - CCarCtrl::RemoveFromInterestingVehicleList(vehToSeek); - return; - } - dest = vehToSeek->GetPosition(); - if (bCollidedWithMyVehicle) { - WarpPedIntoCar(m_pMyVehicle); - return; - } - } - bool foundBetterPosToSeek = PossiblyFindBetterPosToSeekCar(&dest, vehToSeek); - m_vecSeekPos = dest; - float distToDestSqr = (m_vecSeekPos - GetPosition()).MagnitudeSqr(); -#ifndef VC_PED_PORTS - if (bIsRunning) - SetMoveState(PEDMOVE_RUN); -#else - if (bIsRunning || - vehToSeek->pDriver && distToDestSqr > sq(2.0f) && (Abs(vehToSeek->m_vecMoveSpeed.x) > 0.01f || Abs(vehToSeek->m_vecMoveSpeed.y) > 0.01f)) - SetMoveState(PEDMOVE_RUN); -#endif - else if (distToDestSqr < sq(2.0f)) - SetMoveState(PEDMOVE_WALK); - - if (distToDestSqr >= 1.0f) - bCanPedEnterSeekedCar = false; - else if (2.0f * vehToSeek->GetColModel()->boundingBox.max.x > distToDestSqr) - bCanPedEnterSeekedCar = true; - - if (vehToSeek->m_nGettingInFlags & GetCarDoorFlag(m_vehEnterType)) - bVehEnterDoorIsBlocked = true; - else - bVehEnterDoorIsBlocked = false; + break; - // Arrived to the car - if (Seek()) { - if (!foundBetterPosToSeek) { - if (1.5f + GetPosition().z > dest.z && GetPosition().z - 0.5f < dest.z) { - if (vehToSeek->IsTrain()) { - SetEnterTrain(vehToSeek, m_vehEnterType); - } else { - m_fRotationCur = m_fRotationDest; - if (!bVehEnterDoorIsBlocked) { - vehToSeek->SetIsStatic(false); - if (m_objective == OBJECTIVE_SOLICIT_VEHICLE) { - SetSolicit(1000); - } else if (m_objective == OBJECTIVE_BUY_ICE_CREAM) { - SetBuyIceCream(); - } else if (vehToSeek->m_nNumGettingIn < vehToSeek->m_nNumMaxPassengers + 1 - && vehToSeek->CanPedEnterCar()) { + case WAITSTATE_CROSS_ROAD: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer) + m_nWaitState = WAITSTATE_FALSE; + else + SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil); - switch (vehToSeek->GetStatus()) { - case STATUS_PLAYER: - case STATUS_SIMPLE: - case STATUS_PHYSICS: - case STATUS_PLAYER_DISABLED: - if (!vehToSeek->bIsBus && (!m_leader || m_leader != vehToSeek->pDriver) && - (m_vehEnterType == CAR_DOOR_LF && vehToSeek->pDriver || m_vehEnterType == CAR_DOOR_RF && vehToSeek->pPassengers[0] || m_vehEnterType == CAR_DOOR_LR && vehToSeek->pPassengers[1] || m_vehEnterType == CAR_DOOR_RR && vehToSeek->pPassengers[2])) { - SetCarJack(vehToSeek); - if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && m_vehEnterType != CAR_DOOR_LF) - vehToSeek->pDriver->bFleeAfterExitingCar = true; - } else { - SetEnterCar(vehToSeek, m_vehEnterType); - } - break; - case STATUS_ABANDONED: - if (m_vehEnterType == CAR_DOOR_RF && vehToSeek->pPassengers[0]) { - if (vehToSeek->pPassengers[0]->bDontDragMeOutCar) { - if (IsPlayer()) - SetEnterCar(vehToSeek, m_vehEnterType); - } else { - SetCarJack(vehToSeek); - } - } else { - SetEnterCar(vehToSeek, m_vehEnterType); - } - break; - case STATUS_WRECKED: - SetIdle(); - break; - default: - return; - } - } else { - RestorePreviousState(); - } - } else { - SetMoveState(PEDMOVE_STILL); - } + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + } + break; + + case WAITSTATE_CROSS_ROAD_LOOK: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + m_nWaitState = WAITSTATE_FALSE; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; } } - } - } -} + break; -void -CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) -{ - if (m_nPedState == PED_DEAD) { - if (CGame::nastyGame) { - if (hitLevel == HITLEVEL_GROUND) { - CAnimBlendAssociation *floorHitAssoc; - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) { - floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); - } else { - floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f); - } - if (floorHitAssoc) { - floorHitAssoc->SetCurrentTime(0.0f); - floorHitAssoc->SetRun(); - floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + case WAITSTATE_DOUBLEBACK: + if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { + uint32 timeLeft = m_nWaitTimer - CTimer::GetTimeInMilliseconds(); + if (timeLeft < 2500 && timeLeft > 2000) { + m_nWaitTimer -= 500; + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); } + } else { + m_nWaitState = WAITSTATE_FALSE; + SetMoveState(PEDMOVE_WALK); } - if (CGame::nastyGame) { - CVector headPos = GetNodePosition(PED_HEAD); - for(int i = 0; i < 4; ++i) { - CVector bloodDir(0.0f, 0.0f, 0.1f); - CVector bloodPos = headPos - 0.2f * GetForward(); - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0); + break; + + case WAITSTATE_HITWALL: + if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { + if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) { + m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; } + } else { + m_nWaitState = WAITSTATE_FALSE; } - } - } else if (m_nPedState == PED_FALL) { - if (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) { - CAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL) ? - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f) : - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); - if (floorHitAssoc) { - floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; - floorHitAssoc->flags |= ASSOC_DELETEFADEDOUT; + break; + + case WAITSTATE_TURN180: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + m_nWaitState = WAITSTATE_FALSE; + SetMoveState(PEDMOVE_WALK); + m_fRotationCur = m_fRotationCur + PI; + if (m_nPedState == PED_INVESTIGATE) + ClearInvestigateEvent(); } - } - } else if (IsPedInControl()) { - if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f) - || (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) { -#ifndef VC_PED_PORTS - if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) { - if (IsPlayer() || CGeneral::GetRandomNumber() & 3) { -#else - if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) { - if (IsPlayer() || CGeneral::GetRandomNumber() & 1) { -#endif - AnimationId shotAnim; - switch (direction) { - case 1: - shotAnim = ANIM_SHOT_LEFT_PARTIAL; - break; - case 2: - shotAnim = ANIM_SHOT_BACK_PARTIAL; - break; - case 3: - shotAnim = ANIM_SHOT_RIGHT_PARTIAL; - break; - default: - shotAnim = ANIM_SHOT_FRONT_PARTIAL; - break; - } - CAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim); - if (!shotAssoc || shotAssoc->blendDelta < 0.0f) - shotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f); - shotAssoc->SetCurrentTime(0.0f); - shotAssoc->SetRun(); - shotAssoc->flags |= ASSOC_FADEOUTWHENDONE; + if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) { + m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; + } + break; + + case WAITSTATE_SURPRISE: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HIT_WALL)) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); + animAssoc->SetFinishCallback(FinishedWaitCB, this); + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; } else { - int time = CGeneral::GetRandomNumberInRange(1000, 3000); - SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time); - } - } else { -#ifndef VC_PED_PORTS - switch (direction) { - case 1: - SetFall(500, ANIM_KO_SPIN_R, false); - break; - case 2: - SetFall(500, ANIM_KO_SKID_BACK, false); - break; - case 3: - SetFall(500, ANIM_KO_SPIN_L, false); - break; - default: - SetFall(500, ANIM_KO_SHOT_STOM, false); - break; - } -#else - bool fall = true; - AnimationId hitAnim; - switch (direction) { - case 1: - hitAnim = ANIM_KO_SPIN_R; - break; - case 2: - if (CGeneral::GetRandomNumber() & 1) { - fall = false; - hitAnim = ANIM_HIT_BACK; - } else { - hitAnim = ANIM_KO_SKID_BACK; - } - break; - case 3: - hitAnim = ANIM_KO_SPIN_L; - break; - default: - if (hitLevel == HITLEVEL_LOW) { - hitAnim = ANIM_KO_SHOT_STOM; - } else if (CGeneral::GetRandomNumber() & 1) { - fall = false; - hitAnim = ANIM_HIT_WALK; - } else if (CGeneral::GetRandomNumber() & 1) { - fall = false; - hitAnim = ANIM_HIT_HEAD; - } else { - hitAnim = ANIM_KO_SHOT_FACE; - } - break; + m_nWaitState = WAITSTATE_FALSE; } - if (fall) { - SetFall(500, hitAnim, false); + } + break; + + case WAITSTATE_STUCK: + if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) + break; + + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); + + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_TURN_180); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); + + if (animAssoc) { + if (animAssoc->IsPartial()) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; } else { - CAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim); - if (!hitAssoc || hitAssoc->blendDelta < 0.0f) - hitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f); + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); + } - hitAssoc->SetCurrentTime(0.0f); - hitAssoc->SetRun(); - hitAssoc->flags |= ASSOC_FADEOUTWHENDONE; + if (animAssoc->animId == ANIM_TURN_180) { + m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur); + m_nWaitState = WAITSTATE_FALSE; + SetMoveState(PEDMOVE_WALK); + m_nStoredMoveState = PEDMOVE_NONE; + m_panicCounter = 0; + return; } -#endif } - Say(SOUND_PED_DEFEND); - } else { - Say(SOUND_PED_DEFEND); - switch (hitLevel) { - case HITLEVEL_GROUND: - m_curFightMove = FIGHTMOVE_HITONFLOOR; + + AnimationId animToPlay; + + switch (CGeneral::GetRandomNumber() & 3) { + case 0: + animToPlay = ANIM_ROAD_CROSS; break; - case HITLEVEL_LOW: -#ifndef VC_PED_PORTS - if (direction == 2) { - SetFall(1000, ANIM_KO_SKID_BACK, false); - return; - } -#else - if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) { - SetFall(1000, ANIM_KO_SKID_BACK, false); - return; - } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) { - SetFall(1000, ANIM_KO_SHOT_STOM, false); - return; - } -#endif - m_curFightMove = FIGHTMOVE_HITBODY; + case 1: + animToPlay = ANIM_IDLE_TIRED; break; - case HITLEVEL_HIGH: - switch (direction) { - case 1: - m_curFightMove = FIGHTMOVE_HITLEFT; - break; - case 2: - m_curFightMove = FIGHTMOVE_HITBACK; - break; - case 3: - m_curFightMove = FIGHTMOVE_HITRIGHT; - break; - default: - if (unk <= 5) - m_curFightMove = FIGHTMOVE_HITHEAD; - else - m_curFightMove = FIGHTMOVE_HITBIGSTEP; - break; - } + case 2: + animToPlay = ANIM_XPRESS_SCRATCH; + break; + case 3: + animToPlay = ANIM_TURN_180; break; default: - switch (direction) { - case 1: - m_curFightMove = FIGHTMOVE_HITLEFT; - break; - case 2: - m_curFightMove = FIGHTMOVE_HITBACK; - break; - case 3: - m_curFightMove = FIGHTMOVE_HITRIGHT; - break; - default: - if (unk <= 5) - m_curFightMove = FIGHTMOVE_HITCHEST; - else - m_curFightMove = FIGHTMOVE_HITBIGSTEP; - break; - } break; } - if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f)) - m_curFightMove = FIGHTMOVE_HITONFLOOR; - - if (m_nPedState == PED_FIGHT) { - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); - moveAssoc->SetCurrentTime(0.0f); - moveAssoc->SetFinishCallback(FinishFightMoveCB, this); - if (IsPlayer()) - moveAssoc->speed = 1.3f; - - m_takeAStepAfterAttack = 0; - m_fightButtonPressure = 0; - } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) { - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); - moveAssoc->SetCurrentTime(0.0f); - moveAssoc->speed = 1.3f; - } else { - if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK) - SetStoredState(); - if (m_nWaitState != WAITSTATE_FALSE) { - m_nWaitState = WAITSTATE_FALSE; - RestoreHeadingRate(); - } - m_nPedState = PED_FIGHT; - m_fightButtonPressure = 0; - RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); - CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); - if (walkStartAssoc) { - walkStartAssoc->flags |= ASSOC_DELETEFADEDOUT; - walkStartAssoc->blendDelta = -1000.0f; - } - CAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); - if (!walkStopAssoc) - walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); - if (walkStopAssoc) { - walkStopAssoc->flags |= ASSOC_DELETEFADEDOUT; - walkStopAssoc->blendDelta = -1000.0f; - RestoreHeadingRate(); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); + + if (animToPlay == ANIM_TURN_180) + animAssoc->SetFinishCallback(FinishedWaitCB, this); + + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000); + break; + + case WAITSTATE_LOOK_ABOUT: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + m_nWaitState = WAITSTATE_FALSE; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; } - SetMoveState(PEDMOVE_NONE); - m_nStoredMoveState = PEDMOVE_NONE; - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f; - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); - moveAssoc->SetFinishCallback(FinishFightMoveCB, this); - m_fightState = FIGHTSTATE_NO_MOVE; - m_takeAStepAfterAttack = false; - bIsAttacking = true; } - } - } -} + break; -void -CPed::UpdateFromLeader(void) -{ - if (CTimer::GetTimeInMilliseconds() <= m_objectiveTimer) - return; + case WAITSTATE_PLAYANIM_HANDSUP: + mustHaveAnim = ANIM_HANDSUP; + + case WAITSTATE_PLAYANIM_HANDSCOWER: + if (mustHaveAnim == NUM_ANIMS) + mustHaveAnim = ANIM_HANDSCOWER; - if (!m_leader) - return; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim); + pedWeLook = (CPed*) m_pLookTarget; - CVector leaderDist; - if (m_leader->InVehicle()) - leaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition(); - else - leaderDist = m_leader->GetPosition() - GetPosition(); + if ((!m_pLookTarget || !m_pLookTarget->IsPed() || pedWeLook->m_pPointGunAt) + && m_nPedState != PED_FLEE_ENTITY + && m_nPedState != PED_ATTACK + && CTimer::GetTimeInMilliseconds() <= m_nWaitTimer + && animAssoc) { - if (leaderDist.Magnitude() > 30.0f) { - if (IsPedInControl()) { - SetObjective(OBJECTIVE_NONE); - SetIdle(); - SetMoveState(PEDMOVE_STILL); - } - SetLeader(nil); - return; - } + TurnBody(); + } else { + m_nWaitState = WAITSTATE_FALSE; + m_nWaitTimer = 0; + if (m_pLookTarget && m_pLookTarget->IsPed()) { + + if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_ATTACK) { + + if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) { + + if (GetWeapon()->IsTypeMelee()) { +#ifdef VC_PED_PORTS + if(m_pedStats->m_flags & STAT_GUN_PANIC) { +#endif + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); + if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { + + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + } + if (m_nMoveState != PEDMOVE_RUN) + SetMoveState(PEDMOVE_WALK); + + if (m_nPedType != PEDTYPE_COP) { + ProcessObjective(); + SetMoveState(PEDMOVE_WALK); + } +#ifdef VC_PED_PORTS + } else { + SetObjective(OBJECTIVE_NONE); + SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); + } +#endif + } else { + SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget); + SetObjectiveTimer(20000); + } + } else { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); + if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) + { + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + } + SetMoveState(PEDMOVE_RUN); + Say(SOUND_PED_FLEE_RUN); + } + } + } + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim); + if (animAssoc) { + animAssoc->blendDelta = -4.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + } + break; + case WAITSTATE_PLAYANIM_COWER: + mustHaveAnim = ANIM_HANDSCOWER; + + case WAITSTATE_PLAYANIM_DUCK: + if (mustHaveAnim == NUM_ANIMS) + mustHaveAnim = ANIM_DUCK_DOWN; - if (IsPedInControl()) { - if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) - WarpPedToNearLeaderOffScreen(); + case WAITSTATE_PLAYANIM_TAXI: + if (mustHaveAnim == NUM_ANIMS) + mustHaveAnim = ANIM_IDLE_TAXI; - if (m_leader->m_nPedState == PED_DEAD) { - SetLeader(nil); - SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); - return; - } - if (!m_leader->bInVehicle) { - if (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { - if (bInVehicle) { - if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && m_objective != OBJECTIVE_LEAVE_CAR) - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + case WAITSTATE_PLAYANIM_CHAT: + if (mustHaveAnim == NUM_ANIMS) + mustHaveAnim = ANIM_IDLE_CHAT; - return; - } - if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { - RestorePreviousObjective(); - RestorePreviousState(); + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim); + if (animAssoc) { + animAssoc->blendDelta = -4.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; } + m_nWaitState = WAITSTATE_FALSE; } - if (m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy == RANDOM_CHAR) { - SetLeader(nil); - return; - } - } - if (!bInVehicle && m_leader->bInVehicle && m_leader->m_nPedState == PED_DRIVING) { - if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { - if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers) - SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle); - } - } else if (m_leader->m_objective == OBJECTIVE_NONE || (m_leader->IsPlayer() && m_leader->m_objective == OBJECTIVE_WAIT_ON_FOOT) - || m_objective == m_leader->m_objective) { - - if (m_leader->m_nPedState == PED_ATTACK) { - CEntity *lookTargetOfLeader = m_leader->m_pLookTarget; - if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT - && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) { - - SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader); - SetObjectiveTimer(8000); - SetLookFlag(m_leader->m_pLookTarget, false); - SetLookTimer(500); - } - } else { - if (IsPedInControl() && m_nPedState != PED_ATTACK) { -#ifndef VC_PED_PORTS - SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); - SetObjectiveTimer(0); -#else - if (m_leader->m_objective == OBJECTIVE_NONE && m_objective == OBJECTIVE_NONE - && m_leader->m_nPedState == PED_CHAT && m_nPedState == PED_CHAT) { - - SetObjective(OBJECTIVE_NONE); - } else { - SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); - SetObjectiveTimer(0); - } -#endif - } - if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) { - if (ScanForThreats() && m_threatEntity) { - m_pLookTarget = m_threatEntity; +#ifdef VC_PED_PORTS + else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) { + if (m_pedInObjective) { + if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { + + // VC also calls CleanUpOldReference here for old LookTarget. + m_pLookTarget = m_pedInObjective; m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); TurnBody(); - if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) { - m_pPointGunAt = m_threatEntity; - if (m_threatEntity) - m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt); - SetAttack(m_threatEntity); - } } } } - } else { - switch (m_leader->m_objective) { - case OBJECTIVE_WAIT_ON_FOOT: - case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: - case OBJECTIVE_WAIT_IN_CAR: - case OBJECTIVE_FOLLOW_ROUTE: - SetObjective(m_leader->m_objective); - m_objectiveTimer = m_leader->m_objectiveTimer; - break; - case OBJECTIVE_GUARD_SPOT: - SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx); - m_objectiveTimer = m_leader->m_objectiveTimer; - break; - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - if (m_leader->m_pedInObjective) { - SetObjective(m_leader->m_objective, m_leader->m_pedInObjective); - m_objectiveTimer = m_leader->m_objectiveTimer; - } - break; - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - if (m_leader->m_carInObjective) { - SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective); - return; - } - break; - case OBJECTIVE_GUARD_ATTACK: - return; - case OBJECTIVE_HAIL_TAXI: - m_leader = nil; - SetObjective(OBJECTIVE_NONE); - break; - default: - SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); - SetObjectiveTimer(0); - break; - } - } - } else if (bInVehicle) { - if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) { - - switch (m_leader->m_objective) { - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - if (m_pMyVehicle == m_leader->m_pMyVehicle || m_pMyVehicle == m_leader->m_carInObjective) - break; - - // fall through - default: - if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_CAR) { -#ifdef VC_PED_PORTS - m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250; #endif - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } + break; - break; + case WAITSTATE_FINISH_FLEE: + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); + if (animAssoc) { + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); + int timer = 2000; + m_nWaitState = WAITSTATE_FALSE; + SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer); + } + } else { + m_nWaitState = WAITSTATE_FALSE; } - } + break; + default: + break; } + + if(!m_nWaitState) + RestoreHeadingRate(); } void -CPed::UpdatePosition(void) +CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg) { - if (CReplay::IsPlayingBack() || !bIsStanding) - return; + CPed *ped = (CPed*)arg; - CVector2D velocityChange; + ped->m_nWaitTimer = 0; + ped->RestoreHeadingRate(); + ped->Wait(); +} - SetHeading(m_fRotationCur); - if (m_pCurrentPhysSurface) { - CVector2D velocityOfSurface; - if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) { +void +CPed::RestoreHeadingRate(void) +{ + m_headingRate = m_pedStats->m_headingChangeRate; +} - // It seems R* didn't like m_vecOffsetFromPhysSurface for boats - CVector offsetToSurface = GetPosition() - m_pCurrentPhysSurface->GetPosition(); - offsetToSurface.z -= FEET_OFFSET; +void +CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) +{ + ((CPed*)arg)->m_headingRate = ((CPed*)arg)->m_pedStats->m_headingChangeRate; +} - CVector surfaceMoveVelocity = m_pCurrentPhysSurface->m_vecMoveSpeed; - CVector surfaceTurnVelocity = CrossProduct(m_pCurrentPhysSurface->m_vecTurnSpeed, offsetToSurface); +void +CPed::FlagToDestroyWhenNextProcessed(void) +{ + bRemoveFromWorld = true; + if (!InVehicle()) + return; + if (m_pMyVehicle->pDriver == this){ + m_pMyVehicle->pDriver = nil; + if (IsPlayer() && m_pMyVehicle->GetStatus() != STATUS_WRECKED) + m_pMyVehicle->SetStatus(STATUS_ABANDONED); + }else{ + m_pMyVehicle->RemovePassenger(this); + } + bInVehicle = false; + m_pMyVehicle = nil; + if (CharCreatedBy == MISSION_CHAR) + m_nPedState = PED_DEAD; + else + m_nPedState = PED_NONE; + m_pVehicleAnim = nil; +} - // Also we use that weird formula instead of friction if it's boat - float slideMult = -m_pCurrentPhysSurface->m_vecTurnSpeed.MagnitudeSqr(); - velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity); - m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z); +void +CPed::SetSolicit(uint32 time) +{ + if (m_nPedState == PED_SOLICIT || !IsPedInControl() || !m_carInObjective) + return; + + if (CharCreatedBy != MISSION_CHAR && m_carInObjective->m_nNumGettingIn == 0 + && CTimer::GetTimeInMilliseconds() < m_objectiveTimer) { + if (m_vehEnterType == CAR_DOOR_LF) { + m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI; } else { - velocityOfSurface = m_pCurrentPhysSurface->GetSpeed(m_vecOffsetFromPhysSurface); + m_fRotationDest = m_carInObjective->GetForward().Heading() + HALFPI; } - // Reminder: m_moved is displacement from walking/running. - velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed; - m_fRotationCur += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); - m_fRotationDest += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); - } else if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF && (m_vecDamageNormal.x != 0.0f || m_vecDamageNormal.y != 0.0f)) { - // Ped got damaged by steep slope - m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f); - // some kind of - CVector2D reactionForce = m_vecDamageNormal; - reactionForce.Normalise(); - velocityChange = 0.02f * reactionForce + m_moved; + if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) { + m_standardTimer = CTimer::GetTimeInMilliseconds() + time; - float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange); - // they're in same direction - if (reactionAndVelocityDotProd < 0.0f) { - velocityChange -= reactionAndVelocityDotProd * reactionForce; - } - } else { - velocityChange = m_moved - m_vecMoveSpeed; - } - - // Take time step into account - if (m_pCurrentPhysSurface) { - float speedChange = velocityChange.Magnitude(); - float changeMult = speedChange; - if (m_nPedState == PED_DIE && m_pCurrentPhysSurface->IsVehicle()) { - changeMult = 0.002f * CTimer::GetTimeStep(); - } else if (!(m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())) { - changeMult = 0.01f * CTimer::GetTimeStep(); - } + if(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_HOOKERTALK, 4.0f); - if (speedChange > changeMult) { - velocityChange = velocityChange * (changeMult / speedChange); + m_nPedState = PED_SOLICIT; } } - m_vecMoveSpeed.x += velocityChange.x; - m_vecMoveSpeed.y += velocityChange.y; } void -CPed::SetPedPositionInCar(void) +CPed::Solicit(void) { - if (CReplay::IsPlayingBack()) - return; - - if (bChangedSeat) { - bool notYet = false; - if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_GETIN_LHS) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_GETIN_LOW_LHS) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_CLOSEDOOR_LHS) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_CLOSEDOOR_LOW_LHS) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SHUFFLE_RHS) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSHUFFLE_RHS) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_CLOSE_L) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_CLOSE) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_GETIN_L) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_VAN_GETIN) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_COACH_IN_L) - || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_COACH_IN_R)) { - notYet = true; - } - if (notYet) { - LineUpPedWithCar(LINE_UP_TO_CAR_START); - bChangedSeat = false; - return; - } - } - CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex()); - CMatrix newMat(m_pMyVehicle->GetMatrix()); - CVector seatPos; - if (m_pMyVehicle->pDriver == this) { - seatPos = vehModel->GetFrontSeatPosn(); - if (!m_pMyVehicle->IsBoat() && m_pMyVehicle->m_vehType != VEHICLE_TYPE_BIKE) - seatPos.x = -seatPos.x; - - } else if (m_pMyVehicle->pPassengers[0] == this) { - seatPos = vehModel->GetFrontSeatPosn(); - } else if (m_pMyVehicle->pPassengers[1] == this) { - seatPos = vehModel->m_positions[CAR_POS_BACKSEAT]; - seatPos.x = -seatPos.x; - } else { - if (m_pMyVehicle->pPassengers[2] == this) { - seatPos = vehModel->m_positions[CAR_POS_BACKSEAT]; - } else { - seatPos = vehModel->GetFrontSeatPosn(); - } - } - newMat.GetPosition() += Multiply3x3(newMat, seatPos); - // Already done below (SetTranslate(0.0f, 0.0f, 0.0f)) - // tempMat.SetUnity(); + if (m_standardTimer >= CTimer::GetTimeInMilliseconds() && m_carInObjective) { + CVector doorPos = GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType, 0.0f); + SetMoveState(PEDMOVE_STILL); - // Rear seats on vans don't face to front, so rotate them HALFPI. - if (m_pMyVehicle->bIsVan) { - CMatrix tempMat; - if (m_pMyVehicle->pPassengers[1] == this) { - m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI; - tempMat.SetTranslate(0.0f, 0.0f, 0.0f); - tempMat.RotateZ(-HALFPI); - newMat = newMat * tempMat; - } else if (m_pMyVehicle->pPassengers[2] == this) { - m_fRotationCur = m_pMyVehicle->GetForward().Heading() + HALFPI; - tempMat.SetTranslate(0.0f, 0.0f, 0.0f); - tempMat.RotateZ(HALFPI); - newMat = newMat * tempMat; - } else { - m_fRotationCur = m_pMyVehicle->GetForward().Heading(); + // Game uses GetAngleBetweenPoints and converts it to radian + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + doorPos.x, doorPos.y, + GetPosition().x, GetPosition().y); + + if (m_fRotationDest < 0.0f) { + m_fRotationDest = m_fRotationDest + TWOPI; + } else if (m_fRotationDest > TWOPI) { + m_fRotationDest = m_fRotationDest - TWOPI; + } + + if ((GetPosition() - doorPos).MagnitudeSqr() <= 1.0f) + return; + CAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_HOOKERTALK); + if (talkAssoc) { + talkAssoc->blendDelta = -1000.0f; + talkAssoc->flags |= ASSOC_DELETEFADEDOUT; } + RestorePreviousState(); + RestorePreviousObjective(); + SetObjectiveTimer(10000); + } else if (!m_carInObjective) { + RestorePreviousState(); + RestorePreviousObjective(); + SetObjectiveTimer(10000); + } else if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney <= 100) { + m_carInObjective = nil; } else { - m_fRotationCur = m_pMyVehicle->GetForward().Heading(); + m_pVehicleAnim = nil; + SetLeader(m_carInObjective->pDriver); } - GetMatrix() = newMat; -} - -static RwObject* -CloneAtomicToFrameCB(RwObject *frame, void *data) -{ - RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame); - RpAtomicSetFrame(newAtomic, (RwFrame*)data); - RpClumpAddAtomic(flyingClumpTemp, newAtomic); - CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil); - return frame; } -static RwFrame* -RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data) +void +CPed::SetBuyIceCream(void) { - RwFrame *newFrame = RwFrameCreate(); - RwFrameAddChild((RwFrame*)data, newFrame); - RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE); - RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame); - RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame); - return newFrame; -} + if (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl()) + return; -CObject* -CPed::SpawnFlyingComponent(int pedNode, int8 direction) -{ - if (CObject::nNoTempObjects >= NUMTEMPOBJECTS) - return nil; + if (!m_carInObjective) + return; -#ifdef PED_SKIN - assert(!IsClumpSkinned(GetClump())); -#endif +#ifdef FIX_ICECREAM - CObject *obj = new CObject(); - if (!obj) - return nil; - - RwFrame *frame = RwFrameCreate(); - RpClump *clump = RpClumpCreate(); - RpClumpSetFrame(clump, frame); - RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame); - *RwFrameGetMatrix(frame) = *matrix; - - flyingClumpTemp = clump; - RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame); - RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame); - flyingClumpTemp = nil; - switch (pedNode) { - case PED_HEAD: - // So popping head would have wheel collision. They disabled it anyway - obj->SetModelIndexNoCreate(MI_CAR_WHEEL); - break; - case PED_UPPERARML: - case PED_UPPERARMR: - obj->SetModelIndexNoCreate(MI_BODYPARTB); - obj->SetCenterOfMass(0.25f, 0.0f, 0.0f); - break; - case PED_UPPERLEGL: - case PED_UPPERLEGR: - obj->SetModelIndexNoCreate(MI_BODYPARTA); - obj->SetCenterOfMass(0.4f, 0.0f, 0.0f); - break; - default: - break; + // Simulating BuyIceCream + CPed* driver = m_carInObjective->pDriver; + if (driver) { + m_nPedState = PED_BUY_ICECREAM; + bFindNewNodeAfterStateRestore = true; + SetObjectiveTimer(8000); + SetChat(driver, 8000); + driver->SetChat(this, 8000); + return; } - obj->RefModelInfo(GetModelIndex()); - obj->AttachToRwObject((RwObject*)clump); - obj->m_fMass = 15.0f; - obj->m_fTurnMass = 5.0f; - obj->m_fAirResistance = 0.99f; - obj->m_fElasticity = 0.03f; - obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f; - obj->ObjectCreatedBy = TEMP_OBJECT; - obj->SetIsStatic(false); - obj->bIsPickup = false; - obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SMALLBOX; - - // life time - the more objects the are, the shorter this one will live - CObject::nNoTempObjects++; - if (CObject::nNoTempObjects > 20) - obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000; - else if (CObject::nNoTempObjects > 10) - obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000; - else - obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000; +#endif - CVector localForcePos, forceDir; + // Side of the Ice Cream van + m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI; - if (direction == 2) { - obj->m_vecMoveSpeed = 0.03f * GetForward(); - obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f; - obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - localForcePos = CVector(0.0f, 0.0f, 0.0f); - forceDir = GetForward(); - } else { - obj->m_vecMoveSpeed = -0.03f * GetForward(); - obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f; - obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - localForcePos = CVector(0.0f, 0.0f, 0.0f); - forceDir = -GetForward(); + if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) { + m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000; + m_nPedState = PED_BUY_ICECREAM; } - obj->ApplyTurnForce(forceDir, localForcePos); - CWorld::Add(obj); - - return obj; } -void -CPed::WarpPedIntoCar(CVehicle *car) +bool +CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh) { - bInVehicle = true; - m_pMyVehicle = car; - m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); - m_carInObjective = car; - m_carInObjective->RegisterReference((CEntity **) &m_carInObjective); - m_nPedState = PED_DRIVING; - bUsesCollision = false; - bIsInTheAir = false; - bVehExitWillBeInstant = true; - if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { - car->SetDriver(this); - car->pDriver->RegisterReference((CEntity **) &car->pDriver); + bool foundIt = false; - } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { - for (int i = 0; i < 4; i++) { - if (!car->pPassengers[i]) { - car->pPassengers[i] = this; - car->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]); - break; - } - } - } else - return; + CVector helperPos = GetPosition(); + helperPos.z = pos->z - 0.5f; - if (IsPlayer()) { - car->SetStatus(STATUS_PLAYER); - AudioManager.PlayerJustGotInCar(); - CCarCtrl::RegisterVehicleOfInterest(car); - } else { - car->SetStatus(STATUS_PHYSICS); - } + CVector foundPos = *pos; + foundPos.z -= 0.5f; - CWorld::Remove(this); - SetPosition(car->GetPosition()); - CWorld::Add(this); + // If there is another car between target car and us. + if (CWorld::TestSphereAgainstWorld((foundPos + helperPos) / 2.0f, 0.25f, veh, false, true, false, false, false, false)) { - if (car->bIsAmbulanceOnDuty) { - car->bIsAmbulanceOnDuty = false; - --CCarCtrl::NumAmbulancesOnDuty; - } - if (car->bIsFireTruckOnDuty) { - car->bIsFireTruckOnDuty = false; - --CCarCtrl::NumFiretrucksOnDuty; - } - if (!car->bEngineOn) { - car->bEngineOn = true; - DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f); - } + CColModel *vehCol = veh->GetModelInfo()->GetColModel(); + CVector *colMin = &vehCol->boundingBox.min; + CVector *colMax = &vehCol->boundingBox.max; -#ifdef VC_PED_PORTS - RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); + CVector leftRearPos = CVector(colMin->x - 0.5f, colMin->y - 0.5f, 0.0f); + CVector rightRearPos = CVector(0.5f + colMax->x, colMin->y - 0.5f, 0.0f); + CVector leftFrontPos = CVector(colMin->x - 0.5f, 0.5f + colMax->y, 0.0f); + CVector rightFrontPos = CVector(0.5f + colMax->x, 0.5f + colMax->y, 0.0f); - // VC uses AddInCarAnims but we don't have that - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); - RemoveWeaponWhenEnteringVehicle(); -#else - if (car->IsBoat()) { -#ifndef FIX_BUGS - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); -#else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); -#endif - CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - RemoveWeaponModel(ourWeapon->m_nModelId); - } else { - // Because we can use Uzi for drive by - RemoveWeaponWhenEnteringVehicle(); + leftRearPos = veh->GetMatrix() * leftRearPos; + rightRearPos = veh->GetMatrix() * rightRearPos; + leftFrontPos = veh->GetMatrix() * leftFrontPos; + rightFrontPos = veh->GetMatrix() * rightFrontPos; - if (car->bLowVehicle) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); + // Makes helperPos veh-ped distance vector. + helperPos -= veh->GetPosition(); + + // ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour. + // On every run it returns another pos. for ped, with same distance to the veh. + // Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't) + helperPos = veh->GetMatrix() * helperPos; + + float vehForwardHeading = veh->GetForward().Heading(); + + // I'm absolutely not sure about these namings. + // NTVF = needed turn if we're looking to vehicle front and wanna look to... + + float potentialLrHeading = Atan2(leftRearPos.x - helperPos.x, leftRearPos.y - helperPos.y); + float NTVF_LR = CGeneral::LimitRadianAngle(potentialLrHeading - vehForwardHeading); + + float potentialRrHeading = Atan2(rightRearPos.x - helperPos.x, rightRearPos.y - helperPos.y); + float NTVF_RR = CGeneral::LimitRadianAngle(potentialRrHeading - vehForwardHeading); + + float potentialLfHeading = Atan2(leftFrontPos.x - helperPos.x, leftFrontPos.y - helperPos.y); + float NTVF_LF = CGeneral::LimitRadianAngle(potentialLfHeading - vehForwardHeading); + + float potentialRfHeading = Atan2(rightFrontPos.x - helperPos.x, rightFrontPos.y - helperPos.y); + float NTVF_RF = CGeneral::LimitRadianAngle(potentialRfHeading - vehForwardHeading); + + bool canHeadToLr = NTVF_LR <= -PI || NTVF_LR >= -HALFPI; + + bool canHeadToRr = NTVF_RR <= HALFPI || NTVF_RR >= PI; + + bool canHeadToLf = NTVF_LF >= 0.0f || NTVF_LF <= -HALFPI; + + bool canHeadToRf = NTVF_RF <= 0.0f || NTVF_RF >= HALFPI; + + // Only order of conditions are different among enterTypes. + if (m_vehEnterType == CAR_DOOR_RR) { + if (canHeadToRr) { + foundPos = rightRearPos; + foundIt = true; + } else if (canHeadToRf) { + foundPos = rightFrontPos; + foundIt = true; + } else if (canHeadToLr) { + foundPos = leftRearPos; + foundIt = true; + } else if (canHeadToLf) { + foundPos = leftFrontPos; + foundIt = true; + } + } else if(m_vehEnterType == CAR_DOOR_RF) { + if (canHeadToRf) { + foundPos = rightFrontPos; + foundIt = true; + } else if (canHeadToRr) { + foundPos = rightRearPos; + foundIt = true; + } else if (canHeadToLf) { + foundPos = leftFrontPos; + foundIt = true; + } else if (canHeadToLr) { + foundPos = leftRearPos; + foundIt = true; + } + } else if (m_vehEnterType == CAR_DOOR_LF) { + if (canHeadToLf) { + foundPos = leftFrontPos; + foundIt = true; + } else if (canHeadToLr) { + foundPos = leftRearPos; + foundIt = true; + } else if (canHeadToRf) { + foundPos = rightFrontPos; + foundIt = true; + } else if (canHeadToRr) { + foundPos = rightRearPos; + foundIt = true; + } + } else if (m_vehEnterType == CAR_DOOR_LR) { + if (canHeadToLr) { + foundPos = leftRearPos; + foundIt = true; + } else if (canHeadToLf) { + foundPos = leftFrontPos; + foundIt = true; + } else if (canHeadToRr) { + foundPos = rightRearPos; + foundIt = true; + } else if (canHeadToRf) { + foundPos = rightFrontPos; + foundIt = true; + } + } } -#endif + if (!foundIt) + return false; - StopNonPartialAnims(); - if (car->bIsBus) - bRenderPedInCar = false; + helperPos = GetPosition() - foundPos; + helperPos.z = 0.0f; + if (helperPos.MagnitudeSqr() <= sq(0.5f)) + return false; - bChangedSeat = true; + pos->x = foundPos.x; + pos->y = foundPos.y; + return true; } void -CPed::SetObjective(eObjective newObj, CVector dest) +CPed::SetLeader(CEntity *leader) { - if (DyingOrDead()) - return; + m_leader = (CPed*)leader; - if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj) - return; + if(m_leader) + m_leader->RegisterReference((CEntity **)&m_leader); +} - SetObjectiveTimer(0); - if (m_objective == newObj) { - if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) { - if (m_nextRoutePointPos == dest) - return; - } else if (newObj == OBJECTIVE_GUARD_SPOT) { - if (m_vecSeekPosEx == dest) - return; +#ifdef VC_PED_PORTS +bool +CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal) +{ + if (m_nSurfaceTouched == SURFACE_WATER) + return true; + + CVector pos = GetPosition(); + CVector forwardOffset = GetForward(); + if (damageNormal && damageNormal->z > 0.17f) { + if (damageNormal->z > 0.9f) + return false; + + CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); + pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z; + pos.z = pos.z + 0.05f; + float collPower = damageNormal->Magnitude2D(); + if (damageNormal->z > 0.5f) { + CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f); + invDamageNormal *= 1.0f / collPower; + CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius; + forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f); + } else { + forwardOffset += collPower * ourCol->spheres->radius * forwardOffset; } + } else { + pos.z -= 0.15f; } -#ifdef VC_PED_PORTS - ClearPointGunAt(); -#endif - bObjectiveCompleted = false; - switch (newObj) { - case OBJECTIVE_GUARD_SPOT: - m_vecSeekPosEx = dest; - m_distanceToCountSeekDoneEx = 5.0f; - SetMoveState(PEDMOVE_STILL); - break; - case OBJECTIVE_GUARD_AREA: - case OBJECTIVE_WAIT_IN_CAR: - case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: - case OBJECTIVE_KILL_CHAR_ON_FOOT: - case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: - case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: - case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: - case OBJECTIVE_LEAVE_CAR: - case OBJECTIVE_ENTER_CAR_AS_PASSENGER: - case OBJECTIVE_ENTER_CAR_AS_DRIVER: - case OBJECTIVE_FOLLOW_CAR_IN_CAR: - case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE: - case OBJECTIVE_DESTROY_OBJECT: - case OBJECTIVE_DESTROY_CAR: - break; - case OBJECTIVE_GOTO_AREA_ANY_MEANS: - case OBJECTIVE_GOTO_AREA_ON_FOOT: - bIsRunning = false; - m_pNextPathNode = nil; - m_nextRoutePointPos = dest; - m_vecSeekPos = m_nextRoutePointPos; - m_distanceToCountSeekDone = 0.5f; - bUsePedNodeSeek = true; - if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) - return; - break; - case OBJECTIVE_RUN_TO_AREA: - bIsRunning = true; - m_pNextPathNode = nil; - m_nextRoutePointPos = dest; - m_vecSeekPos = m_nextRoutePointPos; - m_distanceToCountSeekDone = 0.5f; - bUsePedNodeSeek = true; - if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) - return; - break; - default: break; - } + CVector forwardPos = pos + forwardOffset; + return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false); +} +#else +bool +CPed::CanPedJumpThis(CEntity *unused) +{ + CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur)); + CVector pos = GetPosition(); + CVector forwardPos( + forward.x + pos.x, + forward.y + pos.y, + pos.z); - if (IsTemporaryObjective(m_objective)) { - m_prevObjective = newObj; - } else { - if (m_objective != newObj) - SetStoredObjective(); + return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false); +} +#endif - m_objective = newObj; +void +CPed::SetJump(void) +{ + if (!bInVehicle && +#if defined VC_PED_PORTS || defined FIX_BUGS + m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) && +#endif + (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { + SetStoredState(); + m_nPedState = PED_JUMP; + CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f); + jumpAssoc->SetFinishCallback(FinishLaunchCB, this); + m_fRotationDest = m_fRotationCur; } } void -CPed::SetMoveAnim(void) +CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg) { - if (m_nStoredMoveState == m_nMoveState || !IsPedInControl()) - return; + CPed *ped = (CPed*)arg; - if (m_nMoveState == PEDMOVE_NONE) { - m_nStoredMoveState = PEDMOVE_NONE; + if (ped->m_nPedState != PED_JUMP) return; - } - - AssocGroupId animGroupToUse; - if (m_leader && m_leader->IsPlayer()) - animGroupToUse = ASSOCGRP_PLAYER; - else - animGroupToUse = m_animGroup; - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK); - if (!animAssoc) { - CAnimBlendAssociation *fightIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); - animAssoc = fightIdleAssoc; - if (fightIdleAssoc && m_nPedState == PED_FIGHT) - return; - - if (fightIdleAssoc) { - CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); - if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 8.0f); - } - } - } - if (!animAssoc) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); - if (animAssoc) - if (m_nWaitState == WAITSTATE_STUCK || m_nWaitState == WAITSTATE_FINISH_FLEE) - return; + CVector forward(0.15f * ped->GetForward() + ped->GetPosition()); + forward.z += CModelInfo::GetModelInfo(ped->GetModelIndex())->GetColModel()->spheres->center.z + 0.25f; - if (animAssoc) { - CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); - if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f); - } - } + CEntity *obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false); + if (!obstacle) { + // Forward of forward + forward += 0.15f * ped->GetForward(); + forward.z += 0.15f; + obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false); } - if (!animAssoc) { - m_nStoredMoveState = m_nMoveState; - if (m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT) { - for (CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL); - assoc; assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_PARTIAL)) { - if (!(assoc->flags & ASSOC_FADEOUTWHENDONE)) { - assoc->blendDelta = -2.0f; - assoc->flags |= ASSOC_DELETEFADEDOUT; - } - } - - ClearAimFlag(); - ClearLookFlag(); - } - - switch (m_nMoveState) { - case PEDMOVE_STILL: - animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f); - break; - case PEDMOVE_WALK: - animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_WALK, 1.0f); - break; - case PEDMOVE_RUN: - if (m_nPedState == PED_FLEE_ENTITY) { - animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 3.0f); - } else { - animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 1.0f); - } - break; - case PEDMOVE_SPRINT: - animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_SPRINT, 1.0f); - break; - default: - break; - } + if (obstacle) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; - if (animAssoc) { - if (m_leader) { - CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_WALK); - if (!walkAssoc) - walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_RUN); + // ANIM_HIT_WALL in VC (which makes more sense) + CAnimBlendAssociation *handsCoverAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 8.0f); + handsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + handsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped); + ped->bIsLanding = true; + return; + } - if (!walkAssoc) - walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_SPRINT); + float velocityFromAnim = 0.1f; + CAnimBlendAssociation *sprintAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_SPRINT); - if (walkAssoc) { - animAssoc->speed = walkAssoc->speed; - } else { - if (CharCreatedBy == MISSION_CHAR) - animAssoc->speed = 1.0f; - else - animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX; - - } - } else { - if (CharCreatedBy == MISSION_CHAR) - animAssoc->speed = 1.0f; - else - animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX; - } + if (sprintAssoc) { + velocityFromAnim = 0.05f * sprintAssoc->blendAmount + 0.17f; + } else { + CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_RUN); + if (runAssoc) { + velocityFromAnim = 0.07f * runAssoc->blendAmount + 0.1f; } } -} -void -CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) -{ - float zDiff = 0.0f; - RemoveWeaponWhenEnteringVehicle(); - car->m_nGettingInFlags |= doorFlag; - bVehEnterDoorIsBlocked = false; - if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT) - SetStoredState(); + if (ped->IsPlayer() +#ifdef VC_PED_PORTS + || ped->m_pedInObjective && ped->m_pedInObjective->IsPlayer() +#endif + ) + ped->ApplyMoveForce(0.0f, 0.0f, 8.5f); + else + ped->ApplyMoveForce(0.0f, 0.0f, 4.5f); + + if (sq(velocityFromAnim) > ped->m_vecMoveSpeed.MagnitudeSqr2D() +#ifdef VC_PED_PORTS + || ped->m_pCurrentPhysSurface +#endif + ) { - m_pSeekTarget = car; - m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); - m_vehEnterType = doorNode; - m_nPedState = PED_ENTER_CAR; - if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && car->m_vehType != VEHICLE_TYPE_BIKE) { - car->bIsBeingCarJacked = true; +#ifdef FREE_CAM + if (TheCamera.Cams[0].Using3rdPersonMouseCam() && !CCamera::bFreeCam) { +#else + if (TheCamera.Cams[0].Using3rdPersonMouseCam()) { +#endif + float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur); + ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle); + ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle); + } else { + ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur); + ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur); + } +#ifdef VC_PED_PORTS + if (ped->m_pCurrentPhysSurface) { + ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x; + ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y; + } +#endif } - m_pMyVehicle = (CVehicle*)m_pSeekTarget; - m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle); - ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++; - bUsesCollision = false; - CVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehEnterType); + ped->bIsStanding = false; + ped->bIsInTheAir = true; + animAssoc->blendDelta = -1000.0f; + CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_JUMP_GLIDE); - // Because buses have stairs - if (!m_pMyVehicle->bIsBus) - zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z); + if (ped->bDoBloodyFootprints) { + CVector bloodPos(0.0f, 0.0f, 0.0f); + ped->TransformToNode(bloodPos, PED_FOOTL); - m_vecOffsetSeek = doorOpenPos - GetPosition(); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; - if (car->IsBoat()) { -#ifdef VC_PED_PORTS - // VC checks for handling flag, but we can't do that - if(car->GetModelIndex() == MI_SPEEDER) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); + bloodPos.z -= 0.1f; + bloodPos += 0.2f * ped->GetForward(); - PedSetInCarCB(nil, this); - bVehExitWillBeInstant = true; -#else + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, + 0.26f * ped->GetForward().x, + 0.26f * ped->GetForward().y, + 0.14f * ped->GetRight().x, + 0.14f * ped->GetRight().y, + 255, 255, 0, 0, 4.0f, 3000, 1.0f); -#ifndef FIX_BUGS - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); -#else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); -#endif + bloodPos = CVector(0.0f, 0.0f, 0.0f); + ped->TransformToNode(bloodPos, PED_FOOTR); - m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this); -#endif - if (IsPlayer()) - CWaterLevel::AllocateBoatWakeArray(); - } else { - if (zDiff > 4.4f) { - if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f); + bloodPos.z -= 0.1f; + bloodPos += 0.2f * ped->GetForward(); + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, + 0.26f * ped->GetForward().x, + 0.26f * ped->GetForward().y, + 0.14f * ped->GetRight().x, + 0.14f * ped->GetRight().y, + 255, 255, 0, 0, 4.0f, 3000, 1.0f); + if (ped->m_bloodyFootprintCountOrDeathTime <= 40) { + ped->m_bloodyFootprintCountOrDeathTime = 0; + ped->bDoBloodyFootprints = false; } else { - if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f); + ped->m_bloodyFootprintCountOrDeathTime -= 40; } - m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this); - car->AutoPilot.m_nCruiseSpeed = 0; } } void -CPed::WanderPath(void) +CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg) { - if (!m_pNextPathNode) { - printf("THIS SHOULDN@T HAPPEN TOO OFTEN\n"); - SetIdle(); - return; - } - if (m_nWaitState == WAITSTATE_FALSE) { - if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE) - SetMoveState(PEDMOVE_WALK); - } - m_vecSeekPos = m_pNextPathNode->GetPosition(); - m_vecSeekPos.z += 1.0f; + CPed *ped = (CPed*)arg; - // Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him. - if (!Seek()) - return; + ped->bResetWalkAnims = true; + ped->bIsLanding = false; - CPathNode *previousLastNode = m_pLastPathNode; - uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100; + animAssoc->blendDelta = -1000.0f; +} - // We don't prefer 180-degree turns in normal situations - uint8 dirWeWouldntPrefer = m_nPathDir; - if (dirWeWouldntPrefer <= 3) - dirWeWouldntPrefer += 4; - else - dirWeWouldntPrefer -= 4; +void +CPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; - CPathNode *nodeWeWouldntPrefer = nil; - uint8 dirToSet = 9; // means undefined - uint8 dirWeWouldntPrefer2 = 9; // means undefined - if (randVal <= 90) { - if (randVal > 80) { - m_nPathDir += 2; - m_nPathDir %= 8; - } - } else { - m_nPathDir -= 2; - if (m_nPathDir < 0) - m_nPathDir += 8; + if (animAssoc) { + animAssoc->blendDelta = -4.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; } - m_pLastPathNode = m_pNextPathNode; - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, - m_nPathDir, &dirToSet); + if (ped->m_nPedState == PED_JUMP) + ped->RestorePreviousState(); - uint8 tryCount = 0; + ped->bIsLanding = false; +} - // NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7 - while (!m_pNextPathNode) { - tryCount++; - m_nPathDir = (m_nPathDir + 1) % 8; +bool +CPed::CanPedDriveOff(void) +{ + if (m_nPedState != PED_DRIVING || m_lookTimer > CTimer::GetTimeInMilliseconds()) + return false; - // We're at where we started and couldn't find any node - if (tryCount > 7) { - if (!nodeWeWouldntPrefer) { - ClearAll(); - SetIdle(); - // Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath. - Error("Can't find valid path node, SetWanderPath, Ped.cpp"); - return; - } - m_pNextPathNode = nodeWeWouldntPrefer; - dirToSet = dirWeWouldntPrefer2; - } else { - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, - m_nPathDir, &dirToSet); - if (m_pNextPathNode) { - if (dirToSet == dirWeWouldntPrefer) { - nodeWeWouldntPrefer = m_pNextPathNode; - dirWeWouldntPrefer2 = dirToSet; - m_pNextPathNode = nil; - } - } + for (int i = 0; i < m_numNearPeds; i++) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed->m_nPedType == m_nPedType && nearPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && nearPed->m_carInObjective == m_carInObjective) { + m_lookTimer = CTimer::GetTimeInMilliseconds() + 1000; + return false; } } + return true; +} - m_nPathDir = dirToSet; - if (m_pLastPathNode == m_pNextPathNode) { - m_pNextPathNode = previousLastNode; - SetWaitState(WAITSTATE_DOUBLEBACK, nil); - Say(SOUND_PED_WAIT_DOUBLEBACK); - } else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) { - SetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil); - } else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) { - SetWaitState(WAITSTATE_CROSS_ROAD, nil); - } else if (m_pNextPathNode == previousLastNode) { - SetWaitState(WAITSTATE_DOUBLEBACK, nil); - Say(SOUND_PED_WAIT_DOUBLEBACK); +// These categories are purely random, most of ped models have no correlation. So I don't think making an enum. +uint8 +CPed::GetPedRadioCategory(uint32 modelIndex) +{ + switch (modelIndex) { + case MI_MALE01: + case MI_FEMALE03: + case MI_PROSTITUTE2: + case MI_WORKER1: + case MI_MOD_MAN: + case MI_MOD_WOM: + case MI_ST_WOM: + case MI_FAN_WOM: + return 3; + case MI_TAXI_D: + case MI_PIMP: + case MI_MALE02: + case MI_FEMALE02: + case MI_FATFEMALE01: + case MI_FATFEMALE02: + case MI_DOCKER1: + case MI_WORKER2: + case MI_FAN_MAN2: + return 9; + case MI_GANG01: + case MI_GANG02: + case MI_SCUM_MAN: + case MI_SCUM_WOM: + case MI_HOS_WOM: + case MI_CONST1: + return 1; + case MI_GANG03: + case MI_GANG04: + case MI_GANG07: + case MI_GANG08: + case MI_CT_MAN2: + case MI_CT_WOM2: + case MI_B_MAN3: + case MI_SHOPPER3: + return 4; + case MI_GANG05: + case MI_GANG06: + case MI_GANG11: + case MI_GANG12: + case MI_CRIMINAL02: + case MI_B_WOM2: + case MI_ST_MAN: + case MI_HOS_MAN: + return 5; + case MI_FATMALE01: + case MI_LI_MAN2: + case MI_SHOPPER1: + case MI_CAS_MAN: + return 6; + case MI_PROSTITUTE: + case MI_P_WOM2: + case MI_LI_WOM2: + case MI_B_WOM3: + case MI_CAS_WOM: + return 2; + case MI_P_WOM1: + case MI_DOCKER2: + case MI_STUD_MAN: + return 7; + case MI_CT_MAN1: + case MI_CT_WOM1: + case MI_LI_MAN1: + case MI_LI_WOM1: + case MI_B_MAN1: + case MI_B_MAN2: + case MI_B_WOM1: + case MI_SHOPPER2: + case MI_STUD_WOM: + return 8; + default: + return 0; } } -bool -CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo) +void +CPed::SetRadioStation(void) { - bool teleported = false; - if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) - return false; - - CVector warpToPos = warpTo->GetPosition(); - CVector distVec = warpToPos - GetPosition(); - float halfOfDist = distVec.Magnitude() * 0.5f; - CVector halfNormalizedDist = distVec / halfOfDist; - - CVector appropriatePos = GetPosition(); - CVector zCorrectedPos = appropriatePos; - int tryCount = Min(10, halfOfDist); - for (int i = 0; i < tryCount; ++i) { - appropriatePos += halfNormalizedDist; - CPedPlacement::FindZCoorForPed(&zCorrectedPos); + static const uint8 radiosPerRadioCategories[10][4] = { + {JAH_RADIO, RISE_FM, GAME_FM, MSX_FM}, + {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK}, + {RISE_FM, GAME_FM, MSX_FM, FLASHBACK}, + {HEAD_RADIO, RISE_FM, LIPS_106, MSX_FM}, + {HEAD_RADIO, RISE_FM, MSX_FM, FLASHBACK}, + {JAH_RADIO, RISE_FM, LIPS_106, FLASHBACK}, + {HEAD_RADIO, RISE_FM, LIPS_106, FLASHBACK}, + {HEAD_RADIO, JAH_RADIO, LIPS_106, FLASHBACK}, + {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK}, + {CHATTERBOX, HEAD_RADIO, LIPS_106, GAME_FM} + }; + uint8 orderInCat = 0; // BUG: this wasn't initialized - if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f) - continue; + if (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this) + return; - appropriatePos.z = zCorrectedPos.z; - if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix()) - && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false) - && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) { - teleported = true; - Teleport(appropriatePos); + uint8 category = GetPedRadioCategory(GetModelIndex()); + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (CGeneral::GetRandomNumber() & 15) { + for (orderInCat = 0; orderInCat < 4; orderInCat++) { + if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat]) + break; + } + } else { + m_pMyVehicle->m_nRadioStation = USERTRACK; + } + } else { + for (orderInCat = 0; orderInCat < 4; orderInCat++) { + if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat]) + break; } } - m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000; - return teleported; -} - -bool -CPed::WarpPedToNearLeaderOffScreen(void) -{ - bool teleported = false; - if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) - return false; - - CVector warpToPos = m_leader->GetPosition(); - CVector distVec = warpToPos - GetPosition(); - float halfOfDist = distVec.Magnitude() * 0.5f; - CVector halfNormalizedDist = distVec / halfOfDist; - - CVector appropriatePos = GetPosition(); - CVector zCorrectedPos = appropriatePos; - int tryCount = Min(10, halfOfDist); - for (int i = 0; i < tryCount; ++i) { - appropriatePos += halfNormalizedDist; - CPedPlacement::FindZCoorForPed(&zCorrectedPos); - - if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f) - continue; - - appropriatePos.z = zCorrectedPos.z; - if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix()) - && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false) - && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) { - teleported = true; - Teleport(appropriatePos); + if (orderInCat == 4) { + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (CGeneral::GetRandomNumber() & 15) + m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3]; + else + m_pMyVehicle->m_nRadioStation = USERTRACK; + } else { + m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3]; } } - m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000; - return teleported; } void -CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) +CPed::WarpPedIntoCar(CVehicle *car) { - RemoveWeaponWhenEnteringVehicle(); - if (m_nPedState != PED_SEEK_CAR) - SetStoredState(); - - m_pSeekTarget = car; - m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget); - m_nPedState = PED_CARJACK; - car->bIsBeingCarJacked = true; - m_pMyVehicle = (CVehicle*)m_pSeekTarget; - m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle); - ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++; - - Say(m_nPedType == PEDTYPE_COP ? SOUND_PED_ARREST_COP : SOUND_PED_CAR_JACKING); - CVector carEnterPos; - carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType); - - car->m_nGettingInFlags |= doorFlag; - m_vecOffsetSeek = carEnterPos - GetPosition(); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; - float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z); + bInVehicle = true; + m_pMyVehicle = car; + m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + m_carInObjective = car; + m_carInObjective->RegisterReference((CEntity **) &m_carInObjective); + m_nPedState = PED_DRIVING; bUsesCollision = false; + bIsInTheAir = false; + bVehExitWillBeInstant = true; + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + car->SetDriver(this); + car->pDriver->RegisterReference((CEntity **) &car->pDriver); - if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f); - - m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this); -} - -void -CPed::SetObjective(eObjective newObj, CVector dest, float safeDist) -{ - if (DyingOrDead()) - return; - - if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj) + } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { + for (int i = 0; i < 4; i++) { + if (!car->pPassengers[i]) { + car->pPassengers[i] = this; + car->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]); + break; + } + } + } else return; - SetObjectiveTimer(0); - if (m_objective == newObj) { - if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) { - if (m_nextRoutePointPos == dest && m_distanceToCountSeekDone == safeDist) - return; - } else if (newObj == OBJECTIVE_GUARD_SPOT) { - if (m_vecSeekPosEx == dest && m_distanceToCountSeekDoneEx == safeDist) - return; - } + if (IsPlayer()) { + car->SetStatus(STATUS_PLAYER); + AudioManager.PlayerJustGotInCar(); + CCarCtrl::RegisterVehicleOfInterest(car); + } else { + car->SetStatus(STATUS_PHYSICS); } -#ifdef VC_PED_PORTS - ClearPointGunAt(); -#endif - bObjectiveCompleted = false; - if (IsTemporaryObjective(m_objective)) { - m_prevObjective = newObj; - } else { - if (m_objective != newObj) - SetStoredObjective(); + CWorld::Remove(this); + SetPosition(car->GetPosition()); + CWorld::Add(this); - m_objective = newObj; + if (car->bIsAmbulanceOnDuty) { + car->bIsAmbulanceOnDuty = false; + --CCarCtrl::NumAmbulancesOnDuty; } - - if (newObj == OBJECTIVE_GUARD_SPOT) { - m_vecSeekPosEx = dest; - m_distanceToCountSeekDoneEx = safeDist; - } else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) { - m_pNextPathNode = nil; - m_nextRoutePointPos = dest; - m_vecSeekPos = m_nextRoutePointPos; - bUsePedNodeSeek = true; + if (car->bIsFireTruckOnDuty) { + car->bIsFireTruckOnDuty = false; + --CCarCtrl::NumFiretrucksOnDuty; + } + if (!car->bEngineOn) { + car->bEngineOn = true; + DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f); } -} -void -CPed::SetCarJack(CVehicle* car) -{ - uint8 doorFlag; - eDoors door; - CPed *pedInSeat = nil; +#ifdef VC_PED_PORTS + RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); - if (car->IsBoat()) - return; + // VC uses AddInCarAnims but we don't have that + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); + RemoveWeaponWhenEnteringVehicle(); +#else + if (car->IsBoat()) { +#ifndef FIX_BUGS + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); +#else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); +#endif + CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + RemoveWeaponModel(ourWeapon->m_nModelId); + } else { + // Because we can use Uzi for drive by + RemoveWeaponWhenEnteringVehicle(); - switch (m_vehEnterType) { - case CAR_DOOR_RF: - doorFlag = CAR_DOOR_FLAG_RF; - door = DOOR_FRONT_RIGHT; - if (car->pPassengers[0]) { - pedInSeat = car->pPassengers[0]; - } else if (m_nPedType == PEDTYPE_COP) { - pedInSeat = car->pDriver; - } - break; - case CAR_DOOR_RR: - doorFlag = CAR_DOOR_FLAG_RR; - door = DOOR_REAR_RIGHT; - pedInSeat = car->pPassengers[2]; - break; - case CAR_DOOR_LF: - doorFlag = CAR_DOOR_FLAG_LF; - door = DOOR_FRONT_LEFT; - pedInSeat = car->pDriver; - break; - case CAR_DOOR_LR: - doorFlag = CAR_DOOR_FLAG_LR; - door = DOOR_REAR_LEFT; - pedInSeat = car->pPassengers[1]; - break; - default: - doorFlag = CAR_DOOR_FLAG_UNKNOWN; - break; + if (car->bLowVehicle) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f); + else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); } +#endif - if(car->bIsBus) - pedInSeat = car->pDriver; + StopNonPartialAnims(); + if (car->bIsBus) + bRenderPedInCar = false; - if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || - (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO))) - if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING) - if (m_nPedState != PED_CARJACK && !m_pVehicleAnim) - if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door))) - if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags)) - SetCarJack_AllClear(car, m_vehEnterType, doorFlag); + bChangedSeat = true; } -void -CPed::Solicit(void) + +#ifdef PEDS_REPORT_CRIMES_ON_PHONE +// returns event id, parameter is optional +int32 +CPed::CheckForPlayerCrimes(CPed *victim) { - if (m_standardTimer >= CTimer::GetTimeInMilliseconds() && m_carInObjective) { - CVector doorPos = GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType, 0.0f); - SetMoveState(PEDMOVE_STILL); + int i; + float dist; + float mindist = 60.0f; + CPlayerPed *player = FindPlayerPed(); + int32 victimRef = (victim ? CPools::GetPedRef(victim) : 0); + int event = -1; - // Game uses GetAngleBetweenPoints and converts it to radian - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - doorPos.x, doorPos.y, - GetPosition().x, GetPosition().y); + for (i = 0; i < NUMEVENTS; i++) { + if (gaEvent[i].type == EVENT_NULL || gaEvent[i].type > EVENT_CAR_SET_ON_FIRE) + continue; - if (m_fRotationDest < 0.0f) { - m_fRotationDest = m_fRotationDest + TWOPI; - } else if (m_fRotationDest > TWOPI) { - m_fRotationDest = m_fRotationDest - TWOPI; + // those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc. + if (gaEvent[i].type == EVENT_DEAD_PED || gaEvent[i].type == EVENT_GUNSHOT || gaEvent[i].type == EVENT_EXPLOSION) + continue; + + if (victim && gaEvent[i].entityRef != victimRef) + continue; + + if (gaEvent[i].criminal != player) + continue; + + dist = (GetPosition() - gaEvent[i].posn).Magnitude(); + if (dist < mindist) { + mindist = dist; + event = i; } + } - if ((GetPosition() - doorPos).MagnitudeSqr() <= 1.0f) - return; - CAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_HOOKERTALK); - if (talkAssoc) { - talkAssoc->blendDelta = -1000.0f; - talkAssoc->flags |= ASSOC_DELETEFADEDOUT; + if (event != -1) { + if (victim) { + m_victimOfPlayerCrime = victim; + } else { + switch (gaEvent[event].entityType) { + case EVENT_ENTITY_PED: + m_victimOfPlayerCrime = CPools::GetPed(gaEvent[event].entityRef); + break; + case EVENT_ENTITY_VEHICLE: + m_victimOfPlayerCrime = CPools::GetVehicle(gaEvent[event].entityRef); + break; + case EVENT_ENTITY_OBJECT: + m_victimOfPlayerCrime = CPools::GetObject(gaEvent[event].entityRef); + break; + default: + break; + } } - RestorePreviousState(); - RestorePreviousObjective(); - SetObjectiveTimer(10000); - } else if (!m_carInObjective) { - RestorePreviousState(); - RestorePreviousObjective(); - SetObjectiveTimer(10000); - } else if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney <= 100) { - m_carInObjective = nil; - } else { - m_pVehicleAnim = nil; - SetLeader(m_carInObjective->pDriver); } + + return event; +} +#endif + +#ifdef PED_SKIN +static RpMaterial* +SetLimbAlphaCB(RpMaterial *material, void *data) +{ + ((RwRGBA*)RpMaterialGetColor(material))->alpha = *(uint8*)data; + return material; } -// Seperate function in VC, more logical. Not sure is it inlined in III. void -CPed::SetExitBoat(CVehicle *boat) +CPed::renderLimb(int node) { -#ifndef VC_PED_PORTS - m_nPedState = PED_IDLE; - CVector firstPos = GetPosition(); - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); - if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) { - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f); - m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this); - m_vehEnterType = CAR_DOOR_RF; - m_nPedState = PED_EXIT_CAR; - } else { - m_vehEnterType = CAR_DOOR_RF; - PedSetOutCarCB(nil, this); - bIsStanding = true; - m_pCurSurface = boat; - m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface); + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + CPedModelInfo *mi = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()); + RpAtomic *atomic; + switch(node){ + case PED_HEAD: + atomic = mi->getHead(); + break; + case PED_HANDL: + atomic = mi->getLeftHand(); + break; + case PED_HANDR: + atomic = mi->getRightHand(); + break; + default: + return; } - SetPosition(firstPos); - SetMoveState(PEDMOVE_STILL); - m_vecMoveSpeed = boat->m_vecMoveSpeed; - bTryingToReachDryLand = true; -#else - m_nPedState = PED_IDLE; - CVector newPos = GetPosition(); - RemoveInCarAnims(); - CColModel* boatCol = boat->GetColModel(); - if (boat->IsUpsideDown()) { - newPos = { 0.0f, 0.0f, boatCol->boundingBox.min.z }; - newPos = boat->GetMatrix() * newPos; - newPos.z += 1.0f; - m_vehEnterType = CAR_DOOR_RF; - PedSetOutCarCB(nil, this); - bIsStanding = true; - m_pCurSurface = boat; - m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface); - m_pCurrentPhysSurface = boat; - } else { -/* if (boat->m_modelIndex != MI_SKIMMER || boat->bIsInWater) { - if (boat->m_modelIndex == MI_SKIMMER) - newPos.z += 2.0f -*/ - m_vehEnterType = CAR_DOOR_RF; - PedSetOutCarCB(nil, this); - bIsStanding = true; - m_pCurSurface = boat; - m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface); - m_pCurrentPhysSurface = boat; - CColPoint foundCol; - CEntity *foundEnt = nil; - if (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil)) - newPos.z = FEET_OFFSET + foundCol.point.z; -/* // VC specific - } else { - m_vehEnterType = CAR_DOOR_RF; - PedSetOutCarCB(nil, this); - bIsStanding = true; - SetMoveState(PEDMOVE_STILL); - bTryingToReachDryLand = true; - float upMult = 1.04f + boatCol->boundingBox.min.z; - float rightMult = 0.6f * boatCol->boundingBox.max.x; - newPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition(); - GetPosition() = newPos; - if (m_pMyVehicle) { - PositionPedOutOfCollision(); - } else { - m_pMyVehicle = boat; - PositionPedOutOfCollision(); - m_pMyVehicle = nil; - } - return; - } -*/ } - SetPosition(newPos); - SetMoveState(PEDMOVE_STILL); - m_vecMoveSpeed = boat->m_vecMoveSpeed; -#endif - // Not there in VC. - CWaterLevel::FreeBoatWakeArray(); + if(atomic == nil) + return; + + RwFrame *frame = RpAtomicGetFrame(atomic); + *RwFrameGetMatrix(frame) = *mat; + RwFrameUpdateObjects(frame); + int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha); + RpAtomicRender(atomic); } +#endif #ifdef COMPATIBLE_SAVES #define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data)); diff --git a/src/peds/Ped.h b/src/peds/Ped.h index dbe61572..a3d4997d 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -5,7 +5,7 @@ #include "Crime.h" #include "EventList.h" #include "PedIK.h" -#include "PedStats.h" +#include "PedType.h" #include "Physical.h" #include "Weapon.h" #include "WeaponInfo.h" @@ -13,6 +13,7 @@ #define FEET_OFFSET 1.04f #define CHECK_NEARBY_THINGS_MAX_DIST 15.0f #define ENTER_CAR_MAX_DIST 30.0f +#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) struct CPathNode; class CAccident; @@ -568,7 +569,7 @@ public: void CalculateNewOrientation(void); float WorkOutHeadingForMovingFirstPerson(float); void CalculateNewVelocity(void); - bool CanSeeEntity(CEntity*, float); + bool CanSeeEntity(CEntity*, float threshold = CAN_SEE_ENTITY_ANGLE_THRESHOLD); void RestorePreviousObjective(void); void SetIdle(void); #ifdef _MSC_VER @@ -747,7 +748,7 @@ public: static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); - bool IsPlayer(void); + bool IsPlayer(void) const; bool UseGroundColModel(void); bool CanSetPedState(void); bool IsPedInControl(void); @@ -765,7 +766,7 @@ public: void SetStoredObjective(void); void SetLeader(CEntity* leader); void SetPedStats(ePedStats); - bool IsGangMember(void); + bool IsGangMember(void) const; void Die(void); void EnterTrain(void); void ExitTrain(void); @@ -788,7 +789,7 @@ public: CObject *SpawnFlyingComponent(int, int8); void SetCarJack_AllClear(CVehicle*, uint32, uint32); #ifdef VC_PED_PORTS - bool CanPedJumpThis(CEntity*, CVector*); + bool CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil); #else bool CanPedJumpThis(CEntity*); #endif @@ -809,9 +810,40 @@ public: bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; } - void ReplaceWeaponWhenExitingVehicle(void); - void RemoveWeaponWhenEnteringVehicle(void); - bool IsNotInWreckedVehicle(); + // It was inlined in III but not in VC. + inline void + ReplaceWeaponWhenExitingVehicle(void) + { + eWeaponType weaponType = GetWeapon()->m_eWeaponType; + + // If it's Uzi, we may have stored weapon. Uzi is the only gun we can use in car. + if (IsPlayer() && weaponType == WEAPONTYPE_UZI) { + if (/*IsPlayer() && */ m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) { + SetCurrentWeapon(m_storedWeapon); + m_storedWeapon = WEAPONTYPE_UNIDENTIFIED; + } + } else { + AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId); + } + } + + // It was inlined in III but not in VC. + inline void + RemoveWeaponWhenEnteringVehicle(void) + { + if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) { + if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED) + m_storedWeapon = GetWeapon()->m_eWeaponType; + SetCurrentWeapon(WEAPONTYPE_UZI); + } else { + CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + RemoveWeaponModel(ourWeapon->m_nModelId); + } + } + bool IsNotInWreckedVehicle() + { + return m_pMyVehicle != nil && ((CEntity*)m_pMyVehicle)->GetStatus() != STATUS_WRECKED; + } // My additions, because there were many, many instances of that. inline void SetFindPathAndFlee(CEntity *fleeFrom, int time, bool walk = false) { diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp new file mode 100644 index 00000000..38303473 --- /dev/null +++ b/src/peds/PedAI.cpp @@ -0,0 +1,5413 @@ +#include "common.h" + +#include "main.h" +#include "Particle.h" +#include "RpAnimBlend.h" +#include "Ped.h" +#include "Wanted.h" +#include "AnimBlendAssociation.h" +#include "DMAudio.h" +#include "General.h" +#include "HandlingMgr.h" +#include "Replay.h" +#include "Camera.h" +#include "PedPlacement.h" +#include "ZoneCull.h" +#include "Pad.h" +#include "Pickups.h" +#include "Train.h" +#include "PedRoutes.h" +#include "CopPed.h" +#include "Script.h" +#include "CarCtrl.h" +#include "WaterLevel.h" +#include "CarAI.h" +#include "Zones.h" +#include "Cranes.h" + +CVector vecPedCarDoorAnimOffset; +CVector vecPedCarDoorLoAnimOffset; +CVector vecPedVanRearDoorAnimOffset; +CVector vecPedQuickDraggedOutCarAnimOffset; +CVector vecPedDraggedOutCarAnimOffset; +CVector vecPedTrainDoorAnimOffset; + +void +CPed::SetObjectiveTimer(int time) +{ + if (time == 0) { + m_objectiveTimer = 0; + } else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { + m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time; + } +} + +void +CPed::SetStoredObjective(void) +{ + if (m_objective == m_prevObjective) + return; + + switch (m_objective) + { + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: + case OBJECTIVE_LEAVE_CAR: + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + case OBJECTIVE_GOTO_AREA_ON_FOOT: + case OBJECTIVE_RUN_TO_AREA: + return; + default: + m_prevObjective = m_objective; + } +} + +void +CPed::ForceStoredObjective(eObjective objective) +{ + if (objective != OBJECTIVE_ENTER_CAR_AS_DRIVER && objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) { + m_prevObjective = m_objective; + return; + } + + switch (m_objective) + { + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + case OBJECTIVE_GOTO_AREA_ON_FOOT: + case OBJECTIVE_RUN_TO_AREA: + return; + default: + m_prevObjective = m_objective; + } +} + +bool +CPed::IsTemporaryObjective(eObjective objective) +{ + return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER || +#ifdef VC_PED_PORTS + objective == OBJECTIVE_LEAVE_CAR_AND_DIE || +#endif + objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER; +} + +void +CPed::SetObjective(eObjective newObj) +{ + if (DyingOrDead()) + return; + + if (newObj == OBJECTIVE_NONE) { + if ((m_objective == OBJECTIVE_LEAVE_CAR || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER +#ifdef VC_PED_PORTS + || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) + && !IsPlayer() +#else + ) +#endif + && !IsPedInControl()) { + + bStartWanderPathOnFoot = true; + return; + } + // Unused code from assembly... + /* + else if(m_objective == OBJECTIVE_FLEE_CAR) { + + } else { + + } + */ + m_objective = OBJECTIVE_NONE; + m_prevObjective = OBJECTIVE_NONE; + } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) { + SetObjectiveTimer(0); + + if (m_objective == newObj) + return; + + if (IsTemporaryObjective(m_objective)) { + m_prevObjective = newObj; + } else { + if (m_objective != newObj) + SetStoredObjective(); + + m_objective = newObj; + } + bObjectiveCompleted = false; + + switch (newObj) { + case OBJECTIVE_NONE: + m_prevObjective = OBJECTIVE_NONE; + break; + case OBJECTIVE_HAIL_TAXI: + m_nWaitTimer = 0; + SetIdle(); + SetMoveState(PEDMOVE_STILL); + break; + default: + break; + } + } +} + +void +CPed::SetObjective(eObjective newObj, void *entity) +{ + if (DyingOrDead()) + return; + + if (m_prevObjective == newObj) { + // Why? + if (m_prevObjective != OBJECTIVE_NONE) + return; + } + + if (entity == this) + return; + + SetObjectiveTimer(0); + if (m_objective == newObj) { + switch (newObj) { + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: + case OBJECTIVE_GOTO_AREA_ANY_MEANS: + case OBJECTIVE_GUARD_ATTACK: + if (m_pedInObjective == entity) + return; + + break; + case OBJECTIVE_LEAVE_CAR: + case OBJECTIVE_FLEE_CAR: +#ifdef VC_PED_PORTS + case OBJECTIVE_LEAVE_CAR_AND_DIE: +#endif + return; + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + case OBJECTIVE_DESTROY_CAR: + case OBJECTIVE_SOLICIT_VEHICLE: + case OBJECTIVE_BUY_ICE_CREAM: + if (m_carInObjective == entity) + return; + + break; + case OBJECTIVE_SET_LEADER: + if (m_leader == entity) + return; + + break; + default: + break; + } + } else { + if ((newObj == OBJECTIVE_LEAVE_CAR +#ifdef VC_PED_PORTS + || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE +#endif + ) && !bInVehicle) + return; + } + +#ifdef VC_PED_PORTS + ClearPointGunAt(); +#endif + bObjectiveCompleted = false; + if (IsTemporaryObjective(m_objective) && !IsTemporaryObjective(newObj)) { + m_prevObjective = newObj; + } else { + if (m_objective != newObj) { + if (IsTemporaryObjective(newObj)) + ForceStoredObjective(newObj); + else + SetStoredObjective(); + } + m_objective = newObj; + } + + switch (newObj) { + case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: + + // In this special case, entity parameter isn't CEntity, but int. + SetObjectiveTimer((uintptr)entity); + break; + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + case OBJECTIVE_MUG_CHAR: + m_pNextPathNode = nil; + bUsePedNodeSeek = false; + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); + m_pedInObjective = (CPed*)entity; + m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); + m_pLookTarget = (CEntity*)entity; + m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget); + break; + case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + case OBJECTIVE_GUARD_ATTACK: + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); + m_pedInObjective = (CPed*)entity; + m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); + break; + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: + m_pedInObjective = (CPed*)entity; + m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); + m_pedFormation = FORMATION_REAR; + break; + case OBJECTIVE_LEAVE_CAR: +#ifdef VC_PED_PORTS + case OBJECTIVE_LEAVE_CAR_AND_DIE: +#endif + case OBJECTIVE_FLEE_CAR: + m_carInObjective = (CVehicle*)entity; + m_carInObjective->RegisterReference((CEntity **)&m_carInObjective); + if (m_carInObjective->bIsBus && m_leaveCarTimer == 0) { + for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) { + if (m_carInObjective->pPassengers[i] == this) { + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i; + break; + } + } + } + + break; + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + if (m_nMoveState == PEDMOVE_STILL) + SetMoveState(PEDMOVE_RUN); + + if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer()) { + RestorePreviousObjective(); + break; + } + // fall through + case OBJECTIVE_DESTROY_CAR: + case OBJECTIVE_SOLICIT_VEHICLE: + case OBJECTIVE_BUY_ICE_CREAM: + m_carInObjective = (CVehicle*)entity; + m_carInObjective->RegisterReference((CEntity**)&m_carInObjective); + m_pSeekTarget = m_carInObjective; + m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget); + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); + if (newObj == OBJECTIVE_SOLICIT_VEHICLE) { + m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; + } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR && + (m_carInObjective->GetStatus() == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->ArePlayerControlsDisabled())) { + SetObjectiveTimer(14000); + } else { + m_objectiveTimer = 0; + } + break; + case OBJECTIVE_SET_LEADER: + SetLeader((CEntity*)entity); + RestorePreviousObjective(); + break; + default: + break; + } +} + +void +CPed::SetObjective(eObjective newObj, CVector dest, float safeDist) +{ + if (DyingOrDead()) + return; + + if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj) + return; + + SetObjectiveTimer(0); + if (m_objective == newObj) { + if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) { + if (m_nextRoutePointPos == dest && m_distanceToCountSeekDone == safeDist) + return; + } else if (newObj == OBJECTIVE_GUARD_SPOT) { + if (m_vecSeekPosEx == dest && m_distanceToCountSeekDoneEx == safeDist) + return; + } + } + +#ifdef VC_PED_PORTS + ClearPointGunAt(); +#endif + bObjectiveCompleted = false; + if (IsTemporaryObjective(m_objective)) { + m_prevObjective = newObj; + } else { + if (m_objective != newObj) + SetStoredObjective(); + + m_objective = newObj; + } + + if (newObj == OBJECTIVE_GUARD_SPOT) { + m_vecSeekPosEx = dest; + m_distanceToCountSeekDoneEx = safeDist; + } else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) { + m_pNextPathNode = nil; + m_nextRoutePointPos = dest; + m_vecSeekPos = m_nextRoutePointPos; + bUsePedNodeSeek = true; + } +} + +// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode +// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call... +void +CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType) +{ + if (DyingOrDead()) + return; + + if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE) + return; + + SetObjectiveTimer(0); + + if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType) + return; + + bObjectiveCompleted = false; + if (IsTemporaryObjective(m_objective)) { + m_prevObjective = newObj; + } else { + if (m_objective != newObj) + SetStoredObjective(); + + m_objective = newObj; + } + + if (newObj == OBJECTIVE_FOLLOW_ROUTE) { + SetFollowRoute(routePoint, routeType); + } +} + +void +CPed::SetObjective(eObjective newObj, CVector dest) +{ + if (DyingOrDead()) + return; + + if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj) + return; + + SetObjectiveTimer(0); + if (m_objective == newObj) { + if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) { + if (m_nextRoutePointPos == dest) + return; + } else if (newObj == OBJECTIVE_GUARD_SPOT) { + if (m_vecSeekPosEx == dest) + return; + } + } + +#ifdef VC_PED_PORTS + ClearPointGunAt(); +#endif + bObjectiveCompleted = false; + switch (newObj) { + case OBJECTIVE_GUARD_SPOT: + m_vecSeekPosEx = dest; + m_distanceToCountSeekDoneEx = 5.0f; + SetMoveState(PEDMOVE_STILL); + break; + case OBJECTIVE_GUARD_AREA: + case OBJECTIVE_WAIT_IN_CAR: + case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: + case OBJECTIVE_LEAVE_CAR: + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + case OBJECTIVE_FOLLOW_CAR_IN_CAR: + case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE: + case OBJECTIVE_DESTROY_OBJECT: + case OBJECTIVE_DESTROY_CAR: + break; + case OBJECTIVE_GOTO_AREA_ANY_MEANS: + case OBJECTIVE_GOTO_AREA_ON_FOOT: + bIsRunning = false; + m_pNextPathNode = nil; + m_nextRoutePointPos = dest; + m_vecSeekPos = m_nextRoutePointPos; + m_distanceToCountSeekDone = 0.5f; + bUsePedNodeSeek = true; + if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) + return; + break; + case OBJECTIVE_RUN_TO_AREA: + bIsRunning = true; + m_pNextPathNode = nil; + m_nextRoutePointPos = dest; + m_vecSeekPos = m_nextRoutePointPos; + m_distanceToCountSeekDone = 0.5f; + bUsePedNodeSeek = true; + if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) + return; + break; + default: break; + } + + if (IsTemporaryObjective(m_objective)) { + m_prevObjective = newObj; + } else { + if (m_objective != newObj) + SetStoredObjective(); + + m_objective = newObj; + } +} + +void +CPed::ClearObjective(void) +{ + if (IsPedInControl() || m_nPedState == PED_DRIVING) { + m_objective = OBJECTIVE_NONE; +#ifdef VC_PED_PORTS + m_pedInObjective = nil; + m_carInObjective = nil; +#endif + if (m_nPedState == PED_DRIVING && m_pMyVehicle) { + + if (m_pMyVehicle->pDriver != this) { +#if defined VC_PED_PORTS || defined FIX_BUGS + if(!IsPlayer()) +#endif + bWanderPathAfterExitingCar = true; + + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } +#ifdef VC_PED_PORTS + m_nLastPedState = PED_NONE; +#endif + } else { + SetIdle(); + SetMoveState(PEDMOVE_STILL); + } + } else { + bClearObjective = true; + } +} + +void +CPed::ClearLeader(void) +{ + if (!m_leader) + return; + + m_leader = nil; + if (IsPedInControl()) { + SetObjective(OBJECTIVE_NONE); + if (CharCreatedBy == MISSION_CHAR) { + SetIdle(); + } else { + SetWanderPath(CGeneral::GetRandomNumberInRange(0,8)); + } + } else if (m_objective != OBJECTIVE_NONE) { + bClearObjective = true; + } +} + +void +CPed::UpdateFromLeader(void) +{ + if (CTimer::GetTimeInMilliseconds() <= m_objectiveTimer) + return; + + if (!m_leader) + return; + + CVector leaderDist; + if (m_leader->InVehicle()) + leaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition(); + else + leaderDist = m_leader->GetPosition() - GetPosition(); + + if (leaderDist.Magnitude() > 30.0f) { + if (IsPedInControl()) { + SetObjective(OBJECTIVE_NONE); + SetIdle(); + SetMoveState(PEDMOVE_STILL); + } + SetLeader(nil); + return; + } + + if (IsPedInControl()) { + if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) + WarpPedToNearLeaderOffScreen(); + + if (m_leader->m_nPedState == PED_DEAD) { + SetLeader(nil); + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); + return; + } + if (!m_leader->bInVehicle) { + if (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { + if (bInVehicle) { + if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && m_objective != OBJECTIVE_LEAVE_CAR) + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + + return; + } + if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { + RestorePreviousObjective(); + RestorePreviousState(); + } + } + if (m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy == RANDOM_CHAR) { + SetLeader(nil); + return; + } + } + if (!bInVehicle && m_leader->bInVehicle && m_leader->m_nPedState == PED_DRIVING) { + if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { + if (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers) + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle); + } + } else if (m_leader->m_objective == OBJECTIVE_NONE || (m_leader->IsPlayer() && m_leader->m_objective == OBJECTIVE_WAIT_ON_FOOT) + || m_objective == m_leader->m_objective) { + + if (m_leader->m_nPedState == PED_ATTACK) { + CEntity *lookTargetOfLeader = m_leader->m_pLookTarget; + if (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT + && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) { + + SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader); + SetObjectiveTimer(8000); + SetLookFlag(m_leader->m_pLookTarget, false); + SetLookTimer(500); + } + } else { + if (IsPedInControl() && m_nPedState != PED_ATTACK) { +#ifndef VC_PED_PORTS + SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); + SetObjectiveTimer(0); +#else + if (m_leader->m_objective == OBJECTIVE_NONE && m_objective == OBJECTIVE_NONE + && m_leader->m_nPedState == PED_CHAT && m_nPedState == PED_CHAT) { + + SetObjective(OBJECTIVE_NONE); + } else { + SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); + SetObjectiveTimer(0); + } +#endif + } + if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) { + if (ScanForThreats() && m_threatEntity) { + m_pLookTarget = m_threatEntity; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + TurnBody(); + if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) { + m_pPointGunAt = m_threatEntity; + if (m_threatEntity) + m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt); + SetAttack(m_threatEntity); + } + } + } + } + } else { + switch (m_leader->m_objective) { + case OBJECTIVE_WAIT_ON_FOOT: + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: + case OBJECTIVE_WAIT_IN_CAR: + case OBJECTIVE_FOLLOW_ROUTE: + SetObjective(m_leader->m_objective); + m_objectiveTimer = m_leader->m_objectiveTimer; + break; + case OBJECTIVE_GUARD_SPOT: + SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx); + m_objectiveTimer = m_leader->m_objectiveTimer; + break; + case OBJECTIVE_KILL_CHAR_ON_FOOT: + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + if (m_leader->m_pedInObjective) { + SetObjective(m_leader->m_objective, m_leader->m_pedInObjective); + m_objectiveTimer = m_leader->m_objectiveTimer; + } + break; + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + if (m_leader->m_carInObjective) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective); + return; + } + break; + case OBJECTIVE_GUARD_ATTACK: + return; + case OBJECTIVE_HAIL_TAXI: + m_leader = nil; + SetObjective(OBJECTIVE_NONE); + break; + default: + SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader); + SetObjectiveTimer(0); + break; + } + } + } else if (bInVehicle) { + if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) { + + switch (m_leader->m_objective) { + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + if (m_pMyVehicle == m_leader->m_pMyVehicle || m_pMyVehicle == m_leader->m_carInObjective) + break; + + // fall through + default: + if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_CAR) { +#ifdef VC_PED_PORTS + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250; +#endif + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } + + break; + } + } + } +} + +void +CPed::RestorePreviousObjective(void) +{ + if (m_objective == OBJECTIVE_NONE) + return; + + if (m_objective != OBJECTIVE_LEAVE_CAR && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER +#if defined VC_PED_PORTS || defined FIX_BUGS + && m_nPedState != PED_CARJACK +#endif + ) + m_pedInObjective = nil; + + if (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) { + m_objective = OBJECTIVE_NONE; + if (m_pMyVehicle) + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + + } else { + m_objective = m_prevObjective; + m_prevObjective = OBJECTIVE_NONE; + } + bObjectiveCompleted = false; +} + +void +CPed::ProcessObjective(void) +{ + if (bClearObjective && (IsPedInControl() || m_nPedState == PED_DRIVING)) { + ClearObjective(); + bClearObjective = false; + } + UpdateFromLeader(); + + CVector carOrOurPos; + CVector targetCarOrHisPos; + CVector distWithTarget; + + if (m_objective != OBJECTIVE_NONE && (IsPedInControl() || m_nPedState == PED_DRIVING)) { + if (bInVehicle) { + if (!m_pMyVehicle) { + bInVehicle = false; + return; + } + carOrOurPos = m_pMyVehicle->GetPosition(); + } else { + carOrOurPos = GetPosition(); + } + + if (m_pedInObjective) { + if (m_pedInObjective->InVehicle() && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { + targetCarOrHisPos = m_pedInObjective->m_pMyVehicle->GetPosition(); + } else { + targetCarOrHisPos = m_pedInObjective->GetPosition(); + } + distWithTarget = targetCarOrHisPos - carOrOurPos; + } else if (m_carInObjective) { + targetCarOrHisPos = m_carInObjective->GetPosition(); + distWithTarget = targetCarOrHisPos - carOrOurPos; + } + + switch (m_objective) { + case OBJECTIVE_NONE: + case OBJECTIVE_GUARD_AREA: + case OBJECTIVE_FOLLOW_CAR_IN_CAR: + case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE: + case OBJECTIVE_DESTROY_OBJECT: + case OBJECTIVE_GOTO_AREA_IN_CAR: + case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: + case OBJECTIVE_SET_LEADER: + break; + case OBJECTIVE_WAIT_ON_FOOT: + SetIdle(); + m_objective = OBJECTIVE_NONE; + SetMoveState(PEDMOVE_STILL); + break; + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: + if (InVehicle()) { + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + bFleeAfterExitingCar = true; + } else if (m_nPedState != PED_FLEE_POS) { + CVector2D fleePos = GetPosition(); + SetFlee(fleePos, 10000); + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + } + break; + case OBJECTIVE_GUARD_SPOT: + { + distWithTarget = m_vecSeekPosEx - GetPosition(); + if (m_pedInObjective) { + SetLookFlag(m_pedInObjective, true); + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + TurnBody(); + } + float distWithTargetSc = distWithTarget.Magnitude(); + if (2.0f * m_distanceToCountSeekDoneEx >= distWithTargetSc) { + if (m_pedInObjective) { + if (distWithTargetSc <= m_distanceToCountSeekDoneEx) + SetIdle(); + else + SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx); + } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { + int threatType = ScanForThreats(); + SetLookTimer(CGeneral::GetRandomNumberInRange(500, 1500)); + + // Second condition is pointless and isn't there in Mobile. + if (threatType == PED_FLAG_GUN || (threatType == PED_FLAG_EXPLOSION && m_threatEntity) || m_threatEntity) { + if (m_threatEntity->IsPed()) + SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity); + } + } + } else { + SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx); + } + break; + } + case OBJECTIVE_WAIT_IN_CAR: + m_nPedState = PED_DRIVING; + break; + case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: + m_nPedState = PED_DRIVING; + break; + case OBJECTIVE_KILL_CHAR_ANY_MEANS: + { + if (m_pedInObjective) { + if (m_pedInObjective->IsPlayer() && CharCreatedBy != MISSION_CHAR + && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops != 0 + && !bKindaStayInSamePlace) { + + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); + break; + } + if (InVehicle()) { + if (distWithTarget.Magnitude() >= 20.0f + || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() >= sq(0.02f)) { + if (m_pMyVehicle->pDriver == this + && !m_pMyVehicle->m_nGettingInFlags) { + 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_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_nCarMission = MISSION_RAMPLAYER_FARAWAY; + } + m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + } + } else { + bool targetHasVeh = m_pedInObjective->bInVehicle; + if (!targetHasVeh + || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) { + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } + } + break; + } + if (distWithTarget.Magnitude() > 30.0f && !bKindaStayInSamePlace) { + if (m_pMyVehicle) { + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); + } else { + float closestVehDist = 60.0f; + int16 lastVehicle; + CEntity* vehicles[8]; + CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + CVehicle *foundVeh = nil; + for(int i = 0; i < lastVehicle; i++) { + CVehicle *nearVeh = (CVehicle*)vehicles[i]; + /* + Not used. + CVector vehSpeed = nearVeh->GetSpeed(); + CVector ourSpeed = GetSpeed(); + */ + CVector vehDistVec = nearVeh->GetPosition() - GetPosition(); + if (vehDistVec.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh + && nearVeh->CanPedOpenLocks(this)) { + + foundVeh = nearVeh; + closestVehDist = vehDistVec.Magnitude(); + } + } + m_pMyVehicle = foundVeh; + if (m_pMyVehicle) { + m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); + } else if (!GetIsOnScreen()) { + CVector ourPos = GetPosition(); + int closestNode = ThePaths.FindNodeClosestToCoors(ourPos, PATH_CAR, 20.0f); + if (closestNode >= 0) { + int16 colliding; + CWorld::FindObjectsKindaColliding( + ThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false); + if (!colliding) { + CZoneInfo zoneInfo; + int chosenCarClass; + CTheZones::GetZoneInfoForTimeOfDay(&ourPos, &zoneInfo); + int chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &ourPos, &chosenCarClass); + CAutomobile *newVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE); + if (newVeh) { + newVeh->GetMatrix().GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition(); + newVeh->GetMatrix().GetPosition().z += 4.0f; + newVeh->SetHeading(DEGTORAD(200.0f)); + newVeh->SetStatus(STATUS_ABANDONED); + newVeh->m_nDoorLock = CARLOCK_UNLOCKED; + CWorld::Add(newVeh); + m_pMyVehicle = newVeh; + if (m_pMyVehicle) { + m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); + } + } + } + } + } + } + break; + } + } else { + ClearLookFlag(); + bObjectiveCompleted = true; + } + } + case OBJECTIVE_KILL_CHAR_ON_FOOT: + { + bool killPlayerInNoPoliceZone = false; + if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) { + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + break; + } + if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) { + ClearLookFlag(); + bObjectiveCompleted = true; + SetMoveAnim(); + break; + } + if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice()) + killPlayerInNoPoliceZone = true; + + if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) { + if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee() && !GetWeapon()->IsTypeMelee()) + bNotAllowedToDuck = true; + } else { + if (!m_pedInObjective->bInVehicle) { + if (m_pedInObjective->GetWeapon()->IsTypeMelee() || GetWeapon()->IsTypeMelee()) { + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + } else if (DuckAndCover()) { + break; + } + } else { + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + } + } + if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) { + SetMoveState(PEDMOVE_STILL); + break; + } + if (m_pedInObjective->IsPlayer()) { + CPlayerPed *player = FindPlayerPed(); + if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops + || player->m_pWanted->m_bIgnoredByEveryone + || m_pedInObjective->bIsInWater + || m_pedInObjective->m_nPedState == PED_ARRESTED) { + + if (m_nPedState != PED_ARREST_PLAYER) + SetIdle(); + + break; + } + } + CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + float wepRange = wepInfo->m_fRange; + float wepRangeAdjusted; + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { + wepRangeAdjusted = wepRange / 3.0f; + } else { + if (m_nPedState == PED_FIGHT) { + if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK)) + wepRange = 2.0f; + } else { + wepRange = 1.3f; + } + wepRangeAdjusted = wepRange; + } + if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) { + wepRangeAdjusted = 2.5f; + } + if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP + && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) { + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); + break; + } + if (m_pedInObjective->m_fHealth <= 0.0f) { + bObjectiveCompleted = true; + bScriptObjectiveCompleted = true; + SetMoveAnim(); + break; + } + float distWithTargetSc = distWithTarget.Magnitude(); + if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { + CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle; + if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED + || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) { + SetIdle(); + return; + } + SetLookFlag(vehOfTarget, false); + if (m_nPedState != PED_CARJACK) { + if (m_pedInObjective->m_nPedState != PED_ARRESTED) { + if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE + && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) { + + // I hope so + CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); + CVector maxShotPos = vehOfTarget->GetPosition() - ourHead; + maxShotPos.Normalise(); + maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead; + + CWorld::bIncludeDeadPeds = true; + CColPoint foundCol; + CEntity *foundEnt; + CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, + true, true, true, true, false, true, false); + CWorld::bIncludeDeadPeds = false; + if (foundEnt == vehOfTarget) { + SetAttack(vehOfTarget); + m_pPointGunAt = vehOfTarget; + if (vehOfTarget) + vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt); + + SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); + if (distWithTargetSc <= m_distanceToCountSeekDone) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500)); + SetMoveState(PEDMOVE_STILL); + } else { + SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); + } + } + } + else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) { + if (vehOfTarget) { + if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) { + GoToNearestDoor(vehOfTarget); + } else { + m_vehEnterType = 0; + if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) { + m_vehEnterType = CAR_DOOR_LF; + } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) { + m_vehEnterType = CAR_DOOR_RF; + } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) { + m_vehEnterType = CAR_DOOR_LR; + } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) { + m_vehEnterType = CAR_DOOR_RR; + } + // Unused + // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType); + SetSeekCar(vehOfTarget, m_vehEnterType); + SetMoveState(PEDMOVE_RUN); + } + } + } + } + } + SetMoveAnim(); + break; + } + if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) { + SetLookFlag(m_pedInObjective, false); + TurnBody(); + } + if (m_nPedType == PEDTYPE_COP && distWithTargetSc < 1.5f && m_pedInObjective->IsPlayer()) { + if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() + || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) { + + ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective); + return; + } + } + if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) { + if (distWithTargetSc > wepRange + || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() + || m_pedInObjective->m_nPedState == PED_ARRESTED + || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f + || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) { + + if (m_pedInObjective->EnteringCar()) + wepRangeAdjusted = 2.0f; + + if (bUsePedNodeSeek) { + CVector bestCoords(0.0f, 0.0f, 0.0f); + m_vecSeekPos = m_pedInObjective->GetPosition(); + + if (!m_pNextPathNode) + FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); + + if (m_pNextPathNode) + m_vecSeekPos = m_pNextPathNode->GetPosition(); + + SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); + } else { + SetSeek(m_pedInObjective, wepRangeAdjusted); + } + bCrouchWhenShooting = false; + if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) { + if (wepRange <= 5.0f) { + if (m_pedInObjective->IsPlayer() + && FindPlayerPed()->m_bSpeedTimerFlag + && (IsGangMember() || m_nPedType == PEDTYPE_COP) + && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { + GiveWeapon(WEAPONTYPE_COLT45, 1000); + SetCurrentWeapon(WEAPONTYPE_COLT45); + } + } else { + bStopAndShoot = true; + } + SetMoveState(PEDMOVE_STILL); + SetMoveAnim(); + break; + } + bStopAndShoot = false; + SetMoveAnim(); + break; + } + } + if (m_attackTimer < CTimer::GetTimeInMilliseconds() + && distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { + if (bIsDucking) { + CAnimBlendAssociation *duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); + if (duckAnim) { + duckAnim->blendDelta = -2.0f; + break; + } + bIsDucking = false; + } else if (wepRange <= 5.0f) { + SetMoveState(PEDMOVE_STILL); + SetAttack(m_pedInObjective); + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, + GetPosition().x, GetPosition().y); + SetShootTimer(CGeneral::GetRandomNumberInRange(0.0f, 500.0f)); + SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f)); + bObstacleShowedUpDuringKillObjective = false; + + } else { + CVector target; + CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); + if (m_pedInObjective->IsPed()) + m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID); + else + target = m_pedInObjective->GetPosition(); + + target -= ourHead; + target.Normalise(); + target = target * wepInfo->m_fRange + ourHead; + + CWorld::bIncludeDeadPeds = true; + CEntity *foundEnt = nil; + CColPoint foundCol; + + CWorld::ProcessLineOfSight( + ourHead, target, foundCol, foundEnt, + true, true, true, false, true, false); + CWorld::bIncludeDeadPeds = 0; + if (foundEnt == m_pedInObjective) { + SetAttack(m_pedInObjective); + m_pPointGunAt = m_pedInObjective; + if (m_pedInObjective) + m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt); + + SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f)); + + int time; + if (distWithTargetSc <= wepRangeAdjusted) + time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f); + else + time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f); + + SetAttackTimer(time); + bObstacleShowedUpDuringKillObjective = false; + + } else if (foundEnt) { + if (foundEnt->IsPed()) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); + bObstacleShowedUpDuringKillObjective = false; + } else { + if (foundEnt->IsObject()) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f)); + bObstacleShowedUpDuringKillObjective = true; + } else if (foundEnt->IsVehicle()) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f)); + bObstacleShowedUpDuringKillObjective = true; + } else { + SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f)); + bObstacleShowedUpDuringKillObjective = true; + } + } + + m_fleeFrom = foundEnt; + m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom); + SetPointGunAt(m_pedInObjective); + } + } + } else { + if (!m_pedInObjective->m_pCurrentPhysSurface) + bStopAndShoot = false; + + if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { + + // This is weird... + if (bNotAllowedToDuck && bKindaStayInSamePlace) { + if (!bIsDucking) { + CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); + if (!duckAnim || duckAnim->blendDelta < 0.0f) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f); + bIsDucking = true; + } + break; + } else { + CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); + if (!duckAnim || duckAnim->blendDelta < 0.0f) { + bIsDucking = false; + } else { + break; + } + } + } + if (bObstacleShowedUpDuringKillObjective) { + if (m_nPedType == PEDTYPE_COP) { + if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45 + || m_fleeFrom && m_fleeFrom->IsObject()) { + wepRangeAdjusted = 6.0f; + } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) { + wepRangeAdjusted = 4.0f; + } else { + wepRangeAdjusted = 2.0f; + } + } else { + wepRangeAdjusted = 2.0f; + } + } + if (distWithTargetSc <= wepRangeAdjusted) { + SetMoveState(PEDMOVE_STILL); + bIsPointingGunAt = true; + if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) { + m_attackTimer = CTimer::GetTimeInMilliseconds(); + SetIdle(); + } + } else { + if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS + && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) { + Say(SOUND_PED_ATTACK); + SetSeek(m_pedInObjective, wepRangeAdjusted); + bIsRunning = true; + } + } + } + } + + if (distWithTargetSc < 2.5f && wepRange > 5.0f + && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE) { + + SetAttack(m_pedInObjective); + if (m_attackTimer < CTimer::GetTimeInMilliseconds()) { + int time = CGeneral::GetRandomNumberInRange(500.0f, 1000.0f); + SetAttackTimer(time); + SetShootTimer(time - 500); + } + SetMoveState(PEDMOVE_STILL); + } + if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y); + + SetMoveAnim(); + break; + } + case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: + case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: + { + if (InVehicle()) { + if (m_nPedState == PED_DRIVING) + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } else if (m_nPedState != PED_FLEE_ENTITY) { + int time; + if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) + time = 0; + else + time = 6000; + + SetFindPathAndFlee(m_pedInObjective, time); + } + break; + } + case OBJECTIVE_GOTO_CHAR_ON_FOOT: + { + if (m_pedInObjective) { + float safeDistance = 2.0f; + if (m_pedInObjective->bInVehicle) + safeDistance = 3.0f; + + float distWithTargetSc = distWithTarget.Magnitude(); + if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) { + if (distWithTargetSc <= safeDistance) { + bScriptObjectiveCompleted = true; + if (m_nPedState != PED_ATTACK) { + SetIdle(); + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + TurnBody(); + } + if (distWithTargetSc > 2.0f) + SetMoveState(m_pedInObjective->m_nMoveState); + else + SetMoveState(PEDMOVE_STILL); + } else { + SetSeek(m_pedInObjective, safeDistance); + if (distWithTargetSc >= 5.0f) { + if (m_leader && m_leader->m_nMoveState == PEDMOVE_SPRINT) + SetMoveState(PEDMOVE_SPRINT); + else + SetMoveState(PEDMOVE_RUN); + } else { + if (m_leader && m_leader->m_nMoveState != PEDMOVE_STILL + && m_leader->m_nMoveState != PEDMOVE_NONE) { + if (m_leader->IsPlayer()) { + if (distWithTargetSc >= 3.0f && FindPlayerPed()->m_fMoveSpeed >= 1.3f) + SetMoveState(PEDMOVE_RUN); + else + SetMoveState(PEDMOVE_WALK); + } else { + SetMoveState(m_leader->m_nMoveState); + } + } else if (distWithTargetSc <= 3.0f) { + SetMoveState(PEDMOVE_WALK); + } else { + SetMoveState(PEDMOVE_RUN); + } + } + } + } + } else { + SetObjective(OBJECTIVE_NONE); + } + break; + } + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: + { + if (m_pedInObjective) { + CVector posToGo = GetFormationPosition(); + distWithTarget = posToGo - carOrOurPos; + SetSeek(posToGo, 1.0f); + if (distWithTarget.Magnitude() <= 3.0f) { + SetSeek(posToGo, 1.0f); + if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) + SetMoveState(m_pedInObjective->m_nMoveState); + } else { + SetSeek(posToGo, 1.0f); + SetMoveState(PEDMOVE_RUN); + } + } else { + SetObjective(OBJECTIVE_NONE); + } + break; + } + case OBJECTIVE_ENTER_CAR_AS_PASSENGER: + { + if (m_carInObjective) { + if (!bInVehicle && m_carInObjective->m_nNumPassengers >= m_carInObjective->m_nNumMaxPassengers) { + RestorePreviousObjective(); + RestorePreviousState(); + if (IsPedInControl()) + m_pMyVehicle = nil; + + break; + } + + if (m_prevObjective == OBJECTIVE_HAIL_TAXI && !((CAutomobile*)m_carInObjective)->bTaxiLight) { + RestorePreviousObjective(); + ClearObjective(); + SetWanderPath(CGeneral::GetRandomNumber() & 7); + bIsRunning = false; + break; + } + if (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) { + if (!EnteringCar()) { + bool foundSeat = false; + if (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) { + if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) { + if (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) { + foundSeat = false; + } else { + m_vehEnterType = CAR_DOOR_RR; + foundSeat = true; + } + } else { + m_vehEnterType = CAR_DOOR_LR; + foundSeat = true; + } + } else { + m_vehEnterType = CAR_DOOR_RF; + foundSeat = true; + } + for (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) { + if (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) { + m_vehEnterType = CAR_DOOR_RF; + foundSeat = true; + } + } + if (foundSeat) { + SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType)); + SetEnterCar(m_carInObjective, m_vehEnterType); + } + } + m_objectiveTimer = 0; + } + } + // fall through + } + case OBJECTIVE_ENTER_CAR_AS_DRIVER: + { + if (!m_carInObjective || bInVehicle) { +#ifdef VC_PED_PORTS + if (bInVehicle && m_pMyVehicle != m_carInObjective) { + SetExitCar(m_pMyVehicle, 0); + } else +#endif + { + bObjectiveCompleted = true; + bScriptObjectiveCompleted = true; + RestorePreviousState(); + } + } else { + if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) { + SetMoveState(PEDMOVE_STILL); + break; + } + if (IsPedInControl()) { + if (m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { + if (distWithTarget.Magnitude() < 20.0f) { + RestorePreviousObjective(); + RestorePreviousState(); + return; + } + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + if (m_carInObjective->pDriver +#ifdef VC_PED_PORTS + && !IsPlayer() +#endif + ) { + if (m_carInObjective->pDriver->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS && m_carInObjective->pDriver != m_pedInObjective) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective); + m_carInObjective->bIsBeingCarJacked = false; + } + } + } + } else if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) { + if (m_carInObjective->pDriver +#ifdef VC_PED_PORTS + && (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR) +#endif + ) { + if (m_carInObjective->pDriver->m_nPedType == m_nPedType) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective); + m_carInObjective->bIsBeingCarJacked = false; + } + } + } + if (m_carInObjective->IsUpsideDown() && m_carInObjective->m_vehType != VEHICLE_TYPE_BIKE) { + RestorePreviousObjective(); + RestorePreviousState(); + return; + } + if (!m_carInObjective->IsBoat() || m_nPedState == PED_SEEK_IN_BOAT) { + if (m_nPedState != PED_SEEK_CAR) + SetSeekCar(m_carInObjective, 0); + } else { + SetSeekBoatPosition(m_carInObjective); + } + if (m_nMoveState == PEDMOVE_STILL && !bVehEnterDoorIsBlocked) + SetMoveState(PEDMOVE_RUN); + + if (m_carInObjective && m_carInObjective->m_fHealth > 0.0f) { + distWithTarget = m_carInObjective->GetPosition() - GetPosition(); + if (!bInVehicle) { + if (nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST < distWithTarget.Magnitude()) { + if (!m_carInObjective->pDriver && !m_carInObjective->GetIsOnScreen() && !GetIsOnScreen()) + WarpPedToNearEntityOffScreen(m_carInObjective); + + if (CharCreatedBy != MISSION_CHAR || m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS +#ifdef VC_PED_PORTS + || IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled() +#endif + ) { + RestorePreviousObjective(); + RestorePreviousState(); + if (IsPedInControl()) + m_pMyVehicle = nil; + } else { + SetIdle(); + SetMoveState(PEDMOVE_STILL); + } + } + } + } else if (!bInVehicle) { + RestorePreviousObjective(); + RestorePreviousState(); + if (IsPedInControl()) + m_pMyVehicle = nil; + } + } + } + break; + } + case OBJECTIVE_DESTROY_CAR: + { + if (!m_carInObjective) { + ClearLookFlag(); + bObjectiveCompleted = true; + break; + } + float distWithTargetSc = distWithTarget.Magnitude(); + CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + float wepRange = wepInfo->m_fRange; + m_pLookTarget = m_carInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + + m_pSeekTarget = m_carInObjective; + m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); + + TurnBody(); + if (m_carInObjective->m_fHealth <= 0.0f) { + ClearLookFlag(); + bScriptObjectiveCompleted = true; + break; + } + + if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE + && distWithTargetSc < wepRange) { + + // I hope so + CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); + CVector maxShotPos = m_carInObjective->GetPosition() - ourHead; + maxShotPos.Normalise(); + maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead; + + CWorld::bIncludeDeadPeds = true; + CColPoint foundCol; + CEntity *foundEnt; + CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, + true, true, true, true, false, true, false); + CWorld::bIncludeDeadPeds = false; + if (foundEnt == m_carInObjective) { + SetAttack(m_carInObjective); + m_pPointGunAt = m_carInObjective; + if (m_pPointGunAt) + m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt); + + SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); + if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); + } else { + SetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300)); + SetMoveState(PEDMOVE_STILL); + } + } + } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) { + + float safeDistance; + if (wepRange <= 5.0f) + safeDistance = 3.0f; + else + safeDistance = wepRange * 0.25f; + + SetSeek(m_carInObjective, safeDistance); + SetMoveState(PEDMOVE_RUN); + } + SetLookFlag(m_carInObjective, false); + TurnBody(); + break; + } + case OBJECTIVE_GOTO_AREA_ANY_MEANS: + { + distWithTarget = m_nextRoutePointPos - GetPosition(); + distWithTarget.z = 0.0f; + if (InVehicle()) { + CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos); + CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle); + if (distWithTarget.MagnitudeSqr() < sq(20.0f)) { + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } + break; + } + if (distWithTarget.Magnitude() > 30.0f) { + if (m_pMyVehicle) { + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + } else { + float closestVehDist = SQR(60.0f); + int16 lastVehicle; + CEntity* vehicles[8]; + CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + CVehicle* foundVeh = nil; + for (int i = 0; i < lastVehicle; i++) { + CVehicle* nearVeh = (CVehicle*)vehicles[i]; + /* + Not used. + CVector vehSpeed = nearVeh->GetSpeed(); + CVector ourSpeed = GetSpeed(); + */ + CVector vehDistVec = nearVeh->GetPosition() - GetPosition(); + if (vehDistVec.MagnitudeSqr() < closestVehDist + && m_pedInObjective->m_pMyVehicle != nearVeh) + { + foundVeh = nearVeh; + closestVehDist = vehDistVec.MagnitudeSqr(); + } + } + m_pMyVehicle = foundVeh; + if (m_pMyVehicle) { + m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); + } + } + break; + } + // fall through + } + case OBJECTIVE_GOTO_AREA_ON_FOOT: + case OBJECTIVE_RUN_TO_AREA: + { + if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) + && InVehicle()) { + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } else { + distWithTarget = m_nextRoutePointPos - GetPosition(); + distWithTarget.z = 0.0f; + if (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) { + bObjectiveCompleted = true; + bScriptObjectiveCompleted = true; + SetMoveState(PEDMOVE_STILL); + } else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) { + if (bUsePedNodeSeek) { + CVector bestCoords(0.0f, 0.0f, 0.0f); + m_vecSeekPos = m_nextRoutePointPos; + + if (!m_pNextPathNode) + FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); + + if (m_pNextPathNode) + m_vecSeekPos = m_pNextPathNode->GetPosition(); + } + SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); + } + } + + break; + } + case OBJECTIVE_GUARD_ATTACK: + { + if (m_pedInObjective) { + SetLookFlag(m_pedInObjective, true); + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + m_lookTimer = m_attackTimer; + TurnBody(); + float distWithTargetSc = distWithTarget.Magnitude(); + if (distWithTargetSc >= 20.0f) { + RestorePreviousObjective(); + } else if (m_attackTimer < CTimer::GetTimeInMilliseconds()) { + if (m_nPedState != PED_SEEK_ENTITY && distWithTargetSc >= 2.0f) { + SetSeek(m_pedInObjective, 1.0f); + } else { + SetAttack(m_pedInObjective); + SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1500.0f)); + } + SetAttackTimer(1000); + } + } else { + RestorePreviousObjective(); + } + break; + } + case OBJECTIVE_FOLLOW_ROUTE: + if (HaveReachedNextPointOnRoute(1.0f)) { + int nextPoint = GetNextPointOnRoute(); + m_nextRoutePointPos = CRouteNode::GetPointPosition(nextPoint); + } else { + SetSeek(m_nextRoutePointPos, 0.8f); + } + break; + case OBJECTIVE_SOLICIT_VEHICLE: + if (m_carInObjective) { + if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) { + if (!bInVehicle) { + SetObjective(OBJECTIVE_NONE); + SetWanderPath(CGeneral::GetRandomNumber() & 7); + m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; + if (IsPedInControl()) + m_pMyVehicle = nil; + } + } else { + if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT) + SetSeekCar(m_carInObjective, 0); + } + } else { + RestorePreviousObjective(); + RestorePreviousState(); + if (IsPedInControl()) + m_pMyVehicle = nil; + } + break; + case OBJECTIVE_HAIL_TAXI: + if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + Say(SOUND_PED_TAXI_WAIT); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TAXI, 4.0f); + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000; + } + break; + case OBJECTIVE_CATCH_TRAIN: + { + if (m_carInObjective) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective); + } else { + CVehicle* trainToEnter = nil; + float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST; + CVector pos = GetPosition(); + int16 lastVehicle; + CEntity* vehicles[8]; + + CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + for (int i = 0; i < lastVehicle; i++) { + CVehicle* nearVeh = (CVehicle*)vehicles[i]; + if (nearVeh->IsTrain()) { + CVector vehDistVec = GetPosition() - nearVeh->GetPosition(); + float vehDist = vehDistVec.Magnitude(); + if (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh) + { + trainToEnter = nearVeh; + closestCarDist = vehDist; + } + } + } + if (trainToEnter) { + m_carInObjective = trainToEnter; + m_carInObjective->RegisterReference((CEntity **) &m_carInObjective); + } + } + break; + } + case OBJECTIVE_BUY_ICE_CREAM: + if (m_carInObjective) { + if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM) + SetSeekCar(m_carInObjective, 0); + } else { + RestorePreviousObjective(); + RestorePreviousState(); + if (IsPedInControl()) + m_pMyVehicle = nil; + } + break; + case OBJECTIVE_STEAL_ANY_CAR: + { + if (bInVehicle) { + bScriptObjectiveCompleted = true; + RestorePreviousObjective(); + } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) { + CVehicle *carToSteal = nil; + float closestCarDist = ENTER_CAR_MAX_DIST; + CVector pos = GetPosition(); + int16 lastVehicle; + CEntity *vehicles[8]; + + // NB: This should've been ENTER_CAR_MAX_DIST actually, and is fixed in VC. + CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + for(int i = 0; i < lastVehicle; i++) { + CVehicle *nearVeh = (CVehicle*)vehicles[i]; + if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) { + if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) { + if (nearVeh->CanPedOpenLocks(this)) { + CVector vehDistVec = GetPosition() - nearVeh->GetPosition(); + float vehDist = vehDistVec.Magnitude(); + if (vehDist < closestCarDist) { + carToSteal = nearVeh; + closestCarDist = vehDist; + } + } + } + } + } + if (carToSteal) { + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal); + m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000; + } else { + RestorePreviousObjective(); + RestorePreviousState(); + } + } + break; + } + case OBJECTIVE_MUG_CHAR: + { + if (m_pedInObjective) { + if (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) { + ClearObjective(); + return; + } + if (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) { + ClearObjective(); + return; + } + if (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective); + SetMoveState(PEDMOVE_SPRINT); + return; + } + if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this + || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) { + ClearObjective(); + SetFindPathAndFlee(m_pedInObjective, 15000, true); + return; + } + float distWithTargetScSqr = distWithTarget.MagnitudeSqr(); + if (distWithTargetScSqr <= sq(10.0f)) { + if (distWithTargetScSqr <= sq(1.4f)) { + CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD); + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, + GetPosition().x, GetPosition().y); + + if (reloadAssoc || !m_pedInObjective->IsPedShootable()) { + if (reloadAssoc && + (!reloadAssoc->IsRunning() || reloadAssoc->currentTime / reloadAssoc->hierarchy->totalLength > 0.8f)) { + CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); + punchAssoc->flags |= ASSOC_DELETEFADEDOUT; + punchAssoc->flags |= ASSOC_FADEOUTWHENDONE; + CVector2D offset(distWithTarget.x, distWithTarget.y); + int dir = m_pedInObjective->GetLocalDirection(offset); + m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5); + m_pedInObjective->ReactToAttack(this); + m_pedInObjective->Say(SOUND_PED_ROBBED); + Say(SOUND_PED_MUGGING); + bRichFromMugging = true; + + // VC FIX: ClearObjective() clears m_pedInObjective in VC (also same with VC_PED_PORTS), so get it before call + CPed *victim = m_pedInObjective; + ClearObjective(); + if (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT + || victim->m_pedInObjective != this) { + SetFindPathAndFlee(victim, 15000, true); + m_nLastPedState = PED_WANDER_PATH; + } else { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim); + SetMoveState(PEDMOVE_SPRINT); + m_nLastPedState = PED_WANDER_PATH; + } + } + } else { + eWeaponType weaponType = GetWeapon()->m_eWeaponType; + if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT) + SetCurrentWeapon(WEAPONTYPE_UNARMED); + + CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_AK_RELOAD, 8.0f); + newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT; + newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE; + } + } else { + SetSeek(m_pedInObjective, 1.0f); + CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK); + + if (walkAssoc) + walkAssoc->speed = 1.3f; + } + } else { + ClearObjective(); + SetWanderPath(CGeneral::GetRandomNumber() & 7); + } + } else { +#ifdef VC_PED_PORTS + m_objective = OBJECTIVE_NONE; +#endif + ClearObjective(); + } + break; + } + case OBJECTIVE_FLEE_CAR: + if (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) { + RestorePreviousObjective(); + SetFlee(m_pMyVehicle, 6000); + break; + } + // fall through + case OBJECTIVE_LEAVE_CAR: + if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { + if (InVehicle() +#ifdef VC_PED_PORTS + && (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() + || bBusJacked) +#endif + ) { + if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN + && (m_nPedType != PEDTYPE_COP +#ifdef VC_PED_PORTS + || m_pMyVehicle->IsBoat() +#endif + || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) { + if (m_pMyVehicle->IsTrain()) + SetExitTrain(m_pMyVehicle); +#ifdef VC_PED_PORTS + else if (m_pMyVehicle->IsBoat()) + SetExitBoat(m_pMyVehicle); +#endif + else + SetExitCar(m_pMyVehicle, 0); + } + } else { + RestorePreviousObjective(); + } + } + break; +#ifdef VC_PED_PORTS + case OBJECTIVE_LEAVE_CAR_AND_DIE: + { + if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { + if (InVehicle()) { + if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN) { + if (m_pMyVehicle->IsBoat()) + SetExitBoat(m_pMyVehicle); + else if (m_pMyVehicle->bIsBus) + SetExitCar(m_pMyVehicle, 0); + else { + eCarNodes doorNode = CAR_DOOR_LF; + if (m_pMyVehicle->pDriver != this) { + if (m_pMyVehicle->pPassengers[0] == this) { + doorNode = CAR_DOOR_RF; + } else if (m_pMyVehicle->pPassengers[1] == this) { + doorNode = CAR_DOOR_LR; + } else if (m_pMyVehicle->pPassengers[2] == this) { + doorNode = CAR_DOOR_RR; + } + } + SetBeingDraggedFromCar(m_pMyVehicle, doorNode, false); + } + } + } + } + break; + } +#endif + } + if (bObjectiveCompleted + || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { + RestorePreviousObjective(); + if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer) + m_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1; + + if (CharCreatedBy != RANDOM_CHAR || bInVehicle) { + if (IsPedInControl()) + RestorePreviousState(); + } else { + SetWanderPath(CGeneral::GetRandomNumber() & 7); + } + ClearAimFlag(); + ClearLookFlag(); + } + } +} + +void +CPed::SetFollowRoute(int16 currentPoint, int16 routeType) +{ + m_routeLastPoint = currentPoint; + m_routeStartPoint = CRouteNode::GetRouteStart(currentPoint); + m_routePointsPassed = 0; + m_routeType = routeType; + m_routePointsBeingPassed = 1; + m_objective = OBJECTIVE_FOLLOW_ROUTE; + m_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute()); +} + +int +CPed::GetNextPointOnRoute(void) +{ + int16 nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint; + + // Route is complete + if (nextPoint < 0 || nextPoint > NUMPEDROUTES || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) { + + switch (m_routeType) { + case PEDROUTE_STOP_WHEN_DONE: + nextPoint = -1; + break; + case PEDROUTE_GO_BACKWARD_WHEN_DONE: + m_routePointsBeingPassed = -m_routePointsBeingPassed; + nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint; + break; + case PEDROUTE_GO_TO_START_WHEN_DONE: + m_routePointsPassed = -1; + nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint; + break; + default: + break; + } + } + return nextPoint; +} + +bool +CPed::HaveReachedNextPointOnRoute(float distToCountReached) +{ + if ((m_nextRoutePointPos - GetPosition()).Magnitude2D() >= distToCountReached) + return false; + + m_routePointsPassed += m_routePointsBeingPassed; + return true; +} + +bool +CPed::CanSeeEntity(CEntity *entity, float threshold) +{ + float neededAngle = CGeneral::GetRadianAngleBetweenPoints( + entity->GetPosition().x, + entity->GetPosition().y, + GetPosition().x, + GetPosition().y); + + if (neededAngle < 0.0f) + neededAngle += TWOPI; + else if (neededAngle > TWOPI) + neededAngle -= TWOPI; + + float ourAngle = m_fRotationCur; + if (ourAngle < 0.0f) + ourAngle += TWOPI; + else if (ourAngle > TWOPI) + ourAngle -= TWOPI; + + float neededTurn = Abs(neededAngle - ourAngle); + + return neededTurn < threshold || TWOPI - threshold < neededTurn; +} + +// Only used while deciding which gun ped should switch to, if no ammo left. +bool +CPed::SelectGunIfArmed(void) +{ + for (int i = 0; i < m_maxWeaponTypeAllowed; i++) { + if (GetWeapon(i).m_nAmmoTotal > 0) { + eWeaponType weaponType = GetWeapon(i).m_eWeaponType; + if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) { + SetCurrentWeapon(i); + return true; + } + } + } + SetCurrentWeapon(WEAPONTYPE_UNARMED); + return false; +} + +void +CPed::ReactToPointGun(CEntity *entWithGun) +{ + CPed *pedWithGun = (CPed*)entWithGun; + int waitTime; + + if (IsPlayer() || !IsPedInControl() || CharCreatedBy == MISSION_CHAR) + return; + + if (m_leader == pedWithGun) + return; + + if (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER || + (GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f) + return; + + if (m_leader) { + if (FindPlayerPed() == m_leader) + return; + + ClearLeader(); + } + if (m_pedStats->m_flags & STAT_GUN_PANIC + && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee()) + && m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_AIM_GUN) { + + waitTime = CGeneral::GetRandomNumberInRange(3000, 6000); + SetWaitState(WAITSTATE_PLAYANIM_HANDSCOWER, &waitTime); + Say(SOUND_PED_HANDS_COWER); + m_pLookTarget = pedWithGun; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + SetMoveState(PEDMOVE_NONE); + + } else if (m_nPedType != pedWithGun->m_nPedType) { + if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) { + RegisterThreatWithGangPeds(pedWithGun); + } + + if (m_nPedType == PEDTYPE_COP) { + if (pedWithGun->IsPlayer()) { + ((CPlayerPed*)pedWithGun)->m_pWanted->SetWantedLevelNoDrop(2); + if (bCrouchWhenShooting || bKindaStayInSamePlace) { + SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000)); + return; + } + } + } + + if (m_nPedType != PEDTYPE_COP + && (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee()) + && (m_nPedState != PED_FLEE_ENTITY || pedWithGun->IsPlayer() && m_fleeFrom != pedWithGun) + && m_nPedState != PED_AIM_GUN && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { + + waitTime = CGeneral::GetRandomNumberInRange(3000, 6000); + SetWaitState(WAITSTATE_PLAYANIM_HANDSUP, &waitTime); + Say(SOUND_PED_HANDS_UP); + m_pLookTarget = pedWithGun; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + SetMoveState(PEDMOVE_NONE); + if (m_nPedState == PED_FLEE_ENTITY) { + m_fleeFrom = pedWithGun; + m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom); + } + + if (FindPlayerPed() == pedWithGun && bRichFromMugging) { + int money = CGeneral::GetRandomNumberInRange(100, 300); + int pickupCount = money / 40 + 1; + int moneyPerPickup = money / pickupCount; + + for (int i = 0; i < pickupCount; i++) { + float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x; + float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y; + bool found = false; + float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f; + if (found) { + CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7)); + } + } + bRichFromMugging = false; + } + } + } +} + +void +CPed::ReactToAttack(CEntity *attacker) +{ + if (IsPlayer() && attacker->IsPed()) { + InformMyGangOfAttack(attacker); + SetLookFlag(attacker, true); + SetLookTimer(700); + return; + } + +#ifdef VC_PED_PORTS + if (m_nPedState == PED_DRIVING && InVehicle() + && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) { + + if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE + && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS) + && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) { + + 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->SetStatus(STATUS_PHYSICS); + } + } else +#endif + if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) { + CPed *ourLeader = m_leader; + if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader) + && attacker->IsPed()) { + + CPed *attackerPed = (CPed*)attacker; + if (bNotAllowedToDuck) { + if (!attackerPed->GetWeapon()->IsTypeMelee()) { + m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds(); + return; + } + } else if (bCrouchWhenShooting || bKindaStayInSamePlace) { + SetDuck(CGeneral::GetRandomNumberInRange(1000, 3000)); + return; + } + + if (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) { + if (m_pedStats != attackerPed->m_pedStats) { + if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) { + RegisterThreatWithGangPeds(attackerPed); + } + if (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker); + SetMoveState(PEDMOVE_RUN); + } else { + SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker); + SetObjectiveTimer(20000); + } + } + } else { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed); + SetMoveState(PEDMOVE_RUN); + if (attackerPed->GetWeapon()->IsTypeMelee()) + Say(SOUND_PED_FLEE_RUN); + } + } + } +} + +void +CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; + + CVehicle *veh = ped->m_pMyVehicle; + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (!ped->IsNotInWreckedVehicle()) + return; + + if (!ped->EnteringCar()) { +#ifdef VC_PED_PORTS + if (ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); + + return; + } + if (ped->m_fHealth == 0.0f) { + ped->QuitEnteringCar(); + return; + } + bool itsVan = !!veh->bIsVan; + bool itsBus = !!veh->bIsBus; +#ifdef FIX_BUGS + bool itsLow = !!veh->bLowVehicle; +#endif + eDoors enterDoor; + AnimationId enterAnim; + + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: + itsVan = false; + enterDoor = DOOR_FRONT_RIGHT; + break; + case CAR_DOOR_RR: + enterDoor = DOOR_REAR_RIGHT; + break; + case CAR_DOOR_LF: + itsVan = false; + enterDoor = DOOR_FRONT_LEFT; + break; + case CAR_DOOR_LR: + enterDoor = DOOR_REAR_LEFT; + break; + default: + break; + } + + if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) { + + veh->AutoPilot.m_nCruiseSpeed = 0; + if (ped->m_nPedState == PED_CARJACK) { + ped->PedAnimDoorOpenCB(nil, ped); + return; + } + if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) { + if (itsVan) { + enterAnim = ANIM_VAN_GETIN; + } else if (itsBus) { + enterAnim = ANIM_COACH_IN_R; +#ifdef FIX_BUGS + } else if (itsLow) { + enterAnim = ANIM_CAR_GETIN_LOW_RHS; +#endif + } else { + enterAnim = ANIM_CAR_GETIN_RHS; + } + } else if (itsVan) { + enterAnim = ANIM_VAN_GETIN_L; + } else if (itsBus) { + enterAnim = ANIM_COACH_IN_L; +#ifdef FIX_BUGS + } else if (itsLow) { + enterAnim = ANIM_CAR_GETIN_LOW_LHS; +#endif + } else { + enterAnim = ANIM_CAR_GETIN_LHS; + } + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterAnim); + ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + + } else if (veh->CanPedOpenLocks(ped)) { + + veh->AutoPilot.m_nCruiseSpeed = 0; + if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) { + if (itsVan) { + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN); + } else if (itsBus) { + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_R); + } else { + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_RHS); + } + } else if (itsVan) { + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN_L); + } else if (itsBus) { + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L); + } else { + + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) { + + if (!veh->bLowVehicle + && veh->pDriver->CharCreatedBy != MISSION_CHAR + && veh->pDriver->m_nPedState == PED_DRIVING) { + + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_QJACK); + ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true); + + if (veh->pDriver->IsGangMember()) + veh->pDriver->RegisterThreatWithGangPeds(ped); + return; + } + } + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS); + } + ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped); + + } else { + if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_RHS); + else + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_LHS); + + ped->bCancelEnteringCar = true; + ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped); + } +} + +void +CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed* ped = (CPed*)arg; + + CVehicle* veh = ped->m_pMyVehicle; + + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (!ped->IsNotInWreckedVehicle()) + return; + + if (!ped->EnteringCar()) { +#ifdef VC_PED_PORTS + if (ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); + + return; + } + + eDoors door; + CPed *pedInSeat = nil; + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; pedInSeat = veh->pPassengers[0]; break; + case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; pedInSeat = veh->pPassengers[2]; break; + case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; pedInSeat = veh->pDriver; break; + case CAR_DOOR_LR: door = DOOR_REAR_LEFT; pedInSeat = veh->pPassengers[1]; break; + default: assert(0); + } + + if (ped->m_fHealth == 0.0f || CPad::GetPad(0)->ArePlayerControlsDisabled() && pedInSeat && pedInSeat->IsPlayer()) { + ped->QuitEnteringCar(); + return; + } + + bool isVan = veh->bIsVan; + bool isBus = veh->bIsBus; + bool isLow = veh->bLowVehicle; + bool vehUpsideDown = veh->IsUpsideDown(); + if (ped->bCancelEnteringCar) { + if (ped->IsPlayer()) { + if (veh->pDriver) { + if (veh->pDriver->m_nPedType == PEDTYPE_COP) { + FindPlayerPed()->SetWantedLevelNoDrop(1); + } + } + } +#ifdef CANCELLABLE_CAR_ENTER + if (!veh->IsDoorMissing(door) && veh->CanPedOpenLocks(ped) && veh->IsCar()) { + ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); + } +#endif + ped->QuitEnteringCar(); + ped->RestorePreviousObjective(); + ped->bCancelEnteringCar = false; + return; + } + if (!veh->IsDoorMissing(door) && veh->IsCar()) { + ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); + } + + if (veh->m_vecMoveSpeed.Magnitude() > 0.2f) { + ped->QuitEnteringCar(); + if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) + ped->SetFall(1000, ANIM_KO_SPIN_R, false); + else + ped->SetFall(1000, ANIM_KO_SPIN_L, false); + + return; + } + veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f); + + if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF) + isVan = false; + + if (ped->m_nPedState != PED_CARJACK || isBus) { + AnimationId animToPlay; + if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) { + + if (isVan) { + animToPlay = ANIM_VAN_GETIN; + } else if (isBus) { + animToPlay = ANIM_COACH_IN_R; + } else if (isLow) { + animToPlay = ANIM_CAR_GETIN_LOW_RHS; + } else { + animToPlay = ANIM_CAR_GETIN_RHS; + } + } else if (isVan) { + animToPlay = ANIM_VAN_GETIN_L; + } else if (isBus) { + animToPlay = ANIM_COACH_IN_L; + } else if (isLow) { + animToPlay = ANIM_CAR_GETIN_LOW_LHS; + } else { + animToPlay = ANIM_CAR_GETIN_LHS; + } + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay); + ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + } else { + CPed *pedToDragOut = nil; + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break; + case CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break; + case CAR_DOOR_LF: pedToDragOut = veh->pDriver; break; + case CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break; + default: assert(0); + } + + if (vehUpsideDown) { + ped->QuitEnteringCar(); + if (ped->m_nPedType == PEDTYPE_COP) + ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective); + } + + if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) { + if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) { + if (pedToDragOut->m_nPedState != PED_DRIVING) { + ped->QuitEnteringCar(); + pedToDragOut = nil; + } else { + if (isLow) + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_RHS); + else + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_RHS); + + ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped); + } + } else if (ped->m_nPedType == PEDTYPE_COP) { + ped->QuitEnteringCar(); + if (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) { + veh->SetStatus(STATUS_PLAYER_DISABLED); + ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective); + } else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) { + ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING); + } + } else { + // BUG: Probably we will sit on top of the passenger if his m_ped_flagF4 is true. + if (isLow) + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS); + else + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS); + + ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + } + } else { + if (pedToDragOut) { + if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) { + + // BUG: Player freezes in that condition due to its objective isn't restored. It's an unfinished feature, used in VC. + ped->QuitEnteringCar(); + pedToDragOut = nil; + } else { + if (isLow) + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_LHS); + else + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LHS); + + ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped); + } + } else { + if (isLow) + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS); + else + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS); + + ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + } + } + + if (pedToDragOut) { + pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false); + if (pedToDragOut->IsGangMember()) + pedToDragOut->RegisterThreatWithGangPeds(ped); + } + } + + if (veh->pDriver && ped) { + veh->pDriver->SetLookFlag(ped, true); + veh->pDriver->SetLookTimer(1000); + } + return; +} + +void +CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed* ped = (CPed*)arg; + + CVehicle* veh = ped->m_pMyVehicle; + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (ped->EnteringCar()) { + if (!ped->IsNotInWreckedVehicle()) + return; + +#ifdef CANCELLABLE_CAR_ENTER + if (ped->bCancelEnteringCar) { + ped->QuitEnteringCar(); + ped->RestorePreviousObjective(); + ped->bCancelEnteringCar = false; + return; + } +#endif + + bool isLow = !!veh->bLowVehicle; + + int padNo; + if (ped->IsPlayer()) { + + // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads + switch (ped->m_nPedType) { + case PEDTYPE_PLAYER1: + padNo = 0; + break; + case PEDTYPE_PLAYER2: + padNo = 1; + break; + case PEDTYPE_PLAYER3: + padNo = 2; + break; + case PEDTYPE_PLAYER4: + padNo = 3; + break; + } + CPad *pad = CPad::GetPad(padNo); + + if (!pad->ArePlayerControlsDisabled()) { + + if (pad->GetTarget() + || pad->NewState.LeftStickX + || pad->NewState.LeftStickY + || pad->NewState.DPadUp + || pad->NewState.DPadDown + || pad->NewState.DPadLeft + || pad->NewState.DPadRight) { + ped->QuitEnteringCar(); + ped->RestorePreviousObjective(); + return; + } + } + } + + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + AnimationId animToPlay; + if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) { + if (isLow) + animToPlay = ANIM_CAR_GETIN_LOW_RHS; + else + animToPlay = ANIM_CAR_GETIN_RHS; + } else if (isLow) { + animToPlay = ANIM_CAR_GETIN_LOW_LHS; + } else { + animToPlay = ANIM_CAR_GETIN_LHS; + } + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay); + ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + } else { + ped->QuitEnteringCar(); + } + } else { + ped->QuitEnteringCar(); + } +} + +void +CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*) arg; + + CVehicle *veh = ped->m_pMyVehicle; + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) + return; + + if (!ped->EnteringCar()) { +#ifdef VC_PED_PORTS + if(ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); + return; + } + + if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) { + PedSetInCarCB(nil, ped); + ped->m_nLastPedState = ped->m_nPedState; + ped->m_nPedState = PED_ARRESTED; + ped->bGonnaKillTheCarJacker = false; + if (veh) { + veh->m_nNumGettingIn = 0; + veh->m_nGettingInFlags = 0; + veh->bIsHandbrakeOn = true; + veh->SetStatus(STATUS_PLAYER_DISABLED); + } + return; + } + if (ped->IsPlayer() && ped->m_vehEnterType == CAR_DOOR_LF + && (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f) + && veh->IsCar()) { + if (((CAutomobile*)veh)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING) + ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING); + + PedSetInCarCB(nil, ped); + return; + } + bool isVan = !!veh->bIsVan; + bool isBus = !!veh->bIsBus; + bool isLow = !!veh->bLowVehicle; + eDoors enterDoor; + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: + isVan = false; + enterDoor = DOOR_FRONT_RIGHT; + break; + case CAR_DOOR_RR: + enterDoor = DOOR_REAR_RIGHT; + break; + case CAR_DOOR_LF: + isVan = false; + enterDoor = DOOR_FRONT_LEFT; + break; + case CAR_DOOR_LR: + enterDoor = DOOR_REAR_LEFT; + break; + default: + break; + } + if (!veh->IsDoorMissing(enterDoor)) { + if (veh->IsCar()) + ((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING); + } + CPed *driver = veh->pDriver; + if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) { + if (veh->bIsBus) { + driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh); + if (driver->IsPlayer()) { + veh->bIsHandbrakeOn = true; + veh->SetStatus(STATUS_PLAYER_DISABLED); + } + driver->bBusJacked = true; + veh->bIsBeingCarJacked = false; + PedSetInCarCB(nil, ped); + if (ped->m_nPedType == PEDTYPE_COP + || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT + || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { + ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); + } + ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400; + return; + } + if (driver != ped && ped->m_vehEnterType != CAR_DOOR_LF) { + if (!driver->IsPlayer()) { + driver->bUsePedNodeSeek = true; + driver->m_pLastPathNode = nil; + if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear + || driver->CharCreatedBy == MISSION_CHAR + || veh->VehicleCreatedBy == MISSION_VEHICLE) { + driver->bFleeAfterExitingCar = true; + } else { + driver->bGonnaKillTheCarJacker = true; + veh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped); + + if (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) { + FindPlayerPed()->SetWantedLevelNoDrop(1); + } + } + } + if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY) + && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) { + veh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh); + veh->pDriver->Say(SOUND_PED_CAR_JACKED); +#ifdef VC_PED_PORTS + veh->pDriver->SetRadioStation(); +#endif + } else { + ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER; + } + } + } + if (veh->IsDoorMissing(enterDoor) || isBus) { + PedAnimDoorCloseCB(nil, ped); + } else { + AnimationId animToPlay; + if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) { + if (isVan) { + animToPlay = ANIM_VAN_CLOSE; + } else if (isLow) { + animToPlay = ANIM_CAR_CLOSEDOOR_LOW_RHS; + } else { + animToPlay = ANIM_CAR_CLOSEDOOR_RHS; + } + } else if (isVan) { + animToPlay = ANIM_VAN_CLOSE_L; + } else if (isLow) { + animToPlay = ANIM_CAR_CLOSEDOOR_LOW_LHS; + } else { + animToPlay = ANIM_CAR_CLOSEDOOR_LHS; + } + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay); + ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped); + } +} + +void +CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; + + CAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle); + + if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) + return; + + if (ped->EnteringCar()) { + bool isLow = !!veh->bLowVehicle; + + if (!veh->bIsBus) + veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f); + + eDoors door; + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break; + case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break; + case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break; + case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break; + default: assert(0); + } + + if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING) + veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK); + + if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus) { + PedSetInCarCB(nil, ped); + } else if (ped->m_vehEnterType == CAR_DOOR_RF + && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF || + (veh->pDriver != nil && + (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR +#ifdef VC_PED_PORTS + && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE +#endif + || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) { + + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER +#if defined VC_PED_PORTS || defined FIX_BUGS + || ped->m_nPedState == PED_CARJACK +#endif + ) + veh->bIsBeingCarJacked = false; + + ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER; + PedSetInCarCB(nil, ped); + + ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); + if (!ped->IsPlayer()) + ped->bFleeAfterExitingCar = true; + + ped->bUsePedNodeSeek = true; + ped->m_pNextPathNode = nil; + + } else { + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (isLow) + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSHUFFLE_RHS); + else + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SHUFFLE_RHS); + + ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped); + } + } else { +#ifdef VC_PED_PORTS + if (ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); + } +} + +void +CPed::SetFormation(eFormation type) +{ + // FIX: Formations in GetFormationPosition were in range 1-8, whereas in here it's 0-7. + // To not change the behaviour, range in here tweaked by 1 with the use of enum. + + switch (m_pedFormation) { + case FORMATION_REAR: + case FORMATION_REAR_LEFT: + case FORMATION_REAR_RIGHT: + case FORMATION_FRONT_LEFT: + case FORMATION_FRONT_RIGHT: + case FORMATION_LEFT: + case FORMATION_RIGHT: + case FORMATION_FRONT: + break; + default: + Error("Unknown formation type, PedAI.cpp"); + break; + } + m_pedFormation = type; +} + +CVector +CPed::GetFormationPosition(void) +{ + if (m_pedInObjective->m_nPedState == PED_DEAD) { + if (!m_pedInObjective->m_pedInObjective) { + m_pedInObjective = nil; + return GetPosition(); + } + m_pedInObjective = m_pedInObjective->m_pedInObjective; + } + + CVector formationOffset; + switch (m_pedFormation) { + case FORMATION_REAR: + formationOffset = CVector(0.0f, -1.5f, 0.0f); + break; + case FORMATION_REAR_LEFT: + formationOffset = CVector(-1.5f, -1.5f, 0.0f); + break; + case FORMATION_REAR_RIGHT: + formationOffset = CVector(1.5f, -1.5f, 0.0f); + break; + case FORMATION_FRONT_LEFT: + formationOffset = CVector(-1.5f, 1.5f, 0.0f); + break; + case FORMATION_FRONT_RIGHT: + formationOffset = CVector(1.5f, 1.5f, 0.0f); + break; + case FORMATION_LEFT: + formationOffset = CVector(-1.5f, 0.0f, 0.0f); + break; + case FORMATION_RIGHT: + formationOffset = CVector(1.5f, 0.0f, 0.0f); + break; + case FORMATION_FRONT: + formationOffset = CVector(0.0f, 1.5f, 0.0f); + break; + default: + formationOffset = CVector(0.0f, 0.0f, 0.0f); + break; + } + return formationOffset + m_pedInObjective->GetPosition(); +} + +void +CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed* ped = (CPed*)arg; + + CVehicle* veh = ped->m_pMyVehicle; + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (!veh) { + PedSetOutCarCB(nil, ped); + return; + } +#ifdef VC_PED_PORTS + CVector posForZ = ped->GetPosition(); + CPedPlacement::FindZCoorForPed(&posForZ); + if (ped->GetPosition().z - 0.5f > posForZ.z) { + PedSetOutCarCB(nil, ped); + return; + } +#endif + veh->m_nStaticFrames = 0; + veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f); + veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f); + if (!veh->bIsBus) + veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f); + + /* + // Duplicate and only in PC for some reason + if (!veh) { + PedSetOutCarCB(nil, ped); + return; + } + */ + eDoors door; + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: + door = DOOR_FRONT_RIGHT; + break; + case CAR_DOOR_RR: + door = DOOR_REAR_RIGHT; + break; + case CAR_DOOR_LF: + door = DOOR_FRONT_LEFT; + break; + case CAR_DOOR_LR: + door = DOOR_REAR_LEFT; + break; + default: + break; + } + bool closeDoor = !veh->IsDoorMissing(door); + + int padNo; + if (ped->IsPlayer()) { + + // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads + switch (ped->m_nPedType) { + case PEDTYPE_PLAYER1: + padNo = 0; + break; + case PEDTYPE_PLAYER2: + padNo = 1; + break; + case PEDTYPE_PLAYER3: + padNo = 2; + break; + case PEDTYPE_PLAYER4: + padNo = 3; + break; + } + CPad* pad = CPad::GetPad(padNo); + bool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225; + if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS + && (pad->GetTarget() + || pad->NewState.LeftStickX + || pad->NewState.LeftStickY + || pad->NewState.DPadUp + || pad->NewState.DPadDown + || pad->NewState.DPadLeft + || pad->NewState.DPadRight) + || veh->bIsBus + || veh->m_pCarFire + || engineIsIntact) { + closeDoor = false; + } + } + +#ifdef VC_PED_PORTS + if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) + closeDoor = false; +#endif + + if (!closeDoor) { + if (!veh->IsDoorMissing(door) && !veh->bIsBus) { + ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); + } + PedSetOutCarCB(nil, ped); + return; + } + + if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) { + // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa? + if (!veh->IsDoorMissing(door)) + ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING); + } else { + switch (door) { + case DOOR_FRONT_LEFT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS); + break; + case DOOR_FRONT_RIGHT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS); + break; + case DOOR_REAR_LEFT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS); + break; + case DOOR_REAR_RIGHT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS); + break; + default: + break; + } + } + + if (ped->m_pVehicleAnim) + ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped); + return; +} + +void +CPed::LineUpPedWithCar(PedLineUpPhase phase) +{ + bool vehIsUpsideDown = false; + int vehAnim; + float seatPosMult = 0.0f; + float currentZ; + float adjustedTimeStep; + + if (CReplay::IsPlayingBack()) + return; + + if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) { + SetPedPositionInCar(); + return; + } + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) { + SetPedPositionInCar(); + return; + } + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) { + SetPedPositionInCar(); + return; + } + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) { + SetPedPositionInCar(); + return; + } + bChangedSeat = true; + } + if (phase == LINE_UP_TO_CAR_START) { + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } + CVehicle *veh = m_pMyVehicle; + + // Not quite right, IsUpsideDown func. checks for <= -0.9f. + if (veh->GetUp().z <= -0.8f) + vehIsUpsideDown = true; + + if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) { + if (vehIsUpsideDown) { + m_fRotationDest = -PI + veh->GetForward().Heading(); + } else if (veh->bIsBus) { + m_fRotationDest = 0.5f * PI + veh->GetForward().Heading(); + } else { + m_fRotationDest = veh->GetForward().Heading(); + } + } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { + if (vehIsUpsideDown) { + m_fRotationDest = veh->GetForward().Heading(); + } else if (veh->bIsBus) { + m_fRotationDest = -0.5f * PI + veh->GetForward().Heading(); + } else { + m_fRotationDest = veh->GetForward().Heading(); + } + } else { + // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional. + + if (vehIsUpsideDown) { + m_fRotationDest = veh->GetForward().Heading(); + } else if (veh->bIsBus) { + m_fRotationDest = 0.5f * PI + veh->GetForward().Heading(); + } else { + m_fRotationDest = veh->GetForward().Heading(); + } + } + + if (!bInVehicle) + seatPosMult = 1.0f; + +#ifdef VC_PED_PORTS + bool multExtractedFromAnim = false; + bool multExtractedFromAnimBus = false; + float zBlend; +#endif + if (m_pVehicleAnim) { + vehAnim = m_pVehicleAnim->animId; + + switch (vehAnim) { + case ANIM_CAR_JACKED_RHS: + case ANIM_CAR_LJACKED_RHS: + case ANIM_CAR_JACKED_LHS: + case ANIM_CAR_LJACKED_LHS: + case ANIM_VAN_GETIN_L: + case ANIM_VAN_GETIN: +#ifdef VC_PED_PORTS + multExtractedFromAnim = true; + zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f); + // fall through +#endif + case ANIM_CAR_QJACKED: + case ANIM_CAR_GETOUT_LHS: + case ANIM_CAR_GETOUT_LOW_LHS: + case ANIM_CAR_GETOUT_RHS: + case ANIM_CAR_GETOUT_LOW_RHS: +#ifdef VC_PED_PORTS + if (!multExtractedFromAnim) { + multExtractedFromAnim = true; + zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f); + } + // fall through +#endif + case ANIM_CAR_CRAWLOUT_RHS: + case ANIM_CAR_CRAWLOUT_RHS2: + case ANIM_VAN_GETOUT_L: + case ANIM_VAN_GETOUT: + seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength; + break; + case ANIM_CAR_GETIN_RHS: + case ANIM_CAR_GETIN_LHS: +#ifdef VC_PED_PORTS + if (veh && veh->IsCar() && veh->bIsBus) { + multExtractedFromAnimBus = true; + zBlend = Min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f; + } + // fall through +#endif + case ANIM_CAR_QJACK: + case ANIM_CAR_GETIN_LOW_LHS: + case ANIM_CAR_GETIN_LOW_RHS: + case ANIM_DRIVE_BOAT: + seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength; + break; + case ANIM_CAR_CLOSEDOOR_LHS: + case ANIM_CAR_CLOSEDOOR_LOW_LHS: + case ANIM_CAR_CLOSEDOOR_RHS: + case ANIM_CAR_CLOSEDOOR_LOW_RHS: + case ANIM_CAR_SHUFFLE_RHS: + case ANIM_CAR_LSHUFFLE_RHS: + seatPosMult = 0.0f; + break; + case ANIM_CAR_CLOSE_LHS: + case ANIM_CAR_CLOSE_RHS: + case ANIM_COACH_OPEN_L: + case ANIM_COACH_OPEN_R: + case ANIM_COACH_IN_L: + case ANIM_COACH_IN_R: + case ANIM_COACH_OUT_L: + seatPosMult = 1.0f; + break; + default: + break; + } + } + + CVector neededPos; + + if (phase == LINE_UP_TO_CAR_2) { + neededPos = GetPosition(); + } else { + neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult); + } + + CVector autoZPos = neededPos; + + if (veh->bIsInWater) { + if (veh->m_vehType == VEHICLE_TYPE_BOAT && veh->IsUpsideDown()) + autoZPos.z += 1.0f; + } else { + CPedPlacement::FindZCoorForPed(&autoZPos); + } + + if (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) { + neededPos.z = GetPosition().z; + + // Getting out + if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) { + float nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep(); + + // If we're not in ground at next step, apply animation + if (neededPos.z + nextZSpeed >= autoZPos.z) { + m_vecMoveSpeed.z = nextZSpeed; + ApplyMoveSpeed(); + // Removing below line breaks the animation + neededPos.z = GetPosition().z; + } else { + neededPos.z = autoZPos.z; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } + } + } + + if (autoZPos.z > neededPos.z) { +#ifdef VC_PED_PORTS + if (multExtractedFromAnim) { + neededPos.z += (autoZPos.z - neededPos.z) * zBlend; + } else { +#endif + currentZ = GetPosition().z; + if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) { + neededPos.z = autoZPos.z; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) { + adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f); + + // Smoothly change ped position + neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep); + } +#ifdef VC_PED_PORTS + } +#endif + } else { + // We may need to raise up the ped + if (phase == LINE_UP_TO_CAR_START) { + currentZ = GetPosition().z; + + if (neededPos.z > currentZ) { +#ifdef VC_PED_PORTS + if (multExtractedFromAnimBus) { + neededPos.z = (neededPos.z - currentZ) * zBlend + currentZ; + } else { +#endif + if (m_pVehicleAnim && + (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS + || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) { + adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f); + + // Smoothly change ped position + neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ; + } else if (EnteringCar()) { + neededPos.z = Max(currentZ, autoZPos.z); + } +#ifdef VC_PED_PORTS + } +#endif + } + } + } + + bool stillGettingInOut = false; + if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) + stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat; + + if (!stillGettingInOut) { + m_fRotationCur = m_fRotationDest; + } else { + float limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest); + float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f; + + if (timeUntilStateChange <= 0.0f) { + m_vecOffsetSeek.x = 0.0f; + m_vecOffsetSeek.y = 0.0f; + } + m_vecOffsetSeek.z = 0.0f; + + neededPos -= timeUntilStateChange * m_vecOffsetSeek; + + if (PI + m_fRotationCur < limitedDest) { + limitedDest -= 2 * PI; + } else if (m_fRotationCur - PI > limitedDest) { + limitedDest += 2 * PI; + } + m_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange); + } + + if (seatPosMult > 0.2f || vehIsUpsideDown) { + SetPosition(neededPos); + SetHeading(m_fRotationCur); + } else { + CMatrix vehDoorMat(veh->GetMatrix()); + vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f)); + // VC couch anims are inverted, so they're fixing it here. + GetMatrix() = vehDoorMat; + } + +} + +void +CPed::SetCarJack(CVehicle* car) +{ + uint8 doorFlag; + eDoors door; + CPed *pedInSeat = nil; + + if (car->IsBoat()) + return; + + switch (m_vehEnterType) { + case CAR_DOOR_RF: + doorFlag = CAR_DOOR_FLAG_RF; + door = DOOR_FRONT_RIGHT; + if (car->pPassengers[0]) { + pedInSeat = car->pPassengers[0]; + } else if (m_nPedType == PEDTYPE_COP) { + pedInSeat = car->pDriver; + } + break; + case CAR_DOOR_RR: + doorFlag = CAR_DOOR_FLAG_RR; + door = DOOR_REAR_RIGHT; + pedInSeat = car->pPassengers[2]; + break; + case CAR_DOOR_LF: + doorFlag = CAR_DOOR_FLAG_LF; + door = DOOR_FRONT_LEFT; + pedInSeat = car->pDriver; + break; + case CAR_DOOR_LR: + doorFlag = CAR_DOOR_FLAG_LR; + door = DOOR_REAR_LEFT; + pedInSeat = car->pPassengers[1]; + break; + default: + doorFlag = CAR_DOOR_FLAG_UNKNOWN; + break; + } + + if(car->bIsBus) + pedInSeat = car->pDriver; + + if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || + (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO))) + if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING) + if (m_nPedState != PED_CARJACK && !m_pVehicleAnim) + if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door))) + if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags)) + SetCarJack_AllClear(car, m_vehEnterType, doorFlag); +} + +void +CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) +{ + RemoveWeaponWhenEnteringVehicle(); + if (m_nPedState != PED_SEEK_CAR) + SetStoredState(); + + m_pSeekTarget = car; + m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget); + m_nPedState = PED_CARJACK; + car->bIsBeingCarJacked = true; + m_pMyVehicle = (CVehicle*)m_pSeekTarget; + m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle); + ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++; + + Say(m_nPedType == PEDTYPE_COP ? SOUND_PED_ARREST_COP : SOUND_PED_CAR_JACKING); + CVector carEnterPos; + carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType); + + car->m_nGettingInFlags |= doorFlag; + m_vecOffsetSeek = carEnterPos - GetPosition(); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; + float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z); + bUsesCollision = false; + + if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f); + else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f); + + m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this); +} + +void +CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack) +{ + if (m_nPedState == PED_DRAG_FROM_CAR) + return; + + bUsesCollision = false; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + m_nLastPedState = PED_IDLE; + SetMoveState(PEDMOVE_STILL); + m_pSeekTarget = veh; + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + m_vehEnterType = vehEnterType; + if (m_vehEnterType == CAR_DOOR_LF) { + if (veh->pDriver && veh->pDriver->IsPlayer()) + veh->SetStatus(STATUS_PLAYER_DISABLED); + else + veh->SetStatus(STATUS_ABANDONED); + } + RemoveInCarAnims(); + SetMoveState(PEDMOVE_NONE); + LineUpPedWithCar(LINE_UP_TO_CAR_START); + m_pVehicleAnim = nil; + m_nPedState = PED_DRAG_FROM_CAR; + bChangedSeat = false; + bWillBeQuickJacked = quickJack; + + SetHeading(m_fRotationCur); + + Say(SOUND_PED_CAR_JACKED); + SetRadioStation(); + veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType); +} + +void +CPed::BeingDraggedFromCar(void) +{ + CAnimBlendAssociation *animAssoc; + AnimationId enterAnim; + bool dontRunAnim = false; + PedLineUpPhase lineUpType; + + if (!m_pVehicleAnim) { + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT); + if (!animAssoc) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT); + if (!animAssoc) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO); + } + } + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { + if (bWillBeQuickJacked) { + enterAnim = ANIM_CAR_QJACKED; + } else if (m_pMyVehicle->bLowVehicle) { + enterAnim = ANIM_CAR_LJACKED_LHS; + } else { + enterAnim = ANIM_CAR_JACKED_LHS; + } + } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) { + if (m_pMyVehicle->bLowVehicle) + enterAnim = ANIM_CAR_LJACKED_RHS; + else + enterAnim = ANIM_CAR_JACKED_RHS; + } else + dontRunAnim = true; + + + if (!dontRunAnim) + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim); + + m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this); + lineUpType = LINE_UP_TO_CAR_START; + } else if (m_pVehicleAnim->currentTime <= 1.4f) { + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + lineUpType = LINE_UP_TO_CAR_START; + } else { + lineUpType = LINE_UP_TO_CAR_2; + } + + LineUpPedWithCar(lineUpType); +#ifdef VC_PED_PORTS + if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { + if (m_pMyVehicle) { + m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f); + } + } +#endif +} + +void +CPed::SetEnterCar(CVehicle *car, uint32 unused) +{ + if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) { + RestorePreviousState(); + RestorePreviousObjective(); + } else { + uint8 doorFlag; + eDoors door; + switch (m_vehEnterType) { + case CAR_DOOR_RF: + doorFlag = CAR_DOOR_FLAG_RF; + door = DOOR_FRONT_RIGHT; + break; + case CAR_DOOR_RR: + doorFlag = CAR_DOOR_FLAG_RR; + door = DOOR_REAR_RIGHT; + break; + case CAR_DOOR_LF: + doorFlag = CAR_DOOR_FLAG_LF; + door = DOOR_FRONT_LEFT; + break; + case CAR_DOOR_LR: + doorFlag = CAR_DOOR_FLAG_LR; + door = DOOR_REAR_LEFT; + break; + default: + doorFlag = CAR_DOOR_FLAG_UNKNOWN; + break; + } + if (!IsPedInControl() || m_fHealth <= 0.0f + || doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags + || car->bIsBeingCarJacked || m_pVehicleAnim + || doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door)) + SetMoveState(PEDMOVE_STILL); + else + SetEnterCar_AllClear(car, m_vehEnterType, doorFlag); + } +} + +void +CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) +{ + float zDiff = 0.0f; + RemoveWeaponWhenEnteringVehicle(); + car->m_nGettingInFlags |= doorFlag; + bVehEnterDoorIsBlocked = false; + if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT) + SetStoredState(); + + m_pSeekTarget = car; + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + m_vehEnterType = doorNode; + m_nPedState = PED_ENTER_CAR; + if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && car->m_vehType != VEHICLE_TYPE_BIKE) { + car->bIsBeingCarJacked = true; + } + + m_pMyVehicle = (CVehicle*)m_pSeekTarget; + m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle); + ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++; + bUsesCollision = false; + CVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehEnterType); + + // Because buses have stairs + if (!m_pMyVehicle->bIsBus) + zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z); + + m_vecOffsetSeek = doorOpenPos - GetPosition(); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; + if (car->IsBoat()) { +#ifdef VC_PED_PORTS + // VC checks for handling flag, but we can't do that + if(car->GetModelIndex() == MI_SPEEDER) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); + else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); + + PedSetInCarCB(nil, this); + bVehExitWillBeInstant = true; +#else + +#ifndef FIX_BUGS + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); +#else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); +#endif + + m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this); +#endif + if (IsPlayer()) + CWaterLevel::AllocateBoatWakeArray(); + } else { + if (zDiff > 4.4f) { + if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f); + else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f); + + } else { + if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f); + else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f); + } + m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this); + car->AutoPilot.m_nCruiseSpeed = 0; + } +} + +void +CPed::EnterCar(void) +{ + if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) { + CVehicle *veh = (CVehicle*)m_pSeekTarget; + + // Not used. + // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType); + + if (veh->CanPedOpenLocks(this)) { + if (m_vehEnterType && m_pVehicleAnim) { + veh->ProcessOpenDoor(m_vehEnterType, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime); + } + } + bIsInTheAir = false; + LineUpPedWithCar(LINE_UP_TO_CAR_START); + } else { + QuitEnteringCar(); + SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + } +} + +void +CPed::QuitEnteringCar(void) +{ + CVehicle *veh = m_pMyVehicle; + if (m_pVehicleAnim) + m_pVehicleAnim->blendDelta = -1000.0f; + + RestartNonPartialAnims(); + + if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE)) + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); + + if (veh) { + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK) + veh->bIsBeingCarJacked = false; + + if (veh->m_nNumGettingIn != 0) + veh->m_nNumGettingIn--; + +#ifdef VC_PED_PORTS + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) + RestorePreviousObjective(); +#endif + + veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType); + } + + bUsesCollision = true; + + ReplaceWeaponWhenExitingVehicle(); + + if (DyingOrDead()) { + if (m_pVehicleAnim) { + m_pVehicleAnim->blendDelta = -4.0f; + m_pVehicleAnim->flags |= ASSOC_DELETEFADEDOUT; + m_pVehicleAnim->flags &= ~ASSOC_RUNNING; + } + } else + SetIdle(); + + m_pVehicleAnim = nil; + + if (veh) { +#ifdef VC_PED_PORTS + if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE) +#else + if (veh->AutoPilot.m_nCruiseSpeed == 0) +#endif + veh->AutoPilot.m_nCruiseSpeed = 17; + } +} + +void +AddYardieDoorSmoke(CVehicle *veh, uint32 doorNode) +{ + eDoors door; + switch (doorNode) { + case CAR_DOOR_RF: + door = DOOR_FRONT_RIGHT; + break; + case CAR_DOOR_LF: + door = DOOR_FRONT_LEFT; + break; + default: + break; + } + + if (!veh->IsDoorMissing(door) && veh->IsComponentPresent(doorNode)) { + CVector pos; +#ifdef FIX_BUGS + veh->GetComponentWorldPosition(doorNode, pos); +#else + veh->GetComponentWorldPosition(CAR_DOOR_LF, pos); +#endif + CParticle::AddYardieDoorSmoke(pos, veh->GetMatrix()); + } +} + +// Seperate function in VC, more logical. Not sure is it inlined in III. +void +CPed::SetExitBoat(CVehicle *boat) +{ +#ifndef VC_PED_PORTS + m_nPedState = PED_IDLE; + CVector firstPos = GetPosition(); + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); + if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) { + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f); + m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this); + m_vehEnterType = CAR_DOOR_RF; + m_nPedState = PED_EXIT_CAR; + } else { + m_vehEnterType = CAR_DOOR_RF; + PedSetOutCarCB(nil, this); + bIsStanding = true; + m_pCurSurface = boat; + m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface); + } + SetPosition(firstPos); + SetMoveState(PEDMOVE_STILL); + m_vecMoveSpeed = boat->m_vecMoveSpeed; + bTryingToReachDryLand = true; +#else + m_nPedState = PED_IDLE; + CVector newPos = GetPosition(); + RemoveInCarAnims(); + CColModel* boatCol = boat->GetColModel(); + if (boat->IsUpsideDown()) { + newPos = { 0.0f, 0.0f, boatCol->boundingBox.min.z }; + newPos = boat->GetMatrix() * newPos; + newPos.z += 1.0f; + m_vehEnterType = CAR_DOOR_RF; + PedSetOutCarCB(nil, this); + bIsStanding = true; + m_pCurSurface = boat; + m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface); + m_pCurrentPhysSurface = boat; + } else { +/* if (boat->m_modelIndex != MI_SKIMMER || boat->bIsInWater) { + if (boat->m_modelIndex == MI_SKIMMER) + newPos.z += 2.0f +*/ + m_vehEnterType = CAR_DOOR_RF; + PedSetOutCarCB(nil, this); + bIsStanding = true; + m_pCurSurface = boat; + m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface); + m_pCurrentPhysSurface = boat; + CColPoint foundCol; + CEntity *foundEnt = nil; + if (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil)) + newPos.z = FEET_OFFSET + foundCol.point.z; +/* // VC specific + } else { + m_vehEnterType = CAR_DOOR_RF; + PedSetOutCarCB(nil, this); + bIsStanding = true; + SetMoveState(PEDMOVE_STILL); + bTryingToReachDryLand = true; + float upMult = 1.04f + boatCol->boundingBox.min.z; + float rightMult = 0.6f * boatCol->boundingBox.max.x; + newPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition(); + GetPosition() = newPos; + if (m_pMyVehicle) { + PositionPedOutOfCollision(); + } else { + m_pMyVehicle = boat; + PositionPedOutOfCollision(); + m_pMyVehicle = nil; + } + return; + } +*/ } + SetPosition(newPos); + SetMoveState(PEDMOVE_STILL); + m_vecMoveSpeed = boat->m_vecMoveSpeed; +#endif + // Not there in VC. + CWaterLevel::FreeBoatWakeArray(); +} + +// wantedDoorNode = 0 means that func. will determine it +void +CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) +{ + uint32 optedDoorNode = wantedDoorNode; + bool teleportNeeded = false; + bool isLow = !!veh->bLowVehicle; + if (!veh->CanPedExitCar()) { + if (veh->pDriver && !veh->pDriver->IsPlayer()) { + veh->AutoPilot.m_nCruiseSpeed = 0; + veh->AutoPilot.m_nCarMission = MISSION_NONE; + } + return; + } + + if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) + return; + + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + if (wantedDoorNode == 0) { + optedDoorNode = CAR_DOOR_LF; + if (!veh->bIsBus) { + if (veh->pDriver == this) { + optedDoorNode = CAR_DOOR_LF; + } else if (veh->pPassengers[0] == this) { + optedDoorNode = CAR_DOOR_RF; + } else if (veh->pPassengers[1] == this) { + optedDoorNode = CAR_DOOR_LR; + } else if (veh->pPassengers[2] == this) { + optedDoorNode = CAR_DOOR_RR; + } else { + for (int i = 3; i < veh->m_nNumMaxPassengers; ++i) { + if (veh->pPassengers[i] == this) { + if (i & 1) + optedDoorNode = CAR_DOOR_RR; + else + optedDoorNode = CAR_DOOR_LR; + + break; + } + } + } + } + } + bool someoneExitsFromOurExitDoor = false; + bool someoneEntersFromOurExitDoor = false; + switch (optedDoorNode) { + case CAR_DOOR_RF: + if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) + someoneEntersFromOurExitDoor = true; + if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RF) + someoneExitsFromOurExitDoor = true; + break; + case CAR_DOOR_RR: + if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) + someoneEntersFromOurExitDoor = true; + if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RR) + someoneExitsFromOurExitDoor = true; + break; + case CAR_DOOR_LF: + if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) + someoneEntersFromOurExitDoor = true; + if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LF) + someoneExitsFromOurExitDoor = true; + break; + case CAR_DOOR_LR: + if (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) + someoneEntersFromOurExitDoor = true; + if (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LR) + someoneExitsFromOurExitDoor = true; + break; + default: + break; + } + if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) { + RestorePreviousObjective(); + return; + } + if (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) { + // Again, unused... + // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode); + bool thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil); + if (veh->IsOnItsSide()) { + teleportNeeded = true; + } else if (!thereIsRoom) { + bool trySideSeat = false; + CPed *pedOnSideSeat = nil; + switch (optedDoorNode) { + case CAR_DOOR_RF: + if (veh->pDriver || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) { + pedOnSideSeat = veh->pDriver; + trySideSeat = true; + } else + optedDoorNode = CAR_DOOR_LF; + + break; + case CAR_DOOR_RR: + if (veh->pPassengers[1] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) { + pedOnSideSeat = veh->pPassengers[1]; + trySideSeat = true; + } else + optedDoorNode = CAR_DOOR_LR; + + break; + case CAR_DOOR_LF: + if (veh->pPassengers[0] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) { + pedOnSideSeat = veh->pPassengers[0]; + trySideSeat = true; + } else + optedDoorNode = CAR_DOOR_RF; + + break; + case CAR_DOOR_LR: + if (veh->pPassengers[2] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) { + pedOnSideSeat = (CPed*)veh->pPassengers[2]; + trySideSeat = true; + } else + optedDoorNode = CAR_DOOR_RR; + + break; + default: + break; + } + if (trySideSeat) { + if (!pedOnSideSeat || !IsPlayer() && CharCreatedBy != MISSION_CHAR) + return; + + switch (optedDoorNode) { + case CAR_DOOR_RF: + optedDoorNode = CAR_DOOR_LF; + break; + case CAR_DOOR_RR: + optedDoorNode = CAR_DOOR_LR; + break; + case CAR_DOOR_LF: + optedDoorNode = CAR_DOOR_RF; + break; + case CAR_DOOR_LR: + optedDoorNode = CAR_DOOR_RR; + break; + default: + break; + } + } + // ... + // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode); + if (!veh->IsRoomForPedToLeaveCar(optedDoorNode, nil)) { + if (!IsPlayer() && CharCreatedBy != MISSION_CHAR) + return; + + teleportNeeded = true; + } + } + if (m_nPedState == PED_FLEE_POS) { + m_nLastPedState = PED_FLEE_POS; + m_nPrevMoveState = PEDMOVE_RUN; + SetMoveState(PEDMOVE_SPRINT); + } else { + m_nLastPedState = PED_IDLE; + m_nPrevMoveState = PEDMOVE_STILL; + SetMoveState(PEDMOVE_STILL); + } + + ReplaceWeaponWhenExitingVehicle(); + bUsesCollision = false; + m_pSeekTarget = veh; + m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); + m_vehEnterType = optedDoorNode; + m_nPedState = PED_EXIT_CAR; + if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL) + m_pVehicleAnim->blendDelta = -1000.0f; + SetMoveState(PEDMOVE_NONE); + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); + RemoveInCarAnims(); + veh->AutoPilot.m_nCruiseSpeed = 0; + if (teleportNeeded) { + PedSetOutCarCB(nil, this); + + // This is same code with CPedPlacement::FindZCoorForPed, except we start from z + 1.5 and also check vehicles. + float zForPed; + float startZ = GetPosition().z - 100.0f; + float foundColZ = -100.0f; + float foundColZ2 = -100.0f; + CColPoint foundCol; + CEntity* foundEnt; + + CVector vec = GetPosition(); + vec.z += 1.5f; + + if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil)) + foundColZ = foundCol.point.z; + + // Adjust coords and do a second test + vec.x += 0.1f; + vec.y += 0.1f; + + if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil)) + foundColZ2 = foundCol.point.z; + + zForPed = Max(foundColZ, foundColZ2); + + if (zForPed > -99.0f) + GetMatrix().GetPosition().z = FEET_OFFSET + zForPed; + } else { + if (veh->GetUp().z > -0.8f) { + bool addDoorSmoke = false; + if (veh->GetModelIndex() == MI_YARDIE) + addDoorSmoke = true; + + switch (m_vehEnterType) { + case CAR_DOOR_RF: + if (veh->bIsBus) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L); + } else { + if (isLow) + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS); + else + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS); + + if (addDoorSmoke) + AddYardieDoorSmoke(veh, CAR_DOOR_RF); + } + break; + case CAR_DOOR_RR: + if (veh->bIsVan) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT); + } else if (isLow) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS); + } else { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS); + } + break; + case CAR_DOOR_LF: + if (veh->bIsBus) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L); + } else { + if (isLow) + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS); + else + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS); + + if (addDoorSmoke) + AddYardieDoorSmoke(veh, CAR_DOOR_LF); + } + break; + case CAR_DOOR_LR: + if (veh->bIsVan) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT_L); + } else if (isLow) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS); + } else { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS); + } + break; + default: + break; + } + if (!bBusJacked) { + switch (m_vehEnterType) { + case CAR_DOOR_RF: + veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RF; + break; + case CAR_DOOR_RR: + veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RR; + break; + case CAR_DOOR_LF: + veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF; + break; + case CAR_DOOR_LR: + veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LR; + break; + default: + break; + } + } + m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this); + } else { + if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS2); + } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS); + } + m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this); + } + } + bChangedSeat = false; + if (veh->bIsBus) + bRenderPedInCar = true; + + SetRadioStation(); + if (veh->pDriver == this) { + if (IsPlayer()) + veh->SetStatus(STATUS_PLAYER_DISABLED); + else + veh->SetStatus(STATUS_ABANDONED); + } + } +} + +void +CPed::ExitCar(void) +{ + if (!m_pVehicleAnim) + return; + + AnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId; + float animTime = m_pVehicleAnim->currentTime; + + m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, exitAnim, animTime); + + if (m_pSeekTarget) { + // Car is upside down + if (m_pMyVehicle->GetUp().z > -0.8f) { + if (exitAnim == ANIM_CAR_CLOSE_RHS || exitAnim == ANIM_CAR_CLOSE_LHS || animTime > 0.3f) + LineUpPedWithCar(LINE_UP_TO_CAR_END); + else + LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START)); + } else { + LineUpPedWithCar(LINE_UP_TO_CAR_END); + } + } + + // If there is someone in front of the door, make him fall while we exit. + if (m_nPedState == PED_EXIT_CAR) { + CPed *foundPed = nil; + for (int i = 0; i < m_numNearPeds; i++) { + if ((m_nearPeds[i]->GetPosition() - GetPosition()).MagnitudeSqr2D() < 0.04f) { + foundPed = m_nearPeds[i]; + break; + } + } + if (foundPed && animTime > 0.4f && foundPed->IsPedInControl()) + foundPed->SetFall(1000, ANIM_KO_SKID_FRONT, 1); + } +} + +// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it. +CVector +CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component) +{ + CVector localPos; + CVector vehDoorPos; + + localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f); + vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition(); + +/* + // Not used. + CVector localVehDoorOffset; + + if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) { + localVehDoorOffset = vecPedVanRearDoorAnimOffset; + } else { + if (veh->bIsLow) { + localVehDoorOffset = vecPedCarDoorLoAnimOffset; + } else { + localVehDoorOffset = vecPedCarDoorAnimOffset; + } + } + + vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition(); +*/ + return vehDoorPos; +} + +void +CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen) +{ + CVector *enterOffset = nil; + if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver + || m_vehEnterType == CAR_DOOR_RF && veh->pPassengers[0] + || m_vehEnterType == CAR_DOOR_LR && veh->pPassengers[1] + || m_vehEnterType == CAR_DOOR_RR && veh->pPassengers[2]) + { + enterOffset = &vecPedQuickDraggedOutCarAnimOffset; + } + + CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF); + CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); + + // Left front door is closer + if ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) { + + if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; + } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { + m_vehEnterType = CAR_DOOR_RF; + posToOpen = rfPos; + } + } else { + + if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { + + CPed *rfPassenger = veh->pPassengers[0]; + if (rfPassenger && (rfPassenger->m_leader == this || rfPassenger->bDontDragMeOutCar || + veh->VehicleCreatedBy == MISSION_VEHICLE && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) + || (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { + + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; + } else { + m_vehEnterType = CAR_DOOR_RF; + posToOpen = rfPos; + } + } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; + } + } +} + +bool +CPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen) +{ + CVector rfPos, lrPos, rrPos; + bool canEnter = false; + + CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex()); + + switch (veh->GetModelIndex()) { + case MI_BUS: + m_vehEnterType = CAR_DOOR_RF; + posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); + return true; + case MI_RHINO: + default: + break; + } + + CVector2D rfPosDist(999.0f, 999.0f); + CVector2D lrPosDist(999.0f, 999.0f); + CVector2D rrPosDist(999.0f, 999.0f); + + if (!veh->pPassengers[0] + && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) { + + rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); + canEnter = true; + rfPosDist = rfPos - GetPosition(); + } + if (vehModel->m_numDoors == 4) { + if (!veh->pPassengers[1] + && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) { + lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR); + canEnter = true; + lrPosDist = lrPos - GetPosition(); + } + if (!veh->pPassengers[2] + && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) + && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) { + rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR); + canEnter = true; + rrPosDist = rrPos - GetPosition(); + } + + // When the door we should enter is blocked by some object. + if (!canEnter) + veh->ShufflePassengersToMakeSpace(); + } + + CVector2D nextToCompare = rfPosDist; + posToOpen = rfPos; + m_vehEnterType = CAR_DOOR_RF; + if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { + m_vehEnterType = CAR_DOOR_LR; + posToOpen = lrPos; + nextToCompare = lrPosDist; + } + + if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) { + m_vehEnterType = CAR_DOOR_RR; + posToOpen = rrPos; + } + return canEnter; +} + +void +CPed::GoToNearestDoor(CVehicle *veh) +{ + CVector posToOpen; + GetNearestDoor(veh, posToOpen); + SetSeek(posToOpen, 0.5f); + SetMoveState(PEDMOVE_RUN); +} + +void +CPed::SetAnimOffsetForEnterOrExitVehicle(void) +{ + // FIX: If there were no translations on enter anims, there were overflows all over this function. + + CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy; + CAnimBlendSequence *seq = enterAssoc->sequences; + CAnimManager::UncompressAnimation(enterAssoc); + if (seq->numFrames > 0) { + if (!seq->HasTranslation()) + vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f); + else { + KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); + vecPedDraggedOutCarAnimOffset = lastFrame->translation; + } + } + + enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LHS)->hierarchy; + seq = enterAssoc->sequences; + CAnimManager::UncompressAnimation(enterAssoc); + if (seq->numFrames > 0) { + if (!seq->HasTranslation()) + vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f); + else { + KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); + vecPedCarDoorAnimOffset = lastFrame->translation; + } + } + + enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS)->hierarchy; + seq = enterAssoc->sequences; + CAnimManager::UncompressAnimation(enterAssoc); + if (seq->numFrames > 0) { + if (!seq->HasTranslation()) + vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f); + else { + KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); + vecPedCarDoorLoAnimOffset = lastFrame->translation; + } + } + + enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_QJACKED)->hierarchy; + seq = enterAssoc->sequences; + CAnimManager::UncompressAnimation(enterAssoc); + if (seq->numFrames > 0) { + if (!seq->HasTranslation()) + vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f); + else { + KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); + vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation; + } + } + + enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_VAN_GETIN_L)->hierarchy; + seq = enterAssoc->sequences; + CAnimManager::UncompressAnimation(enterAssoc); + if (seq->numFrames > 0) { + if (!seq->HasTranslation()) + vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f); + else { + KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); + vecPedVanRearDoorAnimOffset = lastFrame->translation; + } + } + + enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_TRAIN_GETOUT)->hierarchy; + seq = enterAssoc->sequences; + CAnimManager::UncompressAnimation(enterAssoc); + if (seq->numFrames > 0) { + if (!seq->HasTranslation()) + vecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f); + else { + KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1); + vecPedTrainDoorAnimOffset = lastFrame->translation; + } + } +} + +void +CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; + + CVehicle *veh = ped->m_pMyVehicle; + + CVector finalPos; + CVector draggedOutOffset; + + CMatrix pedMat(ped->GetMatrix()); + ped->bUsesCollision = true; + ped->RestartNonPartialAnims(); + draggedOutOffset = vecPedQuickDraggedOutCarAnimOffset; + if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR) + draggedOutOffset.x = -draggedOutOffset.x; + + finalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition(); + CPedPlacement::FindZCoorForPed(&finalPos); + ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + ped->SetPosition(finalPos); + + if (veh) { + ped->m_fRotationDest = veh->GetForward().Heading() - HALFPI; + ped->m_fRotationCur = ped->m_fRotationDest; + ped->CalculateNewOrientation(); + + if (!veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedQuickDraggedOutCarAnimOffset)) + ped->PositionPedOutOfCollision(); + } + + if (!ped->CanSetPedState()) + return; + + ped->SetIdle(); + if (veh) { + if (ped->bFleeAfterExitingCar) { + ped->bFleeAfterExitingCar = false; + ped->SetFlee(veh->GetPosition(), 14000); + + } else if (ped->bWanderPathAfterExitingCar) { + ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); + ped->bWanderPathAfterExitingCar = false; + + } else if (ped->bGonnaKillTheCarJacker) { + ped->bGonnaKillTheCarJacker = false; + if (ped->m_pedInObjective && CGeneral::GetRandomNumber() & 1) { + if (ped->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) + ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped->m_pedInObjective); + + } else { + CPed *driver = veh->pDriver; + if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) { + ped->SetFlee(veh->GetPosition(), 14000); + } else { + ped->ClearObjective(); + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + } + ped->bUsePedNodeSeek = true; + ped->m_pNextPathNode = nil; + ped->Say(SOUND_PED_FLEE_RUN); + } + } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear + && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE + && veh->pDriver && veh->pDriver->IsPlayer() + && !CTheScripts::IsPlayerOnAMission()) { + +#ifndef VC_PED_PORTS + if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) { + ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver); + } else +#endif + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + +#ifdef VC_PED_PORTS + } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear + && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE + && !veh->pDriver && FindPlayerPed()->m_carInObjective == veh + && !CTheScripts::IsPlayerOnAMission()) { + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); +#endif + } else { + ped->SetFindPathAndFlee(veh->GetPosition(), 10000); + if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) { + ped->SetMoveState(PEDMOVE_SPRINT); + ped->Say(SOUND_PED_FLEE_SPRINT); + } else { + ped->Say(SOUND_PED_FLEE_RUN); + } + } + } + if (ped->m_nLastPedState == PED_IDLE) + ped->m_nLastPedState = PED_WANDER_PATH; +} + +void +CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed *ped = (CPed*)arg; + + ped->bUsesCollision = true; + ped->RestartNonPartialAnims(); + bool itsRearDoor = false; + + if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR) + itsRearDoor = true; + + CMatrix pedMat(ped->GetMatrix()); + CVector posAfterBeingDragged = Multiply3x3(pedMat, (itsRearDoor ? -vecPedDraggedOutCarAnimOffset : vecPedDraggedOutCarAnimOffset)); + posAfterBeingDragged += ped->GetPosition(); +#ifndef VC_PED_PORTS + posAfterBeingDragged.z += 1.0f; +#endif + CPedPlacement::FindZCoorForPed(&posAfterBeingDragged); + ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + ped->SetPosition(posAfterBeingDragged); + + if (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedDraggedOutCarAnimOffset)) { + ped->PositionPedOutOfCollision(); + } + + if (!ped->CanSetPedState()) + return; + + if (!ped->m_pMyVehicle) { + ped->SetIdle(); + ped->SetGetUp(); + return; + } + + CPed *driver = ped->m_pMyVehicle->pDriver; + + if (ped->IsPlayer()) { + ped->SetIdle(); + + } else if (ped->bFleeAfterExitingCar) { + ped->bFleeAfterExitingCar = false; + ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000); + + } else if (ped->bWanderPathAfterExitingCar) { + ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); + ped->bWanderPathAfterExitingCar = false; + + } else if (ped->bGonnaKillTheCarJacker) { + // Kill objective is already set at this point. + + ped->bGonnaKillTheCarJacker = false; + if (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) { + if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) { + ped->m_nPedState = PED_NONE; + ped->m_nLastPedState = PED_NONE; + ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000); + } else { + ped->ClearObjective(); + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); + } + } + + } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR + && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && driver + && driver->IsPlayer() && !CTheScripts::IsPlayerOnAMission()) { + +#ifndef VC_PED_PORTS + if (CGeneral::GetRandomNumber() & 1) + ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver); + else +#endif + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); + + } else { +#ifdef VC_PED_PORTS + if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR + && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !driver + && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission()) + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); + else +#endif + { + ped->m_nPedState = PED_NONE; + ped->m_nLastPedState = PED_NONE; + ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000); + } + } + ped->SetGetUp(); +} + +uint8 +CPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos) +{ + GetNearestTrainPedPosition(train, doorPos); +/* + // Not used. + CVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(train->m_modelIndex); + CMatrix trainMat = CMatrix(train->GetMatrix()); + + doorPos = trainModel->m_positions[m_vehEnterType]; + doorPos.x -= 1.5f; + doorPos = Multiply3x3(trainMat, doorPos); + doorPos += train->GetPosition(); +*/ + return 1; +} + +uint8 +CPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos) +{ + CVector enterStepOffset; + CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(train->GetModelIndex()); + CMatrix trainMat = CMatrix(train->GetMatrix()); + CVector leftEntryPos, rightEntryPos, midEntryPos; + float distLeftEntry, distRightEntry, distMidEntry; + + // enterStepOffset = vecPedCarDoorAnimOffset; + enterStepOffset = CVector(1.5f, 0.0f, 0.0f); + + if (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) { + distLeftEntry = 999.0f; + } else { + leftEntryPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterStepOffset; + leftEntryPos = Multiply3x3(trainMat, leftEntryPos); + leftEntryPos += train->GetPosition(); + distLeftEntry = (leftEntryPos - GetPosition()).Magnitude(); + } + + if (train->pPassengers[TRAIN_POS_MID_ENTRY]) { + distMidEntry = 999.0f; + } else { + midEntryPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterStepOffset; + midEntryPos = Multiply3x3(trainMat, midEntryPos); + midEntryPos += train->GetPosition(); + distMidEntry = (midEntryPos - GetPosition()).Magnitude(); + } + + if (train->pPassengers[TRAIN_POS_RIGHT_ENTRY]) { + distRightEntry = 999.0f; + } else { + rightEntryPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterStepOffset; + rightEntryPos = Multiply3x3(trainMat, rightEntryPos); + rightEntryPos += train->GetPosition(); + distRightEntry = (rightEntryPos - GetPosition()).Magnitude(); + } + + if (distMidEntry < distLeftEntry) { + if (distMidEntry < distRightEntry) { + enterPos = midEntryPos; + m_vehEnterType = TRAIN_POS_MID_ENTRY; + } else { + enterPos = rightEntryPos; + m_vehEnterType = TRAIN_POS_RIGHT_ENTRY; + } + } else if (distRightEntry < distLeftEntry) { + enterPos = rightEntryPos; + m_vehEnterType = TRAIN_POS_RIGHT_ENTRY; + } else { + enterPos = leftEntryPos; + m_vehEnterType = TRAIN_POS_LEFT_ENTRY; + } + + return 1; +} + +void +CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed *ped = (CPed*)arg; + CTrain *veh = (CTrain*)ped->m_pMyVehicle; + + if (!veh) + return; + + ped->bInVehicle = true; + ped->m_nPedState = PED_DRIVING; + ped->RestorePreviousObjective(); + ped->SetMoveState(PEDMOVE_STILL); + veh->AddPassenger(ped); +} + +void +CPed::SetEnterTrain(CVehicle *train, uint32 unused) +{ + if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen()) + return; + + /* + // Not used + CVector enterPos; + GetNearestTrainPedPosition(train, enterPos); + */ + m_fRotationCur = train->GetForward().Heading() - HALFPI; + m_pMyVehicle = train; + m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + + m_nPedState = PED_ENTER_TRAIN; + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f); + m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this); + bUsesCollision = false; + LineUpPedWithTrain(); + if (IsPlayer()) { + if (((CPlayerPed*)this)->m_bAdrenalineActive) + ((CPlayerPed*)this)->ClearAdrenaline(); + } +} + +void +CPed::EnterTrain(void) +{ + LineUpPedWithTrain(); +} + +void +CPed::SetPedPositionInTrain(void) +{ + LineUpPedWithTrain(); +} + +void +CPed::LineUpPedWithTrain(void) +{ + CVector lineUpPos; + CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex()); + CVector enterOffset(1.5f, 0.0f, -0.2f); + + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI; + m_fRotationDest = m_fRotationCur; + + if (!bInVehicle) { + GetNearestTrainDoor(m_pMyVehicle, lineUpPos); + lineUpPos.z += 0.2f; + } else { + if (m_pMyVehicle->pPassengers[TRAIN_POS_LEFT_ENTRY] == this) { + + lineUpPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterOffset; + + } else if (m_pMyVehicle->pPassengers[TRAIN_POS_MID_ENTRY] == this) { + + lineUpPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterOffset; + + } else if (m_pMyVehicle->pPassengers[TRAIN_POS_RIGHT_ENTRY] == this) { + + lineUpPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterOffset; + } + lineUpPos = Multiply3x3(m_pMyVehicle->GetMatrix(), lineUpPos); + lineUpPos += m_pMyVehicle->GetPosition(); + } + + if (m_pVehicleAnim) { + float percentageLeft = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength; + lineUpPos += (GetPosition() - lineUpPos) * percentageLeft; + } + + SetPosition(lineUpPos); + SetHeading(m_fRotationCur); +} + +void +CPed::SetExitTrain(CVehicle* train) +{ + if (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen()) + return; + + /* + // Not used + CVector exitPos; + GetNearestTrainPedPosition(train, exitPos); + */ + m_nPedState = PED_EXIT_TRAIN; + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f); + m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this); + bUsesCollision = false; + LineUpPedWithTrain(); +} + +void +CPed::ExitTrain(void) +{ + LineUpPedWithTrain(); +} + +void +CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; + + CVehicle *veh = ped->m_pMyVehicle; + + if (ped->m_pVehicleAnim) + ped->m_pVehicleAnim->blendDelta = -1000.0f; + + ped->bUsesCollision = true; + ped->m_pVehicleAnim = nil; + ped->bInVehicle = false; + ped->m_nPedState = PED_IDLE; + ped->RestorePreviousObjective(); + ped->SetMoveState(PEDMOVE_STILL); + + CMatrix pedMat(ped->GetMatrix()); + ped->m_fRotationCur = HALFPI + veh->GetForward().Heading(); + ped->m_fRotationDest = ped->m_fRotationCur; + CVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset); + posAfterExit += ped->GetPosition(); + CPedPlacement::FindZCoorForPed(&posAfterExit); + ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + ped->SetPosition(posAfterExit); + ped->SetHeading(ped->m_fRotationCur); + veh->RemovePassenger(ped); +} + +void +CPed::RegisterThreatWithGangPeds(CEntity *attacker) +{ + CPed *attackerPed = nil; + if (attacker) { + if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) { + if (attacker->IsPed()) { + attackerPed = (CPed*)attacker; + } else { + if (!attacker->IsVehicle()) + return; + + attackerPed = ((CVehicle*)attacker)->pDriver; + if (!attackerPed) + return; + } + + if (attackerPed && (attackerPed->IsPlayer() || attackerPed->IsGangMember())) { + for (int i = 0; i < m_numNearPeds; ++i) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed->IsPointerValid()) { + if (nearPed != this && nearPed->m_nPedType == m_nPedType) + nearPed->m_fearFlags |= CPedType::GetFlag(attackerPed->m_nPedType); + } + } + } + } + } + + if (attackerPed && attackerPed->IsPlayer() && (attackerPed->m_nPedState == PED_CARJACK || attackerPed->bInVehicle)) { + if (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOYZ) { + int16 lastVehicle; + CEntity *vehicles[8]; + CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + + if (lastVehicle > 8) + lastVehicle = 8; + + for (int j = 0; j < lastVehicle; ++j) { + CVehicle *nearVeh = (CVehicle*) vehicles[j]; + + if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) { + CPed *nearVehDriver = nearVeh->pDriver; + + if (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType) { + + if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) { + nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f; + nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY; + nearVeh->SetStatus(STATUS_PHYSICS); + nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE; + nearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + } + } + } + } + } + } +} + +// Some helper function which doesn't exist in og game. +inline void +SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVector2D farDist, CPathNode *closeNode, CPathNode *closeNode2, int runCount = 3) +{ + for (int i = 0; i < node->numLinks; i++) { + + CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)]; + + if (testNode && testNode != closeNode && testNode != closeNode2) { + CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition()); + float dist = posDiff.MagnitudeSqr(); + + if (farDist.MagnitudeSqr() > dist) { + + if (closeDist.MagnitudeSqr() <= dist) { + ped->m_pNextPathNode = closeNode; + closeDist = posDiff; + } else { + ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode); + farDist = posDiff; + } + } + + if (--runCount > 0) + SelectClosestNodeForSeek(ped, testNode, closeDist, farDist, closeNode, (closeNode2 ? closeNode2 : testNode), runCount); + } + } +} + +bool +CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords) +{ + if (m_pNextPathNode || !bUsePedNodeSeek) + return false; + + CVector ourPos = GetPosition(); + + int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f); + + CVector seekObjPos = m_vecSeekPos; + seekObjPos.z += 1.0f; + + if (CWorld::GetIsLineOfSightClear(ourPos, seekObjPos, true, false, false, true, false, false, false)) + return false; + + m_pNextPathNode = nil; + + CVector2D seekPosDist (m_vecSeekPos - ourPos); + + CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId]; + CVector2D closeDist(m_vecSeekPos - closestNode->GetPosition()); + + SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil); + + // Above function decided that going to the next node is more logical than seeking the object. + if (m_pNextPathNode) { + + CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos; + if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) { + *bestCoords = m_pNextPathNode->GetPosition(); + return true; + } + m_pNextPathNode = nil; + } + + return false; +} + +bool +CPed::DuckAndCover(void) +{ + if (!m_pedInObjective || CTimer::GetTimeInMilliseconds() <= m_duckAndCoverTimer) + return false; + + if (bKindaStayInSamePlace){ + + if (CTimer::GetTimeInMilliseconds() <= m_leaveCarTimer) { + if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) { + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + } + if (!bIsAimingGun) + SetAimFlag(m_pedInObjective); + + } else { + bCrouchWhenShooting = false; + bKindaStayInSamePlace = false; + bIsDucking = false; + bDuckAndCover = false; + m_headingRate = 10.0f; + m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000); + if (m_pSeekTarget && m_pSeekTarget->IsVehicle()) + ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover--; + } + return false; + } + + bool justDucked = false; + CVehicle *foundVeh = nil; + float maxDist = 225.0f; + bIsDucking = false; + bCrouchWhenShooting = false; + if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { + CVector pos = GetPosition(); + int16 lastVehicle; + CEntity *vehicles[8]; + CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + + for (int i = 0; i < lastVehicle; i++) { + CVehicle *veh = (CVehicle*) vehicles[i]; + if (veh->m_vecMoveSpeed.Magnitude() <= 0.02f + && !veh->bIsBus + && !veh->bIsVan + && !veh->bIsBig + && veh->m_numPedsUseItAsCover < 3) { + float dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr(); + if (dist < maxDist) { + maxDist = dist; + foundVeh = veh; + } + } + } + if (foundVeh) { + // Unused. + // CVector lfWheelPos, rfWheelPos; + // foundVeh->GetComponentWorldPosition(CAR_WHEEL_RF, rfWheelPos); + // foundVeh->GetComponentWorldPosition(CAR_WHEEL_LF, lfWheelPos); + CVector rightSide, leftSide; + + // 3 persons can use the car as cover. Found the correct position for us. + if (foundVeh->m_numPedsUseItAsCover == 2) { + rightSide = CVector(1.5f, -0.5f, 0.0f); + leftSide = CVector(-1.5f, -0.5f, 0.0f); + } else if (foundVeh->m_numPedsUseItAsCover == 1) { + rightSide = CVector(1.5f, 0.5f, 0.0f); + leftSide = CVector(-1.5f, 0.5f, 0.0f); + } else if (foundVeh->m_numPedsUseItAsCover == 0) { + rightSide = CVector(1.5f, 0.0f, 0.0f); + leftSide = CVector(-1.5f, 0.0f, 0.0f); + } + + CMatrix vehMatrix(foundVeh->GetMatrix()); + CVector duckAtRightSide = Multiply3x3(vehMatrix, rightSide) + foundVeh->GetPosition(); + + CVector duckAtLeftSide = Multiply3x3(vehMatrix, leftSide) + foundVeh->GetPosition(); + + CVector distWithPedRightSide = m_pedInObjective->GetPosition() - duckAtRightSide; + CVector distWithPedLeftSide = m_pedInObjective->GetPosition() - duckAtLeftSide; + + CVector duckPos; + if (distWithPedRightSide.MagnitudeSqr() <= distWithPedLeftSide.MagnitudeSqr()) + duckPos = duckAtLeftSide; + else + duckPos = duckAtRightSide; + + if (CWorld::TestSphereAgainstWorld(duckPos, 0.5f, nil, true, true, true, false, false, false) + && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) { + SetSeek(duckPos, 1.0f); + m_headingRate = 15.0f; + bIsRunning = true; + bDuckAndCover = true; + justDucked = true; + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500; + if (foundVeh->bIsLawEnforcer) + m_carInObjective = foundVeh; + + // BUG? Shouldn't we register the reference? + m_pSeekTarget = foundVeh; + ClearPointGunAt(); + } else { + m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000); + bDuckAndCover = false; + } + } else { + bDuckAndCover = false; + } + } + + if (!justDucked && !bDuckAndCover) + return false; + + if (!Seek()) + return true; + + bKindaStayInSamePlace = true; + bDuckAndCover = false; + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); + if (m_pSeekTarget && m_pSeekTarget->IsVehicle()) + ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++; + + SetIdle(); + SetMoveState(PEDMOVE_STILL); + SetMoveAnim(); + if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) { + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + } + + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 6000); + return false; +} + +CVector +CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset) +{ + CVector doorPos; + CMatrix vehMat(veh->GetMatrix()); + + doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset)); + + return veh->GetPosition() + doorPos; +} + +CVector +CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult) +{ + CVehicleModelInfo *vehModel; + CVector vehDoorPos; + CVector vehDoorOffset; + float seatOffset; + + vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex()); + if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) { + seatOffset = 0.0f; + vehDoorOffset = vecPedVanRearDoorAnimOffset; + } else { + seatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult; + if (veh->bLowVehicle) { + vehDoorOffset = vecPedCarDoorLoAnimOffset; + } else { + vehDoorOffset = vecPedCarDoorAnimOffset; + } + } + + switch (component) { + case CAR_DOOR_RF: + vehDoorPos = vehModel->GetFrontSeatPosn(); + vehDoorPos.x += seatOffset; + vehDoorOffset.x = -vehDoorOffset.x; + break; + + case CAR_DOOR_RR: + vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT]; + vehDoorPos.x += seatOffset; + vehDoorOffset.x = -vehDoorOffset.x; + break; + + case CAR_DOOR_LF: + vehDoorPos = vehModel->GetFrontSeatPosn(); + vehDoorPos.x = -(vehDoorPos.x + seatOffset); + break; + + case CAR_DOOR_LR: + vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT]; + vehDoorPos.x = -(vehDoorPos.x + seatOffset); + break; + + default: + vehDoorPos = vehModel->GetFrontSeatPosn(); + vehDoorOffset = CVector(0.0f, 0.0f, 0.0f); + } + return vehDoorPos - vehDoorOffset; +} + +void +CPed::SetDuck(uint32 time) +{ + if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer) + return; + + if (bCrouchWhenShooting && (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN)) { + CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); + if (!duckAssoc || duckAssoc->blendDelta < 0.0f) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_LOW, 4.0f); + bIsDucking = true; + m_duckTimer = CTimer::GetTimeInMilliseconds() + time; + } + } else { + CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); + if (!duckAssoc || duckAssoc->blendDelta < 0.0f) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f); + bIsDucking = true; + m_duckTimer = CTimer::GetTimeInMilliseconds() + time; + } + } +} + +void +CPed::Duck(void) +{ + if (CTimer::GetTimeInMilliseconds() > m_duckTimer) + ClearDuck(); +} + +void +CPed::ClearDuck(void) +{ + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); + if (!animAssoc) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); + + if (!animAssoc) { + bIsDucking = false; + return; + } + } + + if (!bCrouchWhenShooting) + return; + + if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN) + return; + + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT); + if (!animAssoc || animAssoc->blendDelta < 0.0f) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); + } +} + +void +CPed::InformMyGangOfAttack(CEntity *attacker) +{ + CPed *attackerPed; + + if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) + return; + + if (attacker->IsPed()) { + attackerPed = (CPed*)attacker; + } else { + if (!attacker->IsVehicle()) + return; + + attackerPed = ((CVehicle*)attacker)->pDriver; + if (!attackerPed) + return; + } + + if (attackerPed->m_nPedType == PEDTYPE_COP) + return; + + for (int i = 0; i < m_numNearPeds; i++) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed && nearPed != this) { + CPed *leader = nearPed->m_leader; + if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper) + { + nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed); + nearPed->SetObjectiveTimer(30000); + } + } + } +} + +void +CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed* ped = (CPed*)arg; + + CAutomobile* veh = (CAutomobile*)(ped->m_pMyVehicle); + + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (veh->bLowVehicle) { + veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR_LOW, 1.0f); + } else { + veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, 1.0f); + } + + veh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF; + + if (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) + veh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK); +} + +void +CPed::SetSeekBoatPosition(CVehicle *boat) +{ + if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver +#if defined VC_PED_PORTS || defined FIX_BUGS + || !IsPedInControl() +#endif + ) + return; + + SetStoredState(); + m_carInObjective = boat; + m_carInObjective->RegisterReference((CEntity **) &m_carInObjective); + m_pMyVehicle = boat; + m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + m_distanceToCountSeekDone = 0.5f; + m_nPedState = PED_SEEK_IN_BOAT; +} + +void +CPed::SeekBoatPosition(void) +{ + if (m_carInObjective && !m_carInObjective->pDriver) { + CVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo(); + + CVector enterOffset; + enterOffset = boatModel->GetFrontSeatPosn(); + enterOffset.x = 0.0f; + CMatrix boatMat(m_carInObjective->GetMatrix()); + SetMoveState(PEDMOVE_WALK); + m_vecSeekPos = boatMat * enterOffset; + if (Seek()) { + // We arrived to the boat + m_vehEnterType = 0; + SetEnterCar(m_carInObjective, 0); + } + } else + RestorePreviousState(); +} + +bool +CPed::IsRoomToBeCarJacked(void) +{ + if (!m_pMyVehicle) + return false; + + CVector offset; + if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) { + offset = vecPedDraggedOutCarAnimOffset; + } else { + offset = vecPedQuickDraggedOutCarAnimOffset; + } + + offset.z = 0.0f; + if (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &offset)) { + return true; + } + + return false; +} + +void +CPed::RemoveInCarAnims(void) +{ + if (!IsPlayer()) + return; + + CAnimBlendAssociation *animAssoc; + + if (m_pMyVehicle && m_pMyVehicle->bLowVehicle) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + } else { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + } + +#ifdef VC_PED_PORTS + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; +#endif + + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB); + if (animAssoc) + animAssoc->blendDelta = -1000.0f; +} + +bool +CPed::PositionPedOutOfCollision(void) +{ + CVehicle *veh; + CVector posNearVeh; + CVector posSomewhereClose; + bool putNearVeh = false; + bool putSomewhereClose = false; + int smallestDistNearVeh = 999; + int smallestDistSomewhereClose = 999; + + if (!m_pMyVehicle) + return false; + + CVector vehPos = m_pMyVehicle->GetPosition(); + CVector potentialPos; + potentialPos.y = GetPosition().y - 3.5f; + potentialPos.z = GetPosition().z; + + for (int yTry = 0; yTry < 15; yTry++) { + potentialPos.x = GetPosition().x - 3.5f; + + for (int xTry = 0; xTry < 15; xTry++) { + CPedPlacement::FindZCoorForPed(&potentialPos); + CVector distVec = potentialPos - vehPos; + float dist = distVec.Magnitude(); + + // Makes close distances bigger for some reason. + float mult = (0.6f + dist) / dist; + CVector adjustedPotentialPos = distVec * mult + vehPos; + if (CWorld::GetIsLineOfSightClear(vehPos, adjustedPotentialPos, true, false, false, true, false, false, false) + && !CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) { + + float potentialChangeSqr = (potentialPos - GetPosition()).MagnitudeSqr(); + veh = (CVehicle*)CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, false, true, false, false, false, false); + if (veh) { + if (potentialChangeSqr < smallestDistNearVeh) { + posNearVeh = potentialPos; + putNearVeh = true; + smallestDistNearVeh = potentialChangeSqr; + } + } else if (potentialChangeSqr < smallestDistSomewhereClose) { + smallestDistSomewhereClose = potentialChangeSqr; + posSomewhereClose = potentialPos; + putSomewhereClose = true; + } + } + potentialPos.x += 0.5f; + } + potentialPos.y += 0.5f; + } + + if (!putSomewhereClose && !putNearVeh) + return false; + + // We refrain from using posNearVeh, probably because of it may be top of the vehicle. + if (putSomewhereClose) { + SetPosition(posSomewhereClose); + } else { + CVector vehSize = veh->GetModelInfo()->GetColModel()->boundingBox.max; + posNearVeh.z += vehSize.z; + SetPosition(posNearVeh); + } + return true; +} + +bool +CPed::WarpPedToNearLeaderOffScreen(void) +{ + bool teleported = false; + if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) + return false; + + CVector warpToPos = m_leader->GetPosition(); + CVector distVec = warpToPos - GetPosition(); + float halfOfDist = distVec.Magnitude() * 0.5f; + CVector halfNormalizedDist = distVec / halfOfDist; + + CVector appropriatePos = GetPosition(); + CVector zCorrectedPos = appropriatePos; + int tryCount = Min(10, halfOfDist); + for (int i = 0; i < tryCount; ++i) { + appropriatePos += halfNormalizedDist; + CPedPlacement::FindZCoorForPed(&zCorrectedPos); + + if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f) + continue; + + appropriatePos.z = zCorrectedPos.z; + if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix()) + && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false) + && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) { + teleported = true; + Teleport(appropriatePos); + } + } + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000; + return teleported; +} + +bool +CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo) +{ + bool teleported = false; + if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) + return false; + + CVector warpToPos = warpTo->GetPosition(); + CVector distVec = warpToPos - GetPosition(); + float halfOfDist = distVec.Magnitude() * 0.5f; + CVector halfNormalizedDist = distVec / halfOfDist; + + CVector appropriatePos = GetPosition(); + CVector zCorrectedPos = appropriatePos; + int tryCount = Min(10, halfOfDist); + for (int i = 0; i < tryCount; ++i) { + appropriatePos += halfNormalizedDist; + CPedPlacement::FindZCoorForPed(&zCorrectedPos); + + if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f) + continue; + + appropriatePos.z = zCorrectedPos.z; + if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix()) + && CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false) + && !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) { + teleported = true; + Teleport(appropriatePos); + } + } + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000; + return teleported; +} \ No newline at end of file diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp new file mode 100644 index 00000000..21310aaa --- /dev/null +++ b/src/peds/PedFight.cpp @@ -0,0 +1,3250 @@ +#include "common.h" + +#include "main.h" +#include "RpAnimBlend.h" +#include "AnimBlendClumpData.h" +#include "AnimBlendAssociation.h" +#include "Camera.h" +#include "CarCtrl.h" +#include "Darkel.h" +#include "DMAudio.h" +#include "FileMgr.h" +#include "General.h" +#include "Object.h" +#include "Pad.h" +#include "Particle.h" +#include "Ped.h" +#include "PlayerPed.h" +#include "Stats.h" +#include "TempColModels.h" +#include "VisibilityPlugins.h" +#include "Vehicle.h" +#include "Automobile.h" +#include "WaterLevel.h" +#include "World.h" + +uint16 nPlayerInComboMove; + +RpClump *flyingClumpTemp; + +// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat. +FightMove tFightMoves[NUM_FIGHTMOVES] = { + {NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_PUNCH_R, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0}, + {ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0}, + {ANIM_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0}, + {ANIM_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0}, + {ANIM_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0}, + {ANIM_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0}, + {ANIM_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0}, + {ANIM_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0}, + {ANIM_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0}, + {ANIM_KICK_FLOOR, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0}, + {ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, +}; + +static PedOnGroundState +CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround) +{ + PedOnGroundState stateToReturn; + float angleToFace; + CPed *currentPed = nil; + PedState currentPedState; + CPed *pedOnTheFloor = nil; + CPed *deadPed = nil; + CPed *pedBelow = nil; + bool foundDead = false; + bool foundOnTheFloor = false; + bool foundBelow = false; + float angleDiff; + float distance; + + if (!CGame::nastyGame) + return NO_PED; + + for (int currentPedId = 0; currentPedId < attacker->m_numNearPeds; currentPedId++) { + + currentPed = attacker->m_nearPeds[currentPedId]; + + CVector posDifference = currentPed->GetPosition() - attacker->GetPosition(); + distance = posDifference.Magnitude(); + + if (distance < 2.0f) { + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + currentPed->GetPosition().x, currentPed->GetPosition().y, + attacker->GetPosition().x, attacker->GetPosition().y); + + angleToFace = CGeneral::LimitRadianAngle(angleToFace); + attacker->m_fRotationCur = CGeneral::LimitRadianAngle(attacker->m_fRotationCur); + + angleDiff = Abs(angleToFace - attacker->m_fRotationCur); + + if (angleDiff > PI) + angleDiff = 2 * PI - angleDiff; + + currentPedState = currentPed->m_nPedState; + + if (currentPed->OnGroundOrGettingUp()) { + if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) { + if (currentPedState == PED_DEAD) { + foundDead = 1; + if (!deadPed) + deadPed = currentPed; + } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) { + foundOnTheFloor = 1; + if (!pedOnTheFloor) + pedOnTheFloor = currentPed; + } + } + } else if ((distance < 0.8f && angleDiff < DEGTORAD(75.0f)) + || (distance < 1.3f && angleDiff < DEGTORAD(55.0f)) + || (distance < 1.7f && angleDiff < DEGTORAD(35.0f)) + || (distance < 2.0f && angleDiff < DEGTORAD(30.0f))) { + + // Either this condition or below one was probably returning 4 early in development. See Fight(). + foundBelow = 1; + pedBelow = currentPed; + break; + } else { + if (angleDiff < DEGTORAD(75.0f)) { + foundBelow = 1; + if (!pedBelow) + pedBelow = currentPed; + } + } + } + } + + if (foundOnTheFloor) { + currentPed = pedOnTheFloor; + stateToReturn = PED_ON_THE_FLOOR; + } else if (foundDead) { + currentPed = deadPed; + stateToReturn = PED_DEAD_ON_THE_FLOOR; + } else if (foundBelow) { + currentPed = pedBelow; + stateToReturn = PED_IN_FRONT_OF_ATTACKER; + } else { + currentPed = nil; + stateToReturn = NO_PED; + } + + if (pedOnGround) + *pedOnGround = currentPed; + + return stateToReturn; +} + +void +CPed::SetPointGunAt(CEntity *to) +{ + if (to) { + SetLookFlag(to, true); + SetAimFlag(to); +#ifdef VC_PED_PORTS + SetLookTimer(INT32_MAX); +#endif + } + + if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK) + return; + + if (m_nPedState != PED_ATTACK) + SetStoredState(); + + m_nPedState = PED_AIM_GUN; + bIsPointingGunAt = true; + CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + SetMoveState(PEDMOVE_NONE); + + CAnimBlendAssociation *aimAssoc; + + if (bCrouchWhenShooting) + aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay); + else + aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay); + + if (!aimAssoc || aimAssoc->blendDelta < 0.0f) { + if (bCrouchWhenShooting) + aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f); + else + aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay); + + aimAssoc->blendAmount = 0.0f; + aimAssoc->blendDelta = 8.0f; + } + if (to) + Say(SOUND_PED_ATTACK); +} + +void +CPed::PointGunAt(void) +{ + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay); + if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f) + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay); + + if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) { + weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart); + weaponAssoc->flags &= ~ASSOC_RUNNING; + + if (weaponInfo->m_bCanAimWithArm) + m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM; + else + m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; + } +} + +void +CPed::ClearPointGunAt(void) +{ + CAnimBlendAssociation *animAssoc; + CWeaponInfo *weaponInfo; + + ClearLookFlag(); + ClearAimFlag(); + bIsPointingGunAt = false; +#ifndef VC_PED_PORTS + if (m_nPedState == PED_AIM_GUN) { + RestorePreviousState(); +#else + if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) { + m_nPedState = PED_IDLE; + RestorePreviousState(); + } +#endif + weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay); + if (!animAssoc || animAssoc->blendDelta < 0.0f) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay); + } + if (animAssoc) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->blendDelta = -4.0f; + } +#ifndef VC_PED_PORTS + } +#endif +} + +void +CPed::SetAttack(CEntity *victim) +{ + CPed *victimPed = nil; + if (victim && victim->IsPed()) + victimPed = (CPed*)victim; + + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED); + if (animAssoc) { + animAssoc->blendDelta = -1000.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + + if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE) + return; + + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HGUN_RELOAD)) { + bIsAttacking = false; + return; + } + + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) { + if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected) + bIsAttacking = false; + else + bIsAttacking = true; + + return; + } + + CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + if (curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && !IsPlayer()) { + if (GetWeapon()->HitsGround(this, nil, victim)) + return; + } + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { + if (IsPlayer() || + (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) { + + if (m_nPedState != PED_ATTACK) { + m_nPedState = PED_ATTACK; + bIsAttacking = false; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f); + animAssoc->SetRun(); + if (animAssoc->currentTime == animAssoc->hierarchy->totalLength) + animAssoc->SetCurrentTime(0.0f); + + animAssoc->SetFinishCallback(FinishedAttackCB, this); + } + } else { + StartFightAttack(CGeneral::GetRandomNumber() % 256); + } + return; + } + + m_pSeekTarget = victim; + if (m_pSeekTarget) + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + + if (curWeapon->m_bCanAim) { + CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition(); + CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false); + if (obstacle) + return; + + m_pLookTarget = victim; + if (victim) { + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + } + if (m_pLookTarget) { + SetAimFlag(m_pLookTarget); + } else { + SetAimFlag(m_fRotationCur); + + if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam()) + ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch(); + } + } + if (m_nPedState == PED_ATTACK) { + bIsAttacking = true; + return; + } + + if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) { + if (IsPlayer()) + CPad::GetPad(0)->ResetAverageWeapon(); + + PointBlankNecessity pointBlankStatus; + if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER) + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT + && (pointBlankStatus = CheckForPointBlankPeds(victimPed)) != NO_POINT_BLANK_PED) { + ClearAimFlag(); + + // This condition is pointless + if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed) + StartFightAttack(200); + } else { + if (!curWeapon->m_bCanAim) + m_pSeekTarget = nil; + + if (m_nPedState != PED_AIM_GUN) + SetStoredState(); + + m_nPedState = PED_ATTACK; + SetMoveState(PEDMOVE_NONE); + if (bCrouchWhenShooting) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); + } else { + float animDelta = 8.0f; + if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE) + animDelta = 1000.0f; + + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT + || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta); + } else { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta); + } + } + + animAssoc->SetRun(); + if (animAssoc->currentTime == animAssoc->hierarchy->totalLength) + animAssoc->SetCurrentTime(0.0f); + + animAssoc->SetFinishCallback(FinishedAttackCB, this); + } + return; + } + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP) + SetWaitState(WAITSTATE_SURPRISE, nil); + + SetLookFlag(victim, false); + SetLookTimer(100); +} + +void +CPed::ClearAttack(void) +{ + if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK) + return; + +#ifdef VC_PED_PORTS + // VC uses CCamera::Using1stPersonWeaponMode + if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER || + TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) { + SetPointGunAt(nil); + } else +#endif + if (bIsPointingGunAt) { + if (m_pLookTarget) + SetPointGunAt(m_pLookTarget); + else + ClearPointGunAt(); + } else if (m_objective != OBJECTIVE_NONE) { + SetIdle(); + } else { + RestorePreviousState(); + } +} + +void +CPed::ClearAttackByRemovingAnim(void) +{ + if (m_nPedState != PED_ATTACK || bIsDucking) + return; + + CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay); + if (!weaponAssoc) { + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay); + + if (!weaponAssoc && weapon->m_bThrow) + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU); + + if (!weaponAssoc) { + ClearAttack(); + return; + } + } + weaponAssoc->blendDelta = -8.0f; + weaponAssoc->flags &= ~ASSOC_RUNNING; + weaponAssoc->flags |= ASSOC_DELETEFADEDOUT; + weaponAssoc->SetDeleteCallback(FinishedAttackCB, this); +} + +void +CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) +{ + CWeaponInfo *currentWeapon; + CAnimBlendAssociation *newAnim; + CPed *ped = (CPed*)arg; + + if (attackAssoc) { + switch (attackAssoc->animId) { + case ANIM_WEAPON_START_THROW: + // what?! + if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) { + attackAssoc->blendDelta = -1000.0f; + newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU); + } else { + attackAssoc->blendDelta = -1000.0f; + newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROW); + } + + newAnim->SetFinishCallback(FinishedAttackCB, ped); + return; + + case ANIM_FIGHT_PPUNCH: + attackAssoc->blendDelta = -8.0f; + attackAssoc->flags |= ASSOC_DELETEFADEDOUT; + ped->ClearAttack(); + return; + + case ANIM_WEAPON_THROW: + case ANIM_WEAPON_THROWU: + if (ped->GetWeapon()->m_nAmmoTotal > 0) { + currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType); + ped->AddWeaponModel(currentWeapon->m_nModelId); + } + break; + default: + break; + } + } + + if (!ped->bIsAttacking) + ped->ClearAttack(); +} + +PointBlankNecessity +CPed::CheckForPointBlankPeds(CPed *pedToVerify) +{ + float pbDistance = 1.1f; + if (GetWeapon()->IsType2Handed()) + pbDistance = 1.6f; + + for (int i = 0; i < m_numNearPeds; i++) { + CPed *nearPed = m_nearPeds[i]; + + if (!pedToVerify || pedToVerify == nearPed) { + + CVector diff = nearPed->GetPosition() - GetPosition(); + if (diff.Magnitude() < pbDistance) { + + float neededAngle = CGeneral::GetRadianAngleBetweenPoints( + nearPed->GetPosition().x, nearPed->GetPosition().y, + GetPosition().x, GetPosition().y); + neededAngle = CGeneral::LimitRadianAngle(neededAngle); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + + float neededTurn = Abs(neededAngle - m_fRotationCur); + + if (neededTurn > PI) + neededTurn = 2*PI - neededTurn; + + if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY) + return NO_POINT_BLANK_PED; + + if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) { + if (pedToVerify == nearPed) + return POINT_BLANK_FOR_WANTED_PED; + else + return POINT_BLANK_FOR_SOMEONE_ELSE; + } + } + } + } + return NO_POINT_BLANK_PED; +} + +void +CPed::Attack(void) +{ + CAnimBlendAssociation *weaponAnimAssoc; + int32 weaponAnim; + float animStart; + eWeaponType ourWeaponType; + float weaponAnimTime; + eWeaponFire ourWeaponFire; + float animLoopEnd; + CWeaponInfo *ourWeapon; + bool attackShouldContinue; + AnimationId reloadAnim; + CAnimBlendAssociation *reloadAnimAssoc; + float delayBetweenAnimAndFire; + CVector firePos; + + ourWeaponType = GetWeapon()->m_eWeaponType; + ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType); + ourWeaponFire = ourWeapon->m_eWeaponFire; + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay); + attackShouldContinue = bIsAttacking; + reloadAnimAssoc = nil; + reloadAnim = NUM_ANIMS; + delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire; + weaponAnim = ourWeapon->m_AnimToPlay; + + if (weaponAnim == ANIM_WEAPON_HGUN_BODY) + reloadAnim = ANIM_HGUN_RELOAD; + else if (weaponAnim == ANIM_WEAPON_AK_BODY) + reloadAnim = ANIM_AK_RELOAD; + + if (reloadAnim != NUM_ANIMS) + reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim); + + if (bIsDucking) + return; + + if (reloadAnimAssoc) { + if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) + ClearAttack(); + + return; + } + + if (CTimer::GetTimeInMilliseconds() < m_shootTimer) + attackShouldContinue = true; + + if (!weaponAnimAssoc) { + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay); + delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire; + + // Long throw granade, molotov + if (!weaponAnimAssoc && ourWeapon->m_bThrow) { + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU); + delayBetweenAnimAndFire = 0.2f; + } + + if (!weaponAnimAssoc) { + if (attackShouldContinue) { + if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) { + if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { + weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); + } + else { + weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); + } + + weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this); + weaponAnimAssoc->SetRun(); + + if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength) + weaponAnimAssoc->SetCurrentTime(0.0f); + + if (IsPlayer()) { + ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f; + ((CPlayerPed*)this)->m_bHaveTargetSelected = false; + } + } + } else + FinishedAttackCB(nil, this); + + return; + } + } + + animStart = ourWeapon->m_fAnimLoopStart; + weaponAnimTime = weaponAnimAssoc->currentTime; + if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) { + if (ourWeapon->m_bCanAimWithArm) + m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM; + else + m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; + } + + if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) { + if (weaponAnimAssoc->speed < 1.0f) + weaponAnimAssoc->speed = 1.0f; + + } else { + firePos = ourWeapon->m_vecFireOffset; + if (ourWeaponType == WEAPONTYPE_BASEBALLBAT) { + if (weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay) + firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f; + + firePos = GetMatrix() * firePos; + } else if (ourWeaponType != WEAPONTYPE_UNARMED) { + TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR); + } else { + firePos = GetMatrix() * firePos; + } + + GetWeapon()->Fire(this, &firePos); + + if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) { + RemoveWeaponModel(ourWeapon->m_nModelId); + } + if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) { + SelectGunIfArmed(); + } + + if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) { + // If reloading just began, start the animation + // Last condition will always return true, even IDA hides it + if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS /* && !reloadAnimAssoc*/) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f); + ClearLookFlag(); + ClearAimFlag(); + bIsAttacking = false; + bIsPointingGunAt = false; + m_shootTimer = CTimer::GetTimeInMilliseconds(); + return; + } + } else { + if (weaponAnimAssoc->animId == ANIM_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_WEAPON_BAT_H) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f); + } else if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); + } + + weaponAnimAssoc->speed = 0.5f; + + if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) { + weaponAnimAssoc->callbackType = 0; + } + } + + attackShouldContinue = false; + } + + if (ourWeaponType == WEAPONTYPE_SHOTGUN) { + weaponAnimTime = weaponAnimAssoc->currentTime; + firePos = ourWeapon->m_vecFireOffset; + + if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) { + TransformToNode(firePos, PED_HANDR); + + CVector gunshellPos( + firePos.x - 0.6f * GetForward().x, + firePos.y - 0.6f * GetForward().y, + firePos.z - 0.15f * GetUp().z + ); + + CVector2D gunshellRot( + GetRight().x, + GetRight().y + ); + + gunshellRot.Normalise(); + GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f); + } + } +#ifdef VC_PED_PORTS + if (IsPlayer()) { + if (CPad::GetPad(0)->GetSprint()) { + // animBreakout is a member of WeaponInfo in VC, so it's me that added the below line. + float animBreakOut = ((ourWeaponType == WEAPONTYPE_FLAMETHROWER || ourWeaponType == WEAPONTYPE_UZI || ourWeaponType == WEAPONTYPE_SHOTGUN) ? 25 / 30.0f : 99 / 30.0f); + if (!attackShouldContinue && weaponAnimAssoc->currentTime > animBreakOut) { + weaponAnimAssoc->blendDelta = -4.0f; + FinishedAttackCB(nil, this); + return; + } + } + } +#endif + animLoopEnd = ourWeapon->m_fAnimLoopEnd; + if (ourWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay) + animLoopEnd = 3.4f/6.0f; + + 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 - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd + && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) + && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) { + + weaponAnim = weaponAnimAssoc->animId; + if (ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { + if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_RBLOCK_CSHOOT) { + weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart); + } else { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); + } + } else { + if (weaponAnim == ourWeapon->m_Anim2ToPlay) + weaponAnimAssoc->SetCurrentTime(0.1f); + else + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); + } +#ifdef VC_PED_PORTS + } else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) { + weaponAnimAssoc->SetCurrentTime(ourWeapon->m_fAnimLoopEnd); + weaponAnimAssoc->flags &= ~ASSOC_RUNNING; + SetPointGunAt(m_pPointGunAt); +#endif + } else { + ClearAimFlag(); + + // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading) + if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) { + switch (ourWeaponType) { + case WEAPONTYPE_UZI: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_AK47: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_M16: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); + break; + default: + break; + } + } + + // Fun fact: removing this part leds to reloading flamethrower + if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) { + weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT; + weaponAnimAssoc->flags &= ~ASSOC_RUNNING; + weaponAnimAssoc->blendDelta = -4.0f; + } + } + } + if (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire) + attackShouldContinue = false; + + bIsAttacking = attackShouldContinue; +} + +void +CPed::StartFightAttack(uint8 buttonPressure) +{ + if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds()) + return; + + if (m_nPedState == PED_FIGHT) { + m_fightButtonPressure = buttonPressure; + return; + } + + if (m_nPedState != PED_AIM_GUN) + SetStoredState(); + + if (m_nWaitState != WAITSTATE_FALSE) { + m_nWaitState = WAITSTATE_FALSE; + RestoreHeadingRate(); + } + + m_nPedState = PED_FIGHT; + m_fightButtonPressure = 0; + RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); + + if (animAssoc) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->blendDelta = -1000.0f; + } + + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); + + if (animAssoc) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->blendDelta = -1000.0f; + RestoreHeadingRate(); + } + + SetMoveState(PEDMOVE_NONE); + m_nStoredMoveState = PEDMOVE_NONE; + + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f; + + CPed *pedOnGround = nil; + if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) { + m_curFightMove = FIGHTMOVE_GROUNDKICK; + } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) { + m_curFightMove = FIGHTMOVE_ROUNDHOUSE; + } else { + m_curFightMove = FIGHTMOVE_STDPUNCH; + } + + if (pedOnGround && IsPlayer()) { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + pedOnGround->GetPosition().x, pedOnGround->GetPosition().y, + GetPosition().x, GetPosition().y); + + m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); + m_fRotationCur = m_fRotationDest; + m_lookTimer = 0; + SetLookFlag(pedOnGround, true); + SetLookTimer(1500); + } + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); + animAssoc->SetFinishCallback(FinishFightMoveCB, this); + m_fightState = FIGHTSTATE_NO_MOVE; + m_takeAStepAfterAttack = false; + bIsAttacking = true; + + if (IsPlayer()) + nPlayerInComboMove = 0; +} + +void +CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) +{ + if (m_nPedState == PED_DEAD) { + if (CGame::nastyGame) { + if (hitLevel == HITLEVEL_GROUND) { + CAnimBlendAssociation *floorHitAssoc; + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) { + floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); + } else { + floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f); + } + if (floorHitAssoc) { + floorHitAssoc->SetCurrentTime(0.0f); + floorHitAssoc->SetRun(); + floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + } + } + if (CGame::nastyGame) { + CVector headPos = GetNodePosition(PED_HEAD); + for(int i = 0; i < 4; ++i) { + CVector bloodDir(0.0f, 0.0f, 0.1f); + CVector bloodPos = headPos - 0.2f * GetForward(); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0); + } + } + } + } else if (m_nPedState == PED_FALL) { + if (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) { + CAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL) ? + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f) : + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); + if (floorHitAssoc) { + floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + floorHitAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + } + } else if (IsPedInControl()) { + if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f) + || (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) { +#ifndef VC_PED_PORTS + if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) { + if (IsPlayer() || CGeneral::GetRandomNumber() & 3) { +#else + if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) { + if (IsPlayer() || CGeneral::GetRandomNumber() & 1) { +#endif + AnimationId shotAnim; + switch (direction) { + case 1: + shotAnim = ANIM_SHOT_LEFT_PARTIAL; + break; + case 2: + shotAnim = ANIM_SHOT_BACK_PARTIAL; + break; + case 3: + shotAnim = ANIM_SHOT_RIGHT_PARTIAL; + break; + default: + shotAnim = ANIM_SHOT_FRONT_PARTIAL; + break; + } + CAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim); + if (!shotAssoc || shotAssoc->blendDelta < 0.0f) + shotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f); + + shotAssoc->SetCurrentTime(0.0f); + shotAssoc->SetRun(); + shotAssoc->flags |= ASSOC_FADEOUTWHENDONE; + } else { + int time = CGeneral::GetRandomNumberInRange(1000, 3000); + SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time); + } + } else { +#ifndef VC_PED_PORTS + switch (direction) { + case 1: + SetFall(500, ANIM_KO_SPIN_R, false); + break; + case 2: + SetFall(500, ANIM_KO_SKID_BACK, false); + break; + case 3: + SetFall(500, ANIM_KO_SPIN_L, false); + break; + default: + SetFall(500, ANIM_KO_SHOT_STOM, false); + break; + } +#else + bool fall = true; + AnimationId hitAnim; + switch (direction) { + case 1: + hitAnim = ANIM_KO_SPIN_R; + break; + case 2: + if (CGeneral::GetRandomNumber() & 1) { + fall = false; + hitAnim = ANIM_HIT_BACK; + } else { + hitAnim = ANIM_KO_SKID_BACK; + } + break; + case 3: + hitAnim = ANIM_KO_SPIN_L; + break; + default: + if (hitLevel == HITLEVEL_LOW) { + hitAnim = ANIM_KO_SHOT_STOM; + } else if (CGeneral::GetRandomNumber() & 1) { + fall = false; + hitAnim = ANIM_HIT_WALK; + } else if (CGeneral::GetRandomNumber() & 1) { + fall = false; + hitAnim = ANIM_HIT_HEAD; + } else { + hitAnim = ANIM_KO_SHOT_FACE; + } + break; + } + if (fall) { + SetFall(500, hitAnim, false); + } else { + CAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim); + if (!hitAssoc || hitAssoc->blendDelta < 0.0f) + hitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f); + + hitAssoc->SetCurrentTime(0.0f); + hitAssoc->SetRun(); + hitAssoc->flags |= ASSOC_FADEOUTWHENDONE; + } +#endif + } + Say(SOUND_PED_DEFEND); + } else { + Say(SOUND_PED_DEFEND); + switch (hitLevel) { + case HITLEVEL_GROUND: + m_curFightMove = FIGHTMOVE_HITONFLOOR; + break; + case HITLEVEL_LOW: +#ifndef VC_PED_PORTS + if (direction == 2) { + SetFall(1000, ANIM_KO_SKID_BACK, false); + return; + } +#else + if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) { + SetFall(1000, ANIM_KO_SKID_BACK, false); + return; + } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) { + SetFall(1000, ANIM_KO_SHOT_STOM, false); + return; + } +#endif + m_curFightMove = FIGHTMOVE_HITBODY; + break; + case HITLEVEL_HIGH: + switch (direction) { + case 1: + m_curFightMove = FIGHTMOVE_HITLEFT; + break; + case 2: + m_curFightMove = FIGHTMOVE_HITBACK; + break; + case 3: + m_curFightMove = FIGHTMOVE_HITRIGHT; + break; + default: + if (unk <= 5) + m_curFightMove = FIGHTMOVE_HITHEAD; + else + m_curFightMove = FIGHTMOVE_HITBIGSTEP; + break; + } + break; + default: + switch (direction) { + case 1: + m_curFightMove = FIGHTMOVE_HITLEFT; + break; + case 2: + m_curFightMove = FIGHTMOVE_HITBACK; + break; + case 3: + m_curFightMove = FIGHTMOVE_HITRIGHT; + break; + default: + if (unk <= 5) + m_curFightMove = FIGHTMOVE_HITCHEST; + else + m_curFightMove = FIGHTMOVE_HITBIGSTEP; + break; + } + break; + } + if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f)) + m_curFightMove = FIGHTMOVE_HITONFLOOR; + + if (m_nPedState == PED_FIGHT) { + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); + moveAssoc->SetCurrentTime(0.0f); + moveAssoc->SetFinishCallback(FinishFightMoveCB, this); + if (IsPlayer()) + moveAssoc->speed = 1.3f; + + m_takeAStepAfterAttack = 0; + m_fightButtonPressure = 0; + } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) { + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); + moveAssoc->SetCurrentTime(0.0f); + moveAssoc->speed = 1.3f; + } else { + if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK) + SetStoredState(); + + if (m_nWaitState != WAITSTATE_FALSE) { + m_nWaitState = WAITSTATE_FALSE; + RestoreHeadingRate(); + } + m_nPedState = PED_FIGHT; + m_fightButtonPressure = 0; + RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); + CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); + if (walkStartAssoc) { + walkStartAssoc->flags |= ASSOC_DELETEFADEDOUT; + walkStartAssoc->blendDelta = -1000.0f; + } + CAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); + if (!walkStopAssoc) + walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); + if (walkStopAssoc) { + walkStopAssoc->flags |= ASSOC_DELETEFADEDOUT; + walkStopAssoc->blendDelta = -1000.0f; + RestoreHeadingRate(); + } + SetMoveState(PEDMOVE_NONE); + m_nStoredMoveState = PEDMOVE_NONE; + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f; + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); + moveAssoc->SetFinishCallback(FinishFightMoveCB, this); + m_fightState = FIGHTSTATE_NO_MOVE; + m_takeAStepAfterAttack = false; + bIsAttacking = true; + } + } + } +} + +void +CPed::Fight(void) +{ + CAnimBlendAssociation *currentAssoc, *animAssoc; + bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse; + float angleToFace, nextAngle; + bool goForward = false; + int nextFightMove; + + switch (m_curFightMove) { + case FIGHTMOVE_NULL: + return; + case FIGHTMOVE_IDLE2NORM: + m_curFightMove = FIGHTMOVE_NULL; + RestorePreviousState(); + + // FIX: Uninitialized + currentAssoc = nil; + break; + case FIGHTMOVE_IDLE: + currentAssoc = nil; + break; + default: + currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); + break; + } + + if (!bIsAttacking && IsPlayer()) { + if (currentAssoc) { + currentAssoc->blendDelta = -1000.0f; + currentAssoc->flags |= ASSOC_DELETEFADEDOUT; + currentAssoc->flags &= ~ASSOC_RUNNING; + } + if (m_takeAStepAfterAttack) + EndFight(ENDFIGHT_WITH_A_STEP); + else + EndFight(ENDFIGHT_FAST); + + } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) { + float animTime = currentAssoc->currentTime; + FightMove &curMove = tFightMoves[m_curFightMove]; + if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) { + + CVector touchingNodePos(0.0f, 0.0f, 0.0f); + + switch (m_curFightMove) { + case FIGHTMOVE_STDPUNCH: + case FIGHTMOVE_PUNCHHOOK: + case FIGHTMOVE_BODYBLOW: + TransformToNode(touchingNodePos, PED_HANDR); + break; + case FIGHTMOVE_IDLE: + case FIGHTMOVE_SHUFFLE_F: + break; + case FIGHTMOVE_KNEE: + TransformToNode(touchingNodePos, PED_LOWERLEGR); + break; + case FIGHTMOVE_HEADBUTT: + TransformToNode(touchingNodePos, PED_HEAD); + break; + case FIGHTMOVE_PUNCHJAB: + TransformToNode(touchingNodePos, PED_HANDL); + break; + case FIGHTMOVE_KICK: + case FIGHTMOVE_LONGKICK: + case FIGHTMOVE_ROUNDHOUSE: + case FIGHTMOVE_GROUNDKICK: + TransformToNode(touchingNodePos, PED_FOOTR); + break; + } + + if (m_curFightMove == FIGHTMOVE_PUNCHJAB) { + touchingNodePos += 0.1f * GetForward(); + } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) { + touchingNodePos += 0.22f * GetForward(); + } + FightStrike(touchingNodePos); + m_fightButtonPressure = 0; + return; + } + + if (curMove.hitLevel != HITLEVEL_NULL) { + if (animTime > curMove.endFireTime) { + if (IsPlayer()) + currentAssoc->speed = 1.0f; + else + currentAssoc->speed = 0.8f; + } + + if (IsPlayer() && !nPlayerInComboMove) { + if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) { + + // Notice that it increases fight move index, because we're in combo! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f); + animAssoc->SetFinishCallback(FinishFightMoveCB, this); + animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength); + m_fightButtonPressure = 0; + nPlayerInComboMove = 1; + } + } + } else { + if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) { + if (IsPlayer()) + currentAssoc->speed = 1.3f; + else + currentAssoc->speed = 0.8f; + } + } + } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { + EndFight(ENDFIGHT_FAST); + + } else if (m_fightButtonPressure != 0) { + bool canAffectMultiplePeople = true; + nextAngle = m_fRotationCur; + bool kickGround = false; + float angleForGroundKick = 0.0f; + CPed *pedOnGround = nil; + + Say(SOUND_PED_ATTACK); + + if (IsPlayer()) { + canRoundhouse = false; + punchOnly = false; + canKick = true; + nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE); + hasShoppingBags = false; + canKneeHead = true; + nPlayerInComboMove = 0; + } else { + nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE); + uint16 pedFeatures = m_pedStats->m_flags; + punchOnly = pedFeatures & STAT_PUNCH_ONLY; + canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE; + canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD; + canKick = pedFeatures & STAT_CAN_KICK; + hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS; + } + + // Attack isn't scripted, find the victim + if (IsPlayer() || !m_pedInObjective) { + + for (int i = 0; i < m_numNearPeds; i++) { + + CPed *nearPed = m_nearPeds[i]; + float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude(); + if (nearPedDist < 3.0f) { + float angleToFace = CGeneral::GetRadianAngleBetweenPoints( + nearPed->GetPosition().x, nearPed->GetPosition().y, + GetPosition().x, GetPosition().y); + + nextAngle = CGeneral::LimitRadianAngle(angleToFace); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + + float neededTurn = Abs(nextAngle - m_fRotationCur); + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; + + if (!nearPed->OnGroundOrGettingUp()) { + + if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) { + canAffectMultiplePeople = false; + } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) { + + if (nearPedDist < 1.7f + && neededTurn < DEGTORAD(35.0f) + && (canKick || hasShoppingBags)) { + + nextFightMove = FIGHTMOVE_KICK; + if (hasShoppingBags) { + nextFightMove = FIGHTMOVE_ROUNDHOUSE; + } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) { + nextFightMove = FIGHTMOVE_ROUNDHOUSE; + } + canAffectMultiplePeople = false; + } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) { + canAffectMultiplePeople = false; + nextFightMove = FIGHTMOVE_LONGKICK; + } else if (neededTurn < DEGTORAD(30.0f)) { + goForward = true; + } + } else { + nextFightMove += 2; // Makes it 6 or 7 + if (punchOnly) + nextFightMove = FIGHTMOVE_PUNCHJAB; + + canAffectMultiplePeople = false; + } + } else if (!CGame::nastyGame + || nearPedDist >= 1.3f + || neededTurn >= DEGTORAD(55.0f) + || punchOnly) { + + if (nearPedDist > 0.8f + && nearPedDist < 3.0f + && neededTurn < DEGTORAD(30.0f)) { + goForward = true; + } + + } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) { + if (!nearPed->IsPedHeadAbovePos(-0.3f)) { + canAffectMultiplePeople = false; + nextFightMove = FIGHTMOVE_GROUNDKICK; + } + + } else { + pedOnGround = nearPed; + kickGround = true; + angleForGroundKick = nextAngle; + } + } + + if (!canAffectMultiplePeople) { + m_fRotationDest = nextAngle; + if (IsPlayer()) { + m_fRotationCur = m_fRotationDest; + m_lookTimer = 0; + SetLookFlag(nearPed, true); + SetLookTimer(1500); + } + break; + } + } + } else { + // Because we're in a scripted fight with some particular ped. + canAffectMultiplePeople = false; + + float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude(); + if (hasShoppingBags) { + if (fightingPedDist >= 1.7f) + nextFightMove = FIGHTMOVE_SHUFFLE_F; + else + nextFightMove = FIGHTMOVE_ROUNDHOUSE; + + } else if (punchOnly) { + if (fightingPedDist >= 1.3f) + nextFightMove = FIGHTMOVE_SHUFFLE_F; + else + nextFightMove = FIGHTMOVE_PUNCHJAB; + + } else if (fightingPedDist >= 3.0f) { + nextFightMove = FIGHTMOVE_STDPUNCH; + + } else { + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + m_pedInObjective->GetPosition().x, + m_pedInObjective->GetPosition().y, + GetPosition().x, + GetPosition().y); + + nextAngle = CGeneral::LimitRadianAngle(angleToFace); + m_fRotationDest = nextAngle; + m_fRotationCur = m_fRotationDest; + if (!m_pedInObjective->OnGroundOrGettingUp()) { + + if (fightingPedDist >= 0.8f || !canKneeHead) { + + if (fightingPedDist >= 1.3f) { + + if (fightingPedDist < 1.7f && canKick) { + nextFightMove = FIGHTMOVE_KICK; + if (canRoundhouse && CGeneral::GetRandomNumber() & 1) + nextFightMove = FIGHTMOVE_ROUNDHOUSE; + + } else if (fightingPedDist < 2.0f && canKick) { + nextFightMove += 5; // Makes it 9 or 10 + + } else { + nextFightMove = FIGHTMOVE_SHUFFLE_F; + + } + } else { + nextFightMove += 2; // Makes it 6 or 7 + } + } + } else if (!CGame::nastyGame + || fightingPedDist >= 1.3f + || m_pedInObjective->IsPlayer() + || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) { + nextFightMove = FIGHTMOVE_IDLE; + } else { + nextFightMove = FIGHTMOVE_GROUNDKICK; + } + } + } + + if (canAffectMultiplePeople) { + if (kickGround && IsPlayer()) { + m_fRotationDest = angleForGroundKick; + nextFightMove = FIGHTMOVE_GROUNDKICK; + m_fRotationCur = m_fRotationDest; + m_lookTimer = 0; + SetLookFlag(pedOnGround, true); + SetLookTimer(1500); + } else if (goForward) { + nextFightMove = FIGHTMOVE_SHUFFLE_F; + } else { + nextFightMove = FIGHTMOVE_STDPUNCH; + } + } + + if (nextFightMove != FIGHTMOVE_IDLE) { + m_curFightMove = nextFightMove; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); + + animAssoc->SetFinishCallback(FinishFightMoveCB, this); + if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) { + animAssoc->SetCurrentTime(0.0f); + animAssoc->SetRun(); + } + m_fightButtonPressure = 0; + } + m_fightState = FIGHTSTATE_NO_MOVE; + } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F +#ifndef FIX_BUGS + && CheckForPedsOnGroundToAttack(this, nil) == 4) { +#else + && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) { +#endif + m_curFightMove = FIGHTMOVE_SHUFFLE_F; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); + + if (animAssoc) { + animAssoc->SetCurrentTime(0.0f); + animAssoc->blendDelta = 4.0f; + animAssoc->SetRun(); + } else { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f); + } + animAssoc->SetFinishCallback(FinishFightMoveCB, this); + m_fightState = FIGHTSTATE_NO_MOVE; + m_fightButtonPressure = 0; + m_takeAStepAfterAttack = false; + + } else if (m_takeAStepAfterAttack) { + EndFight(ENDFIGHT_FAST); + + } else if (m_curFightMove == FIGHTMOVE_IDLE) { + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + EndFight(ENDFIGHT_NORMAL); + } + + } else { + m_curFightMove = FIGHTMOVE_IDLE; + if (IsPlayer()) + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500; + else + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000; + } +} + +void +CPed::EndFight(uint8 endType) +{ + if (m_nPedState != PED_FIGHT) + return; + + m_curFightMove = FIGHTMOVE_NULL; + RestorePreviousState(); + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); + if (animAssoc) + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + + switch (endType) { + case ENDFIGHT_NORMAL: + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f); + break; + case ENDFIGHT_WITH_A_STEP: + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 1.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WALK_START, 8.0f); + break; + case ENDFIGHT_FAST: + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f)->speed = 2.0f; + break; + default: + break; + } + m_nWaitTimer = 0; +} + + +void +CPed::PlayHitSound(CPed *hitTo) +{ + // That was very complicated to reverse for me... + // First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10). + enum { + S33 = SOUND_FIGHT_PUNCH_33, + S34 = SOUND_FIGHT_KICK_34, + S35 = SOUND_FIGHT_HEADBUTT_35, + S36 = SOUND_FIGHT_PUNCH_36, + S37 = SOUND_FIGHT_PUNCH_37, + S38 = SOUND_FIGHT_CLOSE_PUNCH_38, + S39 = SOUND_FIGHT_PUNCH_39, + S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 , + S41 = SOUND_FIGHT_PUNCH_41, + S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42, + S43 = SOUND_FIGHT_KNEE_OR_KICK_43, + S44 = SOUND_FIGHT_KICK_44, + NO_SND = SOUND_NO_SOUND + }; + uint16 hitSoundsByFightMoves[12][10] = { + {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42}, + {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND}, + {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND}, + {S39,S39,S39,S39,S33,S43,S39,S39,S39,S39}, + {S39,S39,S39,S39,S35,S39,S38,S38,S39,S39}, + {S39,S39,S39,S39,S33,S39,S41,S36,S39,S39}, + {S39,S39,S39,S39,S37,S40,S38,S38,S39,S39}, + {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39}, + {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39}, + {S39,S39,S39,S39,S34,S43,S44,S37,S39,S40}, + {S39,S39,S39,S39,S33,S39,S41,S37,S39,S40}, + {S39,S39,S39,S39,S39,S39,S39,S39,S33,S33} + }; + + // This is why first dimension is between FightMove 1 and 12. + if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT) + return; + + uint16 soundId; + + // And this is why second dimension is between 13 and 22. + if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) { + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT]; + + } else { + if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) { + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT]; + } else { + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT]; + } + } + + if (soundId != NO_SND) + DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f); +} + +bool +CPed::FightStrike(CVector &touchedNodePos) +{ + CColModel *ourCol; + CVector attackDistance; + ePedPieceTypes closestPedPiece = PEDPIECE_TORSO; + float maxDistanceToBeBeaten; + CPed *nearPed; + int state = m_fightState; + bool pedFound = false; + + if (state == FIGHTSTATE_JUST_ATTACKED) + return false; + + // Pointless code + if (state > FIGHTSTATE_NO_MOVE) + attackDistance = touchedNodePos - m_vecHitLastPos; + + for (int i = 0; i < m_numNearPeds; i++) { + nearPed = m_nearPeds[i]; + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) + maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f; + else + maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius; + + if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) { + CVector nearPedCentre; + nearPed->GetBoundCentre(nearPedCentre); + CVector potentialAttackDistance = nearPedCentre - touchedNodePos; + + // He can beat us + if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) { + +#ifdef PED_SKIN + // Have to animate a skinned clump because the initial col model is useless + if(IsClumpSkinned(GetClump())) + ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump()); + else +#endif + if (nearPed->OnGround() || !nearPed->IsPedHeadAbovePos(-0.3f)) { + ourCol = &CTempColModels::ms_colModelPedGroundHit; + } else { +#ifdef ANIMATE_PED_COL_MODEL + ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->GetHitColModel(), + RpClumpGetFrame(GetClump())); +#else + ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel(); +#endif + } + + for (int j = 0; j < ourCol->numSpheres; j++) { + attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center; + attackDistance -= touchedNodePos; + CColSphere *ourPieces = ourCol->spheres; + float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius; + + // We can beat him too + if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) { + pedFound = true; + closestPedPiece = (ePedPieceTypes) ourPieces[j].piece; + break; + } + } + } + } + if (pedFound) + break; + } + + if (pedFound) { + if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP) + return false; + + float oldVictimHealth = nearPed->m_fHealth; + CVector bloodPos = 0.5f * attackDistance + touchedNodePos; + int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1; + + CVector2D diff (GetPosition() - nearPed->GetPosition()); + int direction = nearPed->GetLocalDirection(diff); + if (IsPlayer()) { + if (((CPlayerPed*)this)->m_bAdrenalineActive) + damageMult = 20; + } else { + damageMult *= m_pedStats->m_attackStrength; + } + + // Change direction if we used kick. + if (m_curFightMove == FIGHTMOVE_KICK) { + if (CGeneral::GetRandomNumber() & 1) { + direction++; + if (direction > 3) + direction -= 4; + } + } + nearPed->ReactToAttack(this); + + // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it. + int unk2; + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer()) + unk2 = 101; + else + unk2 = damageMult; + + nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2); + PlayHitSound(nearPed); + m_fightState = FIGHTSTATE_JUST_ATTACKED; + RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f; + if (!nearPed->DyingOrDead()) { + nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction); + } + + if (CGame::nastyGame + && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM + && nearPed->m_nPedState == PED_DIE + && nearPed->GetIsOnScreen()) { + + // Just for blood particle. We will restore it below. + attackDistance /= (10.0f * attackDistance.Magnitude()); + for(int i=0; i<4; i++) { + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0); + } + } + if (!nearPed->OnGround()) { + float curVictimHealth = nearPed->m_fHealth; + if (curVictimHealth > 0.0f + && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer() + || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f + || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer() + || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) { + + nearPed->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0); + if (nearPed->m_nPedState == PED_FALL) + nearPed->bIsStanding = false; + } + } + if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) { + attackDistance = nearPed->GetPosition() - GetPosition(); + attackDistance.Normalise(); + attackDistance.z = 1.0f; + nearPed->bIsStanding = false; + + float moveMult; + if (m_curFightMove == FIGHTMOVE_GROUNDKICK) { + moveMult = Min(damageMult * 0.6f, 4.0f); + } else { + if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) { + moveMult = damageMult; + } else { + moveMult = Min(damageMult * 2.0f, 14.0f); + } + } + + nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance); + } + CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000); + } + + if (m_fightState == FIGHTSTATE_NO_MOVE) + m_fightState = FIGHTSTATE_1; + + m_vecHitLastPos = *touchedNodePos; + return false; +} + +void +CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg) +{ + CPed *ped = (CPed*)arg; + + if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) { + ped->m_fightState = FIGHTSTATE_MOVE_FINISHED; + animAssoc->blendDelta = -1000.0f; + } +} + +void +CPed::LoadFightData(void) +{ + float startFireTime, endFireTime, comboFollowOnTime, strikeRadius; + int damage, flags; + char line[256], moveName[32], animName[32], hitLevel; + int moveId = 0; + + CAnimBlendAssociation *animAssoc; + + size_t bp, buflen; + int lp, linelen; + + buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r"); + + for (bp = 0; bp < buflen; ) { + // read file line by line + for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) { + line[linelen++] = work_buff[bp]; + } + bp++; + line[linelen] = '\0'; + + // skip white space + for (lp = 0; line[lp] <= ' ' && line[lp] != '\0'; lp++); + + if (line[lp] == '\0' || + line[lp] == '#') + continue; + + sscanf( + &line[lp], + "%s %f %f %f %f %c %s %d %d", + moveName, + &startFireTime, + &endFireTime, + &comboFollowOnTime, + &strikeRadius, + &hitLevel, + animName, + &damage, + &flags); + + if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0) + return; + + tFightMoves[moveId].startFireTime = startFireTime / 30.0f; + tFightMoves[moveId].endFireTime = endFireTime / 30.0f; + tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f; + tFightMoves[moveId].strikeRadius = strikeRadius; + tFightMoves[moveId].damage = damage; + tFightMoves[moveId].flags = flags; + + switch (hitLevel) { + case 'G': + tFightMoves[moveId].hitLevel = HITLEVEL_GROUND; + break; + case 'H': + tFightMoves[moveId].hitLevel = HITLEVEL_HIGH; + break; + case 'L': + tFightMoves[moveId].hitLevel = HITLEVEL_LOW; + break; + case 'M': + tFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM; + break; + case 'N': + tFightMoves[moveId].hitLevel = HITLEVEL_NULL; + break; + default: + break; + } + + if (strncmp(animName, "null", 4) != 0) { + animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName); + tFightMoves[moveId].animId = (AnimationId)animAssoc->animId; + } else { + tFightMoves[moveId].animId = ANIM_WALK; + } + moveId++; + } +} + +void +CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle) +{ + if (!IsPedInControl() || CharCreatedBy == MISSION_CHAR) + return; + + SetStoredState(); + bFindNewNodeAfterStateRestore = false; + m_nPedState = PED_INVESTIGATE; + m_standardTimer = CTimer::GetTimeInMilliseconds() + time; + m_eventType = event; + m_eventOrThreat = pos; + m_distanceToCountSeekDone = distanceToCountDone; + m_fAngleToEvent = angle; + + if (m_eventType >= EVENT_ICECREAM) + m_lookTimer = 0; + else + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 4.0f); + +} + +void +CPed::InvestigateEvent(void) +{ + CAnimBlendAssociation *animAssoc; + AnimationId animToPlay; + AssocGroupId animGroup; + + if (m_nWaitState == WAITSTATE_TURN180) + return; + + if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { + + if (m_standardTimer) { + if (m_eventType < EVENT_ASSAULT_NASTYWEAPON) + SetWaitState(WAITSTATE_TURN180, nil); + + m_standardTimer = 0; + } else { + ClearInvestigateEvent(); + } + return; + } + + CVector2D vecDist = m_eventOrThreat - GetPosition(); + float distSqr = vecDist.MagnitudeSqr(); + if (sq(m_distanceToCountSeekDone) >= distSqr) { + + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f); + SetMoveState(PEDMOVE_STILL); + + switch (m_eventType) { + case EVENT_DEAD_PED: + case EVENT_HIT_AND_RUN: + case EVENT_HIT_AND_RUN_COP: + + if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); + + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + if (m_pEventEntity) + SetLookFlag(m_pEventEntity, true); + + SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000)); + + } else if (CGeneral::GetRandomNumber() & 3) { + ClearLookFlag(); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f); + + SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); + Say(SOUND_PED_CHAT_EVENT); + + } else { + ClearInvestigateEvent(); + } + } + break; + case EVENT_FIRE: + case EVENT_EXPLOSION: + + if (bHasACamera && CTimer::GetTimeInMilliseconds() > m_lookTimer) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CAM); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); + + if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) { + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); + SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); + + } else if (CGeneral::GetRandomNumber() & 3) { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CAM, 4.0f); + SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000)); + Say(SOUND_PED_CHAT_EVENT); + + } else { + m_standardTimer = 0; + } + + } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); + + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); + + if (animAssoc && animAssoc->animId == ANIM_IDLE_STANCE) { + if (CGeneral::GetRandomNumber() & 1) + animToPlay = ANIM_IDLE_HBHB; + else + animToPlay = ANIM_XPRESS_SCRATCH; + + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); + SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000)); + + } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + if (CGeneral::GetRandomNumber() & 1) { + animToPlay = ANIM_IDLE_STANCE; + animGroup = m_animGroup; + } else { + animToPlay = ANIM_XPRESS_SCRATCH; + animGroup = ASSOCGRP_STD; + } + + CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f); + SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); + + } else { + if (CGeneral::GetRandomNumber() & 1) { + animToPlay = ANIM_IDLE_STANCE; + animGroup = m_animGroup; + } else { + animToPlay = ANIM_IDLE_HBHB; + animGroup = ASSOCGRP_STD; + } + + CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f); + SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); + } + Say(SOUND_PED_CHAT_EVENT); + } + break; + case EVENT_ICECREAM: + case EVENT_SHOPSTALL: + + m_fRotationDest = m_fAngleToEvent; + if (CTimer::GetTimeInMilliseconds() > m_lookTimer) { + + if (m_lookTimer) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); + + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + if (m_eventType == EVENT_ICECREAM) + animToPlay = ANIM_IDLE_CHAT; + else + animToPlay = ANIM_XPRESS_SCRATCH; + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f); + SetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); + + } else { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + ClearInvestigateEvent(); + } else { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + ClearInvestigateEvent(); + } + } + } else { + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f); + SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); + } + } + break; + default: + return; + } + } else { + m_vecSeekPos.x = m_eventOrThreat.x; + m_vecSeekPos.y = m_eventOrThreat.y; + m_vecSeekPos.z = GetPosition().z; + Seek(); + + if (m_eventType < EVENT_ICECREAM) { + if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) { + SetMoveState(PEDMOVE_RUN); + return; + } + } + if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) { + SetMoveState(PEDMOVE_WALK); + return; + } + if (distSqr > sq(1.2f)) { + SetMoveState(PEDMOVE_WALK); + return; + } + + for (int i = 0; i < m_numNearPeds; i++) { + if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) { + SetMoveState(PEDMOVE_STILL); + return; + } + } + + SetMoveState(PEDMOVE_WALK); + } +} + +void +CPed::ClearInvestigateEvent(void) +{ + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + if (m_eventType > EVENT_EXPLOSION) + m_standardTimer = CTimer::GetTimeInMilliseconds() + 15000; + + bGonnaInvestigateEvent = false; + m_pEventEntity = nil; + ClearLookFlag(); + RestorePreviousState(); + if(m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) + SetMoveState(PEDMOVE_WALK); +} + +bool +CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction) +{ + CPlayerPed *player = FindPlayerPed(); + float dieDelta = 4.0f; + float dieSpeed = 0.0f; + AnimationId dieAnim = ANIM_KO_SHOT_FRONT1; + bool headShot = false; + bool willLinger = false; + int random; + + if (player == this) { + if (!player->m_bCanBeDamaged) + return false; + + player->AnnoyPlayerPed(false); + } + + if (DyingOrDead()) + return false; + + if (!bUsesCollision && method != WEAPONTYPE_DROWNING) + return false; + + if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() && + method != WEAPONTYPE_DROWNING && method != WEAPONTYPE_EXPLOSION) + return false; + + float healthImpact; + if (IsPlayer()) + healthImpact = damage * 0.33f; + else + healthImpact = damage * m_pedStats->m_defendWeakness; + + bool detectDieAnim = true; + if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) { + if (!IsPedHeadAbovePos(-0.3f)) { + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) + dieAnim = ANIM_FLOOR_HIT_F; + else + dieAnim = ANIM_FLOOR_HIT; + dieDelta *= 2.0f; + dieSpeed = 0.5f; + detectDieAnim = false; + } else if (m_nPedState == PED_FALL) { + dieAnim = NUM_ANIMS; + detectDieAnim = false; + } + } + if (detectDieAnim) { + switch (method) { + case WEAPONTYPE_UNARMED: + if (bMeleeProof) + return false; + + if (m_nPedState == PED_FALL) { + if (IsPedHeadAbovePos(-0.3f)) { + dieAnim = NUM_ANIMS; + } else { + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) + dieAnim = ANIM_FLOOR_HIT_F; + else + dieAnim = ANIM_FLOOR_HIT; + dieDelta = dieDelta * 2.0f; + dieSpeed = 0.5f; + } + } else { + switch (direction) { + case 0: + dieAnim = ANIM_KO_SKID_FRONT; + break; + case 1: + dieAnim = ANIM_KO_SPIN_R; + break; + case 2: + dieAnim = ANIM_KO_SKID_BACK; + break; + case 3: + dieAnim = ANIM_KO_SPIN_L; + break; + default: + break; + } + } + break; + case WEAPONTYPE_BASEBALLBAT: + if (bMeleeProof) + return false; + + if (m_nPedState == PED_FALL) { + if (IsPedHeadAbovePos(-0.3f)) { + dieAnim = NUM_ANIMS; + } else { + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) + dieAnim = ANIM_FLOOR_HIT_F; + else + dieAnim = ANIM_FLOOR_HIT; + dieDelta = dieDelta * 2.0f; + dieSpeed = 0.5f; + } + } else { + switch (direction) { + case 0: + dieAnim = ANIM_KO_SKID_FRONT; + break; + case 1: + dieAnim = ANIM_KO_SPIN_R; + break; + case 2: + dieAnim = ANIM_KO_SKID_BACK; + break; + case 3: + dieAnim = ANIM_KO_SPIN_L; + break; + default: + break; + } + } + break; + case WEAPONTYPE_COLT45: + case WEAPONTYPE_UZI: + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_AK47: + case WEAPONTYPE_M16: + case WEAPONTYPE_SNIPERRIFLE: + if (bBulletProof) + return false; + + bool dontRemoveLimb; + if (IsPlayer() || bNoCriticalHits) + dontRemoveLimb = true; + else { + switch (method) { + case WEAPONTYPE_SNIPERRIFLE: + dontRemoveLimb = false; + break; + case WEAPONTYPE_M16: + dontRemoveLimb = false; + break; + case WEAPONTYPE_SHOTGUN: + dontRemoveLimb = CGeneral::GetRandomNumber() & 7; + break; + default: + dontRemoveLimb = CGeneral::GetRandomNumber() & 15; + break; + } + } + + if (dontRemoveLimb) { + if (method == WEAPONTYPE_SHOTGUN) { + switch (direction) { + case 0: + dieAnim = ANIM_KO_SKID_FRONT; + break; + case 1: + dieAnim = ANIM_KO_SPIN_R; + break; + case 2: + dieAnim = ANIM_KO_SKID_BACK; + break; + case 3: + dieAnim = ANIM_KO_SPIN_L; + break; + default: + break; + } + } else + dieAnim = ANIM_KO_SHOT_FRONT1; + + willLinger = false; + } else { + switch (pedPiece) { + case PEDPIECE_TORSO: + willLinger = false; + dieAnim = ANIM_KO_SHOT_FRONT1; + break; + case PEDPIECE_MID: + willLinger = false; + dieAnim = ANIM_KO_SHOT_STOM; + break; + case PEDPIECE_LEFTARM: + dieAnim = ANIM_KO_SHOT_ARML; + RemoveBodyPart(PED_UPPERARML, direction); + willLinger = true; + break; + case PEDPIECE_RIGHTARM: + dieAnim = ANIM_KO_SHOT_ARMR; + RemoveBodyPart(PED_UPPERARMR, direction); + willLinger = true; + break; + case PEDPIECE_LEFTLEG: + dieAnim = ANIM_KO_SHOT_LEGL; + RemoveBodyPart(PED_UPPERLEGL, direction); + willLinger = true; + break; + case PEDPIECE_RIGHTLEG: + dieAnim = ANIM_KO_SHOT_LEGR; + RemoveBodyPart(PED_UPPERLEGR, direction); + willLinger = true; + break; + case PEDPIECE_HEAD: + dieAnim = ANIM_KO_SHOT_FACE; + RemoveBodyPart(PED_HEAD, direction); + headShot = true; + willLinger = true; + break; + default: + break; + } + } + break; + case WEAPONTYPE_ROCKETLAUNCHER: + case WEAPONTYPE_GRENADE: + case WEAPONTYPE_EXPLOSION: + if (bExplosionProof) + return false; + + if (CGame::nastyGame && !IsPlayer() && !bInVehicle && + 1.0f + healthImpact > m_fArmour + m_fHealth) { + + random = CGeneral::GetRandomNumber(); + if (random & 1) + RemoveBodyPart(PED_UPPERARML, direction); + if (random & 2) + RemoveBodyPart(PED_UPPERLEGR, direction); + if (random & 4) + RemoveBodyPart(PED_HEAD, direction); + if (random & 8) + RemoveBodyPart(PED_UPPERARMR, direction); + if (random & 0x10) + RemoveBodyPart(PED_UPPERLEGL, direction); + if (bBodyPartJustCameOff) + willLinger = true; + } + // fall through + case WEAPONTYPE_MOLOTOV: + if (bExplosionProof) + return false; + + switch (direction) { + case 0: + dieAnim = ANIM_KO_SKID_FRONT; + break; + case 1: + dieAnim = ANIM_KO_SPIN_R; + break; + case 2: + dieAnim = ANIM_KO_SKID_BACK; + break; + case 3: + dieAnim = ANIM_KO_SPIN_L; + break; + default: + break; + } + break; + case WEAPONTYPE_FLAMETHROWER: + if (bFireProof) + return false; + + dieAnim = ANIM_KO_SHOT_FRONT1; + break; + case WEAPONTYPE_RAMMEDBYCAR: + case WEAPONTYPE_RUNOVERBYCAR: + if (bCollisionProof) + return false; + + random = CGeneral::GetRandomNumber() & 3; + switch (random) { + case 0: + if ((pedPiece != PEDPIECE_LEFTARM || random <= 1) + && (pedPiece != PEDPIECE_MID || random != 1)) { + if (pedPiece == PEDPIECE_RIGHTARM && random > 1 + || pedPiece == PEDPIECE_MID && random == 2) + + dieAnim = ANIM_KO_SPIN_L; + else + dieAnim = ANIM_KO_SKID_FRONT; + } else + dieAnim = ANIM_KO_SPIN_R; + + break; + case 1: + if (m_nPedState == PED_DIVE_AWAY) + dieAnim = ANIM_KD_LEFT; + else + dieAnim = ANIM_KO_SPIN_R; + break; + case 2: + if ((pedPiece != PEDPIECE_LEFTARM || random <= 1) + && (pedPiece != PEDPIECE_MID || random != 1)) { + if ((pedPiece != PEDPIECE_RIGHTARM || random <= 1) + && (pedPiece != PEDPIECE_MID || random != 2)) { + dieAnim = ANIM_KO_SKID_BACK; + } else { + dieAnim = ANIM_KD_RIGHT; + } + } else + dieAnim = ANIM_KD_LEFT; + break; + case 3: + if (m_nPedState == PED_DIVE_AWAY) + dieAnim = ANIM_KD_RIGHT; + else + dieAnim = ANIM_KO_SPIN_L; + break; + default: + break; + } + if (damagedBy) { + CVehicle *vehicle = (CVehicle*)damagedBy; + if (method == WEAPONTYPE_RAMMEDBYCAR) { + float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude(); + dieDelta = 8.0f * vehSpeed + 4.0f; + } else { + float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude(); + dieDelta = 12.0f * vehSpeed + 4.0f; + dieSpeed = 16.0f * vehSpeed + 1.0f; + } + } + break; + case WEAPONTYPE_DROWNING: + dieAnim = ANIM_DROWN; + break; + case WEAPONTYPE_FALL: + if (bCollisionProof) + return false; + + switch (direction) { + case 0: + dieAnim = ANIM_KO_SKID_FRONT; + break; + case 1: + dieAnim = ANIM_KO_SPIN_R; + break; + case 2: + dieAnim = ANIM_KO_SKID_BACK; + break; + case 3: + dieAnim = ANIM_KO_SPIN_L; + break; + default: + break; + } + break; + default: + break; + } + } + + if (m_fArmour != 0.0f && method != WEAPONTYPE_DROWNING) { + if (player == this) + CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss = CTimer::GetTimeInMilliseconds(); + + if (healthImpact < m_fArmour) { + m_fArmour = m_fArmour - healthImpact; + healthImpact = 0.0f; + } else { + healthImpact = healthImpact - m_fArmour; + m_fArmour = 0.0f; + } + } + + if (healthImpact != 0.0f) { + if (player == this) + CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds(); + + m_lastWepDam = method; + } + + if (m_fHealth - healthImpact >= 1.0f && !willLinger) { + m_fHealth -= healthImpact; + return false; + } + + if (bInVehicle) { + if (method != WEAPONTYPE_DROWNING) { +#ifdef VC_PED_PORTS + if (m_pMyVehicle) { + if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) { + if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) { + m_pMyVehicle->SetStatus(STATUS_PHYSICS); + CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle); + } + m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT; + m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; + } + if (m_pMyVehicle->CanPedExitCar()) { + SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle); + } else { + m_fHealth = 0.0f; + if (m_pMyVehicle && m_pMyVehicle->pDriver == this) { + SetRadioStation(); + m_pMyVehicle->SetStatus(STATUS_ABANDONED); + } + SetDie(dieAnim, dieDelta, dieSpeed); + /* + if (damagedBy == FindPlayerPed() && damagedBy != this) { + // PlayerInfo stuff + } + */ + } + for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) { + CPed* passenger = m_pMyVehicle->pPassengers[i]; + if (passenger && passenger != this && damagedBy) + passenger->ReactToAttack(damagedBy); + } + + CPed *driverOfVeh = m_pMyVehicle->pDriver; + if (driverOfVeh && driverOfVeh != this && damagedBy) + driverOfVeh->ReactToAttack(damagedBy); + + if (damagedBy == FindPlayerPed() || damagedBy && damagedBy == FindPlayerVehicle()) { + CDarkel::RegisterKillByPlayer(this, method, headShot); + m_threatEntity = FindPlayerPed(); + } else { + CDarkel::RegisterKillNotByPlayer(this, method); + } + } +#endif + m_fHealth = 1.0f; + return false; + } + m_fHealth = 0.0f; + if (player == this) + m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED); + + SetDie(NUM_ANIMS, 4.0f, 0.0f); + return true; + } else { + m_fHealth = 0.0f; + SetDie(dieAnim, dieDelta, dieSpeed); + + if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) { + + // There are PlayerInfo stuff here in VC + CDarkel::RegisterKillByPlayer(this, method, headShot); + m_threatEntity = player; + } else { + CDarkel::RegisterKillNotByPlayer(this, method); + } + if (method == WEAPONTYPE_DROWNING) + bIsInTheAir = false; + + return true; + } +} + +static RwObject* +SetPedAtomicVisibilityCB(RwObject* object, void* data) +{ + if (data == nil) + RpAtomicSetFlags((RpAtomic*)object, 0); + return object; +} + +static RwFrame* +RecurseFrameChildrenVisibilityCB(RwFrame* frame, void* data) +{ + RwFrameForAllObjects(frame, SetPedAtomicVisibilityCB, data); + RwFrameForAllChildren(frame, RecurseFrameChildrenVisibilityCB, nil); + return frame; +} + +static RwObject* +CloneAtomicToFrameCB(RwObject *frame, void *data) +{ + RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame); + RpAtomicSetFrame(newAtomic, (RwFrame*)data); + RpClumpAddAtomic(flyingClumpTemp, newAtomic); + CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil); + return frame; +} + +static RwFrame* +RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data) +{ + RwFrame *newFrame = RwFrameCreate(); + RwFrameAddChild((RwFrame*)data, newFrame); + RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE); + RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame); + RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame); + return newFrame; +} + +void +CPed::RemoveBodyPart(PedNode nodeId, int8 direction) +{ + RwFrame *frame; + CVector pos; + + frame = m_pFrames[nodeId]->frame; + if (frame) { + if (CGame::nastyGame) { +#ifdef PED_SKIN + if(!IsClumpSkinned(GetClump())) +#endif + { +#ifdef DEBUGMENU + if (bPopHeadsOnHeadshot || nodeId != PED_HEAD) +#else + if (nodeId != PED_HEAD) +#endif + SpawnFlyingComponent(nodeId, direction); + + RecurseFrameChildrenVisibilityCB(frame, nil); + } + pos.x = 0.0f; + pos.y = 0.0f; + pos.z = 0.0f; + TransformToNode(pos, PED_HEAD); + + if (CEntity::GetIsOnScreen()) { + CParticle::AddParticle(PARTICLE_TEST, pos, + CVector(0.0f, 0.0f, 0.0f), + nil, 0.1f, 0, 0, 0, 0); + + for (int i = 0; i < 16; i++) { + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, + pos, + CVector(0.0f, 0.0f, 0.03f), + nil, 0.0f, 0, 0, 0, 0); + } + } + bBodyPartJustCameOff = true; + m_bodyPartBleeding = nodeId; + } + } else { + printf("Trying to remove ped component"); + } +} + +CObject* +CPed::SpawnFlyingComponent(int pedNode, int8 direction) +{ + if (CObject::nNoTempObjects >= NUMTEMPOBJECTS) + return nil; + +#ifdef PED_SKIN + assert(!IsClumpSkinned(GetClump())); +#endif + + CObject *obj = new CObject(); + if (!obj) + return nil; + + RwFrame *frame = RwFrameCreate(); + RpClump *clump = RpClumpCreate(); + RpClumpSetFrame(clump, frame); + RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame); + *RwFrameGetMatrix(frame) = *matrix; + + flyingClumpTemp = clump; + RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame); + RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame); + flyingClumpTemp = nil; + switch (pedNode) { + case PED_HEAD: + // So popping head would have wheel collision. They disabled it anyway + obj->SetModelIndexNoCreate(MI_CAR_WHEEL); + break; + case PED_UPPERARML: + case PED_UPPERARMR: + obj->SetModelIndexNoCreate(MI_BODYPARTB); + obj->SetCenterOfMass(0.25f, 0.0f, 0.0f); + break; + case PED_UPPERLEGL: + case PED_UPPERLEGR: + obj->SetModelIndexNoCreate(MI_BODYPARTA); + obj->SetCenterOfMass(0.4f, 0.0f, 0.0f); + break; + default: + break; + } + obj->RefModelInfo(GetModelIndex()); + obj->AttachToRwObject((RwObject*)clump); + obj->m_fMass = 15.0f; + obj->m_fTurnMass = 5.0f; + obj->m_fAirResistance = 0.99f; + obj->m_fElasticity = 0.03f; + obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f; + obj->ObjectCreatedBy = TEMP_OBJECT; + obj->SetIsStatic(false); + obj->bIsPickup = false; + obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SMALLBOX; + + // life time - the more objects the are, the shorter this one will live + CObject::nNoTempObjects++; + if (CObject::nNoTempObjects > 20) + obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000; + else if (CObject::nNoTempObjects > 10) + obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000; + else + obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000; + + CVector localForcePos, forceDir; + + if (direction == 2) { + obj->m_vecMoveSpeed = 0.03f * GetForward(); + obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f; + obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + localForcePos = CVector(0.0f, 0.0f, 0.0f); + forceDir = GetForward(); + } else { + obj->m_vecMoveSpeed = -0.03f * GetForward(); + obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f; + obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + localForcePos = CVector(0.0f, 0.0f, 0.0f); + forceDir = -GetForward(); + } + obj->ApplyTurnForce(forceDir, localForcePos); + CWorld::Add(obj); + + return obj; +} + +void +CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer) +{ + CVector pos2 = CVector( + pos.x, + pos.y, + pos.z + 0.1f + ); + + if (!IsPlayer() || evenOnPlayer) { + ++CStats::HeadsPopped; + + // BUG: This condition will always return true. Even fixing it won't work, because these states are unused. + // if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) { + SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + // } + + bBodyPartJustCameOff = true; + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150; + + CParticle::AddParticle(PARTICLE_TEST, pos2, + CVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0); + + if (CEntity::GetIsOnScreen()) { + for(int i=0; i < 32; i++) { + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, + pos2, CVector(0.0f, 0.0f, 0.03f), + nil, 0.0f, 0, 0, 0, 0); + } + + for (int i = 0; i < 16; i++) { + CParticle::AddParticle(PARTICLE_DEBRIS2, + pos2, + CVector(0.0f, 0.0f, 0.01f), + nil, 0.0f, 0, 0, 0, 0); + } + } + } +} + +uint8 +CPed::DoesLOSBulletHitPed(CColPoint &colPoint) +{ +#ifdef FIX_BUGS + return 1; +#else + uint8 retVal = 2; + + float headZ = GetNodePosition(PED_HEAD).z; + + if (m_nPedState == PED_FALL) + retVal = 1; + + float colZ = colPoint.point.z; + if (colZ < headZ) + retVal = 1; + + if (headZ + 0.2f <= colZ) + retVal = 0; + + return retVal; +#endif +} + +bool +CPed::IsPedHeadAbovePos(float zOffset) +{ + return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z; +} + +bool +CPed::PlacePedOnDryLand(void) +{ + float waterLevel = 0.0f; + CEntity *foundEnt = nil; + CColPoint foundCol; + float foundColZ; + + CWaterLevel::GetWaterLevelNoWaves(GetPosition().x, GetPosition().y, GetPosition().z, &waterLevel); + + CVector potentialGround = GetPosition(); + potentialGround.z = waterLevel; + + if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false)) + return false; + + CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition(); + potentialGroundDist.z = 0.0f; + potentialGroundDist.Normalise(); + + CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point; + posToCheck.z = 3.0f + waterLevel; + + if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) { + foundColZ = foundCol.point.z; + if (foundColZ >= waterLevel) { + posToCheck.z = 0.8f + foundColZ; + SetPosition(posToCheck); + bIsStanding = true; + bWasStanding = true; + return true; + } + } + + posToCheck = 5.0f * potentialGroundDist + GetPosition(); + posToCheck.z = 3.0f + waterLevel; + + if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) + return false; + + foundColZ = foundCol.point.z; + if (foundColZ < waterLevel) + return false; + + posToCheck.z = 0.8f + foundColZ; + SetPosition(posToCheck); + bIsStanding = true; + bWasStanding = true; + return true; +} + +void +CPed::CollideWithPed(CPed *collideWith) +{ + CAnimBlendAssociation *animAssoc; + AnimationId animToPlay; + + bool weAreMissionChar = CharCreatedBy == MISSION_CHAR; + bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR; + CVector posDiff = collideWith->GetPosition() - GetPosition(); + int waitTime = 0; + + if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) { + bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f; + bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f; + + if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) { + + if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f) + && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT +#ifdef VC_PED_PORTS + || m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith + || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this +#endif + )) { + + if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) { + + if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { + + if (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) { + + if (weAreMissionChar && (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY)) { + + if (collideWith->m_nMoveState != PEDMOVE_STILL + && (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) { + float seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D(); + float heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D(); + + if (seekPosDist <= heAndSeekPosDist) { + waitTime = 1000; + collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime); + collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime; + } else { + waitTime = 500; + SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime; + } + } else if (collideWith->m_nMoveState == PEDMOVE_STILL) { + SetDirectionToWalkAroundObject(collideWith); + } + } else { + if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper + || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) && + (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) { + SetDirectionToWalkAroundObject(collideWith); + if (!weAreMissionChar) + Say(SOUND_PED_CHAT); + } else { + SetEvasiveStep(collideWith, 2); + } + } + } else { + if (m_pedStats->m_temper <= m_pedStats->m_fear + || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED + || weAreMissionChar + || collideWith->m_nPedType == PEDTYPE_CIVFEMALE + || collideWith->m_nPedType == m_nPedType + || collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { + SetDirectionToWalkAroundObject(collideWith); + Say(SOUND_PED_CHAT); + } else { + TurnBody(); + SetAttack(collideWith); +#ifdef VC_PED_PORTS + m_fRotationCur = 0.3f + m_fRotationCur; + m_fRotationDest = m_fRotationCur; +#endif + } + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450); + } + } + } else { +#ifdef VC_PED_PORTS + if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { +#else + if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { +#endif + if (heLooksToUs) { + SetEvasiveStep(collideWith, 1); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; + } + } else if (weDontLookToHim && IsPedInControl()) { + + if (m_pedStats != collideWith->m_pedStats) { + + if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper +#ifdef VC_PED_PORTS + || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer +#endif + ) { + + if (collideWith->IsPlayer()) { + // He's on our right side + if (DotProduct(posDiff,GetRight()) <= 0.0f) + m_fRotationCur -= m_headingRate; + else + m_fRotationCur += m_headingRate; + } else { + // He's on our right side + if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) + collideWith->m_fRotationCur -= collideWith->m_headingRate; + else + collideWith->m_fRotationCur += collideWith->m_headingRate; + } + } else { + SetLookFlag(collideWith, false); + TurnBody(); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); + animAssoc->flags |= ASSOC_FADEOUTWHENDONE; +#ifdef VC_PED_PORTS + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000; +#endif + if (!heIsMissionChar) { + CVector2D posDiff2D(posDiff); + int direction = collideWith->GetLocalDirection(posDiff2D); + collideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5); + } + } + } + } + } + } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar +#ifdef VC_PED_PORTS + || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness +#endif + ) { + // He looks us and we're not at his right side + if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) { + CVector moveForce = GetRight(); + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) + animToPlay = ANIM_HIT_LEFT; + else + animToPlay = ANIM_SHOT_LEFT_PARTIAL; + } else if (heLooksToUs) { + CVector moveForce = GetRight() * -1.0f; + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) + animToPlay = ANIM_HIT_RIGHT; + else + animToPlay = ANIM_SHOT_RIGHT_PARTIAL; + } else { + if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) + animToPlay = ANIM_HIT_BACK; + else + animToPlay = ANIM_SHOT_BACK_PARTIAL; + } + + if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) { + animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f); + animAssoc->flags |= ASSOC_FADEOUTWHENDONE; + collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000; + if (m_nPedState == PED_ATTACK) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); + } + } else { + // We're at his right side + if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) { + CVector moveForce = GetRight() * -1.0f; + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (heLooksToUs) + animToPlay = ANIM_KO_SPIN_L; + else + animToPlay = ANIM_KD_RIGHT; + } else { + CVector moveForce = GetRight(); + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (heLooksToUs) + animToPlay = ANIM_KO_SPIN_R; + else + animToPlay = ANIM_KD_LEFT; + } + + if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl()) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); + + collideWith->SetFall(3000, animToPlay, 0); + } + } else { + if (!IsPedInControl()) + return; + + if (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) + return; + + if (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) { + + if (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) { + + if (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){ + SetEvasiveStep(collideWith, 2); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; + } else if (collideWith->m_nMoveState > PEDMOVE_WALK) { + waitTime = 2000; + SetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime); + } + } + } else if (heLooksToUs + && collideWith->m_nPedState != PED_STEP_AWAY + && m_nPedState != PED_STEP_AWAY + && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { + + SetEvasiveStep(collideWith, 1); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; + } + } + + if (IsPlayer()) { + SetLookFlag(collideWith, true); + SetLookTimer(800); + } + } else { + bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; + SetFindPathAndFlee(collideWith, 5000, !isRunning); + } +} + +void +CPed::KillPedWithCar(CVehicle *car, float impulse) +{ + CVehicleModelInfo *vehModel; + CColModel *vehColModel; + uint8 damageDir; + PedNode nodeToDamage; + eWeaponType killMethod; + + if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) { + if (!this->m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER) + this->m_pCollidingEntity = car; + return; + } + + if (m_nPedState == PED_DEAD) + return; + + if (m_pCurSurface) { + if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer())) + return; + } + + CVector distVec = GetPosition() - car->GetPosition(); + + if ((impulse > 12.0f || car->GetModelIndex() == MI_TRAIN) && !IsPlayer()) { + nodeToDamage = PED_TORSO; + killMethod = WEAPONTYPE_RAMMEDBYCAR; + uint8 randVal = CGeneral::GetRandomNumber() & 3; + + if (car == FindPlayerVehicle()) { + float carSpeed = car->m_vecMoveSpeed.Magnitude(); + uint8 shakeFreq; + if (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) { + shakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f; + } else { + shakeFreq = 250.0f; + } + CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq); + } + bIsStanding = false; + damageDir = GetLocalDirection(-m_vecMoveSpeed); + vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex()); + vehColModel = vehModel->GetColModel(); + float carRightAndDistDotProd = DotProduct(distVec, car->GetRight()); + + if (car->GetModelIndex() == MI_TRAIN) { + killMethod = WEAPONTYPE_RUNOVERBYCAR; + nodeToDamage = PED_HEAD; + m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed; + m_vecMoveSpeed.z = 0.0f; + if (damageDir == 1 || damageDir == 3) + damageDir = 2; + if (CGame::nastyGame) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f); + + // Car doesn't look to us + } else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){ + + if (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) { + + // We're at the right of the car + if (carRightAndDistDotProd <= 0.0f) + nodeToDamage = PED_UPPERARML; + else + nodeToDamage = PED_UPPERARMR; + + if (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) { + killMethod = WEAPONTYPE_RUNOVERBYCAR; + m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed; + m_vecMoveSpeed.z = 0.0f; + if (damageDir == 1 || damageDir == 3) + damageDir = 2; + if (CGame::nastyGame) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f); + + } + } else { + float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward()); + + // carFrontAndDistDotProd <= 0.0 car looks to us + if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) { + killMethod = WEAPONTYPE_RUNOVERBYCAR; + nodeToDamage = PED_HEAD; + m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed; + m_vecMoveSpeed.z = 0.0f; + if (damageDir == 1 || damageDir == 3) + damageDir = 2; + + if (CGame::nastyGame) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f); + + } else { + nodeToDamage = PED_MID; + float vehColMaxY = vehColModel->boundingBox.max.y; + float vehColMinY = vehColModel->boundingBox.min.y; + float vehColMaxZ = vehColModel->boundingBox.max.z; + float carFrontZ = car->GetForward().z; + float carHighestZ, carLength; + + if (carFrontZ < -0.2f) { + // Highest point of car's back + carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z; + carLength = vehColMaxY - vehColMinY; + + } else if (carFrontZ > 0.1f) { + // Highest point of car's front + carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z; + float highestZDist = carHighestZ - GetPosition().z; + if (highestZDist > 0.0f) { + GetMatrix().GetPosition().z += 0.5f * highestZDist; + carHighestZ += highestZDist * 0.25f; + } + carLength = vehColMaxY; + + } else { + // Highest point of car's front + carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z; + carLength = vehColMaxY; + } + + float pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude()); + + // TODO: What are we doing down here? + float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ; + + // After this point, distVec isn't distVec anymore. + distVec = car->m_vecMoveSpeed; + distVec.Normalise(); + distVec *= 0.2 * unknown; + + if (damageDir != 1 && damageDir != 3) + distVec.z += unknown; + else + distVec.z += 1.5f * unknown; + + m_vecMoveSpeed = distVec; + damageDir += 2; + if (damageDir > 3) + damageDir = damageDir - 4; + + if (car->m_vehType == VEHICLE_TYPE_CAR) { + CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision(); + + if (bonnet) { + if (CGeneral::GetRandomNumber() & 1) { + bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f)); + } else { + bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f)); + } + CVector forceDir = car->GetUp() * 10.0f; + bonnet->ApplyTurnForce(forceDir, car->GetForward()); + } + } + } + } + } + + if (car->pDriver) { + CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000); + } + + ePedPieceTypes pieceToDamage; + switch (nodeToDamage) { + case PED_HEAD: + pieceToDamage = PEDPIECE_HEAD; + break; + case PED_UPPERARML: + pieceToDamage = PEDPIECE_LEFTARM; + break; + case PED_UPPERARMR: + pieceToDamage = PEDPIECE_RIGHTARM; + break; + default: + pieceToDamage = PEDPIECE_MID; + break; + } + InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir); + + if (DyingOrDead() + && bIsPedDieAnimPlaying && !m_pCollidingEntity) { + m_pCollidingEntity = car; + } + if (nodeToDamage == PED_MID) + bKnockedUpIntoAir = true; + else + bKnockedUpIntoAir = false; + + distVec.Normalise(); + +#ifdef VC_PED_PORTS + distVec *= Min(car->m_fMass / 1400.0f, 1.0f); +#endif + car->ApplyMoveForce(distVec * -100.0f); + Say(SOUND_PED_DEFEND); + + } else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f + || impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) { + + bIsStanding = false; + uint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed); + float damage; + if (IsPlayer() && car->GetModelIndex() == MI_TRAIN) + damage = 150.0f; + else + damage = 30.0f; + + InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection); + SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true); + + if (OnGround() && !m_pCollidingEntity && + (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) { + + m_pCollidingEntity = car; + } + + bKnockedUpIntoAir = false; + if (car->GetModelIndex() != MI_TRAIN && !bHasHitWall) { + m_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f; + } + m_vecMoveSpeed.z = 0.0f; + distVec.Normalise(); +#ifdef VC_PED_PORTS + distVec *= Min(car->m_fMass / 1400.0f, 1.0f); +#endif + car->ApplyMoveForce(distVec * -60.0f); + Say(SOUND_PED_DEFEND); + } + +#ifdef VC_PED_PORTS + // Killing gang members with car wasn't triggering a fight, until now... Taken from VC. + if (IsGangMember()) { + CPed *driver = car->pDriver; + if (driver && driver->IsPlayer() +#ifdef FIX_BUGS + && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats) && (!m_leader || m_leader != driver) +#endif + ) { + RegisterThreatWithGangPeds(driver); + } + } +#endif +} \ No newline at end of file diff --git a/src/peds/PedStats.cpp b/src/peds/PedStats.cpp deleted file mode 100644 index 1f7a95b4..00000000 --- a/src/peds/PedStats.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "common.h" - -#include "General.h" -#include "FileMgr.h" -#include "PedStats.h" - -CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS]; - -void -CPedStats::Initialise(void) -{ - int i; - - debug("Initialising CPedStats...\n"); - for(i = 0; i < NUM_PEDSTATS; i++){ - ms_apPedStats[i] = new CPedStats; - ms_apPedStats[i]->m_type = PEDSTAT_PLAYER; - ms_apPedStats[i]->m_name[8] = 'R'; // WHAT? - ms_apPedStats[i]->m_fleeDistance = 20.0f; - ms_apPedStats[i]->m_headingChangeRate = 15.0f; - ms_apPedStats[i]->m_fear = 50; - ms_apPedStats[i]->m_temper = 50; - ms_apPedStats[i]->m_lawfulness = 50; - ms_apPedStats[i]->m_sexiness = 50; - ms_apPedStats[i]->m_attackStrength = 1.0f; - ms_apPedStats[i]->m_defendWeakness = 1.0f; - ms_apPedStats[i]->m_flags = 0; - } - debug("Loading pedstats data...\n"); - CPedStats::LoadPedStats(); - debug("CPedStats ready\n"); -} - -void -CPedStats::Shutdown(void) -{ - int i; - debug("Shutting down CPedStats...\n"); - for(i = 0; i < NUM_PEDSTATS; i++) - delete ms_apPedStats[i]; - debug("CPedStats shut down\n"); -} - -void -CPedStats::LoadPedStats(void) -{ - char *buf; - char line[256]; - char name[32]; - size_t bp, buflen; - int lp, linelen; - int type; - float fleeDist, headingChangeRate, attackStrength, defendWeakness; - int fear, temper, lawfullness, sexiness, flags; - - - type = 0; - buf = new char[16 * 1024]; - - CFileMgr::SetDir("DATA"); - buflen = CFileMgr::LoadFile("PEDSTATS.DAT", (uint8*)buf, 16 * 1024, "r"); - CFileMgr::SetDir(""); - - for(bp = 0; bp < buflen; ){ - // read file line by line - for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){ - if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t') - line[linelen++] = ' '; - else - line[linelen++] = buf[bp]; - } - bp++; - line[linelen] = '\0'; - - // skip white space - for(lp = 0; line[lp] <= ' '; lp++); - - if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines - line[lp] == '#') - continue; - - sscanf(&line[lp], "%s %f %f %d %d %d %d %f %f %d", - name, - &fleeDist, - &headingChangeRate, - &fear, - &temper, - &lawfullness, - &sexiness, - &attackStrength, - &defendWeakness, - &flags); - ms_apPedStats[type]->m_type = (ePedStats)type; - strncpy(ms_apPedStats[type]->m_name, name, 24); // FIX: game uses strcpy - ms_apPedStats[type]->m_fleeDistance = fleeDist; - ms_apPedStats[type]->m_headingChangeRate = headingChangeRate; - ms_apPedStats[type]->m_fear = fear; - ms_apPedStats[type]->m_temper = temper; - ms_apPedStats[type]->m_lawfulness = lawfullness; - ms_apPedStats[type]->m_sexiness = sexiness; - ms_apPedStats[type]->m_attackStrength = attackStrength; - ms_apPedStats[type]->m_defendWeakness = defendWeakness; - ms_apPedStats[type]->m_flags = flags; - type++; - } - - delete[] buf; -} - -ePedStats -CPedStats::GetPedStatType(char *name) -{ - for(uint16 type = 0; type < NUM_PEDSTATS; type++) - if(!CGeneral::faststrcmp(ms_apPedStats[type]->m_name, name)) - return (ePedStats) type; - - return NUM_PEDSTATS; -} diff --git a/src/peds/PedStats.h b/src/peds/PedStats.h deleted file mode 100644 index df97bdb8..00000000 --- a/src/peds/PedStats.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -enum ePedStats -{ - PEDSTAT_PLAYER, - PEDSTAT_COP, - PEDSTAT_MEDIC, - PEDSTAT_FIREMAN, - PEDSTAT_GANG1, - PEDSTAT_GANG2, - PEDSTAT_GANG3, - PEDSTAT_GANG4, - PEDSTAT_GANG5, - PEDSTAT_GANG6, - PEDSTAT_GANG7, - PEDSTAT_STREET_GUY, - PEDSTAT_SUIT_GUY, - PEDSTAT_SENSIBLE_GUY, - PEDSTAT_GEEK_GUY, - PEDSTAT_OLD_GUY, - PEDSTAT_TOUGH_GUY, - PEDSTAT_STREET_GIRL, - PEDSTAT_SUIT_GIRL, - PEDSTAT_SENSIBLE_GIRL, - PEDSTAT_GEEK_GIRL, - PEDSTAT_OLD_GIRL, - PEDSTAT_TOUGH_GIRL, - PEDSTAT_TRAMP_MALE, - PEDSTAT_TRAMP_FEMALE, - PEDSTAT_TOURIST, - PEDSTAT_PROSTITUTE, - PEDSTAT_CRIMINAL, - PEDSTAT_BUSKER, - PEDSTAT_TAXIDRIVER, - PEDSTAT_PSYCHO, - PEDSTAT_STEWARD, - PEDSTAT_SPORTSFAN, - PEDSTAT_SHOPPER, - PEDSTAT_OLDSHOPPER, - - NUM_PEDSTATS -}; - -// flags -enum -{ - STAT_PUNCH_ONLY = 1, - STAT_CAN_KNEE_HEAD = 2, - STAT_CAN_KICK = 4, - STAT_CAN_ROUNDHOUSE = 8, - STAT_NO_DIVE = 0x10, - STAT_ONE_HIT_KNOCKDOWN = 0x20, - STAT_SHOPPING_BAGS = 0x40, - STAT_GUN_PANIC = 0x80 -}; - -class CPedStats -{ -public: - ePedStats m_type; - char m_name[24]; - float m_fleeDistance; - float m_headingChangeRate; - int8 m_fear; - int8 m_temper; - int8 m_lawfulness; - int8 m_sexiness; - float m_attackStrength; - float m_defendWeakness; - int16 m_flags; - - static CPedStats *ms_apPedStats[NUM_PEDSTATS]; - - static void Initialise(void); - static void Shutdown(void); - static void LoadPedStats(void); - static ePedStats GetPedStatType(char *name); -}; - -VALIDATE_SIZE(CPedStats, 0x34); diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp index 397cd71d..6e745bd7 100644 --- a/src/peds/PedType.cpp +++ b/src/peds/PedType.cpp @@ -1,9 +1,11 @@ #include "common.h" +#include "General.h" #include "FileMgr.h" #include "PedType.h" CPedType *CPedType::ms_apPedType[NUM_PEDTYPES]; +CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS]; void CPedType::Initialise(void) @@ -202,3 +204,114 @@ INITSAVEBUF *ms_apPedType[i] = ReadSaveBuf(buf); VALIDATESAVEBUF(size) } + +void +CPedStats::Initialise(void) +{ + int i; + + debug("Initialising CPedStats...\n"); + for(i = 0; i < NUM_PEDSTATS; i++){ + ms_apPedStats[i] = new CPedStats; + ms_apPedStats[i]->m_type = PEDSTAT_PLAYER; + ms_apPedStats[i]->m_name[8] = 'R'; // WHAT? + ms_apPedStats[i]->m_fleeDistance = 20.0f; + ms_apPedStats[i]->m_headingChangeRate = 15.0f; + ms_apPedStats[i]->m_fear = 50; + ms_apPedStats[i]->m_temper = 50; + ms_apPedStats[i]->m_lawfulness = 50; + ms_apPedStats[i]->m_sexiness = 50; + ms_apPedStats[i]->m_attackStrength = 1.0f; + ms_apPedStats[i]->m_defendWeakness = 1.0f; + ms_apPedStats[i]->m_flags = 0; + } + debug("Loading pedstats data...\n"); + CPedStats::LoadPedStats(); + debug("CPedStats ready\n"); +} + +void +CPedStats::Shutdown(void) +{ + int i; + debug("Shutting down CPedStats...\n"); + for(i = 0; i < NUM_PEDSTATS; i++) + delete ms_apPedStats[i]; + debug("CPedStats shut down\n"); +} + +void +CPedStats::LoadPedStats(void) +{ + char *buf; + char line[256]; + char name[32]; + size_t bp, buflen; + int lp, linelen; + int type; + float fleeDist, headingChangeRate, attackStrength, defendWeakness; + int fear, temper, lawfullness, sexiness, flags; + + + type = 0; + buf = new char[16 * 1024]; + + CFileMgr::SetDir("DATA"); + buflen = CFileMgr::LoadFile("PEDSTATS.DAT", (uint8*)buf, 16 * 1024, "r"); + CFileMgr::SetDir(""); + + for(bp = 0; bp < buflen; ){ + // read file line by line + for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){ + if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t') + line[linelen++] = ' '; + else + line[linelen++] = buf[bp]; + } + bp++; + line[linelen] = '\0'; + + // skip white space + for(lp = 0; line[lp] <= ' '; lp++); + + if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines + line[lp] == '#') + continue; + + sscanf(&line[lp], "%s %f %f %d %d %d %d %f %f %d", + name, + &fleeDist, + &headingChangeRate, + &fear, + &temper, + &lawfullness, + &sexiness, + &attackStrength, + &defendWeakness, + &flags); + ms_apPedStats[type]->m_type = (ePedStats)type; + strncpy(ms_apPedStats[type]->m_name, name, 24); // FIX: game uses strcpy + ms_apPedStats[type]->m_fleeDistance = fleeDist; + ms_apPedStats[type]->m_headingChangeRate = headingChangeRate; + ms_apPedStats[type]->m_fear = fear; + ms_apPedStats[type]->m_temper = temper; + ms_apPedStats[type]->m_lawfulness = lawfullness; + ms_apPedStats[type]->m_sexiness = sexiness; + ms_apPedStats[type]->m_attackStrength = attackStrength; + ms_apPedStats[type]->m_defendWeakness = defendWeakness; + ms_apPedStats[type]->m_flags = flags; + type++; + } + + delete[] buf; +} + +ePedStats +CPedStats::GetPedStatType(char *name) +{ + for(uint16 type = 0; type < NUM_PEDSTATS; type++) + if(!CGeneral::faststrcmp(ms_apPedStats[type]->m_name, name)) + return (ePedStats) type; + + return NUM_PEDSTATS; +} diff --git a/src/peds/PedType.h b/src/peds/PedType.h index 3a765da1..3e23c249 100644 --- a/src/peds/PedType.h +++ b/src/peds/PedType.h @@ -92,3 +92,82 @@ public: }; VALIDATE_SIZE(CPedType, 0x20); + +enum ePedStats +{ + PEDSTAT_PLAYER, + PEDSTAT_COP, + PEDSTAT_MEDIC, + PEDSTAT_FIREMAN, + PEDSTAT_GANG1, + PEDSTAT_GANG2, + PEDSTAT_GANG3, + PEDSTAT_GANG4, + PEDSTAT_GANG5, + PEDSTAT_GANG6, + PEDSTAT_GANG7, + PEDSTAT_STREET_GUY, + PEDSTAT_SUIT_GUY, + PEDSTAT_SENSIBLE_GUY, + PEDSTAT_GEEK_GUY, + PEDSTAT_OLD_GUY, + PEDSTAT_TOUGH_GUY, + PEDSTAT_STREET_GIRL, + PEDSTAT_SUIT_GIRL, + PEDSTAT_SENSIBLE_GIRL, + PEDSTAT_GEEK_GIRL, + PEDSTAT_OLD_GIRL, + PEDSTAT_TOUGH_GIRL, + PEDSTAT_TRAMP_MALE, + PEDSTAT_TRAMP_FEMALE, + PEDSTAT_TOURIST, + PEDSTAT_PROSTITUTE, + PEDSTAT_CRIMINAL, + PEDSTAT_BUSKER, + PEDSTAT_TAXIDRIVER, + PEDSTAT_PSYCHO, + PEDSTAT_STEWARD, + PEDSTAT_SPORTSFAN, + PEDSTAT_SHOPPER, + PEDSTAT_OLDSHOPPER, + + NUM_PEDSTATS +}; + +// flags +enum +{ + STAT_PUNCH_ONLY = 1, + STAT_CAN_KNEE_HEAD = 2, + STAT_CAN_KICK = 4, + STAT_CAN_ROUNDHOUSE = 8, + STAT_NO_DIVE = 0x10, + STAT_ONE_HIT_KNOCKDOWN = 0x20, + STAT_SHOPPING_BAGS = 0x40, + STAT_GUN_PANIC = 0x80 +}; + +class CPedStats +{ +public: + ePedStats m_type; + char m_name[24]; + float m_fleeDistance; + float m_headingChangeRate; + int8 m_fear; + int8 m_temper; + int8 m_lawfulness; + int8 m_sexiness; + float m_attackStrength; + float m_defendWeakness; + int16 m_flags; + + static CPedStats *ms_apPedStats[NUM_PEDSTATS]; + + static void Initialise(void); + static void Shutdown(void); + static void LoadPedStats(void); + static ePedStats GetPedStatType(char *name); +}; + +VALIDATE_SIZE(CPedStats, 0x34); \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 92bbdd45..949f8c54 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -848,6 +848,37 @@ CRenderer::RequestObjectsInFrustum(void) } } +bool +CPed::SetupLighting(void) +{ + ActivateDirectional(); + SetAmbientColoursForPedsCarsAndObjects(); + +#ifndef MASTER + // Originally this was being called through iteration of Sectors, but putting it here is better. + if (GetDebugDisplay() != 0 && !IsPlayer()) + DebugRenderOnePedText(); +#endif + + if (bRenderScorched) { + WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f); + } else { + // Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0. + float lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition()); + if (!bHasBlip && lightMult != 1.0f) { + SetAmbientAndDirectionalColours(lightMult); + return true; + } + } + return false; +} + +void +CPed::RemoveLighting(bool reset) +{ + CRenderer::RemoveVehiclePedLights(this, reset); +} + float CalcNewDelta(RwV2d *a, RwV2d *b) { diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 95a68769..66afa1d4 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -4182,6 +4182,93 @@ CAutomobile::HasCarStoppedBecauseOfLight(void) return false; } +void +CPed::DeadPedMakesTyresBloody(void) +{ + int minX = CWorld::GetSectorIndexX(GetPosition().x - 2.0f); + if (minX < 0) minX = 0; + int minY = CWorld::GetSectorIndexY(GetPosition().y - 2.0f); + if (minY < 0) minY = 0; + int maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f); + if (maxX > NUMSECTORS_X-1) maxX = NUMSECTORS_X-1; + int maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f); + if (maxY > NUMSECTORS_Y-1) maxY = NUMSECTORS_Y-1; + + CWorld::AdvanceCurrentScanCode(); + + for (int curY = minY; curY <= maxY; curY++) { + for (int curX = minX; curX <= maxX; curX++) { + CSector *sector = CWorld::GetSector(curX, curY); + MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]); + MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]); + } + } +} + +void +CPed::MakeTyresMuddySectorList(CPtrList &list) +{ + for (CPtrNode *node = list.first; node; node = node->next) { + CVehicle *veh = (CVehicle*)node->item; + if (veh->IsCar() && veh->m_scanCode != CWorld::GetCurrentScanCode()) { + veh->m_scanCode = CWorld::GetCurrentScanCode(); + + if (Abs(GetPosition().x - veh->GetPosition().x) < 10.0f) { + + if (Abs(GetPosition().y - veh->GetPosition().y) < 10.0f + && veh->m_vecMoveSpeed.MagnitudeSqr2D() > 0.05f) { + + for(int wheel = 0; wheel < 4; wheel++) { + + if (!((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] + && ((CAutomobile*)veh)->m_aSuspensionSpringRatio[wheel] < 1.0f) { + + CColModel *vehCol = veh->GetModelInfo()->GetColModel(); + CVector approxWheelOffset; + switch (wheel) { + case 0: + approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f); + break; + case 1: + approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f); + break; + case 2: + approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f); + break; + case 3: + approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f); + break; + default: + break; + } + + // I hope so + CVector wheelPos = veh->GetMatrix() * approxWheelOffset; + if (Abs(wheelPos.z - GetPosition().z) < 2.0f) { + + if ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) { + if (CGame::nastyGame) { + ((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] = true; + DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_SPLATTER, 0.0f); + } + veh->ApplyMoveForce(CVector(0.0f, 0.0f, 50.0f)); + + CVector vehAndWheelDist = wheelPos - veh->GetPosition(); + veh->ApplyTurnForce(CVector(0.0f, 0.0f, 50.0f), vehAndWheelDist); + + if (veh == FindPlayerVehicle()) { + CPad::GetPad(0)->StartShake(300, 70); + } + } + } + } + } + } + } + } + } +} + void CAutomobile::SetBusDoorTimer(uint32 timer, uint8 type) { diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 9494c745..dc15485e 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -2287,6 +2287,16 @@ CWeapon::HasWeaponAmmoToBeUsed(void) } } +bool +CPed::IsPedDoingDriveByShooting(void) +{ + if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) { + if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight) + return true; + } + return false; +} + bool CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) { -- cgit v1.2.3 From 6b6b600cee9bda19d10868b5263cf477043ce56a Mon Sep 17 00:00:00 2001 From: Nikolay Date: Sat, 21 Nov 2020 21:12:47 +0300 Subject: no script logging --- src/core/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index db6e5490..f7a3853d 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -295,7 +295,7 @@ enum Config { #endif //#define SIMPLIER_MISSIONS // apply simplifications from mobile #define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT -#define SCRIPT_LOG_FILE_LEVEL 1 // 0 == no log, 1 == overwrite every frame, 2 == full log +#define SCRIPT_LOG_FILE_LEVEL 0 // 0 == no log, 1 == overwrite every frame, 2 == full log #ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #define USE_BASIC_SCRIPT_DEBUG_OUTPUT -- cgit v1.2.3 From 07303c62d12959927cbb72d4beb131f2647350fa Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 22 Nov 2020 00:13:07 +0100 Subject: finished cullzones --- src/core/ZoneCull.cpp | 1165 +++++++++++++++++++++++++++++++++++++++--- src/core/ZoneCull.h | 32 +- src/core/re3.cpp | 3 + src/render/Renderer.cpp | 206 +++++++- src/render/Renderer.h | 22 + src/rw/VisibilityPlugins.cpp | 2 - 6 files changed, 1326 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index c376e11f..075a13bc 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -1,5 +1,6 @@ #include "common.h" +#include "General.h" #include "Building.h" #include "Treadable.h" #include "Train.h" @@ -11,6 +12,9 @@ #include "ZoneCull.h" #include "Zones.h" +#include "Debug.h" +#include "Renderer.h" + int32 CCullZones::NumCullZones; CCullZone CCullZones::aZones[NUMCULLZONES]; int32 CCullZones::NumAttributeZones; @@ -27,6 +31,8 @@ int32 CCullZones::EntityIndicesUsed; bool CCullZones::bCurrentSubwayIsInvisible; bool CCullZones::bCullZonesDisabled; +#define NUMUNCOMPRESSED (6000) +#define NUMTEMPINDICES (140000) void CCullZones::Init(void) @@ -48,26 +54,6 @@ CCullZones::Init(void) aPointersToBigBuildingsForTreadables[i] = -1; } -bool CCullZone::TestLine(CVector vec1, CVector vec2) -{ - CColPoint colPoint; - CEntity *entity; - - if (CWorld::ProcessLineOfSight(vec1, vec2, colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x + 0.05f, vec1.y, vec1.z), CVector(vec2.x + 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x - 0.05f, vec1.y, vec1.z), CVector(vec2.x - 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y + 0.05f, vec1.z), CVector(vec2.x, vec2.y + 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y - 0.05f, vec1.z), CVector(vec2.x, vec2.y - 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z + 0.05f), CVector(vec2.x, vec2.y, vec2.z + 0.05f), colPoint, entity, true, false, false, false, false, true, false)) - return true; - return CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z - 0.05f), CVector(vec2.x, vec2.y, vec2.z - 0.05f), colPoint, entity, true, false, false, false, false, true, false); -} - uint16* pTempArrayIndices; int TempEntityIndicesUsed; @@ -89,19 +75,25 @@ CCullZones::ResolveVisibilities(void) CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables)); CFileMgr::CloseFile(fd); }else{ -#if 0 - // TODO: implement code from mobile to generate data here +#ifndef MASTER EntityIndicesUsed = 0; BuildListForBigBuildings(); - pTempArrayIndices = new uint16[140000]; + pTempArrayIndices = new uint16[NUMTEMPINDICES]; TempEntityIndicesUsed = 0; - for (int i = 0; i < NumCullZones; i++) { - DoVisibilityTestCullZone(i, true); +// if(!LoadTempFile()) // not in final game + { + for (int i = 0; i < NumCullZones; i++) { +//printf("testing zone %d (%d indices)\n", i, TempEntityIndicesUsed); + DoVisibilityTestCullZone(i, true); + } + +// SaveTempFile(); // not in final game } CompressIndicesArray(); delete[] pTempArrayIndices; + pTempArrayIndices = nil; fd = CFileMgr::OpenFileForWriting("data\\cullzone.dat"); if (fd != 0) { @@ -118,16 +110,53 @@ CCullZones::ResolveVisibilities(void) } } +bool +CCullZones::LoadTempFile(void) +{ + int fd = CFileMgr::OpenFile("cullzone.tmp"); + if (fd != 0) { + CFileMgr::Read(fd, (char*)&NumCullZones, sizeof(NumCullZones)); + CFileMgr::Read(fd, (char*)aZones, sizeof(aZones)); + CFileMgr::Read(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones)); + CFileMgr::Read(fd, (char*)&aAttributeZones, sizeof(aAttributeZones)); + CFileMgr::Read(fd, (char*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16)); + CFileMgr::Read(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed)); + CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings)); + CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables)); + CFileMgr::CloseFile(fd); + return true; + } + return false; +} + +void +CCullZones::SaveTempFile(void) +{ + int fd = CFileMgr::OpenFileForWriting("cullzone.tmp"); + if (fd != 0) { + CFileMgr::Write(fd, (char*)&NumCullZones, sizeof(NumCullZones)); + CFileMgr::Write(fd, (char*)aZones, sizeof(aZones)); + CFileMgr::Write(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones)); + CFileMgr::Write(fd, (char*)&aAttributeZones, sizeof(aAttributeZones)); + CFileMgr::Write(fd, (char*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16)); + CFileMgr::Write(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed)); + CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings)); + CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables)); + CFileMgr::CloseFile(fd); + } +} + + void CCullZones::BuildListForBigBuildings() { for (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) { CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); if (building == nil || !building->bIsBIGBuilding) continue; - CSimpleModelInfo *nonlod = (CSimpleModelInfo*)((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->m_atomics[2]; + CSimpleModelInfo *nonlod = ((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->GetRelatedModel(); if (nonlod == nil) continue; - for (int j = i; j >= 0; j--) { + for (int j = CPools::GetBuildingPool()->GetSize()-1; j >= 0; j--) { CBuilding *building2 = CPools::GetBuildingPool()->GetSlot(j); if (building2 == nil || building2->bIsBIGBuilding) continue; if (CModelInfo::GetModelInfo(building2->GetModelIndex()) == nonlod) { @@ -150,7 +179,7 @@ CCullZones::BuildListForBigBuildings() } void -CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt) +CCullZones::DoVisibilityTestCullZone(int zoneId, bool findIndices) { aZones[zoneId].m_groupIndexCount[0] = 0; aZones[zoneId].m_groupIndexCount[1] = 0; @@ -158,16 +187,17 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt) aZones[zoneId].m_indexStart = TempEntityIndicesUsed; aZones[zoneId].FindTestPoints(); - if (!doIt) return; + if (!findIndices) return; for (int i = CPools::GetBuildingPool()->GetSize() - 1; i >= 0; i--) { CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); if (building != nil && !building->bIsBIGBuilding && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForBuildings[i] != -1)) { - CBuilding *building2 = nil; + CBuilding *LODbuilding = nil; if (aPointersToBigBuildingsForBuildings[i] != -1) - building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]); + LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]); - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) { + if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) { + assert(TempEntityIndicesUsed < NUMTEMPINDICES); pTempArrayIndices[TempEntityIndicesUsed++] = i; aZones[zoneId].m_groupIndexCount[0]++; } @@ -175,13 +205,14 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt) } for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) { - CTreadable* building = CPools::GetTreadablePool()->GetSlot(i); + CBuilding* building = CPools::GetTreadablePool()->GetSlot(i); if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) { - CTreadable* building2 = nil; + CBuilding *LODbuilding = nil; if (aPointersToBigBuildingsForTreadables[i] != -1) - building2 = CPools::GetTreadablePool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); + LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, building2)) { + if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, LODbuilding)) { + assert(TempEntityIndicesUsed < NUMTEMPINDICES); pTempArrayIndices[TempEntityIndicesUsed++] = i; aZones[zoneId].m_groupIndexCount[1]++; } @@ -189,23 +220,28 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt) } for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) { - CTreadable *building = CPools::GetTreadablePool()->GetSlot(i); - if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < 40000.0f) { + CBuilding *building = CPools::GetTreadablePool()->GetSlot(i); + if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < SQR(200.0f)) { int start = aZones[zoneId].m_groupIndexCount[0] + aZones[zoneId].m_indexStart; int end = aZones[zoneId].m_groupIndexCount[1] + start; bool alreadyAdded = false; for (int k = start; k < end; k++) { +#ifdef FIX_BUGS + if (pTempArrayIndices[k] == i) +#else if (aIndices[k] == i) +#endif alreadyAdded = true; } if (!alreadyAdded) { - CBuilding *building2 = nil; + CBuilding *LODbuilding = nil; if (aPointersToBigBuildingsForTreadables[i] != -1) - building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) { + LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); + if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) { + assert(TempEntityIndicesUsed < NUMTEMPINDICES); pTempArrayIndices[TempEntityIndicesUsed++] = i; aZones[zoneId].m_groupIndexCount[2]++; } @@ -353,7 +389,9 @@ CCullZones::AddCullZone(CVector const &position, if((flag & ATTRZONE_NOTCULLZONE) == 0){ cull = &aZones[NumCullZones++]; v = position; - // WTF is this? + // reposition start point to the start/end of the + // alley next to the big building in the industrial district. + // probably isn't analyzed correctly otherwise?s if((v-CVector(1032.14f, -624.255f, 24.93f)).Magnitude() < 1.0f) v = CVector(1061.7f, -613.0f, 19.0f); if((v-CVector(1029.48f, -495.757f, 21.98f)).Magnitude() < 1.0f) @@ -385,6 +423,208 @@ CCullZones::AddCullZone(CVector const &position, } } +uint16 *pExtraArrayIndices; + +void +CCullZones::CompressIndicesArray() +{ + uint16 set[3]; + + // These are used to hold the compressed groups in sets of 3 + int numExtraIndices = 0; + pExtraArrayIndices = new uint16[NUMTEMPINDICES]; + + for(int numOccurrences = 6; numOccurrences > 1; numOccurrences--){ + if(NumCullZones == 0) + break; + +//printf("checking occurrences %d\n", numOccurrences); + int attempt = 0; + while(attempt < 10000){ + for(;;){ + attempt++; + + int zone = CGeneral::GetRandomNumber() % NumCullZones; + int group = CGeneral::GetRandomNumber() % 3; + if(!PickRandomSetForGroup(zone, group, set)) + break; + if(!DoWeHaveMoreThanXOccurencesOfSet(numOccurrences, set)) + break; + + // add this set + attempt = 1; + int setId = numExtraIndices + NUMUNCOMPRESSED; + pExtraArrayIndices[numExtraIndices++] = set[0]; + pExtraArrayIndices[numExtraIndices++] = set[1]; + pExtraArrayIndices[numExtraIndices++] = set[2]; + ReplaceSetForAllGroups(set, setId); + } + } + } + + TidyUpAndMergeLists(pExtraArrayIndices, numExtraIndices); + + delete[] pExtraArrayIndices; +} + +// Get three random indices for this group of a zone +bool +CCullZones::PickRandomSetForGroup(int32 zone, int32 group, uint16 *set) +{ + int32 start; + int32 size; + + aZones[zone].GetGroupStartAndSize(group, start, size); + if(size <= 0) + return false; + + int numIndices = 0; + for(int i = 0; i < size; i++) + if(pTempArrayIndices[start + i] != 0xFFFF) + numIndices++; + if(numIndices < 3) + return false; + + int first = CGeneral::GetRandomNumber() % (numIndices-2); + + numIndices = 0; + int n = 0; + for(int i = 0; i < size; i++) + if(pTempArrayIndices[start + i] != 0xFFFF){ + if(n++ < first) continue; + + set[numIndices++] = pTempArrayIndices[start + i]; + if(numIndices == 3) + break; + } + return true; +} + +bool +CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set) +{ + int32 curCount; + int32 start; + int32 size; + + curCount = 0; + for (int i = 0; i < NumCullZones; i++) { + for (int group = 0; group < 3; group++) { + aZones[i].GetGroupStartAndSize(group, start, size); + if(size <= 0) continue; + + // check if the set is a subset of the group + int n = 0; + for (int j = 0; j < size; j++) { + for (int k = 0; k < 3; k++) { + if (pTempArrayIndices[start+j] == set[k]) + n++; + } + } + // yes it is + if(n == 3){ + curCount++; + // check if we have seen this set often enough + if(curCount >= count) + return true; + } + } + } + return false; +} + +void +CCullZones::ReplaceSetForAllGroups(uint16 *set, uint16 setid) +{ + int32 start; + int32 size; + + for(int i = 0; i < NumCullZones; i++) + for(int group = 0; group < 3; group++){ + aZones[i].GetGroupStartAndSize(group, start, size); + if(size <= 0) continue; + + // check if the set is a subset of the group + int n = 0; + for(int j = 0; j < size; j++){ + for(int k = 0; k < 3; k++){ + if(pTempArrayIndices[start+j] == set[k]) + n++; + } + } + + // yes it is, so replace it + if(n == 3){ + bool insertedSet = false; + for(int j = 0; j < size; j++){ + for(int k = 0; k < 3; k++){ + // replace first element by set, invalidate others + if(pTempArrayIndices[start+j] == set[k]){ + if(!insertedSet) + pTempArrayIndices[start+j] = setid; + else + pTempArrayIndices[start+j] = 0xFFFF; + insertedSet = true; + } + } + } + } + } +} + +void +CCullZones::TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices) +{ + int numTempIndices = 0; + for(int i = 0; i < TempEntityIndicesUsed; i++) + if(pTempArrayIndices[i] != 0xFFFF) + numTempIndices++; + + // Fix up zone ranges such that there are no holes + for(int i = 0; i < NumCullZones; i++){ + int j; + int start = 0; + for(j = 0; j < aZones[i].m_indexStart; j++) + if(pTempArrayIndices[j] != 0xFFFF) + start++; + + aZones[i].m_indexStart = start; + aZones[i].m_numBuildings = 0; + aZones[i].m_numTreadablesPlus10m = 0; + aZones[i].m_numTreadables = 0; + + for(int k = 0; k < aZones[i].m_groupIndexCount[0]; k++) + if(pTempArrayIndices[j++] != 0xFFFF) + aZones[i].m_numBuildings++; + for(int k = 0; k < aZones[i].m_groupIndexCount[1]; k++) + if(pTempArrayIndices[j++] != 0xFFFF) + aZones[i].m_numTreadablesPlus10m++; + for(int k = 0; k < aZones[i].m_groupIndexCount[2]; k++) + if(pTempArrayIndices[j++] != 0xFFFF) + aZones[i].m_numTreadables++; + } + + // Now copy the actually used indices + EntityIndicesUsed = 0; + for(int i = 0; i < TempEntityIndicesUsed; i++) + if(pTempArrayIndices[i] != 0xFFFF){ + assert(EntityIndicesUsed < NUMZONEINDICES); + if(pTempArrayIndices[i] < NUMUNCOMPRESSED) + aIndices[EntityIndicesUsed++] = pTempArrayIndices[i]; + else + aIndices[EntityIndicesUsed++] = pTempArrayIndices[i] + numTempIndices; + } + for(int i = 0; i < numExtraIndices; i++) + if(extraIndices[i] != 0xFFFF){ + assert(EntityIndicesUsed < NUMZONEINDICES); + if(extraIndices[i] < NUMUNCOMPRESSED) + aIndices[EntityIndicesUsed++] = extraIndices[i]; + else + aIndices[EntityIndicesUsed++] = extraIndices[i] + numTempIndices; + } +} + + void CCullZone::DoStuffLeavingZone(void) @@ -403,13 +643,14 @@ CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i) int16 bb; int j; - if(i < 6000){ + + if(i < NUMUNCOMPRESSED){ CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false; bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; if(bb != -1) CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false; }else{ - i -= 6000; + i -= NUMUNCOMPRESSED; for(j = 0; j < 3; j++) DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]); } @@ -421,14 +662,14 @@ CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i) int16 bb; int j; - if(i < 6000){ + if(i < NUMUNCOMPRESSED){ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = false; CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = false; bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; if(bb != -1) CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false; }else{ - i -= 6000; + i -= NUMUNCOMPRESSED; for(j = 0; j < 3; j++) DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]); } @@ -453,13 +694,13 @@ CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i) int16 bb; int j; - if(i < 6000){ + if(i < NUMUNCOMPRESSED){ CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true; bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; if(bb != -1) CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; }else{ - i -= 6000; + i -= NUMUNCOMPRESSED; for(j = 0; j < 3; j++) DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[i+j]); } @@ -471,14 +712,14 @@ CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i) int16 bb; int j; - if(i < 6000){ + if(i < NUMUNCOMPRESSED){ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true; CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = true; bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; if(bb != -1) CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; }else{ - i -= 6000; + i -= NUMUNCOMPRESSED; for(j = 0; j < 3; j++) DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[i+j]); } @@ -490,13 +731,13 @@ CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i) int16 bb; int j; - if(i < 6000){ + if(i < NUMUNCOMPRESSED){ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true; bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; if(bb != -1) CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; }else{ - i -= 6000; + i -= NUMUNCOMPRESSED; for(j = 0; j < 3; j++) DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[i+j]); } @@ -518,6 +759,68 @@ CCullZone::CalcDistToCullZoneSquared(float x, float y) return rx + ry; } +bool +CCullZone::TestLine(CVector vec1, CVector vec2) +{ + CColPoint colPoint; + CEntity *entity; + + if (CWorld::ProcessLineOfSight(vec1, vec2, colPoint, entity, true, false, false, false, false, true, false)) + return true; + if (CWorld::ProcessLineOfSight(CVector(vec1.x + 0.05f, vec1.y, vec1.z), CVector(vec2.x + 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) + return true; + if (CWorld::ProcessLineOfSight(CVector(vec1.x - 0.05f, vec1.y, vec1.z), CVector(vec2.x - 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) + return true; + if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y + 0.05f, vec1.z), CVector(vec2.x, vec2.y + 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) + return true; + if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y - 0.05f, vec1.z), CVector(vec2.x, vec2.y - 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) + return true; + if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z + 0.05f), CVector(vec2.x, vec2.y, vec2.z + 0.05f), colPoint, entity, true, false, false, false, false, true, false)) + return true; + return CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z - 0.05f), CVector(vec2.x, vec2.y, vec2.z - 0.05f), colPoint, entity, true, false, false, false, false, true, false); +} + +bool +CCullZone::DoThoroughLineTest(CVector start, CVector end, CEntity *testEntity) +{ + CColPoint colPoint; + CEntity *entity; + + if(CWorld::ProcessLineOfSight(start, end, colPoint, entity, true, false, false, false, false, true, false) && + testEntity != entity) + return false; + + CVector side; +#ifdef FIX_BUGS + if(start.x != end.x || start.y != end.y) +#else + if(start.x != end.x && start.y != end.y) +#endif + side = CVector(0.0f, 0.0f, 1.0f); + else + side = CVector(1.0f, 0.0f, 0.0f); + CVector up = CrossProduct(side, end - start); + side = CrossProduct(up, end - start); + side.Normalise(); + up.Normalise(); + side *= 0.1f; + up *= 0.1f; + + if(CWorld::ProcessLineOfSight(start+side, end+side, colPoint, entity, true, false, false, false, false, true, false) && + testEntity != entity) + return false; + if(CWorld::ProcessLineOfSight(start-side, end-side, colPoint, entity, true, false, false, false, false, true, false) && + testEntity != entity) + return false; + if(CWorld::ProcessLineOfSight(start+up, end+up, colPoint, entity, true, false, false, false, false, true, false) && + testEntity != entity) + return false; + if(CWorld::ProcessLineOfSight(start-up, end-up, colPoint, entity, true, false, false, false, false, true, false) && + testEntity != entity) + return false; + return true; +} + bool CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel) { @@ -526,10 +829,10 @@ CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel) CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex()); float distToZone = CalcDistToCullZone(pos.x, pos.y); float lodDist; - if (minfo->m_isSubway) - lodDist = minfo->GetLargestLodDistance() + 30.0f; + if (minfo->m_noFade) + lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE; else - lodDist = minfo->GetLargestLodDistance() + 50.0f; + lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE + FADE_DISTANCE; if (lodDist > distToZone) return true; if (!checkLevel) return false; @@ -538,27 +841,749 @@ CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel) } bool -CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set) +CCullZone::PointFallsWithinZone(CVector pos, float radius) { - int32 curCount; - int32 start; - int32 size; + if(minx - radius > pos.x || + maxx + radius < pos.x || + miny - radius > pos.y || + maxy + radius < pos.y || + minz - radius > pos.z || + maxz + radius < pos.z) + return false; + return true; +} - for (int i = 0; i < NumCullZones; i++) { - curCount = 0; - for (int group = 0; group < 3; group++) { - aZones[i].GetGroupStartAndSize(group, start, size); - int unk = 0; // TODO: figure out - for (int j = 0; j < size; j++) { - for (int k = 0; k < 3; k++) { - if (set[k] == pTempArrayIndices[start+j]) - unk++; +CVector ExtraFudgePointsCoors[] = { + CVector(978.0, -394.0, 18.0), + CVector(1189.7, -414.6, 27.0), + CVector(978.8, -391.0, 19.0), + CVector(1199.0, -502.3, 28.0), + CVector(1037.0, -391.9, 18.4), + CVector(1140.0, -608.7, 16.0), + CVector(1051.0, -26.0, 11.0), + CVector(951.5, -345.1, 12.0), + CVector(958.2, -394.6, 16.0), + CVector(1036.5, -390.0, 15.2), + CVector(960.6, -390.5, 20.9), + CVector(1061.0, -640.6, 16.3), + CVector(1034.5, -388.96, 14.78), + CVector(1038.4, -13.98, 12.2), + CVector(1047.2, -16.7, 10.6), + CVector(1257.9, -333.3, 40.0), + CVector(885.6, -424.9, 17.0), + CVector(1127.5, -795.8, 17.7), + CVector(1133.0, -716.0, 19.0), + CVector(1125.0, -694.0, 18.5), + CVector(1125.0, -670.0, 16.3), + CVector(1051.6, 36.3, 17.9), + CVector(1054.6, -11.4, 15.0), + CVector(1058.9, -278.0, 15.0), + CVector(1059.4, -261.0, 10.9), + CVector(1051.5, -638.5, 16.5), + CVector(1058.2, -643.4, 15.5), + CVector(1058.2, -643.4, 18.0), + CVector(826.0, -260.0, 7.0), + CVector(826.0, -260.0, 11.0), + CVector(833.0, -603.6, 16.4), + CVector(833.0, -603.6, 20.0), + CVector(1002.0, -318.5, 10.5), + CVector(998.0, -318.0, 9.8), + CVector(1127.0, -183.0, 18.1), + CVector(1123.0, -331.5, 23.8), + CVector(1123.8, -429.0, 24.0), + CVector(1197.0, -30.0, 13.7), + CVector(1117.5, -230.0, 17.3), + CVector(1117.5, -230.0, 20.0), + CVector(1120.0, -281.6, 21.5), + CVector(1120.0, -281.6, 24.0), + CVector(1084.5, -1022.7, 17.0), + CVector(1071.5, 5.4, 4.6), + CVector(1177.2, -215.7, 27.6), + CVector(841.6, -460.0, 19.7), + CVector(874.8, -456.6, 16.6), + CVector(918.3, -451.8, 17.8), + CVector(844.0, -495.7, 16.7), + CVector(842.0, -493.4, 21.0), + CVector(1433.5, -774.4, 16.9), + CVector(1051.0, -205.0, 7.5), + CVector(885.5, -425.6, 15.6), + CVector(182.6, -470.4, 27.8), + CVector(132.5, -930.2, 29.0), + CVector(124.7, -904.0, 28.0), + CVector(-50.0, -686.0, 22.0), + CVector(-49.1, -694.5, 22.5), + CVector(1063.8, -404.45, 16.2), + CVector(1062.2, -405.5, 17.0) +}; +int32 NumTestPoints; +int32 aTestPointsX[100]; +int32 aTestPointsY[100]; +int32 aTestPointsZ[100]; +CVector aTestPoints[100]; +int32 ElementsX, ElementsY, ElementsZ; +float StepX, StepY, StepZ; +int32 Memsize; +uint8 *pMem; +#define MEM(x, y, z) pMem[((x)*ElementsY + (y))*ElementsZ + (z)] +#define FLAG_FREE 1 +#define FLAG_PROCESSED 2 + +int32 MinValX, MaxValX; +int32 MinValY, MaxValY; +int32 MinValZ, MaxValZ; +int32 Point1, Point2; +int32 NewPointX, NewPointY, NewPointZ; + + +void +CCullZone::FindTestPoints() +{ + static int CZNumber; + + NumTestPoints = 0; + ElementsX = (maxx-minx) < 1.0f ? 2 : (maxx-minx)+1.0f; + ElementsY = (maxy-miny) < 1.0f ? 2 : (maxy-miny)+1.0f; + ElementsZ = (maxz-minz) < 1.0f ? 2 : (maxz-minz)+1.0f; + if(ElementsX > 32) ElementsX = 32; + if(ElementsY > 32) ElementsY = 32; + if(ElementsZ > 32) ElementsZ = 32; + Memsize = ElementsX * ElementsY * ElementsZ; + StepX = (maxx-minx)/(ElementsX-1); + StepY = (maxy-miny)/(ElementsY-1); + StepZ = (maxz-minz)/(ElementsZ-1); + + pMem = new uint8[Memsize]; + memset(pMem, 0, Memsize); + + // indices of center + int x = ElementsX * (position.x-minx)/(maxx-minx); + x = clamp(x, 0, ElementsX-1); + int y = ElementsY * (position.y-miny)/(maxy-miny); + y = clamp(y, 0, ElementsY-1); + int z = ElementsZ * (position.z-minz)/(maxz-minz); + z = clamp(z, 0, ElementsZ-1); + + // Mark which test points inside the zone are not occupied by buildings. + // To do this, mark the start point as free and do a food fill. + + // NB: we just assume the start position is free here! + MEM(x, y, z) |= FLAG_FREE; + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + NumTestPoints++; + + bool notDoneYet; + do{ + notDoneYet = false; + for(x = 0; x < ElementsX; x++){ + for(y = 0; y < ElementsY; y++){ + for(z = 0; z < ElementsZ; z++){ + if(!(MEM(x, y, z) & FLAG_FREE) || MEM(x, y, z) & FLAG_PROCESSED) + continue; + + float pX = x*StepX + minx; + float pY = y*StepY + miny; + float pZ = z*StepZ + minz; + + if(x > 0 && !(MEM(x-1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) && + !TestLine(CVector(pX, pY, pZ), CVector(pX-StepX, pY, pZ))) + MEM(x-1, y, z) |= FLAG_FREE; + if(x < ElementsX-1 && !(MEM(x+1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) && + !TestLine(CVector(pX, pY, pZ), CVector(pX+StepX, pY, pZ))) + MEM(x+1, y, z) |= FLAG_FREE; + + if(y > 0 && !(MEM(x, y-1, z) & (FLAG_FREE | FLAG_PROCESSED)) && + !TestLine(CVector(pX, pY, pZ), CVector(pX, pY-StepY, pZ))) + MEM(x, y-1, z) |= FLAG_FREE; + if(y < ElementsY-1 && !(MEM(x, y+1, z) & (FLAG_FREE | FLAG_PROCESSED)) && + !TestLine(CVector(pX, pY, pZ), CVector(pX, pY+StepY, pZ))) + MEM(x, y+1, z) |= FLAG_FREE; + + if(z > 0 && !(MEM(x, y, z-1) & (FLAG_FREE | FLAG_PROCESSED)) && + !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ-StepZ))) + MEM(x, y, z-1) |= FLAG_FREE; + if(z < ElementsZ-1 && !(MEM(x, y, z+1) & (FLAG_FREE | FLAG_PROCESSED)) && + !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ+StepZ))) + MEM(x, y, z+1) |= FLAG_FREE; + + notDoneYet = true; + MEM(x, y, z) |= FLAG_PROCESSED; + } + } + } + }while(notDoneYet); + + bool done; + + // Find bound planes of free space + + // increase x, bounds in y and z + x = 0; + do{ + done = false; + int minA = 10000; + int minB = 10000; + int maxA = -10000; + int maxB = -10000; + for(y = 0; y < ElementsY; y++) + for(z = 0; z < ElementsZ; z++) + if(MEM(x, y, z) & FLAG_FREE){ + if(y + z < minA){ + minA = y + z; + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + } + if(y + z > maxA){ + maxA = y + z; + aTestPointsX[NumTestPoints+1] = x; + aTestPointsY[NumTestPoints+1] = y; + aTestPointsZ[NumTestPoints+1] = z; + } + if(y - z < minB){ + minB = y - z; + aTestPointsX[NumTestPoints+2] = x; + aTestPointsY[NumTestPoints+2] = y; + aTestPointsZ[NumTestPoints+2] = z; + } + if(y - z > maxB){ + maxB = y - z; + aTestPointsX[NumTestPoints+3] = x; + aTestPointsY[NumTestPoints+3] = y; + aTestPointsZ[NumTestPoints+3] = z; + } + done = true; + } + x++; + }while(!done); + NumTestPoints += 4; + + // decrease x, bounds in y and z + x = ElementsX-1; + do{ + done = false; + int minA = 10000; + int minB = 10000; + int maxA = -10000; + int maxB = -10000; + for(y = 0; y < ElementsY; y++) + for(z = 0; z < ElementsZ; z++) + if(MEM(x, y, z) & FLAG_FREE){ + if(y + z < minA){ + minA = y + z; + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + } + if(y + z > maxA){ + maxA = y + z; + aTestPointsX[NumTestPoints+1] = x; + aTestPointsY[NumTestPoints+1] = y; + aTestPointsZ[NumTestPoints+1] = z; + } + if(y - z < minB){ + minB = y - z; + aTestPointsX[NumTestPoints+2] = x; + aTestPointsY[NumTestPoints+2] = y; + aTestPointsZ[NumTestPoints+2] = z; + } + if(y - z > maxB){ + maxB = y - z; + aTestPointsX[NumTestPoints+3] = x; + aTestPointsY[NumTestPoints+3] = y; + aTestPointsZ[NumTestPoints+3] = z; + } + done = true; + } + x--; + }while(!done); + NumTestPoints += 4; + + // increase y, bounds in x and z + y = 0; + do{ + done = false; + int minA = 10000; + int minB = 10000; + int maxA = -10000; + int maxB = -10000; + for(x = 0; x < ElementsX; x++) + for(z = 0; z < ElementsZ; z++) + if(MEM(x, y, z) & FLAG_FREE){ + if(x + z < minA){ + minA = x + z; + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + } + if(x + z > maxA){ + maxA = x + z; + aTestPointsX[NumTestPoints+1] = x; + aTestPointsY[NumTestPoints+1] = y; + aTestPointsZ[NumTestPoints+1] = z; + } + if(x - z < minB){ + minB = x - z; + aTestPointsX[NumTestPoints+2] = x; + aTestPointsY[NumTestPoints+2] = y; + aTestPointsZ[NumTestPoints+2] = z; + } + if(x - z > maxB){ + maxB = x - z; + aTestPointsX[NumTestPoints+3] = x; + aTestPointsY[NumTestPoints+3] = y; + aTestPointsZ[NumTestPoints+3] = z; + } + done = true; + } + y++; + }while(!done); + NumTestPoints += 4; + + // decrease y, bounds in x and z + y = ElementsY-1; + do{ + done = false; + int minA = 10000; + int minB = 10000; + int maxA = -10000; + int maxB = -10000; + for(x = 0; x < ElementsX; x++) + for(z = 0; z < ElementsZ; z++) + if(MEM(x, y, z) & FLAG_FREE){ + if(x + z < minA){ + minA = x + z; + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + } + if(x + z > maxA){ + maxA = x + z; + aTestPointsX[NumTestPoints+1] = x; + aTestPointsY[NumTestPoints+1] = y; + aTestPointsZ[NumTestPoints+1] = z; + } + if(x - z < minB){ + minB = x - z; + aTestPointsX[NumTestPoints+2] = x; + aTestPointsY[NumTestPoints+2] = y; + aTestPointsZ[NumTestPoints+2] = z; + } + if(x - z > maxB){ + maxB = x - z; + aTestPointsX[NumTestPoints+3] = x; + aTestPointsY[NumTestPoints+3] = y; + aTestPointsZ[NumTestPoints+3] = z; + } + done = true; } + y--; + }while(!done); + NumTestPoints += 4; + + // increase z, bounds in x and y + z = 0; + do{ + done = false; + int minA = 10000; + int minB = 10000; + int maxA = -10000; + int maxB = -10000; + for(x = 0; x < ElementsX; x++) + for(y = 0; y < ElementsY; y++) + if(MEM(x, y, z) & FLAG_FREE){ + if(x + y < minA){ + minA = x + y; + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + } + if(x + y > maxA){ + maxA = x + y; + aTestPointsX[NumTestPoints+1] = x; + aTestPointsY[NumTestPoints+1] = y; + aTestPointsZ[NumTestPoints+1] = z; + } + if(x - y < minB){ + minB = x - y; + aTestPointsX[NumTestPoints+2] = x; + aTestPointsY[NumTestPoints+2] = y; + aTestPointsZ[NumTestPoints+2] = z; + } + if(x - y > maxB){ + maxB = x - y; + aTestPointsX[NumTestPoints+3] = x; + aTestPointsY[NumTestPoints+3] = y; + aTestPointsZ[NumTestPoints+3] = z; + } + done = true; + } + z++; + }while(!done); + NumTestPoints += 4; + + // decrease z, bounds in x and y + z = ElementsZ-1; + do{ + done = false; + int minA = 10000; + int minB = 10000; + int maxA = -10000; + int maxB = -10000; + for(x = 0; x < ElementsX; x++) + for(y = 0; y < ElementsY; y++) + if(MEM(x, y, z) & FLAG_FREE){ + if(x + y < minA){ + minA = x + y; + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + } + if(x + y > maxA){ + maxA = x + y; + aTestPointsX[NumTestPoints+1] = x; + aTestPointsY[NumTestPoints+1] = y; + aTestPointsZ[NumTestPoints+1] = z; + } + if(x - y < minB){ + minB = x - y; + aTestPointsX[NumTestPoints+2] = x; + aTestPointsY[NumTestPoints+2] = y; + aTestPointsZ[NumTestPoints+2] = z; + } + if(x - y > maxB){ + maxB = x - y; + aTestPointsX[NumTestPoints+3] = x; + aTestPointsY[NumTestPoints+3] = y; + aTestPointsZ[NumTestPoints+3] = z; + } + done = true; + } + z--; + }while(!done); + NumTestPoints += 4; + + // divide the axis aligned bounding planes into 4 and place some test points + + // x = 0 plane + MinValY = 999999; + MinValZ = 999999; + MaxValY = 0; + MaxValZ = 0; + for(y = 0; y < ElementsY; y++) + for(z = 0; z < ElementsZ; z++) + if(MEM(0, y, z) & FLAG_FREE){ + if(y < MinValY) MinValY = y; + if(z < MinValZ) MinValZ = z; + if(y > MaxValY) MaxValY = y; + if(z > MaxValZ) MaxValZ = z; + } + // pick 4 points in the found bounds and add new test points + if(MaxValY != 0 && MaxValZ != 0) + for(Point1 = 0; Point1 < 2; Point1++) + for(Point2 = 0; Point2 < 2; Point2++){ + NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; + NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; + if(MEM(0, NewPointY, NewPointZ) & FLAG_FREE){ + aTestPointsX[NumTestPoints] = 0; + aTestPointsY[NumTestPoints] = NewPointY; + aTestPointsZ[NumTestPoints] = NewPointZ; + NumTestPoints++; + } + } + + // x = ElementsX-1 plane + MinValY = 999999; + MinValZ = 999999; + MaxValY = 0; + MaxValZ = 0; + for(y = 0; y < ElementsY; y++) + for(z = 0; z < ElementsZ; z++) + if(MEM(ElementsX-1, y, z) & FLAG_FREE){ + if(y < MinValY) MinValY = y; + if(z < MinValZ) MinValZ = z; + if(y > MaxValY) MaxValY = y; + if(z > MaxValZ) MaxValZ = z; + } + // pick 4 points in the found bounds and add new test points + if(MaxValY != 0 && MaxValZ != 0) + for(Point1 = 0; Point1 < 2; Point1++) + for(Point2 = 0; Point2 < 2; Point2++){ + NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; + NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; + if(MEM(ElementsX-1, NewPointY, NewPointZ) & FLAG_FREE){ + aTestPointsX[NumTestPoints] = ElementsX-1; + aTestPointsY[NumTestPoints] = NewPointY; + aTestPointsZ[NumTestPoints] = NewPointZ; + NumTestPoints++; + } + } + + // y = 0 plane + MinValX = 999999; + MinValZ = 999999; + MaxValX = 0; + MaxValZ = 0; + for(x = 0; x < ElementsX; x++) + for(z = 0; z < ElementsZ; z++) + if(MEM(x, 0, z) & FLAG_FREE){ + if(x < MinValX) MinValX = x; + if(z < MinValZ) MinValZ = z; + if(x > MaxValX) MaxValX = x; + if(z > MaxValZ) MaxValZ = z; + } + // pick 4 points in the found bounds and add new test points + if(MaxValX != 0 && MaxValZ != 0) + for(Point1 = 0; Point1 < 2; Point1++) + for(Point2 = 0; Point2 < 2; Point2++){ + NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; + NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; + if(MEM(NewPointX, 0, NewPointZ) & FLAG_FREE){ + aTestPointsX[NumTestPoints] = NewPointX; + aTestPointsY[NumTestPoints] = 0; + aTestPointsZ[NumTestPoints] = NewPointZ; + NumTestPoints++; + } + } + + // y = ElementsY-1 plane + MinValX = 999999; + MinValZ = 999999; + MaxValX = 0; + MaxValZ = 0; + for(x = 0; x < ElementsX; x++) + for(z = 0; z < ElementsZ; z++) + if(MEM(x, ElementsY-1, z) & FLAG_FREE){ + if(x < MinValX) MinValX = x; + if(z < MinValZ) MinValZ = z; + if(x > MaxValX) MaxValX = x; + if(z > MaxValZ) MaxValZ = z; + } + // pick 4 points in the found bounds and add new test points + if(MaxValX != 0 && MaxValZ != 0) + for(Point1 = 0; Point1 < 2; Point1++) + for(Point2 = 0; Point2 < 2; Point2++){ + NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; + NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; + if(MEM(NewPointX, ElementsY-1, NewPointZ) & FLAG_FREE){ + aTestPointsX[NumTestPoints] = NewPointX; + aTestPointsY[NumTestPoints] = ElementsY-1; + aTestPointsZ[NumTestPoints] = NewPointZ; + NumTestPoints++; + } + } + + // z = 0 plane + MinValX = 999999; + MinValY = 999999; + MaxValX = 0; + MaxValY = 0; + for(x = 0; x < ElementsX; x++) + for(y = 0; y < ElementsY; y++) + if(MEM(x, y, 0) & FLAG_FREE){ + if(x < MinValX) MinValX = x; + if(y < MinValY) MinValY = y; + if(x > MaxValX) MaxValX = x; + if(y > MaxValY) MaxValY = y; + } + // pick 4 points in the found bounds and add new test points + if(MaxValX != 0 && MaxValY != 0) + for(Point1 = 0; Point1 < 2; Point1++) + for(Point2 = 0; Point2 < 2; Point2++){ + NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; + NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; + if(MEM(NewPointX, NewPointY, 0) & FLAG_FREE){ + aTestPointsX[NumTestPoints] = NewPointX; + aTestPointsY[NumTestPoints] = NewPointY; + aTestPointsZ[NumTestPoints] = 0; + NumTestPoints++; + } + } + + // z = ElementsZ-1 plane + MinValX = 999999; + MinValY = 999999; + MaxValX = 0; + MaxValY = 0; + for(x = 0; x < ElementsX; x++) + for(y = 0; y < ElementsY; y++) + if(MEM(x, y, ElementsZ-1) & FLAG_FREE){ + if(x < MinValX) MinValX = x; + if(y < MinValY) MinValY = y; + if(x > MaxValX) MaxValX = x; + if(y > MaxValY) MaxValY = y; + } + // pick 4 points in the found bounds and add new test points + if(MaxValX != 0 && MaxValY != 0) + for(Point1 = 0; Point1 < 2; Point1++) + for(Point2 = 0; Point2 < 2; Point2++){ + NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; + NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; + if(MEM(NewPointX, NewPointY, ElementsZ-1) & FLAG_FREE){ + aTestPointsX[NumTestPoints] = NewPointX; + aTestPointsY[NumTestPoints] = NewPointY; + aTestPointsZ[NumTestPoints] = ElementsZ-1; + NumTestPoints++; + } + } + + // add some hardcoded test points + for(int i = 0; i < ARRAY_SIZE(ExtraFudgePointsCoors); i++) + if(PointFallsWithinZone(ExtraFudgePointsCoors[i], 0.0f)){ + x = ElementsX * (ExtraFudgePointsCoors[i].x-minx)/(maxx-minx); + y = ElementsY * (ExtraFudgePointsCoors[i].y-miny)/(maxy-miny); + z = ElementsZ * (ExtraFudgePointsCoors[i].z-minz)/(maxz-minz); + if(MEM(x, y, z) & FLAG_FREE){ + aTestPointsX[NumTestPoints] = x; + aTestPointsY[NumTestPoints] = y; + aTestPointsZ[NumTestPoints] = z; + NumTestPoints++; + } + } + + // remove duplicate points + for(int i = 0; i < NumTestPoints; i++) + for(int j = i+1; j < NumTestPoints; j++) + if(aTestPointsX[j] == aTestPointsX[i] && + aTestPointsY[j] == aTestPointsY[i] && + aTestPointsZ[j] == aTestPointsZ[i]){ + // get rid of [j] + for(int k = j; k < NumTestPoints-1; k++){ + aTestPointsX[k] = aTestPointsX[k+1]; + aTestPointsY[k] = aTestPointsY[k+1]; + aTestPointsZ[k] = aTestPointsZ[k+1]; + } + NumTestPoints--; + } + + // convert points to floating point + for(int i = 0; i < NumTestPoints; i++){ + aTestPoints[i].x = aTestPointsX[i]*StepX + minx; + aTestPoints[i].y = aTestPointsY[i]*StepY + miny; + aTestPoints[i].z = aTestPointsZ[i]*StepZ + minz; + } + + CZNumber++; + + delete[] pMem; + pMem = nil; +} + +bool +CCullZone::TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity) +{ + CColModel *colmodel = entity->GetColModel(); + float boundMaxX = colmodel->boundingBox.max.x; + float boundMaxY = colmodel->boundingBox.max.y; + float boundMaxZ = colmodel->boundingBox.max.z; + float boundMinX = colmodel->boundingBox.min.x; + float boundMinY = colmodel->boundingBox.min.y; + float boundMinZ = colmodel->boundingBox.min.z; + if(LODentity){ + colmodel = LODentity->GetColModel(); + boundMaxX = Max(boundMaxX, colmodel->boundingBox.max.x); + boundMaxY = Max(boundMaxY, colmodel->boundingBox.max.y); + boundMaxZ = Max(boundMaxZ, colmodel->boundingBox.max.z); + boundMinX = Min(boundMinX, colmodel->boundingBox.min.x); + boundMinY = Min(boundMinY, colmodel->boundingBox.min.y); + boundMinZ = Min(boundMinZ, colmodel->boundingBox.min.z); + } + + if(boundMaxZ-boundMinZ + extraDist < 0.5f) + boundMaxZ = boundMinZ + 0.5f; + else + boundMaxZ += extraDist; + + CVector vecMin = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMinZ); + CVector vecMaxX = entity->GetMatrix() * CVector(boundMaxX, boundMinY, boundMinZ); + CVector vecMaxY = entity->GetMatrix() * CVector(boundMinX, boundMaxY, boundMinZ); + CVector vecMaxZ = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMaxZ); + CVector dirx = vecMaxX - vecMin; + CVector diry = vecMaxY - vecMin; + CVector dirz = vecMaxZ - vecMin; + + // If building intersects zone at all, it's visible + int x, y, z; + for(x = 0; x < 9; x++){ + CVector posX = vecMin + x/8.0f*dirx; + for(y = 0; y < 9; y++){ + CVector posY = posX + y/8.0f*diry; + for(z = 0; z < 9; z++){ + CVector posZ = posY + z/8.0f*dirz; + if(PointFallsWithinZone(posZ, 2.0f)) + return true; } - if (unk == 3 && ++curCount >= count) - return true; } } + + float distToZone = CalcDistToCullZone(entity->GetPosition().x, entity->GetPosition().y)/15.0f; + distToZone = Max(distToZone, 7.0f); + int numX = (boundMaxX - boundMinX)/distToZone + 2.0f; + int numY = (boundMaxY - boundMinY)/distToZone + 2.0f; + int numZ = (boundMaxZ - boundMinZ)/distToZone + 2.0f; + + float stepX = 1.0f/(numX-1); + float stepY = 1.0f/(numY-1); + float stepZ = 1.0f/(numZ-1); + float midX = (boundMaxX + boundMinX)/2.0f; + float midY = (boundMaxY + boundMinY)/2.0f; + float midZ = (boundMaxZ + boundMinZ)/2.0f; + + // check both xy planes + for(int i = 0; i < NumTestPoints; i++){ + CVector testPoint = aTestPoints[i]; + CVector mid = entity->GetMatrix() * CVector(midX, midY, midZ); + mid.z += 0.1f; + if(DoThoroughLineTest(testPoint, mid, entity)) + return true; + + CVector ray = entity->GetPosition() - testPoint; + + float dotX = DotProduct(ray, dirx); + float dotY = DotProduct(ray, diry); + float dotZ = DotProduct(ray, dirz); + + for(x = 0; x < numX; x++){ + CVector pMinZ = vecMin + x*stepX*dirx; + CVector pMaxZ = vecMin + x*stepX*dirx + dirz; + for(y = 0; y < numY; y++) + if(dotZ > 0.0f){ + if(DoThoroughLineTest(testPoint, pMinZ + y*stepY*diry, entity)) + return true; + }else{ + if(DoThoroughLineTest(testPoint, pMaxZ + y*stepY*diry, entity)) + return true; + } + } + + for(x = 0; x < numX; x++){ + CVector pMinY = vecMin + x*stepX*dirx; + CVector pMaxY = vecMin + x*stepX*dirx + diry; + for(z = 1; z < numZ-1; z++) // edge cases already handled + if(dotY > 0.0f){ + if(DoThoroughLineTest(testPoint, pMinY + z*stepZ*dirz, entity)) + return true; + }else{ + if(DoThoroughLineTest(testPoint, pMaxY + z*stepZ*dirz, entity)) + return true; + } + } + + for(y = 1; y < numY-1; y++){ // edge cases already handled + CVector pMinX = vecMin + y*stepY*diry; + CVector pMaxX = vecMin + y*stepY*diry + dirx; + for(z = 1; z < numZ-1; z++) // edge cases already handled + if(dotX > 0.0f){ + if(DoThoroughLineTest(testPoint, pMinX + z*stepZ*dirz, entity)) + return true; + }else{ + if(DoThoroughLineTest(testPoint, pMaxX + z*stepZ*dirz, entity)) + return true; + } + } + } + return false; } diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h index 9bc07b8c..10742ffb 100644 --- a/src/core/ZoneCull.h +++ b/src/core/ZoneCull.h @@ -12,7 +12,7 @@ public: float maxz; int32 m_indexStart; - int16 m_groupIndexCount[3]; + int16 m_groupIndexCount[3]; // only useful during resolution stage int16 m_numBuildings; int16 m_numTreadablesPlus10m; int16 m_numTreadables; @@ -26,30 +26,35 @@ public: static void DoStuffEnteringZone_OneTreadable(uint16 i); - static bool TestLine(CVector a1, CVector a2); + static bool TestLine(CVector vec1, CVector vec2); + static bool DoThoroughLineTest(CVector vec1, CVector vec2, CEntity *testEntity); float CalcDistToCullZoneSquared(float x, float y); float CalcDistToCullZone(float x, float y) { return Sqrt(CalcDistToCullZoneSquared(x, y)); }; bool IsEntityCloseEnoughToZone(CEntity* entity, bool checkLevel); + bool PointFallsWithinZone(CVector pos, float radius); + bool TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity); + void FindTestPoints(); void GetGroupStartAndSize(int32 groupid, int32 &start, int32 &size) { switch (groupid) { + case 0: + default: + // buildings + start = m_indexStart; + size = m_groupIndexCount[0]; + break; case 1: + // treadables + 10m start = m_groupIndexCount[0] + m_indexStart; size = m_groupIndexCount[1]; break; case 2: + // treadables start = m_groupIndexCount[0] + m_groupIndexCount[1] + m_indexStart; size = m_groupIndexCount[2]; break; - default: - start = m_indexStart; - size = m_groupIndexCount[0]; - break; } } - - void FindTestPoints() {}; // todo - bool TestEntityVisibilityFromCullZone(CEntity*, float, CEntity*) { return false; }; // todo }; enum eZoneAttribs @@ -121,5 +126,12 @@ public: static void DoVisibilityTestCullZone(int zoneId, bool doIt); static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set); - static void CompressIndicesArray() {};// todo + static void CompressIndicesArray(); + static bool PickRandomSetForGroup(int32 zone, int32 group, uint16 *set); + static void ReplaceSetForAllGroups(uint16 *set, uint16 setid); + static void TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices); + + // debug + static bool LoadTempFile(void); + static void SaveTempFile(void); }; diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 194f75fa..ee747218 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -565,6 +565,9 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Render", "Don't render Objects", &gbDontRenderObjects, nil); DebugMenuAddVarBool8("Render", "Don't Render Water", &gbDontRenderWater, nil); + DebugMenuAddVarBool8("Debug", "Show cullzone debug stuff", &gbShowCullZoneDebugStuff, nil); + DebugMenuAddVarBool8("Debug", "Disable zone cull", &gbDisableZoneCull, nil); + DebugMenuAddVarBool8("Debug", "pad 1 -> pad 2", &CPad::m_bMapPadOneToPadTwo, nil); DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil); #ifdef MENU_MAP diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 92bbdd45..ee6ba58a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -21,12 +21,14 @@ #include "Renderer.h" #include "Frontend.h" #include "custompipes.h" +#include "Debug.h" bool gbShowPedRoadGroups; bool gbShowCarRoadGroups; bool gbShowCollisionPolys; bool gbShowCollisionLines; bool gbShowCullZoneDebugStuff; +bool gbDisableZoneCull; // not original bool gbBigWhiteDebugLightSwitchedOn; bool gbDontRenderBuildings; @@ -35,6 +37,25 @@ bool gbDontRenderPeds; bool gbDontRenderObjects; bool gbDontRenderVehicles; +int32 EntitiesRendered; +int32 EntitiesNotRendered; +int32 RenderedBigBuildings; +int32 RenderedBuildings; +int32 RenderedCars; +int32 RenderedPeds; +int32 RenderedObjects; +int32 RenderedDummies; +int32 TestedBigBuildings; +int32 TestedBuildings; +int32 TestedCars; +int32 TestedPeds; +int32 TestedObjects; +int32 TestedDummies; + +// unused +int16 TestCloseThings; +int16 TestBigThings; + struct EntityInfo { CEntity *ent; @@ -61,6 +82,11 @@ float CRenderer::ms_lodDistScale = 1.2f; #define BACKFACE_CULLING_OFF #endif +// unused +BlockedRange CRenderer::aBlockedRanges[16]; +BlockedRange *CRenderer::pFullBlockedRanges; +BlockedRange *CRenderer::pEmptyBlockedRanges; + void CRenderer::Init(void) { @@ -347,6 +373,14 @@ CRenderer::RenderCollisionLines(void) } } +// unused +void +CRenderer::RenderBlockBuildingLines(void) +{ + for(BlockedRange *br = pFullBlockedRanges; br; br = br->next) + printf("Blocked: %f %f\n", br->a, br->b); +} + enum Visbility { VIS_INVISIBLE, @@ -355,14 +389,6 @@ enum Visbility VIS_STREAMME }; -#ifdef FIX_BUGS -#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier) -#else -#define LOD_DISTANCE 300.0f -#endif -#define FADE_DISTANCE 20.0f -#define STREAM_DISTANCE 30.0f - // Time Objects can be time culled if // other == -1 || CModelInfo::GetModelInfo(other)->GetRwObject() // i.e. we have to draw even at the wrong time if @@ -611,7 +637,21 @@ CRenderer::ConstructRenderList(void) ms_nNoOfVisibleEntities = 0; ms_nNoOfInVisibleEntities = 0; ms_vecCameraPosition = TheCamera.GetPosition(); - // TODO: blocked ranges, but unused + + // unused + pFullBlockedRanges = nil; + pEmptyBlockedRanges = aBlockedRanges; + for(int i = 0; i < 16; i++){ + aBlockedRanges[i].prev = &aBlockedRanges[i-1]; + aBlockedRanges[i].next = &aBlockedRanges[i+1]; + } + aBlockedRanges[0].prev = nil; + aBlockedRanges[15].next = nil; + + // unused + TestCloseThings = 0; + TestBigThings = 0; + ScanWorld(); } @@ -647,6 +687,24 @@ CRenderer::ScanWorld(void) RwMatrix *cammatrix; RwV2d poly[3]; +#ifndef MASTER + // missing in game but has to be done somewhere + EntitiesRendered = 0; + EntitiesNotRendered = 0; + RenderedBigBuildings = 0; + RenderedBuildings = 0; + RenderedCars = 0; + RenderedPeds = 0; + RenderedObjects = 0; + RenderedDummies = 0; + TestedBigBuildings = 0; + TestedBuildings = 0; + TestedCars = 0; + TestedPeds = 0; + TestedObjects = 0; + TestedDummies = 0; +#endif + memset(vectors, 0, sizeof(vectors)); vectors[CORNER_FAR_TOPLEFT].x = -vw.x * f; vectors[CORNER_FAR_TOPLEFT].y = vw.y * f; @@ -765,6 +823,19 @@ CRenderer::ScanWorld(void) ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC)); } } + +#ifndef MASTER + if(gbShowCullZoneDebugStuff){ + sprintf(gString, "Rejected: %d/%d.", EntitiesNotRendered, EntitiesNotRendered + EntitiesRendered); + CDebug::PrintAt(gString, 10, 10); + sprintf(gString, "Tested:BBuild:%d Build:%d Peds:%d Cars:%d Obj:%d Dummies:%d", + TestedBigBuildings, TestedBuildings, TestedPeds, TestedCars, TestedObjects, TestedDummies); + CDebug::PrintAt(gString, 10, 11); + sprintf(gString, "Rendered:BBuild:%d Build:%d Peds:%d Cars:%d Obj:%d Dummies:%d", + RenderedBigBuildings, RenderedBuildings, RenderedPeds, RenderedCars, RenderedObjects, RenderedDummies); + CDebug::PrintAt(gString, 10, 12); + } +#endif } void @@ -1014,8 +1085,20 @@ CRenderer::ScanBigBuildingList(CPtrList &list) for(node = list.first; node; node = node->next){ ent = (CEntity*)node->item; - if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == VIS_VISIBLE) - ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; +#ifndef MASTER + // all missing from game actually + TestedBigBuildings++; +#endif + if(!ent->bZoneCulled){ + if(SetupBigBuildingVisibility(ent) == VIS_VISIBLE) + ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; +#ifndef MASTER + EntitiesRendered++; + RenderedBigBuildings++; + }else{ + EntitiesNotRendered++; +#endif + } } } @@ -1036,7 +1119,7 @@ CRenderer::ScanSectorList(CPtrList *lists) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); - if(IsEntityCullZoneVisible(ent)) + if(IsEntityCullZoneVisible(ent)){ switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; @@ -1059,11 +1142,37 @@ CRenderer::ScanSectorList(CPtrList *lists) CStreaming::RequestModel(ent->GetModelIndex(), 0); break; } - else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){ - if(!CStreaming::ms_disableStreaming) - if(SetupEntityVisibility(ent) == VIS_STREAMME) - if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) - CStreaming::RequestModel(ent->GetModelIndex(), 0); +#ifndef MASTER + EntitiesRendered++; + switch(ent->GetType()){ + case ENTITY_TYPE_BUILDING: + if(ent->bIsBIGBuilding) + RenderedBigBuildings++; + else + RenderedBuildings++; + break; + case ENTITY_TYPE_VEHICLE: + RenderedCars++; + break; + case ENTITY_TYPE_PED: + RenderedPeds++; + break; + case ENTITY_TYPE_OBJECT: + RenderedObjects++; + break; + case ENTITY_TYPE_DUMMY: + RenderedDummies++; + break; + } +#endif + }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){ + if(SetupEntityVisibility(ent) == VIS_STREAMME) + if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) + CStreaming::RequestModel(ent->GetModelIndex(), 0); + }else{ +#ifndef MASTER + EntitiesNotRendered++; +#endif } } } @@ -1086,7 +1195,7 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); - if(IsEntityCullZoneVisible(ent)) + if(IsEntityCullZoneVisible(ent)){ switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; @@ -1111,10 +1220,38 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists) } break; } - else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){ - if(!CStreaming::ms_disableStreaming) - if(SetupEntityVisibility(ent) == VIS_STREAMME) - CStreaming::RequestModel(ent->GetModelIndex(), 0); +#ifndef MASTER + // actually missing in game + EntitiesRendered++; + switch(ent->GetType()){ + case ENTITY_TYPE_BUILDING: + if(ent->bIsBIGBuilding) + RenderedBigBuildings++; + else + RenderedBuildings++; + break; + case ENTITY_TYPE_VEHICLE: + RenderedCars++; + break; + case ENTITY_TYPE_PED: + RenderedPeds++; + break; + case ENTITY_TYPE_OBJECT: + RenderedObjects++; + break; + case ENTITY_TYPE_DUMMY: + RenderedDummies++; + break; + } +#endif + }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){ + if(SetupEntityVisibility(ent) == VIS_STREAMME) + CStreaming::RequestModel(ent->GetModelIndex(), 0); + }else{ +#ifndef MASTER + // actually missing in game + EntitiesNotRendered++; +#endif } } } @@ -1220,9 +1357,34 @@ CRenderer::IsEntityCullZoneVisible(CEntity *ent) CPed *ped; CObject *obj; + if(gbDisableZoneCull) return true; + +#ifndef MASTER + switch(ent->GetType()){ + case ENTITY_TYPE_BUILDING: + if(ent->bIsBIGBuilding) + TestedBigBuildings++; + else + TestedBuildings++; + break; + case ENTITY_TYPE_VEHICLE: + TestedCars++; + break; + case ENTITY_TYPE_PED: + TestedPeds++; + break; + case ENTITY_TYPE_OBJECT: + TestedObjects++; + break; + case ENTITY_TYPE_DUMMY: + TestedDummies++; + break; + } +#endif if(ent->bZoneCulled) return false; + switch(ent->GetType()){ case ENTITY_TYPE_VEHICLE: return IsVehicleCullZoneVisible(ent); diff --git a/src/render/Renderer.h b/src/render/Renderer.h index 362741e3..e14f73b1 100644 --- a/src/render/Renderer.h +++ b/src/render/Renderer.h @@ -2,11 +2,20 @@ class CEntity; +#ifdef FIX_BUGS +#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier) +#else +#define LOD_DISTANCE 300.0f +#endif +#define FADE_DISTANCE 20.0f +#define STREAM_DISTANCE 30.0f + extern bool gbShowPedRoadGroups; extern bool gbShowCarRoadGroups; extern bool gbShowCollisionPolys; extern bool gbShowCollisionLines; extern bool gbShowCullZoneDebugStuff; +extern bool gbDisableZoneCull; // not original extern bool gbBigWhiteDebugLightSwitchedOn; extern bool gbDontRenderBuildings; @@ -18,6 +27,13 @@ extern bool gbDontRenderVehicles; class CVehicle; class CPtrList; +// unused +struct BlockedRange +{ + float a, b; // unknown + BlockedRange *prev, *next; +}; + class CRenderer { static int32 ms_nNoOfVisibleEntities; @@ -28,6 +44,10 @@ class CRenderer static CVector ms_vecCameraPosition; static CVehicle *m_pFirstPersonVehicle; + // unused + static BlockedRange aBlockedRanges[16]; + static BlockedRange *pFullBlockedRanges; + static BlockedRange *pEmptyBlockedRanges; public: static float ms_lodDistScale; static bool m_loadingPriority; @@ -46,6 +66,8 @@ public: static void RenderFirstPersonVehicle(void); static void RenderCollisionLines(void); + // unused + static void RenderBlockBuildingLines(void); static int32 SetupEntityVisibility(CEntity *ent); static int32 SetupBigBuildingVisibility(CEntity *ent); diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 8878a26a..3f10d12a 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -11,8 +11,6 @@ #include "World.h" #include "custompipes.h" -#define FADE_DISTANCE 20.0f - CLinkList CVisibilityPlugins::m_alphaList; CLinkList CVisibilityPlugins::m_alphaEntityList; -- cgit v1.2.3 From d24e1ee5926a1d29633c62f2f29f9112b76b5a08 Mon Sep 17 00:00:00 2001 From: Nikolay Date: Sun, 22 Nov 2020 02:29:17 +0300 Subject: small improvement --- src/control/Restart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index a6482d04..5e9865dd 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -81,7 +81,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f } eLevelName curlevel = CTheZones::FindZoneForPoint(pos); - float fMinDist = 16000000.0f; + float fMinDist = SQR(4000.0f); int closestPoint = NUM_RESTART_POINTS; // find closest point on this level -- cgit v1.2.3 From 222e7f56ffa950427b45a342f3ea795d639cba19 Mon Sep 17 00:00:00 2001 From: Nikolay Date: Sun, 22 Nov 2020 02:31:52 +0300 Subject: one more fix --- src/control/Restart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index 5e9865dd..4ca18c3b 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -128,7 +128,7 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo } eLevelName curlevel = CTheZones::FindZoneForPoint(pos); - float fMinDist = 16000000.0f; + float fMinDist = SQR(4000.0f); int closestPoint = NUM_RESTART_POINTS; // find closest point on this level -- cgit v1.2.3 From f010777e580a4f2bdbfca9dbe037700822f34a88 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 22 Nov 2020 23:10:41 +0200 Subject: Audio fixes --- src/audio/AudioLogic.cpp | 245 +++++++-------------------------------------- src/audio/AudioManager.cpp | 2 +- src/audio/AudioManager.h | 8 +- 3 files changed, 40 insertions(+), 215 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index fc828042..ca493a95 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -2248,7 +2248,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams& params) pedParams.m_fDistance = 0.0f; pedParams.m_bDistanceCalculated = params.m_bDistanceCalculated; pedParams.m_fDistance = params.m_fDistance; - SetupPedComments(&pedParams, SOUND_PED_HELI_PLAYER_FOUND); + SetupPedComments(pedParams, SOUND_PED_HELI_PLAYER_FOUND); continue; case SOUND_PED_BODYCAST_HIT: pedParams.m_pPed = nil; @@ -2256,7 +2256,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams& params) pedParams.m_fDistance = 0.0f; pedParams.m_bDistanceCalculated = params.m_bDistanceCalculated; pedParams.m_fDistance = params.m_fDistance; - SetupPedComments(&pedParams, SOUND_PED_BODYCAST_HIT); + SetupPedComments(pedParams, SOUND_PED_BODYCAST_HIT); continue; case SOUND_WATER_FALL: { const float SOUND_INTENSITY = 40.0f; @@ -2965,21 +2965,21 @@ cAudioManager::ProcessPed(CPhysical *ped) params.m_pPed = (CPed *)ped; params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); if (ped->GetModelIndex() == MI_FATMALE02) - ProcessPedHeadphones(¶ms); - ProcessPedOneShots(¶ms); + ProcessPedHeadphones(params); + ProcessPedOneShots(params); } void -cAudioManager::ProcessPedHeadphones(cPedParams *params) +cAudioManager::ProcessPedHeadphones(cPedParams ¶ms) { CPed *ped; CAutomobile *veh; uint8 emittingVol; - if (params->m_fDistance < SQR(7)) { - ped = params->m_pPed; + if (params.m_fDistance < SQR(7)) { + ped = params.m_pPed; if (!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); if (ped->bInVehicle && ped->m_nPedState == PED_DRIVING) { emittingVol = 10; veh = (CAutomobile *)ped->m_pMyVehicle; @@ -3021,12 +3021,12 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params) } void -cAudioManager::ProcessPedOneShots(cPedParams *params) +cAudioManager::ProcessPedOneShots(cPedParams ¶ms) { uint8 emittingVol; int32 sampleIndex; - CPed *ped = params->m_pPed; + CPed *ped = params.m_pPed; bool stereo; int16 sound; @@ -3036,7 +3036,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) static uint8 iSound = 21; - weapon = params->m_pPed->GetWeapon(); + weapon = params.m_pPed->GetWeapon(); for (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { noReflection = false; stereo = false; @@ -3045,12 +3045,12 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) switch (sound) { case SOUND_STEP_START: case SOUND_STEP_END: - if (!params->m_pPed->bIsLooking) { + 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) { + switch (params.m_pPed->m_nSurfaceTouched) { case SURFACE_GRASS: sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1; break; @@ -3094,7 +3094,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - 28; 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) { + switch (params.m_pPed->m_nMoveState) { case PEDMOVE_WALK: emittingVol /= 4; m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10; @@ -3152,226 +3152,51 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) case SOUND_FIGHT_PUNCH_33: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_KICK_34: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_HEADBUTT_35: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; m_sQueueSample.m_nFrequency = 20000; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_PUNCH_36: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_PUNCH_37: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_CLOSE_PUNCH_38: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; m_sQueueSample.m_nFrequency = 20000; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_PUNCH_39: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_PUNCH_41: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; m_sQueueSample.m_nFrequency = 20000; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_PUNCH_FROM_BEHIND_42: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_KNEE_OR_KICK_43: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SFX_BANK_0; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - 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; + goto AddFightSound; case SOUND_FIGHT_KICK_44: m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; m_sQueueSample.m_nFrequency = 20000; + AddFightSound: m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound; stereo = true; @@ -3729,8 +3554,8 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) if (stereo && iSound > 60) iSound = 21; - if (params->m_fDistance < maxDist) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + if (params.m_fDistance < maxDist) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { if (noReflection) { @@ -3762,9 +3587,9 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) } void -cAudioManager::SetupPedComments(cPedParams *params, uint32 sound) +cAudioManager::SetupPedComments(cPedParams ¶ms, uint16 sound) { - CPed *ped = params->m_pPed; + CPed *ped = params.m_pPed; uint8 emittingVol; float soundIntensity; tPedComment pedComment; @@ -3815,8 +3640,8 @@ cAudioManager::SetupPedComments(cPedParams *params, uint32 sound) } } - if (params->m_fDistance < SQR(soundIntensity)) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + if (params.m_fDistance < SQR(soundIntensity)) { + CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); if (sound != SOUND_PAGER) { switch (sound) { case SOUND_AMMUNATION_WELCOME_1: @@ -6549,14 +6374,14 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) male.m_pPed = nil; male.m_bDistanceCalculated = false; male.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); - SetupPedComments(&male, SOUND_INJURED_PED_MALE_OUCH); + SetupPedComments(male, SOUND_INJURED_PED_MALE_OUCH); return; case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_S: case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_L: female.m_pPed = nil; female.m_bDistanceCalculated = false; female.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); - SetupPedComments(&female, SOUND_INJURED_PED_FEMALE); + SetupPedComments(female, SOUND_INJURED_PED_FEMALE); return; case SCRIPT_SOUND_GATE_START_CLUNK: case SCRIPT_SOUND_GATE_STOP_CLUNK: @@ -7934,7 +7759,7 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound) params.m_bDistanceCalculated = true; params.m_fDistance = distSquared; params.m_pPed = nil; - SetupPedComments(¶ms, SOUND_INJURED_PED_MALE_PRISON); + SetupPedComments(params, SOUND_INJURED_PED_MALE_PRISON); } gCellNextTime = time + 500 + m_anRandomTable[3] % 1500; } diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index d8054181..947bda40 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -167,7 +167,7 @@ cAudioManager::SetEntityStatus(int32 id, uint8 status) } void -cAudioManager::PlayOneShot(int32 index, int16 sound, float vol) +cAudioManager::PlayOneShot(int32 index, uint16 sound, float vol) { static const uint8 OneShotPriority[] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 4, 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 3, 2, 2, 2, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 2d971ac9..d781ad71 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -351,7 +351,7 @@ public: bool MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; void PlayLoadedMissionAudio(); - void PlayOneShot(int32 index, int16 sound, float vol); + void PlayOneShot(int32 index, uint16 sound, float vol); void PlaySuspectLastSeen(float x, float y, float z); void PlayerJustGotInCar() const; void PlayerJustLeftCar() const; @@ -397,8 +397,8 @@ public: void ProcessModelCarEngine(cVehicleParams& params); void ProcessOneShotScriptObject(uint8 sound); void ProcessPed(CPhysical *ped); - void ProcessPedHeadphones(cPedParams *params); - void ProcessPedOneShots(cPedParams *params); + void ProcessPedHeadphones(cPedParams ¶ms); + void ProcessPedOneShots(cPedParams ¶ms); void ProcessPhysical(int32 id); void ProcessPlane(cVehicleParams& params); void ProcessPlayersVehicleEngine(cVehicleParams& params, CAutomobile *automobile); @@ -462,7 +462,7 @@ public: bool SetupJumboRumbleSound(uint8 emittingVol); bool SetupJumboTaxiSound(uint8 vol); bool SetupJumboWhineSound(uint8 emittingVol, uint32 freq); - void SetupPedComments(cPedParams *params, uint32 sound); + void SetupPedComments(cPedParams ¶ms, uint16 sound); void SetupSuspectLastSeenReport(); void Terminate(); -- cgit v1.2.3 From c814a0a1a6b0f71842306052fbdadb06de7883cb Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 22 Nov 2020 23:11:55 +0200 Subject: Renderer fix --- src/render/Renderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 949f8c54..97d2b49c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -570,7 +570,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) // that of an atomic for another draw distance. if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) - if(!ent->IsVisibleComplex()) + if (!ent->IsVisible() || !ent->GetIsOnScreenComplex()) return VIS_INVISIBLE; if(mi->m_drawLast){ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); @@ -600,7 +600,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject; if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) - if(ent->IsVisibleComplex()) + if (ent->IsVisible() && ent->GetIsOnScreenComplex()) CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); return VIS_INVISIBLE; } -- cgit v1.2.3 From 103b8fb426e7e5555d58cfeeff0ace64fb4b54f6 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 22 Nov 2020 23:24:38 +0200 Subject: More audio fix --- src/audio/AudioLogic.cpp | 54 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index ca493a95..7340e73e 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -3028,9 +3028,9 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) CPed *ped = params.m_pPed; - bool stereo; + bool narrowSoundRange; int16 sound; - bool noReflection; + bool stereo; CWeapon *weapon; float maxDist = 0.f; // uninitialized variable @@ -3038,8 +3038,8 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) weapon = params.m_pPed->GetWeapon(); for (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { - noReflection = false; stereo = false; + narrowSoundRange = false; m_sQueueSample.m_bRequireReflection = false; sound = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; switch (sound) { @@ -3199,7 +3199,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) AddFightSound: m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound; - stereo = true; + narrowSoundRange = true; ++iSound; m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_fSpeedMultiplier = 0.0f; @@ -3218,7 +3218,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_BAT_HIT_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 22000; m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_fSpeedMultiplier = 0.0f; @@ -3234,7 +3234,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) if (m_bDynamicAcousticModelingStatus) m_sQueueSample.m_bRequireReflection = true; else - noReflection = true; + stereo = true; break; case SOUND_WEAPON_SHOT_FIRED: weapon = ped->GetWeapon(); @@ -3243,7 +3243,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_COLT45_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COLT45_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -3260,13 +3260,13 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) if (m_bDynamicAcousticModelingStatus) m_sQueueSample.m_bRequireReflection = true; else - noReflection = true; + stereo = true; break; case WEAPONTYPE_UZI: m_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -3285,7 +3285,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_SHOTGUN_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOTGUN_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -3302,13 +3302,13 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) if (m_bDynamicAcousticModelingStatus) m_sQueueSample.m_bRequireReflection = true; else - noReflection = true; + stereo = true; break; case WEAPONTYPE_AK47: m_sQueueSample.m_nSampleIndex = SFX_AK47_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AK47_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -3327,7 +3327,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_M16_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M16_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -3346,7 +3346,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_SNIPER_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SNIPER_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -3363,13 +3363,13 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) if (m_bDynamicAcousticModelingStatus) m_sQueueSample.m_bRequireReflection = true; else - noReflection = true; + stereo = true; break; case WEAPONTYPE_ROCKETLAUNCHER: m_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); m_sQueueSample.m_nReleasingVolumeModificator = 1; @@ -3386,7 +3386,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) if (m_bDynamicAcousticModelingStatus) m_sQueueSample.m_bRequireReflection = true; else - noReflection = true; + stereo = true; break; case WEAPONTYPE_FLAMETHROWER: m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_LEFT; @@ -3408,7 +3408,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) if (m_bDynamicAcousticModelingStatus) m_sQueueSample.m_bRequireReflection = true; else - noReflection = true; + stereo = true; break; default: continue; @@ -3451,7 +3451,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) } emittingVol = 75; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency += RandomDisplacement(300); m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nReleasingVolumeModificator = 5; @@ -3472,7 +3472,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_UZI_END_LEFT; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_END_LEFT); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -3489,7 +3489,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) if (m_bDynamicAcousticModelingStatus) m_sQueueSample.m_bRequireReflection = true; else - noReflection = true; + stereo = true; break; case SOUND_WEAPON_FLAMETHROWER_FIRE: m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_START_LEFT; @@ -3513,7 +3513,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_BULLET_PED; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BULLET_PED); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); m_sQueueSample.m_nReleasingVolumeModificator = 7; @@ -3532,7 +3532,7 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) m_sQueueSample.m_nSampleIndex = SFX_SPLASH_1; m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nCounter = iSound++; - stereo = true; + narrowSoundRange = true; m_sQueueSample.m_nFrequency = RandomDisplacement(1400) + 20000; m_sQueueSample.m_nReleasingVolumeModificator = 1; m_sQueueSample.m_fSpeedMultiplier = 0.0f; @@ -3552,23 +3552,23 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms) continue; } - if (stereo && iSound > 60) + if (narrowSoundRange && iSound > 60) iSound = 21; if (params.m_fDistance < maxDist) { CalculateDistance(params.m_bDistanceCalculated, params.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume != 0) { - if (noReflection) { + if (stereo) { if (m_sQueueSample.m_fDistance < 0.2f * m_sQueueSample.m_fSoundIntensity) { m_sQueueSample.m_bIs2D = true; m_sQueueSample.m_nOffset = 0; } else { - noReflection = false; + stereo = false; } } m_sQueueSample.m_bReverbFlag = true; AddSampleToRequestedQueue(); - if (noReflection) { + if (stereo) { m_sQueueSample.m_nOffset = 127; ++m_sQueueSample.m_nSampleIndex; if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] != SOUND_WEAPON_SHOT_FIRED || -- cgit v1.2.3 From b6da31cfaa021559939ed596d18a27f4db6acebc Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 23 Nov 2020 09:38:51 +0100 Subject: two unused functions --- src/rw/Lights.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/rw/Lights.h | 2 ++ 2 files changed, 43 insertions(+) (limited to 'src') diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp index 5a253854..b3cef6d4 100644 --- a/src/rw/Lights.cpp +++ b/src/rw/Lights.cpp @@ -3,6 +3,7 @@ #include #include "Lights.h" +#include "Timer.h" #include "Timecycle.h" #include "Coronas.h" #include "Weather.h" @@ -248,6 +249,46 @@ SetAmbientAndDirectionalColours(float f) RpLightSetColor(pDirect, &DirectionalLightColour); } +// unused +void +SetFlashyColours(float f) +{ + if(CTimer::GetTimeInMilliseconds() & 0x100){ + AmbientLightColour.red = 1.0f; + AmbientLightColour.green = 1.0f; + AmbientLightColour.blue = 1.0f; + + DirectionalLightColour.red = DirectionalLightColourForFrame.red; + DirectionalLightColour.green = DirectionalLightColourForFrame.green; + DirectionalLightColour.blue = DirectionalLightColourForFrame.blue; + + RpLightSetColor(pAmbient, &AmbientLightColour); + RpLightSetColor(pDirect, &DirectionalLightColour); + }else{ + SetAmbientAndDirectionalColours(f * 0.75f); + } +} + +// unused +void +SetFlashyColours_Mild(float f) +{ + if(CTimer::GetTimeInMilliseconds() & 0x100){ + AmbientLightColour.red = 0.65f; + AmbientLightColour.green = 0.65f; + AmbientLightColour.blue = 0.65f; + + DirectionalLightColour.red = DirectionalLightColourForFrame.red; + DirectionalLightColour.green = DirectionalLightColourForFrame.green; + DirectionalLightColour.blue = DirectionalLightColourForFrame.blue; + + RpLightSetColor(pAmbient, &AmbientLightColour); + RpLightSetColor(pDirect, &DirectionalLightColour); + }else{ + SetAmbientAndDirectionalColours(f * 0.9f); + } +} + void SetBrightMarkerColours(float f) { diff --git a/src/rw/Lights.h b/src/rw/Lights.h index b296816b..5057f1d0 100644 --- a/src/rw/Lights.h +++ b/src/rw/Lights.h @@ -14,6 +14,8 @@ void WorldReplaceScorchedLightsWithNormal(RpWorld *world); void AddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, float red, float green, float blue); void RemoveExtraDirectionalLights(RpWorld *world); void SetAmbientAndDirectionalColours(float f); +void SetFlashyColours(float f); +void SetFlashyColours_Mild(float f); void SetBrightMarkerColours(float f); void ReSetAmbientAndDirectionalColours(void); void DeActivateDirectional(void); -- cgit v1.2.3 From 833bf4a619c7bd40ea69731abe3d31770815d863 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 23 Nov 2020 18:59:50 +0200 Subject: Add some TODO stubs for unused code to be reversed --- src/control/NameGrid.cpp | 87 ++++++++++++++++++++++++++++++++++++++ src/control/NameGrid.h | 53 +++++++++++++++++++++++ src/modelinfo/VehicleModelInfo.cpp | 2 +- src/vehicles/Automobile.cpp | 2 +- src/vehicles/Boat.cpp | 2 +- src/vehicles/HandlingMgr.cpp | 26 +++++++++++- src/vehicles/HandlingMgr.h | 21 ++++++--- src/vehicles/Heli.cpp | 2 +- src/vehicles/Plane.cpp | 2 +- src/vehicles/Train.cpp | 2 +- src/vehicles/Vehicle.cpp | 7 +++ src/vehicles/Vehicle.h | 11 +++++ 12 files changed, 205 insertions(+), 12 deletions(-) create mode 100644 src/control/NameGrid.cpp create mode 100644 src/control/NameGrid.h (limited to 'src') diff --git a/src/control/NameGrid.cpp b/src/control/NameGrid.cpp new file mode 100644 index 00000000..204e8b9c --- /dev/null +++ b/src/control/NameGrid.cpp @@ -0,0 +1,87 @@ +#include "common.h" +#include "NameGrid.h" + +// TODO: reverse mobile code + +CPlayerName::CPlayerName() +{ + // TODO +} + +void +CPlayerName::DisplayName(int) +{ + // TODO +} + +CRow::CRow() +{ + // TODO +} + +void +CRow::SetLetter(int, wchar *) +{ + // TODO +} + +CGrid::CGrid() +{ + // TODO +} + +void +CGrid::ProcessAnyLeftJustDown() +{ + unk_int2--; +} + +void +CGrid::ProcessAnyRightJustDown() +{ + unk_int2++; +} + +void +CGrid::ProcessAnyUpJustDown() +{ + unk_int1--; +} + +void +CGrid::ProcessAnyDownJustDown() +{ + unk_int1++; +} + +void +CGrid::AllDoneMakePlayerName() +{ + // TODO +} + +void +CGrid::ProcessDPadCrossJustDown() +{ + // TODO +} + +void +CGrid::DisplayGrid() +{ + // TODO +} + +void +CGrid::ProcessControllerInput() +{ + // TODO +} + +void +CGrid::Process() +{ + ProcessControllerInput(); + DisplayGrid(); + playerName.DisplayName(2 * playerName.unk_4c); +} \ No newline at end of file diff --git a/src/control/NameGrid.h b/src/control/NameGrid.h new file mode 100644 index 00000000..d52cec73 --- /dev/null +++ b/src/control/NameGrid.h @@ -0,0 +1,53 @@ +#pragma once + +// TODO: reverse mobile code + +class CPlayerName +{ + friend class CGrid; + + float x; + float y; + wchar unk_8[34]; + int unk_4c; +public: + CPlayerName(); + void DisplayName(int); +}; + +class CRow +{ + friend class CGrid; + + int unk_0; + int unk_4; + wchar unk_8[20]; + int unk_30; +public: + CRow(); + void SetLetter(int, wchar *); +}; + +class CGrid +{ + CRow rows[5]; + int unk_int1; + int unk_int2; + int unk_int3; + float unk_float1; + float unk_float2; + CPlayerName playerName; + char unk2[4]; + char unk3[4]; +public: + CGrid(); + void ProcessAnyLeftJustDown(); + void ProcessAnyRightJustDown(); + void ProcessAnyUpJustDown(); + void ProcessAnyDownJustDown(); + void AllDoneMakePlayerName(); + void ProcessDPadCrossJustDown(); + void DisplayGrid(); + void ProcessControllerInput(); + void Process(); +}; \ No newline at end of file diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index a024bb40..5b212f62 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -536,7 +536,7 @@ CVehicleModelInfo::SetVehicleComponentFlags(RwFrame *frame, uint32 flags) { tHandlingData *handling; - handling = mod_HandlingManager.GetHandlingData((eHandlingId)m_handlingId); + handling = mod_HandlingManager.GetHandlingData((tVehicleType)m_handlingId); #define SETFLAGS(f) RwFrameForAllObjects(frame, SetAtomicFlagCB, (void*)(f)) diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 66afa1d4..ec71f690 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -75,7 +75,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) SetModelIndex(id); - pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); + pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId); m_auto_unused1 = 20.0f; m_auto_unused2 = 0; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index dfe9d1d9..aba48bad 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -50,7 +50,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fMovingRotation = 0.0f; SetModelIndex(mi); - pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)minfo->m_handlingId); + pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)minfo->m_handlingId); minfo->ChooseVehicleColour(m_currentColour1, m_currentColour2); m_fMass = pHandling->fMass; diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 5beed29e..18a2481e 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -127,7 +127,7 @@ cHandlingDataMgr::LoadHandlingData(void) handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS); assert(handlingId >= 0 && handlingId < NUMHANDLINGS); handling = &HandlingData[handlingId]; - handling->nIdentifier = (eHandlingId)handlingId; + handling->nIdentifier = (tVehicleType)handlingId; break; case 1: handling->fMass = strtod(word, nil); break; case 2: handling->Dimension.x = strtod(word, nil); break; @@ -237,3 +237,27 @@ cHandlingDataMgr::GetHandlingId(const char *name) break; return i; } + +void +cHandlingDataMgr::ConvertDataToWorldUnits(tHandlingData *handling) +{ + // TODO: mobile code +} + +void +cHandlingDataMgr::RangeCheck(tHandlingData *handling) +{ + // TODO: mobile code +} + +void +cHandlingDataMgr::ModifyHandlingValue(CVehicle *, const tVehicleType &, const tField &, const bool &) +{ + // TODO: mobile code +} + +void +cHandlingDataMgr::DisplayHandlingData(CVehicle *, tHandlingData *, uint8, bool) +{ + // TODO: mobile code +} \ No newline at end of file diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index 10e25573..4d3b8389 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -2,7 +2,7 @@ #include "Transmission.h" -enum eHandlingId +enum tVehicleType { HANDLING_LANDSTAL, HANDLING_IDAHO, @@ -65,6 +65,11 @@ enum eHandlingId NUMHANDLINGS }; +enum tField : uint32 // most likely a handling field enum, never used so :shrug: +{ + +}; + enum { HANDLING_1G_BOOST = 1, @@ -87,7 +92,7 @@ enum struct tHandlingData { - eHandlingId nIdentifier; + tVehicleType nIdentifier; float fMass; float fInvMass; float fTurnMass; @@ -118,6 +123,8 @@ struct tHandlingData }; VALIDATE_SIZE(tHandlingData, 0xD8); +class CVehicle; + class cHandlingDataMgr { float field_0; // unused it seems @@ -135,11 +142,15 @@ public: void Initialise(void); void LoadHandlingData(void); int FindExactWord(const char *word, const char *words, int wordLen, int numWords); + void ConvertDataToWorldUnits(tHandlingData *handling); void ConvertDataToGameUnits(tHandlingData *handling); + void RangeCheck(tHandlingData *handling); + void ModifyHandlingValue(CVehicle *, const tVehicleType &, const tField &, const bool &); + void DisplayHandlingData(CVehicle *, tHandlingData *, uint8, bool); int32 GetHandlingId(const char *name); - tHandlingData *GetHandlingData(eHandlingId id) { return &HandlingData[id]; } - bool HasRearWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'R'; } - bool HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; } + tHandlingData *GetHandlingData(tVehicleType id) { return &HandlingData[id]; } + bool HasRearWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType == 'R'; } + bool HasFrontWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType == 'F'; } }; VALIDATE_SIZE(cHandlingDataMgr, 0x3030); extern cHandlingDataMgr mod_HandlingManager; diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index e1f662d8..a8705524 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -52,7 +52,7 @@ CHeli::CHeli(int32 id, uint8 CreatedBy) CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); m_vehType = VEHICLE_TYPE_HELI; - pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); + pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId); SetModelIndex(id); m_heliStatus = HELI_STATUS_HOVER; m_pathState = 0; diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index b8a957cf..1a6f1a88 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -68,7 +68,7 @@ CPlane::CPlane(int32 id, uint8 CreatedBy) { CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); m_vehType = VEHICLE_TYPE_PLANE; - pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); + pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId); SetModelIndex(id); m_fMass = 100000000.0f; diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp index 26d0dee7..4250f6f4 100644 --- a/src/vehicles/Train.cpp +++ b/src/vehicles/Train.cpp @@ -43,7 +43,7 @@ CTrain::CTrain(int32 id, uint8 CreatedBy) { CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); m_vehType = VEHICLE_TYPE_TRAIN; - pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); + pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId); SetModelIndex(id); Doors[0].Init(0.8f, 0.0f, 1, 0); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index bc77b011..d2ca5a1a 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -582,6 +582,13 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon } } +void +CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, + float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus) +{ + // TODO: mobile code +} + float CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius) { diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 999ee002..3933f1dd 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -103,6 +103,15 @@ enum eFlightModel FLIGHT_MODEL_SEAPLANE }; +// TODO: what is this even? +enum eBikeWheelSpecial { + BIKE_WHEELSPEC_0, // both wheels on ground + BIKE_WHEELSPEC_1, // rear wheel on ground + BIKE_WHEELSPEC_2, // only front wheel on ground + BIKE_WHEELSPEC_3, // can't happen +}; + + class CVehicle : public CPhysical { public: @@ -237,6 +246,8 @@ public: void FlyingControl(eFlightModel flightModel); void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus); + void ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, + float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus); void ExtinguishCarFire(void); void ProcessDelayedExplosion(void); float ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius); -- cgit v1.2.3 From bd3d09fef53680389bd6ef856eb0669e31fba1d7 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 24 Nov 2020 02:15:57 +0200 Subject: Script commands split to original files --- src/control/Script.cpp | 8915 +---------------------------------------------- src/control/Script.h | 23 + src/control/Script2.cpp | 1549 ++++++++ src/control/Script3.cpp | 2082 +++++++++++ src/control/Script4.cpp | 2027 +++++++++++ src/control/Script5.cpp | 2011 +++++++++++ src/control/Script6.cpp | 1343 +++++++ 7 files changed, 9038 insertions(+), 8912 deletions(-) create mode 100644 src/control/Script2.cpp create mode 100644 src/control/Script3.cpp create mode 100644 src/control/Script4.cpp create mode 100644 src/control/Script5.cpp create mode 100644 src/control/Script6.cpp (limited to 'src') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 646bc3f7..085c773a 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -4,94 +4,40 @@ #include "ScriptCommands.h" #include "AnimBlendAssociation.h" +#include "AudioManager.h" #include "Boat.h" -#include "BulletInfo.h" #include "Camera.h" -#include "CarAI.h" #include "CarCtrl.h" -#include "CarGen.h" #include "CivilianPed.h" #include "Clock.h" #include "CopPed.h" -#include "Coronas.h" -#include "Cranes.h" -#include "Credits.h" -#include "CutsceneMgr.h" #include "Debug.h" #include "DMAudio.h" -#include "Darkel.h" #include "EmergencyPed.h" -#include "Explosion.h" #include "FileMgr.h" -#include "Fire.h" #include "Frontend.h" -#include "Gangs.h" -#include "Garages.h" #include "General.h" -#ifdef MISSION_REPLAY -#include "GenericGameStorage.h" -#endif #include "HandlingMgr.h" #include "Heli.h" #include "Hud.h" #include "Lines.h" #include "Messages.h" -#include "ModelIndices.h" #include "Pad.h" -#include "Particle.h" -#include "ParticleObject.h" -#include "PedRoutes.h" -#include "Phones.h" #include "Pickups.h" -#include "Plane.h" -#include "PlayerInfo.h" -#include "PlayerPed.h" -#include "PointLights.h" #include "Pools.h" #include "Population.h" -#include "PowerPoints.h" -#include "ProjectileInfo.h" -#include "Radar.h" -#include "Record.h" #include "Remote.h" #include "Replay.h" -#include "Restart.h" -#include "RpAnimBlend.h" -#include "Rubbish.h" -#include "Shadows.h" -#include "SpecialFX.h" #include "Stats.h" #include "Streaming.h" -#include "Text.h" -#include "TxdStore.h" #include "User.h" -#include "WaterLevel.h" +#include "Wanted.h" #include "Weather.h" -#include "World.h" #include "Zones.h" -#include "main.h" #ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #include #endif -#define PICKUP_PLACEMENT_OFFSET 0.5f -#define PED_FIND_Z_OFFSET 5.0f - -#define SPHERE_MARKER_R 0 -#define SPHERE_MARKER_G 128 -#define SPHERE_MARKER_B 255 -#define SPHERE_MARKER_A 128 -#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 -#else -#define METERS_IN_FOOT 0.3f -#define FEET_IN_METER 3.33f -#endif - uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE]; CRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS]; int32 CTheScripts::BaseBriefIdForContact[MAX_NUM_CONTACTS]; @@ -1362,7 +1308,7 @@ static void PrintToLog(const char* format, ...) #endif -static void FlushLog() +void FlushLog() { #ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2 @@ -1372,7 +1318,6 @@ static void FlushLog() #endif } -#define script_assert(_Expression) FlushLog(); assert(_Expression); const uint32 CRunningScript::nSaveStructSize = #ifdef COMPATIBLE_SAVES @@ -4369,8860 +4314,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) return -1; } -int8 CRunningScript::ProcessCommands300To399(int32 command) -{ - switch (command) { - /* Not implemented. - case COMMAND_SET_CHAR_INVINCIBLE: - case COMMAND_SET_PLAYER_INVINCIBLE: - case COMMAND_SET_CHAR_GRAPHIC_TYPE: - case COMMAND_SET_PLAYER_GRAPHIC_TYPE: - */ - case COMMAND_HAS_PLAYER_BEEN_ARRESTED: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_BUSTED); - return 0; - /* Not implemented. - case COMMAND_STOP_CHAR_DRIVING: - case COMMAND_KILL_CHAR: - case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR: - case COMMAND_SET_CHAR_OCCUPATION: - */ - case COMMAND_CHANGE_CAR_LOCK: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1]; - return 0; - } - case COMMAND_SHAKE_CAM_WITH_POINT: - CollectParameters(&m_nIp, 4); - TheCamera.CamShake(ScriptParams[0] / 1000.0f, - *(float*)&ScriptParams[1], - *(float*)&ScriptParams[2], - *(float*)&ScriptParams[3]); - return 0; - case COMMAND_IS_CAR_MODEL: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]); - return 0; - } - /* Not implemented. - case COMMAND_IS_CAR_REMAP: - case COMMAND_HAS_CAR_JUST_SUNK: - case COMMAND_SET_CAR_NO_COLLIDE: - */ - case COMMAND_IS_CAR_DEAD_IN_AREA_2D: - { - CollectParameters(&m_nIp, 6); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - float x1 = *(float*)&ScriptParams[1]; - float y1 = *(float*)&ScriptParams[2]; - float x2 = *(float*)&ScriptParams[3]; - float y2 = *(float*)&ScriptParams[4]; - UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && - pVehicle->IsWithinArea(x1, y1, x2, y2)); - if (ScriptParams[5]) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) - CTheScripts::DrawDebugSquare(x1, y1, x2, y2); - return 0; - } - case COMMAND_IS_CAR_DEAD_IN_AREA_3D: - { - CollectParameters(&m_nIp, 8); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - float x1 = *(float*)&ScriptParams[1]; - float y1 = *(float*)&ScriptParams[2]; - float z1 = *(float*)&ScriptParams[3]; - float x2 = *(float*)&ScriptParams[4]; - float y2 = *(float*)&ScriptParams[5]; - float z2 = *(float*)&ScriptParams[6]; - UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && - pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (ScriptParams[7]) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); - if (CTheScripts::DbgFlag) - CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); - return 0; - } - /* Not implemented. - case COMMAND_IS_TRAILER_ATTACHED: - case COMMAND_IS_CAR_ON_TRAILER: - case COMMAND_HAS_CAR_GOT_WEAPON: - case COMMAND_PARK: - case COMMAND_HAS_PARK_FINISHED: - case COMMAND_KILL_ALL_PASSENGERS: - case COMMAND_SET_CAR_BULLETPROOF: - case COMMAND_SET_CAR_FLAMEPROOF: - case COMMAND_SET_CAR_ROCKETPROOF: - case COMMAND_IS_CARBOMB_ACTIVE: - case COMMAND_GIVE_CAR_ALARM: - case COMMAND_PUT_CAR_ON_TRAILER: - */ - case COMMAND_IS_CAR_CRUSHED: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0])); - return 0; - /* Not implemented. - case COMMAND_CREATE_GANG_CAR: - */ - case COMMAND_CREATE_CAR_GENERATOR: - CollectParameters(&m_nIp, 12); - ScriptParams[0] = CTheCarGenerators::CreateCarGenerator( - *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], - ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], - ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_SWITCH_CAR_GENERATOR: - { - CollectParameters(&m_nIp, 2); - CCarGenerator* pCarGen = &CTheCarGenerators::CarGeneratorArray[ScriptParams[0]]; - if (ScriptParams[1] == 0){ - pCarGen->SwitchOff(); - }else if (ScriptParams[1] <= 100){ - pCarGen->SwitchOn(); - pCarGen->SetUsesRemaining(ScriptParams[1]); - }else{ - pCarGen->SwitchOn(); - } - return 0; - } - case COMMAND_ADD_PAGER_MESSAGE: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 3); - CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]); - return 0; - } - case COMMAND_DISPLAY_ONSCREEN_TIMER: - { - script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); - m_nIp++; - CUserDisplay::OnscnTimer.AddClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp), nil); - return 0; - } - case COMMAND_CLEAR_ONSCREEN_TIMER: - { - script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); - m_nIp++; - CUserDisplay::OnscnTimer.ClearClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp)); - return 0; - } - case COMMAND_DISPLAY_ONSCREEN_COUNTER: - { - script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); - m_nIp++; - uint16 counter = CTheScripts::Read2BytesFromScript(&m_nIp); - CollectParameters(&m_nIp, 1); - CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil); - return 0; - } - case COMMAND_CLEAR_ONSCREEN_COUNTER: - { - script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); - m_nIp++; - CUserDisplay::OnscnTimer.ClearCounter((uint16)CTheScripts::Read2BytesFromScript(&m_nIp)); - return 0; - } - case COMMAND_SET_ZONE_CAR_INFO: - { - char label[12]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, label); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CollectParameters(&m_nIp, 16); - int zone = CTheZones::FindZoneByLabelAndReturnIndex(label); - if (zone < 0) { - debug("Couldn't find zone - %s\n", label); - return 0; - } - CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], - ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0, - ScriptParams[9], ScriptParams[10], ScriptParams[11], ScriptParams[12], - ScriptParams[13], ScriptParams[14], ScriptParams[15]); - return 0; - } - /* Not implemented. - case COMMAND_IS_CHAR_IN_GANG_ZONE: - */ - case COMMAND_IS_CHAR_IN_ZONE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - char label[12]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, label); - int zone = CTheZones::FindZoneByLabelAndReturnIndex(label); - if (zone != -1) - m_nIp += KEY_LENGTH_IN_SCRIPT; - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); - UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetZone(zone))); - return 0; - } - case COMMAND_SET_CAR_DENSITY: - { - char label[12]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, label); - int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label); - m_nIp += 8; - CollectParameters(&m_nIp, 2); - if (zone < 0) { - debug("Couldn't find zone - %s\n", label); - return 0; - } - CTheZones::SetCarDensity(zone, ScriptParams[0], ScriptParams[1]); - return 0; - } - case COMMAND_SET_PED_DENSITY: - { - char label[12]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, label); - int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CollectParameters(&m_nIp, 2); - if (zone < 0) { - debug("Couldn't find zone - %s\n", label); - return 0; - } - CTheZones::SetPedDensity(zone, ScriptParams[0], ScriptParams[1]); - return 0; - } - case COMMAND_POINT_CAMERA_AT_PLAYER: - { - CollectParameters(&m_nIp, 3); - // ScriptParams[0] is unused. - TheCamera.TakeControl(nil, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); - return 0; - } - case COMMAND_POINT_CAMERA_AT_CAR: - { - CollectParameters(&m_nIp, 3); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); - return 0; - } - case COMMAND_POINT_CAMERA_AT_CHAR: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); - return 0; - } - case COMMAND_RESTORE_CAMERA: - TheCamera.Restore(); - return 0; - case COMMAND_SHAKE_PAD: - CPad::GetPad(ScriptParams[0])->StartShake(ScriptParams[1], ScriptParams[2]); - return 0; - case COMMAND_SET_ZONE_PED_INFO: - { - char label[12]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, label); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CollectParameters(&m_nIp, 10); - int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label); - if (zone < 0) { - debug("Couldn't find zone - %s\n", label); - return 0; - } - CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], - ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0, ScriptParams[9]); - return 0; - } - case COMMAND_SET_TIME_SCALE: - CollectParameters(&m_nIp, 1); - CTimer::SetTimeScale(*(float*)&ScriptParams[0]); - return 0; - case COMMAND_IS_CAR_IN_AIR: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle && pVehicle->IsCar()); - CAutomobile* pCar = (CAutomobile*)pVehicle; - UpdateCompareFlag(pCar->GetAllWheelsOffGround()); - return 0; - } - case COMMAND_SET_FIXED_CAMERA_POSITION: - { - CollectParameters(&m_nIp, 6); - TheCamera.SetCamPositionForFixedMode( - CVector(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]), - CVector(*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5])); - return 0; - } - case COMMAND_POINT_CAMERA_AT_POINT: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - TheCamera.TakeControlNoEntity(pos, ScriptParams[3], CAMCONTROL_SCRIPT); - return 0; - } - case COMMAND_ADD_BLIP_FOR_CAR_OLD: - { - CollectParameters(&m_nIp, 3); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - // Useless call. - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_BLIP_FOR_CHAR_OLD: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - // Useless call. - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_BLIP_FOR_OBJECT_OLD: - { - CollectParameters(&m_nIp, 3); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - // Useless call. - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_REMOVE_BLIP: - CollectParameters(&m_nIp, 1); - CRadar::ClearBlip(ScriptParams[0]); - return 0; - case COMMAND_CHANGE_BLIP_COLOUR: - CollectParameters(&m_nIp, 2); - CRadar::ChangeBlipColour(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_DIM_BLIP: - CollectParameters(&m_nIp, 2); - CRadar::ChangeBlipBrightness(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_ADD_BLIP_FOR_COORD_OLD: - { - CollectParameters(&m_nIp, 5); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - // Useless call - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CRadar::SetCoordBlip(BLIP_COORD, pos, ScriptParams[3], (eBlipDisplay)ScriptParams[4]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_CHANGE_BLIP_SCALE: - CollectParameters(&m_nIp, 2); - CRadar::ChangeBlipScale(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_SET_FADING_COLOUR: - CollectParameters(&m_nIp, 3); - TheCamera.SetFadeColour(ScriptParams[0], ScriptParams[1], ScriptParams[2]); - return 0; - case COMMAND_DO_FADE: - CollectParameters(&m_nIp, 2); - TheCamera.Fade(ScriptParams[0] / 1000.0f, ScriptParams[1]); - return 0; - case COMMAND_GET_FADING_STATUS: - UpdateCompareFlag(TheCamera.GetFading()); - return 0; - case COMMAND_ADD_HOSPITAL_RESTART: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - float angle = *(float*)&ScriptParams[3]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CRestart::AddHospitalRestartPoint(pos, angle); - return 0; - } - case COMMAND_ADD_POLICE_RESTART: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - float angle = *(float*)&ScriptParams[3]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CRestart::AddPoliceRestartPoint(pos, angle); - return 0; - } - case COMMAND_OVERRIDE_NEXT_RESTART: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - float angle = *(float*)&ScriptParams[3]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CRestart::OverrideNextRestart(pos, angle); - return 0; - } - case COMMAND_DRAW_SHADOW: - { - CollectParameters(&m_nIp, 10); - CVector pos = *(CVector*)&ScriptParams[1]; - float angle = *(float*)&ScriptParams[4]; - float length = *(float*)&ScriptParams[5]; - float x, y; - if (angle != 0.0f){ - y = cos(angle) * length; - x = sin(angle) * length; - }else{ - y = length; - x = 0.0f; - } - float frontX = -x; - float frontY = y; - float sideX = y; - float sideY = x; - /* Not very nicely named intermediate variables. */ - CShadows::StoreShadowToBeRendered(ScriptParams[0], &pos, frontX, frontY, sideX, sideY, - ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9]); - return 0; - } - case COMMAND_GET_PLAYER_HEADING: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading(); - *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_PLAYER_HEADING: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - if (pPed->bInVehicle){ - // Is script_assertion required? - return 0; - } - pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]); - pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); - return 0; - } - case COMMAND_GET_CHAR_HEADING: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading(); - *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CHAR_HEADING: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - if (pPed->bInVehicle) { - // Is script_assertion required? - return 0; - } - pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]); - pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); - return 0; - } - case COMMAND_GET_CAR_HEADING: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - float angle = pVehicle->GetForward().Heading(); - *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CAR_HEADING: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); - return 0; - } - case COMMAND_GET_OBJECT_HEADING: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - float angle = pObject->GetForward().Heading(); - *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_OBJECT_HEADING: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CWorld::Remove(pObject); - pObject->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); - pObject->GetMatrix().UpdateRW(); - pObject->UpdateRwFrame(); - CWorld::Add(pObject); - return 0; - } - case COMMAND_IS_PLAYER_TOUCHING_OBJECT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); - script_assert(pObject); - CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed; - UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject)); - return 0; - } - case COMMAND_IS_CHAR_TOUCHING_OBJECT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); - script_assert(pObject); - CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed; - UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject)); - return 0; - } - case COMMAND_SET_PLAYER_AMMO: - { - CollectParameters(&m_nIp, 3); - CWorld::Players[0].m_pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); - return 0; - } - case COMMAND_SET_CHAR_AMMO: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); - return 0; - } - /* Not implemented. - case COMMAND_SET_CAR_AMMO: - case COMMAND_LOAD_CAMERA_SPLINE: - case COMMAND_MOVE_CAMERA_ALONG_SPLINE: - case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE: - */ - case COMMAND_DECLARE_MISSION_FLAG: - CTheScripts::OnAMissionFlag = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp); - return 0; - case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: - CollectParameters(&m_nIp, 1); - CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp); - return 0; - case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT: - CollectParameters(&m_nIp, 2); - CTheScripts::BaseBriefIdForContact[ScriptParams[0]] = ScriptParams[1]; - return 0; - case COMMAND_IS_PLAYER_HEALTH_GREATER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]); - return 0; - } - case COMMAND_IS_CHAR_HEALTH_GREATER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]); - return 0; - } - case COMMAND_IS_CAR_HEALTH_GREATER: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->m_fHealth > ScriptParams[1]); - return 0; - } - case COMMAND_ADD_BLIP_FOR_CAR: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - // Useless call. - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int handle = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH); - CRadar::ChangeBlipScale(handle, 3); - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_BLIP_FOR_CHAR: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - // Useless call. - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int handle = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH); - CRadar::ChangeBlipScale(handle, 3); - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_BLIP_FOR_OBJECT: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - // Useless call. - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int handle = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH); - CRadar::ChangeBlipScale(handle, 3); - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_BLIP_FOR_CONTACT_POINT: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - // Useless call - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int handle = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH); - CRadar::ChangeBlipScale(handle, 3); - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_BLIP_FOR_COORD: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - // Useless call - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH); - CRadar::ChangeBlipScale(handle, 3); - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_CHANGE_BLIP_DISPLAY: - CollectParameters(&m_nIp, 2); - CRadar::ChangeBlipDisplay(ScriptParams[0], (eBlipDisplay)ScriptParams[1]); - return 0; - case COMMAND_ADD_ONE_OFF_SOUND: - { - CollectParameters(&m_nIp, 4); - switch (ScriptParams[3]) { - case SCRIPT_SOUND_EVIDENCE_PICKUP: - DMAudio.PlayFrontEndSound(SOUND_EVIDENCE_PICKUP, 0); - return 0; - case SCRIPT_SOUND_UNLOAD_GOLD: - DMAudio.PlayFrontEndSound(SOUND_UNLOAD_GOLD, 0); - return 0; - case SCRIPT_SOUND_PART_MISSION_COMPLETE: - DMAudio.PlayFrontEndSound(SOUND_PART_MISSION_COMPLETE, 0); - return 0; - case SCRIPT_SOUND_RACE_START_3: - DMAudio.PlayFrontEndSound(SOUND_RACE_START_3, 0); - return 0; - case SCRIPT_SOUND_RACE_START_2: - DMAudio.PlayFrontEndSound(SOUND_RACE_START_2, 0); - return 0; - case SCRIPT_SOUND_RACE_START_1: - DMAudio.PlayFrontEndSound(SOUND_RACE_START_1, 0); - return 0; - case SCRIPT_SOUND_RACE_START_GO: - DMAudio.PlayFrontEndSound(SOUND_RACE_START_GO, 0); - return 0; - default: - break; - } -#ifdef FIX_BUGS - /* BUG: if audio is not initialized, this object will not be freed. */ - if (!DMAudio.IsAudioInitialised()) - return 0; -#endif - cAudioScriptObject* obj = new cAudioScriptObject(); - obj->Posn = *(CVector*)&ScriptParams[0]; - obj->AudioId = ScriptParams[3]; - obj->AudioEntity = AEHANDLE_NONE; - DMAudio.CreateOneShotScriptObject(obj); - return 0; - } - case COMMAND_ADD_CONTINUOUS_SOUND: - { - CollectParameters(&m_nIp, 4); - cAudioScriptObject* obj = new cAudioScriptObject(); - obj->Posn = *(CVector*)&ScriptParams[0]; - obj->AudioId = ScriptParams[3]; - obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj); - ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_REMOVE_SOUND: - { - CollectParameters(&m_nIp, 1); - cAudioScriptObject* obj = CPools::GetAudioScriptObjectPool()->GetAt(ScriptParams[0]); - if (!obj){ - debug("REMOVE_SOUND - Sound doesn't exist\n"); - return 0; - } - DMAudio.DestroyLoopingScriptObject(obj->AudioEntity); - delete obj; - return 0; - } - case COMMAND_IS_CAR_STUCK_ON_ROOF: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(CTheScripts::UpsideDownCars.HasCarBeenUpsideDownForAWhile(ScriptParams[0])); - return 0; - } - default: - script_assert(0); - } - return -1; -} - -int8 CRunningScript::ProcessCommands400To499(int32 command) -{ - switch (command) { - case COMMAND_ADD_UPSIDEDOWN_CAR_CHECK: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CTheScripts::UpsideDownCars.AddCarToCheck(ScriptParams[0]); - return 0; - } - case COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CTheScripts::UpsideDownCars.RemoveCarFromCheck(ScriptParams[0]); - return 0; - } - case COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE); - return 0; - } - case COMMAND_SET_CHAR_OBJ_GUARD_SPOT: - { - CollectParameters(&m_nIp, 4); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos); - return 0; - } - case COMMAND_SET_CHAR_OBJ_GUARD_AREA: - { - CollectParameters(&m_nIp, 5); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - float infX = *(float*)&ScriptParams[1]; - float infY = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - if (infX > supX){ - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[1]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[2]; - } - CVector pos; - pos.x = (infX + supX) / 2; - pos.y = (infY + supY) / 2; - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = Max(pos.x - infX, pos.y - infY); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos, radius); - return 0; - } - case COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_WAIT_IN_CAR); - return 0; - } - case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: - PlayerInAreaCheckCommand(command, &m_nIp); - return 0; - case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D: - case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: - CharInAreaCheckCommand(command, &m_nIp); - return 0; - case COMMAND_IS_CAR_STOPPED_IN_AREA_2D: - case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: - CarInAreaCheckCommand(command, &m_nIp); - return 0; - case COMMAND_LOCATE_CAR_2D: - case COMMAND_LOCATE_STOPPED_CAR_2D: - case COMMAND_LOCATE_CAR_3D: - case COMMAND_LOCATE_STOPPED_CAR_3D: - LocateCarCommand(command, &m_nIp); - return 0; - case COMMAND_GIVE_WEAPON_TO_PLAYER: - { - CollectParameters(&m_nIp, 3); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - pPed->m_nSelectedWepSlot = pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]); - return 0; - } - case COMMAND_GIVE_WEAPON_TO_CHAR: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->SetCurrentWeapon(pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2])); - if (pPed->bInVehicle) - pPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId); - return 0; - } - /* Not implemented */ - //case COMMAND_GIVE_WEAPON_TO_CAR: - case COMMAND_SET_PLAYER_CONTROL: - { - CollectParameters(&m_nIp, 2); - CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; - if (ScriptParams[1]){ - if (CGame::playingIntro || CTheScripts::DelayMakingPlayerUnsafeThisTime){ - CTheScripts::CountdownToMakePlayerUnsafe = 50; - if (CTheScripts::DelayMakingPlayerUnsafeThisTime) - CTheScripts::DelayMakingPlayerUnsafeThisTime--; - }else{ - pPlayer->MakePlayerSafe(false); - } - }else{ - pPlayer->MakePlayerSafe(true); - if (strcmp(m_abScriptName, "camera") == 0){ - pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); - pPlayer->m_pPed->SetTurnSpeed(0.0f, 0.0f, 0.0f); - CAnimManager::BlendAnimation((RpClump*)pPlayer->m_pPed->m_rwObject, pPlayer->m_pPed->m_animGroup, ANIM_IDLE_STANCE, 1000.0f); - } - } - return 0; - } - case COMMAND_FORCE_WEATHER: - CollectParameters(&m_nIp, 1); - CWeather::ForceWeather(ScriptParams[0]); - return 0; - case COMMAND_FORCE_WEATHER_NOW: - CollectParameters(&m_nIp, 1); - CWeather::ForceWeatherNow(ScriptParams[0]); - return 0; - case COMMAND_RELEASE_WEATHER: - CWeather::ReleaseWeather(); - return 0; - case COMMAND_SET_CURRENT_PLAYER_WEAPON: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++){ - if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1]) - pPed->m_nSelectedWepSlot = i; - } - return 0; - } - case COMMAND_SET_CURRENT_CHAR_WEAPON: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { - if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1]) - pPed->SetCurrentWeapon(i); - } - return 0; - } - /* Not implemented */ - //case COMMAND_SET_CURRENT_CAR_WEAPON: - case COMMAND_GET_OBJECT_COORDINATES: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - *(CVector*)&ScriptParams[0] = pObject->GetPosition(); - StoreParameters(&m_nIp, 3); - return 0; - } - case COMMAND_SET_OBJECT_COORDINATES: - { - CollectParameters(&m_nIp, 4); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pObject->Teleport(pos); - CTheScripts::ClearSpaceForMissionEntity(pos, pObject); - return 0; - } - case COMMAND_GET_GAME_TIMER: - ScriptParams[0] = CTimer::GetTimeInMilliseconds(); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_TURN_CHAR_TO_FACE_COORD: - { - CollectParameters(&m_nIp, 4); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle; - CVector pos; - if (pPed->bInVehicle) - pVehicle = pPed->m_pMyVehicle; - else - pVehicle = nil; - if (pVehicle) - pos = pVehicle->GetPosition(); - else - pos = pPed->GetPosition(); - float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]); - heading += HALFPI; - if (heading > TWOPI) - heading -= TWOPI; - if (!pVehicle){ - pPed->m_fRotationCur = heading; - pPed->m_fRotationDest = heading; - pPed->SetHeading(heading); - } - return 0; - } - case COMMAND_TURN_PLAYER_TO_FACE_COORD: - { - CollectParameters(&m_nIp, 4); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CVehicle* pVehicle; - CVector pos; - if (pPed->bInVehicle) - pVehicle = pPed->m_pMyVehicle; - else - pVehicle = nil; - if (pVehicle) - pos = pVehicle->GetPosition(); - else - pos = pPed->GetPosition(); - float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]); - heading += HALFPI; - if (heading > TWOPI) - heading -= TWOPI; - if (!pVehicle) { - pPed->m_fRotationCur = heading; - pPed->m_fRotationDest = heading; - pPed->SetHeading(heading); - } - return 0; - } - case COMMAND_STORE_WANTED_LEVEL: - { - CollectParameters(&m_nIp, 1); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - ScriptParams[0] = pPed->m_pWanted->m_nWantedLevel; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_IS_CAR_STOPPED: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(CTheScripts::IsVehicleStopped(pVehicle)); - return 0; - } - case COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - CTheScripts::CleanUpThisPed(pPed); - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR); - return 0; - } - case COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - CTheScripts::CleanUpThisVehicle(pVehicle); - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR); - return 0; - } - case COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - CTheScripts::CleanUpThisObject(pObject); - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT); - return 0; - } - case COMMAND_DONT_REMOVE_CHAR: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR); - return 0; - } - case COMMAND_DONT_REMOVE_CAR: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR); - return 0; - } - case COMMAND_DONT_REMOVE_OBJECT: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT); - return 0; - } - case COMMAND_CREATE_CHAR_AS_PASSENGER: - { - CollectParameters(&m_nIp, 4); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - switch (ScriptParams[2]) { - case MI_COP: - if (ScriptParams[1] == PEDTYPE_COP) - ScriptParams[2] = COP_STREET; - break; - case MI_SWAT: - if (ScriptParams[1] == PEDTYPE_COP) - ScriptParams[2] = COP_SWAT; - break; - case MI_FBI: - if (ScriptParams[1] == PEDTYPE_COP) - ScriptParams[2] = COP_FBI; - break; - case MI_ARMY: - if (ScriptParams[1] == PEDTYPE_COP) - ScriptParams[2] = COP_ARMY; - break; - case MI_MEDIC: - if (ScriptParams[1] == PEDTYPE_EMERGENCY) - ScriptParams[2] = PEDTYPE_EMERGENCY; - break; - case MI_FIREMAN: - if (ScriptParams[1] == PEDTYPE_FIREMAN) - ScriptParams[2] = PEDTYPE_FIREMAN; - break; - default: - break; - } - CPed* pPed; - if (ScriptParams[1] == PEDTYPE_COP) - pPed = new CCopPed((eCopType)ScriptParams[2]); - else if (ScriptParams[1] == PEDTYPE_EMERGENCY || ScriptParams[1] == PEDTYPE_FIREMAN) - pPed = new CEmergencyPed(ScriptParams[2]); - else - pPed = new CCivilianPed((ePedType)ScriptParams[1], ScriptParams[2]); - pPed->CharCreatedBy = MISSION_CHAR; - pPed->bRespondsToThreats = false; - pPed->bAllowMedicsToReviveMe = false; - pPed->SetPosition(pVehicle->GetPosition()); - pPed->SetOrientation(0.0f, 0.0f, 0.0f); - pPed->SetPedState(PED_DRIVING); - CPopulation::ms_nTotalMissionPeds++; - if (ScriptParams[3] >= 0) - pVehicle->AddPassenger(pPed, ScriptParams[3]); - else - pVehicle->AddPassenger(pPed); - pPed->m_pMyVehicle = pVehicle; - pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); - pPed->bInVehicle = true; - pPed->SetPedState(PED_DRIVING); - pVehicle->SetStatus(STATUS_PHYSICS); - pPed->bUsesCollision = false; -#ifdef FIX_BUGS - AnimationId anim = pVehicle->GetDriverAnim(); -#else - AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT; -#endif - pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); - pPed->StopNonPartialAnims(); - 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); - return 0; - } - case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_LEAVE_CAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); - return 0; - } - case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pVehicle); - return 0; - } - case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle); - return 0; - } - /* Not implemented. - case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR: - case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE: - case COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT: - */ - case COMMAND_SET_CHAR_OBJ_DESTROY_CAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_DESTROY_CAR, pVehicle); - return 0; - } - case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT: - { - CollectParameters(&m_nIp, 5); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - float infX = *(float*)&ScriptParams[1]; - float infY = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[1]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[2]; - } - CVector pos; - pos.x = (infX + supX) / 2; - pos.y = (infY + supY) / 2; - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = Max(pos.x - infX, pos.y - infY); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius); - return 0; - } - /* Not implemented. - case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR: - case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: - case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK: - */ - case COMMAND_SET_CHAR_AS_LEADER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget); - return 0; - } - case COMMAND_SET_PLAYER_AS_LEADER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; - pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget); - return 0; - } - case COMMAND_LEAVE_GROUP: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->ClearLeader(); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FOLLOW_ROUTE, ScriptParams[1], ScriptParams[2]); - return 0; - } - case COMMAND_ADD_ROUTE_POINT: - { - CollectParameters(&m_nIp, 4); - CRouteNode::AddRoutePoint(ScriptParams[0], *(CVector*)&ScriptParams[1]); - return 0; - } - case COMMAND_PRINT_WITH_NUMBER_BIG: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 3); - CMessages::AddBigMessageWithNumber(text, ScriptParams[1], ScriptParams[2] - 1, ScriptParams[0], -1, -1, -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_NUMBER: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 3); - CMessages::AddMessageWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_NUMBER_NOW: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 3); - CMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1); - return 0; - } - /* Not implemented. - case COMMAND_PRINT_WITH_NUMBER_SOON: - */ - case COMMAND_SWITCH_ROADS_ON: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX){ - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY){ - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ){ - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false); - return 0; - } - case COMMAND_SWITCH_ROADS_OFF: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true); - return 0; - } - case COMMAND_GET_NUMBER_OF_PASSENGERS: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - ScriptParams[0] = pVehicle->m_nNumPassengers; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - ScriptParams[0] = pVehicle->m_nNumMaxPassengers; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CAR_DENSITY_MULTIPLIER: - { - CollectParameters(&m_nIp, 1); - CCarCtrl::CarDensityMultiplier = *(float*)&ScriptParams[0]; - return 0; - } - case COMMAND_SET_CAR_HEAVY: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bIsHeavy = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_CLEAR_CHAR_THREAT_SEARCH: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->m_fearFlags = 0; - return 0; - } - case COMMAND_ACTIVATE_CRANE: - { - CollectParameters(&m_nIp, 10); - float infX = *(float*)&ScriptParams[2]; - float infY = *(float*)&ScriptParams[3]; - float supX = *(float*)&ScriptParams[4]; - float supY = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[4]; - supX = *(float*)&ScriptParams[2]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[5]; - supY = *(float*)&ScriptParams[3]; - } - CCranes::ActivateCrane(infX, supX, infY, supY, - *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8], - DEGTORAD(*(float*)&ScriptParams[9]), false, false, - *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); - return 0; - } - case COMMAND_DEACTIVATE_CRANE: - { - CollectParameters(&m_nIp, 2); - CCranes::DeActivateCrane(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); - return 0; - } - case COMMAND_SET_MAX_WANTED_LEVEL: - { - CollectParameters(&m_nIp, 1); - CWanted::SetMaximumWantedLevel(ScriptParams[0]); - return 0; - } - /* Debug commands? - case COMMAND_SAVE_VAR_INT: - case COMMAND_SAVE_VAR_FLOAT: - */ - case COMMAND_IS_CAR_IN_AIR_PROPER: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0); - return 0; - } - default: - script_assert(0); - } - return -1; -} - -int8 CRunningScript::ProcessCommands500To599(int32 command) -{ - switch (command) { - case COMMAND_IS_CAR_UPSIDEDOWN: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->GetUp().z <= -0.97f); - return 0; - } - case COMMAND_GET_PLAYER_CHAR: - { - CollectParameters(&m_nIp, 1); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_CANCEL_OVERRIDE_RESTART: - CRestart::CancelOverrideRestart(); - return 0; - case COMMAND_SET_POLICE_IGNORE_PLAYER: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - if (ScriptParams[1]) { - pPed->m_pWanted->m_bIgnoredByCops = true; - CWorld::StopAllLawEnforcersInTheirTracks(); - } - else { - pPed->m_pWanted->m_bIgnoredByCops = false; - } - return 0; - } - case COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 4); - CUserDisplay::Pager.AddMessageWithNumber(text, ScriptParams[0], -1, -1, -1, -1, -1, - ScriptParams[1], ScriptParams[2], ScriptParams[3]); - return 0; - } - case COMMAND_START_KILL_FRENZY: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 8); - CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2], - ScriptParams[3], text, ScriptParams[4], ScriptParams[5], - ScriptParams[6], ScriptParams[7] != 0, false); - return 0; - } - case COMMAND_READ_KILL_FRENZY_STATUS: - { - ScriptParams[0] = CDarkel::ReadStatus(); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SQRT: - { - CollectParameters(&m_nIp, 1); - *(float*)&ScriptParams[0] = Sqrt(*(float*)&ScriptParams[0]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D: - case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D: - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D: - case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D: - LocatePlayerCarCommand(command, &m_nIp); - return 0; - case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D: - case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D: - case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D: - case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D: - case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D: - case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D: - LocateCharCarCommand(command, &m_nIp); - return 0; - case COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE: - CollectParameters(&m_nIp, 2); - *(float*)&ScriptParams[0] = CGeneral::GetRandomNumberInRange(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_GENERATE_RANDOM_INT_IN_RANGE: - CollectParameters(&m_nIp, 2); - ScriptParams[0] = CGeneral::GetRandomNumberInRange(ScriptParams[0], ScriptParams[1]); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_LOCK_CAR_DOORS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1]; - return 0; - } - case COMMAND_EXPLODE_CAR: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->BlowUpCar(nil); - return 0; - } - case COMMAND_ADD_EXPLOSION: - CollectParameters(&m_nIp, 4); - CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0); - return 0; - - case COMMAND_IS_CAR_UPRIGHT: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->GetUp().z >= 0.0f); - return 0; - } - case COMMAND_TURN_CHAR_TO_FACE_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); - CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil; - CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition(); - CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition(); - float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI; - if (angle > TWOPI) - angle -= TWOPI; - if (!pVehicle) { - pSourcePed->m_fRotationCur = angle; - pSourcePed->m_fRotationDest = angle; - pSourcePed->SetHeading(angle); - } - return 0; - } - case COMMAND_TURN_CHAR_TO_FACE_PLAYER: - { - CollectParameters(&m_nIp, 2); - CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed; - CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil; - CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition(); - CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition(); - float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI; - if (angle > TWOPI) - angle -= TWOPI; - if (!pVehicle) { - pSourcePed->m_fRotationCur = angle; - pSourcePed->m_fRotationDest = angle; - pSourcePed->SetHeading(angle); - } - return 0; - } - case COMMAND_TURN_PLAYER_TO_FACE_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed; - CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); - CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil; - CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition(); - CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition(); - float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI; - if (angle > TWOPI) - angle -= TWOPI; - if (!pVehicle) { - pSourcePed->m_fRotationCur = angle; - pSourcePed->m_fRotationDest = angle; - pSourcePed->SetHeading(angle); - } - return 0; - } - case COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVector target; - target.x = *(float*)&ScriptParams[1]; - target.y = *(float*)&ScriptParams[2]; - target.z = CWorld::FindGroundZForCoord(target.x, target.y); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, target); - return 0; - } - /* Not implemented*/ - //case COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR: - case COMMAND_CREATE_PICKUP: - { - CollectParameters(&m_nIp, 5); - int16 model = ScriptParams[0]; - if (model < 0) - model = CTheScripts::UsedObjectArray[-model].index; - CVector pos = *(CVector*)&ScriptParams[2]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], 0); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_HAS_PICKUP_BEEN_COLLECTED: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CPickups::IsPickUpPickedUp(ScriptParams[0]) != 0); - return 0; - case COMMAND_REMOVE_PICKUP: - CollectParameters(&m_nIp, 1); - CPickups::RemovePickUp(ScriptParams[0]); - return 0; - case COMMAND_SET_TAXI_LIGHTS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - ((CAutomobile*)pVehicle)->SetTaxiLight(ScriptParams[1] != 0); - return 0; - } - case COMMAND_PRINT_BIG_Q: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 2); - CMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1); - return 0; - } - case COMMAND_PRINT_WITH_NUMBER_BIG_Q: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 3); - CMessages::AddBigMessageWithNumberQ(text, ScriptParams[1], ScriptParams[2] - 1, - ScriptParams[0], -1, -1, -1, -1, -1); - return 0; - } - case COMMAND_SET_GARAGE: - { - CollectParameters(&m_nIp, 7); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], 0); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_GARAGE_WITH_CAR_MODEL: - { - CollectParameters(&m_nIp, 8); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], ScriptParams[7]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE: - { - CollectParameters(&m_nIp, 2); - CVehicle* pTarget; - if (ScriptParams[1] >= 0) { - pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - } - else { - pTarget = nil; - } - CGarages::SetTargetCarForMissonGarage(ScriptParams[0], pTarget); - return 0; - } - case COMMAND_IS_CAR_IN_MISSION_GARAGE: - 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); - float f1 = *(float*)&ScriptParams[0]; - float f2 = *(float*)&ScriptParams[1]; - float f3 = *(float*)&ScriptParams[2]; - float f4 = *(float*)&ScriptParams[3]; - float f5 = *(float*)&ScriptParams[4]; - float f6 = *(float*)&ScriptParams[5]; - float temp; - - if (f1 > f4) { - temp = f1; - f1 = f4; - f4 = temp; - } - - if (f2 > f5) { - temp = f2; - f2 = f5; - f5 = temp; - } - - if (f3 > f6) { - temp = f3; - f3 = f6; - f6 = temp; - } - - CPowerPoints::GenerateNewOne(f1, f2, f3, f4, f5, f6, *(uint8*)&ScriptParams[6]); - - return 0; - } -#endif // GTA_PS2 - case COMMAND_SET_ALL_TAXI_LIGHTS: - CollectParameters(&m_nIp, 1); - CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0); - return 0; - case COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB: - { - CollectParameters(&m_nIp, 1); - CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pCar); - script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR); - UpdateCompareFlag(pCar->m_bombType != 0); //TODO: enum - return 0; - } - case COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR: - CollectParameters(&m_nIp, 2); - CPad::GetPad(ScriptParams[0])->bApplyBrakes = (ScriptParams[1] != 0); - return 0; - case COMMAND_SET_PLAYER_HEALTH: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - pPed->m_fHealth = ScriptParams[1]; - return 0; - } - case COMMAND_SET_CHAR_HEALTH: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - if (ScriptParams[1]) { - pPed->m_fHealth = ScriptParams[1]; - } - else if (pPed->bInVehicle) { - pPed->SetDead(); - if (!pPed->IsPlayer()) - pPed->FlagToDestroyWhenNextProcessed(); - } - else { - pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } - return 0; - } - case COMMAND_SET_CAR_HEALTH: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->m_fHealth = ScriptParams[1]; - return 0; - } - case COMMAND_GET_PLAYER_HEALTH: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - ScriptParams[0] = pPed->m_fHealth; // correct cast float to int - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_CHAR_HEALTH: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - ScriptParams[0] = pPed->m_fHealth; // correct cast float to int - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_CAR_HEALTH: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - ScriptParams[0] = pVehicle->m_fHealth; // correct cast float to int - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_IS_CAR_ARMED_WITH_BOMB: - { - CollectParameters(&m_nIp, 2); - CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pCar); - script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR); - UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]); //TODO: enum - return 0; - } - case COMMAND_CHANGE_CAR_COLOUR: - { - CollectParameters(&m_nIp, 3); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - if (ScriptParams[1] >= 256 || ScriptParams[2] >= 256) - debug("CHANGE_CAR_COLOUR - Colours must be less than %d", 256); - pVehicle->m_currentColour1 = ScriptParams[1]; - pVehicle->m_currentColour2 = ScriptParams[2]; - return 0; - } - case COMMAND_SWITCH_PED_ROADS_ON: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false); - return 0; - } - case COMMAND_SWITCH_PED_ROADS_OFF: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true); - return 0; - } - case COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS: - { - CollectParameters(&m_nIp, 2); - CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pSourcePed); - CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pTargetPed); - pSourcePed->SetLookFlag(pTargetPed, true); - pSourcePed->SetLookTimer(60000); - return 0; - } - case COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS: - { - CollectParameters(&m_nIp, 2); - CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pSourcePed); - CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed; - script_assert(pTargetPed); - pSourcePed->SetLookFlag(pTargetPed, true); - pSourcePed->SetLookTimer(60000); - return 0; - } - case COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS: - { - CollectParameters(&m_nIp, 2); - CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pSourcePed); - CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pTargetPed); - pSourcePed->SetLookFlag(pTargetPed, true); - pSourcePed->SetLookTimer(60000); - return 0; - } - case COMMAND_STOP_CHAR_LOOKING: - { - CollectParameters(&m_nIp, 1); - CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pSourcePed); - pSourcePed->ClearLookFlag(); - pSourcePed->bKeepTryingToLook = false; - if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY) - pSourcePed->RestorePreviousState(); - return 0; - } - case COMMAND_STOP_PLAYER_LOOKING: - { - CollectParameters(&m_nIp, 1); - CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pSourcePed); - pSourcePed->ClearLookFlag(); - pSourcePed->bKeepTryingToLook = false; - if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY) - pSourcePed->RestorePreviousState(); - return 0; - } - case COMMAND_SWITCH_HELICOPTER: - CollectParameters(&m_nIp, 1); - CHeli::ActivateHeli(ScriptParams[0] != 0); - return 0; - - //case COMMAND_SET_GANG_ATTITUDE: - //case COMMAND_SET_GANG_GANG_ATTITUDE: - //case COMMAND_SET_GANG_PLAYER_ATTITUDE: - //case COMMAND_SET_GANG_PED_MODELS: - case COMMAND_SET_GANG_CAR_MODEL: - CollectParameters(&m_nIp, 2); - CGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_SET_GANG_WEAPONS: - CollectParameters(&m_nIp, 3); - CGangs::SetGangWeapons(ScriptParams[0], (eWeaponType)ScriptParams[1], (eWeaponType)ScriptParams[2]); - return 0; - case COMMAND_SET_CHAR_OBJ_RUN_TO_AREA: - { - CollectParameters(&m_nIp, 5); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - float infX = *(float*)&ScriptParams[1]; - float infY = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[1]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[2]; - } - CVector pos; - pos.x = (infX + supX) / 2; - pos.y = (infY + supY) / 2; - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = Max(pos.x - infX, pos.y - infY); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius); - return 0; - } - case COMMAND_SET_CHAR_OBJ_RUN_TO_COORD: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVector pos; - pos.x = *(float*)&ScriptParams[1]; - pos.y = *(float*)&ScriptParams[2]; - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos); - return 0; - } - case COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); - bool isTouching = false; - if (pPed->bInVehicle) - isTouching = false; - else if (pPed->GetHasCollidedWith(pObject)) - isTouching = true; - UpdateCompareFlag(isTouching); - return 0; - } - case COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); - bool isTouching = false; - if (pPed->InVehicle()) - isTouching = false; - else if (pPed->GetHasCollidedWith(pObject)) - isTouching = true; - UpdateCompareFlag(isTouching); - return 0; - } - case COMMAND_LOAD_SPECIAL_CHARACTER: - { - CollectParameters(&m_nIp, 1); - char name[16]; - strncpy(name, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - name[i] = tolower(name[i]); - CStreaming::RequestSpecialChar(ScriptParams[0] - 1, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED); - m_nIp += KEY_LENGTH_IN_SCRIPT; - return 0; - } - case COMMAND_HAS_SPECIAL_CHARACTER_LOADED: - { - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CStreaming::HasSpecialCharLoaded(ScriptParams[0] - 1)); - return 0; - } - case COMMAND_FLASH_CAR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bHasBlip = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_FLASH_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bHasBlip = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_FLASH_OBJECT: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - pObject->bHasBlip = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_IS_PLAYER_IN_REMOTE_MODE: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CWorld::Players[ScriptParams[0]].IsPlayerInRemoteMode()); - return 0; - case COMMAND_ARM_CAR_WITH_BOMB: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - ((CAutomobile*)pVehicle)->m_bombType = ScriptParams[1]; - ((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed(); - return 0; - } - case COMMAND_SET_CHAR_PERSONALITY: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->SetPedStats((ePedStats)ScriptParams[1]); - return 0; - } - case COMMAND_SET_CUTSCENE_OFFSET: - CollectParameters(&m_nIp, 3); - CCutsceneMgr::SetCutsceneOffset(*(CVector*)&ScriptParams[0]); - return 0; - case COMMAND_SET_ANIM_GROUP_FOR_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->m_animGroup = (AssocGroupId)ScriptParams[1]; - return 0; - } - case COMMAND_SET_ANIM_GROUP_FOR_PLAYER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - pPed->m_animGroup = (AssocGroupId)ScriptParams[1]; - return 0; - } - case COMMAND_REQUEST_MODEL: - { - CollectParameters(&m_nIp, 1); - int model = ScriptParams[0]; - if (model < 0) - model = CTheScripts::UsedObjectArray[-model].index; - CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_NOFADE | STREAMFLAGS_SCRIPTOWNED); - return 0; - } - case COMMAND_HAS_MODEL_LOADED: - { - CollectParameters(&m_nIp, 1); - int model = ScriptParams[0]; - if (model < 0) - model = CTheScripts::UsedObjectArray[-model].index; - UpdateCompareFlag(CStreaming::HasModelLoaded(model)); - return 0; - } - case COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED: - { - CollectParameters(&m_nIp, 1); - int model = ScriptParams[0]; - if (model < 0) - model = CTheScripts::UsedObjectArray[-model].index; - CStreaming::SetMissionDoesntRequireModel(model); - return 0; - } - case COMMAND_GRAB_PHONE: - { - CollectParameters(&m_nIp, 2); - ScriptParams[0] = gPhoneInfo.GrabPhone(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_REPEATED_PHONE_MESSAGE: - { - CollectParameters(&m_nIp, 1); - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text, nil, nil, nil, nil, nil); - return 0; - } - case COMMAND_SET_PHONE_MESSAGE: - { - CollectParameters(&m_nIp, 1); - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text, nil, nil, nil, nil, nil); - return 0; - } - case COMMAND_HAS_PHONE_DISPLAYED_MESSAGE: - { - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0])); - return 0; - } - case COMMAND_TURN_PHONE_OFF: - { - CollectParameters(&m_nIp, 1); - gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], nil, nil, nil, nil, nil, nil); - return 0; - } - case COMMAND_DRAW_CORONA: - { - CollectParameters(&m_nIp, 9); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], - 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f); - return 0; - } - case COMMAND_DRAW_LIGHT: - { - CollectParameters(&m_nIp, 6); - CVector pos = *(CVector*)&ScriptParams[0]; - CVector unused(0.0f, 0.0f, 0.0f); - CPointLights::AddLight(0, *(CVector*)&ScriptParams[0], CVector(0.0f, 0.0f, 0.0f), 12.0f, - ScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true); - return 0; - } - case COMMAND_STORE_WEATHER: - CWeather::StoreWeatherState(); - return 0; - case COMMAND_RESTORE_WEATHER: - CWeather::RestoreWeatherState(); - return 0; - case COMMAND_STORE_CLOCK: - CClock::StoreClock(); - return 0; - case COMMAND_RESTORE_CLOCK: - CClock::RestoreClock(); - return 0; - case COMMAND_RESTART_CRITICAL_MISSION: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CRestart::OverrideNextRestart(pos, *(float*)&ScriptParams[3]); - if (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING) - printf("RESTART_CRITICAL_MISSION - Player state is not PLAYING\n"); - CWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission(); - return 0; - } - case COMMAND_IS_PLAYER_PLAYING: - { - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_PLAYING); - return 0; - } - //case COMMAND_SET_COLL_OBJ_NO_OBJ: - default: - script_assert(0); - } - return -1; -} - -int8 CRunningScript::ProcessCommands600To699(int32 command) -{ - switch (command){ - /* Collective commands are not implemented until LCS. - case COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT: - case COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE: - case COMMAND_SET_COLL_OBJ_GUARD_SPOT: - case COMMAND_SET_COLL_OBJ_GUARD_AREA: - case COMMAND_SET_COLL_OBJ_WAIT_IN_CAR: - case COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT: - case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT: - case COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS: - case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS: - case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE: - case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE: - case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS: - case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS: - case COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT: - case COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT: - case COMMAND_SET_COLL_OBJ_LEAVE_CAR: - case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER: - case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER: - case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR: - case COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE: - case COMMAND_SET_COLL_OBJ_DESTROY_OBJECT: - case COMMAND_SET_COLL_OBJ_DESTROY_CAR: - case COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT: - case COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR: - case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: - case COMMAND_SET_COLL_OBJ_GUARD_ATTACK: - case COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE: - case COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT: - case COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR: - case COMMAND_SET_COLL_OBJ_RUN_TO_AREA: - case COMMAND_SET_COLL_OBJ_RUN_TO_COORD: - case COMMAND_ADD_PEDS_IN_AREA_TO_COLL: - case COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL: - case COMMAND_CLEAR_COLL: - case COMMAND_IS_COLL_IN_CARS: - case COMMAND_LOCATE_COLL_ANY_MEANS_2D: - case COMMAND_LOCATE_COLL_ON_FOOT_2D: - case COMMAND_LOCATE_COLL_IN_CAR_2D: - case COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D: - case COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D: - case COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D: - case COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D: - case COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D: - case COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D: - case COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D: - case COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D: - case COMMAND_LOCATE_COLL_IN_CAR_CAR_2D: - case COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D: - case COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D: - case COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D: - case COMMAND_IS_COLL_IN_AREA_2D: - case COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_COLL_IN_AREA_IN_CAR_2D: - case COMMAND_IS_COLL_STOPPED_IN_AREA_2D: - case COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D: - case COMMAND_GET_NUMBER_OF_PEDS_IN_COLL: - */ - case COMMAND_SET_CHAR_HEED_THREATS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bRespondsToThreats = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_PLAYER_HEED_THREATS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - pPed->bRespondsToThreats = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_GET_CONTROLLER_MODE: -#if defined(GTA_PC) && !defined(DETECT_PAD_INPUT_SWITCH) - ScriptParams[0] = 0; -#else - ScriptParams[0] = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0; -#endif - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_SET_CAN_RESPRAY_CAR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - ((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0); - return 0; - } - case COMMAND_IS_TAXI: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - int mi = pVehicle->GetModelIndex(); - UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE); - return 0; - } - case COMMAND_UNLOAD_SPECIAL_CHARACTER: - CollectParameters(&m_nIp, 1); - CStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1); - return 0; - case COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER: - CDarkel::ResetModelsKilledByPlayer(); - return 0; - case COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER: - CollectParameters(&m_nIp, 1); - ScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_ACTIVATE_GARAGE: - CollectParameters(&m_nIp, 1); - CGarages::ActivateGarage(ScriptParams[0]); - return 0; - case COMMAND_SWITCH_TAXI_TIMER: - { - CollectParameters(&m_nIp, 1); - if (ScriptParams[0] != 0){ - CWorld::Players[CWorld::PlayerInFocus].m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds(); - CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = true; - }else{ - CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = false; - } - return 0; - } - case COMMAND_CREATE_OBJECT_NO_OFFSET: - { - CollectParameters(&m_nIp, 4); - int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index; - CObject* pObj = new CObject(mi, false); -; pObj->ObjectCreatedBy = MISSION_OBJECT; - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pObj->SetPosition(pos); - pObj->SetOrientation(0.0f, 0.0f, 0.0f); - pObj->GetMatrix().UpdateRW(); - pObj->UpdateRwFrame(); - CTheScripts::ClearSpaceForMissionEntity(pos, pObj); - CWorld::Add(pObj); - ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj); - StoreParameters(&m_nIp, 1); - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT); - return 0; - } - case COMMAND_IS_BOAT: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); - return 0; - } - case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS: - { - CollectParameters(&m_nIp, 5); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - float infX = *(float*)&ScriptParams[1]; - float infY = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[1]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[2]; - } - CVector pos; - pos.x = (infX + supX) / 2; - pos.y = (infY + supY) / 2; - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = Max(pos.x - infX, pos.y - infY); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius); - return 0; - } - //case COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS: - case COMMAND_IS_PLAYER_STOPPED: - { - CollectParameters(&m_nIp, 1); - CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; - UpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer)); - return 0; - } - case COMMAND_IS_CHAR_STOPPED: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(CTheScripts::IsPedStopped(pPed)); - return 0; - } - case COMMAND_MESSAGE_WAIT: - CollectParameters(&m_nIp, 2); - m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0]; - if (ScriptParams[1] != 0) - m_bSkipWakeTime = true; - return 1; - case COMMAND_ADD_PARTICLE_EFFECT: - { - CollectParameters(&m_nIp, 5); - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0); - return 0; - } - case COMMAND_SWITCH_WIDESCREEN: - CollectParameters(&m_nIp, 1); - if (ScriptParams[0] != 0) - TheCamera.SetWideScreenOn(); - else - TheCamera.SetWideScreenOff(); - return 0; - case COMMAND_ADD_SPRITE_BLIP_FOR_CAR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int id = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH); - CRadar::SetBlipSprite(id, ScriptParams[1]); - ScriptParams[0] = id; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_SPRITE_BLIP_FOR_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int id = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH); - CRadar::SetBlipSprite(id, ScriptParams[1]); - ScriptParams[0] = id; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int id = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH); - CRadar::SetBlipSprite(id, ScriptParams[1]); - ScriptParams[0] = id; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int id = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH); - CRadar::SetBlipSprite(id, ScriptParams[3]); - ScriptParams[0] = id; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_SPRITE_BLIP_FOR_COORD: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int id = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH); - CRadar::SetBlipSprite(id, ScriptParams[3]); - ScriptParams[0] = id; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bOnlyDamagedByPlayer = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bOnlyDamagedByPlayer = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_CHAR_PROOFS: - { - CollectParameters(&m_nIp, 6); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bBulletProof = (ScriptParams[1] != 0); - pPed->bFireProof = (ScriptParams[2] != 0); - pPed->bExplosionProof = (ScriptParams[3] != 0); - pPed->bCollisionProof = (ScriptParams[4] != 0); - pPed->bMeleeProof = (ScriptParams[5] != 0); - return 0; - } - case COMMAND_SET_CAR_PROOFS: - { - CollectParameters(&m_nIp, 6); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bBulletProof = (ScriptParams[1] != 0); - pVehicle->bFireProof = (ScriptParams[2] != 0); - pVehicle->bExplosionProof = (ScriptParams[3] != 0); - pVehicle->bCollisionProof = (ScriptParams[4] != 0); - pVehicle->bMeleeProof = (ScriptParams[5] != 0); - return 0; - } - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: - PlayerInAngledAreaCheckCommand(command, &m_nIp); - return 0; - case COMMAND_DEACTIVATE_GARAGE: - CollectParameters(&m_nIp, 1); - CGarages::DeActivateGarage(ScriptParams[0]); - return 0; - case COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE: - CollectParameters(&m_nIp, 1); - ScriptParams[0] = CGarages::QueryCarsCollected(ScriptParams[0]); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE: - CollectParameters(&m_nIp, 2); - UpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1)); - return 0; - default: - script_assert(0); - } - return -1; -} - -int8 CRunningScript::ProcessCommands700To799(int32 command) -{ - switch (command){ - case COMMAND_SET_SWAT_REQUIRED: - CollectParameters(&m_nIp, 1); - FindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0); - return 0; - case COMMAND_SET_FBI_REQUIRED: - CollectParameters(&m_nIp, 1); - FindPlayerPed()->m_pWanted->m_bFbiRequired = (ScriptParams[0] != 0); - return 0; - case COMMAND_SET_ARMY_REQUIRED: - CollectParameters(&m_nIp, 1); - FindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0); - return 0; - case COMMAND_IS_CAR_IN_WATER: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(pVehicle && pVehicle->bIsInWater); - return 0; - } - case COMMAND_GET_CLOSEST_CHAR_NODE: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)]; - *(CVector*)&ScriptParams[0] = pNode->GetPosition(); - StoreParameters(&m_nIp, 3); - return 0; - } - case COMMAND_GET_CLOSEST_CAR_NODE: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)]; - *(CVector*)&ScriptParams[0] = pNode->GetPosition(); - StoreParameters(&m_nIp, 3); - return 0; - } - case COMMAND_CAR_GOTO_COORDINATES_ACCURATE: - { - CollectParameters(&m_nIp, 4); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); - if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pos, false)) - pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE; - else - pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE; - pVehicle->SetStatus(STATUS_PHYSICS); - pVehicle->bEngineOn = true; - pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); - pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); - return 0; - } - case COMMAND_START_PACMAN_RACE: - CollectParameters(&m_nIp, 1); - CPacManPickups::StartPacManRace(ScriptParams[0]); - return 0; - case COMMAND_START_PACMAN_RECORD: - CPacManPickups::StartPacManRecord(); - return 0; - case COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN: - ScriptParams[0] = CPacManPickups::QueryPowerPillsEatenInRace(); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_CLEAR_PACMAN: - CPacManPickups::CleanUpPacManStuff(); - return 0; - case COMMAND_START_PACMAN_SCRAMBLE: - { - CollectParameters(&m_nIp, 5); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CPacManPickups::StartPacManScramble(pos, *(float*)&ScriptParams[3], ScriptParams[4]); - return 0; - } - case COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED: - ScriptParams[0] = CPacManPickups::QueryPowerPillsCarriedByPlayer(); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED: - CPacManPickups::ResetPowerPillsCarriedByPlayer(); - return 0; - case COMMAND_IS_CAR_ON_SCREEN: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(TheCamera.IsSphereVisible(pVehicle->GetBoundCentre(), pVehicle->GetBoundRadius())); - return 0; - } - case COMMAND_IS_CHAR_ON_SCREEN: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(TheCamera.IsSphereVisible(pPed->GetBoundCentre(), pPed->GetBoundRadius())); - return 0; - } - case COMMAND_IS_OBJECT_ON_SCREEN: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - UpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius())); - return 0; - } - case COMMAND_GOSUB_FILE: - { - CollectParameters(&m_nIp, 2); - script_assert(m_nStackPointer < MAX_STACK_DEPTH); - m_anStack[m_nStackPointer++] = m_nIp; - SetIP(ScriptParams[0]); - // ScriptParams[1] == filename - return 0; - } - case COMMAND_GET_GROUND_Z_FOR_3D_COORD: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - bool success; - *(float*)&ScriptParams[0] = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &success); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_START_SCRIPT_FIRE: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - ScriptParams[0] = gFireManager.StartScriptFire(pos, nil, 0.8f, 1); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(gFireManager.IsScriptFireExtinguish(ScriptParams[0])); - return 0; - case COMMAND_REMOVE_SCRIPT_FIRE: - CollectParameters(&m_nIp, 1); - gFireManager.RemoveScriptFire(ScriptParams[0]); - return 0; - case COMMAND_SET_COMEDY_CONTROLS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bComedyControls = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_BOAT_GOTO_COORDS: - { - CollectParameters(&m_nIp, 4); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); - CBoat* pBoat = (CBoat*)pVehicle; - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false); - pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS; - pBoat->AutoPilot.m_vecDestinationCoors = pos; - pBoat->SetStatus(STATUS_PHYSICS); - pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed); - pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); - return 0; - } - case COMMAND_BOAT_STOP: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); - CBoat* pBoat = (CBoat*)pVehicle; - pBoat->AutoPilot.m_nCarMission = MISSION_NONE; - pBoat->SetStatus(STATUS_PHYSICS); - pBoat->bEngineOn = false; - pBoat->AutoPilot.m_nCruiseSpeed = 0; - return 0; - } - case COMMAND_IS_PLAYER_SHOOTING_IN_AREA: - { - CollectParameters(&m_nIp, 6); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - float x1 = *(float*)&ScriptParams[1]; - float y1 = *(float*)&ScriptParams[2]; - float x2 = *(float*)&ScriptParams[3]; - float y2 = *(float*)&ScriptParams[4]; - UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); - if (ScriptParams[5]) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) - CTheScripts::DrawDebugSquare(x1, y1, x2, y2); - return 0; - } - case COMMAND_IS_CHAR_SHOOTING_IN_AREA: - { - CollectParameters(&m_nIp, 6); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - float x1 = *(float*)&ScriptParams[1]; - float y1 = *(float*)&ScriptParams[2]; - float x2 = *(float*)&ScriptParams[3]; - float y2 = *(float*)&ScriptParams[4]; - UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); - if (ScriptParams[5]) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) - CTheScripts::DrawDebugSquare(x1, y1, x2, y2); - return 0; - } - case COMMAND_IS_CURRENT_PLAYER_WEAPON: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType); - return 0; - } - case COMMAND_IS_CURRENT_CHAR_WEAPON: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType); - return 0; - } - case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN: - CPacManPickups::ResetPowerPillsEatenInRace(); - return 0; - case COMMAND_ADD_POWER_PILL: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CPacManPickups::GenerateOnePMPickUp(pos); - return 0; - } - case COMMAND_SET_BOAT_CRUISE_SPEED: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); - CBoat* pBoat = (CBoat*)pVehicle; - pBoat->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1]; - return 0; - } - case COMMAND_GET_RANDOM_CHAR_IN_AREA: - { - CollectParameters(&m_nIp, 4); - int ped_handle = -1; - CVector pos = FindPlayerCoors(); - float x1 = *(float*)&ScriptParams[0]; - float y1 = *(float*)&ScriptParams[1]; - float x2 = *(float*)&ScriptParams[2]; - float y2 = *(float*)&ScriptParams[3]; - int i = CPools::GetPedPool()->GetSize(); - while (--i && ped_handle == -1){ - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (!pPed) - continue; - if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) - continue; - if (pPed->CharCreatedBy != RANDOM_CHAR) - continue; - if (!pPed->IsPedInControl()) - continue; - if (pPed->bRemoveFromWorld) - continue; - if (pPed->bFadeOut) - continue; - if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN) - continue; - if (!ThisIsAValidRandomPed(pPed->m_nPedType)) - continue; - if (pPed->bIsLeader || pPed->m_leader) - continue; - if (!pPed->IsWithinArea(x1, y1, x2, y2)) - continue; - if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) - continue; - if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) - continue; - ped_handle = CPools::GetPedPool()->GetIndex(pPed); - CTheScripts::LastRandomPedId = ped_handle; - pPed->CharCreatedBy = MISSION_CHAR; - pPed->bRespondsToThreats = false; - ++CPopulation::ms_nTotalMissionPeds; - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); - } - ScriptParams[0] = ped_handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_RANDOM_CHAR_IN_ZONE: - { - char zone[KEY_LENGTH_IN_SCRIPT]; - strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone); - if (nZone != -1) - m_nIp += KEY_LENGTH_IN_SCRIPT; - CZone* pZone = CTheZones::GetZone(nZone); - int ped_handle = -1; - CVector pos = FindPlayerCoors(); - int i = CPools::GetPedPool()->GetSize(); - while (--i && ped_handle == -1) { - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (!pPed) - continue; - if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) - continue; - if (pPed->CharCreatedBy != RANDOM_CHAR) - continue; - if (!pPed->IsPedInControl()) - continue; - if (pPed->bRemoveFromWorld) - continue; - if (pPed->bFadeOut) - continue; - if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN) - continue; - if (!ThisIsAValidRandomPed(pPed->m_nPedType)) - continue; - if (pPed->bIsLeader || pPed->m_leader) - continue; - if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone)) - continue; - if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) - continue; - if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) - continue; - ped_handle = CPools::GetPedPool()->GetIndex(pPed); - CTheScripts::LastRandomPedId = ped_handle; - pPed->CharCreatedBy = MISSION_CHAR; - pPed->bRespondsToThreats = false; - ++CPopulation::ms_nTotalMissionPeds; - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); - } - ScriptParams[0] = ped_handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_IS_PLAYER_IN_TAXI: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->IsTaxi()); - return 0; - } - case COMMAND_IS_PLAYER_SHOOTING: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - UpdateCompareFlag(pPed->bIsShooting); - return 0; - } - case COMMAND_IS_CHAR_SHOOTING: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(pPed->bIsShooting); - return 0; - } - case COMMAND_CREATE_MONEY_PICKUP: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_MONEY, PICKUP_MONEY, ScriptParams[3]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CHAR_ACCURACY: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->m_wepAccuracy = ScriptParams[1]; - return 0; - } - case COMMAND_GET_CAR_SPEED: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - *(float*)&ScriptParams[0] = pVehicle->GetSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_LOAD_CUTSCENE: - { - char name[KEY_LENGTH_IN_SCRIPT]; - strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CCutsceneMgr::LoadCutsceneData(name); - return 0; - } - case COMMAND_CREATE_CUTSCENE_OBJECT: - { - CollectParameters(&m_nIp, 1); - CCutsceneObject* pCutObj = CCutsceneMgr::CreateCutsceneObject(ScriptParams[0]); - ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutObj); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CUTSCENE_ANIM: - { - CollectParameters(&m_nIp, 1); - char name[KEY_LENGTH_IN_SCRIPT]; - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CCutsceneMgr::SetCutsceneAnim(name, pObject); - return 0; - } - case COMMAND_START_CUTSCENE: - CCutsceneMgr::ms_cutsceneLoadStatus = 1; - return 0; - case COMMAND_GET_CUTSCENE_TIME: - ScriptParams[0] = CCutsceneMgr::GetCutsceneTimeInMilleseconds(); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_HAS_CUTSCENE_FINISHED: - UpdateCompareFlag(CCutsceneMgr::HasCutsceneFinished()); - return 0; - case COMMAND_CLEAR_CUTSCENE: - CCutsceneMgr::DeleteCutsceneData(); - return 0; - case COMMAND_RESTORE_CAMERA_JUMPCUT: - TheCamera.RestoreWithJumpCut(); - return 0; - case COMMAND_CREATE_COLLECTABLE1: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - CPickups::GenerateNewOne(pos, MI_COLLECTABLE1, PICKUP_COLLECTABLE1, 0); - return 0; - } - case COMMAND_SET_COLLECTABLE1_TOTAL: - CollectParameters(&m_nIp, 1); - CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0]; - return 0; - case COMMAND_IS_PROJECTILE_IN_AREA: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, false)); - if (CTheScripts::DbgFlag) - CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); - return 0; - } - case COMMAND_DESTROY_PROJECTILES_IN_AREA: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, true)); - if (CTheScripts::DbgFlag) - CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); - return 0; - } - case COMMAND_DROP_MINE: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - CPickups::GenerateNewOne(pos, MI_CARMINE, PICKUP_MINE_INACTIVE, 0); - return 0; - } - case COMMAND_DROP_NAUTICAL_MINE: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0); - return 0; - } - case COMMAND_IS_CHAR_MODEL: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(ScriptParams[1] == pPed->GetModelIndex()); - return 0; - } - case COMMAND_LOAD_SPECIAL_MODEL: - { - CollectParameters(&m_nIp, 1); - char name[KEY_LENGTH_IN_SCRIPT]; - strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - name[i] = tolower(name[i]); - CStreaming::RequestSpecialModel(ScriptParams[0], name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED); - m_nIp += KEY_LENGTH_IN_SCRIPT; - return 0; - } - case COMMAND_CREATE_CUTSCENE_HEAD: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]); - ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CUTSCENE_HEAD_ANIM: - { - CollectParameters(&m_nIp, 1); - CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pCutHead); - char name[KEY_LENGTH_IN_SCRIPT]; - strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CTimer::Stop(); - CCutsceneMgr::SetHeadAnim(name, pCutHead); - CTimer::Update(); - return 0; - } - case COMMAND_SIN: - CollectParameters(&m_nIp, 1); - *(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0])); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_COS: - CollectParameters(&m_nIp, 1); - *(float*)&ScriptParams[0] = Cos(DEGTORAD(*(float*)&ScriptParams[0])); - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_GET_CAR_FORWARD_X: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - float forwardX = pVehicle->GetForward().x / pVehicle->GetForward().Magnitude2D(); - *(float*)&ScriptParams[0] = forwardX; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_CAR_FORWARD_Y: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - float forwardY = pVehicle->GetForward().y / pVehicle->GetForward().Magnitude2D(); - *(float*)&ScriptParams[0] = forwardY; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_CHANGE_GARAGE_TYPE: - CollectParameters(&m_nIp, 2); - CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], 0); - return 0; - case COMMAND_ACTIVATE_CRUSHER_CRANE: - { - CollectParameters(&m_nIp, 10); - float infX = *(float*)&ScriptParams[2]; - float infY = *(float*)&ScriptParams[3]; - float supX = *(float*)&ScriptParams[4]; - float supY = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[4]; - supX = *(float*)&ScriptParams[2]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[5]; - supY = *(float*)&ScriptParams[3]; - } - CCranes::ActivateCrane(infX, supX, infY, supY, - *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8], - DEGTORAD(*(float*)&ScriptParams[9]), true, false, - *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); - return 0; - } - case COMMAND_PRINT_WITH_2_NUMBERS: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 4); - CMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_2_NUMBERS_NOW: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 4); - CMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_2_NUMBERS_SOON: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 4); - CMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_3_NUMBERS: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 5); - CMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_3_NUMBERS_NOW: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 5); - CMessages::AddMessageJumpQWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_3_NUMBERS_SOON: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 5); - CMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_4_NUMBERS: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 6); - CMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_4_NUMBERS_NOW: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 6); - CMessages::AddMessageJumpQWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_4_NUMBERS_SOON: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 6); - CMessages::AddMessageSoonWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_5_NUMBERS: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 7); - CMessages::AddMessageWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); - return 0; - } - case COMMAND_PRINT_WITH_5_NUMBERS_NOW: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 7); - CMessages::AddMessageJumpQWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); - return 0; - } - case COMMAND_PRINT_WITH_5_NUMBERS_SOON: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 7); - CMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); - return 0; - } - case COMMAND_PRINT_WITH_6_NUMBERS: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 8); - CMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); - return 0; - } - case COMMAND_PRINT_WITH_6_NUMBERS_NOW: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 8); - CMessages::AddMessageJumpQWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); - return 0; - } - case COMMAND_PRINT_WITH_6_NUMBERS_SOON: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 8); - CMessages::AddMessageSoonWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, pTargetPed); - pPed->SetFormation((eFormation)ScriptParams[2]); - return 0; - } - case COMMAND_PLAYER_MADE_PROGRESS: - CollectParameters(&m_nIp, 1); - CStats::ProgressMade += ScriptParams[0]; - return 0; - case COMMAND_SET_PROGRESS_TOTAL: - CollectParameters(&m_nIp, 1); - CStats::TotalProgressInGame = ScriptParams[0]; - return 0; - case COMMAND_REGISTER_JUMP_DISTANCE: - CollectParameters(&m_nIp, 1); - CStats::MaximumJumpDistance = Max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]); - return 0; - case COMMAND_REGISTER_JUMP_HEIGHT: - CollectParameters(&m_nIp, 1); - CStats::MaximumJumpHeight = Max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]); - return 0; - case COMMAND_REGISTER_JUMP_FLIPS: - CollectParameters(&m_nIp, 1); - CStats::MaximumJumpFlips = Max(CStats::MaximumJumpFlips, ScriptParams[0]); - return 0; - case COMMAND_REGISTER_JUMP_SPINS: - CollectParameters(&m_nIp, 1); - CStats::MaximumJumpSpins = Max(CStats::MaximumJumpSpins, ScriptParams[0]); - return 0; - case COMMAND_REGISTER_JUMP_STUNT: - CollectParameters(&m_nIp, 1); - CStats::BestStuntJump = Max(CStats::BestStuntJump, ScriptParams[0]); - return 0; - case COMMAND_REGISTER_UNIQUE_JUMP_FOUND: - ++CStats::NumberOfUniqueJumpsFound; - return 0; - case COMMAND_SET_UNIQUE_JUMPS_TOTAL: - CollectParameters(&m_nIp, 1); - CStats::TotalNumberOfUniqueJumps = ScriptParams[0]; - return 0; - case COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI: - ++CStats::PassengersDroppedOffWithTaxi; - return 0; - case COMMAND_REGISTER_MONEY_MADE_TAXI: - CollectParameters(&m_nIp, 1); - CStats::MoneyMadeWithTaxi += ScriptParams[0]; - return 0; - case COMMAND_REGISTER_MISSION_GIVEN: - ++CStats::MissionsGiven; - return 0; - case COMMAND_REGISTER_MISSION_PASSED: - { - char name[KEY_LENGTH_IN_SCRIPT]; - strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - m_nIp += KEY_LENGTH_IN_SCRIPT; - strncpy(CStats::LastMissionPassedName, name, KEY_LENGTH_IN_SCRIPT); - ++CStats::MissionsPassed; - CStats::CheckPointReachedSuccessfully(); - return 0; - } - case COMMAND_SET_CHAR_RUNNING: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bIsRunning = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_REMOVE_ALL_SCRIPT_FIRES: - gFireManager.RemoveAllScriptFires(); - return 0; - case COMMAND_IS_FIRST_CAR_COLOUR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->m_currentColour1 == ScriptParams[1]); - return 0; - } - case COMMAND_IS_SECOND_CAR_COLOUR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]); - return 0; - } - case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - if (!pPed) - printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n"); - UpdateCompareFlag(pPed && pPed->m_lastWepDam == ScriptParams[1]); - return 0; - } - case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - if (!pVehicle) - printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n"); - UpdateCompareFlag(pVehicle && pVehicle->m_nLastWeaponDamage == ScriptParams[1]); - return 0; - } - case COMMAND_IS_CHAR_IN_CHARS_GROUP: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pPed); - script_assert(pLeader); - UpdateCompareFlag(pPed->m_leader == pLeader); - return 0; - } - default: - script_assert(0); - } - return -1; -} -int8 CRunningScript::ProcessCommands800To899(int32 command) -{ - CMatrix tmp_matrix; - switch (command) { - case COMMAND_IS_CHAR_IN_PLAYERS_GROUP: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - CPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed; - script_assert(pPed); - script_assert(pLeader); - UpdateCompareFlag(pPed->m_leader == pLeader); - return 0; - } - case COMMAND_EXPLODE_CHAR_HEAD: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - if (pPed->m_nPedState == PED_DRIVING) { - pPed->SetDead(); - if (!pPed->IsPlayer()) - pPed->FlagToDestroyWhenNextProcessed(); - } - else if (CGame::nastyGame && pPed->IsPedInControl()) { - pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); - } - else { - pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } - return 0; - } - case COMMAND_EXPLODE_PLAYER_HEAD: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - if (CGame::nastyGame) { - pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); - } - else { - pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } - return 0; - } - case COMMAND_ANCHOR_BOAT: - { - 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); - return 0; - } - case COMMAND_SET_ZONE_GROUP: - { - char zone[KEY_LENGTH_IN_SCRIPT]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, zone); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CollectParameters(&m_nIp, 2); - int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone); - if (zone_id < 0) { - printf("Couldn't find zone - %s\n", zone); - return 0; - } - CTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]); - return 0; - } - case COMMAND_START_CAR_FIRE: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - ScriptParams[0] = gFireManager.StartScriptFire(pVehicle->GetPosition(), pVehicle, 0.8f, 1); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_START_CHAR_FIRE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - ScriptParams[0] = gFireManager.StartScriptFire(pPed->GetPosition(), pPed, 0.8f, 1); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA: - { - CollectParameters(&m_nIp, 5); - int handle = -1; - uint32 i = CPools::GetVehiclePool()->GetSize(); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float supX = *(float*)&ScriptParams[2]; - float supY = *(float*)&ScriptParams[3]; - while (i--) { - CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); - if (!pVehicle) - continue; - if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0) - continue; - if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE) - continue; - if (!pVehicle->IsWithinArea(infX, infY, supX, supY)) - continue; - handle = CPools::GetVehiclePool()->GetIndex(pVehicle); - pVehicle->VehicleCreatedBy = MISSION_VEHICLE; - ++CCarCtrl::NumMissionCars; - --CCarCtrl::NumRandomCars; - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR); - } - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE: - { - char zone[KEY_LENGTH_IN_SCRIPT]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, zone); - int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone); - if (zone_id != -1) - m_nIp += KEY_LENGTH_IN_SCRIPT; - CZone* pZone = CTheZones::GetZone(zone_id); - CollectParameters(&m_nIp, 1); - int handle = -1; - uint32 i = CPools::GetVehiclePool()->GetSize(); - while (i--) { - CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); - if (!pVehicle) - continue; - if (ScriptParams[0] != pVehicle->GetModelIndex() && ScriptParams[0] >= 0) - continue; - if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE) - continue; - if (!CTheZones::PointLiesWithinZone(&pVehicle->GetPosition(), pZone)) - continue; - handle = CPools::GetVehiclePool()->GetIndex(pVehicle); - pVehicle->VehicleCreatedBy = MISSION_VEHICLE; - ++CCarCtrl::NumMissionCars; - --CCarCtrl::NumRandomCars; - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR); - } - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_HAS_RESPRAY_HAPPENED: - { - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CGarages::HasResprayHappened(ScriptParams[0])); - return 0; - } - case COMMAND_SET_CAMERA_ZOOM: - { - CollectParameters(&m_nIp, 1); - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED) - TheCamera.SetZoomValueFollowPedScript(ScriptParams[0]); - else if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING) - TheCamera.SetZoomValueCamStringScript(ScriptParams[0]); - return 0; - } - case COMMAND_CREATE_PICKUP_WITH_AMMO: - { - CollectParameters(&m_nIp, 6); - int16 model = ScriptParams[0]; - if (model < 0) - model = CTheScripts::UsedObjectArray[-model].index; - CVector pos = *(CVector*)&ScriptParams[3]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], ScriptParams[2]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CAR_RAM_CAR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CCarAI::TellCarToRamOtherCar(pVehicle, pTarget); - return 0; - } - case COMMAND_SET_CAR_BLOCK_CAR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CCarAI::TellCarToBlockOtherCar(pVehicle, pTarget); - return 0; - } - case COMMAND_SET_CHAR_OBJ_CATCH_TRAIN: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_CATCH_TRAIN); - return 0; - } - //case COMMAND_SET_COLL_OBJ_CATCH_TRAIN: - case COMMAND_SET_PLAYER_NEVER_GETS_TIRED: - { - CollectParameters(&m_nIp, 2); - CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; - pPlayer->m_bInfiniteSprint = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_PLAYER_FAST_RELOAD: - { - CollectParameters(&m_nIp, 2); - CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; - pPlayer->m_bFastReload = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_CHAR_BLEEDING: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bPedIsBleeding = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_CAR_FUNNY_SUSPENSION: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - // no action - return 0; - } - case COMMAND_SET_CAR_BIG_WHEELS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - CAutomobile* pCar = (CAutomobile*)pVehicle; - pCar->bBigWheels = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_FREE_RESPRAYS: - CollectParameters(&m_nIp, 1); - CGarages::SetFreeResprays(ScriptParams[0] != 0); - return 0; - case COMMAND_SET_PLAYER_VISIBLE: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - pPed->bIsVisible = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_CHAR_VISIBLE: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bIsVisible = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_SET_CAR_VISIBLE: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bIsVisible = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_IS_AREA_OCCUPIED: - { - CollectParameters(&m_nIp, 11); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - int16 total; - CWorld::FindObjectsIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil, - !!ScriptParams[6], !!ScriptParams[7], !!ScriptParams[8], !!ScriptParams[9], !!ScriptParams[10]); - UpdateCompareFlag(total > 0); - return 0; - } - case COMMAND_START_DRUG_RUN: - CPlane::CreateIncomingCesna(); - return 0; - case COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED: - UpdateCompareFlag(CPlane::HasCesnaLanded()); - return 0; - case COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN: - UpdateCompareFlag(CPlane::HasCesnaBeenDestroyed()); - return 0; - case COMMAND_SAVE_PLAYER_FROM_FIRES: - CollectParameters(&m_nIp, 1); - gFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f); - return 0; - case COMMAND_DISPLAY_TEXT: - { - CollectParameters(&m_nIp, 2); - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0]; - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1]; - uint16 len = CMessages::GetWideStringLength(text); - for (uint16 i = 0; i < len; i++) - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = text[i]; - for (uint16 i = len; i < SCRIPT_TEXT_MAX_LENGTH; i++) - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = 0; - ++CTheScripts::NumberOfIntroTextLinesThisFrame; - return 0; - } - case COMMAND_SET_TEXT_SCALE: - { - CollectParameters(&m_nIp, 2); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleX = *(float*)&ScriptParams[0]; - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleY = *(float*)&ScriptParams[1]; - return 0; - } - case COMMAND_SET_TEXT_COLOUR: - { - CollectParameters(&m_nIp, 4); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sColor = - CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]); - return 0; - } - case COMMAND_SET_TEXT_JUSTIFY: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bJustify = (ScriptParams[0] != 0); - return 0; - } - case COMMAND_SET_TEXT_CENTRE: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bCentered = (ScriptParams[0] != 0); - return 0; - } - case COMMAND_SET_TEXT_WRAPX: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0]; - return 0; - } - case COMMAND_SET_TEXT_CENTRE_SIZE: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0]; - return 0; - } - case COMMAND_SET_TEXT_BACKGROUND: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0); - return 0; - } - case COMMAND_SET_TEXT_BACKGROUND_COLOUR: - { - CollectParameters(&m_nIp, 4); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sBackgroundColor = - CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]); - return 0; - } - case COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0); - return 0; - } - case COMMAND_SET_TEXT_PROPORTIONAL: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0); - return 0; - } - case COMMAND_SET_TEXT_FONT: - { - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_nFont = ScriptParams[0]; - return 0; - } - case COMMAND_INDUSTRIAL_PASSED: - CStats::IndustrialPassed = true; - DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_COMMERCIAL_OPEN); - return 0; - case COMMAND_COMMERCIAL_PASSED: - CStats::CommercialPassed = true; - DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_SUBURBAN_OPEN); - return 0; - case COMMAND_SUBURBAN_PASSED: - CStats::SuburbanPassed = true; - return 0; - case COMMAND_ROTATE_OBJECT: - { - CollectParameters(&m_nIp, 4); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - float heading = LimitAngleOnCircle( - RADTODEG(Atan2(-pObject->GetForward().x, pObject->GetForward().y))); - float headingTarget = *(float*)&ScriptParams[1]; -#ifdef FIX_BUGS - float rotateBy = *(float*)&ScriptParams[2] * CTimer::GetTimeStepFix(); -#else - float rotateBy = *(float*)&ScriptParams[2]; -#endif - if (headingTarget == heading) { // using direct comparasion here is fine - UpdateCompareFlag(true); - return 0; - } - float angleClockwise = LimitAngleOnCircle(headingTarget - heading); - float angleCounterclockwise = LimitAngleOnCircle(heading - headingTarget); - float newHeading; - if (angleClockwise < angleCounterclockwise) - newHeading = rotateBy < angleClockwise ? heading + rotateBy : headingTarget; - else - newHeading = rotateBy < angleCounterclockwise ? heading - rotateBy : headingTarget; - bool obstacleInPath = false; - if (ScriptParams[3]) { - CVector pos = pObject->GetPosition(); - tmp_matrix.SetRotateZ(DEGTORAD(newHeading)); - tmp_matrix.GetPosition() += pos; - CColModel* pColModel = pObject->GetColModel(); - CVector cp1 = tmp_matrix * pColModel->boundingBox.min; - CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z); - CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z); - CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z); - int16 collisions; - CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos, - Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))), - Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))), - Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))), - Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))), - &collisions, 2, nil, false, true, true, false, false); - if (collisions > 0) - obstacleInPath = true; - } - if (obstacleInPath) { - UpdateCompareFlag(true); - return 0; - } - pObject->SetHeading(DEGTORAD(newHeading)); - pObject->GetMatrix().UpdateRW(); - pObject->UpdateRwFrame(); - UpdateCompareFlag(newHeading == headingTarget); // using direct comparasion here is fine - return 0; - } - case COMMAND_SLIDE_OBJECT: - { - CollectParameters(&m_nIp, 8); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CVector pos = pObject->GetPosition(); - CVector posTarget = *(CVector*)&ScriptParams[1]; -#ifdef FIX_BUGS - CVector slideBy = *(CVector*)&ScriptParams[4] * CTimer::GetTimeStepFix(); -#else - CVector slideBy = *(CVector*)&ScriptParams[4]; -#endif - if (posTarget == pos) { // using direct comparasion here is fine - UpdateCompareFlag(true); - return 0; - } - CVector posDiff = pos - posTarget; - CVector newPosition; - if (posDiff.x < 0) - newPosition.x = -posDiff.x < slideBy.x ? posTarget.x : pos.x + slideBy.x; - else - newPosition.x = posDiff.x < slideBy.x ? posTarget.x : pos.x - slideBy.x; - if (posDiff.y < 0) - newPosition.y = -posDiff.y < slideBy.y ? posTarget.y : pos.y + slideBy.y; - else - newPosition.y = posDiff.y < slideBy.y ? posTarget.y : pos.y - slideBy.y; - if (posDiff.z < 0) - newPosition.z = -posDiff.z < slideBy.z ? posTarget.z : pos.z + slideBy.z; - else - newPosition.z = posDiff.z < slideBy.z ? posTarget.z : pos.z - slideBy.z; - bool obstacleInPath = false; - if (ScriptParams[7]) { - tmp_matrix = pObject->GetMatrix(); - tmp_matrix.GetPosition() = newPosition; - CColModel* pColModel = pObject->GetColModel(); - CVector cp1 = tmp_matrix * pColModel->boundingBox.min; - CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z); - CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z); - CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z); - int16 collisions; - CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, newPosition, - Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))), - Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))), - Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))), - Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))), - &collisions, 2, nil, false, true, true, false, false); - if (collisions > 0) - obstacleInPath = true; - } - if (obstacleInPath) { - UpdateCompareFlag(true); - return 0; - } - pObject->Teleport(newPosition); - UpdateCompareFlag(newPosition == posTarget); // using direct comparasion here is fine - return 0; - } - case COMMAND_REMOVE_CHAR_ELEGANTLY: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - if (pPed && pPed->CharCreatedBy == MISSION_CHAR){ - CWorld::RemoveReferencesToDeletedObject(pPed); - if (pPed->bInVehicle){ - if (pPed->m_pMyVehicle){ - if (pPed == pPed->m_pMyVehicle->pDriver){ - pPed->m_pMyVehicle->RemoveDriver(); - pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); - if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) - pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED; - if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle()) - pPed->m_pMyVehicle->ChangeLawEnforcerState(0); - }else{ - pPed->m_pMyVehicle->RemovePassenger(pPed); - } - } - delete pPed; - --CPopulation::ms_nTotalMissionPeds; - }else{ - pPed->CharCreatedBy = RANDOM_CHAR; - pPed->bRespondsToThreats = true; - pPed->bScriptObjectiveCompleted = false; - pPed->ClearLeader(); - --CPopulation::ms_nTotalMissionPeds; - pPed->bFadeOut = true; - } - } - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR); - return 0; - } - case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bKindaStayInSamePlace = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_IS_NASTY_GAME: - UpdateCompareFlag(CGame::nastyGame); - return 0; - case COMMAND_UNDRESS_CHAR: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - char name[KEY_LENGTH_IN_SCRIPT]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, name); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - name[i] = tolower(name[i]); - int mi = pPed->GetModelIndex(); - pPed->DeleteRwObject(); - if (pPed->IsPlayer()) - mi = 0; - CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CWorld::Remove(pPed); - return 0; - } - case COMMAND_DRESS_CHAR: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - int mi = pPed->GetModelIndex(); - pPed->m_modelIndex = -1; - pPed->SetModelIndex(mi); - CWorld::Add(pPed); - return 0; - } - case COMMAND_START_CHASE_SCENE: - CollectParameters(&m_nIp, 1); - CTimer::Suspend(); - CStreaming::DeleteAllRwObjects(); - CRecordDataForChase::StartChaseScene(*(float*)&ScriptParams[0]); - CTimer::Resume(); - return 0; - case COMMAND_STOP_CHASE_SCENE: - CRecordDataForChase::CleanUpChaseScene(); - return 0; - case COMMAND_IS_EXPLOSION_IN_AREA: - { - CollectParameters(&m_nIp, 7); - float infX = *(float*)&ScriptParams[1]; - float infY = *(float*)&ScriptParams[2]; - float infZ = *(float*)&ScriptParams[3]; - float supX = *(float*)&ScriptParams[4]; - float supY = *(float*)&ScriptParams[5]; - float supZ = *(float*)&ScriptParams[6]; - if (infX > supX) { - infX = *(float*)&ScriptParams[4]; - supX = *(float*)&ScriptParams[1]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[5]; - supY = *(float*)&ScriptParams[2]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[6]; - supZ = *(float*)&ScriptParams[3]; - } - UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0], - infX, supX, infY, supY, infZ, supZ)); - return 0; - } - case COMMAND_IS_EXPLOSION_IN_ZONE: - { - CollectParameters(&m_nIp, 1); - char zone[KEY_LENGTH_IN_SCRIPT]; - CTheScripts::ReadTextLabelFromScript(&m_nIp, zone); - int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone); - if (zone_id != -1) - m_nIp += KEY_LENGTH_IN_SCRIPT; - CZone* pZone = CTheZones::GetZone(zone_id); - UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0], - pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz)); - return 0; - } - case COMMAND_START_DRUG_DROP_OFF: - CPlane::CreateDropOffCesna(); - return 0; - case COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN: - UpdateCompareFlag(CPlane::HasDropOffCesnaBeenShotDown()); - return 0; - case COMMAND_FIND_DROP_OFF_PLANE_COORDINATES: - { - CVector pos = CPlane::FindDropOffCesnaCoordinates(); - *(CVector*)&ScriptParams[0] = pos; - StoreParameters(&m_nIp, 3); - return 0; - } - case COMMAND_CREATE_FLOATING_PACKAGE: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR: - { - CollectParameters(&m_nIp, 5); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pVehicle); - CVector offset = *(CVector*)&ScriptParams[2]; - CPhysical::PlacePhysicalRelativeToOtherPhysical(pVehicle, pObject, offset); - return 0; - } - case COMMAND_MAKE_OBJECT_TARGETTABLE: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CPlayerPed* pPlayerPed = CWorld::Players[CWorld::PlayerInFocus].m_pPed; - script_assert(pPlayerPed); - pPlayerPed->MakeObjectTargettable(ScriptParams[0]); - return 0; - } - case COMMAND_ADD_ARMOUR_TO_PLAYER: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPlayerPed); - pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f); - return 0; - } - case COMMAND_ADD_ARMOUR_TO_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->m_fArmour = clamp(pPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f); - return 0; - } - case COMMAND_OPEN_GARAGE: - { - CollectParameters(&m_nIp, 1); - CGarages::OpenGarage(ScriptParams[0]); - return 0; - } - case COMMAND_CLOSE_GARAGE: - { - CollectParameters(&m_nIp, 1); - CGarages::CloseGarage(ScriptParams[0]); - return 0; - } - case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD: - { - CollectParameters(&m_nIp, 4); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - if (pPed->bInVehicle){ - if (pPed->m_pMyVehicle->bIsBus) - pPed->bRenderPedInCar = true; - if (pPed->m_pMyVehicle->pDriver == pPed){ - pPed->m_pMyVehicle->RemoveDriver(); - pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); - pPed->m_pMyVehicle->bEngineOn = false; - pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - }else{ - pPed->m_pMyVehicle->RemovePassenger(pPed); - } - pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f); - pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f); - } - pPed->bInVehicle = false; - pPed->m_pMyVehicle = nil; - pPed->SetPedState(PED_IDLE); - pPed->m_nLastPedState = PED_NONE; - pPed->bUsesCollision = true; - pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); - pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId); - pPed->RemoveInCarAnims(); - if (pPed->m_pVehicleAnim) - pPed->m_pVehicleAnim->blendDelta = -1000.0f; - pPed->m_pVehicleAnim = nil; - pPed->RestartNonPartialAnims(); - pPed->SetMoveState(PEDMOVE_NONE); - CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f); - pos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel(); - pPed->Teleport(pos); - CTheScripts::ClearSpaceForMissionEntity(pos, pPed); - return 0; - } - case COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE: - { - CollectParameters(&m_nIp, 6); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float range = *(float*)&ScriptParams[3]; - int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4]; - int16 total; - CEntity* apEntities[16]; - CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, true, false, false, true, true); - if (total == 0) - CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, range, true, &total, 16, apEntities); - if (total == 0) - CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities); - CEntity* pClosestEntity = nil; - float min_dist = 2.0f * range; - for (int i = 0; i < total; i++) { - float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); - if (dist < min_dist) { - min_dist = dist; - pClosestEntity = apEntities[i]; - } - } - if (pClosestEntity) { - pClosestEntity->bIsVisible = (ScriptParams[5] != 0); - CTheScripts::AddToInvisibilitySwapArray(pClosestEntity, ScriptParams[5] != 0); - } - return 0; - } - case COMMAND_HAS_CHAR_SPOTTED_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - UpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget)); - return 0; - } - case COMMAND_SET_CHAR_OBJ_HAIL_TAXI: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_HAIL_TAXI); - return 0; - } - case COMMAND_HAS_OBJECT_BEEN_DAMAGED: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - UpdateCompareFlag(pObject->bRenderDamaged || !pObject->bIsVisible); - return 0; - } - case COMMAND_START_KILL_FRENZY_HEADSHOT: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 8); - CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2], - ScriptParams[3], text, ScriptParams[4], ScriptParams[5], - ScriptParams[6], ScriptParams[7] != 0, true); - return 0; - } - case COMMAND_ACTIVATE_MILITARY_CRANE: - { - CollectParameters(&m_nIp, 10); - float infX = *(float*)&ScriptParams[2]; - float infY = *(float*)&ScriptParams[3]; - float supX = *(float*)&ScriptParams[4]; - float supY = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[4]; - supX = *(float*)&ScriptParams[2]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[5]; - supY = *(float*)&ScriptParams[3]; - } - CCranes::ActivateCrane(infX, supX, infY, supY, - *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8], - DEGTORAD(*(float*)&ScriptParams[9]), false, true, - *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); - return 0; - } - case COMMAND_WARP_PLAYER_INTO_CAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pVehicle); - pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle); - pPed->WarpPedIntoCar(pVehicle); - return 0; - } - case COMMAND_WARP_CHAR_INTO_CAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pVehicle); - pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle); - pPed->WarpPedIntoCar(pVehicle); - return 0; - } - //case COMMAND_SWITCH_CAR_RADIO: - //case COMMAND_SET_AUDIO_STREAM: - case COMMAND_PRINT_WITH_2_NUMBERS_BIG: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 4); - CMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_3_NUMBERS_BIG: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 5); - CMessages::AddBigMessageWithNumber(text, ScriptParams[3], ScriptParams[4] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_4_NUMBERS_BIG: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 6); - CMessages::AddBigMessageWithNumber(text, ScriptParams[4], ScriptParams[5] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); - return 0; - } - case COMMAND_PRINT_WITH_5_NUMBERS_BIG: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 7); - CMessages::AddBigMessageWithNumber(text, ScriptParams[5], ScriptParams[6] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); - return 0; - } - case COMMAND_PRINT_WITH_6_NUMBERS_BIG: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 8); - CMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); - return 0; - } - case COMMAND_SET_CHAR_WAIT_STATE: - { - CollectParameters(&m_nIp, 3); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->SetWaitState((eWaitState)ScriptParams[1], ScriptParams[2] >= 0 ? &ScriptParams[2] : nil); - return 0; - } - case COMMAND_SET_CAMERA_BEHIND_PLAYER: - TheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString(); - return 0; - case COMMAND_SET_MOTION_BLUR: - CollectParameters(&m_nIp, 1); - TheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]); - return 0; - case COMMAND_PRINT_STRING_IN_STRING: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* string = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 2); - CMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string); - return 0; - } - case COMMAND_CREATE_RANDOM_CHAR: - { - CollectParameters(&m_nIp, 3); - CZoneInfo zoneinfo; - CTheZones::GetZoneInfoForTimeOfDay(&CWorld::Players[CWorld::PlayerInFocus].GetPos(), &zoneinfo); - int mi; - ePedType pedtype = PEDTYPE_COP; - int attempt = 0; - while (pedtype != PEDTYPE_CIVMALE && pedtype != PEDTYPE_CIVFEMALE && attempt < 5) { - mi = CPopulation::ChooseCivilianOccupation(zoneinfo.pedGroup); - if (CModelInfo::GetModelInfo(mi)->GetRwObject()) - pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType; - attempt++; - } - if (!CModelInfo::GetModelInfo(mi)->GetRwObject()) { - mi = MI_MALE01; - pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType; - } - CPed* ped = new CCivilianPed(pedtype, mi); - ped->CharCreatedBy = MISSION_CHAR; - ped->bRespondsToThreats = false; - ped->bAllowMedicsToReviveMe = false; - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pos.z += 1.0f; - ped->SetPosition(pos); - ped->SetOrientation(0.0f, 0.0f, 0.0f); - CTheScripts::ClearSpaceForMissionEntity(pos, ped); - CWorld::Add(ped); - ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); - CPopulation::ms_nTotalMissionPeds++; - ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped); - StoreParameters(&m_nIp, 1); - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR); - return 0; - } - case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR); - return 0; - } - case COMMAND_SET_2_REPEATED_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, nil, nil, nil, nil); - return 0; - } - case COMMAND_SET_2_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, nil, nil, nil, nil); - return 0; - } - case COMMAND_SET_3_REPEATED_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, nil, nil, nil); - return 0; - } - case COMMAND_SET_3_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, nil, nil, nil); - return 0; - } - case COMMAND_SET_4_REPEATED_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, nil, nil); - return 0; - } - case COMMAND_SET_4_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil); - return 0; - } - case COMMAND_IS_SNIPER_BULLET_IN_AREA: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - UpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ)); - return 0; - } - case COMMAND_GIVE_PLAYER_DETONATOR: - CGarages::GivePlayerDetonator(); - return 0; - //case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR: - case COMMAND_SET_OBJECT_VELOCITY: - { - CollectParameters(&m_nIp, 4); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - pObject->SetMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED); - return 0; - } - case COMMAND_SET_OBJECT_COLLISION: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - pObject->bUsesCollision = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_IS_ICECREAM_JINGLE_ON: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - // Adding this check to correspond to command name. - // All original game scripts always assume that the vehicle is actually Mr. Whoopee, - // but maybe there are mods that use it as "is alarm activated"? - script_assert(pVehicle->GetModelIndex() == MI_MRWHOOP); - UpdateCompareFlag(pVehicle->m_bSirenOrAlarm); - return 0; - } - default: - script_assert(0); - } - return -1; -} - -int8 CRunningScript::ProcessCommands900To999(int32 command) -{ - char str[52]; - char onscreen_str[KEY_LENGTH_IN_SCRIPT]; - switch (command) { - case COMMAND_PRINT_STRING_IN_STRING_NOW: - { - wchar* source = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* pstr = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CollectParameters(&m_nIp, 2); - CMessages::AddMessageJumpQWithString(source, ScriptParams[0], ScriptParams[1], pstr); - return 0; - } - //case COMMAND_PRINT_STRING_IN_STRING_SOON: - case COMMAND_SET_5_REPEATED_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, nil); - return 0; - } - case COMMAND_SET_5_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, nil); - return 0; - } - case COMMAND_SET_6_REPEATED_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, text6); - return 0; - } - case COMMAND_SET_6_PHONE_MESSAGES: - { - CollectParameters(&m_nIp, 1); - wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp); - gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6); - return 0; - } - case COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0] - *(float*)&ScriptParams[3]; - float supX = *(float*)&ScriptParams[0] + *(float*)&ScriptParams[3]; - float infY = *(float*)&ScriptParams[1] - *(float*)&ScriptParams[4]; - float supY = *(float*)&ScriptParams[1] + *(float*)&ScriptParams[4]; - float infZ = *(float*)&ScriptParams[2] - *(float*)&ScriptParams[5]; - float supZ = *(float*)&ScriptParams[2] + *(float*)&ScriptParams[5]; - if (infX > supX) { - float tmp = infX; - infX = supX; - supX = tmp; - } - if (infY > supY) { - float tmp = infY; - infY = supY; - supY = tmp; - } - if (infZ > supZ) { - float tmp = infZ; - infZ = supZ; - supZ = tmp; - } - int16 total; - CWorld::FindMissionEntitiesIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil, true, true, true); - UpdateCompareFlag(total > 0); - return 0; - } - case COMMAND_LOAD_ALL_MODELS_NOW: - CTimer::Stop(); - CStreaming::LoadAllRequestedModels(false); - CTimer::Update(); - return 0; - case COMMAND_ADD_TO_OBJECT_VELOCITY: - { - CollectParameters(&m_nIp, 4); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - pObject->SetMoveSpeed(pObject->GetMoveSpeed() + METERS_PER_SECOND_TO_GAME_SPEED * *(CVector*)&ScriptParams[1]); - return 0; - } - case COMMAND_DRAW_SPRITE: - { - CollectParameters(&m_nIp, 9); - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true; - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = ScriptParams[0] - 1; - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect( - *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3], *(float*)&ScriptParams[2] + *(float*)&ScriptParams[4]); - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]); - CTheScripts::NumberOfIntroRectanglesThisFrame++; - return 0; - } - case COMMAND_DRAW_RECT: - { - CollectParameters(&m_nIp, 8); - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true; - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = -1; - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect( - *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[0] + *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3]); - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7]); - CTheScripts::NumberOfIntroRectanglesThisFrame++; - return 0; - } - case COMMAND_LOAD_SPRITE: - { - CollectParameters(&m_nIp, 1); - strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - str[i] = tolower(str[i]); - m_nIp += KEY_LENGTH_IN_SCRIPT; - int slot = CTxdStore::FindTxdSlot("script"); - CTxdStore::PushCurrentTxd(); - CTxdStore::SetCurrentTxd(slot); - CTheScripts::ScriptSprites[ScriptParams[0] - 1].SetTexture(str); - CTxdStore::PopCurrentTxd(); - return 0; - } - case COMMAND_LOAD_TEXTURE_DICTIONARY: - { - strcpy(str, "models\\"); - strncpy(str + sizeof("models\\"), (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - strcat(str, ".txd"); - m_nIp += KEY_LENGTH_IN_SCRIPT; - int slot = CTxdStore::FindTxdSlot("script"); - if (slot == -1) - slot = CTxdStore::AddTxdSlot("script"); - CTxdStore::LoadTxd(slot, str); - CTxdStore::AddRef(slot); - return 0; - } - case COMMAND_REMOVE_TEXTURE_DICTIONARY: - { - for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++) - CTheScripts::ScriptSprites[i].Delete(); - CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script")); - return 0; - } - case COMMAND_SET_OBJECT_DYNAMIC: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - if (ScriptParams[1]) { - if (pObject->bIsStatic) { - pObject->SetIsStatic(false); - pObject->AddToMovingList(); - } - } - else { - if (!pObject->bIsStatic) { - pObject->SetIsStatic(true); - pObject->RemoveFromMovingList(); - } - } - return 0; - } - case COMMAND_SET_CHAR_ANIM_SPEED: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetFirstAssociation(pPed->GetClump()); - if (pAssoc) - pAssoc->speed = *(float*)&ScriptParams[1]; - return 0; - } - case COMMAND_PLAY_MISSION_PASSED_TUNE: - { - CollectParameters(&m_nIp, 1); - DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); - DMAudio.PlayFrontEndTrack(ScriptParams[0] + STREAMED_SOUND_MISSION_COMPLETED - 1, 0); - return 0; - } - case COMMAND_CLEAR_AREA: - { - CollectParameters(&m_nIp, 5); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CWorld::ClearExcitingStuffFromArea(pos, *(float*)&ScriptParams[3], ScriptParams[4]); - return 0; - } - case COMMAND_FREEZE_ONSCREEN_TIMER: - CollectParameters(&m_nIp, 1); - CUserDisplay::OnscnTimer.m_bDisabled = ScriptParams[0] != 0; - return 0; - case COMMAND_SWITCH_CAR_SIREN: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->m_bSirenOrAlarm = ScriptParams[1] != 0; - return 0; - } - case COMMAND_SWITCH_PED_ROADS_ON_ANGLED: - { - CollectParameters(&m_nIp, 7); - ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], - *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 1); - return 0; - } - case COMMAND_SWITCH_PED_ROADS_OFF_ANGLED: - CollectParameters(&m_nIp, 7); - ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], - *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 0); - return 0; - case COMMAND_SWITCH_ROADS_ON_ANGLED: - CollectParameters(&m_nIp, 7); - ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], - *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 1); - return 0; - case COMMAND_SWITCH_ROADS_OFF_ANGLED: - CollectParameters(&m_nIp, 7); - ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], - *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 0); - return 0; - case COMMAND_SET_CAR_WATERTIGHT: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - CAutomobile* pCar = (CAutomobile*)pVehicle; - pCar->bWaterTight = ScriptParams[1] != 0; - return 0; - } - case COMMAND_ADD_MOVING_PARTICLE_EFFECT: - { - CollectParameters(&m_nIp, 12); - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float size = Max(0.0f, *(float*)&ScriptParams[7]); - eParticleObjectType type = (eParticleObjectType)ScriptParams[0]; - RwRGBA color; - if (type == POBJECT_SMOKE_TRAIL){ - color.alpha = -1; - color.red = ScriptParams[8]; - color.green = ScriptParams[9]; - color.blue = ScriptParams[10]; - }else{ - color.alpha = color.red = color.blue = color.green = 0; - } - CVector target = *(CVector*)&ScriptParams[4]; - CParticleObject::AddObject(type, pos, target, size, ScriptParams[11], color, 1); - return 0; - } - case COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bDontDragMeOutCar = ScriptParams[1] != 0; - return 0; - } - case COMMAND_TURN_CAR_TO_FACE_COORD: - { - CollectParameters(&m_nIp, 3); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - const CVector& pos = pVehicle->GetPosition(); - float heading = CGeneral::GetATanOfXY(pos.y - *(float*)&ScriptParams[2], pos.x - *(float*)&ScriptParams[1]) + HALFPI; - if (heading > TWOPI) - heading -= TWOPI; - pVehicle->SetHeading(heading); - return 0; - } - case COMMAND_IS_CRANE_LIFTING_CAR: - { - CollectParameters(&m_nIp, 3); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[2]); - UpdateCompareFlag(CCranes::IsThisCarPickedUp(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], pVehicle)); - return 0; - } - case COMMAND_DRAW_SPHERE: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - C3dMarkers::PlaceMarkerSet((uintptr)this + m_nIp, MARKERTYPE_CYLINDER, pos, *(float*)&ScriptParams[3], - SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, - SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0); - return 0; - } - case COMMAND_SET_CAR_STATUS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->SetStatus((eEntityStatus)ScriptParams[1]); - return 0; - } - case COMMAND_IS_CHAR_MALE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(pPed->m_nPedType != PEDTYPE_CIVFEMALE && pPed->m_nPedType != PEDTYPE_PROSTITUTE); - return 0; - } - case COMMAND_SCRIPT_NAME: - { - strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - str[i] = tolower(str[i]); - m_nIp += KEY_LENGTH_IN_SCRIPT; - strncpy(m_abScriptName, str, KEY_LENGTH_IN_SCRIPT); - return 0; - } - case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL: - { - CollectParameters(&m_nIp, 3); - CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], ScriptParams[2]); - return 0; - } - case COMMAND_FIND_DRUG_PLANE_COORDINATES: - *(CVector*)&ScriptParams[0] = CPlane::FindDrugPlaneCoordinates(); - StoreParameters(&m_nIp, 3); - return 0; - case COMMAND_SAVE_INT_TO_DEBUG_FILE: - // TODO: implement something here - CollectParameters(&m_nIp, 1); - return 0; - case COMMAND_SAVE_FLOAT_TO_DEBUG_FILE: - CollectParameters(&m_nIp, 1); - return 0; - case COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE: - return 0; - case COMMAND_POLICE_RADIO_MESSAGE: - CollectParameters(&m_nIp, 3); - DMAudio.PlaySuspectLastSeen(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]); - return 0; - case COMMAND_SET_CAR_STRONG: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bTakeLessDamage = ScriptParams[1] != 0; - return 0; - } - case COMMAND_REMOVE_ROUTE: - CollectParameters(&m_nIp, 1); - CRouteNode::RemoveRoute(ScriptParams[0]); - return 0; - case COMMAND_SWITCH_RUBBISH: - CollectParameters(&m_nIp, 1); - CRubbish::SetVisibility(ScriptParams[0] != 0);; - return 0; - case COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA: - { - CollectParameters(&m_nIp, 6); - float x1 = *(float*)&ScriptParams[0]; - float y1 = *(float*)&ScriptParams[1]; - float z1 = *(float*)&ScriptParams[2]; - float x2 = *(float*)&ScriptParams[3]; - float y2 = *(float*)&ScriptParams[4]; - float z2 = *(float*)&ScriptParams[5]; - CParticleObject* tmp = CParticleObject::pCloseListHead; - while (tmp) { - CParticleObject* next = tmp->m_pNext; - if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2)) - tmp->RemoveObject(); - tmp = next; - } - tmp = CParticleObject::pFarListHead; - while (tmp) { - CParticleObject* next = tmp->m_pNext; - if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2)) - tmp->RemoveObject(); - tmp = next; - } - return 0; - } - case COMMAND_SWITCH_STREAMING: - CollectParameters(&m_nIp, 1); - CStreaming::ms_disableStreaming = ScriptParams[0] == 0; - return 0; - case COMMAND_IS_GARAGE_OPEN: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CGarages::IsGarageOpen(ScriptParams[0])); - return 0; - case COMMAND_IS_GARAGE_CLOSED: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CGarages::IsGarageClosed(ScriptParams[0])); - return 0; - case COMMAND_START_CATALINA_HELI: - CHeli::StartCatalinaFlyBy(); - return 0; - case COMMAND_CATALINA_HELI_TAKE_OFF: - CHeli::CatalinaTakeOff(); - return 0; - case COMMAND_REMOVE_CATALINA_HELI: - CHeli::RemoveCatalinaHeli(); - return 0; - case COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN: - UpdateCompareFlag(CHeli::HasCatalinaBeenShotDown()); - return 0; - case COMMAND_SWAP_NEAREST_BUILDING_MODEL: - { - CollectParameters(&m_nIp, 6); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = *(float*)&ScriptParams[3]; - int mi1 = ScriptParams[4] >= 0 ? ScriptParams[4] : CTheScripts::UsedObjectArray[-ScriptParams[4]].index; - int mi2 = ScriptParams[5] >= 0 ? ScriptParams[5] : CTheScripts::UsedObjectArray[-ScriptParams[5]].index; - int16 total; - CEntity* apEntities[16]; - CWorld::FindObjectsOfTypeInRange(mi1, pos, radius, true, &total, 16, apEntities, true, false, false, false, false); - if (total == 0) - CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, radius, true, &total, 16, apEntities); - if (total == 0) - CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities); - CEntity* pClosestEntity = nil; - float min_dist = 2.0f * radius; - for (int i = 0; i < total; i++) { - float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); - if (dist < min_dist) { - min_dist = dist; - pClosestEntity = apEntities[i]; - } - } - if (!pClosestEntity) { - printf("Failed to find building\n"); - return 0; - } - CBuilding* pReplacedBuilding = ((CBuilding*)pClosestEntity); - pReplacedBuilding->ReplaceWithNewModel(mi2); - CTheScripts::AddToBuildingSwapArray(pReplacedBuilding, mi1, mi2); - return 0; - } - case COMMAND_SWITCH_WORLD_PROCESSING: - CollectParameters(&m_nIp, 1); - CWorld::bProcessCutsceneOnly = ScriptParams[0] == 0; - return 0; - case COMMAND_REMOVE_ALL_PLAYER_WEAPONS: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - pPed->ClearWeapons(); - return 0; - } - case COMMAND_GRAB_CATALINA_HELI: - { - CHeli* pHeli = CHeli::FindPointerToCatalinasHeli(); - ScriptParams[0] = pHeli ? CPools::GetVehiclePool()->GetIndex(pHeli) : -1; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_CLEAR_AREA_OF_CARS: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - CWorld::ClearCarsFromArea(infX, infY, infZ, supX, supY, supZ); - return 0; - } - case COMMAND_SET_ROTATING_GARAGE_DOOR: - CollectParameters(&m_nIp, 1); - CGarages::SetGarageDoorToRotate(ScriptParams[0]); - return 0; - case COMMAND_ADD_SPHERE: - { - CollectParameters(&m_nIp, 4); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = *(float*)&ScriptParams[3]; - CTheScripts::GetActualScriptSphereIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CTheScripts::AddScriptSphere((uintptr)this + m_nIp, pos, radius); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_REMOVE_SPHERE: - CollectParameters(&m_nIp, 1); - CTheScripts::RemoveScriptSphere(ScriptParams[0]); - return 0; - case COMMAND_CATALINA_HELI_FLY_AWAY: - CHeli::MakeCatalinaHeliFlyAway(); - return 0; - case COMMAND_SET_EVERYONE_IGNORE_PLAYER: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - if (ScriptParams[1]) { - pPed->m_pWanted->m_bIgnoredByEveryone = true; - CWorld::StopAllLawEnforcersInTheirTracks(); - } - else { - pPed->m_pWanted->m_bIgnoredByEveryone = false; - } - return 0; - } - case COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil; - ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil; - ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_IS_PHONE_DISPLAYING_MESSAGE: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(gPhoneInfo.IsMessageBeingDisplayed(ScriptParams[0])); - return 0; - case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING: - { - script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR); - uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp); - wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ??? - strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CUserDisplay::OnscnTimer.AddClock(var, onscreen_str); - return 0; - } - case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING: - { - script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR); - uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp); - CollectParameters(&m_nIp, 1); - wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ??? - strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - m_nIp += KEY_LENGTH_IN_SCRIPT; - CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str); - return 0; - } - case COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK: - { - CollectParameters(&m_nIp, 4); - if (CCarCtrl::NumRandomCars >= 30) - return 0; - int attempts; - int model = -1; - int index = CGeneral::GetRandomNumberInRange(0, 50); - for (attempts = 0; attempts < 50; attempts++) { - if (model != -1) - break; - model = CStreaming::ms_vehiclesLoaded[index]; - if (model == -1) - continue; - // desperatly want to believe this was inlined :| - CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(model); - script_assert(pInfo->GetModelType() == MITYPE_VEHICLE); - CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo; - if (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR) { - switch (model) { - case MI_LANDSTAL: - case MI_LINERUN: - case MI_FIRETRUCK: - case MI_TRASH: - case MI_STRETCH: - case MI_MULE: - case MI_AMBULAN: - case MI_FBICAR: - case MI_MRWHOOP: - case MI_BFINJECT: - case MI_CORPSE: - case MI_POLICE: - case MI_ENFORCER: - case MI_SECURICA: - case MI_PREDATOR: - case MI_BUS: - case MI_RHINO: - case MI_BARRACKS: - case MI_TRAIN: - case MI_CHOPPER: - case MI_DODO: - case MI_COACH: - case MI_RCBANDIT: - case MI_BELLYUP: - case MI_MRWONGS: - case MI_MAFIA: - case MI_YARDIE: - case MI_YAKUZA: - case MI_DIABLOS: - case MI_COLUMB: - case MI_HOODS: - case MI_AIRTRAIN: - case MI_DEADDODO: - case MI_SPEEDER: - case MI_REEFER: - case MI_PANLANT: - case MI_FLATBED: - case MI_YANKEE: - case MI_ESCAPE: - case MI_BORGNINE: - case MI_TOYZ: - case MI_GHOST: - case MI_MIAMI_RCBARON: - case MI_MIAMI_RCRAIDER: - model = -1; - break; - case MI_IDAHO: - case MI_STINGER: - case MI_PEREN: - case MI_SENTINEL: - case MI_PATRIOT: - case MI_MANANA: - case MI_INFERNUS: - case MI_BLISTA: - case MI_PONY: - case MI_CHEETAH: - case MI_MOONBEAM: - case MI_ESPERANT: - case MI_TAXI: - case MI_KURUMA: - case MI_BOBCAT: - case MI_BANSHEE: - case MI_CABBIE: - case MI_STALLION: - case MI_RUMPO: - case 151: - case 152: - case 153: - break; - default: - printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]); - model = -1; - break; - } - } - else - model = -1; - if (++index >= 50) - index = 0; - } - if (model == -1) - return 0; - CVehicle* car; - if (!CModelInfo::IsBikeModel(model)) - car = new CAutomobile(model, RANDOM_VEHICLE); - CVector pos = *(CVector*)&ScriptParams[0]; - pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel(); - car->SetPosition(pos); - car->SetHeading(DEGTORAD(*(float*)&ScriptParams[3])); - CTheScripts::ClearSpaceForMissionEntity(pos, car); - car->SetStatus(STATUS_ABANDONED); - car->bIsLocked = false; - car->bIsCarParkVehicle = true; - CCarCtrl::JoinCarWithRoadSystem(car); - car->AutoPilot.m_nCarMission = MISSION_NONE; - car->AutoPilot.m_nTempAction = TEMPACT_NONE; - car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; - car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f; - car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0; - car->bEngineOn = false; - car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); - CWorld::Add(car); - return 0; - } - case COMMAND_IS_COLLISION_IN_MEMORY: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CCollision::ms_collisionInMemory == ScriptParams[0]); - return 0; - case COMMAND_SET_WANTED_MULTIPLIER: - CollectParameters(&m_nIp, 1); - FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = *(float*)&ScriptParams[0]; - return 0; - case COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER: - TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString(); - return 0; - case COMMAND_IS_CAR_VISIBLY_DAMAGED: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(pVehicle->bIsDamaged); - return 0; - } - case COMMAND_DOES_OBJECT_EXIST: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CPools::GetObjectPool()->GetAt(ScriptParams[0])); - return 0; - case COMMAND_LOAD_SCENE: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - CTimer::Stop(); - CStreaming::LoadScene(pos); - CTimer::Update(); - return 0; - } - case COMMAND_ADD_STUCK_CAR_CHECK: - { - CollectParameters(&m_nIp, 3); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CTheScripts::StuckCars.AddCarToCheck(ScriptParams[0], *(float*)&ScriptParams[1], ScriptParams[2]); - return 0; - } - case COMMAND_REMOVE_STUCK_CAR_CHECK: - { - CollectParameters(&m_nIp, 1); - CTheScripts::StuckCars.RemoveCarFromCheck(ScriptParams[0]); - return 0; - } - case COMMAND_IS_CAR_STUCK: - CollectParameters(&m_nIp, 1); - UpdateCompareFlag(CTheScripts::StuckCars.HasCarBeenStuckForAWhile(ScriptParams[0])); - return 0; - case COMMAND_LOAD_MISSION_AUDIO: - strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - str[i] = tolower(str[i]); - m_nIp += KEY_LENGTH_IN_SCRIPT; - DMAudio.PreloadMissionAudio(str); - return 0; - case COMMAND_HAS_MISSION_AUDIO_LOADED: - UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1); - return 0; - case COMMAND_PLAY_MISSION_AUDIO: - DMAudio.PlayLoadedMissionAudio(); - return 0; - case COMMAND_HAS_MISSION_AUDIO_FINISHED: - UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished()); - return 0; - case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); - *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition(); - *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node); - StoreParameters(&m_nIp, 4); - return 0; - } - case COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED: - { - CollectParameters(&m_nIp, 2); - UpdateCompareFlag(CGarages::HasImportExportGarageCollectedThisCar(ScriptParams[0], ScriptParams[1] - 1)); - return 0; - } - case COMMAND_CLEAR_THIS_PRINT: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CMessages::ClearThisPrint(text); - return 0; - } - case COMMAND_CLEAR_THIS_BIG_PRINT: - { - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CMessages::ClearThisBigPrint(text); - return 0; - } - case COMMAND_SET_MISSION_AUDIO_POSITION: - { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - DMAudio.SetMissionAudioLocation(pos.x, pos.y, pos.z); - return 0; - } - case COMMAND_ACTIVATE_SAVE_MENU: - FrontEndMenuManager.m_bSaveMenuActive = true; - return 0; - case COMMAND_HAS_SAVE_GAME_FINISHED: - UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive); - return 0; - case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE: - CollectParameters(&m_nIp, 1); - CGarages::SetLeaveCameraForThisGarage(ScriptParams[0]); - return 0; - case COMMAND_ADD_BLIP_FOR_PICKUP_OLD: - { - CollectParameters(&m_nIp, 3); - CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject; - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), ScriptParams[1], (eBlipDisplay)ScriptParams[2]); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_BLIP_FOR_PICKUP: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject; - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH); - CRadar::ChangeBlipScale(handle, 3); - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject; - CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); - int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH); - CRadar::SetBlipSprite(handle, ScriptParams[1]); - ScriptParams[0] = handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_PED_DENSITY_MULTIPLIER: - CollectParameters(&m_nIp, 1); - CPopulation::PedDensityMultiplier = *(float*)&ScriptParams[0]; - return 0; - case COMMAND_FORCE_RANDOM_PED_TYPE: - CollectParameters(&m_nIp, 1); - CPopulation::m_AllRandomPedsThisType = ScriptParams[0]; - return 0; - case COMMAND_SET_TEXT_DRAW_BEFORE_FADE: - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextBeforeFade = ScriptParams[0] != 0; - return 0; - case COMMAND_GET_COLLECTABLE1S_COLLECTED: - ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages; - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_REGISTER_EL_BURRO_TIME: - CollectParameters(&m_nIp, 1); - CStats::RegisterElBurroTime(ScriptParams[0]); - return 0; - case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE: - CollectParameters(&m_nIp, 1); - CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0; - return 0; - case COMMAND_SET_TEXT_RIGHT_JUSTIFY: - CollectParameters(&m_nIp, 1); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bRightJustify = ScriptParams[0] != 0; - return 0; - case COMMAND_PRINT_HELP: - { - if (CCamera::m_bUseMouse3rdPerson && ( - strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15", 7) == 0 || - strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A", 7) == 0 || - strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_3A", 7) == 0 || - strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_4A", 7) == 0)) { - m_nIp += KEY_LENGTH_IN_SCRIPT; - return 0; - } - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CHud::SetHelpMessage(text, false); - return 0; - } - case COMMAND_CLEAR_HELP: - CHud::SetHelpMessage(nil, false); - return 0; - case COMMAND_FLASH_HUD_OBJECT: - CollectParameters(&m_nIp, 1); - CHud::m_ItemToFlash = ScriptParams[0]; - return 0; - default: - script_assert(0); - } - return -1; -} - -int8 CRunningScript::ProcessCommands1000To1099(int32 command) -{ -#ifdef GTA_PS2 - char tmp[48]; -#endif - switch (command) { - //case COMMAND_FLASH_RADAR_BLIP: - case COMMAND_IS_CHAR_IN_CONTROL: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(pPed->IsPedInControl()); - return 0; - } - case COMMAND_SET_GENERATE_CARS_AROUND_CAMERA: - CollectParameters(&m_nIp, 1); - CCarCtrl::bCarsGeneratedAroundCamera = (ScriptParams[0] != 0); - return 0; - case COMMAND_CLEAR_SMALL_PRINTS: - CMessages::ClearSmallMessagesOnly(); - return 0; - case COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS: - UpdateCompareFlag(CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()); - return 0; - case COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - CAutomobile* pCar = (CAutomobile*)pVehicle; - pCar->bNotDamagedUpsideDown = (ScriptParams[1] != 0); - return 0; - } - case COMMAND_CAN_PLAYER_START_MISSION: - { - CollectParameters(&m_nIp, 1); - CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPlayerPed); - UpdateCompareFlag(pPlayerPed->IsPedInControl() || pPlayerPed->m_nPedState == PED_DRIVING); - return 0; - } - case COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE: - { - CollectParameters(&m_nIp, 1); -#ifdef MISSION_REPLAY - AllowMissionReplay = 0; - SaveGameForPause(3); -#endif - CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; - CPad::GetPad(ScriptParams[0])->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE); - pPlayerInfo->MakePlayerSafe(true); - CCutsceneMgr::StartCutsceneProcessing(); - return 0; - } - case COMMAND_USE_TEXT_COMMANDS: - CollectParameters(&m_nIp, 1); - CTheScripts::UseTextCommands = (ScriptParams[0] != 0) ? 2 : 1; - return 0; - case COMMAND_SET_THREAT_FOR_PED_TYPE: - CollectParameters(&m_nIp, 2); - CPedType::AddThreat(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_CLEAR_THREAT_FOR_PED_TYPE: - CollectParameters(&m_nIp, 2); - CPedType::RemoveThreat(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_GET_CAR_COLOURS: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - ScriptParams[0] = pVehicle->m_currentColour1; - ScriptParams[1] = pVehicle->m_currentColour2; - StoreParameters(&m_nIp, 2); - return 0; - } - case COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED: - CollectParameters(&m_nIp, 1); - CWorld::SetAllCarsCanBeDamaged(ScriptParams[0] != 0); - if (!ScriptParams[0]) - CWorld::ExtinguishAllCarFiresInArea(FindPlayerCoors(), 4000.0f); - return 0; - case COMMAND_SET_CAR_CAN_BE_DAMAGED: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - pVehicle->bCanBeDamaged = ScriptParams[1] != 0; - if (!ScriptParams[1]) - pVehicle->ExtinguishCarFire(); - return 0; - } - //case COMMAND_MAKE_PLAYER_UNSAFE: - case COMMAND_LOAD_COLLISION: - { - CollectParameters(&m_nIp, 1); - CTimer::Stop(); - CGame::currLevel = (eLevelName)ScriptParams[0]; - ISLAND_LOADING_IS(LOW) - { - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - } - CCollision::SortOutCollisionAfterLoad(); - ISLAND_LOADING_ISNT(HIGH) - { - CStreaming::RequestIslands(CGame::currLevel); - CStreaming::LoadAllRequestedModels(true); - } - CTimer::Update(); - return 0; - } - case COMMAND_GET_BODY_CAST_HEALTH: - ScriptParams[0] = CObject::nBodyCastHealth; - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_SET_CHARS_CHATTING: - { - CollectParameters(&m_nIp, 3); - CPed* pPed1 = CPools::GetPedPool()->GetAt(ScriptParams[0]); - CPed* pPed2 = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pPed1 && pPed2); - pPed1->SetChat(pPed2, ScriptParams[2]); - pPed2->SetChat(pPed1, ScriptParams[2]); - return 0; - } - //case COMMAND_MAKE_PLAYER_SAFE: - case COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - if (ScriptParams[1]) - pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); - else - pVehicle->m_nZoneLevel = LEVEL_GENERIC; - return 0; - } - case COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - if (ScriptParams[1]) - pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); - else - pPed->m_nZoneLevel = LEVEL_GENERIC; - return 0; - } - case COMMAND_REGISTER_4X4_ONE_TIME: - CollectParameters(&m_nIp, 1); - CStats::Register4x4OneTime(ScriptParams[0]); - return 0; - case COMMAND_REGISTER_4X4_TWO_TIME: - CollectParameters(&m_nIp, 1); - CStats::Register4x4TwoTime(ScriptParams[0]); - return 0; - case COMMAND_REGISTER_4X4_THREE_TIME: - CollectParameters(&m_nIp, 1); - CStats::Register4x4ThreeTime(ScriptParams[0]); - return 0; - case COMMAND_REGISTER_4X4_MAYHEM_TIME: - CollectParameters(&m_nIp, 1); - CStats::Register4x4MayhemTime(ScriptParams[0]); - return 0; - case COMMAND_REGISTER_LIFE_SAVED: - CStats::AnotherLifeSavedWithAmbulance(); - return 0; - case COMMAND_REGISTER_CRIMINAL_CAUGHT: - CStats::AnotherCriminalCaught(); - return 0; - case COMMAND_REGISTER_AMBULANCE_LEVEL: - CollectParameters(&m_nIp, 1); - CStats::RegisterLevelAmbulanceMission(ScriptParams[0]); - return 0; - case COMMAND_REGISTER_FIRE_EXTINGUISHED: - CStats::AnotherFireExtinguished(); - return 0; - case COMMAND_TURN_PHONE_ON: - CollectParameters(&m_nIp, 1); - gPhoneInfo.m_aPhones[ScriptParams[0]].m_nState = PHONE_STATE_9; - return 0; - case COMMAND_REGISTER_LONGEST_DODO_FLIGHT: - CollectParameters(&m_nIp, 1); - CStats::RegisterLongestFlightInDodo(ScriptParams[0]); - return 0; - case COMMAND_REGISTER_DEFUSE_BOMB_TIME: - CollectParameters(&m_nIp, 1); - CStats::RegisterTimeTakenDefuseMission(ScriptParams[0]); - return 0; - case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES: - CollectParameters(&m_nIp, 1); - CStats::SetTotalNumberKillFrenzies(ScriptParams[0]); - return 0; - case COMMAND_BLOW_UP_RC_BUGGY: - CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(); - return 0; - case COMMAND_REMOVE_CAR_FROM_CHASE: - CollectParameters(&m_nIp, 1); - CRecordDataForChase::RemoveCarFromChase(ScriptParams[0]); - return 0; - case COMMAND_IS_FRENCH_GAME: - UpdateCompareFlag(CGame::frenchGame); - return 0; - case COMMAND_IS_GERMAN_GAME: - UpdateCompareFlag(CGame::germanGame); - return 0; - case COMMAND_CLEAR_MISSION_AUDIO: - DMAudio.ClearMissionAudio(); - return 0; - case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST: - CollectParameters(&m_nIp, 1); - CRestart::bFadeInAfterNextArrest = !!ScriptParams[0]; - return 0; - case COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH: - CollectParameters(&m_nIp, 1); - CRestart::bFadeInAfterNextDeath = !!ScriptParams[0]; - return 0; - case COMMAND_SET_GANG_PED_MODEL_PREFERENCE: - CollectParameters(&m_nIp, 2); - CGangs::SetGangPedModelOverride(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_SET_CHAR_USE_PEDNODE_SEEK: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - if (ScriptParams[1]) - pPed->m_pNextPathNode = nil; - pPed->bUsePedNodeSeek = !!ScriptParams[1]; - return 0; - } - case COMMAND_SWITCH_VEHICLE_WEAPONS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->bGunSwitchedOff = !ScriptParams[1]; - return 0; - } - case COMMAND_SET_GET_OUT_OF_JAIL_FREE: - CollectParameters(&m_nIp, 2); - CWorld::Players[ScriptParams[0]].m_bGetOutOfJailFree = !!ScriptParams[1]; - return 0; - case COMMAND_SET_FREE_HEALTH_CARE: - CollectParameters(&m_nIp, 2); - CWorld::Players[ScriptParams[0]].m_bGetOutOfHospitalFree = !!ScriptParams[1]; - return 0; - case COMMAND_IS_CAR_DOOR_CLOSED: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - UpdateCompareFlag(!pVehicle->IsDoorMissing((eDoors)ScriptParams[1]) && pVehicle->IsDoorClosed((eDoors)ScriptParams[1])); - return 0; - } - case COMMAND_LOAD_AND_LAUNCH_MISSION: - return 0; - case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL: - { - CollectParameters(&m_nIp, 1); -#ifdef MISSION_REPLAY - missionRetryScriptIndex = ScriptParams[0]; - if (missionRetryScriptIndex == 19) - CStats::LastMissionPassedName[0] = '\0'; -#endif - CTimer::Suspend(); - int offset = CTheScripts::MultiScriptArray[ScriptParams[0]]; - CFileMgr::ChangeDir("\\"); - int handle = CFileMgr::OpenFile("data\\main.scm", "rb"); - CFileMgr::Seek(handle, offset, 0); - CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT); - CFileMgr::CloseFile(handle); - CRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT); - CTimer::Resume(); - pMissionScript->m_bIsMissionScript = true; - pMissionScript->m_bMissionFlag = true; - CTheScripts::bAlreadyRunningAMissionScript = true; - return 0; - } - case COMMAND_SET_OBJECT_DRAW_LAST: - { - CollectParameters(&m_nIp, 2); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - pObject->bDrawLast = !!ScriptParams[1]; - return 0; - } - case COMMAND_GET_AMMO_IN_PLAYER_WEAPON: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]]; - if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1]) - ScriptParams[0] = pWeaponSlot->m_nAmmoTotal; - else - ScriptParams[0] = 0; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_AMMO_IN_CHAR_WEAPON: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]]; - if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1]) - ScriptParams[0] = pWeaponSlot->m_nAmmoTotal; - else - ScriptParams[0] = 0; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_REGISTER_KILL_FRENZY_PASSED: - CStats::AnotherKillFrenzyPassed(); - return 0; - case COMMAND_SET_CHAR_SAY: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - switch (ScriptParams[1]) { - case SCRIPT_SOUND_CHUNKY_RUN_SHOUT: - pPed->Say(SOUND_PED_FLEE_RUN); - break; - case SCRIPT_SOUND_SECURITY_GUARD_AWAY_SHOUT: - pPed->Say(SOUND_PED_FLEE_RUN); - break; - case SCRIPT_SOUND_SWAT_PED_SHOUT: - pPed->Say(SOUND_PED_PURSUIT_SWAT); - break; - case SCRIPT_SOUND_AMMUNATION_CHAT_1: - pPed->Say(SOUND_AMMUNATION_WELCOME_1); - break; - case SCRIPT_SOUND_AMMUNATION_CHAT_2: - pPed->Say(SOUND_AMMUNATION_WELCOME_2); - break; - case SCRIPT_SOUND_AMMUNATION_CHAT_3: - pPed->Say(SOUND_AMMUNATION_WELCOME_3); - break; - default: - break; - } - return 0; - } - case COMMAND_SET_NEAR_CLIP: - CollectParameters(&m_nIp, 1); - TheCamera.SetNearClipScript(*(float*)&ScriptParams[0]); - return 0; - case COMMAND_SET_RADIO_CHANNEL: - CollectParameters(&m_nIp, 2); - DMAudio.SetRadioChannel(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_OVERRIDE_HOSPITAL_LEVEL: - CollectParameters(&m_nIp, 1); - CRestart::OverrideHospitalLevel = ScriptParams[0]; - return 0; - case COMMAND_OVERRIDE_POLICE_STATION_LEVEL: - CollectParameters(&m_nIp, 1); - CRestart::OverridePoliceStationLevel = ScriptParams[0]; - return 0; - case COMMAND_FORCE_RAIN: - CollectParameters(&m_nIp, 1); - CWeather::bScriptsForceRain = !!ScriptParams[0]; - return 0; - case COMMAND_DOES_GARAGE_CONTAIN_CAR: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pVehicle); - UpdateCompareFlag(CGarages::IsThisCarWithinGarageArea(ScriptParams[0], pVehicle)); - return 0; - } - case COMMAND_SET_CAR_TRACTION: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - float fTraction = *(float*)&ScriptParams[1]; - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR || pVehicle->m_vehType == VEHICLE_TYPE_BIKE); - if (pVehicle->m_vehType == VEHICLE_TYPE_CAR) - ((CAutomobile*)pVehicle)->m_fTraction = fTraction; - else - // this is certainly not a boat, trane, heli or plane field - //((CBike*)pVehicle)->m_fTraction = fTraction; - *(float*)(((char*)pVehicle) + 1088) = fTraction; - return 0; - } - case COMMAND_ARE_MEASUREMENTS_IN_METRES: -#ifdef USE_MEASUREMENTS_IN_METERS - UpdateCompareFlag(true); -#else - UpdateCompareFlag(false) -#endif - return 0; - case COMMAND_CONVERT_METRES_TO_FEET: - { - CollectParameters(&m_nIp, 1); - float fMeterValue = *(float*)&ScriptParams[0]; - float fFeetValue = fMeterValue / METERS_IN_FOOT; - *(float*)&ScriptParams[0] = fFeetValue; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_MARK_ROADS_BETWEEN_LEVELS: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ThePaths.MarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ); - return 0; - } - case COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - ThePaths.PedMarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ); - return 0; - } - case COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->AutoPilot.m_bStayInCurrentLevel = !!ScriptParams[1]; - return 0; - } - case COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pPed); - // not implemented - return 0; - } - case COMMAND_IS_THREAT_FOR_PED_TYPE: - CollectParameters(&m_nIp, 2); - UpdateCompareFlag(CPedType::IsThreat(ScriptParams[0], ScriptParams[1])); - return 0; - case COMMAND_CLEAR_AREA_OF_CHARS: - { - CollectParameters(&m_nIp, 6); - float infX = *(float*)&ScriptParams[0]; - float infY = *(float*)&ScriptParams[1]; - float infZ = *(float*)&ScriptParams[2]; - float supX = *(float*)&ScriptParams[3]; - float supY = *(float*)&ScriptParams[4]; - float supZ = *(float*)&ScriptParams[5]; - if (infX > supX) { - infX = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[0]; - } - if (infY > supY) { - infY = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[1]; - } - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[2]; - } - CWorld::ClearPedsFromArea(infX, infY, infZ, supX, supY, supZ); - return 0; - } - case COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS: - CollectParameters(&m_nIp, 1); - CStats::SetTotalNumberMissions(ScriptParams[0]); - return 0; - case COMMAND_CONVERT_METRES_TO_FEET_INT: - CollectParameters(&m_nIp, 1); - ScriptParams[0] *= FEET_IN_METER; - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_REGISTER_FASTEST_TIME: - CollectParameters(&m_nIp, 2); - CStats::RegisterFastestTime(ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_REGISTER_HIGHEST_SCORE: - CollectParameters(&m_nIp, 2); - CStats::RegisterHighestScore(ScriptParams[0], ScriptParams[1]); - return 0; - //case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER: - //case COMMAND_IS_CAR_PASSENGER_SEAT_FREE: - case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(ScriptParams[1] >= 0 && ScriptParams[1] < ARRAY_SIZE(pVehicle->pPassengers)); - CPed* pPassenger = pVehicle->pPassengers[ScriptParams[1]]; - ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPassenger); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bChrisCriminal = !!ScriptParams[1]; - return 0; - } - case COMMAND_START_CREDITS: - CCredits::Start(); - return 0; - case COMMAND_STOP_CREDITS: - CCredits::Stop(); - return 0; - case COMMAND_ARE_CREDITS_FINISHED: - UpdateCompareFlag(CCredits::AreCreditsDone()); - return 0; - case COMMAND_CREATE_SINGLE_PARTICLE: - CollectParameters(&m_nIp, 8); - CParticle::AddParticle((tParticleType)ScriptParams[0], *(CVector*)&ScriptParams[1], - *(CVector*)&ScriptParams[4], nil, *(float*)&ScriptParams[7], 0, 0, 0, 0); - return 0; - case COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - if (ScriptParams[1]) - pPed->m_nZoneLevel = LEVEL_IGNORE; - else - pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); - return 0; - } - case COMMAND_GET_CHASE_CAR: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CRecordDataForChase::TurnChaseCarIntoScriptCar(ScriptParams[0]); - ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle); - StoreParameters(&m_nIp, 1); - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CAR); - return 0; - } - case COMMAND_START_BOAT_FOAM_ANIMATION: - CSpecialParticleStuff::StartBoatFoamAnimation(); - return 0; - case COMMAND_UPDATE_BOAT_FOAM_ANIMATION: - { - CollectParameters(&m_nIp, 1); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CSpecialParticleStuff::UpdateBoatFoamAnimation(&pObject->GetMatrix()); - return 0; - } - case COMMAND_SET_MUSIC_DOES_FADE: - CollectParameters(&m_nIp, 1); - TheCamera.m_bIgnoreFadingStuffForMusic = (ScriptParams[0] == 0); - return 0; - case COMMAND_SET_INTRO_IS_PLAYING: - CollectParameters(&m_nIp, 1); - if (ScriptParams[0]) { - CGame::playingIntro = true; - CStreaming::RemoveCurrentZonesModels(); - } else { - CGame::playingIntro = false; - DMAudio.ChangeMusicMode(MUSICMODE_GAME); - int mi; - CModelInfo::GetModelInfo("bridgefukb", &mi); - CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY); - CStreaming::LoadAllRequestedModels(false); - } - return 0; - case COMMAND_SET_PLAYER_HOOKER: - { - CollectParameters(&m_nIp, 2); - CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; - if (ScriptParams[1] < 0) { - pPlayerInfo->m_pHooker = nil; - pPlayerInfo->m_nNextSexFrequencyUpdateTime = 0; - pPlayerInfo->m_nNextSexMoneyUpdateTime = 0; - } else { - CPed* pHooker = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pHooker); - pPlayerInfo->m_pHooker = (CCivilianPed*)pHooker; - pPlayerInfo->m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000; - pPlayerInfo->m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; - } - return 0; - } - case COMMAND_PLAY_END_OF_GAME_TUNE: - DMAudio.PlayPreloadedCutSceneMusic(); - return 0; - case COMMAND_STOP_END_OF_GAME_TUNE: - DMAudio.StopCutSceneMusic(); - DMAudio.ChangeMusicMode(MUSICMODE_GAME); - return 0; - case COMMAND_GET_CAR_MODEL: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - ScriptParams[0] = pVehicle->GetModelIndex(); - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_IS_PLAYER_SITTING_IN_CAR: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pVehicle); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle); - return 0; - } - case COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR: - { - CollectParameters(&m_nIp, 1); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING); - return 0; - } - case COMMAND_SET_SCRIPT_FIRE_AUDIO: - CollectParameters(&m_nIp, 2); - gFireManager.SetScriptFireAudio(ScriptParams[0], !!ScriptParams[1]); - return 0; - case COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED: - UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3); - return 0; - case COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->bNoCriticalHits = (ScriptParams[0] == 0); - return 0; - } - case COMMAND_IS_PLAYER_LIFTING_A_PHONE: - { - CollectParameters(&m_nIp, 1); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - UpdateCompareFlag(pPed->GetPedState() == PED_MAKE_CALL); - return 0; - } - case COMMAND_IS_CHAR_SITTING_IN_CAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pVehicle); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle); - return 0; - } - case COMMAND_IS_CHAR_SITTING_IN_ANY_CAR: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING); - return 0; - } - case COMMAND_IS_PLAYER_ON_FOOT: - { - CollectParameters(&m_nIp, 1); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && - pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER); - return 0; - } - case COMMAND_IS_CHAR_ON_FOOT: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && - pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER); - return 0; - } -#ifndef GTA_PS2 - default: - script_assert(0); - } - return -1; -} - -int8 CRunningScript::ProcessCommands1100To1199(int32 command) -{ - char tmp[48]; - switch (command) { -#endif - case COMMAND_LOAD_COLLISION_WITH_SCREEN: - CollectParameters(&m_nIp, 1); - CTimer::Stop(); - CGame::currLevel = (eLevelName)ScriptParams[0]; - if (CGame::currLevel != CCollision::ms_collisionInMemory) { - ISLAND_LOADING_IS(LOW) - { - DMAudio.SetEffectsFadeVol(0); - CPad::StopPadsShaking(); - CCollision::LoadCollisionScreen(CGame::currLevel); - DMAudio.Service(); - } - CPopulation::DealWithZoneChange(CCollision::ms_collisionInMemory, CGame::currLevel, false); - - ISLAND_LOADING_IS(LOW) - { - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - } - CCollision::SortOutCollisionAfterLoad(); - - ISLAND_LOADING_ISNT(HIGH) - CStreaming::RequestIslands(CGame::currLevel); - - ISLAND_LOADING_IS(LOW) - CStreaming::RequestBigBuildings(CGame::currLevel); - - ISLAND_LOADING_ISNT(HIGH) - CStreaming::LoadAllRequestedModels(true); - - ISLAND_LOADING_IS(LOW) - DMAudio.SetEffectsFadeVol(127); - } - CTimer::Update(); - return 0; - case COMMAND_LOAD_SPLASH_SCREEN: - CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - tmp[i] = tolower(tmp[i]); - m_nIp += 8; - LoadSplash(tmp); - return 0; - case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - if (ScriptParams[1]) - pVehicle->m_nZoneLevel = LEVEL_IGNORE; - else - pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); - return 0; - } - case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - CAutomobile* pCar = (CAutomobile*)pVehicle; - pCar->bMoreResistantToDamage = ScriptParams[1]; - return 0; - } - case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), false); - return 0; - } - case COMMAND_LOAD_END_OF_GAME_TUNE: - DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE); - printf("Start preload end of game audio\n"); - DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED); - printf("End preload end of game audio\n"); - return 0; - case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA: - CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CAMERA); - return 0; -#ifndef GTA_PS2 - // To be precise, on PS2 previous handlers were in 1000-1099 function - // These are "beta" VC commands (with bugs) - case COMMAND_SET_OBJECT_ROTATION: - { - CollectParameters(&m_nIp, 4); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CWorld::Remove(pObject); - pObject->SetOrientation( - DEGTORAD(*(float*)&ScriptParams[1]), - DEGTORAD(*(float*)&ScriptParams[2]), - DEGTORAD(*(float*)&ScriptParams[3])); - pObject->GetMatrix().UpdateRW(); - pObject->UpdateRwFrame(); - CWorld::Add(pObject); - return 0; - } - case COMMAND_GET_DEBUG_CAMERA_COORDINATES: - *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source; - StoreParameters(&m_nIp, 3); - return 0; - case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR: - *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front; - StoreParameters(&m_nIp, 3); - return 0; - case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR: - { - CollectParameters(&m_nIp, 1); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CEntity* pTarget = pPed->m_pPointGunAt; - UpdateCompareFlag(pTarget && pTarget->IsPed()); - return 0; - } - case COMMAND_IS_PLAYER_TARGETTING_CHAR: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pTestedPed); - CEntity* pTarget = pPed->m_pPointGunAt; - UpdateCompareFlag(pTarget && pTarget->IsPed() && pTarget == pTestedPed); - return 0; - } - case COMMAND_IS_PLAYER_TARGETTING_OBJECT: - { - CollectParameters(&m_nIp, 2); - CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - CObject* pTestedObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); - script_assert(pTestedObject); - CEntity* pTarget = pPed->m_pPointGunAt; - UpdateCompareFlag(pTarget && pTarget->IsObject() && pTarget == pTestedObject); - return 0; - } - case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME: - { - CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp); - for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) - tmp[i] = tolower(tmp[i]); - m_nIp += 8; - CRunningScript* pScript = CTheScripts::pActiveScripts; - while (pScript) { - CRunningScript* pNext = pScript->next; - if (strcmp(pScript->m_abScriptName, tmp) == 0) { - pScript->RemoveScriptFromList(&CTheScripts::pActiveScripts); - pScript->AddScriptToList(&CTheScripts::pIdleScripts); - } - pScript = pNext; - } - return 0; - } - case COMMAND_DISPLAY_TEXT_WITH_NUMBER: - { - CollectParameters(&m_nIp, 2); - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0]; - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1]; - CollectParameters(&m_nIp, 1); - CMessages::InsertNumberInString(text, ScriptParams[0], -1, -1, -1, -1, -1, - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text); - return 0; - } - case COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS: - { - CollectParameters(&m_nIp, 2); - wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0]; - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1]; - CollectParameters(&m_nIp, 2); - CMessages::InsertNumberInString(text, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1, - CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text); - return 0; - } - case COMMAND_FAIL_CURRENT_MISSION: - CTheScripts::FailCurrentMission = 2; - return 0; - case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: - { - CollectParameters(&m_nIp, 5); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float range = *(float*)&ScriptParams[3]; - int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4]; - int16 total; - CEntity* apEntities[16]; - CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true); - CEntity* pClosestEntity = nil; - float min_dist = 2.0f * range; - for (int i = 0; i < total; i++) { - float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); - if (dist < min_dist) { - min_dist = dist; - pClosestEntity = apEntities[i]; - } - } - if (pClosestEntity && pClosestEntity->IsDummy()) { - CPopulation::ConvertToRealObject((CDummyObject*)pClosestEntity); - CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true); - pClosestEntity = nil; - float min_dist = 2.0f * range; - for (int i = 0; i < total; i++) { - float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); - if (dist < min_dist) { - min_dist = dist; - pClosestEntity = apEntities[i]; - } - } - if (pClosestEntity->IsDummy()) - pClosestEntity = nil; - } - if (pClosestEntity) { - script_assert(pClosestEntity->IsObject()); - CObject* pObject = (CObject*)pClosestEntity; - pObject->ObjectCreatedBy = MISSION_OBJECT; - ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObject); - } else { - ScriptParams[0] = -1; - } - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT: - { - CollectParameters(&m_nIp, 5); - CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); - script_assert(pObject); - CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CVector offset = *(CVector*)&ScriptParams[2]; - CPhysical::PlacePhysicalRelativeToOtherPhysical(pTarget, pObject, offset); - return 0; - } - case COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - if (pVehicle->pDriver) { - pVehicle->pDriver->bScriptObjectiveCompleted = false; - pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); - } - for (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++) - { - if (pVehicle->pPassengers[i]) { - pVehicle->pPassengers[i]->bScriptObjectiveCompleted = false; - pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); - } - } - return 0; - } - case COMMAND_SET_INTERPOLATION_PARAMETERS: - CollectParameters(&m_nIp, 2); - TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 50.0f - *(float*)&ScriptParams[0], ScriptParams[1]); - return 0; - case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT: - { - CollectParameters(&m_nIp, 5); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float destX = *(float*)&ScriptParams[3]; - float destY = *(float*)&ScriptParams[4]; - int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); - CPathNode* pNode = &ThePaths.m_pathNodes[nid]; - *(CVector*)&ScriptParams[0] = pNode->GetPosition(); - *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true); - StoreParameters(&m_nIp, 4); - return 0; - } - case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT: - { - CollectParameters(&m_nIp, 5); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float destX = *(float*)&ScriptParams[3]; - float destY = *(float*)&ScriptParams[4]; - int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); - CPathNode* pNode = &ThePaths.m_pathNodes[nid]; - *(CVector*)&ScriptParams[0] = pNode->GetPosition(); - *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false); - StoreParameters(&m_nIp, 4); - return 0; - } - case COMMAND_GET_DEBUG_CAMERA_POINT_AT: - *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source + TheCamera.Cams[2].Front; - StoreParameters(&m_nIp, 3); - return 0; - case COMMAND_ATTACH_CHAR_TO_CAR: - // empty implementation - return 0; - case COMMAND_DETACH_CHAR_FROM_CAR: - // empty implementation - return 0; - case COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->AutoPilot.m_bStayInFastLane = !ScriptParams[1]; - return 0; - } - case COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - pPed->m_lastWepDam = -1; - return 0; - } - case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - pVehicle->m_nLastWeaponDamage = -1; - return 0; - } - case COMMAND_GET_RANDOM_COP_IN_AREA: - { - CollectParameters(&m_nIp, 4); - int ped_handle = -1; - CVector pos = FindPlayerCoors(); - float x1 = *(float*)&ScriptParams[0]; - float y1 = *(float*)&ScriptParams[1]; - float x2 = *(float*)&ScriptParams[2]; - float y2 = *(float*)&ScriptParams[3]; - int i = CPools::GetPedPool()->GetSize(); - while (--i && ped_handle == -1) { - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (!pPed) - continue; - if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) - continue; - if (pPed->m_nPedType != PEDTYPE_COP) - continue; - if (pPed->CharCreatedBy != RANDOM_CHAR) - continue; - if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING) - continue; - if (pPed->bRemoveFromWorld) - continue; - if (pPed->bFadeOut) - continue; - if (pPed->bIsLeader || pPed->m_leader) - continue; - if (!pPed->IsWithinArea(x1, y1, x2, y2)) - continue; - if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) - continue; - if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) - continue; - ped_handle = CPools::GetPedPool()->GetIndex(pPed); - CTheScripts::LastRandomPedId = ped_handle; - pPed->CharCreatedBy = MISSION_CHAR; - pPed->bRespondsToThreats = false; - ++CPopulation::ms_nTotalMissionPeds; - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); - } - ScriptParams[0] = ped_handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_RANDOM_COP_IN_ZONE: - { - char zone[KEY_LENGTH_IN_SCRIPT]; - strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); - int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone); - if (nZone != -1) - m_nIp += KEY_LENGTH_IN_SCRIPT; - CZone* pZone = CTheZones::GetZone(nZone); - int ped_handle = -1; - CVector pos = FindPlayerCoors(); - int i = CPools::GetPedPool()->GetSize(); - while (--i && ped_handle == -1) { - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (!pPed) - continue; - if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) - continue; - if (pPed->m_nPedType != PEDTYPE_COP) - continue; - if (pPed->CharCreatedBy != RANDOM_CHAR) - continue; - if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING) - continue; - if (pPed->bRemoveFromWorld) - continue; - if (pPed->bFadeOut) - continue; - if (pPed->bIsLeader || pPed->m_leader) - continue; - if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone)) - continue; - if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) - continue; - if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) - continue; - ped_handle = CPools::GetPedPool()->GetIndex(pPed); - CTheScripts::LastRandomPedId = ped_handle; - pPed->CharCreatedBy = MISSION_CHAR; - pPed->bRespondsToThreats = false; - ++CPopulation::ms_nTotalMissionPeds; - if (m_bIsMissionScript) - CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); - } - ScriptParams[0] = ped_handle; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_SET_CHAR_OBJ_FLEE_CAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pVehicle); - pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FLEE_CAR, pVehicle); - return 0; - } - case COMMAND_GET_DRIVER_OF_CAR: - { - CollectParameters(&m_nIp, 1); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CPed* pDriver = pVehicle->pDriver; - if (pDriver) - ScriptParams[0] = CPools::GetPedPool()->GetIndex(pDriver); - else - ScriptParams[0] = -1; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_NUMBER_OF_FOLLOWERS: - { - CollectParameters(&m_nIp, 1); - CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pLeader); - int total = 0; - int i = CPools::GetPedPool()->GetSize(); - while (--i) { - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (!pPed) - continue; - if (pPed->m_leader == pLeader) - total++; - } - ScriptParams[0] = total; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER: - { - CollectParameters(&m_nIp, 6); - CVector pos = *(CVector*)&ScriptParams[1]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4]), ScriptParams[5]); - return 0; - } - case COMMAND_GET_CURRENT_PLAYER_WEAPON: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_GET_CURRENT_CHAR_WEAPON: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType; - StoreParameters(&m_nIp, 1); - return 0; - } - case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D: - case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D: - case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D: - case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D: - case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D: - case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D: - LocateCharObjectCommand(command, &m_nIp); - return 0; - case COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT: // this will be changed in final VC version to a more general SET_TEMP_ACTION - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNLEFT; - pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; - return 0; - } - case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNRIGHT; - pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; - return 0; - } - case COMMAND_SET_CAR_HANDBRAKE_STOP: - { - CollectParameters(&m_nIp, 2); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT; - pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; - return 0; - } - case COMMAND_IS_CHAR_ON_ANY_BIKE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE); - return 0; - } - case COMMAND_LOCATE_SNIPER_BULLET_2D: - case COMMAND_LOCATE_SNIPER_BULLET_3D: - LocateSniperBulletCommand(command, &m_nIp); - return 0; - case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL: - CollectParameters(&m_nIp, 1); - ScriptParams[0] = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(ScriptParams[0]) + 1; - StoreParameters(&m_nIp, 1); - return 0; - case COMMAND_IS_PLAYER_ON_ANY_BIKE: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - script_assert(pPed); - UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE); - return 0; - } - case COMMAND_IS_CHAR_LYING_DOWN: - { - CollectParameters(&m_nIp, 1); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - UpdateCompareFlag(pPed->bFallenDown); - return 0; - } - case COMMAND_CAN_CHAR_SEE_DEAD_CHAR: - { - CollectParameters(&m_nIp, 2); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - int pedtype = ScriptParams[1]; - bool can = false; - for (int i = 0; i < pPed->m_numNearPeds; i++) { - CPed* pTestPed = pPed->m_nearPeds[i]; - if (pTestPed->m_fHealth <= 0.0f && pTestPed->m_nPedType == pedtype && pPed->OurPedCanSeeThisOne(pTestPed)) - can = true; - } - UpdateCompareFlag(can); - return 0; - } - case COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER: - CollectParameters(&m_nIp, 1); -#ifdef FIX_BUGS - CPed::nEnterCarRangeMultiplier = *(float*)&ScriptParams[0]; -#else - CPed::nEnterCarRangeMultiplier = (float)ScriptParams[0]; -#endif - return 0; -#endif -#ifndef GTA3_1_1_PATCH - case COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER: - CollectParameters(&m_nIp, 1); -#ifdef FIX_BUGS - CPed::nThreatReactionRangeMultiplier = *(float*)&ScriptParams[0]; -#else - CPed::nThreatReactionRangeMultiplier = (float)ScriptParams[0]; -#endif - return 0; -#endif - default: - script_assert(0); - } - return -1; -} - -int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index) -{ - if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1) - ScriptSphereArray[index].m_Index = 1; - else - ScriptSphereArray[index].m_Index++; - return (uint16)index | ScriptSphereArray[index].m_Index << 16; -} - -int32 CTheScripts::GetActualScriptSphereIndex(int32 index) -{ - if (index == -1) - return -1; - uint16 check = (uint32)index >> 16; - uint16 array_idx = index & (0xFFFF); - script_assert(array_idx < ARRAY_SIZE(ScriptSphereArray)); - if (check != ScriptSphereArray[array_idx].m_Index) - return -1; - return array_idx; -} - -void CTheScripts::DrawScriptSpheres() -{ - for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { - if (ScriptSphereArray[i].m_bInUse) - C3dMarkers::PlaceMarkerSet(ScriptSphereArray[i].m_Id, MARKERTYPE_CYLINDER, ScriptSphereArray[i].m_vecCenter, ScriptSphereArray[i].m_fRadius, - SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0); - } -} - -int32 CTheScripts::AddScriptSphere(int32 id, CVector pos, float radius) -{ - int16 i = 0; - for (i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { - if (!ScriptSphereArray[i].m_bInUse) - break; - } -#ifdef FIX_BUGS - if (i == MAX_NUM_SCRIPT_SPHERES) - return -1; -#endif - ScriptSphereArray[i].m_bInUse = true; - ScriptSphereArray[i].m_Id = id; - ScriptSphereArray[i].m_vecCenter = pos; - ScriptSphereArray[i].m_fRadius = radius; - return GetNewUniqueScriptSphereIndex(i); -} - -void CTheScripts::RemoveScriptSphere(int32 index) -{ - index = GetActualScriptSphereIndex(index); - if (index == -1) - return; - ScriptSphereArray[index].m_bInUse = false; - ScriptSphereArray[index].m_Id = 0; -} - -void CTheScripts::AddToBuildingSwapArray(CBuilding* pBuilding, int32 old_model, int32 new_model) -{ - int i = 0; - bool found = false; - while (i < MAX_NUM_BUILDING_SWAPS && !found) { - if (BuildingSwapArray[i].m_pBuilding == pBuilding) - found = true; - else - i++; - } - if (found) { - if (BuildingSwapArray[i].m_nOldModel == new_model) { - BuildingSwapArray[i].m_pBuilding = nil; - BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; - } - else { - BuildingSwapArray[i].m_nNewModel = new_model; - } - } - else { - i = 0; - while (i < MAX_NUM_BUILDING_SWAPS && !found) { - if (BuildingSwapArray[i].m_pBuilding == nil) - found = true; - else - i++; - } - if (found) { - BuildingSwapArray[i].m_pBuilding = pBuilding; - BuildingSwapArray[i].m_nNewModel = new_model; - BuildingSwapArray[i].m_nOldModel = old_model; - } - } -} - -void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove) -{ - int i = 0; - bool found = false; - while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { - if (InvisibilitySettingArray[i] == pEntity) - found = true; - else - i++; - } - if (found) { - if (remove) - InvisibilitySettingArray[i] = nil; - } - else if (!remove) { - i = 0; - while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { - if (InvisibilitySettingArray[i] == nil) - found = true; - else - i++; - } - if (found) - InvisibilitySettingArray[i] = pEntity; - } -} - -void CTheScripts::UndoBuildingSwaps() -{ - for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { - if (BuildingSwapArray[i].m_pBuilding) { - BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nOldModel); - BuildingSwapArray[i].m_pBuilding = nil; - BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; - } - } -} - -void CTheScripts::UndoEntityInvisibilitySettings() -{ - for (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { - if (InvisibilitySettingArray[i]) { - InvisibilitySettingArray[i]->bIsVisible = true; - InvisibilitySettingArray[i] = nil; - } - } -} - -void CRunningScript::UpdateCompareFlag(bool flag) -{ - if (m_bNotFlag) - flag = !flag; - if (m_nAndOrState == ANDOR_NONE) { - m_bCondResult = flag; - return; - } - if (m_nAndOrState >= ANDS_1 && m_nAndOrState <= ANDS_8) { - m_bCondResult &= flag; - if (m_nAndOrState == ANDS_1) { - m_nAndOrState = ANDOR_NONE; - return; - } - } - else if (m_nAndOrState >= ORS_1 && m_nAndOrState <= ORS_8) { - m_bCondResult |= flag; - if (m_nAndOrState == ORS_1) { - m_nAndOrState = ANDOR_NONE; - return; - } - } - else { - return; - } - m_nAndOrState--; -} - -void CRunningScript::LocatePlayerCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug, decided = false; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_3D: - case COMMAND_LOCATE_PLAYER_IN_CAR_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 8 : 6); - CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; - switch (command) { - case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D: - case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D: - case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D: - case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D: - if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) { - result = false; - decided = true; - } - break; - default: - break; - } - X = *(float*)&ScriptParams[1]; - Y = *(float*)&ScriptParams[2]; - if (b3D) { - Z = *(float*)&ScriptParams[3]; - dX = *(float*)&ScriptParams[4]; - dY = *(float*)&ScriptParams[5]; - dZ = *(float*)&ScriptParams[6]; - debug = ScriptParams[7]; - } else { - dX = *(float*)&ScriptParams[3]; - dY = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - if (!decided) { - CVector pos = pPlayerInfo->GetPos(); - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_LOCATE_PLAYER_ANY_MEANS_2D: - case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D: - case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D: - result = true; - break; - case COMMAND_LOCATE_PLAYER_ON_FOOT_2D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D: - case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D: - result = !pPlayerInfo->m_pPed->bInVehicle; - break; - case COMMAND_LOCATE_PLAYER_IN_CAR_2D: - case COMMAND_LOCATE_PLAYER_IN_CAR_3D: - case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D: - case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D: - result = pPlayerInfo->m_pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocatePlayerCharCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D: - case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 6 : 5); - CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CVector pos = pPlayerInfo->GetPos(); - if (pTarget->bInVehicle) { - X = pTarget->m_pMyVehicle->GetPosition().x; - Y = pTarget->m_pMyVehicle->GetPosition().y; - Z = pTarget->m_pMyVehicle->GetPosition().z; - } else { - X = pTarget->GetPosition().x; - Y = pTarget->GetPosition().y; - Z = pTarget->GetPosition().z; - } - dX = *(float*)&ScriptParams[2]; - dY = *(float*)&ScriptParams[3]; - if (b3D) { - dZ = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - else { - debug = ScriptParams[4]; - } - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } - else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D: - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D: - result = true; - break; - case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D: - result = !pPlayerInfo->m_pPed->bInVehicle; - break; - case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D: - case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D: - result = pPlayerInfo->m_pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - UpdateCompareFlag(result); - if (debug) -#ifdef FIX_BUGS - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); -#else - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT); -#endif - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocatePlayerCarCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D: - case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 6 : 5); - CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; - CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CVector pos = pPlayerInfo->GetPos(); - X = pTarget->GetPosition().x; - Y = pTarget->GetPosition().y; - Z = pTarget->GetPosition().z; - dX = *(float*)&ScriptParams[2]; - dY = *(float*)&ScriptParams[3]; - if (b3D) { - dZ = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - else { - debug = ScriptParams[4]; - } - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } - else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D: - case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D: - result = true; - break; - case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D: - case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D: - result = !pPlayerInfo->m_pPed->bInVehicle; - break; - case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D: - case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D: - result = pPlayerInfo->m_pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocateCharCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug, decided = false; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_3D: - case COMMAND_LOCATE_CHAR_ON_FOOT_3D: - case COMMAND_LOCATE_CHAR_IN_CAR_3D: - case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: - case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D: - case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 8 : 6); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); - switch (command) { - case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D: - case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: - case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D: - case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D: - case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D: - case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D: - if (!CTheScripts::IsPedStopped(pPed)) { - result = false; - decided = true; - } - break; - default: - break; - } - X = *(float*)&ScriptParams[1]; - Y = *(float*)&ScriptParams[2]; - if (b3D) { - Z = *(float*)&ScriptParams[3]; - dX = *(float*)&ScriptParams[4]; - dY = *(float*)&ScriptParams[5]; - dZ = *(float*)&ScriptParams[6]; - debug = ScriptParams[7]; - } - else { - dX = *(float*)&ScriptParams[3]; - dY = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - if (!decided) { - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } - else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_2D: - case COMMAND_LOCATE_CHAR_ANY_MEANS_3D: - case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D: - case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: - result = true; - break; - case COMMAND_LOCATE_CHAR_ON_FOOT_2D: - case COMMAND_LOCATE_CHAR_ON_FOOT_3D: - case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D: - case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D: - result = !pPed->bInVehicle; - break; - case COMMAND_LOCATE_CHAR_IN_CAR_2D: - case COMMAND_LOCATE_CHAR_IN_CAR_3D: - case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D: - case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D: - result = pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocateCharCharCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D: - case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D: - case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 6 : 5); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); - if (pTarget->bInVehicle) { - X = pTarget->m_pMyVehicle->GetPosition().x; - Y = pTarget->m_pMyVehicle->GetPosition().y; - Z = pTarget->m_pMyVehicle->GetPosition().z; - } - else { - X = pTarget->GetPosition().x; - Y = pTarget->GetPosition().y; - Z = pTarget->GetPosition().z; - } - dX = *(float*)&ScriptParams[2]; - dY = *(float*)&ScriptParams[3]; - if (b3D) { - dZ = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - else { - debug = ScriptParams[4]; - } - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } - else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D: - case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D: - result = true; - break; - case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D: - case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D: - result = !pPed->bInVehicle; - break; - case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D: - case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D: - result = pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - UpdateCompareFlag(result); - if (debug) -#ifdef FIX_BUGS - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); -#else - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT); -#endif - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocateCharCarCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D: - case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D: - case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 6 : 5); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); - X = pTarget->GetPosition().x; - Y = pTarget->GetPosition().y; - Z = pTarget->GetPosition().z; - dX = *(float*)&ScriptParams[2]; - dY = *(float*)&ScriptParams[3]; - if (b3D) { - dZ = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - else { - debug = ScriptParams[4]; - } - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } - else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D: - case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D: - result = true; - break; - case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D: - case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D: - result = !pPed->bInVehicle; - break; - case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D: - case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D: - result = pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocateCharObjectCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D: - case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D: - case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 6 : 5); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]); - script_assert(pTarget); - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); - X = pTarget->GetPosition().x; - Y = pTarget->GetPosition().y; - Z = pTarget->GetPosition().z; - dX = *(float*)&ScriptParams[2]; - dY = *(float*)&ScriptParams[3]; - if (b3D) { - dZ = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - else { - debug = ScriptParams[4]; - } - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } - else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D: - case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D: - result = true; - break; - case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D: - case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D: - result = !pPed->bInVehicle; - break; - case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D: - case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D: - result = pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocateCarCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug, decided = false; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_CAR_3D: - case COMMAND_LOCATE_STOPPED_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 8 : 6); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CVector pos = pVehicle->GetPosition(); - switch (command) { - case COMMAND_LOCATE_STOPPED_CAR_2D: - case COMMAND_LOCATE_STOPPED_CAR_3D: - if (!CTheScripts::IsVehicleStopped(pVehicle)) { - result = false; - decided = true; - } - break; - default: - break; - } - X = *(float*)&ScriptParams[1]; - Y = *(float*)&ScriptParams[2]; - if (b3D) { - Z = *(float*)&ScriptParams[3]; - dX = *(float*)&ScriptParams[4]; - dY = *(float*)&ScriptParams[5]; - dZ = *(float*)&ScriptParams[6]; - debug = ScriptParams[7]; - } - else { - dX = *(float*)&ScriptParams[3]; - dY = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - if (!decided) { - result = false; - bool in_area; - if (b3D) { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y && - Z - dZ <= pos.z && - Z + dZ >= pos.z; - } - else { - in_area = X - dX <= pos.x && - X + dX >= pos.x && - Y - dY <= pos.y && - Y + dY >= pos.y; - } - result = in_area; - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::LocateSniperBulletCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug; - float X, Y, Z, dX, dY, dZ; - switch (command) { - case COMMAND_LOCATE_SNIPER_BULLET_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 7 : 5); - X = *(float*)&ScriptParams[0]; - Y = *(float*)&ScriptParams[1]; - if (b3D) { - Z = *(float*)&ScriptParams[2]; - dX = *(float*)&ScriptParams[3]; - dY = *(float*)&ScriptParams[4]; - dZ = *(float*)&ScriptParams[5]; - debug = ScriptParams[6]; - } - else { - dX = *(float*)&ScriptParams[2]; - dY = *(float*)&ScriptParams[3]; - debug = ScriptParams[4]; - } - result = CBulletInfo::TestForSniperBullet(X - dX, X + dX, Y - dY, Y + dY, b3D ? Z - dZ : -1000.0f, b3D ? Z + dZ : 1000.0f); - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); - else - CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); - } -} - -void CRunningScript::PlayerInAreaCheckCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug, decided = false; - float infX, infY, infZ, supX, supY, supZ; - switch (command) { - case COMMAND_IS_PLAYER_IN_AREA_3D: - case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 8 : 6); - CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; - switch (command) { - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D: - if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) { - result = false; - decided = true; - } - break; - default: - break; - } - infX = *(float*)&ScriptParams[1]; - infY = *(float*)&ScriptParams[2]; - if (b3D) { - infZ = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[6]; - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[6]; - supZ = *(float*)&ScriptParams[3]; - } - debug = ScriptParams[7]; - } - else { - supX = *(float*)&ScriptParams[3]; - supY = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - if (infX > supX) { - float tmp = infX; - infX = supX; - supX = tmp; - } - if (infY > supY) { - float tmp = infY; - infY = supY; - supY = tmp; - } - if (!decided) { - CVector pos = pPlayerInfo->GetPos(); - result = false; - bool in_area; - if (b3D) { - in_area = infX <= pos.x && - supX >= pos.x && - infY <= pos.y && - supY >= pos.y && - infZ <= pos.z && - supZ >= pos.z; - } - else { - in_area = infX <= pos.x && - supX >= pos.x && - infY <= pos.y && - supY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_IS_PLAYER_IN_AREA_2D: - case COMMAND_IS_PLAYER_IN_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: - result = true; - break; - case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: - result = !pPlayerInfo->m_pPed->bInVehicle; - break; - case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: - result = pPlayerInfo->m_pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); - else - CTheScripts::DrawDebugSquare(infX, infY, supX, supY); - } -} - -void CRunningScript::PlayerInAngledAreaCheckCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug, decided = false; - float infX, infY, infZ, supX, supY, supZ, side2length; - switch (command) { - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 9 : 7); - CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; - switch (command) { - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D: - if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) { - result = false; - decided = true; - } - break; - default: - break; - } - infX = *(float*)&ScriptParams[1]; - infY = *(float*)&ScriptParams[2]; - if (b3D) { - infZ = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[6]; - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[6]; - supZ = *(float*)&ScriptParams[3]; - } - side2length = *(float*)&ScriptParams[7]; - debug = ScriptParams[8]; - } - else { - supX = *(float*)&ScriptParams[3]; - supY = *(float*)&ScriptParams[4]; - side2length = *(float*)&ScriptParams[5]; - debug = ScriptParams[6]; - } - float initAngle = CGeneral::GetRadianAngleBetweenPoints(infX, infY, supX, supY) + HALFPI; - while (initAngle < 0.0f) - initAngle += TWOPI; - while (initAngle > TWOPI) - initAngle -= TWOPI; - // it looks like the idea is to use a rectangle using the diagonal of the rectangle as - // the side of new rectangle, with "length" being the length of second side - float rotatedSupX = supX + side2length * sin(initAngle); - float rotatedSupY = supY - side2length * cos(initAngle); - float rotatedInfX = infX + side2length * sin(initAngle); - float rotatedInfY = infY - side2length * cos(initAngle); - float side1X = supX - infX; - float side1Y = supY - infY; - float side1Length = CVector2D(side1X, side1Y).Magnitude(); - float side2X = rotatedInfX - infX; - float side2Y = rotatedInfY - infY; - float side2Length = CVector2D(side2X, side2Y).Magnitude(); // == side2length? - if (!decided) { - CVector pos = pPlayerInfo->GetPos(); - result = false; - float X = pos.x - infX; - float Y = pos.y - infY; - float positionAlongSide1 = X * side1X / side1Length + Y * side1Y / side1Length; - bool in_area = false; - if (positionAlongSide1 >= 0.0f && positionAlongSide1 <= side1Length) { - float positionAlongSide2 = X * side2X / side2Length + Y * side2Y / side2Length; - if (positionAlongSide2 >= 0.0f && positionAlongSide2 <= side2Length) { - in_area = !b3D || pos.z >= infZ && pos.z <= supZ; - } - } - - if (in_area) { - switch (command) { - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: - result = true; - break; - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: - result = !pPlayerInfo->m_pPed->bInVehicle; - break; - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D: - case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: - result = pPlayerInfo->m_pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantAngledArea((uintptr)this + m_nIp, infX, infY, supX, supY, - rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugAngledCube(infX, infY, infZ, supX, supY, supZ, - rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY); - else - CTheScripts::DrawDebugAngledSquare(infX, infY, supX, supY, - rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY); - } -} - -void CRunningScript::CharInAreaCheckCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug, decided = false; - float infX, infY, infZ, supX, supY, supZ; - switch (command) { - case COMMAND_IS_CHAR_IN_AREA_3D: - case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 8 : 6); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - script_assert(pPed); - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); - switch (command) { - case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D: - if (!CTheScripts::IsPedStopped(pPed)) { - result = false; - decided = true; - } - break; - default: - break; - } - infX = *(float*)&ScriptParams[1]; - infY = *(float*)&ScriptParams[2]; - if (b3D) { - infZ = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[6]; - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[6]; - supZ = *(float*)&ScriptParams[3]; - } - debug = ScriptParams[7]; - } - else { - supX = *(float*)&ScriptParams[3]; - supY = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - if (infX > supX) { - float tmp = infX; - infX = supX; - supX = tmp; - } - if (infY > supY) { - float tmp = infY; - infY = supY; - supY = tmp; - } - if (!decided) { - result = false; - bool in_area; - if (b3D) { - in_area = infX <= pos.x && - supX >= pos.x && - infY <= pos.y && - supY >= pos.y && - infZ <= pos.z && - supZ >= pos.z; - } - else { - in_area = infX <= pos.x && - supX >= pos.x && - infY <= pos.y && - supY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_IS_CHAR_IN_AREA_2D: - case COMMAND_IS_CHAR_IN_AREA_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: - result = true; - break; - case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: - result = !pPed->bInVehicle; - break; - case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D: - case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D: - case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: - result = pPed->bInVehicle; - break; - default: - script_assert(false); - break; - } - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); - else - CTheScripts::DrawDebugSquare(infX, infY, supX, supY); - } -} - -void CRunningScript::CarInAreaCheckCommand(int32 command, uint32* pIp) -{ - bool b3D, result, debug, decided = false; - float infX, infY, infZ, supX, supY, supZ; - switch (command) { - case COMMAND_IS_CAR_IN_AREA_3D: - case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: - b3D = true; - break; - default: - b3D = false; - break; - } - CollectParameters(pIp, b3D ? 8 : 6); - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - script_assert(pVehicle); - CVector pos = pVehicle->GetPosition(); - switch (command) { - case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: - case COMMAND_IS_CAR_STOPPED_IN_AREA_2D: - if (!CTheScripts::IsVehicleStopped(pVehicle)) { - result = false; - decided = true; - } - break; - default: - break; - } - infX = *(float*)&ScriptParams[1]; - infY = *(float*)&ScriptParams[2]; - if (b3D) { - infZ = *(float*)&ScriptParams[3]; - supX = *(float*)&ScriptParams[4]; - supY = *(float*)&ScriptParams[5]; - supZ = *(float*)&ScriptParams[6]; - if (infZ > supZ) { - infZ = *(float*)&ScriptParams[6]; - supZ = *(float*)&ScriptParams[3]; - } - debug = ScriptParams[7]; - } - else { - supX = *(float*)&ScriptParams[3]; - supY = *(float*)&ScriptParams[4]; - debug = ScriptParams[5]; - } - if (infX > supX) { - float tmp = infX; - infX = supX; - supX = tmp; - } - if (infY > supY) { - float tmp = infY; - infY = supY; - supY = tmp; - } - if (!decided) { - result = false; - bool in_area; - if (b3D) { - in_area = infX <= pos.x && - supX >= pos.x && - infY <= pos.y && - supY >= pos.y && - infZ <= pos.z && - supZ >= pos.z; - } - else { - in_area = infX <= pos.x && - supX >= pos.x && - infY <= pos.y && - supY >= pos.y; - } - if (in_area) { - switch (command) { - case COMMAND_IS_CAR_IN_AREA_2D: - case COMMAND_IS_CAR_IN_AREA_3D: - case COMMAND_IS_CAR_STOPPED_IN_AREA_2D: - case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: - result = true; - break; - default: - script_assert(false); - break; - } - } - } - UpdateCompareFlag(result); - if (debug) - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); - if (CTheScripts::DbgFlag) { - if (b3D) - CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); - else - CTheScripts::DrawDebugSquare(infX, infY, supX, supY); - } -} - -void CRunningScript::DoDeatharrestCheck() -{ - if (!m_bDeatharrestEnabled) - return; - if (!CTheScripts::IsPlayerOnAMission()) - return; - CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus]; - if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest() && !CTheScripts::UpsideDownCars.AreAnyCarsUpsideDown()) - return; -#ifdef MISSION_REPLAY - if (AllowMissionReplay != 0) - return; - if (CanAllowMissionReplay()) - AllowMissionReplay = 1; -#endif - script_assert(m_nStackPointer > 0); - while (m_nStackPointer > 1) - --m_nStackPointer; - m_nIp = m_anStack[--m_nStackPointer]; - int16 messageId; - if (pPlayer->IsRestartingAfterDeath()) - messageId = 0; - else if (pPlayer->IsRestartingAfterArrest()) - messageId = 5; - else - messageId = 10; - messageId += CGeneral::GetRandomNumberInRange(0, 5); - bool found = false; - for (int16 contact = 0; !found && contact < MAX_NUM_CONTACTS; contact++) { - int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact]; - if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) { - messageId += CTheScripts::BaseBriefIdForContact[contact]; - found = true; - } - } - if (!found) - messageId = 8001; - char tmp[16]; - sprintf(tmp, "%d", messageId); - CMessages::ClearSmallMessagesOnly(); - wchar* text = TheText.Get(tmp); - // ...and do nothing about it - *(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0; - m_bDeatharrestExecuted = true; - m_nWakeTime = 0; -} - -int16 CRunningScript::GetPadState(uint16 pad, uint16 button) -{ - CPad* pPad = CPad::GetPad(pad); - switch (button) { - case 0: return pPad->NewState.LeftStickX; - case 1: return pPad->NewState.LeftStickY; - case 2: return pPad->NewState.RightStickX; - case 3: return pPad->NewState.RightStickY; - case 4: return pPad->NewState.LeftShoulder1; - case 5: return pPad->NewState.LeftShoulder2; - case 6: return pPad->NewState.RightShoulder1; - case 7: return pPad->NewState.RightShoulder2; - case 8: return pPad->NewState.DPadUp; - case 9: return pPad->NewState.DPadDown; - case 10: return pPad->NewState.DPadLeft; - case 11: return pPad->NewState.DPadRight; - case 12: return pPad->NewState.Start; - case 13: return pPad->NewState.Select; - case 14: return pPad->NewState.Square; - case 15: return pPad->NewState.Triangle; - case 16: return pPad->NewState.Cross; - case 17: return pPad->NewState.Circle; - case 18: return pPad->NewState.LeftShock; - case 19: return pPad->NewState.RightShock; - default: break; - } - return 0; -} - -void CTheScripts::PrintListSizes() -{ - int active = 0; - int idle = 0; - - for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) - active++; - for (CRunningScript* pScript = pIdleScripts; pScript; pScript = pScript->GetNext()) - idle++; - - debug("active: %d, idle: %d", active, idle); -} - -uint32 DbgLineColour = 0x0000FFFF; // r = 0, g = 0, b = 255, a = 255 - -void CTheScripts::DrawDebugSquare(float infX, float infY, float supX, float supY) -{ - CColPoint tmpCP; - CEntity* tmpEP; - CVector p1, p2, p3, p4; - p1 = CVector(infX, infY, -1000.0f); - CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p1.z = 2.0f + tmpCP.point.z; - p2 = CVector(supX, supY, -1000.0f); - CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p2.z = 2.0f + tmpCP.point.z; - p3 = CVector(infX, supY, -1000.0f); - CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p3.z = 2.0f + tmpCP.point.z; - p4 = CVector(supX, infY, -1000.0f); - CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p4.z = 2.0f + tmpCP.point.z; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour); -} - -void CTheScripts::DrawDebugAngledSquare(float infX, float infY, float supX, float supY, float rotSupX, float rotSupY, float rotInfX, float rotInfY) -{ - CColPoint tmpCP; - CEntity* tmpEP; - CVector p1, p2, p3, p4; - p1 = CVector(infX, infY, -1000.0f); - CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p1.z = 2.0f + tmpCP.point.z; - p2 = CVector(supX, supY, -1000.0f); - CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p2.z = 2.0f + tmpCP.point.z; - p3 = CVector(rotSupX, rotSupY, -1000.0f); - CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p3.z = 2.0f + tmpCP.point.z; - p4 = CVector(rotInfX, rotInfY, -1000.0f); - CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); - p4.z = 2.0f + tmpCP.point.z; - CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour); -} - -void CTheScripts::DrawDebugCube(float infX, float infY, float infZ, float supX, float supY, float supZ) -{ - CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, infY, infZ, supX, supY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, supY, infZ, infX, supY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(infX, supY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, supY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, supY, supZ, infX, supY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, supY, supZ, supX, supY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, supY, infZ, DbgLineColour, DbgLineColour); -} - -void CTheScripts::DrawDebugAngledCube(float infX, float infY, float infZ, float supX, float supY, float supZ, float rotSupX, float rotSupY, float rotInfX, float rotInfY) -{ - CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, infY, infZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, infZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, infY, supZ, rotSupX, rotSupY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, rotInfX, rotInfY, supY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, supZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour); - CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour); -} - -void CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, uint32 col, uint32 col2) -{ - if (NumScriptDebugLines >= MAX_NUM_STORED_LINES) - return; - aStoredLines[NumScriptDebugLines].vecInf = CVector(x1, y1, z1); - aStoredLines[NumScriptDebugLines].vecSup = CVector(x2, y2, z2); - aStoredLines[NumScriptDebugLines].color1 = col; - aStoredLines[NumScriptDebugLines++].color2 = col2; -} - -void CTheScripts::RenderTheScriptDebugLines() -{ - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1); - for (int i = 0; i < NumScriptDebugLines; i++) { - CLines::RenderLineWithClipping( - aStoredLines[i].vecInf.x, - aStoredLines[i].vecInf.y, - aStoredLines[i].vecInf.z, - aStoredLines[i].vecSup.x, - aStoredLines[i].vecSup.y, - aStoredLines[i].vecSup.z, - aStoredLines[i].color1, - aStoredLines[i].color2); - } - NumScriptDebugLines = 0; - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0); -} - -#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) + sizeof(CTheScripts::BaseBriefIdForContact) + sizeof(CTheScripts::OnAMissionForContactFlag) +\ - sizeof(CTheScripts::CollectiveArray) + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32) - -void CTheScripts::SaveAllScripts(uint8* buf, uint32* size) -{ -INITSAVEBUF - uint32 varSpace = GetSizeOfVariableSpace(); - uint32 runningScripts = 0; - for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) - runningScripts++; - *size = CRunningScript::nSaveStructSize * runningScripts + varSpace + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32); - WriteSaveHeader(buf, 'S', 'C', 'R', '\0', *size - SAVE_HEADER_SIZE); - WriteSaveBuf(buf, varSpace); - for (uint32 i = 0; i < varSpace; i++) - WriteSaveBuf(buf, ScriptSpace[i]); -#ifdef CHECK_STRUCT_SIZES - static_assert(SCRIPT_DATA_SIZE == 968, "CTheScripts::SaveAllScripts"); -#endif - uint32 script_data_size = SCRIPT_DATA_SIZE; - WriteSaveBuf(buf, script_data_size); - WriteSaveBuf(buf, OnAMissionFlag); - for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { - WriteSaveBuf(buf, OnAMissionForContactFlag[i]); - WriteSaveBuf(buf, BaseBriefIdForContact[i]); - } - for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) - WriteSaveBuf(buf, CollectiveArray[i]); - WriteSaveBuf(buf, NextFreeCollectiveIndex); - for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { - CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding; - uint32 type, handle; - if (!pBuilding) { - type = 0; - handle = 0; - } else if (pBuilding->GetIsATreadable()) { - type = 1; - handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding) + 1; - } else { - type = 2; - handle = CPools::GetBuildingPool()->GetJustIndex(pBuilding) + 1; - } - WriteSaveBuf(buf, type); - WriteSaveBuf(buf, handle); - WriteSaveBuf(buf, BuildingSwapArray[i].m_nNewModel); - WriteSaveBuf(buf, BuildingSwapArray[i].m_nOldModel); - } - for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { - CEntity* pEntity = InvisibilitySettingArray[i]; - uint32 type, handle; - if (!pEntity) { - type = 0; - handle = 0; - } else { - switch (pEntity->GetType()) { - case ENTITY_TYPE_BUILDING: - if (((CBuilding*)pEntity)->GetIsATreadable()) { - type = 1; - handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pEntity) + 1; - } else { - type = 2; - handle = CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pEntity) + 1; - } - break; - case ENTITY_TYPE_OBJECT: - type = 3; - handle = CPools::GetObjectPool()->GetJustIndex((CObject*)pEntity) + 1; - break; - case ENTITY_TYPE_DUMMY: - type = 4; - handle = CPools::GetDummyPool()->GetJustIndex((CDummy*)pEntity) + 1; - default: break; - } - } - WriteSaveBuf(buf, type); - WriteSaveBuf(buf, handle); - } - WriteSaveBuf(buf, bUsingAMultiScriptFile); - WriteSaveBuf(buf, (uint8)0); - WriteSaveBuf(buf, (uint16)0); - WriteSaveBuf(buf, MainScriptSize); - WriteSaveBuf(buf, LargestMissionScriptSize); - WriteSaveBuf(buf, NumberOfMissionScripts); - WriteSaveBuf(buf, (uint16)0); - WriteSaveBuf(buf, runningScripts); - for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) - pScript->Save(buf); -VALIDATESAVEBUF(*size) -} - -void CTheScripts::LoadAllScripts(uint8* buf, uint32 size) -{ - Init(); -INITSAVEBUF - CheckSaveHeader(buf, 'S', 'C', 'R', '\0', size - SAVE_HEADER_SIZE); - uint32 varSpace = ReadSaveBuf(buf); - for (uint32 i = 0; i < varSpace; i++) - ScriptSpace[i] = ReadSaveBuf(buf); - script_assert(ReadSaveBuf(buf) == SCRIPT_DATA_SIZE); - OnAMissionFlag = ReadSaveBuf(buf); - for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { - OnAMissionForContactFlag[i] = ReadSaveBuf(buf); - BaseBriefIdForContact[i] = ReadSaveBuf(buf); - } - for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) - CollectiveArray[i] = ReadSaveBuf(buf); - NextFreeCollectiveIndex = ReadSaveBuf(buf); - for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { - uint32 type = ReadSaveBuf(buf); - uint32 handle = ReadSaveBuf(buf); - switch (type) { - case 0: - BuildingSwapArray[i].m_pBuilding = nil; - break; - case 1: - BuildingSwapArray[i].m_pBuilding = CPools::GetTreadablePool()->GetSlot(handle - 1); - break; - case 2: - BuildingSwapArray[i].m_pBuilding = CPools::GetBuildingPool()->GetSlot(handle - 1); - break; - default: - script_assert(false); - } - BuildingSwapArray[i].m_nNewModel = ReadSaveBuf(buf); - BuildingSwapArray[i].m_nOldModel = ReadSaveBuf(buf); - if (BuildingSwapArray[i].m_pBuilding) - BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nNewModel); - } - for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { - uint32 type = ReadSaveBuf(buf); - uint32 handle = ReadSaveBuf(buf); - switch (type) { - case 0: - InvisibilitySettingArray[i] = nil; - break; - case 1: - InvisibilitySettingArray[i] = CPools::GetTreadablePool()->GetSlot(handle - 1); - break; - case 2: - InvisibilitySettingArray[i] = CPools::GetBuildingPool()->GetSlot(handle - 1); - break; - case 3: - InvisibilitySettingArray[i] = CPools::GetObjectPool()->GetSlot(handle - 1); - break; - case 4: - InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1); - break; - default: - script_assert(false); - } - if (InvisibilitySettingArray[i]) - InvisibilitySettingArray[i]->bIsVisible = false; - } - script_assert(ReadSaveBuf(buf) == bUsingAMultiScriptFile); - ReadSaveBuf(buf); - ReadSaveBuf(buf); - script_assert(ReadSaveBuf(buf) == MainScriptSize); - script_assert(ReadSaveBuf(buf) == LargestMissionScriptSize); - script_assert(ReadSaveBuf(buf) == NumberOfMissionScripts); - ReadSaveBuf(buf); - uint32 runningScripts = ReadSaveBuf(buf); - for (uint32 i = 0; i < runningScripts; i++) - StartNewScript(0)->Load(buf); -VALIDATESAVEBUF(size) -} - -#undef SCRIPT_DATA_SIZE - -void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity) -{ - static CColPoint aTempColPoints[MAX_COLLISION_POINTS]; - int16 entities = 0; - CEntity* aEntities[16]; - CWorld::FindObjectsKindaColliding(pos, pEntity->GetBoundRadius(), false, &entities, 16, aEntities, false, true, true, false, false); - if (entities <= 0) - return; - for (uint16 i = 0; i < entities; i++) { - if (aEntities[i] != pEntity && aEntities[i]->IsPed() && ((CPed*)aEntities[i])->bInVehicle) - aEntities[i] = nil; - } - for (uint16 i = 0; i < entities; i++) { - if (aEntities[i] == pEntity || !aEntities[i]) - continue; - CEntity* pFound = aEntities[i]; - int cols; - if (pEntity->GetColModel()->numLines <= 0) - cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(), - pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil); - else { - float lines[4]; - lines[0] = lines[1] = lines[2] = lines[3] = 1.0f; - CColPoint tmp[4]; - cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(), - pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines); - } - if (cols <= 0) - continue; - switch (pFound->GetType()) { - case ENTITY_TYPE_VEHICLE: - { - printf("Will try to delete a vehicle where a mission entity should be\n"); - CVehicle* pVehicle = (CVehicle*)pFound; - if (pVehicle->bIsLocked || !pVehicle->CanBeDeleted()) - break; - if (pVehicle->pDriver) { - CPopulation::RemovePed(pVehicle->pDriver); - pVehicle->pDriver = nil; - } - for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) { - if (pVehicle->pPassengers[i]) { - CPopulation::RemovePed(pVehicle->pPassengers[i]); - pVehicle->pPassengers[i] = 0; - pVehicle->m_nNumPassengers--; - } - } - CCarCtrl::RemoveFromInterestingVehicleList(pVehicle); - CWorld::Remove(pVehicle); - delete pVehicle; - break; - } - case ENTITY_TYPE_PED: - { - CPed* pPed = (CPed*)pFound; - if (pPed->IsPlayer() || !pPed->CanBeDeleted()) - break; - CPopulation::RemovePed(pPed); - printf("Deleted a ped where a mission entity should be\n"); - break; - } - default: break; - } - } -} - -void CTheScripts::HighlightImportantArea(uint32 id, float x1, float y1, float x2, float y2, float z) -{ - float infX, infY, supX, supY; - if (x1 < x2) { - infX = x1; - supX = x2; - } else { - infX = x2; - supX = x1; - } - if (y1 < y2) { - infY = y1; - supY = y2; - } - else { - infY = y2; - supY = y1; - } - CVector center; - center.x = (infX + supX) / 2; - center.y = (infY + supY) / 2; - center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z; - CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, ¢er, supX - center.x, 0.0f, 0.0f, center.y - supY, 0); -} - -void CTheScripts::HighlightImportantAngledArea(uint32 id, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float z) -{ - float infX, infY, supX, supY, X, Y; - X = (x1 + x2) / 2; - Y = (y1 + y2) / 2; - supX = infX = X; - supY = infY = Y; - X = (x2 + x3) / 2; - Y = (y2 + y3) / 2; - infX = Min(infX, X); - supX = Max(supX, X); - infY = Min(infY, Y); - supY = Max(supY, Y); - X = (x3 + x4) / 2; - Y = (y3 + y4) / 2; - infX = Min(infX, X); - supX = Max(supX, X); - infY = Min(infY, Y); - supY = Max(supY, Y); - X = (x4 + x1) / 2; - Y = (y4 + y1) / 2; - infX = Min(infX, X); - supX = Max(supX, X); - infY = Min(infY, Y); - supY = Max(supY, Y); - CVector center; - center.x = (infX + supX) / 2; - center.y = (infY + supY) / 2; - center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z; - CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, ¢er, supX - center.x, 0.0f, 0.0f, center.y - supY, 0); -} - -bool CTheScripts::IsPedStopped(CPed* pPed) -{ - if (pPed->bInVehicle) - return IsVehicleStopped(pPed->m_pMyVehicle); - return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL; -} - -bool CTheScripts::IsPlayerStopped(CPlayerInfo* pPlayer) -{ - CPed* pPed = pPlayer->m_pPed; - if (pPed->bInVehicle) - return IsVehicleStopped(pPed->m_pMyVehicle); - if (RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP) || - RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP_R) || - RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_LAUNCH) || - RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_GLIDE)) - return false; - return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL; -} - -bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle) -{ - return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled; -} - -void CTheScripts::CleanUpThisPed(CPed* pPed) -{ - if (!pPed) - return; - if (pPed->CharCreatedBy != MISSION_CHAR) - return; - pPed->CharCreatedBy = RANDOM_CHAR; - if (pPed->m_nPedType == PEDTYPE_PROSTITUTE) - pPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000; - if (pPed->bInVehicle) { - if (pPed->m_pMyVehicle->pDriver == pPed) { - if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) { - CCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle); - pPed->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; - } - } - else { - if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) { - pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle); - pPed->bWanderPathAfterExitingCar = true; - } - } - } - bool flees = false; - PedState state; - eMoveState ms; - if (pPed->m_nPedState == PED_FLEE_ENTITY || pPed->m_nPedState == PED_FLEE_POS) { - ms = pPed->m_nMoveState; - state = pPed->m_nPedState; - flees = true; - } - pPed->ClearObjective(); - pPed->bRespondsToThreats = true; - pPed->bScriptObjectiveCompleted = false; - pPed->ClearLeader(); - if (pPed->IsPedInControl()) - pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7); - if (flees) { - pPed->m_nPedState = state; - pPed->SetMoveState(ms); - } - --CPopulation::ms_nTotalMissionPeds; -} - -void CTheScripts::CleanUpThisVehicle(CVehicle* pVehicle) -{ - if (!pVehicle) - return; - if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) - return; - pVehicle->bIsLocked = false; - CCarCtrl::RemoveFromInterestingVehicleList(pVehicle); - pVehicle->VehicleCreatedBy = RANDOM_VEHICLE; - ++CCarCtrl::NumRandomCars; - --CCarCtrl::NumMissionCars; -} - -void CTheScripts::CleanUpThisObject(CObject* pObject) -{ - if (!pObject) - return; - if (pObject->ObjectCreatedBy != MISSION_OBJECT) - return; - pObject->ObjectCreatedBy = TEMP_OBJECT; - pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000; - pObject->m_nRefModelIndex = -1; - pObject->bUseVehicleColours = false; - ++CObject::nNoTempObjects; -} - -void CTheScripts::ReadObjectNamesFromScript() -{ - int32 varSpace = GetSizeOfVariableSpace(); - uint32 ip = varSpace + 8; - NumberOfUsedObjects = Read2BytesFromScript(&ip); - ip += 2; - for (uint16 i = 0; i < NumberOfUsedObjects; i++) { - for (int j = 0; j < USED_OBJECT_NAME_LENGTH; j++) - UsedObjectArray[i].name[j] = ScriptSpace[ip++]; - UsedObjectArray[i].index = 0; - } -} - -void CTheScripts::UpdateObjectIndices() -{ - char name[USED_OBJECT_NAME_LENGTH]; - char error[112]; - for (int i = 1; i < NumberOfUsedObjects; i++) { - bool found = false; - for (int j = 0; j < MODELINFOSIZE && !found; j++) { - CBaseModelInfo* pModel = CModelInfo::GetModelInfo(j); - if (!pModel) - continue; - strcpy(name, pModel->GetName()); -#ifdef FIX_BUGS - for (int k = 0; k < USED_OBJECT_NAME_LENGTH && name[k]; k++) -#else - for (int k = 0; k < USED_OBJECT_NAME_LENGTH; k++) -#endif - name[k] = toupper(name[k]); - if (strcmp(name, UsedObjectArray[i].name) == 0) { - found = true; - UsedObjectArray[i].index = j; - } - } - if (!found) { - sprintf(error, "CTheScripts::UpdateObjectIndices - Couldn't find %s", UsedObjectArray[i].name); - debug("%s\n", error); - } - } -} - -void CTheScripts::ReadMultiScriptFileOffsetsFromScript() -{ - int32 varSpace = GetSizeOfVariableSpace(); - uint32 ip = varSpace + 3; - int32 objectSize = Read4BytesFromScript(&ip); - ip = objectSize + 8; - MainScriptSize = Read4BytesFromScript(&ip); - LargestMissionScriptSize = Read4BytesFromScript(&ip); - NumberOfMissionScripts = Read2BytesFromScript(&ip); - ip += 2; - for (int i = 0; i < NumberOfMissionScripts; i++) { - MultiScriptArray[i] = Read4BytesFromScript(&ip); - } -} void CRunningScript::Save(uint8*& buf) { diff --git a/src/control/Script.h b/src/control/Script.h index c9e92129..12f3233f 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -13,6 +13,29 @@ class CPlayerInfo; class CRunningScript; +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 SPHERE_MARKER_R 0 +#define SPHERE_MARKER_G 128 +#define SPHERE_MARKER_B 255 +#define SPHERE_MARKER_A 128 +#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 +#else +#define METERS_IN_FOOT 0.3f +#define FEET_IN_METER 3.33f +#endif + #define KEY_LENGTH_IN_SCRIPT 8 struct intro_script_rectangle diff --git a/src/control/Script2.cpp b/src/control/Script2.cpp new file mode 100644 index 00000000..62b9af93 --- /dev/null +++ b/src/control/Script2.cpp @@ -0,0 +1,1549 @@ +#include "common.h" + +#include "Script.h" +#include "ScriptCommands.h" + +#include "Camera.h" +#include "CarCtrl.h" +#include "CarGen.h" +#include "CivilianPed.h" +#include "CopPed.h" +#include "Cranes.h" +#include "DMAudio.h" +#include "EmergencyPed.h" +#include "Garages.h" +#include "General.h" +#include "Messages.h" +#include "Pad.h" +#include "PedRoutes.h" +#include "Pools.h" +#include "Population.h" +#include "Radar.h" +#include "Restart.h" +#include "Shadows.h" +#include "User.h" +#include "Wanted.h" +#include "WaterLevel.h" +#include "Weather.h" +#include "World.h" +#include "Zones.h" + +int8 CRunningScript::ProcessCommands300To399(int32 command) +{ + switch (command) { + /* Not implemented. + case COMMAND_SET_CHAR_INVINCIBLE: + case COMMAND_SET_PLAYER_INVINCIBLE: + case COMMAND_SET_CHAR_GRAPHIC_TYPE: + case COMMAND_SET_PLAYER_GRAPHIC_TYPE: + */ + case COMMAND_HAS_PLAYER_BEEN_ARRESTED: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_BUSTED); + return 0; + /* Not implemented. + case COMMAND_STOP_CHAR_DRIVING: + case COMMAND_KILL_CHAR: + case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR: + case COMMAND_SET_CHAR_OCCUPATION: + */ + case COMMAND_CHANGE_CAR_LOCK: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1]; + return 0; + } + case COMMAND_SHAKE_CAM_WITH_POINT: + CollectParameters(&m_nIp, 4); + TheCamera.CamShake(ScriptParams[0] / 1000.0f, + *(float*)&ScriptParams[1], + *(float*)&ScriptParams[2], + *(float*)&ScriptParams[3]); + return 0; + case COMMAND_IS_CAR_MODEL: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]); + return 0; + } + /* Not implemented. + case COMMAND_IS_CAR_REMAP: + case COMMAND_HAS_CAR_JUST_SUNK: + case COMMAND_SET_CAR_NO_COLLIDE: + */ + case COMMAND_IS_CAR_DEAD_IN_AREA_2D: + { + CollectParameters(&m_nIp, 6); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + float x1 = *(float*)&ScriptParams[1]; + float y1 = *(float*)&ScriptParams[2]; + float x2 = *(float*)&ScriptParams[3]; + float y2 = *(float*)&ScriptParams[4]; + UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && + pVehicle->IsWithinArea(x1, y1, x2, y2)); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) + CTheScripts::DrawDebugSquare(x1, y1, x2, y2); + return 0; + } + case COMMAND_IS_CAR_DEAD_IN_AREA_3D: + { + CollectParameters(&m_nIp, 8); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + float x1 = *(float*)&ScriptParams[1]; + float y1 = *(float*)&ScriptParams[2]; + float z1 = *(float*)&ScriptParams[3]; + float x2 = *(float*)&ScriptParams[4]; + float y2 = *(float*)&ScriptParams[5]; + float z2 = *(float*)&ScriptParams[6]; + UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && + pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (CTheScripts::DbgFlag) + CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); + return 0; + } + /* Not implemented. + case COMMAND_IS_TRAILER_ATTACHED: + case COMMAND_IS_CAR_ON_TRAILER: + case COMMAND_HAS_CAR_GOT_WEAPON: + case COMMAND_PARK: + case COMMAND_HAS_PARK_FINISHED: + case COMMAND_KILL_ALL_PASSENGERS: + case COMMAND_SET_CAR_BULLETPROOF: + case COMMAND_SET_CAR_FLAMEPROOF: + case COMMAND_SET_CAR_ROCKETPROOF: + case COMMAND_IS_CARBOMB_ACTIVE: + case COMMAND_GIVE_CAR_ALARM: + case COMMAND_PUT_CAR_ON_TRAILER: + */ + case COMMAND_IS_CAR_CRUSHED: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0])); + return 0; + /* Not implemented. + case COMMAND_CREATE_GANG_CAR: + */ + case COMMAND_CREATE_CAR_GENERATOR: + CollectParameters(&m_nIp, 12); + ScriptParams[0] = CTheCarGenerators::CreateCarGenerator( + *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], + ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], + ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_SWITCH_CAR_GENERATOR: + { + CollectParameters(&m_nIp, 2); + CCarGenerator* pCarGen = &CTheCarGenerators::CarGeneratorArray[ScriptParams[0]]; + if (ScriptParams[1] == 0){ + pCarGen->SwitchOff(); + }else if (ScriptParams[1] <= 100){ + pCarGen->SwitchOn(); + pCarGen->SetUsesRemaining(ScriptParams[1]); + }else{ + pCarGen->SwitchOn(); + } + return 0; + } + case COMMAND_ADD_PAGER_MESSAGE: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 3); + CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]); + return 0; + } + case COMMAND_DISPLAY_ONSCREEN_TIMER: + { + script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + CUserDisplay::OnscnTimer.AddClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp), nil); + return 0; + } + case COMMAND_CLEAR_ONSCREEN_TIMER: + { + script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + CUserDisplay::OnscnTimer.ClearClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp)); + return 0; + } + case COMMAND_DISPLAY_ONSCREEN_COUNTER: + { + script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + uint16 counter = CTheScripts::Read2BytesFromScript(&m_nIp); + CollectParameters(&m_nIp, 1); + CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil); + return 0; + } + case COMMAND_CLEAR_ONSCREEN_COUNTER: + { + script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + CUserDisplay::OnscnTimer.ClearCounter((uint16)CTheScripts::Read2BytesFromScript(&m_nIp)); + return 0; + } + case COMMAND_SET_ZONE_CAR_INFO: + { + char label[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, label); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CollectParameters(&m_nIp, 16); + int zone = CTheZones::FindZoneByLabelAndReturnIndex(label); + if (zone < 0) { + debug("Couldn't find zone - %s\n", label); + return 0; + } + CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], + ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0, + ScriptParams[9], ScriptParams[10], ScriptParams[11], ScriptParams[12], + ScriptParams[13], ScriptParams[14], ScriptParams[15]); + return 0; + } + /* Not implemented. + case COMMAND_IS_CHAR_IN_GANG_ZONE: + */ + case COMMAND_IS_CHAR_IN_ZONE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + char label[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, label); + int zone = CTheZones::FindZoneByLabelAndReturnIndex(label); + if (zone != -1) + m_nIp += KEY_LENGTH_IN_SCRIPT; + CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetZone(zone))); + return 0; + } + case COMMAND_SET_CAR_DENSITY: + { + char label[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, label); + int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label); + m_nIp += 8; + CollectParameters(&m_nIp, 2); + if (zone < 0) { + debug("Couldn't find zone - %s\n", label); + return 0; + } + CTheZones::SetCarDensity(zone, ScriptParams[0], ScriptParams[1]); + return 0; + } + case COMMAND_SET_PED_DENSITY: + { + char label[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, label); + int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CollectParameters(&m_nIp, 2); + if (zone < 0) { + debug("Couldn't find zone - %s\n", label); + return 0; + } + CTheZones::SetPedDensity(zone, ScriptParams[0], ScriptParams[1]); + return 0; + } + case COMMAND_POINT_CAMERA_AT_PLAYER: + { + CollectParameters(&m_nIp, 3); + // ScriptParams[0] is unused. + TheCamera.TakeControl(nil, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); + return 0; + } + case COMMAND_POINT_CAMERA_AT_CAR: + { + CollectParameters(&m_nIp, 3); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); + return 0; + } + case COMMAND_POINT_CAMERA_AT_CHAR: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); + return 0; + } + case COMMAND_RESTORE_CAMERA: + TheCamera.Restore(); + return 0; + case COMMAND_SHAKE_PAD: + CPad::GetPad(ScriptParams[0])->StartShake(ScriptParams[1], ScriptParams[2]); + return 0; + case COMMAND_SET_ZONE_PED_INFO: + { + char label[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, label); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CollectParameters(&m_nIp, 10); + int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label); + if (zone < 0) { + debug("Couldn't find zone - %s\n", label); + return 0; + } + CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], + ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0, ScriptParams[9]); + return 0; + } + case COMMAND_SET_TIME_SCALE: + CollectParameters(&m_nIp, 1); + CTimer::SetTimeScale(*(float*)&ScriptParams[0]); + return 0; + case COMMAND_IS_CAR_IN_AIR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle && pVehicle->IsCar()); + CAutomobile* pCar = (CAutomobile*)pVehicle; + UpdateCompareFlag(pCar->GetAllWheelsOffGround()); + return 0; + } + case COMMAND_SET_FIXED_CAMERA_POSITION: + { + CollectParameters(&m_nIp, 6); + TheCamera.SetCamPositionForFixedMode( + CVector(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]), + CVector(*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5])); + return 0; + } + case COMMAND_POINT_CAMERA_AT_POINT: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + TheCamera.TakeControlNoEntity(pos, ScriptParams[3], CAMCONTROL_SCRIPT); + return 0; + } + case COMMAND_ADD_BLIP_FOR_CAR_OLD: + { + CollectParameters(&m_nIp, 3); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + // Useless call. + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_BLIP_FOR_CHAR_OLD: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + // Useless call. + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_BLIP_FOR_OBJECT_OLD: + { + CollectParameters(&m_nIp, 3); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + // Useless call. + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_REMOVE_BLIP: + CollectParameters(&m_nIp, 1); + CRadar::ClearBlip(ScriptParams[0]); + return 0; + case COMMAND_CHANGE_BLIP_COLOUR: + CollectParameters(&m_nIp, 2); + CRadar::ChangeBlipColour(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_DIM_BLIP: + CollectParameters(&m_nIp, 2); + CRadar::ChangeBlipBrightness(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_ADD_BLIP_FOR_COORD_OLD: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + // Useless call + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CRadar::SetCoordBlip(BLIP_COORD, pos, ScriptParams[3], (eBlipDisplay)ScriptParams[4]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_CHANGE_BLIP_SCALE: + CollectParameters(&m_nIp, 2); + CRadar::ChangeBlipScale(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_SET_FADING_COLOUR: + CollectParameters(&m_nIp, 3); + TheCamera.SetFadeColour(ScriptParams[0], ScriptParams[1], ScriptParams[2]); + return 0; + case COMMAND_DO_FADE: + CollectParameters(&m_nIp, 2); + TheCamera.Fade(ScriptParams[0] / 1000.0f, ScriptParams[1]); + return 0; + case COMMAND_GET_FADING_STATUS: + UpdateCompareFlag(TheCamera.GetFading()); + return 0; + case COMMAND_ADD_HOSPITAL_RESTART: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + float angle = *(float*)&ScriptParams[3]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRestart::AddHospitalRestartPoint(pos, angle); + return 0; + } + case COMMAND_ADD_POLICE_RESTART: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + float angle = *(float*)&ScriptParams[3]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRestart::AddPoliceRestartPoint(pos, angle); + return 0; + } + case COMMAND_OVERRIDE_NEXT_RESTART: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + float angle = *(float*)&ScriptParams[3]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRestart::OverrideNextRestart(pos, angle); + return 0; + } + case COMMAND_DRAW_SHADOW: + { + CollectParameters(&m_nIp, 10); + CVector pos = *(CVector*)&ScriptParams[1]; + float angle = *(float*)&ScriptParams[4]; + float length = *(float*)&ScriptParams[5]; + float x, y; + if (angle != 0.0f){ + y = cos(angle) * length; + x = sin(angle) * length; + }else{ + y = length; + x = 0.0f; + } + float frontX = -x; + float frontY = y; + float sideX = y; + float sideY = x; + /* Not very nicely named intermediate variables. */ + CShadows::StoreShadowToBeRendered(ScriptParams[0], &pos, frontX, frontY, sideX, sideY, + ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9]); + return 0; + } + case COMMAND_GET_PLAYER_HEADING: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading(); + *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_PLAYER_HEADING: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + if (pPed->bInVehicle){ + // Is script_assertion required? + return 0; + } + pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]); + pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); + return 0; + } + case COMMAND_GET_CHAR_HEADING: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading(); + *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CHAR_HEADING: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + if (pPed->bInVehicle) { + // Is script_assertion required? + return 0; + } + pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]); + pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); + return 0; + } + case COMMAND_GET_CAR_HEADING: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + float angle = pVehicle->GetForward().Heading(); + *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CAR_HEADING: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); + return 0; + } + case COMMAND_GET_OBJECT_HEADING: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + float angle = pObject->GetForward().Heading(); + *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle)); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_OBJECT_HEADING: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CWorld::Remove(pObject); + pObject->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); + pObject->GetMatrix().UpdateRW(); + pObject->UpdateRwFrame(); + CWorld::Add(pObject); + return 0; + } + case COMMAND_IS_PLAYER_TOUCHING_OBJECT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); + script_assert(pObject); + CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed; + UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject)); + return 0; + } + case COMMAND_IS_CHAR_TOUCHING_OBJECT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); + script_assert(pObject); + CPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed; + UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject)); + return 0; + } + case COMMAND_SET_PLAYER_AMMO: + { + CollectParameters(&m_nIp, 3); + CWorld::Players[0].m_pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); + return 0; + } + case COMMAND_SET_CHAR_AMMO: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); + return 0; + } + /* Not implemented. + case COMMAND_SET_CAR_AMMO: + case COMMAND_LOAD_CAMERA_SPLINE: + case COMMAND_MOVE_CAMERA_ALONG_SPLINE: + case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE: + */ + case COMMAND_DECLARE_MISSION_FLAG: + CTheScripts::OnAMissionFlag = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp); + return 0; + case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: + CollectParameters(&m_nIp, 1); + CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp); + return 0; + case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT: + CollectParameters(&m_nIp, 2); + CTheScripts::BaseBriefIdForContact[ScriptParams[0]] = ScriptParams[1]; + return 0; + case COMMAND_IS_PLAYER_HEALTH_GREATER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]); + return 0; + } + case COMMAND_IS_CHAR_HEALTH_GREATER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]); + return 0; + } + case COMMAND_IS_CAR_HEALTH_GREATER: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->m_fHealth > ScriptParams[1]); + return 0; + } + case COMMAND_ADD_BLIP_FOR_CAR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + // Useless call. + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int handle = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH); + CRadar::ChangeBlipScale(handle, 3); + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_BLIP_FOR_CHAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + // Useless call. + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int handle = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH); + CRadar::ChangeBlipScale(handle, 3); + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_BLIP_FOR_OBJECT: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + // Useless call. + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int handle = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH); + CRadar::ChangeBlipScale(handle, 3); + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_BLIP_FOR_CONTACT_POINT: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + // Useless call + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int handle = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH); + CRadar::ChangeBlipScale(handle, 3); + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_BLIP_FOR_COORD: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + // Useless call + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH); + CRadar::ChangeBlipScale(handle, 3); + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_CHANGE_BLIP_DISPLAY: + CollectParameters(&m_nIp, 2); + CRadar::ChangeBlipDisplay(ScriptParams[0], (eBlipDisplay)ScriptParams[1]); + return 0; + case COMMAND_ADD_ONE_OFF_SOUND: + { + CollectParameters(&m_nIp, 4); + switch (ScriptParams[3]) { + case SCRIPT_SOUND_EVIDENCE_PICKUP: + DMAudio.PlayFrontEndSound(SOUND_EVIDENCE_PICKUP, 0); + return 0; + case SCRIPT_SOUND_UNLOAD_GOLD: + DMAudio.PlayFrontEndSound(SOUND_UNLOAD_GOLD, 0); + return 0; + case SCRIPT_SOUND_PART_MISSION_COMPLETE: + DMAudio.PlayFrontEndSound(SOUND_PART_MISSION_COMPLETE, 0); + return 0; + case SCRIPT_SOUND_RACE_START_3: + DMAudio.PlayFrontEndSound(SOUND_RACE_START_3, 0); + return 0; + case SCRIPT_SOUND_RACE_START_2: + DMAudio.PlayFrontEndSound(SOUND_RACE_START_2, 0); + return 0; + case SCRIPT_SOUND_RACE_START_1: + DMAudio.PlayFrontEndSound(SOUND_RACE_START_1, 0); + return 0; + case SCRIPT_SOUND_RACE_START_GO: + DMAudio.PlayFrontEndSound(SOUND_RACE_START_GO, 0); + return 0; + default: + break; + } +#ifdef FIX_BUGS + /* BUG: if audio is not initialized, this object will not be freed. */ + if (!DMAudio.IsAudioInitialised()) + return 0; +#endif + cAudioScriptObject* obj = new cAudioScriptObject(); + obj->Posn = *(CVector*)&ScriptParams[0]; + obj->AudioId = ScriptParams[3]; + obj->AudioEntity = AEHANDLE_NONE; + DMAudio.CreateOneShotScriptObject(obj); + return 0; + } + case COMMAND_ADD_CONTINUOUS_SOUND: + { + CollectParameters(&m_nIp, 4); + cAudioScriptObject* obj = new cAudioScriptObject(); + obj->Posn = *(CVector*)&ScriptParams[0]; + obj->AudioId = ScriptParams[3]; + obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj); + ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_REMOVE_SOUND: + { + CollectParameters(&m_nIp, 1); + cAudioScriptObject* obj = CPools::GetAudioScriptObjectPool()->GetAt(ScriptParams[0]); + if (!obj){ + debug("REMOVE_SOUND - Sound doesn't exist\n"); + return 0; + } + DMAudio.DestroyLoopingScriptObject(obj->AudioEntity); + delete obj; + return 0; + } + case COMMAND_IS_CAR_STUCK_ON_ROOF: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(CTheScripts::UpsideDownCars.HasCarBeenUpsideDownForAWhile(ScriptParams[0])); + return 0; + } + default: + script_assert(0); + } + return -1; +} + +int8 CRunningScript::ProcessCommands400To499(int32 command) +{ + switch (command) { + case COMMAND_ADD_UPSIDEDOWN_CAR_CHECK: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CTheScripts::UpsideDownCars.AddCarToCheck(ScriptParams[0]); + return 0; + } + case COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CTheScripts::UpsideDownCars.RemoveCarFromCheck(ScriptParams[0]); + return 0; + } + case COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE); + return 0; + } + case COMMAND_SET_CHAR_OBJ_GUARD_SPOT: + { + CollectParameters(&m_nIp, 4); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos); + return 0; + } + case COMMAND_SET_CHAR_OBJ_GUARD_AREA: + { + CollectParameters(&m_nIp, 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + float infX = *(float*)&ScriptParams[1]; + float infY = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + if (infX > supX){ + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[1]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[2]; + } + CVector pos; + pos.x = (infX + supX) / 2; + pos.y = (infY + supY) / 2; + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float radius = Max(pos.x - infX, pos.y - infY); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos, radius); + return 0; + } + case COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_WAIT_IN_CAR); + return 0; + } + case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: + PlayerInAreaCheckCommand(command, &m_nIp); + return 0; + case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D: + case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: + CharInAreaCheckCommand(command, &m_nIp); + return 0; + case COMMAND_IS_CAR_STOPPED_IN_AREA_2D: + case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: + CarInAreaCheckCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_CAR_2D: + case COMMAND_LOCATE_STOPPED_CAR_2D: + case COMMAND_LOCATE_CAR_3D: + case COMMAND_LOCATE_STOPPED_CAR_3D: + LocateCarCommand(command, &m_nIp); + return 0; + case COMMAND_GIVE_WEAPON_TO_PLAYER: + { + CollectParameters(&m_nIp, 3); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + pPed->m_nSelectedWepSlot = pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]); + return 0; + } + case COMMAND_GIVE_WEAPON_TO_CHAR: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->SetCurrentWeapon(pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2])); + if (pPed->bInVehicle) + pPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId); + return 0; + } + /* Not implemented */ + //case COMMAND_GIVE_WEAPON_TO_CAR: + case COMMAND_SET_PLAYER_CONTROL: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; + if (ScriptParams[1]){ + if (CGame::playingIntro || CTheScripts::DelayMakingPlayerUnsafeThisTime){ + CTheScripts::CountdownToMakePlayerUnsafe = 50; + if (CTheScripts::DelayMakingPlayerUnsafeThisTime) + CTheScripts::DelayMakingPlayerUnsafeThisTime--; + }else{ + pPlayer->MakePlayerSafe(false); + } + }else{ + pPlayer->MakePlayerSafe(true); + if (strcmp(m_abScriptName, "camera") == 0){ + pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); + pPlayer->m_pPed->SetTurnSpeed(0.0f, 0.0f, 0.0f); + CAnimManager::BlendAnimation((RpClump*)pPlayer->m_pPed->m_rwObject, pPlayer->m_pPed->m_animGroup, ANIM_IDLE_STANCE, 1000.0f); + } + } + return 0; + } + case COMMAND_FORCE_WEATHER: + CollectParameters(&m_nIp, 1); + CWeather::ForceWeather(ScriptParams[0]); + return 0; + case COMMAND_FORCE_WEATHER_NOW: + CollectParameters(&m_nIp, 1); + CWeather::ForceWeatherNow(ScriptParams[0]); + return 0; + case COMMAND_RELEASE_WEATHER: + CWeather::ReleaseWeather(); + return 0; + case COMMAND_SET_CURRENT_PLAYER_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++){ + if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1]) + pPed->m_nSelectedWepSlot = i; + } + return 0; + } + case COMMAND_SET_CURRENT_CHAR_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { + if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1]) + pPed->SetCurrentWeapon(i); + } + return 0; + } + /* Not implemented */ + //case COMMAND_SET_CURRENT_CAR_WEAPON: + case COMMAND_GET_OBJECT_COORDINATES: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + *(CVector*)&ScriptParams[0] = pObject->GetPosition(); + StoreParameters(&m_nIp, 3); + return 0; + } + case COMMAND_SET_OBJECT_COORDINATES: + { + CollectParameters(&m_nIp, 4); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pObject->Teleport(pos); + CTheScripts::ClearSpaceForMissionEntity(pos, pObject); + return 0; + } + case COMMAND_GET_GAME_TIMER: + ScriptParams[0] = CTimer::GetTimeInMilliseconds(); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_TURN_CHAR_TO_FACE_COORD: + { + CollectParameters(&m_nIp, 4); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle; + CVector pos; + if (pPed->bInVehicle) + pVehicle = pPed->m_pMyVehicle; + else + pVehicle = nil; + if (pVehicle) + pos = pVehicle->GetPosition(); + else + pos = pPed->GetPosition(); + float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]); + heading += HALFPI; + if (heading > TWOPI) + heading -= TWOPI; + if (!pVehicle){ + pPed->m_fRotationCur = heading; + pPed->m_fRotationDest = heading; + pPed->SetHeading(heading); + } + return 0; + } + case COMMAND_TURN_PLAYER_TO_FACE_COORD: + { + CollectParameters(&m_nIp, 4); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CVehicle* pVehicle; + CVector pos; + if (pPed->bInVehicle) + pVehicle = pPed->m_pMyVehicle; + else + pVehicle = nil; + if (pVehicle) + pos = pVehicle->GetPosition(); + else + pos = pPed->GetPosition(); + float heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]); + heading += HALFPI; + if (heading > TWOPI) + heading -= TWOPI; + if (!pVehicle) { + pPed->m_fRotationCur = heading; + pPed->m_fRotationDest = heading; + pPed->SetHeading(heading); + } + return 0; + } + case COMMAND_STORE_WANTED_LEVEL: + { + CollectParameters(&m_nIp, 1); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + ScriptParams[0] = pPed->m_pWanted->m_nWantedLevel; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_IS_CAR_STOPPED: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(CTheScripts::IsVehicleStopped(pVehicle)); + return 0; + } + case COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CTheScripts::CleanUpThisPed(pPed); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR); + return 0; + } + case COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + CTheScripts::CleanUpThisVehicle(pVehicle); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR); + return 0; + } + case COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + CTheScripts::CleanUpThisObject(pObject); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT); + return 0; + } + case COMMAND_DONT_REMOVE_CHAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR); + return 0; + } + case COMMAND_DONT_REMOVE_CAR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR); + return 0; + } + case COMMAND_DONT_REMOVE_OBJECT: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT); + return 0; + } + case COMMAND_CREATE_CHAR_AS_PASSENGER: + { + CollectParameters(&m_nIp, 4); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + switch (ScriptParams[2]) { + case MI_COP: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_STREET; + break; + case MI_SWAT: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_SWAT; + break; + case MI_FBI: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_FBI; + break; + case MI_ARMY: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_ARMY; + break; + case MI_MEDIC: + if (ScriptParams[1] == PEDTYPE_EMERGENCY) + ScriptParams[2] = PEDTYPE_EMERGENCY; + break; + case MI_FIREMAN: + if (ScriptParams[1] == PEDTYPE_FIREMAN) + ScriptParams[2] = PEDTYPE_FIREMAN; + break; + default: + break; + } + CPed* pPed; + if (ScriptParams[1] == PEDTYPE_COP) + pPed = new CCopPed((eCopType)ScriptParams[2]); + else if (ScriptParams[1] == PEDTYPE_EMERGENCY || ScriptParams[1] == PEDTYPE_FIREMAN) + pPed = new CEmergencyPed(ScriptParams[2]); + else + pPed = new CCivilianPed((ePedType)ScriptParams[1], ScriptParams[2]); + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + pPed->bAllowMedicsToReviveMe = false; + pPed->SetPosition(pVehicle->GetPosition()); + pPed->SetOrientation(0.0f, 0.0f, 0.0f); + pPed->SetPedState(PED_DRIVING); + CPopulation::ms_nTotalMissionPeds++; + if (ScriptParams[3] >= 0) + pVehicle->AddPassenger(pPed, ScriptParams[3]); + else + pVehicle->AddPassenger(pPed); + pPed->m_pMyVehicle = pVehicle; + pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); + pPed->bInVehicle = true; + pPed->SetPedState(PED_DRIVING); + pVehicle->SetStatus(STATUS_PHYSICS); + pPed->bUsesCollision = false; +#ifdef FIX_BUGS + AnimationId anim = pVehicle->GetDriverAnim(); +#else + AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT; +#endif + pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); + pPed->StopNonPartialAnims(); + 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); + return 0; + } + case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_LEAVE_CAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); + return 0; + } + case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pVehicle); + return 0; + } + case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle); + return 0; + } + /* Not implemented. + case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR: + case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE: + case COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT: + */ + case COMMAND_SET_CHAR_OBJ_DESTROY_CAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_DESTROY_CAR, pVehicle); + return 0; + } + case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT: + { + CollectParameters(&m_nIp, 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + float infX = *(float*)&ScriptParams[1]; + float infY = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[1]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[2]; + } + CVector pos; + pos.x = (infX + supX) / 2; + pos.y = (infY + supY) / 2; + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float radius = Max(pos.x - infX, pos.y - infY); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius); + return 0; + } + /* Not implemented. + case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR: + case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: + case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK: + */ + case COMMAND_SET_CHAR_AS_LEADER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget); + return 0; + } + case COMMAND_SET_PLAYER_AS_LEADER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed; + pPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget); + return 0; + } + case COMMAND_LEAVE_GROUP: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->ClearLeader(); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FOLLOW_ROUTE, ScriptParams[1], ScriptParams[2]); + return 0; + } + case COMMAND_ADD_ROUTE_POINT: + { + CollectParameters(&m_nIp, 4); + CRouteNode::AddRoutePoint(ScriptParams[0], *(CVector*)&ScriptParams[1]); + return 0; + } + case COMMAND_PRINT_WITH_NUMBER_BIG: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 3); + CMessages::AddBigMessageWithNumber(text, ScriptParams[1], ScriptParams[2] - 1, ScriptParams[0], -1, -1, -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_NUMBER: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 3); + CMessages::AddMessageWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_NUMBER_NOW: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 3); + CMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1); + return 0; + } + /* Not implemented. + case COMMAND_PRINT_WITH_NUMBER_SOON: + */ + case COMMAND_SWITCH_ROADS_ON: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX){ + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY){ + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ){ + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false); + return 0; + } + case COMMAND_SWITCH_ROADS_OFF: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true); + return 0; + } + case COMMAND_GET_NUMBER_OF_PASSENGERS: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + ScriptParams[0] = pVehicle->m_nNumPassengers; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + ScriptParams[0] = pVehicle->m_nNumMaxPassengers; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CAR_DENSITY_MULTIPLIER: + { + CollectParameters(&m_nIp, 1); + CCarCtrl::CarDensityMultiplier = *(float*)&ScriptParams[0]; + return 0; + } + case COMMAND_SET_CAR_HEAVY: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bIsHeavy = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_CLEAR_CHAR_THREAT_SEARCH: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->m_fearFlags = 0; + return 0; + } + case COMMAND_ACTIVATE_CRANE: + { + CollectParameters(&m_nIp, 10); + float infX = *(float*)&ScriptParams[2]; + float infY = *(float*)&ScriptParams[3]; + float supX = *(float*)&ScriptParams[4]; + float supY = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[4]; + supX = *(float*)&ScriptParams[2]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[5]; + supY = *(float*)&ScriptParams[3]; + } + CCranes::ActivateCrane(infX, supX, infY, supY, + *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8], + DEGTORAD(*(float*)&ScriptParams[9]), false, false, + *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); + return 0; + } + case COMMAND_DEACTIVATE_CRANE: + { + CollectParameters(&m_nIp, 2); + CCranes::DeActivateCrane(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); + return 0; + } + case COMMAND_SET_MAX_WANTED_LEVEL: + { + CollectParameters(&m_nIp, 1); + CWanted::SetMaximumWantedLevel(ScriptParams[0]); + return 0; + } + /* Debug commands? + case COMMAND_SAVE_VAR_INT: + case COMMAND_SAVE_VAR_FLOAT: + */ + case COMMAND_IS_CAR_IN_AIR_PROPER: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0); + return 0; + } + default: + script_assert(0); + } + return -1; +} diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp new file mode 100644 index 00000000..c0112d06 --- /dev/null +++ b/src/control/Script3.cpp @@ -0,0 +1,2082 @@ +#include "common.h" + +#include "Script.h" +#include "ScriptCommands.h" + +#include "Boat.h" +#include "CarCtrl.h" +#include "Clock.h" +#include "Coronas.h" +#include "Cranes.h" +#include "CutsceneMgr.h" +#include "Darkel.h" +#include "Explosion.h" +#include "Fire.h" +#include "General.h" +#include "Garages.h" +#include "Heli.h" +#include "Messages.h" +#include "Pad.h" +#include "ParticleObject.h" +#include "Phones.h" +#include "Pickups.h" +#include "PointLights.h" +#include "Population.h" +#include "Pools.h" +#include "ProjectileInfo.h" +#include "Radar.h" +#include "Restart.h" +#include "Stats.h" +#include "Streaming.h" +#include "User.h" +#include "WaterLevel.h" +#include "Weather.h" +#include "Zones.h" + +int8 CRunningScript::ProcessCommands500To599(int32 command) +{ + switch (command) { + case COMMAND_IS_CAR_UPSIDEDOWN: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->GetUp().z <= -0.97f); + return 0; + } + case COMMAND_GET_PLAYER_CHAR: + { + CollectParameters(&m_nIp, 1); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_CANCEL_OVERRIDE_RESTART: + CRestart::CancelOverrideRestart(); + return 0; + case COMMAND_SET_POLICE_IGNORE_PLAYER: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + if (ScriptParams[1]) { + pPed->m_pWanted->m_bIgnoredByCops = true; + CWorld::StopAllLawEnforcersInTheirTracks(); + } + else { + pPed->m_pWanted->m_bIgnoredByCops = false; + } + return 0; + } + case COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 4); + CUserDisplay::Pager.AddMessageWithNumber(text, ScriptParams[0], -1, -1, -1, -1, -1, + ScriptParams[1], ScriptParams[2], ScriptParams[3]); + return 0; + } + case COMMAND_START_KILL_FRENZY: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 8); + CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2], + ScriptParams[3], text, ScriptParams[4], ScriptParams[5], + ScriptParams[6], ScriptParams[7] != 0, false); + return 0; + } + case COMMAND_READ_KILL_FRENZY_STATUS: + { + ScriptParams[0] = CDarkel::ReadStatus(); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SQRT: + { + CollectParameters(&m_nIp, 1); + *(float*)&ScriptParams[0] = Sqrt(*(float*)&ScriptParams[0]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D: + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D: + LocatePlayerCarCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D: + case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D: + LocateCharCarCommand(command, &m_nIp); + return 0; + case COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE: + CollectParameters(&m_nIp, 2); + *(float*)&ScriptParams[0] = CGeneral::GetRandomNumberInRange(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_GENERATE_RANDOM_INT_IN_RANGE: + CollectParameters(&m_nIp, 2); + ScriptParams[0] = CGeneral::GetRandomNumberInRange(ScriptParams[0], ScriptParams[1]); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_LOCK_CAR_DOORS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1]; + return 0; + } + case COMMAND_EXPLODE_CAR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->BlowUpCar(nil); + return 0; + } + case COMMAND_ADD_EXPLOSION: + CollectParameters(&m_nIp, 4); + CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0); + return 0; + + case COMMAND_IS_CAR_UPRIGHT: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->GetUp().z >= 0.0f); + return 0; + } + case COMMAND_TURN_CHAR_TO_FACE_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil; + CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition(); + CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition(); + float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI; + if (angle > TWOPI) + angle -= TWOPI; + if (!pVehicle) { + pSourcePed->m_fRotationCur = angle; + pSourcePed->m_fRotationDest = angle; + pSourcePed->SetHeading(angle); + } + return 0; + } + case COMMAND_TURN_CHAR_TO_FACE_PLAYER: + { + CollectParameters(&m_nIp, 2); + CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed; + CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil; + CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition(); + CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition(); + float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI; + if (angle > TWOPI) + angle -= TWOPI; + if (!pVehicle) { + pSourcePed->m_fRotationCur = angle; + pSourcePed->m_fRotationDest = angle; + pSourcePed->SetHeading(angle); + } + return 0; + } + case COMMAND_TURN_PLAYER_TO_FACE_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed; + CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + CVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil; + CVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition(); + CVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition(); + float angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI; + if (angle > TWOPI) + angle -= TWOPI; + if (!pVehicle) { + pSourcePed->m_fRotationCur = angle; + pSourcePed->m_fRotationDest = angle; + pSourcePed->SetHeading(angle); + } + return 0; + } + case COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVector target; + target.x = *(float*)&ScriptParams[1]; + target.y = *(float*)&ScriptParams[2]; + target.z = CWorld::FindGroundZForCoord(target.x, target.y); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, target); + return 0; + } + /* Not implemented*/ + //case COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR: + case COMMAND_CREATE_PICKUP: + { + CollectParameters(&m_nIp, 5); + int16 model = ScriptParams[0]; + if (model < 0) + model = CTheScripts::UsedObjectArray[-model].index; + CVector pos = *(CVector*)&ScriptParams[2]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], 0); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_HAS_PICKUP_BEEN_COLLECTED: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CPickups::IsPickUpPickedUp(ScriptParams[0]) != 0); + return 0; + case COMMAND_REMOVE_PICKUP: + CollectParameters(&m_nIp, 1); + CPickups::RemovePickUp(ScriptParams[0]); + return 0; + case COMMAND_SET_TAXI_LIGHTS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); + ((CAutomobile*)pVehicle)->SetTaxiLight(ScriptParams[1] != 0); + return 0; + } + case COMMAND_PRINT_BIG_Q: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 2); + CMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1); + return 0; + } + case COMMAND_PRINT_WITH_NUMBER_BIG_Q: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 3); + CMessages::AddBigMessageWithNumberQ(text, ScriptParams[1], ScriptParams[2] - 1, + ScriptParams[0], -1, -1, -1, -1, -1); + return 0; + } + case COMMAND_SET_GARAGE: + { + CollectParameters(&m_nIp, 7); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], 0); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_GARAGE_WITH_CAR_MODEL: + { + CollectParameters(&m_nIp, 8); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], ScriptParams[7]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE: + { + CollectParameters(&m_nIp, 2); + CVehicle* pTarget; + if (ScriptParams[1] >= 0) { + pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + } + else { + pTarget = nil; + } + CGarages::SetTargetCarForMissonGarage(ScriptParams[0], pTarget); + return 0; + } + case COMMAND_IS_CAR_IN_MISSION_GARAGE: + 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); + float f1 = *(float*)&ScriptParams[0]; + float f2 = *(float*)&ScriptParams[1]; + float f3 = *(float*)&ScriptParams[2]; + float f4 = *(float*)&ScriptParams[3]; + float f5 = *(float*)&ScriptParams[4]; + float f6 = *(float*)&ScriptParams[5]; + float temp; + + if (f1 > f4) { + temp = f1; + f1 = f4; + f4 = temp; + } + + if (f2 > f5) { + temp = f2; + f2 = f5; + f5 = temp; + } + + if (f3 > f6) { + temp = f3; + f3 = f6; + f6 = temp; + } + + CPowerPoints::GenerateNewOne(f1, f2, f3, f4, f5, f6, *(uint8*)&ScriptParams[6]); + + return 0; + } +#endif // GTA_PS2 + case COMMAND_SET_ALL_TAXI_LIGHTS: + CollectParameters(&m_nIp, 1); + CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0); + return 0; + case COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB: + { + CollectParameters(&m_nIp, 1); + CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pCar); + script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR); + UpdateCompareFlag(pCar->m_bombType != 0); //TODO: enum + return 0; + } + case COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR: + CollectParameters(&m_nIp, 2); + CPad::GetPad(ScriptParams[0])->bApplyBrakes = (ScriptParams[1] != 0); + return 0; + case COMMAND_SET_PLAYER_HEALTH: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + pPed->m_fHealth = ScriptParams[1]; + return 0; + } + case COMMAND_SET_CHAR_HEALTH: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + if (ScriptParams[1]) { + pPed->m_fHealth = ScriptParams[1]; + } + else if (pPed->bInVehicle) { + pPed->SetDead(); + if (!pPed->IsPlayer()) + pPed->FlagToDestroyWhenNextProcessed(); + } + else { + pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + } + return 0; + } + case COMMAND_SET_CAR_HEALTH: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->m_fHealth = ScriptParams[1]; + return 0; + } + case COMMAND_GET_PLAYER_HEALTH: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + ScriptParams[0] = pPed->m_fHealth; // correct cast float to int + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_CHAR_HEALTH: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + ScriptParams[0] = pPed->m_fHealth; // correct cast float to int + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_CAR_HEALTH: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + ScriptParams[0] = pVehicle->m_fHealth; // correct cast float to int + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_IS_CAR_ARMED_WITH_BOMB: + { + CollectParameters(&m_nIp, 2); + CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pCar); + script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR); + UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]); //TODO: enum + return 0; + } + case COMMAND_CHANGE_CAR_COLOUR: + { + CollectParameters(&m_nIp, 3); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + if (ScriptParams[1] >= 256 || ScriptParams[2] >= 256) + debug("CHANGE_CAR_COLOUR - Colours must be less than %d", 256); + pVehicle->m_currentColour1 = ScriptParams[1]; + pVehicle->m_currentColour2 = ScriptParams[2]; + return 0; + } + case COMMAND_SWITCH_PED_ROADS_ON: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false); + return 0; + } + case COMMAND_SWITCH_PED_ROADS_OFF: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true); + return 0; + } + case COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS: + { + CollectParameters(&m_nIp, 2); + CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pSourcePed); + CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pTargetPed); + pSourcePed->SetLookFlag(pTargetPed, true); + pSourcePed->SetLookTimer(60000); + return 0; + } + case COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS: + { + CollectParameters(&m_nIp, 2); + CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pSourcePed); + CPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed; + script_assert(pTargetPed); + pSourcePed->SetLookFlag(pTargetPed, true); + pSourcePed->SetLookTimer(60000); + return 0; + } + case COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS: + { + CollectParameters(&m_nIp, 2); + CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pSourcePed); + CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pTargetPed); + pSourcePed->SetLookFlag(pTargetPed, true); + pSourcePed->SetLookTimer(60000); + return 0; + } + case COMMAND_STOP_CHAR_LOOKING: + { + CollectParameters(&m_nIp, 1); + CPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pSourcePed); + pSourcePed->ClearLookFlag(); + pSourcePed->bKeepTryingToLook = false; + if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY) + pSourcePed->RestorePreviousState(); + return 0; + } + case COMMAND_STOP_PLAYER_LOOKING: + { + CollectParameters(&m_nIp, 1); + CPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pSourcePed); + pSourcePed->ClearLookFlag(); + pSourcePed->bKeepTryingToLook = false; + if (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY) + pSourcePed->RestorePreviousState(); + return 0; + } + case COMMAND_SWITCH_HELICOPTER: + CollectParameters(&m_nIp, 1); + CHeli::ActivateHeli(ScriptParams[0] != 0); + return 0; + + //case COMMAND_SET_GANG_ATTITUDE: + //case COMMAND_SET_GANG_GANG_ATTITUDE: + //case COMMAND_SET_GANG_PLAYER_ATTITUDE: + //case COMMAND_SET_GANG_PED_MODELS: + case COMMAND_SET_GANG_CAR_MODEL: + CollectParameters(&m_nIp, 2); + CGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_SET_GANG_WEAPONS: + CollectParameters(&m_nIp, 3); + CGangs::SetGangWeapons(ScriptParams[0], (eWeaponType)ScriptParams[1], (eWeaponType)ScriptParams[2]); + return 0; + case COMMAND_SET_CHAR_OBJ_RUN_TO_AREA: + { + CollectParameters(&m_nIp, 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + float infX = *(float*)&ScriptParams[1]; + float infY = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[1]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[2]; + } + CVector pos; + pos.x = (infX + supX) / 2; + pos.y = (infY + supY) / 2; + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float radius = Max(pos.x - infX, pos.y - infY); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius); + return 0; + } + case COMMAND_SET_CHAR_OBJ_RUN_TO_COORD: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVector pos; + pos.x = *(float*)&ScriptParams[1]; + pos.y = *(float*)&ScriptParams[2]; + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos); + return 0; + } + case COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); + bool isTouching = false; + if (pPed->bInVehicle) + isTouching = false; + else if (pPed->GetHasCollidedWith(pObject)) + isTouching = true; + UpdateCompareFlag(isTouching); + return 0; + } + case COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); + bool isTouching = false; + if (pPed->InVehicle()) + isTouching = false; + else if (pPed->GetHasCollidedWith(pObject)) + isTouching = true; + UpdateCompareFlag(isTouching); + return 0; + } + case COMMAND_LOAD_SPECIAL_CHARACTER: + { + CollectParameters(&m_nIp, 1); + char name[16]; + strncpy(name, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + name[i] = tolower(name[i]); + CStreaming::RequestSpecialChar(ScriptParams[0] - 1, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED); + m_nIp += KEY_LENGTH_IN_SCRIPT; + return 0; + } + case COMMAND_HAS_SPECIAL_CHARACTER_LOADED: + { + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CStreaming::HasSpecialCharLoaded(ScriptParams[0] - 1)); + return 0; + } + case COMMAND_FLASH_CAR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bHasBlip = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_FLASH_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bHasBlip = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_FLASH_OBJECT: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + pObject->bHasBlip = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_IS_PLAYER_IN_REMOTE_MODE: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CWorld::Players[ScriptParams[0]].IsPlayerInRemoteMode()); + return 0; + case COMMAND_ARM_CAR_WITH_BOMB: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); + ((CAutomobile*)pVehicle)->m_bombType = ScriptParams[1]; + ((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed(); + return 0; + } + case COMMAND_SET_CHAR_PERSONALITY: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->SetPedStats((ePedStats)ScriptParams[1]); + return 0; + } + case COMMAND_SET_CUTSCENE_OFFSET: + CollectParameters(&m_nIp, 3); + CCutsceneMgr::SetCutsceneOffset(*(CVector*)&ScriptParams[0]); + return 0; + case COMMAND_SET_ANIM_GROUP_FOR_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->m_animGroup = (AssocGroupId)ScriptParams[1]; + return 0; + } + case COMMAND_SET_ANIM_GROUP_FOR_PLAYER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + pPed->m_animGroup = (AssocGroupId)ScriptParams[1]; + return 0; + } + case COMMAND_REQUEST_MODEL: + { + CollectParameters(&m_nIp, 1); + int model = ScriptParams[0]; + if (model < 0) + model = CTheScripts::UsedObjectArray[-model].index; + CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_NOFADE | STREAMFLAGS_SCRIPTOWNED); + return 0; + } + case COMMAND_HAS_MODEL_LOADED: + { + CollectParameters(&m_nIp, 1); + int model = ScriptParams[0]; + if (model < 0) + model = CTheScripts::UsedObjectArray[-model].index; + UpdateCompareFlag(CStreaming::HasModelLoaded(model)); + return 0; + } + case COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED: + { + CollectParameters(&m_nIp, 1); + int model = ScriptParams[0]; + if (model < 0) + model = CTheScripts::UsedObjectArray[-model].index; + CStreaming::SetMissionDoesntRequireModel(model); + return 0; + } + case COMMAND_GRAB_PHONE: + { + CollectParameters(&m_nIp, 2); + ScriptParams[0] = gPhoneInfo.GrabPhone(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_REPEATED_PHONE_MESSAGE: + { + CollectParameters(&m_nIp, 1); + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text, nil, nil, nil, nil, nil); + return 0; + } + case COMMAND_SET_PHONE_MESSAGE: + { + CollectParameters(&m_nIp, 1); + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text, nil, nil, nil, nil, nil); + return 0; + } + case COMMAND_HAS_PHONE_DISPLAYED_MESSAGE: + { + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0])); + return 0; + } + case COMMAND_TURN_PHONE_OFF: + { + CollectParameters(&m_nIp, 1); + gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], nil, nil, nil, nil, nil, nil); + return 0; + } + case COMMAND_DRAW_CORONA: + { + CollectParameters(&m_nIp, 9); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], + 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f); + return 0; + } + case COMMAND_DRAW_LIGHT: + { + CollectParameters(&m_nIp, 6); + CVector pos = *(CVector*)&ScriptParams[0]; + CVector unused(0.0f, 0.0f, 0.0f); + CPointLights::AddLight(0, *(CVector*)&ScriptParams[0], CVector(0.0f, 0.0f, 0.0f), 12.0f, + ScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true); + return 0; + } + case COMMAND_STORE_WEATHER: + CWeather::StoreWeatherState(); + return 0; + case COMMAND_RESTORE_WEATHER: + CWeather::RestoreWeatherState(); + return 0; + case COMMAND_STORE_CLOCK: + CClock::StoreClock(); + return 0; + case COMMAND_RESTORE_CLOCK: + CClock::RestoreClock(); + return 0; + case COMMAND_RESTART_CRITICAL_MISSION: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRestart::OverrideNextRestart(pos, *(float*)&ScriptParams[3]); + if (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING) + printf("RESTART_CRITICAL_MISSION - Player state is not PLAYING\n"); + CWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission(); + return 0; + } + case COMMAND_IS_PLAYER_PLAYING: + { + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_PLAYING); + return 0; + } + //case COMMAND_SET_COLL_OBJ_NO_OBJ: + default: + script_assert(0); + } + return -1; +} + +int8 CRunningScript::ProcessCommands600To699(int32 command) +{ + switch (command){ + /* Collective commands are not implemented until LCS. + case COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT: + case COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE: + case COMMAND_SET_COLL_OBJ_GUARD_SPOT: + case COMMAND_SET_COLL_OBJ_GUARD_AREA: + case COMMAND_SET_COLL_OBJ_WAIT_IN_CAR: + case COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT: + case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT: + case COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS: + case COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS: + case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE: + case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE: + case COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS: + case COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS: + case COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT: + case COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT: + case COMMAND_SET_COLL_OBJ_LEAVE_CAR: + case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER: + case COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER: + case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR: + case COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE: + case COMMAND_SET_COLL_OBJ_DESTROY_OBJECT: + case COMMAND_SET_COLL_OBJ_DESTROY_CAR: + case COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT: + case COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR: + case COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: + case COMMAND_SET_COLL_OBJ_GUARD_ATTACK: + case COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE: + case COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT: + case COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR: + case COMMAND_SET_COLL_OBJ_RUN_TO_AREA: + case COMMAND_SET_COLL_OBJ_RUN_TO_COORD: + case COMMAND_ADD_PEDS_IN_AREA_TO_COLL: + case COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL: + case COMMAND_CLEAR_COLL: + case COMMAND_IS_COLL_IN_CARS: + case COMMAND_LOCATE_COLL_ANY_MEANS_2D: + case COMMAND_LOCATE_COLL_ON_FOOT_2D: + case COMMAND_LOCATE_COLL_IN_CAR_2D: + case COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D: + case COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D: + case COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D: + case COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D: + case COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D: + case COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D: + case COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D: + case COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D: + case COMMAND_LOCATE_COLL_IN_CAR_CAR_2D: + case COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D: + case COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D: + case COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D: + case COMMAND_IS_COLL_IN_AREA_2D: + case COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_COLL_IN_AREA_IN_CAR_2D: + case COMMAND_IS_COLL_STOPPED_IN_AREA_2D: + case COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D: + case COMMAND_GET_NUMBER_OF_PEDS_IN_COLL: + */ + case COMMAND_SET_CHAR_HEED_THREATS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bRespondsToThreats = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_PLAYER_HEED_THREATS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + pPed->bRespondsToThreats = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_GET_CONTROLLER_MODE: +#if defined(GTA_PC) && !defined(DETECT_PAD_INPUT_SWITCH) + ScriptParams[0] = 0; +#else + ScriptParams[0] = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0; +#endif + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_SET_CAN_RESPRAY_CAR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); + ((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0); + return 0; + } + case COMMAND_IS_TAXI: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + int mi = pVehicle->GetModelIndex(); + UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE); + return 0; + } + case COMMAND_UNLOAD_SPECIAL_CHARACTER: + CollectParameters(&m_nIp, 1); + CStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1); + return 0; + case COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER: + CDarkel::ResetModelsKilledByPlayer(); + return 0; + case COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER: + CollectParameters(&m_nIp, 1); + ScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_ACTIVATE_GARAGE: + CollectParameters(&m_nIp, 1); + CGarages::ActivateGarage(ScriptParams[0]); + return 0; + case COMMAND_SWITCH_TAXI_TIMER: + { + CollectParameters(&m_nIp, 1); + if (ScriptParams[0] != 0){ + CWorld::Players[CWorld::PlayerInFocus].m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds(); + CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = true; + }else{ + CWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = false; + } + return 0; + } + case COMMAND_CREATE_OBJECT_NO_OFFSET: + { + CollectParameters(&m_nIp, 4); + int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index; + CObject* pObj = new CObject(mi, false); +; pObj->ObjectCreatedBy = MISSION_OBJECT; + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pObj->SetPosition(pos); + pObj->SetOrientation(0.0f, 0.0f, 0.0f); + pObj->GetMatrix().UpdateRW(); + pObj->UpdateRwFrame(); + CTheScripts::ClearSpaceForMissionEntity(pos, pObj); + CWorld::Add(pObj); + ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj); + StoreParameters(&m_nIp, 1); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT); + return 0; + } + case COMMAND_IS_BOAT: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); + return 0; + } + case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS: + { + CollectParameters(&m_nIp, 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + float infX = *(float*)&ScriptParams[1]; + float infY = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[1]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[2]; + } + CVector pos; + pos.x = (infX + supX) / 2; + pos.y = (infY + supY) / 2; + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float radius = Max(pos.x - infX, pos.y - infY); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius); + return 0; + } + //case COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS: + case COMMAND_IS_PLAYER_STOPPED: + { + CollectParameters(&m_nIp, 1); + CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; + UpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer)); + return 0; + } + case COMMAND_IS_CHAR_STOPPED: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(CTheScripts::IsPedStopped(pPed)); + return 0; + } + case COMMAND_MESSAGE_WAIT: + CollectParameters(&m_nIp, 2); + m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0]; + if (ScriptParams[1] != 0) + m_bSkipWakeTime = true; + return 1; + case COMMAND_ADD_PARTICLE_EFFECT: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0); + return 0; + } + case COMMAND_SWITCH_WIDESCREEN: + CollectParameters(&m_nIp, 1); + if (ScriptParams[0] != 0) + TheCamera.SetWideScreenOn(); + else + TheCamera.SetWideScreenOff(); + return 0; + case COMMAND_ADD_SPRITE_BLIP_FOR_CAR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int id = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH); + CRadar::SetBlipSprite(id, ScriptParams[1]); + ScriptParams[0] = id; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_SPRITE_BLIP_FOR_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int id = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH); + CRadar::SetBlipSprite(id, ScriptParams[1]); + ScriptParams[0] = id; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int id = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH); + CRadar::SetBlipSprite(id, ScriptParams[1]); + ScriptParams[0] = id; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int id = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH); + CRadar::SetBlipSprite(id, ScriptParams[3]); + ScriptParams[0] = id; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_SPRITE_BLIP_FOR_COORD: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int id = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH); + CRadar::SetBlipSprite(id, ScriptParams[3]); + ScriptParams[0] = id; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bOnlyDamagedByPlayer = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bOnlyDamagedByPlayer = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_CHAR_PROOFS: + { + CollectParameters(&m_nIp, 6); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bBulletProof = (ScriptParams[1] != 0); + pPed->bFireProof = (ScriptParams[2] != 0); + pPed->bExplosionProof = (ScriptParams[3] != 0); + pPed->bCollisionProof = (ScriptParams[4] != 0); + pPed->bMeleeProof = (ScriptParams[5] != 0); + return 0; + } + case COMMAND_SET_CAR_PROOFS: + { + CollectParameters(&m_nIp, 6); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bBulletProof = (ScriptParams[1] != 0); + pVehicle->bFireProof = (ScriptParams[2] != 0); + pVehicle->bExplosionProof = (ScriptParams[3] != 0); + pVehicle->bCollisionProof = (ScriptParams[4] != 0); + pVehicle->bMeleeProof = (ScriptParams[5] != 0); + return 0; + } + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: + PlayerInAngledAreaCheckCommand(command, &m_nIp); + return 0; + case COMMAND_DEACTIVATE_GARAGE: + CollectParameters(&m_nIp, 1); + CGarages::DeActivateGarage(ScriptParams[0]); + return 0; + case COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE: + CollectParameters(&m_nIp, 1); + ScriptParams[0] = CGarages::QueryCarsCollected(ScriptParams[0]); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE: + CollectParameters(&m_nIp, 2); + UpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1)); + return 0; + default: + script_assert(0); + } + return -1; +} + +int8 CRunningScript::ProcessCommands700To799(int32 command) +{ + switch (command){ + case COMMAND_SET_SWAT_REQUIRED: + CollectParameters(&m_nIp, 1); + FindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0); + return 0; + case COMMAND_SET_FBI_REQUIRED: + CollectParameters(&m_nIp, 1); + FindPlayerPed()->m_pWanted->m_bFbiRequired = (ScriptParams[0] != 0); + return 0; + case COMMAND_SET_ARMY_REQUIRED: + CollectParameters(&m_nIp, 1); + FindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0); + return 0; + case COMMAND_IS_CAR_IN_WATER: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(pVehicle && pVehicle->bIsInWater); + return 0; + } + case COMMAND_GET_CLOSEST_CHAR_NODE: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)]; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); + StoreParameters(&m_nIp, 3); + return 0; + } + case COMMAND_GET_CLOSEST_CAR_NODE: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)]; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); + StoreParameters(&m_nIp, 3); + return 0; + } + case COMMAND_CAR_GOTO_COORDINATES_ACCURATE: + { + CollectParameters(&m_nIp, 4); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); + if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pos, false)) + pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE; + else + pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE; + pVehicle->SetStatus(STATUS_PHYSICS); + pVehicle->bEngineOn = true; + pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); + pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); + return 0; + } + case COMMAND_START_PACMAN_RACE: + CollectParameters(&m_nIp, 1); + CPacManPickups::StartPacManRace(ScriptParams[0]); + return 0; + case COMMAND_START_PACMAN_RECORD: + CPacManPickups::StartPacManRecord(); + return 0; + case COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN: + ScriptParams[0] = CPacManPickups::QueryPowerPillsEatenInRace(); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_CLEAR_PACMAN: + CPacManPickups::CleanUpPacManStuff(); + return 0; + case COMMAND_START_PACMAN_SCRAMBLE: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CPacManPickups::StartPacManScramble(pos, *(float*)&ScriptParams[3], ScriptParams[4]); + return 0; + } + case COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED: + ScriptParams[0] = CPacManPickups::QueryPowerPillsCarriedByPlayer(); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED: + CPacManPickups::ResetPowerPillsCarriedByPlayer(); + return 0; + case COMMAND_IS_CAR_ON_SCREEN: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(TheCamera.IsSphereVisible(pVehicle->GetBoundCentre(), pVehicle->GetBoundRadius())); + return 0; + } + case COMMAND_IS_CHAR_ON_SCREEN: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(TheCamera.IsSphereVisible(pPed->GetBoundCentre(), pPed->GetBoundRadius())); + return 0; + } + case COMMAND_IS_OBJECT_ON_SCREEN: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + UpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius())); + return 0; + } + case COMMAND_GOSUB_FILE: + { + CollectParameters(&m_nIp, 2); + script_assert(m_nStackPointer < MAX_STACK_DEPTH); + m_anStack[m_nStackPointer++] = m_nIp; + SetIP(ScriptParams[0]); + // ScriptParams[1] == filename + return 0; + } + case COMMAND_GET_GROUND_Z_FOR_3D_COORD: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + bool success; + *(float*)&ScriptParams[0] = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &success); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_START_SCRIPT_FIRE: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + ScriptParams[0] = gFireManager.StartScriptFire(pos, nil, 0.8f, 1); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(gFireManager.IsScriptFireExtinguish(ScriptParams[0])); + return 0; + case COMMAND_REMOVE_SCRIPT_FIRE: + CollectParameters(&m_nIp, 1); + gFireManager.RemoveScriptFire(ScriptParams[0]); + return 0; + case COMMAND_SET_COMEDY_CONTROLS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bComedyControls = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_BOAT_GOTO_COORDS: + { + CollectParameters(&m_nIp, 4); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); + CBoat* pBoat = (CBoat*)pVehicle; + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false); + pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS; + pBoat->AutoPilot.m_vecDestinationCoors = pos; + pBoat->SetStatus(STATUS_PHYSICS); + pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed); + pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); + return 0; + } + case COMMAND_BOAT_STOP: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); + CBoat* pBoat = (CBoat*)pVehicle; + pBoat->AutoPilot.m_nCarMission = MISSION_NONE; + pBoat->SetStatus(STATUS_PHYSICS); + pBoat->bEngineOn = false; + pBoat->AutoPilot.m_nCruiseSpeed = 0; + return 0; + } + case COMMAND_IS_PLAYER_SHOOTING_IN_AREA: + { + CollectParameters(&m_nIp, 6); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + float x1 = *(float*)&ScriptParams[1]; + float y1 = *(float*)&ScriptParams[2]; + float x2 = *(float*)&ScriptParams[3]; + float y2 = *(float*)&ScriptParams[4]; + UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) + CTheScripts::DrawDebugSquare(x1, y1, x2, y2); + return 0; + } + case COMMAND_IS_CHAR_SHOOTING_IN_AREA: + { + CollectParameters(&m_nIp, 6); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + float x1 = *(float*)&ScriptParams[1]; + float y1 = *(float*)&ScriptParams[2]; + float x2 = *(float*)&ScriptParams[3]; + float y2 = *(float*)&ScriptParams[4]; + UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) + CTheScripts::DrawDebugSquare(x1, y1, x2, y2); + return 0; + } + case COMMAND_IS_CURRENT_PLAYER_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType); + return 0; + } + case COMMAND_IS_CURRENT_CHAR_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType); + return 0; + } + case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN: + CPacManPickups::ResetPowerPillsEatenInRace(); + return 0; + case COMMAND_ADD_POWER_PILL: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CPacManPickups::GenerateOnePMPickUp(pos); + return 0; + } + case COMMAND_SET_BOAT_CRUISE_SPEED: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); + CBoat* pBoat = (CBoat*)pVehicle; + pBoat->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1]; + return 0; + } + case COMMAND_GET_RANDOM_CHAR_IN_AREA: + { + CollectParameters(&m_nIp, 4); + int ped_handle = -1; + CVector pos = FindPlayerCoors(); + float x1 = *(float*)&ScriptParams[0]; + float y1 = *(float*)&ScriptParams[1]; + float x2 = *(float*)&ScriptParams[2]; + float y2 = *(float*)&ScriptParams[3]; + int i = CPools::GetPedPool()->GetSize(); + while (--i && ped_handle == -1){ + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) + continue; + if (pPed->CharCreatedBy != RANDOM_CHAR) + continue; + if (!pPed->IsPedInControl()) + continue; + if (pPed->bRemoveFromWorld) + continue; + if (pPed->bFadeOut) + continue; + if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN) + continue; + if (!ThisIsAValidRandomPed(pPed->m_nPedType)) + continue; + if (pPed->bIsLeader || pPed->m_leader) + continue; + if (!pPed->IsWithinArea(x1, y1, x2, y2)) + continue; + if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) + continue; + if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) + continue; + ped_handle = CPools::GetPedPool()->GetIndex(pPed); + CTheScripts::LastRandomPedId = ped_handle; + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + ++CPopulation::ms_nTotalMissionPeds; + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); + } + ScriptParams[0] = ped_handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_RANDOM_CHAR_IN_ZONE: + { + char zone[KEY_LENGTH_IN_SCRIPT]; + strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone); + if (nZone != -1) + m_nIp += KEY_LENGTH_IN_SCRIPT; + CZone* pZone = CTheZones::GetZone(nZone); + int ped_handle = -1; + CVector pos = FindPlayerCoors(); + int i = CPools::GetPedPool()->GetSize(); + while (--i && ped_handle == -1) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) + continue; + if (pPed->CharCreatedBy != RANDOM_CHAR) + continue; + if (!pPed->IsPedInControl()) + continue; + if (pPed->bRemoveFromWorld) + continue; + if (pPed->bFadeOut) + continue; + if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN) + continue; + if (!ThisIsAValidRandomPed(pPed->m_nPedType)) + continue; + if (pPed->bIsLeader || pPed->m_leader) + continue; + if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone)) + continue; + if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) + continue; + if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) + continue; + ped_handle = CPools::GetPedPool()->GetIndex(pPed); + CTheScripts::LastRandomPedId = ped_handle; + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + ++CPopulation::ms_nTotalMissionPeds; + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); + } + ScriptParams[0] = ped_handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_IS_PLAYER_IN_TAXI: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->IsTaxi()); + return 0; + } + case COMMAND_IS_PLAYER_SHOOTING: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + UpdateCompareFlag(pPed->bIsShooting); + return 0; + } + case COMMAND_IS_CHAR_SHOOTING: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(pPed->bIsShooting); + return 0; + } + case COMMAND_CREATE_MONEY_PICKUP: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_MONEY, PICKUP_MONEY, ScriptParams[3]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CHAR_ACCURACY: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->m_wepAccuracy = ScriptParams[1]; + return 0; + } + case COMMAND_GET_CAR_SPEED: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + *(float*)&ScriptParams[0] = pVehicle->GetSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_LOAD_CUTSCENE: + { + char name[KEY_LENGTH_IN_SCRIPT]; + strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CCutsceneMgr::LoadCutsceneData(name); + return 0; + } + case COMMAND_CREATE_CUTSCENE_OBJECT: + { + CollectParameters(&m_nIp, 1); + CCutsceneObject* pCutObj = CCutsceneMgr::CreateCutsceneObject(ScriptParams[0]); + ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutObj); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CUTSCENE_ANIM: + { + CollectParameters(&m_nIp, 1); + char name[KEY_LENGTH_IN_SCRIPT]; + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CCutsceneMgr::SetCutsceneAnim(name, pObject); + return 0; + } + case COMMAND_START_CUTSCENE: + CCutsceneMgr::ms_cutsceneLoadStatus = 1; + return 0; + case COMMAND_GET_CUTSCENE_TIME: + ScriptParams[0] = CCutsceneMgr::GetCutsceneTimeInMilleseconds(); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_HAS_CUTSCENE_FINISHED: + UpdateCompareFlag(CCutsceneMgr::HasCutsceneFinished()); + return 0; + case COMMAND_CLEAR_CUTSCENE: + CCutsceneMgr::DeleteCutsceneData(); + return 0; + case COMMAND_RESTORE_CAMERA_JUMPCUT: + TheCamera.RestoreWithJumpCut(); + return 0; + case COMMAND_CREATE_COLLECTABLE1: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + CPickups::GenerateNewOne(pos, MI_COLLECTABLE1, PICKUP_COLLECTABLE1, 0); + return 0; + } + case COMMAND_SET_COLLECTABLE1_TOTAL: + CollectParameters(&m_nIp, 1); + CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0]; + return 0; + case COMMAND_IS_PROJECTILE_IN_AREA: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, false)); + if (CTheScripts::DbgFlag) + CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); + return 0; + } + case COMMAND_DESTROY_PROJECTILES_IN_AREA: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + UpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, true)); + if (CTheScripts::DbgFlag) + CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); + return 0; + } + case COMMAND_DROP_MINE: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + CPickups::GenerateNewOne(pos, MI_CARMINE, PICKUP_MINE_INACTIVE, 0); + return 0; + } + case COMMAND_DROP_NAUTICAL_MINE: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0); + return 0; + } + case COMMAND_IS_CHAR_MODEL: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(ScriptParams[1] == pPed->GetModelIndex()); + return 0; + } + case COMMAND_LOAD_SPECIAL_MODEL: + { + CollectParameters(&m_nIp, 1); + char name[KEY_LENGTH_IN_SCRIPT]; + strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + name[i] = tolower(name[i]); + CStreaming::RequestSpecialModel(ScriptParams[0], name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED); + m_nIp += KEY_LENGTH_IN_SCRIPT; + return 0; + } + case COMMAND_CREATE_CUTSCENE_HEAD: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]); + ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CUTSCENE_HEAD_ANIM: + { + CollectParameters(&m_nIp, 1); + CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pCutHead); + char name[KEY_LENGTH_IN_SCRIPT]; + strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CTimer::Stop(); + CCutsceneMgr::SetHeadAnim(name, pCutHead); + CTimer::Update(); + return 0; + } + case COMMAND_SIN: + CollectParameters(&m_nIp, 1); + *(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0])); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_COS: + CollectParameters(&m_nIp, 1); + *(float*)&ScriptParams[0] = Cos(DEGTORAD(*(float*)&ScriptParams[0])); + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_GET_CAR_FORWARD_X: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + float forwardX = pVehicle->GetForward().x / pVehicle->GetForward().Magnitude2D(); + *(float*)&ScriptParams[0] = forwardX; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_CAR_FORWARD_Y: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + float forwardY = pVehicle->GetForward().y / pVehicle->GetForward().Magnitude2D(); + *(float*)&ScriptParams[0] = forwardY; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_CHANGE_GARAGE_TYPE: + CollectParameters(&m_nIp, 2); + CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], 0); + return 0; + case COMMAND_ACTIVATE_CRUSHER_CRANE: + { + CollectParameters(&m_nIp, 10); + float infX = *(float*)&ScriptParams[2]; + float infY = *(float*)&ScriptParams[3]; + float supX = *(float*)&ScriptParams[4]; + float supY = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[4]; + supX = *(float*)&ScriptParams[2]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[5]; + supY = *(float*)&ScriptParams[3]; + } + CCranes::ActivateCrane(infX, supX, infY, supY, + *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8], + DEGTORAD(*(float*)&ScriptParams[9]), true, false, + *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); + return 0; + } + case COMMAND_PRINT_WITH_2_NUMBERS: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 4); + CMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_2_NUMBERS_NOW: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 4); + CMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_2_NUMBERS_SOON: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 4); + CMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_3_NUMBERS: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 5); + CMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_3_NUMBERS_NOW: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 5); + CMessages::AddMessageJumpQWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_3_NUMBERS_SOON: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 5); + CMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_4_NUMBERS: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 6); + CMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_4_NUMBERS_NOW: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 6); + CMessages::AddMessageJumpQWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_4_NUMBERS_SOON: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 6); + CMessages::AddMessageSoonWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_5_NUMBERS: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 7); + CMessages::AddMessageWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); + return 0; + } + case COMMAND_PRINT_WITH_5_NUMBERS_NOW: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 7); + CMessages::AddMessageJumpQWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); + return 0; + } + case COMMAND_PRINT_WITH_5_NUMBERS_SOON: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 7); + CMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); + return 0; + } + case COMMAND_PRINT_WITH_6_NUMBERS: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 8); + CMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); + return 0; + } + case COMMAND_PRINT_WITH_6_NUMBERS_NOW: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 8); + CMessages::AddMessageJumpQWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); + return 0; + } + case COMMAND_PRINT_WITH_6_NUMBERS_SOON: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 8); + CMessages::AddMessageSoonWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, pTargetPed); + pPed->SetFormation((eFormation)ScriptParams[2]); + return 0; + } + case COMMAND_PLAYER_MADE_PROGRESS: + CollectParameters(&m_nIp, 1); + CStats::ProgressMade += ScriptParams[0]; + return 0; + case COMMAND_SET_PROGRESS_TOTAL: + CollectParameters(&m_nIp, 1); + CStats::TotalProgressInGame = ScriptParams[0]; + return 0; + case COMMAND_REGISTER_JUMP_DISTANCE: + CollectParameters(&m_nIp, 1); + CStats::MaximumJumpDistance = Max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]); + return 0; + case COMMAND_REGISTER_JUMP_HEIGHT: + CollectParameters(&m_nIp, 1); + CStats::MaximumJumpHeight = Max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]); + return 0; + case COMMAND_REGISTER_JUMP_FLIPS: + CollectParameters(&m_nIp, 1); + CStats::MaximumJumpFlips = Max(CStats::MaximumJumpFlips, ScriptParams[0]); + return 0; + case COMMAND_REGISTER_JUMP_SPINS: + CollectParameters(&m_nIp, 1); + CStats::MaximumJumpSpins = Max(CStats::MaximumJumpSpins, ScriptParams[0]); + return 0; + case COMMAND_REGISTER_JUMP_STUNT: + CollectParameters(&m_nIp, 1); + CStats::BestStuntJump = Max(CStats::BestStuntJump, ScriptParams[0]); + return 0; + case COMMAND_REGISTER_UNIQUE_JUMP_FOUND: + ++CStats::NumberOfUniqueJumpsFound; + return 0; + case COMMAND_SET_UNIQUE_JUMPS_TOTAL: + CollectParameters(&m_nIp, 1); + CStats::TotalNumberOfUniqueJumps = ScriptParams[0]; + return 0; + case COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI: + ++CStats::PassengersDroppedOffWithTaxi; + return 0; + case COMMAND_REGISTER_MONEY_MADE_TAXI: + CollectParameters(&m_nIp, 1); + CStats::MoneyMadeWithTaxi += ScriptParams[0]; + return 0; + case COMMAND_REGISTER_MISSION_GIVEN: + ++CStats::MissionsGiven; + return 0; + case COMMAND_REGISTER_MISSION_PASSED: + { + char name[KEY_LENGTH_IN_SCRIPT]; + strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + m_nIp += KEY_LENGTH_IN_SCRIPT; + strncpy(CStats::LastMissionPassedName, name, KEY_LENGTH_IN_SCRIPT); + ++CStats::MissionsPassed; + CStats::CheckPointReachedSuccessfully(); + return 0; + } + case COMMAND_SET_CHAR_RUNNING: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bIsRunning = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_REMOVE_ALL_SCRIPT_FIRES: + gFireManager.RemoveAllScriptFires(); + return 0; + case COMMAND_IS_FIRST_CAR_COLOUR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->m_currentColour1 == ScriptParams[1]); + return 0; + } + case COMMAND_IS_SECOND_CAR_COLOUR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]); + return 0; + } + case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + if (!pPed) + printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n"); + UpdateCompareFlag(pPed && pPed->m_lastWepDam == ScriptParams[1]); + return 0; + } + case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + if (!pVehicle) + printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n"); + UpdateCompareFlag(pVehicle && pVehicle->m_nLastWeaponDamage == ScriptParams[1]); + return 0; + } + case COMMAND_IS_CHAR_IN_CHARS_GROUP: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pPed); + script_assert(pLeader); + UpdateCompareFlag(pPed->m_leader == pLeader); + return 0; + } + default: + script_assert(0); + } + return -1; +} diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp new file mode 100644 index 00000000..f5fb9781 --- /dev/null +++ b/src/control/Script4.cpp @@ -0,0 +1,2027 @@ +#include "common.h" + +#include "Script.h" +#include "ScriptCommands.h" + +#include "AnimBlendAssociation.h" +#include "BulletInfo.h" +#include "CarAI.h" +#include "CarCtrl.h" +#include "CivilianPed.h" +#include "Cranes.h" +#include "DMAudio.h" +#include "Darkel.h" +#include "Explosion.h" +#include "Fire.h" +#include "Frontend.h" +#include "Garages.h" +#include "General.h" +#include "Heli.h" +#include "Hud.h" +#include "Messages.h" +#include "ParticleObject.h" +#include "PedRoutes.h" +#include "Phones.h" +#include "Pickups.h" +#include "Plane.h" +#include "Pools.h" +#include "Population.h" +#include "Radar.h" +#include "Record.h" +#include "RpAnimBlend.h" +#include "Rubbish.h" +#include "SpecialFX.h" +#include "Stats.h" +#include "Streaming.h" +#include "TxdStore.h" +#include "User.h" +#include "WaterLevel.h" +#include "World.h" +#include "Zones.h" + +int8 CRunningScript::ProcessCommands800To899(int32 command) +{ + CMatrix tmp_matrix; + switch (command) { + case COMMAND_IS_CHAR_IN_PLAYERS_GROUP: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed; + script_assert(pPed); + script_assert(pLeader); + UpdateCompareFlag(pPed->m_leader == pLeader); + return 0; + } + case COMMAND_EXPLODE_CHAR_HEAD: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + if (pPed->m_nPedState == PED_DRIVING) { + pPed->SetDead(); + if (!pPed->IsPlayer()) + pPed->FlagToDestroyWhenNextProcessed(); + } + else if (CGame::nastyGame && pPed->IsPedInControl()) { + pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); + } + else { + pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + } + return 0; + } + case COMMAND_EXPLODE_PLAYER_HEAD: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + if (CGame::nastyGame) { + pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); + } + else { + pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + } + return 0; + } + case COMMAND_ANCHOR_BOAT: + { + 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); + return 0; + } + case COMMAND_SET_ZONE_GROUP: + { + char zone[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, zone); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CollectParameters(&m_nIp, 2); + int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone); + if (zone_id < 0) { + printf("Couldn't find zone - %s\n", zone); + return 0; + } + CTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]); + return 0; + } + case COMMAND_START_CAR_FIRE: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + ScriptParams[0] = gFireManager.StartScriptFire(pVehicle->GetPosition(), pVehicle, 0.8f, 1); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_START_CHAR_FIRE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + ScriptParams[0] = gFireManager.StartScriptFire(pPed->GetPosition(), pPed, 0.8f, 1); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA: + { + CollectParameters(&m_nIp, 5); + int handle = -1; + uint32 i = CPools::GetVehiclePool()->GetSize(); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float supX = *(float*)&ScriptParams[2]; + float supY = *(float*)&ScriptParams[3]; + while (i--) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (!pVehicle) + continue; + if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0) + continue; + if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE) + continue; + if (!pVehicle->IsWithinArea(infX, infY, supX, supY)) + continue; + handle = CPools::GetVehiclePool()->GetIndex(pVehicle); + pVehicle->VehicleCreatedBy = MISSION_VEHICLE; + ++CCarCtrl::NumMissionCars; + --CCarCtrl::NumRandomCars; + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR); + } + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE: + { + char zone[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, zone); + int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone); + if (zone_id != -1) + m_nIp += KEY_LENGTH_IN_SCRIPT; + CZone* pZone = CTheZones::GetZone(zone_id); + CollectParameters(&m_nIp, 1); + int handle = -1; + uint32 i = CPools::GetVehiclePool()->GetSize(); + while (i--) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (!pVehicle) + continue; + if (ScriptParams[0] != pVehicle->GetModelIndex() && ScriptParams[0] >= 0) + continue; + if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE) + continue; + if (!CTheZones::PointLiesWithinZone(&pVehicle->GetPosition(), pZone)) + continue; + handle = CPools::GetVehiclePool()->GetIndex(pVehicle); + pVehicle->VehicleCreatedBy = MISSION_VEHICLE; + ++CCarCtrl::NumMissionCars; + --CCarCtrl::NumRandomCars; + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(handle, CLEANUP_CAR); + } + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_HAS_RESPRAY_HAPPENED: + { + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CGarages::HasResprayHappened(ScriptParams[0])); + return 0; + } + case COMMAND_SET_CAMERA_ZOOM: + { + CollectParameters(&m_nIp, 1); + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED) + TheCamera.SetZoomValueFollowPedScript(ScriptParams[0]); + else if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING) + TheCamera.SetZoomValueCamStringScript(ScriptParams[0]); + return 0; + } + case COMMAND_CREATE_PICKUP_WITH_AMMO: + { + CollectParameters(&m_nIp, 6); + int16 model = ScriptParams[0]; + if (model < 0) + model = CTheScripts::UsedObjectArray[-model].index; + CVector pos = *(CVector*)&ScriptParams[3]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], ScriptParams[2]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CAR_RAM_CAR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CCarAI::TellCarToRamOtherCar(pVehicle, pTarget); + return 0; + } + case COMMAND_SET_CAR_BLOCK_CAR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CCarAI::TellCarToBlockOtherCar(pVehicle, pTarget); + return 0; + } + case COMMAND_SET_CHAR_OBJ_CATCH_TRAIN: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_CATCH_TRAIN); + return 0; + } + //case COMMAND_SET_COLL_OBJ_CATCH_TRAIN: + case COMMAND_SET_PLAYER_NEVER_GETS_TIRED: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; + pPlayer->m_bInfiniteSprint = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_PLAYER_FAST_RELOAD: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; + pPlayer->m_bFastReload = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_CHAR_BLEEDING: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bPedIsBleeding = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_CAR_FUNNY_SUSPENSION: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + // no action + return 0; + } + case COMMAND_SET_CAR_BIG_WHEELS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); + CAutomobile* pCar = (CAutomobile*)pVehicle; + pCar->bBigWheels = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_FREE_RESPRAYS: + CollectParameters(&m_nIp, 1); + CGarages::SetFreeResprays(ScriptParams[0] != 0); + return 0; + case COMMAND_SET_PLAYER_VISIBLE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + pPed->bIsVisible = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_CHAR_VISIBLE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bIsVisible = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_SET_CAR_VISIBLE: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bIsVisible = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_IS_AREA_OCCUPIED: + { + CollectParameters(&m_nIp, 11); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + int16 total; + CWorld::FindObjectsIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil, + !!ScriptParams[6], !!ScriptParams[7], !!ScriptParams[8], !!ScriptParams[9], !!ScriptParams[10]); + UpdateCompareFlag(total > 0); + return 0; + } + case COMMAND_START_DRUG_RUN: + CPlane::CreateIncomingCesna(); + return 0; + case COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED: + UpdateCompareFlag(CPlane::HasCesnaLanded()); + return 0; + case COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN: + UpdateCompareFlag(CPlane::HasCesnaBeenDestroyed()); + return 0; + case COMMAND_SAVE_PLAYER_FROM_FIRES: + CollectParameters(&m_nIp, 1); + gFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f); + return 0; + case COMMAND_DISPLAY_TEXT: + { + CollectParameters(&m_nIp, 2); + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0]; + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1]; + uint16 len = CMessages::GetWideStringLength(text); + for (uint16 i = 0; i < len; i++) + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = text[i]; + for (uint16 i = len; i < SCRIPT_TEXT_MAX_LENGTH; i++) + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = 0; + ++CTheScripts::NumberOfIntroTextLinesThisFrame; + return 0; + } + case COMMAND_SET_TEXT_SCALE: + { + CollectParameters(&m_nIp, 2); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleX = *(float*)&ScriptParams[0]; + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleY = *(float*)&ScriptParams[1]; + return 0; + } + case COMMAND_SET_TEXT_COLOUR: + { + CollectParameters(&m_nIp, 4); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sColor = + CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]); + return 0; + } + case COMMAND_SET_TEXT_JUSTIFY: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bJustify = (ScriptParams[0] != 0); + return 0; + } + case COMMAND_SET_TEXT_CENTRE: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bCentered = (ScriptParams[0] != 0); + return 0; + } + case COMMAND_SET_TEXT_WRAPX: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0]; + return 0; + } + case COMMAND_SET_TEXT_CENTRE_SIZE: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0]; + return 0; + } + case COMMAND_SET_TEXT_BACKGROUND: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0); + return 0; + } + case COMMAND_SET_TEXT_BACKGROUND_COLOUR: + { + CollectParameters(&m_nIp, 4); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sBackgroundColor = + CRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]); + return 0; + } + case COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0); + return 0; + } + case COMMAND_SET_TEXT_PROPORTIONAL: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0); + return 0; + } + case COMMAND_SET_TEXT_FONT: + { + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_nFont = ScriptParams[0]; + return 0; + } + case COMMAND_INDUSTRIAL_PASSED: + CStats::IndustrialPassed = true; + DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_COMMERCIAL_OPEN); + return 0; + case COMMAND_COMMERCIAL_PASSED: + CStats::CommercialPassed = true; + DMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_SUBURBAN_OPEN); + return 0; + case COMMAND_SUBURBAN_PASSED: + CStats::SuburbanPassed = true; + return 0; + case COMMAND_ROTATE_OBJECT: + { + CollectParameters(&m_nIp, 4); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + float heading = LimitAngleOnCircle( + RADTODEG(Atan2(-pObject->GetForward().x, pObject->GetForward().y))); + float headingTarget = *(float*)&ScriptParams[1]; +#ifdef FIX_BUGS + float rotateBy = *(float*)&ScriptParams[2] * CTimer::GetTimeStepFix(); +#else + float rotateBy = *(float*)&ScriptParams[2]; +#endif + if (headingTarget == heading) { // using direct comparasion here is fine + UpdateCompareFlag(true); + return 0; + } + float angleClockwise = LimitAngleOnCircle(headingTarget - heading); + float angleCounterclockwise = LimitAngleOnCircle(heading - headingTarget); + float newHeading; + if (angleClockwise < angleCounterclockwise) + newHeading = rotateBy < angleClockwise ? heading + rotateBy : headingTarget; + else + newHeading = rotateBy < angleCounterclockwise ? heading - rotateBy : headingTarget; + bool obstacleInPath = false; + if (ScriptParams[3]) { + CVector pos = pObject->GetPosition(); + tmp_matrix.SetRotateZ(DEGTORAD(newHeading)); + tmp_matrix.GetPosition() += pos; + CColModel* pColModel = pObject->GetColModel(); + CVector cp1 = tmp_matrix * pColModel->boundingBox.min; + CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z); + CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z); + CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z); + int16 collisions; + CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos, + Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))), + Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))), + Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))), + Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))), + &collisions, 2, nil, false, true, true, false, false); + if (collisions > 0) + obstacleInPath = true; + } + if (obstacleInPath) { + UpdateCompareFlag(true); + return 0; + } + pObject->SetHeading(DEGTORAD(newHeading)); + pObject->GetMatrix().UpdateRW(); + pObject->UpdateRwFrame(); + UpdateCompareFlag(newHeading == headingTarget); // using direct comparasion here is fine + return 0; + } + case COMMAND_SLIDE_OBJECT: + { + CollectParameters(&m_nIp, 8); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CVector pos = pObject->GetPosition(); + CVector posTarget = *(CVector*)&ScriptParams[1]; +#ifdef FIX_BUGS + CVector slideBy = *(CVector*)&ScriptParams[4] * CTimer::GetTimeStepFix(); +#else + CVector slideBy = *(CVector*)&ScriptParams[4]; +#endif + if (posTarget == pos) { // using direct comparasion here is fine + UpdateCompareFlag(true); + return 0; + } + CVector posDiff = pos - posTarget; + CVector newPosition; + if (posDiff.x < 0) + newPosition.x = -posDiff.x < slideBy.x ? posTarget.x : pos.x + slideBy.x; + else + newPosition.x = posDiff.x < slideBy.x ? posTarget.x : pos.x - slideBy.x; + if (posDiff.y < 0) + newPosition.y = -posDiff.y < slideBy.y ? posTarget.y : pos.y + slideBy.y; + else + newPosition.y = posDiff.y < slideBy.y ? posTarget.y : pos.y - slideBy.y; + if (posDiff.z < 0) + newPosition.z = -posDiff.z < slideBy.z ? posTarget.z : pos.z + slideBy.z; + else + newPosition.z = posDiff.z < slideBy.z ? posTarget.z : pos.z - slideBy.z; + bool obstacleInPath = false; + if (ScriptParams[7]) { + tmp_matrix = pObject->GetMatrix(); + tmp_matrix.GetPosition() = newPosition; + CColModel* pColModel = pObject->GetColModel(); + CVector cp1 = tmp_matrix * pColModel->boundingBox.min; + CVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z); + CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z); + CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z); + int16 collisions; + CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, newPosition, + Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))), + Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))), + Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))), + Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))), + &collisions, 2, nil, false, true, true, false, false); + if (collisions > 0) + obstacleInPath = true; + } + if (obstacleInPath) { + UpdateCompareFlag(true); + return 0; + } + pObject->Teleport(newPosition); + UpdateCompareFlag(newPosition == posTarget); // using direct comparasion here is fine + return 0; + } + case COMMAND_REMOVE_CHAR_ELEGANTLY: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + if (pPed && pPed->CharCreatedBy == MISSION_CHAR){ + CWorld::RemoveReferencesToDeletedObject(pPed); + if (pPed->bInVehicle){ + if (pPed->m_pMyVehicle){ + if (pPed == pPed->m_pMyVehicle->pDriver){ + pPed->m_pMyVehicle->RemoveDriver(); + pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); + if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) + pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED; + if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle()) + pPed->m_pMyVehicle->ChangeLawEnforcerState(0); + }else{ + pPed->m_pMyVehicle->RemovePassenger(pPed); + } + } + delete pPed; + --CPopulation::ms_nTotalMissionPeds; + }else{ + pPed->CharCreatedBy = RANDOM_CHAR; + pPed->bRespondsToThreats = true; + pPed->bScriptObjectiveCompleted = false; + pPed->ClearLeader(); + --CPopulation::ms_nTotalMissionPeds; + pPed->bFadeOut = true; + } + } + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR); + return 0; + } + case COMMAND_SET_CHAR_STAY_IN_SAME_PLACE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bKindaStayInSamePlace = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_IS_NASTY_GAME: + UpdateCompareFlag(CGame::nastyGame); + return 0; + case COMMAND_UNDRESS_CHAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + char name[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, name); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + name[i] = tolower(name[i]); + int mi = pPed->GetModelIndex(); + pPed->DeleteRwObject(); + if (pPed->IsPlayer()) + mi = 0; + CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CWorld::Remove(pPed); + return 0; + } + case COMMAND_DRESS_CHAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + int mi = pPed->GetModelIndex(); + pPed->m_modelIndex = -1; + pPed->SetModelIndex(mi); + CWorld::Add(pPed); + return 0; + } + case COMMAND_START_CHASE_SCENE: + CollectParameters(&m_nIp, 1); + CTimer::Suspend(); + CStreaming::DeleteAllRwObjects(); + CRecordDataForChase::StartChaseScene(*(float*)&ScriptParams[0]); + CTimer::Resume(); + return 0; + case COMMAND_STOP_CHASE_SCENE: + CRecordDataForChase::CleanUpChaseScene(); + return 0; + case COMMAND_IS_EXPLOSION_IN_AREA: + { + CollectParameters(&m_nIp, 7); + float infX = *(float*)&ScriptParams[1]; + float infY = *(float*)&ScriptParams[2]; + float infZ = *(float*)&ScriptParams[3]; + float supX = *(float*)&ScriptParams[4]; + float supY = *(float*)&ScriptParams[5]; + float supZ = *(float*)&ScriptParams[6]; + if (infX > supX) { + infX = *(float*)&ScriptParams[4]; + supX = *(float*)&ScriptParams[1]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[5]; + supY = *(float*)&ScriptParams[2]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[6]; + supZ = *(float*)&ScriptParams[3]; + } + UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0], + infX, supX, infY, supY, infZ, supZ)); + return 0; + } + case COMMAND_IS_EXPLOSION_IN_ZONE: + { + CollectParameters(&m_nIp, 1); + char zone[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, zone); + int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone); + if (zone_id != -1) + m_nIp += KEY_LENGTH_IN_SCRIPT; + CZone* pZone = CTheZones::GetZone(zone_id); + UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0], + pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz)); + return 0; + } + case COMMAND_START_DRUG_DROP_OFF: + CPlane::CreateDropOffCesna(); + return 0; + case COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN: + UpdateCompareFlag(CPlane::HasDropOffCesnaBeenShotDown()); + return 0; + case COMMAND_FIND_DROP_OFF_PLANE_COORDINATES: + { + CVector pos = CPlane::FindDropOffCesnaCoordinates(); + *(CVector*)&ScriptParams[0] = pos; + StoreParameters(&m_nIp, 3); + return 0; + } + case COMMAND_CREATE_FLOATING_PACKAGE: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR: + { + CollectParameters(&m_nIp, 5); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pVehicle); + CVector offset = *(CVector*)&ScriptParams[2]; + CPhysical::PlacePhysicalRelativeToOtherPhysical(pVehicle, pObject, offset); + return 0; + } + case COMMAND_MAKE_OBJECT_TARGETTABLE: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CPlayerPed* pPlayerPed = CWorld::Players[CWorld::PlayerInFocus].m_pPed; + script_assert(pPlayerPed); + pPlayerPed->MakeObjectTargettable(ScriptParams[0]); + return 0; + } + case COMMAND_ADD_ARMOUR_TO_PLAYER: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPlayerPed); + pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f); + return 0; + } + case COMMAND_ADD_ARMOUR_TO_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->m_fArmour = clamp(pPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f); + return 0; + } + case COMMAND_OPEN_GARAGE: + { + CollectParameters(&m_nIp, 1); + CGarages::OpenGarage(ScriptParams[0]); + return 0; + } + case COMMAND_CLOSE_GARAGE: + { + CollectParameters(&m_nIp, 1); + CGarages::CloseGarage(ScriptParams[0]); + return 0; + } + case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD: + { + CollectParameters(&m_nIp, 4); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + if (pPed->bInVehicle){ + if (pPed->m_pMyVehicle->bIsBus) + pPed->bRenderPedInCar = true; + if (pPed->m_pMyVehicle->pDriver == pPed){ + pPed->m_pMyVehicle->RemoveDriver(); + pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); + pPed->m_pMyVehicle->bEngineOn = false; + pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + }else{ + pPed->m_pMyVehicle->RemovePassenger(pPed); + } + pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f); + pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f); + } + pPed->bInVehicle = false; + pPed->m_pMyVehicle = nil; + pPed->SetPedState(PED_IDLE); + pPed->m_nLastPedState = PED_NONE; + pPed->bUsesCollision = true; + pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); + pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId); + pPed->RemoveInCarAnims(); + if (pPed->m_pVehicleAnim) + pPed->m_pVehicleAnim->blendDelta = -1000.0f; + pPed->m_pVehicleAnim = nil; + pPed->RestartNonPartialAnims(); + pPed->SetMoveState(PEDMOVE_NONE); + CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f); + pos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel(); + pPed->Teleport(pos); + CTheScripts::ClearSpaceForMissionEntity(pos, pPed); + return 0; + } + case COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE: + { + CollectParameters(&m_nIp, 6); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float range = *(float*)&ScriptParams[3]; + int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4]; + int16 total; + CEntity* apEntities[16]; + CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, true, false, false, true, true); + if (total == 0) + CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, range, true, &total, 16, apEntities); + if (total == 0) + CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities); + CEntity* pClosestEntity = nil; + float min_dist = 2.0f * range; + for (int i = 0; i < total; i++) { + float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); + if (dist < min_dist) { + min_dist = dist; + pClosestEntity = apEntities[i]; + } + } + if (pClosestEntity) { + pClosestEntity->bIsVisible = (ScriptParams[5] != 0); + CTheScripts::AddToInvisibilitySwapArray(pClosestEntity, ScriptParams[5] != 0); + } + return 0; + } + case COMMAND_HAS_CHAR_SPOTTED_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + UpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget)); + return 0; + } + case COMMAND_SET_CHAR_OBJ_HAIL_TAXI: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_HAIL_TAXI); + return 0; + } + case COMMAND_HAS_OBJECT_BEEN_DAMAGED: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + UpdateCompareFlag(pObject->bRenderDamaged || !pObject->bIsVisible); + return 0; + } + case COMMAND_START_KILL_FRENZY_HEADSHOT: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 8); + CDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2], + ScriptParams[3], text, ScriptParams[4], ScriptParams[5], + ScriptParams[6], ScriptParams[7] != 0, true); + return 0; + } + case COMMAND_ACTIVATE_MILITARY_CRANE: + { + CollectParameters(&m_nIp, 10); + float infX = *(float*)&ScriptParams[2]; + float infY = *(float*)&ScriptParams[3]; + float supX = *(float*)&ScriptParams[4]; + float supY = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[4]; + supX = *(float*)&ScriptParams[2]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[5]; + supY = *(float*)&ScriptParams[3]; + } + CCranes::ActivateCrane(infX, supX, infY, supY, + *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8], + DEGTORAD(*(float*)&ScriptParams[9]), false, true, + *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); + return 0; + } + case COMMAND_WARP_PLAYER_INTO_CAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pVehicle); + pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle); + pPed->WarpPedIntoCar(pVehicle); + return 0; + } + case COMMAND_WARP_CHAR_INTO_CAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pVehicle); + pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle); + pPed->WarpPedIntoCar(pVehicle); + return 0; + } + //case COMMAND_SWITCH_CAR_RADIO: + //case COMMAND_SET_AUDIO_STREAM: + case COMMAND_PRINT_WITH_2_NUMBERS_BIG: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 4); + CMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_3_NUMBERS_BIG: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 5); + CMessages::AddBigMessageWithNumber(text, ScriptParams[3], ScriptParams[4] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_4_NUMBERS_BIG: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 6); + CMessages::AddBigMessageWithNumber(text, ScriptParams[4], ScriptParams[5] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); + return 0; + } + case COMMAND_PRINT_WITH_5_NUMBERS_BIG: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 7); + CMessages::AddBigMessageWithNumber(text, ScriptParams[5], ScriptParams[6] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); + return 0; + } + case COMMAND_PRINT_WITH_6_NUMBERS_BIG: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 8); + CMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); + return 0; + } + case COMMAND_SET_CHAR_WAIT_STATE: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->SetWaitState((eWaitState)ScriptParams[1], ScriptParams[2] >= 0 ? &ScriptParams[2] : nil); + return 0; + } + case COMMAND_SET_CAMERA_BEHIND_PLAYER: + TheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString(); + return 0; + case COMMAND_SET_MOTION_BLUR: + CollectParameters(&m_nIp, 1); + TheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]); + return 0; + case COMMAND_PRINT_STRING_IN_STRING: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* string = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 2); + CMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string); + return 0; + } + case COMMAND_CREATE_RANDOM_CHAR: + { + CollectParameters(&m_nIp, 3); + CZoneInfo zoneinfo; + CTheZones::GetZoneInfoForTimeOfDay(&CWorld::Players[CWorld::PlayerInFocus].GetPos(), &zoneinfo); + int mi; + ePedType pedtype = PEDTYPE_COP; + int attempt = 0; + while (pedtype != PEDTYPE_CIVMALE && pedtype != PEDTYPE_CIVFEMALE && attempt < 5) { + mi = CPopulation::ChooseCivilianOccupation(zoneinfo.pedGroup); + if (CModelInfo::GetModelInfo(mi)->GetRwObject()) + pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType; + attempt++; + } + if (!CModelInfo::GetModelInfo(mi)->GetRwObject()) { + mi = MI_MALE01; + pedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType; + } + CPed* ped = new CCivilianPed(pedtype, mi); + ped->CharCreatedBy = MISSION_CHAR; + ped->bRespondsToThreats = false; + ped->bAllowMedicsToReviveMe = false; + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pos.z += 1.0f; + ped->SetPosition(pos); + ped->SetOrientation(0.0f, 0.0f, 0.0f); + CTheScripts::ClearSpaceForMissionEntity(pos, ped); + CWorld::Add(ped); + ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); + CPopulation::ms_nTotalMissionPeds++; + ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped); + StoreParameters(&m_nIp, 1); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR); + return 0; + } + case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR); + return 0; + } + case COMMAND_SET_2_REPEATED_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, nil, nil, nil, nil); + return 0; + } + case COMMAND_SET_2_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, nil, nil, nil, nil); + return 0; + } + case COMMAND_SET_3_REPEATED_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, nil, nil, nil); + return 0; + } + case COMMAND_SET_3_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, nil, nil, nil); + return 0; + } + case COMMAND_SET_4_REPEATED_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, nil, nil); + return 0; + } + case COMMAND_SET_4_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil); + return 0; + } + case COMMAND_IS_SNIPER_BULLET_IN_AREA: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + UpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ)); + return 0; + } + case COMMAND_GIVE_PLAYER_DETONATOR: + CGarages::GivePlayerDetonator(); + return 0; + //case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR: + case COMMAND_SET_OBJECT_VELOCITY: + { + CollectParameters(&m_nIp, 4); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + pObject->SetMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED); + return 0; + } + case COMMAND_SET_OBJECT_COLLISION: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + pObject->bUsesCollision = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_IS_ICECREAM_JINGLE_ON: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + // Adding this check to correspond to command name. + // All original game scripts always assume that the vehicle is actually Mr. Whoopee, + // but maybe there are mods that use it as "is alarm activated"? + script_assert(pVehicle->GetModelIndex() == MI_MRWHOOP); + UpdateCompareFlag(pVehicle->m_bSirenOrAlarm); + return 0; + } + default: + script_assert(0); + } + return -1; +} + +int8 CRunningScript::ProcessCommands900To999(int32 command) +{ + char str[52]; + char onscreen_str[KEY_LENGTH_IN_SCRIPT]; + switch (command) { + case COMMAND_PRINT_STRING_IN_STRING_NOW: + { + wchar* source = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* pstr = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 2); + CMessages::AddMessageJumpQWithString(source, ScriptParams[0], ScriptParams[1], pstr); + return 0; + } + //case COMMAND_PRINT_STRING_IN_STRING_SOON: + case COMMAND_SET_5_REPEATED_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, nil); + return 0; + } + case COMMAND_SET_5_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, nil); + return 0; + } + case COMMAND_SET_6_REPEATED_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, text6); + return 0; + } + case COMMAND_SET_6_PHONE_MESSAGES: + { + CollectParameters(&m_nIp, 1); + wchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + wchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp); + gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6); + return 0; + } + case COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0] - *(float*)&ScriptParams[3]; + float supX = *(float*)&ScriptParams[0] + *(float*)&ScriptParams[3]; + float infY = *(float*)&ScriptParams[1] - *(float*)&ScriptParams[4]; + float supY = *(float*)&ScriptParams[1] + *(float*)&ScriptParams[4]; + float infZ = *(float*)&ScriptParams[2] - *(float*)&ScriptParams[5]; + float supZ = *(float*)&ScriptParams[2] + *(float*)&ScriptParams[5]; + if (infX > supX) { + float tmp = infX; + infX = supX; + supX = tmp; + } + if (infY > supY) { + float tmp = infY; + infY = supY; + supY = tmp; + } + if (infZ > supZ) { + float tmp = infZ; + infZ = supZ; + supZ = tmp; + } + int16 total; + CWorld::FindMissionEntitiesIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil, true, true, true); + UpdateCompareFlag(total > 0); + return 0; + } + case COMMAND_LOAD_ALL_MODELS_NOW: + CTimer::Stop(); + CStreaming::LoadAllRequestedModels(false); + CTimer::Update(); + return 0; + case COMMAND_ADD_TO_OBJECT_VELOCITY: + { + CollectParameters(&m_nIp, 4); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + pObject->SetMoveSpeed(pObject->GetMoveSpeed() + METERS_PER_SECOND_TO_GAME_SPEED * *(CVector*)&ScriptParams[1]); + return 0; + } + case COMMAND_DRAW_SPRITE: + { + CollectParameters(&m_nIp, 9); + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true; + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = ScriptParams[0] - 1; + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect( + *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3], *(float*)&ScriptParams[2] + *(float*)&ScriptParams[4]); + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]); + CTheScripts::NumberOfIntroRectanglesThisFrame++; + return 0; + } + case COMMAND_DRAW_RECT: + { + CollectParameters(&m_nIp, 8); + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true; + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = -1; + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect( + *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[0] + *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3]); + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7]); + CTheScripts::NumberOfIntroRectanglesThisFrame++; + return 0; + } + case COMMAND_LOAD_SPRITE: + { + CollectParameters(&m_nIp, 1); + strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + str[i] = tolower(str[i]); + m_nIp += KEY_LENGTH_IN_SCRIPT; + int slot = CTxdStore::FindTxdSlot("script"); + CTxdStore::PushCurrentTxd(); + CTxdStore::SetCurrentTxd(slot); + CTheScripts::ScriptSprites[ScriptParams[0] - 1].SetTexture(str); + CTxdStore::PopCurrentTxd(); + return 0; + } + case COMMAND_LOAD_TEXTURE_DICTIONARY: + { + strcpy(str, "models\\"); + strncpy(str + sizeof("models\\"), (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + strcat(str, ".txd"); + m_nIp += KEY_LENGTH_IN_SCRIPT; + int slot = CTxdStore::FindTxdSlot("script"); + if (slot == -1) + slot = CTxdStore::AddTxdSlot("script"); + CTxdStore::LoadTxd(slot, str); + CTxdStore::AddRef(slot); + return 0; + } + case COMMAND_REMOVE_TEXTURE_DICTIONARY: + { + for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++) + CTheScripts::ScriptSprites[i].Delete(); + CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script")); + return 0; + } + case COMMAND_SET_OBJECT_DYNAMIC: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + if (ScriptParams[1]) { + if (pObject->bIsStatic) { + pObject->SetIsStatic(false); + pObject->AddToMovingList(); + } + } + else { + if (!pObject->bIsStatic) { + pObject->SetIsStatic(true); + pObject->RemoveFromMovingList(); + } + } + return 0; + } + case COMMAND_SET_CHAR_ANIM_SPEED: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetFirstAssociation(pPed->GetClump()); + if (pAssoc) + pAssoc->speed = *(float*)&ScriptParams[1]; + return 0; + } + case COMMAND_PLAY_MISSION_PASSED_TUNE: + { + CollectParameters(&m_nIp, 1); + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.PlayFrontEndTrack(ScriptParams[0] + STREAMED_SOUND_MISSION_COMPLETED - 1, 0); + return 0; + } + case COMMAND_CLEAR_AREA: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CWorld::ClearExcitingStuffFromArea(pos, *(float*)&ScriptParams[3], ScriptParams[4]); + return 0; + } + case COMMAND_FREEZE_ONSCREEN_TIMER: + CollectParameters(&m_nIp, 1); + CUserDisplay::OnscnTimer.m_bDisabled = ScriptParams[0] != 0; + return 0; + case COMMAND_SWITCH_CAR_SIREN: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->m_bSirenOrAlarm = ScriptParams[1] != 0; + return 0; + } + case COMMAND_SWITCH_PED_ROADS_ON_ANGLED: + { + CollectParameters(&m_nIp, 7); + ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], + *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 1); + return 0; + } + case COMMAND_SWITCH_PED_ROADS_OFF_ANGLED: + CollectParameters(&m_nIp, 7); + ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], + *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 0); + return 0; + case COMMAND_SWITCH_ROADS_ON_ANGLED: + CollectParameters(&m_nIp, 7); + ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], + *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 1); + return 0; + case COMMAND_SWITCH_ROADS_OFF_ANGLED: + CollectParameters(&m_nIp, 7); + ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], + *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 0); + return 0; + case COMMAND_SET_CAR_WATERTIGHT: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); + CAutomobile* pCar = (CAutomobile*)pVehicle; + pCar->bWaterTight = ScriptParams[1] != 0; + return 0; + } + case COMMAND_ADD_MOVING_PARTICLE_EFFECT: + { + CollectParameters(&m_nIp, 12); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float size = Max(0.0f, *(float*)&ScriptParams[7]); + eParticleObjectType type = (eParticleObjectType)ScriptParams[0]; + RwRGBA color; + if (type == POBJECT_SMOKE_TRAIL){ + color.alpha = -1; + color.red = ScriptParams[8]; + color.green = ScriptParams[9]; + color.blue = ScriptParams[10]; + }else{ + color.alpha = color.red = color.blue = color.green = 0; + } + CVector target = *(CVector*)&ScriptParams[4]; + CParticleObject::AddObject(type, pos, target, size, ScriptParams[11], color, 1); + return 0; + } + case COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bDontDragMeOutCar = ScriptParams[1] != 0; + return 0; + } + case COMMAND_TURN_CAR_TO_FACE_COORD: + { + CollectParameters(&m_nIp, 3); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + const CVector& pos = pVehicle->GetPosition(); + float heading = CGeneral::GetATanOfXY(pos.y - *(float*)&ScriptParams[2], pos.x - *(float*)&ScriptParams[1]) + HALFPI; + if (heading > TWOPI) + heading -= TWOPI; + pVehicle->SetHeading(heading); + return 0; + } + case COMMAND_IS_CRANE_LIFTING_CAR: + { + CollectParameters(&m_nIp, 3); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[2]); + UpdateCompareFlag(CCranes::IsThisCarPickedUp(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], pVehicle)); + return 0; + } + case COMMAND_DRAW_SPHERE: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + C3dMarkers::PlaceMarkerSet((uintptr)this + m_nIp, MARKERTYPE_CYLINDER, pos, *(float*)&ScriptParams[3], + SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, + SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0); + return 0; + } + case COMMAND_SET_CAR_STATUS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->SetStatus((eEntityStatus)ScriptParams[1]); + return 0; + } + case COMMAND_IS_CHAR_MALE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(pPed->m_nPedType != PEDTYPE_CIVFEMALE && pPed->m_nPedType != PEDTYPE_PROSTITUTE); + return 0; + } + case COMMAND_SCRIPT_NAME: + { + strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + str[i] = tolower(str[i]); + m_nIp += KEY_LENGTH_IN_SCRIPT; + strncpy(m_abScriptName, str, KEY_LENGTH_IN_SCRIPT); + return 0; + } + case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL: + { + CollectParameters(&m_nIp, 3); + CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], ScriptParams[2]); + return 0; + } + case COMMAND_FIND_DRUG_PLANE_COORDINATES: + *(CVector*)&ScriptParams[0] = CPlane::FindDrugPlaneCoordinates(); + StoreParameters(&m_nIp, 3); + return 0; + case COMMAND_SAVE_INT_TO_DEBUG_FILE: + // TODO: implement something here + CollectParameters(&m_nIp, 1); + return 0; + case COMMAND_SAVE_FLOAT_TO_DEBUG_FILE: + CollectParameters(&m_nIp, 1); + return 0; + case COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE: + return 0; + case COMMAND_POLICE_RADIO_MESSAGE: + CollectParameters(&m_nIp, 3); + DMAudio.PlaySuspectLastSeen(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]); + return 0; + case COMMAND_SET_CAR_STRONG: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bTakeLessDamage = ScriptParams[1] != 0; + return 0; + } + case COMMAND_REMOVE_ROUTE: + CollectParameters(&m_nIp, 1); + CRouteNode::RemoveRoute(ScriptParams[0]); + return 0; + case COMMAND_SWITCH_RUBBISH: + CollectParameters(&m_nIp, 1); + CRubbish::SetVisibility(ScriptParams[0] != 0);; + return 0; + case COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA: + { + CollectParameters(&m_nIp, 6); + float x1 = *(float*)&ScriptParams[0]; + float y1 = *(float*)&ScriptParams[1]; + float z1 = *(float*)&ScriptParams[2]; + float x2 = *(float*)&ScriptParams[3]; + float y2 = *(float*)&ScriptParams[4]; + float z2 = *(float*)&ScriptParams[5]; + CParticleObject* tmp = CParticleObject::pCloseListHead; + while (tmp) { + CParticleObject* next = tmp->m_pNext; + if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2)) + tmp->RemoveObject(); + tmp = next; + } + tmp = CParticleObject::pFarListHead; + while (tmp) { + CParticleObject* next = tmp->m_pNext; + if (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2)) + tmp->RemoveObject(); + tmp = next; + } + return 0; + } + case COMMAND_SWITCH_STREAMING: + CollectParameters(&m_nIp, 1); + CStreaming::ms_disableStreaming = ScriptParams[0] == 0; + return 0; + case COMMAND_IS_GARAGE_OPEN: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CGarages::IsGarageOpen(ScriptParams[0])); + return 0; + case COMMAND_IS_GARAGE_CLOSED: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CGarages::IsGarageClosed(ScriptParams[0])); + return 0; + case COMMAND_START_CATALINA_HELI: + CHeli::StartCatalinaFlyBy(); + return 0; + case COMMAND_CATALINA_HELI_TAKE_OFF: + CHeli::CatalinaTakeOff(); + return 0; + case COMMAND_REMOVE_CATALINA_HELI: + CHeli::RemoveCatalinaHeli(); + return 0; + case COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN: + UpdateCompareFlag(CHeli::HasCatalinaBeenShotDown()); + return 0; + case COMMAND_SWAP_NEAREST_BUILDING_MODEL: + { + CollectParameters(&m_nIp, 6); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float radius = *(float*)&ScriptParams[3]; + int mi1 = ScriptParams[4] >= 0 ? ScriptParams[4] : CTheScripts::UsedObjectArray[-ScriptParams[4]].index; + int mi2 = ScriptParams[5] >= 0 ? ScriptParams[5] : CTheScripts::UsedObjectArray[-ScriptParams[5]].index; + int16 total; + CEntity* apEntities[16]; + CWorld::FindObjectsOfTypeInRange(mi1, pos, radius, true, &total, 16, apEntities, true, false, false, false, false); + if (total == 0) + CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, radius, true, &total, 16, apEntities); + if (total == 0) + CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities); + CEntity* pClosestEntity = nil; + float min_dist = 2.0f * radius; + for (int i = 0; i < total; i++) { + float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); + if (dist < min_dist) { + min_dist = dist; + pClosestEntity = apEntities[i]; + } + } + if (!pClosestEntity) { + printf("Failed to find building\n"); + return 0; + } + CBuilding* pReplacedBuilding = ((CBuilding*)pClosestEntity); + pReplacedBuilding->ReplaceWithNewModel(mi2); + CTheScripts::AddToBuildingSwapArray(pReplacedBuilding, mi1, mi2); + return 0; + } + case COMMAND_SWITCH_WORLD_PROCESSING: + CollectParameters(&m_nIp, 1); + CWorld::bProcessCutsceneOnly = ScriptParams[0] == 0; + return 0; + case COMMAND_REMOVE_ALL_PLAYER_WEAPONS: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + pPed->ClearWeapons(); + return 0; + } + case COMMAND_GRAB_CATALINA_HELI: + { + CHeli* pHeli = CHeli::FindPointerToCatalinasHeli(); + ScriptParams[0] = pHeli ? CPools::GetVehiclePool()->GetIndex(pHeli) : -1; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_CLEAR_AREA_OF_CARS: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + CWorld::ClearCarsFromArea(infX, infY, infZ, supX, supY, supZ); + return 0; + } + case COMMAND_SET_ROTATING_GARAGE_DOOR: + CollectParameters(&m_nIp, 1); + CGarages::SetGarageDoorToRotate(ScriptParams[0]); + return 0; + case COMMAND_ADD_SPHERE: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float radius = *(float*)&ScriptParams[3]; + CTheScripts::GetActualScriptSphereIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CTheScripts::AddScriptSphere((uintptr)this + m_nIp, pos, radius); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_REMOVE_SPHERE: + CollectParameters(&m_nIp, 1); + CTheScripts::RemoveScriptSphere(ScriptParams[0]); + return 0; + case COMMAND_CATALINA_HELI_FLY_AWAY: + CHeli::MakeCatalinaHeliFlyAway(); + return 0; + case COMMAND_SET_EVERYONE_IGNORE_PLAYER: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + if (ScriptParams[1]) { + pPed->m_pWanted->m_bIgnoredByEveryone = true; + CWorld::StopAllLawEnforcersInTheirTracks(); + } + else { + pPed->m_pWanted->m_bIgnoredByEveryone = false; + } + return 0; + } + case COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil; + ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil; + ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_IS_PHONE_DISPLAYING_MESSAGE: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(gPhoneInfo.IsMessageBeingDisplayed(ScriptParams[0])); + return 0; + case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING: + { + script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR); + uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp); + wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ??? + strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CUserDisplay::OnscnTimer.AddClock(var, onscreen_str); + return 0; + } + case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING: + { + script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR); + uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp); + CollectParameters(&m_nIp, 1); + wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ??? + strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str); + return 0; + } + case COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK: + { + CollectParameters(&m_nIp, 4); + if (CCarCtrl::NumRandomCars >= 30) + return 0; + int attempts; + int model = -1; + int index = CGeneral::GetRandomNumberInRange(0, 50); + for (attempts = 0; attempts < 50; attempts++) { + if (model != -1) + break; + model = CStreaming::ms_vehiclesLoaded[index]; + if (model == -1) + continue; + // desperatly want to believe this was inlined :| + CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(model); + script_assert(pInfo->GetModelType() == MITYPE_VEHICLE); + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo; + if (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR) { + switch (model) { + case MI_LANDSTAL: + case MI_LINERUN: + case MI_FIRETRUCK: + case MI_TRASH: + case MI_STRETCH: + case MI_MULE: + case MI_AMBULAN: + case MI_FBICAR: + case MI_MRWHOOP: + case MI_BFINJECT: + case MI_CORPSE: + case MI_POLICE: + case MI_ENFORCER: + case MI_SECURICA: + case MI_PREDATOR: + case MI_BUS: + case MI_RHINO: + case MI_BARRACKS: + case MI_TRAIN: + case MI_CHOPPER: + case MI_DODO: + case MI_COACH: + case MI_RCBANDIT: + case MI_BELLYUP: + case MI_MRWONGS: + case MI_MAFIA: + case MI_YARDIE: + case MI_YAKUZA: + case MI_DIABLOS: + case MI_COLUMB: + case MI_HOODS: + case MI_AIRTRAIN: + case MI_DEADDODO: + case MI_SPEEDER: + case MI_REEFER: + case MI_PANLANT: + case MI_FLATBED: + case MI_YANKEE: + case MI_ESCAPE: + case MI_BORGNINE: + case MI_TOYZ: + case MI_GHOST: + case MI_MIAMI_RCBARON: + case MI_MIAMI_RCRAIDER: + model = -1; + break; + case MI_IDAHO: + case MI_STINGER: + case MI_PEREN: + case MI_SENTINEL: + case MI_PATRIOT: + case MI_MANANA: + case MI_INFERNUS: + case MI_BLISTA: + case MI_PONY: + case MI_CHEETAH: + case MI_MOONBEAM: + case MI_ESPERANT: + case MI_TAXI: + case MI_KURUMA: + case MI_BOBCAT: + case MI_BANSHEE: + case MI_CABBIE: + case MI_STALLION: + case MI_RUMPO: + case 151: + case 152: + case 153: + break; + default: + printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]); + model = -1; + break; + } + } + else + model = -1; + if (++index >= 50) + index = 0; + } + if (model == -1) + return 0; + CVehicle* car; + if (!CModelInfo::IsBikeModel(model)) + car = new CAutomobile(model, RANDOM_VEHICLE); + CVector pos = *(CVector*)&ScriptParams[0]; + pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel(); + car->SetPosition(pos); + car->SetHeading(DEGTORAD(*(float*)&ScriptParams[3])); + CTheScripts::ClearSpaceForMissionEntity(pos, car); + car->SetStatus(STATUS_ABANDONED); + car->bIsLocked = false; + car->bIsCarParkVehicle = true; + CCarCtrl::JoinCarWithRoadSystem(car); + car->AutoPilot.m_nCarMission = MISSION_NONE; + car->AutoPilot.m_nTempAction = TEMPACT_NONE; + car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; + car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f; + car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0; + car->bEngineOn = false; + car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); + CWorld::Add(car); + return 0; + } + case COMMAND_IS_COLLISION_IN_MEMORY: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CCollision::ms_collisionInMemory == ScriptParams[0]); + return 0; + case COMMAND_SET_WANTED_MULTIPLIER: + CollectParameters(&m_nIp, 1); + FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = *(float*)&ScriptParams[0]; + return 0; + case COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER: + TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString(); + return 0; + case COMMAND_IS_CAR_VISIBLY_DAMAGED: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(pVehicle->bIsDamaged); + return 0; + } + case COMMAND_DOES_OBJECT_EXIST: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CPools::GetObjectPool()->GetAt(ScriptParams[0])); + return 0; + case COMMAND_LOAD_SCENE: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + CTimer::Stop(); + CStreaming::LoadScene(pos); + CTimer::Update(); + return 0; + } + case COMMAND_ADD_STUCK_CAR_CHECK: + { + CollectParameters(&m_nIp, 3); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CTheScripts::StuckCars.AddCarToCheck(ScriptParams[0], *(float*)&ScriptParams[1], ScriptParams[2]); + return 0; + } + case COMMAND_REMOVE_STUCK_CAR_CHECK: + { + CollectParameters(&m_nIp, 1); + CTheScripts::StuckCars.RemoveCarFromCheck(ScriptParams[0]); + return 0; + } + case COMMAND_IS_CAR_STUCK: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CTheScripts::StuckCars.HasCarBeenStuckForAWhile(ScriptParams[0])); + return 0; + case COMMAND_LOAD_MISSION_AUDIO: + strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + str[i] = tolower(str[i]); + m_nIp += KEY_LENGTH_IN_SCRIPT; + DMAudio.PreloadMissionAudio(str); + return 0; + case COMMAND_HAS_MISSION_AUDIO_LOADED: + UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1); + return 0; + case COMMAND_PLAY_MISSION_AUDIO: + DMAudio.PlayLoadedMissionAudio(); + return 0; + case COMMAND_HAS_MISSION_AUDIO_FINISHED: + UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished()); + return 0; + case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); + *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition(); + *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node); + StoreParameters(&m_nIp, 4); + return 0; + } + case COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED: + { + CollectParameters(&m_nIp, 2); + UpdateCompareFlag(CGarages::HasImportExportGarageCollectedThisCar(ScriptParams[0], ScriptParams[1] - 1)); + return 0; + } + case COMMAND_CLEAR_THIS_PRINT: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CMessages::ClearThisPrint(text); + return 0; + } + case COMMAND_CLEAR_THIS_BIG_PRINT: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CMessages::ClearThisBigPrint(text); + return 0; + } + case COMMAND_SET_MISSION_AUDIO_POSITION: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + DMAudio.SetMissionAudioLocation(pos.x, pos.y, pos.z); + return 0; + } + case COMMAND_ACTIVATE_SAVE_MENU: + FrontEndMenuManager.m_bSaveMenuActive = true; + return 0; + case COMMAND_HAS_SAVE_GAME_FINISHED: + UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive); + return 0; + case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE: + CollectParameters(&m_nIp, 1); + CGarages::SetLeaveCameraForThisGarage(ScriptParams[0]); + return 0; + case COMMAND_ADD_BLIP_FOR_PICKUP_OLD: + { + CollectParameters(&m_nIp, 3); + CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject; + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), ScriptParams[1], (eBlipDisplay)ScriptParams[2]); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_BLIP_FOR_PICKUP: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject; + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH); + CRadar::ChangeBlipScale(handle, 3); + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject; + CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + int handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH); + CRadar::SetBlipSprite(handle, ScriptParams[1]); + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_PED_DENSITY_MULTIPLIER: + CollectParameters(&m_nIp, 1); + CPopulation::PedDensityMultiplier = *(float*)&ScriptParams[0]; + return 0; + case COMMAND_FORCE_RANDOM_PED_TYPE: + CollectParameters(&m_nIp, 1); + CPopulation::m_AllRandomPedsThisType = ScriptParams[0]; + return 0; + case COMMAND_SET_TEXT_DRAW_BEFORE_FADE: + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextBeforeFade = ScriptParams[0] != 0; + return 0; + case COMMAND_GET_COLLECTABLE1S_COLLECTED: + ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages; + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_REGISTER_EL_BURRO_TIME: + CollectParameters(&m_nIp, 1); + CStats::RegisterElBurroTime(ScriptParams[0]); + return 0; + case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE: + CollectParameters(&m_nIp, 1); + CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0; + return 0; + case COMMAND_SET_TEXT_RIGHT_JUSTIFY: + CollectParameters(&m_nIp, 1); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bRightJustify = ScriptParams[0] != 0; + return 0; + case COMMAND_PRINT_HELP: + { + if (CCamera::m_bUseMouse3rdPerson && ( + strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15", 7) == 0 || + strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A", 7) == 0 || + strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_3A", 7) == 0 || + strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_4A", 7) == 0)) { + m_nIp += KEY_LENGTH_IN_SCRIPT; + return 0; + } + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CHud::SetHelpMessage(text, false); + return 0; + } + case COMMAND_CLEAR_HELP: + CHud::SetHelpMessage(nil, false); + return 0; + case COMMAND_FLASH_HUD_OBJECT: + CollectParameters(&m_nIp, 1); + CHud::m_ItemToFlash = ScriptParams[0]; + return 0; + default: + script_assert(0); + } + return -1; +} diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp new file mode 100644 index 00000000..bada95ea --- /dev/null +++ b/src/control/Script5.cpp @@ -0,0 +1,2011 @@ +#include "common.h" + +#include "Script.h" +#include "ScriptCommands.h" + +#include "CarCtrl.h" +#include "BulletInfo.h" +#include "General.h" +#include "Lines.h" +#include "Messages.h" +#include "Pad.h" +#include "Pools.h" +#include "Population.h" +#include "RpAnimBlend.h" +#include "Shadows.h" +#include "SpecialFX.h" +#include "World.h" +#include "main.h" + +int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index) +{ + if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1) + ScriptSphereArray[index].m_Index = 1; + else + ScriptSphereArray[index].m_Index++; + return (uint16)index | ScriptSphereArray[index].m_Index << 16; +} + +int32 CTheScripts::GetActualScriptSphereIndex(int32 index) +{ + if (index == -1) + return -1; + uint16 check = (uint32)index >> 16; + uint16 array_idx = index & (0xFFFF); + script_assert(array_idx < ARRAY_SIZE(ScriptSphereArray)); + if (check != ScriptSphereArray[array_idx].m_Index) + return -1; + return array_idx; +} + +void CTheScripts::DrawScriptSpheres() +{ + for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { + if (ScriptSphereArray[i].m_bInUse) + C3dMarkers::PlaceMarkerSet(ScriptSphereArray[i].m_Id, MARKERTYPE_CYLINDER, ScriptSphereArray[i].m_vecCenter, ScriptSphereArray[i].m_fRadius, + SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0); + } +} + +int32 CTheScripts::AddScriptSphere(int32 id, CVector pos, float radius) +{ + int16 i = 0; + for (i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { + if (!ScriptSphereArray[i].m_bInUse) + break; + } +#ifdef FIX_BUGS + if (i == MAX_NUM_SCRIPT_SPHERES) + return -1; +#endif + ScriptSphereArray[i].m_bInUse = true; + ScriptSphereArray[i].m_Id = id; + ScriptSphereArray[i].m_vecCenter = pos; + ScriptSphereArray[i].m_fRadius = radius; + return GetNewUniqueScriptSphereIndex(i); +} + +void CTheScripts::RemoveScriptSphere(int32 index) +{ + index = GetActualScriptSphereIndex(index); + if (index == -1) + return; + ScriptSphereArray[index].m_bInUse = false; + ScriptSphereArray[index].m_Id = 0; +} + +void CTheScripts::AddToBuildingSwapArray(CBuilding* pBuilding, int32 old_model, int32 new_model) +{ + int i = 0; + bool found = false; + while (i < MAX_NUM_BUILDING_SWAPS && !found) { + if (BuildingSwapArray[i].m_pBuilding == pBuilding) + found = true; + else + i++; + } + if (found) { + if (BuildingSwapArray[i].m_nOldModel == new_model) { + BuildingSwapArray[i].m_pBuilding = nil; + BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; + } + else { + BuildingSwapArray[i].m_nNewModel = new_model; + } + } + else { + i = 0; + while (i < MAX_NUM_BUILDING_SWAPS && !found) { + if (BuildingSwapArray[i].m_pBuilding == nil) + found = true; + else + i++; + } + if (found) { + BuildingSwapArray[i].m_pBuilding = pBuilding; + BuildingSwapArray[i].m_nNewModel = new_model; + BuildingSwapArray[i].m_nOldModel = old_model; + } + } +} + +void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove) +{ + int i = 0; + bool found = false; + while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { + if (InvisibilitySettingArray[i] == pEntity) + found = true; + else + i++; + } + if (found) { + if (remove) + InvisibilitySettingArray[i] = nil; + } + else if (!remove) { + i = 0; + while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { + if (InvisibilitySettingArray[i] == nil) + found = true; + else + i++; + } + if (found) + InvisibilitySettingArray[i] = pEntity; + } +} + +void CTheScripts::UndoBuildingSwaps() +{ + for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { + if (BuildingSwapArray[i].m_pBuilding) { + BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nOldModel); + BuildingSwapArray[i].m_pBuilding = nil; + BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; + } + } +} + +void CTheScripts::UndoEntityInvisibilitySettings() +{ + for (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { + if (InvisibilitySettingArray[i]) { + InvisibilitySettingArray[i]->bIsVisible = true; + InvisibilitySettingArray[i] = nil; + } + } +} + + +void CRunningScript::UpdateCompareFlag(bool flag) +{ + if (m_bNotFlag) + flag = !flag; + if (m_nAndOrState == ANDOR_NONE) { + m_bCondResult = flag; + return; + } + if (m_nAndOrState >= ANDS_1 && m_nAndOrState <= ANDS_8) { + m_bCondResult &= flag; + if (m_nAndOrState == ANDS_1) { + m_nAndOrState = ANDOR_NONE; + return; + } + } + else if (m_nAndOrState >= ORS_1 && m_nAndOrState <= ORS_8) { + m_bCondResult |= flag; + if (m_nAndOrState == ORS_1) { + m_nAndOrState = ANDOR_NONE; + return; + } + } + else { + return; + } + m_nAndOrState--; +} + +void CRunningScript::LocatePlayerCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug, decided = false; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_3D: + case COMMAND_LOCATE_PLAYER_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + switch (command) { + case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D: + if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) { + result = false; + decided = true; + } + break; + default: + break; + } + X = *(float*)&ScriptParams[1]; + Y = *(float*)&ScriptParams[2]; + if (b3D) { + Z = *(float*)&ScriptParams[3]; + dX = *(float*)&ScriptParams[4]; + dY = *(float*)&ScriptParams[5]; + dZ = *(float*)&ScriptParams[6]; + debug = ScriptParams[7]; + } else { + dX = *(float*)&ScriptParams[3]; + dY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + if (!decided) { + CVector pos = pPlayerInfo->GetPos(); + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_LOCATE_PLAYER_ANY_MEANS_2D: + case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D: + result = true; + break; + case COMMAND_LOCATE_PLAYER_ON_FOOT_2D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D: + result = !pPlayerInfo->m_pPed->bInVehicle; + break; + case COMMAND_LOCATE_PLAYER_IN_CAR_2D: + case COMMAND_LOCATE_PLAYER_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D: + result = pPlayerInfo->m_pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocatePlayerCharCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 6 : 5); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CVector pos = pPlayerInfo->GetPos(); + if (pTarget->bInVehicle) { + X = pTarget->m_pMyVehicle->GetPosition().x; + Y = pTarget->m_pMyVehicle->GetPosition().y; + Z = pTarget->m_pMyVehicle->GetPosition().z; + } else { + X = pTarget->GetPosition().x; + Y = pTarget->GetPosition().y; + Z = pTarget->GetPosition().z; + } + dX = *(float*)&ScriptParams[2]; + dY = *(float*)&ScriptParams[3]; + if (b3D) { + dZ = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + else { + debug = ScriptParams[4]; + } + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D: + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D: + result = true; + break; + case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D: + result = !pPlayerInfo->m_pPed->bInVehicle; + break; + case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D: + result = pPlayerInfo->m_pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + UpdateCompareFlag(result); + if (debug) +#ifdef FIX_BUGS + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); +#else + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT); +#endif + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocatePlayerCarCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 6 : 5); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CVector pos = pPlayerInfo->GetPos(); + X = pTarget->GetPosition().x; + Y = pTarget->GetPosition().y; + Z = pTarget->GetPosition().z; + dX = *(float*)&ScriptParams[2]; + dY = *(float*)&ScriptParams[3]; + if (b3D) { + dZ = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + else { + debug = ScriptParams[4]; + } + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D: + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D: + result = true; + break; + case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D: + result = !pPlayerInfo->m_pPed->bInVehicle; + break; + case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D: + result = pPlayerInfo->m_pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocateCharCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug, decided = false; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D: + case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + switch (command) { + case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D: + case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D: + case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D: + case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D: + if (!CTheScripts::IsPedStopped(pPed)) { + result = false; + decided = true; + } + break; + default: + break; + } + X = *(float*)&ScriptParams[1]; + Y = *(float*)&ScriptParams[2]; + if (b3D) { + Z = *(float*)&ScriptParams[3]; + dX = *(float*)&ScriptParams[4]; + dY = *(float*)&ScriptParams[5]; + dZ = *(float*)&ScriptParams[6]; + debug = ScriptParams[7]; + } + else { + dX = *(float*)&ScriptParams[3]; + dY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + if (!decided) { + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_2D: + case COMMAND_LOCATE_CHAR_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D: + case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: + result = true; + break; + case COMMAND_LOCATE_CHAR_ON_FOOT_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_3D: + case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D: + case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D: + result = !pPed->bInVehicle; + break; + case COMMAND_LOCATE_CHAR_IN_CAR_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D: + case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D: + result = pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocateCharCharCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 6 : 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + if (pTarget->bInVehicle) { + X = pTarget->m_pMyVehicle->GetPosition().x; + Y = pTarget->m_pMyVehicle->GetPosition().y; + Z = pTarget->m_pMyVehicle->GetPosition().z; + } + else { + X = pTarget->GetPosition().x; + Y = pTarget->GetPosition().y; + Z = pTarget->GetPosition().z; + } + dX = *(float*)&ScriptParams[2]; + dY = *(float*)&ScriptParams[3]; + if (b3D) { + dZ = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + else { + debug = ScriptParams[4]; + } + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D: + case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D: + result = true; + break; + case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D: + result = !pPed->bInVehicle; + break; + case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D: + result = pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + UpdateCompareFlag(result); + if (debug) +#ifdef FIX_BUGS + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); +#else + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT); +#endif + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocateCharCarCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 6 : 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + X = pTarget->GetPosition().x; + Y = pTarget->GetPosition().y; + Z = pTarget->GetPosition().z; + dX = *(float*)&ScriptParams[2]; + dY = *(float*)&ScriptParams[3]; + if (b3D) { + dZ = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + else { + debug = ScriptParams[4]; + } + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D: + case COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D: + result = true; + break; + case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D: + result = !pPed->bInVehicle; + break; + case COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D: + result = pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocateCharObjectCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 6 : 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + X = pTarget->GetPosition().x; + Y = pTarget->GetPosition().y; + Z = pTarget->GetPosition().z; + dX = *(float*)&ScriptParams[2]; + dY = *(float*)&ScriptParams[3]; + if (b3D) { + dZ = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + else { + debug = ScriptParams[4]; + } + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D: + case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D: + result = true; + break; + case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D: + result = !pPed->bInVehicle; + break; + case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D: + result = pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocateCarCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug, decided = false; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_CAR_3D: + case COMMAND_LOCATE_STOPPED_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CVector pos = pVehicle->GetPosition(); + switch (command) { + case COMMAND_LOCATE_STOPPED_CAR_2D: + case COMMAND_LOCATE_STOPPED_CAR_3D: + if (!CTheScripts::IsVehicleStopped(pVehicle)) { + result = false; + decided = true; + } + break; + default: + break; + } + X = *(float*)&ScriptParams[1]; + Y = *(float*)&ScriptParams[2]; + if (b3D) { + Z = *(float*)&ScriptParams[3]; + dX = *(float*)&ScriptParams[4]; + dY = *(float*)&ScriptParams[5]; + dZ = *(float*)&ScriptParams[6]; + debug = ScriptParams[7]; + } + else { + dX = *(float*)&ScriptParams[3]; + dY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + if (!decided) { + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + result = in_area; + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::LocateSniperBulletCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_SNIPER_BULLET_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 7 : 5); + X = *(float*)&ScriptParams[0]; + Y = *(float*)&ScriptParams[1]; + if (b3D) { + Z = *(float*)&ScriptParams[2]; + dX = *(float*)&ScriptParams[3]; + dY = *(float*)&ScriptParams[4]; + dZ = *(float*)&ScriptParams[5]; + debug = ScriptParams[6]; + } + else { + dX = *(float*)&ScriptParams[2]; + dY = *(float*)&ScriptParams[3]; + debug = ScriptParams[4]; + } + result = CBulletInfo::TestForSniperBullet(X - dX, X + dX, Y - dY, Y + dY, b3D ? Z - dZ : -1000.0f, b3D ? Z + dZ : 1000.0f); + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + +void CRunningScript::PlayerInAreaCheckCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug, decided = false; + float infX, infY, infZ, supX, supY, supZ; + switch (command) { + case COMMAND_IS_PLAYER_IN_AREA_3D: + case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + switch (command) { + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D: + if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) { + result = false; + decided = true; + } + break; + default: + break; + } + infX = *(float*)&ScriptParams[1]; + infY = *(float*)&ScriptParams[2]; + if (b3D) { + infZ = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[6]; + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[6]; + supZ = *(float*)&ScriptParams[3]; + } + debug = ScriptParams[7]; + } + else { + supX = *(float*)&ScriptParams[3]; + supY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + if (infX > supX) { + float tmp = infX; + infX = supX; + supX = tmp; + } + if (infY > supY) { + float tmp = infY; + infY = supY; + supY = tmp; + } + if (!decided) { + CVector pos = pPlayerInfo->GetPos(); + result = false; + bool in_area; + if (b3D) { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y && + infZ <= pos.z && + supZ >= pos.z; + } + else { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_IS_PLAYER_IN_AREA_2D: + case COMMAND_IS_PLAYER_IN_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D: + result = true; + break; + case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D: + result = !pPlayerInfo->m_pPed->bInVehicle; + break; + case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D: + result = pPlayerInfo->m_pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); + else + CTheScripts::DrawDebugSquare(infX, infY, supX, supY); + } +} + +void CRunningScript::PlayerInAngledAreaCheckCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug, decided = false; + float infX, infY, infZ, supX, supY, supZ, side2length; + switch (command) { + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 9 : 7); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + switch (command) { + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D: + if (!CTheScripts::IsPlayerStopped(pPlayerInfo)) { + result = false; + decided = true; + } + break; + default: + break; + } + infX = *(float*)&ScriptParams[1]; + infY = *(float*)&ScriptParams[2]; + if (b3D) { + infZ = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[6]; + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[6]; + supZ = *(float*)&ScriptParams[3]; + } + side2length = *(float*)&ScriptParams[7]; + debug = ScriptParams[8]; + } + else { + supX = *(float*)&ScriptParams[3]; + supY = *(float*)&ScriptParams[4]; + side2length = *(float*)&ScriptParams[5]; + debug = ScriptParams[6]; + } + float initAngle = CGeneral::GetRadianAngleBetweenPoints(infX, infY, supX, supY) + HALFPI; + while (initAngle < 0.0f) + initAngle += TWOPI; + while (initAngle > TWOPI) + initAngle -= TWOPI; + // it looks like the idea is to use a rectangle using the diagonal of the rectangle as + // the side of new rectangle, with "length" being the length of second side + float rotatedSupX = supX + side2length * sin(initAngle); + float rotatedSupY = supY - side2length * cos(initAngle); + float rotatedInfX = infX + side2length * sin(initAngle); + float rotatedInfY = infY - side2length * cos(initAngle); + float side1X = supX - infX; + float side1Y = supY - infY; + float side1Length = CVector2D(side1X, side1Y).Magnitude(); + float side2X = rotatedInfX - infX; + float side2Y = rotatedInfY - infY; + float side2Length = CVector2D(side2X, side2Y).Magnitude(); // == side2length? + if (!decided) { + CVector pos = pPlayerInfo->GetPos(); + result = false; + float X = pos.x - infX; + float Y = pos.y - infY; + float positionAlongSide1 = X * side1X / side1Length + Y * side1Y / side1Length; + bool in_area = false; + if (positionAlongSide1 >= 0.0f && positionAlongSide1 <= side1Length) { + float positionAlongSide2 = X * side2X / side2Length + Y * side2Y / side2Length; + if (positionAlongSide2 >= 0.0f && positionAlongSide2 <= side2Length) { + in_area = !b3D || pos.z >= infZ && pos.z <= supZ; + } + } + + if (in_area) { + switch (command) { + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D: + result = true; + break; + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D: + result = !pPlayerInfo->m_pPed->bInVehicle; + break; + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D: + case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: + result = pPlayerInfo->m_pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantAngledArea((uintptr)this + m_nIp, infX, infY, supX, supY, + rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugAngledCube(infX, infY, infZ, supX, supY, supZ, + rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY); + else + CTheScripts::DrawDebugAngledSquare(infX, infY, supX, supY, + rotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY); + } +} + +void CRunningScript::CharInAreaCheckCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug, decided = false; + float infX, infY, infZ, supX, supY, supZ; + switch (command) { + case COMMAND_IS_CHAR_IN_AREA_3D: + case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + switch (command) { + case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D: + if (!CTheScripts::IsPedStopped(pPed)) { + result = false; + decided = true; + } + break; + default: + break; + } + infX = *(float*)&ScriptParams[1]; + infY = *(float*)&ScriptParams[2]; + if (b3D) { + infZ = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[6]; + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[6]; + supZ = *(float*)&ScriptParams[3]; + } + debug = ScriptParams[7]; + } + else { + supX = *(float*)&ScriptParams[3]; + supY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + if (infX > supX) { + float tmp = infX; + infX = supX; + supX = tmp; + } + if (infY > supY) { + float tmp = infY; + infY = supY; + supY = tmp; + } + if (!decided) { + result = false; + bool in_area; + if (b3D) { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y && + infZ <= pos.z && + supZ >= pos.z; + } + else { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_IS_CHAR_IN_AREA_2D: + case COMMAND_IS_CHAR_IN_AREA_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: + result = true; + break; + case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: + result = !pPed->bInVehicle; + break; + case COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D: + case COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D: + case COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D: + result = pPed->bInVehicle; + break; + default: + script_assert(false); + break; + } + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); + else + CTheScripts::DrawDebugSquare(infX, infY, supX, supY); + } +} + +void CRunningScript::CarInAreaCheckCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug, decided = false; + float infX, infY, infZ, supX, supY, supZ; + switch (command) { + case COMMAND_IS_CAR_IN_AREA_3D: + case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CVector pos = pVehicle->GetPosition(); + switch (command) { + case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: + case COMMAND_IS_CAR_STOPPED_IN_AREA_2D: + if (!CTheScripts::IsVehicleStopped(pVehicle)) { + result = false; + decided = true; + } + break; + default: + break; + } + infX = *(float*)&ScriptParams[1]; + infY = *(float*)&ScriptParams[2]; + if (b3D) { + infZ = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[6]; + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[6]; + supZ = *(float*)&ScriptParams[3]; + } + debug = ScriptParams[7]; + } + else { + supX = *(float*)&ScriptParams[3]; + supY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + if (infX > supX) { + float tmp = infX; + infX = supX; + supX = tmp; + } + if (infY > supY) { + float tmp = infY; + infY = supY; + supY = tmp; + } + if (!decided) { + result = false; + bool in_area; + if (b3D) { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y && + infZ <= pos.z && + supZ >= pos.z; + } + else { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_IS_CAR_IN_AREA_2D: + case COMMAND_IS_CAR_IN_AREA_3D: + case COMMAND_IS_CAR_STOPPED_IN_AREA_2D: + case COMMAND_IS_CAR_STOPPED_IN_AREA_3D: + result = true; + break; + default: + script_assert(false); + break; + } + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); + else + CTheScripts::DrawDebugSquare(infX, infY, supX, supY); + } +} + +void CRunningScript::DoDeatharrestCheck() +{ + if (!m_bDeatharrestEnabled) + return; + if (!CTheScripts::IsPlayerOnAMission()) + return; + CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus]; + if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest() && !CTheScripts::UpsideDownCars.AreAnyCarsUpsideDown()) + return; +#ifdef MISSION_REPLAY + if (AllowMissionReplay != 0) + return; + if (CanAllowMissionReplay()) + AllowMissionReplay = 1; +#endif + script_assert(m_nStackPointer > 0); + while (m_nStackPointer > 1) + --m_nStackPointer; + m_nIp = m_anStack[--m_nStackPointer]; + int16 messageId; + if (pPlayer->IsRestartingAfterDeath()) + messageId = 0; + else if (pPlayer->IsRestartingAfterArrest()) + messageId = 5; + else + messageId = 10; + messageId += CGeneral::GetRandomNumberInRange(0, 5); + bool found = false; + for (int16 contact = 0; !found && contact < MAX_NUM_CONTACTS; contact++) { + int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact]; + if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) { + messageId += CTheScripts::BaseBriefIdForContact[contact]; + found = true; + } + } + if (!found) + messageId = 8001; + char tmp[16]; + sprintf(tmp, "%d", messageId); + CMessages::ClearSmallMessagesOnly(); + wchar* text = TheText.Get(tmp); + // ...and do nothing about it + *(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0; + m_bDeatharrestExecuted = true; + m_nWakeTime = 0; +} + +int16 CRunningScript::GetPadState(uint16 pad, uint16 button) +{ + CPad* pPad = CPad::GetPad(pad); + switch (button) { + case 0: return pPad->NewState.LeftStickX; + case 1: return pPad->NewState.LeftStickY; + case 2: return pPad->NewState.RightStickX; + case 3: return pPad->NewState.RightStickY; + case 4: return pPad->NewState.LeftShoulder1; + case 5: return pPad->NewState.LeftShoulder2; + case 6: return pPad->NewState.RightShoulder1; + case 7: return pPad->NewState.RightShoulder2; + case 8: return pPad->NewState.DPadUp; + case 9: return pPad->NewState.DPadDown; + case 10: return pPad->NewState.DPadLeft; + case 11: return pPad->NewState.DPadRight; + case 12: return pPad->NewState.Start; + case 13: return pPad->NewState.Select; + case 14: return pPad->NewState.Square; + case 15: return pPad->NewState.Triangle; + case 16: return pPad->NewState.Cross; + case 17: return pPad->NewState.Circle; + case 18: return pPad->NewState.LeftShock; + case 19: return pPad->NewState.RightShock; + default: break; + } + return 0; +} + + +void CTheScripts::PrintListSizes() +{ + int active = 0; + int idle = 0; + + for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) + active++; + for (CRunningScript* pScript = pIdleScripts; pScript; pScript = pScript->GetNext()) + idle++; + + debug("active: %d, idle: %d", active, idle); +} + +uint32 DbgLineColour = 0x0000FFFF; // r = 0, g = 0, b = 255, a = 255 + +void CTheScripts::DrawDebugSquare(float infX, float infY, float supX, float supY) +{ + CColPoint tmpCP; + CEntity* tmpEP; + CVector p1, p2, p3, p4; + p1 = CVector(infX, infY, -1000.0f); + CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p1.z = 2.0f + tmpCP.point.z; + p2 = CVector(supX, supY, -1000.0f); + CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p2.z = 2.0f + tmpCP.point.z; + p3 = CVector(infX, supY, -1000.0f); + CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p3.z = 2.0f + tmpCP.point.z; + p4 = CVector(supX, infY, -1000.0f); + CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p4.z = 2.0f + tmpCP.point.z; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour); +} + +void CTheScripts::DrawDebugAngledSquare(float infX, float infY, float supX, float supY, float rotSupX, float rotSupY, float rotInfX, float rotInfY) +{ + CColPoint tmpCP; + CEntity* tmpEP; + CVector p1, p2, p3, p4; + p1 = CVector(infX, infY, -1000.0f); + CWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p1.z = 2.0f + tmpCP.point.z; + p2 = CVector(supX, supY, -1000.0f); + CWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p2.z = 2.0f + tmpCP.point.z; + p3 = CVector(rotSupX, rotSupY, -1000.0f); + CWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p3.z = 2.0f + tmpCP.point.z; + p4 = CVector(rotInfX, rotInfY, -1000.0f); + CWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil); + p4.z = 2.0f + tmpCP.point.z; + CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour); +} + +void CTheScripts::DrawDebugCube(float infX, float infY, float infZ, float supX, float supY, float supZ) +{ + CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, infY, infZ, supX, supY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, supY, infZ, infX, supY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(infX, supY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, supY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, supY, supZ, infX, supY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, supY, supZ, supX, supY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, supY, infZ, DbgLineColour, DbgLineColour); +} + +void CTheScripts::DrawDebugAngledCube(float infX, float infY, float infZ, float supX, float supY, float supZ, float rotSupX, float rotSupY, float rotInfX, float rotInfY) +{ + CTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, infY, infZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, infZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, infY, supZ, rotSupX, rotSupY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, rotInfX, rotInfY, supY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, supZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour); + CTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour); +} + +void CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, uint32 col, uint32 col2) +{ + if (NumScriptDebugLines >= MAX_NUM_STORED_LINES) + return; + aStoredLines[NumScriptDebugLines].vecInf = CVector(x1, y1, z1); + aStoredLines[NumScriptDebugLines].vecSup = CVector(x2, y2, z2); + aStoredLines[NumScriptDebugLines].color1 = col; + aStoredLines[NumScriptDebugLines++].color2 = col2; +} + +void CTheScripts::RenderTheScriptDebugLines() +{ + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1); + for (int i = 0; i < NumScriptDebugLines; i++) { + CLines::RenderLineWithClipping( + aStoredLines[i].vecInf.x, + aStoredLines[i].vecInf.y, + aStoredLines[i].vecInf.z, + aStoredLines[i].vecSup.x, + aStoredLines[i].vecSup.y, + aStoredLines[i].vecSup.z, + aStoredLines[i].color1, + aStoredLines[i].color2); + } + NumScriptDebugLines = 0; + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0); +} + +#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) + sizeof(CTheScripts::BaseBriefIdForContact) + sizeof(CTheScripts::OnAMissionForContactFlag) +\ + sizeof(CTheScripts::CollectiveArray) + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32) + +void CTheScripts::SaveAllScripts(uint8* buf, uint32* size) +{ +INITSAVEBUF + uint32 varSpace = GetSizeOfVariableSpace(); + uint32 runningScripts = 0; + for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) + runningScripts++; + *size = CRunningScript::nSaveStructSize * runningScripts + varSpace + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32); + WriteSaveHeader(buf, 'S', 'C', 'R', '\0', *size - SAVE_HEADER_SIZE); + WriteSaveBuf(buf, varSpace); + for (uint32 i = 0; i < varSpace; i++) + WriteSaveBuf(buf, ScriptSpace[i]); +#ifdef CHECK_STRUCT_SIZES + static_assert(SCRIPT_DATA_SIZE == 968, "CTheScripts::SaveAllScripts"); +#endif + uint32 script_data_size = SCRIPT_DATA_SIZE; + WriteSaveBuf(buf, script_data_size); + WriteSaveBuf(buf, OnAMissionFlag); + for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { + WriteSaveBuf(buf, OnAMissionForContactFlag[i]); + WriteSaveBuf(buf, BaseBriefIdForContact[i]); + } + for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) + WriteSaveBuf(buf, CollectiveArray[i]); + WriteSaveBuf(buf, NextFreeCollectiveIndex); + for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { + CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding; + uint32 type, handle; + if (!pBuilding) { + type = 0; + handle = 0; + } else if (pBuilding->GetIsATreadable()) { + type = 1; + handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding) + 1; + } else { + type = 2; + handle = CPools::GetBuildingPool()->GetJustIndex(pBuilding) + 1; + } + WriteSaveBuf(buf, type); + WriteSaveBuf(buf, handle); + WriteSaveBuf(buf, BuildingSwapArray[i].m_nNewModel); + WriteSaveBuf(buf, BuildingSwapArray[i].m_nOldModel); + } + for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { + CEntity* pEntity = InvisibilitySettingArray[i]; + uint32 type, handle; + if (!pEntity) { + type = 0; + handle = 0; + } else { + switch (pEntity->GetType()) { + case ENTITY_TYPE_BUILDING: + if (((CBuilding*)pEntity)->GetIsATreadable()) { + type = 1; + handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pEntity) + 1; + } else { + type = 2; + handle = CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pEntity) + 1; + } + break; + case ENTITY_TYPE_OBJECT: + type = 3; + handle = CPools::GetObjectPool()->GetJustIndex((CObject*)pEntity) + 1; + break; + case ENTITY_TYPE_DUMMY: + type = 4; + handle = CPools::GetDummyPool()->GetJustIndex((CDummy*)pEntity) + 1; + default: break; + } + } + WriteSaveBuf(buf, type); + WriteSaveBuf(buf, handle); + } + WriteSaveBuf(buf, bUsingAMultiScriptFile); + WriteSaveBuf(buf, (uint8)0); + WriteSaveBuf(buf, (uint16)0); + WriteSaveBuf(buf, MainScriptSize); + WriteSaveBuf(buf, LargestMissionScriptSize); + WriteSaveBuf(buf, NumberOfMissionScripts); + WriteSaveBuf(buf, (uint16)0); + WriteSaveBuf(buf, runningScripts); + for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) + pScript->Save(buf); +VALIDATESAVEBUF(*size) +} + +void CTheScripts::LoadAllScripts(uint8* buf, uint32 size) +{ + Init(); +INITSAVEBUF + CheckSaveHeader(buf, 'S', 'C', 'R', '\0', size - SAVE_HEADER_SIZE); + uint32 varSpace = ReadSaveBuf(buf); + for (uint32 i = 0; i < varSpace; i++) + ScriptSpace[i] = ReadSaveBuf(buf); + script_assert(ReadSaveBuf(buf) == SCRIPT_DATA_SIZE); + OnAMissionFlag = ReadSaveBuf(buf); + for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { + OnAMissionForContactFlag[i] = ReadSaveBuf(buf); + BaseBriefIdForContact[i] = ReadSaveBuf(buf); + } + for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) + CollectiveArray[i] = ReadSaveBuf(buf); + NextFreeCollectiveIndex = ReadSaveBuf(buf); + for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { + uint32 type = ReadSaveBuf(buf); + uint32 handle = ReadSaveBuf(buf); + switch (type) { + case 0: + BuildingSwapArray[i].m_pBuilding = nil; + break; + case 1: + BuildingSwapArray[i].m_pBuilding = CPools::GetTreadablePool()->GetSlot(handle - 1); + break; + case 2: + BuildingSwapArray[i].m_pBuilding = CPools::GetBuildingPool()->GetSlot(handle - 1); + break; + default: + script_assert(false); + } + BuildingSwapArray[i].m_nNewModel = ReadSaveBuf(buf); + BuildingSwapArray[i].m_nOldModel = ReadSaveBuf(buf); + if (BuildingSwapArray[i].m_pBuilding) + BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nNewModel); + } + for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { + uint32 type = ReadSaveBuf(buf); + uint32 handle = ReadSaveBuf(buf); + switch (type) { + case 0: + InvisibilitySettingArray[i] = nil; + break; + case 1: + InvisibilitySettingArray[i] = CPools::GetTreadablePool()->GetSlot(handle - 1); + break; + case 2: + InvisibilitySettingArray[i] = CPools::GetBuildingPool()->GetSlot(handle - 1); + break; + case 3: + InvisibilitySettingArray[i] = CPools::GetObjectPool()->GetSlot(handle - 1); + break; + case 4: + InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1); + break; + default: + script_assert(false); + } + if (InvisibilitySettingArray[i]) + InvisibilitySettingArray[i]->bIsVisible = false; + } + script_assert(ReadSaveBuf(buf) == bUsingAMultiScriptFile); + ReadSaveBuf(buf); + ReadSaveBuf(buf); + script_assert(ReadSaveBuf(buf) == MainScriptSize); + script_assert(ReadSaveBuf(buf) == LargestMissionScriptSize); + script_assert(ReadSaveBuf(buf) == NumberOfMissionScripts); + ReadSaveBuf(buf); + uint32 runningScripts = ReadSaveBuf(buf); + for (uint32 i = 0; i < runningScripts; i++) + StartNewScript(0)->Load(buf); +VALIDATESAVEBUF(size) +} + +#undef SCRIPT_DATA_SIZE + +void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity) +{ + static CColPoint aTempColPoints[MAX_COLLISION_POINTS]; + int16 entities = 0; + CEntity* aEntities[16]; + CWorld::FindObjectsKindaColliding(pos, pEntity->GetBoundRadius(), false, &entities, 16, aEntities, false, true, true, false, false); + if (entities <= 0) + return; + for (uint16 i = 0; i < entities; i++) { + if (aEntities[i] != pEntity && aEntities[i]->IsPed() && ((CPed*)aEntities[i])->bInVehicle) + aEntities[i] = nil; + } + for (uint16 i = 0; i < entities; i++) { + if (aEntities[i] == pEntity || !aEntities[i]) + continue; + CEntity* pFound = aEntities[i]; + int cols; + if (pEntity->GetColModel()->numLines <= 0) + cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(), + pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil); + else { + float lines[4]; + lines[0] = lines[1] = lines[2] = lines[3] = 1.0f; + CColPoint tmp[4]; + cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(), + pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines); + } + if (cols <= 0) + continue; + switch (pFound->GetType()) { + case ENTITY_TYPE_VEHICLE: + { + printf("Will try to delete a vehicle where a mission entity should be\n"); + CVehicle* pVehicle = (CVehicle*)pFound; + if (pVehicle->bIsLocked || !pVehicle->CanBeDeleted()) + break; + if (pVehicle->pDriver) { + CPopulation::RemovePed(pVehicle->pDriver); + pVehicle->pDriver = nil; + } + for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) { + if (pVehicle->pPassengers[i]) { + CPopulation::RemovePed(pVehicle->pPassengers[i]); + pVehicle->pPassengers[i] = 0; + pVehicle->m_nNumPassengers--; + } + } + CCarCtrl::RemoveFromInterestingVehicleList(pVehicle); + CWorld::Remove(pVehicle); + delete pVehicle; + break; + } + case ENTITY_TYPE_PED: + { + CPed* pPed = (CPed*)pFound; + if (pPed->IsPlayer() || !pPed->CanBeDeleted()) + break; + CPopulation::RemovePed(pPed); + printf("Deleted a ped where a mission entity should be\n"); + break; + } + default: break; + } + } +} + +void CTheScripts::HighlightImportantArea(uint32 id, float x1, float y1, float x2, float y2, float z) +{ + float infX, infY, supX, supY; + if (x1 < x2) { + infX = x1; + supX = x2; + } else { + infX = x2; + supX = x1; + } + if (y1 < y2) { + infY = y1; + supY = y2; + } + else { + infY = y2; + supY = y1; + } + CVector center; + center.x = (infX + supX) / 2; + center.y = (infY + supY) / 2; + center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z; + CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, ¢er, supX - center.x, 0.0f, 0.0f, center.y - supY, 0); +} + +void CTheScripts::HighlightImportantAngledArea(uint32 id, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float z) +{ + float infX, infY, supX, supY, X, Y; + X = (x1 + x2) / 2; + Y = (y1 + y2) / 2; + supX = infX = X; + supY = infY = Y; + X = (x2 + x3) / 2; + Y = (y2 + y3) / 2; + infX = Min(infX, X); + supX = Max(supX, X); + infY = Min(infY, Y); + supY = Max(supY, Y); + X = (x3 + x4) / 2; + Y = (y3 + y4) / 2; + infX = Min(infX, X); + supX = Max(supX, X); + infY = Min(infY, Y); + supY = Max(supY, Y); + X = (x4 + x1) / 2; + Y = (y4 + y1) / 2; + infX = Min(infX, X); + supX = Max(supX, X); + infY = Min(infY, Y); + supY = Max(supY, Y); + CVector center; + center.x = (infX + supX) / 2; + center.y = (infY + supY) / 2; + center.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z; + CShadows::RenderIndicatorShadow(id, 2, gpGoalTex, ¢er, supX - center.x, 0.0f, 0.0f, center.y - supY, 0); +} + +bool CTheScripts::IsPedStopped(CPed* pPed) +{ + if (pPed->bInVehicle) + return IsVehicleStopped(pPed->m_pMyVehicle); + return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL; +} + +bool CTheScripts::IsPlayerStopped(CPlayerInfo* pPlayer) +{ + CPed* pPed = pPlayer->m_pPed; + if (pPed->bInVehicle) + return IsVehicleStopped(pPed->m_pMyVehicle); + if (RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP) || + RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP_R) || + RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_LAUNCH) || + RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_GLIDE)) + return false; + return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL; +} + +bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle) +{ + return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled; +} + +void CTheScripts::CleanUpThisPed(CPed* pPed) +{ + if (!pPed) + return; + if (pPed->CharCreatedBy != MISSION_CHAR) + return; + pPed->CharCreatedBy = RANDOM_CHAR; + if (pPed->m_nPedType == PEDTYPE_PROSTITUTE) + pPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000; + if (pPed->bInVehicle) { + if (pPed->m_pMyVehicle->pDriver == pPed) { + if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) { + CCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle); + pPed->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; + } + } + else { + if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) { + pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle); + pPed->bWanderPathAfterExitingCar = true; + } + } + } + bool flees = false; + PedState state; + eMoveState ms; + if (pPed->m_nPedState == PED_FLEE_ENTITY || pPed->m_nPedState == PED_FLEE_POS) { + ms = pPed->m_nMoveState; + state = pPed->m_nPedState; + flees = true; + } + pPed->ClearObjective(); + pPed->bRespondsToThreats = true; + pPed->bScriptObjectiveCompleted = false; + pPed->ClearLeader(); + if (pPed->IsPedInControl()) + pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7); + if (flees) { + pPed->m_nPedState = state; + pPed->SetMoveState(ms); + } + --CPopulation::ms_nTotalMissionPeds; +} + +void CTheScripts::CleanUpThisVehicle(CVehicle* pVehicle) +{ + if (!pVehicle) + return; + if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) + return; + pVehicle->bIsLocked = false; + CCarCtrl::RemoveFromInterestingVehicleList(pVehicle); + pVehicle->VehicleCreatedBy = RANDOM_VEHICLE; + ++CCarCtrl::NumRandomCars; + --CCarCtrl::NumMissionCars; +} + +void CTheScripts::CleanUpThisObject(CObject* pObject) +{ + if (!pObject) + return; + if (pObject->ObjectCreatedBy != MISSION_OBJECT) + return; + pObject->ObjectCreatedBy = TEMP_OBJECT; + pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000; + pObject->m_nRefModelIndex = -1; + pObject->bUseVehicleColours = false; + ++CObject::nNoTempObjects; +} + +void CTheScripts::ReadObjectNamesFromScript() +{ + int32 varSpace = GetSizeOfVariableSpace(); + uint32 ip = varSpace + 8; + NumberOfUsedObjects = Read2BytesFromScript(&ip); + ip += 2; + for (uint16 i = 0; i < NumberOfUsedObjects; i++) { + for (int j = 0; j < USED_OBJECT_NAME_LENGTH; j++) + UsedObjectArray[i].name[j] = ScriptSpace[ip++]; + UsedObjectArray[i].index = 0; + } +} + +void CTheScripts::UpdateObjectIndices() +{ + char name[USED_OBJECT_NAME_LENGTH]; + char error[112]; + for (int i = 1; i < NumberOfUsedObjects; i++) { + bool found = false; + for (int j = 0; j < MODELINFOSIZE && !found; j++) { + CBaseModelInfo* pModel = CModelInfo::GetModelInfo(j); + if (!pModel) + continue; + strcpy(name, pModel->GetName()); +#ifdef FIX_BUGS + for (int k = 0; k < USED_OBJECT_NAME_LENGTH && name[k]; k++) +#else + for (int k = 0; k < USED_OBJECT_NAME_LENGTH; k++) +#endif + name[k] = toupper(name[k]); + if (strcmp(name, UsedObjectArray[i].name) == 0) { + found = true; + UsedObjectArray[i].index = j; + } + } + if (!found) { + sprintf(error, "CTheScripts::UpdateObjectIndices - Couldn't find %s", UsedObjectArray[i].name); + debug("%s\n", error); + } + } +} + +void CTheScripts::ReadMultiScriptFileOffsetsFromScript() +{ + int32 varSpace = GetSizeOfVariableSpace(); + uint32 ip = varSpace + 3; + int32 objectSize = Read4BytesFromScript(&ip); + ip = objectSize + 8; + MainScriptSize = Read4BytesFromScript(&ip); + LargestMissionScriptSize = Read4BytesFromScript(&ip); + NumberOfMissionScripts = Read2BytesFromScript(&ip); + ip += 2; + for (int i = 0; i < NumberOfMissionScripts; i++) { + MultiScriptArray[i] = Read4BytesFromScript(&ip); + } +} diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp new file mode 100644 index 00000000..ca6a1853 --- /dev/null +++ b/src/control/Script6.cpp @@ -0,0 +1,1343 @@ +#include "common.h" + +#include "Script.h" +#include "ScriptCommands.h" + +#include "CarCtrl.h" +#include "Cranes.h" +#include "Credits.h" +#include "CutsceneMgr.h" +#include "DMAudio.h" +#include "FileMgr.h" +#include "Fire.h" +#include "Frontend.h" +#include "Garages.h" +#include "General.h" +#ifdef MISSION_REPLAY +#include "GenericGameStorage.h" +#endif +#include "Messages.h" +#include "Pad.h" +#include "Particle.h" +#include "Phones.h" +#include "Population.h" +#include "Pools.h" +#include "Record.h" +#include "Remote.h" +#include "Restart.h" +#include "SpecialFX.h" +#include "Stats.h" +#include "Streaming.h" +#include "Weather.h" +#include "Zones.h" +#include "main.h" + +int8 CRunningScript::ProcessCommands1000To1099(int32 command) +{ +#ifdef GTA_PS2 + char tmp[48]; +#endif + switch (command) { + //case COMMAND_FLASH_RADAR_BLIP: + case COMMAND_IS_CHAR_IN_CONTROL: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(pPed->IsPedInControl()); + return 0; + } + case COMMAND_SET_GENERATE_CARS_AROUND_CAMERA: + CollectParameters(&m_nIp, 1); + CCarCtrl::bCarsGeneratedAroundCamera = (ScriptParams[0] != 0); + return 0; + case COMMAND_CLEAR_SMALL_PRINTS: + CMessages::ClearSmallMessagesOnly(); + return 0; + case COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS: + UpdateCompareFlag(CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()); + return 0; + case COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); + CAutomobile* pCar = (CAutomobile*)pVehicle; + pCar->bNotDamagedUpsideDown = (ScriptParams[1] != 0); + return 0; + } + case COMMAND_CAN_PLAYER_START_MISSION: + { + CollectParameters(&m_nIp, 1); + CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPlayerPed); + UpdateCompareFlag(pPlayerPed->IsPedInControl() || pPlayerPed->m_nPedState == PED_DRIVING); + return 0; + } + case COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE: + { + CollectParameters(&m_nIp, 1); +#ifdef MISSION_REPLAY + AllowMissionReplay = 0; + SaveGameForPause(3); +#endif + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + CPad::GetPad(ScriptParams[0])->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE); + pPlayerInfo->MakePlayerSafe(true); + CCutsceneMgr::StartCutsceneProcessing(); + return 0; + } + case COMMAND_USE_TEXT_COMMANDS: + CollectParameters(&m_nIp, 1); + CTheScripts::UseTextCommands = (ScriptParams[0] != 0) ? 2 : 1; + return 0; + case COMMAND_SET_THREAT_FOR_PED_TYPE: + CollectParameters(&m_nIp, 2); + CPedType::AddThreat(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_CLEAR_THREAT_FOR_PED_TYPE: + CollectParameters(&m_nIp, 2); + CPedType::RemoveThreat(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_GET_CAR_COLOURS: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + ScriptParams[0] = pVehicle->m_currentColour1; + ScriptParams[1] = pVehicle->m_currentColour2; + StoreParameters(&m_nIp, 2); + return 0; + } + case COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED: + CollectParameters(&m_nIp, 1); + CWorld::SetAllCarsCanBeDamaged(ScriptParams[0] != 0); + if (!ScriptParams[0]) + CWorld::ExtinguishAllCarFiresInArea(FindPlayerCoors(), 4000.0f); + return 0; + case COMMAND_SET_CAR_CAN_BE_DAMAGED: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + pVehicle->bCanBeDamaged = ScriptParams[1] != 0; + if (!ScriptParams[1]) + pVehicle->ExtinguishCarFire(); + return 0; + } + //case COMMAND_MAKE_PLAYER_UNSAFE: + case COMMAND_LOAD_COLLISION: + { + CollectParameters(&m_nIp, 1); + CTimer::Stop(); + CGame::currLevel = (eLevelName)ScriptParams[0]; + ISLAND_LOADING_IS(LOW) + { + CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); + CStreaming::RemoveUnusedBuildings(CGame::currLevel); + } + CCollision::SortOutCollisionAfterLoad(); + ISLAND_LOADING_ISNT(HIGH) + { + CStreaming::RequestIslands(CGame::currLevel); + CStreaming::LoadAllRequestedModels(true); + } + CTimer::Update(); + return 0; + } + case COMMAND_GET_BODY_CAST_HEALTH: + ScriptParams[0] = CObject::nBodyCastHealth; + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_SET_CHARS_CHATTING: + { + CollectParameters(&m_nIp, 3); + CPed* pPed1 = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed* pPed2 = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pPed1 && pPed2); + pPed1->SetChat(pPed2, ScriptParams[2]); + pPed2->SetChat(pPed1, ScriptParams[2]); + return 0; + } + //case COMMAND_MAKE_PLAYER_SAFE: + case COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + if (ScriptParams[1]) + pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); + else + pVehicle->m_nZoneLevel = LEVEL_GENERIC; + return 0; + } + case COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + if (ScriptParams[1]) + pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); + else + pPed->m_nZoneLevel = LEVEL_GENERIC; + return 0; + } + case COMMAND_REGISTER_4X4_ONE_TIME: + CollectParameters(&m_nIp, 1); + CStats::Register4x4OneTime(ScriptParams[0]); + return 0; + case COMMAND_REGISTER_4X4_TWO_TIME: + CollectParameters(&m_nIp, 1); + CStats::Register4x4TwoTime(ScriptParams[0]); + return 0; + case COMMAND_REGISTER_4X4_THREE_TIME: + CollectParameters(&m_nIp, 1); + CStats::Register4x4ThreeTime(ScriptParams[0]); + return 0; + case COMMAND_REGISTER_4X4_MAYHEM_TIME: + CollectParameters(&m_nIp, 1); + CStats::Register4x4MayhemTime(ScriptParams[0]); + return 0; + case COMMAND_REGISTER_LIFE_SAVED: + CStats::AnotherLifeSavedWithAmbulance(); + return 0; + case COMMAND_REGISTER_CRIMINAL_CAUGHT: + CStats::AnotherCriminalCaught(); + return 0; + case COMMAND_REGISTER_AMBULANCE_LEVEL: + CollectParameters(&m_nIp, 1); + CStats::RegisterLevelAmbulanceMission(ScriptParams[0]); + return 0; + case COMMAND_REGISTER_FIRE_EXTINGUISHED: + CStats::AnotherFireExtinguished(); + return 0; + case COMMAND_TURN_PHONE_ON: + CollectParameters(&m_nIp, 1); + gPhoneInfo.m_aPhones[ScriptParams[0]].m_nState = PHONE_STATE_9; + return 0; + case COMMAND_REGISTER_LONGEST_DODO_FLIGHT: + CollectParameters(&m_nIp, 1); + CStats::RegisterLongestFlightInDodo(ScriptParams[0]); + return 0; + case COMMAND_REGISTER_DEFUSE_BOMB_TIME: + CollectParameters(&m_nIp, 1); + CStats::RegisterTimeTakenDefuseMission(ScriptParams[0]); + return 0; + case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES: + CollectParameters(&m_nIp, 1); + CStats::SetTotalNumberKillFrenzies(ScriptParams[0]); + return 0; + case COMMAND_BLOW_UP_RC_BUGGY: + CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(); + return 0; + case COMMAND_REMOVE_CAR_FROM_CHASE: + CollectParameters(&m_nIp, 1); + CRecordDataForChase::RemoveCarFromChase(ScriptParams[0]); + return 0; + case COMMAND_IS_FRENCH_GAME: + UpdateCompareFlag(CGame::frenchGame); + return 0; + case COMMAND_IS_GERMAN_GAME: + UpdateCompareFlag(CGame::germanGame); + return 0; + case COMMAND_CLEAR_MISSION_AUDIO: + DMAudio.ClearMissionAudio(); + return 0; + case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST: + CollectParameters(&m_nIp, 1); + CRestart::bFadeInAfterNextArrest = !!ScriptParams[0]; + return 0; + case COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH: + CollectParameters(&m_nIp, 1); + CRestart::bFadeInAfterNextDeath = !!ScriptParams[0]; + return 0; + case COMMAND_SET_GANG_PED_MODEL_PREFERENCE: + CollectParameters(&m_nIp, 2); + CGangs::SetGangPedModelOverride(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_SET_CHAR_USE_PEDNODE_SEEK: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + if (ScriptParams[1]) + pPed->m_pNextPathNode = nil; + pPed->bUsePedNodeSeek = !!ScriptParams[1]; + return 0; + } + case COMMAND_SWITCH_VEHICLE_WEAPONS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->bGunSwitchedOff = !ScriptParams[1]; + return 0; + } + case COMMAND_SET_GET_OUT_OF_JAIL_FREE: + CollectParameters(&m_nIp, 2); + CWorld::Players[ScriptParams[0]].m_bGetOutOfJailFree = !!ScriptParams[1]; + return 0; + case COMMAND_SET_FREE_HEALTH_CARE: + CollectParameters(&m_nIp, 2); + CWorld::Players[ScriptParams[0]].m_bGetOutOfHospitalFree = !!ScriptParams[1]; + return 0; + case COMMAND_IS_CAR_DOOR_CLOSED: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(!pVehicle->IsDoorMissing((eDoors)ScriptParams[1]) && pVehicle->IsDoorClosed((eDoors)ScriptParams[1])); + return 0; + } + case COMMAND_LOAD_AND_LAUNCH_MISSION: + return 0; + case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL: + { + CollectParameters(&m_nIp, 1); +#ifdef MISSION_REPLAY + missionRetryScriptIndex = ScriptParams[0]; + if (missionRetryScriptIndex == 19) + CStats::LastMissionPassedName[0] = '\0'; +#endif + CTimer::Suspend(); + int offset = CTheScripts::MultiScriptArray[ScriptParams[0]]; + CFileMgr::ChangeDir("\\"); + int handle = CFileMgr::OpenFile("data\\main.scm", "rb"); + CFileMgr::Seek(handle, offset, 0); + CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT); + CFileMgr::CloseFile(handle); + CRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT); + CTimer::Resume(); + pMissionScript->m_bIsMissionScript = true; + pMissionScript->m_bMissionFlag = true; + CTheScripts::bAlreadyRunningAMissionScript = true; + return 0; + } + case COMMAND_SET_OBJECT_DRAW_LAST: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + pObject->bDrawLast = !!ScriptParams[1]; + return 0; + } + case COMMAND_GET_AMMO_IN_PLAYER_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]]; + if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1]) + ScriptParams[0] = pWeaponSlot->m_nAmmoTotal; + else + ScriptParams[0] = 0; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_AMMO_IN_CHAR_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]]; + if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1]) + ScriptParams[0] = pWeaponSlot->m_nAmmoTotal; + else + ScriptParams[0] = 0; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_REGISTER_KILL_FRENZY_PASSED: + CStats::AnotherKillFrenzyPassed(); + return 0; + case COMMAND_SET_CHAR_SAY: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + switch (ScriptParams[1]) { + case SCRIPT_SOUND_CHUNKY_RUN_SHOUT: + pPed->Say(SOUND_PED_FLEE_RUN); + break; + case SCRIPT_SOUND_SECURITY_GUARD_AWAY_SHOUT: + pPed->Say(SOUND_PED_FLEE_RUN); + break; + case SCRIPT_SOUND_SWAT_PED_SHOUT: + pPed->Say(SOUND_PED_PURSUIT_SWAT); + break; + case SCRIPT_SOUND_AMMUNATION_CHAT_1: + pPed->Say(SOUND_AMMUNATION_WELCOME_1); + break; + case SCRIPT_SOUND_AMMUNATION_CHAT_2: + pPed->Say(SOUND_AMMUNATION_WELCOME_2); + break; + case SCRIPT_SOUND_AMMUNATION_CHAT_3: + pPed->Say(SOUND_AMMUNATION_WELCOME_3); + break; + default: + break; + } + return 0; + } + case COMMAND_SET_NEAR_CLIP: + CollectParameters(&m_nIp, 1); + TheCamera.SetNearClipScript(*(float*)&ScriptParams[0]); + return 0; + case COMMAND_SET_RADIO_CHANNEL: + CollectParameters(&m_nIp, 2); + DMAudio.SetRadioChannel(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_OVERRIDE_HOSPITAL_LEVEL: + CollectParameters(&m_nIp, 1); + CRestart::OverrideHospitalLevel = ScriptParams[0]; + return 0; + case COMMAND_OVERRIDE_POLICE_STATION_LEVEL: + CollectParameters(&m_nIp, 1); + CRestart::OverridePoliceStationLevel = ScriptParams[0]; + return 0; + case COMMAND_FORCE_RAIN: + CollectParameters(&m_nIp, 1); + CWeather::bScriptsForceRain = !!ScriptParams[0]; + return 0; + case COMMAND_DOES_GARAGE_CONTAIN_CAR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pVehicle); + UpdateCompareFlag(CGarages::IsThisCarWithinGarageArea(ScriptParams[0], pVehicle)); + return 0; + } + case COMMAND_SET_CAR_TRACTION: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + float fTraction = *(float*)&ScriptParams[1]; + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR || pVehicle->m_vehType == VEHICLE_TYPE_BIKE); + if (pVehicle->m_vehType == VEHICLE_TYPE_CAR) + ((CAutomobile*)pVehicle)->m_fTraction = fTraction; + else + // this is certainly not a boat, trane, heli or plane field + //((CBike*)pVehicle)->m_fTraction = fTraction; + *(float*)(((char*)pVehicle) + 1088) = fTraction; + return 0; + } + case COMMAND_ARE_MEASUREMENTS_IN_METRES: +#ifdef USE_MEASUREMENTS_IN_METERS + UpdateCompareFlag(true); +#else + UpdateCompareFlag(false) +#endif + return 0; + case COMMAND_CONVERT_METRES_TO_FEET: + { + CollectParameters(&m_nIp, 1); + float fMeterValue = *(float*)&ScriptParams[0]; + float fFeetValue = fMeterValue / METERS_IN_FOOT; + *(float*)&ScriptParams[0] = fFeetValue; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_MARK_ROADS_BETWEEN_LEVELS: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ThePaths.MarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ); + return 0; + } + case COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + ThePaths.PedMarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ); + return 0; + } + case COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->AutoPilot.m_bStayInCurrentLevel = !!ScriptParams[1]; + return 0; + } + case COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pPed); + // not implemented + return 0; + } + case COMMAND_IS_THREAT_FOR_PED_TYPE: + CollectParameters(&m_nIp, 2); + UpdateCompareFlag(CPedType::IsThreat(ScriptParams[0], ScriptParams[1])); + return 0; + case COMMAND_CLEAR_AREA_OF_CHARS: + { + CollectParameters(&m_nIp, 6); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float infZ = *(float*)&ScriptParams[2]; + float supX = *(float*)&ScriptParams[3]; + float supY = *(float*)&ScriptParams[4]; + float supZ = *(float*)&ScriptParams[5]; + if (infX > supX) { + infX = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[0]; + } + if (infY > supY) { + infY = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[1]; + } + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[2]; + } + CWorld::ClearPedsFromArea(infX, infY, infZ, supX, supY, supZ); + return 0; + } + case COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS: + CollectParameters(&m_nIp, 1); + CStats::SetTotalNumberMissions(ScriptParams[0]); + return 0; + case COMMAND_CONVERT_METRES_TO_FEET_INT: + CollectParameters(&m_nIp, 1); + ScriptParams[0] *= FEET_IN_METER; + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_REGISTER_FASTEST_TIME: + CollectParameters(&m_nIp, 2); + CStats::RegisterFastestTime(ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_REGISTER_HIGHEST_SCORE: + CollectParameters(&m_nIp, 2); + CStats::RegisterHighestScore(ScriptParams[0], ScriptParams[1]); + return 0; + //case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER: + //case COMMAND_IS_CAR_PASSENGER_SEAT_FREE: + case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(ScriptParams[1] >= 0 && ScriptParams[1] < ARRAY_SIZE(pVehicle->pPassengers)); + CPed* pPassenger = pVehicle->pPassengers[ScriptParams[1]]; + ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPassenger); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bChrisCriminal = !!ScriptParams[1]; + return 0; + } + case COMMAND_START_CREDITS: + CCredits::Start(); + return 0; + case COMMAND_STOP_CREDITS: + CCredits::Stop(); + return 0; + case COMMAND_ARE_CREDITS_FINISHED: + UpdateCompareFlag(CCredits::AreCreditsDone()); + return 0; + case COMMAND_CREATE_SINGLE_PARTICLE: + CollectParameters(&m_nIp, 8); + CParticle::AddParticle((tParticleType)ScriptParams[0], *(CVector*)&ScriptParams[1], + *(CVector*)&ScriptParams[4], nil, *(float*)&ScriptParams[7], 0, 0, 0, 0); + return 0; + case COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + if (ScriptParams[1]) + pPed->m_nZoneLevel = LEVEL_IGNORE; + else + pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); + return 0; + } + case COMMAND_GET_CHASE_CAR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CRecordDataForChase::TurnChaseCarIntoScriptCar(ScriptParams[0]); + ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle); + StoreParameters(&m_nIp, 1); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CAR); + return 0; + } + case COMMAND_START_BOAT_FOAM_ANIMATION: + CSpecialParticleStuff::StartBoatFoamAnimation(); + return 0; + case COMMAND_UPDATE_BOAT_FOAM_ANIMATION: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CSpecialParticleStuff::UpdateBoatFoamAnimation(&pObject->GetMatrix()); + return 0; + } + case COMMAND_SET_MUSIC_DOES_FADE: + CollectParameters(&m_nIp, 1); + TheCamera.m_bIgnoreFadingStuffForMusic = (ScriptParams[0] == 0); + return 0; + case COMMAND_SET_INTRO_IS_PLAYING: + CollectParameters(&m_nIp, 1); + if (ScriptParams[0]) { + CGame::playingIntro = true; + CStreaming::RemoveCurrentZonesModels(); + } else { + CGame::playingIntro = false; + DMAudio.ChangeMusicMode(MUSICMODE_GAME); + int mi; + CModelInfo::GetModelInfo("bridgefukb", &mi); + CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY); + CStreaming::LoadAllRequestedModels(false); + } + return 0; + case COMMAND_SET_PLAYER_HOOKER: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + if (ScriptParams[1] < 0) { + pPlayerInfo->m_pHooker = nil; + pPlayerInfo->m_nNextSexFrequencyUpdateTime = 0; + pPlayerInfo->m_nNextSexMoneyUpdateTime = 0; + } else { + CPed* pHooker = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pHooker); + pPlayerInfo->m_pHooker = (CCivilianPed*)pHooker; + pPlayerInfo->m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000; + pPlayerInfo->m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; + } + return 0; + } + case COMMAND_PLAY_END_OF_GAME_TUNE: + DMAudio.PlayPreloadedCutSceneMusic(); + return 0; + case COMMAND_STOP_END_OF_GAME_TUNE: + DMAudio.StopCutSceneMusic(); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); + return 0; + case COMMAND_GET_CAR_MODEL: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + ScriptParams[0] = pVehicle->GetModelIndex(); + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_IS_PLAYER_SITTING_IN_CAR: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pVehicle); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle); + return 0; + } + case COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR: + { + CollectParameters(&m_nIp, 1); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING); + return 0; + } + case COMMAND_SET_SCRIPT_FIRE_AUDIO: + CollectParameters(&m_nIp, 2); + gFireManager.SetScriptFireAudio(ScriptParams[0], !!ScriptParams[1]); + return 0; + case COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED: + UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3); + return 0; + case COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->bNoCriticalHits = (ScriptParams[0] == 0); + return 0; + } + case COMMAND_IS_PLAYER_LIFTING_A_PHONE: + { + CollectParameters(&m_nIp, 1); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + UpdateCompareFlag(pPed->GetPedState() == PED_MAKE_CALL); + return 0; + } + case COMMAND_IS_CHAR_SITTING_IN_CAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pVehicle); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle); + return 0; + } + case COMMAND_IS_CHAR_SITTING_IN_ANY_CAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING); + return 0; + } + case COMMAND_IS_PLAYER_ON_FOOT: + { + CollectParameters(&m_nIp, 1); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && + pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER); + return 0; + } + case COMMAND_IS_CHAR_ON_FOOT: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && + pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER); + return 0; + } +#ifndef GTA_PS2 + default: + script_assert(0); + } + return -1; +} + +int8 CRunningScript::ProcessCommands1100To1199(int32 command) +{ + char tmp[48]; + switch (command) { +#endif + case COMMAND_LOAD_COLLISION_WITH_SCREEN: + CollectParameters(&m_nIp, 1); + CTimer::Stop(); + CGame::currLevel = (eLevelName)ScriptParams[0]; + if (CGame::currLevel != CCollision::ms_collisionInMemory) { + ISLAND_LOADING_IS(LOW) + { + DMAudio.SetEffectsFadeVol(0); + CPad::StopPadsShaking(); + CCollision::LoadCollisionScreen(CGame::currLevel); + DMAudio.Service(); + } + CPopulation::DealWithZoneChange(CCollision::ms_collisionInMemory, CGame::currLevel, false); + + ISLAND_LOADING_IS(LOW) + { + CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); + CStreaming::RemoveUnusedBuildings(CGame::currLevel); + } + CCollision::SortOutCollisionAfterLoad(); + + ISLAND_LOADING_ISNT(HIGH) + CStreaming::RequestIslands(CGame::currLevel); + + ISLAND_LOADING_IS(LOW) + CStreaming::RequestBigBuildings(CGame::currLevel); + + ISLAND_LOADING_ISNT(HIGH) + CStreaming::LoadAllRequestedModels(true); + + ISLAND_LOADING_IS(LOW) + DMAudio.SetEffectsFadeVol(127); + } + CTimer::Update(); + return 0; + case COMMAND_LOAD_SPLASH_SCREEN: + CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + tmp[i] = tolower(tmp[i]); + m_nIp += 8; + LoadSplash(tmp); + return 0; + case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + if (ScriptParams[1]) + pVehicle->m_nZoneLevel = LEVEL_IGNORE; + else + pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); + return 0; + } + case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); + CAutomobile* pCar = (CAutomobile*)pVehicle; + pCar->bMoreResistantToDamage = ScriptParams[1]; + return 0; + } + case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), false); + return 0; + } + case COMMAND_LOAD_END_OF_GAME_TUNE: + DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE); + printf("Start preload end of game audio\n"); + DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED); + printf("End preload end of game audio\n"); + return 0; + case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA: + CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CAMERA); + return 0; +#ifndef GTA_PS2 + // To be precise, on PS2 previous handlers were in 1000-1099 function + // These are "beta" VC commands (with bugs) + case COMMAND_SET_OBJECT_ROTATION: + { + CollectParameters(&m_nIp, 4); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CWorld::Remove(pObject); + pObject->SetOrientation( + DEGTORAD(*(float*)&ScriptParams[1]), + DEGTORAD(*(float*)&ScriptParams[2]), + DEGTORAD(*(float*)&ScriptParams[3])); + pObject->GetMatrix().UpdateRW(); + pObject->UpdateRwFrame(); + CWorld::Add(pObject); + return 0; + } + case COMMAND_GET_DEBUG_CAMERA_COORDINATES: + *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source; + StoreParameters(&m_nIp, 3); + return 0; + case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR: + *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front; + StoreParameters(&m_nIp, 3); + return 0; + case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR: + { + CollectParameters(&m_nIp, 1); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CEntity* pTarget = pPed->m_pPointGunAt; + UpdateCompareFlag(pTarget && pTarget->IsPed()); + return 0; + } + case COMMAND_IS_PLAYER_TARGETTING_CHAR: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + script_assert(pTestedPed); + CEntity* pTarget = pPed->m_pPointGunAt; + UpdateCompareFlag(pTarget && pTarget->IsPed() && pTarget == pTestedPed); + return 0; + } + case COMMAND_IS_PLAYER_TARGETTING_OBJECT: + { + CollectParameters(&m_nIp, 2); + CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + CObject* pTestedObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); + script_assert(pTestedObject); + CEntity* pTarget = pPed->m_pPointGunAt; + UpdateCompareFlag(pTarget && pTarget->IsObject() && pTarget == pTestedObject); + return 0; + } + case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME: + { + CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp); + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + tmp[i] = tolower(tmp[i]); + m_nIp += 8; + CRunningScript* pScript = CTheScripts::pActiveScripts; + while (pScript) { + CRunningScript* pNext = pScript->next; + if (strcmp(pScript->m_abScriptName, tmp) == 0) { + pScript->RemoveScriptFromList(&CTheScripts::pActiveScripts); + pScript->AddScriptToList(&CTheScripts::pIdleScripts); + } + pScript = pNext; + } + return 0; + } + case COMMAND_DISPLAY_TEXT_WITH_NUMBER: + { + CollectParameters(&m_nIp, 2); + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0]; + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1]; + CollectParameters(&m_nIp, 1); + CMessages::InsertNumberInString(text, ScriptParams[0], -1, -1, -1, -1, -1, + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text); + return 0; + } + case COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS: + { + CollectParameters(&m_nIp, 2); + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0]; + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1]; + CollectParameters(&m_nIp, 2); + CMessages::InsertNumberInString(text, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1, + CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text); + return 0; + } + case COMMAND_FAIL_CURRENT_MISSION: + CTheScripts::FailCurrentMission = 2; + return 0; + case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float range = *(float*)&ScriptParams[3]; + int mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4]; + int16 total; + CEntity* apEntities[16]; + CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true); + CEntity* pClosestEntity = nil; + float min_dist = 2.0f * range; + for (int i = 0; i < total; i++) { + float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); + if (dist < min_dist) { + min_dist = dist; + pClosestEntity = apEntities[i]; + } + } + if (pClosestEntity && pClosestEntity->IsDummy()) { + CPopulation::ConvertToRealObject((CDummyObject*)pClosestEntity); + CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true); + pClosestEntity = nil; + float min_dist = 2.0f * range; + for (int i = 0; i < total; i++) { + float dist = (apEntities[i]->GetPosition() - pos).Magnitude(); + if (dist < min_dist) { + min_dist = dist; + pClosestEntity = apEntities[i]; + } + } + if (pClosestEntity->IsDummy()) + pClosestEntity = nil; + } + if (pClosestEntity) { + script_assert(pClosestEntity->IsObject()); + CObject* pObject = (CObject*)pClosestEntity; + pObject->ObjectCreatedBy = MISSION_OBJECT; + ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObject); + } else { + ScriptParams[0] = -1; + } + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT: + { + CollectParameters(&m_nIp, 5); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + script_assert(pObject); + CObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]); + script_assert(pTarget); + CVector offset = *(CVector*)&ScriptParams[2]; + CPhysical::PlacePhysicalRelativeToOtherPhysical(pTarget, pObject, offset); + return 0; + } + case COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + if (pVehicle->pDriver) { + pVehicle->pDriver->bScriptObjectiveCompleted = false; + pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); + } + for (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++) + { + if (pVehicle->pPassengers[i]) { + pVehicle->pPassengers[i]->bScriptObjectiveCompleted = false; + pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); + } + } + return 0; + } + case COMMAND_SET_INTERPOLATION_PARAMETERS: + CollectParameters(&m_nIp, 2); + TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 50.0f - *(float*)&ScriptParams[0], ScriptParams[1]); + return 0; + case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float destX = *(float*)&ScriptParams[3]; + float destY = *(float*)&ScriptParams[4]; + int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); + CPathNode* pNode = &ThePaths.m_pathNodes[nid]; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); + *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true); + StoreParameters(&m_nIp, 4); + return 0; + } + case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float destX = *(float*)&ScriptParams[3]; + float destY = *(float*)&ScriptParams[4]; + int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); + CPathNode* pNode = &ThePaths.m_pathNodes[nid]; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); + *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false); + StoreParameters(&m_nIp, 4); + return 0; + } + case COMMAND_GET_DEBUG_CAMERA_POINT_AT: + *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source + TheCamera.Cams[2].Front; + StoreParameters(&m_nIp, 3); + return 0; + case COMMAND_ATTACH_CHAR_TO_CAR: + // empty implementation + return 0; + case COMMAND_DETACH_CHAR_FROM_CAR: + // empty implementation + return 0; + case COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->AutoPilot.m_bStayInFastLane = !ScriptParams[1]; + return 0; + } + case COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + pPed->m_lastWepDam = -1; + return 0; + } + case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + pVehicle->m_nLastWeaponDamage = -1; + return 0; + } + case COMMAND_GET_RANDOM_COP_IN_AREA: + { + CollectParameters(&m_nIp, 4); + int ped_handle = -1; + CVector pos = FindPlayerCoors(); + float x1 = *(float*)&ScriptParams[0]; + float y1 = *(float*)&ScriptParams[1]; + float x2 = *(float*)&ScriptParams[2]; + float y2 = *(float*)&ScriptParams[3]; + int i = CPools::GetPedPool()->GetSize(); + while (--i && ped_handle == -1) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) + continue; + if (pPed->m_nPedType != PEDTYPE_COP) + continue; + if (pPed->CharCreatedBy != RANDOM_CHAR) + continue; + if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING) + continue; + if (pPed->bRemoveFromWorld) + continue; + if (pPed->bFadeOut) + continue; + if (pPed->bIsLeader || pPed->m_leader) + continue; + if (!pPed->IsWithinArea(x1, y1, x2, y2)) + continue; + if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) + continue; + if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) + continue; + ped_handle = CPools::GetPedPool()->GetIndex(pPed); + CTheScripts::LastRandomPedId = ped_handle; + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + ++CPopulation::ms_nTotalMissionPeds; + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); + } + ScriptParams[0] = ped_handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_RANDOM_COP_IN_ZONE: + { + char zone[KEY_LENGTH_IN_SCRIPT]; + strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone); + if (nZone != -1) + m_nIp += KEY_LENGTH_IN_SCRIPT; + CZone* pZone = CTheZones::GetZone(nZone); + int ped_handle = -1; + CVector pos = FindPlayerCoors(); + int i = CPools::GetPedPool()->GetSize(); + while (--i && ped_handle == -1) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) + continue; + if (pPed->m_nPedType != PEDTYPE_COP) + continue; + if (pPed->CharCreatedBy != RANDOM_CHAR) + continue; + if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING) + continue; + if (pPed->bRemoveFromWorld) + continue; + if (pPed->bFadeOut) + continue; + if (pPed->bIsLeader || pPed->m_leader) + continue; + if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone)) + continue; + if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) + continue; + if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) + continue; + ped_handle = CPools::GetPedPool()->GetIndex(pPed); + CTheScripts::LastRandomPedId = ped_handle; + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + ++CPopulation::ms_nTotalMissionPeds; + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); + } + ScriptParams[0] = ped_handle; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_SET_CHAR_OBJ_FLEE_CAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + script_assert(pVehicle); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FLEE_CAR, pVehicle); + return 0; + } + case COMMAND_GET_DRIVER_OF_CAR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + CPed* pDriver = pVehicle->pDriver; + if (pDriver) + ScriptParams[0] = CPools::GetPedPool()->GetIndex(pDriver); + else + ScriptParams[0] = -1; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_NUMBER_OF_FOLLOWERS: + { + CollectParameters(&m_nIp, 1); + CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pLeader); + int total = 0; + int i = CPools::GetPedPool()->GetSize(); + while (--i) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + if (pPed->m_leader == pLeader) + total++; + } + ScriptParams[0] = total; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER: + { + CollectParameters(&m_nIp, 6); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4]), ScriptParams[5]); + return 0; + } + case COMMAND_GET_CURRENT_PLAYER_WEAPON: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_GET_CURRENT_CHAR_WEAPON: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D: + case COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D: + LocateCharObjectCommand(command, &m_nIp); + return 0; + case COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT: // this will be changed in final VC version to a more general SET_TEMP_ACTION + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNLEFT; + pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; + return 0; + } + case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNRIGHT; + pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; + return 0; + } + case COMMAND_SET_CAR_HANDBRAKE_STOP: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT; + pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; + return 0; + } + case COMMAND_IS_CHAR_ON_ANY_BIKE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE); + return 0; + } + case COMMAND_LOCATE_SNIPER_BULLET_2D: + case COMMAND_LOCATE_SNIPER_BULLET_3D: + LocateSniperBulletCommand(command, &m_nIp); + return 0; + case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL: + CollectParameters(&m_nIp, 1); + ScriptParams[0] = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(ScriptParams[0]) + 1; + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_IS_PLAYER_ON_ANY_BIKE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + script_assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE); + return 0; + } + case COMMAND_IS_CHAR_LYING_DOWN: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + UpdateCompareFlag(pPed->bFallenDown); + return 0; + } + case COMMAND_CAN_CHAR_SEE_DEAD_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + script_assert(pPed); + int pedtype = ScriptParams[1]; + bool can = false; + for (int i = 0; i < pPed->m_numNearPeds; i++) { + CPed* pTestPed = pPed->m_nearPeds[i]; + if (pTestPed->m_fHealth <= 0.0f && pTestPed->m_nPedType == pedtype && pPed->OurPedCanSeeThisOne(pTestPed)) + can = true; + } + UpdateCompareFlag(can); + return 0; + } + case COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER: + CollectParameters(&m_nIp, 1); +#ifdef FIX_BUGS + CPed::nEnterCarRangeMultiplier = *(float*)&ScriptParams[0]; +#else + CPed::nEnterCarRangeMultiplier = (float)ScriptParams[0]; +#endif + return 0; +#endif +#ifndef GTA3_1_1_PATCH + case COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER: + CollectParameters(&m_nIp, 1); +#ifdef FIX_BUGS + CPed::nThreatReactionRangeMultiplier = *(float*)&ScriptParams[0]; +#else + CPed::nThreatReactionRangeMultiplier = (float)ScriptParams[0]; +#endif + return 0; +#endif + default: + script_assert(0); + } + return -1; +} -- cgit v1.2.3 From 70d8bdc0879c341f2d020544ef3b807bdee89833 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 24 Nov 2020 15:20:41 +0100 Subject: rename badly named camera variable --- src/core/Camera.cpp | 6 +++--- src/core/Camera.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 13d03213..56225fed 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -123,7 +123,7 @@ CCamera::Init(void) Cams[0].Mode = CCam::MODE_FOLLOWPED; Cams[1].Mode = CCam::MODE_FOLLOWPED; unknown = 0; - m_bJustJumpedOutOf1stPersonBecauseOfTarget = false; + m_bUnknown = false; ClearPlayerWeaponMode(); m_bInATunnelAndABigVehicle = false; m_iModeObbeCamIsInForCar = OBBE_INVALID; @@ -3398,10 +3398,10 @@ CCamera::Fade(float timeout, int16 direction) m_fTimeToFadeMusic = timeout; m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds(); // Not on PS2 - if(!m_bJustJumpedOutOf1stPersonBecauseOfTarget && m_iMusicFadingDirection == FADE_OUT){ + if(!m_bUnknown && m_iMusicFadingDirection == FADE_OUT){ unknown++; if(unknown >= 2){ - m_bJustJumpedOutOf1stPersonBecauseOfTarget = true; + m_bUnknown = true; unknown = 0; }else m_bMoveCamToAvoidGeom = true; diff --git a/src/core/Camera.h b/src/core/Camera.h index dd78d952..0797db9b 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -348,7 +348,7 @@ public: bool m_bcutsceneFinished; bool m_bCullZoneChecksOn; bool m_bFirstPersonBeingUsed; - bool m_bJustJumpedOutOf1stPersonBecauseOfTarget; + bool m_bUnknown; bool m_bIdleOn; bool m_bInATunnelAndABigVehicle; bool m_bInitialNodeFound; -- cgit v1.2.3 From 88baa9ce5f22a788a1033040040185001a87f922 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 25 Nov 2020 20:03:44 +0100 Subject: implemented CMemoryHeap, not used or tested yet --- src/rw/MemoryHeap.cpp | 548 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/rw/MemoryHeap.h | 188 +++++++++++++++++ 2 files changed, 736 insertions(+) create mode 100644 src/rw/MemoryHeap.cpp create mode 100644 src/rw/MemoryHeap.h (limited to 'src') diff --git a/src/rw/MemoryHeap.cpp b/src/rw/MemoryHeap.cpp new file mode 100644 index 00000000..d613a708 --- /dev/null +++ b/src/rw/MemoryHeap.cpp @@ -0,0 +1,548 @@ +#include "common.h" +#include "main.h" +#include "FileMgr.h" +#include "Timer.h" +#include "ModelInfo.h" +#include "Streaming.h" +#include "FileLoader.h" +#include "MemoryHeap.h" + +#ifdef USE_CUSTOM_ALLOCATOR + +#define MEMORYHEAP_ASSERT(cond) { if (!(cond)) { printf("ASSERT File:%s Line:%d\n", __FILE__, __LINE__); exit(1); } } +#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) { if (!(cond)) { printf("ASSERT File:%s Line:%d:\n\t%s\n", __FILE__, __LINE__, message); exit(1); } } + +// registered pointers that we keep track of +void **gPtrList[4000]; +int32 numPtrs; +int32 gPosnInList; +// indices into the ptr list in here are free +CStack m_ptrListIndexStack; +// how much memory we've moved +uint32 memMoved; + +CMemoryHeap gMainHeap; + +void +CMemoryHeap::Init(uint32 total) +{ + MEMORYHEAP_ASSERT((total != 0xF) != 0); + + m_totalMemUsed = 0; + m_memUsed = nil; + m_currentMemID = MEMID_FREE; + m_blocksUsed = nil; + m_totalBlocksUsed = 0; + m_unkMemId = -1; + + uint8 *mem = (uint8*)malloc(total); + assert(((uintptr)mem & 0xF) == 0); + m_start = (HeapBlockDesc*)mem; + m_end = (HeapBlockDesc*)(mem + total - sizeof(HeapBlockDesc)); + m_start->m_memId = MEMID_FREE; + m_start->m_size = total - 2*sizeof(HeapBlockDesc); + m_end->m_memId = MEMID_ID1; + m_end->m_size = 0; + + m_freeList.m_last.m_size = INT_MAX; + m_freeList.Init(); + m_freeList.Insert(m_start); + + // TODO: figure out what these are and use sizeof + m_fixedSize[0].Init(0x10); + m_fixedSize[1].Init(0x20); + m_fixedSize[2].Init(0xE0); + m_fixedSize[3].Init(0x60); + m_fixedSize[4].Init(0x1C0); + m_fixedSize[5].Init(0x50); + + m_currentMemID = MEMID_FREE; // disable registration + m_memUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32)); + m_blocksUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32)); + RegisterMalloc(GetDescFromHeapPointer(m_memUsed)); + RegisterMalloc(GetDescFromHeapPointer(m_blocksUsed)); + + m_currentMemID = MEMID_ID1; + for(int i = 0; i < NUM_MEMIDS; i++){ + m_memUsed[i] = 0; + m_blocksUsed[i] = 0; + } +} + +void +CMemoryHeap::RegisterMalloc(HeapBlockDesc *block) +{ + block->m_memId = m_currentMemID; + if(m_currentMemID == MEMID_FREE) + return; + m_totalMemUsed += block->m_size + sizeof(HeapBlockDesc); + m_memUsed[m_currentMemID] += block->m_size + sizeof(HeapBlockDesc); + m_blocksUsed[m_currentMemID]++; + m_totalBlocksUsed++; +} + +void +CMemoryHeap::RegisterFree(HeapBlockDesc *block) +{ + if(block->m_memId == MEMID_FREE) + return; + m_totalMemUsed -= block->m_size + sizeof(HeapBlockDesc); + m_memUsed[m_currentMemID] -= block->m_size + sizeof(HeapBlockDesc); + m_blocksUsed[m_currentMemID]--; + m_totalBlocksUsed--; +} + +void* +CMemoryHeap::Malloc(uint32 size) +{ + static int recursion = 0; + + // weird way to round up + if((size & 0xF) != 0) + size = (size&~0xF) + 0x10; + + recursion++; + + // See if we can allocate from one of the fixed-size lists + for(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){ + CommonSize *list = &m_fixedSize[i]; + if(m_fixedSize[i].m_size == size){ + HeapBlockDesc *block = list->Malloc(); + if(block){ + RegisterMalloc(block); + recursion--; + return block->GetDataPointer(); + } + break; + } + } + + // now try the normal free list + HeapBlockDesc *next; + for(HeapBlockDesc *block = m_freeList.m_first.m_next; + block != &m_freeList.m_last; + block = next){ + MEMORYHEAP_ASSERT(block->m_memId == MEMID_FREE); + MEMORYHEAP_ASSERT_MESSAGE(block >= m_start && block <= m_end, "Block outside of memory"); + + // make sure block has maximum size + uint32 initialsize = block->m_size; + uint32 blocksize = CombineFreeBlocks(block); +#ifdef FIX_BUGS + // has to be done here because block can be moved + next = block->m_next; +#endif + if(initialsize != blocksize){ + block->RemoveHeapFreeBlock(); + HeapBlockDesc *pos = block->m_prev->FindSmallestFreeBlock(block->m_size); + block->InsertHeapFreeBlock(pos->m_prev); + } + if(block->m_size >= size){ + // got space to allocate from! + block->RemoveHeapFreeBlock(); + FillInBlockData(block, block->GetNextConsecutive(), size); + recursion--; + return block->GetDataPointer(); + } +#ifndef FIX_BUGS + next = block->m_next; +#endif + } + + // oh no, we're losing, try to free some stuff + static bool removeCollision = false; + static bool removeIslands = false; + static bool removeBigBuildings = false; + size_t initialMemoryUsed = CStreaming::ms_memoryUsed; + CStreaming::MakeSpaceFor(0xCFE800 - CStreaming::ms_memoryUsed); + if (recursion > 10) + CGame::TidyUpMemory(true, false); + else if (recursion > 6) + CGame::TidyUpMemory(false, true); + if (initialMemoryUsed == CStreaming::ms_memoryUsed && recursion > 11) { + if (!removeCollision && !CGame::playingIntro) { + CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC); + removeCollision = true; + } + else if (!removeIslands && !CGame::playingIntro) { + CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); + CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); + CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); + removeIslands = true; + } + else if (!removeBigBuildings) { + CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL); + CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL); + CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN); + } + else { + LoadingScreen("NO MORE MEMORY", nil, nil); + LoadingScreen("NO MORE MEMORY", nil, nil); + } + CGame::TidyUpMemory(true, false); + } + void *mem = Malloc(size); + if (removeCollision) { + CTimer::Stop(); + // different on PS2 + CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory); + removeCollision = false; + CTimer::Update(); + } + if (removeBigBuildings || removeIslands) { + CTimer::Stop(); + if (!CGame::playingIntro) + CStreaming::RequestBigBuildings(CGame::currLevel); + CStreaming::LoadAllRequestedModels(true); + removeBigBuildings = false; + removeIslands = false; + CTimer::Update(); + } + recursion--; + return mem; +} + +void* +CMemoryHeap::Realloc(void *ptr, uint32 size) +{ + if(ptr == nil) + return Malloc(size); + + // weird way to round up + if((size & 0xF) != 0) + size = (size&~0xF) + 0x10; + + HeapBlockDesc *block = GetDescFromHeapPointer(ptr); + +#ifdef FIX_BUGS + // better handling of size < block->m_size + if(size == 0){ + Free(ptr); + return nil; + } + if(block->m_size >= size){ + // shrink allocated block + RegisterFree(block); + PushMemId(block->m_memId); + FillInBlockData(block, block->GetNextConsecutive(), size); + PopMemId(); + return ptr; + } +#else + // not growing. just returning here is a bit cheap though + if(block->m_size >= size) + return ptr; +#endif + + // have to grow allocated block + HeapBlockDesc *next = block->GetNextConsecutive(); + MEMORYHEAP_ASSERT_MESSAGE(next >= m_start && next <= m_end, "Block outside of memory"); + if(next->m_memId == MEMID_FREE){ + // try to grow the current block + // make sure the next free block has maximum size + uint32 freespace = CombineFreeBlocks(next); + HeapBlockDesc *end = next->GetNextConsecutive(); + MEMORYHEAP_ASSERT_MESSAGE(end >= m_start && end <= m_end, "Block outside of memory"); + // why the sizeof here? + if(block->m_size + next->m_size + sizeof(HeapBlockDesc) >= size){ + // enough space to grow + next->RemoveHeapFreeBlock(); + RegisterFree(block); + PushMemId(block->m_memId); + FillInBlockData(block, next->GetNextConsecutive(), size); + PopMemId(); + return ptr; + } + } + + // can't grow the existing block, have to get a new one and copy + PushMemId(block->m_memId); + void *dst = Malloc(size); + PopMemId(); + memcpy(dst, ptr, block->m_size); + Free(ptr); + return dst; +} + +void +CMemoryHeap::Free(void *ptr) +{ + HeapBlockDesc *block = GetDescFromHeapPointer(ptr); + MEMORYHEAP_ASSERT_MESSAGE(block->m_memId != MEMID_FREE, "MemoryHeap corrupt"); + MEMORYHEAP_ASSERT(m_unkMemId == -1 || m_unkMemId == block->m_memId); + + RegisterFree(block); + CombineFreeBlocks(block); + FreeBlock(block); + if(block->m_ptrListIndex != -1){ + int32 idx = block->m_ptrListIndex; + gPtrList[idx] = nil; + m_ptrListIndexStack.push(idx); + } + block->m_ptrListIndex = -1; +} + +// allocate 'size' bytes from 'block' +void +CMemoryHeap::FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size) +{ + block->m_size = size; + block->m_ptrListIndex = -1; + HeapBlockDesc *remainder = block->GetNextConsecutive(); + MEMORYHEAP_ASSERT(remainder <= end); + + if(remainder < end-1){ + RegisterMalloc(block); + + // can fit another block in the remaining space + remainder->m_size = GetSizeBetweenBlocks(remainder, end); + remainder->m_memId = MEMID_FREE; + MEMORYHEAP_ASSERT(remainder->m_size != 0); + FreeBlock(remainder); + }else{ + // fully allocate this one + if(remainder < end) + // no gaps allowed + block->m_size = GetSizeBetweenBlocks(block, end); + RegisterMalloc(block); + } +} + +// Make sure free block has no other free blocks after it +uint32 +CMemoryHeap::CombineFreeBlocks(HeapBlockDesc *block) +{ + HeapBlockDesc *next = block->GetNextConsecutive(); + if(next->m_memId == MEMID_FREE) + return block->m_size; + // get rid of free blocks after this one and adjust size + for(; next->m_memId == MEMID_FREE; next = next->GetNextConsecutive()) + next->RemoveHeapFreeBlock(); + block->m_size = GetSizeBetweenBlocks(block, next); + return block->m_size; +} + +// Try to move all registered memory blocks into more optimal location +void +CMemoryHeap::TidyHeap(void) +{ + for(int i = 0; i < numPtrs; i++){ + if(gPtrList[i] == nil || *gPtrList[i] == nil) + continue; + HeapBlockDesc *newblock = WhereShouldMemoryMove(*gPtrList[i]); + if(newblock) + *gPtrList[i] = MoveHeapBlock(newblock, GetDescFromHeapPointer(*gPtrList[i])); + } +} + +// +void +CMemoryHeap::RegisterMemPointer(void *ptr) +{ + HeapBlockDesc *block = GetDescFromHeapPointer(*(void**)ptr); + + if(block->m_ptrListIndex != -1) + return; // already registered + + int index; + if(m_ptrListIndexStack.sp > 0){ + // re-use a previously free'd index + index = m_ptrListIndexStack.pop(); + }else{ + // have to find a new index + index = gPosnInList; + + void **pp = gPtrList[index]; + // we're replacing an old pointer here?? + if(pp && *pp && *pp != (void*)0xDDDDDDDD) + GetDescFromHeapPointer(*pp)->m_ptrListIndex = -1; + + gPosnInList++; + if(gPosnInList == 4000) + gPosnInList = 0; + if(numPtrs < 4000) + numPtrs++; + } + gPtrList[index] = (void**)ptr; + block->m_ptrListIndex = index; +} + +void* +CMemoryHeap::MoveMemory(void *ptr) +{ + HeapBlockDesc *newblock = WhereShouldMemoryMove(ptr); + if(newblock) + return MoveHeapBlock(newblock, GetDescFromHeapPointer(ptr)); + else + return ptr; +} + +HeapBlockDesc* +CMemoryHeap::WhereShouldMemoryMove(void *ptr) +{ + HeapBlockDesc *block = GetDescFromHeapPointer(ptr); + MEMORYHEAP_ASSERT(block->m_memId != MEMID_FREE); + + HeapBlockDesc *next = block->GetNextConsecutive(); + if(next->m_memId != MEMID_FREE) + return nil; + + // we want to move the block into another block + // such that the free space between this and the next block can be minimized + HeapBlockDesc *newblock = m_freeList.m_first.FindSmallestFreeBlock(block->m_size); + // size of free space wouldn't decrease, so return + if(newblock->m_size >= block->m_size + next->m_size) + return nil; + // size of free space wouldn't decrease enough + if(newblock->m_size >= 16 + 1.125f*block->m_size) // what are 16 and 1.125 here? sizeof(HeapBlockDesc)? + return nil; + return newblock; +} + +void* +CMemoryHeap::MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src) +{ + PushMemId(src->m_memId); + dst->RemoveHeapFreeBlock(); + FillInBlockData(dst, dst->GetNextConsecutive(), src->m_size); + PopMemId(); + memcpy(dst->GetDataPointer(), src->GetDataPointer(), src->m_size); + memMoved += src->m_size; + dst->m_ptrListIndex = src->m_ptrListIndex; + src->m_ptrListIndex = -1; + Free(src->GetDataPointer()); + return dst->GetDataPointer(); +} + +uint32 +CMemoryHeap::GetMemoryUsed(int32 id) +{ + return m_memUsed[id]; +} + +uint32 +CMemoryHeap::GetBlocksUsed(int32 id) +{ + return m_blocksUsed[id]; +} + +void +CMemoryHeap::PopMemId(void) +{ + m_currentMemID = m_idStack.pop(); +} + +void +CMemoryHeap::PushMemId(int32 id) +{ + MEMORYHEAP_ASSERT(id != MEMID_FREE); + m_idStack.push(m_currentMemID); + m_currentMemID = id; +} + +void +CMemoryHeap::ParseHeap(void) +{ + char tmp[16]; + int fd = CFileMgr::OpenFileForWriting("heap.txt"); + CTimer::Stop(); + + // CMemoryHeap::IntegrityCheck(); + + uint32 addrQW = 0; + for(HeapBlockDesc *block = m_start; block < m_end; block = block->GetNextConsecutive()){ + char chr = '*'; // free + if(block->m_memId != MEMID_FREE) + chr = block->m_memId-MEMID_ID1 + 'A'; + int numQW = block->m_size>>4; + + if((addrQW & 0x3F) == 0){ + sprintf(tmp, "\n%5dK:", addrQW>>6); + CFileMgr::Write(fd, tmp, 8); + } + CFileMgr::Write(fd, "#", 1); // the descriptor, has to be 16 bytes!!!! + addrQW++; + + while(numQW--){ + if((addrQW & 0x3F) == 0){ + sprintf(tmp, "\n%5dK:", addrQW>>6); + CFileMgr::Write(fd, tmp, 8); + } + CFileMgr::Write(fd, &chr, 1); + addrQW++; + } + } + + CTimer::Update(); + CFileMgr::CloseFile(fd); +} + + +void +CommonSize::Init(uint32 size) +{ + m_freeList.Init(); + m_size = size; + m_failed = 0; + m_remaining = 0; +} + + + +void *pMemoryTop; + +void +InitMemoryMgr(void) +{ +#ifdef GTA_PS2 +#error "finish this" +#else + // randomly allocate 128mb + gMainHeap.Init(128*1024*1024); +#endif +} + +void* +MemoryMgrMalloc(uint32 size) +{ + void *mem = gMainHeap.Malloc(size); + if(mem > pMemoryTop) + pMemoryTop = mem; + return mem; +} + +void* +MemoryMgrRealloc(void *ptr, uint32 size) +{ + void *mem = gMainHeap.Realloc(ptr, size); + if(mem > pMemoryTop) + pMemoryTop = mem; + return mem; +} + +void* +MemoryMgrCalloc(uint32 num, uint32 size) +{ + void *mem = gMainHeap.Malloc(num*size); + if(mem > pMemoryTop) + pMemoryTop = mem; +#ifdef FIX_BUGS + memset(mem, 0, num*size); +#endif + return mem; +} + +void +MemoryMgrFree(void *ptr) +{ + gMainHeap.Free(ptr); +} + +RwMemoryFunctions memFuncs = { + MemoryMgrMalloc, + MemoryMgrFree, + MemoryMgrRealloc, + MemoryMgrCalloc +}; + +#endif diff --git a/src/rw/MemoryHeap.h b/src/rw/MemoryHeap.h new file mode 100644 index 00000000..840e016a --- /dev/null +++ b/src/rw/MemoryHeap.h @@ -0,0 +1,188 @@ +#pragma once + +extern RwMemoryFunctions memFuncs; + +template +class CStack +{ +public: + T values[N]; + uint32 sp; + + CStack() : sp(0) {} + void push(const T& val) { values[sp++] = val; } + T& pop() { return values[sp--]; } +}; + + +struct HeapBlockDesc +{ + uint32 m_size; + int16 m_memId; + int16 m_ptrListIndex; + HeapBlockDesc *m_next; + HeapBlockDesc *m_prev; + + HeapBlockDesc *GetNextConsecutive(void) + { + return (HeapBlockDesc*)((uintptr)this + sizeof(HeapBlockDesc) + m_size); + } + + void *GetDataPointer(void) + { + return (void*)((uintptr)this + sizeof(HeapBlockDesc)); + } + + void RemoveHeapFreeBlock(void) + { + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + + // after node + void InsertHeapFreeBlock(HeapBlockDesc *node) + { + m_next = node->m_next; + node->m_next->m_prev = this; + m_prev = node; + node->m_next = this; + } + + HeapBlockDesc *FindSmallestFreeBlock(uint32 size) + { + HeapBlockDesc *b; + for(b = m_next; b->m_size < size; b = b->m_next); + return b; + } +}; + +static_assert(sizeof(HeapBlockDesc) == 0x10, "HeapBlockDesc must have 0x10 size otherwise most of assumptions don't make sense"); + +struct HeapBlockList +{ + HeapBlockDesc m_first; + HeapBlockDesc m_last; + + void Init(void) + { + m_first.m_next = &m_last; + m_last.m_prev = &m_first; + } + + void Insert(HeapBlockDesc *node) + { + node->InsertHeapFreeBlock(&m_first); + } +}; + +struct CommonSize +{ + HeapBlockList m_freeList; + uint32 m_size; + uint32 m_failed; + uint32 m_remaining; + + void Init(uint32 size); + void Free(HeapBlockDesc *node) + { + m_freeList.Insert(node); + m_remaining++; + } + HeapBlockDesc *Malloc(void) + { + if(m_freeList.m_first.m_next == &m_freeList.m_last){ + m_failed++; + return nil; + } + HeapBlockDesc *block = m_freeList.m_first.m_next; + m_remaining--; + block->RemoveHeapFreeBlock(); + block->m_ptrListIndex = -1; + return block; + } +}; + +enum { + MEMID_FREE, + // IDs from LCS: + MEMID_ID1, // "Game" + MEMID_ID2, // "World" + MEMID_ID3, // "Animation" + MEMID_ID4, // "Pools" + MEMID_ID5, // "Default Models" + MEMID_ID6, // "Streaming" + MEMID_ID7, // "Streamed Models" + MEMID_ID8, // "Streamed LODs" + MEMID_ID9, // "Streamed Textures" + MEMID_ID10, // "Streamed Collision" + MEMID_ID11, // "Streamed Animation" + MEMID_ID12, // "Textures" + MEMID_ID13, // "Collision" + MEMID_ID14, // "PreAlloc" + MEMID_ID15, // "Game Process" + MEMID_ID16, // "Script" + MEMID_ID17, // "Cars" + MEMID_ID18, // "Render" + MEMID_ID19, // "Ped Attr" + + NUM_MEMIDS, + + NUM_FIXED_MEMBLOCKS = 6 +}; + +class CMemoryHeap +{ +public: + HeapBlockDesc *m_start; + HeapBlockDesc *m_end; + HeapBlockList m_freeList; + CommonSize m_fixedSize[NUM_FIXED_MEMBLOCKS]; + uint32 m_totalMemUsed; + CStack m_idStack; + uint32 m_currentMemID; + uint32 *m_memUsed; + uint32 m_totalBlocksUsed; + uint32 *m_blocksUsed; + uint32 m_unkMemId; + + CMemoryHeap(void) : m_start(nil) {} + void Init(uint32 total); + void RegisterMalloc(HeapBlockDesc *block); + void RegisterFree(HeapBlockDesc *block); + void *Malloc(uint32 size); + void *Realloc(void *ptr, uint32 size); + void Free(void *ptr); + void FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size); + uint32 CombineFreeBlocks(HeapBlockDesc *block); + void *MoveMemory(void *ptr); + HeapBlockDesc *WhereShouldMemoryMove(void *ptr); + void *MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src); + void PopMemId(void); + void PushMemId(int32 id); + void RegisterMemPointer(void *ptr); + void TidyHeap(void); + uint32 GetMemoryUsed(int32 id); + uint32 GetBlocksUsed(int32 id); + + void ParseHeap(void); + + HeapBlockDesc *GetDescFromHeapPointer(void *block) + { + return (HeapBlockDesc*)((uintptr)block - sizeof(HeapBlockDesc)); + } + uint32 GetSizeBetweenBlocks(HeapBlockDesc *first, HeapBlockDesc *second) + { + return (uintptr)second - (uintptr)first - sizeof(HeapBlockDesc); + } + void FreeBlock(HeapBlockDesc *block){ + for(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){ + if(m_fixedSize[i].m_size == block->m_size){ + m_fixedSize[i].Free(block); + return; + } + } + HeapBlockDesc *it; + for(it = m_freeList.m_first.m_next; it->m_size < block->m_size; it = it->m_next); + block->InsertHeapFreeBlock(it->m_prev); + } +}; -- cgit v1.2.3 From 4ddc35634160da5779c46ab63a5b3d351af50b83 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 25 Nov 2020 22:49:50 +0100 Subject: memory heap starting to work --- src/core/main.cpp | 2 +- src/fakerw/fake.cpp | 32 ++++++++++++++++++++++++++++---- src/fakerw/rwplcore.h | 6 +++--- src/rw/MemoryHeap.cpp | 14 +++++++++++--- src/rw/MemoryHeap.h | 14 +++++++++++--- src/skel/glfw/glfw.cpp | 9 +++++++++ src/skel/win/win.cpp | 11 ++++++++++- 7 files changed, 73 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/core/main.cpp b/src/core/main.cpp index 843f0671..ea88de59 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1601,7 +1601,7 @@ void SystemInit() mwInit(); #endif -#ifdef GTA_PS2 +#ifdef USE_CUSTOM_ALLOCATOR InitMemoryMgr(); #endif diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 64a37421..39606335 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -16,9 +16,14 @@ using namespace rw; RwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; } -void *RwMalloc(size_t size) { return malloc(size); } -void *RwCalloc(size_t numObj, size_t sizeObj) { return calloc(numObj, sizeObj); } -void RwFree(void *mem) { free(mem); } +void *RwMalloc(size_t size) { return engine->memfuncs.rwmalloc(size, 0); } +void *RwCalloc(size_t numObj, size_t sizeObj) { + void *mem = RwMalloc(numObj*sizeObj); + if(mem) + memset(mem, 0, numObj*sizeObj); + return mem; +} +void RwFree(void *mem) { engine->memfuncs.rwfree(mem); } //RwReal RwV3dNormalize(RwV3d * out, const RwV3d * in); @@ -536,8 +541,27 @@ RwBool RwRenderStateSet(RwRenderState state, void *value) } } +static rw::MemoryFunctions gMemfuncs; +static void *(*real_malloc)(size_t size); +static void *(*real_realloc)(void *mem, size_t newSize); +static void *mallocWrap(size_t sz, uint32 hint) { if(sz == 0) return nil; return real_malloc(sz); } +static void *reallocWrap(void *p, size_t sz, uint32 hint) { return real_realloc(p, sz); } + + // WARNING: unused parameters -RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { Engine::init(); return true; } +RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { + if(memFuncs){ + real_malloc = memFuncs->rwmalloc; + real_realloc = memFuncs->rwrealloc; + gMemfuncs.rwmalloc = mallocWrap; + gMemfuncs.rwrealloc = reallocWrap; + gMemfuncs.rwfree = memFuncs->rwfree; + Engine::init(&gMemfuncs); + }else{ + Engine::init(nil); + } + return true; +} // TODO: this is platform dependent RwBool RwEngineOpen(RwEngineOpenParams *initParams) { static EngineOpenParams openParams; diff --git a/src/fakerw/rwplcore.h b/src/fakerw/rwplcore.h index 79c745b6..511f7678 100644 --- a/src/fakerw/rwplcore.h +++ b/src/fakerw/rwplcore.h @@ -141,15 +141,15 @@ RwUInt8 RwObjectGetType(const RwObject *obj); *********************************************** */ -struct RwMemoryFunctions; -/* +struct RwMemoryFunctions { + // NB: from RW 3.6 on the allocating functions take + // a hint parameter! void *(*rwmalloc)(size_t size); void (*rwfree)(void *mem); void *(*rwrealloc)(void *mem, size_t newSize); void *(*rwcalloc)(size_t numObj, size_t sizeObj); }; -*/ void *RwMalloc(size_t size); void RwFree(void *mem); diff --git a/src/rw/MemoryHeap.cpp b/src/rw/MemoryHeap.cpp index d613a708..2a484df4 100644 --- a/src/rw/MemoryHeap.cpp +++ b/src/rw/MemoryHeap.cpp @@ -9,8 +9,11 @@ #ifdef USE_CUSTOM_ALLOCATOR -#define MEMORYHEAP_ASSERT(cond) { if (!(cond)) { printf("ASSERT File:%s Line:%d\n", __FILE__, __LINE__); exit(1); } } -#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) { if (!(cond)) { printf("ASSERT File:%s Line:%d:\n\t%s\n", __FILE__, __LINE__, message); exit(1); } } +//#define MEMORYHEAP_ASSERT(cond) { if (!(cond)) { printf("ASSERT File:%s Line:%d\n", __FILE__, __LINE__); exit(1); } } +//#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) { if (!(cond)) { printf("ASSERT File:%s Line:%d:\n\t%s\n", __FILE__, __LINE__, message); exit(1); } } + +#define MEMORYHEAP_ASSERT(cond) assert(cond) +#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) assert(cond) // registered pointers that we keep track of void **gPtrList[4000]; @@ -272,6 +275,7 @@ CMemoryHeap::Free(void *ptr) MEMORYHEAP_ASSERT(m_unkMemId == -1 || m_unkMemId == block->m_memId); RegisterFree(block); + block->m_memId = MEMID_FREE; CombineFreeBlocks(block); FreeBlock(block); if(block->m_ptrListIndex != -1){ @@ -313,7 +317,7 @@ uint32 CMemoryHeap::CombineFreeBlocks(HeapBlockDesc *block) { HeapBlockDesc *next = block->GetNextConsecutive(); - if(next->m_memId == MEMID_FREE) + if(next->m_memId != MEMID_FREE) return block->m_size; // get rid of free blocks after this one and adjust size for(; next->m_memId == MEMID_FREE; next = next->GetNextConsecutive()) @@ -535,6 +539,10 @@ MemoryMgrCalloc(uint32 num, uint32 size) void MemoryMgrFree(void *ptr) { +#ifdef FIX_BUGS + // i don't suppose this is handled by RW? + if(ptr == nil) return; +#endif gMainHeap.Free(ptr); } diff --git a/src/rw/MemoryHeap.h b/src/rw/MemoryHeap.h index 840e016a..3f6fb5a0 100644 --- a/src/rw/MemoryHeap.h +++ b/src/rw/MemoryHeap.h @@ -1,6 +1,12 @@ #pragma once +// some windows shit +#ifdef MoveMemory +#undef MoveMemory +#endif + extern RwMemoryFunctions memFuncs; +void InitMemoryMgr(void); template class CStack @@ -56,7 +62,10 @@ struct HeapBlockDesc } }; +#ifdef USE_CUSTOM_ALLOCATOR +// TODO: figure something out for 64 bit pointers static_assert(sizeof(HeapBlockDesc) == 0x10, "HeapBlockDesc must have 0x10 size otherwise most of assumptions don't make sense"); +#endif struct HeapBlockList { @@ -181,8 +190,7 @@ public: return; } } - HeapBlockDesc *it; - for(it = m_freeList.m_first.m_next; it->m_size < block->m_size; it = it->m_next); - block->InsertHeapFreeBlock(it->m_prev); + HeapBlockDesc *b = m_freeList.m_first.FindSmallestFreeBlock(block->m_size); + block->InsertHeapFreeBlock(b->m_prev); } }; diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 982e8641..2722a4df 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -40,6 +40,7 @@ #include "Sprite2d.h" #include "AnimViewer.h" #include "Font.h" +#include "MemoryHeap.h" #define MAX_SUBSYSTEMS (16) @@ -277,7 +278,11 @@ psMouseSetPos(RwV2d *pos) RwMemoryFunctions* psGetMemoryFunctions(void) { +#ifdef USE_CUSTOM_ALLOCATOR + return &memFuncs; +#else return nil; +#endif } /* @@ -1461,6 +1466,10 @@ main(int argc, char *argv[]) RwV2d pos; RwInt32 i; +#ifdef USE_CUSTOM_ALLOCATOR + InitMemoryMgr(); +#endif + #ifndef _WIN32 struct sigaction act; act.sa_sigaction = terminateHandler; diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 9effaa31..b4897d67 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -97,6 +97,7 @@ static psGlobalType PsGlobal; #include "Sprite2d.h" #include "AnimViewer.h" #include "Font.h" +#include "MemoryHeap.h" VALIDATE_SIZE(psGlobalType, 0x28); @@ -304,7 +305,11 @@ psMouseSetPos(RwV2d *pos) RwMemoryFunctions* psGetMemoryFunctions(void) { +#ifdef USE_CUSTOM_ALLOCATOR + return &memFuncs; +#else return nil; +#endif } /* @@ -2006,7 +2011,11 @@ WinMain(HINSTANCE instance, RwChar **argv; SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); -#if 0 +#ifdef USE_CUSTOM_ALLOCATOR + InitMemoryMgr(); +#endif + +#if 1 // TODO: make this an option somewhere AllocConsole(); freopen("CONIN$", "r", stdin); -- cgit v1.2.3 From 491274f188c953ae0528248a7fcbe25fb78701f7 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 26 Nov 2020 18:11:55 +0200 Subject: CStreaming::PrintStreamingBufferState --- src/core/Streaming.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/Streaming.h | 2 ++ 2 files changed, 89 insertions(+) (limited to 'src') diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index e9a7af88..77d1773b 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -33,6 +33,7 @@ #endif #include "main.h" #include "Frontend.h" +#include "Font.h" bool CStreaming::ms_disableStreaming; bool CStreaming::ms_bLoadingBigModel; @@ -289,6 +290,11 @@ CStreaming::Shutdown(void) } } +#ifndef MASTER +uint64 timeProcessingTXD; +uint64 timeProcessingDFF; +#endif + void CStreaming::Update(void) { @@ -296,6 +302,11 @@ CStreaming::Update(void) CStreamingInfo *si, *prev; bool requestedSubway = false; +#ifndef MASTER + timeProcessingTXD = 0; + timeProcessingDFF = 0; +#endif + UpdateMemoryUsed(); if(ms_channelError != -1){ @@ -331,6 +342,14 @@ CStreaming::Update(void) LoadRequestedModels(); +#ifndef MASTER + if (CPad::GetPad(1)->GetLeftShoulder1JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2()) + PrintStreamingBufferState(); + + // TODO: PrintRequestList + //if (CPad::GetPad(1)->GetLeftShoulder2JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2()) + // PrintRequestList(); +#endif for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){ prev = si->m_prev; @@ -2636,3 +2655,71 @@ CStreaming::UpdateForAnimViewer(void) CStreaming::RetryLoadFile(CStreaming::ms_channelError); } } + + +void +CStreaming::PrintStreamingBufferState() +{ + char str[128]; + wchar wstr[128]; + uint32 offset, size; + + CTimer::Stop(); + int i = 0; + while (i < NUMSTREAMINFO) { + while (true) { + int j = 0; + DoRWStuffStartOfFrame(50, 50, 50, 0, 0, 0, 255); + CPad::UpdatePads(); + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + DefinedState(); + + CRect unusedRect(0, 0, RsGlobal.maximumWidth, RsGlobal.maximumHeight); + CRGBA unusedColor(255, 255, 255, 255); + CFont::SetFontStyle(FONT_BANK); + CFont::SetBackgroundOff(); + CFont::SetWrapx(DEFAULT_SCREEN_WIDTH); + CFont::SetScale(0.5f, 0.75f); + CFont::SetCentreOff(); + CFont::SetCentreSize(DEFAULT_SCREEN_WIDTH); + CFont::SetJustifyOff(); + CFont::SetColor(CRGBA(200, 200, 200, 200)); + CFont::SetBackGroundOnlyTextOff(); + int modelIndex = i; + if (modelIndex < NUMSTREAMINFO) { + int y = 24; + for ( ; j < 34 && modelIndex < NUMSTREAMINFO; modelIndex++) { + CStreamingInfo *streamingInfo = &ms_aInfoForModel[modelIndex]; + CBaseModelInfo *modelInfo = CModelInfo::GetModelInfo(modelIndex); + if (streamingInfo->m_loadState != STREAMSTATE_LOADED || !streamingInfo->GetCdPosnAndSize(offset, size)) + continue; + + if (modelIndex >= STREAM_OFFSET_TXD) + sprintf(str, "txd %s, refs %d, size %dK, flags 0x%x", CTxdStore::GetTxdName(modelIndex - STREAM_OFFSET_TXD), + CTxdStore::GetNumRefs(modelIndex - STREAM_OFFSET_TXD), 2 * size, streamingInfo->m_flags); + else + sprintf(str, "model %d,%s, refs%d, size%dK, flags%x", modelIndex, modelInfo->GetName(), modelInfo->GetNumRefs(), 2 * size, + streamingInfo->m_flags); + AsciiToUnicode(str, wstr); + CFont::PrintString(24.0f, y, wstr); + y += 12; + j++; + } + } + + if (CPad::GetPad(1)->GetCrossJustDown()) + i = modelIndex; + + if (!CPad::GetPad(1)->GetTriangleJustDown()) + break; + + i = 0; + CFont::DrawFonts(); + DoRWStuffEndOfFrame(); + } + CFont::DrawFonts(); + DoRWStuffEndOfFrame(); + } + CTimer::Update(); +} \ No newline at end of file diff --git a/src/core/Streaming.h b/src/core/Streaming.h index 0b2ff124..ee9183a5 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -188,4 +188,6 @@ public: static void MemoryCardLoad(uint8 *buffer, uint32 length); static void UpdateForAnimViewer(void); + + static void PrintStreamingBufferState(); }; -- cgit v1.2.3 From d857758c167ee06840ec806524191e95ff37f98a Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 26 Nov 2020 16:47:19 +0100 Subject: start using CMemoryHeap --- src/animation/AnimBlendAssociation.cpp | 2 +- src/animation/AnimBlendClumpData.cpp | 2 +- src/animation/AnimBlendSequence.cpp | 12 ++ src/collision/ColModel.cpp | 6 + src/core/CdStream.cpp | 1 + src/core/FileLoader.cpp | 11 ++ src/core/Game.cpp | 111 ++++++++++- src/core/Pools.cpp | 19 ++ src/core/Streaming.cpp | 41 +++- src/core/World.cpp | 3 + src/core/main.cpp | 329 +++++++++++++++++++++++---------- src/core/templates.h | 16 +- src/entities/Entity.cpp | 5 + src/modelinfo/ModelIndices.cpp | 2 +- src/render/WaterLevel.cpp | 5 + src/rw/MemoryHeap.cpp | 88 +++++++-- src/rw/MemoryHeap.h | 98 +++++++--- src/rw/RwHelper.cpp | 39 ---- src/rw/RwHelper.h | 3 - src/rw/VisibilityPlugins.cpp | 87 ++++++--- src/skel/skeleton.cpp | 5 + src/vehicles/Plane.cpp | 5 +- 22 files changed, 652 insertions(+), 238 deletions(-) (limited to 'src') diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp index 8c99b694..61d7d69c 100644 --- a/src/animation/AnimBlendAssociation.cpp +++ b/src/animation/AnimBlendAssociation.cpp @@ -5,7 +5,7 @@ #include "RpAnimBlend.h" #include "AnimManager.h" #include "AnimBlendAssociation.h" -#include "RwHelper.h" +#include "MemoryHeap.h" CAnimBlendAssociation::CAnimBlendAssociation(void) { diff --git a/src/animation/AnimBlendClumpData.cpp b/src/animation/AnimBlendClumpData.cpp index d40e8357..fd2a58de 100644 --- a/src/animation/AnimBlendClumpData.cpp +++ b/src/animation/AnimBlendClumpData.cpp @@ -1,7 +1,7 @@ #include "common.h" #include "AnimBlendClumpData.h" -#include "RwHelper.h" +#include "MemoryHeap.h" CAnimBlendClumpData::CAnimBlendClumpData(void) diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp index d35fbc46..5a2fa605 100644 --- a/src/animation/AnimBlendSequence.cpp +++ b/src/animation/AnimBlendSequence.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "AnimBlendSequence.h" +#include "MemoryHeap.h" CAnimBlendSequence::CAnimBlendSequence(void) { @@ -70,6 +71,8 @@ CAnimBlendSequence::Uncompress(void) if(numFrames == 0) return; + PUSH_MEMID(MEMID_ANIMATION); + float rotScale = 1.0f/4096.0f; float timeScale = 1.0f/60.0f; float transScale = 1.0f/128.0f; @@ -105,8 +108,12 @@ CAnimBlendSequence::Uncompress(void) } keyFrames = newKfs; } + REGISTER_MEMPTR(&keyFrames); + RwFree(keyFramesCompressed); keyFramesCompressed = nil; + + POP_MEMID(); } void @@ -117,6 +124,8 @@ CAnimBlendSequence::CompressKeyframes(void) if(numFrames == 0) return; + PUSH_MEMID(MEMID_ANIMATION); + float rotScale = 4096.0f; float timeScale = 60.0f; float transScale = 128.0f; @@ -152,6 +161,9 @@ CAnimBlendSequence::CompressKeyframes(void) } keyFramesCompressed = newKfs; } + REGISTER_MEMPTR(&keyFramesCompressed); + + POP_MEMID(); } void diff --git a/src/collision/ColModel.cpp b/src/collision/ColModel.cpp index 650e6958..fb90e7dd 100644 --- a/src/collision/ColModel.cpp +++ b/src/collision/ColModel.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "ColModel.h" #include "Game.h" +#include "MemoryHeap.h" CColModel::CColModel(void) { @@ -48,10 +49,15 @@ CColModel::RemoveCollisionVolumes(void) void CColModel::CalculateTrianglePlanes(void) { + PUSH_MEMID(MEMID_COLLISION); + // HACK: allocate space for one more element to stuff the link pointer into trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1)); + REGISTER_MEMPTR(&trianglePlanes); for(int i = 0; i < numTriangles; i++) trianglePlanes[i].Set(vertices, triangles[i]); + + POP_MEMID(); } void diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp index 1d39aa52..a1235930 100644 --- a/src/core/CdStream.cpp +++ b/src/core/CdStream.cpp @@ -5,6 +5,7 @@ #include "CdStream.h" #include "rwcore.h" #include "RwHelper.h" +#include "MemoryHeap.h" #define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) #define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index f46b6134..88a99fa9 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -24,6 +24,7 @@ #include "ZoneCull.h" #include "CdStream.h" #include "FileLoader.h" +#include "MemoryHeap.h" char CFileLoader::ms_line[256]; @@ -71,11 +72,13 @@ CFileLoader::LoadLevel(const char *filename) if(strncmp(line, "IMAGEPATH", 9) == 0){ RwImageSetPath(line + 10); }else if(strncmp(line, "TEXDICTION", 10) == 0){ + PUSH_MEMID(MEMID_TEXTURES); strcpy(txdname, line+11); LoadingScreenLoadingFile(txdname); RwTexDictionary *txd = LoadTexDictionary(txdname); AddTexDictionaries(savedTxd, txd); RwTexDictionaryDestroy(txd); + POP_MEMID(); }else if(strncmp(line, "COLFILE", 7) == 0){ int level; sscanf(line+8, "%d", &level); @@ -94,12 +97,16 @@ CFileLoader::LoadLevel(const char *filename) LoadObjectTypes(line + 4); }else if(strncmp(line, "IPL", 3) == 0){ if(!objectsLoaded){ + PUSH_MEMID(MEMID_DEF_MODELS); CModelInfo::ConstructMloClumps(); + POP_MEMID(); CObjectData::Initialise("DATA\\OBJECT.DAT"); objectsLoaded = true; } + PUSH_MEMID(MEMID_WORLD); LoadingScreenLoadingFile(line + 4); LoadScene(line + 4); + POP_MEMID(); }else if(strncmp(line, "MAPZONE", 7) == 0){ LoadingScreenLoadingFile(line + 8); LoadMapZones(line + 8); @@ -188,6 +195,8 @@ CFileLoader::LoadCollisionFile(const char *filename) CBaseModelInfo *mi; ColHeader header; + PUSH_MEMID(MEMID_COLLISION); + debug("Loading collision file %s\n", filename); fd = CFileMgr::OpenFile(filename, "rb"); @@ -211,6 +220,8 @@ CFileLoader::LoadCollisionFile(const char *filename) } CFileMgr::CloseFile(fd); + + POP_MEMID(); } void diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 1283ecd1..d22a7184 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -90,6 +90,7 @@ #include "custompipes.h" #include "screendroplets.h" #include "crossplatform.h" +#include "MemoryHeap.h" eLevelName CGame::currLevel; bool CGame::bDemoMode = true; @@ -327,21 +328,35 @@ CGame::FinalShutdown(void) bool CGame::Initialise(const char* datFile) { +#ifdef GTA_PS2 + // TODO: upload VU0 collision code here +#else ResetLoadingScreenBar(); strcpy(aDatFile, datFile); - CPools::Initialise(); + CPools::Initialise(); // done in CWorld on PS2 CIniFile::LoadIniFile(); +#endif + currLevel = LEVEL_INDUSTRIAL; + + PUSH_MEMID(MEMID_TEXTURES); LoadingScreen("Loading the Game", "Loading generic textures", GetRandomSplashScreen()); gameTxdSlot = CTxdStore::AddTxdSlot("generic"); CTxdStore::Create(gameTxdSlot); CTxdStore::AddRef(gameTxdSlot); + LoadingScreen("Loading the Game", "Loading particles", nil); int particleTxdSlot = CTxdStore::AddTxdSlot("particle"); CTxdStore::LoadTxd(particleTxdSlot, "MODELS/PARTICLE.TXD"); CTxdStore::AddRef(particleTxdSlot); CTxdStore::SetCurrentTxd(gameTxdSlot); LoadingScreen("Loading the Game", "Setup game variables", nil); + POP_MEMID(); + +#ifdef GTA_PS2 + CDma::SyncChannel(0, true); +#endif + CGameLogic::InitAtStartOfGame(); CReferences::Init(); TheCamera.Init(); @@ -361,20 +376,41 @@ bool CGame::Initialise(const char* datFile) CMessages::ClearAllMessagesDisplayedByGame(); CRecordDataForGame::Init(); CRestart::Initialise(); + + PUSH_MEMID(MEMID_WORLD); CWorld::Initialise(); + POP_MEMID(); + + PUSH_MEMID(MEMID_TEXTURES); CParticle::Initialise(); -#ifdef PS2 + POP_MEMID(); + +#ifdef GTA_PS2 gStartX = -180.0f; gStartY = 180.0f; gStartZ = 14.0f; #endif + + PUSH_MEMID(MEMID_ANIMATION); CAnimManager::Initialise(); CCutsceneMgr::Initialise(); + POP_MEMID(); + + PUSH_MEMID(MEMID_CARS); CCarCtrl::Init(); + POP_MEMID(); + +#ifndef GTA_PS2 InitModelIndices(); +#endif + + PUSH_MEMID(MEMID_DEF_MODELS); CModelInfo::Initialise(); +#ifndef GTA_PS2 + // probably moved before LoadLevel for multiplayer maps? CPickups::Init(); CTheCarGenerators::Init(); +#endif CdStreamAddImage("MODELS\\GTA3.IMG"); CFileLoader::LoadLevel("DATA\\DEFAULT.DAT"); CFileLoader::LoadLevel(datFile); @@ -386,17 +422,23 @@ bool CGame::Initialise(const char* datFile) CVehicleModelInfo::LoadVehicleColours(); CVehicleModelInfo::LoadEnvironmentMaps(); CTheZones::PostZoneCreation(); + POP_MEMID(); + LoadingScreen("Loading the Game", "Setup paths", GetRandomSplashScreen()); ThePaths.PreparePathData(); + // done elsewhere on PS2 for (int i = 0; i < NUMPLAYERS; i++) CWorld::Players[i].Clear(); CWorld::Players[0].LoadPlayerSkin(); TestModelIndices(); + // + LoadingScreen("Loading the Game", "Setup water", nil); CWaterLevel::Initialise("DATA\\WATER.DAT"); TheConsole.Init(); CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; + LoadingScreen("Loading the Game", "Setup streaming", nil); CStreaming::Init(); CStreaming::LoadInitialVehicles(); @@ -404,8 +446,12 @@ bool CGame::Initialise(const char* datFile) CStreaming::RequestBigBuildings(LEVEL_GENERIC); CStreaming::LoadAllRequestedModels(false); printf("Streaming uses %zuK of its memory", CStreaming::ms_memoryUsed / 1024); // original modifier was %d + LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen()); + PUSH_MEMID(MEMID_ANIMATION); CAnimManager::LoadAnimFiles(); + POP_MEMID(); + CPed::Initialise(); CRouteNode::Initialise(); CEventList::Initialise(); @@ -414,13 +460,16 @@ bool CGame::Initialise(const char* datFile) #endif LoadingScreen("Loading the Game", "Find big buildings", nil); CRenderer::Init(); + LoadingScreen("Loading the Game", "Setup game variables", nil); CRadar::Initialise(); CRadar::LoadTextures(); CWeapon::InitialiseWeapons(); + LoadingScreen("Loading the Game", "Setup traffic lights", nil); CTrafficLights::ScanForLightsOnMap(); CRoadBlocks::Init(); + LoadingScreen("Loading the Game", "Setup game variables", nil); CPopulation::Initialise(); CWorld::PlayerInFocus = 0; @@ -431,26 +480,48 @@ bool CGame::Initialise(const char* datFile) CAntennas::Init(); CGlass::Init(); gPhoneInfo.Initialise(); +#ifndef GTA_PS2 CSceneEdit::Initialise(); +#endif + LoadingScreen("Loading the Game", "Load scripts", nil); + PUSH_MEMID(MEMID_SCRIPT); CTheScripts::Init(); CGangs::Initialise(); + POP_MEMID(); + LoadingScreen("Loading the Game", "Setup game variables", nil); +#ifdef GTA_PS2 + CTimer::Initialise(); +#endif CClock::Initialise(1000); +#ifdef GTA_PS2 + CTheCarGenerators::Init(); +#endif CHeli::InitHelis(); CCranes::InitCranes(); CMovingThings::Init(); CDarkel::Init(); CStats::Init(); +#ifdef GTA_PS2 + CPickups::Init(); +#endif CPacManPickups::Init(); + // CGarages::Init(); here on PS2 instead CRubbish::Init(); CClouds::Init(); +#ifdef GTA_PS2 + CRemote::Init(); +#endif CSpecialFX::Init(); CWaterCannons::Init(); CBridge::Init(); CGarages::Init(); + LoadingScreen("Loading the Game", "Position dynamic objects", nil); CWorld::RepositionCertainDynamicObjects(); + // CCullZones::ResolveVisibilities(); on PS2 here instead + LoadingScreen("Loading the Game", "Initialise vehicle paths", nil); CCullZones::ResolveVisibilities(); CTrain::InitTrains(); @@ -458,6 +529,7 @@ bool CGame::Initialise(const char* datFile) CCredits::Init(); CRecordDataForChase::Init(); CReplay::Init(); + #ifdef PS2_MENU if ( !TheMemoryCard.m_bWantToLoad ) { @@ -469,6 +541,7 @@ bool CGame::Initialise(const char* datFile) #ifdef PS2_MENU } #endif + LoadingScreen("Loading the Game", "Load scene", nil); CModelInfo::RemoveColModelsFromOtherLevels(currLevel); CCollision::ms_collisionInMemory = currLevel; @@ -550,7 +623,7 @@ void CGame::ReInitGameObjectVariables(void) CWorld::bDoingCarCollisions = false; CHud::ReInitialise(); CRadar::Initialise(); -#ifdef PS2 +#ifdef GTA_PS2 gStartX = -180.0f; gStartY = 180.0f; gStartZ = 14.0f; @@ -573,15 +646,19 @@ void CGame::ReInitGameObjectVariables(void) CWorld::Players[i].Clear(); CWorld::PlayerInFocus = 0; -#ifdef PS2 +#ifdef GTA_PS2 CWeaponEffects::Init(); CSkidmarks::Init(); #endif CAntennas::Init(); CGlass::Init(); gPhoneInfo.Initialise(); + + PUSH_MEMID(MEMID_SCRIPT); CTheScripts::Init(); CGangs::Initialise(); + POP_MEMID(); + CTimer::Initialise(); CClock::Initialise(1000); CTheCarGenerators::Init(); @@ -592,7 +669,7 @@ void CGame::ReInitGameObjectVariables(void) CPickups::Init(); CPacManPickups::Init(); CGarages::Init(); -#ifdef PS2 +#ifdef GTA_PS2 CClouds::Init(); CRemote::Init(); #endif @@ -807,7 +884,7 @@ void CGame::InitialiseWhenRestarting(void) void CGame::Process(void) { CPad::UpdatePads(); -#ifdef GTA_PS2 +#ifdef USE_CUSTOM_ALLOCATOR ProcessTidyUpMemory(); #endif TheCamera.SetMotionBlurAlpha(0); @@ -817,8 +894,12 @@ void CGame::Process(void) DebugMenuProcess(); #endif CCutsceneMgr::Update(); + + PUSH_MEMID(MEMID_FRONTEND); if (!CCutsceneMgr::IsCutsceneProcessing() && !CTimer::GetIsCodePaused()) FrontEndMenuManager.Process(); + POP_MEMID(); + CStreaming::Update(); if (!CTimer::GetIsPaused()) { @@ -831,7 +912,11 @@ void CGame::Process(void) CPad::DoCheats(); CClock::Update(); CWeather::Update(); + + PUSH_MEMID(MEMID_SCRIPT); CTheScripts::Process(); + POP_MEMID(); + CCollision::Update(); CTrain::UpdateTrains(); CPlane::UpdatePlanes(); @@ -855,7 +940,11 @@ void CGame::Process(void) CWaterCannons::Update(); CUserDisplay::Process(); CReplay::Update(); + + PUSH_MEMID(MEMID_WORLD); CWorld::Process(); + POP_MEMID(); + gAccidentManager.Update(); CPacManPickups::Update(); CPickups::Update(); @@ -876,33 +965,35 @@ void CGame::Process(void) gPhoneInfo.Update(); if (!CReplay::IsPlayingBack()) { + PUSH_MEMID(MEMID_CARS); CCarCtrl::GenerateRandomCars(); CRoadBlocks::GenerateRoadBlocks(); CCarCtrl::RemoveDistantCars(); + POP_MEMID(); } } -#ifdef PS2 +#ifdef GTA_PS2 CMemCheck::DoTest(); #endif } void CGame::DrasticTidyUpMemory(bool) { -#ifdef PS2 +#ifdef USE_CUSTOM_ALLOCATOR // meow #endif } void CGame::TidyUpMemory(bool, bool) { -#ifdef PS2 +#ifdef USE_CUSTOM_ALLOCATOR // meow #endif } void CGame::ProcessTidyUpMemory(void) { -#ifdef PS2 +#ifdef USE_CUSTOM_ALLOCATOR // meow #endif } diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index bd0814d0..79841c14 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -12,6 +12,7 @@ #include "Streaming.h" #include "Wanted.h" #include "World.h" +#include "MemoryHeap.h" CCPtrNodePool *CPools::ms_pPtrNodePool; CEntryInfoNodePool *CPools::ms_pEntryInfoNodePool; @@ -23,18 +24,36 @@ CObjectPool *CPools::ms_pObjectPool; CDummyPool *CPools::ms_pDummyPool; CAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool; +#ifdef GTA_PS2 // or USE_CUSTOM_ALLOCATOR +#define CHECKMEM(msg) CMemCheck::AllocateMemCheckBlock(msg) +#else +#define CHECKMEM(msg) +#endif + void CPools::Initialise(void) { + PUSH_MEMID(MEMID_POOLS); + CHECKMEM("before pools"); ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES); + CHECKMEM("after CPtrNodePool"); ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS); + CHECKMEM("after CEntryInfoNodePool"); ms_pPedPool = new CPedPool(NUMPEDS); + CHECKMEM("after CPedPool"); ms_pVehiclePool = new CVehiclePool(NUMVEHICLES); + CHECKMEM("after CVehiclePool"); ms_pBuildingPool = new CBuildingPool(NUMBUILDINGS); + CHECKMEM("after CBuildingPool"); ms_pTreadablePool = new CTreadablePool(NUMTREADABLES); + CHECKMEM("after CTreadablePool"); ms_pObjectPool = new CObjectPool(NUMOBJECTS); + CHECKMEM("after CObjectPool"); ms_pDummyPool = new CDummyPool(NUMDUMMIES); + CHECKMEM("after CDummyPool"); ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS); + CHECKMEM("after pools"); + POP_MEMID(); } void diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index e9a7af88..8f1a8891 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -33,6 +33,7 @@ #endif #include "main.h" #include "Frontend.h" +#include "MemoryHeap.h" bool CStreaming::ms_disableStreaming; bool CStreaming::ms_bLoadingBigModel; @@ -470,8 +471,10 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) // Set Txd to use CTxdStore::AddRef(mi->GetTxdSlot()); - CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); + PUSH_MEMID(MEMID_STREAM_MODELS); + CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); +// TODO(USE_CUSTOM_ALLOCATOR): register mem pointers if(mi->IsSimple()){ success = CFileLoader::LoadAtomicFile(stream, streamId); } else if (mi->GetModelType() == MITYPE_VEHICLE) { @@ -483,6 +486,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) }else{ success = CFileLoader::LoadClumpFile(stream, streamId); } + POP_MEMID(); UpdateMemoryUsed(); // Txd no longer needed unless we only read part of the file @@ -506,12 +510,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) return false; } + PUSH_MEMID(MEMID_STREAM_TEXUTRES); if(ms_bLoadingBigModel || cdsize > 200){ success = CTxdStore::StartLoadTxd(streamId - STREAM_OFFSET_TXD, stream); if(success) ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED; }else success = CTxdStore::LoadTxd(streamId - STREAM_OFFSET_TXD, stream); + POP_MEMID(); UpdateMemoryUsed(); if(!success){ @@ -561,7 +567,9 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) // Mark objects as loaded if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){ ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; +#ifndef USE_CUSTOM_ALLOCATOR ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE; +#endif } endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond(); @@ -600,32 +608,40 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) if(streamId < STREAM_OFFSET_TXD){ // Model +// TODO(USE_CUSTOM_ALLOCATOR): register pointers mi = CModelInfo::GetModelInfo(streamId); + PUSH_MEMID(MEMID_STREAM_MODELS); CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); success = CFileLoader::FinishLoadClumpFile(stream, streamId); if(success) success = AddToLoadedVehiclesList(streamId); + POP_MEMID(); mi->RemoveRef(); CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot()); }else{ // Txd CTxdStore::AddRef(streamId - STREAM_OFFSET_TXD); + PUSH_MEMID(MEMID_STREAM_TEXUTRES); success = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream); + POP_MEMID(); CTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD); } RwStreamClose(stream, &mem); - ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; + + ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; // only done if success on PS2 +#ifndef USE_CUSTOM_ALLOCATOR ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE; +#endif if(!success){ RemoveModel(streamId); ReRequestModel(streamId); - UpdateMemoryUsed(); + UpdateMemoryUsed(); // directly after pop on PS2 return false; } - UpdateMemoryUsed(); + UpdateMemoryUsed(); // directly after pop on PS2 endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond(); timeDiff = endTime - startTime; @@ -858,7 +874,11 @@ CStreaming::RemoveModel(int32 id) CModelInfo::GetModelInfo(id)->DeleteRwObject(); else CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); +#ifdef USE_CUSTOM_ALLOCATOR + UpdateMemoryUsed(); +#else ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE; +#endif } if(ms_aInfoForModel[id].m_next){ @@ -880,6 +900,9 @@ CStreaming::RemoveModel(int32 id) RpClumpGtaCancelStream(); else CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); +#ifdef USE_CUSTOM_ALLOCATOR + UpdateMemoryUsed(); +#endif } ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED; @@ -2044,19 +2067,25 @@ CStreaming::FlushRequestList(void) void CStreaming::ImGonnaUseStreamingMemory(void) { - // empty + PUSH_MEMID(MEMID_STREAM); } void CStreaming::IHaveUsedStreamingMemory(void) { + POP_MEMID(); UpdateMemoryUsed(); } void CStreaming::UpdateMemoryUsed(void) { - // empty +#ifdef USE_CUSTOM_ALLOCATOR + ms_memoryUsed = + gMainHeap.GetMemoryUsed(MEMID_STREAM) + + gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS) + + gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES); +#endif } #define STREAM_DIST 80.0f diff --git a/src/core/World.cpp b/src/core/World.cpp index d65d57dd..33c2f1c1 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -53,6 +53,9 @@ bool CWorld::bIncludeCarTyres; void CWorld::Initialise() { +#ifdef GTA_PS2 + CPools::Initialise(); +#endif pIgnoreEntity = nil; bDoingCarCollisions = false; bSecondShift = false; diff --git a/src/core/main.cpp b/src/core/main.cpp index ea88de59..d34eb8f3 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -67,6 +67,7 @@ #include "custompipes.h" #include "screendroplets.h" #include "frontendoption.h" +#include "MemoryHeap.h" GlobalScene Scene; @@ -109,6 +110,15 @@ void TheGame(void); void DebugMenuPopulate(void); #endif + +#ifdef GTA_PS2 +#define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad +#define FOUND_GAME_TO_LOAD TheMemoryCard.b_FoundRecentSavedGameWantToLoad +#else +#define WANT_TO_LOAD FrontEndMenuManager.m_bWantToLoad +#define FOUND_GAME_TO_LOAD b_FoundRecentSavedGameWantToLoad +#endif + void ValidateVersion() { @@ -772,6 +782,170 @@ tZonePrint ZonePrint[] = }; #ifndef MASTER + +void +PrintMemoryUsage(void) +{ +// little hack +if(CPools::GetPtrNodePool() == nil) +return; + + // Style taken from LCS, modified for III +// CFont::SetFontStyle(FONT_PAGER); + CFont::SetFontStyle(FONT_BANK); + CFont::SetBackgroundOff(); + CFont::SetWrapx(640.0f); +// CFont::SetScale(0.5f, 0.75f); + CFont::SetScale(0.4f, 0.75f); + CFont::SetCentreOff(); + CFont::SetCentreSize(640.0f); + CFont::SetJustifyOff(); + CFont::SetPropOn(); + CFont::SetColor(CRGBA(200, 200, 200, 200)); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetDropShadowPosition(0); + + float y; + +#ifdef USE_CUSTOM_ALLOCATOR + y = 24.0f; + sprintf(gString, "Total: %d blocks, %d bytes", gMainHeap.m_totalBlocksUsed, gMainHeap.m_totalMemUsed); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Game: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME), gMainHeap.GetMemoryUsed(MEMID_GAME)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "World: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_WORLD), gMainHeap.GetMemoryUsed(MEMID_WORLD)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Render: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDER), gMainHeap.GetMemoryUsed(MEMID_RENDER)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Render List: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDERLIST), gMainHeap.GetMemoryUsed(MEMID_RENDERLIST)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Default Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_DEF_MODELS), gMainHeap.GetMemoryUsed(MEMID_DEF_MODELS)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_TEXTURES), gMainHeap.GetMemoryUsed(MEMID_TEXTURES)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Streaming: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM), gMainHeap.GetMemoryUsed(MEMID_STREAM)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Streamed Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_MODELS), gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Streamed Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_TEXUTRES), gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Animation: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_ANIMATION)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Pools: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_POOLS), gMainHeap.GetMemoryUsed(MEMID_POOLS)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Collision: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_COLLISION), gMainHeap.GetMemoryUsed(MEMID_COLLISION)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Game Process: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME_PROCESS), gMainHeap.GetMemoryUsed(MEMID_GAME_PROCESS)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Script: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_SCRIPT), gMainHeap.GetMemoryUsed(MEMID_SCRIPT)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Cars: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_CARS), gMainHeap.GetMemoryUsed(MEMID_CARS)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Frontend: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_FRONTEND), gMainHeap.GetMemoryUsed(MEMID_FRONTEND)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; +#endif + + y = 132.0f; + AsciiToUnicode("Pools usage:", gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "PtrNode: %d/%d", CPools::GetPtrNodePool()->GetNoOfUsedSpaces(), CPools::GetPtrNodePool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "EntryInfoNode: %d/%d", CPools::GetEntryInfoNodePool()->GetNoOfUsedSpaces(), CPools::GetEntryInfoNodePool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Ped: %d/%d", CPools::GetPedPool()->GetNoOfUsedSpaces(), CPools::GetPedPool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Vehicle: %d/%d", CPools::GetVehiclePool()->GetNoOfUsedSpaces(), CPools::GetVehiclePool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Building: %d/%d", CPools::GetBuildingPool()->GetNoOfUsedSpaces(), CPools::GetBuildingPool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Treadable: %d/%d", CPools::GetTreadablePool()->GetNoOfUsedSpaces(), CPools::GetTreadablePool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Object: %d/%d", CPools::GetObjectPool()->GetNoOfUsedSpaces(), CPools::GetObjectPool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Dummy: %d/%d", CPools::GetDummyPool()->GetNoOfUsedSpaces(), CPools::GetDummyPool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "AudioScriptObjects: %d/%d", CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces(), CPools::GetAudioScriptObjectPool()->GetSize()); + AsciiToUnicode(gString, gUString); + CFont::PrintString(400.0f, y, gUString); + y += 12.0f; +} + void DisplayGameDebugText() { @@ -785,6 +959,7 @@ DisplayGameDebugText() } #endif +// PrintMemoryUsage(); // TODO: put this somewhere else char str[200]; wchar ustr[200]; @@ -1001,13 +1176,9 @@ RenderMenus(void) { if (FrontEndMenuManager.m_bMenuActive) { -#ifdef PS2 - gMainHeap.PushMemId(_TODOCONST(17)); -#endif + PUSH_MEMID(MEMID_FRONTEND); FrontEndMenuManager.DrawFrontEnd(); -#ifdef PS2 - gMainHeap.PopMemId(); -#endif + POP_MEMID(); } } @@ -1046,24 +1217,29 @@ Idle(void *arg) CPad::UpdatePads(); FrontEndMenuManager.Process(); } else { + PUSH_MEMID(MEMID_GAME_PROCESS); CPointLights::InitPerFrame(); tbStartTimer(0, "CGame::Process"); CGame::Process(); tbEndTimer("CGame::Process"); + POP_MEMID(); + tbStartTimer(0, "DMAudio.Service"); DMAudio.Service(); - tbEndTimer("DMAudio.Service"); } if (RsGlobal.quit) return; #else + + PUSH_MEMID(MEMID_GAME_PROCESS); CPointLights::InitPerFrame(); tbStartTimer(0, "CGame::Process"); CGame::Process(); tbEndTimer("CGame::Process"); + POP_MEMID(); tbStartTimer(0, "DMAudio.Service"); DMAudio.Service(); @@ -1071,21 +1247,12 @@ Idle(void *arg) #endif if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){ -#ifdef PS2_MENU - TheMemoryCard.m_bWantToLoad = false; - FrontEndMenuManager.m_bWantToRestart = true; -#else + WANT_TO_LOAD = false; FrontEndMenuManager.m_bWantToRestart = true; - FrontEndMenuManager.m_bWantToLoad = false; -#endif return; } -#ifdef PS2_MENU - if ( FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad ) -#else - if(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad) -#endif + if(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD) { return; } @@ -1095,6 +1262,8 @@ Idle(void *arg) if(arg == nil) return; + PUSH_MEMID(MEMID_RENDER); + if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) && TheCamera.GetScreenFadeStatus() != FADE_2) { @@ -1107,6 +1276,8 @@ Idle(void *arg) RsMouseSetPos(&pos); } #endif + + PUSH_MEMID(MEMID_RENDERLIST); tbStartTimer(0, "CnstrRenderList"); CRenderer::ConstructRenderList(); tbEndTimer("CnstrRenderList"); @@ -1114,6 +1285,7 @@ Idle(void *arg) tbStartTimer(0, "PreRender"); CRenderer::PreRender(); tbEndTimer("PreRender"); + POP_MEMID(); #ifdef FIX_BUGS RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); // TODO: temp? this fixes OpenGL render but there should be a better place for this @@ -1124,12 +1296,12 @@ Idle(void *arg) if(CWeather::LightningFlash && !CCullZones::CamNoRain()){ if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255)) - return; + goto popret; }else{ if(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(), CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(), 255)) - return; + goto popret; } DefinedState(); @@ -1176,7 +1348,7 @@ Idle(void *arg) CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ); if(!RsCameraBeginUpdate(Scene.camera)) - return; + goto popret; } #ifdef PS2_SAVE_DIALOG @@ -1189,7 +1361,7 @@ Idle(void *arg) #ifdef PS2_MENU if ( TheMemoryCard.m_bWantToLoad ) - return; + goto popret; #endif tbStartTimer(0, "DoFade"); @@ -1208,8 +1380,13 @@ Idle(void *arg) DoRWStuffEndOfFrame(); + POP_MEMID(); // MEMID_RENDER + if(g_SlowMode) ProcessSlowMode(); + return; + +popret: POP_MEMID(); // MEMID_RENDER } void @@ -1375,14 +1552,13 @@ TheModelViewer(void) } #endif -#ifdef PS2 + +#ifdef GTA_PS2 void TheGame(void) { printf("Into TheGame!!!\n"); -#ifdef GTA_PS2 - gMainHeap.PushMemId(_TODOCONST(1)); -#endif + PUSH_MEMID(MEMID_GAME); // NB: not popped CTimer::Initialise(); @@ -1420,77 +1596,49 @@ void TheGame(void) while (true) { -#ifdef PS2 - if (TheMemoryCard.m_bWantToLoad) -#else - if (FrontEndMenuManager.m_bWantToLoad) -#endif + if (WANT_TO_LOAD) { Const char *splash1 = GetLevelSplashScreen(CGame::currLevel); LoadSplash(splash1); } -#ifdef PS2 - TheMemoryCard.m_bWantToLoad = false; -#else - FrontEndMenuManager.m_bWantToLoad = false; -#endif + WANT_TO_LOAD = false; CTimer::Update(); -#ifdef PS2 - while (!(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)) -#else - while (!(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)) -#endif + while (!(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)) { CSprite2d::InitPerFrame(); CFont::InitPerFrame(); -#ifdef GTA_PS2 - gMainHeap.PushMemId(_TODOCONST(12)); -#endif - CPointLights::NumLights = 0; + PUSH_MEMID(MEMID_GAME_PROCESS) + CPointLights::InitPerFrame(); CGame::Process(); -#ifdef GTA_PS2 - gMainHeap.PopMemId(); -#endif + POP_MEMID(); DMAudio.Service(); if (CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()) { -#ifdef PS2 - TheMemoryCard.m_bWantToLoad = false; -#else - FrontEndMenuManager.m_bWantToLoad = false; -#endif + WANT_TO_LOAD = false; FrontEndMenuManager.m_bWantToRestart = true; break; } -#ifdef PS2 - if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad) -#else - if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad) -#endif + if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD) break; SetLightsWithTimeOfDayColour(Scene.world); -#ifdef GTA_PS2 - gMainHeap.PushMemId(_TODOCONST(15)); -#endif + + PUSH_MEMID(MEMID_RENDER); if (!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true && TheCamera.GetScreenFadeStatus() != FADE_2 ) { -#ifdef GTA_PS2 - gMainHeap.PushMemId(_TODOCONST(11)); -#endif + + PUSH_MEMID(MEMID_RENDERLIST); CRenderer::ConstructRenderList(); CRenderer::PreRender(); -#ifdef GTA_PS2 - gMainHeap.PopMemId(); -#endif + POP_MEMID(); if (CWeather::LightningFlash && !CCullZones::CamNoRain()) DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255); @@ -1522,15 +1670,9 @@ void TheGame(void) RenderMenus(); -#ifdef PS2 - if (TheMemoryCard.m_bWantToLoad) -#else - if (FrontEndMenuManager.m_bWantToLoad) -#endif + if (WANT_TO_LOAD) { -#ifdef GTA_PS2 - gMainHeap.PopMemId(); -#endif + POP_MEMID(); // MEMID_RENDER break; } @@ -1547,9 +1689,7 @@ void TheGame(void) CTimer::Update(); -#ifdef GTA_PS2 - gMainHeap.PopMemId(); -#endif + POP_MEMID(): // MEMID_RENDER if (g_SlowMode) ProcessSlowMode(); @@ -1561,24 +1701,12 @@ void TheGame(void) CGame::ShutDownForRestart(); CTimer::Stop(); -#ifdef PS2 - if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad) -#else - if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad) -#endif + if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD) { -#ifdef PS2 - if (TheMemoryCard.b_FoundRecentSavedGameWantToLoad) -#else - if (b_FoundRecentSavedGameWantToLoad) -#endif + if (FOUND_GAME_TO_LOAD) { FrontEndMenuManager.m_bWantToRestart = true; -#ifdef PS2 - TheMemoryCard.m_bWantToLoad = true; -#else - FrontEndMenuManager.m_bWantToLoad = true; -#endif + WANT_TO_LOAD = true; } CGame::InitialiseWhenRestarting(); @@ -1718,7 +1846,7 @@ void SystemInit() // #endif -#ifdef PS2 +#ifdef GTA_PS2 TheMemoryCard.Init(); #endif } @@ -1747,7 +1875,7 @@ void GameInit() #endif CdStreamInit(MAX_CDCHANNELS); -#ifdef PS2 +#ifdef GTA_PS2 Initialise3D(); //no params #else //TODO @@ -1861,14 +1989,11 @@ void GameInit() CSprite2d::SetRecipNearClip(); CTxdStore::Initialise(); -#ifdef GTA_PS2 - gMainHeap.PushMemId(_TODOCONST(9)); -#endif + + PUSH_MEMID(MEMID_TEXTURES); CFont::Initialise(); CHud::Initialise(); -#ifdef GTA_PS2 - gMainHeap.PopMemId(); -#endif + POP_MEMID(); ValidateVersion(); @@ -1896,7 +2021,7 @@ main(int argc, char *argv[]) SystemInit(); -#ifdef PS2 +#ifdef GTA_PS2 int32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE); if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT diff --git a/src/core/templates.h b/src/core/templates.h index 4f7b8490..86239664 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -46,8 +46,8 @@ class CPool public: CPool(int size){ // TODO: use new here - m_entries = (U*)malloc(sizeof(U)*size); - m_flags = (Flags*)malloc(sizeof(Flags)*size); + m_entries = (U*)new uint8[sizeof(U)*size]; + m_flags = (Flags*)new uint8[sizeof(Flags)*size]; m_size = size; m_allocPtr = 0; for(int i = 0; i < size; i++){ @@ -61,8 +61,8 @@ public: } void Flush() { if (m_size > 0) { - free(m_entries); - free(m_flags); + delete[] (uint8*)m_entries; + delete[] (uint8*)m_flags; m_entries = nil; m_flags = nil; m_size = 0; @@ -141,8 +141,8 @@ public: } bool IsFreeSlot(int i) { return !!m_flags[i].free; } void ClearStorage(uint8 *&flags, U *&entries){ - free(flags); - free(entries); + delete[] (uint8*)flags; + delete[] (uint8*)entries; flags = nil; entries = nil; } @@ -156,8 +156,8 @@ public: debug("CopyBack:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ } void Store(uint8 *&flags, U *&entries){ - flags = (uint8*)malloc(sizeof(uint8)*m_size); - entries = (U*)malloc(sizeof(U)*m_size); + flags = (uint8*)new uint8[sizeof(uint8)*m_size]; + entries = (U*)new uint8[sizeof(U)*m_size]; memcpy(flags, m_flags, sizeof(uint8)*m_size); memcpy(entries, m_entries, sizeof(U)*m_size); debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 5e3204b2..476439fa 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -28,6 +28,7 @@ #include "Bones.h" #include "Debug.h" #include "Renderer.h" +#include "MemoryHeap.h" int gBuildings; @@ -274,7 +275,11 @@ CEntity::CreateRwObject(void) CBaseModelInfo *mi; mi = CModelInfo::GetModelInfo(m_modelIndex); + + PUSH_MEMID(MEMID_WORLD); m_rwObject = mi->CreateInstance(); + POP_MEMID(); + if(m_rwObject){ if(IsBuilding()) gBuildings++; diff --git a/src/modelinfo/ModelIndices.cpp b/src/modelinfo/ModelIndices.cpp index 056c3733..98c7fb38 100644 --- a/src/modelinfo/ModelIndices.cpp +++ b/src/modelinfo/ModelIndices.cpp @@ -3,7 +3,7 @@ #include "General.h" #include "ModelIndices.h" -#define X(name, var) int16 var; +#define X(name, var) int16 var = -1; MODELINDICES #undef X diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index 6133b1d7..ecfccc90 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -21,6 +21,7 @@ #include "RenderBuffer.h" #include #include "WaterLevel.h" +#include "MemoryHeap.h" float TEXTURE_ADDU; @@ -1157,6 +1158,8 @@ CWaterLevel::AllocateBoatWakeArray() { CStreaming::MakeSpaceFor(14 * CDSTREAM_SECTOR_SIZE); + PUSH_MEMID(MEMID_STREAM); + ASSERT(ms_pWavyAtomic != NULL ); RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); @@ -1230,6 +1233,8 @@ CWaterLevel::AllocateBoatWakeArray() RpGeometryUnlock(apGeomArray[geom]); } } + + POP_MEMID(); } void diff --git a/src/rw/MemoryHeap.cpp b/src/rw/MemoryHeap.cpp index 2a484df4..2cf173b6 100644 --- a/src/rw/MemoryHeap.cpp +++ b/src/rw/MemoryHeap.cpp @@ -44,7 +44,7 @@ CMemoryHeap::Init(uint32 total) m_end = (HeapBlockDesc*)(mem + total - sizeof(HeapBlockDesc)); m_start->m_memId = MEMID_FREE; m_start->m_size = total - 2*sizeof(HeapBlockDesc); - m_end->m_memId = MEMID_ID1; + m_end->m_memId = MEMID_GAME; m_end->m_size = 0; m_freeList.m_last.m_size = INT_MAX; @@ -65,7 +65,7 @@ CMemoryHeap::Init(uint32 total) RegisterMalloc(GetDescFromHeapPointer(m_memUsed)); RegisterMalloc(GetDescFromHeapPointer(m_blocksUsed)); - m_currentMemID = MEMID_ID1; + m_currentMemID = MEMID_GAME; for(int i = 0; i < NUM_MEMIDS; i++){ m_memUsed[i] = 0; m_blocksUsed[i] = 0; @@ -90,8 +90,8 @@ CMemoryHeap::RegisterFree(HeapBlockDesc *block) if(block->m_memId == MEMID_FREE) return; m_totalMemUsed -= block->m_size + sizeof(HeapBlockDesc); - m_memUsed[m_currentMemID] -= block->m_size + sizeof(HeapBlockDesc); - m_blocksUsed[m_currentMemID]--; + m_memUsed[block->m_memId] -= block->m_size + sizeof(HeapBlockDesc); + m_blocksUsed[block->m_memId]--; m_totalBlocksUsed--; } @@ -433,13 +433,16 @@ CMemoryHeap::GetBlocksUsed(int32 id) void CMemoryHeap::PopMemId(void) { + assert(m_idStack.sp > 0); m_currentMemID = m_idStack.pop(); + assert(m_currentMemID != MEMID_FREE); } void CMemoryHeap::PushMemId(int32 id) { MEMORYHEAP_ASSERT(id != MEMID_FREE); + assert(m_idStack.sp < 16); m_idStack.push(m_currentMemID); m_currentMemID = id; } @@ -457,7 +460,7 @@ CMemoryHeap::ParseHeap(void) for(HeapBlockDesc *block = m_start; block < m_end; block = block->GetNextConsecutive()){ char chr = '*'; // free if(block->m_memId != MEMID_FREE) - chr = block->m_memId-MEMID_ID1 + 'A'; + chr = block->m_memId-1 + 'A'; int numQW = block->m_size>>4; if((addrQW & 0x3F) == 0){ @@ -506,10 +509,31 @@ InitMemoryMgr(void) #endif } + +RwMemoryFunctions memFuncs = { + MemoryMgrMalloc, + MemoryMgrFree, + MemoryMgrRealloc, + MemoryMgrCalloc +}; + +#ifdef USE_CUSTOM_ALLOCATOR +// game seems to be using heap directly here, but this is nicer +void *operator new(size_t sz) { return MemoryMgrMalloc(sz); } +void *operator new[](size_t sz) { return MemoryMgrMalloc(sz); } +void operator delete(void *ptr) noexcept { MemoryMgrFree(ptr); } +void operator delete[](void *ptr) noexcept { MemoryMgrFree(ptr); } +#endif +#endif + void* MemoryMgrMalloc(uint32 size) { +#ifdef USE_CUSTOM_ALLOCATOR void *mem = gMainHeap.Malloc(size); +#else + void *mem = malloc(size); +#endif if(mem > pMemoryTop) pMemoryTop = mem; return mem; @@ -518,7 +542,11 @@ MemoryMgrMalloc(uint32 size) void* MemoryMgrRealloc(void *ptr, uint32 size) { +#ifdef USE_CUSTOM_ALLOCATOR void *mem = gMainHeap.Realloc(ptr, size); +#else + void *mem = realloc(ptr, size); +#endif if(mem > pMemoryTop) pMemoryTop = mem; return mem; @@ -527,7 +555,11 @@ MemoryMgrRealloc(void *ptr, uint32 size) void* MemoryMgrCalloc(uint32 num, uint32 size) { +#ifdef USE_CUSTOM_ALLOCATOR void *mem = gMainHeap.Malloc(num*size); +#else + void *mem = calloc(num, size); +#endif if(mem > pMemoryTop) pMemoryTop = mem; #ifdef FIX_BUGS @@ -539,18 +571,52 @@ MemoryMgrCalloc(uint32 num, uint32 size) void MemoryMgrFree(void *ptr) { +#ifdef USE_CUSTOM_ALLOCATOR #ifdef FIX_BUGS // i don't suppose this is handled by RW? if(ptr == nil) return; #endif gMainHeap.Free(ptr); +#else + free(ptr); +#endif } -RwMemoryFunctions memFuncs = { - MemoryMgrMalloc, - MemoryMgrFree, - MemoryMgrRealloc, - MemoryMgrCalloc -}; +void * +RwMallocAlign(RwUInt32 size, RwUInt32 align) +{ +#ifdef FIX_BUGS + uintptr ptralign = align-1; + void *mem = (void *)MemoryMgrMalloc(size + sizeof(uintptr) + ptralign); + + ASSERT(mem != nil); + + void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign); + + ASSERT(addr != nil); +#else + void *mem = (void *)MemoryMgrMalloc(size + align); + ASSERT(mem != nil); + + void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1)); + + ASSERT(addr != nil); #endif + + *(((void **)addr) - 1) = mem; + + return addr; +} + +void +RwFreeAlign(void *mem) +{ + ASSERT(mem != nil); + + void *addr = *(((void **)mem) - 1); + + ASSERT(addr != nil); + + MemoryMgrFree(addr); +} diff --git a/src/rw/MemoryHeap.h b/src/rw/MemoryHeap.h index 3f6fb5a0..22e13617 100644 --- a/src/rw/MemoryHeap.h +++ b/src/rw/MemoryHeap.h @@ -5,9 +5,75 @@ #undef MoveMemory #endif +#ifdef USE_CUSTOM_ALLOCATOR +#define PUSH_MEMID(id) gMainHeap.PushMemId(id) +#define POP_MEMID() gMainHeap.PopMemId() +#define REGISTER_MEMPTR(ptr) gMainHeap.RegisterMemPointer(ptr) +#else +#define PUSH_MEMID(id) +#define POP_MEMID() +#define REGISTER_MEMPTR(ptr) +#endif + +enum { + MEMID_FREE, + // IDs from LCS: +/* + MEMID_GAME = 1, // "Game" + MEMID_WORLD = 2, // "World" + MEMID_ANIMATION = 3, // "Animation" + MEMID_POOLS = 4, // "Pools" + MEMID_DEF_MODELS = 5, // "Default Models" + MEMID_STREAM = 6, // "Streaming" + MEMID_STREAM_MODELS = 7, // "Streamed Models" + MEMID_STREAM_LODS = 8, // "Streamed LODs" + MEMID_STREAM_TEXUTRES = 9, // "Streamed Textures" + MEMID_STREAM_COLLISION = 10, // "Streamed Collision" + MEMID_STREAM_ANIMATION = 11, // "Streamed Animation" + MEMID_TEXTURES = 12, // "Textures" + MEMID_COLLISION = 13, // "Collision" + MEMID_PRE_ALLOC = 14, // "PreAlloc" + MEMID_GAME_PROCESS = 15, // "Game Process" + MEMID_SCRIPT = 16, // "Script" + MEMID_CARS = 17, // "Cars" + MEMID_RENDER = 18, // "Render" + MEMID_PED_ATTR = 19, // "Ped Attr" +*/ + // III: + MEMID_GAME = 1, // "Game" + MEMID_WORLD = 2, // "World" + MEMID_ANIMATION = 3, // "Animation" + MEMID_POOLS = 4, // "Pools" + MEMID_DEF_MODELS = 5, // "Default Models" + MEMID_STREAM = 6, // "Streaming" + MEMID_STREAM_MODELS = 7, // "Streamed Models" (instance) + MEMID_STREAM_TEXUTRES = 8, // "Streamed Textures" + MEMID_TEXTURES = 9, // "Textures" + MEMID_COLLISION = 10, // "Collision" + MEMID_RENDERLIST = 11, // ? + MEMID_GAME_PROCESS = 12, // "Game Process" + MEMID_SCRIPT = 13, // "Script" + MEMID_CARS = 14, // "Cars" + MEMID_RENDER = 15, // "Render" + MEMID_FRONTEND = 17, // ? + + NUM_MEMIDS, + + NUM_FIXED_MEMBLOCKS = 6 +}; + extern RwMemoryFunctions memFuncs; void InitMemoryMgr(void); +void *MemoryMgrMalloc(uint32 size); +void *MemoryMgrRealloc(void *ptr, uint32 size); +void *MemoryMgrCalloc(uint32 num, uint32 size); +void MemoryMgrFree(void *ptr); + +void *RwMallocAlign(RwUInt32 size, RwUInt32 align); +void RwFreeAlign(void *mem); + + template class CStack { @@ -17,7 +83,7 @@ public: CStack() : sp(0) {} void push(const T& val) { values[sp++] = val; } - T& pop() { return values[sp--]; } + T& pop() { return values[--sp]; } }; @@ -111,34 +177,6 @@ struct CommonSize } }; -enum { - MEMID_FREE, - // IDs from LCS: - MEMID_ID1, // "Game" - MEMID_ID2, // "World" - MEMID_ID3, // "Animation" - MEMID_ID4, // "Pools" - MEMID_ID5, // "Default Models" - MEMID_ID6, // "Streaming" - MEMID_ID7, // "Streamed Models" - MEMID_ID8, // "Streamed LODs" - MEMID_ID9, // "Streamed Textures" - MEMID_ID10, // "Streamed Collision" - MEMID_ID11, // "Streamed Animation" - MEMID_ID12, // "Textures" - MEMID_ID13, // "Collision" - MEMID_ID14, // "PreAlloc" - MEMID_ID15, // "Game Process" - MEMID_ID16, // "Script" - MEMID_ID17, // "Cars" - MEMID_ID18, // "Render" - MEMID_ID19, // "Ped Attr" - - NUM_MEMIDS, - - NUM_FIXED_MEMBLOCKS = 6 -}; - class CMemoryHeap { public: @@ -194,3 +232,5 @@ public: block->InsertHeapFreeBlock(b->m_prev); } }; + +extern CMemoryHeap gMainHeap; diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 0069934f..ee370c37 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -64,45 +64,6 @@ void FlushObrsPrintfs() #endif } -void * -RwMallocAlign(RwUInt32 size, RwUInt32 align) -{ -#ifdef FIX_BUGS - uintptr ptralign = align-1; - void *mem = (void *)malloc(size + sizeof(uintptr) + ptralign); - - ASSERT(mem != nil); - - void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign); - - ASSERT(addr != nil); -#else - void *mem = (void *)malloc(size + align); - - ASSERT(mem != nil); - - void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1)); - - ASSERT(addr != nil); -#endif - - *(((void **)addr) - 1) = mem; - - return addr; -} - -void -RwFreeAlign(void *mem) -{ - ASSERT(mem != nil); - - void *addr = *(((void **)mem) - 1); - - ASSERT(addr != nil); - - free(addr); -} - void DefinedState(void) { diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 523a7732..ed9b03ab 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -2,9 +2,6 @@ extern bool gPS2alphaTest; -void *RwMallocAlign(RwUInt32 size, RwUInt32 align); -void RwFreeAlign(void *mem); - void OpenCharsetSafe(); void CreateDebugFont(); void DestroyDebugFont(); diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 3f10d12a..68775c72 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -10,6 +10,7 @@ #include "VisibilityPlugins.h" #include "World.h" #include "custompipes.h" +#include "MemoryHeap.h" CLinkList CVisibilityPlugins::m_alphaList; CLinkList CVisibilityPlugins::m_alphaEntityList; @@ -30,6 +31,41 @@ float CVisibilityPlugins::ms_pedLod0Dist; float CVisibilityPlugins::ms_pedLod1Dist; float CVisibilityPlugins::ms_pedFadeDist; +#ifdef GTA_PS2 +void +rpDefaultGeometryInstance(RpGeometry *geo, void *atomic, int unk) +{ + // TODO + // this function seems to delete the original geometry data + // and only keep the instanced data + AtomicDefaultRenderCallBack((RpAtomic*)atomic); +} + +RpAtomic* +PreInstanceRenderCB(RpAtomic *atomic) +{ + RpGeometry *geo = RpAtomicGetGeometry(atomic); + if(RpGeometryGetTriangles(geo)){ + PUSH_MEMID(MEMID_STREAM_MODELS); + rpDefaultGeometryInstance(geo, atomic, 1); + POP_MEMID(); + }else + AtomicDefaultRenderCallBack(atomic); + return atomic; +} +#define RENDERCALLBACK PreInstanceRenderCB +#else +RpAtomic* +DefaultRenderCB_pushid(RpAtomic *atomic) +{ + PUSH_MEMID(MEMID_STREAM_MODELS); + AtomicDefaultRenderCallBack(atomic); + POP_MEMID(); + return atomic; +} +#define RENDERCALLBACK DefaultRenderCB_pushid +#endif + void CVisibilityPlugins::Initialise(void) { @@ -132,7 +168,7 @@ CVisibilityPlugins::RenderAlphaAtomics(void) for(node = m_alphaList.tail.prev; node != &m_alphaList.head; node = node->prev) - AtomicDefaultRenderCallBack(node->item.atomic); + RENDERCALLBACK(node->item.atomic); } void @@ -201,7 +237,7 @@ CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic) if(lodatm){ if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic)) RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE); - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } return atomic; } @@ -218,7 +254,7 @@ CVisibilityPlugins::RenderObjNormalAtomic(RpAtomic *atomic) len = RwV3dLength(&view); if(RwV3dDotProduct(&view, RwMatrixGetUp(m)) < -0.3f*len && len > 8.0f) return atomic; - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); return atomic; } @@ -232,7 +268,7 @@ CVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha) flags = RpGeometryGetFlags(geo); RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR); RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha); - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255); RpGeometrySetFlags(geo, flags); return atomic; @@ -250,7 +286,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist) lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE); if(mi->m_additive){ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); }else{ fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE; @@ -258,7 +294,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist) fadefactor = 1.0f; alpha = mi->m_alpha * fadefactor; if(alpha == 255) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); else{ RpGeometry *geo = RpAtomicGetGeometry(lodatm); uint32 flags = RpGeometryGetFlags(geo); @@ -266,7 +302,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist) RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha); if(geo != RpAtomicGetGeometry(atomic)) RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255); RpGeometrySetFlags(geo, flags); } @@ -293,7 +329,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic) if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot)) return atomic; } - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } return atomic; } @@ -318,10 +354,10 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic) if(flags & ATOMIC_FLAG_DRAWLAST){ // sort before clump if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f)) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); }else{ if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } } return atomic; @@ -344,7 +380,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic) if(dot > 0.0f) return atomic; } - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } return atomic; } @@ -367,7 +403,7 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic) return atomic; if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } return atomic; } @@ -381,7 +417,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic) clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); distsq = GetDistanceSquaredFromCamera(clumpframe); if(distsq < ms_bigVehicleLod1Dist) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); return atomic; } @@ -403,7 +439,7 @@ CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic) if(dot > 0.0f) return atomic; } - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } return atomic; } @@ -427,7 +463,7 @@ CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic) return atomic; if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } return atomic; } @@ -444,7 +480,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic) if(dist >= ms_vehicleLod0Dist){ alpha = GetClumpAlpha(clump); if(alpha == 255) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); else RenderAlphaAtomic(atomic, alpha); } @@ -461,7 +497,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic) clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic)); distsq = GetDistanceSquaredFromCamera(clumpframe); if(distsq >= ms_bigVehicleLod1Dist) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); return atomic; } @@ -482,7 +518,7 @@ CVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic) if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot)) return atomic; } - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } return atomic; } @@ -507,10 +543,10 @@ CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic) if(flags & ATOMIC_FLAG_DRAWLAST){ // sort before clump if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f)) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); }else{ if(!InsertAtomicIntoSortedList(atomic, distsq + dot)) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); } } return atomic; @@ -521,7 +557,7 @@ CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic) { if(CWorld::Players[0].m_pSkinTexture) RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture); - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); return atomic; } @@ -537,7 +573,7 @@ CVisibilityPlugins::RenderPedLowDetailCB(RpAtomic *atomic) if(dist >= ms_pedLod0Dist){ alpha = GetClumpAlpha(clump); if(alpha == 255) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); else RenderAlphaAtomic(atomic, alpha); } @@ -556,7 +592,7 @@ CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic) if(dist < ms_pedLod0Dist){ alpha = GetClumpAlpha(clump); if(alpha == 255) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); else RenderAlphaAtomic(atomic, alpha); } @@ -575,7 +611,7 @@ CVisibilityPlugins::RenderPedCB(RpAtomic *atomic) if(RwV3dDotProduct(&cam2atm, &cam2atm) < ms_pedLod1Dist){ alpha = GetClumpAlpha(RpAtomicGetClump(atomic)); if(alpha == 255) - AtomicDefaultRenderCallBack(atomic); + RENDERCALLBACK(atomic); else RenderAlphaAtomic(atomic, alpha); } @@ -775,12 +811,11 @@ CVisibilityPlugins::GetAtomicId(RpAtomic *atomic) return ATOMICEXT(atomic)->flags; } -// This is rather useless, but whatever void CVisibilityPlugins::SetAtomicRenderCallback(RpAtomic *atomic, RpAtomicCallBackRender cb) { if(cb == nil) - cb = AtomicDefaultRenderCallBack; // not necessary + cb = RENDERCALLBACK; RpAtomicSetRenderCallBack(atomic, cb); } diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index 4780316a..3166093e 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -10,6 +10,7 @@ #include "skeleton.h" #include "platform.h" +#include "MemoryHeap.h" @@ -307,6 +308,8 @@ RsRwInitialize(void *displayID) { RwEngineOpenParams openParams; + PUSH_MEMID(MEMID_RENDER); // NB: not popped on failed return + /* * Start RenderWare... */ @@ -374,6 +377,8 @@ RsRwInitialize(void *displayID) RwTextureSetMipmapping(FALSE); RwTextureSetAutoMipmapping(FALSE); + POP_MEMID(); + return TRUE; } diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 1a6f1a88..532be938 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -15,6 +15,7 @@ #include "World.h" #include "HandlingMgr.h" #include "Plane.h" +#include "MemoryHeap.h" CPlaneNode *pPathNodes; CPlaneNode *pPath2Nodes; @@ -551,9 +552,11 @@ CPlane::ProcessControl(void) if(m_rwObject && RwObjectGetType(m_rwObject) == rpCLUMP){ DeleteRwObject(); if(mi->m_planeLodId != -1){ + PUSH_MEMID(MEMID_WORLD); m_rwObject = CModelInfo::GetModelInfo(mi->m_planeLodId)->CreateInstance(); + POP_MEMID(); if(m_rwObject) - m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject))); + m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject))); } } }else if(CStreaming::HasModelLoaded(GetModelIndex())){ -- cgit v1.2.3 From f50a53e2907bcadd5c89781c4d9c025a45c8a113 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 27 Nov 2020 19:18:51 +0300 Subject: fix garages --- src/control/Garages.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 5a04285f..fc8f84f2 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1260,9 +1260,9 @@ bool CGarage::IsPlayerOutsideGarage() bool CGarage::IsEntityTouching3D(CEntity * pEntity) { float radius = pEntity->GetBoundRadius(); - if (pEntity->GetPosition().x - radius < m_fX1 || pEntity->GetPosition().x + radius > m_fX2 || - pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 || - pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2) + if (m_fX1 - radius > pEntity->GetPosition().x || m_fX2 + radius < pEntity->GetPosition().x || + m_fY1 - radius > pEntity->GetPosition().y || m_fY2 + radius < pEntity->GetPosition().y || + m_fZ1 - radius > pEntity->GetPosition().z || m_fZ2 + radius < pEntity->GetPosition().z) return false; CColModel* pColModel = pEntity->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { @@ -1271,9 +1271,9 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity) if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 && pos.y + radius > m_fY1 && pos.y - radius < m_fY2 && pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2) - return false; + return true; } - return true; + return false; } bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin) -- cgit v1.2.3 From 18d0fd2e48ab093b953f26b67b769a2d8ab67040 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 28 Nov 2020 15:13:06 +0200 Subject: Add multisampling to librw --- src/core/config.h | 1 - src/fakerw/fake.cpp | 3 +++ src/fakerw/rwcore.h | 2 ++ src/skel/glfw/glfw.cpp | 5 ++++- 4 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index 6433a258..ead9b787 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -353,5 +353,4 @@ enum Config { #ifdef LIBRW // these are not supported with librw yet -# undef MULTISAMPLING #endif diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 39606335..2e04aed2 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -601,6 +601,9 @@ void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) {} RwBool RwD3D8DeviceSupportsDXTTexture(void) { return true; } +void RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level) { Engine::setMultiSamplingLevels(level); } +RwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void) { return Engine::getMaxMultiSamplingLevels(); } + RpMaterial *RpMaterialCreate(void) { return Material::create(); } RwBool RpMaterialDestroy(RpMaterial *material) { material->destroy(); return true; } diff --git a/src/fakerw/rwcore.h b/src/fakerw/rwcore.h index 31bc5541..e5d21865 100644 --- a/src/fakerw/rwcore.h +++ b/src/fakerw/rwcore.h @@ -411,3 +411,5 @@ RwFrame *RwCameraGetFrame(const RwCamera *camera); void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate); RwBool RwD3D8DeviceSupportsDXTTexture(void); +void RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level); +RwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void); diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 2722a4df..617fee18 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -833,7 +833,10 @@ psSelectDevice() PSGLOBAL(fullScreen) = !FrontEndMenuManager.m_nPrefsWindowed; #endif - + +#ifdef MULTISAMPLING + RwD3D8EngineSetMultiSamplingLevels(1 << FrontEndMenuManager.m_nPrefsMSAALevel); +#endif return TRUE; } -- cgit v1.2.3 From ad48b9cde01522938590aab444bb09275ff5359d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 28 Nov 2020 16:29:45 +0200 Subject: Make texture conversion work a bit faster --- src/core/config.h | 1 + src/rw/TexRead.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/core/config.h b/src/core/config.h index ead9b787..99c5f6ef 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -233,6 +233,7 @@ enum Config { #define PS2_ALPHA_TEST // emulate ps2 alpha test #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number #define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time +#define DISABLE_VSYNC_ON_TEXTURE_CONVERSION // make texture conversion work faster by disabling vsync //#define USE_TEXTURE_POOL #ifdef LIBRW //#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 72d2ae17..7403ae1d 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -18,6 +18,7 @@ #include "Sprite2d.h" #include "Text.h" #include "RwHelper.h" +#include "Frontend.h" #endif //GTA_PC float texLoadTime; @@ -357,6 +358,15 @@ CreateTxdImageForVideoCard() // so let's hope that is the case for all rw::gl3::needToReadBackTextures = true; #endif + +#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION + // let's disable vsync and frame limiter to speed up texture conversion + // (actually we probably don't need to disable frame limiter in here, but let's do it just in case =P) + int8 vsyncState = CMenuManager::m_PrefsVsync; + int8 frameLimiterState = CMenuManager::m_PrefsFrameLimiter; + CMenuManager::m_PrefsVsync = 0; + CMenuManager::m_PrefsFrameLimiter = 0; +#endif int32 i; for (i = 0; i < TXDSTORESIZE; i++) { @@ -411,6 +421,12 @@ CreateTxdImageForVideoCard() } } +#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION + // restore vsync and frame limiter states + CMenuManager::m_PrefsVsync = vsyncState; + CMenuManager::m_PrefsFrameLimiter = frameLimiterState; +#endif + RwStreamClose(img, nil); delete []buf; -- cgit v1.2.3 From a8035b64662e9b9fe6689ec60e5087ff95bc2672 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 28 Nov 2020 16:16:15 +0100 Subject: moved some stuff to MemoryMgr --- src/animation/AnimBlendAssociation.cpp | 2 +- src/animation/AnimBlendClumpData.cpp | 2 +- src/core/CdStream.cpp | 2 +- src/core/CdStreamPosix.cpp | 2 +- src/core/Streaming.cpp | 1 + src/render/PlayerSkin.cpp | 1 + src/rw/MemoryHeap.cpp | 125 ------------------------------- src/rw/MemoryHeap.h | 12 --- src/rw/MemoryMgr.cpp | 130 +++++++++++++++++++++++++++++++++ src/rw/MemoryMgr.h | 12 +++ src/skel/glfw/glfw.cpp | 2 +- src/skel/win/win.cpp | 2 +- 12 files changed, 150 insertions(+), 143 deletions(-) create mode 100644 src/rw/MemoryMgr.cpp create mode 100644 src/rw/MemoryMgr.h (limited to 'src') diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp index 61d7d69c..b03571b0 100644 --- a/src/animation/AnimBlendAssociation.cpp +++ b/src/animation/AnimBlendAssociation.cpp @@ -5,7 +5,7 @@ #include "RpAnimBlend.h" #include "AnimManager.h" #include "AnimBlendAssociation.h" -#include "MemoryHeap.h" +#include "MemoryMgr.h" CAnimBlendAssociation::CAnimBlendAssociation(void) { diff --git a/src/animation/AnimBlendClumpData.cpp b/src/animation/AnimBlendClumpData.cpp index fd2a58de..92515427 100644 --- a/src/animation/AnimBlendClumpData.cpp +++ b/src/animation/AnimBlendClumpData.cpp @@ -1,7 +1,7 @@ #include "common.h" #include "AnimBlendClumpData.h" -#include "MemoryHeap.h" +#include "MemoryMgr.h" CAnimBlendClumpData::CAnimBlendClumpData(void) diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp index a1235930..f987dea5 100644 --- a/src/core/CdStream.cpp +++ b/src/core/CdStream.cpp @@ -5,7 +5,7 @@ #include "CdStream.h" #include "rwcore.h" #include "RwHelper.h" -#include "MemoryHeap.h" +#include "MemoryMgr.h" #define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) #define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index 35a90a74..0854d850 100644 --- a/src/core/CdStreamPosix.cpp +++ b/src/core/CdStreamPosix.cpp @@ -16,7 +16,7 @@ #include "CdStream.h" #include "rwcore.h" -#include "RwHelper.h" +#include "MemoryMgr.h" #define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) #define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 628d4923..a28fe39d 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -34,6 +34,7 @@ #include "main.h" #include "Frontend.h" #include "Font.h" +#include "MemoryMgr.h" #include "MemoryHeap.h" bool CStreaming::ms_disableStreaming; diff --git a/src/render/PlayerSkin.cpp b/src/render/PlayerSkin.cpp index d66f7ce4..f0fae45a 100644 --- a/src/render/PlayerSkin.cpp +++ b/src/render/PlayerSkin.cpp @@ -14,6 +14,7 @@ #include "RwHelper.h" #include "Timer.h" #include "Lights.h" +#include "MemoryMgr.h" RpClump *gpPlayerClump; float gOldFov; diff --git a/src/rw/MemoryHeap.cpp b/src/rw/MemoryHeap.cpp index 2cf173b6..0b333ce1 100644 --- a/src/rw/MemoryHeap.cpp +++ b/src/rw/MemoryHeap.cpp @@ -494,129 +494,4 @@ CommonSize::Init(uint32 size) m_remaining = 0; } - - -void *pMemoryTop; - -void -InitMemoryMgr(void) -{ -#ifdef GTA_PS2 -#error "finish this" -#else - // randomly allocate 128mb - gMainHeap.Init(128*1024*1024); -#endif -} - - -RwMemoryFunctions memFuncs = { - MemoryMgrMalloc, - MemoryMgrFree, - MemoryMgrRealloc, - MemoryMgrCalloc -}; - -#ifdef USE_CUSTOM_ALLOCATOR -// game seems to be using heap directly here, but this is nicer -void *operator new(size_t sz) { return MemoryMgrMalloc(sz); } -void *operator new[](size_t sz) { return MemoryMgrMalloc(sz); } -void operator delete(void *ptr) noexcept { MemoryMgrFree(ptr); } -void operator delete[](void *ptr) noexcept { MemoryMgrFree(ptr); } -#endif -#endif - -void* -MemoryMgrMalloc(uint32 size) -{ -#ifdef USE_CUSTOM_ALLOCATOR - void *mem = gMainHeap.Malloc(size); -#else - void *mem = malloc(size); -#endif - if(mem > pMemoryTop) - pMemoryTop = mem; - return mem; -} - -void* -MemoryMgrRealloc(void *ptr, uint32 size) -{ -#ifdef USE_CUSTOM_ALLOCATOR - void *mem = gMainHeap.Realloc(ptr, size); -#else - void *mem = realloc(ptr, size); -#endif - if(mem > pMemoryTop) - pMemoryTop = mem; - return mem; -} - -void* -MemoryMgrCalloc(uint32 num, uint32 size) -{ -#ifdef USE_CUSTOM_ALLOCATOR - void *mem = gMainHeap.Malloc(num*size); -#else - void *mem = calloc(num, size); #endif - if(mem > pMemoryTop) - pMemoryTop = mem; -#ifdef FIX_BUGS - memset(mem, 0, num*size); -#endif - return mem; -} - -void -MemoryMgrFree(void *ptr) -{ -#ifdef USE_CUSTOM_ALLOCATOR -#ifdef FIX_BUGS - // i don't suppose this is handled by RW? - if(ptr == nil) return; -#endif - gMainHeap.Free(ptr); -#else - free(ptr); -#endif -} - -void * -RwMallocAlign(RwUInt32 size, RwUInt32 align) -{ -#ifdef FIX_BUGS - uintptr ptralign = align-1; - void *mem = (void *)MemoryMgrMalloc(size + sizeof(uintptr) + ptralign); - - ASSERT(mem != nil); - - void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign); - - ASSERT(addr != nil); -#else - void *mem = (void *)MemoryMgrMalloc(size + align); - - ASSERT(mem != nil); - - void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1)); - - ASSERT(addr != nil); -#endif - - *(((void **)addr) - 1) = mem; - - return addr; -} - -void -RwFreeAlign(void *mem) -{ - ASSERT(mem != nil); - - void *addr = *(((void **)mem) - 1); - - ASSERT(addr != nil); - - MemoryMgrFree(addr); -} diff --git a/src/rw/MemoryHeap.h b/src/rw/MemoryHeap.h index 22e13617..484cbfab 100644 --- a/src/rw/MemoryHeap.h +++ b/src/rw/MemoryHeap.h @@ -62,18 +62,6 @@ enum { NUM_FIXED_MEMBLOCKS = 6 }; -extern RwMemoryFunctions memFuncs; -void InitMemoryMgr(void); - -void *MemoryMgrMalloc(uint32 size); -void *MemoryMgrRealloc(void *ptr, uint32 size); -void *MemoryMgrCalloc(uint32 num, uint32 size); -void MemoryMgrFree(void *ptr); - -void *RwMallocAlign(RwUInt32 size, RwUInt32 align); -void RwFreeAlign(void *mem); - - template class CStack { diff --git a/src/rw/MemoryMgr.cpp b/src/rw/MemoryMgr.cpp new file mode 100644 index 00000000..ef0ecbdf --- /dev/null +++ b/src/rw/MemoryMgr.cpp @@ -0,0 +1,130 @@ +#include "common.h" +#include "MemoryHeap.h" +#include "MemoryMgr.h" + + +void *pMemoryTop; + +void +InitMemoryMgr(void) +{ +#ifdef USE_CUSTOM_ALLOCATOR +#ifdef GTA_PS2 +#error "finish this" +#else + // randomly allocate 128mb + gMainHeap.Init(128*1024*1024); +#endif +#endif +} + + +RwMemoryFunctions memFuncs = { + MemoryMgrMalloc, + MemoryMgrFree, + MemoryMgrRealloc, + MemoryMgrCalloc +}; + +#ifdef USE_CUSTOM_ALLOCATOR +// game seems to be using heap directly here, but this is nicer +void *operator new(size_t sz) { return MemoryMgrMalloc(sz); } +void *operator new[](size_t sz) { return MemoryMgrMalloc(sz); } +void operator delete(void *ptr) noexcept { MemoryMgrFree(ptr); } +void operator delete[](void *ptr) noexcept { MemoryMgrFree(ptr); } +#endif + +void* +MemoryMgrMalloc(size_t size) +{ +#ifdef USE_CUSTOM_ALLOCATOR + void *mem = gMainHeap.Malloc(size); +#else + void *mem = malloc(size); +#endif + if(mem > pMemoryTop) + pMemoryTop = mem; + return mem; +} + +void* +MemoryMgrRealloc(void *ptr, size_t size) +{ +#ifdef USE_CUSTOM_ALLOCATOR + void *mem = gMainHeap.Realloc(ptr, size); +#else + void *mem = realloc(ptr, size); +#endif + if(mem > pMemoryTop) + pMemoryTop = mem; + return mem; +} + +void* +MemoryMgrCalloc(size_t num, size_t size) +{ +#ifdef USE_CUSTOM_ALLOCATOR + void *mem = gMainHeap.Malloc(num*size); +#else + void *mem = calloc(num, size); +#endif + if(mem > pMemoryTop) + pMemoryTop = mem; +#ifdef FIX_BUGS + memset(mem, 0, num*size); +#endif + return mem; +} + +void +MemoryMgrFree(void *ptr) +{ +#ifdef USE_CUSTOM_ALLOCATOR +#ifdef FIX_BUGS + // i don't suppose this is handled by RW? + if(ptr == nil) return; +#endif + gMainHeap.Free(ptr); +#else + free(ptr); +#endif +} + +void * +RwMallocAlign(RwUInt32 size, RwUInt32 align) +{ +#ifdef FIX_BUGS + uintptr ptralign = align-1; + void *mem = (void *)MemoryMgrMalloc(size + sizeof(uintptr) + ptralign); + + ASSERT(mem != nil); + + void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign); + + ASSERT(addr != nil); +#else + void *mem = (void *)MemoryMgrMalloc(size + align); + + ASSERT(mem != nil); + + void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1)); + + ASSERT(addr != nil); +#endif + + *(((void **)addr) - 1) = mem; + + return addr; +} + +void +RwFreeAlign(void *mem) +{ + ASSERT(mem != nil); + + void *addr = *(((void **)mem) - 1); + + ASSERT(addr != nil); + + MemoryMgrFree(addr); +} diff --git a/src/rw/MemoryMgr.h b/src/rw/MemoryMgr.h new file mode 100644 index 00000000..e2962806 --- /dev/null +++ b/src/rw/MemoryMgr.h @@ -0,0 +1,12 @@ +#pragma once + +extern RwMemoryFunctions memFuncs; +void InitMemoryMgr(void); + +void *MemoryMgrMalloc(size_t size); +void *MemoryMgrRealloc(void *ptr, size_t size); +void *MemoryMgrCalloc(size_t num, size_t size); +void MemoryMgrFree(void *ptr); + +void *RwMallocAlign(RwUInt32 size, RwUInt32 align); +void RwFreeAlign(void *mem); diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 2722a4df..0bde1282 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -40,7 +40,7 @@ #include "Sprite2d.h" #include "AnimViewer.h" #include "Font.h" -#include "MemoryHeap.h" +#include "MemoryMgr.h" #define MAX_SUBSYSTEMS (16) diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index b4897d67..5f6d662c 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -97,7 +97,7 @@ static psGlobalType PsGlobal; #include "Sprite2d.h" #include "AnimViewer.h" #include "Font.h" -#include "MemoryHeap.h" +#include "MemoryMgr.h" VALIDATE_SIZE(psGlobalType, 0x28); -- cgit v1.2.3 From b1a431a740c9bde92e9169c041909cebfa705ae5 Mon Sep 17 00:00:00 2001 From: withmorten Date: Sat, 28 Nov 2020 17:57:10 +0100 Subject: add -console cmdline arg instead of #if 0/1 --- src/skel/glfw/glfw.cpp | 14 ++++++++------ src/skel/win/win.cpp | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 617fee18..c4a3cad1 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1453,12 +1453,14 @@ WinMain(HINSTANCE instance, RwChar** argv; SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); -#if 0 - // TODO: make this an option somewhere - AllocConsole(); - freopen("CONIN$", "r", stdin); - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); +#ifndef MASTER + if (strstr(cmdLine, "-console")) + { + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } #endif #else diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index b4897d67..4dc8c3f0 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -2011,16 +2011,18 @@ WinMain(HINSTANCE instance, RwChar **argv; SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); -#ifdef USE_CUSTOM_ALLOCATOR - InitMemoryMgr(); +#ifndef MASTER + if (strstr(cmdLine, "-console")) + { + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } #endif -#if 1 - // TODO: make this an option somewhere - AllocConsole(); - freopen("CONIN$", "r", stdin); - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); +#ifdef USE_CUSTOM_ALLOCATOR + InitMemoryMgr(); #endif /* -- cgit v1.2.3 From 52826966993a4d91afcbda44ee2e3c9966f9087d Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 29 Nov 2020 11:36:26 +0100 Subject: fix backface culling on vehicles --- src/render/Renderer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 83bd0d21..a0f66819 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -216,6 +216,7 @@ CRenderer::RenderOneNonRoad(CEntity *e) e->Render(); if(e->IsVehicle()){ + BACKFACE_CULLING_OFF; e->bImBeingRendered = true; CVisibilityPlugins::RenderAlphaAtomics(); e->bImBeingRendered = false; -- cgit v1.2.3 From 566282057abbc8e9d5f331c8125a38b00b39fee0 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 29 Nov 2020 11:37:06 +0100 Subject: add debug script hotkey --- src/core/Frontend.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index b84b691d..318e5903 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -4157,12 +4157,22 @@ CMenuManager::ProcessButtonPresses(void) DoSettingsBeforeStartingAGame(); return; } + if (glfwGetKey(PSGLOBAL(window), GLFW_KEY_D) == GLFW_PRESS) { + scriptToLoad = 2; + DoSettingsBeforeStartingAGame(); + return; + } #elif defined _WIN32 if (GetAsyncKeyState('R') & 0x8000) { scriptToLoad = 1; DoSettingsBeforeStartingAGame(); return; } + if (GetAsyncKeyState('D') & 0x8000) { + scriptToLoad = 2; + DoSettingsBeforeStartingAGame(); + return; + } #endif } #endif -- cgit v1.2.3 From d5bc382cb51c5ef5af618377d190e6f34e893314 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 29 Nov 2020 12:26:34 +0100 Subject: GTA_VERSION define and some config.h cleanup --- src/audio/sampman_miles.cpp | 16 ++++++------ src/control/Script.cpp | 2 +- src/control/Script6.cpp | 2 +- src/control/ScriptCommands.h | 2 +- src/core/Cam.cpp | 4 +-- src/core/Camera.cpp | 8 +++--- src/core/Frontend.cpp | 14 +++++----- src/core/MenuScreensCustom.cpp | 2 +- src/core/Pad.cpp | 2 +- src/core/config.h | 26 +++++++++++++------ src/entities/Physical.cpp | 2 +- src/modelinfo/VehicleModelInfo.cpp | 2 +- src/peds/CopPed.cpp | 2 +- src/render/2dEffect.h | 4 +-- src/render/Clouds.cpp | 10 ++++---- src/render/Particle.cpp | 52 +++++++++++++++++++------------------- src/render/Rubbish.cpp | 8 +++--- src/render/Skidmarks.cpp | 6 ++--- src/skel/glfw/glfw.cpp | 4 +-- src/skel/win/win.cpp | 4 +-- src/vehicles/Vehicle.cpp | 2 +- src/weapons/WeaponEffects.cpp | 2 +- 22 files changed, 93 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index 185e08d6..db38da64 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -65,7 +65,7 @@ uint32 _CurMP3Index; int32 _CurMP3Pos; bool _bIsMp3Active; -#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) +#if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK) bool _bUseHDDAudio; char _aHDDPath[MAX_PATH]; #endif @@ -1043,7 +1043,7 @@ cSampleManager::Initialise(void) if ( !m_bInitialised ) { -#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) +#if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK) FrontEndMenuManager.WaitForUserCD(); if ( FrontEndMenuManager.m_bQuitGameNoCD ) { @@ -1060,7 +1060,7 @@ cSampleManager::Initialise(void) } } -#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) +#if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK) // hddaudio /** Option for user to play audio files directly from hard disk. @@ -1297,17 +1297,17 @@ cSampleManager::Terminate(void) bool cSampleManager::CheckForAnAudioFileOnCD(void) { -#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) +#if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK) char filepath[MAX_PATH]; -#if defined(GTA3_1_1_PATCH) +#if GTA_VERSION >= GTA3_PC_11 if (_bUseHDDAudio) strcpy(filepath, _aHDDPath); else strcpy(filepath, m_szCDRomRootPath); #else strcpy(filepath, m_szCDRomRootPath); -#endif // #if defined(GTA3_1_1_PATCH) +#endif // #if GTA_VERSION >= GTA3_PC_11 strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]); @@ -1324,13 +1324,13 @@ cSampleManager::CheckForAnAudioFileOnCD(void) #else return true; -#endif // #if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) +#endif // #if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK) } char cSampleManager::GetCDAudioDriveLetter(void) { -#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) +#if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK) if (_bUseHDDAudio) { if ( strlen(_aHDDPath) != 0 ) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 085c773a..dbd477e2 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1273,7 +1273,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION < GTA3_PC_11 REGISTER_COMMAND(COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), #endif #endif diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp index ca6a1853..acd9e424 100644 --- a/src/control/Script6.cpp +++ b/src/control/Script6.cpp @@ -1326,7 +1326,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) #endif return 0; #endif -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION < GTA3_PC_11 case COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER: CollectParameters(&m_nIp, 1); #ifdef FIX_BUGS diff --git a/src/control/ScriptCommands.h b/src/control/ScriptCommands.h index 56908edb..b9067bea 100644 --- a/src/control/ScriptCommands.h +++ b/src/control/ScriptCommands.h @@ -1156,7 +1156,7 @@ enum { COMMAND_IS_CHAR_LYING_DOWN, COMMAND_CAN_CHAR_SEE_DEAD_CHAR, COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION < GTA3_PC_11 COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER, #endif #ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 3e016667..0e1c9d9f 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -2570,7 +2570,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) ResetStatics = false; } -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION < GTA3_PC_11 ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; @@ -2605,7 +2605,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f); else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 HeadPos.x = 0.0f; HeadPos.y = 0.0f; HeadPos.z = 0.0f; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 56225fed..1e1aa722 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -74,7 +74,7 @@ bool bDidWeProcessAnyCinemaCam; CCamera::CCamera(void) { -#if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS) +#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS) m_fMouseAccelHorzntl = 0.0025f; m_fMouseAccelVertical = 0.003f; #endif @@ -88,7 +88,7 @@ CCamera::CCamera(float) void CCamera::Init(void) { -#if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS) +#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS) float fMouseAccelHorzntl = m_fMouseAccelHorzntl; float fMouseAccelVertical = m_fMouseAccelVertical; #endif @@ -104,7 +104,7 @@ CCamera::Init(void) memset(this, 0, sizeof(CCamera)); // getting rid of vtable, eh? #endif - #if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS) + #if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS) m_fMouseAccelHorzntl = fMouseAccelHorzntl; m_fMouseAccelVertical = fMouseAccelVertical; #endif @@ -237,7 +237,7 @@ CCamera::Init(void) m_uiTransitionState = 0; m_uiTimeTransitionStart = 0; m_bLookingAtPlayer = true; -#if !defined(GTA3_1_1_PATCH) && !defined(FIX_BUGS) +#if GTA_VERSION < GTA3_PC_11 && !defined(FIX_BUGS) m_fMouseAccelHorzntl = 0.0025f; m_fMouseAccelVertical = 0.003f; #endif diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 318e5903..5597b358 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -1009,7 +1009,7 @@ CMenuManager::Draw() CFont::SetCentreOff(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 #ifdef DRAW_MENU_VERSION_TEXT CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); CFont::SetRightJustifyOn(); @@ -3538,7 +3538,7 @@ CMenuManager::LoadAllTextures() CTxdStore::LoadTxd(frontendTxdSlot, "MODELS/FRONTEND.TXD"); CTxdStore::AddRef(frontendTxdSlot); CTxdStore::SetCurrentTxd(frontendTxdSlot); -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION < GTA3_PC_11 CStreaming::IHaveUsedStreamingMemory(); CTimer::Update(); #endif @@ -3568,7 +3568,7 @@ CMenuManager::LoadAllTextures() m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } #endif -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 CStreaming::IHaveUsedStreamingMemory(); CTimer::Update(); #endif @@ -3583,7 +3583,7 @@ CMenuManager::LoadSettings() int fileHandle = CFileMgr::OpenFile("gta3.set", "r"); int32 prevLang = m_PrefsLanguage; -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 CMBlur::BlurOn = (_dwOperatingSystemVersion != OS_WIN98); #else CMBlur::BlurOn = true; @@ -3882,7 +3882,7 @@ void CMenuManager::PrintStats() { int rowNum = ConstructStatLine(99999); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); #endif CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why @@ -4936,7 +4936,7 @@ CMenuManager::ProcessButtonPresses(void) m_PrefsUseWideScreen = false; m_PrefsShowSubtitles = true; m_nDisplayVideoMode = m_nPrefsVideoMode; -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 if (_dwOperatingSystemVersion == OS_WIN98) { CMBlur::BlurOn = false; CMBlur::MotionBlurClose(); @@ -5588,7 +5588,7 @@ CMenuManager::WaitForUserCD() CSprite2d *splash; char *splashscreen = nil; -#if (!(defined RANDOMSPLASH) && !(defined GTA3_1_1_PATCH)) +#if (!(defined RANDOMSPLASH) && GTA_VERSION < GTA3_PC_11) if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) splashscreen = "mainsc2"; else diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index f8ff3acf..ae08f5f5 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -115,7 +115,7 @@ void RestoreDefGraphics(int8 action) { CMenuManager::m_PrefsVsync = true; CMenuManager::m_PrefsUseWideScreen = false; FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode; - #ifdef GTA3_1_1_PATCH + #if GTA_VERSION >= GTA3_PC_11 if (_dwOperatingSystemVersion == OS_WIN98) { CMBlur::BlurOn = false; CMBlur::MotionBlurClose(); diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 9c6bdc98..b971f3ec 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -937,7 +937,7 @@ void CPad::AddToPCCheatString(char c) if ( !_CHEATCMP("GNIROOOOOB") ) SlowTimeCheat(); -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION < GTA3_PC_11 // "TURTOISE" if ( !_CHEATCMP("ESIOTRUT") ) ArmourCheat(); diff --git a/src/core/config.h b/src/core/config.h index 99c5f6ef..5d528d50 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -135,10 +135,6 @@ enum Config { NUM_EXPLOSIONS = 48, }; -// We'll use this once we're ready to become independent of the game -// Use it to mark bugs in the code that will prevent the game from working then -//#define STANDALONE - // We don't expect to compile for PS2 or Xbox // but it might be interesting for documentation purposes #define GTA_PC @@ -165,6 +161,16 @@ enum Config { #define FINAL #endif +// Version defines +#define GTA3_PS2_140 300 +#define GTA3_PS2_160 301 +#define GTA3_PC_10 310 +#define GTA3_PC_11 311 +#define GTA3_PC_STEAM 312 +// TODO? maybe something for xbox or android? + +#define GTA_VERSION GTA3_PC_11 + // quality of life fixes that should also be in FINAL #define NASTY_GAME // nasty game for all languages #define NO_CDCHECK @@ -173,14 +179,18 @@ enum Config { #define DRAW_GAME_VERSION_TEXT #define DRAW_MENU_VERSION_TEXT +// Memory allocation and compression +// #define USE_CUSTOM_ALLOCATOR // use CMemoryHeap for allocation. use with care, not finished yet +//#define COMPRESSED_COL_VECTORS // use compressed vectors for collision vertices +//#define ANIM_COMPRESSION // only keep most recently used anims uncompressed + #if defined GTA_PS2 # define GTA_PS2_STUFF # define RANDOMSPLASH +# define USE_CUSTOM_ALLOCATOR # define VU_COLLISION # define ANIM_COMPRESSION #elif defined GTA_PC -# define GTA3_1_1_PATCH -//# define GTA3_STEAM_PATCH # ifdef GTA_PS2_STUFF # define USE_PS2_RAND # define RANDOMSPLASH // use random splash as on PS2 @@ -190,7 +200,7 @@ enum Config { #endif #ifdef VU_COLLISION -#define COMPRESSED_COL_VECTORS // current need compressed vectors in this code +#define COMPRESSED_COL_VECTORS // currently need compressed vectors in this code #endif #ifdef MASTER @@ -242,7 +252,7 @@ enum Config { #endif #ifndef EXTENDED_COLOURFILTER -#undef SCREEN_DROPLETS // we need the frontbuffer for this effect +#undef SCREEN_DROPLETS // we need the backbuffer for this effect #endif #ifndef EXTENDED_PIPELINES #undef SCREEN_DROPLETS // we need neo.txd diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 172bae3f..04cec96b 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -824,7 +824,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV normalSpeed = DotProduct(speed, colpoint.normal); if(normalSpeed < 0.0f){ float minspeed = 1.3f*GRAVITY * CTimer::GetTimeStep(); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 if ((IsObject() || IsVehicle() && (GetUp().z < -0.3f || ((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED))) && #else if((IsObject() || IsVehicle() && GetUp().z < -0.3f) && diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index 5b212f62..afda70d3 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -962,7 +962,7 @@ CVehicleModelInfo::DeleteVehicleColourTextures(void) for(i = 0; i < 256; i++){ if(ms_colourTextureTable[i]){ RwTextureDestroy(ms_colourTextureTable[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 ms_colourTextureTable[i] = nil; #endif } diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index f289697e..d9f55559 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -667,7 +667,7 @@ CCopPed::ProcessControl(void) } if (bDuckAndCover) { -#if !defined(GTA3_1_1_PATCH) && !defined(VC_PED_PORTS) +#if GTA_VERSION < GTA3_PC_11 && !defined(VC_PED_PORTS) if (!bNotAllowedToDuck && Seek()) { SetMoveState(PEDMOVE_STILL); SetMoveAnim(); diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h index 628d64c2..a8013b34 100644 --- a/src/render/2dEffect.h +++ b/src/render/2dEffect.h @@ -78,12 +78,12 @@ public: if(type == EFFECT_LIGHT){ if(light.corona) RwTextureDestroy(light.corona); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 light.corona = nil; #endif if(light.shadow) RwTextureDestroy(light.shadow); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 light.shadow = nil; #endif } diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 05ddbcdc..161418b9 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -44,23 +44,23 @@ void CClouds::Shutdown(void) { RwTextureDestroy(gpCloudTex[0]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[0] = nil; #endif RwTextureDestroy(gpCloudTex[1]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[1] = nil; #endif RwTextureDestroy(gpCloudTex[2]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[2] = nil; #endif RwTextureDestroy(gpCloudTex[3]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[3] = nil; #endif RwTextureDestroy(gpCloudTex[4]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCloudTex[4] = nil; #endif } diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index acce946b..2b19486e 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -590,7 +590,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_SMOKE_FILES; i++ ) { RwTextureDestroy(gpSmokeTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpSmokeTex[i] = nil; #endif } @@ -598,7 +598,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_SMOKE2_FILES; i++ ) { RwTextureDestroy(gpSmoke2Tex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpSmoke2Tex[i] = nil; #endif } @@ -606,7 +606,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_RUBBER_FILES; i++ ) { RwTextureDestroy(gpRubberTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRubberTex[i] = nil; #endif } @@ -614,7 +614,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_RAINSPLASH_FILES; i++ ) { RwTextureDestroy(gpRainSplashTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRainSplashTex[i] = nil; #endif } @@ -622,7 +622,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_WATERSPRAY_FILES; i++ ) { RwTextureDestroy(gpWatersprayTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpWatersprayTex[i] = nil; #endif } @@ -630,7 +630,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_EXPLOSIONMEDIUM_FILES; i++ ) { RwTextureDestroy(gpExplosionMediumTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpExplosionMediumTex[i] = nil; #endif } @@ -638,7 +638,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ ) { RwTextureDestroy(gpGunFlashTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpGunFlashTex[i] = nil; #endif } @@ -646,7 +646,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_RAINDROP_FILES; i++ ) { RwTextureDestroy(gpRainDropTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRainDropTex[i] = nil; #endif } @@ -654,7 +654,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ ) { RwTextureDestroy(gpRainSplashupTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRainSplashupTex[i] = nil; #endif } @@ -662,7 +662,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ ) { RwTextureDestroy(gpBirdfrontTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpBirdfrontTex[i] = nil; #endif } @@ -670,7 +670,7 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ ) { RwTextureDestroy(gpCarDebrisTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCarDebrisTex[i] = nil; #endif } @@ -678,78 +678,78 @@ void CParticle::Shutdown() for ( int32 i = 0; i < MAX_CARSPLASH_FILES; i++ ) { RwTextureDestroy(gpCarSplashTex[i]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCarSplashTex[i] = nil; #endif } RwTextureDestroy(gpFlame1Tex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpFlame1Tex = nil; #endif RwTextureDestroy(gpFlame5Tex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpFlame5Tex = nil; #endif RwTextureDestroy(gpRainDropSmallTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRainDropSmallTex = nil; #endif RwTextureDestroy(gpBloodTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpBloodTex = nil; #endif RwTextureDestroy(gpLeafTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpLeafTex = nil; #endif RwTextureDestroy(gpCloudTex1); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCloudTex1 = nil; #endif RwTextureDestroy(gpCloudTex4); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCloudTex4 = nil; #endif RwTextureDestroy(gpBloodSmallTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpBloodSmallTex = nil; #endif RwTextureDestroy(gpGungeTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpGungeTex = nil; #endif RwTextureDestroy(gpCollisionSmokeTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCollisionSmokeTex = nil; #endif RwTextureDestroy(gpBulletHitTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpBulletHitTex = nil; #endif RwTextureDestroy(gpGunShellTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpGunShellTex = nil; #endif RwTextureDestroy(gpWakeOldTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpWakeOldTex = nil; #endif RwTextureDestroy(gpPointlightTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpPointlightTex = nil; #endif diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp index bfd50c07..18a20bc7 100644 --- a/src/render/Rubbish.cpp +++ b/src/render/Rubbish.cpp @@ -414,19 +414,19 @@ void CRubbish::Shutdown(void) { RwTextureDestroy(gpRubbishTexture[0]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[0] = nil; #endif RwTextureDestroy(gpRubbishTexture[1]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[1] = nil; #endif RwTextureDestroy(gpRubbishTexture[2]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[2] = nil; #endif RwTextureDestroy(gpRubbishTexture[3]); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpRubbishTexture[3] = nil; #endif } diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp index ad036d58..9e509b52 100644 --- a/src/render/Skidmarks.cpp +++ b/src/render/Skidmarks.cpp @@ -54,15 +54,15 @@ void CSkidmarks::Shutdown(void) { RwTextureDestroy(gpSkidTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpSkidTex = nil; #endif RwTextureDestroy(gpSkidBloodTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpSkidBloodTex = nil; #endif RwTextureDestroy(gpSkidMudTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpSkidMudTex = nil; #endif } diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 56877d37..cad84b8a 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -389,7 +389,7 @@ psInitialize(void) InitialiseLanguage(); -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION < GTA3_PC_11 FrontEndMenuManager.LoadSettings(); #endif @@ -443,7 +443,7 @@ psInitialize(void) #ifndef PS2_MENU -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 FrontEndMenuManager.LoadSettings(); #endif diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 5f6d662c..6d0c2d67 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -651,7 +651,7 @@ psInitialize(void) C_PcSave::SetSaveDirectory(_psGetUserFilesFolder()); InitialiseLanguage(); -#ifndef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 FrontEndMenuManager.LoadSettings(); #endif @@ -703,7 +703,7 @@ psInitialize(void) #ifndef PS2_MENU -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 FrontEndMenuManager.LoadSettings(); #endif diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index d2ca5a1a..9adcf148 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -405,7 +405,7 @@ CVehicle::FlyingControl(eFlightModel flightModel) else fThrust = fThrustVar * (CPad::GetPad(0)->GetAccelerate() - 2 * CPad::GetPad(0)->GetBrake()) / 255.0f + 0.95f; fThrust -= fRotorFallOff * DotProduct(m_vecMoveSpeed, GetUp()); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 if (fThrust > 0.9f && GetPosition().z > 80.0f) fThrust = 0.9f; #endif diff --git a/src/weapons/WeaponEffects.cpp b/src/weapons/WeaponEffects.cpp index 46195d2c..214ae9c7 100644 --- a/src/weapons/WeaponEffects.cpp +++ b/src/weapons/WeaponEffects.cpp @@ -46,7 +46,7 @@ void CWeaponEffects::Shutdown(void) { RwTextureDestroy(gpCrossHairTex); -#ifdef GTA3_1_1_PATCH +#if GTA_VERSION >= GTA3_PC_11 gpCrossHairTex = nil; #endif } -- cgit v1.2.3 From 8f05ccd6c4608172ae4c9a589d2b2c4ce915eb2c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 30 Nov 2020 02:15:03 +0300 Subject: small garages revision + small template stuff --- src/control/Garages.cpp | 190 ++++++++++++++++++++++++++---------------------- src/control/Garages.h | 3 +- src/control/Phones.cpp | 2 +- src/control/Pickups.cpp | 2 +- src/control/Script3.cpp | 4 +- src/control/Script5.cpp | 12 +-- src/core/World.cpp | 8 ++ src/core/templates.h | 12 ++- src/vehicles/Cranes.cpp | 6 +- 9 files changed, 133 insertions(+), 106 deletions(-) (limited to 'src') diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index fc8f84f2..96391914 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -129,7 +129,7 @@ int32 CGarages::PoliceCarsCollected; CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS]; CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS]; CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS]; -int32 CGarages::AudioEntity = AEHANDLE_NONE; +int32 hGarages = AEHANDLE_NONE; CGarage CGarages::aGarages[NUM_GARAGES]; bool CGarages::bCamShouldBeOutisde; @@ -156,12 +156,12 @@ void CGarages::Init(void) aCarsInSafeHouse2[i].Init(); for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) aCarsInSafeHouse3[i].Init(); - AudioEntity = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1); - if (AudioEntity >= 0) - DMAudio.SetEntityStatus(AudioEntity, 1); + hGarages = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1); + if (hGarages >= 0) + DMAudio.SetEntityStatus(hGarages, 1); AddOne( - CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1, - CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2, + CVector(CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1), + CVector(CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2), GARAGE_CRUSHER, 0); } @@ -169,17 +169,17 @@ void CGarages::Init(void) void CGarages::Shutdown(void) { NumGarages = 0; - if (AudioEntity < 0) + if (hGarages < 0) return; - DMAudio.DestroyEntity(AudioEntity); - AudioEntity = AEHANDLE_NONE; + DMAudio.DestroyEntity(hGarages); + hGarages = AEHANDLE_NONE; } #endif void CGarages::Update(void) { static int GarageToBeTidied = 0; -#ifndef PS2 +#ifndef GTA_PS2 if (CReplay::IsPlayingBack()) return; #endif @@ -202,23 +202,23 @@ void CGarages::Update(void) aGarages[GarageToBeTidied].TidyUpGarage(); } -int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId) +int16 CGarages::AddOne(CVector p1, CVector p2, eGarageType type, int32 targetId) { if (NumGarages >= NUM_GARAGES) { assert(0); return NumGarages++; } CGarage* pGarage = &aGarages[NumGarages]; - pGarage->m_fX1 = Min(X1, X2); - pGarage->m_fX2 = Max(X1, X2); - pGarage->m_fY1 = Min(Y1, Y2); - pGarage->m_fY2 = Max(Y1, Y2); - pGarage->m_fZ1 = Min(Z1, Z2); - pGarage->m_fZ2 = Max(Z1, Z2); + pGarage->m_fX1 = Min(p1.x, p2.x); + pGarage->m_fX2 = Max(p1.x, p2.x); + pGarage->m_fY1 = Min(p1.y, p2.y); + pGarage->m_fY2 = Max(p1.y, p2.y); + pGarage->m_fZ1 = Min(p1.z, p2.z); + pGarage->m_fZ2 = Max(p1.z, p2.z); pGarage->m_pDoor1 = nil; pGarage->m_pDoor2 = nil; - pGarage->m_fDoor1Z = Z1; - pGarage->m_fDoor2Z = Z1; + pGarage->m_fDoor1Z = p1.z; + pGarage->m_fDoor2Z = p1.z; pGarage->m_eGarageType = type; pGarage->m_bRecreateDoorOnNextRefresh = false; pGarage->m_bRotatedDoor = false; @@ -368,7 +368,7 @@ void CGarage::Update() if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_RESPRAY; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); CStats::CheckPointReachedSuccessfully(); } UpdateDoorsHeight(); @@ -464,7 +464,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENEDCONTAINSCAR; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -510,7 +510,7 @@ void CGarage::Update() if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_SETUP_BOMB; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); } UpdateDoorsHeight(); break; @@ -575,7 +575,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENEDCONTAINSCAR; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -599,7 +599,8 @@ void CGarage::Update() } } else if (!FindPlayerVehicle() && m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && - !IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f)) { + !IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f) && + !IsAnyOtherCarTouchingGarage(m_pTarget)) { CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE); FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true; m_eGarageState = GS_CLOSING; @@ -609,7 +610,7 @@ void CGarage::Update() case GS_CLOSING: m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); if (m_bClosingWithoutTargetCar) m_eGarageState = GS_FULLYCLOSED; else { @@ -639,7 +640,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -676,7 +677,7 @@ void CGarage::Update() m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); if (m_pTarget) { DestroyVehicleAndDriverAndPassengers(m_pTarget); m_pTarget = nil; @@ -723,7 +724,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -772,7 +773,7 @@ void CGarage::Update() m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); if (m_pTarget) { MarkThisCarAsCollectedForCraig(m_pTarget->GetModelIndex()); DestroyVehicleAndDriverAndPassengers(m_pTarget); @@ -812,7 +813,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -833,7 +834,7 @@ void CGarage::Update() m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); } if (!IsGarageEmpty()) m_eGarageState = GS_OPENING; @@ -844,7 +845,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -893,7 +894,7 @@ void CGarage::Update() m_pTarget = nil; m_eGarageState = GS_AFTERDROPOFF; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_CRUSH_CAR; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); } } else @@ -913,7 +914,7 @@ void CGarage::Update() m_fDoorPos = Min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED); if (m_fDoorPos == HALFPI) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateCrusherAngle(); break; @@ -945,7 +946,7 @@ void CGarage::Update() case GS_CLOSING: m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); if (m_bClosingWithoutTargetCar) m_eGarageState = GS_FULLYCLOSED; else { @@ -974,7 +975,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -994,7 +995,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -1014,7 +1015,7 @@ void CGarage::Update() m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); } UpdateDoorsHeight(); break; @@ -1022,7 +1023,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -1064,7 +1065,7 @@ void CGarage::Update() if (!IsPlayerOutsideGarage()) m_eGarageState = GS_OPENING; else if (m_fDoorPos == 0.0f) { - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); m_eGarageState = GS_FULLYCLOSED; switch (m_eGarageType) { case GARAGE_HIDEOUT_ONE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse1, MAX_STORED_CARS_IN_INDUSTRIAL); break; @@ -1111,7 +1112,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -1136,7 +1137,7 @@ void CGarage::Update() m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f); } UpdateDoorsHeight(); break; @@ -1152,7 +1153,7 @@ void CGarage::Update() m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; - DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); + DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f); } UpdateDoorsHeight(); break; @@ -1387,7 +1388,9 @@ void CGarage::RemoveCarsBlockingDoorNotInside() if (!pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { CWorld::Remove(pVehicle); delete pVehicle; - return; // WHY? +#ifndef FIX_BUGS + return; // makes no sense +#endif } } } @@ -1405,34 +1408,32 @@ void CGarages::PrintMessages() CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); -#if defined(PS2) || defined (FIX_BUGS) +#if defined(GTA_PS2) || defined (FIX_BUGS) float y_offset = SCREEN_HEIGHT / 3; // 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 - if (MessageNumberInString2 < 0) { - if (MessageNumberInString < 0) { - CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString)); + if (MessageNumberInString2 >= 0) { + CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString); + CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString); - CFont::SetColor(CRGBA(89, 115, 150, 255)); - CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString)); - } - else { - CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString); + CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString); + } + else if (MessageNumberInString >= 0) { + CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString); - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString); + CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString); - CFont::SetColor(CRGBA(89, 115, 150, 255)); - CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString); - } + CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString); } else { - CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString); - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString); + CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString)); CFont::SetColor(CRGBA(89, 115, 150, 255)); - CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString); + CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString)); } } } @@ -1508,41 +1509,54 @@ void CGarage::UpdateCrusherShake(float X, float Y) m_pDoor2->GetMatrix().GetPosition().y -= Y; } -// This is dumb but there is no way to avoid goto. What was there originally even? -static bool DoINeedToRefreshPointer(CEntity * pDoor, bool bIsDummy, uint8 nIndex) +void CGarage::RefreshDoorPointers(bool bCreate) { - bool bNeedToFindDoorEntities = false; - if (pDoor) { - if (bIsDummy) { - if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex((CDummy*)pDoor))) - return true; - if (nIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)pDoor) & 0x7F)) + bool bNeedToFindDoorEntities = bCreate || m_bRecreateDoorOnNextRefresh; + m_bRecreateDoorOnNextRefresh = false; + if (m_pDoor1) { + if (m_bDoor1IsDummy) { + if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor1))) bNeedToFindDoorEntities = true; - if (!CGarages::IsModelIndexADoor(pDoor->GetModelIndex())) - return true; + else { + if (m_bDoor1PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor1) & 0x7F)) + bNeedToFindDoorEntities = true; + if (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex())) + bNeedToFindDoorEntities = true; + } } else { - if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex((CObject*)pDoor))) - return true; - if (nIndex != (CPools::GetObjectPool()->GetIndex((CObject*)pDoor) & 0x7F)) + if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor1))) bNeedToFindDoorEntities = true; - if (!CGarages::IsModelIndexADoor(pDoor->GetModelIndex())) - return true; + else { + if (m_bDoor1PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor1) & 0x7F)) + bNeedToFindDoorEntities = true; + if (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex())) + bNeedToFindDoorEntities = true; + } + } + } + if (m_pDoor2) { + if (m_bDoor2IsDummy) { + if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor2))) + bNeedToFindDoorEntities = true; + else { + if (m_bDoor2PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor2) & 0x7F)) + bNeedToFindDoorEntities = true; + if (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex())) + bNeedToFindDoorEntities = true; + } + } + else { + if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor2))) + bNeedToFindDoorEntities = true; + else { + if (m_bDoor2PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor2) & 0x7F)) + bNeedToFindDoorEntities = true; + if (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex())) + bNeedToFindDoorEntities = true; + } } } - return bNeedToFindDoorEntities; -} - -void CGarage::RefreshDoorPointers(bool bCreate) -{ - bool bNeedToFindDoorEntities = true; - if (!bCreate && !m_bRecreateDoorOnNextRefresh) - bNeedToFindDoorEntities = false; - m_bRecreateDoorOnNextRefresh = false; - if (DoINeedToRefreshPointer(m_pDoor1, m_bDoor1IsDummy, m_bDoor1PoolIndex)) - bNeedToFindDoorEntities = true; - if (DoINeedToRefreshPointer(m_pDoor2, m_bDoor2IsDummy, m_bDoor2PoolIndex)) - bNeedToFindDoorEntities = true; if (bNeedToFindDoorEntities) FindDoorsEntities(); } diff --git a/src/control/Garages.h b/src/control/Garages.h index 00020eb3..41b2afb7 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -198,7 +198,6 @@ class CGarages static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS]; static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS]; static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS]; - static int32 AudioEntity; static bool bCamShouldBeOutisde; public: @@ -208,7 +207,7 @@ public: #endif static void Update(void); - static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId); + static int16 AddOne(CVector pos1, CVector pos2, eGarageType type, int32 targetId); static void ChangeGarageType(int16, eGarageType, int32); static void PrintMessages(void); static void TriggerMessage(const char* text, int16, uint16 time, int16); diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index ad29d4fb..c951e868 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -387,7 +387,7 @@ INITSAVEBUF // Convert entity pointer to building pool index while saving if (phone->m_pEntity) { - phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex((CBuilding*)phone->m_pEntity) + 1); + phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1); } } VALIDATESAVEBUF(*size) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 8951ed82..2503f5c8 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1009,7 +1009,7 @@ INITSAVEBUF for (int32 i = 0; i < NUMPICKUPS; i++) { CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]); if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil) - buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1); + buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pObject) + 1); } WriteSaveBuf(buf, CollectedPickUpIndex); diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp index c0112d06..23ab453c 100644 --- a/src/control/Script3.cpp +++ b/src/control/Script3.cpp @@ -291,7 +291,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) infZ = *(float*)&ScriptParams[5]; supZ = *(float*)&ScriptParams[2]; } - ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], 0); + ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), (eGarageType)ScriptParams[6], 0); StoreParameters(&m_nIp, 1); return 0; } @@ -316,7 +316,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) infZ = *(float*)&ScriptParams[5]; supZ = *(float*)&ScriptParams[2]; } - ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], ScriptParams[7]); + ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), (eGarageType)ScriptParams[6], ScriptParams[7]); StoreParameters(&m_nIp, 1); return 0; } diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp index bada95ea..164ca036 100644 --- a/src/control/Script5.cpp +++ b/src/control/Script5.cpp @@ -1604,10 +1604,10 @@ INITSAVEBUF handle = 0; } else if (pBuilding->GetIsATreadable()) { type = 1; - handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding) + 1; + handle = CPools::GetTreadablePool()->GetJustIndex_NoFreeAssert((CTreadable*)pBuilding) + 1; } else { type = 2; - handle = CPools::GetBuildingPool()->GetJustIndex(pBuilding) + 1; + handle = CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pBuilding) + 1; } WriteSaveBuf(buf, type); WriteSaveBuf(buf, handle); @@ -1625,19 +1625,19 @@ INITSAVEBUF case ENTITY_TYPE_BUILDING: if (((CBuilding*)pEntity)->GetIsATreadable()) { type = 1; - handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pEntity) + 1; + handle = CPools::GetTreadablePool()->GetJustIndex_NoFreeAssert((CTreadable*)pEntity) + 1; } else { type = 2; - handle = CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pEntity) + 1; + handle = CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)pEntity) + 1; } break; case ENTITY_TYPE_OBJECT: type = 3; - handle = CPools::GetObjectPool()->GetJustIndex((CObject*)pEntity) + 1; + handle = CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)pEntity) + 1; break; case ENTITY_TYPE_DUMMY: type = 4; - handle = CPools::GetDummyPool()->GetJustIndex((CDummy*)pEntity) + 1; + handle = CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)pEntity) + 1; default: break; } } diff --git a/src/core/World.cpp b/src/core/World.cpp index 33c2f1c1..70388b38 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1738,10 +1738,12 @@ CWorld::ShutDown(void) CWorld::Remove(pEntity); delete pEntity; } +#ifndef FIX_BUGS pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); +#endif } for(int32 i = 0; i < 4; i++) { for(CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) { @@ -1753,6 +1755,12 @@ CWorld::ShutDown(void) } for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); +#ifdef FIX_BUGS + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); +#endif if(pSector->m_lists[ENTITYLIST_BUILDINGS].first) { sprintf(gString, "Building list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); diff --git a/src/core/templates.h b/src/core/templates.h index 86239664..166f865c 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -124,12 +124,18 @@ public: (T*)&m_entries[handle >> 8] : nil; } int GetIndex(T *entry){ - int i = GetJustIndex(entry); + int i = GetJustIndex_NoFreeAssert(entry); return m_flags[i].u + (i<<8); } int GetJustIndex(T *entry){ - // TODO: the cast is unsafe - return (int)((U*)entry - m_entries); + int index = GetJustIndex_NoFreeAssert(entry); + assert(!IsFreeSlot(index)); + return index; + } + int GetJustIndex_NoFreeAssert(T* entry){ + int index = ((U*)entry - m_entries); + assert((U*)entry == (U*)&m_entries[index]); // cast is unsafe - check required + return index; } int GetNoOfUsedSpaces(void) const{ int i; diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index 757974a6..564f493d 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -639,11 +639,11 @@ void CCranes::Save(uint8* buf, uint32* size) for (int i = 0; i < NUM_CRANES; i++) { CCrane *pCrane = WriteSaveBuf(buf, aCranes[i]); if (pCrane->m_pCraneEntity != nil) - pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex(pCrane->m_pCraneEntity) + 1); + pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pCrane->m_pCraneEntity) + 1); if (pCrane->m_pHook != nil) - pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex(pCrane->m_pHook) + 1); + pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pCrane->m_pHook) + 1); if (pCrane->m_pVehiclePickedUp != nil) - pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex(pCrane->m_pVehiclePickedUp) + 1); + pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pCrane->m_pVehiclePickedUp) + 1); } VALIDATESAVEBUF(*size); -- cgit v1.2.3 From 4b9fb631fc1b250a1e353da2e319d49371573bcc Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 30 Nov 2020 23:44:58 +0100 Subject: added a few registered pointers and memory debug --- src/core/FileLoader.cpp | 5 +++++ src/core/Streaming.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- src/core/main.cpp | 8 ++++++-- src/core/main.h | 4 ++++ src/core/re3.cpp | 11 +++++++++++ 5 files changed, 67 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 88a99fa9..aeaede56 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -243,6 +243,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) buf += 44; if(model.numSpheres > 0){ model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere)); + REGISTER_MEMPTR(&model.spheres); for(i = 0; i < model.numSpheres; i++){ model.spheres[i].Set(*(float*)buf, *(CVector*)(buf+4), buf[16], buf[17]); buf += 20; @@ -254,6 +255,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) buf += 4; if(model.numLines > 0){ model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine)); + REGISTER_MEMPTR(&model.lines); for(i = 0; i < model.numLines; i++){ model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12)); buf += 24; @@ -265,6 +267,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) buf += 4; if(model.numBoxes > 0){ model.boxes = (CColBox*)RwMalloc(model.numBoxes*sizeof(CColBox)); + REGISTER_MEMPTR(&model.boxes); for(i = 0; i < model.numBoxes; i++){ model.boxes[i].Set(*(CVector*)buf, *(CVector*)(buf+12), buf[24], buf[25]); buf += 28; @@ -276,6 +279,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) buf += 4; if(numVertices > 0){ model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector)); + REGISTER_MEMPTR(&model.vertices); for(i = 0; i < numVertices; i++){ model.vertices[i].Set(*(float*)buf, *(float*)(buf+4), *(float*)(buf+8)); if(Abs(*(float*)buf) >= 256.0f || @@ -291,6 +295,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) buf += 4; if(model.numTriangles > 0){ model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle)); + REGISTER_MEMPTR(&model.triangles); for(i = 0; i < model.numTriangles; i++){ model.triangles[i].Set(model.vertices, *(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12], buf[13]); buf += 16; diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index a28fe39d..03b49fd6 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -458,6 +458,35 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) CFileMgr::CloseFile(fd); } +#ifdef USE_CUSTOM_ALLOCATOR +RpAtomic* +RegisterAtomicMemPtrsCB(RpAtomic *atomic, void *data) +{ +#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31 + // not quite sure what's going on here: + // gta3's RW 3.1 allocates separate memory for geometry data of RpGeometry. + // Is that a R* change? rpDefaultGeometryInstance also depends on it + RpGeometry *geo = RpAtomicGetGeometry(atomic); + if(geo->triangles) + REGISTER_MEMPTR(&geo->triangles); + if(geo->matList.materials) + REGISTER_MEMPTR(&geo->matList.materials); + if(geo->preLitLum) + REGISTER_MEMPTR(&geo->preLitLum); + if(geo->texCoords[0]) + REGISTER_MEMPTR(&geo->texCoords[0]); + if(geo->texCoords[1]) + REGISTER_MEMPTR(&geo->texCoords[1]); +#else + // normally RpGeometry is allocated in one block (excluding morph targets) + // so we don't really have allocated pointers in the struct. + // NB: in librw we actually do it in two allocations (geometry itself and data) + // so we could conceivably come up with something here +#endif + return atomic; +} +#endif + bool CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) { @@ -494,9 +523,11 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) PUSH_MEMID(MEMID_STREAM_MODELS); CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); -// TODO(USE_CUSTOM_ALLOCATOR): register mem pointers if(mi->IsSimple()){ success = CFileLoader::LoadAtomicFile(stream, streamId); +#ifdef USE_CUSTOM_ALLOCATOR + RegisterAtomicMemPtrsCB(((CSimpleModelInfo*)mi)->m_atomics[0], nil); +#endif } else if (mi->GetModelType() == MITYPE_VEHICLE) { // load vehicles in two parts CModelInfo::GetModelInfo(streamId)->AddRef(); @@ -505,6 +536,10 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED; }else{ success = CFileLoader::LoadClumpFile(stream, streamId); +#ifdef USE_CUSTOM_ALLOCATOR + if(success) + RpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil); +#endif } POP_MEMID(); UpdateMemoryUsed(); @@ -628,13 +663,16 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) if(streamId < STREAM_OFFSET_TXD){ // Model -// TODO(USE_CUSTOM_ALLOCATOR): register pointers mi = CModelInfo::GetModelInfo(streamId); PUSH_MEMID(MEMID_STREAM_MODELS); CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); success = CFileLoader::FinishLoadClumpFile(stream, streamId); - if(success) + if(success){ +#ifdef USE_CUSTOM_ALLOCATOR + RpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil); +#endif success = AddToLoadedVehiclesList(streamId); + } POP_MEMID(); mi->RemoveRef(); CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot()); diff --git a/src/core/main.cpp b/src/core/main.cpp index d34eb8f3..102548b6 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -110,6 +110,9 @@ void TheGame(void); void DebugMenuPopulate(void); #endif +#ifndef FINAL +bool gbPrintMemoryUsage; +#endif #ifdef GTA_PS2 #define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad @@ -957,9 +960,10 @@ DisplayGameDebugText() TWEAKBOOL(bDisplayPosn); TWEAKBOOL(bDisplayRate); } -#endif -// PrintMemoryUsage(); // TODO: put this somewhere else + if(gbPrintMemoryUsage) + PrintMemoryUsage(); +#endif char str[200]; wchar ustr[200]; diff --git a/src/core/main.h b/src/core/main.h index 13fff447..77fac46a 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -20,6 +20,10 @@ extern bool gbShowTimebars; #define gbShowTimebars false #endif +#ifndef FINAL +extern bool gbPrintMemoryUsage; +#endif + class CSprite2d; bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index ee747218..506b2714 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -29,6 +29,7 @@ #include "Script.h" #include "postfx.h" #include "custompipes.h" +#include "MemoryHeap.h" #ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS #include "FileMgr.h" @@ -383,6 +384,10 @@ SwitchToMission(void) } #endif +#ifdef USE_CUSTOM_ALLOCATOR +static void ParseHeap(void) { gMainHeap.ParseHeap(); } +#endif + static const char *carnames[] = { "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony", "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer", @@ -565,6 +570,12 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Render", "Don't render Objects", &gbDontRenderObjects, nil); DebugMenuAddVarBool8("Render", "Don't Render Water", &gbDontRenderWater, nil); +#ifndef FINAL + DebugMenuAddVarBool8("Debug", "Print Memory Usage", &gbPrintMemoryUsage, nil); +#ifdef USE_CUSTOM_ALLOCATOR + DebugMenuAddCmd("Debug", "Parse Heap", ParseHeap); +#endif +#endif DebugMenuAddVarBool8("Debug", "Show cullzone debug stuff", &gbShowCullZoneDebugStuff, nil); DebugMenuAddVarBool8("Debug", "Disable zone cull", &gbDisableZoneCull, nil); -- cgit v1.2.3 From 2c59e1c8945a5c6de6415611d4f1dbc720790d73 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 1 Dec 2020 00:22:57 +0100 Subject: some more GTA_VERSION --- src/core/FileLoader.cpp | 6 +++ src/core/Game.cpp | 101 +++++++++++++++++++++++++++++++++++------------- src/core/World.cpp | 5 ++- 3 files changed, 85 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index aeaede56..b9d475b8 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -59,7 +59,13 @@ CFileLoader::LoadLevel(const char *filename) savedTxd = RwTexDictionaryCreate(); RwTexDictionarySetCurrent(savedTxd); } +#if GTA_VERSION <= GTA3_PS2_160 + CFileMgr::ChangeDir("\\DATA\\"); fd = CFileMgr::OpenFile(filename, "r"); + CFileMgr::ChangeDir("\\"); +#else + fd = CFileMgr::OpenFile(filename, "r"); +#endif assert(fd > 0); for(line = LoadLine(fd); line; line = LoadLine(fd)){ diff --git a/src/core/Game.cpp b/src/core/Game.cpp index d22a7184..7043a5b2 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -265,16 +265,19 @@ void CGame::ShutdownRenderWare(void) #endif } +// missing altogether on PS2 bool CGame::InitialiseOnceAfterRW(void) { +#if GTA_VERSION > GTA3_PS2_160 TheText.Load(); - DMAudio.Initialise(); + DMAudio.Initialise(); // before TheGame() on PS2 CTimer::Initialise(); CTempColModels::Initialise(); mod_HandlingManager.Initialise(); CSurfaceTable::Initialise("DATA\\SURFACE.DAT"); CPedStats::Initialise(); CTimeCycle::Initialise(); +#endif if ( DMAudio.GetNum3DProvidersAvailable() == 0 ) FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = -1; @@ -330,10 +333,15 @@ bool CGame::Initialise(const char* datFile) { #ifdef GTA_PS2 // TODO: upload VU0 collision code here -#else +#endif + +#if GTA_VERSION > GTA3_PS2_160 ResetLoadingScreenBar(); strcpy(aDatFile, datFile); CPools::Initialise(); // done in CWorld on PS2 +#endif + +#ifndef GTA_PS2 CIniFile::LoadIniFile(); #endif @@ -367,13 +375,15 @@ bool CGame::Initialise(const char* datFile) CWeather::Init(); CCullZones::Init(); CCollision::Init(); -#ifdef PS2_MENU +#ifdef PS2_MENU // TODO: is this the right define? TheText.Load(); #endif CTheZones::Init(); CUserDisplay::Init(); CMessages::Init(); +#if GTA_VERSION > GTA3_PS2_160 CMessages::ClearAllMessagesDisplayedByGame(); +#endif CRecordDataForGame::Init(); CRestart::Initialise(); @@ -381,11 +391,17 @@ bool CGame::Initialise(const char* datFile) CWorld::Initialise(); POP_MEMID(); +#if GTA_VERSION <= GTA3_PS2_160 + mod_HandlingManager.Initialise(); + CSurfaceTable::Initialise("DATA\\SURFACE.DAT"); + CTempColModels::Initialise(); +#endif + PUSH_MEMID(MEMID_TEXTURES); CParticle::Initialise(); POP_MEMID(); -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 gStartX = -180.0f; gStartY = 180.0f; gStartZ = 14.0f; @@ -400,20 +416,31 @@ bool CGame::Initialise(const char* datFile) CCarCtrl::Init(); POP_MEMID(); -#ifndef GTA_PS2 +#if GTA_VERSION > GTA3_PS2_160 InitModelIndices(); #endif PUSH_MEMID(MEMID_DEF_MODELS); CModelInfo::Initialise(); -#ifndef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 + CPedStats::Initialise(); // InitialiseOnceAfterRW +#else // probably moved before LoadLevel for multiplayer maps? CPickups::Init(); CTheCarGenerators::Init(); #endif + +#ifndef GTA_PS2 // or GTA_VERSION? CdStreamAddImage("MODELS\\GTA3.IMG"); +#endif + +#if GTA_VERSION > GTA3_PS2_160 CFileLoader::LoadLevel("DATA\\DEFAULT.DAT"); CFileLoader::LoadLevel(datFile); +#else + CFileLoader::LoadLevel("GTA3.DAT"); +#endif + #ifdef EXTENDED_PIPELINES // for generic fallback CustomPipes::SetTxdFindCallback(); @@ -424,18 +451,25 @@ bool CGame::Initialise(const char* datFile) CTheZones::PostZoneCreation(); POP_MEMID(); +#if GTA_VERSION <= GTA3_PS2_160 + TestModelIndices(); +#endif LoadingScreen("Loading the Game", "Setup paths", GetRandomSplashScreen()); ThePaths.PreparePathData(); - // done elsewhere on PS2 +#if GTA_VERSION > GTA3_PS2_160 for (int i = 0; i < NUMPLAYERS; i++) CWorld::Players[i].Clear(); CWorld::Players[0].LoadPlayerSkin(); TestModelIndices(); - // +#endif LoadingScreen("Loading the Game", "Setup water", nil); CWaterLevel::Initialise("DATA\\WATER.DAT"); +#if GTA_VERSION <= GTA3_PS2_160 + CTimeCycle::Initialise(); // InitialiseOnceAfterRW +#else TheConsole.Init(); +#endif CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; @@ -472,6 +506,11 @@ bool CGame::Initialise(const char* datFile) LoadingScreen("Loading the Game", "Setup game variables", nil); CPopulation::Initialise(); +#if GTA_VERSION <= GTA3_PS2_160 + for (int i = 0; i < NUMPLAYERS; i++) + CWorld::Players[i].Clear(); +// CWorld::Players[0].LoadPlayerSkin(); // TODO: use a define for this +#endif CWorld::PlayerInFocus = 0; CCoronas::Init(); CShadows::Init(); @@ -480,7 +519,7 @@ bool CGame::Initialise(const char* datFile) CAntennas::Init(); CGlass::Init(); gPhoneInfo.Initialise(); -#ifndef GTA_PS2 +#ifndef GTA_PS2 // TODO: define for this CSceneEdit::Initialise(); #endif @@ -491,11 +530,11 @@ bool CGame::Initialise(const char* datFile) POP_MEMID(); LoadingScreen("Loading the Game", "Setup game variables", nil); -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 CTimer::Initialise(); #endif CClock::Initialise(1000); -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 CTheCarGenerators::Init(); #endif CHeli::InitHelis(); @@ -503,44 +542,52 @@ bool CGame::Initialise(const char* datFile) CMovingThings::Init(); CDarkel::Init(); CStats::Init(); -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 CPickups::Init(); #endif CPacManPickups::Init(); - // CGarages::Init(); here on PS2 instead +#if GTA_VERSION <= GTA3_PS2_160 + CGarages::Init(); +#endif CRubbish::Init(); CClouds::Init(); -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 CRemote::Init(); #endif CSpecialFX::Init(); CWaterCannons::Init(); CBridge::Init(); +#if GTA_VERSION > GTA3_PS2_160 CGarages::Init(); +#endif LoadingScreen("Loading the Game", "Position dynamic objects", nil); CWorld::RepositionCertainDynamicObjects(); - // CCullZones::ResolveVisibilities(); on PS2 here instead +#if GTA_VERSION <= GTA3_PS2_160 + CCullZones::ResolveVisibilities(); +#endif LoadingScreen("Loading the Game", "Initialise vehicle paths", nil); +#if GTA_VERSION > GTA3_PS2_160 CCullZones::ResolveVisibilities(); +#endif CTrain::InitTrains(); CPlane::InitPlanes(); CCredits::Init(); CRecordDataForChase::Init(); +#ifndef GTA_PS2 // TODO: define for that CReplay::Init(); +#endif #ifdef PS2_MENU if ( !TheMemoryCard.m_bWantToLoad ) - { #endif - LoadingScreen("Loading the Game", "Start script", nil); - CTheScripts::StartTestScript(); - CTheScripts::Process(); - TheCamera.Process(); -#ifdef PS2_MENU + { + LoadingScreen("Loading the Game", "Start script", nil); + CTheScripts::StartTestScript(); + CTheScripts::Process(); + TheCamera.Process(); } -#endif LoadingScreen("Loading the Game", "Load scene", nil); CModelInfo::RemoveColModelsFromOtherLevels(currLevel); @@ -556,7 +603,7 @@ bool CGame::ShutDown(void) CPlane::Shutdown(); CTrain::Shutdown(); CSpecialFX::Shutdown(); -#ifndef PS2 +#if GTA_VERSION > GTA3_PS2_160 CGarages::Shutdown(); #endif CMovingThings::Shutdown(); @@ -597,7 +644,9 @@ bool CGame::ShutDown(void) CSkidmarks::Shutdown(); CWeaponEffects::Shutdown(); CParticle::Shutdown(); +#if GTA_VERSION > GTA3_PS2_160 CPools::ShutDown(); +#endif CTxdStore::RemoveTxdSlot(gameTxdSlot); CdStreamRemoveImages(); return true; @@ -623,7 +672,7 @@ void CGame::ReInitGameObjectVariables(void) CWorld::bDoingCarCollisions = false; CHud::ReInitialise(); CRadar::Initialise(); -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 gStartX = -180.0f; gStartY = 180.0f; gStartZ = 14.0f; @@ -646,7 +695,7 @@ void CGame::ReInitGameObjectVariables(void) CWorld::Players[i].Clear(); CWorld::PlayerInFocus = 0; -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 CWeaponEffects::Init(); CSkidmarks::Init(); #endif @@ -669,7 +718,7 @@ void CGame::ReInitGameObjectVariables(void) CPickups::Init(); CPacManPickups::Init(); CGarages::Init(); -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 CClouds::Init(); CRemote::Init(); #endif diff --git a/src/core/World.cpp b/src/core/World.cpp index 33c2f1c1..62d8d002 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -53,7 +53,7 @@ bool CWorld::bIncludeCarTyres; void CWorld::Initialise() { -#ifdef GTA_PS2 +#if GTA_VERSION <= GTA3_PS2_160 CPools::Initialise(); #endif pIgnoreEntity = nil; @@ -1783,6 +1783,9 @@ CWorld::ShutDown(void) } } ms_listMovingEntityPtrs.Flush(); +#if GTA_VERSION <= GTA3_PS2_160 + CPools::Shutdown(); +#endif } void -- cgit v1.2.3 From 6eb0fd52d7f36623ca78d6717fcbd64fd3e7ecd9 Mon Sep 17 00:00:00 2001 From: Zach Charo Date: Mon, 30 Nov 2020 19:08:15 -0600 Subject: Update Camera.cpp camdist multiplier is consitently between 1 and 1.4 on 16:9 aspect ratio On ultrawide, the cam dist multiplier jumps to anywhere between 2 and 3 The preferred distance generator for car objects is the cam dist multiplier * 120. Which puts cars that it's trying to generate outside of the allowed gen/draw distance for new car objects when on ultrawide. This means no new cars can spawn. This change caps the scaling for the generation distance a bit above what it would be for 16:9 and does not affect the LOD multiplier. --- src/core/Camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 1e1aa722..9281a20a 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -720,7 +720,7 @@ CCamera::Process(void) else LODDistMultiplier = 1.0f; // missing on PS2 - GenerationDistMultiplier = LODDistMultiplier; + GenerationDistMultiplier = 70.0f/CDraw::GetFOV() * fmin(CDraw::GetAspectRatio(),1.82f)/(4.0f/3.0f); LODDistMultiplier *= CRenderer::ms_lodDistScale; // -- cgit v1.2.3 From d6fab1bc53627d55391d10a557a9e0cbcd11ac6d Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 1 Dec 2020 10:12:42 +0100 Subject: cam stuff --- src/core/Camera.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 9281a20a..cd748f09 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -94,9 +94,9 @@ CCamera::Init(void) #endif #ifdef PS2_MENU - if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart ) { + if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart ) #endif - + { #ifdef FIX_BUGS static const CCamera DummyCamera = CCamera(0.f); *this = DummyCamera; @@ -110,9 +110,7 @@ CCamera::Init(void) #endif m_pRwCamera = nil; -#ifdef PS2_MENU } -#endif m_1rstPersonRunCloseToAWall = false; m_fPositionAlongSpline = 0.0f; @@ -719,10 +717,14 @@ CCamera::Process(void) LODDistMultiplier = 70.0f/CDraw::GetFOV() * CDraw::GetAspectRatio()/(4.0f/3.0f); else LODDistMultiplier = 1.0f; - // missing on PS2 - GenerationDistMultiplier = 70.0f/CDraw::GetFOV() * fmin(CDraw::GetAspectRatio(),1.82f)/(4.0f/3.0f); +#if GTA_VERSION > GTA3_PS2_160 +#ifndef FIX_BUGS + // this seems problematic for very wide aspect ratios + // maybe just leaving it at 1.0 is the best thing to do + GenerationDistMultiplier = LODDistMultiplier; +#endif LODDistMultiplier *= CRenderer::ms_lodDistScale; - // +#endif // Keep track of speed if(m_bJustInitalised || m_bJust_Switched){ -- cgit v1.2.3 From b8bc54640d80db3d0c0a6392a0858d83a09e8304 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 1 Dec 2020 17:24:56 +0100 Subject: fix cam-fix --- src/core/Camera.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index cd748f09..51876c93 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -717,12 +717,12 @@ CCamera::Process(void) LODDistMultiplier = 70.0f/CDraw::GetFOV() * CDraw::GetAspectRatio()/(4.0f/3.0f); else LODDistMultiplier = 1.0f; +#ifdef FIX_BUGS + // from VC. to high values bug out spawns + LODDistMultiplier = Min(LODDistMultiplier, 2.2f); +#endif #if GTA_VERSION > GTA3_PS2_160 -#ifndef FIX_BUGS - // this seems problematic for very wide aspect ratios - // maybe just leaving it at 1.0 is the best thing to do GenerationDistMultiplier = LODDistMultiplier; -#endif LODDistMultiplier *= CRenderer::ms_lodDistScale; #endif -- cgit v1.2.3 From 83bbb631d1105502fb3c5b3af90578226ba35583 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 1 Dec 2020 17:42:18 +0100 Subject: some more GTA_VERSIONs and CGame tidy-up (not much actual memory moving yet) --- src/animation/AnimBlendHierarchy.cpp | 11 +++ src/animation/AnimBlendHierarchy.h | 5 + src/animation/AnimBlendSequence.cpp | 21 +++++ src/animation/AnimBlendSequence.h | 5 + src/core/Game.cpp | 175 ++++++++++++++++++++++++++++++++--- src/core/main.cpp | 1 + src/rw/MemoryHeap.cpp | 2 +- src/rw/MemoryHeap.h | 1 + 8 files changed, 209 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp index 67b19019..c7800de5 100644 --- a/src/animation/AnimBlendHierarchy.cpp +++ b/src/animation/AnimBlendHierarchy.cpp @@ -82,3 +82,14 @@ CAnimBlendHierarchy::RemoveUncompressedData(void) #endif compressed = 1; } + +#ifdef USE_CUSTOM_ALLOCATOR +void +CAnimBlendHierarchy::MoveMemory(bool onlyone) +{ + int i; + for(i = 0; i < numSequences; i++) + if(sequences[i].MoveMemory() && onlyone) + return; +} +#endif diff --git a/src/animation/AnimBlendHierarchy.h b/src/animation/AnimBlendHierarchy.h index 0144108d..e35b4925 100644 --- a/src/animation/AnimBlendHierarchy.h +++ b/src/animation/AnimBlendHierarchy.h @@ -2,6 +2,10 @@ #include "templates.h" +#ifdef MoveMemory +#undef MoveMemory // windows shit +#endif + class CAnimBlendSequence; // A collection of sequences @@ -23,6 +27,7 @@ public: void RemoveAnimSequences(void); void Uncompress(void); void RemoveUncompressedData(void); + void MoveMemory(bool onlyone = false); }; VALIDATE_SIZE(CAnimBlendHierarchy, 0x28); \ No newline at end of file diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp index 5a2fa605..c958b71a 100644 --- a/src/animation/AnimBlendSequence.cpp +++ b/src/animation/AnimBlendSequence.cpp @@ -176,3 +176,24 @@ CAnimBlendSequence::RemoveUncompressedData(void) keyFrames = nil; } +#ifdef USE_CUSTOM_ALLOCATOR +bool +CAnimBlendSequence::MoveMemory(void) +{ + if(keyFrames){ + void *newaddr = gMainHeap.MoveMemory(keyFrames); + if(newaddr != keyFrames){ + keyFrames = newaddr; + return true; + } + }else if(keyFramesCompressed){ + void *newaddr = gMainHeap.MoveMemory(keyFramesCompressed); + if(newaddr != keyFramesCompressed){ + keyFramesCompressed = newaddr; + return true; + } + } + return false; +} +#endif + diff --git a/src/animation/AnimBlendSequence.h b/src/animation/AnimBlendSequence.h index e51e5aaa..c6e70f22 100644 --- a/src/animation/AnimBlendSequence.h +++ b/src/animation/AnimBlendSequence.h @@ -2,6 +2,10 @@ #include "Quaternion.h" +#ifdef MoveMemory +#undef MoveMemory // windows shit +#endif + // TODO: put them somewhere else? struct KeyFrame { CQuaternion rotation; @@ -53,6 +57,7 @@ public: void Uncompress(void); void CompressKeyframes(void); void RemoveUncompressedData(void); + bool MoveMemory(void); #ifdef PED_SKIN void SetBoneTag(int tag) { boneTag = tag; } diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 7043a5b2..262aa54a 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -167,6 +167,7 @@ void ReplaceAtomicPipeCallback(); #endif // PS2_ALPHA_TEST #endif // !LIBRW +// missing altogether on PS2, mostly done in GameInit there it seems bool CGame::InitialiseRenderWare(void) { @@ -233,6 +234,7 @@ CGame::InitialiseRenderWare(void) return (true); } +// missing altogether on PS2 void CGame::ShutdownRenderWare(void) { CMBlur::MotionBlurClose(); @@ -321,6 +323,7 @@ bool CGame::InitialiseOnceAfterRW(void) return true; } +// missing altogether on PS2 void CGame::FinalShutdown(void) { @@ -657,13 +660,11 @@ void CGame::ReInitGameObjectVariables(void) CGameLogic::InitAtStartOfGame(); #ifdef PS2_MENU if ( !TheMemoryCard.m_bWantToLoad ) - { #endif - TheCamera.Init(); - TheCamera.SetRwCamera(Scene.camera); -#ifdef PS2_MENU + { + TheCamera.Init(); + TheCamera.SetRwCamera(Scene.camera); } -#endif CDebug::DebugInitTextBuffer(); CWeather::Init(); CUserDisplay::Init(); @@ -769,8 +770,10 @@ void CGame::ReloadIPLs(void) void CGame::ShutDownForRestart(void) { +#ifndef GTA_PS2 // TODO: right define CReplay::FinishPlayback(); CReplay::EmptyReplayBuffer(); +#endif DMAudio.DestroyAllGameCreatedEntities(); for (int i = 0; i < NUMPLAYERS; i++) @@ -788,7 +791,7 @@ void CGame::ShutDownForRestart(void) CRadar::RemoveRadarSections(); FrontEndMenuManager.UnloadTextures(); CParticleObject::RemoveAllParticleObjects(); -#ifndef PS2 +#if GTA_VERSION >= GTA3_PS2_160 CPedType::Shutdown(); CSpecialFX::Shutdown(); #endif @@ -974,7 +977,9 @@ void CGame::Process(void) CSkidmarks::Update(); CAntennas::Update(); CGlass::Update(); +#ifndef GTA_PS2 // TODO: define CSceneEdit::Update(); +#endif CEventList::Update(); CParticle::Update(); gFireManager.Update(); @@ -988,7 +993,9 @@ void CGame::Process(void) CMovingThings::Update(); CWaterCannons::Update(); CUserDisplay::Process(); +#ifndef GTA_PS2 // TODO: define CReplay::Update(); +#endif PUSH_MEMID(MEMID_WORLD); CWorld::Process(); @@ -1001,10 +1008,14 @@ void CGame::Process(void) CRubbish::Update(); CSpecialFX::Update(); CTimeCycle::Update(); +#ifndef GTA_PS2 // TODO: define if (CReplay::ShouldStandardCameraBeProcessed()) +#endif TheCamera.Process(); CCullZones::Update(); +#ifndef GTA_PS2 // TODO: define if (!CReplay::IsPlayingBack()) +#endif CGameLogic::Update(); CBridge::Update(); CCoronas::DoSunAndMoon(); @@ -1012,7 +1023,9 @@ void CGame::Process(void) CShadows::UpdateStaticShadows(); CShadows::UpdatePermanentShadows(); gPhoneInfo.Update(); +#ifndef GTA_PS2 // TODO: define if (!CReplay::IsPlayingBack()) +#endif { PUSH_MEMID(MEMID_CARS); CCarCtrl::GenerateRandomCars(); @@ -1026,23 +1039,163 @@ void CGame::Process(void) #endif } -void CGame::DrasticTidyUpMemory(bool) +int32 gNumMemMoved; + +RwTexture * +MoveTextureMemoryCB(RwTexture *texture, void *pData) +{ + // TODO + return texture; +} + +bool +TidyUpModelInfo(CBaseModelInfo *,bool) +{ + // TODO + return false; +} + +void CGame::DrasticTidyUpMemory(bool flushDraw) { #ifdef USE_CUSTOM_ALLOCATOR - // meow + bool removedCol = false; + + TidyUpMemory(true, flushDraw); + + if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){ + CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); + CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); + CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); + TidyUpMemory(true, flushDraw); + } + + if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){ + CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC); + TidyUpMemory(true, flushDraw); + removedCol = true; + } + + if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){ + CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL); + CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL); + CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN); + TidyUpMemory(true, flushDraw); + } + + if(removedCol){ + // different on PS2 + CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory); + } + + if(!playingIntro) + CStreaming::RequestBigBuildings(currLevel); + + CStreaming::LoadAllRequestedModels(true); #endif } -void CGame::TidyUpMemory(bool, bool) +void CGame::TidyUpMemory(bool moveTextures, bool flushDraw) { #ifdef USE_CUSTOM_ALLOCATOR - // meow + printf("Largest free block before tidy %d\n", gMainHeap.GetLargestFreeBlock()); + + if(moveTextures){ + if(flushDraw){ +#ifdef GTA_PS2 + for(int i = 0; i < sweMaxFlips+1; i++){ +#else + for(int i = 0; i < 5; i++){ // probably more than needed +#endif + RwCameraBeginUpdate(Scene.camera); + RwCameraEndUpdate(Scene.camera); + RwCameraShowRaster(Scene.camera, nil, 0); + } + } + int fontSlot = CTxdStore::FindTxdSlot("fonts"); + + for(int i = 0; i < TXDSTORESIZE; i++){ + if(i == fontSlot || + CTxdStore::GetSlot(i) == nil) + continue; + RwTexDictionary *txd = CTxdStore::GetSlot(i)->texDict; + if(txd) + RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, nil); + } + } + + // animations + for(int i = 0; i < NUMANIMATIONS; i++){ + CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(i); + if(anim == nil) + continue; // cannot happen + anim->MoveMemory(); + } + + // model info + for(int i = 0; i < MODELINFOSIZE; i++){ + CBaseModelInfo *mi = CModelInfo::GetModelInfo(i); + if(mi == nil) + continue; + TidyUpModelInfo(mi, false); + } + + printf("Largest free block after tidy %d\n", gMainHeap.GetLargestFreeBlock()); #endif } void CGame::ProcessTidyUpMemory(void) { #ifdef USE_CUSTOM_ALLOCATOR - // meow + static int32 modelIndex = 0; + static int32 animIndex = 0; + static int32 txdIndex = 0; + bool txdReturn = false; + RwTexDictionary *txd = nil; + gNumMemMoved = 0; + + // model infos + for(int numCleanedUp = 0; numCleanedUp < 10; numCleanedUp++){ + CBaseModelInfo *mi; + do{ + mi = CModelInfo::GetModelInfo(modelIndex); + modelIndex++; + if(modelIndex >= MODELINFOSIZE) + modelIndex = 0; + }while(mi == nil); + + if(TidyUpModelInfo(mi, true)) + return; + } + + // tex dicts + for(int numCleanedUp = 0; numCleanedUp < 3; numCleanedUp++){ + if(gNumMemMoved > 80) + break; + + do{ +#ifdef FIX_BUGS + txd = nil; +#endif + if(CTxdStore::GetSlot(txdIndex)) + txd = CTxdStore::GetSlot(txdIndex)->texDict; + txdIndex++; + if(txdIndex >= TXDSTORESIZE) + txdIndex = 0; + }while(txd == nil); + + RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, &txdReturn); + if(txdReturn) + return; + } + + // animations + CAnimBlendHierarchy *anim; + do{ + anim = CAnimManager::GetAnimation(animIndex); + animIndex++; + if(animIndex >= NUMANIMATIONS) + animIndex = 0; + }while(anim == nil); // always != nil + anim->MoveMemory(true); #endif } diff --git a/src/core/main.cpp b/src/core/main.cpp index 102548b6..fa16b6c2 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -415,6 +415,7 @@ PluginAttach(void) return TRUE; } +// rather different on PS2 static RwBool Initialise3D(void *param) { diff --git a/src/rw/MemoryHeap.cpp b/src/rw/MemoryHeap.cpp index 0b333ce1..469262d3 100644 --- a/src/rw/MemoryHeap.cpp +++ b/src/rw/MemoryHeap.cpp @@ -187,7 +187,7 @@ CMemoryHeap::Malloc(uint32 size) void *mem = Malloc(size); if (removeCollision) { CTimer::Stop(); - // different on PS2 + // TODO: different on PS2 CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory); removeCollision = false; CTimer::Update(); diff --git a/src/rw/MemoryHeap.h b/src/rw/MemoryHeap.h index 484cbfab..23163c1c 100644 --- a/src/rw/MemoryHeap.h +++ b/src/rw/MemoryHeap.h @@ -198,6 +198,7 @@ public: void TidyHeap(void); uint32 GetMemoryUsed(int32 id); uint32 GetBlocksUsed(int32 id); + int32 GetLargestFreeBlock(void) { return m_freeList.m_last.m_prev->m_size; } void ParseHeap(void); -- cgit v1.2.3 From e33ab44b7d179a59887200fe6d22c15fa557c5e2 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 1 Dec 2020 22:08:05 +0200 Subject: Add GTA_REPLAY --- src/control/Pickups.cpp | 4 ++-- src/control/Replay.cpp | 3 ++- src/control/Replay.h | 33 ++++++++++++++++++++++----------- src/core/config.h | 1 + 4 files changed, 27 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 2503f5c8..1b1c8cbc 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -353,11 +353,11 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); - if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z) + if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false) && waterLevel >= m_pObject->GetPosition().z) m_eType = PICKUP_FLOATINGPACKAGE_FLOATING; break; case PICKUP_FLOATINGPACKAGE_FLOATING: - if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0)) + if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) m_pObject->GetMatrix().GetPosition().z = waterLevel; m_pObject->GetMatrix().UpdateRW(); diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index f21703ac..757af0a9 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1,5 +1,5 @@ #include "common.h" - +#ifdef GTA_REPLAY #include "AnimBlendAssociation.h" #include "Boat.h" #include "SpecialFX.h" @@ -1585,3 +1585,4 @@ void CReplay::Display() if (Mode == MODE_PLAYBACK) CFont::PrintString(SCREEN_SCALE_X(63.5f), SCREEN_SCALE_Y(30.0f), TheText.Get("REPLAY")); } +#endif diff --git a/src/control/Replay.h b/src/control/Replay.h index 66bee3bf..cb58a602 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -63,6 +63,12 @@ struct CStoredDetailedAnimationState void PlayReplayFromHD(void); +#ifdef GTA_REPLAY +#define REPLAY_STUB +#else +#define REPLAY_STUB {} +#endif + class CReplay { enum { @@ -273,20 +279,24 @@ private: #endif public: - static void Init(void); - static void DisableReplays(void); - static void EnableReplays(void); - static void Update(void); - static void FinishPlayback(void); - static void EmptyReplayBuffer(void); - static void Display(void); - static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene); - static void StreamAllNecessaryCarsAndPeds(void); - static bool ShouldStandardCameraBeProcessed(void); + static void Init(void) REPLAY_STUB; + static void DisableReplays(void) REPLAY_STUB; + static void EnableReplays(void) REPLAY_STUB; + static void Update(void) REPLAY_STUB; + static void FinishPlayback(void) REPLAY_STUB; + static void EmptyReplayBuffer(void) REPLAY_STUB; + static void Display(void) REPLAY_STUB; + static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) REPLAY_STUB; + static void StreamAllNecessaryCarsAndPeds(void) REPLAY_STUB; +#ifndef GTA_REPLAY + static bool ShouldStandardCameraBeProcessed(void) { return true; } + static bool IsPlayingBack() { return false; } + static bool IsPlayingBackFromFile() { return false; } +#else + static bool ShouldStandardCameraBeProcessed(void); static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; } static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; } - private: static void RecordThisFrame(void); static void StorePedUpdate(CPed *ped, int id); @@ -314,4 +324,5 @@ private: /* Absolute nonsense, but how could this function end up being outside of class? */ friend void PlayReplayFromHD(void); +#endif }; diff --git a/src/core/config.h b/src/core/config.h index 5d528d50..07e91ee2 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -196,6 +196,7 @@ enum Config { # define RANDOMSPLASH // use random splash as on PS2 # define PS2_MATFX # endif +# define GTA_REPLAY #elif defined GTA_XBOX #endif -- cgit v1.2.3 From 9461998304219f91b3b24484d0cee5b5c5d4523c Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 23 Nov 2020 22:46:07 +0200 Subject: TexturePools --- src/core/Game.cpp | 3 + src/rw/RwHelper.cpp | 5 -- src/rw/RwHelper.h | 2 - src/rw/TexturePools.cpp | 221 ++++++++++++++++++++++++++++++++++++++++++++++++ src/rw/TexturePools.h | 42 +++++++++ 5 files changed, 266 insertions(+), 7 deletions(-) create mode 100644 src/rw/TexturePools.cpp create mode 100644 src/rw/TexturePools.h (limited to 'src') diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 262aa54a..9a604757 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -91,6 +91,9 @@ #include "screendroplets.h" #include "crossplatform.h" #include "MemoryHeap.h" +#ifdef USE_TEXTURE_POOL +#include "TexturePools.h" +#endif eLevelName CGame::currLevel; bool CGame::bDemoMode = true; diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index ee370c37..e0133985 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -605,11 +605,6 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer) return (nil); } -#ifdef USE_TEXTURE_POOL -WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); } -WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); } -#endif - #ifdef LIBRW #include #include "VehicleModelInfo.h" diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index ed9b03ab..1a5f64b1 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -50,8 +50,6 @@ RwCamera *CameraCreate(RwInt32 width, RwBool zBuffer); -void _TexturePoolsInitialise(); -void _TexturePoolsShutdown(); RpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data); diff --git a/src/rw/TexturePools.cpp b/src/rw/TexturePools.cpp new file mode 100644 index 00000000..c2ba6cf9 --- /dev/null +++ b/src/rw/TexturePools.cpp @@ -0,0 +1,221 @@ +#ifndef LIBRW + +#include +#define WITHD3D +#include "common.h" +#include "TexturePools.h" + +// TODO: this needs to be integrated into RW + +extern "C" LPDIRECT3DDEVICE8 _RwD3DDevice; + +CTexturePool aTexturePools[12]; +CPaletteList PaletteList; +int numTexturePools; +int MaxPaletteIndex; +bool bUsePaletteIndex = true; + + +void +CTexturePool::Create(D3DFORMAT _Format, int _size, uint32 mipmapLevels, int32 numTextures) +{ + Format = _Format; + size = _size; + levels = mipmapLevels; + pTextures = new IDirect3DTexture8 *[numTextures]; + texturesMax = numTextures; + texturesNum = 0; + texturesUsed = 0; +} + +void +CTexturePool::Release() +{ + int i = 0; + while (i < texturesNum) { + pTextures[i]->Release(); + i++; + } + + delete[] pTextures; + + pTextures = nil; + texturesNum = 0; + texturesUsed = 0; +} + +IDirect3DTexture8 * +CTexturePool::FindTexture() +{ + if (texturesNum == 0) + return nil; + texturesUsed--; + return pTextures[--texturesNum]; +} + +bool +CTexturePool::AddTexture(IDirect3DTexture8 *texture) +{ + ++texturesUsed; + if (texturesNum >= texturesMax) + return false; + pTextures[texturesNum] = texture; + ++texturesNum; + return true; +} + +void +CTexturePool::Resize(int numTextures) +{ + if (numTextures == texturesMax) + return; + + IDirect3DTexture8 **newTextures = new IDirect3DTexture8 *[numTextures]; + + for (int i = 0; i < texturesNum && i < numTextures; i++) + newTextures[i] = pTextures[i]; + + if (numTextures < texturesNum) { + for (int i = numTextures; i < texturesNum; i++) + pTextures[i]->Release(); + } + delete[] pTextures; + pTextures = newTextures; + texturesMax = numTextures; +} + +void +CPaletteList::Alloc(int max) +{ + Data = new int[max]; + Max = max; + Num = 0; +} + +void +CPaletteList::Free() +{ + delete[] Data; + Data = nil; + Num = 0; +} + +int +CPaletteList::Find() +{ + if (Num == 0) + return -1; + return Data[--Num]; +} + +void +CPaletteList::Add(int item) +{ + if (Num < Max) + Data[Num++] = item; + else { + Resize(2 * Max); + Add(item); + } +} + +void +CPaletteList::Resize(int max) +{ + if (max == Max) + return; + + int *newData = new int[4 * max]; + for (int i = 0; i < Num && i < max; i++) + newData[i] = Data[i]; + delete[] Data; + Data = newData; + Max = max; +} + +HRESULT +CreateTexture(int width, int height, int levels, D3DFORMAT Format, IDirect3DTexture8 **texture) +{ + if (width == height) { + for (int i = 0; i < numTexturePools; i++) { + if (width != aTexturePools[i].GetSize() && levels == aTexturePools[i].levels && Format == aTexturePools[i].Format) + *texture = aTexturePools[i].FindTexture(); + } + } + if (*texture) + return D3D_OK; + else + return _RwD3DDevice->CreateTexture(width, height, levels, 0, Format, D3DPOOL_MANAGED, texture); +} + +void +ReleaseTexture(IDirect3DTexture8 *texture) +{ + int levels = 1; + if (texture->GetLevelCount() > 1) + levels = 0; + + D3DSURFACE_DESC SURFACE_DESC; + + texture->GetLevelDesc(0, &SURFACE_DESC); + + if (SURFACE_DESC.Width == SURFACE_DESC.Height) { + for (int i = 0; i < numTexturePools; i++) { + if (SURFACE_DESC.Width == aTexturePools[i].GetSize() && SURFACE_DESC.Format == aTexturePools[i].Format && levels == aTexturePools[i].levels) { + if (!aTexturePools[i].AddTexture(texture)) { + if (aTexturePools[i].texturesUsed > 3 * aTexturePools[i].texturesMax / 2) { + aTexturePools[i].Resize(2 * aTexturePools[i].texturesMax); + aTexturePools[i].texturesUsed--; + aTexturePools[i].AddTexture(texture); + } else { + texture->Release(); + } + } + return; + } + } + } + if (numTexturePools < 12 && bUsePaletteIndex && levels != 0 && SURFACE_DESC.Width == SURFACE_DESC.Height && + (SURFACE_DESC.Width == 64 || SURFACE_DESC.Width == 128 || SURFACE_DESC.Width == 256)) { + aTexturePools[numTexturePools].Create(SURFACE_DESC.Format, SURFACE_DESC.Width, 1, 16); + aTexturePools[numTexturePools].AddTexture(texture); + numTexturePools++; + } else + texture->Release(); +} + +int +FindAvailablePaletteIndex() +{ + int index = PaletteList.Find(); + if (index == -1) + index = MaxPaletteIndex++; + return index; +} + +void +AddAvailablePaletteIndex(int index) +{ + if (bUsePaletteIndex) + PaletteList.Add(index); +} + +void +_TexturePoolsInitialise() +{ + PaletteList.Alloc(100); + MaxPaletteIndex = 0; +} + +void +_TexturePoolsShutdown() +{ + for (int i = 0; i < numTexturePools; i++) + aTexturePools[i].Release(); + + numTexturePools = 0; + bUsePaletteIndex = false; + PaletteList.Free(); +} + +#endif // !LIBRW \ No newline at end of file diff --git a/src/rw/TexturePools.h b/src/rw/TexturePools.h new file mode 100644 index 00000000..75187432 --- /dev/null +++ b/src/rw/TexturePools.h @@ -0,0 +1,42 @@ +#pragma once + +class CTexturePool +{ +public: + D3DFORMAT Format; + int size; + uint32 levels; + int32 texturesMax; + int32 texturesUsed; + int32 texturesNum; + IDirect3DTexture8 **pTextures; + +public: + CTexturePool() {} + void Create(D3DFORMAT _Format, int size, uint32 mipmapLevels, int32 numTextures); + void Release(); + IDirect3DTexture8 *FindTexture(); + bool AddTexture(IDirect3DTexture8 *texture); + void Resize(int numTextures); +#ifdef FIX_BUGS + int GetSize() { return size; } +#else + float GetSize() { return size; } +#endif +}; + +class CPaletteList +{ + int Max; + int Num; + int *Data; +public: + void Alloc(int max); + void Free(); + int Find(); + void Add(int item); + void Resize(int max); +}; + +void _TexturePoolsInitialise(); +void _TexturePoolsShutdown(); \ No newline at end of file -- cgit v1.2.3 From 0b20fd7e77dafc34cf9eebc3ffd25318a7d81476 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 1 Dec 2020 22:35:53 +0200 Subject: Remove ifndef GTA_PS2 around replays --- src/core/Game.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src') diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 9a604757..6b9fd11f 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -581,9 +581,7 @@ bool CGame::Initialise(const char* datFile) CPlane::InitPlanes(); CCredits::Init(); CRecordDataForChase::Init(); -#ifndef GTA_PS2 // TODO: define for that CReplay::Init(); -#endif #ifdef PS2_MENU if ( !TheMemoryCard.m_bWantToLoad ) @@ -773,10 +771,8 @@ void CGame::ReloadIPLs(void) void CGame::ShutDownForRestart(void) { -#ifndef GTA_PS2 // TODO: right define CReplay::FinishPlayback(); CReplay::EmptyReplayBuffer(); -#endif DMAudio.DestroyAllGameCreatedEntities(); for (int i = 0; i < NUMPLAYERS; i++) @@ -996,9 +992,7 @@ void CGame::Process(void) CMovingThings::Update(); CWaterCannons::Update(); CUserDisplay::Process(); -#ifndef GTA_PS2 // TODO: define CReplay::Update(); -#endif PUSH_MEMID(MEMID_WORLD); CWorld::Process(); @@ -1011,14 +1005,10 @@ void CGame::Process(void) CRubbish::Update(); CSpecialFX::Update(); CTimeCycle::Update(); -#ifndef GTA_PS2 // TODO: define if (CReplay::ShouldStandardCameraBeProcessed()) -#endif TheCamera.Process(); CCullZones::Update(); -#ifndef GTA_PS2 // TODO: define if (!CReplay::IsPlayingBack()) -#endif CGameLogic::Update(); CBridge::Update(); CCoronas::DoSunAndMoon(); @@ -1026,9 +1016,7 @@ void CGame::Process(void) CShadows::UpdateStaticShadows(); CShadows::UpdatePermanentShadows(); gPhoneInfo.Update(); -#ifndef GTA_PS2 // TODO: define if (!CReplay::IsPlayingBack()) -#endif { PUSH_MEMID(MEMID_CARS); CCarCtrl::GenerateRandomCars(); -- cgit v1.2.3 From fda58fb1dfaba95c72f564d155560abd8d10b794 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 2 Dec 2020 02:34:51 +0300 Subject: added GTA_SCENE_EDIT --- src/control/SceneEdit.cpp | 3 ++- src/control/SceneEdit.h | 3 ++- src/core/Cam.cpp | 5 ++++- src/core/Camera.cpp | 2 ++ src/core/Camera.h | 2 ++ src/core/Game.cpp | 4 ++-- src/core/config.h | 1 + src/core/main.cpp | 2 ++ src/core/re3.cpp | 2 ++ 9 files changed, 19 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index 154fe603..8224c1d4 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -1,7 +1,7 @@ #include "common.h" #include "SceneEdit.h" - +#ifdef GTA_SCENE_EDIT #include "Automobile.h" #include "Camera.h" #include "CarCtrl.h" @@ -1096,3 +1096,4 @@ bool CSceneEdit::SelectWeapon(void) } return false; } +#endif diff --git a/src/control/SceneEdit.h b/src/control/SceneEdit.h index 6dcefa31..7c8fb98a 100644 --- a/src/control/SceneEdit.h +++ b/src/control/SceneEdit.h @@ -1,5 +1,5 @@ #pragma once - +#ifdef GTA_SCENE_EDIT class CPed; class CVehicle; @@ -93,3 +93,4 @@ public: static void SelectVehicle(void); static bool SelectWeapon(void); }; +#endif diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 0e1c9d9f..3913274a 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -263,9 +263,11 @@ CCam::Process(void) case MODE_FIGHT_CAM_RUNABOUT: Process_1rstPersonPedOnPC(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; +#ifdef GTA_SCENE_EDIT case MODE_EDITOR: Process_Editor(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; +#endif default: Source = CVector(0.0f, 0.0f, 0.0f); Front = CVector(0.0f, 1.0f, 0.0f); @@ -3919,6 +3921,7 @@ CCam::Process_Debug(const CVector&, float, float, float) } #endif +#ifdef GTA_SCENE_EDIT void CCam::Process_Editor(const CVector&, float, float, float) { @@ -3935,7 +3938,6 @@ CCam::Process_Editor(const CVector&, float, float, float) FOV = DefaultFOV; Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f; Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX()*1.5f) / 19.0f; - if(CamTargetEntity && CSceneEdit::m_bCameraFollowActor){ TargetCoors = CamTargetEntity->GetPosition(); }else if(CSceneEdit::m_bRecording){ @@ -3997,6 +3999,7 @@ CCam::Process_Editor(const CVector&, float, float, float) sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z); } } +#endif void CCam::Process_ModelView(const CVector &CameraTarget, float, float, float) diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 51876c93..f28fb450 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -1576,8 +1576,10 @@ CCamera::CamControl(void) switchByJumpCut = true; } } +#ifdef GTA_SCENE_EDIT if(CSceneEdit::m_bEditOn) ReqMode = CCam::MODE_EDITOR; +#endif if((m_uiTransitionState == 0 || switchByJumpCut) && ReqMode != Cams[ActiveCam].Mode){ if(switchByJumpCut){ diff --git a/src/core/Camera.h b/src/core/Camera.h index 0797db9b..ca1bd135 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -213,7 +213,9 @@ public: void PrintMode(void); void Process_Debug(const CVector&, float, float, float); +#ifdef GTA_SCENE_EDIT void Process_Editor(const CVector&, float, float, float); +#endif void Process_ModelView(const CVector &CameraTarget, float, float, float); void Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 6b9fd11f..586b1469 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -525,7 +525,7 @@ bool CGame::Initialise(const char* datFile) CAntennas::Init(); CGlass::Init(); gPhoneInfo.Initialise(); -#ifndef GTA_PS2 // TODO: define for this +#ifdef GTA_SCENE_EDIT CSceneEdit::Initialise(); #endif @@ -976,7 +976,7 @@ void CGame::Process(void) CSkidmarks::Update(); CAntennas::Update(); CGlass::Update(); -#ifndef GTA_PS2 // TODO: define +#ifdef GTA_SCENE_EDIT CSceneEdit::Update(); #endif CEventList::Update(); diff --git a/src/core/config.h b/src/core/config.h index 07e91ee2..ccea1868 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -197,6 +197,7 @@ enum Config { # define PS2_MATFX # endif # define GTA_REPLAY +# define GTA_SCENE_EDIT #elif defined GTA_XBOX #endif diff --git a/src/core/main.cpp b/src/core/main.cpp index fa16b6c2..ebfa096a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1160,9 +1160,11 @@ Render2dStuff(void) MusicManager.DisplayRadioStationName(); TheConsole.Display(); +#ifdef GTA_SCENE_EDIT if(CSceneEdit::m_bEditOn) CSceneEdit::Draw(); else +#endif CHud::Draw(); CUserDisplay::OnscnTimer.ProcessForDisplay(); CMessages::Display(); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 506b2714..5974175a 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -580,7 +580,9 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Disable zone cull", &gbDisableZoneCull, nil); DebugMenuAddVarBool8("Debug", "pad 1 -> pad 2", &CPad::m_bMapPadOneToPadTwo, nil); +#ifdef GTA_SCENE_EDIT DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil); +#endif #ifdef MENU_MAP DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); #endif -- cgit v1.2.3 From 4b9f1680a376d1b9b968078e09dd76dc7404d645 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 2 Dec 2020 02:41:05 +0300 Subject: fast fix --- src/core/Cam.cpp | 1 + src/core/config.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 3913274a..08ebbafd 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -3938,6 +3938,7 @@ CCam::Process_Editor(const CVector&, float, float, float) FOV = DefaultFOV; Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f; Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX()*1.5f) / 19.0f; + if(CamTargetEntity && CSceneEdit::m_bCameraFollowActor){ TargetCoors = CamTargetEntity->GetPosition(); }else if(CSceneEdit::m_bRecording){ diff --git a/src/core/config.h b/src/core/config.h index ccea1868..4e71224f 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -197,7 +197,7 @@ enum Config { # define PS2_MATFX # endif # define GTA_REPLAY -# define GTA_SCENE_EDIT +# define GTA_SCENE_EDIT #elif defined GTA_XBOX #endif -- cgit v1.2.3 From fba657ff0c77b343ac854a5aed16385a6c77492c Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 2 Dec 2020 10:38:27 +0100 Subject: better cam lod dist fix --- src/control/PathFind.cpp | 8 ++++++++ src/core/Camera.cpp | 14 +++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index ecd2d0cb..49e43c81 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -1649,10 +1649,18 @@ CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start) DoPathSearch(type, start, -1, target, pNodeList, &DummyResult, 32, nil, &dist, 999999.88f, -1); else DoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1); +#ifdef FIX_BUGS + // dist has GenerationDistMultiplier as a factor, so our reference dist should have it too + if(type == PATH_CAR) + return dist < 160.0f*TheCamera.GenerationDistMultiplier; + else + return dist < 100.0f*TheCamera.GenerationDistMultiplier; +#else if(type == PATH_CAR) return dist < 160.0f; else return dist < 100.0f; +#endif } void diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 51876c93..4baec2a4 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -713,14 +713,14 @@ CCamera::Process(void) DistanceToWater = CWaterLevel::CalcDistanceToWater(GetPosition().x, GetPosition().y); // LOD dist - if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()) - LODDistMultiplier = 70.0f/CDraw::GetFOV() * CDraw::GetAspectRatio()/(4.0f/3.0f); - else - LODDistMultiplier = 1.0f; -#ifdef FIX_BUGS - // from VC. to high values bug out spawns - LODDistMultiplier = Min(LODDistMultiplier, 2.2f); + if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()){ + LODDistMultiplier = 70.0f/CDraw::GetFOV(); +#ifndef FIX_BUGS + // makes no sense and gone in VC + LODDistMultiplier *= CDraw::GetAspectRatio()/(4.0f/3.0f); #endif + }else + LODDistMultiplier = 1.0f; #if GTA_VERSION > GTA3_PS2_160 GenerationDistMultiplier = LODDistMultiplier; LODDistMultiplier *= CRenderer::ms_lodDistScale; -- cgit v1.2.3 From 50bf0f27a00eec43c1b92a9a0ae81b5916442ba2 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 2 Dec 2020 12:58:29 +0100 Subject: rpDefaultGeometryInstance --- src/rw/VisibilityPlugins.cpp | 91 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 68775c72..019a781e 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -31,14 +31,93 @@ float CVisibilityPlugins::ms_pedLod0Dist; float CVisibilityPlugins::ms_pedLod1Dist; float CVisibilityPlugins::ms_pedFadeDist; -#ifdef GTA_PS2 -void -rpDefaultGeometryInstance(RpGeometry *geo, void *atomic, int unk) +//#ifdef GTA_PS2 +#if 1 +// if wanted, delete the original geometry data after rendering +// and only keep the instanced data +bool +rpDefaultGeometryInstance(RpGeometry *geo, void *atomic, int del) { - // TODO - // this function seems to delete the original geometry data - // and only keep the instanced data +#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31 + if(RpGeometryGetNumMorphTargets(geo) != 1) + return false; + + // this needs R*'s modification that geometry data is + // allocated separately from the geometry itself + geo->instanceFlags = rpGEOMETRYINSTANCE; AtomicDefaultRenderCallBack((RpAtomic*)atomic); + + if(!del) + return true; + + // New mesh without indices + RpMeshHeader *newheader = _rpMeshHeaderCreate(sizeof(RpMesh)*geo->mesh->numMeshes + sizeof(RpMeshHeader)); + newheader->numMeshes = geo->mesh->numMeshes; + newheader->serialNum = 1; + newheader->totalIndicesInMesh = 0; + newheader->firstMeshOffset = 0; + RpMesh *oldmesh = (RpMesh*)(geo->mesh+1); + RpMesh *newmesh = (RpMesh*)(newheader+1); + for(int i = 0; i < geo->mesh->numMeshes; i++){ + newmesh[i].indices = nil; + newmesh[i].numIndices = 0; + newmesh[i].material = oldmesh[i].material; + } + + geo->refCount++; + RpGeometryLock(geo, rpGEOMETRYLOCKPOLYGONS | rpGEOMETRYLOCKVERTICES | + rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | + rpGEOMETRYLOCKTEXCOORDS1 | rpGEOMETRYLOCKTEXCOORDS2); + + // vertices and normals + RpMorphTarget *mt = RpGeometryGetMorphTarget(geo, 0); + if(mt->verts){ + RwFree(mt->verts); + mt->verts = nil; + mt->normals = nil; + } + geo->numVertices = 0; + + // triangles + for(int i = 0; i < RpGeometryGetNumTriangles(geo); i++){ + if(RpGeometryGetTriangles(geo)->matIndex == -1) + continue; + RpMaterialDestroy(_rpMaterialListGetMaterial(&geo->matList, RpGeometryGetTriangles(geo)->matIndex)); + } + if(RpGeometryGetTriangles(geo)){ + RwFree(RpGeometryGetTriangles(geo)); + geo->triangles = nil; + geo->numTriangles = 0; + } + + // tex coords + if(RpGeometryGetVertexTexCoords(geo, 1)){ + RwFree(RpGeometryGetVertexTexCoords(geo, 1)); + geo->texCoords[1] = nil; + } + if(RpGeometryGetVertexTexCoords(geo, 0)){ + RwFree(RpGeometryGetVertexTexCoords(geo, 0)); + geo->texCoords[0] = nil; + } + + // vertex colors + if(RpGeometryGetPreLightColors(geo)){ + RwFree(RpGeometryGetPreLightColors(geo)); + geo->preLitLum = nil; + } + + RpGeometryUnlock(geo); + + geo->instanceFlags = rpGEOMETRYPERSISTENT; + // BUG? don't we have to free the old mesh? + geo->mesh = newheader; + geo->refCount--; +#else + // We can do something for librw here actually, maybe later + AtomicDefaultRenderCallBack((RpAtomic*)atomic); +#endif + + return true; } RpAtomic* -- cgit v1.2.3 From 448ba9b7e86e93581df7813bb5250168b5813c72 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 2 Dec 2020 13:08:30 +0100 Subject: bla --- src/rw/VisibilityPlugins.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 019a781e..f931019c 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -31,8 +31,7 @@ float CVisibilityPlugins::ms_pedLod0Dist; float CVisibilityPlugins::ms_pedLod1Dist; float CVisibilityPlugins::ms_pedFadeDist; -//#ifdef GTA_PS2 -#if 1 +#ifdef GTA_PS2 // maybe something else? // if wanted, delete the original geometry data after rendering // and only keep the instanced data bool -- cgit v1.2.3 From 3c24505990a9a71210b2328c366b43e6f2fd94bc Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 3 Dec 2020 09:34:09 +0100 Subject: little fixes for animviewer --- src/core/AnimViewer.cpp | 10 +++++++++- src/core/Cam.cpp | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp index c8d8cb56..b8354d93 100644 --- a/src/core/AnimViewer.cpp +++ b/src/core/AnimViewer.cpp @@ -49,7 +49,7 @@ CAnimViewer::Render(void) { if (pTarget) { #ifdef FIX_BUGS #ifdef PED_SKIN - if(pTarget->IsPed()) + if(pTarget->IsPed() && IsClumpSkinned(pTarget->GetClump())) ((CPed*)pTarget)->UpdateRpHAnim(); #endif #endif @@ -100,6 +100,9 @@ CAnimViewer::Initialise(void) { CRadar::Initialise(); CRadar::LoadTextures(); CVehicleModelInfo::LoadVehicleColours(); +#ifdef FIX_BUGS + CVehicleModelInfo::LoadEnvironmentMaps(); +#endif CAnimManager::LoadAnimFiles(); CWorld::PlayerInFocus = 0; CWeapon::InitialiseWeapons(); @@ -294,7 +297,12 @@ CAnimViewer::Update(void) if (pTarget->IsVehicle() || pTarget->IsPed() || pTarget->IsObject()) { ((CPhysical*)pTarget)->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); } +#ifdef FIX_BUGS + // so we don't end up in the water + pTarget->GetMatrix().GetPosition().z = 10.0f; +#else pTarget->GetMatrix().GetPosition().z = 0.0f; +#endif if (modelInfo->GetModelType() == MITYPE_PED) { ((CPed*)pTarget)->bKindaStayInSamePlace = true; diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 08ebbafd..b20e6db3 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -4014,6 +4014,12 @@ CCam::Process_ModelView(const CVector &CameraTarget, float, float, float) Distance += CPad::GetPad(0)->GetLeftStickY()/1000.0f; else Distance += CPad::GetPad(0)->GetLeftStickY() * ((Distance - 10.0f)/20.0f + 1.0f) / 1000.0f; +#ifdef IMPROVED_CAMERA + if(CPad::GetPad(0)->GetLeftMouse()){ + Distance += DEGTORAD(CPad::GetPad(0)->GetMouseY()/2.0f); + Angle += DEGTORAD(CPad::GetPad(0)->GetMouseX()/2.0f); + } +#endif if(Distance < 1.5f) Distance = 1.5f; -- cgit v1.2.3 From 13cefd329390c119126af6dcf0558ceb7c720e59 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 3 Dec 2020 16:04:59 +0100 Subject: more PS2 stuff; memory movement done --- src/collision/TempColModels.cpp | 2 +- src/core/Game.cpp | 250 +++++++++++++++++++++++++++++++++++++++- src/core/World.cpp | 38 +++--- src/core/config.h | 10 +- src/modelinfo/BaseModelInfo.h | 4 +- src/modelinfo/SimpleModelInfo.h | 12 ++ src/vehicles/Heli.cpp | 9 ++ 7 files changed, 295 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/collision/TempColModels.cpp b/src/collision/TempColModels.cpp index 849eb01e..dabb6ebb 100644 --- a/src/collision/TempColModels.cpp +++ b/src/collision/TempColModels.cpp @@ -40,7 +40,7 @@ CTempColModels::Initialise(void) colmodel.numSpheres = ARRAY_SIZE(sphrs);\ colmodel.spheres = sphrs;\ colmodel.level = LEVEL_GENERIC;\ - colmodel.ownsCollisionVolumes = false;\ + colmodel.ownsCollisionVolumes = false; int i; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 586b1469..43e2248f 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -1032,17 +1032,261 @@ void CGame::Process(void) int32 gNumMemMoved; +bool +MoveMem(void **ptr) +{ + if(*ptr){ + gNumMemMoved++; + void *newPtr = gMainHeap.MoveMemory(*ptr); + if(*ptr != newPtr){ + *ptr = newPtr; + return true; + } + } + return false; +} + +typedef struct _SkyRasterExt _SkyRasterExt; +struct _SkyRasterExt +{ + RwInt32 dmaRefCount; /**< Internal use */ + RwInt32 dmaClrCount; /**< Internal use */ + + /* General texture setup register */ + RwUInt32 lsb; /**< Internal use */ + RwUInt32 msb; /**< Internal use */ + RwUInt32 palOffset; /**< Internal use */ + + /* K: a 12 bit 8.4 value in bottom bits */ + /* L: a 2 bit value in 12,13 */ + RwUInt16 mipmapKL; /**< Internal use */ + /* NOTE: This is left shifted two */ + RwUInt8 maxMipLevel; /**< Internal use */ + /* Is this texture to stay in the cache? */ + RwUInt8 bLocked; /**< Internal use */ + + /* Mipmap addresses */ + RwUInt32 miptbp1Lsb; /**< Internal use */ + RwUInt32 miptbp1Msb; /**< Internal use */ + RwUInt32 miptbp2Lsb; /**< Internal use */ + RwUInt32 miptbp2Msb; /**< Internal use */ + + /* Size in bytes in system memory for pixels */ + RwUInt32 sysMemSize; /**< Internal use */ + /* Size in bytes in system memory for palette */ + RwUInt32 sysMemPalSize; /**< Internal use */ + + /* Size in words in video memory for pixels + palette */ + RwUInt32 nTexCacheSize; /**< Internal use */ + + /* Should we cache packets for this raster */ + RwUInt8 cachePkts; /**< Internal use */ + RwUInt8 lockedMipLevel; /**< Currently locked mip level */ + RwUInt8 flags; /**< Bit 0 new format texture */ + /**< Bit 1 twiddled (->32) */ + /**< Bit 2 twiddled (->16) */ + RwUInt8 pad[1]; /**< Internal use */ +#if defined(GSB) && defined(GSPLUS) + RwUInt32 lsb3; /**< Internal use */ + RwUInt32 msb3; /**< Internal use */ + RwUInt32 miptbp3Lsb, miptbp3Msb; /**< Internal use */ + RwUInt32 miptbp4Lsb, miptbp4Msb; /**< Internal use */ +#endif /* defined(GSB) && defined(GSPLUS) */ +}; +uint32 skyRasterExt; +#define RASTEREXTFROMRASTER(raster) \ + ((_SkyRasterExt *)(((RwUInt8 *)(raster)) + skyRasterExt)) + + +// Some convenience structs +struct SkyDataPrefix +{ + uint32 pktSize1; + uint32 data; // pointer to data as read from TXD + uint32 pktSize2; + uint32 unused; +}; + +struct DMAGIFUpload +{ + uint32 tag1_qwc, tag1_addr; // dmaref + uint32 nop1, vif_direct1; + + uint32 giftag[4]; + uint32 gs_bitbltbuf[4]; + + uint32 tag2_qwc, tag2_addr; // dmaref + uint32 nop2, vif_direct2; +}; + +// This is very scary. it depends on the exact memory layout of the DMA chains and whatnot RwTexture * MoveTextureMemoryCB(RwTexture *texture, void *pData) { - // TODO +#ifdef GTA_PS2 + bool *pRet = (bool*)pData; + RwRaster *raster = RwTextureGetRaster(texture); + _SkyRasterExt *rasterExt = RASTEREXTFROMRASTER(raster); + if(raster->originalPixels == nil || // the raw data + raster->cpPixels == raster->originalPixels || // old format, can't handle it + rasterExt->dmaRefCount != 0 && rasterExt->dmaClrCount != 0) + return texture; + + // this is the allocated pointer we will move + SkyDataPrefix *prefix = (SkyDataPrefix*)raster->originalPixels; + DMAGIFUpload *uploads = (DMAGIFUpload*)(prefix+1); + + // We have 4qw for each upload, + // i.e. for each buffer width of mip levels, + // and the palette if there is one. + // NB: this code does NOT support mipmaps! + // so we assume two uploads (pixels and palette) + // + // each upload looks like this: + // (DMAcnt; NOP; VIF DIRECT(2)) + // giftag (1, A+D) + // GS_BITBLTBUF + // (DMAref->pixel data; NOP; VIF DIRECT(5)) + // the DMArefs are what we have to adjust + uintptr dataDiff, upload1Diff, upload2Diff, pixelDiff, paletteDiff; + dataDiff = prefix->data - (uintptr)raster->originalPixels; + upload1Diff = uploads[0].tag2_addr - (uintptr)raster->originalPixels; + if(raster->palette) + upload2Diff = uploads[1].tag2_addr - (uintptr)raster->originalPixels; + pixelDiff = (uintptr)raster->cpPixels - (uintptr)raster->originalPixels; + if(raster->palette) + paletteDiff = (uintptr)raster->palette - (uintptr)raster->originalPixels; + uint8 *newptr = (uint8*)gMainHeap.MoveMemory(raster->originalPixels); + if(newptr != raster->originalPixels){ + // adjust everything + prefix->data = (uintptr)newptr + dataDiff; + uploads[0].tag2_addr = (uintptr)newptr + upload1Diff; + if(raster->palette) + uploads[1].tag2_addr = (uintptr)newptr + upload2Diff; + raster->originalPixels = newptr; + raster->cpPixels = newptr + pixelDiff; + if(raster->palette) + raster->palette = newptr + paletteDiff; + + if(pRet){ + *pRet = true; + return nil; + } + } +#else + // nothing to do here really, everything should be in videomemory +#endif return texture; } bool -TidyUpModelInfo(CBaseModelInfo *,bool) +MoveAtomicMemory(RpAtomic *atomic, bool onlyOne) { - // TODO + RpGeometry *geo = RpAtomicGetGeometry(atomic); + +#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31 + if(MoveMem((void**)&geo->triangles) && onlyOne) + return true; + if(MoveMem((void**)&geo->matList.materials) && onlyOne) + return true; + if(MoveMem((void**)&geo->preLitLum) && onlyOne) + return true; + if(MoveMem((void**)&geo->texCoords[0]) && onlyOne) + return true; + if(MoveMem((void**)&geo->texCoords[1]) && onlyOne) + return true; + + // verts and normals of morph target are allocated together + int vertDiff; + if(geo->morphTarget->normals) + vertDiff = geo->morphTarget->normals - geo->morphTarget->verts; + if(MoveMem((void**)&geo->morphTarget->verts)){ + if(geo->morphTarget->normals) + geo->morphTarget->normals = geo->morphTarget->verts + vertDiff; + if(onlyOne) + return true; + } + + RpMeshHeader *oldmesh = geo->mesh; + if(MoveMem((void**)&geo->mesh)){ + // index pointers are allocated together with meshes, + // have to relocate those too + RpMesh *mesh = (RpMesh*)(geo->mesh+1); + uintptr reloc = (uintptr)geo->mesh - (uintptr)oldmesh; + for(int i = 0; i < geo->mesh->numMeshes; i++) + mesh[i].indices = (RxVertexIndex*)((uintptr)mesh[i].indices + reloc); + if(onlyOne) + return true; + } +#else + // we could do something in librw here +#endif + return false; +} + +bool +MoveColModelMemory(CColModel &colModel, bool onlyOne) +{ +#if GTA_VERSION >= GTA3_PS2_160 + // hm...should probably only do this if ownsCollisionVolumes + // but it doesn't exist on PS2... + if(!colModel.ownsCollisionVolumes) + return false; +#endif + + if(MoveMem((void**)&colModel.spheres) && onlyOne) + return true; + if(MoveMem((void**)&colModel.lines) && onlyOne) + return true; + if(MoveMem((void**)&colModel.boxes) && onlyOne) + return true; + if(MoveMem((void**)&colModel.vertices) && onlyOne) + return true; + if(MoveMem((void**)&colModel.triangles) && onlyOne) + return true; + if(MoveMem((void**)&colModel.trianglePlanes) && onlyOne) + return true; + return false; +} + +RpAtomic* +MoveAtomicMemoryCB(RpAtomic *atomic, void *pData) +{ + bool *pRet = (bool*)pData; + if(pRet == nil) + MoveAtomicMemory(atomic, false); + else if(MoveAtomicMemory(atomic, true)){ + *pRet = true; + return nil; + } + return atomic; +} + +bool +TidyUpModelInfo(CBaseModelInfo *modelInfo, bool onlyone) +{ + if(modelInfo->GetColModel() && modelInfo->DoesOwnColModel()) + if(MoveColModelMemory(*modelInfo->GetColModel(), onlyone)) + return true; + + RwObject *rwobj = modelInfo->GetRwObject(); + if(RwObjectGetType(rwobj) == rpATOMIC) + if(MoveAtomicMemory((RpAtomic*)rwobj, onlyone)) + return true; + if(RwObjectGetType(rwobj) == rpCLUMP){ + bool ret = false; + if(onlyone) + RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, &ret); + else + RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, nil); + if(ret) + return true; + } + + if(modelInfo->GetModelType() == MITYPE_PED && ((CPedModelInfo*)modelInfo)->m_hitColModel) + if(MoveColModelMemory(*((CPedModelInfo*)modelInfo)->m_hitColModel, onlyone)) + return true; + return false; } diff --git a/src/core/World.cpp b/src/core/World.cpp index 844a4fb7..0bc564ff 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -922,24 +922,24 @@ CEntity * CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore, bool ignoreSomeObjects) { - static CColModel sphereCol; - - sphereCol.boundingSphere.center.x = 0.0f; - sphereCol.boundingSphere.center.y = 0.0f; - sphereCol.boundingSphere.center.z = 0.0f; - sphereCol.boundingSphere.radius = radius; - sphereCol.boundingBox.min.x = -radius; - sphereCol.boundingBox.min.y = -radius; - sphereCol.boundingBox.min.z = -radius; - sphereCol.boundingBox.max.x = radius; - sphereCol.boundingBox.max.y = radius; - sphereCol.boundingBox.max.z = radius; - sphereCol.numSpheres = 1; - sphereCol.spheres = &sphereCol.boundingSphere; - sphereCol.numLines = 0; - sphereCol.numBoxes = 0; - sphereCol.numTriangles = 0; - sphereCol.ownsCollisionVolumes = false; + static CColModel OurColModel; + + OurColModel.boundingSphere.center.x = 0.0f; + OurColModel.boundingSphere.center.y = 0.0f; + OurColModel.boundingSphere.center.z = 0.0f; + OurColModel.boundingSphere.radius = radius; + OurColModel.boundingBox.min.x = -radius; + OurColModel.boundingBox.min.y = -radius; + OurColModel.boundingBox.min.z = -radius; + OurColModel.boundingBox.max.x = radius; + OurColModel.boundingBox.max.y = radius; + OurColModel.boundingBox.max.z = radius; + OurColModel.numSpheres = 1; + OurColModel.spheres = &OurColModel.boundingSphere; + OurColModel.numLines = 0; + OurColModel.numBoxes = 0; + OurColModel.numTriangles = 0; + OurColModel.ownsCollisionVolumes = false; CMatrix sphereMat; sphereMat.SetTranslate(spherePos); @@ -962,7 +962,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad if(e->GetBoundRadius() + radius > distance) { CColModel *eCol = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); int collidedSpheres = - CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), *eCol, + CCollision::ProcessColModels(sphereMat, OurColModel, e->GetMatrix(), *eCol, gaTempSphereColPoints, nil, nil); if(collidedSpheres != 0 || diff --git a/src/core/config.h b/src/core/config.h index 4e71224f..ad0df2da 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -1,27 +1,27 @@ #pragma once enum Config { - NUMPLAYERS = 1, + NUMPLAYERS = 1, // 4 on PS2 NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC) MAX_CDIMAGES = 8, // additional cdimages MAX_CDCHANNELS = 5, - MODELINFOSIZE = 5500, + MODELINFOSIZE = 5500, // 3150 on PS2 // TXDSTORESIZE = 850, TXDSTORESIZE = 1024, // for Xbox map EXTRADIRSIZE = 128, CUTSCENEDIRSIZE = 512, - SIMPLEMODELSIZE = 5000, + SIMPLEMODELSIZE = 5000, // 2910 on PS2 MLOMODELSIZE = 1, MLOINSTANCESIZE = 1, TIMEMODELSIZE = 30, CLUMPMODELSIZE = 5, PEDMODELSIZE = 90, - VEHICLEMODELSIZE = 120, + VEHICLEMODELSIZE = 120, // 70 on PS2 XTRACOMPSMODELSIZE = 2, - TWODFXSIZE = 2000, + TWODFXSIZE = 2000, // 1210 on PS2 MAXVEHICLESLOADED = 50, // 70 on mobile diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h index 2505967b..4c274aaf 100644 --- a/src/modelinfo/BaseModelInfo.h +++ b/src/modelinfo/BaseModelInfo.h @@ -63,9 +63,9 @@ public: bool DoesOwnColModel(void) { return m_bOwnsColModel; } void DeleteCollisionModel(void); void ClearTexDictionary(void) { m_txdSlot = -1; } - short GetObjectID(void) { return m_objectId; } + int16 GetObjectID(void) { return m_objectId; } void SetObjectID(int16 id) { m_objectId = id; } - short GetTxdSlot(void) { return m_txdSlot; } + int16 GetTxdSlot(void) { return m_txdSlot; } void AddRef(void); void RemoveRef(void); void SetTexDictionary(const char *name); diff --git a/src/modelinfo/SimpleModelInfo.h b/src/modelinfo/SimpleModelInfo.h index ee63f24b..94e55a2f 100644 --- a/src/modelinfo/SimpleModelInfo.h +++ b/src/modelinfo/SimpleModelInfo.h @@ -11,6 +11,18 @@ public: float m_lodDistances[3]; uint8 m_numAtomics; uint8 m_alpha; + /* // For reference, PS2 has: + uint8 m_firstDamaged; + uint8 m_normalCull : 1; + uint8 m_isDamaged : 1; + uint8 m_isBigBuilding : 1; + uint8 m_noFade : 1; + uint8 m_drawLast : 1; + uint8 m_additive : 1; + uint8 m_isSubway : 1; + uint8 m_ignoreLight : 1; + // m_noZwrite is missing because not needed + */ uint16 m_firstDamaged : 2; // 0: no damage model // 1: 1 and 2 are damage models // 2: 2 is damage model diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index a8705524..7008818b 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -778,8 +778,10 @@ CHeli::InitHelis(void) for(i = 0; i < NUM_HELIS; i++) pHelis[i] = nil; +#if GTA_VERSION >= GTA3_PS2_160 ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1); ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1); +#endif } CHeli* @@ -789,6 +791,13 @@ GenerateHeli(bool catalina) CVector heliPos; int i; +#if GTA_VERSION < GTA3_PS2_160 + if(catalina) + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1); + else + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1); +#endif + if(catalina) heli = new CHeli(MI_ESCAPE, PERMANENT_VEHICLE); else -- cgit v1.2.3 From 955698d2d37688b86568ee9633cac64bcc01db17 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 3 Dec 2020 16:05:28 +0100 Subject: kludge to prevent dodo unique jumps --- src/control/Script2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/Script2.cpp b/src/control/Script2.cpp index 62b9af93..9363cc7b 100644 --- a/src/control/Script2.cpp +++ b/src/control/Script2.cpp @@ -1539,7 +1539,8 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(pVehicle); - UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0); + bool usj_with_dodo = strcmp(m_abScriptName, "usj") == 0 && pVehicle->GetModelIndex() == MI_DODO; + UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0 && !usj_with_dodo); return 0; } default: -- cgit v1.2.3 From a6c4d9b77cce5a7709e8ab23ab019e91ea0ab798 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 3 Dec 2020 16:07:16 +0100 Subject: forgot to wrap in FIX_BUGS --- src/control/Script2.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/control/Script2.cpp b/src/control/Script2.cpp index 9363cc7b..562125c6 100644 --- a/src/control/Script2.cpp +++ b/src/control/Script2.cpp @@ -1539,8 +1539,13 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(pVehicle); +#ifdef FIX_BUGS + // don't wanna get stuck in unique stunt jump cam forever bool usj_with_dodo = strcmp(m_abScriptName, "usj") == 0 && pVehicle->GetModelIndex() == MI_DODO; UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0 && !usj_with_dodo); +#else + UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0); +#endif return 0; } default: -- cgit v1.2.3 From 5bed7afd790c0d023b5ce31703f4edf6abded9f8 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 3 Dec 2020 16:56:32 +0100 Subject: forgot some junk --- src/core/Game.cpp | 55 +++---------------------------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 43e2248f..dfc13bb2 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -1030,6 +1030,8 @@ void CGame::Process(void) #endif } +#ifdef USE_CUSTOM_ALLOCATOR + int32 gNumMemMoved; bool @@ -1046,58 +1048,6 @@ MoveMem(void **ptr) return false; } -typedef struct _SkyRasterExt _SkyRasterExt; -struct _SkyRasterExt -{ - RwInt32 dmaRefCount; /**< Internal use */ - RwInt32 dmaClrCount; /**< Internal use */ - - /* General texture setup register */ - RwUInt32 lsb; /**< Internal use */ - RwUInt32 msb; /**< Internal use */ - RwUInt32 palOffset; /**< Internal use */ - - /* K: a 12 bit 8.4 value in bottom bits */ - /* L: a 2 bit value in 12,13 */ - RwUInt16 mipmapKL; /**< Internal use */ - /* NOTE: This is left shifted two */ - RwUInt8 maxMipLevel; /**< Internal use */ - /* Is this texture to stay in the cache? */ - RwUInt8 bLocked; /**< Internal use */ - - /* Mipmap addresses */ - RwUInt32 miptbp1Lsb; /**< Internal use */ - RwUInt32 miptbp1Msb; /**< Internal use */ - RwUInt32 miptbp2Lsb; /**< Internal use */ - RwUInt32 miptbp2Msb; /**< Internal use */ - - /* Size in bytes in system memory for pixels */ - RwUInt32 sysMemSize; /**< Internal use */ - /* Size in bytes in system memory for palette */ - RwUInt32 sysMemPalSize; /**< Internal use */ - - /* Size in words in video memory for pixels + palette */ - RwUInt32 nTexCacheSize; /**< Internal use */ - - /* Should we cache packets for this raster */ - RwUInt8 cachePkts; /**< Internal use */ - RwUInt8 lockedMipLevel; /**< Currently locked mip level */ - RwUInt8 flags; /**< Bit 0 new format texture */ - /**< Bit 1 twiddled (->32) */ - /**< Bit 2 twiddled (->16) */ - RwUInt8 pad[1]; /**< Internal use */ -#if defined(GSB) && defined(GSPLUS) - RwUInt32 lsb3; /**< Internal use */ - RwUInt32 msb3; /**< Internal use */ - RwUInt32 miptbp3Lsb, miptbp3Msb; /**< Internal use */ - RwUInt32 miptbp4Lsb, miptbp4Msb; /**< Internal use */ -#endif /* defined(GSB) && defined(GSPLUS) */ -}; -uint32 skyRasterExt; -#define RASTEREXTFROMRASTER(raster) \ - ((_SkyRasterExt *)(((RwUInt8 *)(raster)) + skyRasterExt)) - - // Some convenience structs struct SkyDataPrefix { @@ -1289,6 +1239,7 @@ TidyUpModelInfo(CBaseModelInfo *modelInfo, bool onlyone) return false; } +#endif void CGame::DrasticTidyUpMemory(bool flushDraw) { -- cgit v1.2.3 From 9714a3776996d97e680cea575967a1d6041f5723 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 4 Dec 2020 01:12:58 +0100 Subject: bit more GTA_VERSION and GTA_PS2 --- src/core/Game.cpp | 47 +++++++++++++++++++++++++++++--------- src/core/main.cpp | 18 ++++++++++----- src/modelinfo/VehicleModelInfo.cpp | 9 +++++++- src/rw/VisibilityPlugins.cpp | 5 ++++ 4 files changed, 61 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/core/Game.cpp b/src/core/Game.cpp index dfc13bb2..33302653 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -170,26 +170,39 @@ void ReplaceAtomicPipeCallback(); #endif // PS2_ALPHA_TEST #endif // !LIBRW -// missing altogether on PS2, mostly done in GameInit there it seems bool CGame::InitialiseRenderWare(void) { #ifdef USE_TEXTURE_POOL _TexturePoolsInitialise(); #endif - - CTxdStore::Initialise(); - CVisibilityPlugins::Initialise(); - + +#if GTA_VERSION > GTA3_PS2_160 + CTxdStore::Initialise(); // in GameInit on ps2 + CVisibilityPlugins::Initialise(); // in plugin attach on ps2 +#endif + + //InitialiseScene(Scene); // PS2 only, only clears Scene.camera + +#ifdef GTA_PS2 + RpSkySelectTrueTSClipper(TRUE); + RpSkySelectTrueTLClipper(TRUE); + + // PS2ManagerApplyDirectionalLightingCB() uploads the GTA lights + // directly without going through RpWorld and all that + SetupPS2ManagerDefaultLightingCallback(); + PreAllocateRwObjects(); +#endif + /* Create camera */ - Scene.camera = CameraCreate(RsGlobal.width, RsGlobal.height, TRUE); + Scene.camera = CameraCreate(SCREEN_WIDTH, SCREEN_HEIGHT, TRUE); ASSERT(Scene.camera != nil); if (!Scene.camera) { return (false); } - RwCameraSetFarClipPlane(Scene.camera, 2000.0f); + RwCameraSetFarClipPlane(Scene.camera, 2000.0f); // 250.0f on PS2 but who cares RwCameraSetNearClipPlane(Scene.camera, 0.9f); CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO); @@ -212,8 +225,12 @@ CGame::InitialiseRenderWare(void) /* Add the camera to the world */ RpWorldAddCamera(Scene.world, Scene.camera); LightsCreate(Scene.world); - - CreateDebugFont(); + +#if GTA_VERSION > GTA3_PS2_160 + CreateDebugFont(); // in GameInit on PS2 +#else + RwImageSetPath("textures"); +#endif #ifdef LIBRW #ifdef PS2_MATFX @@ -229,9 +246,16 @@ CGame::InitialiseRenderWare(void) ReplaceAtomicPipeCallback(); #endif // PS2_ALPHA_TEST #endif // LIBRW - + + +#if GTA_VERSION > GTA3_PS2_160 + // in GameInit on PS2 + PUSH_MEMID(MEMID_TEXTURES); CFont::Initialise(); CHud::Initialise(); + POP_MEMID(); +#endif + // TODO: define CPlayerSkin::Initialise(); return (true); @@ -247,7 +271,8 @@ void CGame::ShutdownRenderWare(void) for ( int32 i = 0; i < NUMPLAYERS; i++ ) CWorld::Players[i].DeletePlayerSkin(); - + + // TODO: define CPlayerSkin::Shutdown(); DestroyDebugFont(); diff --git a/src/core/main.cpp b/src/core/main.cpp index ebfa096a..54821979 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -114,7 +114,7 @@ void DebugMenuPopulate(void); bool gbPrintMemoryUsage; #endif -#ifdef GTA_PS2 +#ifdef PS2_MENU #define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad #define FOUND_GAME_TO_LOAD TheMemoryCard.b_FoundRecentSavedGameWantToLoad #else @@ -415,7 +415,6 @@ PluginAttach(void) return TRUE; } -// rather different on PS2 static RwBool Initialise3D(void *param) { @@ -1766,7 +1765,7 @@ void SystemInit() #ifdef GTA_PS2 CFileMgr::InitCd(); - Char modulepath[256]; + char modulepath[256]; strcpy(modulepath, "cdrom0:\\"); strcat(modulepath, "SYSTEM\\"); @@ -1989,7 +1988,7 @@ void GameInit() CreateDebugFont(); #ifdef GTA_PS2 - AddIntcHandler(_TODOCONST(2), VBlankCounter, 0); + AddIntcHandler(INTC_VBLANK_S, VBlankCounter, 0); #endif CameraSize(Scene.camera, NULL, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO); @@ -2031,8 +2030,7 @@ main(int argc, char *argv[]) #ifdef GTA_PS2 int32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE); - if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT - && r != CMemoryCard::ERR_OPENNOENTRY && r != CMemoryCard::ERR_NONE ) + if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT ) { GameInit(); @@ -2042,6 +2040,8 @@ main(int argc, char *argv[]) CFont::Initialise(); FrontEndMenuManager.DrawMemoryCardStartUpMenus(); + }else if(r == CMemoryCard::ERR_OPENNOENTRY || r == CMemoryCard::ERR_NONE){ + // eh? } #endif @@ -2052,12 +2052,18 @@ main(int argc, char *argv[]) InitMPEGPlayer(); +#ifdef GTA_PAL PlayMPEG("cdrom0:\\MOVIES\\DMAPAL.PSS;1", false); if (CGame::frenchGame || CGame::germanGame) PlayMPEG("cdrom0:\\MOVIES\\INTROPAF.PSS;1", true); else PlayMPEG("cdrom0:\\MOVIES\\INTROPAL.PSS;1", true); +#else + PlayMPEG("cdrom0:\\MOVIES\\DMANTSC.PSS;1", false); + + PlayMPEG("cdrom0:\\MOVIES\\INTRNTSC.PSS;1", true); +#endif ShutdownMPEGPlayer(); diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index afda70d3..17754211 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -998,6 +998,8 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpMaterial *material, void *data) return material; } +bool initialised; + RpAtomic* CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data) { @@ -1011,7 +1013,12 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data) RpGeometryForAllMaterials(geo, SetEnvironmentMapCB, data); RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) | rpGEOMETRYMODULATEMATERIALCOLOR); RpMatFXAtomicEnableEffects(atomic); - // PS2 sets of PS2Manager lighting CB here +#ifdef GTA_PS2 + if(!initialised){ + SetupPS2ManagerLightingCallback(RpAtomicGetInstancePipeline(atomic)); + initialised = true; + } +#endif } return atomic; } diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index f931019c..d81c97f2 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -819,6 +819,11 @@ CVisibilityPlugins::PluginAttach(void) ms_clumpPluginOffset = RpClumpRegisterPlugin(sizeof(ClumpExt), ID_VISIBILITYCLUMP, ClumpConstructor, ClumpDestructor, ClumpCopyConstructor); + +#if GTA_VERSION <= GTA3_PS2_16 + Initialise(); +#endif + return ms_atomicPluginOffset != -1 && ms_clumpPluginOffset != -1; } -- cgit v1.2.3 From 466eee84e76214a3300f3183f5025140c036e431 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 4 Dec 2020 10:23:04 +0100 Subject: typo --- src/rw/VisibilityPlugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index d81c97f2..b27d96c8 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -820,7 +820,7 @@ CVisibilityPlugins::PluginAttach(void) ID_VISIBILITYCLUMP, ClumpConstructor, ClumpDestructor, ClumpCopyConstructor); -#if GTA_VERSION <= GTA3_PS2_16 +#if GTA_VERSION <= GTA3_PS2_160 Initialise(); #endif -- cgit v1.2.3 From 28a942735cbcb329b572a20504b05d88e1364db6 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 5 Dec 2020 14:50:54 +0100 Subject: fix pMemoryTop --- src/rw/MemoryMgr.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/rw/MemoryMgr.cpp b/src/rw/MemoryMgr.cpp index ef0ecbdf..e2f6f144 100644 --- a/src/rw/MemoryMgr.cpp +++ b/src/rw/MemoryMgr.cpp @@ -3,7 +3,7 @@ #include "MemoryMgr.h" -void *pMemoryTop; +uint8 *pMemoryTop; void InitMemoryMgr(void) @@ -42,8 +42,8 @@ MemoryMgrMalloc(size_t size) #else void *mem = malloc(size); #endif - if(mem > pMemoryTop) - pMemoryTop = mem; + if((uint8*)mem + size > pMemoryTop) + pMemoryTop = (uint8*)mem + size ; return mem; } @@ -55,8 +55,8 @@ MemoryMgrRealloc(void *ptr, size_t size) #else void *mem = realloc(ptr, size); #endif - if(mem > pMemoryTop) - pMemoryTop = mem; + if((uint8*)mem + size > pMemoryTop) + pMemoryTop = (uint8*)mem + size ; return mem; } @@ -68,8 +68,8 @@ MemoryMgrCalloc(size_t num, size_t size) #else void *mem = calloc(num, size); #endif - if(mem > pMemoryTop) - pMemoryTop = mem; + if((uint8*)mem + size > pMemoryTop) + pMemoryTop = (uint8*)mem + size ; #ifdef FIX_BUGS memset(mem, 0, num*size); #endif -- cgit v1.2.3 From efb28b888d4ed89e1f8fc770a66ddfd7e03f4942 Mon Sep 17 00:00:00 2001 From: Nikolay Date: Sat, 5 Dec 2020 22:26:45 +0300 Subject: fixed ANCHOR_BOAT --- src/control/Script4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp index f5fb9781..78da2d96 100644 --- a/src/control/Script4.cpp +++ b/src/control/Script4.cpp @@ -89,7 +89,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: -- cgit v1.2.3 From 14eb0cd286483dd14ac110658360ecd76199390c Mon Sep 17 00:00:00 2001 From: Nikolay Date: Sun, 6 Dec 2020 15:27:42 +0300 Subject: fixed parenthesis --- src/control/Garages.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 96391914..33137c69 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1046,8 +1046,8 @@ void CGarage::Update() // Close car doors either if player is far, or if he is in vehicle and garage is full, // or if player is very very far so that we can remove whatever is blocking garage door without him noticing if ((distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR) || - !FindPlayerVehicle() && distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT) && - !IsAnyCarBlockingDoor())) + !FindPlayerVehicle() && distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT)) && + !IsAnyCarBlockingDoor()) m_eGarageState = GS_CLOSING; else if (FindPlayerVehicle() && CountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >= -- cgit v1.2.3 From 3a66b178876498e02d7aa349b3b8c4754c42ba18 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sun, 6 Dec 2020 20:25:26 +0100 Subject: inttypes.h is part of the C++ standard, so prefix it --- src/extras/debugmenu.cpp | 2 +- src/extras/inttypes.h | 216 ---------------------------------------------- src/extras/re3_inttypes.h | 216 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+), 217 deletions(-) delete mode 100644 src/extras/inttypes.h create mode 100644 src/extras/re3_inttypes.h (limited to 'src') diff --git a/src/extras/debugmenu.cpp b/src/extras/debugmenu.cpp index 3a4c4175..533b97f5 100644 --- a/src/extras/debugmenu.cpp +++ b/src/extras/debugmenu.cpp @@ -5,7 +5,7 @@ #include "ControllerConfig.h" #include "Timer.h" #include "rtcharse.h" -#include "inttypes.h" +#include "re3_inttypes.h" #include "debugmenu.h" #include diff --git a/src/extras/inttypes.h b/src/extras/inttypes.h deleted file mode 100644 index bf0c53e2..00000000 --- a/src/extras/inttypes.h +++ /dev/null @@ -1,216 +0,0 @@ -#define PRId8 "hhd" -#define PRId16 "hd" -#define PRId32 "ld" -#define PRId64 "lld" - -#define PRIdFAST8 "hhd" -#define PRIdFAST16 "hd" -#define PRIdFAST32 "ld" -#define PRIdFAST64 "lld" - -#define PRIdLEAST8 "hhd" -#define PRIdLEAST16 "hd" -#define PRIdLEAST32 "ld" -#define PRIdLEAST64 "lld" - -#define PRIdMAX "lld" -#define PRIdPTR "lld" - -#define PRIi8 "hhi" -#define PRIi16 "hi" -#define PRIi32 "li" -#define PRIi64 "lli" - -#define PRIiFAST8 "hhi" -#define PRIiFAST16 "hi" -#define PRIiFAST32 "li" -#define PRIiFAST64 "lli" - -#define PRIiLEAST8 "hhi" -#define PRIiLEAST16 "hi" -#define PRIiLEAST32 "li" -#define PRIiLEAST64 "lli" - -#define PRIiMAX "lli" -#define PRIiPTR "lli" - -#define PRIo8 "hho" -#define PRIo16 "ho" -#define PRIo32 "lo" -#define PRIo64 "llo" - -#define PRIoFAST8 "hho" -#define PRIoFAST16 "ho" -#define PRIoFAST32 "lo" -#define PRIoFAST64 "llo" - -#define PRIoLEAST8 "hho" -#define PRIoLEAST16 "ho" -#define PRIoLEAST32 "lo" -#define PRIoLEAST64 "llo" - -#define PRIoMAX "llo" -#define PRIoPTR "llo" - -#define PRIu8 "hhu" -#define PRIu16 "hu" -#define PRIu32 "lu" -#define PRIu64 "llu" - -#define PRIuFAST8 "hhu" -#define PRIuFAST16 "hu" -#define PRIuFAST32 "lu" -#define PRIuFAST64 "llu" - -#define PRIuLEAST8 "hhu" -#define PRIuLEAST16 "hu" -#define PRIuLEAST32 "lu" -#define PRIuLEAST64 "llu" - -#define PRIuMAX "llu" -#define PRIuPTR "llu" - -#define PRIx8 "hhx" -#define PRIx16 "hx" -#define PRIx32 "lx" -#define PRIx64 "llx" - -#define PRIxFAST8 "hhx" -#define PRIxFAST16 "hx" -#define PRIxFAST32 "lx" -#define PRIxFAST64 "llx" - -#define PRIxLEAST8 "hhx" -#define PRIxLEAST16 "hx" -#define PRIxLEAST32 "lx" -#define PRIxLEAST64 "llx" - -#define PRIxMAX "llx" -#define PRIxPTR "llx" - -#define PRIX8 "hhX" -#define PRIX16 "hX" -#define PRIX32 "lX" -#define PRIX64 "llX" - -#define PRIXFAST8 "hhX" -#define PRIXFAST16 "hX" -#define PRIXFAST32 "lX" -#define PRIXFAST64 "llX" - -#define PRIXLEAST8 "hhX" -#define PRIXLEAST16 "hX" -#define PRIXLEAST32 "lX" -#define PRIXLEAST64 "llX" - -#define PRIXMAX "llX" -#define PRIXPTR "llX" - - /* SCAN FORMAT MACROS */ -#define SCNd8 "hhd" -#define SCNd16 "hd" -#define SCNd32 "ld" -#define SCNd64 "lld" - -#define SCNdFAST8 "hhd" -#define SCNdFAST16 "hd" -#define SCNdFAST32 "ld" -#define SCNdFAST64 "lld" - -#define SCNdLEAST8 "hhd" -#define SCNdLEAST16 "hd" -#define SCNdLEAST32 "ld" -#define SCNdLEAST64 "lld" - -#define SCNdMAX "lld" -#define SCNdPTR "lld" - -#define SCNi8 "hhi" -#define SCNi16 "hi" -#define SCNi32 "li" -#define SCNi64 "lli" - -#define SCNiFAST8 "hhi" -#define SCNiFAST16 "hi" -#define SCNiFAST32 "li" -#define SCNiFAST64 "lli" - -#define SCNiLEAST8 "hhi" -#define SCNiLEAST16 "hi" -#define SCNiLEAST32 "li" -#define SCNiLEAST64 "lli" - -#define SCNiMAX "lli" -#define SCNiPTR "lli" - -#define SCNo8 "hho" -#define SCNo16 "ho" -#define SCNo32 "lo" -#define SCNo64 "llo" - -#define SCNoFAST8 "hho" -#define SCNoFAST16 "ho" -#define SCNoFAST32 "lo" -#define SCNoFAST64 "llo" - -#define SCNoLEAST8 "hho" -#define SCNoLEAST16 "ho" -#define SCNoLEAST32 "lo" -#define SCNoLEAST64 "llo" - -#define SCNoMAX "llo" -#define SCNoPTR "llo" - -#define SCNu8 "hhu" -#define SCNu16 "hu" -#define SCNu32 "lu" -#define SCNu64 "llu" - -#define SCNuFAST8 "hhu" -#define SCNuFAST16 "hu" -#define SCNuFAST32 "lu" -#define SCNuFAST64 "llu" - -#define SCNuLEAST8 "hhu" -#define SCNuLEAST16 "hu" -#define SCNuLEAST32 "lu" -#define SCNuLEAST64 "llu" - -#define SCNuMAX "llu" -#define SCNuPTR "llu" - -#define SCNx8 "hhx" -#define SCNx16 "hx" -#define SCNx32 "lx" -#define SCNx64 "llx" - -#define SCNxFAST8 "hhx" -#define SCNxFAST16 "hx" -#define SCNxFAST32 "lx" -#define SCNxFAST64 "llx" - -#define SCNxLEAST8 "hhx" -#define SCNxLEAST16 "hx" -#define SCNxLEAST32 "lx" -#define SCNxLEAST64 "llx" - -#define SCNxMAX "llx" -#define SCNxPTR "llx" - -#define SCNX8 "hhX" -#define SCNX16 "hX" -#define SCNX32 "lX" -#define SCNX64 "llX" - -#define SCNXFAST8 "hhX" -#define SCNXFAST16 "hX" -#define SCNXFAST32 "lX" -#define SCNXFAST64 "llX" - -#define SCNXLEAST8 "hhX" -#define SCNXLEAST16 "hX" -#define SCNXLEAST32 "lX" -#define SCNXLEAST64 "llX" - -#define SCNXMAX "llX" -#define SCNXPTR "llX" \ No newline at end of file diff --git a/src/extras/re3_inttypes.h b/src/extras/re3_inttypes.h new file mode 100644 index 00000000..bf0c53e2 --- /dev/null +++ b/src/extras/re3_inttypes.h @@ -0,0 +1,216 @@ +#define PRId8 "hhd" +#define PRId16 "hd" +#define PRId32 "ld" +#define PRId64 "lld" + +#define PRIdFAST8 "hhd" +#define PRIdFAST16 "hd" +#define PRIdFAST32 "ld" +#define PRIdFAST64 "lld" + +#define PRIdLEAST8 "hhd" +#define PRIdLEAST16 "hd" +#define PRIdLEAST32 "ld" +#define PRIdLEAST64 "lld" + +#define PRIdMAX "lld" +#define PRIdPTR "lld" + +#define PRIi8 "hhi" +#define PRIi16 "hi" +#define PRIi32 "li" +#define PRIi64 "lli" + +#define PRIiFAST8 "hhi" +#define PRIiFAST16 "hi" +#define PRIiFAST32 "li" +#define PRIiFAST64 "lli" + +#define PRIiLEAST8 "hhi" +#define PRIiLEAST16 "hi" +#define PRIiLEAST32 "li" +#define PRIiLEAST64 "lli" + +#define PRIiMAX "lli" +#define PRIiPTR "lli" + +#define PRIo8 "hho" +#define PRIo16 "ho" +#define PRIo32 "lo" +#define PRIo64 "llo" + +#define PRIoFAST8 "hho" +#define PRIoFAST16 "ho" +#define PRIoFAST32 "lo" +#define PRIoFAST64 "llo" + +#define PRIoLEAST8 "hho" +#define PRIoLEAST16 "ho" +#define PRIoLEAST32 "lo" +#define PRIoLEAST64 "llo" + +#define PRIoMAX "llo" +#define PRIoPTR "llo" + +#define PRIu8 "hhu" +#define PRIu16 "hu" +#define PRIu32 "lu" +#define PRIu64 "llu" + +#define PRIuFAST8 "hhu" +#define PRIuFAST16 "hu" +#define PRIuFAST32 "lu" +#define PRIuFAST64 "llu" + +#define PRIuLEAST8 "hhu" +#define PRIuLEAST16 "hu" +#define PRIuLEAST32 "lu" +#define PRIuLEAST64 "llu" + +#define PRIuMAX "llu" +#define PRIuPTR "llu" + +#define PRIx8 "hhx" +#define PRIx16 "hx" +#define PRIx32 "lx" +#define PRIx64 "llx" + +#define PRIxFAST8 "hhx" +#define PRIxFAST16 "hx" +#define PRIxFAST32 "lx" +#define PRIxFAST64 "llx" + +#define PRIxLEAST8 "hhx" +#define PRIxLEAST16 "hx" +#define PRIxLEAST32 "lx" +#define PRIxLEAST64 "llx" + +#define PRIxMAX "llx" +#define PRIxPTR "llx" + +#define PRIX8 "hhX" +#define PRIX16 "hX" +#define PRIX32 "lX" +#define PRIX64 "llX" + +#define PRIXFAST8 "hhX" +#define PRIXFAST16 "hX" +#define PRIXFAST32 "lX" +#define PRIXFAST64 "llX" + +#define PRIXLEAST8 "hhX" +#define PRIXLEAST16 "hX" +#define PRIXLEAST32 "lX" +#define PRIXLEAST64 "llX" + +#define PRIXMAX "llX" +#define PRIXPTR "llX" + + /* SCAN FORMAT MACROS */ +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "ld" +#define SCNd64 "lld" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 "hd" +#define SCNdFAST32 "ld" +#define SCNdFAST64 "lld" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "ld" +#define SCNdLEAST64 "lld" + +#define SCNdMAX "lld" +#define SCNdPTR "lld" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "li" +#define SCNi64 "lli" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 "hi" +#define SCNiFAST32 "li" +#define SCNiFAST64 "lli" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "li" +#define SCNiLEAST64 "lli" + +#define SCNiMAX "lli" +#define SCNiPTR "lli" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "lo" +#define SCNo64 "llo" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 "ho" +#define SCNoFAST32 "lo" +#define SCNoFAST64 "llo" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "lo" +#define SCNoLEAST64 "llo" + +#define SCNoMAX "llo" +#define SCNoPTR "llo" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "lu" +#define SCNu64 "llu" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 "hu" +#define SCNuFAST32 "lu" +#define SCNuFAST64 "llu" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "lu" +#define SCNuLEAST64 "llu" + +#define SCNuMAX "llu" +#define SCNuPTR "llu" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "lx" +#define SCNx64 "llx" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 "hx" +#define SCNxFAST32 "lx" +#define SCNxFAST64 "llx" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "lx" +#define SCNxLEAST64 "llx" + +#define SCNxMAX "llx" +#define SCNxPTR "llx" + +#define SCNX8 "hhX" +#define SCNX16 "hX" +#define SCNX32 "lX" +#define SCNX64 "llX" + +#define SCNXFAST8 "hhX" +#define SCNXFAST16 "hX" +#define SCNXFAST32 "lX" +#define SCNXFAST64 "llX" + +#define SCNXLEAST8 "hhX" +#define SCNXLEAST16 "hX" +#define SCNXLEAST32 "lX" +#define SCNXLEAST64 "llX" + +#define SCNXMAX "llX" +#define SCNXPTR "llX" \ No newline at end of file -- cgit v1.2.3 From 12d3893fe9454cac13d14c39abcb829fd43caabe Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sun, 6 Dec 2020 20:26:40 +0100 Subject: crossplatform is needed for casepath on non-Windows systems --- src/audio/oal/stream.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 3adb702a..90e90dd8 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -10,13 +10,15 @@ #ifdef _WIN32 #pragma comment( lib, "libsndfile-1.lib" ) #pragma comment( lib, "libmpg123-0.lib" ) -#else -#include "crossplatform.h" #endif #include #include #endif +#ifndef _WIN32 +#include "crossplatform.h" +#endif + #ifndef AUDIO_OPUS class CSndFile : public IDecoder { -- cgit v1.2.3 From 4696e3f9c88cdf9e025205b0b525dec8c310b671 Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 7 Dec 2020 00:36:40 +0100 Subject: uint8 enums fixed --- src/audio/AudioLogic.cpp | 4 ++-- src/control/AutoPilot.cpp | 6 +++--- src/control/AutoPilot.h | 12 ++++++------ src/control/CarAI.cpp | 2 +- src/control/CarAI.h | 2 +- src/control/Pickups.cpp | 2 +- src/control/Pickups.h | 4 ++-- src/control/Script.cpp | 4 ++-- src/control/Script4.cpp | 2 +- src/core/World.cpp | 2 +- src/entities/Entity.h | 12 ++++++------ src/modelinfo/BaseModelInfo.h | 7 +++---- src/peds/Ped.h | 4 ++-- src/peds/PedFight.cpp | 4 ++-- src/vehicles/Cranes.h | 8 ++++---- 15 files changed, 37 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 7340e73e..af67b561 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -52,8 +52,8 @@ uint32 gHomeNextTime; uint32 gCellNextTime; uint32 gNextCryTime; -enum PLAY_STATUS : uint8 { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING, PLAY_STATUS_FINISHED }; -enum LOADING_STATUS : uint8 { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED, LOADING_STATUS_FAILED }; +enum PLAY_STATUS { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING, PLAY_STATUS_FINISHED }; +enum LOADING_STATUS { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED, LOADING_STATUS_FAILED }; void cAudioManager::PreInitialiseGameSpecificSetup() const diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index b1fce95f..4038c93e 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -103,9 +103,9 @@ void CAutoPilot::Load(uint8*& buf) m_nNextDirection = ReadSaveBuf(buf); m_nCurrentLane = ReadSaveBuf(buf); m_nNextLane = ReadSaveBuf(buf); - m_nDrivingStyle = (eCarDrivingStyle)ReadSaveBuf(buf); - m_nCarMission = (eCarMission)ReadSaveBuf(buf); - m_nTempAction = (eCarTempAction)ReadSaveBuf(buf); + m_nDrivingStyle = ReadSaveBuf(buf); + m_nCarMission = ReadSaveBuf(buf); + m_nTempAction = ReadSaveBuf(buf); m_nTimeTempAction = ReadSaveBuf(buf); m_fMaxTrafficSpeed = ReadSaveBuf(buf); m_nCruiseSpeed = ReadSaveBuf(buf); diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h index 337a93c1..6349fce6 100644 --- a/src/control/AutoPilot.h +++ b/src/control/AutoPilot.h @@ -4,7 +4,7 @@ class CVehicle; struct CPathNode; -enum eCarMission : uint8 +enum eCarMission { MISSION_NONE, MISSION_CRUISE, @@ -28,7 +28,7 @@ enum eCarMission : uint8 MISSION_BLOCKCAR_HANDBRAKESTOP, }; -enum eCarTempAction : uint8 +enum eCarTempAction { TEMPACT_NONE, TEMPACT_WAIT, @@ -43,7 +43,7 @@ enum eCarTempAction : uint8 TEMPACT_SWERVERIGHT }; -enum eCarDrivingStyle : uint8 +enum eCarDrivingStyle { DRIVINGSTYLE_STOP_FOR_CARS, DRIVINGSTYLE_SLOW_DOWN_FOR_CARS, @@ -69,9 +69,9 @@ public: int8 m_nNextDirection; int8 m_nCurrentLane; int8 m_nNextLane; - eCarDrivingStyle m_nDrivingStyle; - eCarMission m_nCarMission; - eCarTempAction m_nTempAction; + uint8 m_nDrivingStyle; + uint8 m_nCarMission; + uint8 m_nTempAction; uint32 m_nTimeTempAction; float m_fMaxTrafficSpeed; uint8 m_nCruiseSpeed; diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index ab44510d..8c0c5966 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -539,7 +539,7 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget) pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); } -eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() +uint8 CCarAI::FindPoliceCarMissionForWantedLevel() { switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){ case 0: diff --git a/src/control/CarAI.h b/src/control/CarAI.h index e88807c8..9b731ad5 100644 --- a/src/control/CarAI.h +++ b/src/control/CarAI.h @@ -19,7 +19,7 @@ public: static void TellOccupantsToLeaveCar(CVehicle*); static void TellCarToRamOtherCar(CVehicle*, CVehicle*); static void TellCarToBlockOtherCar(CVehicle*, CVehicle*); - static eCarMission FindPoliceCarMissionForWantedLevel(); + static uint8 FindPoliceCarMissionForWantedLevel(); static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*); static void MellowOutChaseSpeed(CVehicle*); static void MakeWayForCarWithSiren(CVehicle *veh); diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 1b1c8cbc..19b3d3a7 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -535,7 +535,7 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan if (slot >= NUMPICKUPS) return -1; - aPickUps[slot].m_eType = (ePickupType)type; + aPickUps[slot].m_eType = type; aPickUps[slot].m_bRemoved = false; aPickUps[slot].m_nQuantity = quantity; if (type == PICKUP_ONCE_TIMEOUT) diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 95eb6fbf..72a37d99 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -1,7 +1,7 @@ #pragma once #include "Weapon.h" -enum ePickupType : uint8 +enum ePickupType { PICKUP_NONE = 0, PICKUP_IN_SHOP, @@ -29,7 +29,7 @@ class CPlayerPed; class CPickup { public: - ePickupType m_eType; + uint8 m_eType; bool m_bRemoved; uint16 m_nQuantity; CObject *m_pObject; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index dbd477e2..1b51e0d6 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3593,7 +3593,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CollectParameters(&m_nIp, 2); CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(car); - car->AutoPilot.m_nDrivingStyle = (eCarDrivingStyle)ScriptParams[1]; + car->AutoPilot.m_nDrivingStyle = (uint8)ScriptParams[1]; return 0; } case COMMAND_SET_CAR_MISSION: @@ -3601,7 +3601,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CollectParameters(&m_nIp, 2); CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(car); - car->AutoPilot.m_nCarMission = (eCarMission)ScriptParams[1]; + car->AutoPilot.m_nCarMission = (uint8)ScriptParams[1]; car->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); car->bEngineOn = true; return 0; diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp index 78da2d96..feef70bc 100644 --- a/src/control/Script4.cpp +++ b/src/control/Script4.cpp @@ -1436,7 +1436,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(pVehicle); - pVehicle->SetStatus((eEntityStatus)ScriptParams[1]); + pVehicle->SetStatus((uint8)ScriptParams[1]); return 0; } case COMMAND_IS_CHAR_MALE: diff --git a/src/core/World.cpp b/src/core/World.cpp index 0bc564ff..981d1395 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1537,7 +1537,7 @@ CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList &list, float x1, float y1 if(pVehicle->m_scanCode != GetCurrentScanCode()) { pVehicle->m_scanCode = GetCurrentScanCode(); const CVector &vehiclePos = pVehicle->GetPosition(); - eCarMission carMission = pVehicle->AutoPilot.m_nCarMission; + uint8 carMission = pVehicle->AutoPilot.m_nCarMission; if(pVehicle != FindPlayerVehicle() && vehiclePos.x > fStartX && vehiclePos.x < fEndX && vehiclePos.y > fStartY && vehiclePos.y < fEndY && pVehicle->bIsLawEnforcer && (carMission == MISSION_RAMPLAYER_FARAWAY || carMission == MISSION_RAMPLAYER_CLOSE || diff --git a/src/entities/Entity.h b/src/entities/Entity.h index ba4f7ab0..9372c85d 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -6,7 +6,7 @@ struct CReference; class CPtrList; -enum eEntityType : uint8 +enum eEntityType { ENTITY_TYPE_NOTHING = 0, ENTITY_TYPE_BUILDING, @@ -16,7 +16,7 @@ enum eEntityType : uint8 ENTITY_TYPE_DUMMY, }; -enum eEntityStatus : uint8 +enum eEntityStatus { STATUS_PLAYER, STATUS_PLAYER_PLAYBACKFROMBUFFER, @@ -92,10 +92,10 @@ public: CReference *m_pFirstReference; public: - eEntityType GetType() const { return (eEntityType)m_type; } - void SetType(eEntityType type) { m_type = type; } - eEntityStatus GetStatus() const { return (eEntityStatus)m_status; } - void SetStatus(eEntityStatus status) { m_status = status; } + uint8 GetType() const { return m_type; } + void SetType(uint8 type) { m_type = type; } + uint8 GetStatus() const { return m_status; } + void SetStatus(uint8 status) { m_status = status; } CColModel *GetColModel(void) { return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); } bool GetIsStatic(void) const { return bIsStatic; } void SetIsStatic(bool state) { bIsStatic = state; } diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h index 4c274aaf..ae2b6668 100644 --- a/src/modelinfo/BaseModelInfo.h +++ b/src/modelinfo/BaseModelInfo.h @@ -4,7 +4,7 @@ #define MAX_MODEL_NAME (24) -enum ModelInfoType : uint8 +enum ModelInfoType { MITYPE_NA = 0, MITYPE_SIMPLE = 1, @@ -15,7 +15,6 @@ enum ModelInfoType : uint8 MITYPE_PED = 6, MITYPE_XTRACOMPS = 7, }; -VALIDATE_SIZE(ModelInfoType, 1); class C2dEffect; @@ -28,7 +27,7 @@ protected: int16 m_objectId; uint16 m_refCount; int16 m_txdSlot; - ModelInfoType m_type; + uint8 m_type; uint8 m_num2dEffects; bool m_bOwnsColModel; #ifdef EXTRA_MODEL_FLAGS @@ -50,7 +49,7 @@ public: virtual RwObject *GetRwObject(void) = 0; // one day it becomes virtual - ModelInfoType GetModelType() const { return m_type; } + uint8 GetModelType() const { return m_type; } bool IsSimple(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME; } bool IsClump(void) { return m_type == MITYPE_CLUMP || m_type == MITYPE_PED || m_type == MITYPE_VEHICLE || m_type == MITYPE_MLO || m_type == MITYPE_XTRACOMPS; // unused but what the heck diff --git a/src/peds/Ped.h b/src/peds/Ped.h index a3d4997d..7a9f4a9e 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -212,7 +212,7 @@ enum PedOnGroundState { PED_DEAD_ON_THE_FLOOR }; -enum PointBlankNecessity : uint8 { +enum PointBlankNecessity { NO_POINT_BLANK_PED, POINT_BLANK_FOR_WANTED_PED, POINT_BLANK_FOR_SOMEONE_ELSE @@ -598,7 +598,7 @@ public: #endif bool CheckForExplosions(CVector2D &area); CPed *CheckForGunShots(void); - PointBlankNecessity CheckForPointBlankPeds(CPed*); + uint8 CheckForPointBlankPeds(CPed*); bool CheckIfInTheAir(void); void ClearAll(void); void SetPointGunAt(CEntity*); diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp index 21310aaa..c219d94f 100644 --- a/src/peds/PedFight.cpp +++ b/src/peds/PedFight.cpp @@ -329,7 +329,7 @@ CPed::SetAttack(CEntity *victim) if (IsPlayer()) CPad::GetPad(0)->ResetAverageWeapon(); - PointBlankNecessity pointBlankStatus; + uint8 pointBlankStatus; if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER) && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT @@ -475,7 +475,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) ped->ClearAttack(); } -PointBlankNecessity +uint8 CPed::CheckForPointBlankPeds(CPed *pedToVerify) { float pbDistance = 1.1f; diff --git a/src/vehicles/Cranes.h b/src/vehicles/Cranes.h index 6d877d82..0e134310 100644 --- a/src/vehicles/Cranes.h +++ b/src/vehicles/Cranes.h @@ -11,7 +11,7 @@ class CBuilding; class CCrane { public: - enum CraneState : uint8 { + enum CraneState { IDLE = 0, GOING_TOWARDS_TARGET = 1, LIFTING_TARGET = 2, @@ -19,7 +19,7 @@ public: ROTATING_TARGET = 4, DROPPING_TARGET = 5 }; - enum CraneStatus : uint8 { + enum CraneStatus { NONE = 0, ACTIVATED = 1, DEACTIVATED = 2 @@ -47,8 +47,8 @@ public: CVector2D m_vecHookVelocity; CVehicle *m_pVehiclePickedUp; uint32 m_nTimeForNextCheck; - CraneStatus m_nCraneStatus; - CraneState m_nCraneState; + uint8 m_nCraneStatus; + uint8 m_nCraneState; uint8 m_nVehiclesCollected; bool m_bIsCrusher; bool m_bIsMilitaryCrane; -- cgit v1.2.3 From afdf8c25a05f280f524d946384cf74d69aa16e8a Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 7 Dec 2020 00:56:12 +0100 Subject: int8 enums fixed --- src/audio/AudioLogic.cpp | 2 +- src/control/Garages.cpp | 8 ++++---- src/control/Garages.h | 20 ++++++++++---------- src/control/Script3.cpp | 6 +++--- src/control/Script4.cpp | 2 +- src/peds/Ped.h | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index af67b561..ca395136 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -8121,7 +8121,7 @@ cAudioManager::ProcessGarages() const float SOUND_INTENSITY = 80.0f; CEntity *entity; - eGarageState state; + uint8 state; uint32 sampleIndex; uint8 j; float distSquared; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 33137c69..ff11600b 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -202,7 +202,7 @@ void CGarages::Update(void) aGarages[GarageToBeTidied].TidyUpGarage(); } -int16 CGarages::AddOne(CVector p1, CVector p2, eGarageType type, int32 targetId) +int16 CGarages::AddOne(CVector p1, CVector p2, uint8 type, int32 targetId) { if (NumGarages >= NUM_GARAGES) { assert(0); @@ -285,7 +285,7 @@ int16 CGarages::AddOne(CVector p1, CVector p2, eGarageType type, int32 targetId) return NumGarages++; } -void CGarages::ChangeGarageType(int16 garage, eGarageType type, int32 mi) +void CGarages::ChangeGarageType(int16 garage, uint8 type, int32 mi) { CGarage* pGarage = &aGarages[garage]; pGarage->m_eGarageType = type; @@ -2172,7 +2172,7 @@ void CGarages::CloseHideOutGaragesBeforeSave() } } -int32 CGarages::CountCarsInHideoutGarage(eGarageType type) +int32 CGarages::CountCarsInHideoutGarage(uint8 type) { int32 total = 0; for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) { @@ -2192,7 +2192,7 @@ int32 CGarages::CountCarsInHideoutGarage(eGarageType type) return total; } -int32 CGarages::FindMaxNumStoredCarsForGarage(eGarageType type) +int32 CGarages::FindMaxNumStoredCarsForGarage(uint8 type) { switch (type) { case GARAGE_HIDEOUT_ONE: diff --git a/src/control/Garages.h b/src/control/Garages.h index 41b2afb7..79cef36e 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -7,7 +7,7 @@ class CVehicle; class CCamera; -enum eGarageState : int8 +enum eGarageState { GS_FULLYCLOSED, GS_OPENED, @@ -18,7 +18,7 @@ enum eGarageState : int8 GS_AFTERDROPOFF, }; -enum eGarageType : int8 +enum eGarageType { GARAGE_NONE, GARAGE_MISSION, @@ -81,8 +81,8 @@ VALIDATE_SIZE(CStoredCar, 0x28); class CGarage { - eGarageType m_eGarageType; - eGarageState m_eGarageState; + uint8 m_eGarageType; + uint8 m_eGarageState; bool field_2; // unused bool m_bClosingWithoutTargetCar; bool m_bDeactivated; @@ -207,8 +207,8 @@ public: #endif static void Update(void); - static int16 AddOne(CVector pos1, CVector pos2, eGarageType type, int32 targetId); - static void ChangeGarageType(int16, eGarageType, int32); + static int16 AddOne(CVector pos1, CVector pos2, uint8 type, int32 targetId); + static void ChangeGarageType(int16, uint8, int32); static void PrintMessages(void); static void TriggerMessage(const char* text, int16, uint16 time, int16); static void SetTargetCarForMissonGarage(int16, CVehicle*); @@ -244,10 +244,10 @@ private: static bool IsCarSprayable(CVehicle*); static float FindDoorHeightForMI(int32); static void CloseHideOutGaragesBeforeSave(void); - static int32 CountCarsInHideoutGarage(eGarageType); - static int32 FindMaxNumStoredCarsForGarage(eGarageType); - static int32 GetBombTypeForGarageType(eGarageType type) { return type - GARAGE_BOMBSHOP1 + 1; } - static int32 GetCarsCollectedIndexForGarageType(eGarageType type) { return type - GARAGE_COLLECTCARS_1; } + static int32 CountCarsInHideoutGarage(uint8); + static int32 FindMaxNumStoredCarsForGarage(uint8); + static int32 GetBombTypeForGarageType(uint8 type) { return type - GARAGE_BOMBSHOP1 + 1; } + static int32 GetCarsCollectedIndexForGarageType(uint8 type) { return type - GARAGE_COLLECTCARS_1; } friend class cAudioManager; friend class CGarage; diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp index 23ab453c..38bcb2ec 100644 --- a/src/control/Script3.cpp +++ b/src/control/Script3.cpp @@ -291,7 +291,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) infZ = *(float*)&ScriptParams[5]; supZ = *(float*)&ScriptParams[2]; } - ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), (eGarageType)ScriptParams[6], 0); + ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), ScriptParams[6], 0); StoreParameters(&m_nIp, 1); return 0; } @@ -316,7 +316,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) infZ = *(float*)&ScriptParams[5]; supZ = *(float*)&ScriptParams[2]; } - ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), (eGarageType)ScriptParams[6], ScriptParams[7]); + ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), ScriptParams[6], ScriptParams[7]); StoreParameters(&m_nIp, 1); return 0; } @@ -1826,7 +1826,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) } case COMMAND_CHANGE_GARAGE_TYPE: CollectParameters(&m_nIp, 2); - CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], 0); + CGarages::ChangeGarageType(ScriptParams[0], ScriptParams[1], 0); return 0; case COMMAND_ACTIVATE_CRUSHER_CRANE: { diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp index feef70bc..399765f0 100644 --- a/src/control/Script4.cpp +++ b/src/control/Script4.cpp @@ -1459,7 +1459,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL: { CollectParameters(&m_nIp, 3); - CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], ScriptParams[2]); + CGarages::ChangeGarageType(ScriptParams[0], ScriptParams[1], ScriptParams[2]); return 0; } case COMMAND_FIND_DRUG_PLANE_COORDINATES: diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 7a9f4a9e..015ad677 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -43,7 +43,7 @@ enum eFormation FORMATION_FRONT }; -enum FightState : int8 { +enum FightState { FIGHTSTATE_MOVE_FINISHED = -2, FIGHTSTATE_JUST_ATTACKED, FIGHTSTATE_NO_MOVE, @@ -484,7 +484,7 @@ public: CVector m_vecHitLastPos; uint32 m_curFightMove; uint8 m_fightButtonPressure; - FightState m_fightState; + int8 m_fightState; bool m_takeAStepAfterAttack; CFire *m_pFire; CEntity *m_pLookTarget; -- cgit v1.2.3 From b5ffea5c6e824049194c495495af9ec66c0b208d Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 7 Dec 2020 00:57:34 +0100 Subject: uint16 enums fixed --- src/audio/soundlist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/audio/soundlist.h b/src/audio/soundlist.h index 225ed56e..7c3b30a7 100644 --- a/src/audio/soundlist.h +++ b/src/audio/soundlist.h @@ -1,6 +1,6 @@ #pragma once -enum eSound : uint16 +enum eSound { SOUND_CAR_DOOR_CLOSE_BONNET = 0, SOUND_CAR_DOOR_CLOSE_BUMPER, @@ -173,7 +173,7 @@ enum eSound : uint16 }; -enum eScriptSounds : uint16 { +enum eScriptSounds { SCRIPT_SOUND_0 = 0, SCRIPT_SOUND_1, SCRIPT_SOUND_2, -- cgit v1.2.3 From 9e2ac26a1dd84f0701bbadea2d14e4cd6547d9f8 Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 7 Dec 2020 01:04:23 +0100 Subject: uint32 enums fixed --- src/audio/AudioSamples.h | 2 +- src/peds/Ped.h | 2 +- src/vehicles/HandlingMgr.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/audio/AudioSamples.h b/src/audio/AudioSamples.h index e2721888..df64521c 100644 --- a/src/audio/AudioSamples.h +++ b/src/audio/AudioSamples.h @@ -2,7 +2,7 @@ #include "common.h" -enum eSfxSample : uint32 +enum eSfxSample { SFX_CAR_HORN_JEEP = 0, SFX_CAR_HORN_BMW328, diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 015ad677..f8e619d7 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -153,7 +153,7 @@ enum eWaitState { WAITSTATE_FINISH_FLEE }; -enum eObjective : uint32 { +enum eObjective { OBJECTIVE_NONE, OBJECTIVE_WAIT_ON_FOOT, OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE, diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index 4d3b8389..23bd9681 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -65,7 +65,7 @@ enum tVehicleType NUMHANDLINGS }; -enum tField : uint32 // most likely a handling field enum, never used so :shrug: +enum tField // most likely a handling field enum, never used so :shrug: { }; -- cgit v1.2.3 From 5e9a433b7912a597ba0287b4d48332b29773594e Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 7 Dec 2020 01:05:45 +0100 Subject: int32 enum fixed --- src/audio/audio_enums.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/audio/audio_enums.h b/src/audio/audio_enums.h index 20760859..8c6d35aa 100644 --- a/src/audio/audio_enums.h +++ b/src/audio/audio_enums.h @@ -235,7 +235,7 @@ enum AudioEntityHandle { AEHANDLE_ERROR_BADAUDIOTYPE = -1, }; -enum eAudioType : int32 +enum eAudioType { AUDIOTYPE_PHYSICAL = 0, AUDIOTYPE_EXPLOSION, -- cgit v1.2.3 From 7e11f639aa468eaf24e51fa04a59fbe966119892 Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 7 Dec 2020 01:43:03 +0100 Subject: don't cast script param to uint8 --- src/control/Script4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp index 399765f0..3629bb4b 100644 --- a/src/control/Script4.cpp +++ b/src/control/Script4.cpp @@ -1436,7 +1436,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(pVehicle); - pVehicle->SetStatus((uint8)ScriptParams[1]); + pVehicle->SetStatus(ScriptParams[1]); return 0; } case COMMAND_IS_CHAR_MALE: -- cgit v1.2.3 From 5a1ea7bcf579b616e349ed651c67e0f988592cbd Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Sun, 6 Dec 2020 23:22:02 +0100 Subject: audio: define openal extensions in re3 owned namespace --- src/audio/oal/oal_utils.cpp | 11 +++++++++++ src/audio/oal/oal_utils.h | 7 +++++++ 2 files changed, 18 insertions(+) (limited to 'src') diff --git a/src/audio/oal/oal_utils.cpp b/src/audio/oal/oal_utils.cpp index e16de572..e4cb0b77 100644 --- a/src/audio/oal/oal_utils.cpp +++ b/src/audio/oal/oal_utils.cpp @@ -3,6 +3,14 @@ #ifdef AUDIO_OAL +/* + * When linking to a static openal-soft library, + * the extension function inside the openal library conflict with the variables here. + * Therefore declare these re3 owned symbols in a private namespace. + */ + +namespace re3_openal { + LPALGENEFFECTS alGenEffects; LPALDELETEEFFECTS alDeleteEffects; LPALISEFFECT alIsEffect; @@ -37,6 +45,9 @@ LPALGETFILTERIV alGetFilteriv; LPALGETFILTERF alGetFilterf; LPALGETFILTERFV alGetFilterfv; +} + +using namespace re3_openal; void EFXInit() { diff --git a/src/audio/oal/oal_utils.h b/src/audio/oal/oal_utils.h index b89ccf36..f0fa090a 100644 --- a/src/audio/oal/oal_utils.h +++ b/src/audio/oal/oal_utils.h @@ -11,6 +11,8 @@ void EFX_Set(ALuint effect, const EAXLISTENERPROPERTIES *props); void EAX3_SetReverbMix(ALuint filter, float mix); void SetEffectsLevel(ALuint uiFilter, float level); +namespace re3_openal { + extern LPALGENEFFECTS alGenEffects; extern LPALDELETEEFFECTS alDeleteEffects; extern LPALISEFFECT alIsEffect; @@ -44,4 +46,9 @@ extern LPALGETFILTERI alGetFilteri; extern LPALGETFILTERIV alGetFilteriv; extern LPALGETFILTERF alGetFilterf; extern LPALGETFILTERFV alGetFilterfv; + +} + +using namespace re3_openal; + #endif -- cgit v1.2.3 From 84cc31fea3b8205a03b930218f7190303e1fab39 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 8 Dec 2020 02:27:35 +0200 Subject: Fix wrong define --- src/control/Script.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/Script.h b/src/control/Script.h index 12f3233f..7fc18727 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -396,7 +396,7 @@ private: friend class CRunningScript; friend class CHud; friend void CMissionCleanup::Process(); -#ifdef FIX_BUGS +#ifdef MISSION_REPLAY friend void RetryMission(int, int); #endif -- cgit v1.2.3 From 8d3864a4e5830785bf7721cce5896fa7dc7e96d5 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 8 Dec 2020 02:56:20 +0200 Subject: Fix CRecordDataForChase::ShouldThisPadBeLeftAlone --- src/control/Record.cpp | 10 ++++++---- src/control/Record.h | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 8a23ffde..7f636ec2 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -391,15 +391,17 @@ void CRecordDataForChase::ProcessControlCars(void) } } -#if (defined(GTA_PS2) || defined(FIX_BUGS)) bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad) { // may be wrong - if (Status == STATE_NONE || Status == STATE_PLAYBACK) + if (Status == STATE_PLAYBACK_INIT) // this is useless but ps2 def checks if it's STATE_PLAYBACK_INIT return false; - return pad != 0; + + if (Status == STATE_RECORD) + return pad != 0; + + return false; } -#endif void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2) { diff --git a/src/control/Record.h b/src/control/Record.h index 8b55b1f4..6a94c408 100644 --- a/src/control/Record.h +++ b/src/control/Record.h @@ -57,9 +57,7 @@ public: static void RestoreInfoForMatrix(CMatrix&, CCarStateEachFrame*); static void RestoreInfoForCar(CAutomobile*, CCarStateEachFrame*, bool); static void ProcessControlCars(void); -#if (defined(GTA_PS2) || defined(FIX_BUGS)) static bool ShouldThisPadBeLeftAlone(uint8 pad); -#endif static void GiveUsACar(int32, CVector, float, CAutomobile**, uint8, uint8); static void StartChaseScene(float); static void CleanUpChaseScene(void); -- cgit v1.2.3 From b13b26b5fb34ebff9f36cbe8e5e4527bb0435c34 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 8 Dec 2020 03:33:56 +0200 Subject: GenerateOneRandomCar cleanup --- src/control/CarCtrl.cpp | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src') diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 627d7bad..520efe75 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -408,11 +408,6 @@ CCarCtrl::GenerateOneRandomCar() float directionNextLinkX; float directionNextLinkY; if (positionBetweenNodes < 0.5f) { - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX(); - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY(); - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX(); - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY(); - pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; positionOnCurrentLinkIncludingLane = CVector( @@ -442,11 +437,6 @@ CCarCtrl::GenerateOneRandomCar() pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - (uint32)((positionBetweenNodes - 0.5f) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX(); - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY(); - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX(); - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY(); - pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; positionOnCurrentLinkIncludingLane = CVector( -- cgit v1.2.3 From 778d1381bb2dff5371782dbb773770f4adc17a35 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 8 Dec 2020 07:50:29 +0200 Subject: Add NUM_LEVELS --- src/core/Game.h | 3 ++- src/core/World.cpp | 8 ++++---- src/core/World.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/Game.h b/src/core/Game.h index 46e8fc68..b55793af 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -5,7 +5,8 @@ enum eLevelName { LEVEL_GENERIC = 0, LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, - LEVEL_SUBURBAN + LEVEL_SUBURBAN, + NUM_LEVELS }; class CGame diff --git a/src/core/World.cpp b/src/core/World.cpp index 0bc564ff..1c988894 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -33,7 +33,7 @@ CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; -CPtrList CWorld::ms_bigBuildingsList[4]; +CPtrList CWorld::ms_bigBuildingsList[NUM_LEVELS]; CPtrList CWorld::ms_listMovingEntityPtrs; CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X]; uint16 CWorld::ms_nCurrentScanCode; @@ -1745,13 +1745,13 @@ CWorld::ShutDown(void) pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); #endif } - for(int32 i = 0; i < 4; i++) { - for(CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) { + for(int32 i = 0; i < NUM_LEVELS; i++) { + for(CPtrNode *pNode = ms_bigBuildingsList[i].first; pNode; pNode = pNode->next) { CEntity *pEntity = (CEntity *)pNode->item; // Maybe remove from world here? delete pEntity; } - GetBigBuildingList((eLevelName)i).Flush(); + ms_bigBuildingsList[i].Flush(); } for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); diff --git a/src/core/World.h b/src/core/World.h index 9465a914..197f3cee 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -55,7 +55,7 @@ struct CStoredCollPoly; class CWorld { - static CPtrList ms_bigBuildingsList[4]; + static CPtrList ms_bigBuildingsList[NUM_LEVELS]; static CPtrList ms_listMovingEntityPtrs; static CSector ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X]; static uint16 ms_nCurrentScanCode; -- cgit v1.2.3 From a35c96c5ec3f785bac87d34f3cfeaf60caa0f620 Mon Sep 17 00:00:00 2001 From: "Walied K. Yassen" Date: Tue, 8 Dec 2020 21:19:34 +0200 Subject: Fix DeleteAllTempObjectsInArea and bunch of random gen ranges --- src/objects/Object.cpp | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index d91a0f13..466cecac 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -209,15 +209,15 @@ CObject::ObjectDamage(float amount) SetTurnSpeed(0.0f, 0.0f, 0.0f); const RwRGBA color = { 96, 48, 0, 255 }; for (int32 i = 0; i < 25; i++) { - CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ); + CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(0.1f, 0.25f) + fDirectionZ); ++nFrameGen; int32 currentFrame = nFrameGen & 3; float fRandom = CGeneral::GetRandomNumberInRange(0.01f, 1.0f); RwRGBA randomColor = { uint8(color.red * fRandom), uint8(color.green * fRandom) , color.blue, color.alpha }; - float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f); - int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); + float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f); + int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0); } PlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_2, vecPos); @@ -232,15 +232,15 @@ CObject::ObjectDamage(float amount) SetTurnSpeed(0.0f, 0.0f, 0.0f); const RwRGBA color = { 128, 128, 128, 255 }; for (int32 i = 0; i < 45; i++) { - CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ); + CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(0.1f, 0.25f) + fDirectionZ); ++nFrameGen; int32 currentFrame = nFrameGen & 3; - float fRandom = CGeneral::GetRandomNumberInRange(0.5f, 0.5f); + float fRandom = CGeneral::GetRandomNumberInRange(0.5f, 1.0f); RwRGBA randomColor = { uint8(color.red * fRandom), uint8(color.green * fRandom), uint8(color.blue * fRandom), color.alpha }; - float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f); - int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); + float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f); + int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0); } PlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_1, vecPos); @@ -256,16 +256,16 @@ CObject::ObjectDamage(float amount) const RwRGBA color1 = { 200, 0, 0, 255 }; const RwRGBA color2 = { 200, 200, 200, 255 }; for (int32 i = 0; i < 10; i++) { - CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ); + CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(0.1f, 0.25f) + fDirectionZ); ++nFrameGen; int32 currentFrame = nFrameGen & 3; RwRGBA color = color2; if (nFrameGen & 1) color = color1; - float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f); - int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); + float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f); + int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0); } PlayOneShotScriptObject(SCRIPT_SOUND_TIRE_COLLISION, vecPos); @@ -281,16 +281,16 @@ CObject::ObjectDamage(float amount) const RwRGBA color1 = { 200, 0, 0, 255 }; const RwRGBA color2 = { 200, 200, 200, 255 }; for (int32 i = 0; i < 32; i++) { - CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(-0.35f, 0.7f), - CGeneral::GetRandomNumberInRange(0.1f, 0.15f) + fDirectionZ); + CVector vecDir(CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(-0.35f, 0.35f), + CGeneral::GetRandomNumberInRange(0.1f, 0.25f) + fDirectionZ); ++nFrameGen; int32 currentFrame = nFrameGen & 3; RwRGBA color = color2; if (nFrameGen & 1) color = color1; - float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f); - int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); + float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f); + int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0); } PlayOneShotScriptObject(SCRIPT_SOUND_METAL_COLLISION, vecPos); @@ -389,7 +389,8 @@ CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius) CObjectPool *objectPool = CPools::GetObjectPool(); for (int32 i = 0; i < objectPool->GetSize(); i++) { CObject *pObject = objectPool->GetSlot(i); - if (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT && fRadius * fRadius > pObject->GetPosition().MagnitudeSqr()) { + CVector dist = point - pObject->GetPosition(); + if (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT && dist.MagnitudeSqr() < fRadius * fRadius) { CWorld::Remove(pObject); delete pObject; } -- cgit v1.2.3 From fc6f07345e8db32ec5e4f8abddb87d2c8263c96f Mon Sep 17 00:00:00 2001 From: erorcun Date: Tue, 8 Dec 2020 23:33:51 +0300 Subject: Red delete menu background --- src/core/Frontend.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 5597b358..c5eb70fe 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -42,6 +42,7 @@ #define MAX_VISIBLE_LIST_ROW 30 #define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result #define SCROLLABLE_PAGES +#define RED_DELETE_BACKGROUND #ifdef SCROLLABLE_STATS_PAGE #define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS) @@ -2930,6 +2931,45 @@ CMenuManager::DrawFrontEndNormal() } } +#ifdef RED_DELETE_BACKGROUND + if (m_nCurrScreen == MENUPAGE_CHOOSE_DELETE_SLOT || m_nCurrScreen == MENUPAGE_DELETE_SLOT_CONFIRM) { + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(18.0f), MENU_Y(8.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(20.0f), MENU_Y(8.0f), + SCREEN_STRETCH_X(12.0f), MENU_Y(11.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(14.0f), MENU_Y(11.0f), + CRGBA(150, 0, 0, 140)); + + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(12.0f), MENU_Y(11.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(14.0f), MENU_Y(11.0f), + SCREEN_STRETCH_X(10.0f), MENU_Y(16.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(12.0f), MENU_Y(16.0f), + CRGBA(150, 0, 0, 140)); + + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(10.0f), MENU_Y(16.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(12.0f), MENU_Y(16.0f), + SCREEN_STRETCH_X(10.0f), SCREEN_SCALE_Y(431.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(12.0f), SCREEN_SCALE_Y(431.0f), + CRGBA(150, 0, 0, 140)); + + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(10.0f), SCREEN_SCALE_Y(431.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(12.0f), SCREEN_SCALE_Y(431.0f), + SCREEN_STRETCH_X(12.0f), SCREEN_SCALE_Y(435.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(14.0f), SCREEN_SCALE_Y(435.0f), + CRGBA(150, 0, 0, 140)); + + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(12.0f), SCREEN_SCALE_Y(435.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(14.0f), SCREEN_SCALE_Y(435.0f), + SCREEN_STRETCH_X(18.0f), SCREEN_SCALE_Y(438.0f), + SCREEN_WIDTH - SCREEN_STRETCH_X(20.0f), SCREEN_SCALE_Y(438.0f), + CRGBA(150, 0, 0, 140)); + + // yellow bar + CSprite2d::DrawRect(CRect(MENU_X(13.0f), SCREEN_STRETCH_FROM_BOTTOM(96.0f), + SCREEN_STRETCH_FROM_RIGHT(11.0f), SCREEN_STRETCH_FROM_BOTTOM(59.0f)), + CRGBA(235, 170, 50, 255)); + } +#endif + // GTA LOGO RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); -- cgit v1.2.3 From f6cc178a502b276128d52ed976e8dbe53875da8a Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 8 Dec 2020 23:15:59 +0100 Subject: fix CObject::DeleteAllTempObjectsInArea --- src/objects/Object.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index 466cecac..411e245a 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -389,8 +389,7 @@ CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius) CObjectPool *objectPool = CPools::GetObjectPool(); for (int32 i = 0; i < objectPool->GetSize(); i++) { CObject *pObject = objectPool->GetSlot(i); - CVector dist = point - pObject->GetPosition(); - if (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT && dist.MagnitudeSqr() < fRadius * fRadius) { + if (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT && (point - pObject->GetPosition()).MagnitudeSqr() < SQR(fRadius)) { CWorld::Remove(pObject); delete pObject; } -- cgit v1.2.3 From 122c7aa40dda35107312fe91e0c61852c3056ddc Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 9 Dec 2020 03:41:45 +0300 Subject: Use SDL gamepad mapping in environment by @ZLau92, implement @Sergeanur 's idea to use PPSSPP's DB if available, disable DEV() messages by default --- src/core/common.h | 8 +- src/extras/gamecontrollerdb.txt | 199 ++++++++++++++++++++++++++++++++++++++++ src/skel/glfw/glfw.cpp | 33 ++++++- 3 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 src/extras/gamecontrollerdb.txt (limited to 'src') diff --git a/src/core/common.h b/src/core/common.h index 48b20884..d5775e08 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -248,8 +248,14 @@ void re3_usererror(const char *format, ...); #define DEBUGBREAK() __debugbreak(); -#define debug(f, ...) re3_debug("[DBG]: " f, ## __VA_ARGS__) +// Switch to enable development messages. +#if 1 +#define DEV(f, ...) +#else #define DEV(f, ...) re3_debug("[DEV]: " f, ## __VA_ARGS__) +#endif + +#define debug(f, ...) re3_debug("[DBG]: " f, ## __VA_ARGS__) #define TRACE(f, ...) re3_trace(__FILE__, __LINE__, __FUNCTION__, f, ## __VA_ARGS__) #define Error(f, ...) re3_debug("[ERROR]: " f, ## __VA_ARGS__) #define USERERROR(f, ...) re3_usererror(f, ## __VA_ARGS__) diff --git a/src/extras/gamecontrollerdb.txt b/src/extras/gamecontrollerdb.txt new file mode 100644 index 00000000..fcefb88a --- /dev/null +++ b/src/extras/gamecontrollerdb.txt @@ -0,0 +1,199 @@ +# Windows - DINPUT +8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, +6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13, +4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows, +00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows, +00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows, +28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7, +ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9, +8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5, +79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows, +4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows, +d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, +a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows, +4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, +83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows, +10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, +49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows, +4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows, +0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, +79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, +79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, +2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, +300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows, +10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows, +63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8, +02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8, +ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11, +341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows, +c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1, +100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows, +4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows, +4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows, + +# OS X +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X, +4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X, +8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, +4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X, +83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X, +5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4, +050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X, +79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X, +2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, +351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X, +b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X, +10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X, +d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7, +0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4, +5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4, +79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X, +4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X, +5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4, +81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X, +bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X, +03000000632500002305000000010000,Redragon Saturn,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, + +# Linux +050000004c0500006802000000000000,Sony PLAYSTATION(R)3 Controller,platform:Linux,a:b14,b:b13,x:b15,y:b12,back:b0,guide:b16,start:b3,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpdown:b6,dpleft:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a12,righttrigger:a13, +03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux, +030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux, +030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux, +03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux, +030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5, +030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux, +030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux, +030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, +030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7, +0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux, +0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux, +030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1, +030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, +03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5, +030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux, +03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux, +050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux, +05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux, +03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13, +05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2, +05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2, +030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux, +03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1, +050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16, +030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, +030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1, +030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7 +03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +03000000f0250000c283000010010000,Goodbetterbest Ltd PC USB Controller,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7 +0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3, +03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, +030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux, +03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux, +03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux, +03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux, +030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3, +030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux, +030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7, +05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1, +03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1, +030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5, +030000000d0f00006700000001010000,HORIPAD ONE,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, +03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5, +03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7, +03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5, +05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux, +030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +06000000adde0000efbe000002010000,Hidromancer Game Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,platform:Linux,a:b12,b:b10,x:b13,y:b11,back:b4,start:b5,leftstick:b14,rightstick:b15,leftshoulder:b9,rightshoulder:b8,dpup:b0,dpdown:b2,dpleft:b3,dpright:b1,leftx:a1,lefty:a0,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1, +03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1, +03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5, +03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5, +030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux, +030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux, +03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux, +050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, +030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, +05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5, +030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, +030000004c050000cc09000011810000,Sony Interactive Entertainment Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, +050000004c050000cc09000000810000,Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000004c0500006802000011810000,Sony PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, +050000004c0500006802000000810000,PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5, +05000000c82d00002038000000010000,8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, +030000005e040000a102000000010000,Xbox 360 Wireless Receiver,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpdown:b14,dpleft:b11,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5, +050000004c050000cc09000001000000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, +03000000bc2000006412000011010000,BETOP CONTROLLER,a:b2,b:b1,y:b0,x:b3,start:b9,guide:b30,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, +05000000c82d00000161000000010000,8Bitdo SN30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, +03000000380700008532000010010000,MadCatz Madcatz Fightpad,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:b5,righttrigger:b7, +030000000d0f0000ee00000011010000,HORI CO.,LTD. HORIPAD mini4,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +030000000d0f0000c100000011010000,HORI CO.,LTD. HORIPAD S,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +03000000ad1b000003f5000033050000,Hori Fighting Stick VX,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,-leftx:h0.8,+leftx:h0.2,-lefty:h0.1,+lefty:h0.4,lefttrigger:b6,righttrigger:b7, +03000000c82d00000260000011010000,8Bitdo SF30 Pro 8BitDo SN30 Pro+,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, +060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:b14,dpdown:b15,dpleft:b16,dpright:b17,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8, diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 7354c90a..3ebff16a 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -70,9 +70,6 @@ static psGlobalType PsGlobal; #define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var) -#undef MAKEPOINTS -#define MAKEPOINTS(l) (*((POINTS /*FAR*/ *)&(l))) - size_t _dwMemAvailPhys; RwUInt32 gGameState; @@ -870,6 +867,36 @@ void _InputInitialiseJoys() PSGLOBAL(joy1id) = -1; PSGLOBAL(joy2id) = -1; + // Load our gamepad mappings. +#define SDL_GAMEPAD_DB_PATH "gamecontrollerdb.txt" + FILE *f = fopen(SDL_GAMEPAD_DB_PATH, "rb"); + if (f) { + fseek(f, 0, SEEK_END); + size_t fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + char *db = (char*)malloc(fsize + 1); + if (fread(db, 1, fsize, f) == fsize) { + db[fsize] = '\0'; + + if (glfwUpdateGamepadMappings(db) == GLFW_FALSE) + Error("glfwUpdateGamepadMappings didn't succeed, check " SDL_GAMEPAD_DB_PATH ".\n"); + } else + Error("fread on " SDL_GAMEPAD_DB_PATH " wasn't successful.\n"); + + free(db); + fclose(f); + } else + printf("You don't seem to have copied " SDL_GAMEPAD_DB_PATH " file from re3/gamefiles to GTA3 directory. Some gamepads may not be recognized.\n"); + +#undef SDL_GAMEPAD_DB_PATH + + // But always overwrite it with the one in SDL_GAMECONTROLLERCONFIG. + char const* EnvControlConfig = getenv("SDL_GAMECONTROLLERCONFIG"); + if (EnvControlConfig != nil) { + glfwUpdateGamepadMappings(EnvControlConfig); + } + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) { if (PSGLOBAL(joy1id) == -1) -- cgit v1.2.3 From 0dfa8336109c6f449664d83478bf1890d7df71a2 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 9 Dec 2020 03:55:30 +0300 Subject: Fix --- src/extras/gamecontrollerdb.txt | 199 ---------------------------------------- 1 file changed, 199 deletions(-) delete mode 100644 src/extras/gamecontrollerdb.txt (limited to 'src') diff --git a/src/extras/gamecontrollerdb.txt b/src/extras/gamecontrollerdb.txt deleted file mode 100644 index fcefb88a..00000000 --- a/src/extras/gamecontrollerdb.txt +++ /dev/null @@ -1,199 +0,0 @@ -# Windows - DINPUT -8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, -341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, -6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, -4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, -25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, -4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13, -4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows, -00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows, -00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows, -28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7, -ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9, -8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, -8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5, -79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows, -4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows, -d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, -a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows, -4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, -83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows, -10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, -49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows, -4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows, -0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, -79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, -79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, -2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows, -300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows, -10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows, -63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8, -02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8, -ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11, -341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows, -c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1, -100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows, -4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows, -4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows, - -# OS X -0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X, -4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X, -8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, -0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, -4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X, -83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X, -5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4, -050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X, -79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X, -2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, -351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X, -b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X, -10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X, -d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7, -0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4, -5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4, -79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X, -4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X, -5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4, -81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X, -bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X, -03000000632500002305000000010000,Redragon Saturn,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, - -# Linux -050000004c0500006802000000000000,Sony PLAYSTATION(R)3 Controller,platform:Linux,a:b14,b:b13,x:b15,y:b12,back:b0,guide:b16,start:b3,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpdown:b6,dpleft:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a12,righttrigger:a13, -03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, -0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux, -030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux, -030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux, -03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux, -030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux, -030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5, -030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, -030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, -030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, -030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux, -030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux, -030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, -030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7, -0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux, -0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux, -030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1, -030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, -03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5, -030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, -030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux, -03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, -050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux, -050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux, -05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux, -03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13, -05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2, -05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2, -030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux, -03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1, -050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16, -030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, -030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1, -030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7 -03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -03000000f0250000c283000010010000,Goodbetterbest Ltd PC USB Controller,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7 -0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3, -03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, -030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux, -03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux, -03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux, -03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux, -030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3, -030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux, -030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7, -05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1, -03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1, -030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5, -030000000d0f00006700000001010000,HORIPAD ONE,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, -03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5, -03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7, -03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5, -05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux, -030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, -06000000adde0000efbe000002010000,Hidromancer Game Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,platform:Linux,a:b12,b:b10,x:b13,y:b11,back:b4,start:b5,leftstick:b14,rightstick:b15,leftshoulder:b9,rightshoulder:b8,dpup:b0,dpdown:b2,dpleft:b3,dpright:b1,leftx:a1,lefty:a0,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1, -03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1, -03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5, -03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5, -030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux, -030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux, -03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux, -050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, -030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, -05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5, -030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, -030000004c050000cc09000011810000,Sony Interactive Entertainment Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, -050000004c050000cc09000000810000,Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, -030000004c0500006802000011810000,Sony PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, -050000004c0500006802000000810000,PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, -03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5, -05000000c82d00002038000000010000,8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, -030000005e040000a102000000010000,Xbox 360 Wireless Receiver,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpdown:b14,dpleft:b11,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5, -050000004c050000cc09000001000000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux, -03000000bc2000006412000011010000,BETOP CONTROLLER,a:b2,b:b1,y:b0,x:b3,start:b9,guide:b30,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, -05000000c82d00000161000000010000,8Bitdo SN30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, -03000000380700008532000010010000,MadCatz Madcatz Fightpad,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:b5,righttrigger:b7, -030000000d0f0000ee00000011010000,HORI CO.,LTD. HORIPAD mini4,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -030000000d0f0000c100000011010000,HORI CO.,LTD. HORIPAD S,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, -03000000ad1b000003f5000033050000,Hori Fighting Stick VX,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,-leftx:h0.8,+leftx:h0.2,-lefty:h0.1,+lefty:h0.4,lefttrigger:b6,righttrigger:b7, -03000000c82d00000260000011010000,8Bitdo SF30 Pro 8BitDo SN30 Pro+,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, -060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:b14,dpdown:b15,dpleft:b16,dpright:b17,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8, -- cgit v1.2.3 From e1044a79478a3e25bfc44e699eb1f419275e9a0f Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 9 Dec 2020 04:57:45 +0300 Subject: AnimViewer fixes, commentary from miami --- src/core/AnimViewer.cpp | 19 +++++++------- src/core/main.cpp | 26 ++++++++----------- src/skel/crossplatform.h | 3 --- src/skel/glfw/glfw.cpp | 66 ++++++++++++++++++++---------------------------- src/skel/skeleton.cpp | 5 ++-- src/skel/skeleton.h | 3 --- src/skel/win/win.cpp | 53 ++++++++++++++++---------------------- 7 files changed, 72 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp index b8354d93..a888d528 100644 --- a/src/core/AnimViewer.cpp +++ b/src/core/AnimViewer.cpp @@ -45,7 +45,7 @@ CEntity *CAnimViewer::pTarget = nil; void CAnimViewer::Render(void) { if (pTarget) { -// pTarget->GetPosition() = CVector(0.0f, 0.0f, 0.0f); +// pTarget->GetPosition() = CVector(0.0f, 0.0f, 0.0f); // Only on Mobile if (pTarget) { #ifdef FIX_BUGS #ifdef PED_SKIN @@ -61,7 +61,9 @@ CAnimViewer::Render(void) { void CAnimViewer::Initialise(void) { - LoadingScreen("Loading the ModelViewer", "", GetRandomSplashScreen()); + // we need messages, messages needs hud, hud needs this + CHud::m_Wants_To_Draw_Hud = false; + animTxdSlot = CTxdStore::AddTxdSlot("generic"); CTxdStore::Create(animTxdSlot); int hudSlot = CTxdStore::AddTxdSlot("hud"); @@ -75,9 +77,6 @@ CAnimViewer::Initialise(void) { TheCamera.SetRwCamera(Scene.camera); TheCamera.Cams[TheCamera.ActiveCam].Distance = 5.0f; - gbModelViewer = true; - CHud::m_Wants_To_Draw_Hud = false; - ThePaths.Init(); ThePaths.AllocatePathFindInfoMem(4500); CCollision::Init(); @@ -113,7 +112,7 @@ CAnimViewer::Initialise(void) { CTimeCycle::Initialise(); CCarCtrl::Init(); CPlayerPed *player = new CPlayerPed(); - player->SetPosition(0.0f, 0.0f, 0.0f); + player->SetPosition(0.0f, 0.0f, 0.0f); // This is 1000.f for all axes on Xbox, but 0.f on mobile? CWorld::Players[0].m_pPed = player; CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; @@ -222,8 +221,7 @@ CAnimViewer::Update(void) { static int modelId = 0; static int animId = 0; - // Please don't make this bool, static bool's are problematic on my side. - static int reloadIFP = 0; + static bool reloadIFP = false; AssocGroupId animGroup = ASSOCGRP_STD; int nextModelId = modelId; @@ -248,7 +246,7 @@ CAnimViewer::Update(void) CAnimManager::Initialise(); CAnimManager::LoadAnimFiles(); - reloadIFP = 0; + reloadIFP = false; } } else { animGroup = ASSOCGRP_STD; @@ -302,6 +300,7 @@ CAnimViewer::Update(void) pTarget->GetMatrix().GetPosition().z = 10.0f; #else pTarget->GetMatrix().GetPosition().z = 0.0f; + #endif if (modelInfo->GetModelType() == MITYPE_PED) { @@ -309,7 +308,7 @@ CAnimViewer::Update(void) // Triangle in mobile if (pad->GetSquareJustDown()) { - reloadIFP = 1; + reloadIFP = true; AsciiToUnicode("IFP reloaded", gUString); CMessages::AddMessage(gUString, 1000, 0); diff --git a/src/core/main.cpp b/src/core/main.cpp index 54821979..cc20047f 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -616,8 +616,10 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen) AsciiToUnicode(str1, tmpstr); CFont::PrintString(hpos, vpos, tmpstr); vpos += 22*yscale; - AsciiToUnicode(str2, tmpstr); - CFont::PrintString(hpos, vpos, tmpstr); + if (str2) { + AsciiToUnicode(str2, tmpstr); + CFont::PrintString(hpos, vpos, tmpstr); + } #endif } @@ -1513,15 +1515,6 @@ AppEventHandler(RsEvent event, void *param) return rsEVENTPROCESSED; } -#ifndef MASTER - case rsANIMVIEWER: - { - TheModelViewer(); - - return rsEVENTPROCESSED; - } -#endif - default: { return rsEVENTNOTPROCESSED; @@ -1536,8 +1529,11 @@ TheModelViewer(void) #if (defined(GTA_PS2) || defined(GTA_XBOX)) //TODO #else + // This is III Mobile code. III Xbox code run it like main function, which is impossible to implement on PC's state machine implementation. + // Also we want 2D things initialized in here to print animation ids etc., our additions for that marked with X + #ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); + CDraw::SetAspectRatio(CDraw::FindAspectRatio()); // X #endif CAnimViewer::Update(); CTimer::Update(); @@ -1547,12 +1543,12 @@ TheModelViewer(void) CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(), 255); - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); + CSprite2d::InitPerFrame(); // X + CFont::InitPerFrame(); // X DefinedState(); CVisibilityPlugins::InitAlphaEntityList(); CAnimViewer::Render(); - Render2dStuff(); + Render2dStuff(); // X DoRWStuffEndOfFrame(); #endif } diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 1635781b..d8807f2b 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -83,9 +83,6 @@ enum eGameState GS_FRONTEND, GS_INIT_PLAYING_GAME, GS_PLAYING_GAME, -#ifndef MASTER - GS_ANIMVIEWER, -#endif }; extern RwUInt32 gGameState; diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 3ebff16a..b7c4810e 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1257,17 +1257,11 @@ void resizeCB(GLFWwindow* window, int width, int height) { * memory things don't work. */ /* redraw window */ -#ifndef MASTER - if (RwInitialised && (gGameState == GS_PLAYING_GAME || gGameState == GS_ANIMVIEWER)) - { - RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void *)TRUE); - } -#else + if (RwInitialised && gGameState == GS_PLAYING_GAME) { RsEventHandler(rsIDLE, (void *)TRUE); } -#endif if (RwInitialised && height > 0 && width > 0) { RwRect r; @@ -1646,18 +1640,6 @@ main(int argc, char *argv[]) FrontEndMenuManager.DrawMemoryCardStartUpMenus(); } #endif - - if (TurnOnAnimViewer) - { -#ifndef MASTER - CAnimViewer::Initialise(); -#ifndef PS2_MENU - FrontEndMenuManager.m_bGameNotLoaded = false; -#endif - gGameState = GS_ANIMVIEWER; - TurnOnAnimViewer = false; -#endif - } initkeymap(); @@ -1677,6 +1659,18 @@ main(int argc, char *argv[]) * Enter the message processing loop... */ +#ifndef MASTER + if (gbModelViewer) { + // This is TheModelViewer in LCS, but not compiled on III Mobile. + LoadingScreen("Loading the ModelViewer", NULL, GetRandomSplashScreen()); + CAnimViewer::Initialise(); + CTimer::Update(); +#ifndef PS2_MENU + FrontEndMenuManager.m_bGameNotLoaded = false; +#endif + } +#endif + #ifdef PS2_MENU if (TheMemoryCard.m_bWantToLoad) LoadSplash(GetLevelSplashScreen(CGame::currLevel)); @@ -1691,7 +1685,13 @@ main(int argc, char *argv[]) #endif { glfwPollEvents(); - if( ForegroundApp ) +#ifndef MASTER + if (gbModelViewer) { + // This is TheModelViewerCore in LCS, but TheModelViewer on other state-machine III-VCs. + TheModelViewer(); + } else +#endif + if ( ForegroundApp ) { switch ( gGameState ) { @@ -1894,18 +1894,6 @@ main(int argc, char *argv[]) } break; } -#ifndef MASTER - case GS_ANIMVIEWER: - { - float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); - if (RwInitialised) - { - if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) - RsEventHandler(rsANIMVIEWER, (void*)TRUE); - } - break; - } -#endif } } else @@ -1977,12 +1965,13 @@ main(int argc, char *argv[]) } else { - if ( gGameState == GS_PLAYING_GAME ) - CGame::ShutDown(); #ifndef MASTER - else if ( gGameState == GS_ANIMVIEWER ) + if ( gbModelViewer ) CAnimViewer::Shutdown(); + else #endif + if ( gGameState == GS_PLAYING_GAME ) + CGame::ShutDown(); CTimer::Stop(); @@ -2004,12 +1993,13 @@ main(int argc, char *argv[]) } - if ( gGameState == GS_PLAYING_GAME ) - CGame::ShutDown(); #ifndef MASTER - else if ( gGameState == GS_ANIMVIEWER ) + if ( gbModelViewer ) CAnimViewer::Shutdown(); + else #endif + if ( gGameState == GS_PLAYING_GAME ) + CGame::ShutDown(); DMAudio.Terminate(); diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index 3166093e..98fc9843 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -10,14 +10,13 @@ #include "skeleton.h" #include "platform.h" +#include "main.h" #include "MemoryHeap.h" static RwBool DefaultVideoMode = TRUE; -bool TurnOnAnimViewer = false; - RsGlobalType RsGlobal; #ifdef _WIN32 @@ -162,7 +161,7 @@ rsPreInitCommandLine(RwChar *arg) #ifndef MASTER if (!strcmp(arg, RWSTRING("-animviewer"))) { - TurnOnAnimViewer = TRUE; + gbModelViewer = TRUE; return TRUE; } diff --git a/src/skel/skeleton.h b/src/skel/skeleton.h index 1c468179..380b6c05 100644 --- a/src/skel/skeleton.h +++ b/src/skel/skeleton.h @@ -79,11 +79,8 @@ enum RsEvent rsPADANALOGUERIGHTRESET, rsPREINITCOMMANDLINE, rsACTIVATE, - rsANIMVIEWER, }; -extern bool TurnOnAnimViewer; - typedef enum RsEvent RsEvent; typedef RsEventStatus (*RsInputEventHandler)(RsEvent event, void *param); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index c16ea2a1..388090fc 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1017,17 +1017,12 @@ MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) RECT rect; /* redraw window */ -#ifndef MASTER - if (RwInitialised && (gGameState == GS_PLAYING_GAME || gGameState == GS_ANIMVIEWER)) - { - RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void *)TRUE); - } -#else + if (RwInitialised && gGameState == GS_PLAYING_GAME) { RsEventHandler(rsIDLE, (void *)TRUE); } -#endif + /* Manually resize window */ rect.left = rect.top = 0; rect.bottom = newPos->bottom - newPos->top; @@ -2183,17 +2178,17 @@ WinMain(HINSTANCE instance, } #endif - if (TurnOnAnimViewer) - { #ifndef MASTER + if (gbModelViewer) { + // This is TheModelViewer in LCS, but not compiled on III Mobile. + LoadingScreen("Loading the ModelViewer", NULL, GetRandomSplashScreen()); CAnimViewer::Initialise(); + CTimer::Update(); #ifndef PS2_MENU FrontEndMenuManager.m_bGameNotLoaded = false; -#endif - gGameState = GS_ANIMVIEWER; - TurnOnAnimViewer = false; #endif } +#endif while ( TRUE ) { @@ -2238,6 +2233,12 @@ WinMain(HINSTANCE instance, DispatchMessage(&message); } } +#ifndef MASTER + else if (gbModelViewer) { + // This is TheModelViewerCore in LCS + TheModelViewer(); + } +#endif else if( ForegroundApp ) { switch ( gGameState ) @@ -2451,18 +2452,6 @@ WinMain(HINSTANCE instance, } break; } -#ifndef MASTER - case GS_ANIMVIEWER: - { - float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); - if (RwInitialised) - { - if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) - RsEventHandler(rsANIMVIEWER, (void*)TRUE); - } - break; - } -#endif } } else @@ -2534,13 +2523,14 @@ WinMain(HINSTANCE instance, } else { - if ( gGameState == GS_PLAYING_GAME ) - CGame::ShutDown(); #ifndef MASTER - else if ( gGameState == GS_ANIMVIEWER ) + if ( gbModelViewer ) CAnimViewer::Shutdown(); + else #endif - + if ( gGameState == GS_PLAYING_GAME ) + CGame::ShutDown(); + CTimer::Stop(); if ( FrontEndMenuManager.m_bFirstTime == true ) @@ -2561,12 +2551,13 @@ WinMain(HINSTANCE instance, } - if ( gGameState == GS_PLAYING_GAME ) - CGame::ShutDown(); #ifndef MASTER - else if ( gGameState == GS_ANIMVIEWER ) + if ( gbModelViewer ) CAnimViewer::Shutdown(); + else #endif + if ( gGameState == GS_PLAYING_GAME ) + CGame::ShutDown(); DMAudio.Terminate(); -- cgit v1.2.3 From 33e1f28239e715aba0abbf417bbcf57e61985d65 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 9 Dec 2020 06:09:45 +0300 Subject: Vehicle cam fixes - @ZLau92 's idea to remove 3rd person check on num 2/8. It was meaningless on III, probably not on VC tho. - @Nick007J pointed out that camera wasn't checking objects, which was something done by someone to prevent camera to collide with traffic lights. Instead I enabled object check again, and comparing the result if it's a traffic light after the test. --- src/core/Cam.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index b20e6db3..7cb7564a 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -5042,9 +5042,9 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float stickX = -(pad->GetCarGunLeftRight()); float stickY = pad->GetCarGunUpDown(); - // In SA this checks for m_bUseMouse3rdPerson so num2/num8 do not move camera when Keyboard & Mouse controls are used. - if (CCamera::m_bUseMouse3rdPerson) - stickY = 0.0f; + // In SA this is for not let num2/num8 move camera when Keyboard & Mouse controls are used. + // if (CCamera::m_bUseMouse3rdPerson) + // stickY = 0.0f; float xMovement = Abs(stickX) * (FOV / 80.0f * 5.f / 70.f) * stickX * 0.007f * 0.007f; float yMovement = Abs(stickY) * (FOV / 80.0f * 3.f / 70.f) * stickY * 0.007f * 0.007f; @@ -5238,11 +5238,14 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float timestepFactor = Pow(0.99f, CTimer::GetTimeStep()); dontCollideWithCars = (timestepFactor * dontCollideWithCars) + ((1.0f - timestepFactor) * car->m_vecMoveSpeed.Magnitude()); + // Our addition +#define IS_TRAFFIC_LIGHT(ent) (ent->IsObject() && (IsStreetLight(ent->GetModelIndex()) || ent->GetModelIndex() == MI_STREETLAMP1 || ent->GetModelIndex() == MI_STREETLAMP2)) + // Move cam if on collision CColPoint foundCol; CEntity* foundEnt; CWorld::pIgnoreEntity = CamTargetEntity; - if (CWorld::ProcessLineOfSight(TargetCoors, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, false, false, true, false)) { + if (CWorld::ProcessLineOfSight(TargetCoors, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, true, false, true, false) && !IS_TRAFFIC_LIGHT(foundEnt)) { float obstacleTargetDist = (TargetCoors - foundCol.point).Magnitude(); float obstacleCamDist = newDistance - obstacleTargetDist; if (!foundEnt->IsPed() || obstacleCamDist <= 1.0f) { @@ -5251,7 +5254,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, RwCameraSetNearClipPlane(Scene.camera, Max(0.05f, obstacleTargetDist - 0.3f)); } } else { - if (!CWorld::ProcessLineOfSight(foundCol.point, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, false, false, true, false)) { + if (!CWorld::ProcessLineOfSight(foundCol.point, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, true, false, true, false) || IS_TRAFFIC_LIGHT(foundEnt)) { float lessClip = obstacleCamDist - 0.35f; if (lessClip <= DEFAULT_NEAR) RwCameraSetNearClipPlane(Scene.camera, lessClip); @@ -5270,6 +5273,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, } } } + CWorld::pIgnoreEntity = nil; float nearClip = RwCameraGetNearClipPlane(Scene.camera); float radius = Tan(DEGTORAD(FOV * 0.5f)) * CDraw::GetAspectRatio() * 1.1f; @@ -5277,9 +5281,12 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, // If we're seeing blue hell due to camera intersects some surface, fix it. // SA and LCS have this unrolled. for (int i = 0; - i <= 5 && CWorld::TestSphereAgainstWorld((nearClip * Front) + Source, radius * nearClip, nil, true, true, false, true, false, false); + i <= 5 && (foundEnt = CWorld::TestSphereAgainstWorld((nearClip * Front) + Source, radius * nearClip, nil, true, true, false, true, false, false)); i++) { + if (IS_TRAFFIC_LIGHT(foundEnt)) + break; + CVector surfaceCamDist = gaTempSphereColPoints->point - Source; CVector frontButInvertedIfTouchesSurface = DotProduct(surfaceCamDist, Front) * Front; float newNearClip = (surfaceCamDist - frontButInvertedIfTouchesSurface).Magnitude() / radius; @@ -5297,6 +5304,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, nearClip = RwCameraGetNearClipPlane(Scene.camera); radius = Tan(DEGTORAD(FOV * 0.5f)) * CDraw::GetAspectRatio() * 1.1f; } +#undef IS_TRAFFIC_LIGHT } TheCamera.m_bCamDirectlyBehind = false; TheCamera.m_bCamDirectlyInFront = false; -- cgit v1.2.3 From 1caf5d087aeb84b1b21d5c0fc2863bec9975f93b Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 9 Dec 2020 15:39:14 +0300 Subject: Sync Stats page style with miami - and a little veh. cam. fix --- src/core/Cam.cpp | 2 +- src/core/Frontend.cpp | 241 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 147 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 7cb7564a..ba7e5d15 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -5239,7 +5239,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, dontCollideWithCars = (timestepFactor * dontCollideWithCars) + ((1.0f - timestepFactor) * car->m_vecMoveSpeed.Magnitude()); // Our addition -#define IS_TRAFFIC_LIGHT(ent) (ent->IsObject() && (IsStreetLight(ent->GetModelIndex()) || ent->GetModelIndex() == MI_STREETLAMP1 || ent->GetModelIndex() == MI_STREETLAMP2)) +#define IS_TRAFFIC_LIGHT(ent) (ent->IsObject() && (IsStreetLight(ent->GetModelIndex()))) // Move cam if on collision CColPoint foundCol; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index c5eb70fe..118fb8d6 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -132,7 +132,7 @@ const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color #define MILES_IN_METER 0.000621371192f #define FEET_IN_METER 3.28084f #else -#define MILES_IN_METER 0.00059880241f +#define MILES_IN_METER (1 / 1670.f) #define FEET_IN_METER 3.33f #endif @@ -6101,108 +6101,157 @@ CMenuManager::PrintMap(void) int CMenuManager::ConstructStatLine(int rowIdx) { -#define STAT_LINE(str, left, isFloat, right) \ +#define int_STAT_IS_FLOAT false +#define float_STAT_IS_FLOAT true +#define STAT_LINE_1(varType, left, right1) \ do { \ if(counter == rowIdx){ \ - BuildStatLine(str, left, isFloat, right); \ + varType a = right1; \ + BuildStatLine(left, &a, varType##_STAT_IS_FLOAT, nil); \ return 0; \ } counter++; \ } while(0) - int counter = 0, nTemp; +#define STAT_LINE_2(varType, left, right1, right2) \ + do { \ + if(counter == rowIdx){ \ + varType a = right1; \ + varType b = right2; \ + BuildStatLine(left, &a, varType##_STAT_IS_FLOAT, &b); \ + return 0; \ + } counter++; \ + } while(0) + +#define TEXT_ON_LEFT_GXT(name) \ + do { \ + if(counter == rowIdx){ \ + BuildStatLine(name, nil, false, nil); \ + return 0; \ + } counter++; \ + } while(0) + +#define TEXT_ON_RIGHT(text) \ + do { \ + if(counter == rowIdx){ \ + gUString[0] = '\0'; \ + UnicodeStrcpy(gUString2, text); \ + return 0; \ + } counter++; \ + } while(0) - STAT_LINE("PL_STAT", nil, false, nil); + // Like TEXT_ON_LEFT_GXT, but counter wasn't initialized yet I think + if (rowIdx == 0) { + BuildStatLine("PL_STAT", nil, false, nil); + return 0; + } int percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1)); percentCompleted = Min(percentCompleted, 100); - STAT_LINE("PER_COM", &percentCompleted, false, nil); - STAT_LINE("NMISON", &CStats::MissionsGiven, false, nil); - STAT_LINE("FEST_MP", &CStats::MissionsPassed, false, &CStats::TotalNumberMissions); - if (CGame::nastyGame) { - STAT_LINE("FEST_RP", &CStats::NumberKillFrenziesPassed, false, &CStats::TotalNumberKillFrenzies); + switch (rowIdx) { + // 0 is the heading text above + case 1: { + BuildStatLine("PER_COM", &percentCompleted, false, nil); + return 0; + } + case 2: { + BuildStatLine("NMISON", &CStats::MissionsGiven, false, nil); + return 0; + } + case 3: { + BuildStatLine("FEST_MP", &CStats::MissionsPassed, false, &CStats::TotalNumberMissions); + return 0; + } } + int counter = 4; + + if (CGame::nastyGame) + STAT_LINE_2(int, "FEST_RP", CStats::NumberKillFrenziesPassed, CStats::TotalNumberKillFrenzies); CPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus]; + + // Hidden packages shouldn't be shown with percent +#ifdef FIX_BUGS + STAT_LINE_2(int, "PERPIC", player.m_nCollectedPackages, player.m_nTotalPackages); +#else float packagesPercent = 0.0f; if (player.m_nTotalPackages != 0) packagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages; - int nPackagesPercent = packagesPercent; - STAT_LINE("PERPIC", &nPackagesPercent, false, &(nTemp = 100)); - STAT_LINE("NOUNIF", &CStats::NumberOfUniqueJumpsFound, false, &CStats::TotalNumberOfUniqueJumps); - STAT_LINE("DAYSPS", &CStats::DaysPassed, false, nil); + STAT_LINE_2(int, "PERPIC", packagesPercent, 100); +#endif + STAT_LINE_2(int, "NOUNIF", CStats::NumberOfUniqueJumpsFound, CStats::TotalNumberOfUniqueJumps); + STAT_LINE_1(int, "DAYSPS", CStats::DaysPassed); if (CGame::nastyGame) { - STAT_LINE("PE_WAST", &CStats::PeopleKilledByPlayer, false, nil); - STAT_LINE("PE_WSOT", &CStats::PeopleKilledByOthers, false, nil); + STAT_LINE_1(int, "PE_WAST", CStats::PeopleKilledByPlayer); + STAT_LINE_1(int, "PE_WSOT", CStats::PeopleKilledByOthers); } - STAT_LINE("CAR_EXP", &CStats::CarsExploded, false, nil); - STAT_LINE("TM_BUST", &CStats::TimesArrested, false, nil); - STAT_LINE("TM_DED", &CStats::TimesDied, false, nil); - STAT_LINE("GNG_WST", &(nTemp = CStats::PedsKilledOfThisType[PEDTYPE_GANG9] + CStats::PedsKilledOfThisType[PEDTYPE_GANG8] + STAT_LINE_1(int, "CAR_EXP", CStats::CarsExploded); + STAT_LINE_1(int, "TM_BUST", CStats::TimesArrested); + STAT_LINE_1(int, "TM_DED", CStats::TimesDied); + STAT_LINE_1(int, "GNG_WST", CStats::PedsKilledOfThisType[PEDTYPE_GANG9] + CStats::PedsKilledOfThisType[PEDTYPE_GANG8] + CStats::PedsKilledOfThisType[PEDTYPE_GANG7] + CStats::PedsKilledOfThisType[PEDTYPE_GANG6] + CStats::PedsKilledOfThisType[PEDTYPE_GANG5] + CStats::PedsKilledOfThisType[PEDTYPE_GANG4] + CStats::PedsKilledOfThisType[PEDTYPE_GANG3] + CStats::PedsKilledOfThisType[PEDTYPE_GANG2] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG1]), false, nil); - STAT_LINE("DED_CRI", &(nTemp = CStats::PedsKilledOfThisType[PEDTYPE_CRIMINAL]), false, nil); - STAT_LINE("HEL_DST", &CStats::HelisDestroyed, false, nil); - STAT_LINE("KGS_EXP", &CStats::KgsOfExplosivesUsed, false, nil); - STAT_LINE("ACCURA", &(nTemp = (CStats::InstantHitsFiredByPlayer == 0 ? 0 : - CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer)), false, nil); + + CStats::PedsKilledOfThisType[PEDTYPE_GANG1]); + STAT_LINE_1(int, "DED_CRI", CStats::PedsKilledOfThisType[PEDTYPE_CRIMINAL]); + STAT_LINE_1(int, "HEL_DST", CStats::HelisDestroyed); + STAT_LINE_1(int, "KGS_EXP", CStats::KgsOfExplosivesUsed); + STAT_LINE_1(int, "ACCURA", (CStats::InstantHitsFiredByPlayer == 0 ? 0 : + CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer)); if (CStats::ElBurroTime > 0) { - STAT_LINE("ELBURRO", &CStats::ElBurroTime, false, nil); + STAT_LINE_1(int, "ELBURRO", CStats::ElBurroTime); } if (CStats::Record4x4One > 0) { - STAT_LINE("FEST_R1", &CStats::Record4x4One, false, nil); + STAT_LINE_1(int, "FEST_R1", CStats::Record4x4One); } if (CStats::Record4x4Two > 0) { - STAT_LINE("FEST_R2", &CStats::Record4x4Two, false, nil); + STAT_LINE_1(int, "FEST_R2", CStats::Record4x4Two); } if (CStats::Record4x4Three > 0) { - STAT_LINE("FEST_R3", &CStats::Record4x4Three, false, nil); + STAT_LINE_1(int, "FEST_R3", CStats::Record4x4Three); } if (CStats::Record4x4Mayhem > 0) { - STAT_LINE("FEST_RM", &CStats::Record4x4Mayhem, false, nil); + STAT_LINE_1(int, "FEST_RM", CStats::Record4x4Mayhem); } if (CStats::LongestFlightInDodo > 0) { - STAT_LINE("FEST_LF", &CStats::LongestFlightInDodo, false, nil); + STAT_LINE_1(int, "FEST_LF", CStats::LongestFlightInDodo); } if (CStats::TimeTakenDefuseMission > 0) { - STAT_LINE("FEST_BD", &CStats::TimeTakenDefuseMission, false, nil); + STAT_LINE_1(int, "FEST_BD", CStats::TimeTakenDefuseMission); } - STAT_LINE("CAR_CRU", &CStats::CarsCrushed, false, nil); + STAT_LINE_1(int, "CAR_CRU", CStats::CarsCrushed); if (CStats::HighestScores[0] > 0) { - STAT_LINE("FEST_BB", nil, false, nil); - STAT_LINE("FEST_H0", &CStats::HighestScores[0], false, nil); + TEXT_ON_LEFT_GXT("FEST_BB"); + STAT_LINE_1(int, "FEST_H0", CStats::HighestScores[0]); } if (CStats::HighestScores[4] + CStats::HighestScores[3] + CStats::HighestScores[2] + CStats::HighestScores[1] > 0) { - STAT_LINE("FEST_GC", nil, false, nil); + TEXT_ON_LEFT_GXT("FEST_GC"); } if (CStats::HighestScores[1] > 0) { - STAT_LINE("FEST_H1", &CStats::HighestScores[1], false, nil); + STAT_LINE_1(int, "FEST_H1", CStats::HighestScores[1]); } if (CStats::HighestScores[2] > 0) { - STAT_LINE("FEST_H2", &CStats::HighestScores[2], false, nil); + STAT_LINE_1(int, "FEST_H2", CStats::HighestScores[2]); } if (CStats::HighestScores[3] > 0) { - STAT_LINE("FEST_H3", &CStats::HighestScores[3], false, nil); + STAT_LINE_1(int, "FEST_H3", CStats::HighestScores[3]); } if (CStats::HighestScores[4] > 0) { - STAT_LINE("FEST_H4", &CStats::HighestScores[4], false, nil); + STAT_LINE_1(int, "FEST_H4", CStats::HighestScores[4]); } switch (m_PrefsLanguage) { case LANGUAGE_AMERICAN: #ifndef USE_MEASUREMENTS_IN_METERS - float fTemp; - STAT_LINE("FEST_DF", &(fTemp = CStats::DistanceTravelledOnFoot * MILES_IN_METER), true, nil); - STAT_LINE("FEST_DC", &(fTemp = CStats::DistanceTravelledInVehicle * MILES_IN_METER), true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); - STAT_LINE("MXCARD", &(fTemp = CStats::MaximumJumpDistance * FEET_IN_METER), true, nil); - STAT_LINE("MXCARJ", &(fTemp = CStats::MaximumJumpHeight * FEET_IN_METER), true, nil); + STAT_LINE_1(float, "FEST_DF", CStats::DistanceTravelledOnFoot * MILES_IN_METER); + STAT_LINE_1(float, "FEST_DC", CStats::DistanceTravelledInVehicle * MILES_IN_METER); + STAT_LINE_1(int, "MMRAIN", CStats::mmRain); + STAT_LINE_1(float, "MXCARD", CStats::MaximumJumpDistance * FEET_IN_METER); + STAT_LINE_1(float, "MXCARJ", CStats::MaximumJumpHeight * FEET_IN_METER); break; #endif case LANGUAGE_FRENCH: @@ -6214,63 +6263,65 @@ CMenuManager::ConstructStatLine(int rowIdx) case LANGUAGE_RUSSIAN: case LANGUAGE_JAPANESE: #endif - STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); - STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); - STAT_LINE("MXCARDM", &CStats::MaximumJumpDistance, true, nil); - STAT_LINE("MXCARJM", &CStats::MaximumJumpHeight, true, nil); + STAT_LINE_1(float, "FESTDFM", CStats::DistanceTravelledOnFoot); + STAT_LINE_1(float, "FESTDCM", CStats::DistanceTravelledInVehicle); + STAT_LINE_1(int, "MMRAIN", CStats::mmRain); + STAT_LINE_1(float, "MXCARDM", CStats::MaximumJumpDistance); + STAT_LINE_1(float, "MXCARJM", CStats::MaximumJumpHeight); break; default: break; } - STAT_LINE("MXFLIP", &CStats::MaximumJumpFlips, false, nil); - STAT_LINE("MXJUMP", &CStats::MaximumJumpSpins, false, nil); - STAT_LINE("BSTSTU", nil, false, nil); + STAT_LINE_1(int, "MXFLIP", CStats::MaximumJumpFlips); + STAT_LINE_1(int, "MXJUMP", CStats::MaximumJumpSpins); + TEXT_ON_LEFT_GXT("BSTSTU"); - if (counter == rowIdx) { - gUString[0] = '\0'; - switch (CStats::BestStuntJump) { - case 1: - UnicodeStrcpy(gUString2, TheText.Get("INSTUN")); - return 0; - case 2: - UnicodeStrcpy(gUString2, TheText.Get("PRINST")); - return 0; - case 3: - UnicodeStrcpy(gUString2, TheText.Get("DBINST")); - return 0; - case 4: - UnicodeStrcpy(gUString2, TheText.Get("DBPINS")); - return 0; - case 5: - UnicodeStrcpy(gUString2, TheText.Get("TRINST")); - return 0; - case 6: - UnicodeStrcpy(gUString2, TheText.Get("PRTRST")); - return 0; - case 7: - UnicodeStrcpy(gUString2, TheText.Get("QUINST")); - return 0; - case 8: - UnicodeStrcpy(gUString2, TheText.Get("PQUINS")); - return 0; - default: - UnicodeStrcpy(gUString2, TheText.Get("NOSTUC")); - return 0; - } + switch (CStats::BestStuntJump) { + case 1: + TEXT_ON_RIGHT(TheText.Get("INSTUN")); + break; + case 2: + TEXT_ON_RIGHT(TheText.Get("PRINST")); + break; + case 3: + TEXT_ON_RIGHT(TheText.Get("DBINST")); + break; + case 4: + TEXT_ON_RIGHT(TheText.Get("DBPINS")); + break; + case 5: + TEXT_ON_RIGHT(TheText.Get("TRINST")); + break; + case 6: + TEXT_ON_RIGHT(TheText.Get("PRTRST")); + break; + case 7: + TEXT_ON_RIGHT(TheText.Get("QUINST")); + break; + case 8: + TEXT_ON_RIGHT(TheText.Get("PQUINS")); + break; + default: + TEXT_ON_RIGHT(TheText.Get("NOSTUC")); + break; } - counter++; - STAT_LINE("PASDRO", &CStats::PassengersDroppedOffWithTaxi, false, nil); - STAT_LINE("MONTAX", &CStats::MoneyMadeWithTaxi, false, nil); - STAT_LINE("FEST_LS", &CStats::LivesSavedWithAmbulance, false, nil); - STAT_LINE("FEST_HA", &CStats::HighestLevelAmbulanceMission, false, nil); - STAT_LINE("FEST_CC", &CStats::CriminalsCaught, false, nil); - STAT_LINE("FEST_FE", &CStats::FiresExtinguished, false, nil); - STAT_LINE("DAYPLC", &(nTemp = CTimer::GetTimeInMilliseconds() + 100), false, nil); + + STAT_LINE_1(int, "PASDRO", CStats::PassengersDroppedOffWithTaxi); + STAT_LINE_1(int, "MONTAX", CStats::MoneyMadeWithTaxi); + STAT_LINE_1(int, "FEST_LS", CStats::LivesSavedWithAmbulance); + STAT_LINE_1(int, "FEST_HA", CStats::HighestLevelAmbulanceMission); + STAT_LINE_1(int, "FEST_CC", CStats::CriminalsCaught); + STAT_LINE_1(int, "FEST_FE", CStats::FiresExtinguished); + STAT_LINE_1(int, "DAYPLC", CTimer::GetTimeInMilliseconds() + 100); return counter; -#undef STAT_LINE +#undef STAT_LINE_1 +#undef STAT_LINE_2 +#undef TEXT_ON_LEFT_GXT +#undef TEXT_ON_RIGHT +#undef int_STAT_IS_FLOAT +#undef float_STAT_IS_FLOAT } #undef GetBackJustUp -- cgit v1.2.3 From fc3cdf3b3ba9834fbdeb7cafe11669d862a92462 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 9 Dec 2020 21:43:58 +0300 Subject: Sync Frontend with miami 1 --- src/core/Frontend.cpp | 229 ++++++++++++++++++++++++-------------------------- src/core/Frontend.h | 2 - 2 files changed, 112 insertions(+), 119 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 118fb8d6..3bd359c8 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -38,6 +38,30 @@ #include "FileLoader.h" #include "frontendoption.h" +// Game has colors inlined in code. +// For easier modification we collect them here: +const CRGBA LABEL_COLOR(235, 170, 50, 255); +const CRGBA SELECTION_HIGHLIGHTBG_COLOR(100, 200, 50, 50); +const CRGBA MENUOPTION_COLOR = LABEL_COLOR; +const CRGBA SELECTEDMENUOPTION_COLOR(255, 217, 106, 255); +const CRGBA HEADER_COLOR(0, 0, 0, 255); +const CRGBA DARKMENUOPTION_COLOR(155, 117, 6, 255); +const CRGBA SLIDERON_COLOR = SELECTEDMENUOPTION_COLOR; +const CRGBA SLIDEROFF_COLOR(185, 120, 0, 255); +const CRGBA LIST_BACKGROUND_COLOR(200, 200, 50, 50); +const CRGBA LIST_OPTION_COLOR(155, 155, 155, 255); +const CRGBA INACTIVE_RADIO_COLOR(225, 0, 0, 170); +const CRGBA SCROLLBAR_COLOR = LABEL_COLOR; +const CRGBA CONTSETUP_HIGHLIGHTBG_COLOR(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, 210); +const CRGBA CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, 150); + +// This is PS2 menu leftover, and variable name is original. They forgot it here and used in PrintBriefs once (but didn't use the output) +#if defined(FIX_BUGS) && !defined(PS2_LIKE_MENU) +const CRGBA TEXT_COLOR = LABEL_COLOR; +#else +const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); // PS2 option color +#endif + #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 #define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result @@ -91,8 +115,6 @@ int GetOptionCount(int screen) #ifdef MENU_MAP bool CMenuManager::bMenuMapActive = false; -bool CMenuManager::bMapMouseShownOnce = false; -bool CMenuManager::bMapLoaded = false; float CMenuManager::fMapSize; float CMenuManager::fMapCenterY; float CMenuManager::fMapCenterX; @@ -121,13 +143,6 @@ int8 CMenuManager::m_nDisplayMSAALevel = 0; int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW; #endif -// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) -#ifdef PS2_LIKE_MENU -const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); -#else -const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color -#endif - #ifdef USE_PRECISE_MEASUREMENT_CONVERTION #define MILES_IN_METER 0.000621371192f #define FEET_IN_METER 3.28084f @@ -298,7 +313,7 @@ const char* MenuFilenames[][2] = { } while(0) #define PREPARE_MENU_HEADER \ - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \ + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); \ CFont::SetRightJustifyOn(); \ CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -322,7 +337,8 @@ const char* MenuFilenames[][2] = { #define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \ do { \ - sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); \ + sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : \ + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, INACTIVE_RADIO_COLOR.a)); \ if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \ m_nHoverOption = hoverOpt; \ } while (0) @@ -966,10 +982,10 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR curBarX = i * rectSize/16.0f + x; if (i / 16.0f + 1 / 32.0f < progress) { - color = CRGBA(255, 217, 106, FadeIn(255)); + color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255)); lastActiveBarX = curBarX; } else - color = CRGBA(185, 120, 0, FadeIn(255)); + color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255)); maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); @@ -1012,7 +1028,7 @@ CMenuManager::Draw() CFont::SetBackGroundOnlyTextOn(); #if GTA_VERSION >= GTA3_PC_11 #ifdef DRAW_MENU_VERSION_TEXT - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); @@ -1059,7 +1075,7 @@ CMenuManager::Draw() CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y)); CFont::SetRightJustifyOff(); - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); // Label wchar *str; @@ -1247,7 +1263,7 @@ CMenuManager::Draw() // Back button wchar *backTx = TheText.Get("FEDS_TB"); CFont::SetDropShadowPosition(1); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::PrintString(MENU_X(60.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), backTx); CFont::SetDropShadowPosition(0); if (!CheckHover(MENU_X(30.0f), MENU_X(30.0f) + CFont::GetStringWidth(backTx), SCREEN_SCALE_FROM_BOTTOM(125.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f))) { @@ -1636,12 +1652,12 @@ CMenuManager::Draw() #ifdef PS2_LIKE_MENU CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(29.0f), MENU_Y(bitAboveNextItemY), MENU_X_RIGHT_ALIGNED(29.0f), MENU_Y(usableLineHeight + nextItemY)), - CRGBA(100, 200, 50, FadeIn(50))); + CRGBA(SELECTION_HIGHLIGHTBG_COLOR.r, SELECTION_HIGHLIGHTBG_COLOR.g, SELECTION_HIGHLIGHTBG_COLOR.b, FadeIn(SELECTION_HIGHLIGHTBG_COLOR.a))); #else // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), - CRGBA(100, 200, 50, FadeIn(50))); + CRGBA(SELECTION_HIGHLIGHTBG_COLOR.r, SELECTION_HIGHLIGHTBG_COLOR.g, SELECTION_HIGHLIGHTBG_COLOR.b, FadeIn(SELECTION_HIGHLIGHTBG_COLOR.a))); #endif } @@ -1665,14 +1681,14 @@ CMenuManager::Draw() || isOptionDisabled #endif ) - CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); } if (i == m_nCurrOption && itemsAreSelectable){ - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); } else { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } } @@ -1795,7 +1811,7 @@ CMenuManager::Draw() // Scrollbar CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - SCROLLBAR_WIDTH), scrollbarBottom), - CRGBA(235, 170, 50, FadeIn(255))); + CRGBA(SCROLLBAR_COLOR.r, SCROLLBAR_COLOR.g, SCROLLBAR_COLOR.b, FadeIn(255))); } #endif @@ -1877,7 +1893,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 for (int optionIdx = 0, nextY = MENU_Y(yStart); optionIdx < numOptions; nextY = MENU_Y(++optionIdx * rowHeight + yStart)) { int nextX = xStart; int bindingsForThisOpt = 0; - CFont::SetColor(CRGBA(155, 155, 155, FadeIn(255))); + CFont::SetColor(CRGBA(LIST_OPTION_COLOR.r, LIST_OPTION_COLOR.g, LIST_OPTION_COLOR.b, FadeIn(LIST_OPTION_COLOR.a))); if (column == CONTSETUP_PED_COLUMN) { switch (optionIdx) { @@ -2055,18 +2071,18 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 #ifdef FIX_BUGS if (controllerAction == -1) { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); } else { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); } #else if (controllerAction == -1) { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), - MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); + MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); } else { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), - MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); + MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); } #endif CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); @@ -2076,16 +2092,16 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 #ifdef FIX_BUGS if (controllerAction == -1) { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); } else { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); } #else if (controllerAction == -1) { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(235, 170, 50, FadeIn(150))); + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); } else { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(255, 217, 106, FadeIn(210))); + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); } #endif CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); @@ -2244,7 +2260,7 @@ CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeig if (waitingTextVisible) { CFont::SetColor(CRGBA(255, 255, 0, FadeIn(255))); CFont::PrintString(nextX, MENU_Y(yStart), TheText.Get("FEC_QUE")); - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } } yStart += lineHeight; @@ -2344,12 +2360,12 @@ CMenuManager::DrawControllerSetupScreen() // Gray panel background CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT), MENU_Y(CONTSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(CONTSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM)), - CRGBA(200, 200, 50, FadeIn(50))); + CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); if (m_nCurrExLayer == HOVEROPTION_LIST) - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); else - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); // List header CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -2418,16 +2434,16 @@ CMenuManager::DrawControllerSetupScreen() m_nHoverOption = HOVEROPTION_NOT_HOVERING; } } - if (m_nSelectedListRow != 35) - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + if (m_nSelectedListRow != i) + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); else if (m_nCurrExLayer == HOVEROPTION_LIST) - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); CFont::SetRightJustifyOff(); - if (m_PrefsLanguage != LANGUAGE_GERMAN || i != 20 && i != 21) - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - else + if (m_PrefsLanguage == LANGUAGE_GERMAN && (i == 20 || i == 21)) CFont::SetScale(MENU_X(0.32f), MENU_Y(SMALLESTTEXT_Y_SCALE)); + else + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(i * rowHeight + yStart), actionText); } @@ -2458,9 +2474,9 @@ CMenuManager::DrawControllerSetupScreen() SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - 4.0f - i), TheText.Get("FEDS_TB")); if (m_nHoverOption == HOVEROPTION_BACK) - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); else - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } } @@ -2730,12 +2746,12 @@ CMenuManager::DrawFrontEndNormal() CFont::SetScale(MENU_X(0.35f), MENU_Y(0.7f)); CFont::SetRightJustifyOff(); if (hoveredBottomBarOption == i && hoveredBottomBarOption != curBottomBarOption) - CFont::SetColor(CRGBA(235, 170, 50, 255)); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, 255)); else { if(bottomBarActive || curBottomBarOption == i) - CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, 255)); else - CFont::SetColor(CRGBA(0, 0, 0, 110)); + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, 110)); } str = TheText.Get(bbNames[i].name); @@ -3124,13 +3140,14 @@ CMenuManager::DrawPlayerSetupScreen() m_bSkinsEnumerated = true; } CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), - MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(200, 200, 50, FadeIn(50))); + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), + CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); // Header (Skin - Date) if (m_nCurrExLayer == HOVEROPTION_LIST) { - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); } else { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); @@ -3200,7 +3217,7 @@ CMenuManager::DrawPlayerSetupScreen() } else if (!strcmp(m_PrefsSkinFile, m_pSelectedSkin->skinNameOriginal)) { CFont::SetColor(CRGBA(255, 255, 155, FadeIn(255))); } else { - CFont::SetColor(CRGBA(155, 155, 155, FadeIn(255))); + CFont::SetColor(CRGBA(LIST_OPTION_COLOR.r, LIST_OPTION_COLOR.g, LIST_OPTION_COLOR.b, FadeIn(LIST_OPTION_COLOR.a))); } wchar unicodeTemp[80]; AsciiToUnicode(m_pSelectedSkin->skinNameDisplayed, unicodeTemp); @@ -3252,7 +3269,7 @@ CMenuManager::DrawPlayerSetupScreen() // Scrollbar CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom), - CRGBA(235, 170, 50, FadeIn(255))); + CRGBA(SCROLLBAR_COLOR.r, SCROLLBAR_COLOR.g, SCROLLBAR_COLOR.b, FadeIn(255))); // FIX: Scroll button dimensions are buggy, because: // 1 - stretches the original image @@ -3321,7 +3338,7 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f)); break; } - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(120))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(120))); CFont::SetRightJustifyOff(); CFont::PrintString(MENU_X_LEFT_ALIGNED(20.0f), MENU_Y(220.0f), TheText.Get("FET_APL")); } @@ -3412,9 +3429,9 @@ CMenuManager::DrawPlayerSetupScreen() for (int i = 0; i < 2; i++) { CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - i), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FEDS_TB")); if (m_nHoverOption == HOVEROPTION_BACK) { - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); } else { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } } CFont::SetRightJustifyOff(); @@ -3424,11 +3441,11 @@ CMenuManager::DrawPlayerSetupScreen() for (int i = 0; i < 2; i++) { CFont::PrintString(MENU_X_LEFT_ALIGNED(i + PLAYERSETUP_LIST_LEFT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FES_SET")); if (!strcmp(m_aSkinName, m_PrefsSkinFile)) { - CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); } else if (m_nHoverOption == HOVEROPTION_USESKIN) { - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); } else { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } } @@ -3607,6 +3624,9 @@ CMenuManager::LoadAllTextures() m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]); m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } + fMapSize = SCREEN_HEIGHT * 2.0f; + fMapCenterX = 0.0f; + fMapCenterY = 0.0f; #endif #if GTA_VERSION >= GTA3_PC_11 CStreaming::IHaveUsedStreamingMemory(); @@ -3820,7 +3840,7 @@ CMenuManager::MessageScreen(const char *text) CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetCentreSize(SCREEN_SCALE_X(380.0f)); CFont::SetCentreOn(); - CFont::SetColor(CRGBA(255, 217, 106, 255)); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, 255)); CFont::SetScale(SCREEN_SCALE_X(SMALLTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLTEXT_Y_SCALE)); CFont::PrintString(StretchX(320.0f), StretchY(170.0f), TheText.Get(text)); CFont::DrawFonts(); @@ -3846,7 +3866,7 @@ CMenuManager::PickNewPlayerColour() void CMenuManager::PrintBriefs() { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why @@ -3864,19 +3884,14 @@ CMenuManager::PrintBriefs() CMessages::InsertPlayerControlKeysInString(gUString); newColor = TEXT_COLOR; FilterOutColorMarkersFromString(gUString, newColor); - -#ifdef PS2_LIKE_MENU - // This PS2 code was always here, but unused - bool rgSame = newColor.r == TEXT_COLOR.r && newColor.g == TEXT_COLOR.g; - bool bSame = rgSame && newColor.b == TEXT_COLOR.b; - bool colorNotChanged = bSame; /* && newColor.a == TEXT_COLOR.a; */ - - if (!colorNotChanged) { + if (newColor != TEXT_COLOR) { newColor.r /= 2; newColor.g /= 2; newColor.b /= 2; } - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // But this is from PS2 + +#ifdef PS2_LIKE_MENU + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::SetDropShadowPosition(1); #endif @@ -3970,7 +3985,7 @@ CMenuManager::PrintStats() } else alphaMult = 1.0f; - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255.0f * alphaMult))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255.0f * alphaMult))); CFont::SetRightJustifyOff(); CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_ROW_X_MARGIN), y - MENU_Y(STATS_BOTTOM_MARGIN - STATS_TOP_MARGIN), gUString); CFont::SetRightJustifyOn(); @@ -3980,7 +3995,7 @@ CMenuManager::PrintStats() // Game doesn't do that, but it's better float nextX = MENU_X_LEFT_ALIGNED(STATS_RATING_X); - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); CFont::SetRightJustifyOff(); CFont::PrintString(nextX, MENU_Y(STATS_RATING_Y), TheText.Get("CRIMRA")); #ifdef MORE_LANGUAGES @@ -4818,12 +4833,6 @@ CMenuManager::ProcessButtonPresses(void) break; #endif } else { -#ifdef MENU_MAP - if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { - bMapLoaded = false; - } - -#endif ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); } } @@ -5894,26 +5903,14 @@ CMenuManager::PrintMap(void) bMenuMapActive = true; CRadar::InitFrontEndMap(); - // Just entered to map - if (!bMapLoaded) { - fMapSize = SCREEN_HEIGHT * 2.0f; - fMapCenterX = 0.0f; - fMapCenterY = 0.0f; + if (m_nMenuFadeAlpha < 255 && fMapCenterX == 0.f && fMapCenterY == 0.f) { + // Just entered. We need to do these transformations in here, because Radar knows whether map is active or not CVector2D radarSpacePlayer; CVector2D screenSpacePlayer; CRadar::TransformRealWorldPointToRadarSpace(radarSpacePlayer, CVector2D(FindPlayerCoors())); CRadar::TransformRadarPointToScreenSpace(screenSpacePlayer, radarSpacePlayer); - fMapCenterX = (-screenSpacePlayer.x) + SCREEN_WIDTH / 2; fMapCenterY = (-screenSpacePlayer.y) + SCREEN_HEIGHT / 2; - bMapMouseShownOnce = false; - bMapLoaded = true; - - // Let's wait for a frame to not toggle the waypoint - if (CPad::GetPad(0)->NewState.Cross) { - bMenuMapActive = false; - return; - } } // Because fMapSize is half of the map length, and map consists of 3x3 tiles. @@ -5972,34 +5969,35 @@ CMenuManager::PrintMap(void) } CRadar::DrawBlips(); + static CVector2D mapCrosshair; - CVector2D mapPoint; - mapPoint.x = m_nMousePosX; - mapPoint.y = m_nMousePosY; - - if (m_bShowMouse) { - bMapMouseShownOnce = true; - } else if (!bMapMouseShownOnce) { - mapPoint.x = SCREEN_WIDTH / 2; - mapPoint.y = SCREEN_HEIGHT / 2; + if (m_nMenuFadeAlpha != 255 && !m_bShowMouse) { + mapCrosshair.x = SCREEN_WIDTH / 2; + mapCrosshair.y = SCREEN_HEIGHT / 2; + } else if (m_bShowMouse) { + mapCrosshair.x = m_nMousePosX; + mapCrosshair.y = m_nMousePosY; } - CSprite2d::DrawRect(CRect(mapPoint.x - MENU_X(1.0f), 0.0f, - mapPoint.x + MENU_X(1.0f), SCREEN_HEIGHT), + CSprite2d::DrawRect(CRect(mapCrosshair.x - MENU_X(1.0f), 0.0f, + mapCrosshair.x + MENU_X(1.0f), SCREEN_HEIGHT), CRGBA(0, 0, 0, 150)); - CSprite2d::DrawRect(CRect(0.0f, mapPoint.y + MENU_X(1.0f), - SCREEN_WIDTH, mapPoint.y - MENU_X(1.0f)), + CSprite2d::DrawRect(CRect(0.0f, mapCrosshair.y + MENU_X(1.0f), + SCREEN_WIDTH, mapCrosshair.y - MENU_X(1.0f)), CRGBA(0, 0, 0, 150)); - if (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - if (mapPoint.y > fMapCenterY - fMapSize && mapPoint.y < fMapCenterY + fMapSize && - mapPoint.x > fMapCenterX - fMapSize && mapPoint.x < fMapCenterX + fMapSize) { + // Adding marker + if (m_nMenuFadeAlpha >= 255) { + if (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { + if (mapCrosshair.y > fMapCenterY - fMapSize && mapCrosshair.y < fMapCenterY + fMapSize && + mapCrosshair.x > fMapCenterX - fMapSize && mapCrosshair.x < fMapCenterX + fMapSize) { - float diffX = fMapCenterX - fMapSize, diffY = fMapCenterY - fMapSize; - float x = ((mapPoint.x - diffX) / (fMapSize * 2)) * 4000.0f - 2000.0f; - float y = 2000.0f - ((mapPoint.y - diffY) / (fMapSize * 2)) * 4000.0f; - CRadar::ToggleTargetMarker(x, y); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); + float diffX = fMapCenterX - fMapSize, diffY = fMapCenterY - fMapSize; + float x = ((mapCrosshair.x - diffX) / (fMapSize * 2)) * 4000.0f - 2000.0f; + float y = 2000.0f - ((mapCrosshair.y - diffY) / (fMapSize * 2)) * 4000.0f; + CRadar::ToggleTargetMarker(x, y); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); + } } } @@ -6024,12 +6022,12 @@ CMenuManager::PrintMap(void) if (CPad::GetPad(0)->GetMouseWheelDown() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { if (CPad::GetPad(0)->GetMouseWheelDown()) - ZOOM(mapPoint.x, mapPoint.y, false); + ZOOM(mapCrosshair.x, mapCrosshair.y, false); else ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, false); } else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { if (CPad::GetPad(0)->GetMouseWheelUp()) - ZOOM(mapPoint.x, mapPoint.y, true); + ZOOM(mapCrosshair.x, mapCrosshair.y, true); else ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); } @@ -6047,16 +6045,13 @@ CMenuManager::PrintMap(void) bMenuMapActive = false; - // CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(5.0f)); // From VC - // CFont::SetRightJustifyWrap(10.0f); - CSprite2d::DrawRect(CRect(MENU_X(14.0f), SCREEN_STRETCH_FROM_BOTTOM(95.0f), SCREEN_STRETCH_FROM_RIGHT(11.0f), SCREEN_STRETCH_FROM_BOTTOM(59.0f)), CRGBA(235, 170, 50, 255)); CFont::SetScale(MENU_X(0.4f), MENU_Y(0.7f)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); float nextX = MENU_X(30.0f), nextY = 95.0f; wchar *text; diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 21124fdb..9f935510 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -697,8 +697,6 @@ public: #ifdef MENU_MAP static bool bMenuMapActive; - static bool bMapMouseShownOnce; - static bool bMapLoaded; static float fMapSize; static float fMapCenterY; static float fMapCenterX; -- cgit v1.2.3 From 3038fba9ca6b2fcb3a4f95543db624fe81deb392 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sat, 12 Dec 2020 18:20:21 +0300 Subject: Sync Frontend, Peds with miami 2 --- src/core/Frontend.cpp | 100 +++++++++++++++++++++------------------------- src/peds/PedAI.cpp | 28 ++++++------- src/peds/PlayerPed.cpp | 106 +++++++++++++++++++++++-------------------------- 3 files changed, 110 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 3bd359c8..6806230d 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -312,12 +312,33 @@ const char* MenuFilenames[][2] = { m_nMenuFadeAlpha = 0; \ } while(0) -#define PREPARE_MENU_HEADER \ +#define SET_FONT_FOR_MENU_HEADER \ CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); \ CFont::SetRightJustifyOn(); \ CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); +#define RESET_FONT_FOR_NEW_PAGE \ + CFont::SetBackgroundOff(); \ + CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); \ + CFont::SetPropOn(); \ + CFont::SetCentreOff(); \ + CFont::SetJustifyOn(); \ + CFont::SetRightJustifyOff(); \ + CFont::SetBackGroundOnlyTextOn(); \ + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); \ + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); + +#define SET_FONT_FOR_HELPER_TEXT \ + CFont::SetCentreOn(); \ + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); \ + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + +#define SET_FONT_FOR_LIST_ITEM \ + CFont::SetRightJustifyOff(); \ + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); \ + CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + #define ProcessSlider(value, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ do { \ lastActiveBarX = DisplaySlider(MENU_X_RIGHT_ALIGNED(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ @@ -512,6 +533,7 @@ CMenuManager::ProcessList(bool &goBack, bool &optionSelected) m_nTotalListRow = m_nSkinsTotal; } if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + // GetNumOptionsCntrlConfigScreens would have been a better choice m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25; if (m_nSelectedListRow > m_nTotalListRow) m_nSelectedListRow = m_nTotalListRow - 1; @@ -932,10 +954,7 @@ CMenuManager::DisplayHelperText() alpha = m_nHelperTextAlpha > 255 ? 255 : m_nHelperTextAlpha; } - CFont::SetCentreOn(); - CFont::SetScale(SCREEN_SCALE_X(SMALLESTTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - + SET_FONT_FOR_HELPER_TEXT // TODO: name this cases? switch (m_nHelperTextMsgId) { case 0: @@ -1065,7 +1084,7 @@ CMenuManager::Draw() #endif if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { - PREPARE_MENU_HEADER + SET_FONT_FOR_MENU_HEADER CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); // Weird place to put that. @@ -1876,6 +1895,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 int controllerAction = PED_FIREWEAPON; // GetStartOptionsCntrlConfigScreens(); int numOptions = GetNumOptionsCntrlConfigScreens(); + int nextY = MENU_Y(yStart); int bindingMargin = MENU_X(3.0f); float rowHeight; switch (m_ControlMethod) { @@ -1890,9 +1910,10 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 } // MENU_Y(rowHeight * 0.0f + yStart); - for (int optionIdx = 0, nextY = MENU_Y(yStart); optionIdx < numOptions; nextY = MENU_Y(++optionIdx * rowHeight + yStart)) { + for (int optionIdx = 0; optionIdx < numOptions; nextY = MENU_Y(++optionIdx * rowHeight + yStart)) { int nextX = xStart; int bindingsForThisOpt = 0; + int contSetOrder = SETORDER_1; CFont::SetColor(CRGBA(LIST_OPTION_COLOR.r, LIST_OPTION_COLOR.g, LIST_OPTION_COLOR.b, FadeIn(LIST_OPTION_COLOR.a))); if (column == CONTSETUP_PED_COLUMN) { @@ -2112,7 +2133,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 // Print bindings, including seperator (-) between them CFont::SetScale(MENU_X(0.25f), MENU_Y(0.6f)); - for (int contSetOrder = SETORDER_1; contSetOrder < MAX_SETORDERS && controllerAction != -1; contSetOrder++) { + for (; contSetOrder < MAX_SETORDERS && controllerAction != -1; contSetOrder++) { wchar *settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder); if (settingText) { ++bindingsForThisOpt; @@ -2176,9 +2197,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::SetColor(CRGBA(55, 55, 55, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_QUE")); // "???" } - CFont::SetCentreOn(); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + SET_FONT_FOR_HELPER_TEXT CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); if (m_bKeyChangeNotProcessed) { CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_CIG")); // BACKSPACE TO CLEAR - LMB,RETURN TO CHANGE @@ -2186,34 +2205,24 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_RIG")); // SELECT A NEW CONTROL FOR THIS ACTION OR ESC TO CANCEL } - CFont::SetRightJustifyOff(); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + SET_FONT_FOR_LIST_ITEM if (!m_bKeyIsOK) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); m_bKeyIsOK = true; } else { - CFont::SetCentreOn(); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + SET_FONT_FOR_HELPER_TEXT CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_CIG")); // BACKSPACE TO CLEAR - LMB,RETURN TO CHANGE - CFont::SetRightJustifyOff(); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + SET_FONT_FOR_LIST_ITEM m_bKeyIsOK = false; m_bKeyChangeNotProcessed = false; } } else if (optionIdx == m_nSelectedListRow) { - CFont::SetCentreOn(); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + SET_FONT_FOR_HELPER_TEXT CFont::SetColor(CRGBA(55, 55, 55, FadeIn(255))); CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_EIG")); // CANNOT SET A CONTROL FOR THIS ACTION - CFont::SetRightJustifyOff(); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + SET_FONT_FOR_LIST_ITEM } } } @@ -2289,17 +2298,9 @@ CMenuManager::DrawControllerSetupScreen() default: break; } - CFont::SetBackgroundOff(); - CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); - CFont::SetPropOn(); - CFont::SetCentreOff(); - CFont::SetJustifyOn(); - CFont::SetRightJustifyOff(); - CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); + RESET_FONT_FOR_NEW_PAGE - PREPARE_MENU_HEADER + SET_FONT_FOR_MENU_HEADER switch (m_ControlMethod) { case CONTROL_STANDARD: @@ -2374,15 +2375,15 @@ CMenuManager::DrawControllerSetupScreen() CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CAC")); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CFT")); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CCR")); - CFont::SetRightJustifyOff(); - CFont::SetScale(MENU_X_LEFT_ALIGNED(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + SET_FONT_FOR_LIST_ITEM + int yStart; if (m_ControlMethod == CONTROL_CLASSIC) - yStart = CONTSETUP_LIST_HEADER_HEIGHT + 29; + yStart = CONTSETUP_LIST_TOP + CONTSETUP_LIST_HEADER_HEIGHT + 1; else - yStart = CONTSETUP_LIST_HEADER_HEIGHT + 34; + yStart = CONTSETUP_LIST_TOP + CONTSETUP_LIST_HEADER_HEIGHT + 5; + float optionYBottom = yStart + rowHeight; for (int i = 0; i < ARRAY_SIZE(actionTexts); ++i) { wchar *actionText = actionTexts[i]; if (!actionText) @@ -2391,8 +2392,7 @@ CMenuManager::DrawControllerSetupScreen() if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT + 2.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { - float curOptY = i * rowHeight + yStart; - if (m_nMousePosY > MENU_Y(curOptY) && m_nMousePosY < MENU_Y(rowHeight + curOptY)) { + if (m_nMousePosY > MENU_Y(i * rowHeight + yStart) && m_nMousePosY < MENU_Y(i * rowHeight + optionYBottom)) { if (m_nOptionMouseHovering != i && m_nCurrExLayer == HOVEROPTION_LIST) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); @@ -3042,17 +3042,9 @@ CMenuManager::DrawFrontEndNormal() void CMenuManager::DrawPlayerSetupScreen() { - CFont::SetBackgroundOff(); - CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); - CFont::SetPropOn(); - CFont::SetCentreOff(); - CFont::SetJustifyOn(); - CFont::SetRightJustifyOff(); - CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); + RESET_FONT_FOR_NEW_PAGE - PREPARE_MENU_HEADER + SET_FONT_FOR_MENU_HEADER CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); @@ -4018,7 +4010,7 @@ CMenuManager::PrintStats() // ::Draw already does that. /* - PREPARE_MENU_HEADER + SET_FONT_FOR_MENU_HEADER CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); */ CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp index 38303473..62b27134 100644 --- a/src/peds/PedAI.cpp +++ b/src/peds/PedAI.cpp @@ -972,9 +972,9 @@ CPed::ProcessObjective(void) } CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); float wepRange = wepInfo->m_fRange; - float wepRangeAdjusted; + float maxDistToKeep; if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { - wepRangeAdjusted = wepRange / 3.0f; + maxDistToKeep = wepRange / 3.0f; } else { if (m_nPedState == PED_FIGHT) { if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK)) @@ -982,10 +982,10 @@ CPed::ProcessObjective(void) } else { wepRange = 1.3f; } - wepRangeAdjusted = wepRange; + maxDistToKeep = wepRange; } - if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) { - wepRangeAdjusted = 2.5f; + if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && maxDistToKeep < 2.5f) { + maxDistToKeep = 2.5f; } if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) { @@ -1086,7 +1086,7 @@ CPed::ProcessObjective(void) || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) { if (m_pedInObjective->EnteringCar()) - wepRangeAdjusted = 2.0f; + maxDistToKeep = 2.0f; if (bUsePedNodeSeek) { CVector bestCoords(0.0f, 0.0f, 0.0f); @@ -1100,7 +1100,7 @@ CPed::ProcessObjective(void) SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); } else { - SetSeek(m_pedInObjective, wepRangeAdjusted); + SetSeek(m_pedInObjective, maxDistToKeep); } bCrouchWhenShooting = false; if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) { @@ -1172,7 +1172,7 @@ CPed::ProcessObjective(void) SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f)); int time; - if (distWithTargetSc <= wepRangeAdjusted) + if (distWithTargetSc <= maxDistToKeep) time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f); else time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f); @@ -1230,17 +1230,17 @@ CPed::ProcessObjective(void) if (m_nPedType == PEDTYPE_COP) { if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45 || m_fleeFrom && m_fleeFrom->IsObject()) { - wepRangeAdjusted = 6.0f; + maxDistToKeep = 6.0f; } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) { - wepRangeAdjusted = 4.0f; + maxDistToKeep = 4.0f; } else { - wepRangeAdjusted = 2.0f; + maxDistToKeep = 2.0f; } } else { - wepRangeAdjusted = 2.0f; + maxDistToKeep = 2.0f; } } - if (distWithTargetSc <= wepRangeAdjusted) { + if (distWithTargetSc <= maxDistToKeep) { SetMoveState(PEDMOVE_STILL); bIsPointingGunAt = true; if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) { @@ -1251,7 +1251,7 @@ CPed::ProcessObjective(void) if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) { Say(SOUND_PED_ATTACK); - SetSeek(m_pedInObjective, wepRangeAdjusted); + SetSeek(m_pedInObjective, maxDistToKeep); bIsRunning = true; } } diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index fa865aec..f23aa378 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -113,14 +113,10 @@ CPlayerPed::AnnoyPlayerPed(bool annoyedByPassingEntity) { if (m_pedStats->m_temper < 52) { m_pedStats->m_temper++; - } else { - if (annoyedByPassingEntity) { - if (m_pedStats->m_temper < 55) { - m_pedStats->m_temper++; - } else { - m_pedStats->m_temper = 46; - } - } + } else if (annoyedByPassingEntity && m_pedStats->m_temper < 55) { + m_pedStats->m_temper++; + } else if (annoyedByPassingEntity) { + m_pedStats->m_temper = 46; } } @@ -215,7 +211,7 @@ CPlayerPed::ReApplyMoveAnims(void) for(int i = 0; i < ARRAY_SIZE(moveAnims); i++) { CAnimBlendAssociation *curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), moveAnims[i]); if (curMoveAssoc) { - if (strcmp(CAnimManager::GetAnimAssociation(m_animGroup, moveAnims[i])->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) { + if (CGeneral::faststrcmp(CAnimManager::GetAnimAssociation(m_animGroup, moveAnims[i])->hierarchy->name, curMoveAssoc->hierarchy->name)) { CAnimBlendAssociation *newMoveAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, moveAnims[i]); newMoveAssoc->blendDelta = curMoveAssoc->blendDelta; newMoveAssoc->blendAmount = curMoveAssoc->blendAmount; @@ -288,7 +284,7 @@ CPlayerPed::SetRealMoveAnim(void) if (!curIdleAssoc) curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); - if ((!curRunStopAssoc || !(curRunStopAssoc->IsRunning())) && (!curRunStopRAssoc || !(curRunStopRAssoc->IsRunning()))) { + if (!((curRunStopAssoc && curRunStopAssoc->IsRunning()) || (curRunStopRAssoc && curRunStopRAssoc->IsRunning()))) { if (curRunStopAssoc && curRunStopAssoc->blendDelta >= 0.0f || curRunStopRAssoc && curRunStopRAssoc->blendDelta >= 0.0f) { if (curRunStopAssoc) { @@ -340,8 +336,8 @@ CPlayerPed::SetRealMoveAnim(void) CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); } } - m_nMoveState = PEDMOVE_STILL; + } else { if (curIdleAssoc) { if (curWalkStartAssoc) { @@ -394,6 +390,7 @@ CPlayerPed::SetRealMoveAnim(void) } if (curSprintAssoc && (m_nMoveState != PEDMOVE_SPRINT || m_fMoveSpeed < 0.4f)) { + // Stop sprinting in various conditions if (curSprintAssoc->blendAmount == 0.0f) { curSprintAssoc->blendDelta = -1000.0f; curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT; @@ -417,8 +414,8 @@ CPlayerPed::SetRealMoveAnim(void) curRunAssoc->flags &= ~ASSOC_RUNNING; curRunAssoc->blendAmount = 0.0f; curRunAssoc->blendDelta = 0.0f; - } else if (curSprintAssoc->blendDelta >= 0.0f) { + } else if (curSprintAssoc->blendDelta >= 0.0f) { // Stop sprinting when tired curSprintAssoc->flags |= ASSOC_DELETEFADEDOUT; curSprintAssoc->blendDelta = -1.0f; @@ -428,7 +425,9 @@ CPlayerPed::SetRealMoveAnim(void) curSprintAssoc->blendDelta = -8.0f; curRunAssoc->blendDelta = 8.0f; } + } else if (curWalkStartAssoc) { + // Walk start and walk/run shouldn't run at the same time curWalkAssoc->flags &= ~ASSOC_RUNNING; curRunAssoc->flags &= ~ASSOC_RUNNING; curWalkAssoc->blendAmount = 0.0f; @@ -436,11 +435,13 @@ CPlayerPed::SetRealMoveAnim(void) } else if (m_nMoveState == PEDMOVE_SPRINT) { if (curSprintAssoc) { + // We have anim, do it if (curSprintAssoc->blendDelta < 0.0f) { curSprintAssoc->blendDelta = 2.0f; curRunAssoc->blendDelta = -2.0f; } } else { + // Transition between run-sprint curWalkAssoc->blendAmount = 0.0f; curRunAssoc->blendAmount = 1.0f; curSprintAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_SPRINT, 2.0f); @@ -703,14 +704,7 @@ CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) float padMove = CVector2D(leftRight, upDown).Magnitude(); float padMoveInGameUnit = padMove / PAD_MOVE_TO_GAME_WORLD_MOVE; if (padMoveInGameUnit > 0.0f) { -#ifdef FREE_CAM - if (!CCamera::bFreeCam) - m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation); - else - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation; -#else m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation); -#endif m_fMoveSpeed = Min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed); } else { m_fMoveSpeed = 0.0f; @@ -718,8 +712,7 @@ CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) if (m_nPedState == PED_JUMP) { if (bIsInTheAir) { - if (bUsesCollision && !bHitSteepSlope && - (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f) + if (bUsesCollision && !bHitSteepSlope && (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f) && m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) { float angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O @@ -730,8 +723,7 @@ CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) m_fMoveSpeed = 0.0f; } } - if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy) - && padUsed->GetSprint()) { + if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy) && padUsed->GetSprint()) { m_nMoveState = PEDMOVE_SPRINT; } if (m_nPedState != PED_FIGHT) @@ -856,10 +848,9 @@ CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft) { CEntity *nextTarget = nil; float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange; - // nextTarget = nil; + // nextTarget = nil; // duplicate float lastCloseness = -10000.0f; - // unused - // CGeneral::GetATanOfXY(GetForward().x, GetForward().y); + // CGeneral::GetATanOfXY(GetForward().x, GetForward().y); // unused CVector distVec = previousTarget->GetPosition() - GetPosition(); float referenceBeta = CGeneral::GetATanOfXY(distVec.x, distVec.y); @@ -907,7 +898,7 @@ CPlayerPed::FindWeaponLockOnTarget(void) } } - // nextTarget = nil; + // nextTarget = nil; // duplicate float lastCloseness = -10000.0f; float referenceBeta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y); for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) { @@ -1105,7 +1096,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) m_fRotationCur += (limitedRotDest - m_fRotationCur) / 2; } } - } else if (weaponInfo->m_bCanAimWithArm) + } else if (weaponInfo->m_bCanAimWithArm && m_nPedState != PED_ATTACK) ClearPointGunAt(); } } @@ -1212,8 +1203,7 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) if (m_nPedState == PED_JUMP) { if (bIsInTheAir) { - if (bUsesCollision && !bHitSteepSlope && - (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f) + if (bUsesCollision && !bHitSteepSlope && (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f) && m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) { float angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O @@ -1225,8 +1215,7 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) } } - if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy) - && padUsed->GetSprint()) { + if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy) && padUsed->GetSprint()) { m_nMoveState = PEDMOVE_SPRINT; } if (m_nPedState != PED_FIGHT) @@ -1291,25 +1280,26 @@ CPlayerPed::ProcessControl(void) if (m_nPedState == PED_DRIVING && m_objective != OBJECTIVE_LEAVE_CAR) { if (m_pMyVehicle->IsCar() && ((CAutomobile*)m_pMyVehicle)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) { CAnimBlendAssociation *rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR); - if (!rollDoorAssoc) { - rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR_LOW); - } - - // These comparisons are wrong, they return uint16 - if (m_pMyVehicle->m_nGettingOutFlags & CAR_DOOR_FLAG_LF || rollDoorAssoc || padUsed - && (padUsed->GetAccelerate() != 0.0f || padUsed->GetSteeringLeftRight() != 0.0f - || padUsed->GetBrake() != 0.0f)) { + if (m_pMyVehicle->m_nGettingOutFlags & CAR_DOOR_FLAG_LF || rollDoorAssoc || (rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR_LOW))) { if (rollDoorAssoc) m_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, rollDoorAssoc->currentTime); + } else { - m_pMyVehicle->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF; - if (m_pMyVehicle->bLowVehicle) - rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR_LOW); - else - rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR); + // These comparisons are wrong, they return uint16 + if (padUsed && (padUsed->GetAccelerate() != 0.0f || padUsed->GetSteeringLeftRight() != 0.0f || padUsed->GetBrake() != 0.0f)) { + if (rollDoorAssoc) + m_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, rollDoorAssoc->currentTime); + + } else { + m_pMyVehicle->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF; + if (m_pMyVehicle->bLowVehicle) + rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR_LOW); + else + rollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ROLLDOOR); - rollDoorAssoc->SetFinishCallback(PedAnimDoorCloseRollingCB, this); + rollDoorAssoc->SetFinishCallback(PedAnimDoorCloseRollingCB, this); + } } } return; @@ -1338,12 +1328,18 @@ CPlayerPed::ProcessControl(void) case PED_FIGHT: case PED_AIM_GUN: if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK)) { - if (TheCamera.Cams[0].Using3rdPersonMouseCam()) { + if (TheCamera.Cams[0].Using3rdPersonMouseCam() +#ifdef FREE_CAM + && !CCamera::bFreeCam +#endif + ) { if (padUsed) PlayerControl1stPersonRunAround(padUsed); + } else if (m_nPedState == PED_FIGHT) { if (padUsed) PlayerControlFighter(padUsed); + } else if (padUsed) { PlayerControlZelda(padUsed); } @@ -1415,6 +1411,7 @@ CPlayerPed::ProcessControl(void) if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) { if (padUsed) PlayerControlM16(padUsed); + } else if (padUsed) { PlayerControlSniper(padUsed); } @@ -1477,20 +1474,17 @@ CPlayerPed::ProcessControl(void) m_lookTimer = 0; float camAngle = CGeneral::LimitRadianAngle(TheCamera.Cams[TheCamera.ActiveCam].Front.Heading()); float angleBetweenPlayerAndCam = Abs(camAngle - m_fRotationCur); - if (m_nPedState != PED_ATTACK - && angleBetweenPlayerAndCam > DEGTORAD(30.0f) && angleBetweenPlayerAndCam < DEGTORAD(330.0f)) { + if (m_nPedState != PED_ATTACK && angleBetweenPlayerAndCam > DEGTORAD(30.0f) && angleBetweenPlayerAndCam < DEGTORAD(330.0f)) { if (angleBetweenPlayerAndCam > DEGTORAD(150.0f) && angleBetweenPlayerAndCam < DEGTORAD(210.0f)) { float rightTurnAngle = CGeneral::LimitRadianAngle(m_fRotationCur - DEGTORAD(150.0f)); float leftTurnAngle = CGeneral::LimitRadianAngle(DEGTORAD(150.0f) + m_fRotationCur); - if (m_fLookDirection != 999999.0f) { - if (Abs(rightTurnAngle - m_fLookDirection) < Abs(leftTurnAngle - m_fLookDirection)) - camAngle = rightTurnAngle; - else - camAngle = leftTurnAngle; - } else { + if (m_fLookDirection == 999999.0f) camAngle = rightTurnAngle; - } + else if (Abs(rightTurnAngle - m_fLookDirection) < Abs(leftTurnAngle - m_fLookDirection)) + camAngle = rightTurnAngle; + else + camAngle = leftTurnAngle; } SetLookFlag(camAngle, true); SetLookTimer(CTimer::GetTimeStepInMilliseconds() * 5.0f); -- cgit v1.2.3 From 82c40b73ca4a4e67e0e53a34caac546f012fe54d Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 12 Dec 2020 20:35:17 +0300 Subject: fixed a bug --- src/control/CarCtrl.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 520efe75..cb4229eb 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -2338,7 +2338,11 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv switch (pVehicle->AutoPilot.m_nDrivingStyle) { case DRIVINGSTYLE_STOP_FOR_CARS: case DRIVINGSTYLE_SLOW_DOWN_FOR_CARS: - speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle) / pVehicle->AutoPilot.m_nCruiseSpeed; + speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle); +#ifdef FIX_BUGS + if (pVehicle->AutoPilot.m_nCruiseSpeed != 0) +#endif + speedStyleMultiplier /= pVehicle->AutoPilot.m_nCruiseSpeed; break; default: speedStyleMultiplier = 1.0f; -- cgit v1.2.3 From c74f03b180c99b92ab68f999ab63a5e70b4b3ae0 Mon Sep 17 00:00:00 2001 From: erorcun Date: Sat, 12 Dec 2020 20:35:54 +0300 Subject: Kill obj. fix & style change --- src/peds/PedAI.cpp | 71 +++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp index 62b27134..8c066b8f 100644 --- a/src/peds/PedAI.cpp +++ b/src/peds/PedAI.cpp @@ -1015,14 +1015,14 @@ CPed::ProcessObjective(void) // I hope so CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); CVector maxShotPos = vehOfTarget->GetPosition() - ourHead; - maxShotPos.Normalise(); - maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead; + maxShotPos *= wepInfo->m_fRange / maxShotPos.Magnitude(); + maxShotPos += ourHead; - CWorld::bIncludeDeadPeds = true; CColPoint foundCol; CEntity *foundEnt; - CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, - true, true, true, true, false, true, false); + + CWorld::bIncludeDeadPeds = true; + CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, true, true, true, true, false, true, false); CWorld::bIncludeDeadPeds = false; if (foundEnt == vehOfTarget) { SetAttack(vehOfTarget); @@ -1038,8 +1038,7 @@ CPed::ProcessObjective(void) SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); } } - } - else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) { + } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) { if (vehOfTarget) { if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) { GoToNearestDoor(vehOfTarget); @@ -1152,17 +1151,15 @@ CPed::ProcessObjective(void) target = m_pedInObjective->GetPosition(); target -= ourHead; - target.Normalise(); - target = target * wepInfo->m_fRange + ourHead; + target *= wepInfo->m_fRange / target.Magnitude(); + target += ourHead; - CWorld::bIncludeDeadPeds = true; - CEntity *foundEnt = nil; CColPoint foundCol; + CEntity *foundEnt = nil; - CWorld::ProcessLineOfSight( - ourHead, target, foundCol, foundEnt, - true, true, true, false, true, false); - CWorld::bIncludeDeadPeds = 0; + CWorld::bIncludeDeadPeds = true; + CWorld::ProcessLineOfSight(ourHead, target, foundCol, foundEnt, true, true, true, true, false, true, false); + CWorld::bIncludeDeadPeds = false; if (foundEnt == m_pedInObjective) { SetAttack(m_pedInObjective); m_pPointGunAt = m_pedInObjective; @@ -1180,25 +1177,27 @@ CPed::ProcessObjective(void) SetAttackTimer(time); bObstacleShowedUpDuringKillObjective = false; - } else if (foundEnt) { - if (foundEnt->IsPed()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); - bObstacleShowedUpDuringKillObjective = false; - } else { - if (foundEnt->IsObject()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f)); - bObstacleShowedUpDuringKillObjective = true; - } else if (foundEnt->IsVehicle()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f)); - bObstacleShowedUpDuringKillObjective = true; + } else { + if (foundEnt) { + if (foundEnt->IsPed()) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); + bObstacleShowedUpDuringKillObjective = false; } else { - SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f)); - bObstacleShowedUpDuringKillObjective = true; + if (foundEnt->IsObject()) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f)); + bObstacleShowedUpDuringKillObjective = true; + } else if (foundEnt->IsVehicle()) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f)); + bObstacleShowedUpDuringKillObjective = true; + } else { + SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f)); + bObstacleShowedUpDuringKillObjective = true; + } } - } - m_fleeFrom = foundEnt; - m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom); + m_fleeFrom = foundEnt; + m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom); + } SetPointGunAt(m_pedInObjective); } } @@ -1541,14 +1540,14 @@ CPed::ProcessObjective(void) // I hope so CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); CVector maxShotPos = m_carInObjective->GetPosition() - ourHead; - maxShotPos.Normalise(); - maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead; + maxShotPos *= wepInfo->m_fRange / maxShotPos.Magnitude(); + maxShotPos += ourHead; - CWorld::bIncludeDeadPeds = true; CColPoint foundCol; CEntity *foundEnt; - CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, - true, true, true, true, false, true, false); + + CWorld::bIncludeDeadPeds = true; + CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, true, true, true, true, false, true, false); CWorld::bIncludeDeadPeds = false; if (foundEnt == m_carInObjective) { SetAttack(m_carInObjective); -- cgit v1.2.3 From 01c95378e1cffe7ef09f44d992a0144d9a5691a4 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 12 Dec 2020 23:05:12 +0300 Subject: fixed some replay bugs --- src/control/Garages.h | 3 +++ src/control/Replay.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- src/control/Replay.h | 5 +++++ src/core/Fire.cpp | 6 +++++- src/peds/PedAI.cpp | 8 +++++++- 5 files changed, 61 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/control/Garages.h b/src/control/Garages.h index 79cef36e..34b74fb6 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -251,4 +251,7 @@ private: friend class cAudioManager; friend class CGarage; +#ifdef FIX_BUGS + friend class CReplay; +#endif }; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 757af0a9..4732ba2f 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -10,6 +10,10 @@ #include "DMAudio.h" #include "Draw.h" #include "FileMgr.h" +#ifdef FIX_BUGS +#include "Fire.h" +#include "Garages.h" +#endif #include "Heli.h" #include "main.h" #include "Matrix.h" @@ -22,6 +26,10 @@ #include "Plane.h" #include "Pools.h" #include "Population.h" +#ifdef FIX_BUGS +#include "Projectile.h" +#include "ProjectileInfo.h" +#endif #include "Replay.h" #include "References.h" #include "Pools.h" @@ -102,6 +110,11 @@ float CReplay::fDistanceLookAroundCam; float CReplay::fBetaAngleLookAroundCam; float CReplay::fAlphaAngleLookAroundCam; #ifdef FIX_BUGS +uint8* CReplay::pGarages; +CFire* CReplay::FireArray; +uint32 CReplay::NumOfFires; +uint8* CReplay::paProjectileInfo; +uint8* CReplay::paProjectiles; int CReplay::nHandleOfPlayerPed[NUMPLAYERS]; #endif @@ -1156,6 +1169,17 @@ void CReplay::StoreStuffInMem(void) if (ped) StoreDetailedPedAnimation(ped, &pPedAnims[i]); } +#ifdef FIX_BUGS + pGarages = new uint8[sizeof(CGarages::aGarages)]; + memcpy(pGarages, CGarages::aGarages, sizeof(CGarages::aGarages)); + FireArray = new CFire[NUM_FIRES]; + memcpy(FireArray, gFireManager.m_aFires, sizeof(gFireManager.m_aFires)); + NumOfFires = gFireManager.m_nTotalFires; + paProjectileInfo = new uint8[sizeof(gaProjectileInfo)]; + memcpy(paProjectileInfo, gaProjectileInfo, sizeof(gaProjectileInfo)); + paProjectiles = new uint8[sizeof(CProjectileInfo::ms_apProjectile)]; + memcpy(paProjectiles, CProjectileInfo::ms_apProjectile, sizeof(CProjectileInfo::ms_apProjectile)); +#endif } void CReplay::RestoreStuffFromMem(void) @@ -1206,7 +1230,7 @@ void CReplay::RestoreStuffFromMem(void) ped->m_rwObject = nil; ped->m_modelIndex = -1; ped->SetModelIndex(mi); - ped->m_pVehicleAnim = 0; + ped->m_pVehicleAnim = nil; ped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped); DMAudio.SetEntityStatus(ped->m_audioEntityId, true); CPopulation::UpdatePedCount((ePedType)ped->m_nPedType, false); @@ -1322,6 +1346,22 @@ void CReplay::RestoreStuffFromMem(void) } delete[] pPedAnims; pPedAnims = nil; +#ifdef FIX_BUGS + memcpy(CGarages::aGarages, pGarages, sizeof(CGarages::aGarages)); + delete[] pGarages; + pGarages = nil; + memcpy(gFireManager.m_aFires, FireArray, sizeof(gFireManager.m_aFires)); + delete[] FireArray; + FireArray = nil; + gFireManager.m_nTotalFires = NumOfFires; + memcpy(gaProjectileInfo, paProjectileInfo, sizeof(gaProjectileInfo)); + delete[] paProjectileInfo; + paProjectileInfo = nil; + memcpy(CProjectileInfo::ms_apProjectile, paProjectiles, sizeof(CProjectileInfo::ms_apProjectile)); + delete[] paProjectiles; + paProjectiles = nil; + //CExplosion::ClearAllExplosions(); not in III +#endif DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); DMAudio.SetRadioInCar(OldRadioStation); DMAudio.ChangeMusicMode(MUSICMODE_GAME); diff --git a/src/control/Replay.h b/src/control/Replay.h index cb58a602..aa2ecd86 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -275,6 +275,11 @@ private: static float fAlphaAngleLookAroundCam; static float fBetaAngleLookAroundCam; #ifdef FIX_BUGS + static uint8* pGarages; + static CFire* FireArray; + static uint32 NumOfFires; + static uint8* paProjectileInfo; + static uint8* paProjectiles; static int nHandleOfPlayerPed[NUMPLAYERS]; #endif diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index c6dece6a..e1be4194 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -90,7 +90,11 @@ CFire::ProcessFire(void) } } } - if (!FindPlayerVehicle() && !FindPlayerPed()->m_pFire && !(FindPlayerPed()->bFireProof) + if (!FindPlayerVehicle() && +#ifdef FIX_BUGS + FindPlayerPed() && +#endif + !FindPlayerPed()->m_pFire && !(FindPlayerPed()->bFireProof) && ((FindPlayerPed()->GetPosition() - m_vecPos).MagnitudeSqr() < 2.0f)) { FindPlayerPed()->DoStuffToGoOnFire(); gFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1); diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp index 62b27134..367c876c 100644 --- a/src/peds/PedAI.cpp +++ b/src/peds/PedAI.cpp @@ -2990,9 +2990,15 @@ CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) } if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) { - // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa? +#ifdef FIX_BUGS + if (!veh->IsDoorMissing(door)) + ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); + PedSetOutCarCB(nil, ped); + return; +#else if (!veh->IsDoorMissing(door)) ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING); +#endif } else { switch (door) { case DOOR_FRONT_LEFT: -- cgit v1.2.3 From 8fb461b873580fd48539abc26368b7b8082eec3a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 13 Dec 2020 00:20:44 +0300 Subject: removed obsolete ifdef (since we have GTA_REPLAY) --- src/control/Garages.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index ff11600b..07fc0612 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -179,10 +179,8 @@ void CGarages::Shutdown(void) void CGarages::Update(void) { static int GarageToBeTidied = 0; -#ifndef GTA_PS2 if (CReplay::IsPlayingBack()) return; -#endif bCamShouldBeOutisde = false; TheCamera.pToGarageWeAreIn = nil; TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = nil; -- cgit v1.2.3 From 9be5bfe75bbfa6d334656fbc27cfafdeef1eb300 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 13 Dec 2020 12:58:15 +0100 Subject: sync vis-plugins with miami --- src/rw/VisibilityPlugins.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index b27d96c8..21e00725 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -203,6 +203,10 @@ CVisibilityPlugins::InsertAtomicIntoSortedList(RpAtomic *a, float dist) return ret; } +// can't increase this yet unfortunately... +// probably have to fix fading for this so material alpha isn't overwritten +#define VEHICLE_LODDIST_MULTIPLIER (TheCamera.GenerationDistMultiplier) + void CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera) { @@ -215,11 +219,11 @@ CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera) else ms_cullCompsDist = sq(TheCamera.LODDistMultiplier * 20.0f); - ms_vehicleLod0Dist = sq(70.0f * TheCamera.GenerationDistMultiplier); - ms_vehicleLod1Dist = sq(90.0f * TheCamera.GenerationDistMultiplier); - ms_vehicleFadeDist = sq(100.0f * TheCamera.GenerationDistMultiplier); - ms_bigVehicleLod0Dist = sq(60.0f * TheCamera.GenerationDistMultiplier); - ms_bigVehicleLod1Dist = sq(150.0f * TheCamera.GenerationDistMultiplier); + ms_vehicleLod0Dist = sq(70.0f * VEHICLE_LODDIST_MULTIPLIER); + ms_vehicleLod1Dist = sq(90.0f * VEHICLE_LODDIST_MULTIPLIER); + ms_vehicleFadeDist = sq(100.0f * VEHICLE_LODDIST_MULTIPLIER); + ms_bigVehicleLod0Dist = sq(60.0f * VEHICLE_LODDIST_MULTIPLIER); + ms_bigVehicleLod1Dist = sq(150.0f * VEHICLE_LODDIST_MULTIPLIER); ms_pedLod0Dist = sq(25.0f * TheCamera.LODDistMultiplier); ms_pedLod1Dist = sq(60.0f * TheCamera.LODDistMultiplier); ms_pedFadeDist = sq(70.0f * TheCamera.LODDistMultiplier); @@ -311,7 +315,12 @@ CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic) m = RwFrameGetLTM(RpAtomicGetFrame(atomic)); RwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn); len = RwV3dLength(&view); +#ifdef FIX_BUGS + // from VC + lodatm = mi->GetAtomicFromDistance(len * TheCamera.LODDistMultiplier / VEHICLE_LODDIST_MULTIPLIER); +#else lodatm = mi->GetAtomicFromDistance(len); +#endif if(lodatm){ if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic)) RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE); -- cgit v1.2.3 From 0448ae662fd777f7640a0f4486a731a6269e1997 Mon Sep 17 00:00:00 2001 From: erorcun Date: Mon, 14 Dec 2020 02:46:55 +0300 Subject: Fix language initialization call order --- src/skel/glfw/glfw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index b7c4810e..93bfde5a 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1202,15 +1202,15 @@ void InitialiseLanguage() } } - TheText.Unload(); - TheText.Load(); - #ifndef _WIN32 // TODO this is needed for strcasecmp to work correctly across all languages, but can these cause other problems?? setlocale(LC_CTYPE, "C"); setlocale(LC_COLLATE, "C"); setlocale(LC_NUMERIC, "C"); #endif + + TheText.Unload(); + TheText.Load(); } /* -- cgit v1.2.3 From f42a01f653c860b5df3cfdbe34cc37f25dc3c36a Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 14 Dec 2020 09:47:07 +0200 Subject: CPed::SetWeaponLockOnTarget --- src/control/RoadBlocks.cpp | 3 +-- src/peds/CopPed.cpp | 7 ++----- src/peds/Ped.h | 7 +++++++ src/peds/PedAI.cpp | 19 ++++--------------- src/peds/PlayerPed.cpp | 16 ++++++---------- 5 files changed, 20 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 1496b307..170c5ff8 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -90,8 +90,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType pCopPed->m_nRoadblockNode = roadBlockNode; pCopPed->bCrouchWhenShooting = roadBlockType != 2; if (pEntityToAttack) { - pCopPed->m_pPointGunAt = pEntityToAttack; - pEntityToAttack->RegisterReference(&pCopPed->m_pPointGunAt); + pCopPed->SetWeaponLockOnTarget(pEntityToAttack); pCopPed->SetAttack(pEntityToAttack); } pCopPed->m_pMyVehicle = pVehicle; diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index d9f55559..de7b8ad2 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -69,7 +69,7 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP) m_bStopAndShootDisabledZone = false; m_bZoneDisabled = false; field_1364 = -1; - m_pPointGunAt = nil; + SetWeaponLockOnTarget(nil); // VC also initializes in here, but as nil #ifdef FIX_BUGS @@ -472,10 +472,7 @@ CCopPed::CopAI(void) if (!CWorld::ProcessLineOfSight(gunPos, playerOrHisVeh->GetPosition(), foundCol, foundEnt, false, true, false, false, true, false, false) || foundEnt && foundEnt == playerOrHisVeh) { - m_pPointGunAt = playerOrHisVeh; - if (playerOrHisVeh) - playerOrHisVeh->RegisterReference((CEntity**) &m_pPointGunAt); - + SetWeaponLockOnTarget(playerOrHisVeh); SetAttack(playerOrHisVeh); SetShootTimer(CGeneral::GetRandomNumberInRange(500, 1000)); } diff --git a/src/peds/Ped.h b/src/peds/Ped.h index f8e619d7..0e398b25 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -863,6 +863,13 @@ public: SetMoveState(PEDMOVE_WALK); } + inline void SetWeaponLockOnTarget(CEntity *target) + { + m_pPointGunAt = (CPed *)target; + if(target) + ((CEntity *)target)->RegisterReference(&m_pPointGunAt); + } + // Using this to abstract nodes of skinned and non-skinned meshes CVector GetNodePosition(int32 node) { diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp index f1d16119..5eaf8cd8 100644 --- a/src/peds/PedAI.cpp +++ b/src/peds/PedAI.cpp @@ -620,9 +620,7 @@ CPed::UpdateFromLeader(void) m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); TurnBody(); if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) { - m_pPointGunAt = m_threatEntity; - if (m_threatEntity) - m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt); + SetWeaponLockOnTarget(m_threatEntity); SetAttack(m_threatEntity); } } @@ -1026,10 +1024,7 @@ CPed::ProcessObjective(void) CWorld::bIncludeDeadPeds = false; if (foundEnt == vehOfTarget) { SetAttack(vehOfTarget); - m_pPointGunAt = vehOfTarget; - if (vehOfTarget) - vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt); - + SetWeaponLockOnTarget(vehOfTarget); SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); if (distWithTargetSc <= m_distanceToCountSeekDone) { SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500)); @@ -1162,10 +1157,7 @@ CPed::ProcessObjective(void) CWorld::bIncludeDeadPeds = false; if (foundEnt == m_pedInObjective) { SetAttack(m_pedInObjective); - m_pPointGunAt = m_pedInObjective; - if (m_pedInObjective) - m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt); - + SetWeaponLockOnTarget(m_pedInObjective); SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f)); int time; @@ -1551,10 +1543,7 @@ CPed::ProcessObjective(void) CWorld::bIncludeDeadPeds = false; if (foundEnt == m_carInObjective) { SetAttack(m_carInObjective); - m_pPointGunAt = m_carInObjective; - if (m_pPointGunAt) - m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt); - + SetWeaponLockOnTarget(m_carInObjective); SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) { SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index f23aa378..ef9cf201 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -47,8 +47,8 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) m_nSelectedWepSlot = WEAPONTYPE_UNARMED; m_nSpeedTimer = 0; m_bSpeedTimerFlag = false; - m_pPointGunAt = nil; - m_nPedState = PED_IDLE; + SetWeaponLockOnTarget(nil); + SetPedState(PED_IDLE); #ifndef FIX_BUGS m_fCurrentStamina = m_fMaxStamina = 150.0f; #endif @@ -73,7 +73,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) void CPlayerPed::ClearWeaponTarget() { if (m_nPedType == PEDTYPE_PLAYER1) { - m_pPointGunAt = nil; + SetWeaponLockOnTarget(nil); TheCamera.ClearPlayerWeaponMode(); CWeaponEffects::ClearCrossHair(); } @@ -875,9 +875,7 @@ CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft) if (!nextTarget) return false; - m_pPointGunAt = nextTarget; - if (nextTarget) - nextTarget->RegisterReference((CEntity**)&m_pPointGunAt); + SetWeaponLockOnTarget(nextTarget); SetPointGunAt(nextTarget); return true; } @@ -891,7 +889,7 @@ CPlayerPed::FindWeaponLockOnTarget(void) if (m_pPointGunAt) { CVector distVec = m_pPointGunAt->GetPosition() - GetPosition(); if (distVec.Magnitude2D() > weaponRange) { - m_pPointGunAt = nil; + SetWeaponLockOnTarget(nil); return false; } else { return true; @@ -922,9 +920,7 @@ CPlayerPed::FindWeaponLockOnTarget(void) if (!nextTarget) return false; - m_pPointGunAt = nextTarget; - if (nextTarget) - nextTarget->RegisterReference((CEntity**)&m_pPointGunAt); + SetWeaponLockOnTarget(nextTarget); SetPointGunAt(nextTarget); return true; } -- cgit v1.2.3 From 0563478de049c5d3c23656b872c14ae6f6d7eeef Mon Sep 17 00:00:00 2001 From: Seemann Date: Mon, 14 Dec 2020 01:52:49 -0500 Subject: Fix some formatting issues --- src/control/Script.cpp | 12 ++++++------ src/control/Script3.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 1b51e0d6..67d2e618 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -238,12 +238,12 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_DIV_FLOAT_VAR_BY_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " /="), REGISTER_COMMAND(COMMAND_DIV_INT_LVAR_BY_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " /="), REGISTER_COMMAND(COMMAND_DIV_FLOAT_LVAR_BY_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " /="), - REGISTER_COMMAND(COMMAND_ADD_TIMED_VAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), - REGISTER_COMMAND(COMMAND_ADD_TIMED_VAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), - REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), - REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), - REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), - REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), + REGISTER_COMMAND(COMMAND_ADD_TIMED_VAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " +=@"), + REGISTER_COMMAND(COMMAND_ADD_TIMED_VAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " +=@"), + REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " +=@"), + REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " +=@"), + REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " +=@"), + REGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " +=@"), REGISTER_COMMAND(COMMAND_SUB_TIMED_VAL_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), REGISTER_COMMAND(COMMAND_SUB_TIMED_VAL_FROM_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), REGISTER_COMMAND(COMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " -=@"), diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp index 38bcb2ec..1f1ed537 100644 --- a/src/control/Script3.cpp +++ b/src/control/Script3.cpp @@ -996,7 +996,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) CollectParameters(&m_nIp, 4); int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index; CObject* pObj = new CObject(mi, false); -; pObj->ObjectCreatedBy = MISSION_OBJECT; + pObj->ObjectCreatedBy = MISSION_OBJECT; CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); -- cgit v1.2.3 From 3b8ac474a20d7b94049cfb5ae36a9f317176278c Mon Sep 17 00:00:00 2001 From: shfil Date: Mon, 14 Dec 2020 15:33:16 +0100 Subject: Implement COMMAND_IS_CAR_PASSENGER_SEAT_FREE Fixes 881 --- src/control/Script6.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp index acd9e424..c2937e1d 100644 --- a/src/control/Script6.cpp +++ b/src/control/Script6.cpp @@ -545,7 +545,14 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CStats::RegisterHighestScore(ScriptParams[0], ScriptParams[1]); return 0; //case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER: - //case COMMAND_IS_CAR_PASSENGER_SEAT_FREE: + case COMMAND_IS_CAR_PASSENGER_SEAT_FREE: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + script_assert(pVehicle); + UpdateCompareFlag(ScriptParams[1] < pVehicle->m_nNumMaxPassengers && pVehicle->pPassengers[ScriptParams[1]] == nil); + return 0; + } case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT: { CollectParameters(&m_nIp, 2); -- cgit v1.2.3 From 7be7845db00f5ee933479b2716af66066f80d0dc Mon Sep 17 00:00:00 2001 From: withmorten Date: Mon, 14 Dec 2020 23:30:07 +0100 Subject: add dev build code for generating waterpro.dat --- src/render/WaterLevel.cpp | 365 +++++++++++++++++++++++++++++++++++++++++----- src/render/WaterLevel.h | 11 +- 2 files changed, 339 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index ecfccc90..ef5c4c58 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "main.h" #include "FileMgr.h" +#include "FileLoader.h" #include "TxdStore.h" #include "Timer.h" #include "Weather.h" @@ -30,8 +31,8 @@ float TEXTURE_ADDV; int32 CWaterLevel::ms_nNoOfWaterLevels; float CWaterLevel::ms_aWaterZs[48]; CRect CWaterLevel::ms_aWaterRects[48]; -uint8 CWaterLevel::aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; -uint8 CWaterLevel::aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; +int8 CWaterLevel::aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; +int8 CWaterLevel::aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; bool CWaterLevel::WavesCalculatedThisFrame; RpAtomic *CWaterLevel::ms_pWavyAtomic; RpGeometry *CWaterLevel::apGeomArray[8]; @@ -58,28 +59,158 @@ void CWaterLevel::Initialise(Const char *pWaterDat) { ms_nNoOfWaterLevels = 0; - + +#ifdef MASTER int32 hFile = -1; - - do + + while ((hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb")) < 0); +#else + int32 hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb"); +#endif + + if (hFile > 0) { - hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb"); + CFileMgr::Read(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels)); + CFileMgr::Read(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs)); + CFileMgr::Read(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects)); + CFileMgr::Read(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList)); + CFileMgr::Read(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList)); + + CFileMgr::CloseFile(hFile); } - while ( hFile < 0 ); - - if ( hFile > 0 ) +#ifndef MASTER + else { - if ( hFile >= 0 ) + printf("Init waterlevels\n"); + + CFileMgr::SetDir(""); + hFile = CFileMgr::OpenFile(pWaterDat, "r"); + + char *line; + + while ((line = CFileLoader::LoadLine(hFile))) { - CFileMgr::Read(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels)); - CFileMgr::Read(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs)); - CFileMgr::Read(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects)); - CFileMgr::Read(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList)); - CFileMgr::Read(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList)); + if (*line && *line != ';') + { + float z, l, b, r, t; + sscanf(line, "%f %f %f %f %f", &z, &l, &b, &r, &t); + AddWaterLevel(l, b, r, t, z); + } } - + CFileMgr::CloseFile(hFile); + + for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + { + for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + { + aWaterFineBlockList[x][y] = NO_WATER; + } + } + + for (int32 i = 0; i < ms_nNoOfWaterLevels; i++) + { + int32 l = WATER_HUGE_X(ms_aWaterRects[i].left); + int32 r = WATER_HUGE_X(ms_aWaterRects[i].right) + 1.0f; + int32 t = WATER_HUGE_Y(ms_aWaterRects[i].top); + int32 b = WATER_HUGE_Y(ms_aWaterRects[i].bottom) + 1.0f; + + // originally this writes *god* knows where everywhere in game memory ... + // even in debug it manages to reach some textures so librw crashes with a ptr being 0x15151515 .... +#ifdef FIX_BUGS + l = clamp(l, 0, WATER_FINEBLOCK_SIZE - 1); + r = clamp(r, 0, WATER_FINEBLOCK_SIZE - 1); + t = clamp(t, 0, WATER_FINEBLOCK_SIZE - 1); + b = clamp(b, 0, WATER_FINEBLOCK_SIZE - 1); +#endif + + for (int32 x = l; x <= r; x++) + { + for (int32 y = t; y <= b; y++) + { + aWaterFineBlockList[x][y] = i; + } + } + } + + for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + { + int32 worldX = WATER_START_X + x * SMALL_SECTOR_WIDTH; + + for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + { + if (aWaterBlockList[x][y] >= 0) + { + int32 worldY = WATER_START_Y + y * SMALL_SECTOR_WIDTH; + + int32 i; + for (i = 0; i <= 8; i++) + { + for (int32 j = 0; j <= 8; j++) + { + CVector worldPos = CVector(worldX + i * (SMALL_SECTOR_WIDTH / 8), worldY + j * (SMALL_SECTOR_WIDTH / 8), ms_aWaterZs[aWaterFineBlockList[x][y]]); + + if ((worldPos.x > WORLD_MIN_X && worldPos.x < WORLD_MAX_X) && (worldPos.y > WORLD_MIN_Y && worldPos.y < WORLD_MAX_Y)) + { + if (WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) && !TestVisibilityForFineWaterBlocks(worldPos)) + { + i = 1000; + break; + } + } + } + + if (i == 1000) break; + } + + if (i < 1000) aWaterFineBlockList[x][y] = NO_WATER; + } + } + } + + RemoveIsolatedWater(); + + for (int32 x = 0; x < WATER_BLOCK_SIZE; x++) + { + for (int32 y = 0; y < WATER_BLOCK_SIZE; y++) + { + if (aWaterFineBlockList[x * 2][y * 2] >= 0) + { + aWaterBlockList[x][y] = aWaterFineBlockList[x * 2][y * 2]; + } + else if (aWaterFineBlockList[x * 2 + 1][y * 2] >= 0) + { + aWaterBlockList[x][y] = aWaterFineBlockList[x * 2 + 1][y * 2]; + } + else if (aWaterFineBlockList[x * 2][y * 2 + 1] >= 0) + { + aWaterBlockList[x][y] = aWaterFineBlockList[x * 2][y * 2 + 1]; + } + else if (aWaterFineBlockList[x * 2 + 1][y * 2 + 1] >= 0) + { + aWaterBlockList[x][y] = aWaterFineBlockList[x * 2 + 1][y * 2 + 1]; + } + else + { + aWaterBlockList[x][y] = NO_WATER; + } + } + } + + hFile = CFileMgr::OpenFileForWriting("data\\waterpro.dat"); + + if (hFile > 0) + { + CFileMgr::Write(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels)); + CFileMgr::Write(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs)); + CFileMgr::Write(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects)); + CFileMgr::Write(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList)); + CFileMgr::Write(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList)); + + CFileMgr::CloseFile(hFile); + } } +#endif CTxdStore::PushCurrentTxd(); @@ -222,6 +353,170 @@ CWaterLevel::DestroyWavyAtomic() RwFrameDestroy(frame); } +#ifndef MASTER +void +CWaterLevel::AddWaterLevel(float fXLeft, float fYBottom, float fXRight, float fYTop, float fLevel) +{ + ms_aWaterRects[ms_nNoOfWaterLevels] = CRect(fXLeft, fYBottom, fXRight, fYTop); + ms_aWaterZs[ms_nNoOfWaterLevels] = fLevel; + ms_nNoOfWaterLevels++; +} + +bool +CWaterLevel::WaterLevelAccordingToRectangles(float fX, float fY, float *pfOutLevel) +{ + if (ms_nNoOfWaterLevels <= 0) return false; + + for (int32 i = 0; i < ms_nNoOfWaterLevels; i++) + { + if (fX >= ms_aWaterRects[i].left && fX <= ms_aWaterRects[i].right + && fY >= ms_aWaterRects[i].top && fY <= ms_aWaterRects[i].bottom) + { + if (pfOutLevel) *pfOutLevel = ms_aWaterZs[i]; + + return true; + } + } + + return false; +} + +bool +CWaterLevel::TestVisibilityForFineWaterBlocks(const CVector &worldPos) +{ + static CVector2D tab[] = + { + { 50.0f, 50.0f }, + { -50.0f, 50.0f }, + { -50.0f, -50.0f }, + { 50.0f, -50.0f }, + { 50.0f, 0.0f }, + { -50.0f, 0.0f }, + { 0.0f, -50.0f }, + { 0.0f, 50.0f }, + }; + + CEntity *entity; + CColPoint col; + CVector lineStart, lineEnd; + + lineStart = worldPos; + + if (!CWorld::ProcessVerticalLine(lineStart, lineStart.z + 100.0f, col, entity, true, false, false, false, true, false, nil)) + { + lineStart.x += 0.4f; + lineStart.y += 0.4f; + + if (!CWorld::ProcessVerticalLine(lineStart, lineStart.z + 100.0f, col, entity, true, false, false, false, true, false, nil)) + { + return false; + } + } + + for (int32 i = 0; i < ARRAY_SIZE(tab); i++) + { + lineStart = worldPos; + lineEnd = worldPos; + + lineEnd.x += tab[i].x; + lineEnd.y += tab[i].y; + lineEnd.z += 100.0f; + + if ((lineEnd.x > WORLD_MIN_X && lineEnd.x < WORLD_MAX_X) && (lineEnd.y > WORLD_MIN_Y && lineEnd.y < WORLD_MAX_Y)) + { + if (!CWorld::ProcessLineOfSight(lineStart, lineEnd, col, entity, true, false, false, false, true, false, nil)) + { + lineStart.x += 0.4f; + lineStart.y += 0.4f; + lineEnd.x += 0.4f; + lineEnd.y += 0.4f; + + if (!CWorld::ProcessLineOfSight(lineStart, lineEnd, col, entity, true, false, false, false, true, false, nil)) + { + return false; + } + } + } + } + + return true; +} + +void +CWaterLevel::RemoveIsolatedWater() +{ + bool (*isConnected)[WATER_FINEBLOCK_SIZE] = new bool[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; + + for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + { + for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + { + isConnected[x][y] = false; + } + } + + isConnected[0][0] = true; + bool keepGoing; + + do + { + keepGoing = false; + + for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + { + for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + { + if (aWaterBlockList[x][y] >= 0 && !isConnected[x][y]) + { + if (x > 0 && isConnected[x - 1][y]) + { + isConnected[x][y] = true; + keepGoing = true; + } + + if (y > 0 && isConnected[x][y - 1]) + { + isConnected[x][y] = true; + keepGoing = true; + } + + if (x + 1 < WATER_FINEBLOCK_SIZE && isConnected[x + 1][y]) + { + isConnected[x][y] = true; + keepGoing = true; + } + + if (y + 1 < WATER_FINEBLOCK_SIZE && isConnected[x][y + 1]) + { + isConnected[x][y] = true; + keepGoing = true; + } + } + } + } + } + while (keepGoing); + + int32 numRemoved = 0; + + for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + { + for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + { + if (aWaterBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] != 0.0f) + { + numRemoved++; + aWaterFineBlockList[x][y] = NO_WATER; + } + } + } + + printf("Removed %d isolated patches of water\n", numRemoved); + + delete[] isConnected; +} +#endif + bool CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ) { @@ -231,9 +526,9 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE ); ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE ); - uint8 nBlock = aWaterFineBlockList[x][y]; + int8 nBlock = aWaterFineBlockList[x][y]; - if ( nBlock == 128 ) + if ( nBlock == NO_WATER ) return false; ASSERT( pfOutLevel != NULL ); @@ -270,9 +565,9 @@ CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLeve ASSERT( x >= 0 && x < HUGE_SECTOR_SIZE ); ASSERT( y >= 0 && y < HUGE_SECTOR_SIZE ); - uint8 nBlock = aWaterFineBlockList[x][y]; + int8 nBlock = aWaterFineBlockList[x][y]; - if ( nBlock == 128 ) + if ( nBlock == NO_WATER ) return false; ASSERT( pfOutLevel != NULL ); @@ -418,10 +713,10 @@ CWaterLevel::RenderWater() { for ( int32 y = nStartY; y <= nEndY; y++ ) { - if ( !(aWaterBlockList[2*x+0][2*y+0] & 128) - || !(aWaterBlockList[2*x+1][2*y+0] & 128) - || !(aWaterBlockList[2*x+0][2*y+1] & 128) - || !(aWaterBlockList[2*x+1][2*y+1] & 128) ) + if ( aWaterBlockList[2*x+0][2*y+0] >= 0 + || aWaterBlockList[2*x+1][2*y+0] >= 0 + || aWaterBlockList[2*x+0][2*y+1] >= 0 + || aWaterBlockList[2*x+1][2*y+1] >= 0 ) { float fX = WATER_FROM_HUGE_SECTOR_X(x); float fY = WATER_FROM_HUGE_SECTOR_Y(y); @@ -443,16 +738,16 @@ CWaterLevel::RenderWater() { float fZ; - if ( !(aWaterBlockList[2*x+0][2*y+0] & 128) ) + if ( aWaterBlockList[2*x+0][2*y+0] >= 0 ) fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ]; - if ( !(aWaterBlockList[2*x+1][2*y+0] & 128) ) + if ( aWaterBlockList[2*x+1][2*y+0] >= 0 ) fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ]; - if ( !(aWaterBlockList[2*x+0][2*y+1] & 128) ) + if ( aWaterBlockList[2*x+0][2*y+1] >= 0 ) fZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ]; - if ( !(aWaterBlockList[2*x+1][2*y+1] & 128) ) + if ( aWaterBlockList[2*x+1][2*y+1] >= 0 ) fZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ]; RenderOneFlatHugeWaterPoly(fX, fY, fZ, color); @@ -463,7 +758,7 @@ CWaterLevel::RenderWater() { for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ ) { - if ( !(aWaterBlockList[x2][y2] & 128) ) + if ( aWaterBlockList[x2][y2] >= 0 ) { float fLargeX = WATER_FROM_LARGE_SECTOR_X(x2); float fLargeY = WATER_FROM_LARGE_SECTOR_Y(y2); @@ -498,7 +793,7 @@ CWaterLevel::RenderWater() float fZ; // WS - if ( !(aWaterFineBlockList[2*x2+0][2*y2+0] & 128) ) + if ( aWaterFineBlockList[2*x2+0][2*y2+0] >= 0 ) { float fSmallX = fLargeX; float fSmallY = fLargeY; @@ -519,7 +814,7 @@ CWaterLevel::RenderWater() } // SE - if ( !(aWaterFineBlockList[2*x2+1][2*y2+0] & 128) ) + if ( aWaterFineBlockList[2*x2+1][2*y2+0] >= 0 ) { float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2); float fSmallY = fLargeY; @@ -540,7 +835,7 @@ CWaterLevel::RenderWater() } // WN - if ( !(aWaterFineBlockList[2*x2+0][2*y2+1] & 128) ) + if ( aWaterFineBlockList[2*x2+0][2*y2+1] >= 0 ) { float fSmallX = fLargeX; float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2); @@ -561,7 +856,7 @@ CWaterLevel::RenderWater() } //NE - if ( !(aWaterFineBlockList[2*x2+1][2*y2+1] & 128) ) + if ( aWaterFineBlockList[2*x2+1][2*y2+1] >= 0 ) { float fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2); float fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2); @@ -591,7 +886,7 @@ CWaterLevel::RenderWater() } } // if ( TheCamera.IsSphereVisible } // if ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr ) - } // if ( !(aWaterBlockList[x2][y2] & 128) ) + } // if ( aWaterBlockList[x2][y2] >= 0 ) } // for ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ ) } // for ( int32 x2 = 2*x; x2 <= 2*x+1; x2++ ) // @@ -1116,7 +1411,7 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY) { for ( int32 y = nStartY; y <= nEndY; y++ ) { - if ( !(aWaterFineBlockList[x][y] & 128) ) + if ( aWaterFineBlockList[x][y] >= 0 ) { float fSectorX = WATER_FROM_SMALL_SECTOR_X(x); float fSectorY = WATER_FROM_SMALL_SECTOR_Y(y); diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h index 269d6091..cff1a995 100644 --- a/src/render/WaterLevel.h +++ b/src/render/WaterLevel.h @@ -4,6 +4,8 @@ #define WATER_FINEBLOCK_SIZE HUGE_SECTOR_SIZE #define WATER_Z_OFFSET (1.5f) +#define NO_WATER -128 + #define MAX_SMALL_SECTORS 128 #define MAX_LARGE_SECTORS 64 #define MAX_HUGE_SECTORS 32 @@ -23,6 +25,7 @@ #define WATER_WIDTH ((WATER_END_X - WATER_START_X)) #define WATER_HEIGHT ((WATER_END_Y - WATER_START_Y)) +#define SMALL_SECTOR_WIDTH (WATER_WIDTH/MAX_SMALL_SECTORS) #define WATER_UNSIGN_X(x) ( (x) + (WATER_WIDTH /2) ) #define WATER_UNSIGN_Y(y) ( (y) + (WATER_HEIGHT/2) ) @@ -72,8 +75,8 @@ class CWaterLevel static int32 ms_nNoOfWaterLevels; static float ms_aWaterZs[48]; static CRect ms_aWaterRects[48]; - static uint8 aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; - static uint8 aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; + static int8 aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; + static int8 aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; static bool WavesCalculatedThisFrame; static RpAtomic *ms_pWavyAtomic; static RpGeometry *apGeomArray[MAX_BOAT_WAKES]; @@ -84,6 +87,10 @@ public: static void Shutdown(); static void CreateWavyAtomic(); static void DestroyWavyAtomic(); + static void AddWaterLevel(float fXLeft, float fYBottom, float fXRight, float fYTop, float fLevel); + static bool WaterLevelAccordingToRectangles(float fX, float fY, float *pfOutLevel = nil); + static bool TestVisibilityForFineWaterBlocks(const CVector &worldPos); + static void RemoveIsolatedWater(); static bool GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ); static bool GetWaterLevel(CVector coors, float *pfOutLevel, bool bDontCheckZ) { return GetWaterLevel(coors.x, coors.y, coors.z, pfOutLevel, bDontCheckZ); } static bool GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel); -- cgit v1.2.3 From f76dfaee82c0573518d247f7d5666151ccfed765 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 15 Dec 2020 05:11:02 +0200 Subject: Use SetPedState --- src/control/Phones.cpp | 6 +-- src/control/Script5.cpp | 2 +- src/core/Fire.cpp | 4 +- src/core/PlayerInfo.cpp | 2 +- src/peds/CivilianPed.cpp | 8 ++-- src/peds/CopPed.cpp | 6 +-- src/peds/EmergencyPed.cpp | 14 +++---- src/peds/Ped.cpp | 99 +++++++++++++++++------------------------------ src/peds/PedAI.cpp | 34 ++++++++-------- src/peds/PedFight.cpp | 14 +++---- src/peds/PlayerPed.cpp | 41 ++------------------ src/peds/Population.cpp | 6 +-- 12 files changed, 87 insertions(+), 149 deletions(-) (limited to 'src') diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index c951e868..4769559c 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -67,7 +67,7 @@ CPhoneInfo::Update(void) } else { CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PHONE); if (player->m_nPedState == PED_MAKE_CALL) - player->m_nPedState = PED_IDLE; + player->SetPedState(PED_IDLE); } } bool notInCar; @@ -114,7 +114,7 @@ CPhoneInfo::Update(void) player->m_fRotationCur = angleToFace; player->m_fRotationDest = angleToFace; player->SetHeading(angleToFace); - player->m_nPedState = PED_MAKE_CALL; + player->SetPedState(PED_MAKE_CALL); CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PHONE); TheCamera.SetWideScreenOn(); playerInfo->MakePlayerSafe(true); @@ -412,7 +412,7 @@ PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg) ped->bUpdateAnimHeading = true; if (ped->m_nPedState == PED_MAKE_CALL) - ped->m_nPedState = PED_IDLE; + ped->SetPedState(PED_IDLE); } void diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp index 164ca036..4826192e 100644 --- a/src/control/Script5.cpp +++ b/src/control/Script5.cpp @@ -1921,7 +1921,7 @@ void CTheScripts::CleanUpThisPed(CPed* pPed) if (pPed->IsPedInControl()) pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7); if (flees) { - pPed->m_nPedState = state; + pPed->SetPedState(state); pPed->SetMoveState(ms); } --CPopulation::ms_nTotalMissionPeds; diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index e1be4194..2c57c066 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -228,7 +228,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength ped->bDrawLast = false; ped->SetMoveState(PEDMOVE_SPRINT); ped->SetMoveAnim(); - ped->m_nPedState = PED_ON_FIRE; + ped->SetPedState(PED_ON_FIRE); } if (fleeFrom) { if (ped->m_nPedType == PEDTYPE_COP) { @@ -401,7 +401,7 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt CVector2D pos = target->GetPosition(); ped->SetFlee(pos, 10000); ped->SetMoveAnim(); - ped->m_nPedState = PED_ON_FIRE; + ped->SetPedState(PED_ON_FIRE); } } else if (target->IsVehicle()) { veh->m_pCarFire = fire; diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 09b3a499..5866485d 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -419,7 +419,7 @@ CPlayerInfo::Process(void) if (found) sth.z = 1.0f + groundZ; - m_pPed->m_nPedState = PED_IDLE; + m_pPed->SetPedState(PED_IDLE); m_pPed->SetMoveState(PEDMOVE_STILL); CPed::PedSetOutCarCB(0, m_pPed); CAnimManager::BlendAnimation(m_pPed->GetClump(), m_pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f); diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 401d2e67..a2f44357 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -274,7 +274,7 @@ CCivilianPed::ProcessControl(void) } else { crimeReporters[m_phoneId] = this; m_facePhoneStart = true; - m_nPedState = PED_FACE_PHONE; + SetPedState(PED_FACE_PHONE); } #else } else if (bRunningToPhone) { @@ -283,7 +283,7 @@ CCivilianPed::ProcessControl(void) m_phoneId = -1; } else { gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_REPORTING_CRIME; - m_nPedState = PED_FACE_PHONE; + SetPedState(PED_FACE_PHONE); } #endif } else if (m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { @@ -305,7 +305,7 @@ CCivilianPed::ProcessControl(void) break; case PED_FACE_PHONE: if (FacePhone()) - m_nPedState = PED_MAKE_CALL; + SetPedState(PED_MAKE_CALL); break; case PED_MAKE_CALL: if (MakePhonecall()) @@ -331,7 +331,7 @@ CCivilianPed::ProcessControl(void) for (int j = 0; j < m_numNearPeds; ++j) { CPed *nearPed = m_nearPeds[j]; if (nearPed->m_nPedType == m_nPedType && nearPed->m_nPedState == PED_WANDER_PATH) { - nearPed->m_nPedState = PED_UNKNOWN; + nearPed->SetPedState(PED_UNKNOWN); } } } diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index de7b8ad2..b2888082 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -114,14 +114,14 @@ CCopPed::SetArrestPlayer(CPed *player) } else if (player->m_nPedState != PED_DIE && player->m_nPedState != PED_DEAD && player->m_nPedState != PED_ARRESTED) { player->m_nLastPedState = player->m_nPedState; - player->m_nPedState = PED_ARRESTED; + player->SetPedState(PED_ARRESTED); FindPlayerPed()->m_bCanBeDamaged = false; ((CPlayerPed*)player)->m_pArrestingCop = this; this->RegisterReference((CEntity**) &((CPlayerPed*)player)->m_pArrestingCop); } - m_nPedState = PED_ARREST_PLAYER; + SetPedState(PED_ARREST_PLAYER); SetObjective(OBJECTIVE_NONE); m_prevObjective = OBJECTIVE_NONE; bIsPointingGunAt = false; @@ -229,7 +229,7 @@ CCopPed::ArrestPlayer(void) CPed *suspect = (CPed*)m_pSeekTarget; if (suspect) { if (suspect->CanSetPedState()) - suspect->m_nPedState = PED_ARRESTED; + suspect->SetPedState(PED_ARRESTED); if (suspect->bInVehicle && m_pMyVehicle && suspect->m_pMyVehicle == m_pMyVehicle) { diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index 8d6999c3..65aa97ef 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -100,7 +100,7 @@ CEmergencyPed::FiremanAI(void) case EMERGENCY_PED_READY: nearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist); if (nearestFire) { - m_nPedState = PED_NONE; + SetPedState(PED_NONE); SetSeek(nearestFire->m_vecPos, 1.0f); SetMoveState(PEDMOVE_RUN); m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; @@ -114,7 +114,7 @@ CEmergencyPed::FiremanAI(void) case EMERGENCY_PED_DETERMINE_NEXT_STATE: nearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist); if (nearestFire && nearestFire != m_pAttendedFire) { - m_nPedState = PED_NONE; + SetPedState(PED_NONE); SetSeek(nearestFire->m_vecPos, 1.0f); SetMoveState(PEDMOVE_RUN); #ifdef FIX_BUGS @@ -160,7 +160,7 @@ CEmergencyPed::FiremanAI(void) #endif --m_pAttendedFire->m_nFiremenPuttingOut; - m_nPedState = PED_NONE; + SetPedState(PED_NONE); SetWanderPath(CGeneral::GetRandomNumber() & 7); m_pAttendedFire = nil; m_nEmergencyPedState = EMERGENCY_PED_READY; @@ -307,7 +307,7 @@ CEmergencyPed::MedicAI(void) } else { m_pRevivedPed->m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds(); SetMoveState(PEDMOVE_STILL); - m_nPedState = PED_CPR; + SetPedState(PED_CPR); m_nLastPedState = PED_CPR; SetLookFlag(m_pRevivedPed, 0); SetLookTimer(500); @@ -366,12 +366,12 @@ CEmergencyPed::MedicAI(void) break; } m_nEmergencyPedState = EMERGENCY_PED_STOP_CPR; - m_nPedState = PED_NONE; + SetPedState(PED_NONE); SetMoveState(PEDMOVE_WALK); m_pVehicleAnim = nil; if (!m_pRevivedPed->bBodyPartJustCameOff) { m_pRevivedPed->m_fHealth = 100.0f; - m_pRevivedPed->m_nPedState = PED_NONE; + m_pRevivedPed->SetPedState(PED_NONE); m_pRevivedPed->m_nLastPedState = PED_WANDER_PATH; m_pRevivedPed->SetGetUp(); m_pRevivedPed->bUsesCollision = true; @@ -400,7 +400,7 @@ CEmergencyPed::MedicAI(void) break; case EMERGENCY_PED_STOP: m_bStartedToCPR = false; - m_nPedState = PED_NONE; + SetPedState(PED_NONE); if (m_pAttendedAccident) { m_pAttendedAccident->m_pVictim = nil; --m_pAttendedAccident->m_nMedicsAttending; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index c41c1f0c..5e1911ec 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -641,7 +641,7 @@ CPed::RestorePreviousState(void) return; if (InVehicle()) { - m_nPedState = PED_DRIVING; + SetPedState(PED_DRIVING); m_nLastPedState = PED_NONE; } else { if (m_nLastPedState == PED_NONE) { @@ -658,7 +658,7 @@ CPed::RestorePreviousState(void) SetIdle(); break; case PED_WANDER_PATH: - m_nPedState = PED_WANDER_PATH; + SetPedState(PED_WANDER_PATH); bIsRunning = false; if (bFindNewNodeAfterStateRestore) { if (m_pNextPathNode) { @@ -672,7 +672,7 @@ CPed::RestorePreviousState(void) SetWanderPath(CGeneral::GetRandomNumber() & 7); break; default: - m_nPedState = m_nLastPedState; + SetPedState(m_nLastPedState); SetMoveState((eMoveState) m_nPrevMoveState); break; } @@ -1511,8 +1511,8 @@ CPed::ClearAll(void) if (!IsPedInControl() && m_nPedState != PED_DEAD) return; - m_nPedState = PED_NONE; - m_nMoveState = PEDMOVE_NONE; + SetPedState(PED_NONE); + SetMoveState(PEDMOVE_NONE); m_pSeekTarget = nil; m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_fleeFromPosX = 0.0f; @@ -1585,7 +1585,7 @@ CPed::ProcessBuoyancy(void) CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true); #endif m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); return; } } @@ -2692,36 +2692,6 @@ CPed::ProcessControl(void) case PED_WANDER_PATH: WanderPath(); break; - case PED_SEEK_POS: - case PED_SEEK_ENTITY: - case PED_PURSUE: - case PED_SNIPER_MODE: - case PED_ROCKET_MODE: - case PED_DUMMY: - case PED_FACE_PHONE: - case PED_MAKE_CALL: - case PED_MUG: - case PED_AI_CONTROL: - case PED_FOLLOW_ROUTE: - case PED_CPR: - case PED_SOLICIT: - case PED_BUY_ICECREAM: - case PED_STEP_AWAY: - case PED_UNKNOWN: - case PED_STATES_NO_AI: - case PED_JUMP: - case PED_STAGGER: - case PED_DIVE_AWAY: - case PED_STATES_NO_ST: - case PED_ARREST_PLAYER: - case PED_PASSENGER: - case PED_TAXI_PASSENGER: - case PED_OPEN_DOOR: - case PED_DEAD: - case PED_DRAG_FROM_CAR: - case PED_EXIT_CAR: - case PED_STEAL_CAR: - break; case PED_ENTER_CAR: case PED_CARJACK: { @@ -4467,7 +4437,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) if (!veh->bEngineOn) veh->bEngineOn = true; - ped->m_nPedState = PED_DRIVING; + ped->SetPedState(PED_DRIVING); ped->StopNonPartialAnims(); return; } @@ -4512,7 +4482,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { if (ped->m_nPedState == PED_CARJACK) { veh->AddPassenger(ped, 0); - ped->m_nPedState = PED_DRIVING; + ped->SetPedState(PED_DRIVING); ped->RestorePreviousObjective(); ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) { @@ -4552,7 +4522,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) veh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; veh->AutoPilot.m_nCruiseSpeed = 25; } - ped->m_nPedState = PED_DRIVING; + ped->SetPedState(PED_DRIVING); if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT) @@ -4580,7 +4550,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) break; } } - ped->m_nPedState = PED_DRIVING; + ped->SetPedState(PED_DRIVING); if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT) ped->m_prevObjective = OBJECTIVE_NONE; @@ -4967,7 +4937,7 @@ CPed::SetIdle(void) m_nLastPedState = PED_NONE; #endif - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); SetMoveState(PEDMOVE_STILL); } if (m_nWaitState == WAITSTATE_FALSE) { @@ -5055,7 +5025,7 @@ CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl) ClearLookFlag(); ClearAimFlag(); SetStoredState(); - m_nPedState = PED_FALL; + SetPedState(PED_FALL); CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId); if (fallAssoc) { @@ -5220,7 +5190,7 @@ CPed::SetGetUp(void) } if (m_nPedState != PED_GETUP) { SetStoredState(); - m_nPedState = PED_GETUP; + SetPedState(PED_GETUP); } CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity; @@ -5375,7 +5345,7 @@ CPed::SetSeek(CVector pos, float distanceToCountDone) if (m_nPedState != PED_SEEK_POS) SetStoredState(); - m_nPedState = PED_SEEK_POS; + SetPedState(PED_SEEK_POS); m_distanceToCountSeekDone = distanceToCountDone; m_vecSeekPos = pos; } @@ -5395,7 +5365,7 @@ CPed::SetSeek(CEntity *seeking, float distanceToCountDone) if (m_nPedState != PED_SEEK_ENTITY) SetStoredState(); - m_nPedState = PED_SEEK_ENTITY; + SetPedState(PED_SEEK_ENTITY); m_distanceToCountSeekDone = distanceToCountDone; m_pSeekTarget = seeking; m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); @@ -5572,7 +5542,7 @@ CPed::SetFlee(CVector2D const &from, int time) if (m_nPedState != PED_FLEE_ENTITY) { SetStoredState(); - m_nPedState = PED_FLEE_POS; + SetPedState(PED_FLEE_POS); SetMoveState(PEDMOVE_RUN); m_fleeFromPosX = from.x; m_fleeFromPosY = from.y; @@ -5601,7 +5571,7 @@ CPed::SetFlee(CEntity *fleeFrom, int time) return; SetStoredState(); - m_nPedState = PED_FLEE_ENTITY; + SetPedState(PED_FLEE_ENTITY); bUsePedNodeSeek = true; SetMoveState(PEDMOVE_RUN); m_fleeFrom = fleeFrom; @@ -5862,7 +5832,7 @@ CPed::SetWanderPath(int8 pathStateDest) // We did it, save next path state and return true m_nPathDir = nextPathState; - m_nPedState = PED_WANDER_PATH; + SetPedState(PED_WANDER_PATH); SetMoveState(PEDMOVE_WALK); bIsRunning = false; return true; @@ -6047,7 +6017,7 @@ CPed::SetFollowPath(CVector dest) return false; SetStoredState(); - m_nPedState = PED_FOLLOW_PATH; + SetPedState(PED_FOLLOW_PATH); SetMoveState(PEDMOVE_WALK); return true; } @@ -6150,7 +6120,7 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) m_fRotationCur = CGeneral::LimitRadianAngle(angleToFace); ClearAimFlag(); SetStoredState(); - m_nPedState = PED_STEP_AWAY; + SetPedState(PED_STEP_AWAY); } } } @@ -6247,13 +6217,13 @@ CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump) animAssoc->flags &= ~ASSOC_DELETEFADEDOUT; animAssoc->SetFinishCallback(PedEvadeCB, this); SetStoredState(); - m_nPedState = PED_STEP_AWAY; + SetPedState(PED_STEP_AWAY); } else { m_fRotationCur = angleToFace; ClearLookFlag(); ClearAimFlag(); SetStoredState(); - m_nPedState = PED_DIVE_AWAY; + SetPedState(PED_DIVE_AWAY); animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f); animAssoc->SetFinishCallback(PedEvadeCB, this); } @@ -6291,7 +6261,7 @@ CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg) if (ped->m_nPedState == PED_DIVE_AWAY) { ped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1; - ped->m_nPedState = PED_FALL; + ped->SetPedState(PED_FALL); } animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; animAssoc->flags |= ASSOC_DELETEFADEDOUT; @@ -6342,7 +6312,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed) QuitEnteringCar(); } - m_nPedState = PED_DIE; + SetPedState(PED_DIE); if (animId == NUM_ANIMS) { bIsPedDieAnimPlaying = false; } else { @@ -6384,7 +6354,7 @@ CPed::SetDead(void) if (m_nPedState == PED_DRIVING) bIsVisible = false; - m_nPedState = PED_DEAD; + SetPedState(PED_DEAD); m_pVehicleAnim = nil; m_pCollidingEntity = nil; @@ -6417,7 +6387,7 @@ CPed::SetChat(CEntity *chatWith, uint32 time) if(m_nPedState != PED_CHAT) SetStoredState(); - m_nPedState = PED_CHAT; + SetPedState(PED_CHAT); SetMoveState(PEDMOVE_STILL); #if defined VC_PED_PORTS || defined FIX_BUGS m_lookTimer = 0; @@ -6658,7 +6628,7 @@ CPed::SetSeekCar(CVehicle *car, uint32 doorNode) // m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); m_vehEnterType = doorNode; m_distanceToCountSeekDone = 0.5f; - m_nPedState = PED_SEEK_CAR; + SetPedState(PED_SEEK_CAR); } @@ -7683,10 +7653,11 @@ CPed::FlagToDestroyWhenNextProcessed(void) } bInVehicle = false; m_pMyVehicle = nil; + if (CharCreatedBy == MISSION_CHAR) - m_nPedState = PED_DEAD; + SetPedState(PED_DEAD); else - m_nPedState = PED_NONE; + SetPedState(PED_NONE); m_pVehicleAnim = nil; } @@ -7710,7 +7681,7 @@ CPed::SetSolicit(uint32 time) if(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus) m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_HOOKERTALK, 4.0f); - m_nPedState = PED_SOLICIT; + SetPedState(PED_SOLICIT); } } } @@ -7769,7 +7740,7 @@ CPed::SetBuyIceCream(void) // Simulating BuyIceCream CPed* driver = m_carInObjective->pDriver; if (driver) { - m_nPedState = PED_BUY_ICECREAM; + SetPedState(PED_BUY_ICECREAM); bFindNewNodeAfterStateRestore = true; SetObjectiveTimer(8000); SetChat(driver, 8000); @@ -7783,7 +7754,7 @@ CPed::SetBuyIceCream(void) if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) { m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000; - m_nPedState = PED_BUY_ICECREAM; + SetPedState(PED_BUY_ICECREAM); } } @@ -7985,7 +7956,7 @@ CPed::SetJump(void) #endif (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { SetStoredState(); - m_nPedState = PED_JUMP; + SetPedState(PED_JUMP); CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f); jumpAssoc->SetFinishCallback(FinishLaunchCB, this); m_fRotationDest = m_fRotationCur; @@ -8287,7 +8258,7 @@ CPed::WarpPedIntoCar(CVehicle *car) m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); m_carInObjective = car; m_carInObjective->RegisterReference((CEntity **) &m_carInObjective); - m_nPedState = PED_DRIVING; + SetPedState(PED_DRIVING); bUsesCollision = false; bIsInTheAir = false; bVehExitWillBeInstant = true; diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp index 5eaf8cd8..d4385385 100644 --- a/src/peds/PedAI.cpp +++ b/src/peds/PedAI.cpp @@ -809,10 +809,10 @@ CPed::ProcessObjective(void) break; } case OBJECTIVE_WAIT_IN_CAR: - m_nPedState = PED_DRIVING; + SetPedState(PED_DRIVING); break; case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: - m_nPedState = PED_DRIVING; + SetPedState(PED_DRIVING); break; case OBJECTIVE_KILL_CHAR_ANY_MEANS: { @@ -2617,7 +2617,7 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) { PedSetInCarCB(nil, ped); ped->m_nLastPedState = ped->m_nPedState; - ped->m_nPedState = PED_ARRESTED; + ped->SetPedState(PED_ARRESTED); ped->bGonnaKillTheCarJacker = false; if (veh) { veh->m_nNumGettingIn = 0; @@ -3340,7 +3340,7 @@ CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) m_pSeekTarget = car; m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget); - m_nPedState = PED_CARJACK; + SetPedState(PED_CARJACK); car->bIsBeingCarJacked = true; m_pMyVehicle = (CVehicle*)m_pSeekTarget; m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle); @@ -3387,7 +3387,7 @@ CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack) SetMoveState(PEDMOVE_NONE); LineUpPedWithCar(LINE_UP_TO_CAR_START); m_pVehicleAnim = nil; - m_nPedState = PED_DRAG_FROM_CAR; + SetPedState(PED_DRAG_FROM_CAR); bChangedSeat = false; bWillBeQuickJacked = quickJack; @@ -3512,7 +3512,7 @@ CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) m_pSeekTarget = car; m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); m_vehEnterType = doorNode; - m_nPedState = PED_ENTER_CAR; + SetPedState(PED_ENTER_CAR); if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && car->m_vehType != VEHICLE_TYPE_BIKE) { car->bIsBeingCarJacked = true; } @@ -3674,14 +3674,14 @@ void CPed::SetExitBoat(CVehicle *boat) { #ifndef VC_PED_PORTS - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); CVector firstPos = GetPosition(); CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) { m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f); m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this); m_vehEnterType = CAR_DOOR_RF; - m_nPedState = PED_EXIT_CAR; + SetPedState(PED_EXIT_CAR); } else { m_vehEnterType = CAR_DOOR_RF; PedSetOutCarCB(nil, this); @@ -3694,7 +3694,7 @@ CPed::SetExitBoat(CVehicle *boat) m_vecMoveSpeed = boat->m_vecMoveSpeed; bTryingToReachDryLand = true; #else - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); CVector newPos = GetPosition(); RemoveInCarAnims(); CColModel* boatCol = boat->GetColModel(); @@ -3921,7 +3921,7 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) m_pSeekTarget = veh; m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); m_vehEnterType = optedDoorNode; - m_nPedState = PED_EXIT_CAR; + SetPedState(PED_EXIT_CAR); if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL) m_pVehicleAnim->blendDelta = -1000.0f; SetMoveState(PEDMOVE_NONE); @@ -4469,7 +4469,7 @@ CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg) ped->bGonnaKillTheCarJacker = false; if (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) { if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) { - ped->m_nPedState = PED_NONE; + ped->SetPedState(PED_NONE); ped->m_nLastPedState = PED_NONE; ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000); } else { @@ -4498,7 +4498,7 @@ CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg) else #endif { - ped->m_nPedState = PED_NONE; + ped->SetPedState(PED_NONE); ped->m_nLastPedState = PED_NONE; ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000); } @@ -4591,7 +4591,7 @@ CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg) return; ped->bInVehicle = true; - ped->m_nPedState = PED_DRIVING; + ped->SetPedState(PED_DRIVING); ped->RestorePreviousObjective(); ped->SetMoveState(PEDMOVE_STILL); veh->AddPassenger(ped); @@ -4612,7 +4612,7 @@ CPed::SetEnterTrain(CVehicle *train, uint32 unused) m_pMyVehicle = train; m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); - m_nPedState = PED_ENTER_TRAIN; + SetPedState(PED_ENTER_TRAIN); m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f); m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this); bUsesCollision = false; @@ -4686,7 +4686,7 @@ CPed::SetExitTrain(CVehicle* train) CVector exitPos; GetNearestTrainPedPosition(train, exitPos); */ - m_nPedState = PED_EXIT_TRAIN; + SetPedState(PED_EXIT_TRAIN); m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f); m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this); bUsesCollision = false; @@ -4712,7 +4712,7 @@ CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg) ped->bUsesCollision = true; ped->m_pVehicleAnim = nil; ped->bInVehicle = false; - ped->m_nPedState = PED_IDLE; + ped->SetPedState(PED_IDLE); ped->RestorePreviousObjective(); ped->SetMoveState(PEDMOVE_STILL); @@ -5180,7 +5180,7 @@ CPed::SetSeekBoatPosition(CVehicle *boat) m_pMyVehicle = boat; m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); m_distanceToCountSeekDone = 0.5f; - m_nPedState = PED_SEEK_IN_BOAT; + SetPedState(PED_SEEK_IN_BOAT); } void diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp index c219d94f..b4be0954 100644 --- a/src/peds/PedFight.cpp +++ b/src/peds/PedFight.cpp @@ -164,7 +164,7 @@ CPed::SetPointGunAt(CEntity *to) if (m_nPedState != PED_ATTACK) SetStoredState(); - m_nPedState = PED_AIM_GUN; + SetPedState(PED_AIM_GUN); bIsPointingGunAt = true; CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); SetMoveState(PEDMOVE_NONE); @@ -222,7 +222,7 @@ CPed::ClearPointGunAt(void) RestorePreviousState(); #else if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) { - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); RestorePreviousState(); } #endif @@ -281,7 +281,7 @@ CPed::SetAttack(CEntity *victim) (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) { if (m_nPedState != PED_ATTACK) { - m_nPedState = PED_ATTACK; + SetPedState(PED_ATTACK); bIsAttacking = false; animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f); animAssoc->SetRun(); @@ -348,7 +348,7 @@ CPed::SetAttack(CEntity *victim) if (m_nPedState != PED_AIM_GUN) SetStoredState(); - m_nPedState = PED_ATTACK; + SetPedState(PED_ATTACK); SetMoveState(PEDMOVE_NONE); if (bCrouchWhenShooting) { animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); @@ -786,7 +786,7 @@ CPed::StartFightAttack(uint8 buttonPressure) RestoreHeadingRate(); } - m_nPedState = PED_FIGHT; + SetPedState(PED_FIGHT); m_fightButtonPressure = 0; RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); @@ -1062,7 +1062,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) m_nWaitState = WAITSTATE_FALSE; RestoreHeadingRate(); } - m_nPedState = PED_FIGHT; + SetPedState(PED_FIGHT); m_fightButtonPressure = 0; RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); @@ -1796,7 +1796,7 @@ CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCount SetStoredState(); bFindNewNodeAfterStateRestore = false; - m_nPedState = PED_INVESTIGATE; + SetPedState(PED_INVESTIGATE); m_standardTimer = CTimer::GetTimeInMilliseconds() + time; m_eventType = event; m_eventOrThreat = pos; diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index ef9cf201..86d8e9f5 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -244,7 +244,7 @@ CPlayerPed::SetInitialState(void) if (m_pFire) m_pFire->Extinguish(); RpAnimBlendClumpRemoveAllAssociations(GetClump()); - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); SetMoveState(PEDMOVE_STILL); m_nLastPedState = PED_NONE; m_animGroup = ASSOCGRP_PLAYER; @@ -989,7 +989,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) { if (padUsed->TargetJustDown()) { SetStoredState(); - m_nPedState = PED_SNIPER_MODE; + SetPedState(PED_SNIPER_MODE); #ifdef FREE_CAM if (CCamera::bFreeCam && TheCamera.Cams[0].Using3rdPersonMouseCam()) { m_fRotationCur = CGeneral::LimitRadianAngle(-TheCamera.Orientation); @@ -1343,41 +1343,6 @@ CPlayerPed::ProcessControl(void) if (IsPedInControl() && padUsed) ProcessPlayerWeapon(padUsed); break; - case PED_LOOK_ENTITY: - case PED_LOOK_HEADING: - case PED_WANDER_RANGE: - case PED_WANDER_PATH: - case PED_PURSUE: - case PED_FOLLOW_PATH: - case PED_ROCKET_MODE: - case PED_DUMMY: - case PED_PAUSE: - case PED_FACE_PHONE: - case PED_MAKE_CALL: - case PED_CHAT: - case PED_MUG: - case PED_AI_CONTROL: - case PED_FOLLOW_ROUTE: - case PED_CPR: - case PED_SOLICIT: - case PED_BUY_ICECREAM: - case PED_INVESTIGATE: - case PED_STEP_AWAY: - case PED_ON_FIRE: - case PED_UNKNOWN: - case PED_STATES_NO_AI: - case PED_STAGGER: - case PED_DIVE_AWAY: - case PED_STATES_NO_ST: - case PED_ARREST_PLAYER: - case PED_DRIVING: - case PED_PASSENGER: - case PED_TAXI_PASSENGER: - case PED_OPEN_DOOR: - case PED_DIE: - case PED_DEAD: - case PED_HANDS_UP: - break; case PED_SEEK_ENTITY: m_vecSeekPos = m_pSeekTarget->GetPosition(); @@ -1457,6 +1422,8 @@ CPlayerPed::ProcessControl(void) if (m_nLastPedState == PED_DRAG_FROM_CAR && m_pVehicleAnim) BeingDraggedFromCar(); break; + default: + break; } if (padUsed && IsPedShootable()) { ProcessWeaponSwitch(padUsed); diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index b3eaf471..5dbde649 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -718,10 +718,10 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree if (i != 0) { // Gang member newPed->SetLeader(gangLeader); -#ifndef FIX_BUGS +#if !defined(FIX_BUGS) && GTA_VERSION >= GTA3_PC_10 // seems to be a miami leftover (this code is not on PS2) but gang peds end up just being frozen - newPed->m_nPedState = PED_UNKNOWN; - gangLeader->m_nPedState = PED_UNKNOWN; + newPed->SetPedState(PED_UNKNOWN); + gangLeader->SetPedState(PED_UNKNOWN); newPed->m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints( gangLeader->GetPosition().x, gangLeader->GetPosition().y, newPed->GetPosition().x, newPed->GetPosition().y); -- cgit v1.2.3 From 6d3adf57e8968071d16de8746cebf366543039bb Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 15 Dec 2020 14:36:30 +0100 Subject: fixed water.dat code --- src/render/WaterLevel.cpp | 118 +++++++++++++++++++++++----------------------- src/render/WaterLevel.h | 8 +--- 2 files changed, 61 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index ef5c4c58..49fc3a22 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -31,8 +31,8 @@ float TEXTURE_ADDV; int32 CWaterLevel::ms_nNoOfWaterLevels; float CWaterLevel::ms_aWaterZs[48]; CRect CWaterLevel::ms_aWaterRects[48]; -int8 CWaterLevel::aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; -int8 CWaterLevel::aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; +int8 CWaterLevel::aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS]; +int8 CWaterLevel::aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS]; bool CWaterLevel::WavesCalculatedThisFrame; RpAtomic *CWaterLevel::ms_pWavyAtomic; RpGeometry *CWaterLevel::apGeomArray[8]; @@ -54,7 +54,6 @@ const float fGreenMult = 1.0f; const float fBlueMult = 1.4f; - void CWaterLevel::Initialise(Const char *pWaterDat) { @@ -100,14 +99,15 @@ CWaterLevel::Initialise(Const char *pWaterDat) CFileMgr::CloseFile(hFile); - for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + for (int32 x = 0; x < MAX_SMALL_SECTORS; x++) { - for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + for (int32 y = 0; y < MAX_SMALL_SECTORS; y++) { aWaterFineBlockList[x][y] = NO_WATER; } } + // rasterize water rects read from file for (int32 i = 0; i < ms_nNoOfWaterLevels; i++) { int32 l = WATER_HUGE_X(ms_aWaterRects[i].left); @@ -115,13 +115,13 @@ CWaterLevel::Initialise(Const char *pWaterDat) int32 t = WATER_HUGE_Y(ms_aWaterRects[i].top); int32 b = WATER_HUGE_Y(ms_aWaterRects[i].bottom) + 1.0f; - // originally this writes *god* knows where everywhere in game memory ... - // even in debug it manages to reach some textures so librw crashes with a ptr being 0x15151515 .... #ifdef FIX_BUGS - l = clamp(l, 0, WATER_FINEBLOCK_SIZE - 1); - r = clamp(r, 0, WATER_FINEBLOCK_SIZE - 1); - t = clamp(t, 0, WATER_FINEBLOCK_SIZE - 1); - b = clamp(b, 0, WATER_FINEBLOCK_SIZE - 1); + // water.dat has rects that go out of bounds + // which causes memory corruption + l = clamp(l, 0, MAX_SMALL_SECTORS - 1); + r = clamp(r, 0, MAX_SMALL_SECTORS - 1); + t = clamp(t, 0, MAX_SMALL_SECTORS - 1); + b = clamp(b, 0, MAX_SMALL_SECTORS - 1); #endif for (int32 x = l; x <= r; x++) @@ -133,46 +133,46 @@ CWaterLevel::Initialise(Const char *pWaterDat) } } - for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + // remove tiles that are obscured by land + for (int32 x = 0; x < MAX_SMALL_SECTORS; x++) { - int32 worldX = WATER_START_X + x * SMALL_SECTOR_WIDTH; + float worldX = WATER_START_X + x * SMALL_SECTOR_SIZE; - for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + for (int32 y = 0; y < MAX_SMALL_SECTORS; y++) { - if (aWaterBlockList[x][y] >= 0) + if (aWaterFineBlockList[x][y] >= 0) { - int32 worldY = WATER_START_Y + y * SMALL_SECTOR_WIDTH; + float worldY = WATER_START_Y + y * SMALL_SECTOR_SIZE; int32 i; for (i = 0; i <= 8; i++) { for (int32 j = 0; j <= 8; j++) { - CVector worldPos = CVector(worldX + i * (SMALL_SECTOR_WIDTH / 8), worldY + j * (SMALL_SECTOR_WIDTH / 8), ms_aWaterZs[aWaterFineBlockList[x][y]]); + CVector worldPos = CVector(worldX + i * (SMALL_SECTOR_SIZE / 8), worldY + j * (SMALL_SECTOR_SIZE / 8), ms_aWaterZs[aWaterFineBlockList[x][y]]); - if ((worldPos.x > WORLD_MIN_X && worldPos.x < WORLD_MAX_X) && (worldPos.y > WORLD_MIN_Y && worldPos.y < WORLD_MAX_Y)) - { - if (WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) && !TestVisibilityForFineWaterBlocks(worldPos)) - { - i = 1000; - break; - } - } - } + if ((worldPos.x > WORLD_MIN_X && worldPos.x < WORLD_MAX_X) && (worldPos.y > WORLD_MIN_Y && worldPos.y < WORLD_MAX_Y) && + (!WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) || TestVisibilityForFineWaterBlocks(worldPos))) + continue; - if (i == 1000) break; + // at least one point in the tile wasn't blocked, so don't remove water + i = 1000; + break; + } } - if (i < 1000) aWaterFineBlockList[x][y] = NO_WATER; + if (i < 1000) + aWaterFineBlockList[x][y] = NO_WATER; } } } RemoveIsolatedWater(); - for (int32 x = 0; x < WATER_BLOCK_SIZE; x++) + // calculate coarse tiles from fine tiles + for (int32 x = 0; x < MAX_LARGE_SECTORS; x++) { - for (int32 y = 0; y < WATER_BLOCK_SIZE; y++) + for (int32 y = 0; y < MAX_LARGE_SECTORS; y++) { if (aWaterFineBlockList[x * 2][y * 2] >= 0) { @@ -445,11 +445,11 @@ CWaterLevel::TestVisibilityForFineWaterBlocks(const CVector &worldPos) void CWaterLevel::RemoveIsolatedWater() { - bool (*isConnected)[WATER_FINEBLOCK_SIZE] = new bool[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; + bool (*isConnected)[MAX_SMALL_SECTORS] = new bool[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS]; - for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + for (int32 x = 0; x < MAX_SMALL_SECTORS; x++) { - for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + for (int32 y = 0; y < MAX_SMALL_SECTORS; y++) { isConnected[x][y] = false; } @@ -462,35 +462,35 @@ CWaterLevel::RemoveIsolatedWater() { keepGoing = false; - for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + for (int32 x = 0; x < MAX_SMALL_SECTORS; x++) { - for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + for (int32 y = 0; y < MAX_SMALL_SECTORS; y++) { - if (aWaterBlockList[x][y] >= 0 && !isConnected[x][y]) + if (aWaterFineBlockList[x][y] < 0 || isConnected[x][y]) + continue; + + if (x > 0 && isConnected[x - 1][y]) { - if (x > 0 && isConnected[x - 1][y]) - { - isConnected[x][y] = true; - keepGoing = true; - } + isConnected[x][y] = true; + keepGoing = true; + } - if (y > 0 && isConnected[x][y - 1]) - { - isConnected[x][y] = true; - keepGoing = true; - } + if (y > 0 && isConnected[x][y - 1]) + { + isConnected[x][y] = true; + keepGoing = true; + } - if (x + 1 < WATER_FINEBLOCK_SIZE && isConnected[x + 1][y]) - { - isConnected[x][y] = true; - keepGoing = true; - } + if (x + 1 < MAX_SMALL_SECTORS && isConnected[x + 1][y]) + { + isConnected[x][y] = true; + keepGoing = true; + } - if (y + 1 < WATER_FINEBLOCK_SIZE && isConnected[x][y + 1]) - { - isConnected[x][y] = true; - keepGoing = true; - } + if (y + 1 < MAX_SMALL_SECTORS && isConnected[x][y + 1]) + { + isConnected[x][y] = true; + keepGoing = true; } } } @@ -499,11 +499,11 @@ CWaterLevel::RemoveIsolatedWater() int32 numRemoved = 0; - for (int32 x = 0; x < WATER_FINEBLOCK_SIZE; x++) + for (int32 x = 0; x < MAX_SMALL_SECTORS; x++) { - for (int32 y = 0; y < WATER_FINEBLOCK_SIZE; y++) + for (int32 y = 0; y < MAX_SMALL_SECTORS; y++) { - if (aWaterBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] != 0.0f) + if (aWaterFineBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] == 0.0f) { numRemoved++; aWaterFineBlockList[x][y] = NO_WATER; diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h index cff1a995..cf3537ae 100644 --- a/src/render/WaterLevel.h +++ b/src/render/WaterLevel.h @@ -1,7 +1,5 @@ #pragma once -#define WATER_BLOCK_SIZE LARGE_SECTOR_SIZE -#define WATER_FINEBLOCK_SIZE HUGE_SECTOR_SIZE #define WATER_Z_OFFSET (1.5f) #define NO_WATER -128 @@ -25,8 +23,6 @@ #define WATER_WIDTH ((WATER_END_X - WATER_START_X)) #define WATER_HEIGHT ((WATER_END_Y - WATER_START_Y)) -#define SMALL_SECTOR_WIDTH (WATER_WIDTH/MAX_SMALL_SECTORS) - #define WATER_UNSIGN_X(x) ( (x) + (WATER_WIDTH /2) ) #define WATER_UNSIGN_Y(y) ( (y) + (WATER_HEIGHT/2) ) #define WATER_SIGN_X(x) ( (x) - (WATER_WIDTH /2) ) @@ -75,8 +71,8 @@ class CWaterLevel static int32 ms_nNoOfWaterLevels; static float ms_aWaterZs[48]; static CRect ms_aWaterRects[48]; - static int8 aWaterBlockList[WATER_BLOCK_SIZE][WATER_BLOCK_SIZE]; - static int8 aWaterFineBlockList[WATER_FINEBLOCK_SIZE][WATER_FINEBLOCK_SIZE]; + static int8 aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS]; + static int8 aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS]; static bool WavesCalculatedThisFrame; static RpAtomic *ms_pWavyAtomic; static RpGeometry *apGeomArray[MAX_BOAT_WAKES]; -- cgit v1.2.3 From 64b509af52afa88cbbbe6feea05605eb5905176b Mon Sep 17 00:00:00 2001 From: erorcun Date: Tue, 15 Dec 2020 17:33:29 +0300 Subject: Make free cam collision code readable by aap, fixes --- src/core/Cam.cpp | 112 +++++++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index ba7e5d15..65a867be 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -3003,8 +3003,7 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float UseMouse = false; int ZoomInButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_IN); int ZoomOutButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_OUT); - // TODO: enum? this should be mouse wheel up and down - if(ZoomInButton == 4 || ZoomInButton == 5 || ZoomOutButton == 4 || ZoomOutButton == 5){ + if(ZoomInButton == rsMOUSEWHEELUPBUTTON || ZoomInButton == rsMOUSEWHEELDOWNBUTTON || ZoomOutButton == rsMOUSEWHEELUPBUTTON || ZoomOutButton == rsMOUSEWHEELDOWNBUTTON){ if(CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetMouseWheelDown()){ if(CPad::GetPad(0)->SniperZoomIn()){ TargetFOV = FOV - 10.0f; @@ -4894,13 +4893,9 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, if (FOV > DefaultFOV) // 0.98f: CAR_FOV_FADE_MULT - FOV = pow(0.98f, CTimer::GetTimeStep()) * (FOV - DefaultFOV) + DefaultFOV; + FOV = Pow(0.98f, CTimer::GetTimeStep()) * (FOV - DefaultFOV) + DefaultFOV; - if (FOV <= DefaultFOV + 30.0f) { - if (FOV < DefaultFOV) - FOV = DefaultFOV; - } else - FOV = DefaultFOV + 30.0f; + FOV = clamp(FOV, DefaultFOV, DefaultFOV + 30.0f); } // WORKAROUND: I still don't know how looking behind works (m_bCamDirectlyInFront is unused in III, they seem to use m_bUseTransitionBeta) @@ -5030,7 +5025,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, targetAlpha = maxAlphaAllowed; } float maxAlphaBlendAmount = CTimer::GetTimeStep() * CARCAM_SET[camSetArrPos][6]; - float targetAlphaBlendAmount = (1.0f - pow(CARCAM_SET[camSetArrPos][5], CTimer::GetTimeStep())) * (targetAlpha - Alpha); + float targetAlphaBlendAmount = (1.0f - Pow(CARCAM_SET[camSetArrPos][5], CTimer::GetTimeStep())) * (targetAlpha - Alpha); if (targetAlphaBlendAmount <= maxAlphaBlendAmount) { if (targetAlphaBlendAmount < -maxAlphaBlendAmount) targetAlphaBlendAmount = -maxAlphaBlendAmount; @@ -5122,7 +5117,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float betaSpeedFromStickX = xMovement * CARCAM_SET[camSetArrPos][12]; float newAngleSpeedMaxBlendAmount = CARCAM_SET[camSetArrPos][9]; - float angleChangeStep = pow(CARCAM_SET[camSetArrPos][8], CTimer::GetTimeStep()); + float angleChangeStep = Pow(CARCAM_SET[camSetArrPos][8], CTimer::GetTimeStep()); float targetBetaWithStickBlendAmount = betaSpeedFromStickX + (targetBeta - Beta) / Max(CTimer::GetTimeStep(), 1.0f); if (targetBetaWithStickBlendAmount < -newAngleSpeedMaxBlendAmount) @@ -5234,75 +5229,76 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, // SA calls SetColVarsVehicle in here if (nextDirectionIsForward) { - // This is new in LCS! + // LCS uses exactly the same collision code as FollowPedWithMouse, so we will do so. + + // This is only in LCS! float timestepFactor = Pow(0.99f, CTimer::GetTimeStep()); dontCollideWithCars = (timestepFactor * dontCollideWithCars) + ((1.0f - timestepFactor) * car->m_vecMoveSpeed.Magnitude()); // Our addition #define IS_TRAFFIC_LIGHT(ent) (ent->IsObject() && (IsStreetLight(ent->GetModelIndex()))) - // Move cam if on collision - CColPoint foundCol; - CEntity* foundEnt; + // Clip Source and fix near clip + CColPoint colPoint; + CEntity* entity; CWorld::pIgnoreEntity = CamTargetEntity; - if (CWorld::ProcessLineOfSight(TargetCoors, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, true, false, true, false) && !IS_TRAFFIC_LIGHT(foundEnt)) { - float obstacleTargetDist = (TargetCoors - foundCol.point).Magnitude(); - float obstacleCamDist = newDistance - obstacleTargetDist; - if (!foundEnt->IsPed() || obstacleCamDist <= 1.0f) { - Source = foundCol.point; - if (obstacleTargetDist < 1.2f) { - RwCameraSetNearClipPlane(Scene.camera, Max(0.05f, obstacleTargetDist - 0.3f)); - } - } else { - if (!CWorld::ProcessLineOfSight(foundCol.point, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, true, false, true, false) || IS_TRAFFIC_LIGHT(foundEnt)) { - float lessClip = obstacleCamDist - 0.35f; - if (lessClip <= DEFAULT_NEAR) - RwCameraSetNearClipPlane(Scene.camera, lessClip); - else - RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); - } else { - obstacleTargetDist = (TargetCoors - foundCol.point).Magnitude(); - Source = foundCol.point; - if (obstacleTargetDist < 1.2f) { - float lessClip = obstacleTargetDist - 0.3f; - if (lessClip >= 0.05f) - RwCameraSetNearClipPlane(Scene.camera, lessClip); - else - RwCameraSetNearClipPlane(Scene.camera, 0.05f); - } + if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, dontCollideWithCars < 0.1f, false, true, false, true, true) && !IS_TRAFFIC_LIGHT(entity)){ + float PedColDist = (TargetCoors - colPoint.point).Magnitude(); + float ColCamDist = newDistance - PedColDist; + if(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){ + // Ped in the way but not clipping through + if(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, dontCollideWithCars < 0.1f, false, true, false, true, true) || IS_TRAFFIC_LIGHT(entity)){ + PedColDist = (TargetCoors - colPoint.point).Magnitude(); + Source = colPoint.point; + if(PedColDist < DEFAULT_NEAR + 0.3f) + RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f)); + }else{ + RwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR)); } + }else{ + Source = colPoint.point; + if(PedColDist < DEFAULT_NEAR + 0.3f) + RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f)); } } CWorld::pIgnoreEntity = nil; - float nearClip = RwCameraGetNearClipPlane(Scene.camera); - float radius = Tan(DEGTORAD(FOV * 0.5f)) * CDraw::GetAspectRatio() * 1.1f; // If we're seeing blue hell due to camera intersects some surface, fix it. // SA and LCS have this unrolled. - for (int i = 0; - i <= 5 && (foundEnt = CWorld::TestSphereAgainstWorld((nearClip * Front) + Source, radius * nearClip, nil, true, true, false, true, false, false)); - i++) { - if (IS_TRAFFIC_LIGHT(foundEnt)) + float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); + float ViewPlaneWidth = ViewPlaneHeight * CDraw::FindAspectRatio() * fTweakFOV; + float Near = RwCameraGetNearClipPlane(Scene.camera); + float radius = ViewPlaneWidth*Near; + entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, true); + int i = 0; + while(entity){ + + if (IS_TRAFFIC_LIGHT(entity)) break; - CVector surfaceCamDist = gaTempSphereColPoints->point - Source; - CVector frontButInvertedIfTouchesSurface = DotProduct(surfaceCamDist, Front) * Front; - float newNearClip = (surfaceCamDist - frontButInvertedIfTouchesSurface).Magnitude() / radius; + CVector CamToCol = gaTempSphereColPoints[0].point - Source; + float frontDist = DotProduct(CamToCol, Front); + float dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth; + + // Try to decrease near clip + dist = Max(Min(Near, dist), 0.1f); + if(dist < Near) + RwCameraSetNearClipPlane(Scene.camera, dist); - if (newNearClip > nearClip) - newNearClip = nearClip; - if (newNearClip < 0.1f) - newNearClip = 0.1f; - if (nearClip > newNearClip) - RwCameraSetNearClipPlane(Scene.camera, newNearClip); + // Move forward a bit + if(dist == 0.1f) + Source += (TargetCoors - Source)*0.3f; - if (newNearClip == 0.1f) - Source += (TargetCoors - Source) * 0.3f; + // Keep testing + Near = RwCameraGetNearClipPlane(Scene.camera); + radius = ViewPlaneWidth*Near; + entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, true); - nearClip = RwCameraGetNearClipPlane(Scene.camera); - radius = Tan(DEGTORAD(FOV * 0.5f)) * CDraw::GetAspectRatio() * 1.1f; + i++; + if(i > 5) + entity = nil; } #undef IS_TRAFFIC_LIGHT } -- cgit v1.2.3 From 55414f7ef2424e7b6804bae7b144a8be66b187bd Mon Sep 17 00:00:00 2001 From: "Walied K. Yassen" Date: Tue, 15 Dec 2020 18:05:37 +0200 Subject: Few bug fixes in CAutomobile --- src/vehicles/Automobile.cpp | 16 ++++++++-------- src/vehicles/Automobile.h | 2 -- src/vehicles/Vehicle.h | 8 -------- 3 files changed, 8 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index ec71f690..79d3f6af 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -768,7 +768,7 @@ CAutomobile::ProcessControl(void) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB); WheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT]; - if(Damage.GetWheelStatus(VEHWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST) + if(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST) ProcessWheel(wheelFwd, wheelRight, contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT], m_nWheelsOnGround, fThrust, @@ -802,7 +802,7 @@ CAutomobile::ProcessControl(void) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB); WheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT]; - if(Damage.GetWheelStatus(VEHWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST) + if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST) ProcessWheel(wheelFwd, wheelRight, contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT], m_nWheelsOnGround, fThrust, @@ -883,7 +883,7 @@ CAutomobile::ProcessControl(void) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB); WheelState[CARWHEEL_REAR_LEFT] = m_aWheelState[CARWHEEL_REAR_LEFT]; - if(Damage.GetWheelStatus(VEHWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST) + if(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST) ProcessWheel(wheelFwd, wheelRight, contactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT], m_nWheelsOnGround, fThrust, @@ -917,7 +917,7 @@ CAutomobile::ProcessControl(void) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB); WheelState[CARWHEEL_REAR_RIGHT] = m_aWheelState[CARWHEEL_REAR_RIGHT]; - if(Damage.GetWheelStatus(VEHWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST) + if(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST) ProcessWheel(wheelFwd, wheelRight, contactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT], m_nWheelsOnGround, fThrust, @@ -3946,10 +3946,10 @@ void CAutomobile::BurstTyre(uint8 wheel) { switch(wheel){ - case CAR_PIECE_WHEEL_LF: wheel = VEHWHEEL_FRONT_LEFT; break; - case CAR_PIECE_WHEEL_LR: wheel = VEHWHEEL_REAR_LEFT; break; - case CAR_PIECE_WHEEL_RF: wheel = VEHWHEEL_FRONT_RIGHT; break; - case CAR_PIECE_WHEEL_RR: wheel = VEHWHEEL_REAR_RIGHT; break; + case CAR_PIECE_WHEEL_LF: wheel = CARWHEEL_FRONT_LEFT; break; + case CAR_PIECE_WHEEL_RF: wheel = CARWHEEL_FRONT_RIGHT; break; + case CAR_PIECE_WHEEL_LR: wheel = CARWHEEL_REAR_LEFT; break; + case CAR_PIECE_WHEEL_RR: wheel = CARWHEEL_REAR_RIGHT; break; } int status = Damage.GetWheelStatus(wheel); diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 604bed17..a5bee226 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -30,8 +30,6 @@ enum eCarNodes NUM_CAR_NODES, }; -// These are used for all the wheel arrays -// DON'T confuse with VEHWHEEL, which are vehicle components enum { CARWHEEL_FRONT_LEFT, CARWHEEL_REAR_LEFT, diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 3933f1dd..7066a0ea 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -57,14 +57,6 @@ enum eLights VEHLIGHT_REAR_RIGHT, }; -enum eWheels -{ - VEHWHEEL_FRONT_LEFT, - VEHWHEEL_FRONT_RIGHT, - VEHWHEEL_REAR_LEFT, - VEHWHEEL_REAR_RIGHT, -}; - enum { CAR_PIECE_BONNET = 1, -- cgit v1.2.3 From 23b5e664dcd5c178c6f7d4c06bc0e12057d898c9 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 16 Dec 2020 00:38:26 +0300 Subject: Sync Frontend with miami 3/3 --- src/core/Frontend.cpp | 107 ++++++++++++++++++++++---------------------------- src/core/Frontend.h | 13 +++--- 2 files changed, 55 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 6806230d..5ea756e7 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -80,6 +80,7 @@ const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); // PS2 option color #ifdef SCROLLABLE_PAGES #define MAX_VISIBLE_OPTION 12 #define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION) +#define SCREEN_HAS_AUTO_SCROLLBAR (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) int GetOptionCount(int screen) { @@ -176,7 +177,6 @@ int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; int32 CMenuManager::m_PrefsMusicVolume = 102; int32 CMenuManager::m_PrefsSfxVolume = 102; - char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME; int32 CMenuManager::m_KeyPressedCode = -1; @@ -208,7 +208,6 @@ bool CMenuManager::m_PrefsMarketing = false; bool CMenuManager::m_PrefsDisableTutorials = false; #endif // !MASTER -// 0x5F311C const char* FrontendFilenames[][2] = { {"fe2_mainpanel_ul", "" }, {"fe2_mainpanel_ur", "" }, @@ -477,7 +476,7 @@ CMenuManager::ThingsToDoBeforeGoingBack() } #ifdef SCROLLABLE_PAGES - if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) { + if (SCREEN_HAS_AUTO_SCROLLBAR) { m_nSelectedListRow = 0; m_nFirstVisibleRowOnList = 0; m_nScrollbarTopMargin = 0; @@ -962,25 +961,25 @@ CMenuManager::DisplayHelperText() int action = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; if (action != MENUACTION_CHANGEMENU && action != MENUACTION_KEYBOARDCTRLS && action != MENUACTION_RESTOREDEF) { CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_MIG")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_MIG")); } break; } case 1: CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_APP")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_APP")); break; case 2: CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_HRD")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_HRD")); break; case 3: CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSO")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSO")); break; case 4: CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSC")); break; default: break; @@ -1045,8 +1044,7 @@ CMenuManager::Draw() CFont::SetCentreOff(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); -#if GTA_VERSION >= GTA3_PC_11 -#ifdef DRAW_MENU_VERSION_TEXT +#if GTA_VERSION >= GTA3_PC_11 && defined(DRAW_MENU_VERSION_TEXT) CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); @@ -1056,7 +1054,6 @@ CMenuManager::Draw() strcpy(gString, "V1.1"); AsciiToUnicode(gString, gUString); CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); -#endif #endif CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); @@ -1297,11 +1294,12 @@ CMenuManager::Draw() #endif #ifdef CUSTOM_FRONTEND_OPTIONS + // Thanks R*, for checking mouse hovering in Draw(). static int lastSelectedOpt = m_nCurrOption; #endif #ifdef SCROLLABLE_PAGES - int firstOption = m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen) ? m_nFirstVisibleRowOnList : 0; + int firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0; for (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) { #else for (int i = 0; i < NUM_MENUROWS; ++i) { @@ -1334,38 +1332,6 @@ CMenuManager::Draw() leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } -#ifdef CUSTOM_FRONTEND_OPTIONS - if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action < MENUACTION_NOTHING) { // CFO check - CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; - if (option.m_Action == MENUACTION_CFO_SELECT) { - if (option.m_CFOSelect->onlyApplyOnEnter){ - if (m_nCurrOption != i) { - if (option.m_CFOSelect->displayedValue != option.m_CFOSelect->lastSavedValue) - SetHelperText(3); // Restored original value - -// option.displayedValue = option.lastSavedValue = *option.m_CFO->value; - - } else { - if (option.m_CFOSelect->displayedValue != *option.m_CFO->value) - SetHelperText(1); // Enter to apply - else if (m_nHelperTextMsgId == 1) - ResetHelperText(); // Applied - } - } - } - - if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) { - CMenuScreenCustom::CMenuEntry &oldOption = aScreens[m_nCurrScreen].m_aEntries[lastSelectedOpt]; - if (oldOption.m_Action == MENUACTION_CFO_DYNAMIC) - if(oldOption.m_CFODynamic->buttonPressFunc) - oldOption.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); - - if (oldOption.m_Action == MENUACTION_CFO_SELECT && oldOption.m_CFOSelect->onlyApplyOnEnter) - oldOption.m_CFOSelect->displayedValue = oldOption.m_CFOSelect->lastSavedValue = *oldOption.m_CFO->value; - } - } -#endif - switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { case MENUACTION_CHANGEMENU: { switch (aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu) { @@ -1584,7 +1550,25 @@ CMenuManager::Draw() case MENUACTION_CFO_SELECT: CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; if (option.m_Action == MENUACTION_CFO_SELECT) { - // To whom manipulate option.m_CFO->value of static options externally (like RestoreDef functions) + + if (option.m_CFOSelect->onlyApplyOnEnter){ + if (m_nCurrOption != i) { + if (option.m_CFOSelect->displayedValue != option.m_CFOSelect->lastSavedValue) + SetHelperText(3); // Restored original value + + // If that was previously selected option, restore it to default value. + // if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) + option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value; + + } else { + if (option.m_CFOSelect->displayedValue != *option.m_CFO->value) + SetHelperText(1); // Enter to apply + else if (m_nHelperTextMsgId == 1) + ResetHelperText(); // Applied + } + } + + // To whom manipulate option.m_CFO->value of select options externally (like RestoreDef functions) if (*option.m_CFO->value != option.m_CFOSelect->lastSavedValue) option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value; @@ -1594,6 +1578,11 @@ CMenuManager::Draw() rightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]); } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { + if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) { + if(option.m_CFODynamic->buttonPressFunc) + option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + } + if (option.m_CFODynamic->drawFunc) { rightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i); } @@ -1730,7 +1719,9 @@ CMenuManager::Draw() if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 // To make assigning built-in actions to new custom options possible. -#ifndef CUSTOM_FRONTEND_OPTIONS +#ifdef CUSTOM_FRONTEND_OPTIONS + && ScreenHasOption(m_nCurrScreen, "FEA_3DH") +#else && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS #endif && m_nPrefsAudio3DProviderIndex != -1) { @@ -1807,21 +1798,21 @@ CMenuManager::Draw() #endif #ifdef SCROLLABLE_PAGES - #define SCROLLBAR_BOTTOM_X 125.0f // only for background, scrollbar's itself is calculated + #define SCROLLBAR_BOTTOM_Y 125.0f // only for background, scrollbar's itself is calculated #define SCROLLBAR_RIGHT_X 36.0f #define SCROLLBAR_WIDTH 9.5f - #define SCROLLBAR_TOP_X 64 + #define SCROLLBAR_TOP_Y 64 - if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) { + if (SCREEN_HAS_AUTO_SCROLLBAR) { // Scrollbar background - CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_X), - MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_X)), CRGBA(100, 100, 66, FadeIn(205))); + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_Y), + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_Y)), CRGBA(100, 100, 66, FadeIn(205))); float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nTotalListRow / (float) MAX_VISIBLE_OPTION); float scrollbarBottom, scrollbarTop; - scrollbarBottom = MENU_Y(SCROLLBAR_TOP_X - 8 + m_nScrollbarTopMargin + scrollbarHeight); - scrollbarTop = MENU_Y(SCROLLBAR_TOP_X + m_nScrollbarTopMargin); + scrollbarBottom = MENU_Y(SCROLLBAR_TOP_Y - 8 + m_nScrollbarTopMargin + scrollbarHeight); + scrollbarTop = MENU_Y(SCROLLBAR_TOP_Y + m_nScrollbarTopMargin); // Scrollbar shadow CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 1 - SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), @@ -2132,7 +2123,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 } // Print bindings, including seperator (-) between them - CFont::SetScale(MENU_X(0.25f), MENU_Y(0.6f)); + CFont::SetScale(MENU_X(0.25f), MENU_Y(SMALLESTTEXT_Y_SCALE)); for (; contSetOrder < MAX_SETORDERS && controllerAction != -1; contSetOrder++) { wchar *settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder); if (settingText) { @@ -3158,9 +3149,7 @@ CMenuManager::DrawPlayerSetupScreen() CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_SKN")); // Skin list - CFont::SetRightJustifyOff(); - CFont::SetScale(MENU_X(PLAYERSETUP_ROW_TEXT_X_SCALE), MENU_Y(PLAYERSETUP_ROW_TEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + SET_FONT_FOR_LIST_ITEM if (m_nSkinsTotal > 0) { for (m_pSelectedSkin = m_pSkinListHead.nextSkin; m_pSelectedSkin->skinId != m_nFirstVisibleRowOnList; m_pSelectedSkin = m_pSelectedSkin->nextSkin); @@ -5175,7 +5164,7 @@ CMenuManager::ProcessButtonPresses(void) increase = true; } else if ( #ifdef SCROLLABLE_PAGES - !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) && + !SCREEN_HAS_AUTO_SCROLLBAR && #endif CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { increase = true; @@ -5188,7 +5177,7 @@ CMenuManager::ProcessButtonPresses(void) decrease = true; } else if ( #ifdef SCROLLABLE_PAGES - !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) && + !SCREEN_HAS_AUTO_SCROLLBAR && #endif CPad::GetPad(0)->GetMouseWheelDownJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { decrease = true; diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 9f935510..e749069d 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -25,15 +25,18 @@ #define MENUSLIDER_X 256.0f #define MENUSLIDER_UNK 256.0f -#define BIGTEXT_X_SCALE 0.75f +#define BIGTEXT_X_SCALE 0.75f // For FONT_HEADING #define BIGTEXT_Y_SCALE 0.9f -#define MEDIUMTEXT_X_SCALE 0.55f +#define MEDIUMTEXT_X_SCALE 0.55f // For FONT_HEADING #define MEDIUMTEXT_Y_SCALE 0.8f -#define SMALLTEXT_X_SCALE 0.45f +#define SMALLTEXT_X_SCALE 0.45f // used for FONT_HEADING and FONT_BANK, but looks off for HEADING #define SMALLTEXT_Y_SCALE 0.7f -#define SMALLESTTEXT_X_SCALE 0.4f +#define SMALLESTTEXT_X_SCALE 0.4f // used for both FONT_HEADING and FONT_BANK #define SMALLESTTEXT_Y_SCALE 0.6f +#define HELPER_TEXT_LEFT_MARGIN 320.0f +#define HELPER_TEXT_BOTTOM_MARGIN 120.0f + #define PLAYERSETUP_LIST_TOP 28.0f #define PLAYERSETUP_LIST_BOTTOM 125.0f #define PLAYERSETUP_LIST_LEFT 200.0f @@ -45,8 +48,6 @@ #endif #define PLAYERSETUP_SCROLLBUTTON_HEIGHT 17.0f #define PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION 64 -#define PLAYERSETUP_ROW_TEXT_X_SCALE 0.4f -#define PLAYERSETUP_ROW_TEXT_Y_SCALE 0.6f #define PLAYERSETUP_SKIN_COLUMN_LEFT 220.0f #define PLAYERSETUP_DATE_COLUMN_RIGHT 56.0f #define PLAYERSETUP_LIST_BODY_TOP 47 -- cgit v1.2.3 From c4c92c357fac073c80ef256f5be005ff9ce43e7a Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 16 Dec 2020 13:25:23 +0100 Subject: tidy water sync --- src/render/WaterLevel.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index 49fc3a22..6cd3fdad 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -62,7 +62,11 @@ CWaterLevel::Initialise(Const char *pWaterDat) #ifdef MASTER int32 hFile = -1; - while ((hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb")) < 0); + do + { + hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb"); + } + while ( hFile < 0 ); #else int32 hFile = CFileMgr::OpenFile("DATA\\waterpro.dat", "rb"); #endif -- cgit v1.2.3 From c42463bf4e26bc889130d2b3f441f516ca207246 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 16 Dec 2020 13:32:13 +0100 Subject: more tidy water sync --- src/render/WaterLevel.cpp | 86 +++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index 6cd3fdad..977b61f3 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -221,8 +221,8 @@ CWaterLevel::Initialise(Const char *pWaterDat) int32 slot = CTxdStore::FindTxdSlot("particle"); CTxdStore::SetCurrentTxd(slot); - if ( gpWaterTex == NULL ) - gpWaterTex = RwTextureRead("water_old", NULL); + if ( gpWaterTex == nil ) + gpWaterTex = RwTextureRead("water_old", nil); gpWaterRaster = RwTextureGetRaster(gpWaterTex); CTxdStore::PopCurrentTxd(); @@ -239,10 +239,10 @@ CWaterLevel::Shutdown() FreeBoatWakeArray(); DestroyWavyAtomic(); - if ( gpWaterTex != NULL ) + if ( gpWaterTex != nil ) { RwTextureDestroy(gpWaterTex); - gpWaterTex = NULL; + gpWaterTex = nil; } } @@ -264,15 +264,15 @@ CWaterLevel::CreateWavyAtomic() |rpGEOMETRYPRELIT |rpGEOMETRYMODULATEMATERIALCOLOR); - ASSERT(wavyGeometry != NULL); + ASSERT(wavyGeometry != nil); } { wavyMaterial = RpMaterialCreate(); - ASSERT(wavyMaterial != NULL); - ASSERT(gpWaterTex != NULL); + ASSERT(wavyMaterial != nil); + ASSERT(gpWaterTex != nil); RpMaterialSetTexture(wavyMaterial, gpWaterTex); } @@ -280,7 +280,7 @@ CWaterLevel::CreateWavyAtomic() { wavyTriangles = RpGeometryGetTriangles(wavyGeometry); - ASSERT(wavyTriangles != NULL); + ASSERT(wavyTriangles != nil); /* [B] [C] *********** @@ -311,9 +311,9 @@ CWaterLevel::CreateWavyAtomic() { wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0); - ASSERT(wavyMorphTarget != NULL); + ASSERT(wavyMorphTarget != nil); wavyVert = RpMorphTargetGetVertices(wavyMorphTarget); - ASSERT(wavyVert != NULL); + ASSERT(wavyVert != nil); for ( int32 i = 0; i < 9; i++ ) { @@ -333,10 +333,10 @@ CWaterLevel::CreateWavyAtomic() { wavyFrame = RwFrameCreate(); - ASSERT( wavyFrame != NULL ); + ASSERT( wavyFrame != nil ); ms_pWavyAtomic = RpAtomicCreate(); - ASSERT( ms_pWavyAtomic != NULL ); + ASSERT( ms_pWavyAtomic != nil ); RpAtomicSetGeometry(ms_pWavyAtomic, wavyGeometry, 0); RpAtomicSetFrame(ms_pWavyAtomic, wavyFrame); @@ -535,7 +535,7 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool if ( nBlock == NO_WATER ) return false; - ASSERT( pfOutLevel != NULL ); + ASSERT( pfOutLevel != nil ); *pfOutLevel = ms_aWaterZs[nBlock]; float fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f); @@ -574,7 +574,7 @@ CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLeve if ( nBlock == NO_WATER ) return false; - ASSERT( pfOutLevel != NULL ); + ASSERT( pfOutLevel != nil ); *pfOutLevel = ms_aWaterZs[nBlock]; return true; @@ -1247,19 +1247,19 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col CBoat::FillBoatList(); - ASSERT( ms_pWavyAtomic != NULL ); + ASSERT( ms_pWavyAtomic != nil ); RpGeometry *geometry = RpAtomicGetGeometry(ms_pWavyAtomic); - ASSERT( geometry != NULL ); + ASSERT( geometry != nil ); RwRGBA *wavyPreLights = RpGeometryGetPreLightColors(geometry); RwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(geometry, rwTEXTURECOORDINATEINDEX0); RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geometry, 0)); - ASSERT( wavyPreLights != NULL ); - ASSERT( wavyTexCoords != NULL ); - ASSERT( wavyVertices != NULL ); + ASSERT( wavyPreLights != nil ); + ASSERT( wavyTexCoords != nil ); + ASSERT( wavyVertices != nil ); RpGeometryLock(geometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKPRELIGHT @@ -1282,7 +1282,7 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col RpGeometryUnlock(geometry); } - static CBoat *apBoatList[4] = { NULL }; + static CBoat *apBoatList[4] = { nil }; if ( apGeomArray[0] && nGeomUsed < MAX_BOAT_WAKES @@ -1296,16 +1296,16 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); RpGeometry *geom = apGeomArray[nGeomUsed++]; - ASSERT( wavyGeometry != NULL ); - ASSERT( geom != NULL ); + ASSERT( wavyGeometry != nil ); + ASSERT( geom != nil ); RpAtomic *atomic = RpAtomicCreate(); - ASSERT( atomic != NULL ); + ASSERT( atomic != nil ); RpAtomicSetGeometry(atomic, geom, 0); RwFrame *frame = RwFrameCreate(); - ASSERT( frame != NULL ); + ASSERT( frame != nil ); RwMatrixCopy(RwFrameGetMatrix(frame), RwFrameGetMatrix(RpAtomicGetFrame(ms_pWavyAtomic))); RpAtomicSetFrame(atomic, frame); @@ -1316,11 +1316,11 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col RwV3d *geomVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(geom, 0)); RwV3d *wavyVertices = RpMorphTargetGetVertices(RpGeometryGetMorphTarget(wavyGeometry, 0)); - ASSERT( geomTexCoords != NULL ); - ASSERT( wavyTexCoord != NULL ); - ASSERT( geomPreLights != NULL ); - ASSERT( geomVertices != NULL ); - ASSERT( wavyVertices != NULL ); + ASSERT( geomTexCoords != nil ); + ASSERT( wavyTexCoord != nil ); + ASSERT( geomPreLights != nil ); + ASSERT( geomVertices != nil ); + ASSERT( wavyVertices != nil ); RpGeometryLock(geom, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS); @@ -1337,7 +1337,7 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col for ( int32 k = 0; k < 4; k++ ) { - if ( apBoatList[k] != NULL ) + if ( apBoatList[k] != nil ) fDistMult += CBoat::IsVertexAffectedByWake(CVector(fVertexX, fVertexY, 0.0f), apBoatList[k]); } @@ -1386,7 +1386,7 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col pos.y = fY; pos.z = fZ; - ASSERT( ms_pWavyAtomic != NULL ); + ASSERT( ms_pWavyAtomic != nil ); RwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE); @@ -1441,7 +1441,7 @@ CWaterLevel::RenderAndEmptyRenderBuffer() { LittleTest(); - if ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, NULL, rwIM3D_VERTEXUV) ) + if ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV) ) { RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); RwIm3DEnd(); @@ -1459,29 +1459,29 @@ CWaterLevel::AllocateBoatWakeArray() PUSH_MEMID(MEMID_STREAM); - ASSERT(ms_pWavyAtomic != NULL ); + ASSERT(ms_pWavyAtomic != nil ); RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); - ASSERT(wavyGeometry != NULL ); + ASSERT(wavyGeometry != nil ); RpMorphTarget *wavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0); RpMaterial *wavyMaterial = RpGeometryGetMaterial(wavyGeometry, 0); - ASSERT(wavyMorphTarget != NULL ); - ASSERT(wavyMaterial != NULL ); + ASSERT(wavyMorphTarget != nil ); + ASSERT(wavyMaterial != nil ); for ( int32 geom = 0; geom < MAX_BOAT_WAKES; geom++ ) { - if ( apGeomArray[geom] == NULL ) + if ( apGeomArray[geom] == nil ) { apGeomArray[geom] = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP | rpGEOMETRYPRELIT | rpGEOMETRYMODULATEMATERIALCOLOR | rpGEOMETRYTEXTURED); - ASSERT(apGeomArray[geom] != NULL); + ASSERT(apGeomArray[geom] != nil); RpTriangle *geomTriangles = RpGeometryGetTriangles(apGeomArray[geom]); - ASSERT( geomTriangles != NULL ); + ASSERT( geomTriangles != nil ); for ( int32 i = 0; i < 8; i++ ) { @@ -1515,8 +1515,8 @@ CWaterLevel::AllocateBoatWakeArray() RpMorphTarget *geomMorphTarget = RpGeometryGetMorphTarget(apGeomArray[geom], 0); RwV3d *geomVertices = RpMorphTargetGetVertices(geomMorphTarget); - ASSERT( geomMorphTarget != NULL ); - ASSERT( geomVertices != NULL ); + ASSERT( geomMorphTarget != nil ); + ASSERT( geomVertices != nil ); for ( int32 i = 0; i < 9; i++ ) { @@ -1541,10 +1541,10 @@ CWaterLevel::FreeBoatWakeArray() { for ( int32 i = 0; i < MAX_BOAT_WAKES; i++ ) { - if ( apGeomArray[i] != NULL ) + if ( apGeomArray[i] != nil ) { RpGeometryDestroy(apGeomArray[i]); - apGeomArray[i] = NULL; + apGeomArray[i] = nil; } } -- cgit v1.2.3 From 7d89e955fe20696130fe76ed3d4582a756bd3621 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 16 Dec 2020 13:38:09 +0100 Subject: ;end of fucking waterlevel --- src/render/WaterLevel.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index 977b61f3..a0c7ae31 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -93,7 +93,11 @@ CWaterLevel::Initialise(Const char *pWaterDat) while ((line = CFileLoader::LoadLine(hFile))) { +#ifdef FIX_BUGS + if (*line && *line != ';' && !strstr(line, "* ;end of file")) +#else if (*line && *line != ';') +#endif { float z, l, b, r, t; sscanf(line, "%f %f %f %f %f", &z, &l, &b, &r, &t); -- cgit v1.2.3 From 8e454392059a07be3d8b5fa9ee01f27220980230 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 16 Dec 2020 23:45:18 +0300 Subject: Use scrolling if GRAPHICS_MENU_OPTIONS not defined, like miami --- src/core/Frontend.h | 2 -- src/core/MenuScreensCustom.cpp | 26 ++++++-------------------- src/core/config.h | 2 +- 3 files changed, 7 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/core/Frontend.h b/src/core/Frontend.h index e749069d..8cf3dd28 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -242,8 +242,6 @@ enum eMenuScreen #ifdef GRAPHICS_MENU_OPTIONS MENUPAGE_GRAPHICS_SETTINGS, -#else - MENUPAGE_ADVANCED_DISPLAY_SETTINGS, #endif #ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS MENUPAGE_DETECT_JOYSTICK, diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index ae08f5f5..3a6d9c8b 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -399,7 +399,12 @@ CMenuScreenCustom aScreens[MENUPAGES] = { MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, VIDEOMODE_SELECTOR MULTISAMPLING_SELECTOR - MENUACTION_CHANGEMENU, "FET_ADV", { nil, SAVESLOT_NONE, MENUPAGE_ADVANCED_DISPLAY_SETTINGS }, + ISLAND_LOADING_SELECTOR + DUALPASS_SELECTOR + CUTSCENE_BORDERS_TOGGLE + FREE_CAM_TOGGLE + POSTFX_SELECTORS + PIPELINES_SELECTOR MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, }, @@ -829,31 +834,12 @@ CMenuScreenCustom aScreens[MENUPAGES] = { #else MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, #endif -#ifdef EXTENDED_PIPELINES PIPELINES_SELECTOR -#endif ISLAND_LOADING_SELECTOR DUALPASS_SELECTOR MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefGraphics) }, MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, }, -#else - // MENUPAGE_ADVANCED_DISPLAY_SETTINGS - { "FET_ADV", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, - new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil, - - ISLAND_LOADING_SELECTOR - DUALPASS_SELECTOR - CUTSCENE_BORDERS_TOGGLE - FREE_CAM_TOGGLE -#ifdef EXTENDED_COLOURFILTER - POSTFX_SELECTORS -#endif -#ifdef EXTENDED_PIPELINES - PIPELINES_SELECTOR -#endif - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, #endif #ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS diff --git a/src/core/config.h b/src/core/config.h index ad0df2da..8c9c1ccd 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -299,7 +299,7 @@ enum Config { # define CUSTOM_FRONTEND_OPTIONS # ifdef CUSTOM_FRONTEND_OPTIONS -# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full +# define GRAPHICS_MENU_OPTIONS // otherwise Display settings will be scrollable # define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU # define CUTSCENE_BORDERS_SWITCH # define MULTISAMPLING // adds MSAA option -- cgit v1.2.3 From 9a9b1e757495be1eca3477353e040219b9bb7eb7 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 16 Dec 2020 23:28:06 +0200 Subject: Fix placement of some script functions --- src/control/Script4.cpp | 140 +++++++++++++++++++++++++++++++++++++++++++++++ src/control/Script5.cpp | 141 ------------------------------------------------ 2 files changed, 140 insertions(+), 141 deletions(-) (limited to 'src') diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp index 3629bb4b..afd6eba4 100644 --- a/src/control/Script4.cpp +++ b/src/control/Script4.cpp @@ -2025,3 +2025,143 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) } return -1; } + +int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index) +{ + if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1) + ScriptSphereArray[index].m_Index = 1; + else + ScriptSphereArray[index].m_Index++; + return (uint16)index | ScriptSphereArray[index].m_Index << 16; +} + +int32 CTheScripts::GetActualScriptSphereIndex(int32 index) +{ + if (index == -1) + return -1; + uint16 check = (uint32)index >> 16; + uint16 array_idx = index & (0xFFFF); + script_assert(array_idx < ARRAY_SIZE(ScriptSphereArray)); + if (check != ScriptSphereArray[array_idx].m_Index) + return -1; + return array_idx; +} + +void CTheScripts::DrawScriptSpheres() +{ + for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { + if (ScriptSphereArray[i].m_bInUse) + C3dMarkers::PlaceMarkerSet(ScriptSphereArray[i].m_Id, MARKERTYPE_CYLINDER, ScriptSphereArray[i].m_vecCenter, ScriptSphereArray[i].m_fRadius, + SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0); + } +} + +int32 CTheScripts::AddScriptSphere(int32 id, CVector pos, float radius) +{ + int16 i = 0; + for (i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { + if (!ScriptSphereArray[i].m_bInUse) + break; + } +#ifdef FIX_BUGS + if (i == MAX_NUM_SCRIPT_SPHERES) + return -1; +#endif + ScriptSphereArray[i].m_bInUse = true; + ScriptSphereArray[i].m_Id = id; + ScriptSphereArray[i].m_vecCenter = pos; + ScriptSphereArray[i].m_fRadius = radius; + return GetNewUniqueScriptSphereIndex(i); +} + +void CTheScripts::RemoveScriptSphere(int32 index) +{ + index = GetActualScriptSphereIndex(index); + if (index == -1) + return; + ScriptSphereArray[index].m_bInUse = false; + ScriptSphereArray[index].m_Id = 0; +} + +void CTheScripts::AddToBuildingSwapArray(CBuilding* pBuilding, int32 old_model, int32 new_model) +{ + int i = 0; + bool found = false; + while (i < MAX_NUM_BUILDING_SWAPS && !found) { + if (BuildingSwapArray[i].m_pBuilding == pBuilding) + found = true; + else + i++; + } + if (found) { + if (BuildingSwapArray[i].m_nOldModel == new_model) { + BuildingSwapArray[i].m_pBuilding = nil; + BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; + } + else { + BuildingSwapArray[i].m_nNewModel = new_model; + } + } + else { + i = 0; + while (i < MAX_NUM_BUILDING_SWAPS && !found) { + if (BuildingSwapArray[i].m_pBuilding == nil) + found = true; + else + i++; + } + if (found) { + BuildingSwapArray[i].m_pBuilding = pBuilding; + BuildingSwapArray[i].m_nNewModel = new_model; + BuildingSwapArray[i].m_nOldModel = old_model; + } + } +} + +void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove) +{ + int i = 0; + bool found = false; + while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { + if (InvisibilitySettingArray[i] == pEntity) + found = true; + else + i++; + } + if (found) { + if (remove) + InvisibilitySettingArray[i] = nil; + } + else if (!remove) { + i = 0; + while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { + if (InvisibilitySettingArray[i] == nil) + found = true; + else + i++; + } + if (found) + InvisibilitySettingArray[i] = pEntity; + } +} + +void CTheScripts::UndoBuildingSwaps() +{ + for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { + if (BuildingSwapArray[i].m_pBuilding) { + BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nOldModel); + BuildingSwapArray[i].m_pBuilding = nil; + BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; + } + } +} + +void CTheScripts::UndoEntityInvisibilitySettings() +{ + for (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { + if (InvisibilitySettingArray[i]) { + InvisibilitySettingArray[i]->bIsVisible = true; + InvisibilitySettingArray[i] = nil; + } + } +} diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp index 4826192e..153f2393 100644 --- a/src/control/Script5.cpp +++ b/src/control/Script5.cpp @@ -17,147 +17,6 @@ #include "World.h" #include "main.h" -int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index) -{ - if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1) - ScriptSphereArray[index].m_Index = 1; - else - ScriptSphereArray[index].m_Index++; - return (uint16)index | ScriptSphereArray[index].m_Index << 16; -} - -int32 CTheScripts::GetActualScriptSphereIndex(int32 index) -{ - if (index == -1) - return -1; - uint16 check = (uint32)index >> 16; - uint16 array_idx = index & (0xFFFF); - script_assert(array_idx < ARRAY_SIZE(ScriptSphereArray)); - if (check != ScriptSphereArray[array_idx].m_Index) - return -1; - return array_idx; -} - -void CTheScripts::DrawScriptSpheres() -{ - for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { - if (ScriptSphereArray[i].m_bInUse) - C3dMarkers::PlaceMarkerSet(ScriptSphereArray[i].m_Id, MARKERTYPE_CYLINDER, ScriptSphereArray[i].m_vecCenter, ScriptSphereArray[i].m_fRadius, - SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0); - } -} - -int32 CTheScripts::AddScriptSphere(int32 id, CVector pos, float radius) -{ - int16 i = 0; - for (i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) { - if (!ScriptSphereArray[i].m_bInUse) - break; - } -#ifdef FIX_BUGS - if (i == MAX_NUM_SCRIPT_SPHERES) - return -1; -#endif - ScriptSphereArray[i].m_bInUse = true; - ScriptSphereArray[i].m_Id = id; - ScriptSphereArray[i].m_vecCenter = pos; - ScriptSphereArray[i].m_fRadius = radius; - return GetNewUniqueScriptSphereIndex(i); -} - -void CTheScripts::RemoveScriptSphere(int32 index) -{ - index = GetActualScriptSphereIndex(index); - if (index == -1) - return; - ScriptSphereArray[index].m_bInUse = false; - ScriptSphereArray[index].m_Id = 0; -} - -void CTheScripts::AddToBuildingSwapArray(CBuilding* pBuilding, int32 old_model, int32 new_model) -{ - int i = 0; - bool found = false; - while (i < MAX_NUM_BUILDING_SWAPS && !found) { - if (BuildingSwapArray[i].m_pBuilding == pBuilding) - found = true; - else - i++; - } - if (found) { - if (BuildingSwapArray[i].m_nOldModel == new_model) { - BuildingSwapArray[i].m_pBuilding = nil; - BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; - } - else { - BuildingSwapArray[i].m_nNewModel = new_model; - } - } - else { - i = 0; - while (i < MAX_NUM_BUILDING_SWAPS && !found) { - if (BuildingSwapArray[i].m_pBuilding == nil) - found = true; - else - i++; - } - if (found) { - BuildingSwapArray[i].m_pBuilding = pBuilding; - BuildingSwapArray[i].m_nNewModel = new_model; - BuildingSwapArray[i].m_nOldModel = old_model; - } - } -} - -void CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove) -{ - int i = 0; - bool found = false; - while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { - if (InvisibilitySettingArray[i] == pEntity) - found = true; - else - i++; - } - if (found) { - if (remove) - InvisibilitySettingArray[i] = nil; - } - else if (!remove) { - i = 0; - while (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) { - if (InvisibilitySettingArray[i] == nil) - found = true; - else - i++; - } - if (found) - InvisibilitySettingArray[i] = pEntity; - } -} - -void CTheScripts::UndoBuildingSwaps() -{ - for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { - if (BuildingSwapArray[i].m_pBuilding) { - BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nOldModel); - BuildingSwapArray[i].m_pBuilding = nil; - BuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1; - } - } -} - -void CTheScripts::UndoEntityInvisibilitySettings() -{ - for (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { - if (InvisibilitySettingArray[i]) { - InvisibilitySettingArray[i]->bIsVisible = true; - InvisibilitySettingArray[i] = nil; - } - } -} - - void CRunningScript::UpdateCompareFlag(bool flag) { if (m_bNotFlag) -- cgit v1.2.3 From dd579c40800856a427274f7491bb7bcc00df9e00 Mon Sep 17 00:00:00 2001 From: erorcun Date: Thu, 17 Dec 2020 02:47:48 +0300 Subject: Fix --- src/core/World.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/World.cpp b/src/core/World.cpp index da565f22..a7531c83 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1955,12 +1955,11 @@ CWorld::Process(void) } else { for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { CEntity *movingEnt = (CEntity *)node->item; -#ifdef SQUEEZE_PERFORMANCE - if (movingEnt->bRemoveFromWorld) { - RemoveEntityInsteadOfProcessingIt(movingEnt); - } else -#endif +#ifdef FIX_BUGS // from VC + if(!movingEnt->bRemoveFromWorld && movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP && +#else if(movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP && +#endif RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) { RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), 0.02f * (movingEnt->IsObject() -- cgit v1.2.3 From cc5af26417d446ccadb6a8f885926c734d29131f Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 17 Dec 2020 12:47:00 +0100 Subject: PreAllocateRwObjects --- src/core/main.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/main.h | 1 + 2 files changed, 58 insertions(+) (limited to 'src') diff --git a/src/core/main.cpp b/src/core/main.cpp index cc20047f..51c48452 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -415,6 +415,63 @@ PluginAttach(void) return TRUE; } +#ifdef GTA_PS2 +#define NUM_PREALLOC_ATOMICS 3245 +#define NUM_PREALLOC_CLUMPS 101 +#define NUM_PREALLOC_FRAMES 2821 +#define NUM_PREALLOC_GEOMETRIES 1404 +#define NUM_PREALLOC_TEXDICTS 106 +#define NUM_PREALLOC_TEXTURES 1900 +#define NUM_PREALLOC_MATERIALS 3300 +bool preAlloc; + +void +PreAllocateRwObjects(void) +{ + int i; + void **tmp = new void*[0x8000]; + preAlloc = true; + + for(i = 0; i < NUM_PREALLOC_ATOMICS; i++) + tmp[i] = RpAtomicCreate(); + for(i = 0; i < NUM_PREALLOC_ATOMICS; i++) + RpAtomicDestroy((RpAtomic*)tmp[i]); + + for(i = 0; i < NUM_PREALLOC_CLUMPS; i++) + tmp[i] = RpClumpCreate(); + for(i = 0; i < NUM_PREALLOC_CLUMPS; i++) + RpClumpDestroy((RpClump*)tmp[i]); + + for(i = 0; i < NUM_PREALLOC_FRAMES; i++) + tmp[i] = RwFrameCreate(); + for(i = 0; i < NUM_PREALLOC_FRAMES; i++) + RwFrameDestroy((RwFrame*)tmp[i]); + + for(i = 0; i < NUM_PREALLOC_GEOMETRIES; i++) + tmp[i] = RpGeometryCreate(0, 0, 0); + for(i = 0; i < NUM_PREALLOC_GEOMETRIES; i++) + RpGeometryDestroy((RpGeometry*)tmp[i]); + + for(i = 0; i < NUM_PREALLOC_TEXDICTS; i++) + tmp[i] = RwTexDictionaryCreate(); + for(i = 0; i < NUM_PREALLOC_TEXDICTS; i++) + RwTexDictionaryDestroy((RwTexDictionary*)tmp[i]); + + for(i = 0; i < NUM_PREALLOC_TEXTURES; i++) + tmp[i] = RwTextureCreate(RwRasterCreate(0, 0, 0, 0)); + for(i = 0; i < NUM_PREALLOC_TEXDICTS; i++) + RwTextureDestroy((RwTexture*)tmp[i]); + + for(i = 0; i < NUM_PREALLOC_MATERIALS; i++) + tmp[i] = RpMaterialCreate(); + for(i = 0; i < NUM_PREALLOC_MATERIALS; i++) + RpMaterialDestroy((RpMaterial*)tmp[i]); + + delete[] tmp; + preAlloc = false; +} +#endif + static RwBool Initialise3D(void *param) { diff --git a/src/core/main.h b/src/core/main.h index 77fac46a..149c0878 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -29,6 +29,7 @@ class CSprite2d; bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); void DoRWStuffEndOfFrame(void); +void PreAllocateRwObjects(void); void InitialiseGame(void); void LoadingScreen(const char *str1, const char *str2, const char *splashscreen); void LoadingIslandScreen(const char *levelName); -- cgit v1.2.3 From e9a567034818c5e3338120958061e4a4278d97da Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 18 Dec 2020 02:57:54 +0200 Subject: PlayerInfo functions reordered into original order, FindPlayer... functions moved to PlayerInfo, improved CVector <-> RwV3d conversion, small fixes --- src/collision/Collision.cpp | 14 +- src/control/Replay.cpp | 24 +- src/core/Cam.cpp | 12 +- src/core/PlayerInfo.cpp | 768 +++++++++++++++++++++---------------- src/core/PlayerInfo.h | 21 +- src/core/World.cpp | 96 ----- src/core/World.h | 11 - src/extras/screendroplets.cpp | 6 +- src/math/Vector.h | 25 +- src/math/VuVector.h | 13 +- src/modelinfo/VehicleModelInfo.cpp | 2 +- src/peds/CopPed.cpp | 2 +- src/peds/EmergencyPed.cpp | 16 +- src/peds/Ped.cpp | 2 +- src/peds/Ped.h | 4 +- src/peds/PedAI.cpp | 2 +- src/peds/PedFight.cpp | 2 +- src/peds/PedIK.cpp | 14 +- src/peds/PedIK.h | 2 +- src/peds/PlayerPed.cpp | 2 +- src/render/Clouds.cpp | 2 +- src/render/Coronas.cpp | 6 +- src/render/Fluff.cpp | 10 +- src/render/Particle.cpp | 4 +- src/render/PointLights.cpp | 4 +- src/render/Renderer.cpp | 4 +- src/render/Weather.cpp | 2 +- src/weapons/Weapon.cpp | 4 +- 28 files changed, 534 insertions(+), 540 deletions(-) (limited to 'src') diff --git a/src/collision/Collision.cpp b/src/collision/Collision.cpp index 41997e32..7fb5c30b 100644 --- a/src/collision/Collision.cpp +++ b/src/collision/Collision.cpp @@ -665,7 +665,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod // transform line to model space Invert(matrix, matTransform); CVuVector newline[2]; - TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); + TransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2); // If we don't intersect with the bounding box, no chance on the rest if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) @@ -1474,7 +1474,7 @@ CCollision::ProcessLineOfSight(const CColLine &line, // transform line to model space Invert(matrix, matTransform); CVuVector newline[2]; - TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); + TransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2); if(mindist < 1.0f) newline[1] = newline[0] + (newline[1] - newline[0])*mindist; @@ -1606,7 +1606,7 @@ CCollision::ProcessVerticalLine(const CColLine &line, // transform line to model space Invert(matrix, matTransform); CVuVector newline[2]; - TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); + TransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2); if(mindist < 1.0f) newline[1] = newline[0] + (newline[1] - newline[0])*mindist; @@ -1806,16 +1806,16 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA, matAB *= matrixA; CVuVector bsphereAB; // bounding sphere of A in B space - TransformPoint(bsphereAB, matAB, *(RwV3d*)modelA.boundingSphere.center); // inlined + TransformPoint(bsphereAB, matAB, modelA.boundingSphere.center); // inlined bsphereAB.w = modelA.boundingSphere.radius; if(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox)) return 0; // transform modelA's spheres and lines to B space - TransformPoints(aSpheresA, modelA.numSpheres, matAB, (RwV3d*)&modelA.spheres->center, sizeof(CColSphere)); + TransformPoints(aSpheresA, modelA.numSpheres, matAB, &modelA.spheres->center, sizeof(CColSphere)); for(i = 0; i < modelA.numSpheres; i++) aSpheresA[i].w = modelA.spheres[i].radius; - TransformPoints(aLinesA, modelA.numLines*2, matAB, (RwV3d*)&modelA.lines->p0, sizeof(CColLine)/2); + TransformPoints(aLinesA, modelA.numLines*2, matAB, &modelA.lines->p0, sizeof(CColLine)/2); // Test them against model B's bounding volumes int numSpheresA = 0; @@ -1832,7 +1832,7 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA, matBA *= matrixB; // transform modelB's spheres to A space - TransformPoints(aSpheresB, modelB.numSpheres, matBA, (RwV3d*)&modelB.spheres->center, sizeof(CColSphere)); + TransformPoints(aSpheresB, modelB.numSpheres, matBA, &modelB.spheres->center, sizeof(CColSphere)); for(i = 0; i < modelB.numSpheres; i++) aSpheresB[i].w = modelB.spheres[i].radius; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 4732ba2f..d9e5e675 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1038,10 +1038,10 @@ void CReplay::ProcessReplayCamera(void) TheCamera.GetUp() = CVector(0.0f, 1.0f, 0.0f); TheCamera.GetRight() = CVector(1.0f, 0.0f, 0.0f); RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); - pm->pos = *(RwV3d*)&TheCamera.GetPosition(); - pm->at = *(RwV3d*)&TheCamera.GetForward(); - pm->up = *(RwV3d*)&TheCamera.GetUp(); - pm->right = *(RwV3d*)&TheCamera.GetRight(); + pm->pos = TheCamera.GetPosition(); + pm->at = TheCamera.GetForward(); + pm->up = TheCamera.GetUp(); + pm->right = TheCamera.GetRight(); break; } case REPLAYCAMMODE_FIXED: @@ -1057,10 +1057,10 @@ void CReplay::ProcessReplayCamera(void) TheCamera.GetMatrix().GetUp() = up; TheCamera.GetMatrix().GetRight() = right; RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); - pm->pos = *(RwV3d*)&TheCamera.GetMatrix().GetPosition(); - pm->at = *(RwV3d*)&TheCamera.GetMatrix().GetForward(); - pm->up = *(RwV3d*)&TheCamera.GetMatrix().GetUp(); - pm->right = *(RwV3d*)&TheCamera.GetMatrix().GetRight(); + pm->pos = TheCamera.GetMatrix().GetPosition(); + pm->at = TheCamera.GetMatrix().GetForward(); + pm->up = TheCamera.GetMatrix().GetUp(); + pm->right = TheCamera.GetMatrix().GetRight(); break; } default: @@ -1581,10 +1581,10 @@ void CReplay::ProcessLookAroundCam(void) TheCamera.GetRight() = right; TheCamera.SetPosition(camera_pt); RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); - pm->pos = *(RwV3d*)&TheCamera.GetPosition(); - pm->at = *(RwV3d*)&TheCamera.GetForward(); - pm->up = *(RwV3d*)&TheCamera.GetUp(); - pm->right = *(RwV3d*)&TheCamera.GetRight(); + pm->pos = TheCamera.GetPosition(); + pm->at = TheCamera.GetForward(); + pm->up = TheCamera.GetUp(); + pm->right = TheCamera.GetRight(); TheCamera.CalculateDerivedValues(); RwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera))); RwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera)); diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 65a867be..5906310b 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -2472,7 +2472,7 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float) ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); @@ -2573,7 +2573,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) } #if GTA_VERSION < GTA3_PC_11 - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); @@ -2611,7 +2611,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) HeadPos.x = 0.0f; HeadPos.y = 0.0f; HeadPos.z = 0.0f; - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f * Cos(m_fInitialPlayerOrientation); @@ -2700,7 +2700,7 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); @@ -2868,7 +2868,7 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, Source = HeadPos; // unused: - // ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&MidPos, PED_MID); + // ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(MidPos, PED_MID); // Source - MidPos; // Look around @@ -2963,7 +2963,7 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 5866485d..07424736 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -3,6 +3,7 @@ #include "Automobile.h" #include "Bridge.h" #include "Camera.h" +#include "CarCtrl.h" #include "Cranes.h" #include "Darkel.h" #include "Explosion.h" @@ -31,83 +32,6 @@ #include "ZoneCull.h" #include "main.h" -void -CPlayerInfo::SetPlayerSkin(char *skin) -{ - strncpy(m_aSkinName, skin, 32); - LoadPlayerSkin(); -} - -const CVector & -CPlayerInfo::GetPos() -{ -#ifdef FIX_BUGS - if (!m_pPed) - return TheCamera.GetPosition(); -#endif - if (m_pPed->InVehicle()) - return m_pPed->m_pMyVehicle->GetPosition(); - return m_pPed->GetPosition(); -} - -void -CPlayerInfo::LoadPlayerSkin() -{ - DeletePlayerSkin(); - - m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName); - if (!m_pSkinTexture) - m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME); -} - -void -CPlayerInfo::DeletePlayerSkin() -{ - if (m_pSkinTexture) { - RwTextureDestroy(m_pSkinTexture); - m_pSkinTexture = nil; - } -} - -void -CPlayerInfo::KillPlayer() -{ - if (m_WBState != WBSTATE_PLAYING) return; - - m_WBState = WBSTATE_WASTED; - m_nWBTime = CTimer::GetTimeInMilliseconds(); - CDarkel::ResetOnPlayerDeath(); - CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2); - CStats::TimesDied++; -} - -void -CPlayerInfo::ArrestPlayer() -{ - if (m_WBState != WBSTATE_PLAYING) return; - - m_WBState = WBSTATE_BUSTED; - m_nWBTime = CTimer::GetTimeInMilliseconds(); - CDarkel::ResetOnPlayerDeath(); - CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2); - CStats::TimesArrested++; -} - -bool -CPlayerInfo::IsPlayerInRemoteMode() -{ - return m_pRemoteVehicle || m_bInRemoteMode; -} - -void -CPlayerInfo::PlayerFailedCriticalMission() -{ - if (m_WBState != WBSTATE_PLAYING) - return; - m_WBState = WBSTATE_FAILED_CRITICAL_MISSION; - m_nWBTime = CTimer::GetTimeInMilliseconds(); - CDarkel::ResetOnPlayerDeath(); -} void CPlayerInfo::Clear(void) @@ -147,275 +71,84 @@ CPlayerInfo::Clear(void) } void -CPlayerInfo::BlowUpRCBuggy(void) +CPlayerInfo::Process(void) { - if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld) +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) return; - - CRemote::TakeRemoteControlledCarFromPlayer(); - m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); -} - -void -CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car) -{ - if (!car || car == m_pPed->m_pMyVehicle) { - if (m_pPed->EnteringCar()) - m_pPed->QuitEnteringCar(); - } - if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) - m_pPed->ClearObjective(); -} - -void -CPlayerInfo::MakePlayerSafe(bool toggle) -{ - if (toggle) { - CTheScripts::ResetCountdownToMakePlayerUnsafe(); - m_pPed->m_pWanted->m_bIgnoredByEveryone = true; - CWorld::StopAllLawEnforcersInTheirTracks(); - CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PLAYERINFO); - CPad::StopPadsShaking(); - m_pPed->bBulletProof = true; - m_pPed->bFireProof = true; - m_pPed->bCollisionProof = true; - m_pPed->bMeleeProof = true; - m_pPed->bOnlyDamagedByPlayer = true; - m_pPed->bExplosionProof = true; - m_pPed->m_bCanBeDamaged = false; - ((CPlayerPed*)m_pPed)->ClearAdrenaline(); - CancelPlayerEnteringCars(nil); - gFireManager.ExtinguishPoint(GetPos(), 4000.0f); - CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f); - CProjectileInfo::RemoveAllProjectiles(); - CWorld::SetAllCarsCanBeDamaged(false); - CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f); - CReplay::DisableReplays(); - - } else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) { - m_pPed->m_pWanted->m_bIgnoredByEveryone = false; - CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PLAYERINFO); - m_pPed->bBulletProof = false; - m_pPed->bFireProof = false; - m_pPed->bCollisionProof = false; - m_pPed->bMeleeProof = false; - m_pPed->bOnlyDamagedByPlayer = false; - m_pPed->bExplosionProof = false; - m_pPed->m_bCanBeDamaged = true; - CWorld::SetAllCarsCanBeDamaged(true); - CReplay::EnableReplays(); +#endif + // Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode. + bool startTaxiTimer = true; + if (m_bUnusedTaxiThing && m_pPed->bInVehicle) { + CVehicle *veh = m_pPed->m_pMyVehicle; + if ((veh->GetModelIndex() == MI_TAXI || veh->GetModelIndex() == MI_CABBIE || veh->GetModelIndex() == MI_BORGNINE) + && veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) { + for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) { + timePassed -= 1000; + ++m_nMoney; + } + startTaxiTimer = false; + } } -} + if (startTaxiTimer) + m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds(); -bool -CPlayerInfo::IsRestartingAfterDeath() -{ - return m_WBState == WBSTATE_WASTED; -} + // The effect that makes money counter does while earning/losing money + if (m_nVisibleMoney != m_nMoney) { + int diff = m_nMoney - m_nVisibleMoney; + int diffAbs = Abs(diff); + int changeBy; -bool -CPlayerInfo::IsRestartingAfterArrest() -{ - return m_WBState == WBSTATE_BUSTED; -} + if (diffAbs > 100000) + changeBy = 12345; + else if (diffAbs > 10000) + changeBy = 1234; + else if (diffAbs > 1000) + changeBy = 123; + else if (diffAbs > 50) + changeBy = 42; + else + changeBy = 1; -// lastCloseness is passed to other calls of this function -void -CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput) -{ - // This dist used for determining the angle to face - CVector2D dist(carToTest->GetPosition() - player->GetPosition()); - float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y); - while (neededTurn >= PI) { - neededTurn -= 2 * PI; + if (diff < 0) + m_nVisibleMoney -= changeBy; + else + m_nVisibleMoney += changeBy; } - while (neededTurn < -PI) { - neededTurn += 2 * PI; + if (!(CTimer::GetFrameCounter() & 15)) { + CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition(); + m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y); } - // This dist used for evaluating cars' distances, weird... - // Accounts inverted needed turn (or needed turn in long way) and car dist. - float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist); - if (closeness > *lastCloseness) { - *lastCloseness = closeness; - *closestCarOutput = (CVehicle*)carToTest; - } -} + m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f); -// There is something unfinished in here... Sadly all IDBs we have have it unfinished. -void -CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar) -{ - if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000) - ++m_nExplosionsSinceLastReward; + // Because vehicle enter/exit use same key binding. + bool enterOrExitVeh; + if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle) + enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown(); else - m_nExplosionsSinceLastReward = 1; - - m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds(); - int award = wreckedCar->pHandling->nMonetaryValue * 0.002f; - sprintf(gString, "$%d", award); -#ifdef MONEY_MESSAGES - // This line is a leftover from PS2, I don't know what it was meant to be. - // CVector sth(TheCamera.GetPosition() * 4.0f); - - CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f); -#endif - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; + enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle(); - for (int i = m_nExplosionsSinceLastReward; i > 1; --i) { - CGeneral::GetRandomNumber(); - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; - } -} + if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_MODE) { + if (m_pPed->bInVehicle) { + if (!m_pRemoteVehicle) { + CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity; + if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->GetModelIndex())) { + CVehicle *veh = m_pPed->m_pMyVehicle; + if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { -void -CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size) -{ - // Interesting - *size = sizeof(CPlayerInfo); - -#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree); - CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); -#undef CopyToBuf -} - -void -CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size) -{ -#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); buf += sizeof(data); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName) -#undef CopyFromBuf -} - -void -CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput) -{ - for (CPtrNode* node = carList.first; node; node = node->next) { - CVehicle *car = (CVehicle*)node->item; - if(car->m_scanCode != CWorld::GetCurrentScanCode()) { - if (!car->bUsesCollision || !car->IsVehicle()) - continue; - - car->m_scanCode = CWorld::GetCurrentScanCode(); - if (car->GetStatus() != STATUS_WRECKED && car->GetStatus() != STATUS_TRAIN_MOVING - && (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) { - CVector carCentre = car->GetBoundCentre(); - - if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) { - float dist = (ped->GetPosition() - carCentre).Magnitude2D(); - if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) { - EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput); - } - } - } - } - } -} - -void -CPlayerInfo::Process(void) -{ -#ifdef FIX_BUGS - if (CReplay::IsPlayingBack()) - return; -#endif - // Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode. - bool startTaxiTimer = true; - if (m_bUnusedTaxiThing && m_pPed->bInVehicle) { - CVehicle *veh = m_pPed->m_pMyVehicle; - if ((veh->GetModelIndex() == MI_TAXI || veh->GetModelIndex() == MI_CABBIE || veh->GetModelIndex() == MI_BORGNINE) - && veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) { - for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) { - timePassed -= 1000; - ++m_nMoney; - } - startTaxiTimer = false; - } - } - if (startTaxiTimer) - m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds(); - - // The effect that makes money counter does while earning/losing money - if (m_nVisibleMoney != m_nMoney) { - int diff = m_nMoney - m_nVisibleMoney; - int diffAbs = Abs(diff); - int changeBy; - - if (diffAbs > 100000) - changeBy = 12345; - else if (diffAbs > 10000) - changeBy = 1234; - else if (diffAbs > 1000) - changeBy = 123; - else if (diffAbs > 50) - changeBy = 42; - else - changeBy = 1; - - if (diff < 0) - m_nVisibleMoney -= changeBy; - else - m_nVisibleMoney += changeBy; - } - - if (!(CTimer::GetFrameCounter() & 15)) { - CVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition(); - m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y); - } - - m_fRoadDensity = clamp(m_fRoadDensity, 0.4f, 1.45f); - - // Because vehicle enter/exit use same key binding. - bool enterOrExitVeh; - if (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle) - enterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown(); - else - enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle(); - - if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_MODE) { - if (m_pPed->bInVehicle) { - if (!m_pRemoteVehicle) { - CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity; - if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->GetModelIndex())) { - CVehicle *veh = m_pPed->m_pMyVehicle; - if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { - - // This condition will always return true, else block was probably WIP Miami code. - if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { - if (veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) { - if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) { - m_pPed->SetObjective(OBJECTIVE_LEAVE_CAR, veh); - } - } - } else { - CVector sth = 0.7f * veh->GetRight() + veh->GetPosition(); - bool found = false; - float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found); + // This condition will always return true, else block was probably WIP Miami code. + if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { + if (veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) { + if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) { + m_pPed->SetObjective(OBJECTIVE_LEAVE_CAR, veh); + } + } + } else { + CVector sth = 0.7f * veh->GetRight() + veh->GetPosition(); + bool found = false; + float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found); if (found) sth.z = 1.0f + groundZ; @@ -503,13 +236,13 @@ CPlayerInfo::Process(void) uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar; if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) { TheCamera.SetFadeColour(0, 0, 0); - TheCamera.Fade(1.0f, 0); + TheCamera.Fade(1.0f, FADE_OUT); } if (timeWithoutRemoteCar > 2000) { if (m_WBState == WBSTATE_PLAYING) { TheCamera.RestoreWithJumpCut(); TheCamera.SetFadeColour(0, 0, 0); - TheCamera.Fade(1.0f, 1); + TheCamera.Fade(1.0f, FADE_IN); TheCamera.Process(); CTimer::Stop(); CCullZones::ForceCullZoneCoors(TheCamera.GetPosition()); @@ -560,3 +293,370 @@ CPlayerInfo::Process(void) CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled; } } + +bool +CPlayerInfo::IsPlayerInRemoteMode() +{ + return m_pRemoteVehicle || m_bInRemoteMode; +} + +void +CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size) +{ + // Interesting + *size = sizeof(CPlayerInfo); + +#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); +#undef CopyToBuf +} + +void +CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size) +{ +#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); buf += sizeof(data); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName) +#undef CopyFromBuf +} + +void +CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput) +{ + for (CPtrNode* node = carList.first; node; node = node->next) { + CVehicle *car = (CVehicle*)node->item; + if(car->m_scanCode != CWorld::GetCurrentScanCode()) { + if (!car->bUsesCollision || !car->IsVehicle()) + continue; + + car->m_scanCode = CWorld::GetCurrentScanCode(); + if (car->GetStatus() != STATUS_WRECKED && car->GetStatus() != STATUS_TRAIN_MOVING + && (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) { + CVector carCentre = car->GetBoundCentre(); + + if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) { + float dist = (ped->GetPosition() - carCentre).Magnitude2D(); + if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) { + EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput); + } + } + } + } + } +} + +// lastCloseness is passed to other calls of this function +void +CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput) +{ + // This dist used for determining the angle to face + CVector2D dist(carToTest->GetPosition() - player->GetPosition()); + float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y); + while (neededTurn >= PI) { + neededTurn -= 2 * PI; + } + + while (neededTurn < -PI) { + neededTurn += 2 * PI; + } + + // This dist used for evaluating cars' distances, weird... + // Accounts inverted needed turn (or needed turn in long way) and car dist. + float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist); + if (closeness > *lastCloseness) { + *lastCloseness = closeness; + *closestCarOutput = (CVehicle*)carToTest; + } +} + +const CVector & +CPlayerInfo::GetPos() +{ +#ifdef FIX_BUGS + if (!m_pPed) + return TheCamera.GetPosition(); +#endif + if (m_pPed->InVehicle()) + return m_pPed->m_pMyVehicle->GetPosition(); + return m_pPed->GetPosition(); +} + +CVector +FindPlayerCoors(void) +{ +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return TheCamera.GetPosition(); +#endif + CPlayerPed *ped = FindPlayerPed(); + if(ped->InVehicle()) + return ped->m_pMyVehicle->GetPosition(); + else + return ped->GetPosition(); +} + +const CVector & +FindPlayerSpeed(void) +{ +#ifdef FIX_BUGS + static CVector vecTmpVector(0.0f, 0.0f, 0.0f); + if (CReplay::IsPlayingBack()) + return vecTmpVector; +#endif + CPlayerPed *ped = FindPlayerPed(); + if(ped->InVehicle()) + return ped->m_pMyVehicle->m_vecMoveSpeed; + else + return ped->m_vecMoveSpeed; +} + +CVehicle * +FindPlayerVehicle(void) +{ + CPlayerPed *ped = FindPlayerPed(); + if(ped && ped->InVehicle()) return ped->m_pMyVehicle; + return nil; +} + +CEntity * +FindPlayerEntity(void) +{ + CPlayerPed *ped = FindPlayerPed(); + if(ped->InVehicle()) + return ped->m_pMyVehicle; + else + return ped; +} + +CVehicle * +FindPlayerTrain(void) +{ + if(FindPlayerVehicle() && FindPlayerVehicle()->IsTrain()) + return FindPlayerVehicle(); + else + return nil; +} + +CPlayerPed * +FindPlayerPed(void) +{ + return CWorld::Players[CWorld::PlayerInFocus].m_pPed; +} + +const CVector & +FindPlayerCentreOfWorld(int32 player) +{ +#ifdef FIX_BUGS + if(CReplay::IsPlayingBack()) return TheCamera.GetPosition(); +#endif + if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); + if(CWorld::Players[player].m_pRemoteVehicle) return CWorld::Players[player].m_pRemoteVehicle->GetPosition(); + if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); + return CWorld::Players[player].m_pPed->GetPosition(); +} + +const CVector & +FindPlayerCentreOfWorld_NoSniperShift(void) +{ +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) return TheCamera.GetPosition(); +#endif + if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); + if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) + return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition(); + if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); + return FindPlayerPed()->GetPosition(); +} + +float +FindPlayerHeading(void) +{ + if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) + return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading(); + if(FindPlayerVehicle()) return FindPlayerVehicle()->GetForward().Heading(); + return FindPlayerPed()->GetForward().Heading(); +} + +bool +CPlayerInfo::IsRestartingAfterDeath() +{ + return m_WBState == WBSTATE_WASTED; +} + +bool +CPlayerInfo::IsRestartingAfterArrest() +{ + return m_WBState == WBSTATE_BUSTED; +} + +void +CPlayerInfo::KillPlayer() +{ + if (m_WBState != WBSTATE_PLAYING) return; + + m_WBState = WBSTATE_WASTED; + m_nWBTime = CTimer::GetTimeInMilliseconds(); + CDarkel::ResetOnPlayerDeath(); + CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2); + CStats::TimesDied++; +} + +void +CPlayerInfo::ArrestPlayer() +{ + if (m_WBState != WBSTATE_PLAYING) return; + + m_WBState = WBSTATE_BUSTED; + m_nWBTime = CTimer::GetTimeInMilliseconds(); + CDarkel::ResetOnPlayerDeath(); + CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2); + CStats::TimesArrested++; +} + +void +CPlayerInfo::PlayerFailedCriticalMission() +{ + if (m_WBState != WBSTATE_PLAYING) + return; + m_WBState = WBSTATE_FAILED_CRITICAL_MISSION; + m_nWBTime = CTimer::GetTimeInMilliseconds(); + CDarkel::ResetOnPlayerDeath(); +} + +void +CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car) +{ + if (!car || car == m_pPed->m_pMyVehicle) { + if (m_pPed->EnteringCar()) + m_pPed->QuitEnteringCar(); + } + if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) + m_pPed->ClearObjective(); +} + +void +CPlayerInfo::MakePlayerSafe(bool toggle) +{ + if (toggle) { + CTheScripts::ResetCountdownToMakePlayerUnsafe(); + m_pPed->m_pWanted->m_bIgnoredByEveryone = true; + CWorld::StopAllLawEnforcersInTheirTracks(); + CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PLAYERINFO); + CPad::StopPadsShaking(); + m_pPed->bBulletProof = true; + m_pPed->bFireProof = true; + m_pPed->bCollisionProof = true; + m_pPed->bMeleeProof = true; + m_pPed->bOnlyDamagedByPlayer = true; + m_pPed->bExplosionProof = true; + m_pPed->m_bCanBeDamaged = false; + ((CPlayerPed*)m_pPed)->ClearAdrenaline(); + CancelPlayerEnteringCars(nil); + gFireManager.ExtinguishPoint(GetPos(), 4000.0f); + CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f); + CProjectileInfo::RemoveAllProjectiles(); + CWorld::SetAllCarsCanBeDamaged(false); + CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f); + CReplay::DisableReplays(); + + } else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) { + m_pPed->m_pWanted->m_bIgnoredByEveryone = false; + CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PLAYERINFO); + m_pPed->bBulletProof = false; + m_pPed->bFireProof = false; + m_pPed->bCollisionProof = false; + m_pPed->bMeleeProof = false; + m_pPed->bOnlyDamagedByPlayer = false; + m_pPed->bExplosionProof = false; + m_pPed->m_bCanBeDamaged = true; + CWorld::SetAllCarsCanBeDamaged(true); + CReplay::EnableReplays(); + } +} + +void +CPlayerInfo::BlowUpRCBuggy(void) +{ + if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld) + return; + + CRemote::TakeRemoteControlledCarFromPlayer(); + m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); +} + +// There is something unfinished in here... Sadly all IDBs we have have it unfinished. +void +CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar) +{ + if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000) + ++m_nExplosionsSinceLastReward; + else + m_nExplosionsSinceLastReward = 1; + + m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds(); + int award = wreckedCar->pHandling->nMonetaryValue * 0.002f; + sprintf(gString, "$%d", award); +#ifdef MONEY_MESSAGES + // This line is a leftover from PS2, I don't know what it was meant to be. + // CVector sth(TheCamera.GetPosition() * 4.0f); + + CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f); +#endif + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; + + for (int i = m_nExplosionsSinceLastReward; i > 1; --i) { + CGeneral::GetRandomNumber(); + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; + } +} + +#ifdef GTA_PC +void +CPlayerInfo::SetPlayerSkin(const char *skin) +{ + strncpy(m_aSkinName, skin, 32); + LoadPlayerSkin(); +} + +void +CPlayerInfo::LoadPlayerSkin() +{ + DeletePlayerSkin(); + + m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName); + if (!m_pSkinTexture) + m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME); +} + +void +CPlayerInfo::DeletePlayerSkin() +{ + if (m_pSkinTexture) { + RwTextureDestroy(m_pSkinTexture); + m_pSkinTexture = nil; + } +} +#endif \ No newline at end of file diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 94410753..49424b8b 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -54,14 +54,13 @@ public: bool m_bFastReload; bool m_bGetOutOfJailFree; bool m_bGetOutOfHospitalFree; +#ifdef GTA_PC char m_aSkinName[32]; RwTexture *m_pSkinTexture; +#endif void MakePlayerSafe(bool); - void LoadPlayerSkin(); - void DeletePlayerSkin(); void AwardMoneyForExplosion(CVehicle *vehicle); - void SetPlayerSkin(char* skin); const CVector &GetPos(); void Process(void); void KillPlayer(void); @@ -78,7 +77,21 @@ public: void SavePlayerInfo(uint8 *buf, uint32* size); void FindClosestCarSectorList(CPtrList&, CPed*, float, float, float, float, float*, CVehicle**); - ~CPlayerInfo() { }; +#ifdef GTA_PC + void LoadPlayerSkin(); + void SetPlayerSkin(const char *skin); + void DeletePlayerSkin(); +#endif }; +CPlayerPed *FindPlayerPed(void); +CVehicle *FindPlayerVehicle(void); +CVehicle *FindPlayerTrain(void); +CEntity *FindPlayerEntity(void); +CVector FindPlayerCoors(void); +const CVector &FindPlayerSpeed(void); +const CVector &FindPlayerCentreOfWorld(int32 player); +const CVector &FindPlayerCentreOfWorld_NoSniperShift(void); +float FindPlayerHeading(void); + VALIDATE_SIZE(CPlayerInfo, 0x13C); diff --git a/src/core/World.cpp b/src/core/World.cpp index a7531c83..b2c1696c 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1361,102 +1361,6 @@ CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList &list, const CVec } } -CPlayerPed * -FindPlayerPed(void) -{ - return CWorld::Players[CWorld::PlayerInFocus].m_pPed; -} - -CVehicle * -FindPlayerVehicle(void) -{ - CPlayerPed *ped = FindPlayerPed(); - if(ped && ped->InVehicle()) return ped->m_pMyVehicle; - return nil; -} - -CVehicle * -FindPlayerTrain(void) -{ - if(FindPlayerVehicle() && FindPlayerVehicle()->IsTrain()) - return FindPlayerVehicle(); - else - return nil; -} - -CEntity * -FindPlayerEntity(void) -{ - CPlayerPed *ped = FindPlayerPed(); - if(ped->InVehicle()) - return ped->m_pMyVehicle; - else - return ped; -} - -CVector -FindPlayerCoors(void) -{ -#ifdef FIX_BUGS - if (CReplay::IsPlayingBack()) - return TheCamera.GetPosition(); -#endif - CPlayerPed *ped = FindPlayerPed(); - if(ped->InVehicle()) - return ped->m_pMyVehicle->GetPosition(); - else - return ped->GetPosition(); -} - -CVector & -FindPlayerSpeed(void) -{ -#ifdef FIX_BUGS - static CVector vecTmpVector(0.0f, 0.0f, 0.0f); - if (CReplay::IsPlayingBack()) - return vecTmpVector; -#endif - CPlayerPed *ped = FindPlayerPed(); - if(ped->InVehicle()) - return ped->m_pMyVehicle->m_vecMoveSpeed; - else - return ped->m_vecMoveSpeed; -} - -const CVector & -FindPlayerCentreOfWorld(int32 player) -{ -#ifdef FIX_BUGS - if(CReplay::IsPlayingBack()) return TheCamera.GetPosition(); -#endif - if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); - if(CWorld::Players[player].m_pRemoteVehicle) return CWorld::Players[player].m_pRemoteVehicle->GetPosition(); - if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); - return CWorld::Players[player].m_pPed->GetPosition(); -} - -const CVector & -FindPlayerCentreOfWorld_NoSniperShift(void) -{ -#ifdef FIX_BUGS - if (CReplay::IsPlayingBack()) return TheCamera.GetPosition(); -#endif - if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); - if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) - return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition(); - if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); - return FindPlayerPed()->GetPosition(); -} - -float -FindPlayerHeading(void) -{ - if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) - return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading(); - if(FindPlayerVehicle()) return FindPlayerVehicle()->GetForward().Heading(); - return FindPlayerPed()->GetForward().Heading(); -} - void CWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) { diff --git a/src/core/World.h b/src/core/World.h index 197f3cee..9d62e79b 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -157,14 +157,3 @@ public: extern CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; -class CPlayerPed; -class CVehicle; -CPlayerPed *FindPlayerPed(void); -CVehicle *FindPlayerVehicle(void); -CVehicle *FindPlayerTrain(void); -CEntity *FindPlayerEntity(void); -CVector FindPlayerCoors(void); -CVector &FindPlayerSpeed(void); -const CVector &FindPlayerCentreOfWorld(int32 player); -const CVector &FindPlayerCentreOfWorld_NoSniperShift(void); -float FindPlayerHeading(void); diff --git a/src/extras/screendroplets.cpp b/src/extras/screendroplets.cpp index 2d34cdcb..3f91a754 100644 --- a/src/extras/screendroplets.cpp +++ b/src/extras/screendroplets.cpp @@ -384,9 +384,9 @@ ScreenDroplets::ProcessCameraMovement(void) ms_prevCamUp = camUp; ms_prevCamPos = camPos; - ms_screenMoveDelta.x = -RwV3dDotProduct(&camMat->right, (RwV3d*)&ms_camMoveDelta); - ms_screenMoveDelta.y = RwV3dDotProduct(&camMat->up, (RwV3d*)&ms_camMoveDelta); - ms_screenMoveDelta.z = RwV3dDotProduct(&camMat->at, (RwV3d*)&ms_camMoveDelta); + ms_screenMoveDelta.x = -RwV3dDotProduct(&camMat->right, &ms_camMoveDelta); + ms_screenMoveDelta.y = RwV3dDotProduct(&camMat->up, &ms_camMoveDelta); + ms_screenMoveDelta.z = RwV3dDotProduct(&camMat->at, &ms_camMoveDelta); ms_screenMoveDelta *= 10.0f; ms_screenMoveDist = ms_screenMoveDelta.Magnitude2D(); diff --git a/src/math/Vector.h b/src/math/Vector.h index 082b296f..776bfcfe 100644 --- a/src/math/Vector.h +++ b/src/math/Vector.h @@ -1,23 +1,22 @@ #pragma once -class CVector +class CVector : public RwV3d { public: - float x, y, z; CVector(void) {} - CVector(float x, float y, float z) : x(x), y(y), z(z) {} -#ifdef RWCORE_H - CVector(const RwV3d &v) : x(v.x), y(v.y), z(v.z) {} - - operator RwV3d (void) const { - RwV3d vecRw = { this->x, this->y, this->z }; - return vecRw; + CVector(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; } - - operator RwV3d *(void) { - return (RwV3d*)this; + + CVector(const RwV3d &v) + { + x = v.x; + y = v.y; + z = v.z; } -#endif // (0,1,0) means no rotation. So get right vector and its atan float Heading(void) const { return Atan2(-x, y); } float Magnitude(void) const { return Sqrt(x*x + y*y + z*z); } diff --git a/src/math/VuVector.h b/src/math/VuVector.h index f90818e0..30d62cfc 100644 --- a/src/math/VuVector.h +++ b/src/math/VuVector.h @@ -8,18 +8,7 @@ public: CVuVector(float x, float y, float z) : CVector(x, y, z) {} CVuVector(float x, float y, float z, float w) : CVector(x, y, z), w(w) {} CVuVector(const CVector &v) : CVector(v.x, v.y, v.z) {} -#ifdef RWCORE_H - CVuVector(const RwV3d &v) : CVector(v.x, v.y, v.z) {} - - operator RwV3d (void) const { - RwV3d vecRw = { this->x, this->y, this->z }; - return vecRw; - } - - operator RwV3d *(void) { - return (RwV3d*)this; - } -#endif + CVuVector(const RwV3d &v) : CVector(v) {} /* void Normalise(void) { float sq = MagnitudeSqr(); diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index 17754211..cc2a7e34 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -471,7 +471,7 @@ CVehicleModelInfo::PreprocessHierarchy(void) if(desc[i].flags & VEHICLE_FLAG_POS){ f = assoc.frame; - rwvec = (RwV3d*)&m_positions[desc[i].hierId]; + rwvec = &m_positions[desc[i].hierId]; *rwvec = *RwMatrixGetPos(RwFrameGetMatrix(f)); for(f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) RwV3dTransformPoints(rwvec, rwvec, 1, RwFrameGetMatrix(f)); diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index b2888082..e518fae4 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -244,7 +244,7 @@ CCopPed::ArrestPlayer(void) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ARREST_GUN, 4.0f); CVector suspMidPos; - suspect->m_pedIK.GetComponentPosition((RwV3d*)suspMidPos, PED_MID); + suspect->m_pedIK.GetComponentPosition(suspMidPos, PED_MID); m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(suspMidPos.x, suspMidPos.y, GetPosition().x, GetPosition().y); diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index 65aa97ef..9f87c12b 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -234,8 +234,8 @@ CEmergencyPed::MedicAI(void) if (nearestAccident) { m_pRevivedPed = nearestAccident->m_pVictim; m_pRevivedPed->RegisterReference((CEntity**)&m_pRevivedPed); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD); SetSeek((headPos + midPos) * 0.5f, 1.0f); SetObjective(OBJECTIVE_NONE); bIsRunning = true; @@ -274,8 +274,8 @@ CEmergencyPed::MedicAI(void) m_nEmergencyPedState = EMERGENCY_PED_STOP; break; } - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD); SetSeek((headPos + midPos) * 0.5f, nearestAccident->m_nMedicsPerformingCPR * 0.5f + 1.0f); SetObjective(OBJECTIVE_NONE); bIsRunning = true; @@ -329,8 +329,8 @@ CEmergencyPed::MedicAI(void) if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f) m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; else { - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD); midPos = (headPos + midPos) * 0.5f; m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( midPos.x, midPos.y, @@ -351,8 +351,8 @@ CEmergencyPed::MedicAI(void) m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; break; } - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD); midPos = (headPos + midPos) * 0.5f; m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( midPos.x, midPos.y, diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 5e1911ec..df78902f 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -960,7 +960,7 @@ CPed::MoveHeadToLook(void) } if (m_pLookTarget->IsPed()) { - ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID); + ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition(lookPos, PED_MID); } else { lookPos = m_pLookTarget->GetPosition(); } diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 0e398b25..d27853d6 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -898,13 +898,13 @@ public: RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); int32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID); RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); - RwV3dTransformPoints((RwV3d*)&pos, (RwV3d*)&pos, 1, &mats[idx]); + RwV3dTransformPoints(&pos, &pos, 1, &mats[idx]); }else #endif { RwFrame *frame; for (frame = m_pFrames[node]->frame; frame; frame = RwFrameGetParent(frame)) - RwV3dTransformPoints((RwV3d*)&pos, (RwV3d*)&pos, 1, RwFrameGetMatrix(frame)); + RwV3dTransformPoints(&pos, &pos, 1, RwFrameGetMatrix(frame)); } } diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp index d4385385..a747c684 100644 --- a/src/peds/PedAI.cpp +++ b/src/peds/PedAI.cpp @@ -1141,7 +1141,7 @@ CPed::ProcessObjective(void) CVector target; CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); if (m_pedInObjective->IsPed()) - m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID); + m_pedInObjective->m_pedIK.GetComponentPosition(target, PED_MID); else target = m_pedInObjective->GetPosition(); diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp index b4be0954..b57364d8 100644 --- a/src/peds/PedFight.cpp +++ b/src/peds/PedFight.cpp @@ -1690,7 +1690,7 @@ CPed::FightStrike(CVector &touchedNodePos) if (m_fightState == FIGHTSTATE_NO_MOVE) m_fightState = FIGHTSTATE_1; - m_vecHitLastPos = *touchedNodePos; + m_vecHitLastPos = touchedNodePos; return false; } diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index ebd41296..8bace9a0 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -137,28 +137,28 @@ CPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool change } void -CPedIK::GetComponentPosition(RwV3d *pos, uint32 node) +CPedIK::GetComponentPosition(RwV3d &pos, uint32 node) { RwFrame *f; RwMatrix *mat; #ifdef PED_SKIN if(IsClumpSkinned(m_ped->GetClump())){ - pos->x = 0.0f; - pos->y = 0.0f; - pos->z = 0.0f; + pos.x = 0.0f; + pos.y = 0.0f; + pos.z = 0.0f; mat = GetComponentMatrix(m_ped, node); // could just copy the position out of the matrix... - RwV3dTransformPoints(pos, pos, 1, mat); + RwV3dTransformPoints(&pos, &pos, 1, mat); }else #endif { f = m_ped->m_pFrames[node]->frame; mat = RwFrameGetMatrix(f); - *pos = mat->pos; + pos = mat->pos; for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) - RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(f)); + RwV3dTransformPoints(&pos, &pos, 1, RwFrameGetMatrix(f)); } } diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h index e91d7c06..4eeef6f0 100644 --- a/src/peds/PedIK.h +++ b/src/peds/PedIK.h @@ -51,7 +51,7 @@ public: bool PointGunInDirection(float targetYaw, float targetPitch); bool PointGunInDirectionUsingArm(float targetYaw, float targetPitch); bool PointGunAtPosition(CVector const& position); - void GetComponentPosition(RwV3d *pos, uint32 node); + void GetComponentPosition(RwV3d &pos, uint32 node); static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination); void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll); void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch); diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 86d8e9f5..8a6adbeb 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -1146,7 +1146,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) #else CVector markPos; if (m_pPointGunAt->IsPed()) { - ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d*)markPos, PED_MID); + ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition(markPos, PED_MID); } else { markPos = m_pPointGunAt->GetPosition(); } diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 161418b9..b5af6619 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -133,7 +133,7 @@ CClouds::Render(void) CSprite::InitSpriteBuffer(); int minute = CClock::GetHours()*60 + CClock::GetMinutes(); - RwV3d campos = *(RwV3d*)&TheCamera.GetPosition(); + RwV3d campos = TheCamera.GetPosition(); // Moon int moonfadeout = Abs(minute - 180); // fully visible at 3AM diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index 33c3f4bf..48f0f6b9 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -255,7 +255,7 @@ CCoronas::Render(void) CVector spriteCoors; float spritew, spriteh; - if(!CSprite::CalcScreenCoors(aCoronas[i].coors, spriteCoors, &spritew, &spriteh, true)){ + if(!CSprite::CalcScreenCoors(aCoronas[i].coors, &spriteCoors, &spritew, &spriteh, true)){ aCoronas[i].offScreen = true; aCoronas[i].sightClear = false; }else{ @@ -464,7 +464,7 @@ CCoronas::RenderReflections(void) CVector spriteCoors; float spritew, spriteh; - if(CSprite::CalcScreenCoors(coors, spriteCoors, &spritew, &spriteh, true)){ + if(CSprite::CalcScreenCoors(coors, &spriteCoors, &spritew, &spriteh, true)){ float drawDist = 0.75f * aCoronas[i].drawDist; drawDist = Min(drawDist, 55.0f); if(spriteCoors.z < drawDist){ @@ -531,7 +531,7 @@ CCoronas::DoSunAndMoon(void) CVector spriteCoors; float spritew, spriteh; - if(CSprite::CalcScreenCoors(sunCoors, spriteCoors, &spritew, &spriteh, true)){ + if(CSprite::CalcScreenCoors(sunCoors, &spriteCoors, &spritew, &spriteh, true)){ SunScreenX = spriteCoors.x; SunScreenY = spriteCoors.y; }else{ diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 690a1d3f..c76d6109 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -655,7 +655,7 @@ void CScrollBar::Render() RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); CVector coronaCoord, screenCoord; - float screenW, screenH; + float screenW, screenH; for (int i = 1; i < ARRAY_SIZE(m_MessageBar); ++i) { for (int j = 0; j < 5; ++j) @@ -667,7 +667,7 @@ void CScrollBar::Render() // Render main coronas if (m_MessageBar[i] & (1 << j)) { - if (CSprite::CalcScreenCoors(coronaCoord, screenCoord, &screenW, &screenH, true)) + if (CSprite::CalcScreenCoors(coronaCoord, &screenCoord, &screenW, &screenH, true)) { CSprite::RenderBufferedOneXLUSprite( screenCoord.x, screenCoord.y, screenCoord.z, @@ -679,7 +679,7 @@ void CScrollBar::Render() // Render smaller and faded coronas for a trailing effect else if (m_MessageBar[i - 1] & (1 << j)) { - if (CSprite::CalcScreenCoors(coronaCoord, screenCoord, &screenW, &screenH, true)) + if (CSprite::CalcScreenCoors(coronaCoord, &screenCoord, &screenW, &screenH, true)) { CSprite::RenderBufferedOneXLUSprite( screenCoord.x, screenCoord.y, screenCoord.z, @@ -834,7 +834,7 @@ void CDigitalClock::Render() const char* clockMessage = FindDigitalClockMessage(); CVector coronaCoord, screenCoord; - float screenW, screenH; + float screenW, screenH; for (int c = 0; c < 5; ++c) // for each char to be displayed { for (int i = 0; i < 5; ++i) // for each column of coronas @@ -847,7 +847,7 @@ void CDigitalClock::Render() coronaCoord.y = m_Position.y + (8 * c + i) * m_Size.y * m_fScale / 8.0f; coronaCoord.z = m_Position.z + j * m_fScale / 8.0f; - if (CSprite::CalcScreenCoors(coronaCoord, screenCoord, &screenW, &screenH, true)) + if (CSprite::CalcScreenCoors(coronaCoord, &screenCoord, &screenW, &screenH, true)) { CSprite::RenderBufferedOneXLUSprite( screenCoord.x, screenCoord.y, screenCoord.z, diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index 2b19486e..f175c264 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -1570,7 +1570,7 @@ void CParticle::Render() float w; float h; - if ( CSprite::CalcScreenCoors(particle->m_vecPosition, coors, &w, &h, true) ) + if ( CSprite::CalcScreenCoors(particle->m_vecPosition, &coors, &w, &h, true) ) { #ifdef PC_PARTICLE if ( (!particleBanned || SCREEN_WIDTH * fParticleScaleLimit >= w) @@ -1650,7 +1650,7 @@ void CParticle::Render() float fRotation; float fTrailLength; - if ( CSprite::CalcScreenCoors(vecPrevPos, particle->m_vecScreenPosition, &fTrailLength, &fRotation, true) ) + if ( CSprite::CalcScreenCoors(vecPrevPos, &particle->m_vecScreenPosition, &fTrailLength, &fRotation, true) ) { CVector2D vecDist ( diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp index 0713dc6d..6f0b4d46 100644 --- a/src/render/PointLights.cpp +++ b/src/render/PointLights.cpp @@ -218,7 +218,7 @@ CPointLights::RenderFogEffect(void) // more intensity the closer to line intensity *= 1.0f - sq(Sqrt(linedistsq) / FOG_AREA_WIDTH); - if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){ + if(CSprite::CalcScreenCoors(fogcoors, &spriteCoors, &spritew, &spriteh, true)){ float rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x2000; float size = FogSizes[r>>1]; CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z, @@ -267,7 +267,7 @@ CPointLights::RenderFogEffect(void) intensity *= 1.0f - sq(lightdist / FOG_AREA_RADIUS); CVector fogcoors(xi, yi, point.point.z + 1.6f); - if(CSprite::CalcScreenCoors(fogcoors, spriteCoors, &spritew, &spriteh, true)){ + if(CSprite::CalcScreenCoors(fogcoors, &spriteCoors, &spritew, &spriteh, true)){ float rotation = (CTimer::GetTimeInMilliseconds()&0x3FFF) * 2*3.14f / 0x4000; float size = FogSizes[r>>1]; CSprite::RenderOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z, diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a0f66819..d47cac31 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -741,7 +741,7 @@ CRenderer::ScanWorld(void) vectors[CORNER_PRIO_RIGHT].x = vectors[CORNER_LOD_RIGHT].x * 0.2f; vectors[CORNER_PRIO_RIGHT].y = vectors[CORNER_LOD_RIGHT].y * 0.2f; vectors[CORNER_PRIO_RIGHT].z = vectors[CORNER_LOD_RIGHT].z; - RwV3dTransformPoints((RwV3d*)vectors, (RwV3d*)vectors, 9, cammatrix); + RwV3dTransformPoints(vectors, vectors, 9, cammatrix); m_loadingPriority = false; if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || @@ -881,7 +881,7 @@ CRenderer::RequestObjectsInFrustum(void) vectors[CORNER_PRIO_RIGHT].x = vectors[CORNER_LOD_RIGHT].x * 0.2f; vectors[CORNER_PRIO_RIGHT].y = vectors[CORNER_LOD_RIGHT].y * 0.2f; vectors[CORNER_PRIO_RIGHT].z = vectors[CORNER_LOD_RIGHT].z; - RwV3dTransformPoints((RwV3d*)vectors, (RwV3d*)vectors, 9, cammatrix); + RwV3dTransformPoints(vectors, vectors, 9, cammatrix); if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || #ifdef FIX_BUGS diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index f16467b6..e765f306 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -359,7 +359,7 @@ void CWeather::AddRain() RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude(); splash_points[3] = 4.0f * CVector(RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) * RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude(); - RwV3dTransformPoints((RwV3d*)splash_points, (RwV3d*)splash_points, 4, RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera))); + RwV3dTransformPoints(splash_points, splash_points, 4, RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera))); CVector fp = (splash_points[0] + splash_points[1] + splash_points[2] + splash_points[3]) / 4; for (int i = 0; i < num_splash_attempts; i++) { CColPoint point; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index dc15485e..a987a4c7 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -385,7 +385,7 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() ) { CVector victimPedPos = victimPed->GetPosition(); - if ( SQR(victimPedRadius) > (victimPedPos-(*fireSource)).MagnitudeSqr() ) + if ( SQR(victimPedRadius) > (victimPedPos-fireSource).MagnitudeSqr() ) { CVector collisionDist; @@ -393,7 +393,7 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) while ( s < victimPedCol->numSpheres ) { CColSphere *sphere = &victimPedCol->spheres[s]; - collisionDist = victimPedPos+sphere->center-(*fireSource); + collisionDist = victimPedPos+sphere->center-fireSource; if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) { -- cgit v1.2.3 From a080fbfbd41ac8a2bc6cfe053d4fa0932dd8d334 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 18 Dec 2020 13:58:59 +0100 Subject: little cleanup of templates --- src/core/FileLoader.cpp | 4 ++-- src/core/templates.h | 49 ++++++++++++++++++++++---------------------- src/modelinfo/ModelInfo.cpp | 50 ++++++++++++++++++++++----------------------- 3 files changed, 51 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index b9d475b8..0ad03f61 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1065,7 +1065,7 @@ CFileLoader::LoadMLOInstance(int id, const char *line) &rot.x, &rot.y, &rot.z, &angle); float rad = Acos(angle) * 2.0f; - CInstance *inst = CModelInfo::GetMloInstanceStore().alloc(); + CInstance *inst = CModelInfo::GetMloInstanceStore().Alloc(); minfo->lastInstance++; RwMatrix *matrix = RwMatrixCreate(); @@ -1305,7 +1305,7 @@ CFileLoader::Load2dEffect(const char *line) CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("particle")); mi = CModelInfo::GetModelInfo(id); - effect = CModelInfo::Get2dEffectStore().alloc(); + effect = CModelInfo::Get2dEffectStore().Alloc(); mi->Add2dEffect(effect); effect->pos = CVector(x, y, z); effect->col = CRGBA(r, g, b, a); diff --git a/src/core/templates.h b/src/core/templates.h index 166f865c..3a5b314f 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -1,31 +1,31 @@ #pragma once -template +template class CStore { public: - int allocPtr; + int32 allocPtr; T store[n]; - T *alloc(void){ - if(this->allocPtr >= n){ + T *Alloc(void){ + if(allocPtr >= n){ printf("Size of this thing:%d needs increasing\n", n); assert(0); } - return &this->store[this->allocPtr++]; + return &store[allocPtr++]; } - void clear(void){ - this->allocPtr = 0; + void Clear(void){ + allocPtr = 0; } - int getIndex(T *item){ - assert(item >= &this->store[0]); - assert(item < &this->store[n]); - return item - this->store; + int32 GetIndex(T *item){ + assert(item >= &store[0]); + assert(item < &store[n]); + return item - store; } - T *getItem(int index){ + T *GetItem(int32 index){ assert(index >= 0); assert(index < n); - return &this->store[index]; + return &store[index]; } }; @@ -40,12 +40,11 @@ class CPool }; uint8 u; } *m_flags; - int m_size; - int m_allocPtr; + int32 m_size; + int32 m_allocPtr; public: - CPool(int size){ - // TODO: use new here + CPool(int32 size){ m_entries = (U*)new uint8[sizeof(U)*size]; m_flags = (Flags*)new uint8[sizeof(Flags)*size]; m_size = size; @@ -69,7 +68,7 @@ public: m_allocPtr = 0; } } - int GetSize(void) const { return m_size; } + int32 GetSize(void) const { return m_size; } T *New(void){ bool wrapped = false; do @@ -93,12 +92,12 @@ public: m_flags[m_allocPtr].id++; return (T*)&m_entries[m_allocPtr]; } - T *New(int handle){ + T *New(int32 handle){ T *entry = (T*)&m_entries[handle>>8]; SetNotFreeAt(handle); return entry; } - void SetNotFreeAt(int handle){ + void SetNotFreeAt(int32 handle){ int idx = handle>>8; m_flags[idx].free = 0; m_flags[idx].id = handle & 0x7F; @@ -123,21 +122,21 @@ public: return m_flags[handle>>8].u == (handle & 0xFF) ? (T*)&m_entries[handle >> 8] : nil; } - int GetIndex(T *entry){ + int32 GetIndex(T *entry){ int i = GetJustIndex_NoFreeAssert(entry); return m_flags[i].u + (i<<8); } - int GetJustIndex(T *entry){ + int32 GetJustIndex(T *entry){ int index = GetJustIndex_NoFreeAssert(entry); assert(!IsFreeSlot(index)); return index; } - int GetJustIndex_NoFreeAssert(T* entry){ + int32 GetJustIndex_NoFreeAssert(T* entry){ int index = ((U*)entry - m_entries); assert((U*)entry == (U*)&m_entries[index]); // cast is unsafe - check required return index; } - int GetNoOfUsedSpaces(void) const{ + int32 GetNoOfUsedSpaces(void) const{ int i; int n = 0; for(i = 0; i < m_size; i++) @@ -241,7 +240,7 @@ public: link->Remove(); // remove from list freeHead.Insert(link); // insert into free list } - int Count(void){ + int32 Count(void){ int n = 0; CLink *lnk; for(lnk = head.next; lnk != &tail; lnk = lnk->next) diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp index 4ee8e72b..dcde0df3 100644 --- a/src/modelinfo/ModelInfo.cpp +++ b/src/modelinfo/ModelInfo.cpp @@ -26,15 +26,15 @@ CModelInfo::Initialise(void) for(i = 0; i < MODELINFOSIZE; i++) ms_modelInfoPtrs[i] = nil; - ms_2dEffectStore.clear(); - ms_mloInstanceStore.clear(); - ms_xtraCompsModelStore.clear(); - ms_simpleModelStore.clear(); - ms_timeModelStore.clear(); - ms_mloModelStore.clear(); - ms_clumpModelStore.clear(); - ms_pedModelStore.clear(); - ms_vehicleModelStore.clear(); + ms_2dEffectStore.Clear(); + ms_mloInstanceStore.Clear(); + ms_xtraCompsModelStore.Clear(); + ms_simpleModelStore.Clear(); + ms_timeModelStore.Clear(); + ms_mloModelStore.Clear(); + ms_clumpModelStore.Clear(); + ms_pedModelStore.Clear(); + ms_vehicleModelStore.Clear(); m = AddSimpleModel(MI_CAR_DOOR); m->SetColModel(&CTempColModels::ms_colModelDoor1); @@ -108,22 +108,22 @@ CModelInfo::ShutDown(void) for(i = 0; i < ms_2dEffectStore.allocPtr; i++) ms_2dEffectStore.store[i].Shutdown(); - ms_2dEffectStore.clear(); - ms_simpleModelStore.clear(); - ms_mloInstanceStore.clear(); - ms_mloModelStore.clear(); - ms_xtraCompsModelStore.clear(); - ms_timeModelStore.clear(); - ms_pedModelStore.clear(); - ms_clumpModelStore.clear(); - ms_vehicleModelStore.clear(); + ms_2dEffectStore.Clear(); + ms_simpleModelStore.Clear(); + ms_mloInstanceStore.Clear(); + ms_mloModelStore.Clear(); + ms_xtraCompsModelStore.Clear(); + ms_timeModelStore.Clear(); + ms_pedModelStore.Clear(); + ms_clumpModelStore.Clear(); + ms_vehicleModelStore.Clear(); } CSimpleModelInfo* CModelInfo::AddSimpleModel(int id) { CSimpleModelInfo *modelinfo; - modelinfo = CModelInfo::ms_simpleModelStore.alloc(); + modelinfo = CModelInfo::ms_simpleModelStore.Alloc(); CModelInfo::ms_modelInfoPtrs[id] = modelinfo; modelinfo->Init(); return modelinfo; @@ -133,7 +133,7 @@ CMloModelInfo * CModelInfo::AddMloModel(int id) { CMloModelInfo *modelinfo; - modelinfo = CModelInfo::ms_mloModelStore.alloc(); + modelinfo = CModelInfo::ms_mloModelStore.Alloc(); CModelInfo::ms_modelInfoPtrs[id] = modelinfo; modelinfo->m_clump = nil; modelinfo->firstInstance = 0; @@ -145,7 +145,7 @@ CTimeModelInfo* CModelInfo::AddTimeModel(int id) { CTimeModelInfo *modelinfo; - modelinfo = CModelInfo::ms_timeModelStore.alloc(); + modelinfo = CModelInfo::ms_timeModelStore.Alloc(); CModelInfo::ms_modelInfoPtrs[id] = modelinfo; modelinfo->Init(); return modelinfo; @@ -155,7 +155,7 @@ CClumpModelInfo* CModelInfo::AddClumpModel(int id) { CClumpModelInfo *modelinfo; - modelinfo = CModelInfo::ms_clumpModelStore.alloc(); + modelinfo = CModelInfo::ms_clumpModelStore.Alloc(); CModelInfo::ms_modelInfoPtrs[id] = modelinfo; modelinfo->m_clump = nil; return modelinfo; @@ -165,7 +165,7 @@ CPedModelInfo* CModelInfo::AddPedModel(int id) { CPedModelInfo *modelinfo; - modelinfo = CModelInfo::ms_pedModelStore.alloc(); + modelinfo = CModelInfo::ms_pedModelStore.Alloc(); CModelInfo::ms_modelInfoPtrs[id] = modelinfo; modelinfo->m_clump = nil; return modelinfo; @@ -175,7 +175,7 @@ CVehicleModelInfo* CModelInfo::AddVehicleModel(int id) { CVehicleModelInfo *modelinfo; - modelinfo = CModelInfo::ms_vehicleModelStore.alloc(); + modelinfo = CModelInfo::ms_vehicleModelStore.Alloc(); CModelInfo::ms_modelInfoPtrs[id] = modelinfo; modelinfo->m_clump = nil; modelinfo->m_vehicleType = -1; @@ -245,7 +245,7 @@ CModelInfo::ConstructMloClumps() void CModelInfo::ReInit2dEffects() { - ms_2dEffectStore.clear(); + ms_2dEffectStore.Clear(); for (int i = 0; i < MODELINFOSIZE; i++) { if (ms_modelInfoPtrs[i]) -- cgit v1.2.3