diff --git a/SilentPatchSA/SilentPatchSA.cpp b/SilentPatchSA/SilentPatchSA.cpp index e301345..b6a4a3f 100644 --- a/SilentPatchSA/SilentPatchSA.cpp +++ b/SilentPatchSA/SilentPatchSA.cpp @@ -1003,66 +1003,9 @@ void DrawScriptSpritesAndRectangles( uint8_t arg ) orgDrawScriptSpritesAndRectangles( arg ); } -std::vector< std::pair > doubleRearWheelsList; -bool ReadDoubleRearWheels(const wchar_t* pPath) -{ - bool listedAny = false; - - constexpr size_t SCRATCH_PAD_SIZE = 32767; - WideDelimStringReader reader( SCRATCH_PAD_SIZE ); - - GetPrivateProfileSectionW( L"DoubleRearWheels", reader.GetBuffer(), reader.GetSize(), pPath ); - while ( const wchar_t* str = reader.GetString() ) - { - wchar_t textLine[64]; - wchar_t* context = nullptr; - wchar_t* token; - - wcscpy_s( textLine, str ); - token = wcstok_s( textLine, L"=", &context ); - - int32_t toList = wcstol( token, nullptr, 0 ); - if ( toList <= 0 ) continue; - - wchar_t* begin = wcstok_s( nullptr, L"=", &context ); - if ( begin == nullptr ) continue; - - wchar_t* end = nullptr; - bool value = wcstoul( begin, &end, 0 ) != 0; - if ( begin != end ) - { - doubleRearWheelsList.emplace_back( toList, value ); - listedAny = true; - } - } - return listedAny; -} - -// 1.0 ONLY! -bool __stdcall CheckDoubleRWheelsList( void* modelInfo, uint8_t* handlingData ) -{ - static void* lastModelInfo = nullptr; - static bool lastResult = false; - - if ( modelInfo == lastModelInfo ) return lastResult; - lastModelInfo = modelInfo; - - const uint32_t numModelInfoPtrs = *(uint32_t*)0x4C5956+2; - int32_t modelID = std::distance( ms_modelInfoPtrs, std::find( ms_modelInfoPtrs, ms_modelInfoPtrs+numModelInfoPtrs, modelInfo ) ); - - auto it = std::find_if( doubleRearWheelsList.begin(), doubleRearWheelsList.end(), [modelID]( const auto& item ) { - return item.first == modelID; - } ); - if ( it == doubleRearWheelsList.end() ) - { - uint32_t flags = *(uint32_t*)(handlingData+0xCC); - lastResult = (flags & 0x20000000) != 0; - return lastResult; - } - - lastResult = it->second; - return lastResult; -} +// Now in VehicleSA.cpp +bool ReadDoubleRearWheels(const wchar_t* pPath); +bool __stdcall CheckDoubleRWheelsList( void* modelInfo, uint8_t* handlingData ); CVehicleModelInfo* (__thiscall *orgVehicleModelInfoCtor)(CVehicleModelInfo*); CVehicleModelInfo* __fastcall VehicleModelInfoCtor(CVehicleModelInfo* me) diff --git a/SilentPatchSA/VehicleSA.cpp b/SilentPatchSA/VehicleSA.cpp index c798dce..3fcc9ba 100644 --- a/SilentPatchSA/VehicleSA.cpp +++ b/SilentPatchSA/VehicleSA.cpp @@ -41,11 +41,13 @@ namespace SVF { // Internal SP use only, formerly "rotor exceptions" // Unreachable from RegisterSpecialVehicleFeature NO_ROTOR_FADE, + FORCE_DOUBLE_RWHEELS_OFF, + FORCE_DOUBLE_RWHEELS_ON, }; Feature GetFeatureFromName( const char* featureName ) { - const std::pair< const char*, Feature > features[] = { + constexpr std::pair< const char*, Feature > features[] = { { "PHOENIX_FLUTTER", Feature::PHOENIX_FLUTTER }, { "SWEEPER_BRUSHES", Feature::SWEEPER_BRUSHES }, { "NEWSVAN_DISH", Feature::NEWSVAN_DISH }, @@ -142,6 +144,90 @@ namespace SVF { return std::get(e.second) == feature; } ) != results.second; } + + template + Pred ForAllModelFeatures( int32_t modelID, Pred&& pred ) + { + auto results = specialVehFeatures.equal_range( modelID ); + for ( auto it = results.first; it != results.second; ++it ) + { + std::forward(pred)(std::get(it->second)); + } + return std::forward(pred); + } +} + +bool ReadDoubleRearWheels(const wchar_t* pPath) +{ + bool listedAny = false; + + constexpr size_t SCRATCH_PAD_SIZE = 32767; + WideDelimStringReader reader( SCRATCH_PAD_SIZE ); + + GetPrivateProfileSectionW( L"DoubleRearWheels", reader.GetBuffer(), reader.GetSize(), pPath ); + while ( const wchar_t* str = reader.GetString() ) + { + wchar_t textLine[64]; + wchar_t* context = nullptr; + wchar_t* token; + + wcscpy_s( textLine, str ); + token = wcstok_s( textLine, L"=", &context ); + + int32_t toList = wcstol( token, nullptr, 0 ); + if ( toList <= 0 ) continue; + + wchar_t* begin = wcstok_s( nullptr, L"=", &context ); + if ( begin == nullptr ) continue; + + wchar_t* end = nullptr; + bool value = wcstoul( begin, &end, 0 ) != 0; + if ( begin != end ) + { + SVF::RegisterFeature( toList, value ? SVF::Feature::FORCE_DOUBLE_RWHEELS_ON : SVF::Feature::FORCE_DOUBLE_RWHEELS_OFF ); + listedAny = true; + } + } + return listedAny; +} + +// 1.0 ONLY! +bool __stdcall CheckDoubleRWheelsList( void* modelInfo, uint8_t* handlingData ) +{ + static void* lastModelInfo = nullptr; + static bool lastResult = false; + + if ( modelInfo == lastModelInfo ) return lastResult; + lastModelInfo = modelInfo; + + const uint32_t numModelInfoPtrs = *(uint32_t*)0x4C5956+2; + int32_t modelID = std::distance( ms_modelInfoPtrs, std::find( ms_modelInfoPtrs, ms_modelInfoPtrs+numModelInfoPtrs, modelInfo ) ); + + bool foundFeature = false; + bool featureStatus = false; + SVF::ForAllModelFeatures( modelID, [&]( SVF::Feature f ) { + if ( foundFeature ) return; + + if ( f == SVF::Feature::FORCE_DOUBLE_RWHEELS_OFF ) + { + foundFeature = true; + featureStatus = false; + } + else if ( f == SVF::Feature::FORCE_DOUBLE_RWHEELS_ON ) + { + foundFeature = true; + featureStatus = true; + } + } ); + if ( !foundFeature ) + { + uint32_t flags = *(uint32_t*)(handlingData+0xCC); + lastResult = (flags & 0x20000000) != 0; + return lastResult; + } + + lastResult = featureStatus; + return lastResult; }