VC: Fix the construction site LOD losing its HQ model and showing at all times

This commit is contained in:
Silent 2024-05-23 20:07:34 +02:00
parent b76637d391
commit 0f92e082b4
No known key found for this signature in database
GPG Key ID: AE53149BB0C45AF1
7 changed files with 134 additions and 28 deletions

View File

@ -839,7 +839,7 @@ namespace SitInBoat
} }
namespace SVFReadyHook namespace ModelIndicesReadyHook
{ {
static void (*orgInitialiseObjectData)(const char*); static void (*orgInitialiseObjectData)(const char*);
static void InitialiseObjectData_ReadySVF(const char* path) static void InitialiseObjectData_ReadySVF(const char* path)
@ -1010,7 +1010,7 @@ void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModul
// Register CBaseModelInfo::GetModelInfo for SVF so we can resolve model names // Register CBaseModelInfo::GetModelInfo for SVF so we can resolve model names
try try
{ {
using namespace SVFReadyHook; using namespace ModelIndicesReadyHook;
auto initialiseObjectData = get_pattern("E8 ? ? ? ? B3 01 59 8D 6D 04"); auto initialiseObjectData = get_pattern("E8 ? ? ? ? B3 01 59 8D 6D 04");
auto getModelInfo = (void*(*)(const char*, int*))get_pattern("31 FF 8D 84 20 00 00 00 00 8B 04 BD", -7); auto getModelInfo = (void*(*)(const char*, int*))get_pattern("31 FF 8D 84 20 00 00 00 00 8B 04 BD", -7);

View File

@ -2652,7 +2652,7 @@ static bool IgnoresWeaponPedsForPCFix()
} }
namespace SVFReadyHook namespace ModelIndicesReadyHook
{ {
static void (*orgMatchAllModelStrings)(); static void (*orgMatchAllModelStrings)();
static void MatchAllModelStrings_ReadySVF() static void MatchAllModelStrings_ReadySVF()
@ -3899,7 +3899,7 @@ BOOL InjectDelayedPatches_10()
// Register CBaseModelInfo::GetModelInfo for SVF so we can resolve model names // Register CBaseModelInfo::GetModelInfo for SVF so we can resolve model names
{ {
using namespace SVFReadyHook; using namespace ModelIndicesReadyHook;
auto func = (void*(*)(const char*, int*))0x4C5940; auto func = (void*(*)(const char*, int*))0x4C5940;

22
SilentPatchVC/EntityVC.h Normal file
View File

@ -0,0 +1,22 @@
#pragma
#include <cstdint>
#include <cstddef>
#include "TheFLAUtils.h"
enum // m_objectCreatedBy
{
GAME_OBJECT = 1,
MISSION_OBJECT = 2,
TEMP_OBJECT = 3,
};
class CEntity
{
public:
std::byte __pad[80];
uint8_t m_nType : 3;
std::byte __pad2[11];
FLAUtils::int16 m_modelIndex;
};

View File

@ -23,5 +23,16 @@ public:
static void AttachCarPipeToRwObject_Default(RwObject*) { } static void AttachCarPipeToRwObject_Default(RwObject*) { }
static inline void (*AttachCarPipeToRwObject)(RwObject* object) = &AttachCarPipeToRwObject_Default; static inline void (*AttachCarPipeToRwObject)(RwObject* object) = &AttachCarPipeToRwObject_Default;
}; };
static_assert(sizeof(CVehicleModelInfo) == 0x174, "Wrong size: CVehicleModelInfo");
static_assert(sizeof(CVehicleModelInfo) == 0x174, "Wrong size: CvehicleModelInfo"); class CSimpleModelInfo
{
public:
void* __vmt;
char m_name[24];
uint8_t __pad[12];
void* m_atomics[3];
float m_lodDistances[3];
uint8_t __pad2[4];
};
static_assert(sizeof(CSimpleModelInfo) == 68, "Wrong size: CSimpleModelInfo");

View File

@ -5,6 +5,7 @@
#include "Common.h" #include "Common.h"
#include "Common_ddraw.h" #include "Common_ddraw.h"
#include "Desktop.h" #include "Desktop.h"
#include "EntityVC.h"
#include "ModelInfoVC.h" #include "ModelInfoVC.h"
#include "VehicleVC.h" #include "VehicleVC.h"
#include "SVF.h" #include "SVF.h"
@ -65,6 +66,8 @@ DebugMenuAPI gDebugMenuAPI;
static RsGlobalType* RsGlobal; static RsGlobalType* RsGlobal;
static const void* SubtitlesShadowFix_JumpBack; static const void* SubtitlesShadowFix_JumpBack;
void* (*GetModelInfo)(const char*, int*);
// This is actually CBaseModelInfo, but we currently don't have it defined // This is actually CBaseModelInfo, but we currently don't have it defined
CVehicleModelInfo**& ms_modelInfoPtrs = *hook::get_pattern<CVehicleModelInfo**>("8B 15 ? ? ? ? 8D 04 24", 2); CVehicleModelInfo**& ms_modelInfoPtrs = *hook::get_pattern<CVehicleModelInfo**>("8B 15 ? ? ? ? 8D 04 24", 2);
int32_t& numModelInfos = *hook::get_pattern<int32_t>("81 FD ? ? ? ? 7C B7", 2); int32_t& numModelInfos = *hook::get_pattern<int32_t>("81 FD ? ? ? ? 7C B7", 2);
@ -722,22 +725,7 @@ namespace SelectableBackfaceCulling
} }
} }
// Only the parts of CEntity and CObject we need // Only the parts of CObject we need
enum // m_objectCreatedBy
{
GAME_OBJECT = 1,
MISSION_OBJECT = 2,
TEMP_OBJECT = 3,
};
struct Entity
{
std::byte __pad[80];
uint8_t m_nType : 3;
std::byte __pad2[11];
FLAUtils::int16 m_modelIndex;
};
struct Object struct Object
{ {
std::byte __pad[364]; std::byte __pad[364];
@ -755,7 +743,7 @@ namespace SelectableBackfaceCulling
}; };
static void* EntityRender_Prologue_JumpBack; static void* EntityRender_Prologue_JumpBack;
__declspec(naked) static void __fastcall EntityRender_Original(Entity*) __declspec(naked) static void __fastcall EntityRender_Original(CEntity*)
{ {
_asm _asm
{ {
@ -766,7 +754,7 @@ namespace SelectableBackfaceCulling
} }
} }
static bool ShouldDisableBackfaceCulling(const Entity* entity) static bool ShouldDisableBackfaceCulling(const CEntity* entity)
{ {
const uint8_t entityType = entity->m_nType; const uint8_t entityType = entity->m_nType;
@ -797,9 +785,9 @@ namespace SelectableBackfaceCulling
} }
// If CEntity::Render is re-routed by another mod, we overwrite this later // If CEntity::Render is re-routed by another mod, we overwrite this later
static void (__fastcall *orgEntityRender)(Entity* obj) = &EntityRender_Original; static void (__fastcall *orgEntityRender)(CEntity* obj) = &EntityRender_Original;
static void __fastcall EntityRender_BackfaceCulling(Entity* obj) static void __fastcall EntityRender_BackfaceCulling(CEntity* obj)
{ {
RwScopedRenderState<rwRENDERSTATECULLMODE> cullState; RwScopedRenderState<rwRENDERSTATECULLMODE> cullState;
@ -813,15 +801,76 @@ namespace SelectableBackfaceCulling
} }
namespace SVFReadyHook // ============= Fix the construction site LOD losing its HQ model and showing at all times =============
namespace ConstructionSiteLODFix
{ {
static void* (*GetModelInfo)(const char*, int*); static bool bActivateConstructionSiteFix = false;
static int32_t MI_BLDNGST2MESH, MI_BLDNGST2MESHDAM;
static CSimpleModelInfo* Bldngst2mesh_ModelInfo;
static CSimpleModelInfo* Bldngst2meshDam_ModelInfo;
static CSimpleModelInfo* LODngst2mesh_ModelInfo;
void MatchModelIndices()
{
CSimpleModelInfo* Bldngst2mesh = reinterpret_cast<CSimpleModelInfo*>(GetModelInfo("bldngst2mesh", &MI_BLDNGST2MESH));
CSimpleModelInfo* Bldngst2meshDam = reinterpret_cast<CSimpleModelInfo*>(GetModelInfo("bldngst2meshdam", &MI_BLDNGST2MESHDAM));
CSimpleModelInfo* LODngst2mesh = reinterpret_cast<CSimpleModelInfo*>(GetModelInfo("LODngst2mesh", nullptr));
CSimpleModelInfo* LODngst2meshDam = reinterpret_cast<CSimpleModelInfo*>(GetModelInfo("LODngst2meshdam", nullptr));
const bool bHasBldngst2mesh = Bldngst2mesh != nullptr;
const bool bHasBldngst2meshDam = Bldngst2meshDam != nullptr;
const bool bHasLODngst2mesh = LODngst2mesh != nullptr;
const bool bHasLODngst2meshDam = LODngst2meshDam != nullptr;
// LODngst2meshdam doesn't exist in the vanilla game, so if it exists - a mod to fix this issue via
// the map modifications has been installed.
bActivateConstructionSiteFix = bHasBldngst2mesh && bHasBldngst2meshDam && bHasLODngst2mesh && !bHasLODngst2meshDam;
Bldngst2mesh_ModelInfo = Bldngst2mesh;
Bldngst2meshDam_ModelInfo = Bldngst2meshDam;
LODngst2mesh_ModelInfo = LODngst2mesh;
}
static void FixConstructionSiteModel(int oldModelID, int newModelID)
{
if (!bActivateConstructionSiteFix)
{
return;
}
if (oldModelID == MI_BLDNGST2MESH && newModelID == MI_BLDNGST2MESHDAM)
{
LODngst2mesh_ModelInfo->m_atomics[2] = Bldngst2meshDam_ModelInfo;
}
else if (oldModelID == MI_BLDNGST2MESHDAM && newModelID == MI_BLDNGST2MESH)
{
LODngst2mesh_ModelInfo->m_atomics[2] = Bldngst2mesh_ModelInfo;
}
}
template<std::size_t Index>
static void (__fastcall *orgReplaceWithNewModel)(CEntity* building, void*, int newModelID);
template<std::size_t Index>
static void __fastcall ReplaceWithNewModel_ConstructionSiteFix(CEntity* building, void*, int newModelID)
{
const int oldModelID = building->m_modelIndex.Get();
orgReplaceWithNewModel<Index>(building, nullptr, newModelID);
FixConstructionSiteModel(oldModelID, newModelID);
}
HOOK_EACH_FUNC(ReplaceWithNewModel, orgReplaceWithNewModel, ReplaceWithNewModel_ConstructionSiteFix);
}
namespace ModelIndicesReadyHook
{
static void (*orgInitialiseObjectData)(const char*); static void (*orgInitialiseObjectData)(const char*);
static void InitialiseObjectData_ReadySVF(const char* path) static void InitialiseObjectData_ReadySVF(const char* path)
{ {
orgInitialiseObjectData(path); orgInitialiseObjectData(path);
SVF::MarkModelNamesReady(); SVF::MarkModelNamesReady();
ConstructionSiteLODFix::MatchModelIndices();
// This is a bit dirty, but whatever // This is a bit dirty, but whatever
// Tooled Up in North Point Mall needs a "draw last" flag, or else our BFC changes break it very badly // Tooled Up in North Point Mall needs a "draw last" flag, or else our BFC changes break it very badly
@ -991,10 +1040,12 @@ void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModule
TXN_CATCH(); TXN_CATCH();
} }
bool HasModelInfo = false;
// Register CBaseModelInfo::GetModelInfo for SVF so we can resolve model names // Register CBaseModelInfo::GetModelInfo for SVF so we can resolve model names
try try
{ {
using namespace SVFReadyHook; using namespace ModelIndicesReadyHook;
auto initialiseObjectData = get_pattern("E8 ? ? ? ? 59 E8 ? ? ? ? E8 ? ? ? ? 31 DB"); auto initialiseObjectData = get_pattern("E8 ? ? ? ? 59 E8 ? ? ? ? E8 ? ? ? ? 31 DB");
auto getModelInfo = (void*(*)(const char*, int*))get_pattern("57 31 FF 55 8B 6C 24 14", -6); auto getModelInfo = (void*(*)(const char*, int*))get_pattern("57 31 FF 55 8B 6C 24 14", -6);
@ -1002,6 +1053,24 @@ void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModule
GetModelInfo = getModelInfo; GetModelInfo = getModelInfo;
InterceptCall(initialiseObjectData, orgInitialiseObjectData, InitialiseObjectData_ReadySVF); InterceptCall(initialiseObjectData, orgInitialiseObjectData, InitialiseObjectData_ReadySVF);
SVF::RegisterGetModelInfoCB(getModelInfo); SVF::RegisterGetModelInfoCB(getModelInfo);
HasModelInfo = true;
}
TXN_CATCH();
// Fix the construction site LOD losing its HQ model and showing at all times
if (HasModelInfo) try
{
using namespace ConstructionSiteLODFix;
std::array<void*, 3> replaceWithNewModel = {
get_pattern("E8 ? ? ? ? C7 85 ? ? ? ? 00 00 00 00 83 8D ? ? ? ? FF"),
get_pattern("DD D8 E8 ? ? ? ? 56", 2),
get_pattern("E8 ? ? ? ? FF 44 24 0C 83 C5 0C"),
};
HookEach_ReplaceWithNewModel(replaceWithNewModel, InterceptCall);
} }
TXN_CATCH(); TXN_CATCH();

View File

@ -181,6 +181,7 @@
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h" /> <ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h" />
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h" /> <ClInclude Include="..\SilentPatch\Utils\MemoryMgr.h" />
<ClInclude Include="..\SilentPatch\Utils\Patterns.h" /> <ClInclude Include="..\SilentPatch\Utils\Patterns.h" />
<ClInclude Include="EntityVC.h" />
<ClInclude Include="ModelInfoVC.h" /> <ClInclude Include="ModelInfoVC.h" />
<ClInclude Include="VehicleVC.h" /> <ClInclude Include="VehicleVC.h" />
</ItemGroup> </ItemGroup>

View File

@ -72,6 +72,9 @@
<ClInclude Include="..\SilentPatch\Random.h"> <ClInclude Include="..\SilentPatch\Random.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="EntityVC.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\SilentPatch\Timer.cpp"> <ClCompile Include="..\SilentPatch\Timer.cpp">