Factorized SVF to be usable by all 3 games

This commit is contained in:
Silent 2019-12-25 15:36:30 +01:00
parent 9248a822c6
commit 3555242811
No known key found for this signature in database
GPG key ID: AE53149BB0C45AF1
5 changed files with 207 additions and 173 deletions

145
SilentPatch/SVF.cpp Normal file
View file

@ -0,0 +1,145 @@
#include "SVF.h"
#include <cstdint>
#include <algorithm>
#include <map>
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<int32_t, std::tuple<Feature, int32_t> > 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<int32_t>(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<Feature>(it->second) == feature && std::get<int32_t>(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<Feature>(e.second) == feature;
} ) != results.second;
}
std::function<void(Feature)> ForAllModelFeatures( int32_t modelID, std::function<void(Feature)> pred )
{
auto results = specialVehFeatures.equal_range( modelID );
for ( auto it = results.first; it != results.second; ++it )
{
pred(std::get<Feature>(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) );
}
}

41
SilentPatch/SVF.h Normal file
View file

@ -0,0 +1,41 @@
#pragma once
#include <functional>
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<void(Feature)> ForAllModelFeatures( int32_t modelID, std::function<void(Feature)> pred );
};

View file

@ -186,6 +186,11 @@ copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\scripts\newsteam_r2_lowvio
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\SilentPatch\SVF.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Master|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\SilentPatch\TheFLAUtils.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
@ -226,6 +231,7 @@ copy /y "$(TargetPath)" "D:\gry\GTA San Andreas clean\scripts\newsteam_r2_lowvio
<ClInclude Include="..\SilentPatch\FLAC\stream_decoder.h" />
<ClInclude Include="..\SilentPatch\Maths.h" />
<ClInclude Include="..\SilentPatch\resource1.h" />
<ClInclude Include="..\SilentPatch\SVF.h" />
<ClInclude Include="..\SilentPatch\TheFLAUtils.h" />
<ClInclude Include="..\SilentPatch\Utils\DelimStringReader.h" />
<ClInclude Include="..\SilentPatch\Utils\MemoryMgr.GTA.h" />

View file

@ -78,6 +78,9 @@
<ClCompile Include="..\SilentPatch\Utils\Patterns.cpp">
<Filter>Source Files\Utils</Filter>
</ClCompile>
<ClCompile Include="..\SilentPatch\SVF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\SilentPatch\FLAC\callback.h">
@ -173,6 +176,9 @@
<ClInclude Include="..\SilentPatch\Maths.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\SVF.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">

View file

@ -1,14 +1,14 @@
#include "StdAfxSA.h"
#include <functional>
#include <algorithm>
#include <map>
#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<int32_t, std::tuple<Feature, int32_t> > 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<int32_t>(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<Feature>(it->second) == feature && std::get<int32_t>(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<Feature>(e.second) == feature;
} ) != results.second;
}
template<typename Pred>
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>(pred)(std::get<Feature>(it->second));
}
return std::forward<Pred>(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<void*>(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) );
}
}