diff --git a/IIIFix/IIIFix.vcxproj b/IIIFix/IIIFix.vcxproj
index 20e4516..28ec42a 100644
--- a/IIIFix/IIIFix.vcxproj
+++ b/IIIFix/IIIFix.vcxproj
@@ -89,7 +89,7 @@
AnySuitable
Speed
true
- SILENTPATCH_III_VER;%(PreprocessorDefinitions)
+ SILENTPATCH_III_VER;NDEBUG;%(PreprocessorDefinitions)
D:\RWSDK\Graphics\rwsdk\include\d3d9
diff --git a/SAFix/SAFix.vcxproj b/SAFix/SAFix.vcxproj
index 753c45f..2b9ade8 100644
--- a/SAFix/SAFix.vcxproj
+++ b/SAFix/SAFix.vcxproj
@@ -71,7 +71,7 @@
AnySuitable
Speed
true
- SILENTPATCH_SA_VER;%(PreprocessorDefinitions)
+ SILENTPATCH_SA_VER;NDEBUG;%(PreprocessorDefinitions)
true
MultiThreaded
D:\RWSDK\Graphics\rwsdk\include\d3d9
diff --git a/SilentPatch/ModelInfoSA.cpp b/SilentPatch/ModelInfoSA.cpp
index 409d7fd..149d8b3 100644
--- a/SilentPatch/ModelInfoSA.cpp
+++ b/SilentPatch/ModelInfoSA.cpp
@@ -1,6 +1,20 @@
#include "StdAfx.h"
#include "ModelInfoSA.h"
+WRAPPER void CBaseModelInfo::Shutdown() { EAXJMP(0x4C4D50); }
+
+WRAPPER RwTexture* CCustomCarPlateMgr::CreatePlateTexture(const char* pText, signed char nDesign) { EAXJMP(0x6FDEA0); }
+WRAPPER bool CCustomCarPlateMgr::GeneratePlateText(char* pBuf, int nLen) { EAXJMP(0x6FD5B0); }
+WRAPPER signed char CCustomCarPlateMgr::GetMapRegionPlateDesign() { EAXJMP(0x6FD7A0); }
+WRAPPER void CCustomCarPlateMgr::SetupMaterialPlatebackTexture(RpMaterial* pMaterial, signed char nDesign) { EAXJMP(0x6FDE50); }
+
+void CVehicleModelInfo::Shutdown()
+{
+ CBaseModelInfo::Shutdown();
+
+ delete m_apPlateMaterials;
+}
+
void CVehicleModelInfo::FindEditableMaterialList()
{
std::pair MatsPair = std::make_pair(this, 0);
@@ -19,6 +33,18 @@ void CVehicleModelInfo::FindEditableMaterialList()
m_nQuaternaryColor = -1;
}
+void CVehicleModelInfo::SetCarCustomPlate()
+{
+ m_plateText[0] = '\0';
+ m_nPlateType = -1;
+
+ m_apPlateMaterials = reinterpret_cast(new DWORD_PTR[2*NUM_MAX_PLATES]);
+
+ for ( int i = 0; i < 2*NUM_MAX_PLATES; i++ )
+ m_apPlateMaterials[i] = nullptr;
+CCustomCarPlateMgr::SetupClump(reinterpret_cast(pRwObject), m_apPlateMaterials);
+}
+
RpAtomic* CVehicleModelInfo::GetEditableMaterialListCB(RpAtomic* pAtomic, void* pData)
{
RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), GetEditableMaterialListCB, pData);
@@ -38,4 +64,47 @@ RpMaterial* CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial* pMaterial,
}
}
return pMaterial;
+}
+
+static RpMaterial* PollPlateData(RpMaterial* pMaterial, void* pData)
+{
+ if ( RwTexture* pTexture = RpMaterialGetTexture(pMaterial) )
+ {
+ if ( RwTextureGetName(pTexture) )
+ {
+ if ( !_strnicmp(RwTextureGetName(pTexture), "carplate", 8) )
+ {
+ auto& pCallbackData = *static_cast*>(pData);
+
+ assert(std::get<2>(pCallbackData) < NUM_MAX_PLATES);
+ if ( std::get<2>(pCallbackData)++ < NUM_MAX_PLATES )
+ *(std::get<0>(pCallbackData)++) = pMaterial;
+ }
+ else if ( !_strnicmp(RwTextureGetName(pTexture), "carpback", 8) )
+ {
+ auto& pCallbackData = *static_cast*>(pData);
+
+ assert(std::get<3>(pCallbackData) < NUM_MAX_PLATES);
+ if ( std::get<3>(pCallbackData)++ < NUM_MAX_PLATES )
+ *(std::get<1>(pCallbackData)++) = pMaterial;
+ }
+ }
+ }
+
+
+ return pMaterial;
+}
+
+static RpAtomic* PollPlateData(RpAtomic* pAtomic, void* pData)
+{
+ RpGeometryForAllMaterials(RpAtomicGetGeometry(pAtomic), PollPlateData, pData);
+ return pAtomic;
+}
+
+void CCustomCarPlateMgr::SetupClump(RpClump* pClump, RpMaterial** pMatsArray)
+{
+ // Split pMatsArray
+ std::tuple CallbackData = std::make_tuple(pMatsArray, pMatsArray+NUM_MAX_PLATES, 0, 0);
+
+ RpClumpForAllAtomics(pClump, PollPlateData, &CallbackData);
}
\ No newline at end of file
diff --git a/SilentPatch/ModelInfoSA.h b/SilentPatch/ModelInfoSA.h
index e631d4f..da03f5d 100644
--- a/SilentPatch/ModelInfoSA.h
+++ b/SilentPatch/ModelInfoSA.h
@@ -116,7 +116,7 @@ class CAtomicModelInfo;
class CDamageAtomicModelInfo;
class CLodAtomicModelInfo;
-class CBaseModelInfo
+class NOVMT CBaseModelInfo
{
public:
unsigned int ulHashKey; // +4 Generated by CKeyGen::GetUppercaseKey(char const *) called by CBaseModelInfo::SetModelName(char const *)
@@ -190,7 +190,7 @@ public:
void AddRef();
};
-class CClumpModelInfo : public CBaseModelInfo
+class NOVMT CClumpModelInfo : public CBaseModelInfo
{
public:
int nAnimIndex;
@@ -209,13 +209,13 @@ public:
virtual void SetClump(RpClump* pClump);
};
-class CVehicleModelInfo : public CClumpModelInfo
+class NOVMT CVehicleModelInfo : public CClumpModelInfo
{
public:
- RpMaterial* m_pPlateMaterial;
+ RpMaterial** m_apPlateMaterials; // Changed in SilentPatchh
char m_plateText[8];
char field_30;
- unsigned char m_nPlateType;
+ signed char m_nPlateType;
char m_nGameName[8];
unsigned int m_dwType;
float m_fWheelSizeFront;
@@ -269,12 +269,37 @@ public:
class CAnimBlock* m_pAnimBlock;
public:
+ inline const char* GetCustomCarPlateText()
+ { return m_plateText[0] ? m_plateText : nullptr; }
+
+ virtual void Shutdown() override;
+
void FindEditableMaterialList();
+ void SetCarCustomPlate();
static RpAtomic* GetEditableMaterialListCB(RpAtomic* pAtomic, void* pData);
static RpMaterial* GetEditableMaterialListCB(RpMaterial* pMaterial, void* pData);
};
+#define NUM_MAX_PLATES 6
+
+class CCustomCarPlateMgr
+{
+ // Pretty much rewritten for SilentPatch
+private:
+ //static RpMaterial** m_pMaterialsWeWorkingWith;
+ //static unsigned char m_nCurPlateMaterial, m_nCurPlateBackMaterial;
+ //static signed char m_nCurPlateDesign;
+
+public:
+ static RwTexture* CreatePlateTexture(const char* pText, signed char nDesign);
+ static bool GeneratePlateText(char* pBuf, int nLen);
+ static signed char GetMapRegionPlateDesign();
+ static void SetupMaterialPlatebackTexture(RpMaterial* pMaterial, signed char nDesign);
+
+ static void SetupClump(RpClump* pClump, RpMaterial** pMatsArray);
+};
+
static_assert(sizeof(CBaseModelInfo) == 0x20, "Wrong size: CBaseModelInfo");
static_assert(sizeof(CClumpModelInfo) == 0x24, "Wrong size: CClumpModelInfo");
static_assert(sizeof(CVehicleModelInfo) == 0x308, "Wrong size: CvehicleModelInfo");
diff --git a/SilentPatch/StdAfx.h b/SilentPatch/StdAfx.h
index 52f0565..7317549 100644
--- a/SilentPatch/StdAfx.h
+++ b/SilentPatch/StdAfx.h
@@ -15,6 +15,8 @@
#include
#include
#include
+#include
+#include
#define RwEngineInstance (*rwengine)
#define RWFRAMESTATICPLUGINSSIZE 24
diff --git a/SilentPatch/Vehicle.cpp b/SilentPatch/Vehicle.cpp
index dfdaacf..619cf93 100644
--- a/SilentPatch/Vehicle.cpp
+++ b/SilentPatch/Vehicle.cpp
@@ -16,6 +16,74 @@ static RwObject* GetCurrentAtomicObjectCB(RwObject* pObject, void* data)
return pObject;
}
+bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo)
+{
+ char PlateText[8];
+ const char* pOverrideText = pModelInfo->GetCustomCarPlateText();
+
+ if ( pOverrideText )
+ strncpy(PlateText, pOverrideText, 8);
+ else
+ CCustomCarPlateMgr::GeneratePlateText(PlateText, 8);
+
+ PlateTexture = CCustomCarPlateMgr::CreatePlateTexture(PlateText, pModelInfo->m_nPlateType);
+ PlateDesign = pModelInfo->m_nPlateType != -1 ? pModelInfo->m_nPlateType : CCustomCarPlateMgr::GetMapRegionPlateDesign();
+
+ assert(PlateDesign >= 0 && PlateDesign < 3);
+
+ pModelInfo->m_plateText[0] = '\0';
+ pModelInfo->m_nPlateType = -1;
+
+ return true;
+}
+
+static RwTexture* pPushedTextures[NUM_MAX_PLATES];
+
+void CVehicle::CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo)
+{
+ for ( int i = 0; i < NUM_MAX_PLATES; i++ )
+ {
+ if ( pModelInfo->m_apPlateMaterials[i] )
+ {
+ RwTexture* pPlateTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[i]);
+
+ RwTextureAddRef(pPlateTex);
+ pPushedTextures[i] = pPlateTex;
+
+ RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], PlateTexture);
+ }
+
+ if ( pModelInfo->m_apPlateMaterials[NUM_MAX_PLATES+i] )
+ CCustomCarPlateMgr::SetupMaterialPlatebackTexture(pModelInfo->m_apPlateMaterials[NUM_MAX_PLATES+i], PlateDesign);
+ //RwTexture* pPlatebackTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[4+i]);
+
+ //RwTextureAddRef(pPlatebackTex);
+ //pPushedTextures[4+i] = pPlateTex;
+
+ //RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], PlateTexture);
+ }
+}
+
+
+void CVehicle::CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo)
+{
+ for ( int i = 0; i < NUM_MAX_PLATES; i++ )
+ {
+ if ( pModelInfo->m_apPlateMaterials[i] )
+ {
+ //RwTexture* pPlateTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[i]);
+
+ //RwTextureAddRef(pPlateTex);
+ //pPushedTextures[i] = pPlateTex;
+
+ RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], pPushedTextures[i]);
+ RwTextureDestroy(pPushedTextures[i]);
+ pPushedTextures[i] = nullptr;
+ }
+ }
+
+}
+
void CHeli::Render()
{
double dRotorsSpeed, dMovingRotorSpeed;
diff --git a/SilentPatch/Vehicle.h b/SilentPatch/Vehicle.h
index 756657a..6bc3710 100644
--- a/SilentPatch/Vehicle.h
+++ b/SilentPatch/Vehicle.h
@@ -2,6 +2,7 @@
#define __VEHICLE
#include "General.h"
+#include "ModelInfoSA.h"
struct CVehicleFlags
{
@@ -94,7 +95,11 @@ protected:
signed int m_nTimeTillWeNeedThisCar;
BYTE __pad4[56];
CEntity* pDamagingEntity;
- BYTE __pad3[144];
+ BYTE __pad3[116];
+ char padpad, padpad2, padpad3;
+ signed char PlateDesign;
+ RwTexture* PlateTexture;
+ BYTE __pad5[20];
public:
CVehicleFlags& GetVehicleFlags()
@@ -104,6 +109,10 @@ public:
virtual void Render() override;
+ bool CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo);
+ void CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo);
+ void CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo);
+
static void SetComponentAtomicAlpha(RpAtomic* pAtomic, int nAlpha);
};
diff --git a/SilentPatch/dllmain.cpp b/SilentPatch/dllmain.cpp
index 2990078..af6b5a1 100644
--- a/SilentPatch/dllmain.cpp
+++ b/SilentPatch/dllmain.cpp
@@ -51,6 +51,8 @@ WRAPPER RwRaster* RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, R
WRAPPER RwRaster* RwRasterSetFromImage(RwRaster* raster, RwImage* image) { WRAPARG(raster); WRAPARG(image); EAXJMP(0x804290); }
WRAPPER RwBool RwImageDestroy(RwImage* image) { WRAPARG(image); EAXJMP(0x802740); }
WRAPPER RwImage* RwImageFindRasterFormat(RwImage* ipImage, RwInt32 nRasterType, RwInt32* npWidth, RwInt32* npHeight, RwInt32* npDepth, RwInt32* npFormat) { WRAPARG(ipImage); WRAPARG(nRasterType); WRAPARG(npWidth); WRAPARG(npHeight); WRAPARG(npDepth); WRAPARG(npFormat); EAXJMP(0x8042C0); }
+WRAPPER RpMaterial *RpMaterialSetTexture(RpMaterial *material, RwTexture *texture) { EAXJMP(0x74DBC0); }
+WRAPPER RwBool RwTextureDestroy(RwTexture* texture) { EAXJMP(0x7F3820); }
WRAPPER bool CanSeeOutSideFromCurrArea() { EAXJMP(0x53C4A0); }
@@ -2377,6 +2379,20 @@ __forceinline void Patch_SA_10()
// Zones fix
InjectHook(0x572130, GetCurrentZoneLockedOrUnlocked, PATCH_JUMP);
+ // Properly random numberplates
+ DWORD* pVMT = *(DWORD**)0x4C75FC;
+ void* pFunc;
+ _asm
+ {
+ mov eax, offset CVehicleModelInfo::Shutdown
+ mov [pFunc], eax
+ }
+ Patch(&pVMT[7], pFunc);
+ InjectMethodVP(0x4C9660, CVehicleModelInfo::SetCarCustomPlate, PATCH_NOTHING);
+ InjectMethodVP(0x6D6A58, CVehicle::CustomCarPlate_TextureCreate, PATCH_NOTHING);
+ InjectMethodVP(0x6D651C, CVehicle::CustomCarPlate_BeforeRenderingStart, PATCH_NOTHING);
+ InjectMethodVP(0x6D0E53, CVehicle::CustomCarPlate_AfterRenderingStop, PATCH_NOTHING);
+
// Fixed police scanner names
char* pScannerNames = *(char**)0x4E72D4;
strncpy(pScannerNames + (8*113), "WESTP", 8);
diff --git a/VCFix/VCFix.vcxproj b/VCFix/VCFix.vcxproj
index 09b5505..a13c83c 100644
--- a/VCFix/VCFix.vcxproj
+++ b/VCFix/VCFix.vcxproj
@@ -67,7 +67,7 @@
MaxSpeed
true
true
- SILENTPATCH_VC_VER;%(PreprocessorDefinitions)
+ SILENTPATCH_VC_VER;NDEBUG;%(PreprocessorDefinitions)
true
MultiThreaded
false