diff --git a/SAFix/SAFix.vcxproj b/SAFix/SAFix.vcxproj
index e58e8a1..b0e45fa 100644
--- a/SAFix/SAFix.vcxproj
+++ b/SAFix/SAFix.vcxproj
@@ -78,7 +78,7 @@
Use
- false
+ true
true
true
Windows
diff --git a/SilentPatch/General.cpp b/SilentPatch/General.cpp
index 06c52a0..47647ef 100644
--- a/SilentPatch/General.cpp
+++ b/SilentPatch/General.cpp
@@ -9,3 +9,51 @@ WRAPPER void CEntity::UpdateRW() { EAXJMP(0x446F90); }
WRAPPER void CEntity::RegisterReference(CEntity** pAddress) { WRAPARG(pAddress); EAXJMP(0x571B70); }
WRAPPER void CEntity::CleanUpOldReference(CEntity** pAddress) { WRAPARG(pAddress); EAXJMP(0x571A00); }
WRAPPER void CEntity::Render() { EAXJMP(0x534310); }
+
+static RwTexture*& ms_pRemapTexture = *(RwTexture**)0xB4E47C;
+static unsigned char* ms_currentCol = *(unsigned char**)0x4C84C8;
+
+WRAPPER RpAtomic* SetEditableMaterialsCB(RpAtomic* pMaterial, void* pData) { WRAPARG(pMaterial); WRAPARG(pData); EAXJMP(0x4C83E0); }
+
+static void SetVehicleColour(unsigned char primaryColour, unsigned char secondaryColour, unsigned char tertiaryColour, unsigned char quaternaryColour)
+{
+ ms_currentCol[0] = primaryColour;
+ ms_currentCol[1] = secondaryColour;
+ ms_currentCol[2] = tertiaryColour;
+ ms_currentCol[3] = quaternaryColour;
+}
+
+static void ResetEditableMaterials(std::pair* pData)
+{
+ for ( auto* i = pData; i->first; i++ )
+ *static_cast(i->first) = i->second;
+}
+
+void CObject::Render()
+{
+ if ( m_bDoNotRender )
+ return;
+
+ bool bCallRestore;
+ std::pair materialRestoreData[16];
+
+ if ( m_wCarPartModelIndex != -1 && m_nObjectType == 3 && bObjectFlag7 && RwObjectGetType(m_pRwObject) == rpATOMIC )
+ {
+ auto* pData = materialRestoreData;
+
+ ms_pRemapTexture = m_pPaintjobTex;
+ SetVehicleColour(m_nCarColor[0], m_nCarColor[1], m_nCarColor[2], m_nCarColor[3]);
+
+ SetEditableMaterialsCB(reinterpret_cast(m_pRwObject), &pData);
+ pData->first = nullptr;
+
+ bCallRestore = true;
+ }
+ else
+ bCallRestore = false;
+
+ CEntity::Render();
+
+ if ( bCallRestore )
+ ResetEditableMaterials(materialRestoreData);
+}
\ No newline at end of file
diff --git a/SilentPatch/General.h b/SilentPatch/General.h
index 47e462e..f9a0b91 100644
--- a/SilentPatch/General.h
+++ b/SilentPatch/General.h
@@ -44,7 +44,8 @@ public:
((One.b * OneStrength) + (Two.b * TwoStrength) + (Three.b * ThreeStrength))/TotalStrength,
((One.a * OneStrength) + (Two.a * TwoStrength) + (Three.a * ThreeStrength))/TotalStrength); }
- void BaseColors__Constructor();
+ // SilentPatch
+ CRGBA* BlendGangColour(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
};
class CRect
@@ -277,7 +278,95 @@ public:
: CEntity(0) {}
};
+class NOVMT CObject : public CPhysical
+{
+public:
+ void* m_pObjectList;
+ unsigned char m_nObjectType;
+ __int8 field_13D;
+ __int16 field_13E;
+ bool bObjectFlag0 : 1;
+ bool bObjectFlag1 : 1;
+ bool bObjectFlag2 : 1;
+ bool bObjectFlag3 : 1;
+ bool bObjectFlag4 : 1;
+ bool bObjectFlag5 : 1;
+ bool m_bIsExploded : 1;
+ bool bObjectFlag7 : 1;
+ bool m_bIsLampPost : 1;
+ bool m_bIsTargetable : 1;
+ bool m_bIsBroken : 1;
+ bool m_bTrainCrossEnabled : 1;
+ bool m_bIsPhotographed : 1;
+ bool m_bIsLiftable : 1;
+ bool bObjectFlag14 : 1;
+ bool m_bIsDoor : 1;
+ bool m_bHasNoModel : 1;
+ bool m_bIsScaled : 1;
+ bool m_bCanBeAttachedToMagnet : 1;
+ bool bObjectFlag19 : 1;
+ bool bObjectFlag20 : 1;
+ bool bObjectFlag21 : 1;
+ bool m_bFadingIn : 1;
+ bool m_bAffectedByColBrightness : 1;
+ bool bObjectFlag24 : 1;
+ bool m_bDoNotRender : 1;
+ bool m_bFadingIn2 : 1;
+ bool bObjectFlag27 : 1;
+ bool bObjectFlag28 : 1;
+ bool bObjectFlag29 : 1;
+ bool bObjectFlag30 : 1;
+ bool bObjectFlag31 : 1;
+ unsigned char m_nColDamageEffect;
+ __int8 field_145;
+ __int8 field_146;
+ __int8 field_147;
+ unsigned char m_nLastWeaponDamage;
+ unsigned char m_nColBrightness;
+ __int16 m_wCarPartModelIndex;
+ // this is used for detached car parts
+ unsigned __int8 m_nCarColor[4];
+ // time when this object must be deleted
+ unsigned __int32 m_dwRemovalTime;
+ float m_fHealth;
+ // this is used for door objects
+ float m_fDoorStartAngle;
+ float m_fScale;
+ void* m_pObjectInfo;
+ void* m_pFire; // CFire *
+ short field_168;
+ // this is used for detached car parts
+ short m_wPaintjobTxd;
+ // this is used for detached car parts
+ RwTexture* m_pPaintjobTex;
+ void* m_pDummyObject;
+ // time when particles must be stopped
+ signed int m_dwTimeToStopParticles;
+ float m_fParticlesIntensity;
+
+public:
+ virtual void Render() override;
+};
+
+class CZoneInfo
+{
+public:
+ unsigned char GangDensity[10];
+ unsigned char DrugDealerCounter;
+ CRGBA ZoneColour;
+ bool unk1 : 1;
+ bool unk2 : 1;
+ bool unk3 : 1;
+ bool unk4 : 1;
+ bool unk5 : 1;
+ bool bUseColour : 1;
+ bool bInGangWar : 1;
+ bool bNoCops : 1;
+ unsigned char flags;
+};
+
static_assert(sizeof(CEntity) == 0x38, "Wrong size: CEntity");
static_assert(sizeof(CPhysical) == 0x138, "Wrong size: CPhysical");
+static_assert(sizeof(CObject) == 0x17C, "Wrong size: CObject");
#endif
\ No newline at end of file
diff --git a/SilentPatch/dllmain.cpp b/SilentPatch/dllmain.cpp
index ba9750c..c7f0f67 100644
--- a/SilentPatch/dllmain.cpp
+++ b/SilentPatch/dllmain.cpp
@@ -1872,12 +1872,35 @@ FLACInit_DontFallBack:
}
}
+void __declspec(naked) LightMaterialsFix()
+{
+ _asm
+ {
+ mov [esi], edi
+ mov ebx, [ecx]
+ lea esi, [edx+4]
+ mov [ebx+4], esi
+ mov edi, [esi]
+ mov [ebx+8], edi
+ add esi, 4
+ mov [ebx+12], esi
+ mov edi, [esi]
+ mov [ebx+16], edi
+ add ebx, 20
+ mov [ecx], ebx
+ retn
+ }
+}
+
static BOOL (*IsAlreadyRunning)();
static void (*TheScriptsLoad)();
static unsigned char* ScriptSpace = *(unsigned char**)0x5D5380;
static int* ScriptParams = *(int**)0x48995B;
+static CZoneInfo*& pCurrZoneInfo = **(CZoneInfo***)0x58ADB1;
+static CRGBA* HudColour = *(CRGBA**)0x58ADF6;
+
static void BasketballFix(unsigned char* pBuf, int nSize)
{
for ( int i = 0, hits = 0; i < nSize && hits < 7; i++, pBuf++ )
@@ -1934,6 +1957,14 @@ void StartNewMission_BasketballFix()
BasketballFix(ScriptSpace+200000, 69000);
}
+CRGBA* CRGBA::BlendGangColour(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ *this = Blend(CRGBA(r, g, b), pCurrZoneInfo->ZoneColour.a, HudColour[3], static_cast(255-pCurrZoneInfo->ZoneColour.a));
+ this->a = a;
+
+ return this;
+}
+
static const float fSteamSubtitleSizeX = 0.45f;
static const float fSteamSubtitleSizeY = 0.9f;
static const float fSteamRadioNamePosY = 33.0f;
@@ -2014,6 +2045,26 @@ BOOL InjectDelayedPatches_10()
Patch(0x4E9F38, &fSteamRadioNameSizeX);
}
+ if ( GetPrivateProfileInt("SilentPatch", "ColouredZoneNames", FALSE, ".\\SilentPatchSA.ini") != FALSE )
+ {
+ // Coloured zone names
+ Patch(0x58ADBE, 0x0E75);
+ Patch(0x58ADC5, 0x0775);
+
+ InjectMethodVP(0x58ADE4, CRGBA::BlendGangColour, PATCH_NOTHING);
+ }
+ else
+ {
+ Patch(0x58ADAE, 0xEB);
+ }
+
+ // ImVehFt conflicts
+ if ( GetModuleHandle("ImVehFt.asi") == nullptr )
+ {
+ InjectHook(0x4C830C, LightMaterialsFix, PATCH_CALL);
+ InjectMethodVP(0x59F180, CObject::Render, PATCH_JUMP);
+ }
+
return FALSE;
}
return TRUE;
@@ -2061,10 +2112,6 @@ __forceinline void Patch_SA_10()
// No framedelay
Patch(0x53E923, 0x42EB56);
- // Coloured zone names
- Patch(0x58ADBE, 0x0E75);
- Patch(0x58ADC5, 0x0775);
-
// Disable re-initialization of DirectInput mouse device by the game
Patch(0x576CCC, 0xEB);
Patch(0x576EBA, 0xEB);
@@ -2209,7 +2256,7 @@ __forceinline void Patch_SA_Steam()
{
using namespace MemoryVP;
- InjectHook(0x72F058, HandleMoonStuffStub_Steam, PATCH_JUMP);
+ //InjectHook(0x72F058, HandleMoonStuffStub_Steam, PATCH_JUMP);
}
#endif