From 3555242811de6d1ebacfbfcd602ecb3d2886bf2f Mon Sep 17 00:00:00 2001 From: Silent Date: Wed, 25 Dec 2019 15:36:30 +0100 Subject: [PATCH] Factorized SVF to be usable by all 3 games --- SilentPatch/SVF.cpp | 145 ++++++++++++++++ SilentPatch/SVF.h | 41 +++++ SilentPatchSA/SilentPatchSA.vcxproj | 6 + SilentPatchSA/SilentPatchSA.vcxproj.filters | 6 + SilentPatchSA/VehicleSA.cpp | 182 +------------------- 5 files changed, 207 insertions(+), 173 deletions(-) create mode 100644 SilentPatch/SVF.cpp create mode 100644 SilentPatch/SVF.h diff --git a/SilentPatch/SVF.cpp b/SilentPatch/SVF.cpp new file mode 100644 index 0000000..8f5f5e9 --- /dev/null +++ b/SilentPatch/SVF.cpp @@ -0,0 +1,145 @@ +#include "SVF.h" + +#include +#include +#include + +namespace SVF +{ + Feature GetFeatureFromName( const char* featureName ) + { + constexpr std::pair< const char*, Feature > features[] = { +#if _GTA_SA + { "PHOENIX_FLUTTER", Feature::PHOENIX_FLUTTER }, + { "SWEEPER_BRUSHES", Feature::SWEEPER_BRUSHES }, + { "NEWSVAN_DISH", Feature::NEWSVAN_DISH }, + { "EXTRA_AILERONS1", Feature::EXTRA_AILERONS1 }, + { "EXTRA_AILERONS2", Feature::EXTRA_AILERONS2 }, + { "DOUBLE_TRAILER", Feature::DOUBLE_TRAILER }, + { "VORTEX_EXHAUST", Feature::VORTEX_EXHAUST }, + { "TOWTRUCK_HOOK", Feature::TOWTRUCK_HOOK }, + { "TRACTOR_HOOK", Feature::TRACTOR_HOOK }, + { "RHINO_WHEELS", Feature::RHINO_WHEELS }, + { "FIRELA_LADDER", Feature::FIRELA_LADDER }, +#endif + }; + + auto it = std::find_if( std::begin(features), std::end(features), [featureName]( const auto& e ) { + return _stricmp( e.first, featureName ) == 0; + }); + + if ( it == std::end(features) ) return Feature::NO_FEATURE; + return it->second; + } + + static int32_t nextFeatureCookie = 0; + int32_t _getCookie() + { + return nextFeatureCookie++; + } + + static int32_t highestStockCookie = 0; + int32_t _getCookieStockID() + { + return highestStockCookie = _getCookie(); + } + + auto _registerFeatureInternal( int32_t modelID, Feature feature ) + { + return std::make_pair( modelID, std::make_tuple( feature, _getCookieStockID() ) ); + } + + static std::multimap > specialVehFeatures = { +#if _GTA_SA + _registerFeatureInternal( 432, Feature::RHINO_WHEELS ), + _registerFeatureInternal( 511, Feature::EXTRA_AILERONS1 ), + _registerFeatureInternal( 513, Feature::EXTRA_AILERONS2 ), + _registerFeatureInternal( 525, Feature::TOWTRUCK_HOOK ), + _registerFeatureInternal( 531, Feature::TRACTOR_HOOK ), + _registerFeatureInternal( 539, Feature::VORTEX_EXHAUST ), + _registerFeatureInternal( 544, Feature::FIRELA_LADDER ), + _registerFeatureInternal( 574, Feature::SWEEPER_BRUSHES ), + _registerFeatureInternal( 582, Feature::NEWSVAN_DISH ), + _registerFeatureInternal( 591, Feature::DOUBLE_TRAILER ), + _registerFeatureInternal( 603, Feature::PHOENIX_FLUTTER ), +#endif + }; + + int32_t RegisterFeature( int32_t modelID, Feature feature ) + { + if ( feature == Feature::NO_FEATURE ) return -1; + + const int32_t cookie = _getCookie(); + specialVehFeatures.emplace( modelID, std::make_tuple(feature, cookie) ); + return cookie; + } + + void DeleteFeature( int32_t cookie ) + { + for ( auto it = specialVehFeatures.begin(); it != specialVehFeatures.end(); ++it ) + { + if ( std::get(it->second) == cookie ) + { + specialVehFeatures.erase( it ); + return; + } + } + } + + void DisableStockVehiclesForFeature( Feature feature ) + { + if ( feature == Feature::NO_FEATURE ) return; + for ( auto it = specialVehFeatures.begin(); it != specialVehFeatures.end(); ) + { + if ( std::get(it->second) == feature && std::get(it->second) <= highestStockCookie ) + { + it = specialVehFeatures.erase( it ); + } + else + { + ++it; + } + } + } + + bool ModelHasFeature( int32_t modelID, Feature feature ) + { + auto results = specialVehFeatures.equal_range( modelID ); + return std::find_if( results.first, results.second, [feature] ( const auto& e ) { + return std::get(e.second) == feature; + } ) != results.second; + } + + std::function ForAllModelFeatures( int32_t modelID, std::function pred ) + { + auto results = specialVehFeatures.equal_range( modelID ); + for ( auto it = results.first; it != results.second; ++it ) + { + pred(std::get(it->second)); + } + return std::move(pred); + } +} + +// Returns "feature cookie" on success, -1 on failure +extern "C" { + +__declspec(dllexport) int32_t RegisterSpecialVehicleFeature( int32_t modelID, const char* featureName ) +{ + if ( featureName == nullptr ) return -1; + return SVF::RegisterFeature( modelID, SVF::GetFeatureFromName(featureName) ); +} + +__declspec(dllexport) void DeleteSpecialVehicleFeature( int32_t cookie ) +{ + if ( cookie == -1 ) return; + SVF::DeleteFeature( cookie ); +} + +__declspec(dllexport) void DisableStockVehiclesForSpecialVehicleFeature( const char* featureName ) +{ + if ( featureName == nullptr ) return; + SVF::DisableStockVehiclesForFeature( SVF::GetFeatureFromName(featureName) ); +} + +} \ No newline at end of file diff --git a/SilentPatch/SVF.h b/SilentPatch/SVF.h new file mode 100644 index 0000000..147dd0d --- /dev/null +++ b/SilentPatch/SVF.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace SVF +{ + enum class Feature + { + NO_FEATURE, + +#if _GTA_SA + // Those are fully controlled by SilentPatch + PHOENIX_FLUTTER, + SWEEPER_BRUSHES, + NEWSVAN_DISH, + EXTRA_AILERONS1, // Like on Beagle + EXTRA_AILERONS2, // Like on Stuntplane + DOUBLE_TRAILER, // Like on artict3 + + // Those are partially controlled by SilentPatch (only affected by minor fixes) + VORTEX_EXHAUST, + TOWTRUCK_HOOK, + TRACTOR_HOOK, + RHINO_WHEELS, + FIRELA_LADDER, + + // Internal SP use only, formerly "rotor exceptions" + // Unreachable from RegisterSpecialVehicleFeature + _INTERNAL_NO_ROTOR_FADE, + _INTERNAL_NO_LIGHTBEAM_BFC_FIX, + _INTERNAL_FORCE_DOUBLE_RWHEELS_OFF, + _INTERNAL_FORCE_DOUBLE_RWHEELS_ON, +#endif + }; + + int32_t RegisterFeature( int32_t modelID, Feature feature ); + void DeleteFeature( int32_t cookie ); + void DisableStockVehiclesForFeature( Feature feature ); + bool ModelHasFeature( int32_t modelID, Feature feature ); + std::function ForAllModelFeatures( int32_t modelID, std::function pred ); +}; \ No newline at end of file diff --git a/SilentPatchSA/SilentPatchSA.vcxproj b/SilentPatchSA/SilentPatchSA.vcxproj index 5716f8f..75cb31b 100644 --- a/SilentPatchSA/SilentPatchSA.vcxproj +++ b/SilentPatchSA/SilentPatchSA.vcxproj @@ -186,6 +186,11 @@ copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\scripts\newsteam_r2_lowvio + + NotUsing + NotUsing + NotUsing + NotUsing NotUsing @@ -226,6 +231,7 @@ copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\scripts\newsteam_r2_lowvio + diff --git a/SilentPatchSA/SilentPatchSA.vcxproj.filters b/SilentPatchSA/SilentPatchSA.vcxproj.filters index ad472dd..28d3f3f 100644 --- a/SilentPatchSA/SilentPatchSA.vcxproj.filters +++ b/SilentPatchSA/SilentPatchSA.vcxproj.filters @@ -78,6 +78,9 @@ Source Files\Utils + + Source Files + @@ -173,6 +176,9 @@ Header Files + + Header Files + diff --git a/SilentPatchSA/VehicleSA.cpp b/SilentPatchSA/VehicleSA.cpp index 8d4dd94..476436c 100644 --- a/SilentPatchSA/VehicleSA.cpp +++ b/SilentPatchSA/VehicleSA.cpp @@ -1,14 +1,14 @@ #include "StdAfxSA.h" -#include #include -#include #include "VehicleSA.h" #include "TimerSA.h" #include "PedSA.h" #include "Utils/DelimStringReader.h" #include "PlayerInfoSA.h" +#include "SVF.h" + static constexpr float PHOENIX_FLUTTER_PERIOD = 70.0f; static constexpr float PHOENIX_FLUTTER_AMP = 0.13f; static constexpr float SWEEPER_BRUSH_SPEED = 0.3f; @@ -17,147 +17,6 @@ static constexpr float PI = 3.14159265358979323846f; float CAutomobile::ms_engineCompSpeed; - -namespace SVF { - enum class Feature - { - NO_FEATURE, - - // Those are fully controlled by SilentPatch - PHOENIX_FLUTTER, - SWEEPER_BRUSHES, - NEWSVAN_DISH, - EXTRA_AILERONS1, // Like on Beagle - EXTRA_AILERONS2, // Like on Stuntplane - DOUBLE_TRAILER, // Like on artict3 - - // Those are partially controlled by SilentPatch (only affected by minor fixes) - VORTEX_EXHAUST, - TOWTRUCK_HOOK, - TRACTOR_HOOK, - RHINO_WHEELS, - FIRELA_LADDER, - - // Internal SP use only, formerly "rotor exceptions" - // Unreachable from RegisterSpecialVehicleFeature - NO_ROTOR_FADE, - NO_LIGHTBEAM_BFC_FIX, - FORCE_DOUBLE_RWHEELS_OFF, - FORCE_DOUBLE_RWHEELS_ON, - }; - - Feature GetFeatureFromName( const char* featureName ) - { - constexpr std::pair< const char*, Feature > features[] = { - { "PHOENIX_FLUTTER", Feature::PHOENIX_FLUTTER }, - { "SWEEPER_BRUSHES", Feature::SWEEPER_BRUSHES }, - { "NEWSVAN_DISH", Feature::NEWSVAN_DISH }, - { "EXTRA_AILERONS1", Feature::EXTRA_AILERONS1 }, - { "EXTRA_AILERONS2", Feature::EXTRA_AILERONS2 }, - { "DOUBLE_TRAILER", Feature::DOUBLE_TRAILER }, - { "VORTEX_EXHAUST", Feature::VORTEX_EXHAUST }, - { "TOWTRUCK_HOOK", Feature::TOWTRUCK_HOOK }, - { "TRACTOR_HOOK", Feature::TRACTOR_HOOK }, - { "RHINO_WHEELS", Feature::RHINO_WHEELS }, - { "FIRELA_LADDER", Feature::FIRELA_LADDER }, - }; - - auto it = std::find_if( std::begin(features), std::end(features), [featureName]( const auto& e ) { - return _stricmp( e.first, featureName ) == 0; - }); - - if ( it == std::end(features) ) return Feature::NO_FEATURE; - return it->second; - } - - static int32_t nextFeatureCookie = 0; - int32_t _getCookie() - { - return nextFeatureCookie++; - } - - static int32_t highestStockCookie = 0; - int32_t _getCookieStockID() - { - return highestStockCookie = _getCookie(); - } - - auto _registerFeatureInternal( int32_t modelID, Feature feature ) - { - return std::make_pair( modelID, std::make_tuple( feature, _getCookieStockID() ) ); - } - - static std::multimap > specialVehFeatures = { - _registerFeatureInternal( 432, Feature::RHINO_WHEELS ), - _registerFeatureInternal( 511, Feature::EXTRA_AILERONS1 ), - _registerFeatureInternal( 513, Feature::EXTRA_AILERONS2 ), - _registerFeatureInternal( 525, Feature::TOWTRUCK_HOOK ), - _registerFeatureInternal( 531, Feature::TRACTOR_HOOK ), - _registerFeatureInternal( 539, Feature::VORTEX_EXHAUST ), - _registerFeatureInternal( 544, Feature::FIRELA_LADDER ), - _registerFeatureInternal( 574, Feature::SWEEPER_BRUSHES ), - _registerFeatureInternal( 582, Feature::NEWSVAN_DISH ), - _registerFeatureInternal( 591, Feature::DOUBLE_TRAILER ), - _registerFeatureInternal( 603, Feature::PHOENIX_FLUTTER ), - }; - - int32_t RegisterFeature( int32_t modelID, Feature feature ) - { - if ( feature == Feature::NO_FEATURE ) return -1; - - const int32_t cookie = _getCookie(); - specialVehFeatures.emplace( modelID, std::make_tuple(feature, cookie) ); - return cookie; - } - - void DeleteFeature( int32_t cookie ) - { - for ( auto it = specialVehFeatures.begin(); it != specialVehFeatures.end(); ++it ) - { - if ( std::get(it->second) == cookie ) - { - specialVehFeatures.erase( it ); - return; - } - } - } - - void DisableStockVehiclesForFeature( Feature feature ) - { - if ( feature == Feature::NO_FEATURE ) return; - for ( auto it = specialVehFeatures.begin(); it != specialVehFeatures.end(); ) - { - if ( std::get(it->second) == feature && std::get(it->second) <= highestStockCookie ) - { - it = specialVehFeatures.erase( it ); - } - else - { - ++it; - } - } - } - - bool ModelHasFeature( int32_t modelID, Feature feature ) - { - auto results = specialVehFeatures.equal_range( modelID ); - return std::find_if( results.first, results.second, [feature] ( const auto& e ) { - 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; @@ -185,7 +44,7 @@ bool ReadDoubleRearWheels(const wchar_t* pPath) 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 ); + SVF::RegisterFeature( toList, value ? SVF::Feature::_INTERNAL_FORCE_DOUBLE_RWHEELS_ON : SVF::Feature::_INTERNAL_FORCE_DOUBLE_RWHEELS_OFF ); listedAny = true; } } @@ -209,12 +68,12 @@ bool __stdcall CheckDoubleRWheelsList( void* modelInfo, uint8_t* handlingData ) SVF::ForAllModelFeatures( modelID, [&]( SVF::Feature f ) { if ( foundFeature ) return; - if ( f == SVF::Feature::FORCE_DOUBLE_RWHEELS_OFF ) + if ( f == SVF::Feature::_INTERNAL_FORCE_DOUBLE_RWHEELS_OFF ) { foundFeature = true; featureStatus = false; } - else if ( f == SVF::Feature::FORCE_DOUBLE_RWHEELS_ON ) + else if ( f == SVF::Feature::_INTERNAL_FORCE_DOUBLE_RWHEELS_ON ) { foundFeature = true; featureStatus = true; @@ -239,7 +98,7 @@ bool CVehicle::IgnoresRotorFix() const { return ms_rotorFixOverride < 0; } - return SVF::ModelHasFeature( m_nModelIndex.Get(), SVF::Feature::NO_ROTOR_FADE ); + return SVF::ModelHasFeature( m_nModelIndex.Get(), SVF::Feature::_INTERNAL_NO_ROTOR_FADE ); } static void* varVehicleRender = AddressByVersion(0x6D0E60, 0x6D1680, 0x70C0B0); @@ -341,7 +200,7 @@ void ReadRotorFixExceptions(const wchar_t* pPath) { int32_t toList = wcstol( str, nullptr, 0 ); if ( toList > 0 ) - SVF::RegisterFeature( toList, SVF::Feature::NO_ROTOR_FADE ); + SVF::RegisterFeature( toList, SVF::Feature::_INTERNAL_NO_ROTOR_FADE ); } } @@ -355,7 +214,7 @@ void ReadLightbeamFixExceptions(const wchar_t* pPath) { int32_t toList = wcstol( str, nullptr, 0 ); if ( toList > 0 ) - SVF::RegisterFeature( toList, SVF::Feature::NO_LIGHTBEAM_BFC_FIX ); + SVF::RegisterFeature( toList, SVF::Feature::_INTERNAL_NO_LIGHTBEAM_BFC_FIX ); } } @@ -395,7 +254,7 @@ bool CVehicle::IgnoresLightbeamFix() const { return ms_lightbeamFixOverride < 0; } - return SVF::ModelHasFeature( m_nModelIndex.Get(), SVF::Feature::NO_LIGHTBEAM_BFC_FIX ); + return SVF::ModelHasFeature( m_nModelIndex.Get(), SVF::Feature::_INTERNAL_NO_LIGHTBEAM_BFC_FIX ); } @@ -854,26 +713,3 @@ CVehicle* CStoredCar::RestoreCar_SilentPatch() return vehicle; } - -// Returns "feature cookie" on success, -1 on failure -extern "C" { - -__declspec(dllexport) int32_t RegisterSpecialVehicleFeature( int32_t modelID, const char* featureName ) -{ - if ( featureName == nullptr ) return -1; - return SVF::RegisterFeature( modelID, SVF::GetFeatureFromName(featureName) ); -} - -__declspec(dllexport) void DeleteSpecialVehicleFeature( int32_t cookie ) -{ - if ( cookie == -1 ) return; - SVF::DeleteFeature( cookie ); -} - -__declspec(dllexport) void DisableStockVehiclesForSpecialVehicleFeature( const char* featureName ) -{ - if ( featureName == nullptr ) return; - SVF::DisableStockVehiclesForFeature( SVF::GetFeatureFromName(featureName) ); -} - -}