2024-12-30 01:25:31 +02:00
# include <Windows.h>
2025-01-06 09:11:01 +02:00
# include <algorithm>
2024-12-30 01:25:31 +02:00
# include <spdlog\spdlog.h>
# include <EGSDK\Offsets.h>
# include <EGSDK\GamePH\PlayerState.h>
# include <EGSDK\GamePH\PlayerVariables.h>
# include <EGSDK\ClassHelpers.h>
namespace EGSDK : : GamePH {
2025-01-06 09:11:01 +02:00
static constexpr int STRING_SIZE_OFFSET = 3 ;
static constexpr int FLOAT_SIZE_OFFSET = 3 ;
static constexpr int BOOL_SIZE_OFFSET = 2 ;
std : : unordered_map < PlayerVariable * , std : : string > PlayerVariable : : playerVarNames { } ;
std : : unordered_map < PlayerVariable * , PlayerVarType > PlayerVariable : : playerVarTypes { } ;
PlayerVariable : : PlayerVariable ( const std : : string & name ) {
playerVarNames [ this ] = name ;
playerVarTypes [ this ] = PlayerVarType : : NONE ;
}
const char * PlayerVariable : : GetName ( ) {
auto it = playerVarNames . find ( this ) ;
if ( it ! = playerVarNames . end ( ) ) {
return it - > second . c_str ( ) ;
}
return nullptr ;
}
void PlayerVariable : : SetName ( const std : : string & newName ) {
playerVarNames [ this ] = newName ;
}
PlayerVarType PlayerVariable : : GetType ( ) {
auto it = playerVarTypes . find ( this ) ;
if ( it ! = playerVarTypes . end ( ) ) {
return it - > second ;
}
return PlayerVarType : : NONE ;
}
void PlayerVariable : : SetType ( PlayerVarType newType ) {
playerVarTypes [ this ] = newType ;
}
2024-12-30 01:25:31 +02:00
2025-01-06 09:11:01 +02:00
StringPlayerVariable : : StringPlayerVariable ( const std : : string & name ) : PlayerVariable ( name ) {
SetType ( PlayerVarType : : String ) ;
}
FloatPlayerVariable : : FloatPlayerVariable ( const std : : string & name ) : PlayerVariable ( name ) {
SetType ( PlayerVarType : : Float ) ;
}
2025-01-07 00:28:09 +02:00
void FloatPlayerVariable : : SetValues ( float value ) {
this - > value = value ;
this - > defaultValue = value ;
}
2025-01-06 09:11:01 +02:00
BoolPlayerVariable : : BoolPlayerVariable ( const std : : string & name ) : PlayerVariable ( name ) {
SetType ( PlayerVarType : : Bool ) ;
}
2025-01-07 00:28:09 +02:00
void BoolPlayerVariable : : SetValues ( bool value ) {
this - > value = value ;
this - > defaultValue = value ;
}
2025-01-06 09:11:01 +02:00
2025-01-07 04:42:06 +02:00
std : : unique_ptr < PlayerVariable > & PlayerVarVector : : emplace_back ( std : : unique_ptr < PlayerVariable > playerVar ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
_playerVars . emplace_back ( std : : move ( playerVar ) ) ;
return _playerVars . back ( ) ;
}
auto PlayerVarVector : : begin ( ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
return _playerVars . begin ( ) ;
}
auto PlayerVarVector : : end ( ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
return _playerVars . end ( ) ;
}
bool PlayerVarVector : : none_of ( const std : : string & name ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
return std : : none_of ( _playerVars . begin ( ) , _playerVars . end ( ) , [ & name ] ( const auto & playerVar ) {
return playerVar - > GetName ( ) = = name ;
} ) ;
}
auto PlayerVarVector : : FindIter ( const std : : string & name ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
auto playerVarIt = std : : find_if ( _playerVars . begin ( ) , _playerVars . end ( ) , [ & name ] ( const auto & playerVar ) {
return playerVar - > GetName ( ) = = name ;
} ) ;
return playerVarIt ;
}
std : : unique_ptr < PlayerVariable > * PlayerVarVector : : FindPtr ( const std : : string & name ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
auto playerVarIt = FindIter ( name ) ;
return playerVarIt = = _playerVars . end ( ) ? nullptr : & * playerVarIt ;
}
PlayerVariable * PlayerVarVector : : Find ( const std : : string & name ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
auto playerVarPtr = FindPtr ( name ) ;
return ! playerVarPtr ? nullptr : playerVarPtr - > get ( ) ;
}
auto PlayerVarVector : : Erase ( const std : : string & name ) {
std : : lock_guard < std : : mutex > lock ( _mutex ) ;
auto playerVarIt = FindIter ( name ) ;
if ( playerVarIt ! = _playerVars . end ( ) )
return _playerVars . erase ( playerVarIt ) ;
return _playerVars . end ( ) ;
}
2025-01-07 00:28:09 +02:00
PlayerVarVector PlayerVariables : : playerVars { } ;
PlayerVarVector PlayerVariables : : customPlayerVars { } ;
PlayerVarVector PlayerVariables : : defaultPlayerVars { } ;
PlayerVarVector PlayerVariables : : customDefaultPlayerVars { } ;
2024-12-30 01:25:31 +02:00
bool PlayerVariables : : gotPlayerVars = false ;
static bool sortedPlayerVars = false ;
2025-01-06 09:11:01 +02:00
std : : unordered_map < std : : string , std : : any > PlayerVariables : : prevPlayerVarValueMap { } ;
std : : unordered_map < std : : string , bool > PlayerVariables : : prevBoolValueMap { } ;
2024-12-30 01:25:31 +02:00
template < typename T >
2025-01-07 00:28:09 +02:00
static void updateDefaultVar ( PlayerVarVector & defaultVars , const std : : string & name , T value , T defaultValue ) {
2025-01-06 09:11:01 +02:00
static_assert ( std : : is_same_v < T , std : : string > | | std : : is_same_v < T , float > | | std : : is_same_v < T , bool > , " Invalid type: value must be string, float or bool " ) ;
2024-12-30 01:25:31 +02:00
2025-01-07 00:28:09 +02:00
auto playerVar = defaultVars . Find ( name ) ;
if ( ! playerVar ) {
2025-01-06 09:11:01 +02:00
if constexpr ( std : : is_same_v < T , std : : string > ) {
auto stringPlayerVar = std : : make_unique < StringPlayerVariable > ( name ) ;
defaultVars . emplace_back ( std : : move ( stringPlayerVar ) ) ;
}
else if constexpr ( std : : is_same_v < T , float > ) {
auto floatPlayerVar = std : : make_unique < FloatPlayerVariable > ( name ) ;
2025-01-07 00:28:09 +02:00
floatPlayerVar - > SetValues ( value ) ;
2025-01-06 09:11:01 +02:00
defaultVars . emplace_back ( std : : move ( floatPlayerVar ) ) ;
}
else if constexpr ( std : : is_same_v < T , bool > ) {
auto boolPlayerVar = std : : make_unique < BoolPlayerVariable > ( name ) ;
2025-01-07 00:28:09 +02:00
boolPlayerVar - > SetValues ( value ) ;
2025-01-06 09:11:01 +02:00
defaultVars . emplace_back ( std : : move ( boolPlayerVar ) ) ;
}
} else {
if constexpr ( std : : is_same_v < T , std : : string > ) {
// TO IMPLEMENT
return ;
} else if constexpr ( std : : is_same_v < T , float > ) {
2025-01-07 00:28:09 +02:00
auto floatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( playerVar ) ;
floatPlayerVar - > SetValues ( value ) ;
2025-01-06 09:11:01 +02:00
} else if constexpr ( std : : is_same_v < T , bool > ) {
2025-01-07 00:51:27 +02:00
auto boolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( playerVar ) ;
2025-01-07 00:28:09 +02:00
boolPlayerVar - > SetValues ( value ) ;
2025-01-06 09:11:01 +02:00
}
}
2024-12-30 01:25:31 +02:00
}
2025-01-07 00:28:09 +02:00
static void processPlayerVar ( DWORD64 * ( * playerVarsGetter ) ( ) , std : : unique_ptr < PlayerVariable > & playerVarPtr ) {
2024-12-30 01:25:31 +02:00
static int offset = 0 ;
2025-01-06 09:11:01 +02:00
int offsetDif = 0 ;
2025-01-04 04:53:31 +02:00
while ( true ) {
2025-01-06 09:11:01 +02:00
std : : string vTableName = Utils : : RTTI : : GetVTableName ( playerVarsGetter ( ) + offset ) ;
if ( vTableName ! = " StringPlayerVariable " & & vTableName ! = " FloatPlayerVariable " & & vTableName ! = " BoolPlayerVariable " ) {
if ( offsetDif > 150 )
return ;
2024-12-30 01:25:31 +02:00
2025-01-04 04:53:31 +02:00
offset + = 1 ;
2025-01-06 09:11:01 +02:00
offsetDif + = 1 ;
continue ;
}
2025-01-07 00:28:09 +02:00
std : : string varName = playerVarPtr - > GetName ( ) ;
PlayerVarType varType = playerVarPtr - > GetType ( ) ;
2025-01-06 09:11:01 +02:00
2025-01-07 00:28:09 +02:00
switch ( playerVarPtr - > GetType ( ) ) {
case PlayerVarType : : String :
{
2025-01-06 09:11:01 +02:00
if ( vTableName ! = " StringPlayerVariable " )
return ;
StringPlayerVariable * stringPlayerVar = reinterpret_cast < StringPlayerVariable * > ( playerVarsGetter ( ) + offset ) ;
2025-01-07 00:28:09 +02:00
playerVarPtr . reset ( stringPlayerVar ) ;
playerVarPtr - > SetName ( varName ) ;
playerVarPtr - > SetType ( varType ) ;
2025-01-06 09:11:01 +02:00
// TO IMPLEMENT
offset + = STRING_SIZE_OFFSET ;
return ;
}
2025-01-07 00:28:09 +02:00
case PlayerVarType : : Float :
{
2025-01-06 09:11:01 +02:00
if ( vTableName ! = " FloatPlayerVariable " )
return ;
FloatPlayerVariable * floatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( playerVarsGetter ( ) + offset ) ;
2025-01-07 00:28:09 +02:00
playerVarPtr . reset ( floatPlayerVar ) ;
playerVarPtr - > SetName ( varName ) ;
playerVarPtr - > SetType ( varType ) ;
2025-01-06 09:11:01 +02:00
updateDefaultVar ( PlayerVariables : : customDefaultPlayerVars , varName , floatPlayerVar - > value . data , floatPlayerVar - > defaultValue . data ) ;
offset + = FLOAT_SIZE_OFFSET ;
return ;
}
2025-01-07 00:28:09 +02:00
case PlayerVarType : : Bool :
{
2025-01-06 09:11:01 +02:00
if ( vTableName ! = " BoolPlayerVariable " )
return ;
BoolPlayerVariable * boolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( playerVarsGetter ( ) + offset ) ;
2025-01-07 00:28:09 +02:00
playerVarPtr . reset ( boolPlayerVar ) ;
playerVarPtr - > SetName ( varName ) ;
playerVarPtr - > SetType ( varType ) ;
2025-01-06 09:11:01 +02:00
updateDefaultVar ( PlayerVariables : : customDefaultPlayerVars , varName , boolPlayerVar - > value . data , boolPlayerVar - > defaultValue . data ) ;
offset + = BOOL_SIZE_OFFSET ;
return ;
}
default :
offset + = 1 ;
return ;
}
2024-12-30 01:25:31 +02:00
}
}
2025-01-07 00:51:27 +02:00
static void processPlayerVarSafe ( DWORD64 * ( * playerVarsGetter ) ( ) , std : : unique_ptr < PlayerVariable > & playerVarPtr ) {
__try {
processPlayerVar ( playerVarsGetter , playerVarPtr ) ;
} __except ( EXCEPTION_EXECUTE_HANDLER ) {
SPDLOG_ERROR ( " Failed to process player variable: {} " , playerVarPtr - > GetName ( ) ) ;
}
}
2024-12-30 01:25:31 +02:00
void PlayerVariables : : GetPlayerVars ( ) {
if ( gotPlayerVars )
return ;
if ( ! sortedPlayerVars )
return ;
if ( ! Get ( ) )
return ;
2025-01-07 00:51:27 +02:00
for ( auto & playerVarPtr : playerVars )
processPlayerVarSafe ( reinterpret_cast < DWORD64 * ( * ) ( ) > ( & Get ) , playerVarPtr ) ;
2024-12-30 01:25:31 +02:00
gotPlayerVars = true ;
}
# pragma region Player Variables Sorting
struct VarTypeFieldMeta {
2025-01-06 09:11:01 +02:00
PlayerVarType type ;
2025-01-03 04:35:13 +02:00
std : : string_view className ;
2024-12-30 01:25:31 +02:00
} ;
const std : : vector < VarTypeFieldMeta > varTypeFields = {
2025-01-06 09:11:01 +02:00
{ PlayerVarType : : String , " constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<StringPlayerVariable> " } ,
{ PlayerVarType : : Float , " constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<FloatPlayerVariable> " } ,
{ PlayerVarType : : Bool , " constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<BoolPlayerVariable> " }
2024-12-30 01:25:31 +02:00
} ;
2025-01-04 04:53:31 +02:00
static bool isRetInstruction ( BYTE * address ) {
2024-12-30 01:25:31 +02:00
//return address[0] == 0xC3 && address[1] == 0xCC;
return address [ 0 ] = = 0x00 & & address [ 1 ] = = 0x00 & & address [ 2 ] = = 0xC3 & & address [ 3 ] = = 0xCC ;
}
2025-01-04 04:53:31 +02:00
static bool isLeaInstruction ( BYTE * address , BYTE REX , BYTE ModRM ) {
2024-12-30 01:25:31 +02:00
return address [ 0 ] = = REX & & address [ 1 ] = = 0x8D & & address [ 2 ] = = ModRM ;
}
2025-01-04 04:53:31 +02:00
static bool isCallInstruction ( BYTE * address ) {
2024-12-30 01:25:31 +02:00
return address [ 0 ] = = 0xE8 & & address [ 4 ] ! = 0xE8 ;
}
2025-01-04 04:53:31 +02:00
static bool isBelowFuncSizeLimit ( BYTE * address , DWORD64 startOfFunc , size_t sizeLimit ) {
2024-12-30 01:25:31 +02:00
return ( reinterpret_cast < DWORD64 > ( address ) - startOfFunc ) < sizeLimit ;
}
// to prevent infinite loops, assuming function is no longer than 500000 bytes LMAO Techland... why is your function even like 250000 bytes to begin with? bad code...
static const size_t MAX_FUNC_SIZE = 500000 ;
static const size_t MAX_LOAD_VAR_FUNC_SIZE = 2000 ;
static const char * getPlayerVarName ( BYTE * & funcAddress , DWORD64 startOfFunc ) {
const char * playerVarName = nullptr ;
while ( ! playerVarName & & ! isRetInstruction ( funcAddress ) & & isBelowFuncSizeLimit ( funcAddress , startOfFunc , MAX_FUNC_SIZE ) ) {
// lea r8, varNameString
if ( ! isLeaInstruction ( funcAddress , 0x4C , 0x05 ) ) {
funcAddress + + ;
continue ;
}
2025-01-03 04:35:13 +02:00
playerVarName = reinterpret_cast < const char * > ( Utils : : Memory : : CalcTargetAddrOfRelativeInstr ( reinterpret_cast < DWORD64 > ( funcAddress ) , 3 ) ) ;
2024-12-30 01:25:31 +02:00
if ( ! playerVarName ) {
funcAddress + + ;
continue ;
}
// add the size of the instruction, so we skip this instruction because this instruction is the name
funcAddress + = 0x7 ;
}
return playerVarName ;
}
2025-01-06 09:11:01 +02:00
static PlayerVarType getPlayerVarType ( BYTE * & funcAddress , DWORD64 startOfFunc ) {
PlayerVarType playerVarType = PlayerVarType : : NONE ;
2024-12-30 01:25:31 +02:00
while ( ! playerVarType & & ! isRetInstruction ( funcAddress ) & & isBelowFuncSizeLimit ( funcAddress , startOfFunc , MAX_FUNC_SIZE ) ) {
// call LoadPlayerXVariable
if ( ! isCallInstruction ( funcAddress ) ) {
funcAddress + + ;
continue ;
}
2025-01-03 04:35:13 +02:00
DWORD64 startOfLoadVarFunc = Utils : : Memory : : CalcTargetAddrOfRelativeInstr ( reinterpret_cast < DWORD64 > ( funcAddress ) , 1 ) ;
2025-01-06 09:11:01 +02:00
BYTE * loadVarFuncAddress = reinterpret_cast < BYTE * > ( startOfLoadVarFunc ) ;
DWORD64 metaVTAddrFromFunc = 0 ;
while ( ! metaVTAddrFromFunc & & ! isRetInstruction ( loadVarFuncAddress ) & & isBelowFuncSizeLimit ( loadVarFuncAddress , startOfLoadVarFunc , MAX_LOAD_VAR_FUNC_SIZE ) ) {
// lea rax, typedFieldMetaVT
if ( ! isLeaInstruction ( loadVarFuncAddress , 0x48 , 0x05 ) ) {
loadVarFuncAddress + + ;
continue ;
2024-12-30 01:25:31 +02:00
}
2025-01-06 09:11:01 +02:00
metaVTAddrFromFunc = Utils : : Memory : : CalcTargetAddrOfRelativeInstr ( reinterpret_cast < DWORD64 > ( loadVarFuncAddress ) , 3 ) ;
std : : string vTableName = Utils : : RTTI : : GetVTableNameFromVTPtr ( reinterpret_cast < DWORD64 * > ( metaVTAddrFromFunc ) ) ;
auto varTypeIt = std : : find_if ( varTypeFields . begin ( ) , varTypeFields . end ( ) , [ & vTableName ] ( const auto & varType ) {
return varType . className = = vTableName ;
} ) ;
if ( varTypeIt = = varTypeFields . end ( ) ) {
metaVTAddrFromFunc = 0 ;
loadVarFuncAddress + + ;
continue ;
2024-12-30 01:25:31 +02:00
}
2025-01-06 09:11:01 +02:00
playerVarType = varTypeIt - > type ;
break ;
2024-12-30 01:25:31 +02:00
}
// if it's still NONE after seeing the function doesnt reference any of the variables, break so the loop stops
2025-01-06 09:11:01 +02:00
if ( playerVarType = = PlayerVarType : : NONE )
2024-12-30 01:25:31 +02:00
break ;
}
return playerVarType ;
}
bool PlayerVariables : : SortPlayerVars ( ) {
DWORD64 startOfFunc = 0 ;
while ( ! startOfFunc )
startOfFunc = reinterpret_cast < DWORD64 > ( Offsets : : Get_LoadPlayerVars ( ) ) ;
BYTE * funcAddress = reinterpret_cast < BYTE * > ( startOfFunc ) ;
while ( ! isRetInstruction ( funcAddress ) & & ( reinterpret_cast < DWORD64 > ( funcAddress ) - startOfFunc ) < MAX_FUNC_SIZE ) {
const char * playerVarName = getPlayerVarName ( funcAddress , startOfFunc ) ;
if ( ! playerVarName )
continue ;
PlayerVarType playerVarType = getPlayerVarType ( funcAddress , startOfFunc ) ;
switch ( playerVarType ) {
2025-01-06 09:11:01 +02:00
case PlayerVarType : : String :
playerVars . emplace_back ( std : : make_unique < StringPlayerVariable > ( playerVarName ) ) ;
break ;
2024-12-30 01:25:31 +02:00
case PlayerVarType : : Float :
2025-01-06 09:11:01 +02:00
playerVars . emplace_back ( std : : make_unique < FloatPlayerVariable > ( playerVarName ) ) ;
2024-12-30 01:25:31 +02:00
break ;
case PlayerVarType : : Bool :
2025-01-06 09:11:01 +02:00
playerVars . emplace_back ( std : : make_unique < BoolPlayerVariable > ( playerVarName ) ) ;
2024-12-30 01:25:31 +02:00
break ;
default :
2025-01-06 09:11:01 +02:00
//playerVars.emplace_back(std::make_unique<PlayerVariable>(playerVarName));
2024-12-30 01:25:31 +02:00
break ;
}
}
sortedPlayerVars = true ;
return true ;
}
# pragma endregion
2025-01-07 04:42:06 +02:00
template < typename T >
static T getDefaultValue ( ) {
static_assert ( std : : is_same_v < T , std : : string > | | std : : is_same_v < T , float > | | std : : is_same_v < T , bool > , " Invalid type: value must be string, float or bool " ) ;
if constexpr ( std : : is_same_v < T , std : : string > )
return { } ;
else if constexpr ( std : : is_same_v < T , float > )
return - 404.0f ;
else if constexpr ( std : : is_same_v < T , bool > )
return false ;
else
return T ( ) ;
}
template < typename T >
static T GetPlayerVarValue ( const std : : string & name ) {
static_assert ( std : : is_same_v < T , std : : string > | | std : : is_same_v < T , float > | | std : : is_same_v < T , bool > , " Invalid type: value must be string, float or bool " ) ;
if ( ! gotPlayerVars )
return getDefaultValue < T > ( ) ;
auto playerVar = playerVars . Find ( name ) ;
if ( ! playerVar )
return getDefaultValue < T > ( ) ;
if constexpr ( std : : is_same_v < T , std : : string > ) {
StringPlayerVariable * stringPlayerVar = reinterpret_cast < StringPlayerVariable * > ( playerVar ) ;
return stringPlayerVar - > value . data ;
} else if constexpr ( std : : is_same_v < T , float > ) {
FloatPlayerVariable * floatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( playerVar ) ;
return floatPlayerVar - > value . data ;
} else if constexpr ( std : : is_same_v < T , bool > ) {
BoolPlayerVariable * boolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( playerVar ) ;
return boolPlayerVar - > value . data ;
}
}
template < typename T >
static void ChangePlayerVar ( const std : : string & name , const T value ) {
static_assert ( std : : is_same_v < T , std : : string > | | std : : is_same_v < T , float > | | std : : is_same_v < T , bool > , " Invalid type: value must be string, float or bool " ) ;
if ( ! gotPlayerVars )
return ;
auto playerVar = playerVars . Find ( name ) ;
if ( ! playerVar )
return ;
if constexpr ( std : : is_same_v < T , std : : string > ) {
switch ( playerVar - > GetType ( ) ) {
case PlayerVarType : : String :
// TO IMPLEMENT
break ;
case PlayerVarType : : Float :
{
std : : string valueStr = Utils : : Values : : to_string ( value ) ;
float actualValue = std : : stof ( valueStr ) ;
FloatPlayerVariable * floatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( playerVar ) ;
floatPlayerVar - > SetValues ( actualValue ) ;
break ;
}
case PlayerVarType : : Bool :
{
std : : string valueStr = Utils : : Values : : to_string ( value ) ;
bool actualValue = valueStr = = " true " ;
BoolPlayerVariable * boolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( playerVar ) ;
boolPlayerVar - > SetValues ( actualValue ) ;
break ;
}
default :
break ;
}
} else if constexpr ( std : : is_same_v < T , float > ) {
if ( playerVar - > GetType ( ) ! = PlayerVarType : : Float )
return ;
FloatPlayerVariable * floatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( playerVar ) ;
floatPlayerVar - > SetValues ( value ) ;
} else if constexpr ( std : : is_same_v < T , bool > ) {
if ( playerVar - > GetType ( ) ! = PlayerVarType : : Bool )
return ;
BoolPlayerVariable * boolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( playerVar ) ;
boolPlayerVar - > SetValues ( value ) ;
}
}
template < typename T >
static void ChangePlayerVarFromList ( const std : : string & name , const T value , PlayerVariable * playerVar = nullptr ) {
static_assert ( std : : is_same_v < T , std : : string > | | std : : is_same_v < T , float > | | std : : is_same_v < T , bool > , " Invalid type: value must be string, float or bool " ) ;
if ( ! gotPlayerVars )
return ;
if ( ! playerVar ) {
playerVar = playerVars . Find ( name ) ;
if ( ! playerVar )
return ;
}
auto customPlayerVar = customPlayerVars . Find ( name ) ;
auto defPlayerVar = defaultPlayerVars . Find ( name ) ;
if constexpr ( std : : is_same_v < T , std : : string > ) {
switch ( playerVar - > GetType ( ) ) {
case PlayerVarType : : String :
// TO IMPLEMENT
break ;
case PlayerVarType : : Float :
{
if ( ! customPlayerVar )
customPlayerVar = customPlayerVars . emplace_back ( std : : make_unique < FloatPlayerVariable > ( name ) ) . get ( ) ;
std : : string valueStr = Utils : : Values : : to_string ( value ) ;
float actualValue = std : : stof ( valueStr ) ;
FloatPlayerVariable * floatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( playerVar ) ;
FloatPlayerVariable * customFloatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( customPlayerVar ) ;
if ( ! defPlayerVar ) {
defPlayerVar = defaultPlayerVars . emplace_back ( std : : make_unique < FloatPlayerVariable > ( name ) ) . get ( ) ;
FloatPlayerVariable * defFloatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( defPlayerVar ) ;
defFloatPlayerVar - > SetValues ( floatPlayerVar - > value ) ;
}
floatPlayerVar - > SetValues ( actualValue ) ;
customFloatPlayerVar - > SetValues ( actualValue ) ;
break ;
}
case PlayerVarType : : Bool :
{
if ( ! customPlayerVar )
customPlayerVar = customPlayerVars . emplace_back ( std : : make_unique < BoolPlayerVariable > ( name ) ) . get ( ) ;
std : : string valueStr = Utils : : Values : : to_string ( value ) ;
bool actualValue = valueStr = = " true " ;
BoolPlayerVariable * boolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( playerVar ) ;
BoolPlayerVariable * customBoolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( customPlayerVar ) ;
if ( ! defPlayerVar ) {
defPlayerVar = defaultPlayerVars . emplace_back ( std : : make_unique < BoolPlayerVariable > ( name ) ) . get ( ) ;
BoolPlayerVariable * defBoolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( defPlayerVar ) ;
defBoolPlayerVar - > SetValues ( boolPlayerVar - > value ) ;
}
boolPlayerVar - > SetValues ( actualValue ) ;
customBoolPlayerVar - > SetValues ( actualValue ) ;
break ;
}
default :
break ;
}
} else if constexpr ( std : : is_same_v < T , float > ) {
if ( playerVar - > GetType ( ) ! = PlayerVarType : : Float )
return ;
if ( ! customPlayerVar )
customPlayerVar = customPlayerVars . emplace_back ( std : : make_unique < FloatPlayerVariable > ( name ) ) . get ( ) ;
FloatPlayerVariable * floatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( playerVar ) ;
FloatPlayerVariable * customFloatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( customPlayerVar ) ;
if ( ! defPlayerVar ) {
defPlayerVar = defaultPlayerVars . emplace_back ( std : : make_unique < FloatPlayerVariable > ( name ) ) . get ( ) ;
FloatPlayerVariable * defFloatPlayerVar = reinterpret_cast < FloatPlayerVariable * > ( defPlayerVar ) ;
defFloatPlayerVar - > SetValues ( floatPlayerVar - > value ) ;
}
floatPlayerVar - > SetValues ( value ) ;
customFloatPlayerVar - > SetValues ( value ) ;
} else if constexpr ( std : : is_same_v < T , bool > ) {
if ( playerVar - > GetType ( ) ! = PlayerVarType : : Bool )
return ;
if ( ! customPlayerVar )
customPlayerVar = customPlayerVars . emplace_back ( std : : make_unique < BoolPlayerVariable > ( name ) ) . get ( ) ;
BoolPlayerVariable * boolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( playerVar ) ;
BoolPlayerVariable * customBoolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( customPlayerVar ) ;
if ( ! defPlayerVar ) {
defPlayerVar = defaultPlayerVars . emplace_back ( std : : make_unique < BoolPlayerVariable > ( name ) ) . get ( ) ;
BoolPlayerVariable * defBoolPlayerVar = reinterpret_cast < BoolPlayerVariable * > ( defPlayerVar ) ;
defBoolPlayerVar - > SetValues ( boolPlayerVar - > value ) ;
}
boolPlayerVar - > SetValues ( value ) ;
customBoolPlayerVar - > SetValues ( value ) ;
}
}
template < typename T >
static void ManagePlayerVarByBool ( const std : : string & name , const T valueIfTrue , const T valueIfFalse , bool boolVal , bool usePreviousVal = true ) {
if ( ! gotPlayerVars )
return ;
if ( prevPlayerVarValueMap . find ( name ) = = prevPlayerVarValueMap . end ( ) )
prevPlayerVarValueMap [ name ] = GetPlayerVarValue < T > ( name ) ;
if ( prevBoolValueMap . find ( name ) = = prevBoolValueMap . end ( ) )
prevBoolValueMap [ name ] = false ;
if ( boolVal ) {
if ( ! prevBoolValueMap [ name ] )
prevPlayerVarValueMap [ name ] = GetPlayerVarValue < T > ( name ) ;
ChangePlayerVar ( name , valueIfTrue ) ;
prevBoolValueMap [ name ] = true ;
} else if ( prevBoolValueMap [ name ] ) {
prevBoolValueMap [ name ] = false ;
ChangePlayerVar ( name , usePreviousVal ? std : : any_cast < T > ( prevPlayerVarValueMap [ name ] ) : valueIfFalse ) ;
prevPlayerVarValueMap . erase ( name ) ;
}
}
static bool IsPlayerVarManagedByBool ( const std : : string & name ) {
if ( ! gotPlayerVars )
return false ;
return prevBoolValueMap . find ( name ) ! = prevBoolValueMap . end ( ) & & prevBoolValueMap [ name ] ;
}
2024-12-30 01:25:31 +02:00
static PlayerVariables * GetOffset_PlayerVariables ( ) {
2025-01-06 09:11:01 +02:00
PlayerState * playerState = PlayerState : : Get ( ) ;
return playerState ? playerState - > playerVariables : nullptr ;
2024-12-30 01:25:31 +02:00
}
PlayerVariables * PlayerVariables : : Get ( ) {
2025-01-04 04:53:31 +02:00
return ClassHelpers : : SafeGetter < PlayerVariables > ( GetOffset_PlayerVariables , false , false ) ;
2024-12-30 01:25:31 +02:00
}
}