diff --git a/Client/cefweb/CWebApp.cpp b/Client/cefweb/CWebApp.cpp index a6fe5397e5..dde8e11863 100644 --- a/Client/cefweb/CWebApp.cpp +++ b/Client/cefweb/CWebApp.cpp @@ -21,6 +21,13 @@ CefRefPtr CWebApp::HandleError(const SString& strError, unsi void CWebApp::OnBeforeCommandLineProcessing(const CefString& process_type, CefRefPtr command_line) { + CWebCore* pWebCore = static_cast(g_pCore->GetWebCore()); + + if (!pWebCore->GetGPUEnabled()) + command_line->AppendSwitch("disable-gpu"); + + command_line->AppendSwitch("disable-gpu-compositing"); // always disable this, causes issues with official builds + // command_line->AppendSwitch("disable-d3d11"); command_line->AppendSwitch("enable-begin-frame-scheduling"); diff --git a/Client/cefweb/CWebCore.cpp b/Client/cefweb/CWebCore.cpp index fe02e029a3..bd26c68711 100644 --- a/Client/cefweb/CWebCore.cpp +++ b/Client/cefweb/CWebCore.cpp @@ -49,10 +49,13 @@ CWebCore::~CWebCore() delete m_pXmlConfig; } -bool CWebCore::Initialise() +bool CWebCore::Initialise(bool gpuEnabled) { CefMainArgs mainArgs; void* sandboxInfo = nullptr; + + m_bGPUEnabled = gpuEnabled; + CefRefPtr app(new CWebApp); #ifdef CEF_ENABLE_SANDBOX @@ -869,3 +872,8 @@ void CWebCore::StaticFetchBlacklistFinished(const SHttpDownloadResult& result) OutputDebugLine("Updated browser blacklist!"); #endif } + +bool CWebCore::GetGPUEnabled() const noexcept +{ + return m_bGPUEnabled; +} diff --git a/Client/cefweb/CWebCore.h b/Client/cefweb/CWebCore.h index 4db4a9036c..815e4b5815 100644 --- a/Client/cefweb/CWebCore.h +++ b/Client/cefweb/CWebCore.h @@ -54,7 +54,7 @@ class CWebCore : public CWebCoreInterface public: CWebCore(); ~CWebCore(); - bool Initialise() override; + bool Initialise(bool gpuEnabled) override; CWebViewInterface* CreateWebView(unsigned int uiWidth, unsigned int uiHeight, bool bIsLocal, CWebBrowserItem* pWebBrowserRenderItem, bool bTransparent); void DestroyWebView(CWebViewInterface* pWebViewInterface); @@ -108,6 +108,8 @@ class CWebCore : public CWebCoreInterface static void StaticFetchWhitelistFinished(const SHttpDownloadResult& result); static void StaticFetchBlacklistFinished(const SHttpDownloadResult& result); + bool GetGPUEnabled() const noexcept; + private: typedef std::pair WebFilterPair; @@ -129,4 +131,7 @@ class CWebCore : public CWebCoreInterface CXMLFile* m_pXmlConfig; int m_iWhitelistRevision; int m_iBlacklistRevision; + + // Shouldn't be changed after init + bool m_bGPUEnabled; }; diff --git a/Client/cefweb/CWebView.cpp b/Client/cefweb/CWebView.cpp index ef3f016e7c..744247599f 100644 --- a/Client/cefweb/CWebView.cpp +++ b/Client/cefweb/CWebView.cpp @@ -936,10 +936,10 @@ void CWebView::OnBeforeClose(CefRefPtr browser) // // // // //////////////////////////////////////////////////////////////////// -bool CWebView::OnBeforePopup(CefRefPtr browser, CefRefPtr frame, const CefString& target_url, const CefString& target_frame_name, - CefLifeSpanHandler::WindowOpenDisposition target_disposition, bool user_gesture, const CefPopupFeatures& popupFeatures, - CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, CefRefPtr& extra_info, - bool* no_javascript_access) +bool CWebView::OnBeforePopup(CefRefPtr browser, CefRefPtr frame, int popup_id, const CefString& target_url, + const CefString& target_frame_name, CefLifeSpanHandler::WindowOpenDisposition target_disposition, bool user_gesture, + const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, + CefRefPtr& extra_info, bool* no_javascript_access) { // ATTENTION: This method is called on the IO thread diff --git a/Client/cefweb/CWebView.h b/Client/cefweb/CWebView.h index 0c9589d6c9..59cd64f381 100644 --- a/Client/cefweb/CWebView.h +++ b/Client/cefweb/CWebView.h @@ -152,10 +152,10 @@ class CWebView : public CWebViewInterface, // CefLifeSpawnHandler methods virtual void OnBeforeClose(CefRefPtr browser) override; - virtual bool OnBeforePopup(CefRefPtr browser, CefRefPtr frame, const CefString& target_url, const CefString& target_frame_name, - CefLifeSpanHandler::WindowOpenDisposition target_disposition, bool user_gesture, const CefPopupFeatures& popupFeatures, - CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, CefRefPtr& extra_info, - bool* no_javascript_access) override; + virtual bool OnBeforePopup(CefRefPtr browser, CefRefPtr frame, int popup_id, const CefString& target_url, + const CefString& target_frame_name, CefLifeSpanHandler::WindowOpenDisposition target_disposition, bool user_gesture, + const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, + CefRefPtr& extra_info, bool* no_javascript_access) override; virtual void OnAfterCreated(CefRefPtr browser) override; // CefJSDialogHandler methods diff --git a/Client/core/CClientVariables.cpp b/Client/core/CClientVariables.cpp index fb9bd3b245..85dee800fa 100644 --- a/Client/core/CClientVariables.cpp +++ b/Client/core/CClientVariables.cpp @@ -256,6 +256,7 @@ void CClientVariables::ValidateValues() ClampValue("mtavolume", 0.0f, 1.0f); ClampValue("voicevolume", 0.0f, 1.0f); ClampValue("mapalpha", 0, 255); + ClampValue("mapimage", 0, 1); } void CClientVariables::LoadDefaults() @@ -273,9 +274,6 @@ void CClientVariables::LoadDefaults() DEFAULT("host", _S("127.0.0.1")); // hostname DEFAULT("port", 22003); // port DEFAULT("password", _S("")); // password - DEFAULT("qc_host", _S("127.0.0.1")); // quick connect hostname - DEFAULT("qc_port", 22003); // quick connect port - DEFAULT("qc_password", _S("")); // quick connect password DEFAULT("debugfile", _S("")); // debug filename DEFAULT("console_pos", CVector2D(0, 0)); // console position DEFAULT("console_size", CVector2D(200, 200)); // console size @@ -313,7 +311,8 @@ void CClientVariables::LoadDefaults() DEFAULT("mastervolume", 1.0f); // master volume DEFAULT("mtavolume", 1.0f); // custom sound's volume DEFAULT("voicevolume", 1.0f); // voice chat output volume - DEFAULT("mapalpha", 155); // map alpha + DEFAULT("mapalpha", 155); // player map alpha + DEFAULT("mapimage", 0); // player map image DEFAULT("browser_speed", 1); // Browser speed DEFAULT("single_download", 0); // Single connection for downloads DEFAULT("packet_tag", 0); // Tag network packets @@ -357,7 +356,7 @@ void CClientVariables::LoadDefaults() DEFAULT("allow_discord_rpc", true); // Enable Discord Rich Presence DEFAULT("discord_rpc_share_data", false); // Consistent Rich Presence data sharing DEFAULT("discord_rpc_share_data_firsttime", false); // Display the user data sharing consent dialog box - for the first time - DEFAULT("_beta_qc_rightclick_command", _S("reconnect")); // Command to run when right clicking quick connect (beta - can be removed at any time) + DEFAULT("browser_enable_gpu", true); // Enable GPU in CEF? (allows stuff like WebGL to function) if (!Exists("locale")) { diff --git a/Client/core/CCommandFuncs.cpp b/Client/core/CCommandFuncs.cpp index a2ca37ccbd..294a58e01e 100644 --- a/Client/core/CCommandFuncs.cpp +++ b/Client/core/CCommandFuncs.cpp @@ -302,7 +302,6 @@ void CCommandFuncs::Reconnect(const char* szParameters) unsigned int uiPort; CVARS_GET("host", strHost); - CVARS_GET("nick", strNick); CVARS_GET("password", strPassword); CVARS_GET("port", uiPort); @@ -315,7 +314,7 @@ void CCommandFuncs::Reconnect(const char* szParameters) // Verify and convert the port number if (uiPort <= 0 || uiPort > 0xFFFF) { - CCore::GetSingleton().GetConsole()->Print(_("connect: Bad port number")); + CCore::GetSingleton().GetConsole()->Print(_("reconnect: Bad port number")); return; } @@ -330,16 +329,16 @@ void CCommandFuncs::Reconnect(const char* szParameters) // Start the connect if (CCore::GetSingleton().GetConnectManager()->Reconnect(strHost.c_str(), usPort, strPassword.c_str(), false)) { - CCore::GetSingleton().GetConsole()->Printf(_("connect: Connecting to %s:%u..."), strHost.c_str(), usPort); + CCore::GetSingleton().GetConsole()->Printf(_("reconnect: Reconnecting to %s:%u..."), strHost.c_str(), usPort); } else { - CCore::GetSingleton().GetConsole()->Printf(_("connect: could not connect to %s:%u!"), strHost.c_str(), usPort); + CCore::GetSingleton().GetConsole()->Printf(_("reconnect: could not connect to %s:%u!"), strHost.c_str(), usPort); } } else { - CCore::GetSingleton().GetConsole()->Print("connect: Failed to unload current mod"); + CCore::GetSingleton().GetConsole()->Print("reconnect: Failed to unload current mod"); } } diff --git a/Client/core/CConnectManager.cpp b/Client/core/CConnectManager.cpp index d53cdc8934..4c15524d7c 100644 --- a/Client/core/CConnectManager.cpp +++ b/Client/core/CConnectManager.cpp @@ -145,6 +145,8 @@ bool CConnectManager::Connect(const char* szHost, unsigned short usPort, const c // Display the status box SString strBuffer(_("Connecting to %s:%u ..."), m_strHost.c_str(), m_usPort); + if (m_bReconnect) + strBuffer = SString(_("Reconnecting to %s:%u ..."), m_strHost.c_str(), m_usPort); CCore::GetSingleton().ShowMessageBox(_("CONNECTING"), strBuffer, MB_BUTTON_CANCEL | MB_ICON_INFO, m_pOnCancelClick); WriteDebugEvent(SString("Connecting to %s:%u ...", m_strHost.c_str(), m_usPort)); diff --git a/Client/core/CConsole.h b/Client/core/CConsole.h index 5899fa645d..677e1133ff 100644 --- a/Client/core/CConsole.h +++ b/Client/core/CConsole.h @@ -41,7 +41,6 @@ class CConsole : public CConsoleInterface bool IsInputActive(); void ActivateInput(); - void HandleTextAccepted(bool bHandled); void GetCommandInfo(const std::string& strIn, std::string& strCmdOut, std::string& strCmdLineOut); void ResetHistoryChanges(); diff --git a/Client/core/CCore.cpp b/Client/core/CCore.cpp index b9a2391f46..12e8cf81d5 100644 --- a/Client/core/CCore.cpp +++ b/Client/core/CCore.cpp @@ -1155,8 +1155,12 @@ CWebCoreInterface* CCore::GetWebCore() { if (m_pWebCore == nullptr) { + bool gpuEnabled; + auto cvars = g_pCore->GetCVars(); + cvars->Get("browser_enable_gpu", gpuEnabled); + m_pWebCore = CreateModule(m_WebCoreModule, "CefWeb", "cefweb", "InitWebCoreInterface", this); - m_pWebCore->Initialise(); + m_pWebCore->Initialise(gpuEnabled); } return m_pWebCore; } diff --git a/Client/core/CGUI.cpp b/Client/core/CGUI.cpp index c4a2729d7a..6273536347 100644 --- a/Client/core/CGUI.cpp +++ b/Client/core/CGUI.cpp @@ -56,9 +56,15 @@ CLocalGUI::~CLocalGUI() void CLocalGUI::SetSkin(const char* szName) { + CVector2D consolePos, consoleSize; + bool guiWasLoaded = m_pMainMenu != NULL; if (guiWasLoaded) + { + consolePos = m_pConsole->GetPosition(); + consoleSize = m_pConsole->GetSize(); DestroyWindows(); + } std::string error; @@ -93,7 +99,11 @@ void CLocalGUI::SetSkin(const char* szName) m_LastSettingsRevision = cvars->GetRevision(); if (guiWasLoaded) + { CreateWindows(guiWasLoaded); + m_pConsole->SetPosition(consolePos); + m_pConsole->SetSize(consoleSize); + } if (CCore::GetSingleton().GetConsole() && !error.empty()) CCore::GetSingleton().GetConsole()->Echo(error.c_str()); @@ -104,8 +114,8 @@ void CLocalGUI::ChangeLocale(const char* szName) bool guiWasLoaded = m_pMainMenu != NULL; assert(guiWasLoaded); - CVector2D vPos = m_pConsole->GetPosition(); - CVector2D vSize = m_pConsole->GetSize(); + CVector2D consolePos = m_pConsole->GetPosition(); + CVector2D consoleSize = m_pConsole->GetSize(); if (guiWasLoaded) DestroyWindows(); @@ -119,12 +129,8 @@ void CLocalGUI::ChangeLocale(const char* szName) if (guiWasLoaded) { CreateWindows(guiWasLoaded); - - if (m_pConsole != nullptr) - { - m_pConsole->SetPosition(vPos); - m_pConsole->SetSize(vSize); - } + m_pConsole->SetPosition(consolePos); + m_pConsole->SetSize(consoleSize); } } diff --git a/Client/core/CMainMenu.cpp b/Client/core/CMainMenu.cpp index 7d1c2740a8..1ef82a75c6 100644 --- a/Client/core/CMainMenu.cpp +++ b/Client/core/CMainMenu.cpp @@ -912,17 +912,13 @@ bool CMainMenu::OnQuickConnectButtonClick(CGUIElement* pElement, bool left) if (m_ucFade != FADE_VISIBLE) return false; - // If we're right clicking, execute special command - if (!left) + if (left) + g_pCore->GetCommands()->Execute("reconnect", ""); + else { - std::string command; - CVARS_GET("_beta_qc_rightclick_command", command); - g_pCore->GetCommands()->Execute(command.data()); - return true; + m_ServerBrowser.SetVisible(true); + m_ServerBrowser.OnQuickConnectButtonClick(); } - - m_ServerBrowser.SetVisible(true); - m_ServerBrowser.OnQuickConnectButtonClick(); return true; } diff --git a/Client/core/CNickGen.cpp b/Client/core/CNickGen.cpp index a4cb2738e2..f877588539 100644 --- a/Client/core/CNickGen.cpp +++ b/Client/core/CNickGen.cpp @@ -8,10 +8,10 @@ *****************************************************************************/ #include "StdInc.h" -#include "time.h" +#include // These words are of a maximum length of 10 characters, capitalized, and stripped of whitespace -const char* const CNickGen::m_szAdjectives[] = { +const char* const szAdjectives[] = { "Aback", "Abaft", "Abandoned", "Abashed", "Aberrant", "Abhorrent", "Abiding", "Abject", "Ablaze", "Able", "Abnormal", "Aboard", "Aboriginal", "Abortive", "Abounding", "Abrasive", "Abrupt", "Absent", "Absorbed", "Absorbing", "Abstracted", "Absurd", "Abundant", "Abusive", "Acceptable", "Accessible", "Accidental", "Accurate", "Acid", "Acidic", "Acoustic", "Acrid", "Actually", @@ -109,7 +109,7 @@ const char* const CNickGen::m_szAdjectives[] = { "Worried", "Worthless", "Wrathful", "Wretched", "Wrong", "Wry", }; -const char* const CNickGen::m_szNouns[] = { +const char* const szNouns[] = { "Aardvark", "Buffalo", "Alligator", "Ant", "Anteater", "Antelope", "Ape", "Armadillo", "Donkey", "Baboon", "Badger", "Barracuda", "Bat", "Bear", "Beaver", "Bee", "Bison", "Boar", "Bush", "Butterfly", "Camel", "Calf", "Cat", "Kitten", "Cattle", "Chamois", "Cheetah", "Chicken", "Chick", "Chimpanzee", "Infant", "Empress", "Troop", @@ -196,10 +196,18 @@ const char* const CNickGen::m_szNouns[] = { "Vampire", "Parasite", "Tramp", "Bum", "Hobo", "Hitchhiker", "Deadbeat", "Acrobat", }; +constexpr auto numAdjectives = std::size(szAdjectives); +constexpr auto numNouns = std::size(szNouns); +constexpr auto maxNum = 100; + SString CNickGen::GetRandomNickname() { - srand((unsigned int)time(NULL)); - int iAdjective = rand() % NICKGEN_NUM_ADJECTIVES; - int iNoun = rand() % NICKGEN_NUM_NOUNS; - return SString("%s%s%i", m_szAdjectives[iAdjective], m_szNouns[iNoun], rand() % 100); + std::random_device rd; + std::mt19937 gen(rd()); + + std::uniform_int_distribution adjectiveDist(0, numAdjectives - 1); + std::uniform_int_distribution nounDist(0, numNouns - 1); + std::uniform_int_distribution numDist(0, maxNum); + + return SString("%s%s%i", szAdjectives[adjectiveDist(gen)], szNouns[nounDist(gen)], numDist(gen)); } diff --git a/Client/core/CNickGen.h b/Client/core/CNickGen.h index b98254f01b..86a3699072 100644 --- a/Client/core/CNickGen.h +++ b/Client/core/CNickGen.h @@ -9,13 +9,8 @@ #pragma once -#define NICKGEN_NUM_ADJECTIVES 1048 -#define NICKGEN_NUM_NOUNS 934 - class CNickGen { public: - static const char* const m_szAdjectives[NICKGEN_NUM_ADJECTIVES]; - static const char* const m_szNouns[NICKGEN_NUM_NOUNS]; static SString GetRandomNickname(); }; diff --git a/Client/core/CQueryReceiver.cpp b/Client/core/CQueryReceiver.cpp index 559691bcb3..4d1e516de9 100644 --- a/Client/core/CQueryReceiver.cpp +++ b/Client/core/CQueryReceiver.cpp @@ -183,7 +183,7 @@ SQueryInfo CQueryReceiver::GetServerResponse() // Recover server ping status if present const SString strPingStatus = strBuildNumber.Right(strBuildNumber.length() - strlen(strBuildNumber) - 1); - CCore::GetSingleton().GetNetwork()->UpdatePingStatus(*strPingStatus, info.players, info.isStatusVerified); + CCore::GetSingleton().GetNetwork()->UpdatePingStatus(strPingStatus.c_str(), strPingStatus.length(), info.players, info.isStatusVerified); // Recover server http port if present const SString strNetRoute = strPingStatus.Right(strPingStatus.length() - strlen(strPingStatus) - 1); diff --git a/Client/core/CSettings.cpp b/Client/core/CSettings.cpp index 847735a891..6792bac450 100644 --- a/Client/core/CSettings.cpp +++ b/Client/core/CSettings.cpp @@ -376,7 +376,7 @@ void CSettings::CreateGUI() m_pButtonGenerateNickIcon->SetProperty("DistributeCapturedInputs", "True"); m_pSavePasswords = reinterpret_cast(pManager->CreateCheckBox(pTabMultiplayer, _("Save server passwords"), true)); - m_pSavePasswords->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 50.0f)); + m_pSavePasswords->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 35.0f)); m_pSavePasswords->GetPosition(vecTemp, false); m_pSavePasswords->AutoSize(NULL, 20.0f); @@ -411,11 +411,13 @@ void CSettings::CreateGUI() m_pCheckBoxCustomizedSAFiles->AutoSize(NULL, 20.0f); m_pMapRenderingLabel = reinterpret_cast(pManager->CreateLabel(pTabMultiplayer, _("Map rendering options"))); - m_pMapRenderingLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 29.0f)); + m_pMapRenderingLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 30.0f)); m_pMapRenderingLabel->GetPosition(vecTemp, false); m_pMapRenderingLabel->SetFont("default-bold-small"); m_pMapRenderingLabel->AutoSize(); + vecTemp.fX += 5.0f; + m_pMapAlphaLabel = reinterpret_cast(pManager->CreateLabel(pTabMultiplayer, _("Opacity:"))); m_pMapAlphaLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 24.0f)); m_pMapAlphaLabel->GetPosition(vecTemp, false); @@ -433,6 +435,20 @@ void CSettings::CreateGUI() m_pMapAlphaValueLabel->GetPosition(vecTemp, false); m_pMapAlphaValueLabel->AutoSize("100%"); + m_pMapAlphaLabel->GetPosition(vecTemp, false); + vecTemp.fY += 24.0f; + + m_pPlayerMapImageLabel = reinterpret_cast(pManager->CreateLabel(pTabMultiplayer, _("Image resolution:"))); + m_pPlayerMapImageLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 2.0f)); + m_pPlayerMapImageLabel->AutoSize(); + + m_pPlayerMapImageCombo = reinterpret_cast(pManager->CreateComboBox(pTabMultiplayer, "")); + m_pPlayerMapImageCombo->SetPosition(CVector2D(vecTemp.fX + fIndentX + 5.0f, vecTemp.fY - 1.0f)); + m_pPlayerMapImageCombo->SetSize(CVector2D(170.f, 95.0f)); + m_pPlayerMapImageCombo->AddItem(_("1024 x 1024 (Default)")); // index 0 + m_pPlayerMapImageCombo->AddItem(_("2048 x 2048")); // index 1 + m_pPlayerMapImageCombo->SetReadOnly(true); + /** * Audio tab **/ @@ -625,16 +641,13 @@ void CSettings::CreateGUI() * Video tab **/ fIndentX = pManager->CGUI_GetMaxTextExtent("default-normal", _("Resolution:"), _("FOV:"), _("Draw Distance:"), _("Brightness:"), _("FX Quality:"), - _("Anisotropic filtering:"), _("Anti-aliasing:"), _("Aspect Ratio:"), _("Opacity:")); + _("Anisotropic filtering:"), _("Anti-aliasing:"), _("Aspect Ratio:")); - m_pVideoGeneralLabel = reinterpret_cast(pManager->CreateLabel(pTabVideo, _("General"))); - m_pVideoGeneralLabel->SetPosition(CVector2D(11, 13)); - m_pVideoGeneralLabel->GetPosition(vecTemp, false); - m_pVideoGeneralLabel->AutoSize(NULL, 3.0f); - m_pVideoGeneralLabel->SetFont("default-bold-small"); + vecTemp.fX = 11.0f; + vecTemp.fY = 13.0f; m_pVideoResolutionLabel = reinterpret_cast(pManager->CreateLabel(pTabVideo, _("Resolution:"))); - m_pVideoResolutionLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 26.0f)); + m_pVideoResolutionLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY)); m_pVideoResolutionLabel->GetPosition(vecTemp, false); m_pVideoResolutionLabel->AutoSize(); @@ -833,6 +846,10 @@ void CSettings::CreateGUI() m_pCheckBoxBlur->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 130.0f)); m_pCheckBoxBlur->AutoSize(NULL, 20.0f); + m_pCheckBoxCoronaReflections = reinterpret_cast(pManager->CreateCheckBox(pTabVideo, _("Corona rain reflections"), true)); + m_pCheckBoxCoronaReflections->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 150.0f)); + m_pCheckBoxCoronaReflections->AutoSize(nullptr, 20.0f); + float fPosY = vecTemp.fY; m_pCheckBoxMinimize = reinterpret_cast(pManager->CreateCheckBox(pTabVideo, _("Full Screen Minimize"), true)); m_pCheckBoxMinimize->SetPosition(CVector2D(vecTemp.fX + 245.0f, fPosY + 30.0f)); @@ -878,10 +895,6 @@ void CSettings::CreateGUI() m_pCheckBoxHighDetailPeds->SetPosition(CVector2D(vecTemp.fX + 245.0f, fPosY + 110.0f)); m_pCheckBoxHighDetailPeds->AutoSize(NULL, 20.0f); - m_pCheckBoxCoronaReflections = reinterpret_cast(pManager->CreateCheckBox(pTabVideo, _("Corona rain reflections"), true)); - m_pCheckBoxCoronaReflections->SetPosition(CVector2D(vecTemp.fX + 245.0f, fPosY + 130.0f)); - m_pCheckBoxCoronaReflections->AutoSize(NULL, 20.0f); - vecTemp.fY += 10; m_pTabs->GetSize(vecTemp); @@ -917,6 +930,10 @@ void CSettings::CreateGUI() m_pCheckBoxRemoteJavascript->GetPosition(vecTemp); m_pCheckBoxRemoteJavascript->AutoSize(NULL, 20.0f); + m_pCheckBoxBrowserGPUEnabled = reinterpret_cast(pManager->CreateCheckBox(m_pTabBrowser, _("Enable GPU rendering"), true)); + m_pCheckBoxBrowserGPUEnabled->SetPosition(CVector2D(vecTemp.fX + 300.0f, vecTemp.fY - 25.0f)); + m_pCheckBoxBrowserGPUEnabled->AutoSize(NULL, 20.0f); + m_pLabelBrowserCustomBlacklist = reinterpret_cast(pManager->CreateLabel(m_pTabBrowser, _("Custom blacklist"))); m_pLabelBrowserCustomBlacklist->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 30.0f)); m_pLabelBrowserCustomBlacklist->GetPosition(vecTemp); @@ -1006,6 +1023,7 @@ void CSettings::CreateGUI() 5.0f; vecTemp.fX += 10.0f; + // Fast clothes loading m_pFastClothesLabel = reinterpret_cast(pManager->CreateLabel(pTabAdvanced, _("Fast CJ clothes loading:"))); m_pFastClothesLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY)); @@ -1234,7 +1252,7 @@ void CSettings::CreateGUI() vecTemp.fX -= fComboWidth + 15; // Description label - vecTemp.fY = 354 + 10; + vecTemp.fY += 15.0f; m_pAdvancedSettingDescriptionLabel = reinterpret_cast(pManager->CreateLabel(pTabAdvanced, "")); m_pAdvancedSettingDescriptionLabel->SetPosition(CVector2D(vecTemp.fX + 10.f, vecTemp.fY)); m_pAdvancedSettingDescriptionLabel->SetFont("default-bold-small"); @@ -1625,12 +1643,17 @@ void CSettings::UpdateVideoTab() float fPos = SharedUtil::Unlerp(g_pCore->GetMinStreamingMemory(), uiStreamingMemory, g_pCore->GetMaxStreamingMemory()); m_pStreamingMemory->SetScrollPosition(fPos); + // Player map alpha int iVar = 0; CVARS_GET("mapalpha", iVar); int iAlphaPercent = ceil(((float)Clamp(0, iVar, 255) / 255) * 100); m_pMapAlphaValueLabel->SetText(SString("%i%%", iAlphaPercent).c_str()); float sbPos = (float)iAlphaPercent / 100.0f; m_pMapAlpha->SetScrollPosition(sbPos); + + // Player map image + CVARS_GET("mapimage", iVar); + m_pPlayerMapImageCombo->SetSelectedItemByIndex(iVar); } // @@ -1847,7 +1870,9 @@ bool CSettings::OnVideoDefaultClick(CGUIElement* pElement) CVARS_SET("streaming_memory", g_pCore->GetMaxStreamingMemory()); + // Player map defaults CVARS_SET("mapalpha", 155); + CVARS_SET("mapimage", 0); // Display restart required message if required bool bIsAntiAliasingChanged = gameSettings->GetAntiAliasing() != m_pComboAntiAliasing->GetSelectedItemIndex(); @@ -3287,6 +3312,8 @@ void CSettings::LoadData() m_pCheckBoxRemoteBrowser->SetSelected(bVar); CVARS_GET("browser_remote_javascript", bVar); m_pCheckBoxRemoteJavascript->SetSelected(bVar); + CVARS_GET("browser_enable_gpu", bVar); + m_pCheckBoxBrowserGPUEnabled->SetSelected(bVar); ReloadBrowserLists(); } @@ -3603,12 +3630,16 @@ void CSettings::SaveData() CVARS_SET("update_auto_install", iSelected); } - // Map alpha + // Player map alpha SString sText = m_pMapAlphaValueLabel->GetText(); - float fMapAlpha = ((atof(sText.substr(0, sText.length() - 1).c_str())) / 100) * 255; CVARS_SET("mapalpha", fMapAlpha); + // Player map image + int selectedComboIndex = m_pPlayerMapImageCombo->GetSelectedItemIndex(); + if (selectedComboIndex != -1) + CVARS_SET("mapimage", selectedComboIndex); + // Language CGUIListItem* pItem = m_pInterfaceLanguageSelector->GetSelectedItem(); if (pItem) @@ -3711,6 +3742,13 @@ void CSettings::SaveData() bBrowserSettingChanged = true; } + bool bBrowserGPUEnabled = false; + CVARS_GET("browser_enable_gpu", bBrowserGPUEnabled); + + bool bBrowserGPUSetting = m_pCheckBoxBrowserGPUEnabled->GetSelected(); + bool bBrowserGPUSettingChanged = (bBrowserGPUSetting != bBrowserGPUEnabled); + CVARS_SET("browser_enable_gpu", bBrowserGPUSetting); + // Ensure CVARS ranges ok CClientVariables::GetSingleton().ValidateValues(); @@ -3720,7 +3758,7 @@ void CSettings::SaveData() gameSettings->Save(); // Ask to restart? - if (bIsVideoModeChanged || bIsAntiAliasingChanged || bIsCustomizedSAFilesChanged || processsDPIAwareChanged) + if (bIsVideoModeChanged || bIsAntiAliasingChanged || bIsCustomizedSAFilesChanged || processsDPIAwareChanged || bBrowserGPUSettingChanged) ShowRestartQuestion(); else if (CModManager::GetSingleton().IsLoaded() && bBrowserSettingChanged) ShowDisconnectQuestion(); diff --git a/Client/core/CSettings.h b/Client/core/CSettings.h index bfeec87c44..9c288557e6 100644 --- a/Client/core/CSettings.h +++ b/Client/core/CSettings.h @@ -196,6 +196,8 @@ class CSettings CGUIComboBox* m_pFullscreenStyleCombo; CGUILabel* m_pPriorityLabel; CGUIComboBox* m_pPriorityCombo; + CGUILabel* m_pPlayerMapImageLabel; + CGUIComboBox* m_pPlayerMapImageCombo; CGUILabel* m_pFastClothesLabel; CGUIComboBox* m_pFastClothesCombo; CGUILabel* m_pAudioGeneralLabel; @@ -338,6 +340,7 @@ class CSettings CGUIButton* m_pButtonBrowserWhitelistAdd; CGUIGridList* m_pGridBrowserWhitelist; CGUIButton* m_pButtonBrowserWhitelistRemove; + CGUICheckBox* m_pCheckBoxBrowserGPUEnabled; bool m_bBrowserListsChanged; bool m_bBrowserListsLoadEnabled; diff --git a/Client/core/ServerBrowser/CServerBrowser.cpp b/Client/core/ServerBrowser/CServerBrowser.cpp index 1246276b70..2ea47cafdf 100644 --- a/Client/core/ServerBrowser/CServerBrowser.cpp +++ b/Client/core/ServerBrowser/CServerBrowser.cpp @@ -924,30 +924,6 @@ void CServerBrowser::CreateHistoryList() } } - // If we had no history, import it from our old quick connect - if (bEmpty) - { - std::string strAddress; - CVARS_GET("qc_host", strAddress); - - if (!strAddress.empty()) - { - std::string strPort; - CVARS_GET("qc_port", strPort); - - if (!strPort.empty()) - { - in_addr Address; - if (CServerListItem::Parse(strAddress.c_str(), Address)) - { - m_ServersHistory.AddUnique(Address, atoi(strPort.c_str())); - CreateHistoryList(); // Restart with our new list. - return; - } - } - } - } - m_ServersHistory.Refresh(); } @@ -2030,21 +2006,6 @@ std::string CServerBrowser::GetServerPassword(const std::string& strHost) } } } - - // If the server is the one from old quick connect, try importing the password from that - std::string strQCEndpoint; - CVARS_GET("qc_host", strQCEndpoint); - - std::string strTemp; - CVARS_GET("qc_port", strTemp); - - strQCEndpoint = strQCEndpoint + ":" + strTemp; - if (strQCEndpoint == strHost) - { - CVARS_GET("qc_password", strTemp); - return strTemp; - } - return ""; } diff --git a/Client/game_sa/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp index 50ae14bb3c..7cd8e887ae 100644 --- a/Client/game_sa/CBuildingsPoolSA.cpp +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -53,6 +53,13 @@ CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint1 if (!HasFreeBuildingSlot()) return nullptr; + auto modelInfo = pGame->GetModelInfo(modelId); + + // Change the properties group to force dynamic models to be created as buildings instead of dummies + auto prevGroup = modelInfo->GetObjectPropertiesGroup(); + if (prevGroup != MODEL_PROPERTIES_GROUP_STATIC) + modelInfo->SetObjectPropertiesGroup(MODEL_PROPERTIES_GROUP_STATIC); + // Load building SFileObjectInstance instance; instance.modelID = modelId; @@ -70,9 +77,12 @@ CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint1 pBuilding->m_pLod = nullptr; pBuilding->m_iplIndex = 0; + // Restore changed properties group + if (prevGroup != MODEL_PROPERTIES_GROUP_STATIC) + modelInfo->SetObjectPropertiesGroup(prevGroup); + // Always stream model collosion // TODO We can setup collison bounding box and use GTA streamer for it - auto modelInfo = pGame->GetModelInfo(modelId); modelInfo->AddColRef(); // Add building in world diff --git a/Client/game_sa/CEntitySA.cpp b/Client/game_sa/CEntitySA.cpp index 02a9f00380..9053910737 100644 --- a/Client/game_sa/CEntitySA.cpp +++ b/Client/game_sa/CEntitySA.cpp @@ -679,7 +679,7 @@ bool CEntitySA::GetBonePosition(eBone boneId, CVector& position) return false; const RwV3d& pos = rwBoneMatrix->pos; - position = {pos.x, pos.y, pos.z}; + position = CVector(pos.x, pos.y, pos.z); return true; } diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 07ac611c09..c3eafa78d6 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -71,177 +71,202 @@ unsigned int OBJECTDYNAMICINFO_MAX = *(uint32_t*)0x59FB4C != 0x90909090 ? *(uint */ CGameSA::CGameSA() { - pGame = this; + try + { + pGame = this; - // Find the game version and initialize m_eGameVersion so GetGameVersion() will return the correct value - FindGameVersion(); + // Find the game version and initialize m_eGameVersion so GetGameVersion() will return the correct value + FindGameVersion(); - m_bAsyncScriptEnabled = false; - m_bAsyncScriptForced = false; - m_bASyncLoadingSuspended = false; - m_iCheckStatus = 0; + m_bAsyncScriptEnabled = false; + m_bAsyncScriptForced = false; + m_bASyncLoadingSuspended = false; + m_iCheckStatus = 0; - const unsigned int modelInfoMax = GetCountOfAllFileIDs(); - ModelInfo = new CModelInfoSA[modelInfoMax]; - ObjectGroupsInfo = new CObjectGroupPhysicalPropertiesSA[OBJECTDYNAMICINFO_MAX]; + const unsigned int modelInfoMax = GetCountOfAllFileIDs(); + ModelInfo = new CModelInfoSA[modelInfoMax]; + ObjectGroupsInfo = new CObjectGroupPhysicalPropertiesSA[OBJECTDYNAMICINFO_MAX]; - SetInitialVirtualProtect(); + SetInitialVirtualProtect(); - // Set the model ids for all the CModelInfoSA instances - for (unsigned int i = 0; i < modelInfoMax; i++) - { - ModelInfo[i].SetModelID(i); - } + // Set the model ids for all the CModelInfoSA instances + for (unsigned int i = 0; i < modelInfoMax; i++) + { + ModelInfo[i].SetModelID(i); + } - // Prepare all object dynamic infos for CObjectGroupPhysicalPropertiesSA instances - for (unsigned int i = 0; i < OBJECTDYNAMICINFO_MAX; i++) - { - ObjectGroupsInfo[i].SetGroup(i); - } + // Prepare all object dynamic infos for CObjectGroupPhysicalPropertiesSA instances + for (unsigned int i = 0; i < OBJECTDYNAMICINFO_MAX; i++) + { + ObjectGroupsInfo[i].SetGroup(i); + } - m_pAudioEngine = new CAudioEngineSA((CAudioEngineSAInterface*)CLASS_CAudioEngine); - m_pAEAudioHardware = new CAEAudioHardwareSA((CAEAudioHardwareSAInterface*)CLASS_CAEAudioHardware); - m_pAESoundManager = new CAESoundManagerSA((CAESoundManagerSAInterface*)CLASS_CAESoundManager); - m_pAudioContainer = new CAudioContainerSA(); - m_pWorld = new CWorldSA(); - m_pPools = new CPoolsSA(); - m_pClock = new CClockSA(); - m_pRadar = new CRadarSA(); - m_pCamera = new CCameraSA((CCameraSAInterface*)CLASS_CCamera); - m_pCoronas = new CCoronasSA(); - m_pCheckpoints = new CCheckpointsSA(); - m_pPickups = new CPickupsSA(); - m_pExplosionManager = new CExplosionManagerSA(); - m_pHud = new CHudSA(); - m_pFireManager = new CFireManagerSA(); - m_p3DMarkers = new C3DMarkersSA(); - m_pPad = new CPadSA((CPadSAInterface*)CLASS_CPad); - m_pCAERadioTrackManager = new CAERadioTrackManagerSA(); - m_pWeather = new CWeatherSA(); - m_pStats = new CStatsSA(); - m_pTaskManagementSystem = new CTaskManagementSystemSA(); - m_pSettings = new CSettingsSA(); - m_pCarEnterExit = new CCarEnterExitSA(); - m_pControllerConfigManager = new CControllerConfigManagerSA(); - m_pProjectileInfo = new CProjectileInfoSA(); - m_pRenderWare = new CRenderWareSA(); - m_pHandlingManager = new CHandlingManagerSA(); - m_pEventList = new CEventListSA(); - m_pGarages = new CGaragesSA((CGaragesSAInterface*)CLASS_CGarages); - m_pTasks = new CTasksSA((CTaskManagementSystemSA*)m_pTaskManagementSystem); - m_pAnimManager = new CAnimManagerSA; - m_pStreaming = new CStreamingSA; - m_pVisibilityPlugins = new CVisibilityPluginsSA; - m_pKeyGen = new CKeyGenSA; - m_pRopes = new CRopesSA; - m_pFx = new CFxSA((CFxSAInterface*)CLASS_CFx); - m_pFxManager = new CFxManagerSA((CFxManagerSAInterface*)CLASS_CFxManager); - m_pWaterManager = new CWaterManagerSA(); - m_pWeaponStatsManager = new CWeaponStatManagerSA(); - m_pPointLights = new CPointLightsSA(); - m_collisionStore = new CColStoreSA(); - m_pIplStore = new CIplStoreSA(); - m_pCoverManager = new CCoverManagerSA(); - m_pPlantManager = new CPlantManagerSA(); - m_pBuildingRemoval = new CBuildingRemovalSA(); - - m_pRenderer = std::make_unique(); - - // Normal weapon types (WEAPONSKILL_STD) - for (int i = 0; i < NUM_WeaponInfosStdSkill; i++) - { - eWeaponType weaponType = (eWeaponType)(WEAPONTYPE_PISTOL + i); - WeaponInfos[i] = new CWeaponInfoSA((CWeaponInfoSAInterface*)(ARRAY_WeaponInfo + i * CLASSSIZE_WeaponInfo), weaponType); - m_pWeaponStatsManager->CreateWeaponStat(WeaponInfos[i], (eWeaponType)(weaponType - WEAPONTYPE_PISTOL), WEAPONSKILL_STD); - } + m_pAudioEngine = new CAudioEngineSA((CAudioEngineSAInterface*)CLASS_CAudioEngine); + m_pAEAudioHardware = new CAEAudioHardwareSA((CAEAudioHardwareSAInterface*)CLASS_CAEAudioHardware); + m_pAESoundManager = new CAESoundManagerSA((CAESoundManagerSAInterface*)CLASS_CAESoundManager); + m_pAudioContainer = new CAudioContainerSA(); + m_pWorld = new CWorldSA(); + m_Pools = std::make_unique(); + m_pClock = new CClockSA(); + m_pRadar = new CRadarSA(); + m_pCamera = new CCameraSA((CCameraSAInterface*)CLASS_CCamera); + m_pCoronas = new CCoronasSA(); + m_pCheckpoints = new CCheckpointsSA(); + m_pPickups = new CPickupsSA(); + m_pExplosionManager = new CExplosionManagerSA(); + m_pHud = new CHudSA(); + m_pFireManager = new CFireManagerSA(); + m_p3DMarkers = new C3DMarkersSA(); + m_pPad = new CPadSA((CPadSAInterface*)CLASS_CPad); + m_pCAERadioTrackManager = new CAERadioTrackManagerSA(); + m_pWeather = new CWeatherSA(); + m_pStats = new CStatsSA(); + m_pTaskManagementSystem = new CTaskManagementSystemSA(); + m_pSettings = new CSettingsSA(); + m_pCarEnterExit = new CCarEnterExitSA(); + m_pControllerConfigManager = new CControllerConfigManagerSA(); + m_pProjectileInfo = new CProjectileInfoSA(); + m_pRenderWare = new CRenderWareSA(); + m_HandlingManager = std::make_unique(); + m_pEventList = new CEventListSA(); + m_pGarages = new CGaragesSA((CGaragesSAInterface*)CLASS_CGarages); + m_pTasks = new CTasksSA((CTaskManagementSystemSA*)m_pTaskManagementSystem); + m_pAnimManager = new CAnimManagerSA; + m_pStreaming = new CStreamingSA; + m_pVisibilityPlugins = new CVisibilityPluginsSA; + m_pKeyGen = new CKeyGenSA; + m_pRopes = new CRopesSA; + m_pFx = new CFxSA((CFxSAInterface*)CLASS_CFx); + m_pFxManager = new CFxManagerSA((CFxManagerSAInterface*)CLASS_CFxManager); + m_pWaterManager = new CWaterManagerSA(); + m_pWeaponStatsManager = new CWeaponStatManagerSA(); + m_pPointLights = new CPointLightsSA(); + m_collisionStore = new CColStoreSA(); + m_pIplStore = new CIplStoreSA(); + m_pCoverManager = new CCoverManagerSA(); + m_pPlantManager = new CPlantManagerSA(); + m_pBuildingRemoval = new CBuildingRemovalSA(); + + m_pRenderer = std::make_unique(); + + // Normal weapon types (WEAPONSKILL_STD) + for (int i = 0; i < NUM_WeaponInfosStdSkill; i++) + { + eWeaponType weaponType = (eWeaponType)(WEAPONTYPE_PISTOL + i); + WeaponInfos[i] = new CWeaponInfoSA((CWeaponInfoSAInterface*)(ARRAY_WeaponInfo + i * CLASSSIZE_WeaponInfo), weaponType); + m_pWeaponStatsManager->CreateWeaponStat(WeaponInfos[i], (eWeaponType)(weaponType - WEAPONTYPE_PISTOL), WEAPONSKILL_STD); + } - // Extra weapon types for skills (WEAPONSKILL_POOR,WEAPONSKILL_PRO,WEAPONSKILL_SPECIAL) - int index; - eWeaponSkill weaponSkill = eWeaponSkill::WEAPONSKILL_POOR; - for (int skill = 0; skill < 3; skill++) - { - // STD is created first, then it creates "extra weapon types" (poor, pro, special?) but in the enum 1 = STD which meant the STD weapon skill contained - // pro info - if (skill >= 1) + // Extra weapon types for skills (WEAPONSKILL_POOR,WEAPONSKILL_PRO,WEAPONSKILL_SPECIAL) + int index; + eWeaponSkill weaponSkill = eWeaponSkill::WEAPONSKILL_POOR; + for (int skill = 0; skill < 3; skill++) { - if (skill == 1) + // STD is created first, then it creates "extra weapon types" (poor, pro, special?) but in the enum 1 = STD which meant the STD weapon skill + // contained pro info + if (skill >= 1) { - weaponSkill = eWeaponSkill::WEAPONSKILL_PRO; + if (skill == 1) + { + weaponSkill = eWeaponSkill::WEAPONSKILL_PRO; + } + if (skill == 2) + { + weaponSkill = eWeaponSkill::WEAPONSKILL_SPECIAL; + } } - if (skill == 2) + for (int i = 0; i < NUM_WeaponInfosOtherSkill; i++) { - weaponSkill = eWeaponSkill::WEAPONSKILL_SPECIAL; + eWeaponType weaponType = (eWeaponType)(WEAPONTYPE_PISTOL + i); + index = NUM_WeaponInfosStdSkill + skill * NUM_WeaponInfosOtherSkill + i; + WeaponInfos[index] = new CWeaponInfoSA((CWeaponInfoSAInterface*)(ARRAY_WeaponInfo + index * CLASSSIZE_WeaponInfo), weaponType); + m_pWeaponStatsManager->CreateWeaponStat(WeaponInfos[index], weaponType, weaponSkill); } } - for (int i = 0; i < NUM_WeaponInfosOtherSkill; i++) - { - eWeaponType weaponType = (eWeaponType)(WEAPONTYPE_PISTOL + i); - index = NUM_WeaponInfosStdSkill + skill * NUM_WeaponInfosOtherSkill + i; - WeaponInfos[index] = new CWeaponInfoSA((CWeaponInfoSAInterface*)(ARRAY_WeaponInfo + index * CLASSSIZE_WeaponInfo), weaponType); - m_pWeaponStatsManager->CreateWeaponStat(WeaponInfos[index], weaponType, weaponSkill); - } - } - m_pPlayerInfo = new CPlayerInfoSA((CPlayerInfoSAInterface*)CLASS_CPlayerInfo); - - // Init cheat name => address map - m_Cheats[CHEAT_HOVERINGCARS] = new SCheatSA((BYTE*)VAR_HoveringCarsEnabled); - m_Cheats[CHEAT_FLYINGCARS] = new SCheatSA((BYTE*)VAR_FlyingCarsEnabled); - m_Cheats[CHEAT_EXTRABUNNYHOP] = new SCheatSA((BYTE*)VAR_ExtraBunnyhopEnabled); - m_Cheats[CHEAT_EXTRAJUMP] = new SCheatSA((BYTE*)VAR_ExtraJumpEnabled); - - // New cheats for Anticheat - m_Cheats[CHEAT_TANKMODE] = new SCheatSA((BYTE*)VAR_TankModeEnabled, false); - m_Cheats[CHEAT_NORELOAD] = new SCheatSA((BYTE*)VAR_NoReloadEnabled, false); - m_Cheats[CHEAT_PERFECTHANDLING] = new SCheatSA((BYTE*)VAR_PerfectHandling, false); - m_Cheats[CHEAT_ALLCARSHAVENITRO] = new SCheatSA((BYTE*)VAR_AllCarsHaveNitro, false); - m_Cheats[CHEAT_BOATSCANFLY] = new SCheatSA((BYTE*)VAR_BoatsCanFly, false); - m_Cheats[CHEAT_INFINITEOXYGEN] = new SCheatSA((BYTE*)VAR_InfiniteOxygen, false); - m_Cheats[CHEAT_WALKUNDERWATER] = new SCheatSA((BYTE*)VAR_WalkUnderwater, false); - m_Cheats[CHEAT_FASTERCLOCK] = new SCheatSA((BYTE*)VAR_FasterClock, false); - m_Cheats[CHEAT_FASTERGAMEPLAY] = new SCheatSA((BYTE*)VAR_FasterGameplay, false); - m_Cheats[CHEAT_SLOWERGAMEPLAY] = new SCheatSA((BYTE*)VAR_SlowerGameplay, false); - m_Cheats[CHEAT_ALWAYSMIDNIGHT] = new SCheatSA((BYTE*)VAR_AlwaysMidnight, false); - m_Cheats[CHEAT_FULLWEAPONAIMING] = new SCheatSA((BYTE*)VAR_FullWeaponAiming, false); - m_Cheats[CHEAT_INFINITEHEALTH] = new SCheatSA((BYTE*)VAR_InfiniteHealth, false); - m_Cheats[CHEAT_NEVERWANTED] = new SCheatSA((BYTE*)VAR_NeverWanted, false); - m_Cheats[CHEAT_HEALTARMORMONEY] = new SCheatSA((BYTE*)VAR_HealthArmorMoney, false); - - // Change pool sizes here - m_pPools->SetPoolCapacity(TASK_POOL, 5000); // Default is 500 - m_pPools->SetPoolCapacity(OBJECT_POOL, MAX_OBJECTS); // Default is 350 - m_pPools->SetPoolCapacity(EVENT_POOL, 5000); // Default is 200 - m_pPools->SetPoolCapacity(COL_MODEL_POOL, 12000); // Default is 10150 - m_pPools->SetPoolCapacity(ENV_MAP_MATERIAL_POOL, 16000); // Default is 4096 - m_pPools->SetPoolCapacity(ENV_MAP_ATOMIC_POOL, 4000); // Default is 1024 - m_pPools->SetPoolCapacity(SPEC_MAP_MATERIAL_POOL, 16000); // Default is 4096 - m_pPools->SetPoolCapacity(ENTRY_INFO_NODE_POOL, MAX_ENTRY_INFO_NODES); // Default is 500 - m_pPools->SetPoolCapacity(POINTER_SINGLE_LINK_POOL, MAX_POINTER_SINGLE_LINKS); // Default is 70000 - m_pPools->SetPoolCapacity(POINTER_DOUBLE_LINK_POOL, MAX_POINTER_DOUBLE_LINKS); // Default is 3200 - dassert(m_pPools->GetPoolCapacity(POINTER_SINGLE_LINK_POOL) == MAX_POINTER_SINGLE_LINKS); - - // Increase streaming object instances list size - MemPut(0x05B8E55, MAX_RWOBJECT_INSTANCES * 12); // Default is 1000 * 12 - MemPut(0x05B8EB0, MAX_RWOBJECT_INSTANCES * 12); // Default is 1000 * 12 - - // Increase matrix array size - MemPut(0x054F3A1, MAX_OBJECTS * 3); // Default is 900 - - CEntitySAInterface::StaticSetHooks(); - CPhysicalSAInterface::StaticSetHooks(); - CObjectSA::StaticSetHooks(); - CModelInfoSA::StaticSetHooks(); - CPlayerPedSA::StaticSetHooks(); - CRenderWareSA::StaticSetHooks(); - CRenderWareSA::StaticSetClothesReplacingHooks(); - CTasksSA::StaticSetHooks(); - CPedSA::StaticSetHooks(); - CSettingsSA::StaticSetHooks(); - CFxSystemSA::StaticSetHooks(); - CFileLoaderSA::StaticSetHooks(); - D3DResourceSystemSA::StaticSetHooks(); - CVehicleSA::StaticSetHooks(); - CCheckpointSA::StaticSetHooks(); + m_pPlayerInfo = new CPlayerInfoSA((CPlayerInfoSAInterface*)CLASS_CPlayerInfo); + + // Init cheat name => address map + m_Cheats[CHEAT_HOVERINGCARS] = new SCheatSA((BYTE*)VAR_HoveringCarsEnabled); + m_Cheats[CHEAT_FLYINGCARS] = new SCheatSA((BYTE*)VAR_FlyingCarsEnabled); + m_Cheats[CHEAT_EXTRABUNNYHOP] = new SCheatSA((BYTE*)VAR_ExtraBunnyhopEnabled); + m_Cheats[CHEAT_EXTRAJUMP] = new SCheatSA((BYTE*)VAR_ExtraJumpEnabled); + + // New cheats for Anticheat + m_Cheats[CHEAT_TANKMODE] = new SCheatSA((BYTE*)VAR_TankModeEnabled, false); + m_Cheats[CHEAT_NORELOAD] = new SCheatSA((BYTE*)VAR_NoReloadEnabled, false); + m_Cheats[CHEAT_PERFECTHANDLING] = new SCheatSA((BYTE*)VAR_PerfectHandling, false); + m_Cheats[CHEAT_ALLCARSHAVENITRO] = new SCheatSA((BYTE*)VAR_AllCarsHaveNitro, false); + m_Cheats[CHEAT_BOATSCANFLY] = new SCheatSA((BYTE*)VAR_BoatsCanFly, false); + m_Cheats[CHEAT_INFINITEOXYGEN] = new SCheatSA((BYTE*)VAR_InfiniteOxygen, false); + m_Cheats[CHEAT_WALKUNDERWATER] = new SCheatSA((BYTE*)VAR_WalkUnderwater, false); + m_Cheats[CHEAT_FASTERCLOCK] = new SCheatSA((BYTE*)VAR_FasterClock, false); + m_Cheats[CHEAT_FASTERGAMEPLAY] = new SCheatSA((BYTE*)VAR_FasterGameplay, false); + m_Cheats[CHEAT_SLOWERGAMEPLAY] = new SCheatSA((BYTE*)VAR_SlowerGameplay, false); + m_Cheats[CHEAT_ALWAYSMIDNIGHT] = new SCheatSA((BYTE*)VAR_AlwaysMidnight, false); + m_Cheats[CHEAT_FULLWEAPONAIMING] = new SCheatSA((BYTE*)VAR_FullWeaponAiming, false); + m_Cheats[CHEAT_INFINITEHEALTH] = new SCheatSA((BYTE*)VAR_InfiniteHealth, false); + m_Cheats[CHEAT_NEVERWANTED] = new SCheatSA((BYTE*)VAR_NeverWanted, false); + m_Cheats[CHEAT_HEALTARMORMONEY] = new SCheatSA((BYTE*)VAR_HealthArmorMoney, false); + + // Change pool sizes here + m_Pools->SetPoolCapacity(TASK_POOL, 5000); // Default is 500 + m_Pools->SetPoolCapacity(OBJECT_POOL, MAX_OBJECTS); // Default is 350 + m_Pools->SetPoolCapacity(EVENT_POOL, 5000); // Default is 200 + m_Pools->SetPoolCapacity(COL_MODEL_POOL, 12000); // Default is 10150 + m_Pools->SetPoolCapacity(ENV_MAP_MATERIAL_POOL, 16000); // Default is 4096 + m_Pools->SetPoolCapacity(ENV_MAP_ATOMIC_POOL, 4000); // Default is 1024 + m_Pools->SetPoolCapacity(SPEC_MAP_MATERIAL_POOL, 16000); // Default is 4096 + m_Pools->SetPoolCapacity(ENTRY_INFO_NODE_POOL, MAX_ENTRY_INFO_NODES); // Default is 500 + m_Pools->SetPoolCapacity(POINTER_SINGLE_LINK_POOL, MAX_POINTER_SINGLE_LINKS); // Default is 70000 + m_Pools->SetPoolCapacity(POINTER_DOUBLE_LINK_POOL, MAX_POINTER_DOUBLE_LINKS); // Default is 3200 + dassert(m_Pools->GetPoolCapacity(POINTER_SINGLE_LINK_POOL) == MAX_POINTER_SINGLE_LINKS); + + // Increase streaming object instances list size + MemPut(0x05B8E55, MAX_RWOBJECT_INSTANCES * 12); // Default is 1000 * 12 + MemPut(0x05B8EB0, MAX_RWOBJECT_INSTANCES * 12); // Default is 1000 * 12 + + // Increase matrix array size + MemPut(0x054F3A1, MAX_OBJECTS * 3); // Default is 900 + + CEntitySAInterface::StaticSetHooks(); + CPhysicalSAInterface::StaticSetHooks(); + CObjectSA::StaticSetHooks(); + CModelInfoSA::StaticSetHooks(); + CPlayerPedSA::StaticSetHooks(); + CRenderWareSA::StaticSetHooks(); + CRenderWareSA::StaticSetClothesReplacingHooks(); + CTasksSA::StaticSetHooks(); + CPedSA::StaticSetHooks(); + CSettingsSA::StaticSetHooks(); + CFxSystemSA::StaticSetHooks(); + CFileLoaderSA::StaticSetHooks(); + D3DResourceSystemSA::StaticSetHooks(); + CVehicleSA::StaticSetHooks(); + CCheckpointSA::StaticSetHooks(); + } + catch (const std::bad_alloc& e) + { + std::string error = _("Failed initialization game_sa"); + error += "\n"; + error += _("Memory allocations failed"); + error += ": "; + error += e.what(); + + MessageBoxUTF8(nullptr, error.c_str(), _("Error"), MB_ICONERROR | MB_OK); + ExitProcess(EXIT_FAILURE); + } + catch (const std::exception& e) + { + std::string error = _("Failed initialization game_sa"); + error += "\n"; + error += _("Information"); + error += ": "; + error += e.what(); + + MessageBoxUTF8(nullptr, error, _("Error"), MB_ICONERROR | MB_OK); + ExitProcess(EXIT_FAILURE); + } } CGameSA::~CGameSA() @@ -261,7 +286,6 @@ CGameSA::~CGameSA() delete reinterpret_cast(m_pAnimManager); delete reinterpret_cast(m_pTasks); delete reinterpret_cast(m_pTaskManagementSystem); - delete reinterpret_cast(m_pHandlingManager); delete reinterpret_cast(m_pStats); delete reinterpret_cast(m_pWeather); delete reinterpret_cast(m_pCAERadioTrackManager); @@ -276,7 +300,6 @@ CGameSA::~CGameSA() delete reinterpret_cast(m_pCamera); delete reinterpret_cast(m_pRadar); delete reinterpret_cast(m_pClock); - delete reinterpret_cast(m_pPools); delete reinterpret_cast(m_pWorld); delete reinterpret_cast(m_pAudioEngine); delete reinterpret_cast(m_pAEAudioHardware); @@ -848,6 +871,34 @@ void CGameSA::SetRoadSignsTextEnabled(bool isEnabled) m_isRoadSignsTextEnabled = isEnabled; } +void CGameSA::SetIgnoreFireStateEnabled(bool isEnabled) +{ + if (isEnabled == m_isIgnoreFireStateEnabled) + return; + + if (isEnabled) + { + MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable + MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask + MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask + MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter + + MemSet((void*)0x685A7F, 0x90, 14); // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon + } + else + { + // Restore original bytes + MemCpy((void*)0x6511B9, "\x88\x86\x90\x04\x00\x00\x85\xC0\x75\x3E", 10); + MemCpy((void*)0x643A95, "\x8B\x88\x90\x04\x00\x00\x85\xC9\x0F\x85\x99\x01\x00\x00", 14); + MemCpy((void*)0x6900B5, "\x8B\x81\x90\x04\x00\x00\x85\xC0\x0F\x85\x1A\x01\x00\x00", 14); + MemCpy((void*)0x64F3DB, "\x8B\x85\x90\x04\x00\x00\x85\xC0\x0F\x85\x1B\x01\x00\x00", 14); + + MemCpy((void*)0x685A7F, "\x8B\x86\x30\x07\x00\x00\x85\xC0\x0F\x85\x1D\x01\x00\x00", 14); + } + + m_isIgnoreFireStateEnabled = isEnabled; +} + bool CGameSA::PerformChecks() { std::map::iterator it; @@ -1011,8 +1062,8 @@ void CGameSA::RemoveAllBuildings() { m_pIplStore->SetDynamicIplStreamingEnabled(false); - m_pPools->GetDummyPool().RemoveAllBuildingLods(); - m_pPools->GetBuildingsPool().RemoveAllBuildings(); + m_Pools->GetDummyPool().RemoveAllBuildingLods(); + m_Pools->GetBuildingsPool().RemoveAllBuildings(); auto pBuildingRemoval = static_cast(m_pBuildingRemoval); pBuildingRemoval->DropCaches(); @@ -1022,8 +1073,8 @@ void CGameSA::RemoveAllBuildings() void CGameSA::RestoreGameBuildings() { - m_pPools->GetBuildingsPool().RestoreAllBuildings(); - m_pPools->GetDummyPool().RestoreAllBuildingsLods(); + m_Pools->GetBuildingsPool().RestoreAllBuildings(); + m_Pools->GetDummyPool().RestoreAllBuildingsLods(); m_pIplStore->SetDynamicIplStreamingEnabled(true, [](CIplSAInterface* ipl) { return memcmp("barriers", ipl->name, 8) != 0; }); m_isBuildingsRemoved = false; @@ -1041,7 +1092,7 @@ bool CGameSA::SetBuildingPoolSize(size_t size) static_cast(m_pBuildingRemoval)->DropCaches(); } - bool status = m_pPools->GetBuildingsPool().Resize(size); + bool status = m_Pools->GetBuildingsPool().Resize(size); if (shouldRemoveBuilding) { diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index cf4788d953..2133d7d9a5 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -125,7 +125,7 @@ class CGameSA : public CGame CGameSA(); ~CGameSA(); - CPools* GetPools() { return m_pPools; } + CPools* GetPools() const noexcept { return m_Pools.get(); } CPlayerInfo* GetPlayerInfo() { return m_pPlayerInfo; } CProjectileInfo* GetProjectileInfo() { return m_pProjectileInfo; } CRadar* GetRadar() { return m_pRadar; } @@ -155,7 +155,7 @@ class CGameSA : public CGame CCarEnterExit* GetCarEnterExit() { return m_pCarEnterExit; } CControllerConfigManager* GetControllerConfigManager() { return m_pControllerConfigManager; } CRenderWare* GetRenderWare() { return m_pRenderWare; } - CHandlingManager* GetHandlingManager() { return m_pHandlingManager; } + CHandlingManager* GetHandlingManager() const noexcept { return m_HandlingManager.get(); } CAnimManager* GetAnimManager() { return m_pAnimManager; } CStreaming* GetStreaming() { return m_pStreaming; } CVisibilityPlugins* GetVisibilityPlugins() { return m_pVisibilityPlugins; } @@ -249,6 +249,8 @@ class CGameSA : public CGame bool IsTunnelWeatherBlendEnabled() const noexcept override { return m_isTunnelWeatherBlendEnabled; } void SetTunnelWeatherBlendEnabled(bool isEnabled) override; + bool IsIgnoreFireStateEnabled() const noexcept override { return m_isIgnoreFireStateEnabled; } + void SetIgnoreFireStateEnabled(bool isEnabled) override; unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); @@ -311,42 +313,42 @@ class CGameSA : public CGame bool SetBuildingPoolSize(size_t size); private: - CPools* m_pPools; - CPlayerInfo* m_pPlayerInfo; - CProjectileInfo* m_pProjectileInfo; - CRadar* m_pRadar; - CClock* m_pClock; - CCoronas* m_pCoronas; - CCheckpoints* m_pCheckpoints; - CEventList* m_pEventList; - CFireManager* m_pFireManager; - CGarages* m_pGarages; - CHud* m_pHud; - CWeather* m_pWeather; - CWorld* m_pWorld; - CCamera* m_pCamera; - CModelInfo* m_pModelInfo; - CPickups* m_pPickups; - CWeaponInfo* m_pWeaponInfo; - CExplosionManager* m_pExplosionManager; - C3DMarkers* m_p3DMarkers; - CRenderWareSA* m_pRenderWare; - CHandlingManager* m_pHandlingManager; - CAnimManager* m_pAnimManager; - CStreaming* m_pStreaming; - CVisibilityPlugins* m_pVisibilityPlugins; - CKeyGen* m_pKeyGen; - CRopes* m_pRopes; - CFx* m_pFx; - CFxManagerSA* m_pFxManager; - CWaterManager* m_pWaterManager; - CWeaponStatManager* m_pWeaponStatsManager; - CPointLights* m_pPointLights; - CColStore* m_collisionStore; - CObjectGroupPhysicalProperties* m_pObjectGroupPhysicalProperties; - CCoverManagerSA* m_pCoverManager; - CPlantManagerSA* m_pPlantManager; - CBuildingRemoval* m_pBuildingRemoval; + std::unique_ptr m_Pools; + CPlayerInfo* m_pPlayerInfo; + CProjectileInfo* m_pProjectileInfo; + CRadar* m_pRadar; + CClock* m_pClock; + CCoronas* m_pCoronas; + CCheckpoints* m_pCheckpoints; + CEventList* m_pEventList; + CFireManager* m_pFireManager; + CGarages* m_pGarages; + CHud* m_pHud; + CWeather* m_pWeather; + CWorld* m_pWorld; + CCamera* m_pCamera; + CModelInfo* m_pModelInfo; + CPickups* m_pPickups; + CWeaponInfo* m_pWeaponInfo; + CExplosionManager* m_pExplosionManager; + C3DMarkers* m_p3DMarkers; + CRenderWareSA* m_pRenderWare; + std::unique_ptr m_HandlingManager; + CAnimManager* m_pAnimManager; + CStreaming* m_pStreaming; + CVisibilityPlugins* m_pVisibilityPlugins; + CKeyGen* m_pKeyGen; + CRopes* m_pRopes; + CFx* m_pFx; + CFxManagerSA* m_pFxManager; + CWaterManager* m_pWaterManager; + CWeaponStatManager* m_pWeaponStatsManager; + CPointLights* m_pPointLights; + CColStore* m_collisionStore; + CObjectGroupPhysicalProperties* m_pObjectGroupPhysicalProperties; + CCoverManagerSA* m_pCoverManager; + CPlantManagerSA* m_pPlantManager; + CBuildingRemoval* m_pBuildingRemoval; std::unique_ptr m_pRenderer; @@ -378,6 +380,7 @@ class CGameSA : public CGame bool m_isRoadSignsTextEnabled{true}; bool m_isBuildingsRemoved{false}; bool m_isExtendedWaterCannonsEnabled{false}; + bool m_isIgnoreFireStateEnabled{false}; static unsigned int& ClumpOffset; diff --git a/Client/game_sa/CHandlingEntrySA.cpp b/Client/game_sa/CHandlingEntrySA.cpp index 1ebb1471e3..3e38045dda 100644 --- a/Client/game_sa/CHandlingEntrySA.cpp +++ b/Client/game_sa/CHandlingEntrySA.cpp @@ -19,47 +19,42 @@ extern CGameSA* pGame; CHandlingEntrySA::CHandlingEntrySA() { // Create a new interface and zero it - m_pHandlingSA = new tHandlingDataSA; - memset(m_pHandlingSA, 0, sizeof(tHandlingDataSA)); - m_bDeleteInterface = true; + if (m_HandlingSA = std::make_unique()) + { + MemSetFast(m_HandlingSA.get(), 0, sizeof(tHandlingDataSA)); + } } -CHandlingEntrySA::CHandlingEntrySA(tHandlingDataSA* pOriginal) +CHandlingEntrySA::CHandlingEntrySA(const tHandlingDataSA* const pOriginal) { // Store gta's pointer - m_pHandlingSA = nullptr; - m_bDeleteInterface = false; - memcpy(&m_Handling, pOriginal, sizeof(tHandlingDataSA)); -} - -CHandlingEntrySA::~CHandlingEntrySA() -{ - if (m_bDeleteInterface) + m_HandlingSA = nullptr; + if (pOriginal) { - SAFE_DELETE(m_pHandlingSA); + MemCpyFast(&m_Handling, pOriginal, sizeof(tHandlingDataSA)); } } // Apply the handlingdata from another data -void CHandlingEntrySA::Assign(const CHandlingEntry* pEntry) +void CHandlingEntrySA::Assign(const CHandlingEntry* const pEntry) noexcept { if (!pEntry) return; // Copy the data - const CHandlingEntrySA* pEntrySA = static_cast(pEntry); + const CHandlingEntrySA* const pEntrySA = static_cast(pEntry); m_Handling = pEntrySA->m_Handling; } -void CHandlingEntrySA::Recalculate() +void CHandlingEntrySA::Recalculate() noexcept { // Real GTA class? - if (!m_pHandlingSA) + if (!m_HandlingSA) return; - // Copy our stored field to GTA's - memcpy(m_pHandlingSA, &m_Handling, sizeof(m_Handling)); - ((void(_stdcall*)(tHandlingDataSA*))FUNC_HandlingDataMgr_ConvertDataToGameUnits)(m_pHandlingSA); + // Copy our stored field to GTA's + MemCpyFast(m_HandlingSA.get(), &m_Handling, sizeof(m_Handling)); + ((void(_stdcall*)(tHandlingDataSA*))FUNC_HandlingDataMgr_ConvertDataToGameUnits)(m_HandlingSA.get()); } void CHandlingEntrySA::SetSuspensionForceLevel(float fForce) noexcept @@ -104,7 +99,7 @@ void CHandlingEntrySA::SetSuspensionAntiDiveMultiplier(float fAntidive) noexcept m_Handling.fSuspensionAntiDiveMultiplier = fAntidive; } -void CHandlingEntrySA::CheckSuspensionChanges() noexcept +void CHandlingEntrySA::CheckSuspensionChanges() const noexcept { pGame->GetHandlingManager()->CheckSuspensionChanges(this); } diff --git a/Client/game_sa/CHandlingEntrySA.h b/Client/game_sa/CHandlingEntrySA.h index d1836f461e..bab11335be 100644 --- a/Client/game_sa/CHandlingEntrySA.h +++ b/Client/game_sa/CHandlingEntrySA.h @@ -91,83 +91,83 @@ class CHandlingEntrySA : public CHandlingEntry CHandlingEntrySA(); // Constructor for original entries - CHandlingEntrySA(tHandlingDataSA* pOriginal); + CHandlingEntrySA(const tHandlingDataSA* const pOriginal); - virtual ~CHandlingEntrySA(); + virtual ~CHandlingEntrySA(){}; // Use this to copy data from an another handling class to this - void Assign(const CHandlingEntry* pEntry); + void Assign(const CHandlingEntry* const pEntry) noexcept; // Get functions - float GetMass() const { return m_Handling.fMass; } - float GetTurnMass() const { return m_Handling.fTurnMass; } - float GetDragCoeff() const { return m_Handling.fDragCoeff; } - const CVector& GetCenterOfMass() const { return m_Handling.vecCenterOfMass; } + float GetMass() const noexcept { return m_Handling.fMass; } + float GetTurnMass() const noexcept { return m_Handling.fTurnMass; } + float GetDragCoeff() const noexcept { return m_Handling.fDragCoeff; } + const CVector& GetCenterOfMass() const noexcept { return m_Handling.vecCenterOfMass; } - unsigned int GetPercentSubmerged() const { return m_Handling.uiPercentSubmerged; } - float GetTractionMultiplier() const { return m_Handling.fTractionMultiplier; } + unsigned int GetPercentSubmerged() const noexcept { return m_Handling.uiPercentSubmerged; } + float GetTractionMultiplier() const noexcept { return m_Handling.fTractionMultiplier; } - eDriveType GetCarDriveType() const { return static_cast(m_Handling.Transmission.ucDriveType); } - eEngineType GetCarEngineType() const { return static_cast(m_Handling.Transmission.ucEngineType); } - unsigned char GetNumberOfGears() const { return m_Handling.Transmission.ucNumberOfGears; } + eDriveType GetCarDriveType() const noexcept { return static_cast(m_Handling.Transmission.ucDriveType); } + eEngineType GetCarEngineType() const noexcept { return static_cast(m_Handling.Transmission.ucEngineType); } + unsigned char GetNumberOfGears() const noexcept { return m_Handling.Transmission.ucNumberOfGears; } - float GetEngineAcceleration() const { return m_Handling.Transmission.fEngineAcceleration; } - float GetEngineInertia() const { return m_Handling.Transmission.fEngineInertia; } - float GetMaxVelocity() const { return m_Handling.Transmission.fMaxVelocity; } + float GetEngineAcceleration() const noexcept { return m_Handling.Transmission.fEngineAcceleration; } + float GetEngineInertia() const noexcept { return m_Handling.Transmission.fEngineInertia; } + float GetMaxVelocity() const noexcept { return m_Handling.Transmission.fMaxVelocity; } - float GetBrakeDeceleration() const { return m_Handling.fBrakeDeceleration; } - float GetBrakeBias() const { return m_Handling.fBrakeBias; } - bool GetABS() const { return m_Handling.bABS; } + float GetBrakeDeceleration() const noexcept { return m_Handling.fBrakeDeceleration; } + float GetBrakeBias() const noexcept { return m_Handling.fBrakeBias; } + bool GetABS() const noexcept { return m_Handling.bABS; } - float GetSteeringLock() const { return m_Handling.fSteeringLock; } - float GetTractionLoss() const { return m_Handling.fTractionLoss; } - float GetTractionBias() const { return m_Handling.fTractionBias; } + float GetSteeringLock() const noexcept { return m_Handling.fSteeringLock; } + float GetTractionLoss() const noexcept { return m_Handling.fTractionLoss; } + float GetTractionBias() const noexcept { return m_Handling.fTractionBias; } - float GetSuspensionForceLevel() const { return m_Handling.fSuspensionForceLevel; } - float GetSuspensionDamping() const { return m_Handling.fSuspensionDamping; } - float GetSuspensionHighSpeedDamping() const { return m_Handling.fSuspensionHighSpdDamping; } - float GetSuspensionUpperLimit() const { return m_Handling.fSuspensionUpperLimit; } - float GetSuspensionLowerLimit() const { return m_Handling.fSuspensionLowerLimit; } - float GetSuspensionFrontRearBias() const { return m_Handling.fSuspensionFrontRearBias; } - float GetSuspensionAntiDiveMultiplier() const { return m_Handling.fSuspensionAntiDiveMultiplier; } + float GetSuspensionForceLevel() const noexcept { return m_Handling.fSuspensionForceLevel; } + float GetSuspensionDamping() const noexcept { return m_Handling.fSuspensionDamping; } + float GetSuspensionHighSpeedDamping() const noexcept { return m_Handling.fSuspensionHighSpdDamping; } + float GetSuspensionUpperLimit() const noexcept { return m_Handling.fSuspensionUpperLimit; } + float GetSuspensionLowerLimit() const noexcept { return m_Handling.fSuspensionLowerLimit; } + float GetSuspensionFrontRearBias() const noexcept { return m_Handling.fSuspensionFrontRearBias; } + float GetSuspensionAntiDiveMultiplier() const noexcept { return m_Handling.fSuspensionAntiDiveMultiplier; } - float GetCollisionDamageMultiplier() const { return m_Handling.fCollisionDamageMultiplier; } + float GetCollisionDamageMultiplier() const noexcept { return m_Handling.fCollisionDamageMultiplier; } - unsigned int GetHandlingFlags() const { return m_Handling.uiHandlingFlags; } - unsigned int GetModelFlags() const { return m_Handling.uiModelFlags; } - float GetSeatOffsetDistance() const { return m_Handling.fSeatOffsetDistance; } - unsigned int GetMonetary() const { return m_Handling.uiMonetary; } + unsigned int GetHandlingFlags() const noexcept { return m_Handling.uiHandlingFlags; } + unsigned int GetModelFlags() const noexcept { return m_Handling.uiModelFlags; } + float GetSeatOffsetDistance() const noexcept { return m_Handling.fSeatOffsetDistance; } + unsigned int GetMonetary() const noexcept { return m_Handling.uiMonetary; } - eLightType GetHeadLight() const { return static_cast(m_Handling.ucHeadLight); } - eLightType GetTailLight() const { return static_cast(m_Handling.ucTailLight); } - unsigned char GetAnimGroup() const { return m_Handling.ucAnimGroup; } + eLightType GetHeadLight() const noexcept { return static_cast(m_Handling.ucHeadLight); } + eLightType GetTailLight() const noexcept { return static_cast(m_Handling.ucTailLight); } + unsigned char GetAnimGroup() const noexcept { return m_Handling.ucAnimGroup; } - std::uint16_t GetVehicleID() const { return static_cast(m_Handling.iVehicleID); } + eHandlingTypes GetVehicleID() const noexcept { return static_cast(m_Handling.iVehicleID); } // Set functions - void SetMass(float fMass) { m_Handling.fMass = fMass; } - void SetTurnMass(float fTurnMass) { m_Handling.fTurnMass = fTurnMass; } - void SetDragCoeff(float fDrag) { m_Handling.fDragCoeff = fDrag; } - void SetCenterOfMass(const CVector& vecCenter) { m_Handling.vecCenterOfMass = vecCenter; } + void SetMass(float fMass) noexcept { m_Handling.fMass = fMass; } + void SetTurnMass(float fTurnMass) noexcept { m_Handling.fTurnMass = fTurnMass; } + void SetDragCoeff(float fDrag) noexcept { m_Handling.fDragCoeff = fDrag; } + void SetCenterOfMass(const CVector& vecCenter) noexcept { m_Handling.vecCenterOfMass = vecCenter; } - void SetPercentSubmerged(unsigned int uiPercent) { m_Handling.uiPercentSubmerged = uiPercent; } - void SetTractionMultiplier(float fTractionMultiplier) { m_Handling.fTractionMultiplier = fTractionMultiplier; } + void SetPercentSubmerged(unsigned int uiPercent) noexcept { m_Handling.uiPercentSubmerged = uiPercent; } + void SetTractionMultiplier(float fTractionMultiplier) noexcept { m_Handling.fTractionMultiplier = fTractionMultiplier; } - void SetCarDriveType(eDriveType Type) { m_Handling.Transmission.ucDriveType = Type; } - void SetCarEngineType(eEngineType Type) { m_Handling.Transmission.ucEngineType = Type; } - void SetNumberOfGears(unsigned char ucNumber) { m_Handling.Transmission.ucNumberOfGears = ucNumber; } + void SetCarDriveType(eDriveType Type) noexcept { m_Handling.Transmission.ucDriveType = Type; } + void SetCarEngineType(eEngineType Type) noexcept { m_Handling.Transmission.ucEngineType = Type; } + void SetNumberOfGears(unsigned char ucNumber) noexcept { m_Handling.Transmission.ucNumberOfGears = ucNumber; } - void SetEngineAcceleration(float fAcceleration) { m_Handling.Transmission.fEngineAcceleration = fAcceleration; } - void SetEngineInertia(float fInertia) { m_Handling.Transmission.fEngineInertia = fInertia; } - void SetMaxVelocity(float fVelocity) { m_Handling.Transmission.fMaxVelocity = fVelocity; } + void SetEngineAcceleration(float fAcceleration) noexcept { m_Handling.Transmission.fEngineAcceleration = fAcceleration; } + void SetEngineInertia(float fInertia) noexcept { m_Handling.Transmission.fEngineInertia = fInertia; } + void SetMaxVelocity(float fVelocity) noexcept { m_Handling.Transmission.fMaxVelocity = fVelocity; } - void SetBrakeDeceleration(float fDeceleration) { m_Handling.fBrakeDeceleration = fDeceleration; } - void SetBrakeBias(float fBias) { m_Handling.fBrakeBias = fBias; } - void SetABS(bool bABS) { m_Handling.bABS = bABS; } + void SetBrakeDeceleration(float fDeceleration) noexcept { m_Handling.fBrakeDeceleration = fDeceleration; } + void SetBrakeBias(float fBias) noexcept { m_Handling.fBrakeBias = fBias; } + void SetABS(bool bABS) noexcept { m_Handling.bABS = bABS; } - void SetSteeringLock(float fSteeringLock) { m_Handling.fSteeringLock = fSteeringLock; } - void SetTractionLoss(float fTractionLoss) { m_Handling.fTractionLoss = fTractionLoss; } - void SetTractionBias(float fTractionBias) { m_Handling.fTractionBias = fTractionBias; } + void SetSteeringLock(float fSteeringLock) noexcept { m_Handling.fSteeringLock = fSteeringLock; } + void SetTractionLoss(float fTractionLoss) noexcept { m_Handling.fTractionLoss = fTractionLoss; } + void SetTractionBias(float fTractionBias) noexcept { m_Handling.fTractionBias = fTractionBias; } void SetSuspensionForceLevel(float fForce) noexcept; void SetSuspensionDamping(float fDamping) noexcept; @@ -177,26 +177,24 @@ class CHandlingEntrySA : public CHandlingEntry void SetSuspensionFrontRearBias(float fBias) noexcept; void SetSuspensionAntiDiveMultiplier(float fAntidive) noexcept; - void SetCollisionDamageMultiplier(float fMultiplier) { m_Handling.fCollisionDamageMultiplier = fMultiplier; } + void SetCollisionDamageMultiplier(float fMultiplier) noexcept { m_Handling.fCollisionDamageMultiplier = fMultiplier; } - void SetHandlingFlags(unsigned int uiFlags) { m_Handling.uiHandlingFlags = uiFlags; } - void SetModelFlags(unsigned int uiFlags) { m_Handling.uiModelFlags = uiFlags; } - void SetSeatOffsetDistance(float fDistance) { m_Handling.fSeatOffsetDistance = fDistance; } - void SetMonetary(unsigned int uiMonetary) { m_Handling.uiMonetary = uiMonetary; } + void SetHandlingFlags(unsigned int uiFlags) noexcept { m_Handling.uiHandlingFlags = uiFlags; } + void SetModelFlags(unsigned int uiFlags) noexcept { m_Handling.uiModelFlags = uiFlags; } + void SetSeatOffsetDistance(float fDistance) noexcept { m_Handling.fSeatOffsetDistance = fDistance; } + void SetMonetary(unsigned int uiMonetary) noexcept { m_Handling.uiMonetary = uiMonetary; } - void SetHeadLight(eLightType Style) { m_Handling.ucHeadLight = Style; } - void SetTailLight(eLightType Style) { m_Handling.ucTailLight = Style; } - void SetAnimGroup(unsigned char ucGroup) { m_Handling.ucAnimGroup = ucGroup; } + void SetHeadLight(eLightType Style) noexcept { m_Handling.ucHeadLight = Style; } + void SetTailLight(eLightType Style) noexcept { m_Handling.ucTailLight = Style; } + void SetAnimGroup(unsigned char ucGroup) noexcept { m_Handling.ucAnimGroup = ucGroup; } - void CheckSuspensionChanges() noexcept; + void CheckSuspensionChanges() const noexcept; - void Recalculate(); + void Recalculate() noexcept; - tHandlingDataSA* GetInterface() const { return m_pHandlingSA; } + tHandlingDataSA* GetInterface() const noexcept { return m_HandlingSA.get(); } private: - tHandlingDataSA* m_pHandlingSA; - bool m_bDeleteInterface; - - tHandlingDataSA m_Handling; + std::unique_ptr m_HandlingSA; + tHandlingDataSA m_Handling; }; diff --git a/Client/game_sa/CHandlingManagerSA.cpp b/Client/game_sa/CHandlingManagerSA.cpp index 8bbfb348b1..d967bec968 100644 --- a/Client/game_sa/CHandlingManagerSA.cpp +++ b/Client/game_sa/CHandlingManagerSA.cpp @@ -27,19 +27,19 @@ extern CGameSA* pGame; #define DUMP_HANDLING_DATA 0 // Original handling data unaffected by handling.cfg changes -tHandlingDataSA m_OriginalHandlingData[HT_MAX]; -CHandlingEntrySA* m_pOriginalEntries[HT_MAX]; +static tHandlingDataSA m_OriginalHandlingData[HT_MAX]; +static std::unique_ptr m_OriginalEntries[HT_MAX]; -tFlyingHandlingDataSA m_OriginalFlyingHandlingData[24]; -CFlyingHandlingEntrySA* m_pOriginalFlyingEntries[24]; +static tFlyingHandlingDataSA m_OriginalFlyingHandlingData[24]; +static std::unique_ptr m_OriginalFlyingEntries[24]; -tBoatHandlingDataSA m_OriginalBoatHandlingData[12]; -CBoatHandlingEntrySA* m_pOriginalBoatEntries[12]; +static tBoatHandlingDataSA m_OriginalBoatHandlingData[12]; +static std::unique_ptr m_OriginalBoatEntries[12]; -tBikeHandlingDataSA m_OriginalBikeHandlingData[14]; -CBikeHandlingEntrySA* m_pOriginalBikeEntries[14]; +static tBikeHandlingDataSA m_OriginalBikeHandlingData[14]; +static std::unique_ptr m_OriginalBikeEntries[14]; -std::map m_HandlingNames; +static std::map m_HandlingNames; // TODO We need install a hook in 0x6F52D0 to make some stuff work corrently @@ -120,12 +120,6 @@ static __declspec(naked) void Hook_Calculate() } } -static bool IsVehicleModel(eVehicleTypes eModel) -{ - const auto pModelInfo = pGame->GetModelInfo(eModel); - return pModelInfo && pModelInfo->IsVehicle(); -} - CHandlingManagerSA::CHandlingManagerSA() { // Initialize all default handlings @@ -134,22 +128,22 @@ CHandlingManagerSA::CHandlingManagerSA() // Create a handling entry for every original handling data. for (std::size_t i = 0; i < HT_MAX; i++) { - m_pOriginalEntries[i] = new CHandlingEntrySA(&m_OriginalHandlingData[i]); + m_OriginalEntries[i] = std::make_unique(&m_OriginalHandlingData[i]); } for (std::size_t i = 0; i < 24; i++) { - m_pOriginalFlyingEntries[i] = new CFlyingHandlingEntrySA(&m_OriginalFlyingHandlingData[i]); + m_OriginalFlyingEntries[i] = std::make_unique(&m_OriginalFlyingHandlingData[i]); } for (std::size_t i = 0; i < 12; i++) { - m_pOriginalBoatEntries[i] = new CBoatHandlingEntrySA(&m_OriginalBoatHandlingData[i]); + m_OriginalBoatEntries[i] = std::make_unique(&m_OriginalBoatHandlingData[i]); } for (std::size_t i = 0; i < 14; i++) { - m_pOriginalBikeEntries[i] = new CBikeHandlingEntrySA(&m_OriginalBikeHandlingData[i]); + m_OriginalBikeEntries[i] = std::make_unique(&m_OriginalBikeHandlingData[i]); } #if DUMP_HANDLING_DATA @@ -193,116 +187,96 @@ CHandlingManagerSA::CHandlingManagerSA() CHandlingManagerSA::~CHandlingManagerSA() { - // Destroy all original handling entries - for (std::size_t i = 0; i < HT_MAX; i++) - { - delete m_pOriginalEntries[i]; - } - - for (std::size_t i = 0; i < 24; i++) - { - delete m_pOriginalFlyingEntries[i]; - } - - for (std::size_t i = 0; i < 12; i++) - { - delete m_pOriginalBoatEntries[i]; - } - - for (std::size_t i = 0; i < 14; i++) - { - delete m_pOriginalBikeEntries[i]; - } } -eHandlingProperty CHandlingManagerSA::GetPropertyEnumFromName(const std::string& strName) const +eHandlingProperty CHandlingManagerSA::GetPropertyEnumFromName(const std::string& name) const noexcept { - const auto it = m_HandlingNames.find(strName); + const auto it = m_HandlingNames.find(name); return it != m_HandlingNames.end() ? it->second : HANDLING_MAX; } -CHandlingEntry* CHandlingManagerSA::CreateHandlingData() +std::unique_ptr CHandlingManagerSA::CreateHandlingData() const noexcept { - return new CHandlingEntrySA; + return std::make_unique(); } -CFlyingHandlingEntry* CHandlingManagerSA::CreateFlyingHandlingData() +std::unique_ptr CHandlingManagerSA::CreateFlyingHandlingData() const noexcept { - return new CFlyingHandlingEntrySA; + return std::make_unique(); } -CBoatHandlingEntry* CHandlingManagerSA::CreateBoatHandlingData() +std::unique_ptr CHandlingManagerSA::CreateBoatHandlingData() const noexcept { - return new CBoatHandlingEntrySA; + return std::make_unique(); } -CBikeHandlingEntry* CHandlingManagerSA::CreateBikeHandlingData() +std::unique_ptr CHandlingManagerSA::CreateBikeHandlingData() const noexcept { - return new CBikeHandlingEntrySA; + return std::make_unique(); } -const CHandlingEntry* CHandlingManagerSA::GetOriginalHandlingData(eVehicleTypes eModel) const +const CHandlingEntry* CHandlingManagerSA::GetOriginalHandlingData(std::uint32_t model) const noexcept { // Vehicle? - if (!IsVehicleModel(eModel)) + if (!CModelInfoSA::IsVehicleModel(model)) return nullptr; // Get our Handling ID, the default value will be HT_LANDSTAL - const eHandlingTypes eHandling = GetHandlingID(eModel); + const eHandlingTypes eHandling = GetHandlingID(model); // Return it - return m_pOriginalEntries[eHandling]; + return m_OriginalEntries[eHandling].get(); } -const CFlyingHandlingEntry* CHandlingManagerSA::GetOriginalFlyingHandlingData(eVehicleTypes eModel) const +const CFlyingHandlingEntry* CHandlingManagerSA::GetOriginalFlyingHandlingData(std::uint32_t model) const noexcept { // Vehicle? - if (!IsVehicleModel(eModel)) + if (!CModelInfoSA::IsVehicleModel(model)) return nullptr; // Get our Handling ID, the default value will be HT_LANDSTAL - const eHandlingTypes eHandling = GetHandlingID(eModel); + const eHandlingTypes eHandling = GetHandlingID(model); // Original GTA:SA behavior if (eHandling < HT_SEAPLANE || eHandling > HT_RCRAIDER) - return m_pOriginalFlyingEntries[0]; + return m_OriginalFlyingEntries[0].get(); else - return m_pOriginalFlyingEntries[eHandling - HT_SEAPLANE]; + return m_OriginalFlyingEntries[eHandling - HT_SEAPLANE].get(); } -const CBoatHandlingEntry* CHandlingManagerSA::GetOriginalBoatHandlingData(eVehicleTypes eModel) const +const CBoatHandlingEntry* CHandlingManagerSA::GetOriginalBoatHandlingData(std::uint32_t model) const noexcept { // Vehicle? - if (!IsVehicleModel(eModel)) + if (!CModelInfoSA::IsVehicleModel(model)) return nullptr; // Get our Handling ID, the default value will be HT_LANDSTAL - const eHandlingTypes eHandling = GetHandlingID(eModel); + const eHandlingTypes eHandling = GetHandlingID(model); // Original GTA:SA behavior if (eHandling < HT_PREDATOR || eHandling > HT_SEAPLANE) - return m_pOriginalBoatEntries[0]; + return m_OriginalBoatEntries[0].get(); else - return m_pOriginalBoatEntries[eHandling - HT_PREDATOR]; + return m_OriginalBoatEntries[eHandling - HT_PREDATOR].get(); } -const CBikeHandlingEntry* CHandlingManagerSA::GetOriginalBikeHandlingData(eVehicleTypes eModel) const +const CBikeHandlingEntry* CHandlingManagerSA::GetOriginalBikeHandlingData(std::uint32_t model) const noexcept { // Vehicle? - if (!IsVehicleModel(eModel)) + if (!CModelInfoSA::IsVehicleModel(model)) return nullptr; // Get our Handling ID, the default value will be HT_LANDSTAL - const eHandlingTypes eHandling = GetHandlingID(eModel); + const eHandlingTypes eHandling = GetHandlingID(model); if (eHandling >= HT_BIKE && eHandling <= HT_FREEWAY) - return m_pOriginalBikeEntries[eHandling - HT_BIKE]; + return m_OriginalBikeEntries[eHandling - HT_BIKE].get(); else if (eHandling == HT_FAGGIO) - return m_pOriginalBikeEntries[13]; + return m_OriginalBikeEntries[13].get(); else return nullptr; } // Return the handling manager id -eHandlingTypes CHandlingManagerSA::GetHandlingID(eVehicleTypes eModel) const +eHandlingTypes CHandlingManagerSA::GetHandlingID(std::uint32_t model) const noexcept { - switch (eModel) + switch (model) { case VT_LANDSTAL: return HT_LANDSTAL; @@ -732,11 +706,8 @@ eHandlingTypes CHandlingManagerSA::GetHandlingID(eVehicleTypes eModel) const return HT_LANDSTAL; } -void CHandlingManagerSA::InitializeDefaultHandlings() +void CHandlingManagerSA::InitializeDefaultHandlings() noexcept { - // Reset - MemSetFast(m_OriginalHandlingData, 0, sizeof(m_OriginalHandlingData)); - // NB: Don't waste your time changing this manually. Use the dumping code // commented out at the bottom :) m_OriginalHandlingData[0].iVehicleID = 0; @@ -9154,53 +9125,53 @@ void CHandlingManagerSA::InitializeDefaultHandlings() m_OriginalBikeHandlingData[13].iVehicleID = 214; } -void CHandlingManagerSA::CheckSuspensionChanges(CHandlingEntry* pEntry) noexcept +void CHandlingManagerSA::CheckSuspensionChanges(const CHandlingEntry* const pEntry) const noexcept { - // Valid? - if (!pEntry) - return; - - // Grab us a multiplayer_sa pointer - CMultiplayer* const pMultiplayer = g_pCore->GetMultiplayer(); - if (!pMultiplayer) - return; - - // Get Handling ID - const eHandlingTypes eHandling = static_cast(pEntry->GetVehicleID()); - if (eHandling >= HT_MAX) - return; - - const CHandlingEntrySA* pOriginal = m_pOriginalEntries[eHandling]; - if (!pOriginal) - return; - - // Default bChanged to false - bool bChanged = false; - - // Set bChanged to true if we find ANY change. - if (pEntry->GetSuspensionAntiDiveMultiplier() != pOriginal->GetSuspensionAntiDiveMultiplier()) - bChanged = true; - - if (pEntry->GetSuspensionDamping() != pOriginal->GetSuspensionDamping()) - bChanged = true; - - if (pEntry->GetSuspensionForceLevel() != pOriginal->GetSuspensionForceLevel()) - bChanged = true; - - if (pEntry->GetSuspensionFrontRearBias() != pOriginal->GetSuspensionFrontRearBias()) - bChanged = true; - - if (pEntry->GetSuspensionHighSpeedDamping() != pOriginal->GetSuspensionHighSpeedDamping()) - bChanged = true; - - if (pEntry->GetSuspensionLowerLimit() != pOriginal->GetSuspensionLowerLimit()) - bChanged = true; - - if (pEntry->GetSuspensionUpperLimit() != pOriginal->GetSuspensionUpperLimit()) - bChanged = true; - - if (!bChanged) - return; - - pMultiplayer->UpdateVehicleSuspension(); + try + { + // Valid? + if (!pEntry) + return; + + // Grab us a multiplayer_sa pointer + const CMultiplayer* const pMultiplayer = g_pCore->GetMultiplayer(); + if (!pMultiplayer) + return; + + // Get Handling ID + const eHandlingTypes eHandling = pEntry->GetVehicleID(); + if (eHandling >= HT_MAX) + return; + + const auto& entries = m_OriginalEntries[eHandling]; + if (!entries) + return; + + // Default bChanged to false + bool bChanged = false; + + // Set bChanged to true if we find ANY change. + if (pEntry->GetSuspensionAntiDiveMultiplier() != entries->GetSuspensionAntiDiveMultiplier()) + bChanged = true; + else if (pEntry->GetSuspensionDamping() != entries->GetSuspensionDamping()) + bChanged = true; + else if (pEntry->GetSuspensionForceLevel() != entries->GetSuspensionForceLevel()) + bChanged = true; + else if (pEntry->GetSuspensionFrontRearBias() != entries->GetSuspensionFrontRearBias()) + bChanged = true; + else if (pEntry->GetSuspensionHighSpeedDamping() != entries->GetSuspensionHighSpeedDamping()) + bChanged = true; + else if (pEntry->GetSuspensionLowerLimit() != entries->GetSuspensionLowerLimit()) + bChanged = true; + else if (pEntry->GetSuspensionUpperLimit() != entries->GetSuspensionUpperLimit()) + bChanged = true; + + if (!bChanged) + return; + + pMultiplayer->UpdateVehicleSuspension(); + } + catch (...) + { + } } diff --git a/Client/game_sa/CHandlingManagerSA.h b/Client/game_sa/CHandlingManagerSA.h index 52ce90c9f3..d27ec2459f 100644 --- a/Client/game_sa/CHandlingManagerSA.h +++ b/Client/game_sa/CHandlingManagerSA.h @@ -23,22 +23,22 @@ class CHandlingManagerSA : public CHandlingManager CHandlingManagerSA(); ~CHandlingManagerSA(); - CHandlingEntry* CreateHandlingData(); - CFlyingHandlingEntry* CreateFlyingHandlingData(); - CBoatHandlingEntry* CreateBoatHandlingData(); - CBikeHandlingEntry* CreateBikeHandlingData(); + std::unique_ptr CreateHandlingData() const noexcept; + std::unique_ptr CreateFlyingHandlingData() const noexcept; + std::unique_ptr CreateBoatHandlingData() const noexcept; + std::unique_ptr CreateBikeHandlingData() const noexcept; - const CHandlingEntry* GetOriginalHandlingData(eVehicleTypes eModel) const; - const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(eVehicleTypes eModel) const; - const CBoatHandlingEntry* GetOriginalBoatHandlingData(eVehicleTypes eModel) const; - const CBikeHandlingEntry* GetOriginalBikeHandlingData(eVehicleTypes eModel) const; + const CHandlingEntry* GetOriginalHandlingData(std::uint32_t model) const noexcept; + const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(std::uint32_t model) const noexcept; + const CBoatHandlingEntry* GetOriginalBoatHandlingData(std::uint32_t model) const noexcept; + const CBikeHandlingEntry* GetOriginalBikeHandlingData(std::uint32_t model) const noexcept; - eHandlingProperty GetPropertyEnumFromName(const std::string& strName) const; + eHandlingProperty GetPropertyEnumFromName(const std::string& name) const noexcept; - void CheckSuspensionChanges(CHandlingEntry* pEntry) noexcept; + void CheckSuspensionChanges(const CHandlingEntry* const pEntry) const noexcept; private: - void InitializeDefaultHandlings(); + void InitializeDefaultHandlings() noexcept; - eHandlingTypes GetHandlingID(eVehicleTypes eModel) const; + eHandlingTypes GetHandlingID(std::uint32_t uiModel) const noexcept; }; diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index 4bf3146d7f..0b5ff312b3 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -270,20 +270,14 @@ bool CModelInfoSA::IsTrailer() return bReturn; } -BYTE CModelInfoSA::GetVehicleType() +BYTE CModelInfoSA::GetVehicleType() const noexcept { // This function will return a vehicle type for vehicles or 0xFF on failure - DWORD dwFunction = FUNC_IsVehicleModelType; - DWORD ModelID = m_dwModelID; - BYTE bReturn = -1; - _asm - { - push ModelID - call dwFunction - mov bReturn, al - add esp, 4 - } - return bReturn; + if (!IsVehicle()) + return -1; + + auto GetVehicleModelType = reinterpret_cast(FUNC_IsVehicleModelType); + return GetVehicleModelType(m_dwModelID); } bool CModelInfoSA::IsVehicle() const @@ -292,9 +286,25 @@ bool CModelInfoSA::IsVehicle() const if (m_dwModelID >= 20000) return false; + if (!IsAllocatedInArchive()) + return false; + // NOTE(botder): m_pInterface might be a nullptr here, we can't use it CBaseModelInfoSAInterface* model = ppModelInfo[m_dwModelID]; - return model != nullptr && reinterpret_cast(model->VFTBL) == vftable_CVehicleModelInfo; + return model && reinterpret_cast(model->VFTBL) == vftable_CVehicleModelInfo; +} + +bool CModelInfoSA::IsVehicleModel(std::uint32_t model) noexcept +{ + try + { + const auto* const modelInfo = pGame->GetModelInfo(model); + return modelInfo && modelInfo->IsVehicle(); + } + catch (...) + { + return false; + } } bool CModelInfoSA::IsPlayerModel() @@ -754,9 +764,16 @@ bool CModelInfoSA::IsValid() return true; } -bool CModelInfoSA::IsAllocatedInArchive() +bool CModelInfoSA::IsAllocatedInArchive() const noexcept { - return pGame->GetStreaming()->GetStreamingInfo(m_dwModelID)->sizeInBlocks > 0; + try + { + return pGame->GetStreaming()->GetStreamingInfo(m_dwModelID)->sizeInBlocks > 0; + } + catch (...) + { + return false; + } } float CModelInfoSA::GetDistanceFromCentreOfMassToBaseOfModel() diff --git a/Client/game_sa/CModelInfoSA.h b/Client/game_sa/CModelInfoSA.h index b261bcc04a..6fc7b04811 100644 --- a/Client/game_sa/CModelInfoSA.h +++ b/Client/game_sa/CModelInfoSA.h @@ -359,7 +359,7 @@ class CModelInfoSA : public CModelInfo char* GetNameIfVehicle(); - BYTE GetVehicleType(); + BYTE GetVehicleType() const noexcept; void Request(EModelRequestType requestType, const char* szTag); void Remove(); bool UnloadUnused(); @@ -374,7 +374,7 @@ class CModelInfoSA : public CModelInfo static void StaticResetFlags(); CBoundingBox* GetBoundingBox(); bool IsValid(); - bool IsAllocatedInArchive(); + bool IsAllocatedInArchive() const noexcept; float GetDistanceFromCentreOfMassToBaseOfModel(); unsigned short GetTextureDictionaryID(); void SetTextureDictionaryID(unsigned short usID); @@ -466,7 +466,9 @@ class CModelInfoSA : public CModelInfo // Vehicle towing functions bool IsTowableBy(CModelInfo* towingModel) override; - bool IsDynamic() { return m_pInterface ? m_pInterface->usDynamicIndex != 0xffff : false; }; + bool IsDynamic() { return m_pInterface ? m_pInterface->usDynamicIndex != MODEL_PROPERTIES_GROUP_STATIC : false; }; + + static bool IsVehicleModel(std::uint32_t model) noexcept; private: void CopyStreamingInfoFromModel(ushort usCopyFromModelID); diff --git a/Client/game_sa/CPhysicalSA.cpp b/Client/game_sa/CPhysicalSA.cpp index d13513a414..ec05a42225 100644 --- a/Client/game_sa/CPhysicalSA.cpp +++ b/Client/game_sa/CPhysicalSA.cpp @@ -39,7 +39,7 @@ void CPhysicalSA::RestoreLastGoodPhysicsState() CVector vecDefault; SetTurnSpeed(&vecDefault); - SetMoveSpeed(&vecDefault); + SetMoveSpeed(vecDefault); CPhysicalSAInterface* pInterface = (CPhysicalSAInterface*)GetInterface(); pInterface->m_pad4d = 0; @@ -100,24 +100,30 @@ CVector* CPhysicalSA::GetTurnSpeedInternal(CVector* vecTurnSpeed) return vecTurnSpeed; } -void CPhysicalSA::SetMoveSpeed(CVector* vecMoveSpeed) +void CPhysicalSA::SetMoveSpeed(const CVector& vecMoveSpeed) noexcept { - DWORD dwFunc = FUNC_GetMoveSpeed; - DWORD dwThis = (DWORD)((CPhysicalSAInterface*)GetInterface()); - DWORD dwReturn = 0; - - _asm + try { - mov ecx, dwThis - call dwFunc - mov dwReturn, eax + DWORD dwFunc = FUNC_GetMoveSpeed; + DWORD dwThis = (DWORD)((CPhysicalSAInterface*)GetInterface()); + DWORD dwReturn = 0; + + __asm + { + mov ecx, dwThis + call dwFunc + mov dwReturn, eax + } + MemCpyFast((void*)dwReturn, &vecMoveSpeed, sizeof(CVector)); + + if (GetInterface()->nType == ENTITY_TYPE_OBJECT) + { + AddToMovingList(); + SetStatic(false); + } } - MemCpyFast((void*)dwReturn, vecMoveSpeed, sizeof(CVector)); - - if (GetInterface()->nType == ENTITY_TYPE_OBJECT) + catch (...) { - AddToMovingList(); - SetStatic(false); } } diff --git a/Client/game_sa/CPhysicalSA.h b/Client/game_sa/CPhysicalSA.h index 2b1234150c..eb5a2a4515 100644 --- a/Client/game_sa/CPhysicalSA.h +++ b/Client/game_sa/CPhysicalSA.h @@ -121,7 +121,7 @@ class CPhysicalSA : public virtual CPhysical, public virtual CEntitySA CVector* GetTurnSpeed(CVector* vecTurnSpeed); CVector* GetMoveSpeedInternal(CVector* vecMoveSpeed); CVector* GetTurnSpeedInternal(CVector* vecTurnSpeed); - void SetMoveSpeed(CVector* vecMoveSpeed); + void SetMoveSpeed(const CVector& vecMoveSpeed) noexcept; void SetTurnSpeed(CVector* vecTurnSpeed); float GetMass(); diff --git a/Client/game_sa/CPlayerPedSA.cpp b/Client/game_sa/CPlayerPedSA.cpp index 534f8376c6..cf8a03faea 100644 --- a/Client/game_sa/CPlayerPedSA.cpp +++ b/Client/game_sa/CPlayerPedSA.cpp @@ -18,6 +18,7 @@ #include "CPlayerInfoSA.h" #include "CPlayerPedSA.h" #include "CWorldSA.h" +#include "CProjectileInfoSA.h" extern CCoreInterface* g_pCore; extern CGameSA* pGame; @@ -137,6 +138,7 @@ CPlayerPedSA::~CPlayerPedSA() if ((DWORD)GetInterface()->vtbl != VTBL_CPlaceable) { CWorldSA* world = (CWorldSA*)pGame->GetWorld(); + pGame->GetProjectileInfo()->RemoveEntityReferences(this); world->Remove(m_pInterface, CPlayerPed_Destructor); DWORD dwThis = (DWORD)m_pInterface; diff --git a/Client/game_sa/CPoolsSA.cpp b/Client/game_sa/CPoolsSA.cpp index 1aaac0b40d..bd7a5f9c96 100644 --- a/Client/game_sa/CPoolsSA.cpp +++ b/Client/game_sa/CPoolsSA.cpp @@ -71,70 +71,76 @@ inline bool CPoolsSA::AddVehicleToPool(CClientVehicle* pClientVehicle, CVehicleS return true; } -CVehicle* CPoolsSA::AddVehicle(CClientVehicle* pClientVehicle, eVehicleTypes eVehicleType, unsigned char ucVariation, unsigned char ucVariation2) +CVehicle* CPoolsSA::AddVehicle(CClientVehicle* pClientVehicle, std::uint16_t model, std::uint8_t variation, std::uint8_t variation2) noexcept { - CVehicleSA* pVehicle = nullptr; - - if (m_vehiclePool.ulCount < MAX_VEHICLES) + try { - MemSetFast((void*)VAR_CVehicle_Variation1, ucVariation, 1); - MemSetFast((void*)VAR_CVehicle_Variation2, ucVariation2, 1); + if (m_vehiclePool.ulCount >= MAX_VEHICLES) + return nullptr; + + MemSetFast((void*)VAR_CVehicle_Variation1, variation, 1); + MemSetFast((void*)VAR_CVehicle_Variation2, variation2, 1); // CCarCtrl::CreateCarForScript - CVehicleSAInterface* pInterface = - ((CVehicleSAInterface * (__cdecl*)(int, CVector, unsigned char)) FUNC_CCarCtrlCreateCarForScript)(eVehicleType, CVector(0, 0, 0), 0); + auto* pInterface = ((CVehicleSAInterface*(__cdecl*)(int, CVector, std::uint8_t))FUNC_CCarCtrlCreateCarForScript)(model, CVector(), 0); + if (!pInterface) + return nullptr; - auto vehicleClass = static_cast(pGame->GetModelInfo(eVehicleType)->GetVehicleType()); + // Valid model? + if (!CModelInfoSA::IsVehicleModel(model)) + return nullptr; + auto vehicleClass = static_cast(pGame->GetModelInfo(model)->GetVehicleType()); + + std::unique_ptr vehicle = nullptr; switch (vehicleClass) { case VehicleClass::MONSTER_TRUCK: - pVehicle = new CMonsterTruckSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::QUAD: - pVehicle = new CQuadBikeSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::HELI: - pVehicle = new CHeliSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::PLANE: - pVehicle = new CPlaneSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::BOAT: - pVehicle = new CBoatSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::TRAIN: - pVehicle = new CTrainSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::BIKE: - pVehicle = new CBikeSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::BMX: - pVehicle = new CBmxSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; case VehicleClass::TRAILER: - pVehicle = new CTrailerSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; default: - pVehicle = new CAutomobileSA(reinterpret_cast(pInterface)); + vehicle = std::make_unique(reinterpret_cast(pInterface)); break; } - if (pVehicle && AddVehicleToPool(pClientVehicle, pVehicle)) - { - pVehicle->m_ucVariant = ucVariation; - pVehicle->m_ucVariant2 = ucVariation2; + if (!vehicle || !AddVehicleToPool(pClientVehicle, vehicle.get())) + return nullptr; - pVehicle->DumpVehicleFrames(); - } - else - { - delete pVehicle; - pVehicle = nullptr; - } - } + vehicle->m_ucVariant = variation; + vehicle->m_ucVariant2 = variation2; - return pVehicle; + vehicle->DumpVehicleFrames(); + + return vehicle.release(); + } + catch (...) + { + return nullptr; + } } void CPoolsSA::RemoveVehicle(CVehicle* pVehicle, bool bDelete) @@ -564,108 +570,89 @@ CClientEntity* CPoolsSA::GetClientEntity(DWORD* pGameInterface) return NULL; } -CVehicle* CPoolsSA::AddTrain(CClientVehicle* pClientVehicle, CVector* vecPosition, DWORD dwModels[], int iSize, bool bDirection, uchar ucTrackId) +static void CreateMissionTrain(const CVector& vecPos, bool bDirection, std::uint32_t uiTrainType, CTrainSAInterface** ppTrainBeginning, + CTrainSAInterface** ppTrainEnd, int iNodeIndex, int iTrackId, bool bMissionTrain) noexcept +{ + try + { + auto createMissionTrain = reinterpret_cast(FUNC_CTrain_CreateMissionTrain); + + createMissionTrain(vecPos, bDirection, uiTrainType, ppTrainBeginning, ppTrainEnd, iNodeIndex, iTrackId, bMissionTrain); + } + catch (...) + { + } +} + +CVehicle* CPoolsSA::AddTrain(CClientVehicle* pClientVehicle, const CVector& vecPosition, std::vector models, bool bDirection, + std::uint8_t ucTrackId) noexcept { // clean the existing array MemSetFast((void*)VAR_TrainModelArray, 0, 32 * sizeof(DWORD)); // now load the models we're going to use and add them to the array - for (int i = 0; i < iSize; i++) + std::size_t count = 0; + for (const auto model : models) { - if (dwModels[i] == 449 || dwModels[i] == 537 || dwModels[i] == 538 || dwModels[i] == 569 || dwModels[i] == 590 || dwModels[i] == 570) + // Valid model? + if (!CModelInfoSA::IsVehicleModel(model)) + return nullptr; + + if (model == 449 || model == 537 || model == 538 || model == 569 || model == 590 || model == 570) { - MemPutFast(VAR_TrainModelArray + i * 4, dwModels[i]); + MemPutFast(VAR_TrainModelArray + count * 4, model); + count += 1; } } - CTrainSAInterface* pTrainBeginning = nullptr; - CTrainSAInterface* pTrainEnd = nullptr; - - float fX = vecPosition->fX; - float fY = vecPosition->fY; - float fZ = vecPosition->fZ; - // Disable GetVehicle because CreateMissionTrain calls it before our CVehicleSA instance is inited m_bGetVehicleEnabled = false; // Find closest track node float fRailDistance; - int iNodeId = pGame->GetWorld()->FindClosestRailTrackNode(*vecPosition, ucTrackId, fRailDistance); + int iNodeId = pGame->GetWorld()->FindClosestRailTrackNode(vecPosition, ucTrackId, fRailDistance); int iDesiredTrackId = ucTrackId; - DWORD dwFunc = FUNC_CTrain_CreateMissionTrain; - _asm - { - push 0 // place as close to point as possible (rather than at node)? (maybe) (actually seems to have an effect on the speed, so changed from - // 1 to 0) - push iDesiredTrackId // track ID - push iNodeId // node to start at (-1 for closest node) - lea ecx, pTrainEnd - push ecx // end of train - lea ecx, pTrainBeginning - push ecx // begining of train - push 0 // train type (always use 0 as thats where we're writing to) - push bDirection // direction - push fZ // z - push fY // y - push fX // x - call dwFunc - add esp, 0x28 - } + CTrainSAInterface* pTrainBeginning = nullptr; + CTrainSAInterface* pTrainEnd = nullptr; + + CreateMissionTrain(vecPosition, bDirection, 0, &pTrainBeginning, &pTrainEnd, iNodeId, iDesiredTrackId, false); // Enable GetVehicle m_bGetVehicleEnabled = true; - CVehicleSA* trainHead = NULL; - if (pTrainBeginning) - { - DWORD vehicleIndex = 0; + if (!pTrainBeginning || m_vehiclePool.ulCount >= MAX_VEHICLES) + return nullptr; - if (m_vehiclePool.ulCount < MAX_VEHICLES) - { - trainHead = new CTrainSA(pTrainBeginning); - if (!AddVehicleToPool(pClientVehicle, trainHead)) - { - delete trainHead; - trainHead = NULL; - } - else - ++vehicleIndex; - } + std::size_t vehicleIndex = 0; + + std::unique_ptr train = std::make_unique(pTrainBeginning); + if (!train || !AddVehicleToPool(pClientVehicle, train.get())) + return nullptr; - CVehicleSA* carriage = trainHead; + ++vehicleIndex; - while (carriage) + CVehicleSA* pCarriage = train.get(); + while (m_vehiclePool.ulCount < MAX_VEHICLES && pCarriage && pCarriage->GetNextCarriageInTrain()) + { + CTrainSAInterface* pVehCarriage = pCarriage->GetNextCarriageInTrain(); + if (!pVehCarriage) + break; + + auto newCarriage = std::make_unique(pVehCarriage); + if (!newCarriage || !AddVehicleToPool(pClientVehicle, newCarriage.get())) { - if (m_vehiclePool.ulCount < MAX_VEHICLES) - { - CTrainSAInterface* vehCarriage = carriage->GetNextCarriageInTrain(); - if (vehCarriage) - { - carriage = new CTrainSA(vehCarriage); - if (!AddVehicleToPool(pClientVehicle, carriage)) - { - delete carriage; - carriage = NULL; - } - else - ++vehicleIndex; - } - else - carriage = NULL; - } + newCarriage.reset(); + break; } - } - // Stops the train from moving at ludacrist speeds right after creation - // due to some glitch in the node finding in CreateMissionTrain - CVector vec(0, 0, 0); - if (trainHead) - { - trainHead->SetMoveSpeed(&vec); + pCarriage = newCarriage.release(); + ++vehicleIndex; } - return trainHead; + train->SetMoveSpeed(CVector()); + return train.release(); } DWORD CPoolsSA::GetPedPoolIndex(std::uint8_t* pInterface) diff --git a/Client/game_sa/CPoolsSA.h b/Client/game_sa/CPoolsSA.h index 5718421d6c..27eeec68bc 100644 --- a/Client/game_sa/CPoolsSA.h +++ b/Client/game_sa/CPoolsSA.h @@ -30,7 +30,7 @@ class CPoolsSA : public CPools ~CPoolsSA(); // Vehicles pool - CVehicle* AddVehicle(CClientVehicle* pClientVehicle, eVehicleTypes eVehicleType, unsigned char ucVariation, unsigned char ucVariation2); + CVehicle* AddVehicle(CClientVehicle* pClientVehicle, std::uint16_t model, std::uint8_t variation, std::uint8_t variation2) noexcept; private: bool AddVehicleToPool(CClientVehicle* pClientVehicle, CVehicleSA* pVehicle); @@ -76,7 +76,8 @@ class CPoolsSA : public CPools uint GetModelIdFromClump(RpClump* pRpClump); // Others - CVehicle* AddTrain(CClientVehicle* pClientVehicle, CVector* vecPosition, DWORD dwModels[], int iSize, bool bDirection, uchar ucTrackId = 0xFF); + CVehicle* AddTrain(CClientVehicle* pClientVehicle, const CVector& vecPosition, std::vector models, bool bDirection, + std::uint8_t ucTrackId = 255) noexcept; DWORD GetPedPoolIndex(std::uint8_t* pInterface); DWORD GetVehiclePoolIndex(std::uint8_t* pInterfacee); diff --git a/Client/game_sa/CProjectileInfoSA.cpp b/Client/game_sa/CProjectileInfoSA.cpp index 439553941d..843f029462 100644 --- a/Client/game_sa/CProjectileInfoSA.cpp +++ b/Client/game_sa/CProjectileInfoSA.cpp @@ -180,3 +180,18 @@ DWORD CProjectileInfoSA::GetCounter() { return internalInterface->dwCounter - pGame->GetSystemTime(); } + +void CProjectileInfoSA::RemoveEntityReferences(CEntity* entity) +{ + const CEntitySAInterface* entityInterface = entity->GetInterface(); + for (int i = 0; i < PROJECTILE_INFO_COUNT; i++) + { + auto projectileInterface = projectileInfo[i]->internalInterface; + + if (projectileInterface->pEntProjectileOwner == entityInterface) + projectileInterface->pEntProjectileOwner = nullptr; + + if (projectileInterface->pEntProjectileTarget == entityInterface) + projectileInterface->pEntProjectileTarget = nullptr; + } +} diff --git a/Client/game_sa/CProjectileInfoSA.h b/Client/game_sa/CProjectileInfoSA.h index 2d8ba9cb32..73b69f74e2 100644 --- a/Client/game_sa/CProjectileInfoSA.h +++ b/Client/game_sa/CProjectileInfoSA.h @@ -42,7 +42,8 @@ class CProjectileInfoSAInterface }; // #pragma pack(pop) -class CProjectileInfoSA : public CProjectileInfo +// TODO extract manager class +class CProjectileInfoSA final : public CProjectileInfo { private: CProjectileInfoSA* projectileInfo[PROJECTILE_INFO_COUNT]; @@ -65,6 +66,7 @@ class CProjectileInfoSA : public CProjectileInfo CProjectileInfo* GetProjectileInfo(DWORD dwIndex); bool AddProjectile(CEntity* creator, eWeaponType eWeapon, CVector vecOrigin, float fForce, CVector* target, CEntity* targetEntity); CProjectile* GetProjectile(void* projectilePointer); + void RemoveEntityReferences(CEntity* entity); CEntity* GetTarget(); void SetTarget(CEntity* pEntity); diff --git a/Client/game_sa/CSettingsSA.cpp b/Client/game_sa/CSettingsSA.cpp index 4ce70b5eed..95b66d40df 100644 --- a/Client/game_sa/CSettingsSA.cpp +++ b/Client/game_sa/CSettingsSA.cpp @@ -316,6 +316,20 @@ void CSettingsSA::SetDynamicPedShadowsEnabled(bool bEnable) m_bDynamicPedShadowsEnabled = bEnable; } +bool CSettingsSA::IsDynamicPedShadowsEnabledByVideoSetting() const noexcept +{ + bool pedDynamicShadows; + g_pCore->GetCVars()->Get("dynamic_ped_shadows", pedDynamicShadows); + return pedDynamicShadows; +} + +bool CSettingsSA::ResetDynamicPedShadows() noexcept +{ + pGame->GetSettings()->SetDynamicPedShadowsEnabled(pGame->GetSettings()->IsDynamicPedShadowsEnabledByVideoSetting()); + return true; +} + + // // Volumetric shadow hooks // diff --git a/Client/game_sa/CSettingsSA.h b/Client/game_sa/CSettingsSA.h index 7947c94929..3986ec1059 100644 --- a/Client/game_sa/CSettingsSA.h +++ b/Client/game_sa/CSettingsSA.h @@ -147,6 +147,8 @@ class CSettingsSA : public CGameSettings bool IsDynamicPedShadowsEnabled(); void SetDynamicPedShadowsEnabled(bool bEnable); + bool IsDynamicPedShadowsEnabledByVideoSetting() const noexcept; + bool ResetDynamicPedShadows() noexcept; float GetAspectRatioValue(); eAspectRatio GetAspectRatio(); diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index ab899723be..5fe90c6e52 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -281,6 +281,7 @@ CVehicleSA::~CVehicleSA() } CWorldSA* pWorld = (CWorldSA*)pGame->GetWorld(); + pGame->GetProjectileInfo()->RemoveEntityReferences(this); pWorld->Remove(m_pInterface, CVehicle_Destructor); pWorld->RemoveReferencesToDeletedObject(m_pInterface); @@ -297,18 +298,24 @@ CVehicleSA::~CVehicleSA() } } -void CVehicleSA::SetMoveSpeed(CVector* vecMoveSpeed) +void CVehicleSA::SetMoveSpeed(const CVector& vecMoveSpeed) noexcept { - DWORD dwFunc = FUNC_GetMoveSpeed; - DWORD dwThis = (DWORD)GetInterface(); - DWORD dwReturn = 0; - _asm + try + { + DWORD dwFunc = FUNC_GetMoveSpeed; + DWORD dwThis = (DWORD)GetInterface(); + DWORD dwReturn = 0; + _asm + { + mov ecx, dwThis + call dwFunc + mov dwReturn, eax + } + MemCpyFast((void*)dwReturn, &vecMoveSpeed, sizeof(CVector)); + } + catch (...) { - mov ecx, dwThis - call dwFunc - mov dwReturn, eax } - MemCpyFast((void*)dwReturn, vecMoveSpeed, sizeof(CVector)); // INACCURATE. Use Get/SetTrainSpeed instead of Get/SetMoveSpeed. (Causes issue #4829). #if 0 @@ -1425,16 +1432,20 @@ void CVehicleSA::RecalculateHandling() continue; // If NOS is installed we need set the flag - if ((upgradeID >= 1008 && upgradeID <= 1010) && !(uiHandlingFlags & HANDLING_NOS_Flag)) + if ((upgradeID >= 1008 && upgradeID <= 1010)) { - uiHandlingFlags |= HANDLING_NOS_Flag; + if (!(uiHandlingFlags & HANDLING_NOS_Flag)) + uiHandlingFlags |= HANDLING_NOS_Flag; + nitroInstalled = true; } // If hydraulics is installed we need set the flag - if ((upgradeID == 1087) && !(uiHandlingFlags & HANDLING_Hydraulics_Flag)) + if ((upgradeID == 1087)) { - uiHandlingFlags |= HANDLING_Hydraulics_Flag; + if (!(uiHandlingFlags & HANDLING_Hydraulics_Flag)) + uiHandlingFlags |= HANDLING_Hydraulics_Flag; + hydralicsInstalled = true; } } diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index 0d65184440..9d2855e093 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -441,7 +441,7 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA virtual void OnChangingPosition(const CVector& vecNewPosition); // Override of CPhysicalSA::SetMoveSpeed to take trains into account - void SetMoveSpeed(CVector* vecMoveSpeed); + void SetMoveSpeed(const CVector& vecMoveSpeed) noexcept; bool AddProjectile(eWeaponType eWeapon, CVector vecOrigin, float fForce, CVector* target, CEntity* targetEntity); diff --git a/Client/game_sa/CWorldSA.cpp b/Client/game_sa/CWorldSA.cpp index a60e360464..72befc316e 100644 --- a/Client/game_sa/CWorldSA.cpp +++ b/Client/game_sa/CWorldSA.cpp @@ -528,6 +528,23 @@ bool CWorldSA::ProcessLineOfSight(const CVector* vecStart, const CVector* vecEnd return bReturn; } +CEntity* CWorldSA::TestSphereAgainstWorld(const CVector& sphereCenter, float radius, CEntity* ignoredEntity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool cameraIgnore, STestSphereAgainstWorldResult& result) +{ + auto entity = ((CEntitySAInterface*(__cdecl*)(CVector, float, CEntitySAInterface*, bool, bool, bool, bool, bool, bool))FUNC_CWorld_TestSphereAgainstWorld)(sphereCenter, radius, ignoredEntity ? ignoredEntity->GetInterface() : nullptr, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, cameraIgnore); + if (!entity) + return nullptr; + + result.collisionDetected = true; + result.modelID = entity->m_nModelIndex; + result.entityPosition = entity->Placeable.matrix->vPos; + ConvertMatrixToEulerAngles(*entity->Placeable.matrix, result.entityRotation.fX, result.entityRotation.fY, result.entityRotation.fZ); + result.entityRotation = -result.entityRotation; + result.lodID = entity->m_pLod ? entity->m_pLod->m_nModelIndex : 0; + result.type = static_cast(entity->nType); + + return pGame->GetPools()->GetEntity(reinterpret_cast(entity)); +} + void CWorldSA::IgnoreEntity(CEntity* pEntity) { CEntitySA* pEntitySA = dynamic_cast(pEntity); diff --git a/Client/game_sa/CWorldSA.h b/Client/game_sa/CWorldSA.h index 340db3ef5d..5da287a1a6 100644 --- a/Client/game_sa/CWorldSA.h +++ b/Client/game_sa/CWorldSA.h @@ -25,6 +25,7 @@ #define VAR_COcclusion_NumActiveOccluders 0xC73CC0 #define CALL_CCullZones_FindTunnelAttributesForCoors 0x55570D #define FUNC_CWorld_FindPositionForTrackPosition 0x6F59E0 +#define FUNC_CWorld_TestSphereAgainstWorld 0x569E20 #define VAR_IgnoredEntity 0xB7CD68 #define VAR_currArea 0xB72914 @@ -74,6 +75,8 @@ class CWorldSA : public CWorld void ResetAllSurfaceInfo() override; bool ResetSurfaceInfo(short sSurfaceID) override; + CEntity* TestSphereAgainstWorld(const CVector& sphereCenter, float radius, CEntity* ignoredEntity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool cameraIgnore, STestSphereAgainstWorldResult& result) override; + private: float m_fAircraftMaxHeight; CSurfaceType* m_pSurfaceInfo; diff --git a/Client/loader/Utils.cpp b/Client/loader/Utils.cpp index 9d3ead9eba..7dae8ce439 100644 --- a/Client/loader/Utils.cpp +++ b/Client/loader/Utils.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #pragma comment (lib, "wintrust") namespace fs = std::filesystem; @@ -527,30 +528,26 @@ bool LookForGtaProcess(SString& strOutPathFilename) // // /////////////////////////////////////////////////////////////// -SString DoUserAssistedSearch() +static const SString DoUserAssistedSearch() noexcept { - SString strResult; + SString result; - ShowProgressDialog(g_hInstance, _("Searching for Grand Theft Auto San Andreas"), true); + MessageBox(nullptr, _("Start Grand Theft Auto: San Andreas.\nEnsure the game is placed in the 'Program Files (x86)' folder."), _("Searching for GTA: San Andreas"), MB_OK | MB_ICONINFORMATION); - while (!UpdateProgress(0, 100, _("Please start Grand Theft Auto San Andreas"))) + while (true) { - SString strPathFilename; - // Check if user has started GTA - if (LookForGtaProcess(strPathFilename)) + SString path; + + if (LookForGtaProcess(path)) { - // If so, get the exe path - ExtractFilename(strPathFilename, &strResult, NULL); - // And then stop it + ExtractFilename(path, &result, nullptr); TerminateGTAIfRunning(); - break; + return result; } - Sleep(200); + if (MessageBox(nullptr, _("Sorry, game not found.\nStart Grand Theft Auto: San Andreas and click retry.\nEnsure the game is placed in the 'Program Files (x86)' folder."), _("Searching for GTA: San Andreas"), MB_RETRYCANCEL | MB_ICONWARNING) == IDCANCEL) + return result; } - - HideProgressDialog(); - return strResult; } /////////////////////////////////////////////////////////////// diff --git a/Client/mods/deathmatch/CClient.cpp b/Client/mods/deathmatch/CClient.cpp index ec17655996..e532ef2f71 100644 --- a/Client/mods/deathmatch/CClient.cpp +++ b/Client/mods/deathmatch/CClient.cpp @@ -64,17 +64,17 @@ int CClient::ClientInitialize(const char* szArguments, CCoreInterface* pCore) g_pCore->GetCommands()->Add("enter_passenger", _("enters a car as passenger"), COMMAND_EnterPassenger, true, true); g_pCore->GetCommands()->Add("radio_next", _("next radio channel"), COMMAND_RadioNext, true, true); g_pCore->GetCommands()->Add("radio_previous", _("previous radio channel"), COMMAND_RadioPrevious, true, true); - g_pCore->GetCommands()->Add("radar", _("enables the radar view"), COMMAND_RadarMap, true, true); - g_pCore->GetCommands()->Add("radar_zoom_in", _("zooms the radar in"), COMMAND_RadarZoomIn, true, true); - g_pCore->GetCommands()->Add("radar_zoom_out", _("zooms the radar out"), COMMAND_RadarZoomOut, true, true); - g_pCore->GetCommands()->Add("radar_move_north", _("moves the radar north"), COMMAND_RadarMoveNorth, true, true); - g_pCore->GetCommands()->Add("radar_move_south", _("moves the radar south"), COMMAND_RadarMoveSouth, true, true); - g_pCore->GetCommands()->Add("radar_move_east", _("moves the radar east"), COMMAND_RadarMoveEast, true, true); - g_pCore->GetCommands()->Add("radar_move_west", _("moves the radar west"), COMMAND_RadarMoveWest, true, true); - g_pCore->GetCommands()->Add("radar_attach", _("attaches the radar"), COMMAND_RadarAttach, true, true); - g_pCore->GetCommands()->Add("radar_opacity_down", _("reduces radar opacity"), COMMAND_RadarOpacityDown, true, true); - g_pCore->GetCommands()->Add("radar_opacity_up", _("increases radar opacity"), COMMAND_RadarOpacityUp, true, true); - g_pCore->GetCommands()->Add("radar_help", _("toggles radar help text"), COMMAND_RadarHelp, true, true); + g_pCore->GetCommands()->Add("radar", _("enables the player-map view"), COMMAND_PlayerMap, true, true); + g_pCore->GetCommands()->Add("radar_zoom_in", _("zooms the player-map in"), COMMAND_PlayerMapZoomIn, true, true); + g_pCore->GetCommands()->Add("radar_zoom_out", _("zooms the player-map out"), COMMAND_PlayerMapZoomOut, true, true); + g_pCore->GetCommands()->Add("radar_move_north", _("moves the player-map north"), COMMAND_PlayerMapMoveNorth, true, true); + g_pCore->GetCommands()->Add("radar_move_south", _("moves the player-map south"), COMMAND_PlayerMapMoveSouth, true, true); + g_pCore->GetCommands()->Add("radar_move_east", _("moves the player-map east"), COMMAND_PlayerMapMoveEast, true, true); + g_pCore->GetCommands()->Add("radar_move_west", _("moves the player-map west"), COMMAND_PlayerMapMoveWest, true, true); + g_pCore->GetCommands()->Add("radar_attach", _("attaches the player-map"), COMMAND_PlayerMapAttach, true, true); + g_pCore->GetCommands()->Add("radar_opacity_down", _("reduces player-map opacity"), COMMAND_PlayerMapOpacityDown, true, true); + g_pCore->GetCommands()->Add("radar_opacity_up", _("increases player-map opacity"), COMMAND_PlayerMapOpacityUp, true, true); + g_pCore->GetCommands()->Add("radar_help", _("toggles player-map help text"), COMMAND_PlayerMapHelp, true, true); g_pCore->GetCommands()->Add("msg_target", _("sends a message to the targetted player"), COMMAND_MessageTarget, true); g_pCore->GetCommands()->Add("vehicle_next_weapon", _("changes to the next weapon whilst in a vehicle"), COMMAND_VehicleNextWeapon, true); g_pCore->GetCommands()->Add("vehicle_previous_weapon", _("changes to the previous weapon whilst in a vehicle"), COMMAND_VehiclePreviousWeapon, true); diff --git a/Client/mods/deathmatch/ClientCommands.cpp b/Client/mods/deathmatch/ClientCommands.cpp index 6ca4d73625..123ee59dcb 100644 --- a/Client/mods/deathmatch/ClientCommands.cpp +++ b/Client/mods/deathmatch/ClientCommands.cpp @@ -235,154 +235,137 @@ void COMMAND_Screenshot ( const char* szCmdLine ) } */ -void COMMAND_RadarMap(const char* szCmdLine) +void COMMAND_PlayerMap(const char* szCmdLine) { - int iCmd = (szCmdLine && szCmdLine[0]) ? atoi(szCmdLine) : -1; - bool bShow = (iCmd == 1) ? true : (iCmd == 0) ? false : !g_pClientGame->GetRadarMap()->GetRadarEnabled(); - g_pClientGame->GetRadarMap()->SetRadarEnabled(bShow); + int cmd = (szCmdLine && szCmdLine[0]) ? atoi(szCmdLine) : -1; + bool show = (cmd == 1) ? true : (cmd == 0) ? false : !g_pClientGame->GetPlayerMap()->GetPlayerMapEnabled(); + g_pClientGame->GetPlayerMap()->SetPlayerMapEnabled(show); } -void COMMAND_RadarZoomIn(const char* szCmdLine) +void COMMAND_PlayerMapZoomIn(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); - - if (pRadarMap->IsRadarShowing()) - { - pRadarMap->ZoomIn(); - } + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (playerMap->IsPlayerMapShowing()) + playerMap->ZoomIn(); } -void COMMAND_RadarZoomOut(const char* szCmdLine) +void COMMAND_PlayerMapZoomOut(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); - - if (pRadarMap->IsRadarShowing()) - { - pRadarMap->ZoomOut(); - } + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (playerMap->IsPlayerMapShowing()) + playerMap->ZoomOut(); } -void COMMAND_RadarMoveNorth(const char* szCmdLine) +void COMMAND_PlayerMapMoveNorth(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (!playerMap->IsPlayerMapShowing()) + return; - if (pRadarMap->IsRadarShowing()) + if (playerMap->IsMovingNorth()) + playerMap->SetMovingNorth(false); + else if (playerMap->IsMovingSouth()) + playerMap->SetMovingSouth(false); + else { - // Toggle on/off - if (pRadarMap->IsMovingNorth()) - pRadarMap->SetMovingNorth(false); - else if (pRadarMap->IsMovingSouth()) - pRadarMap->SetMovingSouth(false); - else - { - pRadarMap->SetMovingNorth(true); - pRadarMap->SetMovingSouth(false); - pRadarMap->SetMovingEast(false); - pRadarMap->SetMovingWest(false); - } + playerMap->SetMovingNorth(true); + playerMap->SetMovingSouth(false); + playerMap->SetMovingEast(false); + playerMap->SetMovingWest(false); } } -void COMMAND_RadarMoveSouth(const char* szCmdLine) +void COMMAND_PlayerMapMoveSouth(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (!playerMap->IsPlayerMapShowing()) + return; - if (pRadarMap->IsRadarShowing()) + if (playerMap->IsMovingSouth()) + playerMap->SetMovingSouth(false); + else if (playerMap->IsMovingNorth()) + playerMap->SetMovingNorth(false); + else { - // Toggle on/off - if (pRadarMap->IsMovingSouth()) - pRadarMap->SetMovingSouth(false); - else if (pRadarMap->IsMovingNorth()) - pRadarMap->SetMovingNorth(false); - else - { - pRadarMap->SetMovingNorth(false); - pRadarMap->SetMovingSouth(true); - pRadarMap->SetMovingEast(false); - pRadarMap->SetMovingWest(false); - } + playerMap->SetMovingNorth(false); + playerMap->SetMovingSouth(true); + playerMap->SetMovingEast(false); + playerMap->SetMovingWest(false); } } -void COMMAND_RadarMoveEast(const char* szCmdLine) +void COMMAND_PlayerMapMoveEast(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (!playerMap->IsPlayerMapShowing()) + return; - if (pRadarMap->IsRadarShowing()) + if (playerMap->IsMovingEast()) + playerMap->SetMovingEast(false); + else if (playerMap->IsMovingWest()) + playerMap->SetMovingWest(false); + else { - // Toggle on/off - if (pRadarMap->IsMovingEast()) - pRadarMap->SetMovingEast(false); - else if (pRadarMap->IsMovingWest()) - pRadarMap->SetMovingWest(false); - else - { - pRadarMap->SetMovingNorth(false); - pRadarMap->SetMovingSouth(false); - pRadarMap->SetMovingEast(true); - pRadarMap->SetMovingWest(false); - } + playerMap->SetMovingNorth(false); + playerMap->SetMovingSouth(false); + playerMap->SetMovingEast(true); + playerMap->SetMovingWest(false); } } -void COMMAND_RadarMoveWest(const char* szCmdLine) +void COMMAND_PlayerMapMoveWest(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (!playerMap->IsPlayerMapShowing()) + return; - if (pRadarMap->IsRadarShowing()) + if (playerMap->IsMovingWest()) + playerMap->SetMovingWest(false); + else if (playerMap->IsMovingEast()) + playerMap->SetMovingEast(false); + else { - // Toggle on/off - if (pRadarMap->IsMovingWest()) - pRadarMap->SetMovingWest(false); - else if (pRadarMap->IsMovingEast()) - pRadarMap->SetMovingEast(false); - else - { - pRadarMap->SetMovingNorth(false); - pRadarMap->SetMovingSouth(false); - pRadarMap->SetMovingEast(false); - pRadarMap->SetMovingWest(true); - } + playerMap->SetMovingNorth(false); + playerMap->SetMovingSouth(false); + playerMap->SetMovingEast(false); + playerMap->SetMovingWest(true); } } -void COMMAND_RadarAttach(const char* szCmdLine) +void COMMAND_PlayerMapAttach(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); - - if (pRadarMap->IsRadarShowing()) - { - pRadarMap->SetAttachedToLocalPlayer(!g_pClientGame->GetRadarMap()->IsAttachedToLocalPlayer()); - } + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (playerMap->IsPlayerMapShowing()) + playerMap->SetAttachedToLocalPlayer(!g_pClientGame->GetPlayerMap()->IsAttachedToLocalPlayer()); } -void COMMAND_RadarOpacityDown(const char* szCmdLine) +void COMMAND_PlayerMapOpacityDown(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); - if (pRadarMap->IsRadarShowing()) - { - int iAlpha; - g_pCore->GetCVars()->Get("mapalpha", iAlpha); - iAlpha = std::max(0, iAlpha - 20); - g_pCore->GetCVars()->Set("mapalpha", iAlpha); - } + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (!playerMap->IsPlayerMapShowing()) + return; + + int mapAlpha; + g_pCore->GetCVars()->Get("mapalpha", mapAlpha); + mapAlpha = std::max(0, mapAlpha - 20); + g_pCore->GetCVars()->Set("mapalpha", mapAlpha); } -void COMMAND_RadarOpacityUp(const char* szCmdLine) +void COMMAND_PlayerMapOpacityUp(const char* szCmdLine) { - CRadarMap* pRadarMap = g_pClientGame->GetRadarMap(); - if (pRadarMap->IsRadarShowing()) - { - int iAlpha; - g_pCore->GetCVars()->Get("mapalpha", iAlpha); - iAlpha = std::min(255, iAlpha + 20); - g_pCore->GetCVars()->Set("mapalpha", iAlpha); - } + CPlayerMap* playerMap = g_pClientGame->GetPlayerMap(); + if (!playerMap->IsPlayerMapShowing()) + return; + + int mapAlpha; + g_pCore->GetCVars()->Get("mapalpha", mapAlpha); + mapAlpha = std::min(255, mapAlpha + 20); + g_pCore->GetCVars()->Set("mapalpha", mapAlpha); } -void COMMAND_RadarHelp(const char* szCmdLine) +void COMMAND_PlayerMapHelp(const char* szCmdLine) { - g_pClientGame->GetRadarMap()->ToggleHelpText(); + g_pClientGame->GetPlayerMap()->ToggleHelpText(); } void COMMAND_MessageTarget(const char* szCmdLine) diff --git a/Client/mods/deathmatch/ClientCommands.h b/Client/mods/deathmatch/ClientCommands.h index c6aa755099..af31db12d4 100644 --- a/Client/mods/deathmatch/ClientCommands.h +++ b/Client/mods/deathmatch/ClientCommands.h @@ -21,17 +21,17 @@ void COMMAND_ShowNetstat(const char* szCmdLine); void COMMAND_EnterPassenger(const char* szCmdLine); void COMMAND_RadioNext(const char* szCmdLine); void COMMAND_RadioPrevious(const char* szCmdLine); -void COMMAND_RadarMap(const char* szCmdLine); -void COMMAND_RadarZoomIn(const char* szCmdLine); -void COMMAND_RadarZoomOut(const char* szCmdLine); -void COMMAND_RadarMoveNorth(const char* szCmdLine); -void COMMAND_RadarMoveSouth(const char* szCmdLine); -void COMMAND_RadarMoveEast(const char* szCmdLine); -void COMMAND_RadarMoveWest(const char* szCmdLine); -void COMMAND_RadarAttach(const char* szCmdLine); -void COMMAND_RadarOpacityDown(const char* szCmdLine); -void COMMAND_RadarOpacityUp(const char* szCmdLine); -void COMMAND_RadarHelp(const char* szCmdLine); +void COMMAND_PlayerMap(const char* szCmdLine); +void COMMAND_PlayerMapZoomIn(const char* szCmdLine); +void COMMAND_PlayerMapZoomOut(const char* szCmdLine); +void COMMAND_PlayerMapMoveNorth(const char* szCmdLine); +void COMMAND_PlayerMapMoveSouth(const char* szCmdLine); +void COMMAND_PlayerMapMoveEast(const char* szCmdLine); +void COMMAND_PlayerMapMoveWest(const char* szCmdLine); +void COMMAND_PlayerMapAttach(const char* szCmdLine); +void COMMAND_PlayerMapOpacityDown(const char* szCmdLine); +void COMMAND_PlayerMapOpacityUp(const char* szCmdLine); +void COMMAND_PlayerMapHelp(const char* szCmdLine); void COMMAND_MessageTarget(const char* szCmdLine); void COMMAND_VehicleNextWeapon(const char* szCmdLine); void COMMAND_VehiclePreviousWeapon(const char* szCmdLine); diff --git a/Client/mods/deathmatch/logic/CClientBuildingManager.cpp b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp index 243917b89f..a09df6a226 100644 --- a/Client/mods/deathmatch/logic/CClientBuildingManager.cpp +++ b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp @@ -73,11 +73,6 @@ bool CClientBuildingManager::IsValidModel(uint16_t modelId) if (!pModelInfo->IsAllocatedInArchive()) return false; - if (pModelInfo->IsDynamic()) - { - return false; - } - eModelInfoType eType = pModelInfo->GetModelType(); return (eType == eModelInfoType::CLUMP || eType == eModelInfoType::ATOMIC || eType == eModelInfoType::WEAPON || eType == eModelInfoType::TIME); } @@ -106,29 +101,9 @@ void CClientBuildingManager::RestoreDestroyed() { const CClientBuilding* highLodBuilding = building->GetHighLodBuilding(); if (highLodBuilding && !highLodBuilding->IsValid()) - { hasInvalidLods = true; - } else - { - CModelInfo* modelInfo = building->GetModelInfo(); - const uint16_t physicalGroup = modelInfo->GetObjectPropertiesGroup(); - - if (physicalGroup == -1) - { - building->Create(); - } - else - { - // GTA creates dynamic models as dummies. - // It's possible that the physical group was changes after - // creating a new building. We can avoid crashes in this case. - modelInfo->SetObjectPropertiesGroup(-1); - building->Create(); - modelInfo->SetObjectPropertiesGroup(physicalGroup); - } - - } + building->Create(); } } } diff --git a/Client/mods/deathmatch/logic/CClientGUIManager.cpp b/Client/mods/deathmatch/logic/CClientGUIManager.cpp index b2eb23322c..8b3db9650a 100644 --- a/Client/mods/deathmatch/logic/CClientGUIManager.cpp +++ b/Client/mods/deathmatch/logic/CClientGUIManager.cpp @@ -43,7 +43,7 @@ void CClientGUIManager::DeleteAll() bool CClientGUIManager::Exists(CClientGUIElement* pGUIElement) { - return m_Elements.Contains(pGUIElement); + return pGUIElement ? m_Elements.Contains(pGUIElement) : false; } bool CClientGUIManager::Exists(CGUIElement* pCGUIElement) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index bc20947eac..99eb78de34 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -34,6 +34,7 @@ #include #include #include "game/CClock.h" +#include #include #include "CServerInfo.h" @@ -135,6 +136,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_Glitches[GLITCH_BADDRIVEBYHITBOX] = false; m_Glitches[GLITCH_QUICKSTAND] = false; m_Glitches[GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE] = false; + g_pMultiplayer->DisableBadDrivebyHitboxes(true); // Remove Night & Thermal vision view (if enabled). @@ -227,7 +229,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_pObjectSync = new CObjectSync(m_pObjectManager); #endif m_pNametags = new CNametags(m_pManager); - m_pRadarMap = new CRadarMap(m_pManager); + m_pPlayerMap = new CPlayerMap(m_pManager); // Set the screenshot path /* This is now done in CCore, to maintain a global screenshot path @@ -402,6 +404,10 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) CClientGame::~CClientGame() { m_bBeingDeleted = true; + // Remove active projectile references to local player + if (auto pLocalPlayer = g_pClientGame->GetLocalPlayer()) + g_pGame->GetProjectileInfo()->RemoveEntityReferences(pLocalPlayer->GetGameEntity()); + // Stop all explosions. Unfortunately this doesn't fix the crash // if a vehicle is destroyed while it explodes. g_pGame->GetExplosionManager()->RemoveAllExplosions(); @@ -548,7 +554,7 @@ CClientGame::~CClientGame() #endif SAFE_DELETE(m_pBlendedWeather); SAFE_DELETE(m_pMovingObjectsManager); - SAFE_DELETE(m_pRadarMap); + SAFE_DELETE(m_pPlayerMap); SAFE_DELETE(m_pRemoteCalls); SAFE_DELETE(m_pLuaManager); SAFE_DELETE(m_pLatentTransferManager); @@ -1097,7 +1103,7 @@ void CClientGame::DoPulsePostFrame() CClientPerfStatManager::GetSingleton()->DoPulse(); } - m_pRadarMap->DoRender(); + m_pPlayerMap->DoRender(); m_pManager->DoRender(); DoPulses(); @@ -1435,8 +1441,8 @@ void CClientGame::DoPulses() } // Check for radar input - m_pRadarMap->DoPulse(); - g_pCore->GetGraphics()->SetAspectRatioAdjustmentSuspended(m_pRadarMap->IsRadarShowing()); + m_pPlayerMap->DoPulse(); + g_pCore->GetGraphics()->SetAspectRatioAdjustmentSuspended(m_pPlayerMap->IsPlayerMapShowing()); // Got a local player? if (m_pLocalPlayer) @@ -2778,6 +2784,7 @@ void CClientGame::AddBuiltInEvents() m_Events.AddEvent("onClientBrowserTooltip", "text", NULL, false); m_Events.AddEvent("onClientBrowserInputFocusChanged", "gainedfocus", NULL, false); m_Events.AddEvent("onClientBrowserResourceBlocked", "url, domain, reason", NULL, false); + m_Events.AddEvent("onClientBrowserConsoleMessage", "message, source, line, level", nullptr, false); // Misc events m_Events.AddEvent("onClientFileDownloadComplete", "fileName, success", NULL, false); @@ -5406,8 +5413,8 @@ void CClientGame::ResetMapInfo() // Keybinds g_pCore->GetKeyBinds()->SetAllControlsEnabled(true, true, true); - // Radarmap - m_pRadarMap->SetForcedState(false); + // Player map + m_pPlayerMap->SetForcedState(false); // Camera m_pCamera->FadeOut(0.0f, 0, 0, 0); @@ -5456,10 +5463,6 @@ void CClientGame::ResetMapInfo() // Players m_pPlayerManager->ResetAll(); - // Reset Frozen Time - g_pGame->GetClock()->ResetTimeFrozen(); - g_pGame->GetSettings()->ResetVolumetricShadows(); - // Disable the change of any player stats g_pMultiplayer->SetLocalStatsStatic(true); @@ -5985,7 +5988,7 @@ bool CClientGame::IsGlitchEnabled(unsigned char ucGlitch) return ucGlitch < NUM_GLITCHES && m_Glitches[ucGlitch]; } -bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool isEnabled) +bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool isEnabled) noexcept { switch (property) { @@ -5993,44 +5996,60 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is case WorldSpecialProperty::AIRCARS: case WorldSpecialProperty::EXTRABUNNY: case WorldSpecialProperty::EXTRAJUMP: - return g_pGame->SetCheatEnabled(EnumToString(property), isEnabled); + g_pGame->SetCheatEnabled(EnumToString(property), isEnabled); + break; case WorldSpecialProperty::RANDOMFOLIAGE: g_pGame->SetRandomFoliageEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::SNIPERMOON: g_pGame->SetMoonEasterEggEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::EXTRAAIRRESISTANCE: g_pGame->SetExtraAirResistanceEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::UNDERWORLDWARP: g_pGame->SetUnderWorldWarpEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::VEHICLESUNGLARE: g_pGame->SetVehicleSunGlareEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::CORONAZTEST: g_pGame->SetCoronaZTestEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::WATERCREATURES: g_pGame->SetWaterCreaturesEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::BURNFLIPPEDCARS: g_pGame->SetBurnFlippedCarsEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::FIREBALLDESTRUCT: g_pGame->SetFireballDestructEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::EXTENDEDWATERCANNONS: g_pGame->SetExtendedWaterCannonsEnabled(isEnabled); + break; case WorldSpecialProperty::ROADSIGNSTEXT: g_pGame->SetRoadSignsTextEnabled(isEnabled); - return true; + break; case WorldSpecialProperty::TUNNELWEATHERBLEND: g_pGame->SetTunnelWeatherBlendEnabled(isEnabled); - return true; + break; + case WorldSpecialProperty::IGNOREFIRESTATE: + g_pGame->SetIgnoreFireStateEnabled(isEnabled); + break; + default: + return false; } - return false; + + if (g_pNet->CanServerBitStream(eBitStreamVersion::WorldSpecialPropertyEvent)) { + NetBitStreamInterface* stream = g_pNet->AllocateNetBitStream(); + stream->WriteString(EnumToString(property)); + stream->WriteBit(isEnabled); + g_pNet->SendPacket(PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY, stream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(stream); + } + + return true; } bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property) @@ -6066,6 +6085,8 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property) return g_pGame->IsRoadSignsTextEnabled(); case WorldSpecialProperty::TUNNELWEATHERBLEND: return g_pGame->IsTunnelWeatherBlendEnabled(); + case WorldSpecialProperty::IGNOREFIRESTATE: + return g_pGame->IsIgnoreFireStateEnabled(); } return false; } @@ -6479,7 +6500,7 @@ void CClientGame::OutputServerInfo() { SString strEnabledGlitches; const char* szGlitchNames[] = {"Quick reload", "Fast fire", "Fast move", "Crouch bug", "Close damage", "Hit anim", "Fast sprint", - "Bad driveby hitboxes", "Quick stand"}; + "Bad driveby hitboxes", "Quick stand", "Kickout of vehicle on model replace"}; for (uint i = 0; i < NUM_GLITCHES; i++) { if (IsGlitchEnabled(i)) @@ -6887,6 +6908,12 @@ void CClientGame::ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo // Reset volumetric shadows g_pGame->GetSettings()->ResetVolumetricShadows(); + + // Reset Frozen Time + g_pGame->GetClock()->ResetTimeFrozen(); + + // Reset DynamicPedShadows + g_pGame->GetSettings()->ResetDynamicPedShadows(); } void CClientGame::OnWindowFocusChange(bool state) diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index ba6bc29334..e887199fcd 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -28,7 +28,7 @@ #include "CUnoccupiedVehicleSync.h" #include "CPedSync.h" #include "CObjectSync.h" -#include "CRadarMap.h" +#include "CPlayerMap.h" #include "CClientTeamManager.h" #include "CClientPedManager.h" #include "lua/CLuaManager.h" @@ -296,7 +296,7 @@ class CClientGame CBlendedWeather* GetBlendedWeather() { return m_pBlendedWeather; }; CNetAPI* GetNetAPI() { return m_pNetAPI; }; - CRadarMap* GetRadarMap() { return m_pRadarMap; }; + CPlayerMap* GetPlayerMap() { return m_pPlayerMap; }; CMovingObjectsManager* GetMovingObjectsManager() { return m_pMovingObjectsManager; } CClientPlayer* GetLocalPlayer() { return m_pLocalPlayer; } @@ -410,7 +410,7 @@ class CClientGame bool SetGlitchEnabled(unsigned char cGlitch, bool bEnabled); bool IsGlitchEnabled(unsigned char cGlitch); - bool SetWorldSpecialProperty(WorldSpecialProperty property, bool isEnabled); + bool SetWorldSpecialProperty(WorldSpecialProperty property, bool isEnabled) noexcept; bool IsWorldSpecialProperty(WorldSpecialProperty property); bool SetCloudsEnabled(bool bEnabled); @@ -694,7 +694,7 @@ class CClientGame CNetworkStats* m_pNetworkStats; CSyncDebug* m_pSyncDebug; // CScreenshot* m_pScreenshot; - CRadarMap* m_pRadarMap; + CPlayerMap* m_pPlayerMap; CTransferBox* m_pTransferBox; CResourceManager* m_pResourceManager; CScriptKeyBinds* m_pScriptKeyBinds; diff --git a/Client/mods/deathmatch/logic/CClientObject.cpp b/Client/mods/deathmatch/logic/CClientObject.cpp index 7d34045f1b..de1cdaad50 100644 --- a/Client/mods/deathmatch/logic/CClientObject.cpp +++ b/Client/mods/deathmatch/logic/CClientObject.cpp @@ -668,7 +668,7 @@ void CClientObject::SetMoveSpeed(const CVector& vecMoveSpeed) { if (m_pObject) { - m_pObject->SetMoveSpeed(const_cast(&vecMoveSpeed)); + m_pObject->SetMoveSpeed(vecMoveSpeed); } m_vecMoveSpeed = vecMoveSpeed; } diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index f4c9ba5ee6..b20189dd5e 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -831,7 +831,7 @@ void CClientPed::SetMoveSpeed(const CVector& vecMoveSpeed) { if (m_pPlayerPed) { - m_pPlayerPed->SetMoveSpeed(const_cast(&vecMoveSpeed)); + m_pPlayerPed->SetMoveSpeed(vecMoveSpeed); } m_vecMoveSpeed = vecMoveSpeed; } @@ -1131,7 +1131,7 @@ CClientVehicle* CClientPed::GetRealOccupiedVehicle() CClientVehicle* CClientPed::GetClosestEnterableVehicle(bool bGetPositionFromClosestDoor, bool bCheckDriverDoor, bool bCheckPassengerDoors, bool bCheckStreamedOutVehicles, unsigned int* uiClosestDoor, CVector* pClosestDoorPosition, - float fWithinRange) + float fWithinRange, bool localVehicles) { if (bGetPositionFromClosestDoor) { @@ -1163,8 +1163,8 @@ CClientVehicle* CClientPed::GetClosestEnterableVehicle(bool bGetPositionFromClos for (; iter != listEnd; iter++) { pTempVehicle = *iter; - // Skip clientside vehicles as they are not enterable - if (pTempVehicle->IsLocalEntity()) + + if (pTempVehicle->IsLocalEntity() != localVehicles) continue; CVehicle* pGameVehicle = pTempVehicle->GetGameVehicle(); @@ -2683,9 +2683,6 @@ void CClientPed::WorldIgnore(bool bIgnore) void CClientPed::StreamedInPulse(bool bDoStandardPulses) { - if (!m_pPlayerPed) - return; - // ControllerState checks and fixes are done at the same same as everything else unless using alt pulse order bool bDoControllerStateFixPulse = g_pClientGame->IsUsingAlternatePulseOrder() ? !bDoStandardPulses : bDoStandardPulses; @@ -2714,6 +2711,10 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses) // Do we have a player? (streamed in) if (m_pPlayerPed) { + // If it's local entity, update in/out vehicle state + if (IsLocalEntity()) + UpdateVehicleInOut(); + // Handle waiting for the ground to load if (IsFrozenWaitingForGroundToLoad()) HandleWaitingForGroundToLoad(); @@ -2754,7 +2755,7 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses) { CVector vecTemp; m_pPlayerPed->SetMatrix(&m_matFrozen); - m_pPlayerPed->SetMoveSpeed(&vecTemp); + m_pPlayerPed->SetMoveSpeed(vecTemp); } // Is our health locked? @@ -3612,7 +3613,7 @@ void CClientPed::_CreateModel() m_pPlayerPed->SetMatrix(&m_Matrix); m_pPlayerPed->SetCurrentRotation(m_fCurrentRotation); m_pPlayerPed->SetTargetRotation(m_fTargetRotation); - m_pPlayerPed->SetMoveSpeed(&m_vecMoveSpeed); + m_pPlayerPed->SetMoveSpeed(m_vecMoveSpeed); m_pPlayerPed->SetTurnSpeed(&m_vecTurnSpeed); Duck(m_bDucked); SetWearingGoggles(m_bWearingGoggles); @@ -6400,7 +6401,7 @@ void CClientPed::UpdateStreamPosition(const CVector& vecInPosition) bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger) { // Are we local player or ped we are syncing - if (!IsSyncing() && !IsLocalPlayer()) + if (!IsSyncing() && !IsLocalPlayer() && !IsLocalEntity()) { return false; } @@ -6456,7 +6457,7 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger) if (!pVehicle) { // Find the closest vehicle and door - CClientVehicle* pClosestVehicle = GetClosestEnterableVehicle(true, !bPassenger, bPassenger, false, &uiDoor, nullptr, 20.0f); + CClientVehicle* pClosestVehicle = GetClosestEnterableVehicle(true, !bPassenger, bPassenger, false, &uiDoor, nullptr, 20.0f, IsLocalEntity()); if (pClosestVehicle) { pVehicle = pClosestVehicle; @@ -6478,7 +6479,7 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger) return false; } - if (!pVehicle->IsEnterable()) + if (!pVehicle->IsEnterable(IsLocalEntity())) { // Stop if the vehicle is not enterable return false; @@ -6553,6 +6554,32 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger) return false; } + if (IsLocalEntity()) + { + // If vehicle is not local, we can't enter it + if (!pVehicle->IsLocalEntity()) + return false; + + // Set the vehicle id we're about to enter + m_VehicleInOutID = pVehicle->GetID(); + m_ucVehicleInOutSeat = uiSeat; + m_bIsJackingVehicle = false; + + // Make ped enter vehicle + GetIntoVehicle(pVehicle, uiSeat, uiDoor); + + // Remember that this ped is working on entering a vehicle + SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); + + pVehicle->CalcAndUpdateCanBeDamagedFlag(); + pVehicle->CalcAndUpdateTyresCanBurstFlag(); + + m_bIsGettingIntoVehicle = true; + m_bIsGettingOutOfVehicle = false; + + return true; + } + // Send an in request NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); if (!pBitStream) @@ -6602,7 +6629,7 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger) bool CClientPed::ExitVehicle() { // Are we local player or ped we are syncing - if (!IsSyncing() && !IsLocalPlayer()) + if (!IsSyncing() && !IsLocalPlayer() && !IsLocalEntity()) { return false; } @@ -6627,6 +6654,7 @@ bool CClientPed::ExitVehicle() return false; } + // Check the server is compatible if we are a ped if (!IsLocalPlayer() && !g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) { @@ -6654,6 +6682,37 @@ bool CClientPed::ExitVehicle() return false; } + std::int8_t targetDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pPlayerPed, pOccupiedVehicle->GetGameVehicle()); + + // If it's a local entity, we can just exit the vehicle + if (IsLocalEntity()) + { + // Set the vehicle id and the seat we're about to exit from + m_VehicleInOutID = pOccupiedVehicle->GetID(); + m_ucVehicleInOutSeat = GetOccupiedVehicleSeat(); + + // Call the onClientVehicleStartExit event for the ped + // Check if it is cancelled before making the ped exit the vehicle + CLuaArguments arguments; + arguments.PushElement(this); // player / ped + arguments.PushNumber(m_ucVehicleInOutSeat); // seat + arguments.PushNumber(0); // door + + if (!pOccupiedVehicle->CallEvent("onClientVehicleStartExit", arguments, true)) // Event has been cancelled + return false; + + // Make ped exit vehicle + GetOutOfVehicle(targetDoor); + + // Remember that this ped is working on leaving a vehicle + SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT); + + m_bIsGettingIntoVehicle = false; + m_bIsGettingOutOfVehicle = true; + + return true; + } + // We're about to exit a vehicle // Send an out request NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); @@ -6673,11 +6732,10 @@ bool CClientPed::ExitVehicle() unsigned char ucAction = static_cast(CClientGame::VEHICLE_REQUEST_OUT); pBitStream->WriteBits(&ucAction, 4); - unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pPlayerPed, pOccupiedVehicle->GetGameVehicle()); - if (ucDoor >= 2 && ucDoor <= 5) + if (targetDoor >= 2 && targetDoor <= 5) { - ucDoor -= 2; - pBitStream->WriteBits(&ucDoor, 2); + targetDoor -= 2; + pBitStream->WriteBits(&targetDoor, 2); } // Send and destroy it @@ -6719,6 +6777,56 @@ void CClientPed::ResetVehicleInOut() ////////////////////////////////////////////////////////////////// void CClientPed::UpdateVehicleInOut() { + if (IsLocalEntity()) + { + // If getting inside vehicle + if (m_bIsGettingIntoVehicle) + { + CClientVehicle* vehicle = GetRealOccupiedVehicle(); + if (!vehicle) + return; + + // Call the onClientVehicleEnter event for the ped + // Check if it is cancelled before allowing the ped to enter the vehicle + CLuaArguments arguments; + arguments.PushElement(this); // player / ped + arguments.PushNumber(m_ucVehicleInOutSeat); // seat + + if (!vehicle->CallEvent("onClientVehicleEnter", arguments, true)) + { + m_bIsGettingIntoVehicle = false; + RemoveFromVehicle(); + return; + } + + m_bIsGettingIntoVehicle = false; + m_VehicleInOutID = INVALID_ELEMENT_ID; + WarpIntoVehicle(vehicle, m_ucVehicleInOutSeat); + SetVehicleInOutState(VEHICLE_INOUT_NONE); + } + else if (m_bIsGettingOutOfVehicle) + { + // If getting out of vehicle + CClientVehicle* realVehicle = GetRealOccupiedVehicle(); + CClientVehicle* networkVehicle = GetOccupiedVehicle(); + + if (realVehicle) + return; + + // Call the onClientVehicleExit event for the ped + CLuaArguments arguments; + arguments.PushElement(this); // player / ped + arguments.PushNumber(m_ucVehicleInOutSeat); // seat + networkVehicle->CallEvent("onClientVehicleExit", arguments, true); + + m_bIsGettingOutOfVehicle = false; + m_VehicleInOutID = INVALID_ELEMENT_ID; + SetVehicleInOutState(VEHICLE_INOUT_NONE); + } + + return; + } + // We got told by the server to animate into a certain vehicle? if (m_VehicleInOutID != INVALID_ELEMENT_ID) { @@ -6729,59 +6837,56 @@ void CClientPed::UpdateVehicleInOut() if (m_bIsGettingOutOfVehicle) { // If we aren't working on leaving the car (he's eiter finished or cancelled/failed leaving) - if (!IsLeavingVehicle()) + if (IsLeavingVehicle()) + return; + + // Are we outside the car? + CClientVehicle* pVehicle = GetRealOccupiedVehicle(); + if (pVehicle) + { + // Warp us out now to keep in sync with the server + RemoveFromVehicle(); + return; + } + // Tell the server that we successfully left the car + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (pBitStream) { - // Are we outside the car? - CClientVehicle* pVehicle = GetRealOccupiedVehicle(); - if (!pVehicle) + // Write the ped ID to it + if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) { - // Tell the server that we successfully left the car - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) - { - // Write the ped ID to it - if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) - { - pBitStream->Write(GetID()); - } + pBitStream->Write(GetID()); + } - // Write the car id and the action id (enter complete) - pBitStream->Write(m_VehicleInOutID); - unsigned char ucAction = CClientGame::VEHICLE_NOTIFY_OUT; - pBitStream->WriteBits(&ucAction, 4); + // Write the car id and the action id (enter complete) + pBitStream->Write(m_VehicleInOutID); + unsigned char ucAction = CClientGame::VEHICLE_NOTIFY_OUT; + pBitStream->WriteBits(&ucAction, 4); - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); - } + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); + } - // Warp ourself out (so we're sure the records are correct) - RemoveFromVehicle(); + // Warp ourself out (so we're sure the records are correct) + RemoveFromVehicle(); - if (pInOutVehicle) - { - pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); - pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); - } + if (pInOutVehicle) + { + pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); + pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); + } - // Reset the vehicle in out stuff so we're ready for another car entry/leave. - // Don't allow a new entry/leave until we've gotten the notify return packet - ElementID ReasonVehicleID = m_VehicleInOutID; - ResetVehicleInOut(); - m_bNoNewVehicleTask = true; - m_NoNewVehicleTaskReasonID = ReasonVehicleID; + // Reset the vehicle in out stuff so we're ready for another car entry/leave. + // Don't allow a new entry/leave until we've gotten the notify return packet + ElementID ReasonVehicleID = m_VehicleInOutID; + ResetVehicleInOut(); + m_bNoNewVehicleTask = true; + m_NoNewVehicleTaskReasonID = ReasonVehicleID; #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_out"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_out"); #endif - } - // Are we still inside the car? - else - { - // Warp us out now to keep in sync with the server - RemoveFromVehicle(); - } - } } // Are we getting into a vehicle? @@ -6789,144 +6894,144 @@ void CClientPed::UpdateVehicleInOut() { // If we aren't working on entering the car (he's either finished or cancelled) // Or we are dead (fix for #908) or we are in water (fix for #521) - if (!IsEnteringVehicle() || IsDead() || IsInWater()) + if (IsEnteringVehicle() && !IsDead() && !IsInWater()) + return; + + // Is he in a vehicle now? + CClientVehicle* pVehicle = GetRealOccupiedVehicle(); + if (pVehicle) { - // Is he in a vehicle now? - CClientVehicle* pVehicle = GetRealOccupiedVehicle(); - if (pVehicle) + // Tell the server that we successfully entered the car + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (pBitStream) { - // Tell the server that we successfully entered the car - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) + // Write the ped or player ID to it + if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) { - // Write the ped or player ID to it - if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) - { - pBitStream->Write(GetID()); - } + pBitStream->Write(GetID()); + } - // Write the car id and the action id (enter complete) - pBitStream->Write(m_VehicleInOutID); - unsigned char ucAction; + // Write the car id and the action id (enter complete) + pBitStream->Write(m_VehicleInOutID); + unsigned char ucAction; - if (m_bIsJackingVehicle) - { - ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_JACK); + if (m_bIsJackingVehicle) + { + ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_JACK); #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack"); #endif - } - else - { - ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_IN); + } + else + { + ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_IN); #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in"); #endif - } - pBitStream->WriteBits(&ucAction, 4); - - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); } + pBitStream->WriteBits(&ucAction, 4); - // Warp ourself in (so we're sure the records are correct) - pVehicle->AllowDoorRatioSetting(m_ucEnteringDoor, true); - WarpIntoVehicle(pVehicle, m_ucVehicleInOutSeat); + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); + } - if (pInOutVehicle) - { - pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); - pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); - } + // Warp ourself in (so we're sure the records are correct) + pVehicle->AllowDoorRatioSetting(m_ucEnteringDoor, true); + WarpIntoVehicle(pVehicle, m_ucVehicleInOutSeat); + + if (pInOutVehicle) + { + pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); + pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); } - else + } + else + { + // Tell the server that we aborted entered the car + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (pBitStream) { - // Tell the server that we aborted entered the car - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) + // Write the ped or player ID to it + if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) { - // Write the ped or player ID to it - if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) - { - pBitStream->Write(GetID()); - } + pBitStream->Write(GetID()); + } - // Write the car id and the action id (enter complete) - pBitStream->Write(m_VehicleInOutID); - unsigned char ucAction; - if (m_bIsJackingVehicle) - { - ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_JACK_ABORT); - pBitStream->WriteBits(&ucAction, 4); + // Write the car id and the action id (enter complete) + pBitStream->Write(m_VehicleInOutID); + unsigned char ucAction; + if (m_bIsJackingVehicle) + { + ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_JACK_ABORT); + pBitStream->WriteBits(&ucAction, 4); - // Did we start jacking them? - bool bAlreadyStartedJacking = false; - CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); - if (pVehicle) + // Did we start jacking them? + bool bAlreadyStartedJacking = false; + CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); + if (pVehicle) + { + CClientPed* pJackedPlayer = pVehicle->GetOccupant(); + if (pJackedPlayer) { - CClientPed* pJackedPlayer = pVehicle->GetOccupant(); - if (pJackedPlayer) + // Jax: have we already started to jack the other player? + if (pJackedPlayer->IsGettingJacked()) { - // Jax: have we already started to jack the other player? - if (pJackedPlayer->IsGettingJacked()) - { - bAlreadyStartedJacking = true; - } + bAlreadyStartedJacking = true; } - unsigned char ucDoor = m_ucEnteringDoor - 2; - pBitStream->WriteBits(&ucDoor, 3); - SDoorOpenRatioSync door; - door.data.fRatio = pVehicle->GetDoorOpenRatio(m_ucEnteringDoor); - pBitStream->Write(&door); } - pBitStream->WriteBit(bAlreadyStartedJacking); + unsigned char ucDoor = m_ucEnteringDoor - 2; + pBitStream->WriteBits(&ucDoor, 3); + SDoorOpenRatioSync door; + door.data.fRatio = pVehicle->GetDoorOpenRatio(m_ucEnteringDoor); + pBitStream->Write(&door); + } + pBitStream->WriteBit(bAlreadyStartedJacking); #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack_abort"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack_abort"); #endif - } - else + } + else + { + ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_IN_ABORT); + pBitStream->WriteBits(&ucAction, 4); + CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); + if (pVehicle) { - ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_IN_ABORT); - pBitStream->WriteBits(&ucAction, 4); - CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); - if (pVehicle) - { - unsigned char ucDoor = m_ucEnteringDoor - 2; - pBitStream->WriteBits(&ucDoor, 3); - SDoorOpenRatioSync door; - door.data.fRatio = pVehicle->GetDoorOpenRatio(m_ucEnteringDoor); - pBitStream->Write(&door); - } + unsigned char ucDoor = m_ucEnteringDoor - 2; + pBitStream->WriteBits(&ucDoor, 3); + SDoorOpenRatioSync door; + door.data.fRatio = pVehicle->GetDoorOpenRatio(m_ucEnteringDoor); + pBitStream->Write(&door); + } #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in_abort"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in_abort"); #endif - } - - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); } - // Warp ourself out again (so we're sure the records are correct) - RemoveFromVehicle(); - - if (pInOutVehicle) - { - pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); - pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); - } + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); } - // Reset - // Don't allow a new entry/leave until we've gotten the notify return packet - ElementID ReasonID = m_VehicleInOutID; - ResetVehicleInOut(); - m_bNoNewVehicleTask = true; - m_NoNewVehicleTaskReasonID = ReasonID; + // Warp ourself out again (so we're sure the records are correct) + RemoveFromVehicle(); + + if (pInOutVehicle) + { + pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); + pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); + } } + + // Reset + // Don't allow a new entry/leave until we've gotten the notify return packet + ElementID ReasonID = m_VehicleInOutID; + ResetVehicleInOut(); + m_bNoNewVehicleTask = true; + m_NoNewVehicleTaskReasonID = ReasonID; } } else @@ -6936,75 +7041,75 @@ void CClientPed::UpdateVehicleInOut() return; // If we aren't getting jacked - if (!m_bIsGettingJacked) - { - CClientVehicle* pVehicle = GetRealOccupiedVehicle(); - CClientVehicle* pOccupiedVehicle = GetOccupiedVehicle(); + if (m_bIsGettingJacked) + return; + + CClientVehicle* pVehicle = GetRealOccupiedVehicle(); + CClientVehicle* pOccupiedVehicle = GetOccupiedVehicle(); - // Jax: this was commented, re-comment if it was there for a reason (..and give the reason!) - // Are we in a vehicle we aren't supposed to be in? - if (pVehicle && !pOccupiedVehicle) - { - g_pCore->GetConsole()->Print("You shouldn't be in this vehicle"); - RemoveFromVehicle(); - } + // Jax: this was commented, re-comment if it was there for a reason (..and give the reason!) + // Are we in a vehicle we aren't supposed to be in? + if (pVehicle && !pOccupiedVehicle) + { + g_pCore->GetConsole()->Print("You shouldn't be in this vehicle"); + RemoveFromVehicle(); + } - // Are we supposed to be in a vehicle? But aren't? - if (pOccupiedVehicle && !pVehicle && !IsWarpInToVehicleRequired()) - { - // Jax: this happens when we try to warp into a streamed out vehicle, including when we use CClientVehicle::StreamInNow - // ..maybe we need a different way to detect bike falls? + // Are we supposed to be in a vehicle? But aren't? + if (!pOccupiedVehicle || pVehicle || IsWarpInToVehicleRequired()) + return; + + // Jax: this happens when we try to warp into a streamed out vehicle, including when we use CClientVehicle::StreamInNow + // ..maybe we need a different way to detect bike falls? - // Tell the server - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) - { - // Write the ped or player ID to it - if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) - { - pBitStream->Write(GetID()); - } + // Tell the server + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (!pBitStream) + return; + + // Write the ped or player ID to it + if (g_pNet->CanServerBitStream(eBitStreamVersion::PedEnterExit)) + { + pBitStream->Write(GetID()); + } - // Vehicle id - pBitStream->Write(pOccupiedVehicle->GetID()); - unsigned char ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_FELL_OFF); - pBitStream->WriteBits(&ucAction, 4); + // Vehicle id + pBitStream->Write(pOccupiedVehicle->GetID()); + unsigned char ucAction = static_cast(CClientGame::VEHICLE_NOTIFY_FELL_OFF); + pBitStream->WriteBits(&ucAction, 4); - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); - // We're not allowed to enter any vehicle before we get a confirm - m_bNoNewVehicleTask = true; - m_NoNewVehicleTaskReasonID = pOccupiedVehicle->GetID(); + // We're not allowed to enter any vehicle before we get a confirm + m_bNoNewVehicleTask = true; + m_NoNewVehicleTaskReasonID = pOccupiedVehicle->GetID(); - // Remove him from the vehicle - RemoveFromVehicle(); + // Remove him from the vehicle + RemoveFromVehicle(); - /* - // Make it undamagable if we're not syncing it - CDeathmatchVehicle* pInOutVehicle = static_cast < CDeathmatchVehicle* > ( pOccupiedVehicle ); - if ( pInOutVehicle ) - { - if ( pInOutVehicle->IsSyncing () ) - { - pInOutVehicle->SetCanBeDamaged ( true ); - pInOutVehicle->SetTyresCanBurst ( true ); - } - else - { - pInOutVehicle->SetCanBeDamaged ( false ); - pInOutVehicle->SetTyresCanBurst ( false ); - } - } - */ + /* + // Make it undamagable if we're not syncing it + CDeathmatchVehicle* pInOutVehicle = static_cast < CDeathmatchVehicle* > ( pOccupiedVehicle ); + if ( pInOutVehicle ) + { + if ( pInOutVehicle->IsSyncing () ) + { + pInOutVehicle->SetCanBeDamaged ( true ); + pInOutVehicle->SetTyresCanBurst ( true ); + } + else + { + pInOutVehicle->SetCanBeDamaged ( false ); + pInOutVehicle->SetTyresCanBurst ( false ); + } + } + */ #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_fell_off"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_fell_off"); #endif - } - } - } } } diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 6998856774..38cefbadfa 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -253,7 +253,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule CClientVehicle* GetRealOccupiedVehicle(); CClientVehicle* GetClosestEnterableVehicle(bool bGetPositionFromClosestDoor, bool bCheckDriverDoor, bool bCheckPassengerDoors, bool bCheckStreamedOutVehicles, unsigned int* uiClosestDoor = NULL, CVector* pClosestDoorPosition = NULL, - float fWithinRange = 6000.0f); + float fWithinRange = 6000.0f, bool localVehicles = false); bool GetClosestDoor(CClientVehicle* pVehicle, bool bCheckDriverDoor, bool bCheckPassengerDoors, unsigned int& uiClosestDoor, CVector* pClosestDoorPosition = NULL); diff --git a/Client/mods/deathmatch/logic/CClientProjectile.cpp b/Client/mods/deathmatch/logic/CClientProjectile.cpp index 43f2d1930d..048334da6a 100644 --- a/Client/mods/deathmatch/logic/CClientProjectile.cpp +++ b/Client/mods/deathmatch/logic/CClientProjectile.cpp @@ -289,7 +289,7 @@ void CClientProjectile::GetVelocity(CVector& vecVelocity) void CClientProjectile::SetVelocity(CVector& vecVelocity) { if (m_pProjectile) - m_pProjectile->SetMoveSpeed(&vecVelocity); + m_pProjectile->SetMoveSpeed(vecVelocity); } unsigned short CClientProjectile::GetModel() diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index de6a612938..2c5ef561ef 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -55,30 +55,30 @@ CClientVehicle::CClientVehicle(CClientManager* pManager, ElementID ID, unsigned m_pModelInfo = g_pGame->GetModelInfo(usModel); // Apply handling - ushort usHandlingModelID = m_usModel; + std::uint16_t usHandlingModelID = m_usModel; if (m_usModel < 400 || m_usModel > 611) usHandlingModelID = m_pModelInfo->GetParentID(); - m_pOriginalHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(static_cast(usHandlingModelID)); - m_pHandlingEntry = g_pGame->GetHandlingManager()->CreateHandlingData(); - m_pHandlingEntry->Assign(m_pOriginalHandlingEntry); + m_pOriginalHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(usHandlingModelID); + m_HandlingEntry = g_pGame->GetHandlingManager()->CreateHandlingData(); + m_HandlingEntry->Assign(m_pOriginalHandlingEntry); - m_pOriginalFlyingHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalFlyingHandlingData(static_cast(usHandlingModelID)); - m_pFlyingHandlingEntry = g_pGame->GetHandlingManager()->CreateFlyingHandlingData(); - m_pFlyingHandlingEntry->Assign(m_pOriginalFlyingHandlingEntry); + m_pOriginalFlyingHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalFlyingHandlingData(usHandlingModelID); + m_FlyingHandlingEntry = g_pGame->GetHandlingManager()->CreateFlyingHandlingData(); + m_FlyingHandlingEntry->Assign(m_pOriginalFlyingHandlingEntry); - m_pOriginalBoatHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBoatHandlingData(static_cast(usHandlingModelID)); + m_pOriginalBoatHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBoatHandlingData(usHandlingModelID); if (m_pOriginalBoatHandlingEntry) { - m_pBoatHandlingEntry = g_pGame->GetHandlingManager()->CreateBoatHandlingData(); - m_pBoatHandlingEntry->Assign(m_pOriginalBoatHandlingEntry); + m_BoatHandlingEntry = g_pGame->GetHandlingManager()->CreateBoatHandlingData(); + m_BoatHandlingEntry->Assign(m_pOriginalBoatHandlingEntry); } - m_pOriginalBikeHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBikeHandlingData(static_cast(usHandlingModelID)); + m_pOriginalBikeHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBikeHandlingData(usHandlingModelID); if (m_pOriginalBikeHandlingEntry) { - m_pBikeHandlingEntry = g_pGame->GetHandlingManager()->CreateBikeHandlingData(); - m_pBikeHandlingEntry->Assign(m_pOriginalBikeHandlingEntry); + m_BikeHandlingEntry = g_pGame->GetHandlingManager()->CreateBikeHandlingData(); + m_BikeHandlingEntry->Assign(m_pOriginalBikeHandlingEntry); } SetTypeName("vehicle"); @@ -277,10 +277,6 @@ CClientVehicle::~CClientVehicle() Unlink(); delete m_pUpgrades; - delete m_pHandlingEntry; - delete m_pFlyingHandlingEntry; - delete m_pBoatHandlingEntry; - delete m_pBikeHandlingEntry; delete m_LastSyncedData; CClientEntityRefManager::RemoveEntityRefs(0, &m_pDriver, &m_pOccupyingDriver, &m_pPreviousLink, &m_pNextLink, &m_pTowedVehicle, &m_pTowedByVehicle, &m_pPickedUpWinchEntity, NULL); @@ -361,7 +357,7 @@ void CClientVehicle::SetPosition(const CVector& vecPosition, bool bResetInterpol if (vecMoveSpeed.fX == 0.0f && vecMoveSpeed.fY == 0.0f && vecMoveSpeed.fZ == 0.0f) { vecMoveSpeed.fZ -= 0.01f; - m_pVehicle->SetMoveSpeed(&vecMoveSpeed); + m_pVehicle->SetMoveSpeed(vecMoveSpeed); } } } @@ -564,7 +560,7 @@ void CClientVehicle::SetMoveSpeed(const CVector& vecMoveSpeed) if (!m_bIsFrozen) { if (m_pVehicle) - m_pVehicle->SetMoveSpeed(const_cast(&vecMoveSpeed)); + m_pVehicle->SetMoveSpeed(vecMoveSpeed); m_vecMoveSpeed = vecMoveSpeed; @@ -1055,32 +1051,32 @@ void CClientVehicle::SetModelBlocking(unsigned short usModel, unsigned char ucVa // Reset handling to fit the vehicle if (IsLocalEntity() || !(usModel < 400 || usModel > 611)) { - ushort usHandlingModelID = usModel; + std::uint16_t usHandlingModelID = usModel; if (usHandlingModelID < 400 || usHandlingModelID > 611) usHandlingModelID = m_pModelInfo->GetParentID(); - m_pOriginalHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData((eVehicleTypes)usHandlingModelID); - m_pHandlingEntry->Assign(m_pOriginalHandlingEntry); + m_pOriginalHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(usHandlingModelID); + m_HandlingEntry->Assign(m_pOriginalHandlingEntry); - m_pOriginalFlyingHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalFlyingHandlingData((eVehicleTypes)usHandlingModelID); - m_pFlyingHandlingEntry->Assign(m_pOriginalFlyingHandlingEntry); + m_pOriginalFlyingHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalFlyingHandlingData(usHandlingModelID); + m_FlyingHandlingEntry->Assign(m_pOriginalFlyingHandlingEntry); - m_pOriginalBoatHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBoatHandlingData((eVehicleTypes)usHandlingModelID); + m_pOriginalBoatHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBoatHandlingData(usHandlingModelID); if (m_pOriginalBoatHandlingEntry) { - if (!m_pBoatHandlingEntry) - m_pBoatHandlingEntry = g_pGame->GetHandlingManager()->CreateBoatHandlingData(); + if (!m_BoatHandlingEntry) + m_BoatHandlingEntry = g_pGame->GetHandlingManager()->CreateBoatHandlingData(); - m_pBoatHandlingEntry->Assign(m_pOriginalBoatHandlingEntry); + m_BoatHandlingEntry->Assign(m_pOriginalBoatHandlingEntry); } - m_pOriginalBikeHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBikeHandlingData((eVehicleTypes)usHandlingModelID); + m_pOriginalBikeHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalBikeHandlingData(usHandlingModelID); if (m_pOriginalBikeHandlingEntry) { - if (!m_pBikeHandlingEntry) - m_pBikeHandlingEntry = g_pGame->GetHandlingManager()->CreateBikeHandlingData(); + if (!m_BikeHandlingEntry) + m_BikeHandlingEntry = g_pGame->GetHandlingManager()->CreateBikeHandlingData(); - m_pBikeHandlingEntry->Assign(m_pOriginalBikeHandlingEntry); + m_BikeHandlingEntry->Assign(m_pOriginalBikeHandlingEntry); } } @@ -1815,7 +1811,7 @@ void CClientVehicle::SetFrozen(bool bFrozen) if (m_pVehicle) { m_pVehicle->GetMatrix(&m_matFrozen); - m_pVehicle->SetMoveSpeed(&vecTemp); + m_pVehicle->SetMoveSpeed(vecTemp); m_pVehicle->SetTurnSpeed(&vecTemp); } else @@ -1835,7 +1831,7 @@ void CClientVehicle::SetFrozen(bool bFrozen) if (m_pVehicle) { m_pVehicle->GetMatrix(&m_matFrozen); - m_pVehicle->SetMoveSpeed(&vecTemp); + m_pVehicle->SetMoveSpeed(vecTemp); m_pVehicle->SetTurnSpeed(&vecTemp); } else @@ -1876,7 +1872,7 @@ void CClientVehicle::SetFrozenWaitingForGroundToLoad(bool bFrozen, bool bSuspend if (m_pVehicle) { m_pVehicle->GetMatrix(&m_matFrozen); - m_pVehicle->SetMoveSpeed(&vecTemp); + m_pVehicle->SetMoveSpeed(vecTemp); m_pVehicle->SetTurnSpeed(&vecTemp); } else @@ -1900,7 +1896,7 @@ void CClientVehicle::SetFrozenWaitingForGroundToLoad(bool bFrozen, bool bSuspend m_vecTurnSpeed = m_vecWaitingForGroundSavedTurnSpeed; if (m_pVehicle) { - m_pVehicle->SetMoveSpeed(&m_vecMoveSpeed); + m_pVehicle->SetMoveSpeed(m_vecMoveSpeed); m_pVehicle->SetTurnSpeed(&m_vecTurnSpeed); } m_bAsyncLoadingDisabled = false; @@ -2240,7 +2236,7 @@ void CClientVehicle::StreamedInPulse() { CVector vecTemp; m_pVehicle->SetMatrix(&m_matFrozen); - m_pVehicle->SetMoveSpeed(&vecTemp); + m_pVehicle->SetMoveSpeed(vecTemp); m_pVehicle->SetTurnSpeed(&vecTemp); } else @@ -2262,7 +2258,7 @@ void CClientVehicle::StreamedInPulse() { m_pVehicle->SetMatrix(&m_matFrozen); CVector vec(0.0f, 0.0f, 0.0f); - m_pVehicle->SetMoveSpeed(&vec); + m_pVehicle->SetMoveSpeed(vec); } // Added by ChrML 27. Nov: Shouldn't cause any problems m_pVehicle->SetUsesCollision(false); @@ -2493,13 +2489,12 @@ void CClientVehicle::Create() // Create the vehicle if (CClientVehicleManager::IsTrainModel(m_usModel)) { - DWORD dwModels[1]; - dwModels[0] = m_usModel; - m_pVehicle = g_pGame->GetPools()->AddTrain(this, &m_Matrix.vPos, dwModels, 1, m_bTrainDirection, m_ucTrackID); + std::vector Models{m_usModel}; + m_pVehicle = g_pGame->GetPools()->AddTrain(this, m_Matrix.vPos, Models, m_bTrainDirection, m_ucTrackID); } else { - m_pVehicle = g_pGame->GetPools()->AddVehicle(this, static_cast(m_usModel), m_ucVariation, m_ucVariation2); + m_pVehicle = g_pGame->GetPools()->AddVehicle(this, m_usModel, m_ucVariation, m_ucVariation2); } // Failed. Remove our reference to the vehicle model and return @@ -2735,7 +2730,7 @@ void CClientVehicle::Create() m_vecMoveSpeed.fZ > -0.01f) { m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.01f); - m_pVehicle->SetMoveSpeed(&m_vecMoveSpeed); + m_pVehicle->SetMoveSpeed(m_vecMoveSpeed); } // Validate @@ -2755,19 +2750,19 @@ void CClientVehicle::Create() SetWindowOpen(i, m_bWindowOpen[i]); // Re-apply handling entry - if (m_pHandlingEntry) + if (m_HandlingEntry) { - m_pVehicle->SetHandlingData(m_pHandlingEntry); - m_pVehicle->SetFlyingHandlingData(m_pFlyingHandlingEntry); + m_pVehicle->SetHandlingData(m_HandlingEntry.get()); + m_pVehicle->SetFlyingHandlingData(m_FlyingHandlingEntry.get()); switch (m_eVehicleType) { case CLIENTVEHICLE_BOAT: - dynamic_cast(m_pVehicle)->SetBoatHandlingData(m_pBoatHandlingEntry); + dynamic_cast(m_pVehicle)->SetBoatHandlingData(m_BoatHandlingEntry.get()); break; case CLIENTVEHICLE_BIKE: case CLIENTVEHICLE_BMX: - dynamic_cast(m_pVehicle)->SetBikeHandlingData(m_pBikeHandlingEntry); + dynamic_cast(m_pVehicle)->SetBikeHandlingData(m_BikeHandlingEntry.get()); break; } @@ -2932,17 +2927,17 @@ void CClientVehicle::Destroy() m_bIsOnGround = IsOnGround(); m_fHeliRotorSpeed = GetHeliRotorSpeed(); m_bHeliSearchLightVisible = IsHeliSearchLightVisible(); - m_pHandlingEntry = m_pVehicle->GetHandlingData(); - m_pFlyingHandlingEntry = m_pVehicle->GetFlyingHandlingData(); + m_HandlingEntry->Assign(m_pVehicle->GetHandlingData()); + m_FlyingHandlingEntry->Assign(m_pVehicle->GetFlyingHandlingData()); switch (m_eVehicleType) { case CLIENTVEHICLE_BOAT: - m_pBoatHandlingEntry = dynamic_cast(m_pVehicle)->GetBoatHandlingData(); + m_BoatHandlingEntry->Assign(dynamic_cast(m_pVehicle)->GetBoatHandlingData()); break; case CLIENTVEHICLE_BIKE: case CLIENTVEHICLE_BMX: - m_pBikeHandlingEntry = dynamic_cast(m_pVehicle)->GetBikeHandlingData(); + m_BikeHandlingEntry->Assign(dynamic_cast(m_pVehicle)->GetBikeHandlingData()); break; default: break; @@ -3772,12 +3767,12 @@ void CClientVehicle::UpdateTargetPosition() if (m_eVehicleType != CLIENTVEHICLE_HELI && m_eVehicleType != CLIENTVEHICLE_BOAT) { // Ghostmode upwards movement compensation - CVector MoveSpeed; - m_pVehicle->GetMoveSpeed(&MoveSpeed); - float SpeedXY = CVector(MoveSpeed.fX, MoveSpeed.fY, 0).Length(); - if (MoveSpeed.fZ > 0.00 && MoveSpeed.fZ < 0.02 && MoveSpeed.fZ > SpeedXY) - MoveSpeed.fZ = SpeedXY; - m_pVehicle->SetMoveSpeed(&MoveSpeed); + CVector vecMoveSpeed; + m_pVehicle->GetMoveSpeed(&vecMoveSpeed); + float SpeedXY = CVector(vecMoveSpeed.fX, vecMoveSpeed.fY, 0).Length(); + if (vecMoveSpeed.fZ > 0.00 && vecMoveSpeed.fZ < 0.02 && vecMoveSpeed.fZ > SpeedXY) + vecMoveSpeed.fZ = SpeedXY; + m_pVehicle->SetMoveSpeed(vecMoveSpeed); } } @@ -3877,25 +3872,22 @@ void CClientVehicle::UpdateUnderFloorFix(const CVector& vecTargetPosition, bool } } -bool CClientVehicle::IsEnterable() +bool CClientVehicle::IsEnterable(bool localEntity) { - if (m_pVehicle) - { - // Server vehicle? - if (!IsLocalEntity()) - { - if (GetHealth() > 0.0f) - { - if (!IsInWater() || (GetVehicleType() == CLIENTVEHICLE_BOAT || m_usModel == 447 /* sea sparrow */ - || m_usModel == 417 /* levithan */ - || m_usModel == 460 /* skimmer */)) - { - return true; - } - } - } - } - return false; + if (!m_pVehicle) + return false; + + // Server vehicle? + if (IsLocalEntity() != localEntity) + return false; + + if (GetHealth() <= 0.0f) + return false; + + return !IsInWater() || (GetVehicleType() == CLIENTVEHICLE_BOAT + || m_usModel == 447 /* sea sparrow */ + || m_usModel == 417 /* levithan */ + || m_usModel == 460 /* skimmer */); } bool CClientVehicle::HasRadio() @@ -4265,8 +4257,8 @@ CHandlingEntry* CClientVehicle::GetHandlingData() { if (m_pVehicle) return m_pVehicle->GetHandlingData(); - else if (m_pHandlingEntry) - return m_pHandlingEntry; + else if (m_HandlingEntry) + return m_HandlingEntry.get(); return nullptr; } @@ -4275,8 +4267,8 @@ CFlyingHandlingEntry* CClientVehicle::GetFlyingHandlingData() { if (m_pVehicle) return m_pVehicle->GetFlyingHandlingData(); - else if (m_pFlyingHandlingEntry) - return m_pFlyingHandlingEntry; + else if (m_FlyingHandlingEntry) + return m_FlyingHandlingEntry.get(); return nullptr; } @@ -4288,8 +4280,8 @@ CBoatHandlingEntry* CClientVehicle::GetBoatHandlingData() if (m_pVehicle) return reinterpret_cast(m_pVehicle)->GetBoatHandlingData(); - else if (m_pBoatHandlingEntry) - return m_pBoatHandlingEntry; + else if (m_BoatHandlingEntry) + return m_BoatHandlingEntry.get(); return nullptr; } @@ -4301,8 +4293,8 @@ CBikeHandlingEntry* CClientVehicle::GetBikeHandlingData() if (m_pVehicle) return reinterpret_cast(m_pVehicle)->GetBikeHandlingData(); - else if (m_pBikeHandlingEntry) - return m_pBikeHandlingEntry; + else if (m_BikeHandlingEntry) + return m_BikeHandlingEntry.get(); return nullptr; } @@ -4355,7 +4347,7 @@ void CClientVehicle::HandleWaitingForGroundToLoad() // Reset position CVector vecTemp; m_pVehicle->SetMatrix(&m_matFrozen); - m_pVehicle->SetMoveSpeed(&vecTemp); + m_pVehicle->SetMoveSpeed(vecTemp); m_pVehicle->SetTurnSpeed(&vecTemp); m_vecMoveSpeed = vecTemp; m_vecTurnSpeed = vecTemp; diff --git a/Client/mods/deathmatch/logic/CClientVehicle.h b/Client/mods/deathmatch/logic/CClientVehicle.h index 304d6dc291..4bb12c11f7 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.h +++ b/Client/mods/deathmatch/logic/CClientVehicle.h @@ -458,7 +458,7 @@ class CClientVehicle : public CClientStreamElement int GetCurrentGear(); - bool IsEnterable(); + bool IsEnterable(bool localEntity = false); bool HasRadio(); bool HasPoliceRadio(); @@ -655,13 +655,13 @@ class CClientVehicle : public CClientStreamElement float m_fHeliRotorSpeed; float m_fPlaneRotorSpeed; const CHandlingEntry* m_pOriginalHandlingEntry = nullptr; - CHandlingEntry* m_pHandlingEntry = nullptr; + std::unique_ptr m_HandlingEntry = nullptr; const CFlyingHandlingEntry* m_pOriginalFlyingHandlingEntry = nullptr; - CFlyingHandlingEntry* m_pFlyingHandlingEntry = nullptr; + std::unique_ptr m_FlyingHandlingEntry = nullptr; const CBoatHandlingEntry* m_pOriginalBoatHandlingEntry = nullptr; - CBoatHandlingEntry* m_pBoatHandlingEntry = nullptr; + std::unique_ptr m_BoatHandlingEntry = nullptr; const CBikeHandlingEntry* m_pOriginalBikeHandlingEntry = nullptr; - CBikeHandlingEntry* m_pBikeHandlingEntry = nullptr; + std::unique_ptr m_BikeHandlingEntry = nullptr; float m_fNitroLevel; char m_cNitroCount; float m_fWheelScale; diff --git a/Client/mods/deathmatch/logic/CClientWebBrowser.cpp b/Client/mods/deathmatch/logic/CClientWebBrowser.cpp index cf54f463e7..5284382d96 100644 --- a/Client/mods/deathmatch/logic/CClientWebBrowser.cpp +++ b/Client/mods/deathmatch/logic/CClientWebBrowser.cpp @@ -305,6 +305,16 @@ void CClientWebBrowser::Events_OnAjaxRequest(CAjaxResourceHandlerInterface* pHan pHandler->SetResponse(result); } +void CClientWebBrowser::Events_OnConsoleMessage(const std::string& message, const std::string& source, int line, std::int16_t level) +{ + CLuaArguments arguments; + arguments.PushString(message); + arguments.PushString(source); + arguments.PushNumber(line); + arguments.PushNumber(level); + CallEvent("onClientBrowserConsoleMessage", arguments, false); +} + bool CClientWebBrowser::AddAjaxHandler(const SString& strURL, ajax_callback_t& handler) { if (!m_pWebView->RegisterAjaxHandler(strURL)) diff --git a/Client/mods/deathmatch/logic/CClientWebBrowser.h b/Client/mods/deathmatch/logic/CClientWebBrowser.h index 09de6ce0af..9838d2a533 100644 --- a/Client/mods/deathmatch/logic/CClientWebBrowser.h +++ b/Client/mods/deathmatch/logic/CClientWebBrowser.h @@ -84,6 +84,7 @@ class CClientWebBrowser : public CClientTexture, public CWebBrowserEventsInterfa bool Events_OnResourceFileCheck(const SString& strURL, CBuffer& outFileData) override; void Events_OnResourceBlocked(const SString& strURL, const SString& strDomain, unsigned char reason) override; void Events_OnAjaxRequest(CAjaxResourceHandlerInterface* pHandler, const SString& strURL) override; + void Events_OnConsoleMessage(const std::string& message, const std::string& source, int line, std::int16_t level) override; private: CWebViewInterface* m_pWebView; diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index ebf2ba5140..787cd4c239 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -572,6 +572,10 @@ void CPacketHandler::Packet_ServerDisconnected(NetBitStreamInterface& bitStream) strReason = _("Disconnected: Serial verification failed"); strErrorCode = _E("CD44"); break; + case ePlayerDisconnectType::SERIAL_DUPLICATE: + strReason = _("Disconnected: Serial already in use"); + strErrorCode = _E("CD50"); + break; case ePlayerDisconnectType::CONNECTION_DESYNC: strReason = _("Disconnected: Connection desync %s"); strErrorCode = _E("CD45"); @@ -2393,6 +2397,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::ROADSIGNSTEXT, wsProps.data3.roadsignstext); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::TUNNELWEATHERBLEND, wsProps.data5.tunnelweatherblend); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::IGNOREFIRESTATE, wsProps.data6.ignoreFireState); float fJetpackMaxHeight = 100; if (!bitStream.Read(fJetpackMaxHeight)) diff --git a/Client/mods/deathmatch/logic/CPacketHandler.h b/Client/mods/deathmatch/logic/CPacketHandler.h index ca0f6f3d69..9a50b24615 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.h +++ b/Client/mods/deathmatch/logic/CPacketHandler.h @@ -42,7 +42,8 @@ class CPacketHandler BAN, KICK, CUSTOM, - SHUTDOWN + SHUTDOWN, + SERIAL_DUPLICATE }; struct SEntityDependantStuff diff --git a/Client/mods/deathmatch/logic/CRadarMap.cpp b/Client/mods/deathmatch/logic/CPlayerMap.cpp similarity index 71% rename from Client/mods/deathmatch/logic/CRadarMap.cpp rename to Client/mods/deathmatch/logic/CPlayerMap.cpp index 4dd01baccd..de1529972a 100644 --- a/Client/mods/deathmatch/logic/CRadarMap.cpp +++ b/Client/mods/deathmatch/logic/CPlayerMap.cpp @@ -2,8 +2,8 @@ * * PROJECT: Multi Theft Auto v1.0 * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CRadarMap.cpp - * PURPOSE: Full screen radar map renderer + * FILE: mods/deathmatch/logic/CPlayerMap.cpp + * PURPOSE: Full screen player map renderer * * Multi Theft Auto is available from http://www.multitheftauto.com/ * @@ -23,15 +23,19 @@ enum MARKER_LAST_SPRITE_INDEX = MARKER_FIRST_SPRITE_INDEX + RADAR_MARKER_LIMIT - 1, }; -CRadarMap::CRadarMap(CClientManager* pManager) +constexpr std::array MAP_IMAGE_SIZES = {1024, 2048}; + +CPlayerMap::CPlayerMap(CClientManager* pManager) { + m_failedToLoadTextures = false; + // Setup our managers m_pManager = pManager; m_pRadarMarkerManager = pManager->GetRadarMarkerManager(); m_pRadarAreaManager = m_pManager->GetRadarAreaManager(); - // Set the radar bools - m_bIsRadarEnabled = false; + // Set the map bools + m_bIsPlayerMapEnabled = false; m_bForcedState = false; m_bIsAttachedToLocal = false; m_bHideHelpText = false; @@ -52,17 +56,17 @@ CRadarMap::CRadarMap(CClientManager* pManager) m_fZoom = 1; m_iHorizontalMovement = 0; m_iVerticalMovement = 0; - SetupMapVariables(); - // Create the radar and local player blip images - m_pRadarImage = - g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(CalcMTASAPath("MTA\\cgui\\images\\radar.jpg"), NULL, false, 1024, 1024, RFORMAT_DXT1); - m_pLocalPlayerBlip = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(CalcMTASAPath("MTA\\cgui\\images\\radarset\\02.png")); + // Init texture vars + m_mapImageTexture = nullptr; + m_playerMarkerTexture = nullptr; - // Create the marker textures - CreateMarkerTextures(); + // Create all map textures + CreateAllTextures(); // Create the text displays for the help text + const SColorRGBA colorWhiteTransparent(255, 255, 255, 200); + const SColorRGBA colorWhite(255, 255, 255, 255); struct { SColor color; @@ -70,17 +74,15 @@ CRadarMap::CRadarMap(CClientManager* pManager) float fScale; SString strMessage; } messageList[] = { - {SColorRGBA(255, 255, 255, 200), 0.92f, 1.5f, "Current Mode: Kill all humans"}, - {SColorRGBA(255, 255, 255, 255), 0.95f, 1.0f, SString("Press %s to change mode.", *GetBoundKeyName("radar_attach"))}, - {SColorRGBA(255, 255, 255, 255), 0.05f, 1.0f, - SString("Press %s/%s to zoom in/out.", *GetBoundKeyName("radar_zoom_in"), *GetBoundKeyName("radar_zoom_out"))}, - {SColorRGBA(255, 255, 255, 255), 0.08f, 1.0f, - SString("Press %s, %s, %s, %s to navigate the map.", *GetBoundKeyName("radar_move_north"), *GetBoundKeyName("radar_move_east"), - *GetBoundKeyName("radar_move_south"), *GetBoundKeyName("radar_move_west"))}, - {SColorRGBA(255, 255, 255, 255), 0.11f, 1.0f, - SString("Press %s/%s to change opacity.", *GetBoundKeyName("radar_opacity_down"), *GetBoundKeyName("radar_opacity_up"))}, - {SColorRGBA(255, 255, 255, 255), 0.14f, 1.0f, SString("Press %s to hide the map.", *GetBoundKeyName("radar"))}, - {SColorRGBA(255, 255, 255, 255), 0.17f, 1.0f, SString("Press %s to hide this help text.", *GetBoundKeyName("radar_help"))}, + {colorWhiteTransparent, 0.92f, 1.5f, ""}, + {colorWhite, 0.95f, 1.0f, SString(_("Change mode: %s"), *GetBoundKeyName("radar_attach"))}, + + {colorWhite, 0.05f, 1.0f, SString(_("Zoom: %s/%s Movement: %s, %s, %s, %s Opacity: %s/%s"), + *GetBoundKeyName("radar_zoom_in"), *GetBoundKeyName("radar_zoom_out"), *GetBoundKeyName("radar_move_north"), + *GetBoundKeyName("radar_move_east"), *GetBoundKeyName("radar_move_south"), *GetBoundKeyName("radar_move_west"), + *GetBoundKeyName("radar_opacity_down"), *GetBoundKeyName("radar_opacity_up"))}, + {colorWhite, 0.07f, 1.0f, SString(_("Toggle map: %s Toggle help text: %s"), + *GetBoundKeyName("radar"), *GetBoundKeyName("radar_help"))}, }; for (uint i = 0; i < NUMELMS(messageList); i++) @@ -98,26 +100,82 @@ CRadarMap::CRadarMap(CClientManager* pManager) // Default to attached to player SetAttachedToLocalPlayer(true); + + SetupMapVariables(); } -CRadarMap::~CRadarMap() +CPlayerMap::~CPlayerMap() { // Delete our images - SAFE_RELEASE(m_pRadarImage); - SAFE_RELEASE(m_pLocalPlayerBlip); + SAFE_RELEASE(m_mapImageTexture); + SAFE_RELEASE(m_playerMarkerTexture); + for (uint i = 0; i < m_markerTextureList.size(); i++) + SAFE_RELEASE(m_markerTextureList[i]); + m_markerTextureList.clear(); - for (uint i = 0; i < m_MarkerTextureList.size(); i++) - SAFE_RELEASE(m_MarkerTextureList[i]); + // Don't need to delete the help texts as those are destroyed by the display manager +} - m_MarkerTextureList.clear(); +void CPlayerMap::CreateOrUpdateMapTexture() +{ + const std::uint32_t mapSize = MAP_IMAGE_SIZES[m_playerMapImageIndex]; + const SString fileName("MTA\\cgui\\images\\map_%d.png", mapSize); - // Don't need to delete the help texts as those are destroyed by the display manager + auto* newTexture = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(CalcMTASAPath(fileName), nullptr, false, mapSize, mapSize, RFORMAT_DXT1); + if (!newTexture) + throw std::runtime_error("Failed to load map image"); + + SAFE_RELEASE(m_mapImageTexture); + m_mapImageTexture = newTexture; +} + +void CPlayerMap::UpdateOrRevertMapTexture(std::size_t newImageIndex) +{ + const std::size_t oldImageIndex = m_playerMapImageIndex; + try + { + m_playerMapImageIndex = newImageIndex; + CreateOrUpdateMapTexture(); + } + catch (const std::exception& e) + { + m_playerMapImageIndex = oldImageIndex; + g_pCore->GetConsole()->Printf("Problem updating map image: %s", e.what()); + } +} + +void CPlayerMap::CreatePlayerBlipTexture() +{ + m_playerMarkerTexture = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(CalcMTASAPath("MTA\\cgui\\images\\radarset\\02.png")); + if (!m_playerMarkerTexture) + throw std::runtime_error("Failed to load player blip image"); +} + +void CPlayerMap::CreateAllTextures() +{ + try + { + // Create the map texture + m_playerMapImageIndex = g_pCore->GetCVars()->GetValue("mapimage"); + CreateOrUpdateMapTexture(); + + // Create the player blip texture + CreatePlayerBlipTexture(); + + // Create the other marker textures + CreateMarkerTextures(); + } + catch (const std::exception& e) + { + m_failedToLoadTextures = true; + g_pCore->GetConsole()->Printf("Problem initializing player map: %s", e.what()); + } } -void CRadarMap::DoPulse() +void CPlayerMap::DoPulse() { - // If our radar image exists - if (IsRadarShowing()) + // If our map image exists + if (IsPlayerMapShowing()) { // If we are following the local player blip if (m_bIsAttachedToLocal) @@ -154,11 +212,11 @@ void CRadarMap::DoPulse() } // -// Precreate all the textures for the radar map markers +// Precreate all the textures for the player map markers // -void CRadarMap::CreateMarkerTextures() +void CPlayerMap::CreateMarkerTextures() { - assert(m_MarkerTextureList.empty()); + m_markerTextureList.clear(); SString strRadarSetDirectory = CalcMTASAPath("MTA\\cgui\\images\\radarset\\"); // Load the 3 shapes @@ -166,25 +224,27 @@ void CRadarMap::CreateMarkerTextures() for (uint i = 0; i < NUMELMS(shapeFileNames); i++) { CTextureItem* pTextureItem = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(PathJoin(strRadarSetDirectory, shapeFileNames[i])); - m_MarkerTextureList.push_back(pTextureItem); + m_markerTextureList.push_back(pTextureItem); } - assert(m_MarkerTextureList.size() == MARKER_FIRST_SPRITE_INDEX); + if (m_markerTextureList.size() != MARKER_FIRST_SPRITE_INDEX) + throw std::runtime_error("Failed to load marker textures [1]"); // Load the icons for (uint i = 0; i < RADAR_MARKER_LIMIT; i++) { CTextureItem* pTextureItem = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(PathJoin(strRadarSetDirectory, SString("%02u.png", i + 1))); - m_MarkerTextureList.push_back(pTextureItem); + m_markerTextureList.push_back(pTextureItem); } - assert(m_MarkerTextureList.size() == MARKER_LAST_SPRITE_INDEX + 1); + if (m_markerTextureList.size() != MARKER_LAST_SPRITE_INDEX + 1) + throw std::runtime_error("Failed to load marker textures [2]"); } // // Get a texture for a marker, including scale and color // -CTextureItem* CRadarMap::GetMarkerTexture(CClientRadarMarker* pMarker, float fLocalZ, float* pfScale, SColor* pColor) +CTextureItem* CPlayerMap::GetMarkerTexture(CClientRadarMarker* pMarker, float fLocalZ, float* pfScale, SColor* pColor) { float fScale = pMarker->GetScale(); ulong ulSprite = pMarker->GetSprite(); @@ -220,26 +280,33 @@ CTextureItem* CRadarMap::GetMarkerTexture(CClientRadarMarker* pMarker, float fLo *pfScale = fScale; *pColor = color; - if (uiListIndex >= m_MarkerTextureList.size()) + if (uiListIndex >= m_markerTextureList.size()) return NULL; - return m_MarkerTextureList[uiListIndex]; + return m_markerTextureList[uiListIndex]; } -void CRadarMap::DoRender() +void CPlayerMap::DoRender() { - bool bIsRadarShowing = IsRadarShowing(); + bool isMapShowing = IsPlayerMapShowing(); - // Render if showing - if (bIsRadarShowing) + // Render if showing and textures are all loaded + if (isMapShowing && !m_failedToLoadTextures) { // Get the alpha value from the settings - int iRadarAlpha; - g_pCore->GetCVars()->Get("mapalpha", iRadarAlpha); + int mapAlpha; + g_pCore->GetCVars()->Get("mapalpha", mapAlpha); + const SColorARGB mapColor(mapAlpha, 255, 255, 255); + + // Update the image if the user changed it via a setting + auto mapImageIndex = g_pCore->GetCVars()->GetValue("mapimage"); + if (mapImageIndex != m_playerMapImageIndex) + { + UpdateOrRevertMapTexture(mapImageIndex); + } - g_pCore->GetGraphics()->DrawTexture(m_pRadarImage, static_cast(m_iMapMinX), static_cast(m_iMapMinY), - m_fMapSize / m_pRadarImage->m_uiSizeX, m_fMapSize / m_pRadarImage->m_uiSizeY, 0.0f, 0.0f, 0.0f, - SColorARGB(iRadarAlpha, 255, 255, 255)); + g_pCore->GetGraphics()->DrawTexture(m_mapImageTexture, static_cast(m_iMapMinX), static_cast(m_iMapMinY), + m_fMapSize / m_mapImageTexture->m_uiSizeX, m_fMapSize / m_mapImageTexture->m_uiSizeY, 0.0f, 0.0f, 0.0f, mapColor); // Grab the info for the local player blip CVector2D vecLocalPos; @@ -316,11 +383,11 @@ void CRadarMap::DoRender() } } - g_pCore->GetGraphics()->DrawTexture(m_pLocalPlayerBlip, vecLocalPos.fX, vecLocalPos.fY, 1.0, 1.0, vecLocalRot.fZ, 0.5f, 0.5f); + g_pCore->GetGraphics()->DrawTexture(m_playerMarkerTexture, vecLocalPos.fX, vecLocalPos.fY, 1.0, 1.0, vecLocalRot.fZ, 0.5f, 0.5f); } // Update visibility of help text - bool bRequiredTextVisible = bIsRadarShowing && !m_bHideHelpText; + bool bRequiredTextVisible = isMapShowing && !m_bHideHelpText; if (bRequiredTextVisible != m_bTextVisible) { m_bTextVisible = bRequiredTextVisible; @@ -331,31 +398,31 @@ void CRadarMap::DoRender() } } -void CRadarMap::SetRadarEnabled(bool bIsRadarEnabled) +void CPlayerMap::SetPlayerMapEnabled(bool show) { - bool bAlreadyEnabled = (m_bIsRadarEnabled || m_bForcedState); - bool bWillShow = (bIsRadarEnabled || m_bForcedState); - if (bAlreadyEnabled != bWillShow) + bool alreadyEnabled = (m_bIsPlayerMapEnabled || m_bForcedState); + bool definitiveShow = (show || m_bForcedState); + if (alreadyEnabled != definitiveShow) { - InternalSetRadarEnabled(bWillShow); + InternalSetPlayerMapEnabled(definitiveShow); } - m_bIsRadarEnabled = bIsRadarEnabled; + m_bIsPlayerMapEnabled = show; } -void CRadarMap::SetForcedState(bool bState) +void CPlayerMap::SetForcedState(bool state) { - bool bAlreadyShowing = (m_bIsRadarEnabled || m_bForcedState); - bool bWillShow = (m_bIsRadarEnabled || bState); - if (bAlreadyShowing != bWillShow) + bool currState = (m_bIsPlayerMapEnabled || m_bForcedState); + bool definitiveState = (m_bIsPlayerMapEnabled || state); + if (currState != definitiveState) { - InternalSetRadarEnabled(bWillShow); + InternalSetPlayerMapEnabled(definitiveState); } - m_bForcedState = bState; + m_bForcedState = state; } -void CRadarMap::InternalSetRadarEnabled(bool bEnabled) +void CPlayerMap::InternalSetPlayerMapEnabled(bool enable) { - if (bEnabled) + if (enable) { m_bChatVisible = g_pCore->IsChatVisible(); m_bChatInputBlocked = g_pCore->IsChatInputBlocked(); @@ -375,7 +442,7 @@ void CRadarMap::InternalSetRadarEnabled(bool bEnabled) } } -bool CRadarMap::CalculateEntityOnScreenPosition(CClientEntity* pEntity, CVector2D& vecLocalPos) +bool CPlayerMap::CalculateEntityOnScreenPosition(CClientEntity* pEntity, CVector2D& vecLocalPos) { // If the entity exists if (pEntity) @@ -406,7 +473,7 @@ bool CRadarMap::CalculateEntityOnScreenPosition(CClientEntity* pEntity, CVector2 return false; } -bool CRadarMap::CalculateEntityOnScreenPosition(CVector vecPosition, CVector2D& vecLocalPos) +bool CPlayerMap::CalculateEntityOnScreenPosition(CVector vecPosition, CVector2D& vecLocalPos) { // Adjust to the map variables and create the map ratio float fX = vecPosition.fX + 3000.0f; @@ -428,7 +495,7 @@ bool CRadarMap::CalculateEntityOnScreenPosition(CVector vecPosition, CVector2D& return false; } -void CRadarMap::SetupMapVariables() +void CPlayerMap::SetupMapVariables() { // Calculate the map size and the middle of the screen coords m_fMapSize = static_cast(m_uiHeight * m_fZoom); @@ -524,7 +591,7 @@ void CRadarMap::SetupMapVariables() } } -void CRadarMap::ZoomIn() +void CPlayerMap::ZoomIn() { if (m_fZoom <= 4) { @@ -533,7 +600,7 @@ void CRadarMap::ZoomIn() } } -void CRadarMap::ZoomOut() +void CPlayerMap::ZoomOut() { if (m_fZoom >= 1) { @@ -559,7 +626,7 @@ void CRadarMap::ZoomOut() } } -void CRadarMap::MoveNorth() +void CPlayerMap::MoveNorth() { if (!m_bIsAttachedToLocal) { @@ -579,7 +646,7 @@ void CRadarMap::MoveNorth() } } -void CRadarMap::MoveSouth() +void CPlayerMap::MoveSouth() { if (!m_bIsAttachedToLocal) { @@ -599,7 +666,7 @@ void CRadarMap::MoveSouth() } } -void CRadarMap::MoveEast() +void CPlayerMap::MoveEast() { if (!m_bIsAttachedToLocal) { @@ -619,7 +686,7 @@ void CRadarMap::MoveEast() } } -void CRadarMap::MoveWest() +void CPlayerMap::MoveWest() { if (!m_bIsAttachedToLocal) { @@ -639,30 +706,26 @@ void CRadarMap::MoveWest() } } -void CRadarMap::SetAttachedToLocalPlayer(bool bIsAttachedToLocal) +void CPlayerMap::SetAttachedToLocalPlayer(bool bIsAttachedToLocal) { m_bIsAttachedToLocal = bIsAttachedToLocal; SetupMapVariables(); if (m_bIsAttachedToLocal) - { - m_HelpTextList[0]->SetCaption("Current Mode: Attached to local player"); - } + m_HelpTextList[0]->SetCaption(_("Following Player")); else - { - m_HelpTextList[0]->SetCaption("Current Mode: Free Move"); - } + m_HelpTextList[0]->SetCaption(_("Free Movement")); } -bool CRadarMap::IsRadarShowing() +bool CPlayerMap::IsPlayerMapShowing() { - return ((m_bIsRadarEnabled || m_bForcedState) && m_pRadarImage && m_pLocalPlayerBlip && (!g_pCore->GetConsole()->IsVisible() && !g_pCore->IsMenuVisible())); + return ((m_bIsPlayerMapEnabled || m_bForcedState) && m_mapImageTexture && m_playerMarkerTexture && (!g_pCore->GetConsole()->IsVisible() && !g_pCore->IsMenuVisible())); } -bool CRadarMap::GetBoundingBox(CVector& vecMin, CVector& vecMax) +bool CPlayerMap::GetBoundingBox(CVector& vecMin, CVector& vecMax) { - // If our radar image exists (Values are not calculated unless map is showing) - if (IsRadarShowing()) + // If our map image exists (Values are not calculated unless map is showing) + if (IsPlayerMapShowing()) { vecMin.fX = static_cast(m_iMapMinX); vecMin.fY = static_cast(m_iMapMinY); @@ -678,12 +741,12 @@ bool CRadarMap::GetBoundingBox(CVector& vecMin, CVector& vecMax) } } -void CRadarMap::ToggleHelpText() +void CPlayerMap::ToggleHelpText() { m_bHideHelpText = !m_bHideHelpText; } -SString CRadarMap::GetBoundKeyName(const SString& strCommand) +SString CPlayerMap::GetBoundKeyName(const SString& strCommand) { CCommandBind* pCommandBind = g_pCore->GetKeyBinds()->GetBindFromCommand(strCommand, 0, 0, 0, false, 0); if (!pCommandBind) diff --git a/Client/mods/deathmatch/logic/CRadarMap.h b/Client/mods/deathmatch/logic/CPlayerMap.h similarity index 77% rename from Client/mods/deathmatch/logic/CRadarMap.h rename to Client/mods/deathmatch/logic/CPlayerMap.h index a3dd8f0d51..0d6edebb6f 100644 --- a/Client/mods/deathmatch/logic/CRadarMap.h +++ b/Client/mods/deathmatch/logic/CPlayerMap.h @@ -2,8 +2,8 @@ * * PROJECT: Multi Theft Auto v1.0 * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CRadarMap.h - * PURPOSE: Header for radar map class + * FILE: mods/deathmatch/logic/CPlayerMap.h + * PURPOSE: Header for player map class * * Multi Theft Auto is available from http://www.multitheftauto.com/ * @@ -16,19 +16,19 @@ #include #include -class CRadarMap +class CPlayerMap { public: - CRadarMap(class CClientManager* pManager); - virtual ~CRadarMap(); + CPlayerMap(class CClientManager* pManager); + virtual ~CPlayerMap(); void DoPulse(); void DoRender(); - bool IsRadarShowing(); + bool IsPlayerMapShowing(); - bool GetRadarEnabled() const { return m_bIsRadarEnabled; }; - void SetRadarEnabled(bool bIsRadarEnabled); + bool GetPlayerMapEnabled() const { return m_bIsPlayerMapEnabled; }; + void SetPlayerMapEnabled(bool bIsRadarEnabled); bool GetForcedState() const { return m_bForcedState; } void SetForcedState(bool bState); @@ -38,10 +38,14 @@ class CRadarMap void ToggleHelpText(); protected: - void InternalSetRadarEnabled(bool bEnabled); + void InternalSetPlayerMapEnabled(bool bEnabled); void CreateMarkerTextures(); CTextureItem* GetMarkerTexture(CClientRadarMarker* pMarker, float fLocalZ, float* pfScale, SColor* pColor); + void CreatePlayerBlipTexture(); + void CreateOrUpdateMapTexture(); + void UpdateOrRevertMapTexture(std::size_t imageIndex); + void CreateAllTextures(); public: bool IsAttachedToLocalPlayer() const { return m_bIsAttachedToLocal; }; @@ -79,9 +83,13 @@ class CRadarMap class CClientRadarMarkerManager* m_pRadarMarkerManager; class CClientRadarAreaManager* m_pRadarAreaManager; - CTextureItem* m_pRadarImage; - CTextureItem* m_pLocalPlayerBlip; - std::vector m_MarkerTextureList; + bool m_failedToLoadTextures; + + std::size_t m_playerMapImageIndex; + + CTextureItem* m_mapImageTexture; + CTextureItem* m_playerMarkerTexture; + std::vector m_markerTextureList; unsigned int m_uiHeight; unsigned int m_uiWidth; @@ -97,7 +105,7 @@ class CRadarMap float m_fZoom; - bool m_bIsRadarEnabled; + bool m_bIsPlayerMapEnabled; bool m_bForcedState; bool m_bIsAttachedToLocal; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 5efe5b417e..c17a0d1c2b 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -51,7 +51,7 @@ static CClientMarkerManager* m_pMarkerManager; static CClientPickupManager* m_pPickupManager; static CMovingObjectsManager* m_pMovingObjectsManager; static CBlendedWeather* m_pBlendedWeather; -static CRadarMap* m_pRadarMap; +static CPlayerMap* m_pPlayerMap; static CClientCamera* m_pCamera; static CClientExplosionManager* m_pExplosionManager; static CClientProjectileManager* m_pProjectileManager; @@ -88,7 +88,7 @@ CStaticFunctionDefinitions::CStaticFunctionDefinitions(CLuaManager* pLuaManager, m_pPickupManager = pManager->GetPickupManager(); m_pMovingObjectsManager = m_pClientGame->GetMovingObjectsManager(); m_pBlendedWeather = m_pClientGame->GetBlendedWeather(); - m_pRadarMap = m_pClientGame->GetRadarMap(); + m_pPlayerMap = m_pClientGame->GetPlayerMap(); m_pCamera = pManager->GetCamera(); m_pExplosionManager = pManager->GetExplosionManager(); m_pProjectileManager = pManager->GetProjectileManager(); @@ -7840,25 +7840,25 @@ bool CStaticFunctionDefinitions::SetWeaponClipAmmo(CClientWeapon* pWeapon, int i bool CStaticFunctionDefinitions::ForcePlayerMap(bool& bForced) { - m_pClientGame->GetRadarMap()->SetForcedState(bForced); + m_pClientGame->GetPlayerMap()->SetForcedState(bForced); return true; } bool CStaticFunctionDefinitions::IsPlayerMapForced(bool& bForced) { - bForced = m_pRadarMap->GetForcedState(); + bForced = m_pPlayerMap->GetForcedState(); return true; } bool CStaticFunctionDefinitions::IsPlayerMapVisible(bool& bVisible) { - bVisible = m_pRadarMap->IsRadarShowing(); + bVisible = m_pPlayerMap->IsPlayerMapShowing(); return true; } bool CStaticFunctionDefinitions::GetPlayerMapBoundingBox(CVector& vecMin, CVector& vecMax) { - if (m_pRadarMap->GetBoundingBox(vecMin, vecMax)) + if (m_pPlayerMap->GetBoundingBox(vecMin, vecMax)) { return true; } @@ -8975,11 +8975,8 @@ bool CStaticFunctionDefinitions::ResetVehicleHandling(CClientVehicle* pVehicle) { assert(pVehicle); - eVehicleTypes eModel = (eVehicleTypes)pVehicle->GetModel(); CHandlingEntry* pEntry = pVehicle->GetHandlingData(); - const CHandlingEntry* pNewEntry; - - pNewEntry = pVehicle->GetOriginalHandlingData(); + const CHandlingEntry* pNewEntry = pVehicle->GetOriginalHandlingData(); pEntry->SetMass(pNewEntry->GetMass()); pEntry->SetTurnMass(pNewEntry->GetTurnMass()); @@ -9015,17 +9012,13 @@ bool CStaticFunctionDefinitions::ResetVehicleHandling(CClientVehicle* pVehicle) // pEntry->SetTailLight(pNewEntry->GetTailLight ()); pEntry->SetAnimGroup(pNewEntry->GetAnimGroup()); - // Lower and Upper limits cannot match or LSOD (unless boat) - // if ( eModel != VEHICLE_BOAT ) // Commented until fully tested + float fSuspensionLimitSize = pEntry->GetSuspensionUpperLimit() - pEntry->GetSuspensionLowerLimit(); + if (fSuspensionLimitSize > -0.1f && fSuspensionLimitSize < 0.1f) { - float fSuspensionLimitSize = pEntry->GetSuspensionUpperLimit() - pEntry->GetSuspensionLowerLimit(); - if (fSuspensionLimitSize > -0.1f && fSuspensionLimitSize < 0.1f) - { - if (fSuspensionLimitSize >= 0.f) - pEntry->SetSuspensionUpperLimit(pEntry->GetSuspensionLowerLimit() + 0.1f); - else - pEntry->SetSuspensionUpperLimit(pEntry->GetSuspensionLowerLimit() - 0.1f); - } + if (fSuspensionLimitSize >= 0.f) + pEntry->SetSuspensionUpperLimit(pEntry->GetSuspensionLowerLimit() + 0.1f); + else + pEntry->SetSuspensionUpperLimit(pEntry->GetSuspensionLowerLimit() - 0.1f); } pVehicle->ApplyHandling(); diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index 64708dea0c..6fc425fa83 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -910,6 +910,22 @@ ADD_ENUM(PreloadAreaOption::COLLISIONS, "collisions") ADD_ENUM(PreloadAreaOption::ALL, "all") IMPLEMENT_ENUM_CLASS_END("preload-area-option") + +IMPLEMENT_ENUM_CLASS_BEGIN(taskType) +ADD_ENUM(taskType::PRIMARY_TASK, "primary") +ADD_ENUM(taskType::SECONDARY_TASK, "secondary") +IMPLEMENT_ENUM_CLASS_END("tasks-types") + +IMPLEMENT_ENUM_BEGIN(eEntityType) +ADD_ENUM(ENTITY_TYPE_NOTHING, "unknown") +ADD_ENUM(ENTITY_TYPE_BUILDING, "building") +ADD_ENUM(ENTITY_TYPE_VEHICLE, "vehicle") +ADD_ENUM(ENTITY_TYPE_PED, "ped") +ADD_ENUM(ENTITY_TYPE_OBJECT, "object") +ADD_ENUM(ENTITY_TYPE_DUMMY, "dummy") +ADD_ENUM(ENTITY_TYPE_NOTINPOOLS, "unknown") +IMPLEMENT_ENUM_END("entity-type") + // // CResource from userdata // @@ -1109,6 +1125,42 @@ void MixedReadMaterialString(CScriptArgReader& argStream, CClientMaterial*& pMat } } +// +// Check 4x4 lua table +// +bool IsValidMatrixLuaTable(lua_State* luaVM, std::uint32_t argIndex) noexcept +{ + std::uint32_t cell = 0; + + if (lua_type(luaVM, argIndex) == LUA_TTABLE) + { + lua_pushnil(luaVM); + for (std::uint32_t row = 0; lua_next(luaVM, argIndex) != 0; lua_pop(luaVM, 1), ++row) + { + if (lua_type(luaVM, -1) != LUA_TTABLE) + return false; + + std::uint32_t col = 0; + + lua_pushnil(luaVM); + for (; lua_next(luaVM, -2) != 0; lua_pop(luaVM, 1), ++col, ++cell) + { + int argumentType = lua_type(luaVM, -1); + if (argumentType != LUA_TNUMBER && argumentType != LUA_TSTRING) + return false; + } + + if (col != 4) + return false; + } + } + + if (cell != 16) + return false; + + return true; +} + // // 4x4 matrix into CMatrix // diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index e134a73bea..818ebeb308 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -88,6 +88,9 @@ DECLARE_ENUM(ePools); DECLARE_ENUM(eWorldProperty); DECLARE_ENUM_CLASS(eModelLoadState); DECLARE_ENUM_CLASS(PreloadAreaOption); +DECLARE_ENUM_CLASS(taskType); +DECLARE_ENUM(eEntityType); + class CRemoteCall; @@ -584,6 +587,7 @@ class CScriptArgReader; void MixedReadDxFontString(CScriptArgReader& argStream, eFontType& outFontType, eFontType defaultFontType, CClientDxFont*& poutDxFontElement); void MixedReadGuiFontString(CScriptArgReader& argStream, SString& strFontName, const char* szDefaultFontName, CClientGuiFont*& poutGuiFontElement); void MixedReadMaterialString(CScriptArgReader& argStream, CClientMaterial*& pMaterialElement); +bool IsValidMatrixLuaTable(lua_State* luaVM, std::uint32_t argIndex) noexcept; bool ReadMatrix(lua_State* luaVM, uint uiArgIndex, CMatrix& outMatrix); void MinClientReqCheck(lua_State* luaVM, const char* szVersionReq, const char* szReason); bool MinClientReqCheck(CScriptArgReader& argStream, const char* szVersionReq, const char* szReason = nullptr); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp index 6077f45346..a5b9fa95ac 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp @@ -49,6 +49,7 @@ void CLuaBrowserDefs::LoadFunctions() {"resizeBrowser", ResizeBrowser}, {"guiCreateBrowser", GUICreateBrowser}, {"guiGetBrowser", GUIGetBrowser}, + {"isBrowserGPUEnabled", ArgumentParser}, }; // Add browser functions @@ -97,6 +98,7 @@ void CLuaBrowserDefs::AddClass(lua_State* luaVM) lua_classvariable(luaVM, "renderingPaused", "setBrowserRenderingPaused", "isBrowserRenderingPaused"); lua_classvariable(luaVM, "volume", "setBrowserVolume", "getBrowserVolume"); lua_classvariable(luaVM, "devTools", "toggleBrowserDevTools", nullptr); + lua_classvariable(luaVM, "gpuEnabled", nullptr, "isBrowserGPUEnabled"); lua_registerclass(luaVM, "Browser", "DxTexture"); @@ -1054,3 +1056,8 @@ int CLuaBrowserDefs::SetBrowserAjaxHandler(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +bool CLuaBrowserDefs::IsBrowserGPUEnabled() noexcept +{ + return g_pCore->GetWebCore()->GetGPUEnabled(); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.h index 33d156b0f5..988efb6c40 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.h @@ -51,4 +51,5 @@ class CLuaBrowserDefs : public CLuaDefs LUA_DECLARE(ResizeBrowser); LUA_DECLARE(GUICreateBrowser); LUA_DECLARE(GUIGetBrowser); + static bool IsBrowserGPUEnabled() noexcept; }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index f38096dcee..6caf245618 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -115,6 +115,7 @@ void CLuaPedDefs::LoadFunctions() {"isPedDucked", IsPedDucked}, {"isPedDead", IsPedDead}, {"isPedReloadingWeapon", IsPedReloadingWeapon}, + {"killPedTask", ArgumentParser}, }; // Add functions @@ -2493,3 +2494,20 @@ bool CLuaPedDefs::SetPedExitVehicle(CClientPed* pPed) { return pPed->ExitVehicle(); } + +bool CLuaPedDefs::killPedTask(CClientPed* ped, taskType taskType, std::uint8_t taskNumber, std::optional gracefully) noexcept +{ + switch (taskType) + { + case taskType::PRIMARY_TASK: + { + return ped->KillTask(taskNumber, gracefully.value_or(true)); + } + case taskType::SECONDARY_TASK: + { + return ped->KillTaskSecondary(taskNumber, gracefully.value_or(true)); + } + default: + return false; + } +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index d97a484d8e..76b9771332 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -115,4 +115,6 @@ class CLuaPedDefs : public CLuaDefs static bool SetPedExitVehicle(CClientPed* pPed); static bool IsPedBleeding(CClientPed* ped); static bool SetPedBleeding(CClientPed* ped, bool bleeding); + + static bool killPedTask(CClientPed* ped, taskType taskType, std::uint8_t taskNumber, std::optional gracefully) noexcept; }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index 411aba2e56..7af3738c28 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -13,6 +13,7 @@ #include #include #include "lua/CLuaFunctionParser.h" +#include void CLuaVehicleDefs::LoadFunctions() { @@ -92,6 +93,7 @@ void CLuaVehicleDefs::LoadFunctions() {"getVehicleModelWheelSize", ArgumentParser}, {"getVehicleWheelFrictionState", ArgumentParser}, {"getVehicleEntryPoints", ArgumentParser}, + {"isVehicleSmokeTrailEnabled", ArgumentParser}, {"getVehicleRotorState", ArgumentParser}, // Vehicle set funcs @@ -157,6 +159,7 @@ void CLuaVehicleDefs::LoadFunctions() {"setVehicleWheelScale", ArgumentParser}, {"setVehicleModelWheelSize", ArgumentParser}, {"spawnVehicleFlyingComponent", ArgumentParser}, + {"setVehicleSmokeTrailEnabled", ArgumentParser}, {"setVehicleRotorState", ArgumentParser}, }; @@ -246,6 +249,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getModelWheelSize", "getVehicleModelWheelSize"); lua_classfunction(luaVM, "getWheelFrictionState", "getVehicleWheelFrictionState"); lua_classfunction(luaVM, "getEntryPoints", ArgumentParser); + lua_classfunction(luaVM, "isSmokeTrailEnabled", "isVehicleSmokeTrailEnabled"); lua_classfunction(luaVM, "getRotorState", "getVehicleRotorState"); lua_classfunction(luaVM, "setComponentVisible", "setVehicleComponentVisible"); @@ -295,6 +299,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setVariant", "setVehicleVariant"); lua_classfunction(luaVM, "setWheelScale", "setVehicleWheelScale"); lua_classfunction(luaVM, "setModelWheelSize", "setVehicleModelWheelSize"); + lua_classfunction(luaVM, "setSmokeTrailEnabled", "setVehicleSmokeTrailEnabled"); lua_classfunction(luaVM, "setRotorState", "setVehicleRotorState"); lua_classfunction(luaVM, "resetComponentPosition", "resetVehicleComponentPosition"); @@ -2658,7 +2663,7 @@ int CLuaVehicleDefs::SetVehicleHandling(lua_State* luaVM) int CLuaVehicleDefs::GetVehicleHandling(lua_State* luaVM) { // table getVehicleHandling ( element theVehicle, [ string property ] ) - CClientVehicle* pVehicle = NULL; + CClientVehicle* pVehicle = nullptr; CScriptArgReader argStream(luaVM); argStream.ReadUserData(pVehicle); @@ -2669,50 +2674,55 @@ int CLuaVehicleDefs::GetVehicleHandling(lua_State* luaVM) SString strProperty; argStream.ReadString(strProperty); + bool bResult = true; eHandlingProperty eProperty = g_pGame->GetHandlingManager()->GetPropertyEnumFromName(strProperty); - if (eProperty == HANDLING_MAX) - { - argStream.SetCustomError("Invalid property"); - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - lua_pushboolean(luaVM, false); - return 1; - } - - float fValue = 0.0f; - CVector vecValue = CVector(0.0f, 0.0f, 0.0f); - SString strValue = ""; - unsigned int uiValue = 0; - unsigned char ucValue = 0; - if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, fValue)) - { - lua_pushnumber(luaVM, fValue); - } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, uiValue)) - { - lua_pushnumber(luaVM, uiValue); - } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, ucValue)) - { - lua_pushnumber(luaVM, ucValue); - } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, strValue)) + if (eProperty != HANDLING_MAX) { - lua_pushstring(luaVM, strValue); + float fValue = 0.0f; + CVector vecValue = CVector(0.0f, 0.0f, 0.0f); + SString strValue = ""; + unsigned int uiValue = 0; + unsigned char ucValue = 0; + if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, fValue)) + { + lua_pushnumber(luaVM, fValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, uiValue)) + { + lua_pushnumber(luaVM, uiValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, ucValue)) + { + lua_pushnumber(luaVM, ucValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, strValue)) + { + lua_pushstring(luaVM, strValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, vecValue)) + { + lua_createtable(luaVM, 3, 0); + lua_pushnumber(luaVM, 1); + lua_pushnumber(luaVM, vecValue.fX); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 2); + lua_pushnumber(luaVM, vecValue.fY); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 3); + lua_pushnumber(luaVM, vecValue.fZ); + lua_settable(luaVM, -3); + } + else + { + bResult = false; + } } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, vecValue)) + else { - lua_createtable(luaVM, 3, 0); - lua_pushnumber(luaVM, 1); - lua_pushnumber(luaVM, vecValue.fX); - lua_settable(luaVM, -3); - lua_pushnumber(luaVM, 2); - lua_pushnumber(luaVM, vecValue.fY); - lua_settable(luaVM, -3); - lua_pushnumber(luaVM, 3); - lua_pushnumber(luaVM, vecValue.fZ); - lua_settable(luaVM, -3); + bResult = false; } - else + + if (!bResult) { argStream.SetCustomError("Invalid property"); m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); @@ -2720,149 +2730,157 @@ int CLuaVehicleDefs::GetVehicleHandling(lua_State* luaVM) } return 1; } - CHandlingEntry* pEntry = pVehicle->GetHandlingData(); - lua_newtable(luaVM); + if (const auto* const entry = pVehicle->GetHandlingData()) + { + lua_newtable(luaVM); - lua_pushnumber(luaVM, pEntry->GetMass()); - lua_setfield(luaVM, -2, "mass"); - - lua_pushnumber(luaVM, pEntry->GetTurnMass()); - lua_setfield(luaVM, -2, "turnMass"); - - lua_pushnumber(luaVM, pEntry->GetDragCoeff()); - lua_setfield(luaVM, -2, "dragCoeff"); - - lua_createtable(luaVM, 3, 0); - CVector vecCenter = pEntry->GetCenterOfMass(); - lua_pushnumber(luaVM, 1); - lua_pushnumber(luaVM, vecCenter.fX); - lua_settable(luaVM, -3); - lua_pushnumber(luaVM, 2); - lua_pushnumber(luaVM, vecCenter.fY); - lua_settable(luaVM, -3); - lua_pushnumber(luaVM, 3); - lua_pushnumber(luaVM, vecCenter.fZ); - lua_settable(luaVM, -3); - lua_setfield(luaVM, -2, "centerOfMass"); - - lua_pushnumber(luaVM, pEntry->GetPercentSubmerged()); - lua_setfield(luaVM, -2, "percentSubmerged"); - - lua_pushnumber(luaVM, pEntry->GetTractionMultiplier()); - lua_setfield(luaVM, -2, "tractionMultiplier"); - - CHandlingEntry::eDriveType eDriveType = pEntry->GetCarDriveType(); - if (eDriveType == CHandlingEntry::FWD) - lua_pushstring(luaVM, "fwd"); - else if (eDriveType == CHandlingEntry::RWD) - lua_pushstring(luaVM, "rwd"); - else if (eDriveType == CHandlingEntry::FOURWHEEL) - lua_pushstring(luaVM, "awd"); - else // What the ... (yeah, security) - lua_pushnil(luaVM); - lua_setfield(luaVM, -2, "driveType"); - CHandlingEntry::eEngineType eEngineType = pEntry->GetCarEngineType(); - if (eEngineType == CHandlingEntry::PETROL) - lua_pushstring(luaVM, "petrol"); - else if (eEngineType == CHandlingEntry::DIESEL) - lua_pushstring(luaVM, "diesel"); - else if (eEngineType == CHandlingEntry::ELECTRIC) - lua_pushstring(luaVM, "electric"); - else - lua_pushnil(luaVM); - lua_setfield(luaVM, -2, "engineType"); + lua_pushnumber(luaVM, entry->GetMass()); + lua_setfield(luaVM, -2, "mass"); + + lua_pushnumber(luaVM, entry->GetTurnMass()); + lua_setfield(luaVM, -2, "turnMass"); + + lua_pushnumber(luaVM, entry->GetDragCoeff()); + lua_setfield(luaVM, -2, "dragCoeff"); + + lua_createtable(luaVM, 3, 0); + CVector vecCenter = entry->GetCenterOfMass(); + lua_pushnumber(luaVM, 1); + lua_pushnumber(luaVM, vecCenter.fX); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 2); + lua_pushnumber(luaVM, vecCenter.fY); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 3); + lua_pushnumber(luaVM, vecCenter.fZ); + lua_settable(luaVM, -3); + lua_setfield(luaVM, -2, "centerOfMass"); + + lua_pushnumber(luaVM, entry->GetPercentSubmerged()); + lua_setfield(luaVM, -2, "percentSubmerged"); + + lua_pushnumber(luaVM, entry->GetTractionMultiplier()); + lua_setfield(luaVM, -2, "tractionMultiplier"); + + CHandlingEntry::eDriveType eDriveType = entry->GetCarDriveType(); + if (eDriveType == CHandlingEntry::FWD) + lua_pushstring(luaVM, "fwd"); + else if (eDriveType == CHandlingEntry::RWD) + lua_pushstring(luaVM, "rwd"); + else if (eDriveType == CHandlingEntry::FOURWHEEL) + lua_pushstring(luaVM, "awd"); + else // What the ... (yeah, security) + lua_pushnil(luaVM); + lua_setfield(luaVM, -2, "driveType"); + CHandlingEntry::eEngineType eEngineType = entry->GetCarEngineType(); + if (eEngineType == CHandlingEntry::PETROL) + lua_pushstring(luaVM, "petrol"); + else if (eEngineType == CHandlingEntry::DIESEL) + lua_pushstring(luaVM, "diesel"); + else if (eEngineType == CHandlingEntry::ELECTRIC) + lua_pushstring(luaVM, "electric"); + else + lua_pushnil(luaVM); + lua_setfield(luaVM, -2, "engineType"); - lua_pushnumber(luaVM, pEntry->GetNumberOfGears()); - lua_setfield(luaVM, -2, "numberOfGears"); + lua_pushnumber(luaVM, entry->GetNumberOfGears()); + lua_setfield(luaVM, -2, "numberOfGears"); - lua_pushnumber(luaVM, pEntry->GetEngineAcceleration()); - lua_setfield(luaVM, -2, "engineAcceleration"); + lua_pushnumber(luaVM, entry->GetEngineAcceleration()); + lua_setfield(luaVM, -2, "engineAcceleration"); - lua_pushnumber(luaVM, pEntry->GetEngineInertia()); - lua_setfield(luaVM, -2, "engineInertia"); + lua_pushnumber(luaVM, entry->GetEngineInertia()); + lua_setfield(luaVM, -2, "engineInertia"); - lua_pushnumber(luaVM, pEntry->GetMaxVelocity()); - lua_setfield(luaVM, -2, "maxVelocity"); + lua_pushnumber(luaVM, entry->GetMaxVelocity()); + lua_setfield(luaVM, -2, "maxVelocity"); - lua_pushnumber(luaVM, pEntry->GetBrakeDeceleration()); - lua_setfield(luaVM, -2, "brakeDeceleration"); + lua_pushnumber(luaVM, entry->GetBrakeDeceleration()); + lua_setfield(luaVM, -2, "brakeDeceleration"); - lua_pushnumber(luaVM, pEntry->GetBrakeBias()); - lua_setfield(luaVM, -2, "brakeBias"); + lua_pushnumber(luaVM, entry->GetBrakeBias()); + lua_setfield(luaVM, -2, "brakeBias"); - lua_pushboolean(luaVM, pEntry->GetABS()); - lua_setfield(luaVM, -2, "ABS"); + lua_pushboolean(luaVM, entry->GetABS()); + lua_setfield(luaVM, -2, "ABS"); - lua_pushnumber(luaVM, pEntry->GetSteeringLock()); - lua_setfield(luaVM, -2, "steeringLock"); + lua_pushnumber(luaVM, entry->GetSteeringLock()); + lua_setfield(luaVM, -2, "steeringLock"); - lua_pushnumber(luaVM, pEntry->GetTractionLoss()); - lua_setfield(luaVM, -2, "tractionLoss"); + lua_pushnumber(luaVM, entry->GetTractionLoss()); + lua_setfield(luaVM, -2, "tractionLoss"); - lua_pushnumber(luaVM, pEntry->GetTractionBias()); - lua_setfield(luaVM, -2, "tractionBias"); + lua_pushnumber(luaVM, entry->GetTractionBias()); + lua_setfield(luaVM, -2, "tractionBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionForceLevel()); - lua_setfield(luaVM, -2, "suspensionForceLevel"); + lua_pushnumber(luaVM, entry->GetSuspensionForceLevel()); + lua_setfield(luaVM, -2, "suspensionForceLevel"); - lua_pushnumber(luaVM, pEntry->GetSuspensionDamping()); - lua_setfield(luaVM, -2, "suspensionDamping"); + lua_pushnumber(luaVM, entry->GetSuspensionDamping()); + lua_setfield(luaVM, -2, "suspensionDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionHighSpeedDamping()); - lua_setfield(luaVM, -2, "suspensionHighSpeedDamping"); + lua_pushnumber(luaVM, entry->GetSuspensionHighSpeedDamping()); + lua_setfield(luaVM, -2, "suspensionHighSpeedDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionUpperLimit()); - lua_setfield(luaVM, -2, "suspensionUpperLimit"); + lua_pushnumber(luaVM, entry->GetSuspensionUpperLimit()); + lua_setfield(luaVM, -2, "suspensionUpperLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionLowerLimit()); - lua_setfield(luaVM, -2, "suspensionLowerLimit"); + lua_pushnumber(luaVM, entry->GetSuspensionLowerLimit()); + lua_setfield(luaVM, -2, "suspensionLowerLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionFrontRearBias()); - lua_setfield(luaVM, -2, "suspensionFrontRearBias"); + lua_pushnumber(luaVM, entry->GetSuspensionFrontRearBias()); + lua_setfield(luaVM, -2, "suspensionFrontRearBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionAntiDiveMultiplier()); - lua_setfield(luaVM, -2, "suspensionAntiDiveMultiplier"); + lua_pushnumber(luaVM, entry->GetSuspensionAntiDiveMultiplier()); + lua_setfield(luaVM, -2, "suspensionAntiDiveMultiplier"); - lua_pushnumber(luaVM, pEntry->GetCollisionDamageMultiplier()); - lua_setfield(luaVM, -2, "collisionDamageMultiplier"); + lua_pushnumber(luaVM, entry->GetCollisionDamageMultiplier()); + lua_setfield(luaVM, -2, "collisionDamageMultiplier"); - lua_pushnumber(luaVM, pEntry->GetSeatOffsetDistance()); - lua_setfield(luaVM, -2, "seatOffsetDistance"); + lua_pushnumber(luaVM, entry->GetSeatOffsetDistance()); + lua_setfield(luaVM, -2, "seatOffsetDistance"); - lua_pushnumber(luaVM, pEntry->GetHandlingFlags()); - lua_setfield(luaVM, -2, "handlingFlags"); + lua_pushnumber(luaVM, entry->GetHandlingFlags()); + lua_setfield(luaVM, -2, "handlingFlags"); - lua_pushnumber(luaVM, pEntry->GetModelFlags()); - lua_setfield(luaVM, -2, "modelFlags"); + lua_pushnumber(luaVM, entry->GetModelFlags()); + lua_setfield(luaVM, -2, "modelFlags"); - lua_pushnumber(luaVM, pEntry->GetMonetary()); - lua_setfield(luaVM, -2, "monetary"); + lua_pushnumber(luaVM, entry->GetMonetary()); + lua_setfield(luaVM, -2, "monetary"); - CHandlingEntry::eLightType eHeadType = pEntry->GetHeadLight(); - if (eHeadType == CHandlingEntry::LONG) - lua_pushstring(luaVM, "long"); - else if (eHeadType == CHandlingEntry::SMALL) - lua_pushstring(luaVM, "small"); - else if (eHeadType == CHandlingEntry::BIG) - lua_pushstring(luaVM, "big"); - else - lua_pushnil(luaVM); - lua_setfield(luaVM, -2, "headLight"); - - CHandlingEntry::eLightType eTailType = pEntry->GetTailLight(); - if (eTailType == CHandlingEntry::LONG) - lua_pushstring(luaVM, "long"); - else if (eTailType == CHandlingEntry::SMALL) - lua_pushstring(luaVM, "small"); - else if (eTailType == CHandlingEntry::BIG) - lua_pushstring(luaVM, "big"); - else - lua_pushnil(luaVM); - lua_setfield(luaVM, -2, "tailLight"); + CHandlingEntry::eLightType eHeadType = entry->GetHeadLight(); + if (eHeadType == CHandlingEntry::LONG) + lua_pushstring(luaVM, "long"); + else if (eHeadType == CHandlingEntry::SMALL) + lua_pushstring(luaVM, "small"); + else if (eHeadType == CHandlingEntry::BIG) + lua_pushstring(luaVM, "big"); + else + lua_pushnil(luaVM); + lua_setfield(luaVM, -2, "headLight"); + + CHandlingEntry::eLightType eTailType = entry->GetTailLight(); + if (eTailType == CHandlingEntry::LONG) + lua_pushstring(luaVM, "long"); + else if (eTailType == CHandlingEntry::SMALL) + lua_pushstring(luaVM, "small"); + else if (eTailType == CHandlingEntry::BIG) + lua_pushstring(luaVM, "big"); + else + lua_pushnil(luaVM); + lua_setfield(luaVM, -2, "tailLight"); - lua_pushnumber(luaVM, pEntry->GetAnimGroup()); - lua_setfield(luaVM, -2, "animGroup"); + lua_pushnumber(luaVM, entry->GetAnimGroup()); + lua_setfield(luaVM, -2, "animGroup"); + } + else + { + argStream.SetCustomError("Invalid handling data"); + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + lua_pushboolean(luaVM, false); + } return 1; } else @@ -2874,27 +2892,26 @@ int CLuaVehicleDefs::GetVehicleHandling(lua_State* luaVM) int CLuaVehicleDefs::GetOriginalHandling(lua_State* luaVM) { - int iType = 0; + std::uint32_t uiModel; + CScriptArgReader argStream(luaVM); - argStream.ReadNumber(iType); + argStream.ReadNumber(uiModel); if (!argStream.HasErrors()) { - eVehicleTypes eModel = static_cast(iType); - if (eModel) + if (CClientVehicleManager::IsValidModel(uiModel)) { - const CHandlingEntry* pEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); - if (pEntry) + if (const auto* const entry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(uiModel)) { lua_newtable(luaVM); - lua_pushnumber(luaVM, pEntry->GetMass()); + lua_pushnumber(luaVM, entry->GetMass()); lua_setfield(luaVM, -2, "mass"); - lua_pushnumber(luaVM, pEntry->GetTurnMass()); + lua_pushnumber(luaVM, entry->GetTurnMass()); lua_setfield(luaVM, -2, "turnMass"); - lua_pushnumber(luaVM, pEntry->GetDragCoeff()); + lua_pushnumber(luaVM, entry->GetDragCoeff()); lua_setfield(luaVM, -2, "dragCoeff"); lua_createtable(luaVM, 3, 0); - CVector vecCenter = pEntry->GetCenterOfMass(); + CVector vecCenter = entry->GetCenterOfMass(); lua_pushnumber(luaVM, 1); lua_pushnumber(luaVM, vecCenter.fX); lua_settable(luaVM, -3); @@ -2905,11 +2922,11 @@ int CLuaVehicleDefs::GetOriginalHandling(lua_State* luaVM) lua_pushnumber(luaVM, vecCenter.fZ); lua_settable(luaVM, -3); lua_setfield(luaVM, -2, "centerOfMass"); - lua_pushnumber(luaVM, pEntry->GetPercentSubmerged()); + lua_pushnumber(luaVM, entry->GetPercentSubmerged()); lua_setfield(luaVM, -2, "percentSubmerged"); - lua_pushnumber(luaVM, pEntry->GetTractionMultiplier()); + lua_pushnumber(luaVM, entry->GetTractionMultiplier()); lua_setfield(luaVM, -2, "tractionMultiplier"); - CHandlingEntry::eDriveType eDriveType = pEntry->GetCarDriveType(); + CHandlingEntry::eDriveType eDriveType = entry->GetCarDriveType(); if (eDriveType == CHandlingEntry::FWD) lua_pushstring(luaVM, "fwd"); else if (eDriveType == CHandlingEntry::RWD) @@ -2919,7 +2936,7 @@ int CLuaVehicleDefs::GetOriginalHandling(lua_State* luaVM) else // What the ... (yeah, security) lua_pushnil(luaVM); lua_setfield(luaVM, -2, "driveType"); - CHandlingEntry::eEngineType eEngineType = pEntry->GetCarEngineType(); + CHandlingEntry::eEngineType eEngineType = entry->GetCarEngineType(); if (eEngineType == CHandlingEntry::PETROL) lua_pushstring(luaVM, "petrol"); else if (eEngineType == CHandlingEntry::DIESEL) @@ -2929,51 +2946,51 @@ int CLuaVehicleDefs::GetOriginalHandling(lua_State* luaVM) else lua_pushnil(luaVM); lua_setfield(luaVM, -2, "engineType"); - lua_pushnumber(luaVM, pEntry->GetNumberOfGears()); + lua_pushnumber(luaVM, entry->GetNumberOfGears()); lua_setfield(luaVM, -2, "numberOfGears"); - lua_pushnumber(luaVM, pEntry->GetEngineAcceleration()); + lua_pushnumber(luaVM, entry->GetEngineAcceleration()); lua_setfield(luaVM, -2, "engineAcceleration"); - lua_pushnumber(luaVM, pEntry->GetEngineInertia()); + lua_pushnumber(luaVM, entry->GetEngineInertia()); lua_setfield(luaVM, -2, "engineInertia"); - lua_pushnumber(luaVM, pEntry->GetMaxVelocity()); + lua_pushnumber(luaVM, entry->GetMaxVelocity()); lua_setfield(luaVM, -2, "maxVelocity"); - lua_pushnumber(luaVM, pEntry->GetBrakeDeceleration()); + lua_pushnumber(luaVM, entry->GetBrakeDeceleration()); lua_setfield(luaVM, -2, "brakeDeceleration"); - lua_pushnumber(luaVM, pEntry->GetBrakeBias()); + lua_pushnumber(luaVM, entry->GetBrakeBias()); lua_setfield(luaVM, -2, "brakeBias"); - lua_pushboolean(luaVM, pEntry->GetABS()); + lua_pushboolean(luaVM, entry->GetABS()); lua_setfield(luaVM, -2, "ABS"); - lua_pushnumber(luaVM, pEntry->GetSteeringLock()); + lua_pushnumber(luaVM, entry->GetSteeringLock()); lua_setfield(luaVM, -2, "steeringLock"); - lua_pushnumber(luaVM, pEntry->GetTractionLoss()); + lua_pushnumber(luaVM, entry->GetTractionLoss()); lua_setfield(luaVM, -2, "tractionLoss"); - lua_pushnumber(luaVM, pEntry->GetTractionBias()); + lua_pushnumber(luaVM, entry->GetTractionBias()); lua_setfield(luaVM, -2, "tractionBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionForceLevel()); + lua_pushnumber(luaVM, entry->GetSuspensionForceLevel()); lua_setfield(luaVM, -2, "suspensionForceLevel"); - lua_pushnumber(luaVM, pEntry->GetSuspensionDamping()); + lua_pushnumber(luaVM, entry->GetSuspensionDamping()); lua_setfield(luaVM, -2, "suspensionDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionHighSpeedDamping()); + lua_pushnumber(luaVM, entry->GetSuspensionHighSpeedDamping()); lua_setfield(luaVM, -2, "suspensionHighSpeedDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionUpperLimit()); + lua_pushnumber(luaVM, entry->GetSuspensionUpperLimit()); lua_setfield(luaVM, -2, "suspensionUpperLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionLowerLimit()); + lua_pushnumber(luaVM, entry->GetSuspensionLowerLimit()); lua_setfield(luaVM, -2, "suspensionLowerLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionFrontRearBias()); + lua_pushnumber(luaVM, entry->GetSuspensionFrontRearBias()); lua_setfield(luaVM, -2, "suspensionFrontRearBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionAntiDiveMultiplier()); + lua_pushnumber(luaVM, entry->GetSuspensionAntiDiveMultiplier()); lua_setfield(luaVM, -2, "suspensionAntiDiveMultiplier"); - lua_pushnumber(luaVM, pEntry->GetCollisionDamageMultiplier()); + lua_pushnumber(luaVM, entry->GetCollisionDamageMultiplier()); lua_setfield(luaVM, -2, "collisionDamageMultiplier"); - lua_pushnumber(luaVM, pEntry->GetSeatOffsetDistance()); + lua_pushnumber(luaVM, entry->GetSeatOffsetDistance()); lua_setfield(luaVM, -2, "seatOffsetDistance"); - lua_pushnumber(luaVM, pEntry->GetHandlingFlags()); + lua_pushnumber(luaVM, entry->GetHandlingFlags()); lua_setfield(luaVM, -2, "handlingFlags"); - lua_pushnumber(luaVM, pEntry->GetModelFlags()); + lua_pushnumber(luaVM, entry->GetModelFlags()); lua_setfield(luaVM, -2, "modelFlags"); - lua_pushnumber(luaVM, pEntry->GetMonetary()); + lua_pushnumber(luaVM, entry->GetMonetary()); lua_setfield(luaVM, -2, "monetary"); - CHandlingEntry::eLightType eHeadType = pEntry->GetHeadLight(); + CHandlingEntry::eLightType eHeadType = entry->GetHeadLight(); if (eHeadType == CHandlingEntry::LONG) lua_pushstring(luaVM, "long"); else if (eHeadType == CHandlingEntry::SMALL) @@ -2983,7 +3000,7 @@ int CLuaVehicleDefs::GetOriginalHandling(lua_State* luaVM) else lua_pushnil(luaVM); lua_setfield(luaVM, -2, "headLight"); - CHandlingEntry::eLightType eTailType = pEntry->GetTailLight(); + CHandlingEntry::eLightType eTailType = entry->GetTailLight(); if (eTailType == CHandlingEntry::LONG) lua_pushstring(luaVM, "long"); else if (eTailType == CHandlingEntry::SMALL) @@ -2993,7 +3010,7 @@ int CLuaVehicleDefs::GetOriginalHandling(lua_State* luaVM) else lua_pushnil(luaVM); lua_setfield(luaVM, -2, "tailLight"); - lua_pushnumber(luaVM, pEntry->GetAnimGroup()); + lua_pushnumber(luaVM, entry->GetAnimGroup()); lua_setfield(luaVM, -2, "animGroup"); return 1; } @@ -4346,6 +4363,21 @@ bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, return vehicle->SpawnFlyingComponent(partNodeIndex, collisionType, removalTime.value_or(-1)); } +bool CLuaVehicleDefs::SetSmokeTrailEnabled(CClientVehicle* vehicle, bool state) +{ + std::uint16_t model = vehicle->GetModel(); + if (model != 512 && model != 513) + throw LuaFunctionError("Invaild model ID"); + + vehicle->SetSmokeTrailEnabled(state); + return true; +} + +bool CLuaVehicleDefs::IsSmokeTrailEnabled(CClientVehicle* vehicle) noexcept +{ + return vehicle->IsSmokeTrailEnabled(); +} + bool CLuaVehicleDefs::SetVehicleRotorState(CClientVehicle* vehicle, bool state, std::optional stopRotor) noexcept { if (vehicle->GetVehicleType() != eClientVehicleType::CLIENTVEHICLE_HELI && vehicle->GetVehicleType() != eClientVehicleType::CLIENTVEHICLE_PLANE) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index 237d4dad78..cfae84faba 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -184,4 +184,7 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(GetVehicleComponents); static bool SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, std::optional removalTime); + + static bool SetSmokeTrailEnabled(CClientVehicle* vehicle, bool state); + static bool IsSmokeTrailEnabled(CClientVehicle* vehicle) noexcept; }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp index 382c2c7488..185b0ae44b 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp @@ -106,6 +106,7 @@ void CLuaWorldDefs::LoadFunctions() {"restoreWorldModel", RestoreWorldBuilding}, {"setTimeFrozen", ArgumentParser}, {"setVolumetricShadowsEnabled", ArgumentParser}, + {"setDynamicPedShadowsEnabled", ArgumentParser}, // World create funcs {"createSWATRope", CreateSWATRope}, @@ -131,6 +132,7 @@ void CLuaWorldDefs::LoadFunctions() {"resetTimeFrozen", ArgumentParser}, {"resetVolumetricShadows", ArgumentParser}, {"resetWorldProperties", ArgumentParser}, + {"resetDynamicPedShadows", ArgumentParser}, // World check funcs {"areTrafficLightsLocked", AreTrafficLightsLocked}, @@ -139,7 +141,9 @@ void CLuaWorldDefs::LoadFunctions() {"isWorldSpecialPropertyEnabled", ArgumentParserWarn}, {"isGarageOpen", IsGarageOpen}, {"isTimeFrozen", ArgumentParser}, - {"isVolumetricShadowsEnabled", ArgumentParser}}; + {"isVolumetricShadowsEnabled", ArgumentParser}, + {"isDynamicPedShadowsEnabled", ArgumentParser}, + {"testSphereAgainstWorld", ArgumentParser}}; // Add functions for (const auto& [name, func] : functions) @@ -2278,3 +2282,31 @@ void CLuaWorldDefs::ResetWorldProperties(std::optional resetSpecialWorldPr { g_pClientGame->ResetWorldProperties(ResetWorldPropsInfo{resetSpecialWorldProperties.value_or(true), resetWorldProperties.value_or(true), resetWeatherProperties.value_or(true), resetLODs.value_or(true), resetSounds.value_or(true)}); } + +bool CLuaWorldDefs::SetDynamicPedShadowsEnabled(bool enable) +{ + g_pGame->GetSettings()->SetDynamicPedShadowsEnabled(enable); + return true; +} + +bool CLuaWorldDefs::IsDynamicPedShadowsEnabled() noexcept +{ + return g_pGame->GetSettings()->IsDynamicPedShadowsEnabled(); +} + +bool CLuaWorldDefs::ResetDynamicPedShadows() noexcept +{ + return g_pGame->GetSettings()->ResetDynamicPedShadows(); +} + +CLuaMultiReturn CLuaWorldDefs::TestSphereAgainstWorld(CVector sphereCenter, float radius, std::optional ignoredEntity, std::optional checkBuildings, std::optional checkVehicles, std::optional checkPeds, std::optional checkObjects, std::optional checkDummies, std::optional cameraIgnore) +{ + STestSphereAgainstWorldResult result; + CClientEntity* collidedEntity = nullptr; + + CEntity* entity = g_pGame->GetWorld()->TestSphereAgainstWorld(sphereCenter, radius, ignoredEntity.has_value() ? ignoredEntity.value()->GetGameEntity() : nullptr, checkBuildings.value_or(true), checkVehicles.value_or(true), checkPeds.value_or(true), checkObjects.value_or(true), checkDummies.value_or(true), cameraIgnore.value_or(false), result); + if (entity) + collidedEntity = reinterpret_cast(entity->GetStoredPointer()); + + return {result.collisionDetected, collidedEntity, result.modelID, result.entityPosition.fX, result.entityPosition.fY, result.entityPosition.fZ, ConvertRadiansToDegrees(result.entityRotation.fX), ConvertRadiansToDegrees(result.entityRotation.fY), ConvertRadiansToDegrees(result.entityRotation.fZ), result.lodID, result.type}; +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h index ac38251dc7..3c19ed8857 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h @@ -140,6 +140,12 @@ class CLuaWorldDefs : public CLuaDefs static bool ResetVolumetricShadows() noexcept; static void ResetWorldProperties(std::optional resetSpecialWorldProperties, std::optional resetWorldProperties, std::optional resetWeatherProperties, std::optional resetLODs, std::optional resetSounds) noexcept; - + + static bool SetDynamicPedShadowsEnabled(bool enable); + static bool IsDynamicPedShadowsEnabled() noexcept; + static bool ResetDynamicPedShadows() noexcept; + + static CLuaMultiReturn TestSphereAgainstWorld(CVector sphereCenter, float radius, std::optional ignoredEntity, std::optional checkBuildings, std::optional checkVehicles, std::optional checkPeds, std::optional checkObjects, std::optional checkDummies, std::optional cameraIgnore); + }; diff --git a/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp index e8cda43283..321c030652 100644 --- a/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp @@ -60,7 +60,7 @@ void CPlayerRPCs::ForcePlayerMap(NetBitStreamInterface& bitStream) if (bitStream.Read(ucVisible)) { bool bVisible = (ucVisible == 1); - m_pClientGame->GetRadarMap()->SetForcedState(bVisible); + m_pClientGame->GetPlayerMap()->SetForcedState(bVisible); } } diff --git a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp index d92ba4788b..380767ccc7 100644 --- a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp @@ -619,6 +619,12 @@ void CWorldRPCs::SetSyncIntervals(NetBitStreamInterface& bitStream) bitStream.Read(g_TickRateSettings.iObjectSync); bitStream.Read(g_TickRateSettings.iKeySyncRotation); bitStream.Read(g_TickRateSettings.iKeySyncAnalogMove); + + if (bitStream.Can(eBitStreamVersion::FixSyncerDistance)) + { + bitStream.Read(g_TickRateSettings.iPedSyncerDistance); + bitStream.Read(g_TickRateSettings.iUnoccupiedVehicleSyncerDistance); + } } void CWorldRPCs::SetMoonSize(NetBitStreamInterface& bitStream) diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 1b21f79a23..f0cd566133 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -1574,6 +1574,7 @@ void CMultiplayerSA::InitHooks() MemSet((void*)0x6C4453, 0x90, 0x68); InitHooks_CrashFixHacks(); + InitHooks_DeviceSelection(); // Init our 1.3 hooks. Init_13(); @@ -1861,6 +1862,7 @@ void CMultiplayerSA::DisableCloseRangeDamage(bool bDisabled) MemPut(0x73BA00, 0x86); } } + bool CMultiplayerSA::GetInteriorSoundsEnabled() { return bInteriorSoundsEnabled; @@ -4581,7 +4583,7 @@ void _cdecl CPhysical_ApplyGravity(DWORD dwThis) pVehicle->GetGravity(&vecGravity); pVehicle->GetMoveSpeed(&vecMoveSpeed); vecMoveSpeed += vecGravity * fTimeStep * fGravity; - pVehicle->SetMoveSpeed(&vecMoveSpeed); + pVehicle->SetMoveSpeed(vecMoveSpeed); } else { @@ -4678,7 +4680,7 @@ bool _cdecl VehicleCamStart(DWORD dwCam, DWORD pVehicleInterface) pVehicle->GetMoveSpeed(&gravcam_vecVehicleVelocity); CVector vecVelocityInverted = gravcam_matInvertGravity * gravcam_vecVehicleVelocity; - pVehicle->SetMoveSpeed(&vecVelocityInverted); + pVehicle->SetMoveSpeed(vecVelocityInverted); return true; } @@ -4874,7 +4876,7 @@ void _cdecl VehicleCamEnd(DWORD pVehicleInterface) return; pVehicle->SetMatrix(&gravcam_matVehicleTransform); - pVehicle->SetMoveSpeed(&gravcam_vecVehicleVelocity); + pVehicle->SetMoveSpeed(gravcam_vecVehicleVelocity); } void _declspec(naked) HOOK_VehicleCamEnd() @@ -5012,7 +5014,7 @@ void _cdecl ApplyVehicleBlowHop(DWORD pVehicleInterface) pVehicle->GetGravity(&vecGravity); pVehicle->GetMoveSpeed(&vecVelocity); vecVelocity -= vecGravity * 0.13f; - pVehicle->SetMoveSpeed(&vecVelocity); + pVehicle->SetMoveSpeed(vecVelocity); } void _declspec(naked) HOOK_ApplyCarBlowHop() @@ -6182,7 +6184,7 @@ void _declspec(naked) HOOK_ProcessVehicleCollision() } } -void CMultiplayerSA::UpdateVehicleSuspension() noexcept +void CMultiplayerSA::UpdateVehicleSuspension() const noexcept { HookInstallCall(CALL_CAutomobile_ProcessEntityCollision, reinterpret_cast(HOOK_ProcessVehicleCollision)); HookInstallCall(CALL_CMonsterTruck_ProcessEntityCollision, reinterpret_cast(HOOK_ProcessVehicleCollision)); diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 802b9b56ea..0dd642cb4b 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -80,6 +80,7 @@ class CMultiplayerSA : public CMultiplayer void InitHooks_ProjectileCollisionFix(); void InitHooks_ObjectStreamerOptimization(); void InitHooks_Postprocess(); + void InitHooks_DeviceSelection(); CRemoteDataStorage* CreateRemoteDataStorage(); void DestroyRemoteDataStorage(CRemoteDataStorage* pData); void AddRemoteDataStorage(CPlayerPed* pPed, CRemoteDataStorage* pData); @@ -311,7 +312,7 @@ class CMultiplayerSA : public CMultiplayer CLimits* GetLimits() { return &m_limits; } - void UpdateVehicleSuspension() noexcept; + void UpdateVehicleSuspension() const noexcept; virtual void FlushClothesCache(); virtual void SetFastClothesLoading(EFastClothesLoading fastClothesLoading); diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp new file mode 100644 index 0000000000..586f387270 --- /dev/null +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -0,0 +1,155 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#define FUNC_rwDeviceSystemRequest 0x7F2AB0 +#define FUNC_DialogFunc 0x745E50 +#define FUNC_RwEngineGetSubSystemInfo 0x7F2C30 +#define CLASS_RwGlobals 0xC97B24 +#define CLASS_IDirect3D9 0xC97C20 +#define NUM_DialogFuncStackPushAddress 0x746239 + +// This is copied from SilentPatch: +// https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp +std::unordered_map GetFriendlyMonitorNamesForDevicePaths() +{ + std::unordered_map monitorNames; + + HMODULE user32Lib = LoadLibrary(TEXT("user32")); + if (!user32Lib) + return monitorNames; + + auto* getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes"); + auto* queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig"); + auto* displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo"); + if (!getDisplayConfigBufferSizes || !queryDisplayConfig || !displayConfigGetDeviceInfo) + { + FreeLibrary(user32Lib); + return monitorNames; + } + + UINT32 pathCount, modeCount; + std::unique_ptr paths; + std::unique_ptr modes; + + LONG result = ERROR_SUCCESS; + do + { + result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); + if (result != ERROR_SUCCESS) + { + break; + } + paths = std::make_unique(pathCount); + modes = std::make_unique(modeCount); + result = queryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.get(), &modeCount, modes.get(), nullptr); + } while (result == ERROR_INSUFFICIENT_BUFFER); + + if (result != ERROR_SUCCESS) + { + FreeLibrary(user32Lib); + return monitorNames; + } + + for (size_t i = 0; i < pathCount; i++) + { + DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; + targetName.header.adapterId = paths[i].targetInfo.adapterId; + targetName.header.id = paths[i].targetInfo.id; + targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + targetName.header.size = sizeof(targetName); + const LONG targetNameResult = DisplayConfigGetDeviceInfo(&targetName.header); + + DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {}; + sourceName.header.adapterId = paths[i].sourceInfo.adapterId; + sourceName.header.id = paths[i].sourceInfo.id; + sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + sourceName.header.size = sizeof(sourceName); + const LONG sourceNameResult = DisplayConfigGetDeviceInfo(&sourceName.header); + if (targetNameResult == ERROR_SUCCESS && sourceNameResult == ERROR_SUCCESS && targetName.monitorFriendlyDeviceName[0] != '\0') + { + char gdiDeviceName[std::size(sourceName.viewGdiDeviceName)]; + char monitorFriendlyDeviceName[std::size(targetName.monitorFriendlyDeviceName)]; + WideCharToMultiByte(CP_ACP, 0, sourceName.viewGdiDeviceName, -1, gdiDeviceName, static_cast(std::size(gdiDeviceName)), nullptr, nullptr); + WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName, + static_cast(std::size(monitorFriendlyDeviceName)), nullptr, nullptr); + + monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName); + } + } + + FreeLibrary(user32Lib); + return monitorNames; +} + +struct RwSubSystemInfo +{ + char name[80]; +}; + +using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn); +static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, std::int32_t subSystemIndex) +{ + auto* rwGlobals = *(RwGlobals**)CLASS_RwGlobals; + auto* rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); + if (!rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex)) + return nullptr; + + auto* pDxDevice = *(IDirect3D9**)CLASS_IDirect3D9; + if (!pDxDevice) + return subSystemInfo; + + D3DADAPTER_IDENTIFIER9 identifier; + if (FAILED(pDxDevice->GetAdapterIdentifier(subSystemIndex, 0, &identifier))) + return subSystemInfo; + + static const auto friendlyNames = GetFriendlyMonitorNamesForDevicePaths(); + + // If we can't find the friendly name, either because it doesn't exist or we're on an ancient Windows, fall back to the device name + auto it = friendlyNames.find(identifier.DeviceName); + if (it != friendlyNames.end()) + { + strncpy_s(subSystemInfo->name, it->second.c_str(), _TRUNCATE); + } + else + { + strncpy_s(subSystemInfo->name, identifier.Description, _TRUNCATE); + } + + return subSystemInfo; +} + +INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) +{ + auto* orgDialogFunc = (DLGPROC)FUNC_DialogFunc; + if (msg != WM_INITDIALOG) + return orgDialogFunc(window, msg, wParam, lParam); + + orgDialogFunc(window, msg, wParam, lParam); + + // Set Icon + HMODULE hGameModule = GetModuleHandle(nullptr); + SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast(LoadIcon(hGameModule, MAKEINTRESOURCE(100)))); + + // Make the dialog visible in the task bar + // https://stackoverflow.com/a/1462811 + SetWindowLongPtr(window, GWL_EXSTYLE, WS_EX_APPWINDOW); + ShowWindow(window, SW_HIDE); + ShowWindow(window, SW_SHOW); + return FALSE; +} + +void CMultiplayerSA::InitHooks_DeviceSelection() +{ + // 0x746239 -> Exact address where the original DialogFunc address is being pushed as an argument to DialogBoxParamA(), + // we're replacing it with out own proxy function + MemPut(NUM_DialogFuncStackPushAddress, (DLGPROC)&CustomDlgProc); + HookInstall(FUNC_RwEngineGetSubSystemInfo, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6); +} diff --git a/Client/multiplayer_sa/CMultiplayerSA_Weapons.cpp b/Client/multiplayer_sa/CMultiplayerSA_Weapons.cpp index ea0f6fab19..d7513941df 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_Weapons.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_Weapons.cpp @@ -200,6 +200,33 @@ void _declspec(naked) HOOK_Fx_AddBulletImpact() } } +////////////////////////////////////////////////////////////////////////////////////////// +// +// CVisibilityPlugins::RenderWeaponPedsForPC +// +// Fix for the bright objects after weapon change sometimes +// +////////////////////////////////////////////////////////////////////////////////////////// +#define HOOKPOS_CVisibilityPlugins_RenderWeaponPedsForPC 0x733123 +#define HOOKSIZE_CVisibilityPlugins_RenderWeaponPedsForPC 5 +static constexpr DWORD CONTINUE_CVisibilityPlugins_RenderWeaponPedsForPC = 0x733128; +static void _declspec(naked) HOOK_CVisibilityPlugins_RenderWeaponPedsForPC() +{ + _asm + { + mov eax, 5DF4E0h + call eax // call CPed::ResetGunFlashAlpha + + mov eax, 5533B0h + mov ecx, ebx + + push 0 + call eax // call CPed::RemoveLighting + + jmp CONTINUE_CVisibilityPlugins_RenderWeaponPedsForPC + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // // CMultiplayerSA::InitHooks_Weapons @@ -212,4 +239,5 @@ void CMultiplayerSA::InitHooks_Weapons() EZHookInstall(CWeapon_GenerateDamageEvent); EZHookInstall(CShotInfo_Update); EZHookInstall(Fx_AddBulletImpact); + EZHookInstall(CVisibilityPlugins_RenderWeaponPedsForPC); } diff --git a/Client/sdk/core/CWebBrowserEventsInterface.h b/Client/sdk/core/CWebBrowserEventsInterface.h index 1db426df89..4479b5a050 100644 --- a/Client/sdk/core/CWebBrowserEventsInterface.h +++ b/Client/sdk/core/CWebBrowserEventsInterface.h @@ -28,4 +28,5 @@ class CWebBrowserEventsInterface virtual bool Events_OnResourceFileCheck(const SString& strURL, CBuffer& outFileData) = 0; virtual void Events_OnResourceBlocked(const SString& strURL, const SString& strDomain, unsigned char reason) = 0; virtual void Events_OnAjaxRequest(CAjaxResourceHandlerInterface* pHandler, const SString& strURL) = 0; + virtual void Events_OnConsoleMessage(const std::string& message, const std::string& source, int line, std::int16_t level) = 0; }; diff --git a/Client/sdk/core/CWebCoreInterface.h b/Client/sdk/core/CWebCoreInterface.h index e1e2f7651d..6b95690756 100644 --- a/Client/sdk/core/CWebCoreInterface.h +++ b/Client/sdk/core/CWebCoreInterface.h @@ -49,7 +49,7 @@ class CWebCoreInterface { public: virtual ~CWebCoreInterface() {} - virtual bool Initialise() = 0; + virtual bool Initialise(bool gpuEnabled) = 0; virtual CWebViewInterface* CreateWebView(unsigned int uiWidth, unsigned int uiHeight, bool bIsLocal, CWebBrowserItem* pWebBrowserRenderItem, bool bTransparent) = 0; @@ -90,4 +90,6 @@ class CWebCoreInterface virtual void WriteCustomList(const SString& strListName, const std::vector& customList, bool bReset = true) = 0; virtual void GetFilterEntriesByType(std::vector>& outEntries, eWebFilterType filterType, eWebFilterState state = eWebFilterState::WEBFILTER_ALL) = 0; + + virtual bool GetGPUEnabled() const noexcept = 0; }; diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 2314fdad0e..51f94c9d77 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -108,7 +108,7 @@ class __declspec(novtable) CGame typedef std::unique_ptr AssocGroup_type; public: - virtual CPools* GetPools() = 0; + virtual CPools* GetPools() const noexcept = 0; virtual CPlayerInfo* GetPlayerInfo() = 0; virtual CProjectileInfo* GetProjectileInfo() = 0; virtual CRadar* GetRadar() = 0; @@ -137,7 +137,7 @@ class __declspec(novtable) CGame virtual CCarEnterExit* GetCarEnterExit() = 0; virtual CControllerConfigManager* GetControllerConfigManager() = 0; virtual CRenderWare* GetRenderWare() = 0; - virtual CHandlingManager* GetHandlingManager() = 0; + virtual CHandlingManager* GetHandlingManager() const noexcept = 0; virtual CAnimManager* GetAnimManager() = 0; virtual CStreaming* GetStreaming() = 0; virtual CVisibilityPlugins* GetVisibilityPlugins() = 0; @@ -230,6 +230,9 @@ class __declspec(novtable) CGame virtual bool IsTunnelWeatherBlendEnabled() const noexcept = 0; virtual void SetTunnelWeatherBlendEnabled(bool isEnabled) = 0; + virtual bool IsIgnoreFireStateEnabled() const noexcept = 0; + virtual void SetIgnoreFireStateEnabled(bool isEnabled) = 0; + virtual CWeapon* CreateWeapon() = 0; virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0; diff --git a/Client/sdk/game/CHandlingEntry.h b/Client/sdk/game/CHandlingEntry.h index a2da6167c9..90038f6d07 100644 --- a/Client/sdk/game/CHandlingEntry.h +++ b/Client/sdk/game/CHandlingEntry.h @@ -91,78 +91,78 @@ class CHandlingEntry virtual ~CHandlingEntry(){}; // Use this to copy data from an another handling class to this - virtual void Assign(const CHandlingEntry* pEntry) = 0; + virtual void Assign(const CHandlingEntry* pEntry) noexcept = 0; // Get functions - virtual float GetMass() const = 0; - virtual float GetTurnMass() const = 0; - virtual float GetDragCoeff() const = 0; - virtual const CVector& GetCenterOfMass() const = 0; + virtual float GetMass() const noexcept = 0; + virtual float GetTurnMass() const noexcept = 0; + virtual float GetDragCoeff() const noexcept = 0; + virtual const CVector& GetCenterOfMass() const noexcept = 0; - virtual unsigned int GetPercentSubmerged() const = 0; - virtual float GetTractionMultiplier() const = 0; + virtual unsigned int GetPercentSubmerged() const noexcept = 0; + virtual float GetTractionMultiplier() const noexcept = 0; - virtual eDriveType GetCarDriveType() const = 0; - virtual eEngineType GetCarEngineType() const = 0; - virtual unsigned char GetNumberOfGears() const = 0; + virtual eDriveType GetCarDriveType() const noexcept = 0; + virtual eEngineType GetCarEngineType() const noexcept = 0; + virtual unsigned char GetNumberOfGears() const noexcept = 0; - virtual float GetEngineAcceleration() const = 0; - virtual float GetEngineInertia() const = 0; - virtual float GetMaxVelocity() const = 0; + virtual float GetEngineAcceleration() const noexcept = 0; + virtual float GetEngineInertia() const noexcept = 0; + virtual float GetMaxVelocity() const noexcept = 0; - virtual float GetBrakeDeceleration() const = 0; - virtual float GetBrakeBias() const = 0; - virtual bool GetABS() const = 0; + virtual float GetBrakeDeceleration() const noexcept = 0; + virtual float GetBrakeBias() const noexcept = 0; + virtual bool GetABS() const noexcept = 0; - virtual float GetSteeringLock() const = 0; - virtual float GetTractionLoss() const = 0; - virtual float GetTractionBias() const = 0; + virtual float GetSteeringLock() const noexcept = 0; + virtual float GetTractionLoss() const noexcept = 0; + virtual float GetTractionBias() const noexcept = 0; - virtual float GetSuspensionForceLevel() const = 0; - virtual float GetSuspensionDamping() const = 0; - virtual float GetSuspensionHighSpeedDamping() const = 0; - virtual float GetSuspensionUpperLimit() const = 0; - virtual float GetSuspensionLowerLimit() const = 0; - virtual float GetSuspensionFrontRearBias() const = 0; - virtual float GetSuspensionAntiDiveMultiplier() const = 0; + virtual float GetSuspensionForceLevel() const noexcept = 0; + virtual float GetSuspensionDamping() const noexcept = 0; + virtual float GetSuspensionHighSpeedDamping() const noexcept = 0; + virtual float GetSuspensionUpperLimit() const noexcept = 0; + virtual float GetSuspensionLowerLimit() const noexcept = 0; + virtual float GetSuspensionFrontRearBias() const noexcept = 0; + virtual float GetSuspensionAntiDiveMultiplier() const noexcept = 0; - virtual float GetCollisionDamageMultiplier() const = 0; + virtual float GetCollisionDamageMultiplier() const noexcept = 0; - virtual unsigned int GetHandlingFlags() const = 0; - virtual unsigned int GetModelFlags() const = 0; - virtual float GetSeatOffsetDistance() const = 0; - virtual unsigned int GetMonetary() const = 0; + virtual unsigned int GetHandlingFlags() const noexcept = 0; + virtual unsigned int GetModelFlags() const noexcept = 0; + virtual float GetSeatOffsetDistance() const noexcept = 0; + virtual unsigned int GetMonetary() const noexcept = 0; - virtual eLightType GetHeadLight() const = 0; - virtual eLightType GetTailLight() const = 0; - virtual unsigned char GetAnimGroup() const = 0; + virtual eLightType GetHeadLight() const noexcept = 0; + virtual eLightType GetTailLight() const noexcept = 0; + virtual unsigned char GetAnimGroup() const noexcept = 0; - virtual std::uint16_t GetVehicleID() const = 0; + virtual eHandlingTypes GetVehicleID() const noexcept = 0; // Set functions - virtual void SetMass(float fMass) = 0; - virtual void SetTurnMass(float fTurnMass) = 0; - virtual void SetDragCoeff(float fDrag) = 0; - virtual void SetCenterOfMass(const CVector& vecCenter) = 0; + virtual void SetMass(float fMass) noexcept = 0; + virtual void SetTurnMass(float fTurnMass) noexcept = 0; + virtual void SetDragCoeff(float fDrag) noexcept = 0; + virtual void SetCenterOfMass(const CVector& vecCenter) noexcept = 0; - virtual void SetPercentSubmerged(unsigned int uiPercent) = 0; - virtual void SetTractionMultiplier(float fTractionMultiplier) = 0; + virtual void SetPercentSubmerged(unsigned int uiPercent) noexcept = 0; + virtual void SetTractionMultiplier(float fTractionMultiplier) noexcept = 0; - virtual void SetCarDriveType(eDriveType Type) = 0; - virtual void SetCarEngineType(eEngineType Type) = 0; - virtual void SetNumberOfGears(unsigned char ucNumber) = 0; + virtual void SetCarDriveType(eDriveType Type) noexcept = 0; + virtual void SetCarEngineType(eEngineType Type) noexcept = 0; + virtual void SetNumberOfGears(unsigned char ucNumber) noexcept = 0; - virtual void SetEngineAcceleration(float fAcceleration) = 0; - virtual void SetEngineInertia(float fInertia) = 0; - virtual void SetMaxVelocity(float fVelocity) = 0; + virtual void SetEngineAcceleration(float fAcceleration) noexcept = 0; + virtual void SetEngineInertia(float fInertia) noexcept = 0; + virtual void SetMaxVelocity(float fVelocity) noexcept = 0; - virtual void SetBrakeDeceleration(float fDeceleration) = 0; - virtual void SetBrakeBias(float fBias) = 0; - virtual void SetABS(bool bABS) = 0; + virtual void SetBrakeDeceleration(float fDeceleration) noexcept = 0; + virtual void SetBrakeBias(float fBias) noexcept = 0; + virtual void SetABS(bool bABS) noexcept = 0; - virtual void SetSteeringLock(float fSteeringLock) = 0; - virtual void SetTractionLoss(float fTractionLoss) = 0; - virtual void SetTractionBias(float fTractionBias) = 0; + virtual void SetSteeringLock(float fSteeringLock) noexcept = 0; + virtual void SetTractionLoss(float fTractionLoss) noexcept = 0; + virtual void SetTractionBias(float fTractionBias) noexcept = 0; virtual void SetSuspensionForceLevel(float fForce) noexcept = 0; virtual void SetSuspensionDamping(float fDamping) noexcept = 0; @@ -172,18 +172,20 @@ class CHandlingEntry virtual void SetSuspensionFrontRearBias(float fBias) noexcept = 0; virtual void SetSuspensionAntiDiveMultiplier(float fAntiDive) noexcept = 0; - virtual void SetCollisionDamageMultiplier(float fMultiplier) = 0; + virtual void SetCollisionDamageMultiplier(float fMultiplier) noexcept = 0; - virtual void SetHandlingFlags(unsigned int uiFlags) = 0; - virtual void SetModelFlags(unsigned int uiFlags) = 0; - virtual void SetSeatOffsetDistance(float fDistance) = 0; - virtual void SetMonetary(unsigned int uiMonetary) = 0; + virtual void SetHandlingFlags(unsigned int uiFlags) noexcept = 0; + virtual void SetModelFlags(unsigned int uiFlags) noexcept = 0; + virtual void SetSeatOffsetDistance(float fDistance) noexcept = 0; + virtual void SetMonetary(unsigned int uiMonetary) noexcept = 0; - virtual void SetHeadLight(eLightType Style) = 0; - virtual void SetTailLight(eLightType Style) = 0; - virtual void SetAnimGroup(unsigned char ucGroup) = 0; + virtual void SetHeadLight(eLightType Style) noexcept = 0; + virtual void SetTailLight(eLightType Style) noexcept = 0; + virtual void SetAnimGroup(unsigned char ucGroup) noexcept = 0; + + virtual void CheckSuspensionChanges() const noexcept = 0; // Call this every time you're done changing something. This will recalculate // all transmission/handling values according to the new values. - virtual void Recalculate() = 0; + virtual void Recalculate() noexcept = 0; }; diff --git a/Client/sdk/game/CHandlingManager.h b/Client/sdk/game/CHandlingManager.h index 25d706220e..d10e55c8af 100644 --- a/Client/sdk/game/CHandlingManager.h +++ b/Client/sdk/game/CHandlingManager.h @@ -22,17 +22,17 @@ class CHandlingEntry; class CHandlingManager { public: - virtual CHandlingEntry* CreateHandlingData() = 0; - virtual CFlyingHandlingEntry* CreateFlyingHandlingData() = 0; - virtual CBoatHandlingEntry* CreateBoatHandlingData() = 0; - virtual CBikeHandlingEntry* CreateBikeHandlingData() = 0; + virtual std::unique_ptr CreateHandlingData() const noexcept = 0; + virtual std::unique_ptr CreateFlyingHandlingData() const noexcept = 0; + virtual std::unique_ptr CreateBoatHandlingData() const noexcept = 0; + virtual std::unique_ptr CreateBikeHandlingData() const noexcept = 0; - virtual const CHandlingEntry* GetOriginalHandlingData(enum eVehicleTypes eModel) const = 0; - virtual const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(enum eVehicleTypes eModel) const = 0; - virtual const CBoatHandlingEntry* GetOriginalBoatHandlingData(enum eVehicleTypes eModel) const = 0; - virtual const CBikeHandlingEntry* GetOriginalBikeHandlingData(enum eVehicleTypes eModel) const = 0; + virtual const CHandlingEntry* GetOriginalHandlingData(std::uint32_t model) const noexcept = 0; + virtual const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(std::uint32_t model) const noexcept = 0; + virtual const CBoatHandlingEntry* GetOriginalBoatHandlingData(std::uint32_t model) const noexcept = 0; + virtual const CBikeHandlingEntry* GetOriginalBikeHandlingData(std::uint32_t model) const noexcept = 0; - virtual eHandlingProperty GetPropertyEnumFromName(const std::string& strName) const = 0; + virtual eHandlingProperty GetPropertyEnumFromName(const std::string& name) const noexcept = 0; - virtual void CheckSuspensionChanges(CHandlingEntry* pEntry) noexcept = 0; + virtual void CheckSuspensionChanges(const CHandlingEntry* const pEntry) const noexcept = 0; }; diff --git a/Client/sdk/game/CModelInfo.h b/Client/sdk/game/CModelInfo.h index 08cb032e4c..c578be1990 100644 --- a/Client/sdk/game/CModelInfo.h +++ b/Client/sdk/game/CModelInfo.h @@ -15,6 +15,8 @@ #include "CAnimBlock.h" #include "Common.h" +constexpr std::uint16_t MODEL_PROPERTIES_GROUP_STATIC = 0xFFFF; + class CBaseModelInfoSAInterface; class CColModel; class CPedModelInfo; @@ -131,6 +133,7 @@ struct SVehicleSupportedUpgrades bool m_bMisc; bool m_bInitialised; }; + class CModelInfo { public: @@ -154,7 +157,7 @@ class CModelInfo virtual char* GetNameIfVehicle() = 0; - virtual BYTE GetVehicleType() = 0; + virtual BYTE GetVehicleType() const noexcept = 0; virtual void Request(EModelRequestType requestType, const char* szTag /* = NULL*/) = 0; virtual bool IsLoaded() = 0; virtual unsigned short GetFlags() = 0; @@ -165,7 +168,7 @@ class CModelInfo virtual void SetIdeFlag(eModelIdeFlag eFlag, bool bState) = 0; virtual CBoundingBox* GetBoundingBox() = 0; virtual bool IsValid() = 0; - virtual bool IsAllocatedInArchive() = 0; + virtual bool IsAllocatedInArchive() const noexcept = 0; virtual unsigned short GetTextureDictionaryID() = 0; virtual void SetTextureDictionaryID(unsigned short usTxdId) = 0; virtual void ResetTextureDictionaryID() = 0; diff --git a/Client/sdk/game/CPhysical.h b/Client/sdk/game/CPhysical.h index e46159456a..26e25465bb 100644 --- a/Client/sdk/game/CPhysical.h +++ b/Client/sdk/game/CPhysical.h @@ -20,7 +20,7 @@ class CPhysical : public virtual CEntity virtual CVector* GetMoveSpeed(CVector* vecMoveSpeed) = 0; virtual CVector* GetTurnSpeed(CVector* vecTurnSpeed) = 0; - virtual void SetMoveSpeed(CVector* vecMoveSpeed) = 0; + virtual void SetMoveSpeed(const CVector& vecMoveSpeed) noexcept = 0; virtual void SetTurnSpeed(CVector* vecTurnSpeed) = 0; virtual float GetMass() = 0; diff --git a/Client/sdk/game/CPools.h b/Client/sdk/game/CPools.h index 5b7dd0bd2b..46359a02a6 100644 --- a/Client/sdk/game/CPools.h +++ b/Client/sdk/game/CPools.h @@ -66,7 +66,7 @@ class CPools { public: // Vehicles pool - virtual CVehicle* AddVehicle(class CClientVehicle* pClientVehicle, eVehicleTypes eVehicleType, unsigned char ucVariation, unsigned char ucVariation2) = 0; + virtual CVehicle* AddVehicle(class CClientVehicle* pClientVehicle, std::uint16_t model, std::uint8_t variation, std::uint8_t variation2) noexcept = 0; virtual void RemoveVehicle(CVehicle* pVehicle, bool bDelete = true) = 0; virtual SClientEntity* GetVehicle(DWORD* pGameInterface) = 0; @@ -92,8 +92,8 @@ class CPools virtual unsigned long GetPedCount() = 0; // Others - virtual CVehicle* AddTrain(class CClientVehicle* pClientVehicle, CVector* vecPosition, DWORD dwModels[], int iSize, bool iDirection, - uchar ucTrackId = 0xFF) = 0; + virtual CVehicle* AddTrain(class CClientVehicle* pClientVehicle, const CVector& vecPosition, std::vector models, bool iDirection, + std::uint8_t ucTrackId = 255) noexcept = 0; virtual CEntity* GetEntity(DWORD* pGameInterface) = 0; virtual CClientEntity* GetClientEntity(DWORD* pGameInterface) = 0; diff --git a/Client/sdk/game/CProjectileInfo.h b/Client/sdk/game/CProjectileInfo.h index 586cbd029c..d32a538623 100644 --- a/Client/sdk/game/CProjectileInfo.h +++ b/Client/sdk/game/CProjectileInfo.h @@ -24,6 +24,7 @@ class CProjectileInfo virtual CProjectileInfo* GetProjectileInfo(void* projectileInfoInterface) = 0; // don't use virtual void RemoveProjectile(CProjectileInfo* pProjectileInfo, CProjectile* pProjectile, bool bBlow = true) = 0; virtual CProjectileInfo* GetProjectileInfo(DWORD Index) = 0; + virtual void RemoveEntityReferences(CEntity* entity) = 0; virtual CEntity* GetTarget() = 0; virtual void SetTarget(CEntity* pEntity) = 0; diff --git a/Client/sdk/game/CSettings.h b/Client/sdk/game/CSettings.h index d5ef10a05b..6ce85f2c2e 100644 --- a/Client/sdk/game/CSettings.h +++ b/Client/sdk/game/CSettings.h @@ -140,6 +140,8 @@ class CGameSettings virtual bool IsDynamicPedShadowsEnabled() = 0; virtual void SetDynamicPedShadowsEnabled(bool bEnable) = 0; + virtual bool IsDynamicPedShadowsEnabledByVideoSetting() const noexcept = 0; + virtual bool ResetDynamicPedShadows() noexcept = 0; virtual float GetAspectRatioValue() = 0; virtual eAspectRatio GetAspectRatio() = 0; diff --git a/Client/sdk/game/CTaskManager.h b/Client/sdk/game/CTaskManager.h index 3467f34928..f89d145dd4 100644 --- a/Client/sdk/game/CTaskManager.h +++ b/Client/sdk/game/CTaskManager.h @@ -41,6 +41,13 @@ enum ABORT_PRIORITY_IMMEDIATE }; +enum taskType +{ + PRIMARY_TASK = 0, + SECONDARY_TASK +}; + + class CTaskManager { public: diff --git a/Client/sdk/game/CWorld.h b/Client/sdk/game/CWorld.h index 3684172f01..c22762f7a8 100644 --- a/Client/sdk/game/CWorld.h +++ b/Client/sdk/game/CWorld.h @@ -10,6 +10,7 @@ *****************************************************************************/ #pragma once +#include "CEntity.h" class CEntitySAInterface; class CVector; @@ -61,6 +62,16 @@ struct SProcessLineOfSightMaterialInfoResult { bool valid{}; //< Data found in this struct is only valid if this is `true`! }; +struct STestSphereAgainstWorldResult +{ + bool collisionDetected{false}; + std::uint32_t modelID{0}; + CVector entityPosition{}; + CVector entityRotation{}; + std::uint32_t lodID{0}; + eEntityType type{ENTITY_TYPE_NOTHING}; +}; + enum eDebugCaller { CEntity_SetMatrix, @@ -274,4 +285,6 @@ class CWorld virtual CSurfaceType* GetSurfaceInfo() = 0; virtual void ResetAllSurfaceInfo() = 0; virtual bool ResetSurfaceInfo(short sSurfaceID) = 0; + + virtual CEntity* TestSphereAgainstWorld(const CVector& sphereCenter, float radius, CEntity* ignoredEntity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool cameraIgnore, STestSphereAgainstWorldResult& result) = 0; }; diff --git a/Client/sdk/game/RenderWare.h b/Client/sdk/game/RenderWare.h index 20249e01fd..d85011b291 100644 --- a/Client/sdk/game/RenderWare.h +++ b/Client/sdk/game/RenderWare.h @@ -526,3 +526,49 @@ struct RwError { int err1, err2; }; + +/*****************************************************************************/ +/** RenderWare Globals **/ +/*****************************************************************************/ + +typedef bool (*RwSystemFunc)(std::int32_t, void*, void*, std::int32_t); +struct RwDevice +{ + float gammaCorrection; + RwSystemFunc fpSystem; + float zBufferNear; + float zBufferFar; + // RwRenderStateSetFunction fpRenderStateSet; + // RwRenderStateGetFunction fpRenderStateGet; + // RwIm2DRenderLineFunction fpIm2DRenderLine; + // RwIm2DRenderTriangleFunction fpIm2DRenderTriangle; + // RwIm2DRenderPrimitiveFunction fpIm2DRenderPrimitive; + // RwIm2DRenderIndexedPrimitiveFunction fpIm2DRenderIndexedPrimitive; + // RwIm3DRenderLineFunction fpIm3DRenderLine; + // RwIm3DRenderTriangleFunction fpIm3DRenderTriangle; + // RwIm3DRenderPrimitiveFunction fpIm3DRenderPrimitive; + // RwIm3DRenderIndexedPrimitiveFunction fpIm3DRenderIndexedPrimitive; +}; +// static_assert(sizeof(RwDevice) == 0x38, "Incorrect class size: RwDevice"); + +typedef bool (*RwStandardFunc)(void*, void*, std::int32_t); +struct RwGlobals +{ + void* curCamera; + void* curWorld; + std::uint16_t renderFrame; + std::uint16_t lightFrame; + std::uint16_t pad[2]; + RwDevice dOpenDevice; + RwStandardFunc stdFunc[29]; + // RwLinkList dirtyFrameList; + // RwFileFunctions fileFuncs; + // RwStringFunctions stringFuncs; + // RwMemoryFunctions memoryFuncs; + // RwMemoryAllocFn memoryAlloc; + // RwMemoryFreeFn memoryFree; + // RwMetrics* metrics; + // RwEngineStatus engineStatus; + // RwUInt32 resArenaInitSize; +}; +//static_assert(sizeof(RwGlobals) == 0x158, "Incorrect class size: RwGlobals"); diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 02c932cf57..33e349ea71 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -429,7 +429,7 @@ class CMultiplayer virtual CLimits* GetLimits() = 0; - virtual void UpdateVehicleSuspension() noexcept = 0; + virtual void UpdateVehicleSuspension() const noexcept = 0; virtual void FlushClothesCache() = 0; virtual void SetFastClothesLoading(EFastClothesLoading fastClothesLoading) = 0; diff --git a/Client/sdk/net/CNet.h b/Client/sdk/net/CNet.h index cb38718f47..24a61a7a22 100644 --- a/Client/sdk/net/CNet.h +++ b/Client/sdk/net/CNet.h @@ -115,7 +115,7 @@ class CNet virtual const char* GetNextBuffer() = 0; virtual const char* GetDiagnosticStatus() = 0; - virtual void UpdatePingStatus(const char* szStatus, ushort& usDataRef, bool& isVerified) = 0; + virtual void UpdatePingStatus(const char* status, size_t statusLength, ushort& usDataRef, bool& isVerified) = 0; virtual bool VerifySignature(const char* pData, unsigned long ulSize) = 0; diff --git a/Server/mods/deathmatch/StdInc.h b/Server/mods/deathmatch/StdInc.h index c2e6355739..fb397aad5b 100644 --- a/Server/mods/deathmatch/StdInc.h +++ b/Server/mods/deathmatch/StdInc.h @@ -49,6 +49,7 @@ #include #include #include +#include "version.h" extern class CNetServer* g_pRealNetServer; extern class CGame* g_pGame; diff --git a/Server/mods/deathmatch/editor.conf b/Server/mods/deathmatch/editor.conf index f72486a6cb..1355e673ee 100644 --- a/Server/mods/deathmatch/editor.conf +++ b/Server/mods/deathmatch/editor.conf @@ -263,6 +263,16 @@ *NOTE* This only protects resources which use dbConnect with mysql Values: 0 - Off, 1 - Enabled. Default - 1 --> 1 + + + 1 + + + 1 diff --git a/Server/mods/deathmatch/local.conf b/Server/mods/deathmatch/local.conf index ec3defd37d..d30a608781 100644 --- a/Server/mods/deathmatch/local.conf +++ b/Server/mods/deathmatch/local.conf @@ -263,6 +263,22 @@ *NOTE* This only protects resources which use dbConnect with mysql Values: 0 - Off, 1 - Enabled. Default - 1 --> 1 + + + 1 + + + 0 + + + 1 diff --git a/Server/mods/deathmatch/logic/CConsoleCommands.cpp b/Server/mods/deathmatch/logic/CConsoleCommands.cpp index 5f19e566f3..a22c872eeb 100644 --- a/Server/mods/deathmatch/logic/CConsoleCommands.cpp +++ b/Server/mods/deathmatch/logic/CConsoleCommands.cpp @@ -24,6 +24,7 @@ #include "CDatabaseManager.h" #include "CGame.h" #include "CMainConfig.h" +#include "CMapManager.h" extern CGame* g_pGame; @@ -1111,6 +1112,9 @@ bool CConsoleCommands::Shutdown(CConsole* pConsole, const char* szArguments, CCl { // shutdown + CLuaArguments arguments; + arguments.PushNil(); + if (szArguments && strlen(szArguments) > 0) { // Copy to a buffer and strip it for bad characters @@ -1118,13 +1122,18 @@ bool CConsoleCommands::Shutdown(CConsole* pConsole, const char* szArguments, CCl // Output the action + reason to the console CLogger::LogPrintf("SHUTDOWN: Got shutdown command from %s (Reason: %s)\n", GetAdminNameForLog(pClient).c_str(), szBuffer); + arguments.PushString(szBuffer); } else { // Output the action to the console CLogger::LogPrintf("SHUTDOWN: Got shutdown command from %s (No reason specified)\n", GetAdminNameForLog(pClient).c_str()); + arguments.PushString("No reason specified"); } + // Call event + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onShutdown", arguments); + // Shut the server down asap g_pGame->SetIsFinished(true); return true; diff --git a/Server/mods/deathmatch/logic/CCustomData.cpp b/Server/mods/deathmatch/logic/CCustomData.cpp index f18bbd37d1..545df5a0c3 100644 --- a/Server/mods/deathmatch/logic/CCustomData.cpp +++ b/Server/mods/deathmatch/logic/CCustomData.cpp @@ -21,7 +21,7 @@ void CCustomData::Copy(CCustomData* pCustomData) } } -SCustomData* CCustomData::Get(const char* szName) +SCustomData* CCustomData::Get(const char* szName) const { assert(szName); @@ -100,6 +100,7 @@ void CCustomData::Set(const char* szName, const CLuaArgument& Variable, ESyncTyp SCustomData newData; newData.Variable = Variable; newData.syncType = syncType; + newData.clientChangesMode = eCustomDataClientTrust::UNSET; m_Data[szName] = newData; UpdateSynced(szName, Variable, syncType); } @@ -120,6 +121,12 @@ bool CCustomData::Delete(const char* szName) return false; } +void CCustomData::SetClientChangesMode(const char* szName, eCustomDataClientTrust mode) +{ + SCustomData& pData = m_Data[szName]; + pData.clientChangesMode = mode; +} + CXMLNode* CCustomData::OutputToXML(CXMLNode* pNode) { std::map::const_iterator iter = m_Data.begin(); diff --git a/Server/mods/deathmatch/logic/CCustomData.h b/Server/mods/deathmatch/logic/CCustomData.h index bfb17ff529..887ef34dee 100644 --- a/Server/mods/deathmatch/logic/CCustomData.h +++ b/Server/mods/deathmatch/logic/CCustomData.h @@ -25,10 +25,18 @@ enum class ESyncType SUBSCRIBE, }; +enum class eCustomDataClientTrust : std::uint8_t +{ + UNSET, + ALLOW, + DENY, +}; + struct SCustomData { - CLuaArgument Variable; - ESyncType syncType; + CLuaArgument Variable; + ESyncType syncType; + eCustomDataClientTrust clientChangesMode; }; class CCustomData @@ -36,12 +44,14 @@ class CCustomData public: void Copy(CCustomData* pCustomData); - SCustomData* Get(const char* szName); + SCustomData* Get(const char* szName) const; SCustomData* GetSynced(const char* szName); void Set(const char* szName, const CLuaArgument& Variable, ESyncType syncType = ESyncType::BROADCAST); bool Delete(const char* szName); + void SetClientChangesMode(const char* szName, eCustomDataClientTrust mode); + unsigned short CountOnlySynchronized(); CXMLNode* OutputToXML(CXMLNode* pNode); diff --git a/Server/mods/deathmatch/logic/CElement.cpp b/Server/mods/deathmatch/logic/CElement.cpp index 59086a2f14..79a051b545 100644 --- a/Server/mods/deathmatch/logic/CElement.cpp +++ b/Server/mods/deathmatch/logic/CElement.cpp @@ -508,7 +508,7 @@ void CElement::ReadCustomData(CEvents* pEvents, CXMLNode& Node) } } -CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType) +CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType, eCustomDataClientTrust* clientChangesMode) { assert(szName); @@ -518,13 +518,17 @@ CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESy { if (pSyncType) *pSyncType = pData->syncType; + + if (clientChangesMode) + *clientChangesMode = pData->clientChangesMode; + return &pData->Variable; } // If none, try returning parent's custom data if (bInheritData && m_pParent) { - return m_pParent->GetCustomData(szName, true, pSyncType); + return m_pParent->GetCustomData(szName, true, pSyncType, clientChangesMode); } // None available diff --git a/Server/mods/deathmatch/logic/CElement.h b/Server/mods/deathmatch/logic/CElement.h index e3a0fa4d07..802981cd5a 100644 --- a/Server/mods/deathmatch/logic/CElement.h +++ b/Server/mods/deathmatch/logic/CElement.h @@ -136,7 +136,7 @@ class CElement void ReadCustomData(CEvents* pEvents, CXMLNode& Node); CCustomData& GetCustomDataManager() { return m_CustomData; } - CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = NULL); + CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = nullptr, eCustomDataClientTrust* clientChangesMode = nullptr); CLuaArguments* GetAllCustomData(CLuaArguments* table); bool GetCustomDataString(const char* szName, char* pOut, size_t sizeBuffer, bool bInheritData); bool GetCustomDataInt(const char* szName, int& iOut, bool bInheritData); diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index d4efea393f..1bcdf5ce66 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -58,6 +58,7 @@ #include "packets/CPlayerNetworkStatusPacket.h" #include "packets/CPlayerListPacket.h" #include "packets/CPlayerClothesPacket.h" +#include "packets/CPlayerWorldSpecialPropertyPacket.h" #include "packets/CServerInfoSyncPacket.h" #include "packets/CLuaPacket.h" #include "../utils/COpenPortsTester.h" @@ -166,7 +167,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_pUnoccupiedVehicleSync = NULL; m_pConsole = NULL; m_pMapManager = NULL; - m_pHandlingManager = NULL; + m_HandlingManager = nullptr; m_pLuaManager = NULL; m_pPacketTranslator = NULL; m_pMarkerManager = NULL; @@ -258,6 +259,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_WorldSpecialProps[WorldSpecialProperty::EXTENDEDWATERCANNONS] = true; m_WorldSpecialProps[WorldSpecialProperty::ROADSIGNSTEXT] = true; m_WorldSpecialProps[WorldSpecialProperty::TUNNELWEATHERBLEND] = true; + m_WorldSpecialProps[WorldSpecialProperty::IGNOREFIRESTATE] = false; m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true; m_JetpackWeapons[WEAPONTYPE_TEC9] = true; @@ -343,9 +345,12 @@ CGame::~CGame() CSimControl::EnableSimSystem(false); // Disconnect all players - std::list::const_iterator iter = m_pPlayerManager->IterBegin(); - for (; iter != m_pPlayerManager->IterEnd(); iter++) - DisconnectPlayer(this, **iter, CPlayerDisconnectedPacket::SHUTDOWN); + if (m_pPlayerManager) + { + std::list::const_iterator iter = m_pPlayerManager->IterBegin(); + for (; iter != m_pPlayerManager->IterEnd(); iter++) + DisconnectPlayer(this, **iter, CPlayerDisconnectedPacket::SHUTDOWN); + } // Stop networking Stop(); @@ -372,7 +377,6 @@ CGame::~CGame() SAFE_DELETE(m_pRadarAreaManager); SAFE_DELETE(m_pPlayerManager); SAFE_DELETE(m_pVehicleManager); - SAFE_DELETE(m_pHandlingManager); SAFE_DELETE(m_pPickupManager); SAFE_DELETE(m_pObjectManager); SAFE_DELETE(m_pColManager); @@ -579,43 +583,57 @@ bool CGame::Start(int iArgumentCount, char* szArguments[]) CElement::StartupEntitiesFromRoot(); CSimControl::Startup(); - m_pGroups = new CGroups; - m_pClock = new CClock; - m_pBlipManager = new CBlipManager; - m_pColManager = new CColManager; - m_pObjectManager = new CObjectManager; - m_pPickupManager = new CPickupManager(m_pColManager); - m_pPlayerManager = new CPlayerManager; - m_pRadarAreaManager = new CRadarAreaManager; - m_pMarkerManager = new CMarkerManager(m_pColManager); - m_pHandlingManager = new CHandlingManager; - m_pVehicleManager = new CVehicleManager; - m_pPacketTranslator = new CPacketTranslator(m_pPlayerManager); - m_pBanManager = new CBanManager; - m_pTeamManager = new CTeamManager; - m_pPedManager = new CPedManager; - m_pWaterManager = new CWaterManager; - m_pScriptDebugging = new CScriptDebugging(); - m_pMapManager = - new CMapManager(m_pBlipManager, m_pObjectManager, m_pPickupManager, m_pPlayerManager, m_pRadarAreaManager, m_pMarkerManager, m_pVehicleManager, - m_pTeamManager, m_pPedManager, m_pColManager, m_pWaterManager, m_pClock, m_pGroups, &m_Events, m_pScriptDebugging, &m_ElementDeleter); - m_pACLManager = new CAccessControlListManager; - m_pHqComms = new CHqComms; - - m_pRegisteredCommands = new CRegisteredCommands(m_pACLManager); - m_pLuaManager = new CLuaManager(m_pObjectManager, m_pPlayerManager, m_pVehicleManager, m_pBlipManager, m_pRadarAreaManager, m_pRegisteredCommands, - m_pMapManager, &m_Events); - m_pConsole = new CConsole(m_pBlipManager, m_pMapManager, m_pPlayerManager, m_pRegisteredCommands, m_pVehicleManager, m_pBanManager, m_pACLManager); - m_pMainConfig = new CMainConfig(m_pConsole); - m_pRPCFunctions = new CRPCFunctions; - - m_pWeaponStatsManager = new CWeaponStatManager(); - - m_pBuildingRemovalManager = new CBuildingRemovalManager; - - m_pCustomWeaponManager = new CCustomWeaponManager(); - - m_pTrainTrackManager = std::make_shared(); + + try + { + m_pGroups = new CGroups; + m_pClock = new CClock; + m_pBlipManager = new CBlipManager; + m_pColManager = new CColManager; + m_pObjectManager = new CObjectManager; + m_pPickupManager = new CPickupManager(m_pColManager); + m_pPlayerManager = new CPlayerManager; + m_pRadarAreaManager = new CRadarAreaManager; + m_pMarkerManager = new CMarkerManager(m_pColManager); + m_HandlingManager = std::make_unique(); + m_pVehicleManager = new CVehicleManager; + m_pPacketTranslator = new CPacketTranslator(m_pPlayerManager); + m_pBanManager = new CBanManager; + m_pTeamManager = new CTeamManager; + m_pPedManager = new CPedManager; + m_pWaterManager = new CWaterManager; + m_pScriptDebugging = new CScriptDebugging(); + m_pMapManager = new CMapManager(m_pBlipManager, m_pObjectManager, m_pPickupManager, m_pPlayerManager, m_pRadarAreaManager, m_pMarkerManager, + m_pVehicleManager, m_pTeamManager, m_pPedManager, m_pColManager, m_pWaterManager, m_pClock, m_pGroups, &m_Events, + m_pScriptDebugging, &m_ElementDeleter); + m_pACLManager = new CAccessControlListManager; + m_pHqComms = new CHqComms; + + m_pRegisteredCommands = new CRegisteredCommands(m_pACLManager); + m_pLuaManager = new CLuaManager(m_pObjectManager, m_pPlayerManager, m_pVehicleManager, m_pBlipManager, m_pRadarAreaManager, m_pRegisteredCommands, + m_pMapManager, &m_Events); + m_pConsole = new CConsole(m_pBlipManager, m_pMapManager, m_pPlayerManager, m_pRegisteredCommands, m_pVehicleManager, m_pBanManager, m_pACLManager); + m_pMainConfig = new CMainConfig(m_pConsole); + m_pRPCFunctions = new CRPCFunctions; + + m_pWeaponStatsManager = new CWeaponStatManager(); + + m_pBuildingRemovalManager = new CBuildingRemovalManager; + + m_pCustomWeaponManager = new CCustomWeaponManager(); + + m_pTrainTrackManager = std::make_shared(); + } + catch (const std::bad_alloc& e) + { + std::cout << "ERROR: Memory allocations failed: " << e.what() << std::endl; + return false; + } + catch (const std::exception& e) + { + std::cout << "ERROR: Constructors failed: " << e.what() << std::endl; + return false; + } // Parse the commandline if (!m_CommandLineParser.Parse(iArgumentCount, szArguments)) @@ -1292,6 +1310,12 @@ bool CGame::ProcessPacket(CPacket& Packet) return true; } + case PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY: + { + Packet_PlayerWorldSpecialProperty(static_cast(Packet)); + return true; + } + default: break; } @@ -1607,6 +1631,8 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onPlayerTriggerEventThreshold", "", nullptr, false); m_Events.AddEvent("onPlayerTeamChange", "oldTeam, newTeam", nullptr, false); m_Events.AddEvent("onPlayerTriggerInvalidEvent", "eventName, isAdded, isRemote", nullptr, false); + m_Events.AddEvent("onPlayerChangesProtectedData", "element, key, value", nullptr, false); + m_Events.AddEvent("onPlayerChangesWorldSpecialProperty", "property, enabled", nullptr, false); // Ped events m_Events.AddEvent("onPedVehicleEnter", "vehicle, seat, jacked", NULL, false); @@ -1664,6 +1690,7 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onSettingChange", "setting, oldValue, newValue", NULL, false); m_Events.AddEvent("onChatMessage", "message, element", NULL, false); m_Events.AddEvent("onExplosion", "x, y, z, type, origin", nullptr, false); + m_Events.AddEvent("onShutdown", "resource, reason", nullptr, false); // Weapon events m_Events.AddEvent("onWeaponFire", "", NULL, false); @@ -1797,6 +1824,21 @@ void CGame::Packet_PlayerJoinData(CPlayerJoinDataPacket& Packet) return; } + // Check if another player is using the same serial + if (m_pMainConfig->IsCheckDuplicateSerialsEnabled() && m_pPlayerManager->GetBySerial(strSerial)) + { + // Tell the console + CLogger::LogPrintf("CONNECT: %s failed to connect (Serial already in use) (%s)\n", szNick, strIPAndSerial.c_str()); + + // Tell the player the problem + if (pPlayer->CanBitStream(eBitStreamVersion::CheckDuplicateSerials)) + DisconnectPlayer(this, *pPlayer, CPlayerDisconnectedPacket::SERIAL_DUPLICATE); + else + DisconnectPlayer(this, *pPlayer, CPlayerDisconnectedPacket::KICK); + + return; + } + // Check the nick is valid if (!CheckNickProvided(szNick)) { @@ -2652,7 +2694,24 @@ void CGame::Packet_CustomData(CCustomDataPacket& Packet) } ESyncType lastSyncType = ESyncType::BROADCAST; - pElement->GetCustomData(szName, false, &lastSyncType); + eCustomDataClientTrust clientChangesMode{}; + + pElement->GetCustomData(szName, false, &lastSyncType, &clientChangesMode); + + const bool changesAllowed = clientChangesMode == eCustomDataClientTrust::UNSET ? !m_pMainConfig->IsElementDataWhitelisted() + : clientChangesMode == eCustomDataClientTrust::ALLOW; + if (!changesAllowed) + { + CLogger::ErrorPrintf("Client trying to change protected element data %s (%s)", Packet.GetSourcePlayer()->GetNick(), + szName); + + CLuaArguments arguments; + arguments.PushElement(pElement); + arguments.PushString(szName); + arguments.PushArgument(Value); + pSourcePlayer->CallEvent("onPlayerChangesProtectedData", arguments); + return; + } if (lastSyncType != ESyncType::LOCAL) { @@ -4222,6 +4281,23 @@ void CGame::Packet_PlayerResourceStart(CPlayerResourceStartPacket& Packet) } } +void CGame::Packet_PlayerWorldSpecialProperty(CPlayerWorldSpecialPropertyPacket& packet) noexcept +{ + CPlayer* player = packet.GetSourcePlayer(); + + if (!player) + return; + + const std::string& property = packet.GetProperty(); + const bool enabled = packet.IsEnabled(); + + CLuaArguments arguments; + arguments.PushString(property); + arguments.PushBoolean(enabled); + + player->CallEvent("onPlayerChangesWorldSpecialProperty", arguments, nullptr); +} + void CGame::Packet_PlayerModInfo(CPlayerModInfoPacket& Packet) { CPlayer* pPlayer = Packet.GetSourcePlayer(); diff --git a/Server/mods/deathmatch/logic/CGame.h b/Server/mods/deathmatch/logic/CGame.h index d865e858ec..c4344a8180 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -215,55 +215,54 @@ class CGame void SetIsFinished(bool bFinished) { m_bIsFinished = bFinished; }; bool IsFinished() { return m_bIsFinished; }; - CMainConfig* GetConfig() { return m_pMainConfig; } - CHandlingManager* GetHandlingManager() { return m_pHandlingManager; } - CMapManager* GetMapManager() { return m_pMapManager; } - CPlayerManager* GetPlayerManager() { return m_pPlayerManager; } - CObjectManager* GetObjectManager() { return m_pObjectManager; } - CVehicleManager* GetVehicleManager() { return m_pVehicleManager; } - CTeamManager* GetTeamManager() { return m_pTeamManager; } - CUnoccupiedVehicleSync* GetUnoccupiedVehicleSync() { return m_pUnoccupiedVehicleSync; } - CPedSync* GetPedSync() { return m_pPedSync; } - CRegisteredCommands* GetRegisteredCommands() { return m_pRegisteredCommands; } + CMainConfig* GetConfig() { return m_pMainConfig; } + CHandlingManager* GetHandlingManager() const noexcept { return m_HandlingManager.get(); } + CMapManager* GetMapManager() { return m_pMapManager; } + CPlayerManager* GetPlayerManager() { return m_pPlayerManager; } + CObjectManager* GetObjectManager() { return m_pObjectManager; } + CVehicleManager* GetVehicleManager() { return m_pVehicleManager; } + CTeamManager* GetTeamManager() { return m_pTeamManager; } + CUnoccupiedVehicleSync* GetUnoccupiedVehicleSync() { return m_pUnoccupiedVehicleSync; } + CPedSync* GetPedSync() { return m_pPedSync; } + CRegisteredCommands* GetRegisteredCommands() { return m_pRegisteredCommands; } #ifdef WITH_OBJECT_SYNC - CObjectSync* GetObjectSync() { return m_pObjectSync; } + CObjectSync* GetObjectSync() { return m_pObjectSync; } #endif - CConsole* GetConsole() { return m_pConsole; } - CDatabaseManager* GetDatabaseManager() { return m_pDatabaseManager; } - CLuaCallbackManager* GetLuaCallbackManager() { return m_pLuaCallbackManager; } - CRegistryManager* GetRegistryManager() { return m_pRegistryManager; } - CRegistry* GetRegistry() { return m_pRegistry; } - CAccountManager* GetAccountManager() { return m_pAccountManager; } - CScriptDebugging* GetScriptDebugging() { return m_pScriptDebugging; } - CEvents* GetEvents() { return &m_Events; } - CColManager* GetColManager() { return m_pColManager; } - CLatentTransferManager* GetLatentTransferManager() { return m_pLatentTransferManager; } - CDebugHookManager* GetDebugHookManager() { return m_pDebugHookManager; } - CPedManager* GetPedManager() { return m_pPedManager; } - CResourceManager* GetResourceManager() { return m_pResourceManager; } - CMarkerManager* GetMarkerManager() { return m_pMarkerManager; } - CBlipManager* GetBlipManager() { return m_pBlipManager; } - CPickupManager* GetPickupManager() { return m_pPickupManager; } - CRadarAreaManager* GetRadarAreaManager() { return m_pRadarAreaManager; } - CGroups* GetGroups() { return m_pGroups; } - CElementDeleter* GetElementDeleter() { return &m_ElementDeleter; } - CConnectHistory* GetJoinFloodProtector() { return &m_FloodProtect; } - CHTTPD* GetHTTPD() { return m_pHTTPD; } - CSettings* GetSettings() { return m_pSettings; } - CAccessControlListManager* GetACLManager() { return m_pACLManager; } - CBanManager* GetBanManager() { return m_pBanManager; } - CRemoteCalls* GetRemoteCalls() { return m_pRemoteCalls; } - CZoneNames* GetZoneNames() { return m_pZoneNames; } - CClock* GetClock() { return m_pClock; } - CWaterManager* GetWaterManager() { return m_pWaterManager; } - CLightsyncManager* GetLightSyncManager() { return &m_lightsyncManager; } - CWeaponStatManager* GetWeaponStatManager() { return m_pWeaponStatsManager; } - CBuildingRemovalManager* GetBuildingRemovalManager() { return m_pBuildingRemovalManager; } - CCustomWeaponManager* GetCustomWeaponManager() { return m_pCustomWeaponManager; } - CFunctionUseLogger* GetFunctionUseLogger() { return m_pFunctionUseLogger; } - CMasterServerAnnouncer* GetMasterServerAnnouncer() { return m_pMasterServerAnnouncer; } - SharedUtil::CAsyncTaskScheduler* GetAsyncTaskScheduler() { return m_pAsyncTaskScheduler; } - + CConsole* GetConsole() { return m_pConsole; } + CDatabaseManager* GetDatabaseManager() { return m_pDatabaseManager; } + CLuaCallbackManager* GetLuaCallbackManager() { return m_pLuaCallbackManager; } + CRegistryManager* GetRegistryManager() { return m_pRegistryManager; } + CRegistry* GetRegistry() { return m_pRegistry; } + CAccountManager* GetAccountManager() { return m_pAccountManager; } + CScriptDebugging* GetScriptDebugging() { return m_pScriptDebugging; } + CEvents* GetEvents() { return &m_Events; } + CColManager* GetColManager() { return m_pColManager; } + CLatentTransferManager* GetLatentTransferManager() { return m_pLatentTransferManager; } + CDebugHookManager* GetDebugHookManager() { return m_pDebugHookManager; } + CPedManager* GetPedManager() { return m_pPedManager; } + CResourceManager* GetResourceManager() { return m_pResourceManager; } + CMarkerManager* GetMarkerManager() { return m_pMarkerManager; } + CBlipManager* GetBlipManager() { return m_pBlipManager; } + CPickupManager* GetPickupManager() { return m_pPickupManager; } + CRadarAreaManager* GetRadarAreaManager() { return m_pRadarAreaManager; } + CGroups* GetGroups() { return m_pGroups; } + CElementDeleter* GetElementDeleter() { return &m_ElementDeleter; } + CConnectHistory* GetJoinFloodProtector() { return &m_FloodProtect; } + CHTTPD* GetHTTPD() { return m_pHTTPD; } + CSettings* GetSettings() { return m_pSettings; } + CAccessControlListManager* GetACLManager() { return m_pACLManager; } + CBanManager* GetBanManager() { return m_pBanManager; } + CRemoteCalls* GetRemoteCalls() { return m_pRemoteCalls; } + CZoneNames* GetZoneNames() { return m_pZoneNames; } + CClock* GetClock() { return m_pClock; } + CWaterManager* GetWaterManager() { return m_pWaterManager; } + CLightsyncManager* GetLightSyncManager() { return &m_lightsyncManager; } + CWeaponStatManager* GetWeaponStatManager() { return m_pWeaponStatsManager; } + CBuildingRemovalManager* GetBuildingRemovalManager() { return m_pBuildingRemovalManager; } + CCustomWeaponManager* GetCustomWeaponManager() { return m_pCustomWeaponManager; } + CFunctionUseLogger* GetFunctionUseLogger() { return m_pFunctionUseLogger; } + CMasterServerAnnouncer* GetMasterServerAnnouncer() { return m_pMasterServerAnnouncer; } + SharedUtil::CAsyncTaskScheduler* GetAsyncTaskScheduler() { return m_pAsyncTaskScheduler; } std::shared_ptr GetTrainTrackManager() { return m_pTrainTrackManager; } void JoinPlayer(CPlayer& Player); @@ -519,6 +518,7 @@ class CGame void Packet_PlayerNoSocket(class CPlayerNoSocketPacket& Packet); void Packet_PlayerNetworkStatus(class CPlayerNetworkStatusPacket& Packet); void Packet_PlayerResourceStart(class CPlayerResourceStartPacket& Packet); + void Packet_PlayerWorldSpecialProperty(class CPlayerWorldSpecialPropertyPacket& packet) noexcept; static void PlayerCompleteConnect(CPlayer* pPlayer); @@ -528,53 +528,53 @@ class CGame // Technically, this could be put somewhere else. It's a callback function // which the voice server library will call to send out data. - CEvents m_Events; - CRemoteCalls* m_pRemoteCalls; - CHTTPD* m_pHTTPD; - CMainConfig* m_pMainConfig; - CBlipManager* m_pBlipManager; - CGroups* m_pGroups; - CColManager* m_pColManager; - CObjectManager* m_pObjectManager; - CPickupManager* m_pPickupManager; - CPlayerManager* m_pPlayerManager; - CRadarAreaManager* m_pRadarAreaManager; - CVehicleManager* m_pVehicleManager; - CPacketTranslator* m_pPacketTranslator; - CMapManager* m_pMapManager; - CElementDeleter m_ElementDeleter; - CConnectHistory m_FloodProtect; - CLuaManager* m_pLuaManager; - CScriptDebugging* m_pScriptDebugging; - CConsole* m_pConsole; - CUnoccupiedVehicleSync* m_pUnoccupiedVehicleSync; - CPedSync* m_pPedSync; + CEvents m_Events; + CRemoteCalls* m_pRemoteCalls; + CHTTPD* m_pHTTPD; + CMainConfig* m_pMainConfig; + CBlipManager* m_pBlipManager; + CGroups* m_pGroups; + CColManager* m_pColManager; + CObjectManager* m_pObjectManager; + CPickupManager* m_pPickupManager; + CPlayerManager* m_pPlayerManager; + CRadarAreaManager* m_pRadarAreaManager; + CVehicleManager* m_pVehicleManager; + CPacketTranslator* m_pPacketTranslator; + CMapManager* m_pMapManager; + CElementDeleter m_ElementDeleter; + CConnectHistory m_FloodProtect; + CLuaManager* m_pLuaManager; + CScriptDebugging* m_pScriptDebugging; + CConsole* m_pConsole; + CUnoccupiedVehicleSync* m_pUnoccupiedVehicleSync; + CPedSync* m_pPedSync; #ifdef WITH_OBJECT_SYNC - CObjectSync* m_pObjectSync; + CObjectSync* m_pObjectSync; #endif - CMarkerManager* m_pMarkerManager; - CClock* m_pClock; - CBanManager* m_pBanManager; - CTeamManager* m_pTeamManager; - CCommandLineParser m_CommandLineParser; - CRegisteredCommands* m_pRegisteredCommands; - CDatabaseManager* m_pDatabaseManager; - CLuaCallbackManager* m_pLuaCallbackManager; - CRegistryManager* m_pRegistryManager; - CRegistry* m_pRegistry; - CAccountManager* m_pAccountManager; - CLatentTransferManager* m_pLatentTransferManager; - CDebugHookManager* m_pDebugHookManager; - CPedManager* m_pPedManager; - CResourceManager* m_pResourceManager; - CAccessControlListManager* m_pACLManager; - CSettings* m_pSettings; - CZoneNames* m_pZoneNames; - ASE* m_pASE; - CHandlingManager* m_pHandlingManager; - CRPCFunctions* m_pRPCFunctions; - CLanBroadcast* m_pLanBroadcast; - CWaterManager* m_pWaterManager; + CMarkerManager* m_pMarkerManager; + CClock* m_pClock; + CBanManager* m_pBanManager; + CTeamManager* m_pTeamManager; + CCommandLineParser m_CommandLineParser; + CRegisteredCommands* m_pRegisteredCommands; + CDatabaseManager* m_pDatabaseManager; + CLuaCallbackManager* m_pLuaCallbackManager; + CRegistryManager* m_pRegistryManager; + CRegistry* m_pRegistry; + CAccountManager* m_pAccountManager; + CLatentTransferManager* m_pLatentTransferManager; + CDebugHookManager* m_pDebugHookManager; + CPedManager* m_pPedManager; + CResourceManager* m_pResourceManager; + CAccessControlListManager* m_pACLManager; + CSettings* m_pSettings; + CZoneNames* m_pZoneNames; + ASE* m_pASE; + std::unique_ptr m_HandlingManager; + CRPCFunctions* m_pRPCFunctions; + CLanBroadcast* m_pLanBroadcast; + CWaterManager* m_pWaterManager; CWeaponStatManager* m_pWeaponStatsManager; CBuildingRemovalManager* m_pBuildingRemovalManager; diff --git a/Server/mods/deathmatch/logic/CHandlingEntry.cpp b/Server/mods/deathmatch/logic/CHandlingEntry.cpp index 7079a9a223..eef8923604 100644 --- a/Server/mods/deathmatch/logic/CHandlingEntry.cpp +++ b/Server/mods/deathmatch/logic/CHandlingEntry.cpp @@ -2,10 +2,10 @@ * * PROJECT: Multi Theft Auto v1.0 * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CHandlingEntry.cpp + * FILE: Server/mods/deathmatch/logic/CHandlingEntry.cpp * PURPOSE: Vehicle handling data entry * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -14,16 +14,19 @@ CHandlingEntry::CHandlingEntry(tHandlingData* pOriginal) { - if (pOriginal) - { - // Copy the data from our original - m_Handling = *pOriginal; - } + if (!pOriginal) + return; + + // Copy the data from our original + m_Handling = *pOriginal; } // Apply the handling data from another data -void CHandlingEntry::ApplyHandlingData(const CHandlingEntry* pData) +void CHandlingEntry::ApplyHandlingData(const CHandlingEntry* const pData) noexcept { + if (!pData) + return; + // Copy the data from our handling entry m_Handling = pData->m_Handling; } diff --git a/Server/mods/deathmatch/logic/CHandlingEntry.h b/Server/mods/deathmatch/logic/CHandlingEntry.h index 4dd866baac..7f2afeca2a 100644 --- a/Server/mods/deathmatch/logic/CHandlingEntry.h +++ b/Server/mods/deathmatch/logic/CHandlingEntry.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CHandlingEntry.h + * FILE: Server/mods/deathmatch/logic/CHandlingEntry.h * PURPOSE: Header file for vehicle handling data entry class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -104,96 +104,96 @@ class CHandlingEntry ~CHandlingEntry(){}; // Use this to copy data from an another handling class to this - void ApplyHandlingData(const CHandlingEntry* pData); + void ApplyHandlingData(const CHandlingEntry* const pData) noexcept; // Get functions - tHandlingData GetHandlingData() { return m_Handling; }; - float GetMass() const { return m_Handling.fMass; }; - float GetTurnMass() const { return m_Handling.fTurnMass; }; - float GetDragCoeff() const { return m_Handling.fDragCoeff; }; - const CVector& GetCenterOfMass() const { return m_Handling.vecCenterOfMass; }; - - unsigned int GetPercentSubmerged() const { return m_Handling.uiPercentSubmerged; }; - float GetTractionMultiplier() const { return m_Handling.fTractionMultiplier; }; - - eDriveType GetCarDriveType() const { return static_cast(m_Handling.Transmission.ucDriveType); }; - eEngineType GetCarEngineType() const { return static_cast(m_Handling.Transmission.ucEngineType); }; - unsigned char GetNumberOfGears() const { return m_Handling.Transmission.ucNumberOfGears; }; - - float GetEngineAcceleration() const { return m_Handling.Transmission.fEngineAcceleration; }; - float GetEngineInertia() const { return m_Handling.Transmission.fEngineInertia; }; - float GetMaxVelocity() const { return m_Handling.Transmission.fMaxVelocity; }; - - float GetBrakeDeceleration() const { return m_Handling.fBrakeDeceleration; }; - float GetBrakeBias() const { return m_Handling.fBrakeBias; }; - bool GetABS() const { return m_Handling.bABS; }; - - float GetSteeringLock() const { return m_Handling.fSteeringLock; }; - float GetTractionLoss() const { return m_Handling.fTractionLoss; }; - float GetTractionBias() const { return m_Handling.fTractionBias; }; - - float GetSuspensionForceLevel() const { return m_Handling.fSuspensionForceLevel; }; - float GetSuspensionDamping() const { return m_Handling.fSuspensionDamping; }; - float GetSuspensionHighSpeedDamping() const { return m_Handling.fSuspensionHighSpdDamping; }; - float GetSuspensionUpperLimit() const { return m_Handling.fSuspensionUpperLimit; }; - float GetSuspensionLowerLimit() const { return m_Handling.fSuspensionLowerLimit; }; - float GetSuspensionFrontRearBias() const { return m_Handling.fSuspensionFrontRearBias; }; - float GetSuspensionAntiDiveMultiplier() const { return m_Handling.fSuspensionAntiDiveMultiplier; }; - - float GetCollisionDamageMultiplier() const { return m_Handling.fCollisionDamageMultiplier; }; - - unsigned int GetHandlingFlags() const { return m_Handling.uiHandlingFlags; }; - unsigned int GetModelFlags() const { return m_Handling.uiModelFlags; }; - float GetSeatOffsetDistance() const { return m_Handling.fSeatOffsetDistance; }; - unsigned int GetMonetary() const { return m_Handling.uiMonetary; }; - - eLightType GetHeadLight() const { return static_cast(m_Handling.ucHeadLight); }; - eLightType GetTailLight() const { return static_cast(m_Handling.ucTailLight); }; - unsigned char GetAnimGroup() const { return m_Handling.ucAnimGroup; }; + tHandlingData GetHandlingData() const noexcept { return m_Handling; } + float GetMass() const noexcept { return m_Handling.fMass; } + float GetTurnMass() const noexcept { return m_Handling.fTurnMass; } + float GetDragCoeff() const noexcept { return m_Handling.fDragCoeff; } + const CVector& GetCenterOfMass() const noexcept { return m_Handling.vecCenterOfMass; } + + unsigned int GetPercentSubmerged() const noexcept { return m_Handling.uiPercentSubmerged; } + float GetTractionMultiplier() const noexcept { return m_Handling.fTractionMultiplier; } + + eDriveType GetCarDriveType() const noexcept { return static_cast(m_Handling.Transmission.ucDriveType); } + eEngineType GetCarEngineType() const noexcept { return static_cast(m_Handling.Transmission.ucEngineType); } + unsigned char GetNumberOfGears() const noexcept { return m_Handling.Transmission.ucNumberOfGears; } + + float GetEngineAcceleration() const noexcept { return m_Handling.Transmission.fEngineAcceleration; } + float GetEngineInertia() const noexcept { return m_Handling.Transmission.fEngineInertia; } + float GetMaxVelocity() const noexcept { return m_Handling.Transmission.fMaxVelocity; } + + float GetBrakeDeceleration() const noexcept { return m_Handling.fBrakeDeceleration; } + float GetBrakeBias() const noexcept { return m_Handling.fBrakeBias; } + bool GetABS() const noexcept { return m_Handling.bABS; } + + float GetSteeringLock() const noexcept { return m_Handling.fSteeringLock; } + float GetTractionLoss() const noexcept { return m_Handling.fTractionLoss; } + float GetTractionBias() const noexcept { return m_Handling.fTractionBias; } + + float GetSuspensionForceLevel() const noexcept { return m_Handling.fSuspensionForceLevel; } + float GetSuspensionDamping() const noexcept { return m_Handling.fSuspensionDamping; } + float GetSuspensionHighSpeedDamping() const noexcept { return m_Handling.fSuspensionHighSpdDamping; } + float GetSuspensionUpperLimit() const noexcept { return m_Handling.fSuspensionUpperLimit; } + float GetSuspensionLowerLimit() const noexcept { return m_Handling.fSuspensionLowerLimit; } + float GetSuspensionFrontRearBias() const noexcept { return m_Handling.fSuspensionFrontRearBias; } + float GetSuspensionAntiDiveMultiplier() const noexcept { return m_Handling.fSuspensionAntiDiveMultiplier; } + + float GetCollisionDamageMultiplier() const noexcept { return m_Handling.fCollisionDamageMultiplier; } + + unsigned int GetHandlingFlags() const noexcept { return m_Handling.uiHandlingFlags; } + unsigned int GetModelFlags() const noexcept { return m_Handling.uiModelFlags; } + float GetSeatOffsetDistance() const noexcept { return m_Handling.fSeatOffsetDistance; } + unsigned int GetMonetary() const noexcept { return m_Handling.uiMonetary; } + + eLightType GetHeadLight() const noexcept { return static_cast(m_Handling.ucHeadLight); } + eLightType GetTailLight() const noexcept { return static_cast(m_Handling.ucTailLight); } + unsigned char GetAnimGroup() const noexcept { return m_Handling.ucAnimGroup; } // Set functions - void SetMass(float fMass) { m_Handling.fMass = fMass; }; - void SetTurnMass(float fTurnMass) { m_Handling.fTurnMass = fTurnMass; }; - void SetDragCoeff(float fDrag) { m_Handling.fDragCoeff = fDrag; }; - void SetCenterOfMass(const CVector& vecCenter) { m_Handling.vecCenterOfMass = vecCenter; }; - - void SetPercentSubmerged(unsigned int uiPercent) { m_Handling.uiPercentSubmerged = uiPercent; }; - void SetTractionMultiplier(float fTractionMultiplier) { m_Handling.fTractionMultiplier = fTractionMultiplier; }; - - void SetCarDriveType(eDriveType Type) { m_Handling.Transmission.ucDriveType = Type; }; - void SetCarEngineType(eEngineType Type) { m_Handling.Transmission.ucEngineType = Type; }; - void SetNumberOfGears(unsigned char ucNumber) { m_Handling.Transmission.ucNumberOfGears = ucNumber; }; - - void SetEngineAcceleration(float fAcceleration) { m_Handling.Transmission.fEngineAcceleration = fAcceleration; }; - void SetEngineInertia(float fInertia) { m_Handling.Transmission.fEngineInertia = fInertia; }; - void SetMaxVelocity(float fVelocity) { m_Handling.Transmission.fMaxVelocity = fVelocity; }; - - void SetBrakeDeceleration(float fDeceleration) { m_Handling.fBrakeDeceleration = fDeceleration; }; - void SetBrakeBias(float fBias) { m_Handling.fBrakeBias = fBias; }; - void SetABS(bool bABS) { m_Handling.bABS = bABS; }; - - void SetSteeringLock(float fSteeringLock) { m_Handling.fSteeringLock = fSteeringLock; }; - void SetTractionLoss(float fTractionLoss) { m_Handling.fTractionLoss = fTractionLoss; }; - void SetTractionBias(float fTractionBias) { m_Handling.fTractionBias = fTractionBias; }; - - void SetSuspensionForceLevel(float fForce) { m_Handling.fSuspensionForceLevel = fForce; }; - void SetSuspensionDamping(float fDamping) { m_Handling.fSuspensionDamping = fDamping; }; - void SetSuspensionHighSpeedDamping(float fDamping) { m_Handling.fSuspensionHighSpdDamping = fDamping; }; - void SetSuspensionUpperLimit(float fUpperLimit) { m_Handling.fSuspensionUpperLimit = fUpperLimit; }; - void SetSuspensionLowerLimit(float fLowerLimit) { m_Handling.fSuspensionLowerLimit = fLowerLimit; }; - void SetSuspensionFrontRearBias(float fBias) { m_Handling.fSuspensionFrontRearBias = fBias; }; - void SetSuspensionAntiDiveMultiplier(float fAntidive) { m_Handling.fSuspensionAntiDiveMultiplier = fAntidive; }; - - void SetCollisionDamageMultiplier(float fMultiplier) { m_Handling.fCollisionDamageMultiplier = fMultiplier; }; - - void SetHandlingFlags(unsigned int uiFlags) { m_Handling.uiHandlingFlags = uiFlags; }; - void SetModelFlags(unsigned int uiFlags) { m_Handling.uiModelFlags = uiFlags; }; - void SetSeatOffsetDistance(float fDistance) { m_Handling.fSeatOffsetDistance = fDistance; }; - void SetMonetary(unsigned int uiMonetary) { m_Handling.uiMonetary = uiMonetary; }; - - void SetHeadLight(eLightType Style) { m_Handling.ucHeadLight = Style; }; - void SetTailLight(eLightType Style) { m_Handling.ucTailLight = Style; }; - void SetAnimGroup(unsigned char ucGroup) { m_Handling.ucAnimGroup = ucGroup; }; + void SetMass(float fMass) noexcept { m_Handling.fMass = fMass; } + void SetTurnMass(float fTurnMass) noexcept { m_Handling.fTurnMass = fTurnMass; } + void SetDragCoeff(float fDrag) noexcept { m_Handling.fDragCoeff = fDrag; } + void SetCenterOfMass(const CVector& vecCenter) noexcept { m_Handling.vecCenterOfMass = vecCenter; } + + void SetPercentSubmerged(unsigned int uiPercent) noexcept { m_Handling.uiPercentSubmerged = uiPercent; } + void SetTractionMultiplier(float fTractionMultiplier) noexcept { m_Handling.fTractionMultiplier = fTractionMultiplier; } + + void SetCarDriveType(eDriveType Type) noexcept { m_Handling.Transmission.ucDriveType = Type; } + void SetCarEngineType(eEngineType Type) noexcept { m_Handling.Transmission.ucEngineType = Type; } + void SetNumberOfGears(unsigned char ucNumber) noexcept { m_Handling.Transmission.ucNumberOfGears = ucNumber; } + + void SetEngineAcceleration(float fAcceleration) noexcept { m_Handling.Transmission.fEngineAcceleration = fAcceleration; } + void SetEngineInertia(float fInertia) noexcept { m_Handling.Transmission.fEngineInertia = fInertia; } + void SetMaxVelocity(float fVelocity) noexcept { m_Handling.Transmission.fMaxVelocity = fVelocity; } + + void SetBrakeDeceleration(float fDeceleration) noexcept { m_Handling.fBrakeDeceleration = fDeceleration; } + void SetBrakeBias(float fBias) noexcept { m_Handling.fBrakeBias = fBias; } + void SetABS(bool bABS) noexcept { m_Handling.bABS = bABS; } + + void SetSteeringLock(float fSteeringLock) noexcept { m_Handling.fSteeringLock = fSteeringLock; } + void SetTractionLoss(float fTractionLoss) noexcept { m_Handling.fTractionLoss = fTractionLoss; } + void SetTractionBias(float fTractionBias) noexcept { m_Handling.fTractionBias = fTractionBias; } + + void SetSuspensionForceLevel(float fForce) noexcept { m_Handling.fSuspensionForceLevel = fForce; } + void SetSuspensionDamping(float fDamping) noexcept { m_Handling.fSuspensionDamping = fDamping; } + void SetSuspensionHighSpeedDamping(float fDamping) noexcept { m_Handling.fSuspensionHighSpdDamping = fDamping; } + void SetSuspensionUpperLimit(float fUpperLimit) noexcept { m_Handling.fSuspensionUpperLimit = fUpperLimit; } + void SetSuspensionLowerLimit(float fLowerLimit) noexcept { m_Handling.fSuspensionLowerLimit = fLowerLimit; } + void SetSuspensionFrontRearBias(float fBias) noexcept { m_Handling.fSuspensionFrontRearBias = fBias; } + void SetSuspensionAntiDiveMultiplier(float fAntidive) noexcept { m_Handling.fSuspensionAntiDiveMultiplier = fAntidive; } + + void SetCollisionDamageMultiplier(float fMultiplier) noexcept { m_Handling.fCollisionDamageMultiplier = fMultiplier; } + + void SetHandlingFlags(unsigned int uiFlags) noexcept { m_Handling.uiHandlingFlags = uiFlags; } + void SetModelFlags(unsigned int uiFlags) noexcept { m_Handling.uiModelFlags = uiFlags; } + void SetSeatOffsetDistance(float fDistance) noexcept { m_Handling.fSeatOffsetDistance = fDistance; } + void SetMonetary(unsigned int uiMonetary) noexcept { m_Handling.uiMonetary = uiMonetary; } + + void SetHeadLight(eLightType Style) noexcept { m_Handling.ucHeadLight = Style; } + void SetTailLight(eLightType Style) noexcept { m_Handling.ucTailLight = Style; } + void SetAnimGroup(unsigned char ucGroup) noexcept { m_Handling.ucAnimGroup = ucGroup; } private: tHandlingData m_Handling; diff --git a/Server/mods/deathmatch/logic/CHandlingManager.cpp b/Server/mods/deathmatch/logic/CHandlingManager.cpp index 8f7be518c9..bc491da14f 100644 --- a/Server/mods/deathmatch/logic/CHandlingManager.cpp +++ b/Server/mods/deathmatch/logic/CHandlingManager.cpp @@ -14,10 +14,15 @@ #include "CCommon.h" #include "CVehicleManager.h" -SFixedArray CHandlingManager::m_OriginalHandlingData; +// Original handling data +static tHandlingData m_OriginalHandlingData[HT_MAX]; +static std::unique_ptr m_OriginalEntries[HT_MAX]; -SFixedArray CHandlingManager::m_pOriginalEntries; -SFixedArray CHandlingManager::m_pModelEntries; +// Model handling data +static std::unordered_map> m_ModelEntries; +static std::unordered_map m_bModelHandlingChanged; + +static std::map m_HandlingNames; CHandlingManager::CHandlingManager() { @@ -25,14 +30,10 @@ CHandlingManager::CHandlingManager() InitializeDefaultHandlings(); // Create a handling entry - for (int i = 0; i < HT_MAX; i++) + for (std::size_t i = 0; i < HT_MAX; i++) { // For every original handling data - m_pOriginalEntries[i] = new CHandlingEntry(&m_OriginalHandlingData[i]); - - // For every model - m_pModelEntries[i] = new CHandlingEntry(&m_OriginalHandlingData[i]); - m_bModelHandlingChanged[i] = false; + m_OriginalEntries[i] = std::make_unique(&m_OriginalHandlingData[i]); } // http://www.gtamodding.com/index.php?title=Handling.cfg#GTA_San_Andreas @@ -76,93 +77,88 @@ CHandlingManager::CHandlingManager() CHandlingManager::~CHandlingManager() { - // Destroy - for (int i = 0; i < HT_MAX; i++) - { - // All original handling entries - delete m_pOriginalEntries[i]; - - // All model handling entries - delete m_pModelEntries[i]; - } } -CHandlingEntry* CHandlingManager::CreateHandlingData() +std::unique_ptr CHandlingManager::CreateHandlingData() const noexcept { - return new CHandlingEntry; + return std::make_unique(); } -bool CHandlingManager::ApplyHandlingData(eVehicleTypes eModel, CHandlingEntry* pEntry) +bool CHandlingManager::ApplyHandlingData(std::uint32_t model, CHandlingEntry* pEntry) const noexcept { - // Within range? - if (!CVehicleManager::IsValidModel(eModel)) + CHandlingEntry* pHandling = GetModelHandlingData(model); + if (!pHandling) return false; - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Apply the data and return success - m_pModelEntries[eHandling]->ApplyHandlingData(pEntry); + pHandling->ApplyHandlingData(pEntry); return true; } -const CHandlingEntry* CHandlingManager::GetOriginalHandlingData(eVehicleTypes eModel) +const CHandlingEntry* CHandlingManager::GetOriginalHandlingData(std::uint32_t model) const noexcept { // Within range? - if (!CVehicleManager::IsValidModel(eModel)) + if (!CVehicleManager::IsValidModel(model)) return nullptr; // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); + const eHandlingTypes eHandling = GetHandlingID(model); + // Return it - return m_pOriginalEntries[eHandling]; + return m_OriginalEntries[eHandling].get(); } -const CHandlingEntry* CHandlingManager::GetModelHandlingData(eVehicleTypes eModel) +CHandlingEntry* CHandlingManager::GetModelHandlingData(std::uint32_t model) const noexcept { // Within range? - if (!CVehicleManager::IsValidModel(eModel)) + if (!CVehicleManager::IsValidModel(model)) return nullptr; - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Return it - return m_pModelEntries[eHandling]; + auto entries = m_ModelEntries.find(model); + if (entries == m_ModelEntries.end()) + { + // Get our Handling ID + const eHandlingTypes eHandling = GetHandlingID(model); + + m_ModelEntries[model] = std::make_unique(&m_OriginalHandlingData[eHandling]); + if (!m_ModelEntries[model]) + return nullptr; + + entries = m_ModelEntries.find(model); + } + + return entries->second.get(); } -eHandlingProperty CHandlingManager::GetPropertyEnumFromName(const std::string& strName) +eHandlingProperty CHandlingManager::GetPropertyEnumFromName(const std::string& name) const noexcept { - const auto it = m_HandlingNames.find(strName); + const auto it = m_HandlingNames.find(name); return it != m_HandlingNames.end() ? it->second : HANDLING_MAX; } -bool CHandlingManager::HasModelHandlingChanged(eVehicleTypes eModel) +bool CHandlingManager::HasModelHandlingChanged(std::uint32_t model) const noexcept { // Within range? - if (!CVehicleManager::IsValidModel(eModel)) + if (!CVehicleManager::IsValidModel(model)) return false; - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); // Return if we have changed - return m_bModelHandlingChanged[eHandling]; + return m_bModelHandlingChanged[model]; } -void CHandlingManager::SetModelHandlingHasChanged(eVehicleTypes eModel, bool bChanged) +void CHandlingManager::SetModelHandlingHasChanged(std::uint32_t model, bool bChanged) const noexcept { // Within range? - if (!CVehicleManager::IsValidModel(eModel)) + if (!CVehicleManager::IsValidModel(model)) return; - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); // Return if we have changed. - m_bModelHandlingChanged[eHandling] = bChanged; + m_bModelHandlingChanged[model] = bChanged; } // Return the handling manager id -eHandlingTypes CHandlingManager::GetHandlingID(eVehicleTypes eModel) +eHandlingTypes CHandlingManager::GetHandlingID(std::uint32_t model) const noexcept { - switch (eModel) + switch (model) { case VT_LANDSTAL: return HT_LANDSTAL; @@ -594,7 +590,7 @@ eHandlingTypes CHandlingManager::GetHandlingID(eVehicleTypes eModel) return HT_LANDSTAL; } -void CHandlingManager::InitializeDefaultHandlings() +void CHandlingManager::InitializeDefaultHandlings() noexcept { // Reset memset(&m_OriginalHandlingData[0], 0, sizeof(m_OriginalHandlingData)); diff --git a/Server/mods/deathmatch/logic/CHandlingManager.h b/Server/mods/deathmatch/logic/CHandlingManager.h index 4d52c5cc18..bd0e2f0aa6 100644 --- a/Server/mods/deathmatch/logic/CHandlingManager.h +++ b/Server/mods/deathmatch/logic/CHandlingManager.h @@ -22,33 +22,20 @@ class CHandlingManager CHandlingManager(); ~CHandlingManager(); - CHandlingEntry* CreateHandlingData(); + std::unique_ptr CreateHandlingData() const noexcept; - bool ApplyHandlingData(eVehicleTypes eModel, CHandlingEntry* pEntry); + bool ApplyHandlingData(std::uint32_t model, CHandlingEntry* pEntry) const noexcept; - const CHandlingEntry* GetModelHandlingData(eVehicleTypes eModel); - const CHandlingEntry* GetOriginalHandlingData(eVehicleTypes eModel); + const CHandlingEntry* GetOriginalHandlingData(std::uint32_t model) const noexcept; + CHandlingEntry* GetModelHandlingData(std::uint32_t model) const noexcept; - eHandlingTypes GetHandlingID(eVehicleTypes eModel); + eHandlingTypes GetHandlingID(std::uint32_t model) const noexcept; // Helper functions - eHandlingProperty GetPropertyEnumFromName(const std::string& strName); - bool HasModelHandlingChanged(eVehicleTypes eModel); - void SetModelHandlingHasChanged(eVehicleTypes eModel, bool bChanged); - - std::map m_HandlingNames; + eHandlingProperty GetPropertyEnumFromName(const std::string& name) const noexcept; + bool HasModelHandlingChanged(std::uint32_t model) const noexcept; + void SetModelHandlingHasChanged(std::uint32_t model, bool bChanged) const noexcept; private: - void InitializeDefaultHandlings(); - - // Original handling data unaffected by handling.cfg changes - static SFixedArray m_OriginalHandlingData; - - // Array with the original handling entries - static SFixedArray m_pOriginalEntries; - - // Array with the model handling entries - static SFixedArray m_pModelEntries; - - SFixedArray m_bModelHandlingChanged; + void InitializeDefaultHandlings() noexcept; }; diff --git a/Server/mods/deathmatch/logic/CMainConfig.cpp b/Server/mods/deathmatch/logic/CMainConfig.cpp index a535aa0ab6..49c73419ca 100644 --- a/Server/mods/deathmatch/logic/CMainConfig.cpp +++ b/Server/mods/deathmatch/logic/CMainConfig.cpp @@ -79,6 +79,8 @@ CMainConfig::CMainConfig(CConsole* pConsole) : CXMLConfig(NULL) m_iBackupInterval = 3; m_iBackupAmount = 5; m_bSyncMapElementData = true; + m_elementDataWhitelisted = false; + m_checkDuplicateSerials = true; } bool CMainConfig::Load() @@ -133,6 +135,9 @@ bool CMainConfig::Load() return false; } + // Strip spaces from beginning and end of server name + m_strServerName = SString(m_strServerName).TrimStart(" ").TrimEnd(" "); + // Grab the forced server ip(s) GetString(m_pRootNode, "serverip", m_strServerIP); m_strServerIP = SString(m_strServerIP).Replace(" ", ""); @@ -523,6 +528,9 @@ bool CMainConfig::Load() g_TickRateSettings.iLightSync = Clamp(200, g_TickRateSettings.iLightSync, 4000); } + GetBoolean(m_pRootNode, "elementdata_whitelisted", m_elementDataWhitelisted); + GetBoolean(m_pRootNode, "check_duplicate_serials", m_checkDuplicateSerials); + ApplyNetOptions(); return true; @@ -1465,6 +1473,7 @@ const std::vector& CMainConfig::GetIntSettingList() {false, false, 0, 0, 1, "fakelag", &m_bFakeLagCommandEnabled, NULL}, {true, true, 50, 1000, 5000, "player_triggered_event_interval", &m_iPlayerTriggeredEventIntervalMs, &CMainConfig::OnPlayerTriggeredEventIntervalChange}, {true, true, 1, 100, 1000, "max_player_triggered_events_per_interval", &m_iMaxPlayerTriggeredEventsPerInterval, &CMainConfig::OnPlayerTriggeredEventIntervalChange}, + {true, true, 0, 1, 1, "resource_client_file_checks", &m_checkResourceClientFiles, nullptr}, }; static std::vector settingsList; diff --git a/Server/mods/deathmatch/logic/CMainConfig.h b/Server/mods/deathmatch/logic/CMainConfig.h index b52733229a..05df0e2f32 100644 --- a/Server/mods/deathmatch/logic/CMainConfig.h +++ b/Server/mods/deathmatch/logic/CMainConfig.h @@ -126,6 +126,9 @@ class CMainConfig : public CXMLConfig const std::vector& GetOwnerEmailAddressList() const { return m_OwnerEmailAddressList; } bool IsDatabaseCredentialsProtectionEnabled() const { return m_bDatabaseCredentialsProtectionEnabled != 0; } bool IsFakeLagCommandEnabled() const { return m_bFakeLagCommandEnabled != 0; } + bool IsElementDataWhitelisted() const { return m_elementDataWhitelisted; } + bool IsCheckDuplicateSerialsEnabled() const noexcept { return m_checkDuplicateSerials; } + bool IsCheckResourceClientFilesEnabled() const noexcept { return m_checkResourceClientFiles != 0; } SString GetSetting(const SString& configSetting); bool GetSetting(const SString& configSetting, SString& strValue); @@ -227,4 +230,7 @@ class CMainConfig : public CXMLConfig int m_bFakeLagCommandEnabled; int m_iPlayerTriggeredEventIntervalMs; int m_iMaxPlayerTriggeredEventsPerInterval; + bool m_elementDataWhitelisted; + bool m_checkDuplicateSerials; + int m_checkResourceClientFiles; }; diff --git a/Server/mods/deathmatch/logic/CPacketTranslator.cpp b/Server/mods/deathmatch/logic/CPacketTranslator.cpp index 3b6d92c3db..3cf0fa0965 100644 --- a/Server/mods/deathmatch/logic/CPacketTranslator.cpp +++ b/Server/mods/deathmatch/logic/CPacketTranslator.cpp @@ -48,6 +48,7 @@ #include "packets/CPlayerNoSocketPacket.h" #include "packets/CPlayerNetworkStatusPacket.h" #include "packets/CPlayerResourceStartPacket.h" +#include "packets/CPlayerWorldSpecialPropertyPacket.h" CPacketTranslator::CPacketTranslator(CPlayerManager* pPlayerManager) { @@ -212,6 +213,10 @@ CPacket* CPacketTranslator::Translate(const NetServerPlayerID& Socket, ePacketID pTemp = new CPlayerResourceStartPacket; break; + case PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY: + pTemp = new CPlayerWorldSpecialPropertyPacket; + break; + default: break; } diff --git a/Server/mods/deathmatch/logic/CPlayerManager.cpp b/Server/mods/deathmatch/logic/CPlayerManager.cpp index abdf923df7..227d3677f2 100644 --- a/Server/mods/deathmatch/logic/CPlayerManager.cpp +++ b/Server/mods/deathmatch/logic/CPlayerManager.cpp @@ -138,6 +138,17 @@ CPlayer* CPlayerManager::Get(const char* szNick, bool bCaseSensitive) return NULL; } +CPlayer* CPlayerManager::GetBySerial(const std::string_view serial) const noexcept +{ + for (const auto& player : m_Players) + { + if (player->GetSerial() == serial) + return player; + } + + return nullptr; +} + void CPlayerManager::DeleteAll() { // Delete all the items in the list diff --git a/Server/mods/deathmatch/logic/CPlayerManager.h b/Server/mods/deathmatch/logic/CPlayerManager.h index bd503380f4..0380c4bce4 100644 --- a/Server/mods/deathmatch/logic/CPlayerManager.h +++ b/Server/mods/deathmatch/logic/CPlayerManager.h @@ -40,6 +40,7 @@ class CPlayerManager CPlayer* Get(const NetServerPlayerID& PlayerSocket); CPlayer* Get(const char* szNick, bool bCaseSensitive = false); + CPlayer* GetBySerial(const std::string_view serial) const noexcept; std::list::const_iterator IterBegin() { return m_Players.begin(); }; std::list::const_iterator IterEnd() { return m_Players.end(); }; diff --git a/Server/mods/deathmatch/logic/CResource.cpp b/Server/mods/deathmatch/logic/CResource.cpp index 1c2ebe3ea8..279f1937a7 100644 --- a/Server/mods/deathmatch/logic/CResource.cpp +++ b/Server/mods/deathmatch/logic/CResource.cpp @@ -35,6 +35,7 @@ #include #include #include +#include "CStaticFunctionDefinitions.h" #ifdef WIN32 #include diff --git a/Server/mods/deathmatch/logic/CResourceChecker.Data.h b/Server/mods/deathmatch/logic/CResourceChecker.Data.h index e6bdee9212..630f70fd81 100644 --- a/Server/mods/deathmatch/logic/CResourceChecker.Data.h +++ b/Server/mods/deathmatch/logic/CResourceChecker.Data.h @@ -167,8 +167,8 @@ namespace //{false, "doesPedHaveJetPack", "isPedWearingJetpack"}, // Base Encoding & Decoding - {false, "base64Encode", "encodeString"}, - {false, "base64Decode", "decodeString"}, + {true, "base64Encode", "Please manually change this to encodeString (different syntax). Refer to the wiki for details"}, + {true, "base64Decode", "Please manually change this to decodeString (different syntax). Refer to the wiki for details"}, {false, "setHelicopterRotorSpeed", "setVehicleRotorSpeed"} }; @@ -271,7 +271,7 @@ namespace {true, "setPlayerDiscordJoinParams", "See GitHub PR #2499 for more details"}, // Base Encoding & Decoding - {false, "base64Encode", "encodeString"}, - {false, "base64Decode", "decodeString"} + {true, "base64Encode", "Please manually change this to encodeString (different syntax). Refer to the wiki for details"}, + {true, "base64Decode", "Please manually change this to decodeString (different syntax). Refer to the wiki for details"} }; } // namespace diff --git a/Server/mods/deathmatch/logic/CResourceChecker.cpp b/Server/mods/deathmatch/logic/CResourceChecker.cpp index db2909cb1c..9998b089ca 100644 --- a/Server/mods/deathmatch/logic/CResourceChecker.cpp +++ b/Server/mods/deathmatch/logic/CResourceChecker.cpp @@ -13,6 +13,8 @@ #include "CResourceChecker.h" #include "CResourceChecker.Data.h" #include "CResource.h" +#include "CMainConfig.h" +#include "CGame.h" #include "CLogger.h" #include "CStaticFunctionDefinitions.h" #include @@ -28,6 +30,7 @@ extern CNetServer* g_pRealNetServer; extern CServerInterface* g_pServerInterface; +extern CGame* g_pGame; /////////////////////////////////////////////////////////////// // @@ -48,6 +51,9 @@ void CResourceChecker::CheckResourceForIssues(CResource* pResource, const string m_ulDeprecatedWarningCount = 0; m_upgradedFullPathList.clear(); + // Checking certain resource client files is optional + bool checkResourceClientFiles = g_pGame->GetConfig()->IsCheckResourceClientFilesEnabled(); + // Check each file in the resource std::list::iterator iterf = pResource->IterBegin(); for (; iterf != pResource->IterEnd(); iterf++) @@ -73,7 +79,7 @@ void CResourceChecker::CheckResourceForIssues(CResource* pResource, const string bScript = true; bClient = true; } - else if (type == CResourceFile::RESOURCE_FILE_TYPE_CLIENT_FILE) + else if (type == CResourceFile::RESOURCE_FILE_TYPE_CLIENT_FILE && checkResourceClientFiles) { bScript = false; bClient = true; @@ -361,16 +367,25 @@ void CResourceChecker::CheckMetaSourceForIssues(CXMLNode* pRootNode, const strin attributes.Delete("client"); attributes.Delete("both"); - if (!m_strReqServerVersion.empty()) + // Use "both" if client and server versions are the same + if (!m_strReqServerVersion.empty() && !m_strReqClientVersion.empty() && m_strReqServerVersion == m_strReqClientVersion) { - CXMLAttribute* pAttr = attributes.Create("server"); + CXMLAttribute* pAttr = attributes.Create("both"); pAttr->SetValue(m_strReqServerVersion); } - - if (!m_strReqClientVersion.empty()) + else { - CXMLAttribute* pAttr = attributes.Create("client"); - pAttr->SetValue(m_strReqClientVersion); + if (!m_strReqServerVersion.empty()) + { + CXMLAttribute* pAttr = attributes.Create("server"); + pAttr->SetValue(m_strReqServerVersion); + } + + if (!m_strReqClientVersion.empty()) + { + CXMLAttribute* pAttr = attributes.Create("client"); + pAttr->SetValue(m_strReqClientVersion); + } } if (pbOutHasChanged) diff --git a/Server/mods/deathmatch/logic/CResourceChecker.h b/Server/mods/deathmatch/logic/CResourceChecker.h index 50c7ec00bb..ea9e7a1be9 100644 --- a/Server/mods/deathmatch/logic/CResourceChecker.h +++ b/Server/mods/deathmatch/logic/CResourceChecker.h @@ -2,7 +2,7 @@ * * PROJECT: Multi Theft Auto v1.0 * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CResourceChecker.cpp + * FILE: mods/deathmatch/logic/CResourceChecker.h * PURPOSE: Resource file content checker/validator/upgrader * * Multi Theft Auto is available from http://www.multitheftauto.com/ diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 67764f8057..6e1c06d124 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -79,27 +79,28 @@ extern CGame* g_pGame; extern CTimeUsMarker<20> markerLatentEvent; -static CLuaManager* m_pLuaManager; -static CColManager* m_pColManager; -static CPickupManager* m_pPickupManager; -static CPlayerManager* m_pPlayerManager; -static CVehicleManager* m_pVehicleManager; -static CObjectManager* m_pObjectManager; -static CMarkerManager* m_pMarkerManager; -static CMapManager* m_pMapManager; -static CBlipManager* m_pBlipManager; -static CRadarAreaManager* m_pRadarAreaManager; -static CTeamManager* m_pTeamManager; -static CClock* m_pClock; -static CEvents* m_pEvents; -static CElementDeleter* m_pElementDeleter; -static CMainConfig* m_pMainConfig; -static CRegistry* m_pRegistry; -static CAccountManager* m_pAccountManager; -static CBanManager* m_pBanManager; -static CPedManager* m_pPedManager; -static CWaterManager* m_pWaterManager; -static CCustomWeaponManager* m_pCustomWeaponManager; +static CLuaManager* m_pLuaManager; +static CColManager* m_pColManager; +static CPickupManager* m_pPickupManager; +static CPlayerManager* m_pPlayerManager; +static CVehicleManager* m_pVehicleManager; +static CObjectManager* m_pObjectManager; +static CMarkerManager* m_pMarkerManager; +static CMapManager* m_pMapManager; +static CBlipManager* m_pBlipManager; +static CRadarAreaManager* m_pRadarAreaManager; +static CTeamManager* m_pTeamManager; +static CClock* m_pClock; +static CEvents* m_pEvents; +static CElementDeleter* m_pElementDeleter; +static CMainConfig* m_pMainConfig; +static CRegistry* m_pRegistry; +static CAccountManager* m_pAccountManager; +static CBanManager* m_pBanManager; +static CPedManager* m_pPedManager; +static CWaterManager* m_pWaterManager; +static CCustomWeaponManager* m_pCustomWeaponManager; +static CHandlingManager* m_pHandlingManager; // Used to run a function on all the children of the elements too #define RUN_CHILDREN(func) \ @@ -134,6 +135,7 @@ CStaticFunctionDefinitions::CStaticFunctionDefinitions(CGame* pGame) m_pPedManager = pGame->GetPedManager(); m_pWaterManager = pGame->GetWaterManager(); m_pCustomWeaponManager = pGame->GetCustomWeaponManager(); + m_pHandlingManager = pGame->GetHandlingManager(); } CStaticFunctionDefinitions::~CStaticFunctionDefinitions() @@ -954,14 +956,19 @@ bool CStaticFunctionDefinitions::SetElementID(CElement* pElement, const char* sz return true; } -bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType) +bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType, + std::optional clientTrust) { assert(pElement); assert(szName); assert(strlen(szName) <= MAX_CUSTOMDATA_NAME_LENGTH); - ESyncType lastSyncType = ESyncType::BROADCAST; - CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType); + ESyncType lastSyncType = ESyncType::BROADCAST; + eCustomDataClientTrust lastClientTrust{}; + CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType, &lastClientTrust); + + if (clientTrust.has_value() && lastClientTrust != clientTrust.value()) + pElement->GetCustomDataManager().SetClientChangesMode(szName, clientTrust.value()); if (!pCurrentVariable || *pCurrentVariable != Variable || lastSyncType != syncType) { @@ -5480,190 +5487,165 @@ bool CStaticFunctionDefinitions::GetVehicleHandling(CVehicle* pVehicle, eHandlin return false; } -bool CStaticFunctionDefinitions::GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, CVector& vecValue, bool bOriginal) +bool CStaticFunctionDefinitions::GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, CVector& vecValue, bool bOriginal) { - const CHandlingEntry* pEntry = NULL; + const CHandlingEntry* pEntry = nullptr; if (bOriginal) { - pEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); + pEntry = m_pHandlingManager->GetOriginalHandlingData(model); } else { - pEntry = g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); + pEntry = m_pHandlingManager->GetModelHandlingData(model); } - if (pEntry) + if (!pEntry) + return false; + + if (eProperty == HANDLING_CENTEROFMASS) { - if (eProperty == HANDLING_CENTEROFMASS) - { - vecValue = pEntry->GetCenterOfMass(); - return true; - } + vecValue = pEntry->GetCenterOfMass(); + return true; } + return false; } -bool CStaticFunctionDefinitions::GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, float& fValue, bool bOriginal) +bool CStaticFunctionDefinitions::GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, float& fValue, bool bOriginal) { - const CHandlingEntry* pEntry = NULL; + const CHandlingEntry* pEntry = nullptr; if (bOriginal) { - pEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); + pEntry = m_pHandlingManager->GetOriginalHandlingData(model); } else { - pEntry = g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); + pEntry = m_pHandlingManager->GetModelHandlingData(model); } - if (pEntry) - { - if (GetEntryHandling(pEntry, eProperty, fValue)) - { - return true; - } - } - return false; + if (!pEntry) + return false; + + return GetEntryHandling(pEntry, eProperty, fValue); } -bool CStaticFunctionDefinitions::GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned int& uiValue, bool bOriginal) +bool CStaticFunctionDefinitions::GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned int& uiValue, bool bOriginal) { - const CHandlingEntry* pEntry = NULL; + const CHandlingEntry* pEntry = nullptr; if (bOriginal) { - pEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); + pEntry = m_pHandlingManager->GetOriginalHandlingData(model); } else { - pEntry = g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); + pEntry = m_pHandlingManager->GetModelHandlingData(model); } - if (pEntry) - { - if (GetEntryHandling(pEntry, eProperty, uiValue)) - { - return true; - } - } - return false; + if (!pEntry) + return false; + + return GetEntryHandling(pEntry, eProperty, uiValue); } -bool CStaticFunctionDefinitions::GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned char& ucValue, bool bOriginal) +bool CStaticFunctionDefinitions::GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned char& ucValue, bool bOriginal) { - const CHandlingEntry* pEntry = NULL; + const CHandlingEntry* pEntry = nullptr; if (bOriginal) { - pEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); + pEntry = m_pHandlingManager->GetOriginalHandlingData(model); } else { - pEntry = g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); + pEntry = m_pHandlingManager->GetModelHandlingData(model); } - if (pEntry) - { - if (GetEntryHandling(pEntry, eProperty, ucValue)) - { - return true; - } - } - return false; + if (!pEntry) + return false; + + return GetEntryHandling(pEntry, eProperty, ucValue); } -bool CStaticFunctionDefinitions::GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, std::string& strValue, bool bOriginal) +bool CStaticFunctionDefinitions::GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, std::string& strValue, bool bOriginal) { - const CHandlingEntry* pEntry = NULL; + const CHandlingEntry* pEntry = nullptr; if (bOriginal) { - pEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); + pEntry = m_pHandlingManager->GetOriginalHandlingData(model); } else { - pEntry = g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); + pEntry = m_pHandlingManager->GetModelHandlingData(model); } - if (pEntry) - { - if (GetEntryHandling(pEntry, eProperty, strValue)) - { - return true; - } - } - return false; + if (!pEntry) + return false; + + return GetEntryHandling(pEntry, eProperty, strValue); } -bool CStaticFunctionDefinitions::SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, float fValue) +bool CStaticFunctionDefinitions::SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, float fValue) { - CHandlingEntry* pEntry = (CHandlingEntry*)g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); - if (pEntry) - { - if (SetEntryHandling(pEntry, eProperty, fValue)) - { - g_pGame->GetHandlingManager()->SetModelHandlingHasChanged(eModel, true); - return true; - } - } + CHandlingEntry* pEntry = m_pHandlingManager->GetModelHandlingData(model); + if (!pEntry) + return false; - return false; + if (!SetEntryHandling(pEntry, eProperty, fValue)) + return false; + + m_pHandlingManager->SetModelHandlingHasChanged(model, true); + return true; } -bool CStaticFunctionDefinitions::SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, CVector vecValue) +bool CStaticFunctionDefinitions::SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, CVector vecValue) { - CHandlingEntry* pEntry = (CHandlingEntry*)g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); + CHandlingEntry* pEntry = m_pHandlingManager->GetModelHandlingData(model); + if (!pEntry) + return false; - if (pEntry) - { - if (SetEntryHandling(pEntry, eProperty, vecValue)) - { - g_pGame->GetHandlingManager()->SetModelHandlingHasChanged(eModel, true); - return true; - } - } - return false; + if (!SetEntryHandling(pEntry, eProperty, vecValue)) + return false; + + m_pHandlingManager->SetModelHandlingHasChanged(model, true); + return true; } -bool CStaticFunctionDefinitions::SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, std::string strValue) +bool CStaticFunctionDefinitions::SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, std::string strValue) { - CHandlingEntry* pEntry = (CHandlingEntry*)g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); - if (pEntry) - { - if (SetEntryHandling(pEntry, eProperty, strValue)) - { - g_pGame->GetHandlingManager()->SetModelHandlingHasChanged(eModel, true); - return true; - } - } + CHandlingEntry* pEntry = m_pHandlingManager->GetModelHandlingData(model); + if (!pEntry) + return false; - return false; + if (!SetEntryHandling(pEntry, eProperty, strValue)) + return false; + + m_pHandlingManager->SetModelHandlingHasChanged(model, true); + return true; } -bool CStaticFunctionDefinitions::SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned char ucValue) +bool CStaticFunctionDefinitions::SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned char ucValue) { - CHandlingEntry* pEntry = (CHandlingEntry*)g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); - if (pEntry) - { - if (SetEntryHandling(pEntry, eProperty, ucValue)) - { - g_pGame->GetHandlingManager()->SetModelHandlingHasChanged(eModel, true); - return true; - } - } + CHandlingEntry* pEntry = m_pHandlingManager->GetModelHandlingData(model); + if (!pEntry) + return false; - return false; + if (!SetEntryHandling(pEntry, eProperty, ucValue)) + return false; + + m_pHandlingManager->SetModelHandlingHasChanged(model, true); + return true; } -bool CStaticFunctionDefinitions::SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned int uiValue) +bool CStaticFunctionDefinitions::SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned int uiValue) { - CHandlingEntry* pEntry = (CHandlingEntry*)g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); - if (pEntry) - { - if (SetEntryHandling(pEntry, eProperty, uiValue)) - { - g_pGame->GetHandlingManager()->SetModelHandlingHasChanged(eModel, true); - return true; - } - } + CHandlingEntry* pEntry = m_pHandlingManager->GetModelHandlingData(model); + if (!pEntry) + return false; - return false; + if (!SetEntryHandling(pEntry, eProperty, uiValue)) + return false; + + m_pHandlingManager->SetModelHandlingHasChanged(model, true); + return true; } bool CStaticFunctionDefinitions::GetEntryHandling(const CHandlingEntry* pEntry, eHandlingProperty eProperty, float& fValue) @@ -7415,60 +7397,62 @@ bool CStaticFunctionDefinitions::SetVehicleHandling(CVehicle* pVehicle, eHandlin bool CStaticFunctionDefinitions::ResetVehicleHandling(CVehicle* pVehicle, bool bUseOriginal) { - assert(pVehicle); + try + { + const std::uint16_t model = pVehicle->GetModel(); + CHandlingEntry* pEntry = pVehicle->GetHandlingData(); + const CHandlingEntry* pNewEntry = nullptr; + CBitStream BitStream; - eVehicleTypes eModel = (eVehicleTypes)pVehicle->GetModel(); - CHandlingEntry* pEntry = pVehicle->GetHandlingData(); - const CHandlingEntry* pNewEntry; - CBitStream BitStream; + if (bUseOriginal) + { + pNewEntry = m_pHandlingManager->GetOriginalHandlingData(model); + if (!pNewEntry) + return false; - if (bUseOriginal) - { - pNewEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); - m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pVehicle, RESET_VEHICLE_HANDLING, *BitStream.pBitStream)); - } - else - { - pNewEntry = g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); - - SVehicleHandlingSync handling; - handling.data.fMass = pNewEntry->GetMass(); - handling.data.fTurnMass = pNewEntry->GetTurnMass(); - handling.data.fDragCoeff = pNewEntry->GetDragCoeff(); - handling.data.vecCenterOfMass = pNewEntry->GetCenterOfMass(); - handling.data.ucPercentSubmerged = pNewEntry->GetPercentSubmerged(); - handling.data.fTractionMultiplier = pNewEntry->GetTractionMultiplier(); - handling.data.ucDriveType = pNewEntry->GetCarDriveType(); - handling.data.ucEngineType = pNewEntry->GetCarEngineType(); - handling.data.ucNumberOfGears = pNewEntry->GetNumberOfGears(); - handling.data.fEngineAcceleration = pNewEntry->GetEngineAcceleration(); - handling.data.fEngineInertia = pNewEntry->GetEngineInertia(); - handling.data.fMaxVelocity = pNewEntry->GetMaxVelocity(); - handling.data.fBrakeDeceleration = pNewEntry->GetBrakeDeceleration(); - handling.data.fBrakeBias = pNewEntry->GetBrakeBias(); - handling.data.bABS = pNewEntry->GetABS(); - handling.data.fSteeringLock = pNewEntry->GetSteeringLock(); - handling.data.fTractionLoss = pNewEntry->GetTractionLoss(); - handling.data.fTractionBias = pNewEntry->GetTractionBias(); - handling.data.fSuspensionForceLevel = pNewEntry->GetSuspensionForceLevel(); - handling.data.fSuspensionDamping = pNewEntry->GetSuspensionDamping(); - handling.data.fSuspensionHighSpdDamping = pNewEntry->GetSuspensionHighSpeedDamping(); - handling.data.fSuspensionUpperLimit = pNewEntry->GetSuspensionUpperLimit(); - handling.data.fSuspensionLowerLimit = pNewEntry->GetSuspensionLowerLimit(); - handling.data.fSuspensionFrontRearBias = pNewEntry->GetSuspensionFrontRearBias(); - handling.data.fSuspensionAntiDiveMultiplier = pNewEntry->GetSuspensionAntiDiveMultiplier(); - handling.data.fCollisionDamageMultiplier = pNewEntry->GetCollisionDamageMultiplier(); - handling.data.uiModelFlags = pNewEntry->GetModelFlags(); - handling.data.uiHandlingFlags = pNewEntry->GetHandlingFlags(); - handling.data.fSeatOffsetDistance = pNewEntry->GetSeatOffsetDistance(); - // handling.data.uiMonetary = pNewEntry->GetMonetary (); - // handling.data.ucHeadLight = pNewEntry->GetHeadLight (); - // handling.data.ucTailLight = pNewEntry->GetTailLight (); - handling.data.ucAnimGroup = pNewEntry->GetAnimGroup(); - - // Lower and Upper limits cannot match or LSOD (unless boat) - // if ( eModel != VEHICLE_BOAT ) // Commented until fully tested + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pVehicle, RESET_VEHICLE_HANDLING, *BitStream.pBitStream)); + } + else { + pNewEntry = m_pHandlingManager->GetModelHandlingData(model); + if (!pNewEntry) + return false; + + SVehicleHandlingSync handling; + handling.data.fMass = pNewEntry->GetMass(); + handling.data.fTurnMass = pNewEntry->GetTurnMass(); + handling.data.fDragCoeff = pNewEntry->GetDragCoeff(); + handling.data.vecCenterOfMass = pNewEntry->GetCenterOfMass(); + handling.data.ucPercentSubmerged = pNewEntry->GetPercentSubmerged(); + handling.data.fTractionMultiplier = pNewEntry->GetTractionMultiplier(); + handling.data.ucDriveType = pNewEntry->GetCarDriveType(); + handling.data.ucEngineType = pNewEntry->GetCarEngineType(); + handling.data.ucNumberOfGears = pNewEntry->GetNumberOfGears(); + handling.data.fEngineAcceleration = pNewEntry->GetEngineAcceleration(); + handling.data.fEngineInertia = pNewEntry->GetEngineInertia(); + handling.data.fMaxVelocity = pNewEntry->GetMaxVelocity(); + handling.data.fBrakeDeceleration = pNewEntry->GetBrakeDeceleration(); + handling.data.fBrakeBias = pNewEntry->GetBrakeBias(); + handling.data.bABS = pNewEntry->GetABS(); + handling.data.fSteeringLock = pNewEntry->GetSteeringLock(); + handling.data.fTractionLoss = pNewEntry->GetTractionLoss(); + handling.data.fTractionBias = pNewEntry->GetTractionBias(); + handling.data.fSuspensionForceLevel = pNewEntry->GetSuspensionForceLevel(); + handling.data.fSuspensionDamping = pNewEntry->GetSuspensionDamping(); + handling.data.fSuspensionHighSpdDamping = pNewEntry->GetSuspensionHighSpeedDamping(); + handling.data.fSuspensionUpperLimit = pNewEntry->GetSuspensionUpperLimit(); + handling.data.fSuspensionLowerLimit = pNewEntry->GetSuspensionLowerLimit(); + handling.data.fSuspensionFrontRearBias = pNewEntry->GetSuspensionFrontRearBias(); + handling.data.fSuspensionAntiDiveMultiplier = pNewEntry->GetSuspensionAntiDiveMultiplier(); + handling.data.fCollisionDamageMultiplier = pNewEntry->GetCollisionDamageMultiplier(); + handling.data.uiModelFlags = pNewEntry->GetModelFlags(); + handling.data.uiHandlingFlags = pNewEntry->GetHandlingFlags(); + handling.data.fSeatOffsetDistance = pNewEntry->GetSeatOffsetDistance(); + // handling.data.uiMonetary = pNewEntry->GetMonetary (); + // handling.data.ucHeadLight = pNewEntry->GetHeadLight (); + // handling.data.ucTailLight = pNewEntry->GetTailLight (); + handling.data.ucAnimGroup = pNewEntry->GetAnimGroup(); + float fSuspensionLimitSize = handling.data.fSuspensionUpperLimit - handling.data.fSuspensionLowerLimit; if (fSuspensionLimitSize > -0.1f && fSuspensionLimitSize < 0.1f) { @@ -7477,32 +7461,38 @@ bool CStaticFunctionDefinitions::ResetVehicleHandling(CVehicle* pVehicle, bool b else handling.data.fSuspensionUpperLimit = handling.data.fSuspensionLowerLimit - 0.1f; } + + BitStream.pBitStream->Write(&handling); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pVehicle, SET_VEHICLE_HANDLING, *BitStream.pBitStream)); } - BitStream.pBitStream->Write(&handling); - m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pVehicle, SET_VEHICLE_HANDLING, *BitStream.pBitStream)); + pEntry->ApplyHandlingData(pNewEntry); + return true; + } + catch (...) + { + return false; } - - pEntry->ApplyHandlingData(pNewEntry); - return true; } bool CStaticFunctionDefinitions::ResetVehicleHandlingProperty(CVehicle* pVehicle, eHandlingProperty eProperty, bool bUseOriginal) { - assert(pVehicle); - - eVehicleTypes eModel = (eVehicleTypes)pVehicle->GetModel(); - CHandlingEntry* pEntry = pVehicle->GetHandlingData(); - if (pEntry) + try { + CHandlingEntry* pEntry = pVehicle->GetHandlingData(); + if (!pEntry) + return false; + CBitStream BitStream; - float fValue = 0.0f; - CVector vecValue = CVector(0.0f, 0.0f, 0.0f); - SString strValue = ""; - unsigned int uiValue = 0; - unsigned int ucValue = 0; - if (GetModelHandling(eModel, eProperty, fValue, bUseOriginal)) + const std::uint32_t model = pVehicle->GetModel(); + + float fValue; + CVector vecValue; + std::string strValue; + std::uint32_t uiValue; + std::uint32_t ucValue; + if (GetModelHandling(model, eProperty, fValue, bUseOriginal)) { BitStream.pBitStream->Write(static_cast(eProperty)); @@ -7510,7 +7500,7 @@ bool CStaticFunctionDefinitions::ResetVehicleHandlingProperty(CVehicle* pVehicle BitStream.pBitStream->Write(fValue); } - else if (GetModelHandling(eModel, eProperty, uiValue, bUseOriginal)) + else if (GetModelHandling(model, eProperty, uiValue, bUseOriginal)) { BitStream.pBitStream->Write(static_cast(eProperty)); @@ -7518,7 +7508,7 @@ bool CStaticFunctionDefinitions::ResetVehicleHandlingProperty(CVehicle* pVehicle BitStream.pBitStream->Write(uiValue); } - else if (GetModelHandling(eModel, eProperty, ucValue, bUseOriginal)) + else if (GetModelHandling(model, eProperty, ucValue, bUseOriginal)) { BitStream.pBitStream->Write(static_cast(eProperty)); @@ -7526,7 +7516,7 @@ bool CStaticFunctionDefinitions::ResetVehicleHandlingProperty(CVehicle* pVehicle BitStream.pBitStream->Write(ucValue); } - else if (GetModelHandling(eModel, eProperty, strValue, bUseOriginal)) + else if (GetModelHandling(model, eProperty, strValue, bUseOriginal)) { unsigned char ucValue = 0; BitStream.pBitStream->Write(static_cast(eProperty)); @@ -7536,7 +7526,7 @@ bool CStaticFunctionDefinitions::ResetVehicleHandlingProperty(CVehicle* pVehicle BitStream.pBitStream->Write(ucValue); } - else if (GetModelHandling(eModel, eProperty, vecValue, bUseOriginal)) + else if (GetModelHandling(model, eProperty, vecValue, bUseOriginal)) { BitStream.pBitStream->Write(static_cast(eProperty)); @@ -7554,53 +7544,53 @@ bool CStaticFunctionDefinitions::ResetVehicleHandlingProperty(CVehicle* pVehicle m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pVehicle, SET_VEHICLE_HANDLING_PROPERTY, *BitStream.pBitStream)); return true; } - - return false; + catch (...) + { + return false; + } } -bool CStaticFunctionDefinitions::ResetModelHandling(eVehicleTypes eModel) +bool CStaticFunctionDefinitions::ResetModelHandling(std::uint32_t model) { - CHandlingEntry* pEntry = (CHandlingEntry*)g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); - if (pEntry) - { - const CHandlingEntry* pHandlingEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); - if (pHandlingEntry) - { - pEntry->ApplyHandlingData(pHandlingEntry); - return true; - } - } + CHandlingEntry* pEntry = m_pHandlingManager->GetModelHandlingData(model); + if (!pEntry) + return false; - return false; + const CHandlingEntry* pHandlingEntry = m_pHandlingManager->GetOriginalHandlingData(model); + if (!pHandlingEntry) + return false; + + pEntry->ApplyHandlingData(pHandlingEntry); + return true; } -bool CStaticFunctionDefinitions::ResetModelHandlingProperty(eVehicleTypes eModel, eHandlingProperty eProperty) +bool CStaticFunctionDefinitions::ResetModelHandlingProperty(std::uint32_t model, eHandlingProperty eProperty) { - CHandlingEntry* pEntry = (CHandlingEntry*)g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); + CHandlingEntry* pEntry = m_pHandlingManager->GetModelHandlingData(model); - float fValue = 0.0f; - CVector vecValue = CVector(0.0f, 0.0f, 0.0f); - SString strValue = ""; - uint uiValue = 0; - uchar ucValue = 0; + float fValue; + CVector vecValue; + std::string strValue; + std::uint32_t uiValue; + std::uint8_t ucValue; - if (GetModelHandling(eModel, eProperty, fValue, true)) + if (GetModelHandling(model, eProperty, fValue, true)) { SetEntryHandling(pEntry, eProperty, fValue); } - else if (GetModelHandling(eModel, eProperty, strValue, true)) + else if (GetModelHandling(model, eProperty, strValue, true)) { SetEntryHandling(pEntry, eProperty, strValue); } - else if (GetModelHandling(eModel, eProperty, vecValue, true)) + else if (GetModelHandling(model, eProperty, vecValue, true)) { SetEntryHandling(pEntry, eProperty, vecValue); } - else if (GetModelHandling(eModel, eProperty, uiValue, true)) + else if (GetModelHandling(model, eProperty, uiValue, true)) { SetEntryHandling(pEntry, eProperty, uiValue); } - else if (GetModelHandling(eModel, eProperty, ucValue, true)) + else if (GetModelHandling(model, eProperty, ucValue, true)) { SetEntryHandling(pEntry, eProperty, ucValue); } @@ -10847,19 +10837,35 @@ bool CStaticFunctionDefinitions::ResetMoonSize() bool CStaticFunctionDefinitions::SendSyncIntervals(CPlayer* pPlayer) { - CBitStream BitStream; - BitStream.pBitStream->Write(g_TickRateSettings.iPureSync); - BitStream.pBitStream->Write(g_TickRateSettings.iLightSync); - BitStream.pBitStream->Write(g_TickRateSettings.iCamSync); - BitStream.pBitStream->Write(g_TickRateSettings.iPedSync); - BitStream.pBitStream->Write(g_TickRateSettings.iUnoccupiedVehicle); - BitStream.pBitStream->Write(g_TickRateSettings.iObjectSync); - BitStream.pBitStream->Write(g_TickRateSettings.iKeySyncRotation); - BitStream.pBitStream->Write(g_TickRateSettings.iKeySyncAnalogMove); - if (pPlayer) + auto sendSyncIntervalPatket = [](CPlayer* pPlayer) + { + CBitStream BitStream; + BitStream.pBitStream->Write(g_TickRateSettings.iPureSync); + BitStream.pBitStream->Write(g_TickRateSettings.iLightSync); + BitStream.pBitStream->Write(g_TickRateSettings.iCamSync); + BitStream.pBitStream->Write(g_TickRateSettings.iPedSync); + BitStream.pBitStream->Write(g_TickRateSettings.iUnoccupiedVehicle); + BitStream.pBitStream->Write(g_TickRateSettings.iObjectSync); + BitStream.pBitStream->Write(g_TickRateSettings.iKeySyncRotation); + BitStream.pBitStream->Write(g_TickRateSettings.iKeySyncAnalogMove); + + if (pPlayer->CanBitStream(eBitStreamVersion::FixSyncerDistance)) + { + BitStream.pBitStream->Write(g_TickRateSettings.iPedSyncerDistance); + BitStream.pBitStream->Write(g_TickRateSettings.iUnoccupiedVehicleSyncerDistance); + } + pPlayer->Send(CLuaPacket(SET_SYNC_INTERVALS, *BitStream.pBitStream)); + }; + + + if (pPlayer) + sendSyncIntervalPatket(pPlayer); else - m_pPlayerManager->BroadcastOnlyJoined(CLuaPacket(SET_SYNC_INTERVALS, *BitStream.pBitStream)); + { + for (auto iter = m_pPlayerManager->IterBegin(); iter != m_pPlayerManager->IterEnd(); ++iter) + sendSyncIntervalPatket(*iter); + } return true; } diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index dd6202208f..ffb21fa804 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -83,7 +83,8 @@ class CStaticFunctionDefinitions // Element set funcs static bool ClearElementVisibleTo(CElement* pElement); static bool SetElementID(CElement* pElement, const char* szID); - static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType); + static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType, + std::optional clientTrust); static bool RemoveElementData(CElement* pElement, const char* szName); static bool AddElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer); static bool RemoveElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer); @@ -285,11 +286,11 @@ class CStaticFunctionDefinitions static bool GetVehicleHandling(CVehicle* pVehicle, eHandlingProperty eProperty, std::string& strValue); static bool GetVehicleHandling(CVehicle* pVehicle, eHandlingProperty eProperty, unsigned int& uiValue); static bool GetVehicleHandling(CVehicle* pVehicle, eHandlingProperty eProperty, unsigned char& ucValue); - static bool GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, float& fValue, bool origin = false); - static bool GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, CVector& vecValue, bool origin = false); - static bool GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, std::string& strValue, bool origin = false); - static bool GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned int& uiValue, bool origin = false); - static bool GetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned char& ucValue, bool origin = false); + static bool GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, float& fValue, bool origin = false); + static bool GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, CVector& vecValue, bool origin = false); + static bool GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, std::string& strValue, bool origin = false); + static bool GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned int& uiValue, bool origin = false); + static bool GetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned char& ucValue, bool origin = false); static bool GetEntryHandling(const CHandlingEntry* pEntry, eHandlingProperty eProperty, float& fValue); static bool GetEntryHandling(const CHandlingEntry* pEntry, eHandlingProperty eProperty, std::string& strValue); static bool GetEntryHandling(const CHandlingEntry* pEntry, eHandlingProperty eProperty, unsigned int& uiValue); @@ -351,13 +352,13 @@ class CStaticFunctionDefinitions static bool SetVehicleHandling(CVehicle* pVehicle, eHandlingProperty eProperty, std::string strValue); static bool SetVehicleHandling(CVehicle* pVehicle, eHandlingProperty eProperty, unsigned int uiValue); static bool SetVehicleHandling(CVehicle* pVehicle, eHandlingProperty eProperty, unsigned char ucValue); - static bool ResetModelHandling(eVehicleTypes eModel); - static bool ResetModelHandlingProperty(eVehicleTypes eModel, eHandlingProperty eProperty); - static bool SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, float fValue); - static bool SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, CVector vecValue); - static bool SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, std::string strValue); - static bool SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned int uiValue); - static bool SetModelHandling(eVehicleTypes eModel, eHandlingProperty eProperty, unsigned char ucValue); + static bool ResetModelHandling(std::uint32_t model); + static bool ResetModelHandlingProperty(std::uint32_t model, eHandlingProperty eProperty); + static bool SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, float fValue); + static bool SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, CVector vecValue); + static bool SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, std::string strValue); + static bool SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned int uiValue); + static bool SetModelHandling(std::uint32_t model, eHandlingProperty eProperty, unsigned char ucValue); static bool SetEntryHandling(CHandlingEntry* pEntry, eHandlingProperty eProperty, float fValue); static bool SetEntryHandling(CHandlingEntry* pEntry, eHandlingProperty eProperty, CVector vecValue); static bool SetEntryHandling(CHandlingEntry* pEntry, eHandlingProperty eProperty, std::string strValue); diff --git a/Server/mods/deathmatch/logic/CVehicle.cpp b/Server/mods/deathmatch/logic/CVehicle.cpp index ee5f7eb0e6..ff85b48823 100644 --- a/Server/mods/deathmatch/logic/CVehicle.cpp +++ b/Server/mods/deathmatch/logic/CVehicle.cpp @@ -54,7 +54,7 @@ CVehicle::CVehicle(CVehicleManager* pVehicleManager, CElement* pParent, unsigned m_pTowedByVehicle = NULL; m_ucPaintjob = 3; m_ucMaxPassengersOverride = VEHICLE_PASSENGERS_UNDEFINED; - m_pHandlingEntry = NULL; + m_HandlingEntry = nullptr; m_fRespawnHealth = DEFAULT_VEHICLE_HEALTH; m_bRespawnEnabled = false; @@ -167,7 +167,6 @@ CVehicle::~CVehicle() } } delete m_pUpgrades; - delete m_pHandlingEntry; CElementRefManager::RemoveElementRefs(ELEMENT_REF_DEBUG(this, "CVehicle"), &m_pTowedVehicle, &m_pTowedByVehicle, &m_pSyncer, &m_pJackingPed, NULL); @@ -849,13 +848,16 @@ void CVehicle::GetInitialDoorStates(SFixedArray& ucOut } } -void CVehicle::GenerateHandlingData() +void CVehicle::GenerateHandlingData() noexcept { + const auto* handlingManager = g_pGame->GetHandlingManager(); + // Make a new CHandlingEntry - if (m_pHandlingEntry == NULL) - m_pHandlingEntry = g_pGame->GetHandlingManager()->CreateHandlingData(); + if (!m_HandlingEntry) + m_HandlingEntry = handlingManager->CreateHandlingData(); + // Apply the model handling info - m_pHandlingEntry->ApplyHandlingData(g_pGame->GetHandlingManager()->GetModelHandlingData(static_cast(m_usModel))); + m_HandlingEntry->ApplyHandlingData(handlingManager->GetModelHandlingData(m_usModel)); m_bHandlingChanged = false; } diff --git a/Server/mods/deathmatch/logic/CVehicle.h b/Server/mods/deathmatch/logic/CVehicle.h index d5dbb43243..0e2ecbd278 100644 --- a/Server/mods/deathmatch/logic/CVehicle.h +++ b/Server/mods/deathmatch/logic/CVehicle.h @@ -374,8 +374,8 @@ class CVehicle final : public CElement void SpawnAt(const CVector& vecPosition, const CVector& vecRotation); void Respawn(); - void GenerateHandlingData(); - CHandlingEntry* GetHandlingData() { return m_pHandlingEntry; }; + void GenerateHandlingData() noexcept; + CHandlingEntry* GetHandlingData() noexcept { return m_HandlingEntry.get(); }; uint GetTimeSinceLastPush() { return (uint)(CTickCount::Now(true) - m_LastPushedTime).ToLongLong(); } void ResetLastPushTime() { m_LastPushedTime = CTickCount::Now(true); } @@ -485,8 +485,8 @@ class CVehicle final : public CElement unsigned short m_usAdjustableProperty; bool m_bCollisionsEnabled; - CHandlingEntry* m_pHandlingEntry; - bool m_bHandlingChanged; + std::unique_ptr m_HandlingEntry; + bool m_bHandlingChanged; unsigned char m_ucVariant; unsigned char m_ucVariant2; diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index ef25750c05..27afc8510e 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -285,6 +285,12 @@ ADD_ENUM(ESyncType::LOCAL, "local") ADD_ENUM(ESyncType::SUBSCRIBE, "subscribe") IMPLEMENT_ENUM_CLASS_END("sync-mode") +IMPLEMENT_ENUM_CLASS_BEGIN(eCustomDataClientTrust) +ADD_ENUM(eCustomDataClientTrust::UNSET, "default") +ADD_ENUM(eCustomDataClientTrust::ALLOW, "allow") +ADD_ENUM(eCustomDataClientTrust::DENY, "deny") +IMPLEMENT_ENUM_CLASS_END("client-trust-mode") + // // CResource from userdata // @@ -640,6 +646,42 @@ void ReadPregFlags(CScriptArgReader& argStream, pcrecpp::RE_Options& pOptions) } } +// +// Check 4x4 lua table +// +bool IsValidMatrixLuaTable(lua_State* luaVM, std::uint32_t argIndex) noexcept +{ + std::uint32_t cell = 0; + + if (lua_type(luaVM, argIndex) == LUA_TTABLE) + { + lua_pushnil(luaVM); + for (std::uint32_t row = 0; lua_next(luaVM, argIndex) != 0; lua_pop(luaVM, 1), ++row) + { + if (lua_type(luaVM, -1) != LUA_TTABLE) + return false; + + std::uint32_t col = 0; + + lua_pushnil(luaVM); + for (; lua_next(luaVM, -2) != 0; lua_pop(luaVM, 1), ++col, ++cell) + { + int argumentType = lua_type(luaVM, -1); + if (argumentType != LUA_TNUMBER && argumentType != LUA_TSTRING) + return false; + } + + if (col != 4) + return false; + } + } + + if (cell != 16) + return false; + + return true; +} + // // 4x4 matrix into CMatrix // diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index 52a4536012..62d4312c51 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -38,6 +38,7 @@ DECLARE_ENUM(CAccessControlListRight::ERightType); DECLARE_ENUM(CElement::EElementType); DECLARE_ENUM(CAccountPassword::EAccountPasswordType); DECLARE_ENUM_CLASS(ESyncType); +DECLARE_ENUM_CLASS(eCustomDataClientTrust) enum eHudComponent { @@ -389,6 +390,7 @@ void MixedReadResourceString(CScriptArgReader& argStream, CResource*& pOutRes bool StringToBool(const SString& strText); void MinServerReqCheck(CScriptArgReader& argStream, const char* szVersionReq, const char* szReason); void ReadPregFlags(CScriptArgReader& argStream, pcrecpp::RE_Options& pOptions); +bool IsValidMatrixLuaTable(lua_State* luaVM, std::uint32_t argIndex) noexcept; bool ReadMatrix(lua_State* luaVM, uint uiArgIndex, CMatrix& outMatrix); // diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaDefs.cpp index 8d8e3a3646..6afc751f67 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaDefs.cpp @@ -38,25 +38,25 @@ namespace bool ms_bRegisterdPostCallHook = false; } // namespace -CElementDeleter* CLuaDefs::m_pElementDeleter = NULL; -CBlipManager* CLuaDefs::m_pBlipManager = NULL; -CHandlingManager* CLuaDefs::m_pHandlingManager = NULL; -CLuaManager* CLuaDefs::m_pLuaManager = NULL; -CMarkerManager* CLuaDefs::m_pMarkerManager = NULL; -CObjectManager* CLuaDefs::m_pObjectManager = NULL; -CPickupManager* CLuaDefs::m_pPickupManager = NULL; -CPlayerManager* CLuaDefs::m_pPlayerManager = NULL; -CRadarAreaManager* CLuaDefs::m_pRadarAreaManager = NULL; -CRegisteredCommands* CLuaDefs::m_pRegisteredCommands; -CElement* CLuaDefs::m_pRootElement = NULL; -CScriptDebugging* CLuaDefs::m_pScriptDebugging = NULL; -CVehicleManager* CLuaDefs::m_pVehicleManager = NULL; -CTeamManager* CLuaDefs::m_pTeamManager = NULL; -CAccountManager* CLuaDefs::m_pAccountManager = NULL; -CColManager* CLuaDefs::m_pColManager = NULL; -CResourceManager* CLuaDefs::m_pResourceManager = NULL; -CAccessControlListManager* CLuaDefs::m_pACLManager = NULL; -CMainConfig* CLuaDefs::m_pMainConfig = NULL; +CElementDeleter* CLuaDefs::m_pElementDeleter = NULL; +CBlipManager* CLuaDefs::m_pBlipManager = NULL; +CHandlingManager* CLuaDefs::m_pHandlingManager = nullptr; +CLuaManager* CLuaDefs::m_pLuaManager = NULL; +CMarkerManager* CLuaDefs::m_pMarkerManager = NULL; +CObjectManager* CLuaDefs::m_pObjectManager = NULL; +CPickupManager* CLuaDefs::m_pPickupManager = NULL; +CPlayerManager* CLuaDefs::m_pPlayerManager = NULL; +CRadarAreaManager* CLuaDefs::m_pRadarAreaManager = NULL; +CRegisteredCommands* CLuaDefs::m_pRegisteredCommands; +CElement* CLuaDefs::m_pRootElement = NULL; +CScriptDebugging* CLuaDefs::m_pScriptDebugging = NULL; +CVehicleManager* CLuaDefs::m_pVehicleManager = NULL; +CTeamManager* CLuaDefs::m_pTeamManager = NULL; +CAccountManager* CLuaDefs::m_pAccountManager = NULL; +CColManager* CLuaDefs::m_pColManager = NULL; +CResourceManager* CLuaDefs::m_pResourceManager = NULL; +CAccessControlListManager* CLuaDefs::m_pACLManager = NULL; +CMainConfig* CLuaDefs::m_pMainConfig = NULL; void CLuaDefs::Initialize(CGame* pGame) { diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h index ae81ecdf4e..2bde93fb0e 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h @@ -66,26 +66,26 @@ class CLuaDefs // This is just for the Lua funcs. Please don't public this and use it other // places in the server. protected: - static CElementDeleter* m_pElementDeleter; - static CBlipManager* m_pBlipManager; - static CHandlingManager* m_pHandlingManager; - static CLuaManager* m_pLuaManager; - static CMarkerManager* m_pMarkerManager; - static CObjectManager* m_pObjectManager; - static CPickupManager* m_pPickupManager; - static CPlayerManager* m_pPlayerManager; - static CRadarAreaManager* m_pRadarAreaManager; - static CRegisteredCommands* m_pRegisteredCommands; - static CElement* m_pRootElement; - static CScriptDebugging* m_pScriptDebugging; - static CVehicleManager* m_pVehicleManager; - static CTeamManager* m_pTeamManager; - static CAccountManager* m_pAccountManager; - static CColManager* m_pColManager; - static CResourceManager* m_pResourceManager; - static CAccessControlListManager* m_pACLManager; - static CMainConfig* m_pMainConfig; - static inline CLuaModuleManager* m_pLuaModuleManager = nullptr; + static CElementDeleter* m_pElementDeleter; + static CBlipManager* m_pBlipManager; + static CHandlingManager* m_pHandlingManager; + static CLuaManager* m_pLuaManager; + static CMarkerManager* m_pMarkerManager; + static CObjectManager* m_pObjectManager; + static CPickupManager* m_pPickupManager; + static CPlayerManager* m_pPlayerManager; + static CRadarAreaManager* m_pRadarAreaManager; + static CRegisteredCommands* m_pRegisteredCommands; + static CElement* m_pRootElement; + static CScriptDebugging* m_pScriptDebugging; + static CVehicleManager* m_pVehicleManager; + static CTeamManager* m_pTeamManager; + static CAccountManager* m_pAccountManager; + static CColManager* m_pColManager; + static CResourceManager* m_pResourceManager; + static CAccessControlListManager* m_pACLManager; + static CMainConfig* m_pMainConfig; + static inline CLuaModuleManager* m_pLuaModuleManager = nullptr; protected: // Old style: Only warn on failure. This should diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index 6cacbdcc98..f8effd7b89 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -1538,6 +1538,7 @@ int CLuaElementDefs::setElementData(lua_State* luaVM) SString strKey; CLuaArgument value; ESyncType syncType = ESyncType::BROADCAST; + std::optional clientTrust{}; CScriptArgReader argStream(luaVM); argStream.ReadUserData(pElement); @@ -1554,6 +1555,13 @@ int CLuaElementDefs::setElementData(lua_State* luaVM) else argStream.ReadEnumString(syncType, ESyncType::BROADCAST); + if (!argStream.NextIsNone()) + { + eCustomDataClientTrust trustReaded; + argStream.ReadEnumString(trustReaded); + clientTrust = trustReaded; + } + if (!argStream.HasErrors()) { LogWarningIfPlayerHasNotJoinedYet(luaVM, pElement); @@ -1566,7 +1574,7 @@ int CLuaElementDefs::setElementData(lua_State* luaVM) strKey = strKey.Left(MAX_CUSTOMDATA_NAME_LENGTH); } - if (CStaticFunctionDefinitions::SetElementData(pElement, strKey, value, syncType)) + if (CStaticFunctionDefinitions::SetElementData(pElement, strKey, value, syncType, clientTrust)) { lua_pushboolean(luaVM, true); return 1; diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp index 554bf2efc9..4aa82ac5f9 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp @@ -16,6 +16,7 @@ #include "ASE.h" #include "CStaticFunctionDefinitions.h" #include "CPerfStatManager.h" +#include "CMapManager.h" #define MIN_SERVER_REQ_CALLREMOTE_QUEUE_NAME "1.5.3-9.11270" #define MIN_SERVER_REQ_CALLREMOTE_CONNECTION_ATTEMPTS "1.3.0-9.04563" @@ -349,6 +350,12 @@ bool CLuaFunctionDefs::Shutdown(lua_State* luaVM, std::optionalGetModManager()->SetExitCode(maybeExitCode.value()); + // Call event + CLuaArguments arguments; + arguments.PushResource(&resource); + arguments.PushString(reason.data()); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onShutdown", arguments); + g_pGame->SetIsFinished(true); return true; } diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp index 4a80b4acfd..6e5c5bd92a 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp @@ -213,15 +213,14 @@ int CLuaHandlingDefs::SetVehicleHandling(lua_State* luaVM) int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) { // bool setModelHandling ( int modelId, [ string property, var value ] ) - unsigned short usModel; + std::uint16_t model; CScriptArgReader argStream(luaVM); - argStream.ReadNumber(usModel); + argStream.ReadNumber(model); if (!argStream.HasErrors()) { - eVehicleTypes eModel = static_cast(usModel); - if (eModel) + if (model) { if (argStream.NextIsString()) { @@ -235,7 +234,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) { if (argStream.NextIsNil()) { - if (CStaticFunctionDefinitions::ResetModelHandlingProperty(eModel, eProperty)) + if (CStaticFunctionDefinitions::ResetModelHandlingProperty(model, eProperty)) { lua_pushboolean(luaVM, true); return 1; @@ -269,7 +268,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) { float fValue; argStream.ReadNumber(fValue); - if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(eModel, eProperty, fValue)) + if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(model, eProperty, fValue)) { lua_pushboolean(luaVM, true); return 1; @@ -289,7 +288,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) { argStream.SetCustomError("Invalid value"); } - if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(eModel, eProperty, uiValue)) + if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(model, eProperty, uiValue)) { lua_pushboolean(luaVM, true); return 1; @@ -302,7 +301,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) { unsigned char ucValue; argStream.ReadNumber(ucValue); - if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(eModel, eProperty, ucValue)) + if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(model, eProperty, ucValue)) { lua_pushboolean(luaVM, true); return 1; @@ -330,7 +329,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) CVector vecCenterOfMass(fX, fY, fZ); - if (CStaticFunctionDefinitions::SetModelHandling(eModel, eProperty, vecCenterOfMass)) + if (CStaticFunctionDefinitions::SetModelHandling(model, eProperty, vecCenterOfMass)) { lua_pushboolean(luaVM, true); return 1; @@ -348,7 +347,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) { SString strValue; argStream.ReadString(strValue); - if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(eModel, eProperty, strValue)) + if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(model, eProperty, strValue)) { lua_pushboolean(luaVM, true); return 1; @@ -358,7 +357,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) { bool bValue; argStream.ReadBool(bValue); - if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(eModel, eProperty, bValue ? 1.0f : 0.0f)) + if (!argStream.HasErrors() && CStaticFunctionDefinitions::SetModelHandling(model, eProperty, bValue ? 1.0f : 0.0f)) { lua_pushboolean(luaVM, true); return 1; @@ -403,50 +402,55 @@ int CLuaHandlingDefs::GetVehicleHandling(lua_State* luaVM) SString strProperty; argStream.ReadString(strProperty); + bool bResult = true; eHandlingProperty eProperty = m_pHandlingManager->GetPropertyEnumFromName(strProperty); - if (eProperty == HANDLING_MAX) + if (eProperty != HANDLING_MAX) { - argStream.SetCustomError("Invalid property"); - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - lua_pushboolean(luaVM, false); - return 1; - } - - float fValue = 0.0f; - CVector vecValue = CVector(0.0f, 0.0f, 0.0f); - SString strValue = ""; - unsigned int uiValue = 0; - unsigned char ucValue = 0; - if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, fValue)) - { - lua_pushnumber(luaVM, fValue); - } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, uiValue)) - { - lua_pushnumber(luaVM, uiValue); - } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, ucValue)) - { - lua_pushnumber(luaVM, ucValue); - } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, strValue)) - { - lua_pushstring(luaVM, strValue); + float fValue = 0.0f; + CVector vecValue = CVector(0.0f, 0.0f, 0.0f); + SString strValue = ""; + unsigned int uiValue = 0; + unsigned char ucValue = 0; + if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, fValue)) + { + lua_pushnumber(luaVM, fValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, uiValue)) + { + lua_pushnumber(luaVM, uiValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, ucValue)) + { + lua_pushnumber(luaVM, ucValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, strValue)) + { + lua_pushstring(luaVM, strValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, vecValue)) + { + lua_createtable(luaVM, 3, 0); + lua_pushnumber(luaVM, 1); + lua_pushnumber(luaVM, vecValue.fX); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 2); + lua_pushnumber(luaVM, vecValue.fY); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 3); + lua_pushnumber(luaVM, vecValue.fZ); + lua_settable(luaVM, -3); + } + else + { + bResult = false; + } } - else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, vecValue)) + else { - lua_createtable(luaVM, 3, 0); - lua_pushnumber(luaVM, 1); - lua_pushnumber(luaVM, vecValue.fX); - lua_settable(luaVM, -3); - lua_pushnumber(luaVM, 2); - lua_pushnumber(luaVM, vecValue.fY); - lua_settable(luaVM, -3); - lua_pushnumber(luaVM, 3); - lua_pushnumber(luaVM, vecValue.fZ); - lua_settable(luaVM, -3); + bResult = false; } - else + + if (!bResult) { argStream.SetCustomError("Invalid property"); m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); @@ -611,32 +615,30 @@ int CLuaHandlingDefs::GetVehicleHandling(lua_State* luaVM) int CLuaHandlingDefs::GetModelHandling(lua_State* luaVM) { // table getModelHandling ( int modelId ) - unsigned short usModel; + std::uint16_t model; CScriptArgReader argStream(luaVM); - argStream.ReadNumber(usModel); + argStream.ReadNumber(model); if (!argStream.HasErrors()) { - eVehicleTypes eModel = static_cast(usModel); - if (eModel) + if (CVehicleManager::IsValidModel(model)) { - const CHandlingEntry* pEntry = g_pGame->GetHandlingManager()->GetModelHandlingData(eModel); - if (pEntry) + if (const auto* const entry = m_pHandlingManager->GetModelHandlingData(model)) { lua_newtable(luaVM); - lua_pushnumber(luaVM, pEntry->GetMass()); + lua_pushnumber(luaVM, entry->GetMass()); lua_setfield(luaVM, -2, "mass"); - lua_pushnumber(luaVM, pEntry->GetTurnMass()); + lua_pushnumber(luaVM, entry->GetTurnMass()); lua_setfield(luaVM, -2, "turnMass"); - lua_pushnumber(luaVM, pEntry->GetDragCoeff()); + lua_pushnumber(luaVM, entry->GetDragCoeff()); lua_setfield(luaVM, -2, "dragCoeff"); lua_createtable(luaVM, 3, 0); - CVector vecCenter = pEntry->GetCenterOfMass(); + CVector vecCenter = entry->GetCenterOfMass(); lua_pushnumber(luaVM, 1); lua_pushnumber(luaVM, vecCenter.fX); lua_settable(luaVM, -3); @@ -648,13 +650,13 @@ int CLuaHandlingDefs::GetModelHandling(lua_State* luaVM) lua_settable(luaVM, -3); lua_setfield(luaVM, -2, "centerOfMass"); - lua_pushnumber(luaVM, pEntry->GetPercentSubmerged()); + lua_pushnumber(luaVM, entry->GetPercentSubmerged()); lua_setfield(luaVM, -2, "percentSubmerged"); - lua_pushnumber(luaVM, pEntry->GetTractionMultiplier()); + lua_pushnumber(luaVM, entry->GetTractionMultiplier()); lua_setfield(luaVM, -2, "tractionMultiplier"); - CHandlingEntry::eDriveType eDriveType = pEntry->GetCarDriveType(); + CHandlingEntry::eDriveType eDriveType = entry->GetCarDriveType(); if (eDriveType == CHandlingEntry::FWD) lua_pushstring(luaVM, "fwd"); else if (eDriveType == CHandlingEntry::RWD) @@ -665,7 +667,7 @@ int CLuaHandlingDefs::GetModelHandling(lua_State* luaVM) lua_pushnil(luaVM); lua_setfield(luaVM, -2, "driveType"); - CHandlingEntry::eEngineType eEngineType = pEntry->GetCarEngineType(); + CHandlingEntry::eEngineType eEngineType = entry->GetCarEngineType(); if (eEngineType == CHandlingEntry::PETROL) lua_pushstring(luaVM, "petrol"); else if (eEngineType == CHandlingEntry::DIESEL) @@ -676,73 +678,73 @@ int CLuaHandlingDefs::GetModelHandling(lua_State* luaVM) lua_pushnil(luaVM); lua_setfield(luaVM, -2, "engineType"); - lua_pushnumber(luaVM, pEntry->GetNumberOfGears()); + lua_pushnumber(luaVM, entry->GetNumberOfGears()); lua_setfield(luaVM, -2, "numberOfGears"); - lua_pushnumber(luaVM, pEntry->GetEngineAcceleration()); + lua_pushnumber(luaVM, entry->GetEngineAcceleration()); lua_setfield(luaVM, -2, "engineAcceleration"); - lua_pushnumber(luaVM, pEntry->GetEngineInertia()); + lua_pushnumber(luaVM, entry->GetEngineInertia()); lua_setfield(luaVM, -2, "engineInertia"); - lua_pushnumber(luaVM, pEntry->GetMaxVelocity()); + lua_pushnumber(luaVM, entry->GetMaxVelocity()); lua_setfield(luaVM, -2, "maxVelocity"); - lua_pushnumber(luaVM, pEntry->GetBrakeDeceleration()); + lua_pushnumber(luaVM, entry->GetBrakeDeceleration()); lua_setfield(luaVM, -2, "brakeDeceleration"); - lua_pushnumber(luaVM, pEntry->GetBrakeBias()); + lua_pushnumber(luaVM, entry->GetBrakeBias()); lua_setfield(luaVM, -2, "brakeBias"); - lua_pushboolean(luaVM, pEntry->GetABS()); + lua_pushboolean(luaVM, entry->GetABS()); lua_setfield(luaVM, -2, "ABS"); - lua_pushnumber(luaVM, pEntry->GetSteeringLock()); + lua_pushnumber(luaVM, entry->GetSteeringLock()); lua_setfield(luaVM, -2, "steeringLock"); - lua_pushnumber(luaVM, pEntry->GetTractionLoss()); + lua_pushnumber(luaVM, entry->GetTractionLoss()); lua_setfield(luaVM, -2, "tractionLoss"); - lua_pushnumber(luaVM, pEntry->GetTractionBias()); + lua_pushnumber(luaVM, entry->GetTractionBias()); lua_setfield(luaVM, -2, "tractionBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionForceLevel()); + lua_pushnumber(luaVM, entry->GetSuspensionForceLevel()); lua_setfield(luaVM, -2, "suspensionForceLevel"); - lua_pushnumber(luaVM, pEntry->GetSuspensionDamping()); + lua_pushnumber(luaVM, entry->GetSuspensionDamping()); lua_setfield(luaVM, -2, "suspensionDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionHighSpeedDamping()); + lua_pushnumber(luaVM, entry->GetSuspensionHighSpeedDamping()); lua_setfield(luaVM, -2, "suspensionHighSpeedDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionUpperLimit()); + lua_pushnumber(luaVM, entry->GetSuspensionUpperLimit()); lua_setfield(luaVM, -2, "suspensionUpperLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionLowerLimit()); + lua_pushnumber(luaVM, entry->GetSuspensionLowerLimit()); lua_setfield(luaVM, -2, "suspensionLowerLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionFrontRearBias()); + lua_pushnumber(luaVM, entry->GetSuspensionFrontRearBias()); lua_setfield(luaVM, -2, "suspensionFrontRearBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionAntiDiveMultiplier()); + lua_pushnumber(luaVM, entry->GetSuspensionAntiDiveMultiplier()); lua_setfield(luaVM, -2, "suspensionAntiDiveMultiplier"); - lua_pushnumber(luaVM, pEntry->GetCollisionDamageMultiplier()); + lua_pushnumber(luaVM, entry->GetCollisionDamageMultiplier()); lua_setfield(luaVM, -2, "collisionDamageMultiplier"); - lua_pushnumber(luaVM, pEntry->GetSeatOffsetDistance()); + lua_pushnumber(luaVM, entry->GetSeatOffsetDistance()); lua_setfield(luaVM, -2, "seatOffsetDistance"); - lua_pushnumber(luaVM, pEntry->GetHandlingFlags()); + lua_pushnumber(luaVM, entry->GetHandlingFlags()); lua_setfield(luaVM, -2, "handlingFlags"); - lua_pushnumber(luaVM, pEntry->GetModelFlags()); + lua_pushnumber(luaVM, entry->GetModelFlags()); lua_setfield(luaVM, -2, "modelFlags"); - lua_pushnumber(luaVM, pEntry->GetMonetary()); + lua_pushnumber(luaVM, entry->GetMonetary()); lua_setfield(luaVM, -2, "monetary"); - CHandlingEntry::eLightType eHeadType = pEntry->GetHeadLight(); + CHandlingEntry::eLightType eHeadType = entry->GetHeadLight(); if (eHeadType == CHandlingEntry::LONG) lua_pushstring(luaVM, "long"); else if (eHeadType == CHandlingEntry::SMALL) @@ -753,7 +755,7 @@ int CLuaHandlingDefs::GetModelHandling(lua_State* luaVM) lua_pushnil(luaVM); lua_setfield(luaVM, -2, "headLight"); - CHandlingEntry::eLightType eTailType = pEntry->GetTailLight(); + CHandlingEntry::eLightType eTailType = entry->GetTailLight(); if (eTailType == CHandlingEntry::LONG) lua_pushstring(luaVM, "long"); else if (eTailType == CHandlingEntry::SMALL) @@ -764,7 +766,7 @@ int CLuaHandlingDefs::GetModelHandling(lua_State* luaVM) lua_pushnil(luaVM); lua_setfield(luaVM, -2, "tailLight"); - lua_pushnumber(luaVM, pEntry->GetAnimGroup()); + lua_pushnumber(luaVM, entry->GetAnimGroup()); lua_setfield(luaVM, -2, "animGroup"); return 1; @@ -784,28 +786,26 @@ int CLuaHandlingDefs::GetModelHandling(lua_State* luaVM) int CLuaHandlingDefs::GetOriginalHandling(lua_State* luaVM) { // table getOriginalHandling ( int modelID ) - unsigned short usModel; + std::uint16_t model; CScriptArgReader argStream(luaVM); - argStream.ReadNumber(usModel); + argStream.ReadNumber(model); if (!argStream.HasErrors()) { - eVehicleTypes eModel = static_cast(usModel); - if (eModel) + if (CVehicleManager::IsValidModel(model)) { - const CHandlingEntry* pEntry = g_pGame->GetHandlingManager()->GetOriginalHandlingData(eModel); - if (pEntry) + if (const auto* const entry = m_pHandlingManager->GetOriginalHandlingData(model)) { lua_newtable(luaVM); - lua_pushnumber(luaVM, pEntry->GetMass()); + lua_pushnumber(luaVM, entry->GetMass()); lua_setfield(luaVM, -2, "mass"); - lua_pushnumber(luaVM, pEntry->GetTurnMass()); + lua_pushnumber(luaVM, entry->GetTurnMass()); lua_setfield(luaVM, -2, "turnMass"); - lua_pushnumber(luaVM, pEntry->GetDragCoeff()); + lua_pushnumber(luaVM, entry->GetDragCoeff()); lua_setfield(luaVM, -2, "dragCoeff"); lua_createtable(luaVM, 3, 0); - CVector vecCenter = pEntry->GetCenterOfMass(); + CVector vecCenter = entry->GetCenterOfMass(); lua_pushnumber(luaVM, 1); lua_pushnumber(luaVM, vecCenter.fX); lua_settable(luaVM, -3); @@ -816,11 +816,11 @@ int CLuaHandlingDefs::GetOriginalHandling(lua_State* luaVM) lua_pushnumber(luaVM, vecCenter.fZ); lua_settable(luaVM, -3); lua_setfield(luaVM, -2, "centerOfMass"); - lua_pushnumber(luaVM, pEntry->GetPercentSubmerged()); + lua_pushnumber(luaVM, entry->GetPercentSubmerged()); lua_setfield(luaVM, -2, "percentSubmerged"); - lua_pushnumber(luaVM, pEntry->GetTractionMultiplier()); + lua_pushnumber(luaVM, entry->GetTractionMultiplier()); lua_setfield(luaVM, -2, "tractionMultiplier"); - CHandlingEntry::eDriveType eDriveType = pEntry->GetCarDriveType(); + CHandlingEntry::eDriveType eDriveType = entry->GetCarDriveType(); if (eDriveType == CHandlingEntry::FWD) lua_pushstring(luaVM, "fwd"); else if (eDriveType == CHandlingEntry::RWD) @@ -830,7 +830,7 @@ int CLuaHandlingDefs::GetOriginalHandling(lua_State* luaVM) else // What the ... (yeah, security) lua_pushnil(luaVM); lua_setfield(luaVM, -2, "driveType"); - CHandlingEntry::eEngineType eEngineType = pEntry->GetCarEngineType(); + CHandlingEntry::eEngineType eEngineType = entry->GetCarEngineType(); if (eEngineType == CHandlingEntry::PETROL) lua_pushstring(luaVM, "petrol"); else if (eEngineType == CHandlingEntry::DIESEL) @@ -840,51 +840,51 @@ int CLuaHandlingDefs::GetOriginalHandling(lua_State* luaVM) else lua_pushnil(luaVM); lua_setfield(luaVM, -2, "engineType"); - lua_pushnumber(luaVM, pEntry->GetNumberOfGears()); + lua_pushnumber(luaVM, entry->GetNumberOfGears()); lua_setfield(luaVM, -2, "numberOfGears"); - lua_pushnumber(luaVM, pEntry->GetEngineAcceleration()); + lua_pushnumber(luaVM, entry->GetEngineAcceleration()); lua_setfield(luaVM, -2, "engineAcceleration"); - lua_pushnumber(luaVM, pEntry->GetEngineInertia()); + lua_pushnumber(luaVM, entry->GetEngineInertia()); lua_setfield(luaVM, -2, "engineInertia"); - lua_pushnumber(luaVM, pEntry->GetMaxVelocity()); + lua_pushnumber(luaVM, entry->GetMaxVelocity()); lua_setfield(luaVM, -2, "maxVelocity"); - lua_pushnumber(luaVM, pEntry->GetBrakeDeceleration()); + lua_pushnumber(luaVM, entry->GetBrakeDeceleration()); lua_setfield(luaVM, -2, "brakeDeceleration"); - lua_pushnumber(luaVM, pEntry->GetBrakeBias()); + lua_pushnumber(luaVM, entry->GetBrakeBias()); lua_setfield(luaVM, -2, "brakeBias"); - lua_pushboolean(luaVM, pEntry->GetABS()); + lua_pushboolean(luaVM, entry->GetABS()); lua_setfield(luaVM, -2, "ABS"); - lua_pushnumber(luaVM, pEntry->GetSteeringLock()); + lua_pushnumber(luaVM, entry->GetSteeringLock()); lua_setfield(luaVM, -2, "steeringLock"); - lua_pushnumber(luaVM, pEntry->GetTractionLoss()); + lua_pushnumber(luaVM, entry->GetTractionLoss()); lua_setfield(luaVM, -2, "tractionLoss"); - lua_pushnumber(luaVM, pEntry->GetTractionBias()); + lua_pushnumber(luaVM, entry->GetTractionBias()); lua_setfield(luaVM, -2, "tractionBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionForceLevel()); + lua_pushnumber(luaVM, entry->GetSuspensionForceLevel()); lua_setfield(luaVM, -2, "suspensionForceLevel"); - lua_pushnumber(luaVM, pEntry->GetSuspensionDamping()); + lua_pushnumber(luaVM, entry->GetSuspensionDamping()); lua_setfield(luaVM, -2, "suspensionDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionHighSpeedDamping()); + lua_pushnumber(luaVM, entry->GetSuspensionHighSpeedDamping()); lua_setfield(luaVM, -2, "suspensionHighSpeedDamping"); - lua_pushnumber(luaVM, pEntry->GetSuspensionUpperLimit()); + lua_pushnumber(luaVM, entry->GetSuspensionUpperLimit()); lua_setfield(luaVM, -2, "suspensionUpperLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionLowerLimit()); + lua_pushnumber(luaVM, entry->GetSuspensionLowerLimit()); lua_setfield(luaVM, -2, "suspensionLowerLimit"); - lua_pushnumber(luaVM, pEntry->GetSuspensionFrontRearBias()); + lua_pushnumber(luaVM, entry->GetSuspensionFrontRearBias()); lua_setfield(luaVM, -2, "suspensionFrontRearBias"); - lua_pushnumber(luaVM, pEntry->GetSuspensionAntiDiveMultiplier()); + lua_pushnumber(luaVM, entry->GetSuspensionAntiDiveMultiplier()); lua_setfield(luaVM, -2, "suspensionAntiDiveMultiplier"); - lua_pushnumber(luaVM, pEntry->GetCollisionDamageMultiplier()); + lua_pushnumber(luaVM, entry->GetCollisionDamageMultiplier()); lua_setfield(luaVM, -2, "collisionDamageMultiplier"); - lua_pushnumber(luaVM, pEntry->GetSeatOffsetDistance()); + lua_pushnumber(luaVM, entry->GetSeatOffsetDistance()); lua_setfield(luaVM, -2, "seatOffsetDistance"); - lua_pushnumber(luaVM, pEntry->GetHandlingFlags()); + lua_pushnumber(luaVM, entry->GetHandlingFlags()); lua_setfield(luaVM, -2, "handlingFlags"); - lua_pushnumber(luaVM, pEntry->GetModelFlags()); + lua_pushnumber(luaVM, entry->GetModelFlags()); lua_setfield(luaVM, -2, "modelFlags"); - lua_pushnumber(luaVM, pEntry->GetMonetary()); + lua_pushnumber(luaVM, entry->GetMonetary()); lua_setfield(luaVM, -2, "monetary"); - CHandlingEntry::eLightType eHeadType = pEntry->GetHeadLight(); + CHandlingEntry::eLightType eHeadType = entry->GetHeadLight(); if (eHeadType == CHandlingEntry::LONG) lua_pushstring(luaVM, "long"); else if (eHeadType == CHandlingEntry::SMALL) @@ -894,7 +894,7 @@ int CLuaHandlingDefs::GetOriginalHandling(lua_State* luaVM) else lua_pushnil(luaVM); lua_setfield(luaVM, -2, "headLight"); - CHandlingEntry::eLightType eTailType = pEntry->GetTailLight(); + CHandlingEntry::eLightType eTailType = entry->GetTailLight(); if (eTailType == CHandlingEntry::LONG) lua_pushstring(luaVM, "long"); else if (eTailType == CHandlingEntry::SMALL) @@ -904,7 +904,7 @@ int CLuaHandlingDefs::GetOriginalHandling(lua_State* luaVM) else lua_pushnil(luaVM); lua_setfield(luaVM, -2, "tailLight"); - lua_pushnumber(luaVM, pEntry->GetAnimGroup()); + lua_pushnumber(luaVM, entry->GetAnimGroup()); lua_setfield(luaVM, -2, "animGroup"); return 1; } diff --git a/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp b/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp index a001ba518f..8973abc6b1 100644 --- a/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp @@ -612,8 +612,7 @@ bool CEntityAddPacket::Write(NetBitStreamInterface& BitStream) const BitStream.WriteBit(false); // Write handling - if (g_pGame->GetHandlingManager()->HasModelHandlingChanged(static_cast(pVehicle->GetModel())) || - pVehicle->HasHandlingChanged()) + if (g_pGame->GetHandlingManager()->HasModelHandlingChanged(pVehicle->GetModel()) || pVehicle->HasHandlingChanged()) { BitStream.WriteBit(true); SVehicleHandlingSync handling; diff --git a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp index e62547b3fb..e2adf9a5bc 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -192,6 +192,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const wsProps.data3.roadsignstext = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::ROADSIGNSTEXT); wsProps.data4.extendedwatercannons = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTENDEDWATERCANNONS); wsProps.data5.tunnelweatherblend = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::TUNNELWEATHERBLEND); + wsProps.data6.ignoreFireState = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::IGNOREFIRESTATE); BitStream.Write(&wsProps); } diff --git a/Server/mods/deathmatch/logic/packets/CPlayerDisconnectedPacket.h b/Server/mods/deathmatch/logic/packets/CPlayerDisconnectedPacket.h index 82fdfbd1b0..541f9b191c 100644 --- a/Server/mods/deathmatch/logic/packets/CPlayerDisconnectedPacket.h +++ b/Server/mods/deathmatch/logic/packets/CPlayerDisconnectedPacket.h @@ -39,7 +39,8 @@ class CPlayerDisconnectedPacket final : public CPacket BAN, KICK, CUSTOM, - SHUTDOWN + SHUTDOWN, + SERIAL_DUPLICATE }; CPlayerDisconnectedPacket(const char* szReason); diff --git a/Server/mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.cpp b/Server/mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.cpp new file mode 100644 index 0000000000..59c3ec4c7b --- /dev/null +++ b/Server/mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.cpp @@ -0,0 +1,20 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.cpp + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CPlayerWorldSpecialPropertyPacket.h" + +bool CPlayerWorldSpecialPropertyPacket::Read(NetBitStreamInterface& stream) noexcept +{ + stream.ReadString(m_property); + stream.ReadBit(m_enabled); + + return true; +} diff --git a/Server/mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.h b/Server/mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.h new file mode 100644 index 0000000000..cb6dd9e2f1 --- /dev/null +++ b/Server/mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.h @@ -0,0 +1,34 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/packets/CPlayerWorldSpecialPropertyPacket.h + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include +#include "CPacket.h" + +class CPlayerWorldSpecialPropertyPacket final : public CPacket +{ +public: + CPlayerWorldSpecialPropertyPacket() noexcept {} + + ePacketID GetPacketID() const noexcept { return PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY; } + unsigned long GetFlags() const noexcept { return PACKET_HIGH_PRIORITY | PACKET_RELIABLE | PACKET_SEQUENCED; } + virtual ePacketOrdering GetPacketOrdering() const noexcept { return PACKET_ORDERING_DEFAULT; } + + bool Read(NetBitStreamInterface& stream) noexcept; + + std::string GetProperty() const noexcept { return m_property; } + bool IsEnabled() const noexcept { return m_enabled; } + +private: + std::string m_property; + bool m_enabled; +}; diff --git a/Server/mods/deathmatch/mtaserver.conf b/Server/mods/deathmatch/mtaserver.conf index 19fe4a05d8..726199d548 100644 --- a/Server/mods/deathmatch/mtaserver.conf +++ b/Server/mods/deathmatch/mtaserver.conf @@ -268,12 +268,28 @@ Values: 0 - Off, 1 - Enabled. Default - 1 --> 1 + + 0 + + + 1 + 1000 100 + + + 1 diff --git a/Server/mods/deathmatch/mtaserver.conf.template b/Server/mods/deathmatch/mtaserver.conf.template index faf1c71a6d..13237b1b10 100644 --- a/Server/mods/deathmatch/mtaserver.conf.template +++ b/Server/mods/deathmatch/mtaserver.conf.template @@ -269,10 +269,26 @@ Values: 0 - Off, 1 - Enabled. Default - 1 --> 1 + + 0 + + + 1 + 1000 100 + + + 1 diff --git a/Shared/data/MTA San Andreas/MTA/cgui/images/map_1024.png b/Shared/data/MTA San Andreas/MTA/cgui/images/map_1024.png new file mode 100644 index 0000000000..747e6d6d49 Binary files /dev/null and b/Shared/data/MTA San Andreas/MTA/cgui/images/map_1024.png differ diff --git a/Shared/data/MTA San Andreas/MTA/cgui/images/map_2048.png b/Shared/data/MTA San Andreas/MTA/cgui/images/map_2048.png new file mode 100644 index 0000000000..c41bfbb347 Binary files /dev/null and b/Shared/data/MTA San Andreas/MTA/cgui/images/map_2048.png differ diff --git a/Shared/data/MTA San Andreas/MTA/cgui/images/radar.jpg b/Shared/data/MTA San Andreas/MTA/cgui/images/radar.jpg deleted file mode 100644 index 4249b8943f..0000000000 Binary files a/Shared/data/MTA San Andreas/MTA/cgui/images/radar.jpg and /dev/null differ diff --git a/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot b/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot index 0947cb8c01..bb5c84bc7a 100644 --- a/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot +++ b/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: MTA San Andreas 1.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-10 20:57+0000\n" +"POT-Creation-Date: 2024-12-23 15:13+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -35,7 +35,7 @@ msgstr "" msgid "Remember decision" msgstr "" -#: Client/cefweb/CWebsiteRequests.cpp:51 Client/core/CSettings.cpp:974 +#: Client/cefweb/CWebsiteRequests.cpp:51 Client/core/CSettings.cpp:991 msgid "Allow" msgstr "" @@ -85,47 +85,47 @@ msgid "previous radio channel" msgstr "" #: Client/mods/deathmatch/CClient.cpp:67 -msgid "enables the radar view" +msgid "enables the player-map view" msgstr "" #: Client/mods/deathmatch/CClient.cpp:68 -msgid "zooms the radar in" +msgid "zooms the player-map in" msgstr "" #: Client/mods/deathmatch/CClient.cpp:69 -msgid "zooms the radar out" +msgid "zooms the player-map out" msgstr "" #: Client/mods/deathmatch/CClient.cpp:70 -msgid "moves the radar north" +msgid "moves the player-map north" msgstr "" #: Client/mods/deathmatch/CClient.cpp:71 -msgid "moves the radar south" +msgid "moves the player-map south" msgstr "" #: Client/mods/deathmatch/CClient.cpp:72 -msgid "moves the radar east" +msgid "moves the player-map east" msgstr "" #: Client/mods/deathmatch/CClient.cpp:73 -msgid "moves the radar west" +msgid "moves the player-map west" msgstr "" #: Client/mods/deathmatch/CClient.cpp:74 -msgid "attaches the radar" +msgid "attaches the player-map" msgstr "" #: Client/mods/deathmatch/CClient.cpp:75 -msgid "reduces radar opacity" +msgid "reduces player-map opacity" msgstr "" #: Client/mods/deathmatch/CClient.cpp:76 -msgid "increases radar opacity" +msgid "increases player-map opacity" msgstr "" #: Client/mods/deathmatch/CClient.cpp:77 -msgid "toggles radar help text" +msgid "toggles player-map help text" msgstr "" #: Client/mods/deathmatch/CClient.cpp:78 @@ -159,123 +159,123 @@ msgid "(Development mode) prints world sound ids into the debug window" msgstr "" #: Client/mods/deathmatch/logic/CResource.cpp:375 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1089 Client/core/CCore.cpp:674 -#: Client/core/CSettings.cpp:3483 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1095 Client/core/CCore.cpp:674 +#: Client/core/CSettings.cpp:3510 msgid "In-game" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:374 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Flying a UFO around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:374 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Cruising around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:374 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Riding the waves of" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:375 +#: Client/mods/deathmatch/logic/CClientGame.cpp:377 msgid "Riding the train in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:375 +#: Client/mods/deathmatch/logic/CClientGame.cpp:377 msgid "Flying around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:376 +#: Client/mods/deathmatch/logic/CClientGame.cpp:378 msgid "Riding around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:376 +#: Client/mods/deathmatch/logic/CClientGame.cpp:378 msgid "Monster truckin' around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:376 +#: Client/mods/deathmatch/logic/CClientGame.cpp:378 msgid "Quaddin' around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:377 +#: Client/mods/deathmatch/logic/CClientGame.cpp:379 msgid "Bunny hopping around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:377 +#: Client/mods/deathmatch/logic/CClientGame.cpp:379 msgid "Doing weird stuff in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:381 +#: Client/mods/deathmatch/logic/CClientGame.cpp:383 msgid "Climbing around in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:382 -#: Client/mods/deathmatch/logic/CClientGame.cpp:383 +#: Client/mods/deathmatch/logic/CClientGame.cpp:384 +#: Client/mods/deathmatch/logic/CClientGame.cpp:385 msgid "Doing a drive-by in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:384 +#: Client/mods/deathmatch/logic/CClientGame.cpp:386 msgid "Blub blub..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:385 +#: Client/mods/deathmatch/logic/CClientGame.cpp:387 msgid "Breathing water" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:386 +#: Client/mods/deathmatch/logic/CClientGame.cpp:388 msgid "Drowning in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:387 +#: Client/mods/deathmatch/logic/CClientGame.cpp:389 msgid "Ducking for cover in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:388 +#: Client/mods/deathmatch/logic/CClientGame.cpp:390 msgid "Fighting in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:389 +#: Client/mods/deathmatch/logic/CClientGame.cpp:391 msgid "Throwing fists in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:390 +#: Client/mods/deathmatch/logic/CClientGame.cpp:392 msgid "Blastin' fools in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:391 +#: Client/mods/deathmatch/logic/CClientGame.cpp:393 msgid "Shooting up" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:392 +#: Client/mods/deathmatch/logic/CClientGame.cpp:394 msgid "Jetpacking in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:393 +#: Client/mods/deathmatch/logic/CClientGame.cpp:395 msgid "Literally on fire in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:394 +#: Client/mods/deathmatch/logic/CClientGame.cpp:396 msgid "Burning up in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:395 +#: Client/mods/deathmatch/logic/CClientGame.cpp:397 msgid "Swimming in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:396 +#: Client/mods/deathmatch/logic/CClientGame.cpp:398 msgid "Floating around in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:397 +#: Client/mods/deathmatch/logic/CClientGame.cpp:399 msgid "Being chased by a shark" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:398 +#: Client/mods/deathmatch/logic/CClientGame.cpp:400 msgid "Choking to death in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:533 +#: Client/mods/deathmatch/logic/CClientGame.cpp:539 #: Client/core/CMainMenu.cpp:304 Client/core/CCore.cpp:674 -#: Client/core/CSettings.cpp:3479 +#: Client/core/CSettings.cpp:3506 msgid "Main menu" msgstr "" @@ -283,176 +283,200 @@ msgstr "" #. Display an error, reset the error status and exit #. Show a message that the connection timed out and abort #. Show failed message and abort the attempt -#: Client/mods/deathmatch/logic/CClientGame.cpp:641 -#: Client/mods/deathmatch/logic/CClientGame.cpp:715 -#: Client/mods/deathmatch/logic/CClientGame.cpp:739 -#: Client/mods/deathmatch/logic/CClientGame.cpp:761 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1174 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1254 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1264 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1333 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1370 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1419 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1431 +#: Client/mods/deathmatch/logic/CClientGame.cpp:647 +#: Client/mods/deathmatch/logic/CClientGame.cpp:721 +#: Client/mods/deathmatch/logic/CClientGame.cpp:745 +#: Client/mods/deathmatch/logic/CClientGame.cpp:767 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1180 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1260 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1270 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1339 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1376 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1425 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1437 #: Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp:145 +#: Client/game_sa/CGameSA.cpp:256 Client/game_sa/CGameSA.cpp:267 #: Client/loader/MainFunctions.cpp:252 Client/loader/MainFunctions.cpp:267 #: Client/loader/MainFunctions.cpp:269 Client/loader/MainFunctions.cpp:846 #: Client/loader/CInstallManager.cpp:552 Client/loader/CInstallManager.cpp:561 -#: Client/core/CGUI.cpp:87 Client/core/CCore.cpp:1275 -#: Client/core/CCore.cpp:1288 Client/core/CSettings.cpp:2941 -#: Client/core/CSettings.cpp:4166 Client/core/CSettings.cpp:4194 -#: Client/core/CSettings.cpp:4764 Client/core/CConnectManager.cpp:80 +#: Client/core/CGUI.cpp:93 Client/core/CCore.cpp:1279 +#: Client/core/CCore.cpp:1292 Client/core/CSettings.cpp:2966 +#: Client/core/CSettings.cpp:4204 Client/core/CSettings.cpp:4232 +#: Client/core/CSettings.cpp:4802 Client/core/CConnectManager.cpp:80 #: Client/core/CConnectManager.cpp:111 Client/core/CConnectManager.cpp:127 -#: Client/core/CConnectManager.cpp:263 Client/core/CConnectManager.cpp:321 -#: Client/core/CConnectManager.cpp:404 Client/core/CConnectManager.cpp:411 -#: Client/core/CConnectManager.cpp:421 +#: Client/core/CConnectManager.cpp:265 Client/core/CConnectManager.cpp:323 +#: Client/core/CConnectManager.cpp:406 Client/core/CConnectManager.cpp:413 +#: Client/core/CConnectManager.cpp:423 #: Client/core/DXHook/CDirect3DHook9.cpp:127 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1285 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1307 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1364 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1413 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1261 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1283 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1340 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1389 #: Shared/mods/deathmatch/logic/CLatentTransferManager.cpp:378 #: Shared/sdk/SharedUtil.Misc.hpp:137 msgid "Error" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:641 -#: Client/mods/deathmatch/logic/CClientGame.cpp:739 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1307 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1364 +#: Client/mods/deathmatch/logic/CClientGame.cpp:647 +#: Client/mods/deathmatch/logic/CClientGame.cpp:745 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1283 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1340 msgid "Invalid nickname! Please go to Settings and set a new one!" msgstr "" #. Display the status box -#: Client/mods/deathmatch/logic/CClientGame.cpp:657 -#: Client/core/CConnectManager.cpp:148 +#: Client/mods/deathmatch/logic/CClientGame.cpp:663 +#: Client/core/CConnectManager.cpp:150 msgid "CONNECTING" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:657 +#: Client/mods/deathmatch/logic/CClientGame.cpp:663 msgid "Entering the game ..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:715 +#: Client/mods/deathmatch/logic/CClientGame.cpp:721 msgid "" "Not connected; please use Quick Connect or the 'connect' command to connect " "to a server." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:761 +#: Client/mods/deathmatch/logic/CClientGame.cpp:767 msgid "Could not start the local server. See console for details." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:771 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1243 +#: Client/mods/deathmatch/logic/CClientGame.cpp:777 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1249 msgid "Local Server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:771 +#: Client/mods/deathmatch/logic/CClientGame.cpp:777 msgid "Starting local server ..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1019 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1025 msgid "Area 51" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1028 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1034 msgid "Walking around " msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1174 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1180 #, c-format msgid "You were kicked from the game ( %s )" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1243 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1249 msgid "Connecting to local server..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1254 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1260 msgid "Error connecting to server." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1264 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1270 msgid "Connecting to local server timed out. See console for details." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1333 -#: Client/core/CConnectManager.cpp:263 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1339 +#: Client/core/CConnectManager.cpp:265 msgid "Connection timed out" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1370 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1376 msgid "Connection with the server was lost" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1381 -#: Client/core/CConnectManager.cpp:277 Client/core/CConnectManager.cpp:281 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1387 +#: Client/core/CConnectManager.cpp:279 Client/core/CConnectManager.cpp:283 msgid "Disconnected: unknown protocol error" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1385 -#: Client/core/CConnectManager.cpp:285 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1391 +#: Client/core/CConnectManager.cpp:287 msgid "Disconnected: disconnected remotely" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1389 -#: Client/core/CConnectManager.cpp:289 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1395 +#: Client/core/CConnectManager.cpp:291 msgid "Disconnected: connection lost remotely" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1393 -#: Client/core/CConnectManager.cpp:293 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1399 +#: Client/core/CConnectManager.cpp:295 msgid "Disconnected: you are banned from this server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1397 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1403 msgid "Disconnected: the server is currently full" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1401 -#: Client/core/CConnectManager.cpp:300 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1407 +#: Client/core/CConnectManager.cpp:302 msgid "Disconnected: disconnected from the server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1405 -#: Client/core/CConnectManager.cpp:304 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1411 +#: Client/core/CConnectManager.cpp:306 msgid "Disconnected: connection to the server was lost" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1409 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1415 msgid "Disconnected: invalid password specified" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1413 -#: Client/core/CConnectManager.cpp:311 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1419 +#: Client/core/CConnectManager.cpp:313 msgid "Disconnected: connection was refused" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1431 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1437 msgid "MTA Client verification failed!" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5623 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5626 msgid "In a ditch" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5623 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5626 msgid "En-route to hospital" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5623 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5626 msgid "Meeting their maker" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5624 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5627 msgid "Regretting their decisions" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5624 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5627 msgid "Wasted" msgstr "" +#: Client/mods/deathmatch/logic/CPlayerMap.cpp:78 +#, c-format +msgid "Change mode: %s" +msgstr "" + +#: Client/mods/deathmatch/logic/CPlayerMap.cpp:80 +#, c-format +msgid "Zoom: %s/%s Movement: %s, %s, %s, %s Opacity: %s/%s" +msgstr "" + +#: Client/mods/deathmatch/logic/CPlayerMap.cpp:84 +#, c-format +msgid "Toggle map: %s Toggle help text: %s" +msgstr "" + +#: Client/mods/deathmatch/logic/CPlayerMap.cpp:715 +msgid "Following Player" +msgstr "" + +#: Client/mods/deathmatch/logic/CPlayerMap.cpp:717 +msgid "Free Movement" +msgstr "" + #: Client/mods/deathmatch/logic/CTransferBox.cpp:25 msgid "Map download progress:" msgstr "" @@ -556,108 +580,112 @@ msgid "Disconnected: Serial verification failed" msgstr "" #: Client/mods/deathmatch/logic/CPacketHandler.cpp:576 +msgid "Disconnected: Serial already in use" +msgstr "" + +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:580 #, c-format msgid "Disconnected: Connection desync %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:585 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:589 #, c-format msgid "Disconnected: You were kicked by %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:590 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:594 #, c-format msgid "Disconnected: You were banned by %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:601 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:605 msgid "Disconnected: Server shutdown or restarting" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:621 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:625 msgid "You were kicked from the game" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:622 -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:633 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:626 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:637 msgid "This server requires a non-modifed gta_sa.exe" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:623 -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:634 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:627 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:638 msgid "Please replace gta_sa.exe" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:624 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:628 msgid "This server does not allow custom D3D9.DLLs" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:625 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:629 msgid "Remove D3D9.DLL from your GTA install directory and restart MTA" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:626 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:630 msgid "This server does not allow virtual machines" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:627 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:631 msgid "This server requires driver signing to be enabled" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:628 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:632 msgid "Please restart your PC" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:629 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:633 msgid "This server has detected missing anti-cheat components" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:630 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:634 msgid "Try restarting MTA" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:631 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:635 msgid "This server requires a non-modifed gta3.img and gta_int.img" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:632 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:636 msgid "Please replace gta3.img or gta_int.img" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:635 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:639 msgid "This server does not allow Wine" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:636 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:640 msgid "Ensure no other program is modifying MTA:SA" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:650 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:654 msgid "Time Remaining: " msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:660 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:664 #, c-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:662 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:666 #, c-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:664 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:668 #, c-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:666 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:670 #, c-format msgid "%d second" msgid_plural "%d seconds" @@ -665,7 +693,7 @@ msgstr[0] "" msgstr[1] "" #. Display the error -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:670 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:674 msgid "Disconnected" msgstr "" @@ -677,8 +705,8 @@ msgstr "" #. * Webbrowser tab #. * #: Client/mods/deathmatch/logic/CLocalServer.cpp:51 -#: Client/core/CSettings.cpp:442 Client/core/CSettings.cpp:630 -#: Client/core/CSettings.cpp:904 Client/core/CSettings.cpp:2018 +#: Client/core/CSettings.cpp:458 Client/core/CSettings.cpp:917 +#: Client/core/CSettings.cpp:2043 msgid "General" msgstr "" @@ -734,7 +762,7 @@ msgstr "" #: Client/gui/CGUIMessageBox_Impl.cpp:68 Client/loader/Dialogs.cpp:136 #: Client/core/CVersionUpdater.cpp:1790 Client/core/CVersionUpdater.cpp:1806 #: Client/core/CVersionUpdater.cpp:1841 Client/core/CSettings.cpp:132 -#: Client/core/CSettings.cpp:4784 +#: Client/core/CSettings.cpp:4822 msgid "Cancel" msgstr "" @@ -744,19 +772,34 @@ msgstr "" msgid "Download error: %s" msgstr "" -#: Client/game_sa/CSettingsSA.cpp:767 +#: Client/game_sa/CSettingsSA.cpp:781 msgid "Can't find valid screen resolution." msgstr "" #. Confirm that res should be used -#: Client/game_sa/CSettingsSA.cpp:843 +#: Client/game_sa/CSettingsSA.cpp:857 msgid "Are you sure you want to use this screen resolution?" msgstr "" -#: Client/game_sa/CSettingsSA.cpp:845 Client/loader/Dialogs.cpp:194 +#: Client/game_sa/CSettingsSA.cpp:859 Client/loader/Dialogs.cpp:194 msgid "MTA: San Andreas" msgstr "" +#: Client/game_sa/CGameSA.cpp:250 Client/game_sa/CGameSA.cpp:261 +msgid "Failed initialization game_sa" +msgstr "" + +#: Client/game_sa/CGameSA.cpp:252 +msgid "Memory allocations failed" +msgstr "" + +#: Client/game_sa/CGameSA.cpp:263 Client/loader/MainFunctions.cpp:603 +#: Client/loader/MainFunctions.cpp:610 Client/loader/MainFunctions.cpp:1219 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1363 +#: Client/core/ServerBrowser/CServerInfo.cpp:319 +msgid "Information" +msgstr "" + #. Couldn't create render target for CPostEffects #: Client/multiplayer_sa/CMultiplayerSA_CrashFixHacks.cpp:1450 msgid "Problem with graphics driver" @@ -770,7 +813,7 @@ msgstr "" #: Client/core/CVersionUpdater.cpp:1956 Client/core/CVersionUpdater.cpp:1968 #: Client/core/CVersionUpdater.cpp:2120 Client/core/CVersionUpdater.cpp:2129 #: Client/core/CVersionUpdater.cpp:2138 Client/core/CVersionUpdater.cpp:2152 -#: Client/core/CSettings.cpp:127 Client/core/CSettings.cpp:4785 +#: Client/core/CSettings.cpp:127 Client/core/CSettings.cpp:4823 msgid "OK" msgstr "" @@ -783,10 +826,10 @@ msgstr "" #: Client/gui/CGUIMessageBox_Impl.cpp:72 Client/loader/Dialogs.cpp:131 #: Client/core/CVersionUpdater.cpp:1572 Client/core/CVersionUpdater.cpp:1590 #: Client/core/CVersionUpdater.cpp:1859 Client/core/CVersionUpdater.cpp:1878 -#: Client/core/CQuestionBox.cpp:195 Client/core/CMainMenu.cpp:1200 -#: Client/core/CSettings.cpp:1389 Client/core/CSettings.cpp:1413 -#: Client/core/CSettings.cpp:4489 Client/core/CSettings.cpp:4563 -#: Client/core/CSettings.cpp:4593 Client/core/CSettings.cpp:4642 +#: Client/core/CQuestionBox.cpp:195 Client/core/CMainMenu.cpp:1196 +#: Client/core/CSettings.cpp:1407 Client/core/CSettings.cpp:1431 +#: Client/core/CSettings.cpp:4527 Client/core/CSettings.cpp:4601 +#: Client/core/CSettings.cpp:4631 Client/core/CSettings.cpp:4680 #: Client/core/ServerBrowser/CServerInfo.cpp:481 msgid "Yes" msgstr "" @@ -824,19 +867,28 @@ msgstr "" msgid "Extracting files..." msgstr "" -#: Client/loader/Utils.cpp:534 Client/loader/Dialogs.cpp:890 -msgid "Searching for Grand Theft Auto San Andreas" +#: Client/loader/Utils.cpp:535 +msgid "" +"Start Grand Theft Auto: San Andreas.\n" +"Ensure the game is placed in the 'Program Files (x86)' folder." msgstr "" -#: Client/loader/Utils.cpp:536 Client/loader/Dialogs.cpp:893 -msgid "Please start Grand Theft Auto San Andreas" +#: Client/loader/Utils.cpp:535 Client/loader/Utils.cpp:548 +msgid "Searching for GTA: San Andreas" msgstr "" -#: Client/loader/Utils.cpp:600 +#: Client/loader/Utils.cpp:548 +msgid "" +"Sorry, game not found.\n" +"Start Grand Theft Auto: San Andreas and click retry.\n" +"Ensure the game is placed in the 'Program Files (x86)' folder." +msgstr "" + +#: Client/loader/Utils.cpp:597 msgid "Select your Grand Theft Auto: San Andreas Installation Directory" msgstr "" -#: Client/loader/Utils.cpp:968 Client/loader/CInstallManager.cpp:361 +#: Client/loader/Utils.cpp:965 Client/loader/CInstallManager.cpp:361 #, c-format msgid "" "MTA:SA needs Administrator access for the following task:\n" @@ -846,28 +898,28 @@ msgid "" "Please confirm in the next window." msgstr "" -#: Client/loader/Utils.cpp:1069 +#: Client/loader/Utils.cpp:1066 #, c-format msgid "Error loading %s module! (%s)" msgstr "" -#: Client/loader/Utils.cpp:1394 Client/loader/Dialogs.cpp:914 +#: Client/loader/Utils.cpp:1391 Client/loader/Dialogs.cpp:914 msgid "Copying files..." msgstr "" -#: Client/loader/Utils.cpp:1454 Client/loader/Dialogs.cpp:919 +#: Client/loader/Utils.cpp:1451 Client/loader/Dialogs.cpp:919 msgid "Copy finished early. Everything OK." msgstr "" -#: Client/loader/Utils.cpp:1460 Client/loader/Dialogs.cpp:924 +#: Client/loader/Utils.cpp:1457 Client/loader/Dialogs.cpp:924 msgid "Finishing..." msgstr "" -#: Client/loader/Utils.cpp:1462 Client/loader/Dialogs.cpp:928 +#: Client/loader/Utils.cpp:1459 Client/loader/Dialogs.cpp:928 msgid "Done!" msgstr "" -#: Client/loader/Utils.cpp:1502 +#: Client/loader/Utils.cpp:1499 #, c-format msgid "" "New installation of %s detected.\n" @@ -875,48 +927,48 @@ msgid "" "Do you want to copy your settings from %s ?" msgstr "" -#: Client/loader/Utils.cpp:1541 +#: Client/loader/Utils.cpp:1538 #, c-format msgid "GTA:SA had trouble opening the file '%s'" msgstr "" -#: Client/loader/Utils.cpp:1563 +#: Client/loader/Utils.cpp:1560 #, c-format msgid "GTA:SA is missing the file '%s'." msgstr "" -#: Client/loader/Utils.cpp:1588 +#: Client/loader/Utils.cpp:1585 msgid "GTA:SA had trouble loading a model." msgstr "" -#: Client/loader/Utils.cpp:1590 +#: Client/loader/Utils.cpp:1587 msgid "If you recently modified gta3.img, then try reinstalling GTA:SA." msgstr "" -#: Client/loader/Utils.cpp:1615 +#: Client/loader/Utils.cpp:1612 msgid "GTA:SA had trouble adding an upgrade to a vehicle." msgstr "" -#: Client/loader/Utils.cpp:1634 +#: Client/loader/Utils.cpp:1631 #, c-format msgid "GTA:SA found errors in the file '%s'" msgstr "" -#: Client/loader/Utils.cpp:1716 +#: Client/loader/Utils.cpp:1713 msgid "Did your computer restart when playing MTA:SA?" msgstr "" -#: Client/loader/Utils.cpp:1781 +#: Client/loader/Utils.cpp:1778 msgid "Please terminate the following programs before continuing:" msgstr "" #: Client/loader/Dialogs.cpp:132 Client/core/CVersionUpdater.cpp:1571 #: Client/core/CVersionUpdater.cpp:1589 Client/core/CVersionUpdater.cpp:1858 #: Client/core/CVersionUpdater.cpp:1877 Client/core/CQuestionBox.cpp:194 -#: Client/core/CMainMenu.cpp:1199 Client/core/CSettings.cpp:1388 -#: Client/core/CSettings.cpp:1412 Client/core/CSettings.cpp:4488 -#: Client/core/CSettings.cpp:4562 Client/core/CSettings.cpp:4592 -#: Client/core/CSettings.cpp:4641 Client/core/ServerBrowser/CServerInfo.cpp:481 +#: Client/core/CMainMenu.cpp:1195 Client/core/CSettings.cpp:1406 +#: Client/core/CSettings.cpp:1430 Client/core/CSettings.cpp:4526 +#: Client/core/CSettings.cpp:4600 Client/core/CSettings.cpp:4630 +#: Client/core/CSettings.cpp:4679 Client/core/ServerBrowser/CServerInfo.cpp:481 msgid "No" msgstr "" @@ -1054,6 +1106,14 @@ msgid "" "I want my PC to lag and be part of a botnet." msgstr "" +#: Client/loader/Dialogs.cpp:890 +msgid "Searching for Grand Theft Auto San Andreas" +msgstr "" + +#: Client/loader/Dialogs.cpp:893 +msgid "Please start Grand Theft Auto San Andreas" +msgstr "" + #: Client/loader/MainFunctions.cpp:248 msgid "" "Trouble restarting MTA:SA\n" @@ -1122,13 +1182,13 @@ msgid "" "Do you want to change the following setting?" msgstr "" -#: Client/loader/MainFunctions.cpp:389 Client/core/CSettings.cpp:662 -#: Client/core/CSettings.cpp:1004 +#: Client/loader/MainFunctions.cpp:389 Client/core/CSettings.cpp:675 +#: Client/core/CSettings.cpp:1021 msgid "Fullscreen mode:" msgstr "" -#: Client/loader/MainFunctions.cpp:389 Client/core/CSettings.cpp:670 -#: Client/core/CSettings.cpp:1615 +#: Client/loader/MainFunctions.cpp:389 Client/core/CSettings.cpp:683 +#: Client/core/CSettings.cpp:1633 msgid "Borderless window" msgstr "" @@ -1159,13 +1219,6 @@ msgid "" "terminated before MTA:SA can be started. Do you want to do that now?" msgstr "" -#: Client/loader/MainFunctions.cpp:603 Client/loader/MainFunctions.cpp:610 -#: Client/loader/MainFunctions.cpp:1219 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1387 -#: Client/core/ServerBrowser/CServerInfo.cpp:319 -msgid "Information" -msgstr "" - #: Client/loader/MainFunctions.cpp:609 msgid "" "Unable to terminate GTA: San Andreas. If the problem persists, please " @@ -1516,7 +1569,7 @@ msgstr "" msgid " - Unknown problem in _DialogUpdateResult" msgstr "" -#: Client/core/CVersionUpdater.cpp:2081 Client/core/CSettings.cpp:4590 +#: Client/core/CVersionUpdater.cpp:2081 Client/core/CSettings.cpp:4628 msgid "CUSTOMIZED GTA:SA FILES" msgstr "" @@ -1569,13 +1622,13 @@ msgstr "" msgid "Backwards" msgstr "" -#: Client/core/CKeyBinds.cpp:191 Client/core/CSettings.cpp:2240 -#: Client/core/CSettings.cpp:2268 +#: Client/core/CKeyBinds.cpp:191 Client/core/CSettings.cpp:2265 +#: Client/core/CSettings.cpp:2293 msgid "Left" msgstr "" -#: Client/core/CKeyBinds.cpp:192 Client/core/CSettings.cpp:2242 -#: Client/core/CSettings.cpp:2269 +#: Client/core/CKeyBinds.cpp:192 Client/core/CSettings.cpp:2267 +#: Client/core/CSettings.cpp:2294 msgid "Right" msgstr "" @@ -1758,16 +1811,16 @@ msgstr "" msgid "connect: Syntax is 'connect [ ]'" msgstr "" -#: Client/core/CCommandFuncs.cpp:250 Client/core/CCommandFuncs.cpp:318 +#: Client/core/CCommandFuncs.cpp:250 msgid "connect: Bad port number" msgstr "" -#: Client/core/CCommandFuncs.cpp:272 Client/core/CCommandFuncs.cpp:333 +#: Client/core/CCommandFuncs.cpp:272 #, c-format msgid "connect: Connecting to %s:%u..." msgstr "" -#: Client/core/CCommandFuncs.cpp:276 Client/core/CCommandFuncs.cpp:337 +#: Client/core/CCommandFuncs.cpp:276 #, c-format msgid "connect: could not connect to %s:%u!" msgstr "" @@ -1776,16 +1829,30 @@ msgstr "" msgid "connect: Failed to unload current mod" msgstr "" -#: Client/core/CCommandFuncs.cpp:371 +#: Client/core/CCommandFuncs.cpp:317 +msgid "reconnect: Bad port number" +msgstr "" + +#: Client/core/CCommandFuncs.cpp:332 +#, c-format +msgid "reconnect: Reconnecting to %s:%u..." +msgstr "" + +#: Client/core/CCommandFuncs.cpp:336 +#, c-format +msgid "reconnect: could not connect to %s:%u!" +msgstr "" + +#: Client/core/CCommandFuncs.cpp:370 msgid "Bound all controls from GTA" msgstr "" -#: Client/core/CCommandFuncs.cpp:385 +#: Client/core/CCommandFuncs.cpp:384 msgid "Saved configuration file" msgstr "" #. Print it -#: Client/core/CCommandFuncs.cpp:451 +#: Client/core/CCommandFuncs.cpp:450 #, c-format msgid "* Your serial is: %s" msgstr "" @@ -1818,7 +1885,7 @@ msgid "English" msgstr "" #. Even the default skin doesn't work, so give up -#: Client/core/CGUI.cpp:86 +#: Client/core/CGUI.cpp:92 msgid "" "The skin you selected could not be loaded, and the default skin also could " "not be loaded, please reinstall MTA." @@ -1871,14 +1938,14 @@ msgid "" "Upgrade Windows to play on the latest servers." msgstr "" -#: Client/core/CMainMenu.cpp:1193 +#: Client/core/CMainMenu.cpp:1189 msgid "" "This will disconnect you from the current server.\n" "\n" "Are you sure you want to disconnect?" msgstr "" -#: Client/core/CMainMenu.cpp:1197 +#: Client/core/CMainMenu.cpp:1193 msgid "DISCONNECT WARNING" msgstr "" @@ -1895,102 +1962,102 @@ msgstr "" msgid "%s module is incorrect!" msgstr "" -#: Client/core/CCore.cpp:1275 +#: Client/core/CCore.cpp:1279 msgid "Error executing URL" msgstr "" -#: Client/core/CCore.cpp:1287 +#: Client/core/CCore.cpp:1291 #, c-format msgid "Error running mod specified in command line ('%s')" msgstr "" #. m_pCommands->Add ( "e", CCommandFuncs::Editor ); #. m_pCommands->Add ( "clear", CCommandFuncs::Clear ); -#: Client/core/CCore.cpp:1389 +#: Client/core/CCore.cpp:1393 msgid "this help screen" msgstr "" -#: Client/core/CCore.cpp:1390 Client/core/CCore.cpp:1391 +#: Client/core/CCore.cpp:1394 Client/core/CCore.cpp:1395 msgid "exits the application" msgstr "" -#: Client/core/CCore.cpp:1392 +#: Client/core/CCore.cpp:1396 msgid "shows the version" msgstr "" -#: Client/core/CCore.cpp:1393 +#: Client/core/CCore.cpp:1397 msgid "shows the time" msgstr "" -#: Client/core/CCore.cpp:1394 +#: Client/core/CCore.cpp:1398 msgid "shows the hud" msgstr "" -#: Client/core/CCore.cpp:1395 +#: Client/core/CCore.cpp:1399 msgid "shows all the binds" msgstr "" -#: Client/core/CCore.cpp:1396 +#: Client/core/CCore.cpp:1400 msgid "shows your serial" msgstr "" -#: Client/core/CCore.cpp:1405 +#: Client/core/CCore.cpp:1409 msgid "connects to a server (host port nick pass)" msgstr "" -#: Client/core/CCore.cpp:1406 +#: Client/core/CCore.cpp:1410 msgid "connects to a previous server" msgstr "" -#: Client/core/CCore.cpp:1407 +#: Client/core/CCore.cpp:1411 msgid "binds a key (key control)" msgstr "" -#: Client/core/CCore.cpp:1408 +#: Client/core/CCore.cpp:1412 msgid "unbinds a key (key)" msgstr "" -#: Client/core/CCore.cpp:1409 +#: Client/core/CCore.cpp:1413 msgid "copies the default gta controls" msgstr "" -#: Client/core/CCore.cpp:1410 +#: Client/core/CCore.cpp:1414 msgid "outputs a screenshot" msgstr "" -#: Client/core/CCore.cpp:1411 +#: Client/core/CCore.cpp:1415 msgid "immediately saves the config" msgstr "" -#: Client/core/CCore.cpp:1413 +#: Client/core/CCore.cpp:1417 msgid "clears the debug view" msgstr "" -#: Client/core/CCore.cpp:1414 +#: Client/core/CCore.cpp:1418 msgid "scrolls the chatbox upwards" msgstr "" -#: Client/core/CCore.cpp:1415 +#: Client/core/CCore.cpp:1419 msgid "scrolls the chatbox downwards" msgstr "" -#: Client/core/CCore.cpp:1416 +#: Client/core/CCore.cpp:1420 msgid "scrolls the debug view upwards" msgstr "" -#: Client/core/CCore.cpp:1417 +#: Client/core/CCore.cpp:1421 msgid "scrolls the debug view downwards" msgstr "" -#: Client/core/CCore.cpp:1420 +#: Client/core/CCore.cpp:1424 msgid "shows the memory statistics" msgstr "" -#: Client/core/CCore.cpp:1421 +#: Client/core/CCore.cpp:1425 msgid "shows the frame timing graph" msgstr "" -#: Client/core/CCore.cpp:1425 +#: Client/core/CCore.cpp:1429 msgid "for developers: reload news" msgstr "" @@ -2032,7 +2099,7 @@ msgid "Advanced" msgstr "" #: Client/core/CSettings.cpp:147 Client/core/CSettings.cpp:338 -#: Client/core/CSettings.cpp:617 Client/core/CSettings.cpp:889 +#: Client/core/CSettings.cpp:633 Client/core/CSettings.cpp:902 msgid "Load defaults" msgstr "" @@ -2149,606 +2216,623 @@ msgstr "" msgid "Map rendering options" msgstr "" -#: Client/core/CSettings.cpp:419 Client/core/CSettings.cpp:628 +#: Client/core/CSettings.cpp:421 msgid "Opacity:" msgstr "" +#: Client/core/CSettings.cpp:441 +msgid "Image resolution:" +msgstr "" + +#: Client/core/CSettings.cpp:448 +msgid "1024 x 1024 (Default)" +msgstr "" + +#. index 0 +#: Client/core/CSettings.cpp:449 +msgid "2048 x 2048" +msgstr "" + #. * #. * Audio tab #. * -#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:448 +#: Client/core/CSettings.cpp:455 Client/core/CSettings.cpp:464 msgid "Master volume:" msgstr "" -#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:467 +#: Client/core/CSettings.cpp:455 Client/core/CSettings.cpp:483 msgid "Radio volume:" msgstr "" -#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:486 +#: Client/core/CSettings.cpp:455 Client/core/CSettings.cpp:502 msgid "SFX volume:" msgstr "" -#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:505 +#: Client/core/CSettings.cpp:455 Client/core/CSettings.cpp:521 msgid "MTA volume:" msgstr "" -#: Client/core/CSettings.cpp:440 Client/core/CSettings.cpp:524 +#: Client/core/CSettings.cpp:456 Client/core/CSettings.cpp:540 msgid "Voice volume:" msgstr "" -#: Client/core/CSettings.cpp:440 Client/core/CSettings.cpp:565 +#: Client/core/CSettings.cpp:456 Client/core/CSettings.cpp:581 msgid "Play mode:" msgstr "" -#: Client/core/CSettings.cpp:543 +#: Client/core/CSettings.cpp:559 msgid "Radio options" msgstr "" -#: Client/core/CSettings.cpp:549 +#: Client/core/CSettings.cpp:565 msgid "Radio Equalizer" msgstr "" -#: Client/core/CSettings.cpp:554 +#: Client/core/CSettings.cpp:570 msgid "Radio Auto-tune" msgstr "" -#: Client/core/CSettings.cpp:559 +#: Client/core/CSettings.cpp:575 msgid "Usertrack options" msgstr "" -#: Client/core/CSettings.cpp:573 Client/core/CSettings.cpp:3087 +#: Client/core/CSettings.cpp:589 Client/core/CSettings.cpp:3112 msgid "Radio" msgstr "" -#: Client/core/CSettings.cpp:574 Client/core/CSettings.cpp:3089 +#: Client/core/CSettings.cpp:590 Client/core/CSettings.cpp:3114 msgid "Random" msgstr "" -#: Client/core/CSettings.cpp:575 Client/core/CSettings.cpp:3091 +#: Client/core/CSettings.cpp:591 Client/core/CSettings.cpp:3116 msgid "Sequential" msgstr "" -#: Client/core/CSettings.cpp:578 +#: Client/core/CSettings.cpp:594 msgid "Automatic Media Scan" msgstr "" -#: Client/core/CSettings.cpp:585 +#: Client/core/CSettings.cpp:601 msgid "Mute options" msgstr "" -#: Client/core/CSettings.cpp:591 +#: Client/core/CSettings.cpp:607 msgid "Mute All sounds when minimized" msgstr "" -#: Client/core/CSettings.cpp:596 +#: Client/core/CSettings.cpp:612 msgid "Mute Radio sounds when minimized" msgstr "" -#: Client/core/CSettings.cpp:601 +#: Client/core/CSettings.cpp:617 msgid "Mute SFX sounds when minimized" msgstr "" -#: Client/core/CSettings.cpp:606 +#: Client/core/CSettings.cpp:622 msgid "Mute MTA sounds when minimized" msgstr "" -#: Client/core/CSettings.cpp:611 +#: Client/core/CSettings.cpp:627 msgid "Mute Voice sounds when minimized" msgstr "" #. * #. * Video tab #. * -#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:636 +#: Client/core/CSettings.cpp:643 Client/core/CSettings.cpp:649 msgid "Resolution:" msgstr "" -#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:683 +#: Client/core/CSettings.cpp:643 Client/core/CSettings.cpp:696 msgid "FOV:" msgstr "" -#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:699 +#: Client/core/CSettings.cpp:643 Client/core/CSettings.cpp:712 msgid "Draw Distance:" msgstr "" -#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:717 +#: Client/core/CSettings.cpp:643 Client/core/CSettings.cpp:730 msgid "Brightness:" msgstr "" -#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:735 +#: Client/core/CSettings.cpp:643 Client/core/CSettings.cpp:748 msgid "FX Quality:" msgstr "" -#: Client/core/CSettings.cpp:628 Client/core/CSettings.cpp:749 +#: Client/core/CSettings.cpp:644 Client/core/CSettings.cpp:762 msgid "Anisotropic filtering:" msgstr "" -#: Client/core/CSettings.cpp:628 Client/core/CSettings.cpp:776 +#: Client/core/CSettings.cpp:644 Client/core/CSettings.cpp:789 msgid "Anti-aliasing:" msgstr "" -#: Client/core/CSettings.cpp:628 Client/core/CSettings.cpp:790 +#: Client/core/CSettings.cpp:644 Client/core/CSettings.cpp:803 msgid "Aspect Ratio:" msgstr "" -#: Client/core/CSettings.cpp:648 +#: Client/core/CSettings.cpp:661 msgid "Windowed" msgstr "" -#: Client/core/CSettings.cpp:654 +#: Client/core/CSettings.cpp:667 msgid "DPI aware" msgstr "" -#: Client/core/CSettings.cpp:669 Client/core/CSettings.cpp:1613 +#: Client/core/CSettings.cpp:682 Client/core/CSettings.cpp:1631 msgid "Standard" msgstr "" -#: Client/core/CSettings.cpp:671 Client/core/CSettings.cpp:1617 +#: Client/core/CSettings.cpp:684 Client/core/CSettings.cpp:1635 msgid "Borderless keep res" msgstr "" -#: Client/core/CSettings.cpp:675 +#: Client/core/CSettings.cpp:688 msgid "Mip Mapping" msgstr "" -#: Client/core/CSettings.cpp:743 Client/core/CSettings.cpp:1517 +#: Client/core/CSettings.cpp:756 Client/core/CSettings.cpp:1535 msgid "Low" msgstr "" -#: Client/core/CSettings.cpp:744 Client/core/CSettings.cpp:1519 +#: Client/core/CSettings.cpp:757 Client/core/CSettings.cpp:1537 msgid "Medium" msgstr "" -#: Client/core/CSettings.cpp:745 Client/core/CSettings.cpp:1086 -#: Client/core/CSettings.cpp:1521 Client/core/CSettings.cpp:3145 +#: Client/core/CSettings.cpp:758 Client/core/CSettings.cpp:1104 +#: Client/core/CSettings.cpp:1539 Client/core/CSettings.cpp:3170 msgid "High" msgstr "" -#: Client/core/CSettings.cpp:746 Client/core/CSettings.cpp:1523 +#: Client/core/CSettings.cpp:759 Client/core/CSettings.cpp:1541 msgid "Very high" msgstr "" -#: Client/core/CSettings.cpp:761 Client/core/CSettings.cpp:784 -#: Client/core/CSettings.cpp:1017 Client/core/CSettings.cpp:1071 -#: Client/core/CSettings.cpp:1201 Client/core/CSettings.cpp:1527 -#: Client/core/CSettings.cpp:3152 Client/core/CSettings.cpp:3184 -#: Client/core/CSettings.cpp:3206 Client/core/CSettings.cpp:4234 +#: Client/core/CSettings.cpp:774 Client/core/CSettings.cpp:797 +#: Client/core/CSettings.cpp:1035 Client/core/CSettings.cpp:1089 +#: Client/core/CSettings.cpp:1219 Client/core/CSettings.cpp:1545 +#: Client/core/CSettings.cpp:3177 Client/core/CSettings.cpp:3209 +#: Client/core/CSettings.cpp:3231 Client/core/CSettings.cpp:4272 msgid "Off" msgstr "" -#: Client/core/CSettings.cpp:785 Client/core/CSettings.cpp:1529 +#: Client/core/CSettings.cpp:798 Client/core/CSettings.cpp:1547 msgid "1x" msgstr "" -#: Client/core/CSettings.cpp:786 Client/core/CSettings.cpp:1531 +#: Client/core/CSettings.cpp:799 Client/core/CSettings.cpp:1549 msgid "2x" msgstr "" -#: Client/core/CSettings.cpp:787 Client/core/CSettings.cpp:1533 +#: Client/core/CSettings.cpp:800 Client/core/CSettings.cpp:1551 msgid "3x" msgstr "" -#: Client/core/CSettings.cpp:800 Client/core/CSettings.cpp:1019 -#: Client/core/CSettings.cpp:1539 Client/core/CSettings.cpp:3154 +#: Client/core/CSettings.cpp:813 Client/core/CSettings.cpp:1037 +#: Client/core/CSettings.cpp:1557 Client/core/CSettings.cpp:3179 msgid "Auto" msgstr "" -#: Client/core/CSettings.cpp:801 Client/core/CSettings.cpp:1541 +#: Client/core/CSettings.cpp:814 Client/core/CSettings.cpp:1559 msgid "4:3" msgstr "" -#: Client/core/CSettings.cpp:802 Client/core/CSettings.cpp:1543 +#: Client/core/CSettings.cpp:815 Client/core/CSettings.cpp:1561 msgid "16:10" msgstr "" -#: Client/core/CSettings.cpp:803 Client/core/CSettings.cpp:1545 +#: Client/core/CSettings.cpp:816 Client/core/CSettings.cpp:1563 msgid "16:9" msgstr "" -#: Client/core/CSettings.cpp:806 +#: Client/core/CSettings.cpp:819 msgid "HUD Match Aspect Ratio" msgstr "" -#: Client/core/CSettings.cpp:812 +#: Client/core/CSettings.cpp:825 msgid "Volumetric Shadows" msgstr "" -#: Client/core/CSettings.cpp:816 +#: Client/core/CSettings.cpp:829 msgid "Grass effect" msgstr "" -#: Client/core/CSettings.cpp:820 +#: Client/core/CSettings.cpp:833 msgid "Heat haze" msgstr "" -#: Client/core/CSettings.cpp:824 +#: Client/core/CSettings.cpp:837 msgid "Tyre Smoke etc" msgstr "" -#: Client/core/CSettings.cpp:828 +#: Client/core/CSettings.cpp:841 msgid "Dynamic ped shadows" msgstr "" -#: Client/core/CSettings.cpp:832 +#: Client/core/CSettings.cpp:845 msgid "Motion blur" msgstr "" -#: Client/core/CSettings.cpp:837 +#: Client/core/CSettings.cpp:849 +msgid "Corona rain reflections" +msgstr "" + +#: Client/core/CSettings.cpp:854 msgid "Full Screen Minimize" msgstr "" -#: Client/core/CSettings.cpp:849 +#: Client/core/CSettings.cpp:866 msgid "Enable Device Selection Dialog" msgstr "" -#: Client/core/CSettings.cpp:861 +#: Client/core/CSettings.cpp:878 msgid "Show unsafe resolutions" msgstr "" -#: Client/core/CSettings.cpp:873 +#: Client/core/CSettings.cpp:890 msgid "Render vehicles always in high detail" msgstr "" -#: Client/core/CSettings.cpp:877 +#: Client/core/CSettings.cpp:894 msgid "Render peds always in high detail" msgstr "" -#: Client/core/CSettings.cpp:881 -msgid "Corona rain reflections" -msgstr "" - -#: Client/core/CSettings.cpp:910 +#: Client/core/CSettings.cpp:923 msgid "Enable remote websites" msgstr "" -#: Client/core/CSettings.cpp:915 +#: Client/core/CSettings.cpp:928 msgid "Enable Javascript on remote websites" msgstr "" -#: Client/core/CSettings.cpp:920 +#: Client/core/CSettings.cpp:933 +msgid "Enable GPU rendering" +msgstr "" + +#: Client/core/CSettings.cpp:937 msgid "Custom blacklist" msgstr "" -#: Client/core/CSettings.cpp:931 Client/core/CSettings.cpp:966 +#: Client/core/CSettings.cpp:948 Client/core/CSettings.cpp:983 msgid "Enter a domain e.g. google.com" msgstr "" -#: Client/core/CSettings.cpp:939 +#: Client/core/CSettings.cpp:956 msgid "Block" msgstr "" -#: Client/core/CSettings.cpp:947 Client/core/CSettings.cpp:982 +#: Client/core/CSettings.cpp:964 Client/core/CSettings.cpp:999 msgid "Domain" msgstr "" -#: Client/core/CSettings.cpp:949 Client/core/CSettings.cpp:984 +#: Client/core/CSettings.cpp:966 Client/core/CSettings.cpp:1001 msgid "Remove domain" msgstr "" #. Reset vecTemp -#: Client/core/CSettings.cpp:955 +#: Client/core/CSettings.cpp:972 msgid "Custom whitelist" msgstr "" #. Misc section label -#: Client/core/CSettings.cpp:997 +#: Client/core/CSettings.cpp:1014 msgid "Misc" msgstr "" #. Fast clothes loading -#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1010 -#: Client/core/CSettings.cpp:4803 +#: Client/core/CSettings.cpp:1020 Client/core/CSettings.cpp:1028 +#: Client/core/CSettings.cpp:4841 msgid "Fast CJ clothes loading:" msgstr "" #. Browser scan speed -#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1024 -#: Client/core/CSettings.cpp:4805 +#: Client/core/CSettings.cpp:1020 Client/core/CSettings.cpp:1042 +#: Client/core/CSettings.cpp:4843 msgid "Browser speed:" msgstr "" #. Single download -#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1038 -#: Client/core/CSettings.cpp:4807 +#: Client/core/CSettings.cpp:1020 Client/core/CSettings.cpp:1056 +#: Client/core/CSettings.cpp:4845 msgid "Single connection:" msgstr "" #. Packet tag -#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1051 -#: Client/core/CSettings.cpp:4809 +#: Client/core/CSettings.cpp:1020 Client/core/CSettings.cpp:1069 +#: Client/core/CSettings.cpp:4847 msgid "Packet tag:" msgstr "" #. Progress animation -#: Client/core/CSettings.cpp:1004 Client/core/CSettings.cpp:1064 -#: Client/core/CSettings.cpp:4811 +#: Client/core/CSettings.cpp:1021 Client/core/CSettings.cpp:1082 +#: Client/core/CSettings.cpp:4849 msgid "Progress animation:" msgstr "" #. Process priority -#: Client/core/CSettings.cpp:1004 Client/core/CSettings.cpp:1077 -#: Client/core/CSettings.cpp:4801 +#: Client/core/CSettings.cpp:1021 Client/core/CSettings.cpp:1095 +#: Client/core/CSettings.cpp:4839 msgid "Process priority:" msgstr "" #. Debug setting -#: Client/core/CSettings.cpp:1004 Client/core/CSettings.cpp:1091 -#: Client/core/CSettings.cpp:4813 +#: Client/core/CSettings.cpp:1021 Client/core/CSettings.cpp:1109 +#: Client/core/CSettings.cpp:4851 msgid "Debug setting:" msgstr "" #. Streaming memory -#: Client/core/CSettings.cpp:1005 Client/core/CSettings.cpp:1114 -#: Client/core/CSettings.cpp:4815 +#: Client/core/CSettings.cpp:1022 Client/core/CSettings.cpp:1132 +#: Client/core/CSettings.cpp:4853 msgid "Streaming memory:" msgstr "" #. Update build type -#: Client/core/CSettings.cpp:1005 Client/core/CSettings.cpp:1215 +#: Client/core/CSettings.cpp:1022 Client/core/CSettings.cpp:1233 msgid "Update build type:" msgstr "" #. UpdateAutoInstall -#: Client/core/CSettings.cpp:1005 Client/core/CSettings.cpp:1194 +#: Client/core/CSettings.cpp:1022 Client/core/CSettings.cpp:1212 msgid "Install important updates:" msgstr "" -#: Client/core/CSettings.cpp:1018 Client/core/CSettings.cpp:1046 -#: Client/core/CSettings.cpp:1059 Client/core/CSettings.cpp:3156 -#: Client/core/CSettings.cpp:3172 Client/core/CSettings.cpp:3179 +#: Client/core/CSettings.cpp:1036 Client/core/CSettings.cpp:1064 +#: Client/core/CSettings.cpp:1077 Client/core/CSettings.cpp:3181 +#: Client/core/CSettings.cpp:3197 Client/core/CSettings.cpp:3204 msgid "On" msgstr "" -#: Client/core/CSettings.cpp:1031 Client/core/CSettings.cpp:3161 +#: Client/core/CSettings.cpp:1049 Client/core/CSettings.cpp:3186 msgid "Very slow" msgstr "" -#: Client/core/CSettings.cpp:1032 Client/core/CSettings.cpp:1045 -#: Client/core/CSettings.cpp:1058 Client/core/CSettings.cpp:1072 -#: Client/core/CSettings.cpp:1098 Client/core/CSettings.cpp:1110 -#: Client/core/CSettings.cpp:1202 Client/core/CSettings.cpp:1222 -#: Client/core/CSettings.cpp:3163 Client/core/CSettings.cpp:3170 -#: Client/core/CSettings.cpp:3177 Client/core/CSettings.cpp:3186 -#: Client/core/CSettings.cpp:3199 +#: Client/core/CSettings.cpp:1050 Client/core/CSettings.cpp:1063 +#: Client/core/CSettings.cpp:1076 Client/core/CSettings.cpp:1090 +#: Client/core/CSettings.cpp:1116 Client/core/CSettings.cpp:1128 +#: Client/core/CSettings.cpp:1220 Client/core/CSettings.cpp:1240 +#: Client/core/CSettings.cpp:3188 Client/core/CSettings.cpp:3195 +#: Client/core/CSettings.cpp:3202 Client/core/CSettings.cpp:3211 +#: Client/core/CSettings.cpp:3224 msgid "Default" msgstr "" -#: Client/core/CSettings.cpp:1033 Client/core/CSettings.cpp:3165 +#: Client/core/CSettings.cpp:1051 Client/core/CSettings.cpp:3190 msgid "Fast" msgstr "" -#: Client/core/CSettings.cpp:1084 Client/core/CSettings.cpp:3141 +#: Client/core/CSettings.cpp:1102 Client/core/CSettings.cpp:3166 msgid "Normal" msgstr "" -#: Client/core/CSettings.cpp:1085 Client/core/CSettings.cpp:3143 +#: Client/core/CSettings.cpp:1103 Client/core/CSettings.cpp:3168 msgid "Above normal" msgstr "" -#: Client/core/CSettings.cpp:1121 +#: Client/core/CSettings.cpp:1139 msgid "Min" msgstr "" -#: Client/core/CSettings.cpp:1134 +#: Client/core/CSettings.cpp:1152 msgid "Max" msgstr "" #. Windows 8 compatibility -#: Client/core/CSettings.cpp:1141 +#: Client/core/CSettings.cpp:1159 msgid "Windows 8 compatibility:" msgstr "" -#: Client/core/CSettings.cpp:1145 +#: Client/core/CSettings.cpp:1163 msgid "16-bit color" msgstr "" -#: Client/core/CSettings.cpp:1150 +#: Client/core/CSettings.cpp:1168 msgid "Mouse fix" msgstr "" #. Cache path info -#: Client/core/CSettings.cpp:1168 +#: Client/core/CSettings.cpp:1186 msgid "Client resource files:" msgstr "" -#: Client/core/CSettings.cpp:1172 +#: Client/core/CSettings.cpp:1190 msgid "Show in Explorer" msgstr "" #. Auto updater section label -#: Client/core/CSettings.cpp:1187 Client/core/CSettings.cpp:1190 +#: Client/core/CSettings.cpp:1205 Client/core/CSettings.cpp:1208 msgid "Auto updater" msgstr "" #. Check for updates -#: Client/core/CSettings.cpp:1228 +#: Client/core/CSettings.cpp:1246 msgid "Check for update now" msgstr "" -#: Client/core/CSettings.cpp:1382 +#: Client/core/CSettings.cpp:1400 msgid "Some settings will be changed when you next start MTA" msgstr "" -#: Client/core/CSettings.cpp:1383 +#: Client/core/CSettings.cpp:1401 msgid "" "\n" "\n" "Do you want to restart now?" msgstr "" -#: Client/core/CSettings.cpp:1386 +#: Client/core/CSettings.cpp:1404 msgid "RESTART REQUIRED" msgstr "" -#: Client/core/CSettings.cpp:1406 +#: Client/core/CSettings.cpp:1424 msgid "Some settings will be changed when you disconnect the current server" msgstr "" -#: Client/core/CSettings.cpp:1407 +#: Client/core/CSettings.cpp:1425 msgid "" "\n" "\n" "Do you want to disconnect now?" msgstr "" -#: Client/core/CSettings.cpp:1410 +#: Client/core/CSettings.cpp:1428 msgid "DISCONNECT REQUIRED" msgstr "" #. Update the joystick name -#: Client/core/CSettings.cpp:1737 +#: Client/core/CSettings.cpp:1760 msgid "Joypad not detected - Check connections and restart game" msgstr "" -#: Client/core/CSettings.cpp:1932 +#: Client/core/CSettings.cpp:1957 msgid "Binding axis" msgstr "" -#: Client/core/CSettings.cpp:1932 +#: Client/core/CSettings.cpp:1957 msgid "Move an axis to bind, or escape to clear" msgstr "" -#: Client/core/CSettings.cpp:2009 +#: Client/core/CSettings.cpp:2034 msgid "Language:" msgstr "" -#: Client/core/CSettings.cpp:2009 +#: Client/core/CSettings.cpp:2034 msgid "Skin:" msgstr "" -#: Client/core/CSettings.cpp:2009 +#: Client/core/CSettings.cpp:2034 msgid "Presets:" msgstr "" -#: Client/core/CSettings.cpp:2058 +#: Client/core/CSettings.cpp:2083 msgid "Chat" msgstr "" -#: Client/core/CSettings.cpp:2075 +#: Client/core/CSettings.cpp:2100 msgid "Load" msgstr "" -#: Client/core/CSettings.cpp:2087 +#: Client/core/CSettings.cpp:2112 msgid "Colors" msgstr "" -#: Client/core/CSettings.cpp:2088 +#: Client/core/CSettings.cpp:2113 msgid "Layout" msgstr "" -#: Client/core/CSettings.cpp:2089 Client/core/CSettings.cpp:2335 +#: Client/core/CSettings.cpp:2114 Client/core/CSettings.cpp:2360 msgid "Options" msgstr "" -#: Client/core/CSettings.cpp:2095 +#: Client/core/CSettings.cpp:2120 msgid "Chat Background" msgstr "" -#: Client/core/CSettings.cpp:2095 +#: Client/core/CSettings.cpp:2120 msgid "Chat Text" msgstr "" -#: Client/core/CSettings.cpp:2095 +#: Client/core/CSettings.cpp:2120 msgid "Input Background" msgstr "" -#: Client/core/CSettings.cpp:2095 +#: Client/core/CSettings.cpp:2120 msgid "Input Text" msgstr "" -#: Client/core/CSettings.cpp:2118 +#: Client/core/CSettings.cpp:2143 msgid "Lines:" msgstr "" -#: Client/core/CSettings.cpp:2118 +#: Client/core/CSettings.cpp:2143 msgid "Scale:" msgstr "" -#: Client/core/CSettings.cpp:2118 +#: Client/core/CSettings.cpp:2143 msgid "Width:" msgstr "" -#: Client/core/CSettings.cpp:2121 +#: Client/core/CSettings.cpp:2146 msgid "Size" msgstr "" -#: Client/core/CSettings.cpp:2170 +#: Client/core/CSettings.cpp:2195 msgid "after" msgstr "" -#: Client/core/CSettings.cpp:2170 +#: Client/core/CSettings.cpp:2195 msgid "for" msgstr "" -#: Client/core/CSettings.cpp:2170 +#: Client/core/CSettings.cpp:2195 msgid "sec" msgstr "" -#: Client/core/CSettings.cpp:2173 +#: Client/core/CSettings.cpp:2198 msgid "Fading" msgstr "" -#: Client/core/CSettings.cpp:2179 +#: Client/core/CSettings.cpp:2204 msgid "Fade out old lines" msgstr "" -#: Client/core/CSettings.cpp:2219 +#: Client/core/CSettings.cpp:2244 msgid "Horizontal:" msgstr "" -#: Client/core/CSettings.cpp:2219 +#: Client/core/CSettings.cpp:2244 msgid "Vertical:" msgstr "" -#: Client/core/CSettings.cpp:2219 +#: Client/core/CSettings.cpp:2244 msgid "Text-Align:" msgstr "" -#: Client/core/CSettings.cpp:2219 +#: Client/core/CSettings.cpp:2244 msgid "X-Offset:" msgstr "" -#: Client/core/CSettings.cpp:2220 +#: Client/core/CSettings.cpp:2245 msgid "Y-Offset:" msgstr "" -#: Client/core/CSettings.cpp:2226 +#: Client/core/CSettings.cpp:2251 msgid "Position" msgstr "" -#: Client/core/CSettings.cpp:2241 Client/core/CSettings.cpp:2255 +#: Client/core/CSettings.cpp:2266 Client/core/CSettings.cpp:2280 msgid "Center" msgstr "" -#: Client/core/CSettings.cpp:2254 +#: Client/core/CSettings.cpp:2279 msgid "Top" msgstr "" -#: Client/core/CSettings.cpp:2256 +#: Client/core/CSettings.cpp:2281 msgid "Bottom" msgstr "" -#: Client/core/CSettings.cpp:2304 +#: Client/core/CSettings.cpp:2329 msgid "Font" msgstr "" -#: Client/core/CSettings.cpp:2341 +#: Client/core/CSettings.cpp:2366 msgid "Hide background when not typing" msgstr "" -#: Client/core/CSettings.cpp:2346 +#: Client/core/CSettings.cpp:2371 msgid "Nickname completion using the \"Tab\" key" msgstr "" -#: Client/core/CSettings.cpp:2351 +#: Client/core/CSettings.cpp:2376 msgid "Allow server to flash the window" msgstr "" -#: Client/core/CSettings.cpp:2356 +#: Client/core/CSettings.cpp:2381 msgid "Allow tray balloon notifications" msgstr "" -#: Client/core/CSettings.cpp:2361 +#: Client/core/CSettings.cpp:2386 msgid "Chat text black/white outline" msgstr "" @@ -2756,85 +2840,85 @@ msgstr "" #. SString strText = SString::Printf ( "Press a key to bind to '%s'", pItemBind->GetText ().c_str () ); #. Create a messagebox to notify the user #. sSString strText = SString::Printf ( "Press a key to bind to '%s'", pItemBind->GetText ().c_str () ); -#: Client/core/CSettings.cpp:2610 Client/core/CSettings.cpp:2617 +#: Client/core/CSettings.cpp:2635 Client/core/CSettings.cpp:2642 msgid "Press a key to bind, or escape to clear" msgstr "" -#: Client/core/CSettings.cpp:2611 +#: Client/core/CSettings.cpp:2636 msgid "Binding a primary key" msgstr "" -#: Client/core/CSettings.cpp:2618 +#: Client/core/CSettings.cpp:2643 msgid "Binding a secondary key" msgstr "" -#: Client/core/CSettings.cpp:2694 +#: Client/core/CSettings.cpp:2719 msgid "GTA GAME CONTROLS" msgstr "" -#: Client/core/CSettings.cpp:2696 +#: Client/core/CSettings.cpp:2721 msgid "MULTIPLAYER CONTROLS" msgstr "" -#: Client/core/CSettings.cpp:2941 Client/core/CSettings.cpp:4764 +#: Client/core/CSettings.cpp:2966 Client/core/CSettings.cpp:4802 msgid "Your nickname contains invalid characters!" msgstr "" -#: Client/core/CSettings.cpp:3778 +#: Client/core/CSettings.cpp:3816 msgid "Red:" msgstr "" -#: Client/core/CSettings.cpp:3778 +#: Client/core/CSettings.cpp:3816 msgid "Green:" msgstr "" -#: Client/core/CSettings.cpp:3778 +#: Client/core/CSettings.cpp:3816 msgid "Blue:" msgstr "" -#: Client/core/CSettings.cpp:3778 +#: Client/core/CSettings.cpp:3816 msgid "Transparency:" msgstr "" -#: Client/core/CSettings.cpp:3781 +#: Client/core/CSettings.cpp:3819 msgid "Color" msgstr "" -#: Client/core/CSettings.cpp:3858 +#: Client/core/CSettings.cpp:3896 msgid "Preview" msgstr "" -#: Client/core/CSettings.cpp:4166 +#: Client/core/CSettings.cpp:4204 msgid "Please disconnect before changing language" msgstr "" -#: Client/core/CSettings.cpp:4194 +#: Client/core/CSettings.cpp:4232 msgid "Please disconnect before changing skin" msgstr "" -#: Client/core/CSettings.cpp:4482 +#: Client/core/CSettings.cpp:4520 msgid "" "Volmetric shadows can cause some systems to slow down.\n" "\n" "Are you sure you want to enable them?" msgstr "" -#: Client/core/CSettings.cpp:4486 +#: Client/core/CSettings.cpp:4524 msgid "PERFORMANCE WARNING" msgstr "" -#: Client/core/CSettings.cpp:4506 +#: Client/core/CSettings.cpp:4544 msgid "" "Screen upload is required by some servers for anti-cheat purposes.\n" "\n" "(The chat box and GUI is excluded from the upload)\n" msgstr "" -#: Client/core/CSettings.cpp:4508 +#: Client/core/CSettings.cpp:4546 msgid "SCREEN UPLOAD INFORMATION" msgstr "" -#: Client/core/CSettings.cpp:4523 +#: Client/core/CSettings.cpp:4561 msgid "" "Some scripts may play sounds, such as radio, from the internet.\n" "\n" @@ -2842,11 +2926,11 @@ msgid "" "bandwidth consumption.\n" msgstr "" -#: Client/core/CSettings.cpp:4526 +#: Client/core/CSettings.cpp:4564 msgid "EXTERNAL SOUNDS" msgstr "" -#: Client/core/CSettings.cpp:4555 +#: Client/core/CSettings.cpp:4593 msgid "" "It seems that you have the Rich Presence connection option enabled.\n" "Do you want to allow servers to share their data?\n" @@ -2854,11 +2938,11 @@ msgid "" "This includes yours unique ID identifier." msgstr "" -#: Client/core/CSettings.cpp:4560 +#: Client/core/CSettings.cpp:4598 msgid "CONSENT TO ALLOW DATA SHARING" msgstr "" -#: Client/core/CSettings.cpp:4584 +#: Client/core/CSettings.cpp:4622 msgid "" "Some files in your GTA:SA data directory are customized.\n" "MTA will only use these modified files if this check box is ticked.\n" @@ -2868,7 +2952,7 @@ msgid "" "Are you sure you want to use them?" msgstr "" -#: Client/core/CSettings.cpp:4633 +#: Client/core/CSettings.cpp:4671 msgid "" "Enabling DPI awareness is an experimental feature and\n" "we only recommend it when you play MTA:SA on a scaled monitor.\n" @@ -2877,77 +2961,77 @@ msgid "" "Are you sure you want to enable this option?" msgstr "" -#: Client/core/CSettings.cpp:4639 +#: Client/core/CSettings.cpp:4677 msgid "EXPERIMENTAL FEATURE" msgstr "" -#: Client/core/CSettings.cpp:4782 +#: Client/core/CSettings.cpp:4820 msgid "Please enter a nickname" msgstr "" -#: Client/core/CSettings.cpp:4783 +#: Client/core/CSettings.cpp:4821 msgid "" "Please enter a nickname to be used ingame. \n" "This will be your name when you connect to and play in a server" msgstr "" -#: Client/core/CSettings.cpp:4801 +#: Client/core/CSettings.cpp:4839 msgid "Very experimental feature." msgstr "" -#: Client/core/CSettings.cpp:4803 +#: Client/core/CSettings.cpp:4841 msgid "Stops stalls with CJ variations (Uses 65MB more RAM)" msgstr "" -#: Client/core/CSettings.cpp:4805 +#: Client/core/CSettings.cpp:4843 msgid "Older routers may require a slower scan speed." msgstr "" -#: Client/core/CSettings.cpp:4807 +#: Client/core/CSettings.cpp:4845 msgid "Switch on to use only one connection when downloading." msgstr "" -#: Client/core/CSettings.cpp:4809 +#: Client/core/CSettings.cpp:4847 msgid "Tag network packets to help ISPs identify MTA traffic." msgstr "" -#: Client/core/CSettings.cpp:4811 +#: Client/core/CSettings.cpp:4849 msgid "Spinning circle animation at the bottom of the screen" msgstr "" -#: Client/core/CSettings.cpp:4813 +#: Client/core/CSettings.cpp:4851 msgid "Select default always. (This setting is not saved)" msgstr "" -#: Client/core/CSettings.cpp:4815 +#: Client/core/CSettings.cpp:4853 msgid "Maximum is usually best" msgstr "" -#: Client/core/CSettings.cpp:4817 Client/core/CSettings.cpp:4819 +#: Client/core/CSettings.cpp:4855 Client/core/CSettings.cpp:4857 msgid "Auto updater:" msgstr "" -#: Client/core/CSettings.cpp:4817 +#: Client/core/CSettings.cpp:4855 msgid "Select default unless you like filling out bug reports." msgstr "" -#: Client/core/CSettings.cpp:4819 +#: Client/core/CSettings.cpp:4857 msgid "Select default to automatically install important updates." msgstr "" -#: Client/core/CSettings.cpp:4821 +#: Client/core/CSettings.cpp:4859 msgid "16-bit color:" msgstr "" -#: Client/core/CSettings.cpp:4821 +#: Client/core/CSettings.cpp:4859 msgid "Enable 16 bit color modes - Requires MTA restart" msgstr "" -#: Client/core/CSettings.cpp:4823 +#: Client/core/CSettings.cpp:4861 msgid "Mouse fix:" msgstr "" -#: Client/core/CSettings.cpp:4823 +#: Client/core/CSettings.cpp:4861 msgid "Mouse movement fix - May need PC restart" msgstr "" @@ -2970,17 +3054,22 @@ msgstr "" msgid "Connecting to %s:%u ..." msgstr "" +#: Client/core/CConnectManager.cpp:149 +#, c-format +msgid "Reconnecting to %s:%u ..." +msgstr "" + #. Failed loading the mod -#: Client/core/CConnectManager.cpp:403 +#: Client/core/CConnectManager.cpp:405 #, c-format msgid "No such mod installed (%s)" msgstr "" -#: Client/core/CConnectManager.cpp:411 +#: Client/core/CConnectManager.cpp:413 msgid "Bad server response (2)" msgstr "" -#: Client/core/CConnectManager.cpp:421 +#: Client/core/CConnectManager.cpp:423 msgid "Bad server response (1)" msgstr "" @@ -3064,12 +3153,12 @@ msgid "Start search" msgstr "" #: Client/core/ServerBrowser/CServerBrowser.cpp:299 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1704 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1680 msgid "Search players..." msgstr "" #: Client/core/ServerBrowser/CServerBrowser.cpp:422 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1702 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1678 msgid "Search servers..." msgstr "" @@ -3129,25 +3218,25 @@ msgstr "" msgid "Loading..." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1247 -#: Client/core/ServerBrowser/CServerBrowser.cpp:2189 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1223 +#: Client/core/ServerBrowser/CServerBrowser.cpp:2150 msgid " ..loading.." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1285 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1413 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1261 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1389 msgid "No address specified!" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1298 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1274 msgid "Unknown protocol" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1298 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1274 msgid "Please use the mtasa:// protocol!" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1387 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1363 msgid "You have to select a server to connect to." msgstr "" diff --git a/Shared/data/launchers/CEFLauncher.exe b/Shared/data/launchers/CEFLauncher.exe index 8ddad15d39..a9be86fc62 100644 Binary files a/Shared/data/launchers/CEFLauncher.exe and b/Shared/data/launchers/CEFLauncher.exe differ diff --git a/Shared/data/launchers/MTA Server ARM64.exe b/Shared/data/launchers/MTA Server ARM64.exe index f64006f3d8..974d0d82b5 100644 Binary files a/Shared/data/launchers/MTA Server ARM64.exe and b/Shared/data/launchers/MTA Server ARM64.exe differ diff --git a/Shared/data/launchers/MTA Server.exe b/Shared/data/launchers/MTA Server.exe index bc664aec89..78b87553a5 100644 Binary files a/Shared/data/launchers/MTA Server.exe and b/Shared/data/launchers/MTA Server.exe differ diff --git a/Shared/data/launchers/MTA Server64.exe b/Shared/data/launchers/MTA Server64.exe index 021e55401f..7397e22a42 100644 Binary files a/Shared/data/launchers/MTA Server64.exe and b/Shared/data/launchers/MTA Server64.exe differ diff --git a/Shared/data/launchers/Multi Theft Auto.exe b/Shared/data/launchers/Multi Theft Auto.exe index 99fcb3c6bf..547a73812a 100644 Binary files a/Shared/data/launchers/Multi Theft Auto.exe and b/Shared/data/launchers/Multi Theft Auto.exe differ diff --git a/Shared/data/launchers/wow64_helper.exe b/Shared/data/launchers/wow64_helper.exe index 24a78f7abb..51fc605af7 100644 Binary files a/Shared/data/launchers/wow64_helper.exe and b/Shared/data/launchers/wow64_helper.exe differ diff --git a/Shared/installer/nightly.nsi b/Shared/installer/nightly.nsi index d270a0d719..cba6d23680 100644 --- a/Shared/installer/nightly.nsi +++ b/Shared/installer/nightly.nsi @@ -780,8 +780,8 @@ SectionGroup /e "$(INST_SEC_CLIENT)" SECGCLIENT File "${FILES_ROOT}\mta\cgui\unifont.ttf" SetOutPath "$INSTDIR\MTA\cgui\images" - File "${FILES_ROOT}\mta\cgui\images\*.png" - File "${FILES_ROOT}\mta\cgui\images\*.jpg" + File /nonfatal "${FILES_ROOT}\mta\cgui\images\*.png" + File /nonfatal "${FILES_ROOT}\mta\cgui\images\*.jpg" SetOutPath "$INSTDIR\MTA\cgui\images\radarset" File "${FILES_ROOT}\mta\cgui\images\radarset\*.png" diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index 1e3d0b2003..64aa8db8f1 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -101,6 +101,7 @@ ADD_ENUM(WorldSpecialProperty::FIREBALLDESTRUCT, "fireballdestruct") ADD_ENUM(WorldSpecialProperty::EXTENDEDWATERCANNONS, "extendedwatercannons") ADD_ENUM(WorldSpecialProperty::ROADSIGNSTEXT, "roadsignstext") ADD_ENUM(WorldSpecialProperty::TUNNELWEATHERBLEND, "tunnelweatherblend") +ADD_ENUM(WorldSpecialProperty::IGNOREFIRESTATE, "ignorefirestate") IMPLEMENT_ENUM_CLASS_END("world-special-property") IMPLEMENT_ENUM_BEGIN(ePacketID) @@ -213,4 +214,5 @@ ADD_ENUM1(PACKET_ID_CHAT_CLEAR) ADD_ENUM1(PACKET_ID_SERVER_INFO_SYNC) ADD_ENUM1(PACKET_ID_DISCORD_JOIN) ADD_ENUM1(PACKET_ID_PLAYER_RESOURCE_START) +ADD_ENUM1(PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY) IMPLEMENT_ENUM_END("ePacketID") diff --git a/Shared/mods/deathmatch/logic/Enums.h b/Shared/mods/deathmatch/logic/Enums.h index e975d0d907..3125179714 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -91,6 +91,7 @@ enum class WorldSpecialProperty ROADSIGNSTEXT, EXTENDEDWATERCANNONS, TUNNELWEATHERBLEND, + IGNOREFIRESTATE, }; DECLARE_ENUM_CLASS(WorldSpecialProperty); diff --git a/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h b/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h index fef13d708b..d6d1cc3297 100644 --- a/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h +++ b/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h @@ -283,9 +283,12 @@ struct CLuaFunctionParserBase return true; return iArgument == LUA_TUSERDATA || iArgument == LUA_TLIGHTUSERDATA; } - // CMatrix may either be represented by 3 CLuaVector or by 12 numbers + // CMatrix can be represented either by 3 CLuaVectors, 12 numbers, or a 4x4 Lua table else if constexpr (std::is_same_v) { + if (IsValidMatrixLuaTable(L, index)) + return true; + for (int i = 0; i < sizeof(CMatrix) / sizeof(float); i++) { if (!lua_isnumber(L, index + i)) @@ -536,7 +539,11 @@ struct CLuaFunctionParserBase else if constexpr (std::is_same_v) { if (lua_isnumber(L, index)) - return {PopUnsafe(L, index), PopUnsafe(L, index)}; + { + auto x = PopUnsafe(L, index); + auto y = PopUnsafe(L, index); + return CVector2D(x, y); + } int iType = lua_type(L, index); bool isLightUserData = iType == LUA_TLIGHTUSERDATA; @@ -561,7 +568,12 @@ struct CLuaFunctionParserBase else if constexpr (std::is_same_v) { if (lua_isnumber(L, index)) - return {PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)}; + { + auto x = PopUnsafe(L, index); + auto y = PopUnsafe(L, index); + auto z = PopUnsafe(L, index); + return CVector(x, y, z); + } int iType = lua_type(L, index); bool isLightUserData = iType == LUA_TLIGHTUSERDATA; @@ -584,7 +596,13 @@ struct CLuaFunctionParserBase else if constexpr (std::is_same_v) { if (lua_isnumber(L, index)) - return {PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)}; + { + auto x = PopUnsafe(L, index); + auto y = PopUnsafe(L, index); + auto z = PopUnsafe(L, index); + auto w = PopUnsafe(L, index); + return CVector4D(x, y, z, w); + } int iType = lua_type(L, index); bool isLightUserData = iType == LUA_TLIGHTUSERDATA; @@ -606,7 +624,13 @@ struct CLuaFunctionParserBase { if (lua_isnumber(L, index)) { - const auto ReadVector = [&] { return CVector(PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)); }; + const auto ReadVector = [&] + { + auto x = PopUnsafe(L, index); + auto y = PopUnsafe(L, index); + auto z = PopUnsafe(L, index); + return CVector(x, y, z); + }; CMatrix matrix; @@ -618,6 +642,19 @@ struct CLuaFunctionParserBase return matrix; } + if (lua_istable(L, index)) + { + CMatrix matrix; + + if (!ReadMatrix(L, index, matrix)) + { + SetBadArgumentError(L, "matrix", index, "table"); + return T{}; + } + + return matrix; + } + int iType = lua_type(L, index); bool isLightUserData = iType == LUA_TLIGHTUSERDATA; void* pValue = lua::PopPrimitive(L, index); diff --git a/Shared/sdk/CVector.h b/Shared/sdk/CVector.h index 5c2ddde7a6..b39bfb951e 100644 --- a/Shared/sdk/CVector.h +++ b/Shared/sdk/CVector.h @@ -30,13 +30,12 @@ class CVector float fY; float fZ; - struct NoInit{}; + struct NoInit {}; + CVector(NoInit) noexcept {} - CVector(NoInit) {} - - constexpr CVector() : fX(0.0f), fY(0.0f), fZ(0.0f) {} - - constexpr CVector(float x, float y, float z) : fX(x), fY(y), fZ(z) {} + constexpr CVector() noexcept : fX(0.0f), fY(0.0f), fZ(0.0f) {} + + constexpr explicit CVector(float x, float y = 0.0f, float z = 0.0f) noexcept : fX(x), fY(y), fZ(z) {} constexpr CVector(const CVector4D& vec) noexcept : fX(vec.fX), fY(vec.fY), fZ(vec.fZ) {} @@ -187,7 +186,7 @@ class CVector { *outVec = *this + vecRay * t; if (outHitBary) { // Calculate all barycentric coords if necessary - *outHitBary = { 1.f - u - v, u, v }; // For vertices A, B, C [I assume?] + *outHitBary = CVector( 1.f - u - v, u, v ); // For vertices A, B, C [I assume?] } return true; } diff --git a/Shared/sdk/net/Packets.h b/Shared/sdk/net/Packets.h index 0941ca49dd..411af7cb88 100644 --- a/Shared/sdk/net/Packets.h +++ b/Shared/sdk/net/Packets.h @@ -151,4 +151,5 @@ enum ePacketID PACKET_ID_SERVER_INFO_SYNC, PACKET_ID_DISCORD_JOIN, PACKET_ID_PLAYER_RESOURCE_START, + PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY }; diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 1e9b8215b3..0e42407aae 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2044,6 +2044,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { BITCOUNT5 = 1 }; + enum + { + BITCOUNT6 = 1 + }; bool Read(NetBitStreamInterface& bitStream) { @@ -2068,6 +2072,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure else data5.tunnelweatherblend = true; + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_IgnoreFireState)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data6), BITCOUNT6); + else + data6.ignoreFireState = false; + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // isOK &= bitStream.ReadBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2091,6 +2100,9 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_TunnelWeatherBlend)) bitStream.WriteBits(reinterpret_cast(&data5), BITCOUNT5); + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_IgnoreFireState)) + bitStream.WriteBits(reinterpret_cast(&data6), BITCOUNT6); + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2132,6 +2144,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { bool tunnelweatherblend : 1; } data5; + + struct + { + bool ignoreFireState : 1; + } data6; SWorldSpecialPropertiesStateSync() { @@ -2152,6 +2169,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure data3.roadsignstext = true; data4.extendedwatercannons = true; data5.tunnelweatherblend = true; + data6.ignoreFireState = false; } }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index c29f739ff1..f422739ad4 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -572,6 +572,22 @@ enum class eBitStreamVersion : unsigned short // 2024-09-04 RespawnObject_Serverside, + // Add check_duplicate_serials + // 2024-09-04 + CheckDuplicateSerials, + + // Add ignorefirestate special world property + // 2024-11-07 + WorldSpecialProperty_IgnoreFireState, + + // Fix iPedSyncerDistance and iUnoccupiedVehicleSyncerDistance sync + // 2024-11-22 + FixSyncerDistance, + + // Add onPlayerChangesWorldSpecialProperty + // 2024-11-26 + WorldSpecialPropertyEvent, + // This allows us to automatically increment the BitStreamVersion when things are added to this enum. // Make sure you only add things above this comment. Next, diff --git a/Shared/sdk/version.h b/Shared/sdk/version.h index 12d10c80a5..81bfe01318 100644 --- a/Shared/sdk/version.h +++ b/Shared/sdk/version.h @@ -108,7 +108,7 @@ #define _ASE_VERSION QUOTE_DEFINE(MTASA_VERSION_MAJOR) "." QUOTE_DEFINE(MTASA_VERSION_MINOR) #define _NETCODE_VERSION_BRANCH_ID 0x4 // Use 0x1 - 0xF to indicate an incompatible branch is being used (0x0 is reserved, 0x4 is trunk) -#define _CLIENT_NET_MODULE_VERSION 0x0AF // (0x000 - 0xfff) Lvl9 wizards only +#define _CLIENT_NET_MODULE_VERSION 0x0B0 // (0x000 - 0xfff) Lvl9 wizards only #define _SERVER_NET_MODULE_VERSION 0x0AB // (0x000 - 0xfff) Lvl9 wizards only #define _NETCODE_VERSION 0x1DA // (0x000 - 0xfff) Increment when net messages change (pre-release) diff --git a/utils/buildactions/install_cef.lua b/utils/buildactions/install_cef.lua index 65b686aa56..f3367efcb1 100644 --- a/utils/buildactions/install_cef.lua +++ b/utils/buildactions/install_cef.lua @@ -9,8 +9,8 @@ local CEF_URL_PREFIX = "https://cef-builds.spotifycdn.com/cef_binary_" local CEF_URL_SUFFIX = "_windows32_minimal.tar.bz2" -- Change here to update CEF version -local CEF_VERSION = "129.0.12+gf09539f+chromium-129.0.6668.101" -local CEF_HASH = "ec759dbfafafac2ae26f4960caad1c8464205a7787ec247e0fc21ab4620c8a5c" +local CEF_VERSION = "131.3.5+g573cec5+chromium-131.0.6778.205" +local CEF_HASH = "85d9e37766ae0f0f0b5ac6074220c1c6452ab6348bfa867487df7e041a8231cc" function make_cef_download_url() return CEF_URL_PREFIX..http.escapeUrlParam(CEF_VERSION)..CEF_URL_SUFFIX