From 6ff15d63274a1465deb2cc05f94821e77d6dcae4 Mon Sep 17 00:00:00 2001 From: MaZaHa-Ka <155328345+MaZaHa-Ka@users.noreply.github.com> Date: Fri, 27 Sep 2024 13:18:22 +0300 Subject: [PATCH] Add files via upload --- src/save/GenericGameStorage.cpp | 47 ++- src/save/PCSave.cpp | 2 +- src/skel/skeleton.cpp | 2 +- src/skel/win/gtavcs.ico | Bin 0 -> 4286 bytes src/skel/win/win.aps | Bin 0 -> 79660 bytes src/skel/win/win.cpp | 65 +++- src/skel/win/win.h | 12 +- src/skel/win/win.rc | 2 +- src/text/Messages.h | 10 +- src/utils/ConsoleTools.cpp | 100 ++++++ src/utils/ConsoleTools.h | 11 + src/utils/SetCurrDir.cpp | 23 ++ src/utils/SetCurrDir.h | 7 + src/utils/Utils.cpp | 555 ++++++++++++++++++++++++++++++++ src/utils/Utils.h | 115 +++++++ src/vehicles/Automobile.cpp | 6 +- src/vehicles/Boat.cpp | 10 +- src/vehicles/Boat.h | 3 + src/vehicles/Cranes.cpp | 14 +- src/vehicles/Ferry.cpp | 86 ++++- src/vehicles/Plane.cpp | 2 + 21 files changed, 1035 insertions(+), 37 deletions(-) create mode 100644 src/skel/win/gtavcs.ico create mode 100644 src/skel/win/win.aps create mode 100644 src/utils/ConsoleTools.cpp create mode 100644 src/utils/ConsoleTools.h create mode 100644 src/utils/SetCurrDir.cpp create mode 100644 src/utils/SetCurrDir.h create mode 100644 src/utils/Utils.cpp create mode 100644 src/utils/Utils.h diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index ca6f5263..fd937a9d 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -405,17 +405,50 @@ GenericLoad() //ReadDataFromBlock("Loading AudioScript Objects \n", cAudioScriptObject::LoadAllAudioScriptObjects); //LoadSaveDataBlock(); //ReadDataFromBlock("Loading ScriptPaths \n", CScriptPaths::Load); + // MAZAHAKA!! IF UNCOMMENT SAVE BLOCK CHECK !load bool CGame::ReInitGameObjectVariables(bool load) prolem reinit after load (empty save data) LoadSaveDataBlock(); ReadDataFromBlock("Loading Player Info \n", CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo); LoadSaveDataBlock(); ReadDataFromBlock("Loading Stats \n", CStats::LoadStats); - assert(*CStats::LastMissionPassedName); // reinit after load bug. After load CStats was empty Mazahaka - //LoadSaveDataBlock(); - //ReadDataFromBlock("Loading Set Pieces \n", CSetPieces::Load); - //LoadSaveDataBlock(); - //ReadDataFromBlock("Loading Streaming Stuff \n", CStreaming::MemoryCardLoad); - //LoadSaveDataBlock(); - //ReadDataFromBlock("Loading PedType Stuff \n", CPedType::Load); + //assert(*CStats::LastMissionPassedName); // init after load save vars!! mazahaka // tmp disabled + // debug("======================last mission: %s\n", CStats::LastMissionPassedName); + + // Загрузка блока данных + /*if(!ReadDataFromFile(file, (uint8 *)&size, 4)) { return false; } + size = align4bytes(size); + if(!ReadDataFromFile(file, work_buff, size)) { return false; } + buf = work_buff; + + // Чтение данных из блока "Loading Player Info \n" + debug("Loading Player Info \n"); + memcpy(&size, buf, sizeof(size)); + buf += align4bytes(sizeof(size)); + CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo(buf, size); + size = align4bytes(size); + buf += size; + + + + // Загрузка следующего блока данных + if(!ReadDataFromFile(file, (uint8 *)&size, 4)) { return false; } + size = align4bytes(size); + if(!ReadDataFromFile(file, work_buff, size)) { return false; } + buf = work_buff; + + // Чтение данных из блока "Loading Stats \n" + debug("Loading Stats \n"); + memcpy(&size, buf, sizeof(size)); + buf += align4bytes(sizeof(size)); + CStats::LoadStats(buf, size); + size = align4bytes(size); + buf += size;*/ + + // LoadSaveDataBlock(); + // ReadDataFromBlock("Loading Set Pieces \n", CSetPieces::Load); + // LoadSaveDataBlock(); + // ReadDataFromBlock("Loading Streaming Stuff \n", CStreaming::MemoryCardLoad); + // LoadSaveDataBlock(); + // ReadDataFromBlock("Loading PedType Stuff \n", CPedType::Load); CStreaming::ReInit(); DMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume); DMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume); diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index a33e9d90..79965584 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -19,7 +19,7 @@ C_PcSave PcSaveHelper; void C_PcSave::SetSaveDirectory(const char *path) { - sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTAVCsf"); + sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTAVCSsf"); } bool diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index d5805681..80fb608f 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -397,7 +397,7 @@ RsInitialize(void) */ RwBool result; - RsGlobal.appName = RWSTRING("GTA: Liberty City Stories"); + RsGlobal.appName = RWSTRING("GTA: Vice City Stories"); RsGlobal.maximumWidth = DEFAULT_SCREEN_WIDTH; RsGlobal.maximumHeight = DEFAULT_SCREEN_HEIGHT; RsGlobal.width = DEFAULT_SCREEN_WIDTH; diff --git a/src/skel/win/gtavcs.ico b/src/skel/win/gtavcs.ico new file mode 100644 index 0000000000000000000000000000000000000000..a4959fe762e99c65a9e8e8167aaa5bd0a49e4be7 GIT binary patch literal 4286 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 z%0A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 z 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 literal 0 HcmV?d00001 diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 639f6272..63651c91 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -50,6 +50,9 @@ #include "skeleton.h" #include "platform.h" #include "crossplatform.h" +#ifdef MAZAHAKA_PLUGIN_CODE +#include "../plugin/plugin.h" +#endif #define MAX_SUBSYSTEMS (16) @@ -67,7 +70,7 @@ static RwBool useDefault; /* Class name for the MS Window's window class. */ -static const RwChar *AppClassName = RWSTRING("Grand theft auto 3"); +static const RwChar *AppClassName = RWSTRING("Grand theft auto vcs"); static psGlobalType PsGlobal; @@ -148,6 +151,19 @@ void CJoySticks::ClearJoyInfo(int joyID) m_aJoys[joyID].m_bHasAxisR = false; } +#ifdef MAZAHAKA_FIX_BACKGROUND_APP_NO_HOLD_MOUSE +bool +CheckWindowStateIsOpenedMaZaHaKa() +{ + // HWND window = ((psGlobalType *)(RsGlobal.ps))->window; // PSGLOBAL(window) + HWND window = PSGLOBAL(window); + HWND activeWindow = GetForegroundWindow(); + + // bool IsMinimized = (IsIconic(window) != 0); // no used here + bool IsActive = (window == activeWindow); + return IsActive; +} +#endif /* @@ -194,7 +210,7 @@ const char *_psGetUserFilesFolder() &KeycbData) == ERROR_SUCCESS ) { RegCloseKey(hKey); - strcat(szUserFiles, "\\GTA Vice City User Files"); + strcat(szUserFiles, "\\GTA LCS User Files"); _psCreateFolder(szUserFiles); return szUserFiles; } @@ -1541,7 +1557,7 @@ psSelectDevice() } if(bestFsMode < 0){ - MessageBox(nil, "Cannot find desired video mode", "GTA: Vice City", MB_OK); + MessageBox(nil, "Cannot find desired video mode", "GTA: LCS", MB_OK); return FALSE; } GcurSelVM = bestFsMode; @@ -2006,6 +2022,11 @@ void HandleExit() /* ***************************************************************************** */ +//#include "Windows.h" +//#include +#include "../utils/SetCurrDir.h" // ++ MAZAHAKA +#include "../utils/ConsoleTools.h" // ++ MAZAHAKA +#include int PASCAL WinMain(HINSTANCE instance, HINSTANCE prevInstance __RWUNUSED__, @@ -2018,14 +2039,40 @@ WinMain(HINSTANCE instance, RwChar **argv; SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); -#ifndef MASTER - if (strstr(cmdLine, "-console")) + //#ifndef MASTER + // if (strstr(cmdLine, "-console")) { - AllocConsole(); - freopen("CONIN$", "r", stdin); - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); +#ifdef MAZAHAKA_DEBUG // ++ MAZAHAKA + // AllocConsole(); + // freopen("CONIN$", "r", stdin); + // freopen("CONOUT$", "w", stdout); + // freopen("CONOUT$", "w", stderr); + OpenConsole(); +#else +#ifndef MAZAHAKA_RELEASE_NO_SHIFT_CONSOLE_AT_START + if((GetAsyncKeyState(VK_SHIFT) & 0x8000)) { OpenConsole(); } +#endif +#endif + + // mod by diktor SET CURRENT PATH + // char currentDir[MAX_PATH]; // STATIC PATH + // GetCurrentDirectory(MAX_PATH, currentDir); + // printf("DIR: %s\n", currentDir); + // memset(currentDir, 0, MAX_PATH); + // strncpy(currentDir, "C:\\_GTA_RE\\revc\\reVC_GAME", MAX_PATH); + // currentDir[MAX_PATH - 1] = '\0'; // Ensure null-termination + // SetCurrentDirectory(currentDir); + + // char currentDir[MAX_PATH]; // dynamic set curr dir to exe + // GetModuleFileName(NULL, currentDir, MAX_PATH); + // std::string::size_type pos = std::string(currentDir).find_last_of("\\/"); + // SetCurrentDirectory(std::string(currentDir).substr(0, pos).c_str()); + if(!gbIsSettedCurrDir) { U_SetCurrentDirectory(); } } + //#endif + +#ifdef MAZAHAKA_PLUGIN_CODE + PLG_Start(); // PLG PLUGIN MAZAHAKA // after setting no debug dir #endif #ifdef USE_CUSTOM_ALLOCATOR diff --git a/src/skel/win/win.h b/src/skel/win/win.h index be840898..53de668d 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -88,4 +88,14 @@ void CloseClip(void); } #endif /* __cplusplus */ -#endif /* (!defined(_PLATFORM_WIN_H)) */ + +//#include "config.h" // ifdef? +//#ifdef MAZAHAKA_FIX_BACKGROUND_APP_NO_HOLD_MOUSE +//#include "Windows.h" +// bool CheckWindowState(HWND window = PSGLOBAL(window)); +//#endif +#ifdef MAZAHAKA_FIX_BACKGROUND_APP_NO_HOLD_MOUSE +bool CheckWindowStateIsOpenedMaZaHaKa(); +#endif + +#endif /* (!defined(_PLATFORM_WIN_H)) */ \ No newline at end of file diff --git a/src/skel/win/win.rc b/src/skel/win/win.rc index 702c3de7..645ff1fb 100644 --- a/src/skel/win/win.rc +++ b/src/skel/win/win.rc @@ -42,6 +42,6 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_MAIN_ICON ICON DISCARDABLE "gtalcs.ico" +IDI_MAIN_ICON ICON DISCARDABLE "gtavcs.ico" ///////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/text/Messages.h b/src/text/Messages.h index 15abaafe..bb5898bc 100644 --- a/src/text/Messages.h +++ b/src/text/Messages.h @@ -40,13 +40,13 @@ public: static bool WideStringCompare(wchar *str1, wchar *str2, uint16 size); static void Process(void); static void Display(void); - static void AddMessage(wchar *key, uint32 time, uint16 pos); - static void AddMessageJumpQ(wchar *key, uint32 time, uint16 pos); - static void AddMessageSoon(wchar *key, uint32 time, uint16 pos); + static void AddMessage(wchar *msg, uint32 time, uint16 pos); + static void AddMessageJumpQ(wchar *msg, uint32 time, uint16 pos); + static void AddMessageSoon(wchar *msg, uint32 time, uint16 pos); static void ClearMessages(void); static void ClearSmallMessagesOnly(void); - static void AddBigMessage(wchar *key, uint32 time, uint16 pos); - static void AddBigMessageQ(wchar *key, uint32 time, uint16 pos); + static void AddBigMessage(wchar *msg, uint32 time, uint16 pos); + static void AddBigMessageQ(wchar *msg, uint32 time, uint16 pos); static void AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string); static void InsertNumberInString(wchar *src, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *dst); static void InsertStringInString(wchar *str1, wchar *str2); diff --git a/src/utils/ConsoleTools.cpp b/src/utils/ConsoleTools.cpp new file mode 100644 index 00000000..0d7c5f48 --- /dev/null +++ b/src/utils/ConsoleTools.cpp @@ -0,0 +1,100 @@ +#pragma once +#include "ConsoleTools.h" +#include "Windows.h" +#include +#include + +//#define MY_ALLOC +HANDLE InitConsole(); + + +extern bool gbIsConsoleOpened = false; + + +void OpenConsole() +{ + if(!gbIsConsoleOpened) + { +#ifdef MY_ALLOC + InitConsole(); +#else + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); +#endif + gbIsConsoleOpened = true; + } +} + + + +//------------------------------------------------------------------ +HANDLE InitConsole() // with proto +{ + AllocConsole(); + + //SetConsoleOutputCP(866); + setlocale(LC_ALL, "Russian"); + SetConsoleOutputCP(1251); + SetConsoleCP(1251); + + + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); + + return hConsole; +} + +//void LeaveConsole(HANDLE hConsole = nullptr) +void LeaveConsole(HANDLE hConsole) // with proto +{ + if (hConsole != nullptr) { SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } // Reset to default color + FreeConsole(); +} + +//void Mbox(const char* msg, const char* title) +//{ +// MessageBoxA(HWND_DESKTOP, msg, title, MB_SYSTEMMODAL | MB_ICONWARNING); +//} +// +////void MboxSTD(const std::string& msg, const std::string& title = "title") +//void MboxSTD(std::string msg, std::string title) +//{ +// MessageBoxA(HWND_DESKTOP, msg.c_str(), title.c_str(), MB_SYSTEMMODAL | MB_ICONWARNING); +//} +//void EXIT_F() +//{ +// ExitProcess(EXIT_FAILURE); +//} +//void EXIT_S() +//{ +// ExitProcess(EXIT_SUCCESS); +//} +//void RaiseError(const char* fmt, ...) +//{ +// char buf[2048]; +// va_list args; +// va_start(args, fmt); +// vsprintf_s(buf, fmt, args); +// va_end(args); +// +// MessageBoxA(HWND_DESKTOP, buf, "Fatal Error", MB_SYSTEMMODAL | MB_ICONWARNING); +// ExitProcess(EXIT_FAILURE); +//} + + +//std::string ToUpper(std::string strToConvert) +//{ +// std::transform(strToConvert.begin(), strToConvert.end(), strToConvert.begin(), std::toupper); //::toupper +// return strToConvert; +//} +//std::string ToLower(std::string strToConvert) +//{ +// std::transform(strToConvert.begin(), strToConvert.end(), strToConvert.begin(), std::tolower); +// return strToConvert; +//} +//std::string CustomStringConcat(std::string str1, std::string str2) { return str1 + str2; } \ No newline at end of file diff --git a/src/utils/ConsoleTools.h b/src/utils/ConsoleTools.h new file mode 100644 index 00000000..a1a9f32c --- /dev/null +++ b/src/utils/ConsoleTools.h @@ -0,0 +1,11 @@ +#pragma once +#include "Windows.h" +//#include +//#include +#pragma warning(disable : 4996) // freopen unsafe + +//#define MY_ALLOC +extern bool gbIsConsoleOpened; +void OpenConsole(); +HANDLE InitConsole(); +void LeaveConsole(HANDLE); diff --git a/src/utils/SetCurrDir.cpp b/src/utils/SetCurrDir.cpp new file mode 100644 index 00000000..7056d25f --- /dev/null +++ b/src/utils/SetCurrDir.cpp @@ -0,0 +1,23 @@ +#pragma once +#include "Windows.h" +#include + +static bool gbIsSettedCurrDir = false; +void +U_SetCurrentDirectory() +{ + // mod by diktor SET CURRENT PATH + // char currentDir[MAX_PATH]; // STATIC PATH + // GetCurrentDirectory(MAX_PATH, currentDir); + // printf("DIR: %s\n", currentDir); + // memset(currentDir, 0, MAX_PATH); + // strncpy(currentDir, "C:\\_GTA_RE\\revc\\reVC_GAME", MAX_PATH); + // currentDir[MAX_PATH - 1] = '\0'; // Ensure null-termination + // SetCurrentDirectory(currentDir); + + char currentDir[MAX_PATH]; // dynamic set curr dir to exe + GetModuleFileName(NULL, currentDir, MAX_PATH); + std::string::size_type pos = std::string(currentDir).find_last_of("\\/"); + SetCurrentDirectory(std::string(currentDir).substr(0, pos).c_str()); + gbIsSettedCurrDir = true; +} \ No newline at end of file diff --git a/src/utils/SetCurrDir.h b/src/utils/SetCurrDir.h new file mode 100644 index 00000000..c6d67c13 --- /dev/null +++ b/src/utils/SetCurrDir.h @@ -0,0 +1,7 @@ +#pragma once +#include "Windows.h" +#include + +static bool gbIsSettedCurrDir; +void +U_SetCurrentDirectory(); \ No newline at end of file diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp new file mode 100644 index 00000000..4a56e281 --- /dev/null +++ b/src/utils/Utils.cpp @@ -0,0 +1,555 @@ +#pragma once +#include "Utils.h" +//#include "../core/config.h" +#include "../core/common.h" +#include "../core/General.h" +#include "../weapons/WeaponType.h" +#include "../weapons/WeaponInfo.h" +#include "../rw/TxdStore.h" +#include "../fakerw/rpworld.h" +#include "../entities/Entity.h" +#include "../peds/Ped.h" +#include "../vehicles/Vehicle.h" +#include "../core/PlayerInfo.h" +#include "../peds/Ped.h" +#include "../peds/PlayerPed.h" +#include "../peds/CivilianPed.h" +#include "../core/Wanted.h" +#include "../control/PathFind.h" +#include "../core/Camera.h" +#include "../control/Replay.h" +#include "../renderer/Hud.h" +#include "../renderer/Font.h" +#include "../text/Text.h" +#include "../core/World.h" +#include "../control/Script.h" +#include "../core/Frontend.h" +#ifdef MAZAHAKA_FIX_BACKGROUND_APP_NO_HOLD_MOUSE +#include "../skel/win/win.h" +#endif + +//class CEntity; +//class CPed; +//class CVehicle; +//class CPlayerPed; +//class CCivilianPed; + +#include "Windows.h" +#include + + +////------------------------------------------------------------------ +//HANDLE InitConsole() // with proto +//{ +// AllocConsole(); +// +// //SetConsoleOutputCP(866); +// setlocale(LC_ALL, "Russian"); +// SetConsoleOutputCP(1251); +// SetConsoleCP(1251); +// +// +// freopen("CONIN$", "r", stdin); +// freopen("CONOUT$", "w", stdout); +// +// HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +// SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); +// +// return hConsole; +//} +// +////void LeaveConsole(HANDLE hConsole = nullptr) +//void LeaveConsole(HANDLE hConsole) // with proto +//{ +// if (hConsole != nullptr) { SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } // Reset to default color +// FreeConsole(); +//} + + + + +void Mbox(const char* msg, const char* title) +{ + MessageBoxA(HWND_DESKTOP, msg, title, MB_SYSTEMMODAL | MB_ICONWARNING); +} +//void MboxSTD(const std::string& msg, const std::string& title = "title") +void MboxSTD(std::string msg, std::string title) +{ + MessageBoxA(HWND_DESKTOP, msg.c_str(), title.c_str(), MB_SYSTEMMODAL | MB_ICONWARNING); +} +void EXIT_F() +{ + ExitProcess(EXIT_FAILURE); +} +void EXIT_S() +{ + ExitProcess(EXIT_SUCCESS); +} +void RaiseError(const char* fmt, ...) +{ + char buf[2048]; + va_list args; + va_start(args, fmt); + vsprintf_s(buf, fmt, args); + va_end(args); + + MessageBoxA(HWND_DESKTOP, buf, "Fatal Error", MB_SYSTEMMODAL | MB_ICONWARNING); + ExitProcess(EXIT_FAILURE); +} + + + + +void DumpTexturesNames(RpAtomic* pRpAtomic, CEntity* pEntity, bool dump_error) +{ + if (pEntity) { pRpAtomic = pEntity->GetAtomic(); } + if (!pRpAtomic) { if (dump_error) { std::cout << "!rpAtomic\n"; } return; } + if (dump_error) { printf("Atomic: 0x%p\n", pRpAtomic); } + RpGeometry* geo = pRpAtomic->geometry; + if (!geo) { if (dump_error) { std::cout << "!geo\n"; } return; } + rw::MaterialList matList = geo->matList; + //if (!matList) { return; } + //std::cout << "\n\n"; + for (int i = 0; i < matList.numMaterials; ++i) + { + RpMaterial* mat = matList.materials[i]; + if (mat && mat->texture) { + const char* textureName = mat->texture->name; + if (dump_error) { printf("%d: %s \t 0x%p\n", i, textureName, mat->texture); } + else { printf("%d: %s\n", i, textureName); } + } + //else { debug("!Material %d .", i); } + } + std::cout << "\n\n"; +} + + + +int GetModelIndex(CEntity* pEntity) // lol +{ + if (!pEntity) { return -1; } + return (pEntity->GetModelIndex()); +} + +std::string GetModelName(CEntity* pEntity) +{ + if (!pEntity) { return ""; } + //return (CModelInfo::ms_modelInfoPtrs[pEntity->GetModelIndex()]->m_name); // +".txd" ? + return (CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetModelName()); // +".txd" ? +} + +std::string GetModelTxdSlotName(CEntity* pEntity) +{ + if (!pEntity) { return ""; } + //return (CTxdStore::GetTxdName(CModelInfo::ms_modelInfoPtrs[pEntity->GetModelIndex()]->GetTxdSlot())); // +".txd" ? + return (CTxdStore::GetTxdName(CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetTxdSlot())); // +".txd" ? +} + +// crash if entity is ped +void DumpEntityData(CEntity* pEntity, bool clear_console) +{ + if (!pEntity) { std::cout << "!pEntity" << "\n"; return; } + if(clear_console) { system("cls"); } + else {std::cout << "\n\n"; } + std::cout << "MI: " << GetModelIndex(pEntity) << " Entity: 0x" << pEntity << " Name: " << GetModelName(pEntity) << "\t TXD: " << GetModelTxdSlotName(pEntity) << "\n"; + std::cout << "\n" << "Tex List" << "\n"; + DumpTexturesNames(nullptr, pEntity, false); + std::cout << "\n\n"; +} + + +CWeaponInfo* GetPlayerCurrentWeaponInfo() +{ + if (!FindPlayerPed()) { return nullptr; } + CWeaponInfo* info = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType); + return info; +} + +int32_t GetPlayerCurrentWeaponType() +{ + //if (!FindPlayerPed()) { return eWeaponType::WEAPONTYPE_UNARMED; } + if (!FindPlayerPed()) { return eWeaponType::WEAPONTYPE_UNARMED; } + //int32_t WeaponType = FindPlayerPed()->m_aWeapons[FindPlayerPed()->m_nCurrentWeapon].m_eWeaponType; + return FindPlayerPed()->GetWeapon()->m_eWeaponType; +} + + +//----- +bool IsWeaponPistol() +{ + if (!FindPlayerPed()) { return false; } + return (GetPlayerCurrentWeaponType() == WEAPONTYPE_COLT45); +} + +bool IsWeaponUziPlayer() +{ + if (!FindPlayerPed()) { return false; } + return (GetPlayerCurrentWeaponType() == WEAPONTYPE_UZI); +} + +/*bool IsWeaponAK47Player() +{ + if (!FindPlayerPed()) { return false; } + return (GetPlayerCurrentWeaponType() == WEAPONTYPE_AK47); +} + +bool IsWeaponM16Player() +{ + if (!FindPlayerPed()) { return false; } + return (GetPlayerCurrentWeaponType() == WEAPONTYPE_M16); +}*/ + +bool IsUnArmedPlayer() +{ + if (!FindPlayerPed()) { return false; } + return (GetPlayerCurrentWeaponType() == WEAPONTYPE_UNARMED); +} +//----- + + +RpClump* GetPlayerClump() +{ + if(!FindPlayerPed()) { return nullptr; } + // CWeaponInfo::GetWeaponInfo(FindPlayerPed()->m_aWeapons[FindPlayerPed()->m_nCurrentWeapon] + return (RpClump*)FindPlayerPed()->GetClump(); +} + +bool IsPlayerDriveVehicle() +{ + if(!FindPlayerPed()) { return false; } + // return FindPlayerPed()->m_pVehicle != nullptr; // NOT WORK. тачка педа остаёться если он вышел + return FindPlayerPed()->InVehicle(); // work +} + +// if (!DKSleep(deltaTime.count(), gfMemingTimer, gfTimerBuffer)) { return; } // задержка прокрута +bool DKSleep(float deltaTime, float wait_time, float& sleepBuffer) +{ + sleepBuffer += deltaTime; // Накапливаем время + // Если накопленное время больше или равно времени ожидания + if (sleepBuffer >= wait_time) { + sleepBuffer = 0.0f; // Сбрасываем накопленное время + return true; // Время ожидания истекло, возвращаем true + } + return false; // Время ожидания не истекло, возвращаем false +} + + +bool +IsWindowActive(HWND hwnd) +{ + HWND activeWindow = GetForegroundWindow(); + return (hwnd == activeWindow); +} + +bool +IsWindowMinimized(HWND hwnd) +{ + return IsIconic(hwnd) != 0; +} + + +/*wchar strW[200]; +// char strA[250]; +// sprintf(strA, "TTS DAT Reloaded!"); +AsciiToUnicode(str, strW); +if(play_beep) { CHud::SetHelpMessage(strW, true); }*/ + +std::wstring +Utf8ToWide(const std::string &utf8Str) +{ + int wideStrLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0); + wchar_t *wideStr = new wchar_t[wideStrLen]; + MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, wideStr, wideStrLen); + std::wstring result(wideStr); + delete[] wideStr; + return result; +} + +//inline +int +GetFrontendAudioPercentVolume(bool bSFX, bool crt_vol) +{ // FrontEndMenuManager MAX VOL 128 +#define FRONTEND_AUDIO_MAX 127 + // InitConsole(); + // std::cout << "FrontEndMenuManager.m_nPrefsSfxVolume: " << FrontEndMenuManager.m_nPrefsSfxVolume << "\n"; + // std::cout << "FrontEndMenuManager.m_nPrefsMusicVolume: " << FrontEndMenuManager.m_nPrefsMusicVolume << "\n\n"; + // return 20; + int res = bSFX ? (FrontEndMenuManager.m_PrefsSfxVolume * 100) / FRONTEND_AUDIO_MAX : (FrontEndMenuManager.m_PrefsMusicVolume * 100) / FRONTEND_AUDIO_MAX; + // std::cout << "bSFX:" << bSFX << " vol:" << res << "\n"; + return res; +#undef FRONTEND_AUDIO_MAX +} + + +void +UAsciiToUnicode(const char *src, wchar *dst) // font?cpp +{ + while((*dst++ = (unsigned char)*src++) != '\0') + ; +} + + +void +UUnicodeToAscii(wchar *src, char *dst) +{ + while((*dst++ = (char)*src++) != '\0') + ; +} + +bool +IsPlayerAsPassangerNow() +{ + CPlayerPed *pPlayer = FindPlayerPed(); + if(!pPlayer) { return false; } + if(pPlayer->InVehicle() && pPlayer->m_pMyVehicle->pDriver != pPlayer) { return true; } // passanger? + return false; +} + +bool +CheckWastedBustedPlayer() // return true if wasted/busted +{ + CPlayerInfo *pPlayerInfo = &CWorld::Players[CWorld::PlayerInFocus]; + if(!pPlayerInfo) { return false; } + //CPlayerInfo::IsRestartingAfterDeath + //CPlayerInfo::IsRestartingAfterArres + return (pPlayerInfo->m_WBState != WBSTATE_PLAYING); + //return ((pPlayerInfo->m_WBState == WBSTATE_WASTED) || (pPlayerInfo->m_WBState == WBSTATE_BUSTED)); +} + +bool +IsPlayerPlaying() +{ // CPlayerInfo::MakePlayerSafe(bool toggle) + CPlayerInfo *pPlayerInfo = &CWorld::Players[CWorld::PlayerInFocus]; + CPlayerPed *pPlayer = FindPlayerPed(); + + if(!pPlayerInfo) { return false; } + if(!pPlayer) { return false; } + + // if (CCutsceneMgr::ms_running) { return false; } + // if (IsPlayerOnMission()) { return false; } // desp rando wanted +#ifdef MAZAHAKA_FIX_BACKGROUND_APP_NO_HOLD_MOUSE + if(!CheckWindowStateIsOpenedMaZaHaKa()) { return false; } +#endif + if(FrontEndMenuManager.m_bMenuActive) { return false; } + if(TheCamera.m_bFading) { return false; } + if(FrontEndMenuManager.m_bGameNotLoaded) { return false; } + if(CheckWastedBustedPlayer()) { return false; } + if(FindPlayerVehicle() && (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_TRAIN)) { return false; } + + //if(pPlayer->InVehicle() && pPlayer->m_pMyVehicle->pDriver != pPlayer) { return false; } // passanger? + if(IsPlayerAsPassangerNow()) { return false; } // passanger? + if(CReplay::IsPlayingBack()) { return false; } + + + bool defaultgamesafeped = + (true + && pPlayer->m_pWanted->m_bIgnoredByEveryone + && pPlayer->bBulletProof + && pPlayer->bFireProof + && pPlayer->bCollisionProof + && pPlayer->bMeleeProof + && pPlayer->bOnlyDamagedByPlayer + && pPlayer->bExplosionProof + && !(pPlayer->m_bCanBeDamaged)); + if(defaultgamesafeped) { return false; } + // on true safe + // 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; + return true; +} + + +CVector +Transform3DPoint2NearPathNode(CVector target) +{ + int node = ThePaths.FindNodeClosestToCoors(target, 0, 150.0f, true, true); + if(node < 0) { return target; } + CVector output = ThePaths.m_pathNodes[node].GetPosition(); + return output; +} + +int +GetRandomNumInclude(int start, int end) +{ + // Добавляем 1 к `end` в выражении, чтобы включить верхнюю границу + return start + CGeneral::GetRandomNumberInRange(0, end - start + 1); +} + +int +GetRandomNumUnInclude(int start, int end) +{ + // Здесь верхняя граница уже исключена, поэтому никакие изменения не требуются + return start + CGeneral::GetRandomNumberInRange(0, end - start); +} + + +bool +IsWithinRadius(const CVector &point1, const CVector &point2, float radius) // есть реализация в игре готовая? +{ + CVector diff = point1 - point2; + float distSquared = diff.x * diff.x + diff.y * diff.y + diff.z * diff.z; + float radiusSquared = radius * radius; + return distSquared <= radiusSquared; +} + + +void +Message(const char *str, bool play_beep) +{ + /*std::wstring wideStr = Utf8ToWide(str); +#ifdef MAZAHAKA_SILENT_CHUD_MESSAGE + if(play_beep) { CHud::SetHelpMessage((wchar *)wideStr.c_str(), true); } + else { CHud::SetHelpMessageNoSound((wchar *)wideStr.c_str(), true); } +#else + CHud::SetHelpMessage((wchar *)wideStr.c_str(), true); +#endif*/ + + wchar strW[200]; + // char strA[250]; + // sprintf(strA, "TTS DAT Reloaded!"); + AsciiToUnicode(str, strW); + +#ifdef MAZAHAKA_SILENT_CHUD_MESSAGE + if(play_beep) { + CHud::SetHelpMessage(strW, true); + } else { + CHud::SetHelpMessageNoSound(strW, true); + } +#else + CHud::SetHelpMessage(strW, true); +#endif +} + +//__declspec(noinline) +CVehicle * +GetRandomPoolVehicle(bool nodriver, bool all) +{ + CPlayerPed *pPlayer = FindPlayerPed(); + int j = CPools::GetVehiclePool()->GetSize(); + while(j-- > 0) { + //if(CVehicle *veh = CPools::GetVehiclePool()->GetSlot(j)) veh->BlowUpCar(nil); + CVehicle *veh = CPools::GetVehiclePool()->GetSlot(j); + if(!veh) {continue; } + if(pPlayer && pPlayer->InVehicle() && pPlayer->m_pMyVehicle == veh) { continue; } + if(all) { if(veh->IsCar()) { return veh; } } + else { + if(nodriver && (!veh->pDriver) && veh->IsCar()) { return veh; } + else if(!nodriver && veh->pDriver && veh->IsCar()) { return veh; } + } + + } + + /*while(1) + { + int i = _RandVUKL(0, CPools::GetVehiclePool()->GetSize()); + CVehicle *veh = CPools::GetVehiclePool()->GetSlot(i); + if(veh && veh->IsCar()) { return veh; } + Sleep(0); + }*/ + return nil; +} + +CVehicle* +GetVehicleNearPlayer() +{ + //CVehicle *veh = nil; + CPlayerPed *pPlayer = FindPlayerPed(); + CPlayerInfo *pPlayerInfo = &CWorld::Players[CWorld::PlayerInFocus]; + if(!pPlayer || !pPlayerInfo) { return false; } + //veh = pPlayer->m_pMyVehicle; // tmp dummy + + bool weAreOnBoat = false; + float lastCloseness = 0.0f; + CVehicle *carBelow = nil; + CEntity *surfaceBelow = pPlayer->m_pCurrentPhysSurface; + if(surfaceBelow && surfaceBelow->IsVehicle()) { + carBelow = (CVehicle *)surfaceBelow; + if(carBelow->IsBoat()) { + weAreOnBoat = true; + pPlayer->bOnBoat = true; +#ifdef VC_PED_PORTS + if(carBelow->GetStatus() != STATUS_WRECKED && carBelow->GetUp().z > 0.3f) +#else + if(carBelow->GetStatus() != STATUS_WRECKED) +#endif + pPlayer->SetSeekBoatPosition(carBelow); + } + } + // Find closest car + if(!weAreOnBoat) { + float minX = pPlayer->GetPosition().x - 10.0f; + float maxX = 10.0f + pPlayer->GetPosition().x; + float minY = pPlayer->GetPosition().y - 10.0f; + float maxY = 10.0f + pPlayer->GetPosition().y; + + int minXSector = CWorld::GetSectorIndexX(minX); + if(minXSector < 0) minXSector = 0; + int minYSector = CWorld::GetSectorIndexY(minY); + if(minYSector < 0) minYSector = 0; + int maxXSector = CWorld::GetSectorIndexX(maxX); + if(maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1; + int maxYSector = CWorld::GetSectorIndexY(maxY); + if(maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1; + + CWorld::AdvanceCurrentScanCode(); + + for(int curY = minYSector; curY <= maxYSector; curY++) { + for(int curX = minXSector; curX <= maxXSector; curX++) { + CSector *sector = CWorld::GetSector(curX, curY); + pPlayerInfo->FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], pPlayer, minX, minY, maxX, maxY, &lastCloseness, + &carBelow); + pPlayerInfo->CPlayerInfo::FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pPlayer, minX, minY, maxX, + maxY, &lastCloseness, &carBelow); + } + } + } + + + return carBelow; +} + +void +DumpAllScriptsOffsets() +{ + // re3.cpp (no have re3.h) + static const char* missions[] = { + "initial: objects", "initial: hidden packages", "initial: car generators", "initial: pickups", "initial: unique stunt jumps", + "initial: player", "initial: general info", "initial: lods", "initial: weapons", "Home Sweet Home", "Taxi-Driver Sub-Mission", + "Paramedic Sub-Mission", "Vigilante Sub-Mission", "Karmageddon", "Firefighter Sub-Mission", "Trash Dash", "RC Triad Take-Down", + "Thrashin' RC", "Ragin' RC", "Chasin' RC", "GO GO Faggio", "Noodleboy", "Pizzaboy", "Wong Side Of The Tracks", "Bumps and Grinds: Course 1", + "Bumps and Grinds: Course 2", "Bumps and Grinds: Course 3", "Bumps and Grinds: Course 4", "Bumps and Grinds: Course 5", "Bumps and Grinds: Course 6", + "Bumps and Grinds: Course 7", "Bumps and Grinds: Course 8", "Bumps and Grinds: Course 9", "Bumps and Grinds: Course 10", "Car Salesman", "Bike Salesman", + "RACE: Low-Rider Rumble", "RACE: Deimos Dash", "RACE: Wi-Cheetah Run", "RACE: Red Light Racing", "RACE: Torrington TT", "RACE: Gangsta GP", + "Scooter Shooter", "AWOL Angel", "9mm Mayhem", "Scrapyard Challenge", "See the Sight Before your Flight", "SlashTV", "Slacker (Vincenzo)", + "Dealing Revenge (Vincenzo)", "Snuff (Vincenzo)", "Smash and Grab (Vincenzo)", "Hot Wheels (Vincenzo)", "The Portland Chainsaw Masquerade (Vincenzo)", + "The Offer (Salvatore)", "Ho Selecta! (Salvatore)", "Frighteners (Salvatore)", "Rollercoaster Ride (Salvatore)", "Contra-Banned (Salvatore)", + "Sindacco Sabotage (Salvatore)", "The Trouble with Triads (Salvatore)", "Driving Mr Leone (Salvatore)", "conversation (JD)", "Bone Voyeur! (JD)", + "Don in 60 Seconds (JD)", "A Volatile Situation (JD)", "Blow up 'Dolls' (JD)", "Salvatore's Salvation (JD)", "The Guns of Leone (JD)", + "Calm before the Storm (JD)", "The Made Man (JD)", "Snappy Dresser (Ma Cipriani)", "Big Rumble in Little China (Ma Cipriani)", "Grease Sucho (Ma Cipriani)", + "Dead Meat (Ma Cipriani)", "No Son of Mine (Ma Cipriani)", "Shop 'til you Strop (Maria)", "Taken for a Ride (Maria)", "Booby Prize (Maria)", + "Biker Heat (Maria)", "Overdose of Trouble (Maria)", "Making Toni (Salvatore)", "A Walk In The Park (Salvatore)", "Caught In The Act (Salvatore)", + "Search And Rescue (Salvatore)", "Taking The Peace (Salvatore)", "Shoot The Messenger (Salvatore)", "Sayonara Sindaccos (Leon McAffrey)", + "The Whole 9 Yardies (Leon McAffrey)", "Crazy '69' (Leon McAffrey)", "Night Of The Livid Dreads (Leon McAffrey)", "Munitions Dump (Leon McAffrey)", + "The Morgue Party Candidate (Donald Love)", "Steering The Vote (Donald Love)", "Cam-Pain (Donald Love)", "Friggin' The Riggin' (Donald Love)", + "Love & Bullets (Donald Love)", "Counterfeit Count (Donald Love)", "Love On The Rocks (Donald Love)", "L.C. Confidential (Church Confessional)", + "The Passion Of The Heist (Church Confessional)", "Karmageddon (Church Confessional)", "False Idols (Church Confessional)", "Rough Justice (Salvatore)", + "Dead Reckoning (Salvatore)", "Shogun Showdown (Salvatore)", "The Shoreside Redemption (Salvatore)", "The Sicilian Gambit (Salvatore)", + "Panlantic Land Grab (Donald Love)", "Stop the Press (Donald Love)", "Morgue Party Resurrection (Donald Love)", "No Money, Mo' Problems (Donald Love)", + "Bringing the House Down (Donald Love)", "Love on the Run (Donald Love)", "More Deadly than the Male (Toshiko Kasen)", "Cash Clash (Toshiko Kasen)", + "A Date with Death (Toshiko Kasen)", "Cash in Kazuki's Chips (Toshiko Kasen)" + }; + + CPlayerPed *pPlayer = FindPlayerPed(); + if(!pPlayer || FrontEndMenuManager.m_bGameNotLoaded) { return; } // if not loaded, scm offsets not inited, only in game + //void CTheScripts::ReadMultiScriptFileOffsetsFromScript() Script5.cpp + int NumberOfMissionScripts = CTheScripts::NumberOfMissionScripts; + for(int i = 0; i < NumberOfMissionScripts; i++) + { // todo refw auto labels? + std::cout << i << ": " << "0x" << std::hex << CTheScripts::MultiScriptArray[i] << std::dec << " " << missions[i] << "\n"; + } +} \ No newline at end of file diff --git a/src/utils/Utils.h b/src/utils/Utils.h new file mode 100644 index 00000000..c3600576 --- /dev/null +++ b/src/utils/Utils.h @@ -0,0 +1,115 @@ +#pragma once +#include "../core/common.h" + +class CEntity; +class CPed; +class CVehicle; +class CPlayerPed; +class CCivilianPed; +class CWeaponInfo; + +//struct RpAtomic; + +#include "Windows.h" +#include + +//HANDLE InitConsole(); +//void LeaveConsole(HANDLE hConsole); + + + + +void Mbox(const char* msg, const char* title); +//void MboxSTD(const std::string& msg, const std::string& title = "title") +void MboxSTD(std::string msg, std::string title = ""); +void EXIT_F(); +void EXIT_S(); +void RaiseError(const char* fmt, ...); + + + +void DumpTexturesNames(RpAtomic* pRpAtomic, CEntity* pEntity = nullptr, bool dump_error = true); + + + +int GetModelIndex(CEntity* pEntity); + +std::string GetModelName(CEntity* pEntity); + +std::string GetModelTxdSlotName(CEntity* pEntity); + +// crash if entity is ped +void DumpEntityData(CEntity* pEntity, bool clear_console = true); + +CWeaponInfo* GetPlayerCurrentWeaponInfo(); + +int32_t GetPlayerCurrentWeaponType(); + + +//----- +bool IsWeaponPistol(); +bool IsWeaponUziPlayer(); +bool IsWeaponAK47Player(); +bool IsWeaponM16Player(); +bool IsUnArmedPlayer(); +//----- + +RpClump* GetPlayerClump(); +bool IsPlayerDriveVehicle(); + +// if(!DKSleep(deltaTime.count(), gfMemingTimer, gfTimerBuffer)) { return; } // задержка прокрута +bool DKSleep(float deltaTime, float wait_time, float& sleepBuffer); + +bool +IsWindowActive(HWND hwnd); + +bool +IsWindowMinimized(HWND hwnd); + +// example in cpp +//std::wstring +//Utf8ToWide(const std::string &utf8Str); + +//inline +int +GetFrontendAudioPercentVolume(bool bSFX, bool crt_vol = true); + +void +UAsciiToUnicode(const char *src, wchar *dst); // font.cpp + +void +UUnicodeToAscii(wchar *src, char *dst); + + +bool +IsPlayerAsPassangerNow(); + +bool +CheckWastedBustedPlayer(); // return true if wasted/busted + +bool +IsPlayerPlaying(); + +CVector +Transform3DPoint2NearPathNode(CVector target); + +int +GetRandomNumInclude(int start, int end); + +int +GetRandomNumUnInclude(int start, int end); + +bool +IsWithinRadius(const CVector &point1, const CVector &point2, float radius); + +void +Message(const char *str, bool play_beep = true); + +CVehicle * +GetRandomPoolVehicle(bool nodriver = false, bool all = false); + +CVehicle * +GetVehicleNearPlayer(); + +void +DumpAllScriptsOffsets(); \ No newline at end of file diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index b0f21af7..4e906b3a 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -4893,8 +4893,10 @@ CAutomobile::BlowUpCar(CEntity *culprit) { RpAtomic *atomic; - if(!bCanBeDamaged) - return; + if(!bCanBeDamaged) { return; } +#ifdef MAZAHAKA_MISC + //if(bExplosionProof) { return; } // mazahaka // fire +#endif if(culprit == FindPlayerPed() || culprit == FindPlayerVehicle()){ CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 20; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index cf46f37b..19448b72 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -109,6 +109,9 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_boom.Init(-PI/10.0f, PI/10.0f, 0, 2); else m_boom.Init(-PI/5.0f, PI/5.0f, 0, 2); +#ifdef MAZAHAKA_MISC + //bool m_bIsBlowProof = false; +#endif } void @@ -840,8 +843,11 @@ CBoat::BlowUpCar(CEntity *culprit) RwMatrix *matrix; CObject *obj; - if(!bCanBeDamaged) - return; + if(!bCanBeDamaged) { return; } +#ifdef MAZAHAKA_MISC + //if(bExplosionProof) { return; } // mazahaka + //if(m_bIsBlowProof) { return; } // mazahaka can explode if fire and exproof but if fire and blow proof dont!! +#endif // explosion pushes vehicle up m_vecMoveSpeed.z += 0.13f; diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index 5d866c48..6d63bcce 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -46,6 +46,9 @@ public: uint16 m_nNumWakePoints; CVector2D m_avec2dWakePoints[32]; float m_afWakePointLifeTime[32]; +#ifdef MAZAHAKA_MISC + //bool m_bIsBlowProof; // like explosion proof but if exproof and check in blow its fire but not blow and broke game logic +#endif static float MAX_WAKE_LENGTH; static float MIN_WAKE_INTERVAL; diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index d4b58f05..2b850c8a 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -68,6 +68,7 @@ void CCranes::InitCranes(void) } } // TODO(LCS) +#ifndef MAZAHAKA_MAPZONE_VC for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; if (MODELID_CRANE_1 == pEntity->GetModelIndex() || @@ -78,7 +79,18 @@ void CCranes::InitCranes(void) MODELID_CRANE_6 == pEntity->GetModelIndex()) AddThisOneCrane(pEntity); } - +#else + for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_MAINLAND).first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + if (MODELID_CRANE_1 == pEntity->GetModelIndex() || + MODELID_CRANE_2 == pEntity->GetModelIndex() || + MODELID_CRANE_3 == pEntity->GetModelIndex() || + MODELID_CRANE_4 == pEntity->GetModelIndex() || + MODELID_CRANE_5 == pEntity->GetModelIndex() || + MODELID_CRANE_6 == pEntity->GetModelIndex()) + AddThisOneCrane(pEntity); + } +#endif } void CCranes::AddThisOneCrane(CEntity* pEntity) diff --git a/src/vehicles/Ferry.cpp b/src/vehicles/Ferry.cpp index 339c2819..bacdd2bf 100644 --- a/src/vehicles/Ferry.cpp +++ b/src/vehicles/Ferry.cpp @@ -21,9 +21,12 @@ CFerryInst* CFerry::mspInst; #define FERRY_SPEED (0.1f) #define FERRY_SLOWDOWN_DISTANCE (50.0f) #define FERRY_TIME_STOPPED_AT_STATION (10.0f) +#define FERRY_MODEL_INDEX MI_FERRY +//#define FERRY_MODEL_INDEX MI_BANSHEE CFerry::CFerry(int32 id, uint8 owner) : CVehicle(owner) { +#ifdef GTA_FERRY m_bPlayerArrivedHorn = false; m_nTimeAlongPath = 0; m_vehType = VEHICLE_TYPE_FERRY; @@ -51,10 +54,12 @@ CFerry::CFerry(int32 id, uint8 owner) : CVehicle(owner) m_nCollision = 0; m_pDefaultColModel = mi->GetColModel(); m_level = LEVEL_GENERIC; +#endif } void CFerry::Init(void* pInstancePtr) { +#ifdef GTA_FERRY mspInst = (CFerryInst*)pInstancePtr; if (mspInst) return; @@ -198,10 +203,12 @@ void CFerry::Init(void* pInstancePtr) // end pPath->aLineBits[j].time = pPath->TotalDurationOfTrack; } +#endif } void CFerry::InitFerrys(void) { +#ifdef GTA_FERRY printf("init ferrys\n"); #ifdef GTA_NETWORK if (gIsMultiplayerGame) @@ -212,12 +219,14 @@ void CFerry::InitFerrys(void) for (int i = 0; i < NUM_FERRIES; i++) mspInst->m_apFerries[i] = nil; CStreaming::LoadAllRequestedModels(false); - CStreaming::RequestModel(MI_FERRY, 0); + CStreaming::RequestModel(FERRY_MODEL_INDEX, 0); CStreaming::LoadAllRequestedModels(false); +#endif } void CFerry::SwitchFerryCollision(int type) { +#ifdef GTA_FERRY for (int i = 0; i < NUM_FERRIES; i++) { CFerry* pFerry = GetFerry(i); if (pFerry && pFerry->m_nCollision != type) { @@ -229,10 +238,12 @@ void CFerry::SwitchFerryCollision(int type) mi->SetColModel(pFerry->m_pDefaultColModel, true); } } +#endif } void CFerry::UpdateFerrys(void) { +#ifdef GTA_FERRY int i, j; float t, deltaT; if (mspInst->m_bFerriesDisabled) @@ -301,18 +312,22 @@ void CFerry::UpdateFerrys(void) } } } +#endif } void CFerry::SetModelIndex(uint32 mi) { +#ifdef GTA_FERRY CVehicle::SetModelIndex(mi); for (int i = 0; i < NUM_FERRY_NODES; i++) m_aFerryNodes[i] = nil; CClumpModelInfo::FillFrameArray(GetClump(), m_aFerryNodes); +#endif } void CFerry::PreRender(void) { +#ifdef GTA_FERRY CVehicleModelInfo* mi = GetModelInfo(); if (CGeneral::GetRandomTrueFalse()) CParticle::AddParticle(PARTICLE_FERRY_CHIM_SMOKE, GetMatrix() * mi->m_positions[FERRY_POS_CHIM_LEFT], CVector(0.0f, 0.0f, 0.2f)); @@ -344,16 +359,20 @@ void CFerry::PreRender(void) CVector vRearLightPosition2 = vRearLightPosition - 2 * mi->m_positions[FERRY_POS_LIGHT_REAR].x * GetRight(); CCoronas::RegisterCorona((uint32)(uintptr)this + 28, 255, 0, 0, 255, vRearLightPosition2, 1.0f, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f); CCoronas::RegisterCorona((uint32)(uintptr)this + 29, 255, 0, 0, 255, vRearLightPosition, 1.0f, 80.0f, CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f); +#endif } void CFerry::Render(void) { +#ifdef GTA_FERRY m_bAlreadyRendered = true; CEntity::Render(); +#endif } void CFerry::RenderAllRemaning(void) { +#ifdef GTA_FERRY #ifdef GTA_NETWORK if (gIsMultiplayerGame) return; @@ -366,19 +385,23 @@ void CFerry::RenderAllRemaning(void) pFerry->m_bAlreadyRendered = false; } } +#endif } void CFerry::FerryHitStuff(CPtrList& lst) { +#ifdef GTA_FERRY for (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next) { CPhysical* pEntity = (CPhysical*)pNode->item; if (pEntity != this && Abs(GetPosition().x - pEntity->GetPosition().z) < 1.5f) pEntity->bHitByTrain = true; } +#endif } void CFerry::ProcessControl(void) { +#ifdef GTA_FERRY if (gbModelViewer) return; PruneWakeTrail(); @@ -564,15 +587,15 @@ void CFerry::ProcessControl(void) if (m_rwObject) DeleteRwObject(); } - else if (CStreaming::HasModelLoaded(MI_FERRY)) { + else if (CStreaming::HasModelLoaded(FERRY_MODEL_INDEX)) { if (m_rwObject == nil) { m_modelIndex = -1; - SetModelIndex(MI_FERRY); + SetModelIndex(FERRY_MODEL_INDEX); } } else { if (FindPlayerCoors().z * GetPosition().z >= 0.0f) - CStreaming::RequestModel(MI_FERRY, STREAMFLAGS_DEPENDENCY); + CStreaming::RequestModel(FERRY_MODEL_INDEX, STREAMFLAGS_DEPENDENCY); } // Hit stuff @@ -610,10 +633,12 @@ void CFerry::ProcessControl(void) FerryHitStuff(s->m_lists[ENTITYLIST_PEDS_OVERLAP]); } } +#endif } void CFerry::OpenFerryDoor(float ratio) { +#ifdef GTA_FERRY if (!m_rwObject) return; @@ -640,10 +665,12 @@ void CFerry::OpenFerryDoor(float ratio) doorL.UpdateRW(); doorR.UpdateRW(); +#endif } CVector CFerry::GetBoardingSpace(CFerry::eSpaceUse use, CFerry::eSpaceStyle style, uint8 position) { +#ifdef GTA_FERRY CVehicleModelInfo* pModelInfo = GetModelInfo(); CVector space; if (m_nFerryId & 1) { @@ -669,10 +696,14 @@ CVector CFerry::GetBoardingSpace(CFerry::eSpaceUse use, CFerry::eSpaceStyle styl break; } return space; +#else + return CVector(); +#endif } CFerry* CFerry::GetClosestFerry(float x, float y) { +#ifdef GTA_FERRY int closest = -1; float mindist = 9999.9f; for (int i = 0; i < NUM_FERRIES; i++) { @@ -688,15 +719,23 @@ CFerry* CFerry::GetClosestFerry(float x, float y) if (closest == -1) return nil; return GetFerry(closest); +#else + return nil; +#endif } bool CFerry::IsDocked(void) { +#ifdef GTA_FERRY return m_bFerryDocked; +#else + return false; +#endif } void CFerry::OpenDoor(void) { +#ifdef GTA_FERRY printf("opening the ferry door\n"); m_nDoorState = FERRY_DOOR_OPENING; m_nDoorTimer = CTimer::GetTimeInMilliseconds() + 10000; @@ -708,42 +747,58 @@ void CFerry::OpenDoor(void) if (fDistToCar4 < fDistToCar1) m_bUseFrontDoor = false; AudioManager.DirectlyEnqueueSample(SFX_GATE_START_CLU, SFX_BANK_0, 0, 1, 22050, 127, 20); +#endif } void CFerry::CloseDoor(void) { +#ifdef GTA_FERRY printf("closing the ferry door\n"); m_nDoorState = FERRY_DOOR_CLOSING; m_nDoorTimer = CTimer::GetTimeInMilliseconds() + 10000; AudioManager.DirectlyEnqueueSample(SFX_GATE_START_CLU, SFX_BANK_0, 0, 1, 22050, 127, 20); // shouldn't this be SFX_GATE_STOP_CLU? +#endif } bool CFerry::IsDoorOpen(void) { +#ifdef GTA_FERRY return m_nDoorState == FERRY_DOOR_OPEN; +#else + return false; +#endif } bool CFerry::IsDoorClosed(void) { +#ifdef GTA_FERRY return m_nDoorState == FERRY_DOOR_CLOSED; +#else + return false; +#endif } void CFerry::CompleteDorrMovement(void) { +#ifdef GTA_FERRY m_nDoorTimer = 0; +#endif } void CFerry::DissableFerryPath(int) { +#ifdef GTA_FERRY +#endif } void CFerry::EnableFerryPath(int path) { +#ifdef GTA_FERRY CStreaming::LoadAllRequestedModels(false); - CStreaming::RequestModel(MI_FERRY, 0); + CStreaming::RequestModel(FERRY_MODEL_INDEX, 0); CStreaming::LoadAllRequestedModels(false); for (int i = path * 2; i < path * 2 + 2; i++) { - CFerry* pFerry = new CFerry(MI_FERRY, PERMANENT_VEHICLE); + CFerry *pFerry = new CFerry(FERRY_MODEL_INDEX, PERMANENT_VEHICLE); bool bDirect = i & 1; mspInst->m_apFerries[i] = pFerry; pFerry->SetPosition(0.0f, 0.0f, 0.0f); @@ -754,15 +809,19 @@ void CFerry::EnableFerryPath(int path) pFerry->m_nCurTrackNode = 0; CWorld::Add(pFerry); } +#endif } void CFerry::SkipFerryToNextDock(void) { +#ifdef GTA_FERRY m_nSkipFerryStatus = 1; +#endif } void CFerry::PruneWakeTrail(void) { +#ifdef GTA_FERRY int16 num_remaining = 0; for (int i = 0; i < NUM_WAKE_POINTS; i++) { if (mspInst->m_afWakePointTimer[m_nFerryId][i] <= 0.0f) @@ -775,10 +834,12 @@ void CFerry::PruneWakeTrail(void) num_remaining++; } mspInst->m_anNumWakePoints[m_nFerryId] = num_remaining; +#endif } void CFerry::AddWakePoint(CVector point) { +#ifdef GTA_FERRY if (mspInst->m_afWakePointTimer[m_nFerryId][0] > 0.0f) { int nNewWakePoints = Min(NUM_WAKE_POINTS - 1, mspInst->m_anNumWakePoints[m_nFerryId]); for (int i = 0; i < nNewWakePoints; i++) { @@ -789,10 +850,12 @@ void CFerry::AddWakePoint(CVector point) mspInst->m_avWakePoints[m_nFerryId][0] = point; mspInst->m_afWakePointTimer[m_nFerryId][0] = 900.0f; // TODO: define mspInst->m_anNumWakePoints[m_nFerryId] += 1; +#endif } void CFerry::PlayArrivedHorn(void) { +#ifdef GTA_FERRY if (m_bPlayerArrivedHorn) return; m_bPlayerArrivedHorn = true; @@ -801,23 +864,31 @@ void CFerry::PlayArrivedHorn(void) uint8 volume = (200.0f - fDistToCamera) / 200.0f * 127; AudioManager.DirectlyEnqueueSample(SFX_CAR_HORN_TRUCK, SFX_BANK_0, 0, 1, 18000, volume, 50); } +#endif } CVector CFerry::GetNearestDoor(CVector) { +#ifdef GTA_FERRY return CVector(0.0f, 0.0f, 1.0f); +#else + return CVector(); +#endif } void CFerry::SetupForMultiplayer(void) { +#ifdef GTA_FERRY for (int i = 0; i < NUM_FERRIES; i++) mspInst->m_apFerries[i] = nil; printf("setting up the ferrys for multiplayer\n"); - CStreaming::SetModelIsDeletable(MI_FERRY); + CStreaming::SetModelIsDeletable(FERRY_MODEL_INDEX); +#endif } void CFerry::Write(base::cRelocatableChunkWriter& writer) { +#ifdef GTA_FERRY writer.AllocateRaw(mspInst, sizeof(*mspInst), 4); if (!mspInst) return; @@ -829,5 +900,6 @@ void CFerry::Write(base::cRelocatableChunkWriter& writer) writer.AllocateRaw(mspInst->pPathData[i]->aLineBits, (NUM_FERRY_STATIONS * 4 + 2) * sizeof(CFerryInterpolationLine), 4); writer.AddPatch(&mspInst->pPathData[i]->aTrackNodes); } +#endif } diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 7684d7dd..adc5df4c 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -693,6 +693,7 @@ CPlane::RenderAllRemaning(void) void CPlane::InitPlanes(void) { +#ifdef FLIGHT_PATH int i; CesnaMissionStatus = CESNA_STATUS_NONE; @@ -802,6 +803,7 @@ CPlane::InitPlanes(void) plane->m_nCurPathNode = 0; CWorld::Add(plane); } +#endif } void