mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-11-21 21:12:29 +01:00
III/VC: Apply the environment mapping on extra components
Also includes an INI exception list "ExtraCompSpecularityExceptions" for cars with incorrectly set specular on extras, like Stallion and Mesa Grande
This commit is contained in:
parent
f72f85ecd6
commit
858abbd342
@ -5,6 +5,8 @@
|
||||
#include "StoredCar.h"
|
||||
#include "SVF.h"
|
||||
|
||||
#include "Utils/DelimStringReader.h"
|
||||
|
||||
#include <rwcore.h>
|
||||
|
||||
RwCamera*& Camera = **hook::get_pattern<RwCamera**>( "A1 ? ? ? ? D8 88 ? ? ? ?", 1 );
|
||||
@ -104,6 +106,30 @@ namespace CompsToUseFix
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ============= Extra component specularity exceptions =============
|
||||
namespace ExtraCompSpecularity
|
||||
{
|
||||
void ReadExtraCompSpecularityExceptions(const wchar_t* pPath)
|
||||
{
|
||||
constexpr size_t SCRATCH_PAD_SIZE = 32767;
|
||||
WideDelimStringReader reader(SCRATCH_PAD_SIZE);
|
||||
|
||||
GetPrivateProfileSectionW(L"ExtraCompSpecularityExceptions", reader.GetBuffer(), reader.GetSize(), pPath);
|
||||
while (const wchar_t* str = reader.GetString())
|
||||
{
|
||||
int32_t toList = wcstol(str, nullptr, 0);
|
||||
if ( toList > 0 )
|
||||
SVF::RegisterFeature(toList, SVF::Feature::_INTERNAL_NO_SPECULARITY_ON_EXTRAS);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpecularityExcluded(int32_t modelID)
|
||||
{
|
||||
return SVF::ModelHasFeature(modelID, SVF::Feature::_INTERNAL_NO_SPECULARITY_ON_EXTRAS);
|
||||
}
|
||||
}
|
||||
|
||||
// ============= Delayed patches =============
|
||||
namespace DelayedPatches
|
||||
{
|
||||
@ -266,6 +292,8 @@ namespace Common {
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
|
||||
ExtraCompSpecularity::ReadExtraCompSpecularityExceptions(wcModulePath);
|
||||
|
||||
// Corrected taxi light placement for Taxi
|
||||
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 )
|
||||
{
|
||||
|
@ -1,5 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ExtraCompSpecularity
|
||||
{
|
||||
void ReadExtraCompSpecularityExceptions(const wchar_t* pPath);
|
||||
bool SpecularityExcluded(int32_t modelID);
|
||||
}
|
||||
namespace Common
|
||||
{
|
||||
namespace Patches
|
||||
|
@ -18,6 +18,10 @@ namespace SVF
|
||||
VICE_CHEETAH_SIREN,
|
||||
#endif
|
||||
|
||||
#if _GTA_III || _GTA_VC
|
||||
_INTERNAL_NO_SPECULARITY_ON_EXTRAS, // Band-aid fix for leather roofs being reflective now that envmaps are applied on them
|
||||
#endif
|
||||
|
||||
#if _GTA_SA
|
||||
// Those are fully controlled by SilentPatch
|
||||
PHOENIX_FLUTTER,
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "Utils/MemoryMgr.h"
|
||||
#include "Utils/MemoryMgr.GTA.h"
|
||||
#include "Utils/Patterns.h"
|
||||
|
||||
// Move this to ModUtils when it matures a bit more
|
||||
#define HOOK_EACH_FUNC_CTR(name, ctr, origFunc, hook) \
|
||||
|
@ -1,8 +1,65 @@
|
||||
#include "StdAfx.h"
|
||||
#include "ModelInfoIII.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include "RWUtils.hpp"
|
||||
|
||||
RpAtomic* (*CVehicleModelInfo::SetEnvironmentMapCB)(RpAtomic* atomic, void* data) = hook::get_pattern<RpAtomic*(RpAtomic*, void*)>("8B 5C 24 14 C6 44 24", -5);
|
||||
|
||||
// This is actually CBaseModelInfo, but we currently don't have it defined
|
||||
CVehicleModelInfo**& ms_modelInfoPtrs = *hook::get_pattern<CVehicleModelInfo**>("8B 2C 85 ? ? ? ? 89 E9", 3);
|
||||
int32_t& numModelInfos = *hook::get_pattern<int32_t>("81 FD ? ? ? ? 7C B7 31 C0", 2);
|
||||
|
||||
static void RemoveSpecularityFromAtomic(RpAtomic* atomic)
|
||||
{
|
||||
RpGeometry* geometry = RpAtomicGetGeometry(atomic);
|
||||
if (geometry != nullptr)
|
||||
{
|
||||
RpGeometryForAllMaterials(geometry, [](RpMaterial* material)
|
||||
{
|
||||
bool bRemoveSpecularity = false;
|
||||
|
||||
// Only remove specularity from the body materials, keep glass intact.
|
||||
// This is only done on a best-effort basis, as mods can fine-tune it better
|
||||
// and just remove the model from the exceptions list
|
||||
RwTexture* texture = RpMaterialGetTexture(material);
|
||||
if (texture != nullptr)
|
||||
{
|
||||
if (strstr(RwTextureGetName(texture), "glass") == nullptr && strstr(RwTextureGetMaskName(texture), "glass") == nullptr)
|
||||
{
|
||||
bRemoveSpecularity = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bRemoveSpecularity)
|
||||
{
|
||||
RpMaterialGetSurfaceProperties(material)->specular = 0.0f;
|
||||
}
|
||||
return material;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleModelInfo::SetNearDistanceForLOD_SilentPatch()
|
||||
{
|
||||
// 100.0f for real LOD's, 0.0f otherwise
|
||||
m_lodDistances[2] = _strnicmp( m_name, "lod", 3 ) == 0 ? 100.0f : 0.0f;
|
||||
}
|
||||
|
||||
void CVehicleModelInfo::SetEnvironmentMap_ExtraComps()
|
||||
{
|
||||
std::invoke(orgSetEnvironmentMap, this);
|
||||
|
||||
const int32_t modelID = std::distance(ms_modelInfoPtrs, std::find(ms_modelInfoPtrs, ms_modelInfoPtrs+numModelInfos, this));
|
||||
const bool bRemoveSpecularity = ExtraCompSpecularity::SpecularityExcluded(modelID);
|
||||
for (int32_t i = 0; i < m_numComps; i++)
|
||||
{
|
||||
if (bRemoveSpecularity)
|
||||
{
|
||||
RemoveSpecularityFromAtomic(m_comps[i]);
|
||||
}
|
||||
|
||||
SetEnvironmentMapCB(m_comps[i], m_envMap);
|
||||
AttachCarPipeToRwObject(reinterpret_cast<RwObject*>(m_comps[i]));
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
#include <cstdint>
|
||||
#include "Maths.h"
|
||||
|
||||
#include <rwcore.h>
|
||||
#include <rpworld.h>
|
||||
|
||||
// This really belongs in Maths.h but San Andreas optimized those structured heavily...
|
||||
struct CColSphere
|
||||
{
|
||||
@ -90,4 +93,24 @@ public:
|
||||
void SetNearDistanceForLOD_SilentPatch();
|
||||
};
|
||||
|
||||
static_assert(sizeof(CSimpleModelInfo) == 0x4C, "Wrong size: CSimpleModelInfo");
|
||||
static_assert(sizeof(CSimpleModelInfo) == 0x4C, "Wrong size: CSimpleModelInfo");
|
||||
|
||||
class CVehicleModelInfo
|
||||
{
|
||||
private:
|
||||
std::byte __pad[472];
|
||||
RwTexture* m_envMap;
|
||||
RpAtomic* m_comps[6];
|
||||
int32_t m_numComps;
|
||||
|
||||
public:
|
||||
static RpAtomic* (*SetEnvironmentMapCB)(RpAtomic* atomic, void* data);
|
||||
|
||||
static inline void (CVehicleModelInfo::*orgSetEnvironmentMap)();
|
||||
void SetEnvironmentMap_ExtraComps();
|
||||
|
||||
// For SkyGfx interop
|
||||
static void AttachCarPipeToRwObject_Default(RwObject*) { }
|
||||
static inline void (*AttachCarPipeToRwObject)(RwObject* object) = &AttachCarPipeToRwObject_Default;
|
||||
};
|
||||
static_assert(sizeof(CVehicleModelInfo) == 0x1F8, "Wrong size: CVehicleModelInfo");
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <memory>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include "Utils/ModuleList.hpp"
|
||||
#include "Utils/Patterns.h"
|
||||
#include "Utils/ScopedUnprotect.hpp"
|
||||
|
||||
@ -548,6 +549,18 @@ void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModul
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
|
||||
const ModuleList moduleList;
|
||||
|
||||
const HMODULE skygfxModule = moduleList.Get(L"skygfx");
|
||||
if (skygfxModule != nullptr)
|
||||
{
|
||||
auto attachCarPipe = reinterpret_cast<void(*)(RwObject*)>(GetProcAddress(skygfxModule, "AttachCarPipeToRwObject"));
|
||||
if (attachCarPipe != nullptr)
|
||||
{
|
||||
CVehicleModelInfo::AttachCarPipeToRwObject = attachCarPipe;
|
||||
}
|
||||
}
|
||||
|
||||
// Locale based metric/imperial system INI/debug menu
|
||||
{
|
||||
using namespace Localization;
|
||||
@ -1332,6 +1345,14 @@ void Patch_III_Common()
|
||||
auto getSkinTexture = get_pattern("E8 ? ? ? ? 89 C3 59 55");
|
||||
InterceptCall(getSkinTexture, orgRwTextureCreate, RwTextureCreate_SetLinearFilter);
|
||||
}
|
||||
|
||||
|
||||
// Apply the environment mapping on extra components
|
||||
{
|
||||
auto setEnvironmentMap = get_pattern("C7 83 D8 01 00 00 00 00 00 00 E8", 10);
|
||||
|
||||
InterceptCall(setEnvironmentMap, CVehicleModelInfo::orgSetEnvironmentMap, &CVehicleModelInfo::SetEnvironmentMap_ExtraComps);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
|
@ -5,13 +5,23 @@
|
||||
|
||||
class CVehicleModelInfo
|
||||
{
|
||||
private:
|
||||
uint8_t __pad1[60];
|
||||
unsigned int m_dwType;
|
||||
uint8_t __pad2[308];
|
||||
public:
|
||||
uint8_t __pad1[40];
|
||||
RpClump* m_clump;
|
||||
uint8_t __pad3[16];
|
||||
unsigned int m_dwType;
|
||||
uint8_t __pad4[11];
|
||||
int8_t m_numComps;
|
||||
uint8_t __pad2[268];
|
||||
RpAtomic* m_comps[6];
|
||||
uint8_t __pad5[4];
|
||||
|
||||
public:
|
||||
RwFrame* GetExtrasFrame( RpClump* clump );
|
||||
|
||||
// For SkyGfx interop
|
||||
static void AttachCarPipeToRwObject_Default(RwObject*) { }
|
||||
static inline void (*AttachCarPipeToRwObject)(RwObject* object) = &AttachCarPipeToRwObject_Default;
|
||||
};
|
||||
|
||||
static_assert(sizeof(CVehicleModelInfo) == 0x174, "Wrong size: CvehicleModelInfo");
|
@ -8,11 +8,13 @@
|
||||
#include "ModelInfoVC.h"
|
||||
#include "VehicleVC.h"
|
||||
#include "SVF.h"
|
||||
#include "RWUtils.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include "Utils/ModuleList.hpp"
|
||||
#include "Utils/Patterns.h"
|
||||
#include "Utils/ScopedUnprotect.hpp"
|
||||
|
||||
@ -61,6 +63,10 @@ static void (*PrintString)(float,float,const wchar_t*);
|
||||
static RsGlobalType* RsGlobal;
|
||||
static const void* SubtitlesShadowFix_JumpBack;
|
||||
|
||||
// This is actually CBaseModelInfo, but we currently don't have it defined
|
||||
CVehicleModelInfo**& ms_modelInfoPtrs = *hook::get_pattern<CVehicleModelInfo**>("8B 15 ? ? ? ? 8D 04 24", 2);
|
||||
int32_t& numModelInfos = *hook::get_pattern<int32_t>("81 FD ? ? ? ? 7C B7", 2);
|
||||
|
||||
inline float GetWidthMult()
|
||||
{
|
||||
static const float& ResolutionWidthMult = **AddressByVersion<float**>(0x5FA15E, 0x5FA17E, 0x5F9DBE);
|
||||
@ -474,11 +480,78 @@ namespace RemoveDriverStatusFix
|
||||
}
|
||||
|
||||
|
||||
// ============= Apply the environment mapping on extra components =============
|
||||
namespace EnvMapsOnExtras
|
||||
{
|
||||
static void RemoveSpecularityFromAtomic(RpAtomic* atomic)
|
||||
{
|
||||
RpGeometry* geometry = RpAtomicGetGeometry(atomic);
|
||||
if (geometry != nullptr)
|
||||
{
|
||||
RpGeometryForAllMaterials(geometry, [](RpMaterial* material)
|
||||
{
|
||||
bool bRemoveSpecularity = false;
|
||||
|
||||
// Only remove specularity from the body materials, keep glass intact.
|
||||
// This is only done on a best-effort basis, as mods can fine-tune it better
|
||||
// and just remove the model from the exceptions list
|
||||
RwTexture* texture = RpMaterialGetTexture(material);
|
||||
if (texture != nullptr)
|
||||
{
|
||||
if (strstr(RwTextureGetName(texture), "glass") == nullptr && strstr(RwTextureGetMaskName(texture), "glass") == nullptr)
|
||||
{
|
||||
bRemoveSpecularity = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bRemoveSpecularity)
|
||||
{
|
||||
RpMaterialGetSurfaceProperties(material)->specular = 0.0f;
|
||||
}
|
||||
return material;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static RpClump* (*orgRpClumpForAllAtomics)(RpClump* clump, RpAtomicCallBack callback, void* data);
|
||||
static RpClump* RpClumpForAllAtomics_ExtraComps(CVehicleModelInfo* modelInfo, RpAtomicCallBack callback, void* data)
|
||||
{
|
||||
RpClump* result = orgRpClumpForAllAtomics(modelInfo->m_clump, callback, data);
|
||||
|
||||
const int32_t modelID = std::distance(ms_modelInfoPtrs, std::find(ms_modelInfoPtrs, ms_modelInfoPtrs+numModelInfos, modelInfo));
|
||||
const bool bRemoveSpecularity = ExtraCompSpecularity::SpecularityExcluded(modelID);
|
||||
for (int32_t i = 0; i < modelInfo->m_numComps; i++)
|
||||
{
|
||||
if (bRemoveSpecularity)
|
||||
{
|
||||
RemoveSpecularityFromAtomic(modelInfo->m_comps[i]);
|
||||
}
|
||||
|
||||
callback(modelInfo->m_comps[i], data);
|
||||
CVehicleModelInfo::AttachCarPipeToRwObject(reinterpret_cast<RwObject*>(modelInfo->m_comps[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
|
||||
const ModuleList moduleList;
|
||||
|
||||
const HMODULE skygfxModule = moduleList.Get(L"skygfx");
|
||||
if (skygfxModule != nullptr)
|
||||
{
|
||||
auto attachCarPipe = reinterpret_cast<void(*)(RwObject*)>(GetProcAddress(skygfxModule, "AttachCarPipeToRwObject"));
|
||||
if (attachCarPipe != nullptr)
|
||||
{
|
||||
CVehicleModelInfo::AttachCarPipeToRwObject = attachCarPipe;
|
||||
}
|
||||
}
|
||||
|
||||
// Locale based metric/imperial system INI/debug menu
|
||||
{
|
||||
using namespace Localization;
|
||||
@ -1204,6 +1277,18 @@ void Patch_VC_Common()
|
||||
Nop(removeThisPed, 3);
|
||||
Nop(pedSetOutCar, 3);
|
||||
}
|
||||
|
||||
|
||||
// Apply the environment mapping on extra components
|
||||
{
|
||||
using namespace EnvMapsOnExtras;
|
||||
|
||||
auto forAllAtomics = pattern("50 E8 ? ? ? ? 66 8B 4B 44").get_one();
|
||||
|
||||
// push eax -> push ebx
|
||||
Patch<uint8_t>(forAllAtomics.get<void>(), 0x53);
|
||||
InterceptCall(forAllAtomics.get<void>(1), orgRpClumpForAllAtomics, RpClumpForAllAtomics_ExtraComps);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
|
Loading…
Reference in New Issue
Block a user