backup with working Player Variables

This commit is contained in:
EricPlayZ
2025-01-07 04:42:06 +02:00
parent 35bf50de2e
commit c64cf6fc93
3 changed files with 318 additions and 102 deletions

View File

@ -4,6 +4,7 @@
#include <vector>
#include <memory>
#include <algorithm>
#include <mutex>
#include <EGSDK\ClassHelpers.h>
#include <EGSDK\Utils\Values.h>
@ -34,7 +35,7 @@ namespace EGSDK::GamePH {
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);
explicit StringPlayerVariable(const std::string& name);
};
class EGameSDK_API FloatPlayerVariable : public PlayerVariable {
public:
@ -42,7 +43,7 @@ namespace EGSDK::GamePH {
EGSDK::ClassHelpers::buffer<0x8, float> value;
EGSDK::ClassHelpers::buffer<0xC, float> defaultValue;
};
FloatPlayerVariable(const std::string& name);
explicit FloatPlayerVariable(const std::string& name);
void SetValues(float value);
};
@ -52,7 +53,7 @@ namespace EGSDK::GamePH {
EGSDK::ClassHelpers::buffer<0x8, bool> value;
EGSDK::ClassHelpers::buffer<0x9, bool> defaultValue;
};
BoolPlayerVariable(const std::string& name);
explicit BoolPlayerVariable(const std::string& name);
void SetValues(bool value);
};
@ -60,50 +61,24 @@ namespace EGSDK::GamePH {
class EGameSDK_API PlayerVarVector {
public:
PlayerVarVector() = default;
PlayerVarVector(const PlayerVarVector&) = delete; // Prevent copying
PlayerVarVector& operator=(const PlayerVarVector&) = delete; // Prevent assignment
PlayerVarVector(const PlayerVarVector&) = delete;
PlayerVarVector& operator=(const PlayerVarVector&) = delete;
PlayerVarVector(PlayerVarVector&&) = default; // Allow moving
PlayerVarVector& operator=(PlayerVarVector&&) = default; // Allow move assignment
PlayerVarVector(PlayerVarVector&&) noexcept = default;
PlayerVarVector& operator=(PlayerVarVector&&) noexcept = default;
std::unique_ptr<PlayerVariable>& emplace_back(std::unique_ptr<PlayerVariable> playerVar) {
_playerVars.emplace_back(std::move(playerVar));
return _playerVars.back();
}
auto begin() {
return _playerVars.begin();
}
auto end() {
return _playerVars.end();
}
bool none_of(const std::string& name) {
return std::none_of(_playerVars.begin(), _playerVars.end(), [&name](const auto& playerVar) {
return playerVar->GetName() == name;
});
}
auto FindIter(const std::string& name) {
auto playerVarIt = std::find_if(_playerVars.begin(), _playerVars.end(), [&name](const auto& playerVar) {
return playerVar->GetName() == name;
});
return playerVarIt;
}
std::unique_ptr<PlayerVariable>* FindPtr(const std::string& name) {
auto playerVarIt = FindIter(name);
return playerVarIt == _playerVars.end() ? nullptr : &*playerVarIt;
}
PlayerVariable* Find(const std::string& name) {
auto playerVarPtr = FindPtr(name);
return playerVarPtr == nullptr ? nullptr : playerVarPtr->get();
}
auto Erase(const std::string& name) {
auto playerVarIt = FindIter(name);
if (playerVarIt != _playerVars.end())
return _playerVars.erase(playerVarIt);
return _playerVars.end();
}
std::unique_ptr<PlayerVariable>& emplace_back(std::unique_ptr<PlayerVariable> playerVar);
auto begin();
auto end();
bool none_of(const std::string& name);
auto FindIter(const std::string& name);
std::unique_ptr<PlayerVariable>* FindPtr(const std::string& name);
PlayerVariable* Find(const std::string& name);
auto Erase(const std::string& name);
private:
std::vector<std::unique_ptr<PlayerVariable>> _playerVars{};
mutable std::mutex _mutex;
};
class EGameSDK_API PlayerVariables {
@ -340,7 +315,7 @@ namespace EGSDK::GamePH {
if (!gotPlayerVars)
return false;
return prevBoolValueMap.find(name) != prevBoolValueMap.end() && !prevBoolValueMap[name];
return prevBoolValueMap.find(name) != prevBoolValueMap.end() && prevBoolValueMap[name];
}
static PlayerVariables* Get();

View File

@ -56,6 +56,51 @@ namespace EGSDK::GamePH {
this->defaultValue = value;
}
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();
}
PlayerVarVector PlayerVariables::playerVars{};
PlayerVarVector PlayerVariables::customPlayerVars{};
PlayerVarVector PlayerVariables::defaultPlayerVars{};
@ -314,6 +359,226 @@ namespace EGSDK::GamePH {
}
#pragma endregion
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];
}
static PlayerVariables* GetOffset_PlayerVariables() {
PlayerState* playerState = PlayerState::Get();
return playerState ? playerState->playerVariables : nullptr;

View File

@ -139,41 +139,6 @@ namespace EGT::Menu {
break;
}
}
/*auto customPlayerVarBeginIt = EGSDK::GamePH::PlayerVariables::customPlayerVars.begin();
for (auto& customPlayerVarIt = customPlayerVarBeginIt; customPlayerVarIt != EGSDK::GamePH::PlayerVariables::customPlayerVars.end(); ++customPlayerVarIt) {
auto customPlayerVar = customPlayerVarIt->get();
try {
auto defPlayerVar = &EGSDK::GamePH::PlayerVariables::defaultPlayerVars.at(playerVarIt - playerVarBeginIt);
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);
SPDLOG_ERROR("PlayerVarsUpdate() threw an exception! Restart the game to fix this error. If the error still happens, please open a bug report.");
}
}*/
}
static void PlayerHealthUpdate() {
EGSDK::GamePH::PlayerHealthModule* playerHealthModule = EGSDK::GamePH::PlayerHealthModule::Get();
@ -397,8 +362,14 @@ namespace EGT::Menu {
break;
}
if (!restoreVarsToSavedVarsEnabled)
if (!restoreVarsToSavedVarsEnabled) {
defVars.Erase(name);
auto customPlayerVar = EGSDK::GamePH::PlayerVariables::customPlayerVars.Find(name);
if (!customPlayerVar)
return;
EGSDK::GamePH::PlayerVariables::customPlayerVars.Erase(name);
}
}
static bool shouldDisplayVariable(const std::unique_ptr<EGSDK::GamePH::PlayerVariable>& playerVarPtr, const std::string& searchFilter) {
@ -440,32 +411,37 @@ namespace EGT::Menu {
ImGui::PopStyleColor();
}
static void renderPlayerVariable(const std::unique_ptr<EGSDK::GamePH::PlayerVariable>& playerVarPtr) {
switch (playerVarPtr->GetType()) {
case EGSDK::GamePH::PlayerVarType::String:
// TO IMPLEMENT
break;
case EGSDK::GamePH::PlayerVarType::Float: {
EGSDK::GamePH::FloatPlayerVariable* floatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(playerVarPtr.get());
float newValue = floatPlayerVar->value;
if (ImGui::InputFloat(floatPlayerVar->GetName(), &newValue))
EGSDK::GamePH::PlayerVariables::ChangePlayerVarFromList(floatPlayerVar->GetName(), newValue, playerVarPtr.get());
break;
}
case EGSDK::GamePH::PlayerVarType::Bool: {
EGSDK::GamePH::BoolPlayerVariable* boolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(playerVarPtr.get());
bool newValue = boolPlayerVar->value;
if (ImGui::Checkbox(boolPlayerVar->GetName(), &newValue))
EGSDK::GamePH::PlayerVariables::ChangePlayerVarFromList(boolPlayerVar->GetName(), newValue, playerVarPtr.get());
break;
}
default:
break;
ImGui::BeginDisabled(EGSDK::GamePH::PlayerVariables::IsPlayerVarManagedByBool(playerVarPtr->GetName()));
{
switch (playerVarPtr->GetType()) {
case EGSDK::GamePH::PlayerVarType::String:
// TO IMPLEMENT
break;
case EGSDK::GamePH::PlayerVarType::Float: {
EGSDK::GamePH::FloatPlayerVariable* floatPlayerVar = reinterpret_cast<EGSDK::GamePH::FloatPlayerVariable*>(playerVarPtr.get());
float newValue = floatPlayerVar->value;
if (ImGui::InputFloat(floatPlayerVar->GetName(), &newValue))
EGSDK::GamePH::PlayerVariables::ChangePlayerVarFromList(floatPlayerVar->GetName(), newValue, playerVarPtr.get());
break;
}
case EGSDK::GamePH::PlayerVarType::Bool: {
EGSDK::GamePH::BoolPlayerVariable* boolPlayerVar = reinterpret_cast<EGSDK::GamePH::BoolPlayerVariable*>(playerVarPtr.get());
bool newValue = boolPlayerVar->value;
if (ImGui::Checkbox(boolPlayerVar->GetName(), &newValue))
EGSDK::GamePH::PlayerVariables::ChangePlayerVarFromList(boolPlayerVar->GetName(), newValue, playerVarPtr.get());
break;
}
default:
break;
}
ImGui::EndDisabled();
}
ImGui::SameLine();
static std::string restoreBtnName{};
restoreBtnName = "Restore##" + std::string(playerVarPtr->GetName());
ImGui::BeginDisabled(EGSDK::GamePH::PlayerVariables::customPlayerVars.none_of(playerVarPtr->GetName()));
ImGui::BeginDisabled(EGSDK::GamePH::PlayerVariables::customPlayerVars.none_of(playerVarPtr->GetName()) || EGSDK::GamePH::PlayerVariables::IsPlayerVarManagedByBool(playerVarPtr->GetName()));
{
if (ImGui::Button(restoreBtnName.c_str(), "Restores player variable to default"))
RestoreVariableToDefault(playerVarPtr->GetName());
@ -614,11 +590,11 @@ namespace EGT::Menu {
Tab Tab::instance{};
void Tab::Update() {
PlayerPositionUpdate();
PlayerVarsUpdate();
PlayerHealthUpdate();
PlayerImmunityUpdate();
UpdateDisabledOptions();
UpdatePlayerVars();
PlayerVarsUpdate();
HandleToggles();
}
void Tab::Render() {