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;
m_dirtMaterials = nullptr;
delete m_apPlateMaterials;
m_apPlateMaterials = nullptr;
}
void CVehicleModelInfo::FindEditableMaterialList()
@ -103,10 +100,6 @@ void CVehicleModelInfo::SetCarCustomPlate()
{
m_plateText[0] = '\0';
m_nPlateType = -1;
m_apPlateMaterials = new PlateMaterialsData;
CCustomCarPlateMgr::SetupClump(reinterpret_cast<RpClump*>(pRwObject), m_apPlateMaterials);
}
void CVehicleModelInfo::ResetCompsForNoExtras()
@ -115,59 +108,7 @@ void CVehicleModelInfo::ResetCompsForNoExtras()
ms_compsToUse[0] = ms_compsToUse[1] = -2;
}
void CCustomCarPlateMgr::PollPlates( RpClump* clump, PlateMaterialsData* materials )
{
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)
void CCustomCarPlateMgr::SetupClumpAfterVehicleUpgrade(RpClump* pClump, void* /*unused*/, signed char nDesign)
{
UNREFERENCED_PARAMETER(nDesign);
if ( pMatsArray != nullptr )
{
PollPlates( pClump, pMatsArray );
}
}

View File

@ -222,27 +222,14 @@ public:
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
{
public:
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 field_30;
signed char m_nPlateType;
@ -344,11 +331,7 @@ public:
static signed char (*GetMapRegionPlateDesign)();
static void (*SetupMaterialPlatebackTexture)(RpMaterial* pMaterial, signed char nDesign);
static void SetupClump(RpClump* pClump, PlateMaterialsData* pMatsArray);
static void SetupClumpAfterVehicleUpgrade(RpClump* pClump, PlateMaterialsData* pMatsArray, signed char nDesign);
private:
static void PollPlates( RpClump* clump, PlateMaterialsData* materials );
static void SetupClumpAfterVehicleUpgrade(RpClump* pClump, void* /*unused*/, signed char nDesign);
};
static_assert(sizeof(CBaseModelInfo) == 0x20, "Wrong size: CBaseModelInfo");

View File

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

View File

@ -297,17 +297,41 @@ bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo)
return true;
}
static std::vector<std::pair<RpMaterial*, RwTexture*>> originalPlateMaterials;
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++ )
{
CCustomCarPlateMgr::SetupMaterialPlatebackTexture(pModelInfo->m_apPlateMaterials->m_platebacks[i], PlateDesign);
return material;
} );
return atomic;
} );
}
void CVehicle::CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo)
{
for (const auto& platesToRestore : originalPlateMaterials)
{
RpMaterialSetTexture(platesToRestore.first, platesToRestore.second);
}
originalPlateMaterials.clear();
}
void CVehicle::SetComponentRotation( RwFrame* component, eRotAxis axis, float angle, bool absolute )

View File

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