Remade custom numberplates

Removed the "cache" to make the code simpler,
and resolve a SP bug where number plates from
the upgrade parts broke any number plates
on future spawns of the same car model.
This commit is contained in:
Silent 2024-01-28 20:49:52 +01:00
parent 99f57a0855
commit 7787d92dc7
No known key found for this signature in database
GPG Key ID: AE53149BB0C45AF1
5 changed files with 43 additions and 94 deletions

View File

@ -48,9 +48,6 @@ void CVehicleModelInfo::Shutdown()
delete[] m_dirtMaterials; delete[] m_dirtMaterials;
m_dirtMaterials = nullptr; m_dirtMaterials = nullptr;
delete m_apPlateMaterials;
m_apPlateMaterials = nullptr;
} }
void CVehicleModelInfo::FindEditableMaterialList() void CVehicleModelInfo::FindEditableMaterialList()
@ -103,10 +100,6 @@ void CVehicleModelInfo::SetCarCustomPlate()
{ {
m_plateText[0] = '\0'; m_plateText[0] = '\0';
m_nPlateType = -1; m_nPlateType = -1;
m_apPlateMaterials = new PlateMaterialsData;
CCustomCarPlateMgr::SetupClump(reinterpret_cast<RpClump*>(pRwObject), m_apPlateMaterials);
} }
void CVehicleModelInfo::ResetCompsForNoExtras() void CVehicleModelInfo::ResetCompsForNoExtras()
@ -115,59 +108,7 @@ void CVehicleModelInfo::ResetCompsForNoExtras()
ms_compsToUse[0] = ms_compsToUse[1] = -2; ms_compsToUse[0] = ms_compsToUse[1] = -2;
} }
void CCustomCarPlateMgr::PollPlates( RpClump* clump, PlateMaterialsData* materials ) void CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade(RpClump* pClump, void* /*unused*/, signed char nDesign)
{
std::vector<RpMaterial*> carplates;
std::vector<RpMaterial*> carpbacks;
RpClumpForAllAtomics( clump, [&] ( RpAtomic* atomic ) -> RpAtomic* {
RpGeometryForAllMaterials( RpAtomicGetGeometry(atomic), [&] ( RpMaterial* material ) -> RpMaterial* {
if ( RwTexture* texture = RpMaterialGetTexture(material) )
{
if ( const char* texName = RwTextureGetName(texture) )
{
if ( strcmp( texName, "carplate" ) == 0 )
{
carplates.push_back( material );
}
else if ( strcmp( texName, "carpback" ) == 0 )
{
carpbacks.push_back( material );
}
}
}
return material;
} );
return atomic;
} );
materials->m_numPlates = carplates.size();
materials->m_numPlatebacks = carpbacks.size();
if ( materials->m_numPlates > 0 )
{
materials->m_plates = new RpMaterial* [materials->m_numPlates];
std::copy( carplates.begin(), carplates.end(), stdext::make_checked_array_iterator(materials->m_plates, materials->m_numPlates) );
}
if ( materials->m_numPlatebacks > 0 )
{
materials->m_platebacks = new RpMaterial* [materials->m_numPlatebacks];
std::copy( carpbacks.begin(), carpbacks.end(), stdext::make_checked_array_iterator(materials->m_platebacks, materials->m_numPlatebacks) );
}
}
void CCustomCarPlateMgr::SetupClump(RpClump* pClump, PlateMaterialsData* pMatsArray)
{
PollPlates( pClump, pMatsArray );
}
void CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade(RpClump* pClump, PlateMaterialsData* pMatsArray, signed char nDesign)
{ {
UNREFERENCED_PARAMETER(nDesign); UNREFERENCED_PARAMETER(nDesign);
if ( pMatsArray != nullptr )
{
PollPlates( pClump, pMatsArray );
}
} }

View File

@ -222,27 +222,14 @@ public:
virtual void SetClump(RpClump* pClump); virtual void SetClump(RpClump* pClump);
}; };
struct PlateMaterialsData // Added in SilentPatch
{
RpMaterial** m_plates = nullptr;
RpMaterial** m_platebacks = nullptr;
size_t m_numPlates = 0;
size_t m_numPlatebacks = 0;
~PlateMaterialsData()
{
delete[] m_plates;
delete[] m_platebacks;
}
};
class NOVMT CVehicleModelInfo : public CClumpModelInfo class NOVMT CVehicleModelInfo : public CClumpModelInfo
{ {
public: public:
static const size_t PLATE_TEXT_LEN = 8; static const size_t PLATE_TEXT_LEN = 8;
PlateMaterialsData* m_apPlateMaterials; // Changed in SilentPatch // m_pCustomPlateMaterial in the stock game, m_apPlateMaterials in older SilentPatch,
// now entirely deprecated. Points to a dummy variable just to satisfy some existing null checks
void* __removedInSilentPatch;
char m_plateText[PLATE_TEXT_LEN]; char m_plateText[PLATE_TEXT_LEN];
char field_30; char field_30;
signed char m_nPlateType; signed char m_nPlateType;
@ -344,11 +331,7 @@ public:
static signed char (*GetMapRegionPlateDesign)(); static signed char (*GetMapRegionPlateDesign)();
static void (*SetupMaterialPlatebackTexture)(RpMaterial* pMaterial, signed char nDesign); static void (*SetupMaterialPlatebackTexture)(RpMaterial* pMaterial, signed char nDesign);
static void SetupClump(RpClump* pClump, PlateMaterialsData* pMatsArray); static void SetupClumpAfterVehicleUpgrade(RpClump* pClump, void* /*unused*/, signed char nDesign);
static void SetupClumpAfterVehicleUpgrade(RpClump* pClump, PlateMaterialsData* pMatsArray, signed char nDesign);
private:
static void PollPlates( RpClump* clump, PlateMaterialsData* materials );
}; };
static_assert(sizeof(CBaseModelInfo) == 0x20, "Wrong size: CBaseModelInfo"); static_assert(sizeof(CBaseModelInfo) == 0x20, "Wrong size: CBaseModelInfo");

View File

@ -919,7 +919,11 @@ CVehicleModelInfo* (__thiscall *orgVehicleModelInfoCtor)(CVehicleModelInfo*);
CVehicleModelInfo* __fastcall VehicleModelInfoCtor(CVehicleModelInfo* me) CVehicleModelInfo* __fastcall VehicleModelInfoCtor(CVehicleModelInfo* me)
{ {
orgVehicleModelInfoCtor(me); orgVehicleModelInfoCtor(me);
me->m_apPlateMaterials = nullptr;
// Hack to satisfy some null checks
static uintptr_t DUMMY;
me->__removedInSilentPatch = &DUMMY;
me->m_dirtMaterials = nullptr; me->m_dirtMaterials = nullptr;
me->m_numDirtMaterials = 0; me->m_numDirtMaterials = 0;
std::fill( std::begin( me->m_staticDirtMaterials ), std::end( me->m_staticDirtMaterials ), nullptr ); std::fill( std::begin( me->m_staticDirtMaterials ), std::end( me->m_staticDirtMaterials ), nullptr );
@ -2947,13 +2951,13 @@ BOOL InjectDelayedPatches_10()
// Properly random numberplates // Properly random numberplates
DWORD* pVMT = *(DWORD**)0x4C75FC; DWORD* pVMT = *(DWORD**)0x4C75FC;
Patch(&pVMT[7], &CVehicleModelInfo::Shutdown_Stub); Patch(&pVMT[7], &CVehicleModelInfo::Shutdown_Stub);
Patch<BYTE>(0x6D0E43, 0xEB);
InjectHook(0x4C9660, &CVehicleModelInfo::SetCarCustomPlate); InjectHook(0x4C9660, &CVehicleModelInfo::SetCarCustomPlate);
InjectHook(0x6D6A58, &CVehicle::CustomCarPlate_TextureCreate); InjectHook(0x6D6A58, &CVehicle::CustomCarPlate_TextureCreate);
InjectHook(0x6D651C, &CVehicle::CustomCarPlate_BeforeRenderingStart); InjectHook(0x6D651C, &CVehicle::CustomCarPlate_BeforeRenderingStart);
InjectHook(0x6FDFE0, CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade, HookType::Jump); InjectHook(0x6FDFE0, CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade, HookType::Jump);
//InjectMethodVP(0x6D0E53, CVehicle::CustomCarPlate_AfterRenderingStop, PATCH_NOTHING); InjectHook(0x6D0E53, &CVehicle::CustomCarPlate_AfterRenderingStop);
Nop(0x6D6517, 2); Nop(0x6D6517, 2);
Nop(0x6D0E43, 2);
} }
// SSE conflicts // SSE conflicts
@ -3383,7 +3387,6 @@ BOOL InjectDelayedPatches_11()
// Properly random numberplates // Properly random numberplates
DWORD* pVMT = *(DWORD**)0x4C767C; DWORD* pVMT = *(DWORD**)0x4C767C;
Patch(&pVMT[7], &CVehicleModelInfo::Shutdown_Stub); Patch(&pVMT[7], &CVehicleModelInfo::Shutdown_Stub);
Patch<BYTE>(0x6D1663, 0xEB);
InjectHook(0x4C984D, &CVehicleModelInfo::SetCarCustomPlate); InjectHook(0x4C984D, &CVehicleModelInfo::SetCarCustomPlate);
InjectHook(0x6D7288, &CVehicle::CustomCarPlate_TextureCreate); InjectHook(0x6D7288, &CVehicle::CustomCarPlate_TextureCreate);
InjectHook(0x6D6D4C, &CVehicle::CustomCarPlate_BeforeRenderingStart); InjectHook(0x6D6D4C, &CVehicle::CustomCarPlate_BeforeRenderingStart);
@ -3560,12 +3563,10 @@ BOOL InjectDelayedPatches_Steam()
// Properly random numberplates // Properly random numberplates
DWORD* pVMT = *(DWORD**)0x4D1E9A; DWORD* pVMT = *(DWORD**)0x4D1E9A;
Patch(&pVMT[7], &CVehicleModelInfo::Shutdown_Stub); Patch(&pVMT[7], &CVehicleModelInfo::Shutdown_Stub);
Patch<BYTE>(0x70C094, 0xEB);
InjectHook(0x4D3F65, &CVehicleModelInfo::SetCarCustomPlate); InjectHook(0x4D3F65, &CVehicleModelInfo::SetCarCustomPlate);
InjectHook(0x711F28, &CVehicle::CustomCarPlate_TextureCreate); InjectHook(0x711F28, &CVehicle::CustomCarPlate_TextureCreate);
InjectHook(0x71194D, &CVehicle::CustomCarPlate_BeforeRenderingStart); InjectHook(0x71194D, &CVehicle::CustomCarPlate_BeforeRenderingStart);
InjectHook(0x736BD0, CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade, HookType::Jump); InjectHook(0x736BD0, CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade, HookType::Jump);
//InjectMethodVP(0x6D0E53, CVehicle::CustomCarPlate_AfterRenderingStop, PATCH_NOTHING);
Nop(0x711948, 2); Nop(0x711948, 2);
} }

View File

@ -297,17 +297,41 @@ bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo)
return true; return true;
} }
static std::vector<std::pair<RpMaterial*, RwTexture*>> originalPlateMaterials;
void CVehicle::CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo) void CVehicle::CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo)
{ {
for ( size_t i = 0; i < pModelInfo->m_apPlateMaterials->m_numPlates; i++ ) RpClumpForAllAtomics(reinterpret_cast<RpClump*>(m_pRwObject), [&] (RpAtomic* atomic) -> RpAtomic* {
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), [&] (RpMaterial* material) -> RpMaterial* {
if ( RwTexture* texture = RpMaterialGetTexture(material) )
{ {
RpMaterialSetTexture(pModelInfo->m_apPlateMaterials->m_plates[i], PlateTexture); if ( const char* texName = RwTextureGetName(texture) )
{
if ( strcmp( texName, "carplate" ) == 0 )
{
originalPlateMaterials.emplace_back(material, texture);
RpMaterialSetTexture(material, PlateTexture);
}
else if ( strcmp( texName, "carpback" ) == 0 )
{
originalPlateMaterials.emplace_back(material, texture);
CCustomCarPlateMgr::SetupMaterialPlatebackTexture(material, PlateDesign);
}
}
} }
for ( size_t i = 0; i < pModelInfo->m_apPlateMaterials->m_numPlatebacks; i++ ) return material;
} );
return atomic;
} );
}
void CVehicle::CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo)
{
for (const auto& platesToRestore : originalPlateMaterials)
{ {
CCustomCarPlateMgr::SetupMaterialPlatebackTexture(pModelInfo->m_apPlateMaterials->m_platebacks[i], PlateDesign); RpMaterialSetTexture(platesToRestore.first, platesToRestore.second);
} }
originalPlateMaterials.clear();
} }
void CVehicle::SetComponentRotation( RwFrame* component, eRotAxis axis, float angle, bool absolute ) void CVehicle::SetComponentRotation( RwFrame* component, eRotAxis axis, float angle, bool absolute )

View File

@ -260,7 +260,7 @@ public:
bool CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo); bool CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo);
void CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo); void CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo);
//void CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo); void CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo);
bool HasFirelaLadder() const; bool HasFirelaLadder() const;
void* PlayPedHitSample_GetColModel(); void* PlayPedHitSample_GetColModel();