mirror of
https://github.com/EricPlayZ/EGameTools.git
synced 2025-07-18 17:37:53 +08:00
massive changes to Player Variables structure
This commit is contained in:
@ -4,6 +4,8 @@
|
||||
namespace EGSDK::GamePH {
|
||||
class EGameSDK_API InventoryMoney {
|
||||
public:
|
||||
ClassHelpers::buffer<0x38, int> oldWorldMoney;
|
||||
union {
|
||||
ClassHelpers::buffer<0x38, int> oldWorldMoney;
|
||||
};
|
||||
};
|
||||
}
|
@ -7,7 +7,7 @@ namespace EGSDK::GamePH {
|
||||
class EGameSDK_API PlayerState {
|
||||
public:
|
||||
union {
|
||||
ClassHelpers::buffer<0x300, PlayerVariables*> pPlayerVariables;
|
||||
ClassHelpers::buffer<0x300, PlayerVariables*> playerVariables;
|
||||
};
|
||||
|
||||
static PlayerState* Get();
|
||||
|
@ -2,24 +2,66 @@
|
||||
#include <any>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
#include <EGSDK\Utils\Values.h>
|
||||
|
||||
namespace EGSDK::GamePH {
|
||||
enum EGameSDK_API PlayerVarType {
|
||||
NONE = 0,
|
||||
String,
|
||||
Float,
|
||||
Bool
|
||||
};
|
||||
|
||||
class EGameSDK_API PlayerVariable {
|
||||
public:
|
||||
PlayerVariable(const std::string& name);
|
||||
|
||||
const char* GetName();
|
||||
void SetName(const std::string& newName);
|
||||
|
||||
PlayerVarType GetType();
|
||||
void SetType(PlayerVarType newType);
|
||||
private:
|
||||
static std::unordered_map<PlayerVariable*, std::string> playerVarNames;
|
||||
static std::unordered_map<PlayerVariable*, PlayerVarType> playerVarTypes;
|
||||
};
|
||||
class EGameSDK_API StringPlayerVariable : public PlayerVariable {
|
||||
public:
|
||||
union {
|
||||
EGSDK::ClassHelpers::buffer<0x8, const char*> value; // remove 0x2 bit to access ptr
|
||||
EGSDK::ClassHelpers::buffer<0x10, const char*> defaultValue; // remove 0x2 bit to access ptr
|
||||
};
|
||||
StringPlayerVariable(const std::string& name);
|
||||
};
|
||||
class EGameSDK_API FloatPlayerVariable : public PlayerVariable {
|
||||
public:
|
||||
union {
|
||||
EGSDK::ClassHelpers::buffer<0x8, float> value;
|
||||
EGSDK::ClassHelpers::buffer<0xC, float> defaultValue;
|
||||
};
|
||||
FloatPlayerVariable(const std::string& name);
|
||||
};
|
||||
class EGameSDK_API BoolPlayerVariable : public PlayerVariable {
|
||||
public:
|
||||
union {
|
||||
EGSDK::ClassHelpers::buffer<0x8, bool> value;
|
||||
EGSDK::ClassHelpers::buffer<0x9, bool> defaultValue;
|
||||
};
|
||||
BoolPlayerVariable(const std::string& name);
|
||||
};
|
||||
|
||||
class EGameSDK_API PlayerVariables {
|
||||
public:
|
||||
enum PlayerVarType {
|
||||
NONE = 0,
|
||||
String,
|
||||
Float,
|
||||
Bool
|
||||
};
|
||||
|
||||
static std::vector<std::pair<std::string, std::pair<void*, std::string>>> playerVars;
|
||||
static std::vector<std::pair<std::string, std::pair<std::any, std::string>>> playerVarsDefault;
|
||||
static std::vector<std::pair<std::string, std::pair<std::any, std::string>>> playerCustomVarsDefault;
|
||||
static std::vector<std::unique_ptr<PlayerVariable>> playerVars;
|
||||
static std::vector<std::unique_ptr<PlayerVariable>> defaultPlayerVars;
|
||||
static std::vector<std::unique_ptr<PlayerVariable>> customDefaultPlayerVars;
|
||||
static bool gotPlayerVars;
|
||||
|
||||
static std::unordered_map<std::string, std::any> prevPlayerVarValueMap;
|
||||
static std::unordered_map<std::string, bool> prevBoolValueMap;
|
||||
|
||||
#ifdef EGameSDK_EXPORTS
|
||||
static void GetPlayerVars();
|
||||
static bool SortPlayerVars();
|
||||
@ -27,70 +69,99 @@ namespace EGSDK::GamePH {
|
||||
|
||||
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, bool>)
|
||||
return false;
|
||||
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 GetPlayerVar(const std::string& playerVar) {
|
||||
static_assert(std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, std::string>, "Invalid type: value must be bool, float or string");
|
||||
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 it = std::find_if(PlayerVariables::playerVars.begin(), PlayerVariables::playerVars.end(), [&playerVar](const auto& pair) {
|
||||
return pair.first == playerVar;
|
||||
auto playerVarIt = std::find_if(playerVars.begin(), playerVars.end(), [&name](const auto& playerVar) {
|
||||
return playerVar->GetName() == name;
|
||||
});
|
||||
|
||||
if (it == PlayerVariables::playerVars.end())
|
||||
if (playerVarIt == playerVars.end())
|
||||
return getDefaultValue<T>();
|
||||
|
||||
return *reinterpret_cast<T*>(it->second.first);
|
||||
}
|
||||
template <typename T>
|
||||
static void ChangePlayerVar(const std::string& playerVar, const T value) {
|
||||
static_assert(std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, std::string>, "Invalid type: value must be bool, float or string");
|
||||
|
||||
if (!gotPlayerVars)
|
||||
return;
|
||||
|
||||
auto it = std::find_if(PlayerVariables::playerVars.begin(), PlayerVariables::playerVars.end(), [&playerVar](const auto& pair) {
|
||||
return pair.first == playerVar;
|
||||
});
|
||||
|
||||
if (it == PlayerVariables::playerVars.end())
|
||||
return;
|
||||
|
||||
if (std::is_same_v<T, std::string>) {
|
||||
std::string valueStr = Utils::Values::to_string(value);
|
||||
if (it->second.second == "float") {
|
||||
float* const varValue = reinterpret_cast<float*>(it->second.first);
|
||||
const float actualValue = std::stof(valueStr);
|
||||
|
||||
*varValue = actualValue;
|
||||
*(varValue + 1) = actualValue;
|
||||
} else {
|
||||
bool* const varValue = reinterpret_cast<bool*>(it->second.first);
|
||||
const bool actualValue = valueStr == "true";
|
||||
|
||||
*varValue = actualValue;
|
||||
*(varValue + 1) = actualValue;
|
||||
}
|
||||
} else {
|
||||
T* const varValue = reinterpret_cast<T*>(it->second.first);
|
||||
|
||||
*varValue = value;
|
||||
*(varValue + 1) = value;
|
||||
auto playerVar = playerVarIt->get();
|
||||
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 playerVarIt = std::find_if(playerVars.begin(), playerVars.end(), [&name](const auto& playerVar) {
|
||||
return playerVar->GetName() == name;
|
||||
});
|
||||
if (playerVarIt == playerVars.end())
|
||||
return;
|
||||
|
||||
auto playerVar = playerVarIt->get();
|
||||
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->value = actualValue;
|
||||
floatPlayerVar->defaultValue = actualValue;
|
||||
break;
|
||||
}
|
||||
case PlayerVarType::Bool: {
|
||||
std::string valueStr = Utils::Values::to_string(value);
|
||||
bool actualValue = valueStr == "true";
|
||||
|
||||
BoolPlayerVariable* boolPlayerVar = reinterpret_cast<BoolPlayerVariable*>(playerVar);
|
||||
boolPlayerVar->value = actualValue;
|
||||
boolPlayerVar->defaultValue = 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->value = value;
|
||||
floatPlayerVar->defaultValue = value;
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
if (playerVar->GetType() != PlayerVarType::Bool)
|
||||
return;
|
||||
|
||||
BoolPlayerVariable* boolPlayerVar = reinterpret_cast<BoolPlayerVariable*>(playerVar);
|
||||
boolPlayerVar->value = value;
|
||||
boolPlayerVar->defaultValue = value;
|
||||
}
|
||||
}
|
||||
static std::unordered_map<std::string, std::any> prevPlayerVarValueMap;
|
||||
static std::unordered_map<std::string, bool> prevBoolValueMap;
|
||||
|
||||
template <typename T>
|
||||
static void ManagePlayerVarByBool(const std::string& playerVar, const T valueIfTrue, const T valueIfFalse, bool boolVal, bool usePreviousVal = true) {
|
||||
@ -98,19 +169,19 @@ namespace EGSDK::GamePH {
|
||||
return;
|
||||
|
||||
if (prevPlayerVarValueMap.find(playerVar) == prevPlayerVarValueMap.end())
|
||||
prevPlayerVarValueMap[playerVar] = GamePH::PlayerVariables::GetPlayerVar<T>(playerVar);
|
||||
prevPlayerVarValueMap[playerVar] = GetPlayerVarValue<T>(playerVar);
|
||||
if (prevBoolValueMap.find(playerVar) == prevBoolValueMap.end())
|
||||
prevBoolValueMap[playerVar] = false;
|
||||
|
||||
if (boolVal) {
|
||||
if (!prevBoolValueMap[playerVar])
|
||||
prevPlayerVarValueMap[playerVar] = GamePH::PlayerVariables::GetPlayerVar<T>(playerVar);
|
||||
prevPlayerVarValueMap[playerVar] = GetPlayerVarValue<T>(playerVar);
|
||||
|
||||
GamePH::PlayerVariables::ChangePlayerVar(playerVar, valueIfTrue);
|
||||
ChangePlayerVar(playerVar, valueIfTrue);
|
||||
prevBoolValueMap[playerVar] = true;
|
||||
} else if (prevBoolValueMap[playerVar]) {
|
||||
prevBoolValueMap[playerVar] = false;
|
||||
GamePH::PlayerVariables::ChangePlayerVar(playerVar, usePreviousVal ? std::any_cast<T>(prevPlayerVarValueMap[playerVar]) : valueIfFalse);
|
||||
ChangePlayerVar(playerVar, usePreviousVal ? std::any_cast<T>(prevPlayerVarValueMap[playerVar]) : valueIfFalse);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,8 @@ namespace EGSDK::Utils {
|
||||
extern EGameSDK_API float round_decimal(float value, int decimal_places = 2);
|
||||
|
||||
extern EGameSDK_API bool str_replace(std::string& str, const std::string& from, const std::string& to);
|
||||
template <typename T> auto to_string(T val) {
|
||||
template <typename T>
|
||||
auto to_string(T val) {
|
||||
if constexpr (std::is_same<T, std::string>::value)
|
||||
return static_cast<std::string>(val);
|
||||
else
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <Windows.h>
|
||||
#include <algorithm>
|
||||
#include <spdlog\spdlog.h>
|
||||
#include <EGSDK\Offsets.h>
|
||||
#include <EGSDK\GamePH\PlayerState.h>
|
||||
@ -6,59 +7,160 @@
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
|
||||
namespace EGSDK::GamePH {
|
||||
static const int FLOAT_VAR_OFFSET = 3;
|
||||
static const int BOOL_VAR_OFFSET = 2;
|
||||
static const int VAR_LOC_OFFSET = 1;
|
||||
static constexpr int STRING_SIZE_OFFSET = 3;
|
||||
static constexpr int FLOAT_SIZE_OFFSET = 3;
|
||||
static constexpr int BOOL_SIZE_OFFSET = 2;
|
||||
|
||||
std::vector<std::pair<std::string, std::pair<void*, std::string>>> PlayerVariables::playerVars;
|
||||
std::vector<std::pair<std::string, std::pair<std::any, std::string>>> PlayerVariables::playerVarsDefault;
|
||||
std::vector<std::pair<std::string, std::pair<std::any, std::string>>> PlayerVariables::playerCustomVarsDefault;
|
||||
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;
|
||||
}
|
||||
|
||||
StringPlayerVariable::StringPlayerVariable(const std::string& name) : PlayerVariable(name) {
|
||||
SetType(PlayerVarType::String);
|
||||
}
|
||||
FloatPlayerVariable::FloatPlayerVariable(const std::string& name) : PlayerVariable(name) {
|
||||
SetType(PlayerVarType::Float);
|
||||
}
|
||||
BoolPlayerVariable::BoolPlayerVariable(const std::string& name) : PlayerVariable(name) {
|
||||
SetType(PlayerVarType::Bool);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<PlayerVariable>> PlayerVariables::playerVars{};
|
||||
std::vector<std::unique_ptr<PlayerVariable>> PlayerVariables::defaultPlayerVars{};
|
||||
std::vector<std::unique_ptr<PlayerVariable>> PlayerVariables::customDefaultPlayerVars{};
|
||||
bool PlayerVariables::gotPlayerVars = false;
|
||||
static bool sortedPlayerVars = false;
|
||||
|
||||
std::unordered_map<std::string, std::any> PlayerVariables::prevPlayerVarValueMap{};
|
||||
std::unordered_map<std::string, bool> PlayerVariables::prevBoolValueMap{};
|
||||
|
||||
template <typename T>
|
||||
static void updateDefaultVar(std::vector<std::pair<std::string, std::pair<std::any, std::string>>>& defaultVars, const std::string& varName, T varValue) {
|
||||
static_assert(std::is_same<T, float>::value || std::is_same<T, bool>::value, "Invalid type: value must be float or bool");
|
||||
static void updateDefaultVar(std::vector<std::unique_ptr<PlayerVariable>>& defaultVars, const std::string& name, T value, T defaultValue) {
|
||||
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");
|
||||
|
||||
auto it = std::find_if(defaultVars.begin(), defaultVars.end(), [&varName](const auto& pair) {
|
||||
return pair.first == varName;
|
||||
auto playerVarIt = std::find_if(defaultVars.begin(), defaultVars.end(), [&name](const auto& playerVar) {
|
||||
return playerVar->GetName() == name;
|
||||
});
|
||||
if (it == defaultVars.end())
|
||||
return;
|
||||
|
||||
it->second.first.template emplace<T>(varValue);
|
||||
if (playerVarIt == defaultVars.end()) {
|
||||
if constexpr (std::is_same_v<T, std::string>) {
|
||||
auto stringPlayerVar = std::make_unique<StringPlayerVariable>(name);
|
||||
stringPlayerVar->value = value;
|
||||
stringPlayerVar->defaultValue = defaultValue;
|
||||
defaultVars.emplace_back(std::move(stringPlayerVar));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, float>) {
|
||||
auto floatPlayerVar = std::make_unique<FloatPlayerVariable>(name);
|
||||
floatPlayerVar->value = value;
|
||||
floatPlayerVar->defaultValue = defaultValue;
|
||||
defaultVars.emplace_back(std::move(floatPlayerVar));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, bool>) {
|
||||
auto boolPlayerVar = std::make_unique<BoolPlayerVariable>(name);
|
||||
boolPlayerVar->value = value;
|
||||
boolPlayerVar->defaultValue = defaultValue;
|
||||
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>) {
|
||||
auto floatPlayerVar = reinterpret_cast<FloatPlayerVariable*>(playerVarIt->get());
|
||||
floatPlayerVar->value = value;
|
||||
floatPlayerVar->defaultValue = defaultValue;
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
auto boolPlayerVar = reinterpret_cast<BoolPlayerVariable*>(playerVarIt->get());
|
||||
boolPlayerVar->value = value;
|
||||
boolPlayerVar->defaultValue = defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void processPlayerVar(DWORD64*(*playerVarsGetter)(), std::pair<std::string, std::pair<void*, std::string>>& var) {
|
||||
static void processPlayerVar(DWORD64*(*playerVarsGetter)(), std::unique_ptr<PlayerVariable>& playerVar) {
|
||||
static int offset = 0;
|
||||
static const std::string floatPlayerVarClassName = "FloatPlayerVariable";
|
||||
static const std::string boolPlayerVarClassName = "BoolPlayerVariable";
|
||||
|
||||
int offsetDif = 0;
|
||||
while (true) {
|
||||
const std::string vTableName = Utils::RTTI::GetVTableName(playerVarsGetter() + offset);
|
||||
const bool isFloatPlayerVar = vTableName == floatPlayerVarClassName;
|
||||
const bool isBoolPlayerVar = vTableName == boolPlayerVarClassName;
|
||||
std::string vTableName = Utils::RTTI::GetVTableName(playerVarsGetter() + offset);
|
||||
if (vTableName != "StringPlayerVariable" && vTableName != "FloatPlayerVariable" && vTableName != "BoolPlayerVariable") {
|
||||
if (offsetDif > 150)
|
||||
return;
|
||||
|
||||
if (isFloatPlayerVar || isBoolPlayerVar) {
|
||||
var.second.first = playerVarsGetter() + offset + VAR_LOC_OFFSET;
|
||||
const std::string& varName = var.first;
|
||||
|
||||
if (isFloatPlayerVar) {
|
||||
float* varValue = reinterpret_cast<float*>(var.second.first);
|
||||
updateDefaultVar(GamePH::PlayerVariables::playerVarsDefault, varName, *varValue);
|
||||
updateDefaultVar(GamePH::PlayerVariables::playerCustomVarsDefault, varName, *varValue);
|
||||
|
||||
offset += FLOAT_VAR_OFFSET;
|
||||
} else {
|
||||
bool* varValue = reinterpret_cast<bool*>(var.second.first);
|
||||
updateDefaultVar(GamePH::PlayerVariables::playerVarsDefault, varName, *varValue);
|
||||
updateDefaultVar(GamePH::PlayerVariables::playerCustomVarsDefault, varName, *varValue);
|
||||
|
||||
offset += BOOL_VAR_OFFSET;
|
||||
}
|
||||
|
||||
break;
|
||||
} else
|
||||
offset += 1;
|
||||
offsetDif += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string varName = playerVar->GetName();
|
||||
PlayerVarType varType = playerVar->GetType();
|
||||
|
||||
switch (playerVar->GetType()) {
|
||||
case PlayerVarType::String: {
|
||||
if (vTableName != "StringPlayerVariable")
|
||||
return;
|
||||
|
||||
StringPlayerVariable* stringPlayerVar = reinterpret_cast<StringPlayerVariable*>(playerVarsGetter() + offset);
|
||||
playerVar.reset(stringPlayerVar);
|
||||
playerVar->SetName(varName);
|
||||
playerVar->SetType(varType);
|
||||
// TO IMPLEMENT
|
||||
|
||||
offset += STRING_SIZE_OFFSET;
|
||||
return;
|
||||
}
|
||||
case PlayerVarType::Float: {
|
||||
if (vTableName != "FloatPlayerVariable")
|
||||
return;
|
||||
|
||||
FloatPlayerVariable* floatPlayerVar = reinterpret_cast<FloatPlayerVariable*>(playerVarsGetter() + offset);
|
||||
playerVar.reset(floatPlayerVar);
|
||||
playerVar->SetName(varName);
|
||||
playerVar->SetType(varType);
|
||||
updateDefaultVar(PlayerVariables::defaultPlayerVars, varName, floatPlayerVar->value.data, floatPlayerVar->defaultValue.data);
|
||||
updateDefaultVar(PlayerVariables::customDefaultPlayerVars, varName, floatPlayerVar->value.data, floatPlayerVar->defaultValue.data);
|
||||
|
||||
offset += FLOAT_SIZE_OFFSET;
|
||||
return;
|
||||
}
|
||||
case PlayerVarType::Bool: {
|
||||
if (vTableName != "BoolPlayerVariable")
|
||||
return;
|
||||
|
||||
BoolPlayerVariable* boolPlayerVar = reinterpret_cast<BoolPlayerVariable*>(playerVarsGetter() + offset);
|
||||
playerVar.reset(boolPlayerVar);
|
||||
playerVar->SetName(varName);
|
||||
playerVar->SetType(varType);
|
||||
updateDefaultVar(PlayerVariables::defaultPlayerVars, varName, boolPlayerVar->value.data, boolPlayerVar->defaultValue.data);
|
||||
updateDefaultVar(PlayerVariables::customDefaultPlayerVars, varName, boolPlayerVar->value.data, boolPlayerVar->defaultValue.data);
|
||||
|
||||
offset += BOOL_SIZE_OFFSET;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
offset += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +176,7 @@ namespace EGSDK::GamePH {
|
||||
__try {
|
||||
processPlayerVar(reinterpret_cast<DWORD64*(*)()>(&Get), var);
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
SPDLOG_ERROR("Failed to process player variable: {}", var.first);
|
||||
SPDLOG_ERROR("Failed to process player variable: {}", var->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,12 +185,13 @@ namespace EGSDK::GamePH {
|
||||
|
||||
#pragma region Player Variables Sorting
|
||||
struct VarTypeFieldMeta {
|
||||
PlayerVariables::PlayerVarType type;
|
||||
PlayerVarType type;
|
||||
std::string_view className;
|
||||
};
|
||||
const std::vector<VarTypeFieldMeta> varTypeFields = {
|
||||
{ PlayerVariables::PlayerVarType::Float, "constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<FloatPlayerVariable>" },
|
||||
{ PlayerVariables::PlayerVarType::Bool, "constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<BoolPlayerVariable>" }
|
||||
{ PlayerVarType::String, "constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<StringPlayerVariable>" },
|
||||
{ PlayerVarType::Float, "constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<FloatPlayerVariable>" },
|
||||
{ PlayerVarType::Bool, "constds::FieldsCollection<PlayerVariables>::TypedFieldMeta<BoolPlayerVariable>" }
|
||||
};
|
||||
|
||||
static bool isRetInstruction(BYTE* address) {
|
||||
@ -130,8 +233,8 @@ namespace EGSDK::GamePH {
|
||||
|
||||
return playerVarName;
|
||||
}
|
||||
static PlayerVariables::PlayerVarType getPlayerVarType(BYTE*& funcAddress, DWORD64 startOfFunc) {
|
||||
PlayerVariables::PlayerVarType playerVarType = PlayerVariables::PlayerVarType::NONE;
|
||||
static PlayerVarType getPlayerVarType(BYTE*& funcAddress, DWORD64 startOfFunc) {
|
||||
PlayerVarType playerVarType = PlayerVarType::NONE;
|
||||
|
||||
while (!playerVarType && !isRetInstruction(funcAddress) && isBelowFuncSizeLimit(funcAddress, startOfFunc, MAX_FUNC_SIZE)) {
|
||||
// call LoadPlayerXVariable
|
||||
@ -141,33 +244,33 @@ namespace EGSDK::GamePH {
|
||||
}
|
||||
|
||||
DWORD64 startOfLoadVarFunc = Utils::Memory::CalcTargetAddrOfRelativeInstr(reinterpret_cast<DWORD64>(funcAddress), 1);
|
||||
for (const auto& varType : varTypeFields) {
|
||||
BYTE* loadVarFuncAddress = reinterpret_cast<BYTE*>(startOfLoadVarFunc);
|
||||
DWORD64 metaVTAddrFromFunc = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
metaVTAddrFromFunc = Utils::Memory::CalcTargetAddrOfRelativeInstr(reinterpret_cast<DWORD64>(loadVarFuncAddress), 3);
|
||||
if (Utils::RTTI::GetVTableNameFromVTPtr(reinterpret_cast<DWORD64*>(metaVTAddrFromFunc)) != varType.className) {
|
||||
metaVTAddrFromFunc = 0;
|
||||
loadVarFuncAddress++;
|
||||
continue;
|
||||
}
|
||||
while (!metaVTAddrFromFunc && !isRetInstruction(loadVarFuncAddress) && isBelowFuncSizeLimit(loadVarFuncAddress, startOfLoadVarFunc, MAX_LOAD_VAR_FUNC_SIZE)) {
|
||||
// lea rax, typedFieldMetaVT
|
||||
if (!isLeaInstruction(loadVarFuncAddress, 0x48, 0x05)) {
|
||||
loadVarFuncAddress++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Utils::RTTI::GetVTableNameFromVTPtr(reinterpret_cast<DWORD64*>(metaVTAddrFromFunc)) == varType.className) {
|
||||
playerVarType = varType.type;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
playerVarType = varTypeIt->type;
|
||||
break;
|
||||
}
|
||||
|
||||
// if it's still NONE after seeing the function doesnt reference any of the variables, break so the loop stops
|
||||
if (playerVarType == PlayerVariables::PlayerVarType::NONE)
|
||||
if (playerVarType == PlayerVarType::NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -186,24 +289,20 @@ namespace EGSDK::GamePH {
|
||||
continue;
|
||||
|
||||
PlayerVarType playerVarType = getPlayerVarType(funcAddress, startOfFunc);
|
||||
if (!playerVarType)
|
||||
continue;
|
||||
|
||||
std::string varType{};
|
||||
switch (playerVarType) {
|
||||
case PlayerVarType::String:
|
||||
playerVars.emplace_back(std::make_unique<StringPlayerVariable>(playerVarName));
|
||||
break;
|
||||
case PlayerVarType::Float:
|
||||
varType = "float";
|
||||
playerVars.emplace_back(std::make_unique<FloatPlayerVariable>(playerVarName));
|
||||
break;
|
||||
case PlayerVarType::Bool:
|
||||
varType = "bool";
|
||||
playerVars.emplace_back(std::make_unique<BoolPlayerVariable>(playerVarName));
|
||||
break;
|
||||
default:
|
||||
//playerVars.emplace_back(std::make_unique<PlayerVariable>(playerVarName));
|
||||
break;
|
||||
}
|
||||
|
||||
PlayerVariables::playerVars.emplace_back(playerVarName, std::make_pair(nullptr, varType));
|
||||
PlayerVariables::playerVarsDefault.emplace_back(playerVarName, std::make_pair(varType == "float" ? 0.0f : false, varType));
|
||||
PlayerVariables::playerCustomVarsDefault.emplace_back(playerVarName, std::make_pair(varType == "float" ? 0.0f : false, varType));
|
||||
}
|
||||
|
||||
sortedPlayerVars = true;
|
||||
@ -211,12 +310,9 @@ namespace EGSDK::GamePH {
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
std::unordered_map<std::string, std::any> PlayerVariables::prevPlayerVarValueMap{};
|
||||
std::unordered_map<std::string, bool> PlayerVariables::prevBoolValueMap{};
|
||||
|
||||
static PlayerVariables* GetOffset_PlayerVariables() {
|
||||
PlayerState* pPlayerState = PlayerState::Get();
|
||||
return pPlayerState ? pPlayerState->pPlayerVariables : nullptr;
|
||||
PlayerState* playerState = PlayerState::Get();
|
||||
return playerState ? playerState->playerVariables : nullptr;
|
||||
}
|
||||
PlayerVariables* PlayerVariables::Get() {
|
||||
return ClassHelpers::SafeGetter<PlayerVariables>(GetOffset_PlayerVariables, false, false);
|
||||
|
@ -115,22 +115,34 @@ namespace EGT::Menu {
|
||||
if (!playerVariables.GetValue())
|
||||
return;
|
||||
|
||||
auto bgn = EGSDK::GamePH::PlayerVariables::playerVars.begin();
|
||||
for (auto it = bgn; it != EGSDK::GamePH::PlayerVariables::playerVars.end(); ++it) {
|
||||
if (!it->second.first)
|
||||
continue;
|
||||
|
||||
auto playerVarBeginIt = EGSDK::GamePH::PlayerVariables::playerVars.begin();
|
||||
for (auto& playerVarIt = playerVarBeginIt; playerVarIt != EGSDK::GamePH::PlayerVariables::playerVars.end(); ++playerVarIt) {
|
||||
auto playerVar = playerVarIt->get();
|
||||
try {
|
||||
auto& valDef = EGSDK::GamePH::PlayerVariables::playerVarsDefault.at(it - bgn);
|
||||
auto defPlayerVar = &EGSDK::GamePH::PlayerVariables::defaultPlayerVars.at(playerVarIt - playerVarBeginIt);
|
||||
|
||||
if (it->second.second == "float") {
|
||||
float* varAddr = reinterpret_cast<float*>(it->second.first);
|
||||
if (!EGSDK::Utils::Values::are_samef(*varAddr, *(varAddr + 1)) && !EGSDK::Utils::Values::are_samef(*(varAddr + 1), std::any_cast<float>(valDef.second.first)))
|
||||
*varAddr = *(varAddr + 1);
|
||||
} else if (it->second.second == "bool") {
|
||||
bool* varAddr = reinterpret_cast<bool*>(it->second.first);
|
||||
if (*varAddr != *(varAddr + 1) && *(varAddr + 1) != std::any_cast<bool>(valDef.second.first))
|
||||
*varAddr = *(varAddr + 1);
|
||||
switch (playerVar->GetType()) {
|
||||
case EGSDK::GamePH::PlayerVarType::String:
|
||||
// TO IMPLEMENT
|
||||
break;
|
||||
case EGSDK::GamePH::PlayerVarType::Float: {
|
||||
EGSDK::GamePH::FloatPlayerVariable* floatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(playerVar);
|
||||
EGSDK::GamePH::FloatPlayerVariable* defFloatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(defPlayerVar->get());
|
||||
|
||||
if (!EGSDK::Utils::Values::are_samef(floatPlayerVar->value, floatPlayerVar->defaultValue) && !EGSDK::Utils::Values::are_samef(floatPlayerVar->defaultValue, defFloatPlayerVar->value))
|
||||
floatPlayerVar->value = floatPlayerVar->defaultValue;
|
||||
break;
|
||||
}
|
||||
case EGSDK::GamePH::PlayerVarType::Bool: {
|
||||
EGSDK::GamePH::BoolPlayerVariable* boolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(playerVar);
|
||||
EGSDK::GamePH::BoolPlayerVariable* defBoolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(defPlayerVar->get());
|
||||
|
||||
if (!EGSDK::Utils::Values::are_samef(boolPlayerVar->value, boolPlayerVar->defaultValue) && !EGSDK::Utils::Values::are_samef(boolPlayerVar->defaultValue, defBoolPlayerVar->value))
|
||||
boolPlayerVar->value = boolPlayerVar->defaultValue;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
UNREFERENCED_PARAMETER(e);
|
||||
@ -208,23 +220,33 @@ namespace EGT::Menu {
|
||||
std::string line{};
|
||||
while (std::getline(iss, line)) {
|
||||
const std::string origLine = line;
|
||||
const std::string paramName = getParamName(line);
|
||||
if (paramName.empty())
|
||||
const std::string name = getParamName(line);
|
||||
if (name.empty())
|
||||
continue;
|
||||
|
||||
auto it = std::find_if(EGSDK::GamePH::PlayerVariables::playerVars.begin(), EGSDK::GamePH::PlayerVariables::playerVars.end(), [¶mName](const auto& pair) {
|
||||
return pair.first == paramName;
|
||||
auto playerVarIt = std::find_if(EGSDK::GamePH::PlayerVariables::playerVars.begin(), EGSDK::GamePH::PlayerVariables::playerVars.end(), [&name](const auto& playerVar) {
|
||||
return playerVar->GetName() == name;
|
||||
});
|
||||
if (it == EGSDK::GamePH::PlayerVariables::playerVars.end())
|
||||
if (playerVarIt == EGSDK::GamePH::PlayerVariables::playerVars.end())
|
||||
continue;
|
||||
|
||||
if (it->second.second == "float") {
|
||||
float value = *reinterpret_cast<float*>(it->second.first);
|
||||
replaceParamValue(line, std::to_string(value));
|
||||
|
||||
} else {
|
||||
bool value = *reinterpret_cast<bool*>(it->second.first);
|
||||
replaceParamValue(line, value ? "true" : "false");
|
||||
auto playerVar = playerVarIt->get();
|
||||
switch (playerVar->GetType()) {
|
||||
case EGSDK::GamePH::PlayerVarType::String:
|
||||
// TO IMPLEMENT
|
||||
break;
|
||||
case EGSDK::GamePH::PlayerVarType::Float: {
|
||||
EGSDK::GamePH::FloatPlayerVariable* floatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(playerVar);
|
||||
replaceParamValue(line, std::to_string(floatPlayerVar->value));
|
||||
break;
|
||||
}
|
||||
case EGSDK::GamePH::PlayerVarType::Bool: {
|
||||
EGSDK::GamePH::BoolPlayerVariable* boolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(playerVar);
|
||||
replaceParamValue(line, boolPlayerVar ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
EGSDK::Utils::Values::str_replace(tempPlayerVarsSCR, origLine, line);
|
||||
}
|
||||
@ -251,14 +273,14 @@ namespace EGT::Menu {
|
||||
|
||||
std::string line{};
|
||||
while (std::getline(file, line)) {
|
||||
const std::string paramName = getParamName(line);
|
||||
if (paramName.empty())
|
||||
std::string name = getParamName(line);
|
||||
if (name.empty())
|
||||
continue;
|
||||
const std::string paramValue = getParamValue(line);
|
||||
if (paramValue.empty())
|
||||
std::string value = getParamValue(line);
|
||||
if (value.empty())
|
||||
continue;
|
||||
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(paramName, paramValue);
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(name, value);
|
||||
}
|
||||
file.close();
|
||||
|
||||
@ -266,82 +288,117 @@ namespace EGT::Menu {
|
||||
}
|
||||
|
||||
static void RestoreVariablesToDefault() {
|
||||
for (auto const& [key, val] : EGSDK::GamePH::PlayerVariables::playerVars) {
|
||||
if (!val.first)
|
||||
continue;
|
||||
|
||||
auto& defVars = restoreVarsToSavedVarsEnabled ? EGSDK::GamePH::PlayerVariables::playerCustomVarsDefault : EGSDK::GamePH::PlayerVariables::playerVarsDefault;
|
||||
auto itDef = std::find_if(defVars.begin(), defVars.end(), [&key](const auto& pair) {
|
||||
return pair.first == key;
|
||||
for (auto const& playerVar : EGSDK::GamePH::PlayerVariables::playerVars) {
|
||||
auto& defVars = restoreVarsToSavedVarsEnabled ? EGSDK::GamePH::PlayerVariables::customDefaultPlayerVars : EGSDK::GamePH::PlayerVariables::defaultPlayerVars;
|
||||
auto defPlayerVarIt = std::find_if(defVars.begin(), defVars.end(), [&playerVar](const auto& defPlayerVar) {
|
||||
return defPlayerVar->GetName() == playerVar->GetName();
|
||||
});
|
||||
if (itDef == defVars.end())
|
||||
if (defPlayerVarIt == defVars.end())
|
||||
continue;
|
||||
|
||||
if (val.second == "float")
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(key, std::any_cast<float>(itDef->second.first));
|
||||
else
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(key, std::any_cast<bool>(itDef->second.first));
|
||||
switch (playerVar->GetType()) {
|
||||
case EGSDK::GamePH::PlayerVarType::String:
|
||||
// TO IMPLEMENT
|
||||
break;
|
||||
case EGSDK::GamePH::PlayerVarType::Float: {
|
||||
EGSDK::GamePH::FloatPlayerVariable* defFloatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(defPlayerVarIt->get());
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(playerVar->GetName(), defFloatPlayerVar->value.data);
|
||||
break;
|
||||
}
|
||||
case EGSDK::GamePH::PlayerVarType::Bool: {
|
||||
EGSDK::GamePH::BoolPlayerVariable* defBoolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(defPlayerVarIt->get());
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(playerVar->GetName(), defBoolPlayerVar->value.data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::OpenPopup("Restored player variables!");
|
||||
}
|
||||
static void SaveVariablesAsDefault() {
|
||||
for (auto const& [key, val] : EGSDK::GamePH::PlayerVariables::playerVars) {
|
||||
if (!val.first)
|
||||
continue;
|
||||
|
||||
auto itCustomDef = std::find_if(EGSDK::GamePH::PlayerVariables::playerCustomVarsDefault.begin(), EGSDK::GamePH::PlayerVariables::playerCustomVarsDefault.end(), [&key](const auto& pair) {
|
||||
return pair.first == key;
|
||||
for (auto const& playerVar : EGSDK::GamePH::PlayerVariables::playerVars) {
|
||||
auto defCustomPlayerVarIt = std::find_if(EGSDK::GamePH::PlayerVariables::customDefaultPlayerVars.begin(), EGSDK::GamePH::PlayerVariables::customDefaultPlayerVars.end(), [&playerVar](const auto& defCustomPlayerVar) {
|
||||
return defCustomPlayerVar->GetName() == playerVar->GetName();
|
||||
});
|
||||
if (itCustomDef == EGSDK::GamePH::PlayerVariables::playerCustomVarsDefault.end())
|
||||
if (defCustomPlayerVarIt == EGSDK::GamePH::PlayerVariables::customDefaultPlayerVars.end())
|
||||
continue;
|
||||
|
||||
if (val.second == "float") {
|
||||
float* const varAddr = reinterpret_cast<float*>(val.first);
|
||||
itCustomDef->second.first = *varAddr;
|
||||
} else if (val.second == "bool") {
|
||||
bool* const varAddr = reinterpret_cast<bool*>(val.first);
|
||||
itCustomDef->second.first = *varAddr;
|
||||
switch (playerVar->GetType()) {
|
||||
case EGSDK::GamePH::PlayerVarType::String:
|
||||
// TO IMPLEMENT
|
||||
break;
|
||||
case EGSDK::GamePH::PlayerVarType::Float: {
|
||||
EGSDK::GamePH::FloatPlayerVariable* floatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(playerVar.get());
|
||||
EGSDK::GamePH::FloatPlayerVariable* defCustomFloatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(defCustomPlayerVarIt->get());
|
||||
defCustomFloatPlayerVar->value = floatPlayerVar->value;
|
||||
break;
|
||||
}
|
||||
case EGSDK::GamePH::PlayerVarType::Bool: {
|
||||
EGSDK::GamePH::BoolPlayerVariable* boolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(playerVar.get());
|
||||
EGSDK::GamePH::BoolPlayerVariable* defCustomBoolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(defCustomPlayerVarIt->get());
|
||||
defCustomBoolPlayerVar->value = boolPlayerVar->value;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::OpenPopup("Saved current player variables!");
|
||||
}
|
||||
static void RestoreVariableToDefault(const std::string& varName) {
|
||||
auto& defVars = restoreVarsToSavedVarsEnabled ? EGSDK::GamePH::PlayerVariables::playerCustomVarsDefault : EGSDK::GamePH::PlayerVariables::playerVarsDefault;
|
||||
auto itDef = std::find_if(defVars.begin(), defVars.end(), [&varName](const auto& pair) {
|
||||
return pair.first == varName;
|
||||
static void RestoreVariableToDefault(const std::string& name) {
|
||||
auto& defVars = restoreVarsToSavedVarsEnabled ? EGSDK::GamePH::PlayerVariables::customDefaultPlayerVars : EGSDK::GamePH::PlayerVariables::defaultPlayerVars;
|
||||
auto defPlayerVarIt = std::find_if(defVars.begin(), defVars.end(), [&name](const auto& defPlayerVar) {
|
||||
return defPlayerVar->GetName() == name;
|
||||
});
|
||||
if (itDef == defVars.end())
|
||||
if (defPlayerVarIt == defVars.end())
|
||||
return;
|
||||
|
||||
if (itDef->second.second == "float")
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(varName, std::any_cast<float>(itDef->second.first));
|
||||
else
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(varName, std::any_cast<bool>(itDef->second.first));
|
||||
switch (defPlayerVarIt->get()->GetType()) {
|
||||
case EGSDK::GamePH::PlayerVarType::String:
|
||||
// TO IMPLEMENT
|
||||
break;
|
||||
case EGSDK::GamePH::PlayerVarType::Float: {
|
||||
EGSDK::GamePH::FloatPlayerVariable* defFloatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(defPlayerVarIt->get());
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(name, defFloatPlayerVar->value.data);
|
||||
break;
|
||||
}
|
||||
case EGSDK::GamePH::PlayerVarType::Bool: {
|
||||
EGSDK::GamePH::BoolPlayerVariable* defBoolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(defPlayerVarIt->get());
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar(name, defBoolPlayerVar->value.data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool shouldDisplayVariable(const std::string& key, const std::string& searchFilter) {
|
||||
if (searchFilter.empty()) return true;
|
||||
static bool shouldDisplayVariable(const std::unique_ptr<EGSDK::GamePH::PlayerVariable>& playerVar, const std::string& searchFilter) {
|
||||
if (playerVar->GetType() == EGSDK::GamePH::PlayerVarType::String || playerVar->GetType() == EGSDK::GamePH::PlayerVarType::NONE) // TO IMPLEMENT
|
||||
return false;
|
||||
if (searchFilter.empty())
|
||||
return true;
|
||||
|
||||
// Convert searchFilter to lowercase
|
||||
std::string lowerFilter = searchFilter;
|
||||
std::transform(lowerFilter.begin(), lowerFilter.end(), lowerFilter.begin(), ::tolower);
|
||||
|
||||
// Convert key to lowercase and check if it contains the filter
|
||||
std::string lowerKey = key;
|
||||
// Convert variable name to lowercase and check if it contains the filter
|
||||
std::string lowerKey = playerVar->GetName();
|
||||
std::transform(lowerKey.begin(), lowerKey.end(), lowerKey.begin(), ::tolower);
|
||||
return lowerKey.find(lowerFilter) != std::string::npos;
|
||||
}
|
||||
static void renderDebugInfo(const std::string& key, const std::pair<void*, std::string>& val) {
|
||||
static void renderDebugInfo(const std::unique_ptr<EGSDK::GamePH::PlayerVariable>& playerVar) {
|
||||
const float maxInputTextWidth = ImGui::CalcTextSize("0x0000000000000000").x;
|
||||
static std::string labelID{};
|
||||
labelID = "##DebugAddrInputText" + std::string(key);
|
||||
DWORD64 finalAddr = val.second == "float" ? reinterpret_cast<DWORD64>(reinterpret_cast<float*>(val.first)) : reinterpret_cast<DWORD64>(reinterpret_cast<bool*>(val.first));
|
||||
labelID = "##DebugAddrInputText" + std::string(playerVar->GetName());
|
||||
DWORD64 finalVarValueAddr = reinterpret_cast<DWORD64>(playerVar.get()) + 0x8;
|
||||
|
||||
std::stringstream ss;
|
||||
if (finalAddr)
|
||||
ss << "0x" << std::uppercase << std::hex << finalAddr;
|
||||
if (finalVarValueAddr)
|
||||
ss << "0x" << std::uppercase << std::hex << finalVarValueAddr;
|
||||
else
|
||||
ss << "NULL";
|
||||
|
||||
@ -352,38 +409,45 @@ namespace EGT::Menu {
|
||||
|
||||
//ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ((ImGui::GetFrameHeight() - ImGui::GetTextLineHeight()) / 2.0f));
|
||||
ImGui::SetNextItemWidth(maxInputTextWidth);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, finalAddr ? IM_COL32(0, 255, 0, 255) : IM_COL32(255, 0, 0, 255));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, finalVarValueAddr ? IM_COL32(0, 255, 0, 255) : IM_COL32(255, 0, 0, 255));
|
||||
ImGui::InputText(labelID.c_str(), const_cast<char*>(addrString.c_str()), strlen(addrString.c_str()), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
static void renderPlayerVariable(const std::string& key, const std::pair<void*, std::string>& val) {
|
||||
float* floatVarAddr = nullptr;
|
||||
bool* boolVarAddr = nullptr;
|
||||
|
||||
if (val.second == "float") {
|
||||
floatVarAddr = reinterpret_cast<float*>(val.first);
|
||||
float newValue = *floatVarAddr;
|
||||
if (ImGui::InputFloat(key.c_str(), &newValue)) {
|
||||
*floatVarAddr = newValue;
|
||||
*(floatVarAddr + 1) = newValue;
|
||||
static void renderPlayerVariable(const std::unique_ptr<EGSDK::GamePH::PlayerVariable>& playerVar) {
|
||||
switch (playerVar->GetType()) {
|
||||
case EGSDK::GamePH::PlayerVarType::String:
|
||||
// TO IMPLEMENT
|
||||
break;
|
||||
case EGSDK::GamePH::PlayerVarType::Float: {
|
||||
EGSDK::GamePH::FloatPlayerVariable* floatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(playerVar.get());
|
||||
float newValue = floatPlayerVar->value;
|
||||
if (ImGui::InputFloat(floatPlayerVar->GetName(), &newValue)) {
|
||||
floatPlayerVar->value = newValue;
|
||||
floatPlayerVar->defaultValue = newValue;
|
||||
}
|
||||
} else if (val.second == "bool") {
|
||||
boolVarAddr = reinterpret_cast<bool*>(val.first);
|
||||
bool newValue = *boolVarAddr;
|
||||
if (ImGui::Checkbox(key.c_str(), &newValue)) {
|
||||
*boolVarAddr = newValue;
|
||||
*(boolVarAddr + 1) = newValue;
|
||||
break;
|
||||
}
|
||||
case EGSDK::GamePH::PlayerVarType::Bool: {
|
||||
EGSDK::GamePH::BoolPlayerVariable* boolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(playerVar.get());
|
||||
bool newValue = boolPlayerVar->value;
|
||||
if (ImGui::Checkbox(boolPlayerVar->GetName(), &newValue)) {
|
||||
boolPlayerVar->value = newValue;
|
||||
boolPlayerVar->defaultValue = newValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
static std::string restoreBtnName{};
|
||||
restoreBtnName = "Restore##" + key;
|
||||
restoreBtnName = "Restore##" + std::string(playerVar->GetName());
|
||||
if (ImGui::Button(restoreBtnName.c_str(), "Restores player variable to default"))
|
||||
RestoreVariableToDefault(key);
|
||||
RestoreVariableToDefault(playerVar->GetName());
|
||||
|
||||
if (debugEnabled)
|
||||
renderDebugInfo(key, val);
|
||||
renderDebugInfo(playerVar);
|
||||
}
|
||||
static void HandlePlayerVariablesList() {
|
||||
if (!playerVariables.GetValue())
|
||||
@ -411,11 +475,11 @@ namespace EGT::Menu {
|
||||
ImGui::Separator();
|
||||
ImGui::InputTextWithHint("##VarsSearch", "Search variables", playerVarsSearchFilter, 64);
|
||||
|
||||
for (auto const& [key, val] : EGSDK::GamePH::PlayerVariables::playerVars) {
|
||||
if (!val.first || !shouldDisplayVariable(key, playerVarsSearchFilter))
|
||||
for (auto const& playerVar : EGSDK::GamePH::PlayerVariables::playerVars) {
|
||||
if (!shouldDisplayVariable(playerVar, playerVarsSearchFilter))
|
||||
continue;
|
||||
|
||||
renderPlayerVariable(key, val);
|
||||
renderPlayerVariable(playerVar);
|
||||
}
|
||||
|
||||
ImGui::Unindent();
|
||||
|
@ -107,7 +107,7 @@ namespace EGT::Menu {
|
||||
static bool haveResetAntizinDrainBlocked = true;
|
||||
if (ImGui::SliderFloat("Time", &time, 0.01f, 24.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp)) {
|
||||
if (haveResetAntizinDrainBlocked)
|
||||
previousAntizinDrainBlocked = EGSDK::GamePH::PlayerVariables::GetPlayerVar<bool>("AntizinDrainBlocked");
|
||||
previousAntizinDrainBlocked = EGSDK::GamePH::PlayerVariables::GetPlayerVarValue<bool>("AntizinDrainBlocked");
|
||||
EGSDK::GamePH::PlayerVariables::ChangePlayerVar("AntizinDrainBlocked", true);
|
||||
haveResetAntizinDrainBlocked = false;
|
||||
|
||||
|
Reference in New Issue
Block a user