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/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/CModelInfoSA.h b/Client/game_sa/CModelInfoSA.h index b261bcc04a..ed306f4c8f 100644 --- a/Client/game_sa/CModelInfoSA.h +++ b/Client/game_sa/CModelInfoSA.h @@ -14,6 +14,7 @@ #include #include #include "CRenderWareSA.h" +#include "game/RenderWare.h" class CPedModelInfoSA; class CPedModelInfoSAInterface; @@ -231,6 +232,11 @@ class CBaseModelInfoSAInterface // +726 = Word array as referenced in CVehicleModelInfo::GetVehicleUpgrade(int) // +762 = Array of WORD containing something relative to paintjobs // +772 = Anim file index + + void Shutdown() + { + ((void(*)())VFTBL->Shutdown)(); + } }; static_assert(sizeof(CBaseModelInfoSAInterface) == 0x20, "Invalid size for CBaseModelInfoSAInterface"); @@ -259,53 +265,66 @@ class CTimeModelInfoSAInterface : public CBaseModelInfoSAInterface CTimeInfoSAInterface timeInfo; }; +class CVehicleModelUpgradePosnDesc +{ + CVector m_vPosition; + RtQuat m_vRotation; + int m_iParentId; +}; + class CVehicleModelVisualInfoSAInterface // Not sure about this name. If somebody knows more, please change { public: - CVector vecDummies[15]; - char m_sUpgrade[18]; + CVector vecDummies[15]; + CVehicleModelUpgradePosnDesc m_sUpgrade[18]; + RpAtomic* m_pExtra[6]; + std::uint8_t m_numExtras; + std::uint8_t _pad[3]; + int m_maskComponentDamagable; }; -class CVehicleModelInfoSAInterface : public CBaseModelInfoSAInterface +class CVehicleModelInfoSAInterface : public CClumpModelInfoSAInterface { public: - uint32 pad1; // +32 - RpMaterial* pPlateMaterial; // +36 + RpMaterial* pPlateMaterial; char plateText[8]; - char pad[2]; + std::uint8_t field_30; + std::uint8_t plateType; char gameName[8]; - char pad2[2]; - unsigned int uiVehicleType; + std::uint8_t field_3A[2]; + std::uint32_t vehicleType; float fWheelSizeFront; float fWheelSizeRear; - short sWheelModel; - short sHandlingID; - byte ucNumDoors; - byte ucVehicleList; - byte ucVehicleFlags; - byte ucWheelUpgradeClass; - byte ucTimesUsed; - short sVehFrequency; - unsigned int uiComponentRules; - float fSteeringAngle; - CVehicleModelVisualInfoSAInterface* pVisualInfo; // +92 - char pad3[464]; - char pDirtMaterial[64]; // *RwMaterial - char pad4[64]; - char primColors[8]; - char secondColors[8]; - char treeColors[8]; - char fourColors[8]; - unsigned char ucNumOfColorVariations; - unsigned char ucLastColorVariation; - unsigned char ucPrimColor; - unsigned char ucSecColor; - unsigned char ucTertColor; - unsigned char ucQuatColor; - char upgrades[36]; - char anRemapTXDs[8]; - char pad5[2]; - char pAnimBlock[4]; + std::int16_t wheelModelID; + std::int16_t handlingID; + std::uint8_t numDoors; + std::uint8_t vehicleClass; + std::uint8_t vehicleFlags; + std::uint8_t wheelUpgradeClass; + std::uint8_t timesUsed; + std::uint8_t field_51; + std::int16_t vehFrequency; + std::uint32_t componentRules; + float bikeSteeringAngle; + CVehicleModelVisualInfoSAInterface* pVisualInfo; // vehicleStruct + std::uint8_t field_60[464]; + RpMaterial** m_dirtMaterials; + std::size_t m_numDirtMaterials; + RpMaterial* m_staticDirtMaterials[30]; + std::uint8_t primColors[8]; + std::uint8_t secondColors[8]; + std::uint8_t treeColors[8]; + std::uint8_t fourColors[8]; + std::uint8_t numOfColorVariations; + std::uint8_t lastColorVariation; + std::uint8_t primColor; + std::uint8_t secColor; + std::uint8_t tertColor; + std::uint8_t quatColor; + std::uint8_t upgrades[36]; + std::uint8_t anRemapTXDs[8]; + std::uint8_t field_302[2]; + void* pAnimBlock; // CAnimBlock* }; class CModelInfoSA : public CModelInfo @@ -466,7 +485,7 @@ 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; }; private: void CopyStreamingInfoFromModel(ushort usCopyFromModelID); 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/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/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index 9d4a02598e..579ebb6180 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -224,6 +224,7 @@ CVehicleSA::~CVehicleSA() } CWorldSA* pWorld = (CWorldSA*)pGame->GetWorld(); + pGame->GetProjectileInfo()->RemoveEntityReferences(this); pWorld->Remove(m_pInterface, CVehicle_Destructor); pWorld->RemoveReferencesToDeletedObject(m_pInterface); diff --git a/Client/game_sa/gamesa_renderware.h b/Client/game_sa/gamesa_renderware.h index 594c203b59..4073f8f2b2 100644 --- a/Client/game_sa/gamesa_renderware.h +++ b/Client/game_sa/gamesa_renderware.h @@ -105,6 +105,7 @@ typedef RpHAnimHierarchy*(__cdecl* GetAnimHierarchyFromSkinClump_t)(RpClump*); typedef int(__cdecl* RpHAnimIDGetIndex_t)(RpHAnimHierarchy*, int); typedef RwMatrix*(__cdecl* RpHAnimHierarchyGetMatrixArray_t)(RpHAnimHierarchy*); typedef RtQuat*(__cdecl* RtQuatRotate_t)(RtQuat* quat, const RwV3d* axis, float angle, RwOpCombineType combineOp); +typedef RpGeometry*(__cdecl* RpGeometryForAllMaterials_t)(RpGeometry* geom, void* callback, void* data); /*****************************************************************************/ /** Renderware function mappings **/ @@ -195,6 +196,7 @@ RWFUNC(GetAnimHierarchyFromSkinClump_t GetAnimHierarchyFromSkinClump, (GetAnimHi RWFUNC(RpHAnimIDGetIndex_t RpHAnimIDGetIndex, (RpHAnimIDGetIndex_t)0xDEAD) RWFUNC(RpHAnimHierarchyGetMatrixArray_t RpHAnimHierarchyGetMatrixArray, (RpHAnimHierarchyGetMatrixArray_t)0xDEAD) RWFUNC(RtQuatRotate_t RtQuatRotate, (RtQuatRotate_t)0xDEAD) +RWFUNC(RpGeometryForAllMaterials_t RpGeometryForAllMaterials, (RpGeometryForAllMaterials_t)0xDEAD) /*****************************************************************************/ /** GTA function definitions and mappings **/ diff --git a/Client/game_sa/gamesa_renderware.hpp b/Client/game_sa/gamesa_renderware.hpp index a638cfede0..f52d205dda 100644 --- a/Client/game_sa/gamesa_renderware.hpp +++ b/Client/game_sa/gamesa_renderware.hpp @@ -89,7 +89,8 @@ void InitRwFunctions() RpHAnimIDGetIndex = (RpHAnimIDGetIndex_t)0x7C51A0; RpHAnimHierarchyGetMatrixArray = (RpHAnimHierarchyGetMatrixArray_t)0x7C5120; RtQuatRotate = (RtQuatRotate_t)0x7EB7C0; - + RpGeometryForAllMaterials = (RpGeometryForAllMaterials_t)0x74C790; + SetTextureDict = (SetTextureDict_t)0x007319C0; LoadClumpFile = (LoadClumpFile_t)0x005371F0; LoadModel = (LoadModel_t)0x0040C6B0; 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/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 52ca69f3f0..acc385998c 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" @@ -403,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(); @@ -5982,7 +5987,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) { @@ -5990,47 +5995,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); - return true; + 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) diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index c76dc223aa..e887199fcd 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -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); diff --git a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp index fd305f6955..380767ccc7 100644 --- a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp @@ -619,8 +619,12 @@ void CWorldRPCs::SetSyncIntervals(NetBitStreamInterface& bitStream) bitStream.Read(g_TickRateSettings.iObjectSync); bitStream.Read(g_TickRateSettings.iKeySyncRotation); bitStream.Read(g_TickRateSettings.iKeySyncAnalogMove); - bitStream.Read(g_TickRateSettings.iPedSyncerDistance); - bitStream.Read(g_TickRateSettings.iUnoccupiedVehicleSyncerDistance); + + 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_Vehicles.cpp b/Client/multiplayer_sa/CMultiplayerSA_Vehicles.cpp index 88b0b11eb8..afaa8de6f1 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_Vehicles.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_Vehicles.cpp @@ -9,6 +9,12 @@ *****************************************************************************/ #include "StdInc.h" +#include "..\game_sa\gamesa_renderware.h" + +#define FUNC_CBaseModelInfo_Shutdown 0x4C4D50 +#define IN_PLACE_BUFFER_DIRT_SIZE 30 + +static RwTexture** const ms_aDirtTextures = (RwTexture**)0xC02BD0; static bool __fastcall AreVehicleDoorsUndamageable(CVehicleSAInterface* vehicle) { @@ -107,6 +113,100 @@ static void _declspec(naked) HOOK_CAEVehicleAudioEntity__Initialise() } } +static void __fastcall CVehicleModelInfo_Shutdown(CVehicleModelInfoSAInterface* mi) +{ + if (!mi) + return; + + mi->Shutdown(); + + delete[] mi->m_dirtMaterials; + mi->m_dirtMaterials = nullptr; +} + +static void SetDirtTextures(CVehicleModelInfoSAInterface* mi, std::uint32_t level) +{ + RpMaterial** materials = mi->m_numDirtMaterials > IN_PLACE_BUFFER_DIRT_SIZE ? mi->m_dirtMaterials : mi->m_staticDirtMaterials; + for (std::uint32_t i = 0; i < mi->m_numDirtMaterials; i++) + RpMaterialSetTexture(materials[i], ms_aDirtTextures[level]); +} + +#define HOOKPOS_CVehicleModelInfo_SetDirtTextures 0x5D5DBB +#define HOOKSIZE_CVehicleModelInfo_SetDirtTextures 6 +static constexpr DWORD CONTINUE_CVehicleModelInfo_SetDirtTextures = 0x5D5DE3; +static void _declspec(naked) HOOK_CVehicleModelInfo_SetDirtTextures() +{ + _asm + { + push ebx + push esi + call SetDirtTextures + add esp, 8 + + jmp CONTINUE_CVehicleModelInfo_SetDirtTextures + } +} + +static RpMaterial* GetAtomicGeometryMaterialsCB(RpMaterial* material, void* data) +{ + RwTexture* texture = material->texture; + if (!texture) + return nullptr; + + auto cbData = static_cast*>(data); + if (texture->name && std::strcmp(texture->name, "vehiclegrunge256") == 0) + cbData->push_back(material); + + return material; +} + +static bool GetEditableMaterialListCB(RpAtomic* atomic, void* data) +{ + RpGeometryForAllMaterials(atomic->geometry, &GetAtomicGeometryMaterialsCB, data); + return true; +} + +static void __fastcall FindEditableMaterialList(CVehicleModelInfoSAInterface* mi) +{ + std::vector list; + RpClumpForAllAtomics(reinterpret_cast(mi->pRwObject), &GetEditableMaterialListCB, &list); + + for (std::uint32_t i = 0; i < mi->pVisualInfo->m_numExtras; i++) + GetEditableMaterialListCB(mi->pVisualInfo->m_pExtra[i], &list); + + mi->m_numDirtMaterials = list.size(); + if (mi->m_numDirtMaterials > IN_PLACE_BUFFER_DIRT_SIZE) + { + mi->m_dirtMaterials = new RpMaterial*[mi->m_numDirtMaterials]; + std::copy(list.begin(), list.end(), mi->m_dirtMaterials); + } + else + { + mi->m_dirtMaterials = nullptr; + std::copy(list.begin(), list.end(), mi->m_staticDirtMaterials); + } + + mi->primColor = 255; + mi->secColor = 255; + mi->tertColor = 255; + mi->quatColor = 255; +} + +#define HOOKPOS_CVehicleModelInfo_SetClump 0x4C9648 +#define HOOKSIZE_CVehicleModelInfo_SetClump 24 +static constexpr DWORD CONTINUE_CVehicleModelInfo_SetClump = 0x4C9660; +static void _declspec(naked) HOOK_CVehicleModelInfo_SetClump() +{ + _asm + { + push ecx + call FindEditableMaterialList + pop ecx + + jmp CONTINUE_CVehicleModelInfo_SetClump + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // // CMultiplayerSA::InitHooks_Vehicles @@ -118,4 +218,9 @@ void CMultiplayerSA::InitHooks_Vehicles() { EZHookInstall(CDamageManager__ProgressDoorDamage); EZHookInstall(CAEVehicleAudioEntity__Initialise); + + // Fix vehicle dirt level + EZHookInstall(CVehicleModelInfo_SetClump); + EZHookInstall(CVehicleModelInfo_SetDirtTextures); + MemCpy((void*)0x85C5E4, &CVehicleModelInfo_Shutdown, 4); } diff --git a/Client/sdk/game/CModelInfo.h b/Client/sdk/game/CModelInfo.h index 08cb032e4c..3541750038 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: 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/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 98ea8250b2..b1a2ca18d6 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" @@ -1293,6 +1294,12 @@ bool CGame::ProcessPacket(CPacket& Packet) return true; } + case PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY: + { + Packet_PlayerWorldSpecialProperty(static_cast(Packet)); + return true; + } + default: break; } @@ -1609,6 +1616,7 @@ void CGame::AddBuiltInEvents() 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); @@ -4256,6 +4264,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..e6bd4dfccf 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -519,6 +519,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); 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/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 930e814879..ce44a7d79a 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -10852,21 +10852,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); - BitStream.pBitStream->Write(g_TickRateSettings.iPedSyncerDistance); - BitStream.pBitStream->Write(g_TickRateSettings.iUnoccupiedVehicleSyncerDistance); - 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/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/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot b/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot index 6016d1813e..79dcedc833 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-11-21 22:40+0000\n" +"POT-Creation-Date: 2024-12-16 23:16+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -159,121 +159,121 @@ 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:1090 Client/core/CCore.cpp:674 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1095 Client/core/CCore.cpp:674 #: Client/core/CSettings.cpp:3489 msgid "In-game" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:375 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Flying a UFO around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:375 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Cruising around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:375 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Riding the waves of" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:376 +#: Client/mods/deathmatch/logic/CClientGame.cpp:377 msgid "Riding the train in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:376 +#: Client/mods/deathmatch/logic/CClientGame.cpp:377 msgid "Flying around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:377 +#: Client/mods/deathmatch/logic/CClientGame.cpp:378 msgid "Riding around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:377 +#: Client/mods/deathmatch/logic/CClientGame.cpp:378 msgid "Monster truckin' around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:377 +#: Client/mods/deathmatch/logic/CClientGame.cpp:378 msgid "Quaddin' around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:378 +#: Client/mods/deathmatch/logic/CClientGame.cpp:379 msgid "Bunny hopping around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:378 +#: Client/mods/deathmatch/logic/CClientGame.cpp:379 msgid "Doing weird stuff in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:382 +#: Client/mods/deathmatch/logic/CClientGame.cpp:383 msgid "Climbing around in" msgstr "" -#: 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:385 +#: Client/mods/deathmatch/logic/CClientGame.cpp:386 msgid "Blub blub..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:386 +#: Client/mods/deathmatch/logic/CClientGame.cpp:387 msgid "Breathing water" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:387 +#: Client/mods/deathmatch/logic/CClientGame.cpp:388 msgid "Drowning in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:388 +#: Client/mods/deathmatch/logic/CClientGame.cpp:389 msgid "Ducking for cover in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:389 +#: Client/mods/deathmatch/logic/CClientGame.cpp:390 msgid "Fighting in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:390 +#: Client/mods/deathmatch/logic/CClientGame.cpp:391 msgid "Throwing fists in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:391 +#: Client/mods/deathmatch/logic/CClientGame.cpp:392 msgid "Blastin' fools in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:392 +#: Client/mods/deathmatch/logic/CClientGame.cpp:393 msgid "Shooting up" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:393 +#: Client/mods/deathmatch/logic/CClientGame.cpp:394 msgid "Jetpacking in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:394 +#: Client/mods/deathmatch/logic/CClientGame.cpp:395 msgid "Literally on fire in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:395 +#: Client/mods/deathmatch/logic/CClientGame.cpp:396 msgid "Burning up in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:396 +#: Client/mods/deathmatch/logic/CClientGame.cpp:397 msgid "Swimming in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:397 +#: Client/mods/deathmatch/logic/CClientGame.cpp:398 msgid "Floating around in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:398 +#: Client/mods/deathmatch/logic/CClientGame.cpp:399 msgid "Being chased by a shark" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:399 +#: Client/mods/deathmatch/logic/CClientGame.cpp:400 msgid "Choking to death in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:534 +#: Client/mods/deathmatch/logic/CClientGame.cpp:539 #: Client/core/CMainMenu.cpp:304 Client/core/CCore.cpp:674 #: Client/core/CSettings.cpp:3485 msgid "Main menu" @@ -283,17 +283,17 @@ 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:642 -#: Client/mods/deathmatch/logic/CClientGame.cpp:716 -#: Client/mods/deathmatch/logic/CClientGame.cpp:740 -#: Client/mods/deathmatch/logic/CClientGame.cpp:762 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1175 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1255 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1265 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1334 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1371 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1420 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1432 +#: 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/loader/MainFunctions.cpp:252 Client/loader/MainFunctions.cpp:267 #: Client/loader/MainFunctions.cpp:269 Client/loader/MainFunctions.cpp:846 @@ -316,140 +316,140 @@ msgstr "" msgid "Error" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:642 -#: Client/mods/deathmatch/logic/CClientGame.cpp:740 +#: Client/mods/deathmatch/logic/CClientGame.cpp:647 +#: Client/mods/deathmatch/logic/CClientGame.cpp:745 #: Client/core/ServerBrowser/CServerBrowser.cpp:1307 #: Client/core/ServerBrowser/CServerBrowser.cpp:1364 msgid "Invalid nickname! Please go to Settings and set a new one!" msgstr "" #. Display the status box -#: Client/mods/deathmatch/logic/CClientGame.cpp:658 +#: Client/mods/deathmatch/logic/CClientGame.cpp:663 #: Client/core/CConnectManager.cpp:148 msgid "CONNECTING" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:658 +#: Client/mods/deathmatch/logic/CClientGame.cpp:663 msgid "Entering the game ..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:716 +#: 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:762 +#: 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:772 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1244 +#: Client/mods/deathmatch/logic/CClientGame.cpp:777 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1249 msgid "Local Server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:772 +#: Client/mods/deathmatch/logic/CClientGame.cpp:777 msgid "Starting local server ..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1020 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1025 msgid "Area 51" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1029 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1034 msgid "Walking around " msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1175 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1180 #, c-format msgid "You were kicked from the game ( %s )" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1244 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1249 msgid "Connecting to local server..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1255 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1260 msgid "Error connecting to server." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1265 +#: 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:1334 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1339 #: Client/core/CConnectManager.cpp:263 msgid "Connection timed out" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1371 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1376 msgid "Connection with the server was lost" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1382 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1387 #: Client/core/CConnectManager.cpp:277 Client/core/CConnectManager.cpp:281 msgid "Disconnected: unknown protocol error" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1386 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1391 #: Client/core/CConnectManager.cpp:285 msgid "Disconnected: disconnected remotely" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1390 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1395 #: Client/core/CConnectManager.cpp:289 msgid "Disconnected: connection lost remotely" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1394 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1399 #: Client/core/CConnectManager.cpp:293 msgid "Disconnected: you are banned from this server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1398 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1403 msgid "Disconnected: the server is currently full" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1402 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1407 #: Client/core/CConnectManager.cpp:300 msgid "Disconnected: disconnected from the server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1406 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1411 #: Client/core/CConnectManager.cpp:304 msgid "Disconnected: connection to the server was lost" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1410 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1415 msgid "Disconnected: invalid password specified" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1414 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1419 #: Client/core/CConnectManager.cpp:311 msgid "Disconnected: connection was refused" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1432 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1437 msgid "MTA Client verification failed!" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5620 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5625 msgid "In a ditch" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5620 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5625 msgid "En-route to hospital" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5620 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5625 msgid "Meeting their maker" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5621 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5626 msgid "Regretting their decisions" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5621 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5626 msgid "Wasted" msgstr "" @@ -828,19 +828,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: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:600 +#: 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" @@ -850,28 +859,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" @@ -879,38 +888,38 @@ 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 "" @@ -1058,6 +1067,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" 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 20be17719d..64aa8db8f1 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -214,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/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/bitstream.h b/Shared/sdk/net/bitstream.h index 88bdfcfff2..f422739ad4 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -580,6 +580,14 @@ enum class eBitStreamVersion : unsigned short // 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/utils/buildactions/install_cef.lua b/utils/buildactions/install_cef.lua index 364bedf3e2..663c5a244d 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 = "130.1.2+g48f3ef6+chromium-130.0.6723.44" -local CEF_HASH = "f436f0f23caa8167d14e8de331d15fbb534e411f4235895024c2e242510e8deb" +local CEF_VERSION = "131.3.4+g7ecebf0+chromium-131.0.6778.140" +local CEF_HASH = "c6f00e0bcc8973c5ff0aa1d9297748ab0bdc483f6d8932946ad70450fb1f14ed" function make_cef_download_url() return CEF_URL_PREFIX..http.escapeUrlParam(CEF_VERSION)..CEF_URL_SUFFIX