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