backup of new VarManagerBase for variable managing such as PlayerVariables or CVars

This commit is contained in:
EricPlayZ
2025-02-10 04:02:37 +02:00
parent ae711dca84
commit f3ece5c0e5
35 changed files with 783 additions and 385 deletions

View File

@ -30,9 +30,10 @@
<ClCompile Include="src\Engine\IBaseCamera.cpp" />
<ClCompile Include="src\Engine\IControlObject.cpp" />
<ClCompile Include="src\Engine\IPhysicsCharacter.cpp" />
<ClCompile Include="src\Engine\RendererCVars.cpp" />
<ClCompile Include="src\Engine\CVars.cpp" />
<ClCompile Include="src\Engine\CVideoSettings.cpp" />
<ClCompile Include="src\Engine\Engine_Misc.cpp" />
<ClCompile Include="src\Engine\VarBase.cpp" />
<ClCompile Include="src\GamePH\CoPlayerRestrictions.cpp" />
<ClCompile Include="src\GamePH\DayNightCycle.cpp" />
<ClCompile Include="src\GamePH\FreeCamera.cpp" />
@ -65,6 +66,8 @@
<ClCompile Include="src\Vec3.cpp" />
<ClCompile Include="src\Vec4.cpp" />
<ClCompile Include="SteamAPI.cpp" />
<ClCompile Include="VarManagerBase.cpp" />
<ClCompile Include="VarMapBase.cpp" />
<ClCompile Include="WinMemory.cpp" />
</ItemGroup>
<ItemGroup>
@ -86,9 +89,12 @@
<ClInclude Include="include\EGSDK\Engine\IControlObject.h" />
<ClInclude Include="include\EGSDK\Engine\IGSObject.h" />
<ClInclude Include="include\EGSDK\Engine\IPhysicsCharacter.h" />
<ClInclude Include="include\EGSDK\Engine\RendererCVars.h" />
<ClInclude Include="include\EGSDK\Engine\CVars.h" />
<ClInclude Include="include\EGSDK\Engine\CVideoSettings.h" />
<ClInclude Include="include\EGSDK\Engine\Engine_Misc.h" />
<ClInclude Include="include\EGSDK\Engine\VarBase.h" />
<ClInclude Include="include\EGSDK\Engine\VarManagerBase.h" />
<ClInclude Include="include\EGSDK\Engine\VarMapBase.h" />
<ClInclude Include="include\EGSDK\Exports.h" />
<ClInclude Include="include\EGSDK\GamePH\CameraFPPDI.h" />
<ClInclude Include="include\EGSDK\GamePH\CoBaseCameraProxy.h" />
@ -170,6 +176,7 @@
<GenerateManifest>true</GenerateManifest>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetName>EGameSDK</TargetName>
@ -210,7 +217,7 @@
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>DebugFastLink</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>DbgHelp.lib;Version.lib;libMinHook-x64-v141-mdd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OptimizeReferences>
@ -246,7 +253,7 @@
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalLibraryDirectories>deps\MinHook\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>DbgHelp.lib;Version.lib;libMinHook-x64-v141-mdd.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>

View File

@ -142,7 +142,7 @@
<ClCompile Include="Offsets.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\Engine\RendererCVars.cpp">
<ClCompile Include="src\Engine\CVars.cpp">
<Filter>src\Engine</Filter>
</ClCompile>
<ClCompile Include="WinMemory.cpp">
@ -166,6 +166,15 @@
<ClCompile Include="src\Vec2.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="VarMapBase.cpp">
<Filter>src\Engine</Filter>
</ClCompile>
<ClCompile Include="VarManagerBase.cpp">
<Filter>src\Engine</Filter>
</ClCompile>
<ClCompile Include="src\Engine\VarBase.cpp">
<Filter>src\Engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="include">
@ -365,7 +374,7 @@
<ClInclude Include="include\EGSDK\Core\SteamAPI.h">
<Filter>include\Core</Filter>
</ClInclude>
<ClInclude Include="include\EGSDK\Engine\RendererCVars.h">
<ClInclude Include="include\EGSDK\Engine\CVars.h">
<Filter>include\Engine</Filter>
</ClInclude>
<ClInclude Include="include\EGSDK\Utils\WinMemory.h">
@ -401,5 +410,14 @@
<ClInclude Include="include\EGSDK\Vec2.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="include\EGSDK\Engine\VarMapBase.h">
<Filter>include\Engine</Filter>
</ClInclude>
<ClInclude Include="include\EGSDK\Engine\VarManagerBase.h">
<Filter>include\Engine</Filter>
</ClInclude>
<ClInclude Include="include\EGSDK\Engine\VarBase.h">
<Filter>include\Engine</Filter>
</ClInclude>
</ItemGroup>
</Project>

104
EGameSDK/VarManagerBase.cpp Normal file
View File

@ -0,0 +1,104 @@
#include <EGSDK\Vec4.h>
#include <EGSDK\Engine\VarManagerBase.h>
#include <EGSDK\Engine\VarMapBase.h>
#include <EGSDK\Engine\CVars.h>
namespace EGSDK::Engine {
#define StaticAssertValueType static_assert(std::is_same_v<T, std::string> || std::is_same_v<T, float> || std::is_same_v<T, int> || std::is_same_v<T, Vec3> || std::is_same_v<T, Vec4> || std::is_same_v<T, bool>, "Invalid type: value must be string, float, int, Vec3, Vec4 or bool")
template <typename VarMapType, typename VarType>
VarMapType VarManagerBase<VarMapType, VarType>::vars;
template <typename VarMapType, typename VarType>
VarMapType VarManagerBase<VarMapType, VarType>::customVars;
template <typename VarMapType, typename VarType>
VarMapType VarManagerBase<VarMapType, VarType>::defaultVars;
template <typename VarMapType, typename VarType>
template <typename T>
T* VarManagerBase<VarMapType, VarType>::GetVarValue(const std::string& name) {
StaticAssertValueType;
auto var = vars.Find(name);
return var ? std::get_if<T>(&var->GetValue()) : nullptr;
}
template <typename VarMapType, typename VarType>
template <typename T>
T* VarManagerBase<VarMapType, VarType>::GetVarValue(VarType* var) {
StaticAssertValueType;
return var ? std::get_if<T>(&var->GetValue()) : nullptr;
}
template <typename VarMapType, typename VarType>
template <typename T>
T* VarManagerBase<VarMapType, VarType>::GetVarValueFromMap(const std::string& name, const VarMapType& map) {
StaticAssertValueType;
auto var = map.Find(name);
return var ? std::get_if<T>(&var->GetValue()) : nullptr;
}
template <typename VarMapType, typename VarType>
template <typename T>
void VarManagerBase<VarMapType, VarType>::ChangeVar(const std::string& name, T value) {
StaticAssertValueType;
auto var = vars.Find(name);
if (var)
var->SetValue(value);
}
template <typename VarMapType, typename VarType>
template <typename T>
void VarManagerBase<VarMapType, VarType>::ChangeVar(VarType* var, T value) {
StaticAssertValueType;
if (var)
var->SetValue(value);
}
template <typename VarMapType, typename VarType>
template <typename T>
void VarManagerBase<VarMapType, VarType>::ChangeVarFromList(const std::string& name, T value) {
StaticAssertValueType;
auto var = vars.Find(name);
if (!var)
return;
ChangeVarFromList<T>(var, value);
}
template <typename VarMapType, typename VarType>
template <typename T>
void VarManagerBase<VarMapType, VarType>::ChangeVarFromList(VarType* var, T value) {
StaticAssertValueType;
if (!var)
return;
auto customVar = customVars.Find(var->GetName());
auto defVar = defaultVars.Find(var->GetName());
if (!customVar)
customVar = customVars.try_emplace(std::make_unique<VarType>(var->GetName(), var->GetType())).get();
if (!defVar) {
defVar = defaultVars.try_emplace(std::make_unique<VarType>(var->GetName(), var->GetType())).get();
if (auto varValue = GetVarValue<T>(var); defVar && varValue)
defVar->SetValue(*varValue);
}
if (customVar)
customVar->SetValue(value);
var->SetValue(value);
}
template EGameSDK_API class VarManagerBase<CVarMap, CVar>;
template EGameSDK_API float* VarManagerBase<CVarMap, CVar>::GetVarValue<float>(const std::string&);
template EGameSDK_API float* VarManagerBase<CVarMap, CVar>::GetVarValue<float>(CVar*);
template EGameSDK_API int* VarManagerBase<CVarMap, CVar>::GetVarValue<int>(const std::string&);
template EGameSDK_API int* VarManagerBase<CVarMap, CVar>::GetVarValue<int>(CVar*);
template EGameSDK_API float* VarManagerBase<CVarMap, CVar>::GetVarValueFromMap<float>(const std::string&, const CVarMap& map);
template EGameSDK_API int* VarManagerBase<CVarMap, CVar>::GetVarValueFromMap<int>(const std::string&, const CVarMap& map);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVar<float>(const std::string&, float);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVar<float>(CVar*, float);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVar<int>(const std::string&, int);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVar<int>(CVar*, int);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVarFromList<float>(const std::string&, float);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVarFromList<float>(CVar*, float);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVarFromList<int>(const std::string&, int);
template EGameSDK_API void VarManagerBase<CVarMap, CVar>::ChangeVarFromList<int>(CVar*, int);
}

57
EGameSDK/VarMapBase.cpp Normal file
View File

@ -0,0 +1,57 @@
#include <EGSDK\Engine\VarMapBase.h>
#include <EGSDK\Engine\CVars.h>
namespace EGSDK::Engine {
template <typename VarType>
std::unique_ptr<VarType>& VarMapBase<VarType>::try_emplace(std::unique_ptr<VarType> var) {
std::lock_guard<decltype(mutex)> lock(mutex);
const std::string& name = var->GetName();
auto [it, inserted] = vars.try_emplace(name, std::move(var));
if (inserted)
varsOrdered.emplace_back(name);
return it->second;
}
template <typename VarType>
bool VarMapBase<VarType>::empty() const {
std::lock_guard<decltype(mutex)> lock(mutex);
return vars.empty();
}
template <typename VarType>
bool VarMapBase<VarType>::none_of(const std::string& name) const {
std::lock_guard<decltype(mutex)> lock(mutex);
return vars.find(name) == vars.end();
}
template <typename VarType>
void VarMapBase<VarType>::reserve(size_t count) {
std::lock_guard<decltype(mutex)> lock(mutex);
vars.reserve(count);
}
template <typename VarType>
size_t VarMapBase<VarType>::size() {
std::lock_guard<decltype(mutex)> lock(mutex);
return vars.size();
}
template <typename VarType>
VarType* VarMapBase<VarType>::Find(const std::string& name) const {
std::lock_guard<decltype(mutex)> lock(mutex);
auto it = vars.find(name);
return (it != vars.end()) ? it->second.get() : nullptr;
}
template <typename VarType>
void VarMapBase<VarType>::Erase(const std::string& name) {
std::lock_guard<decltype(mutex)> lock(mutex);
auto it = vars.find(name);
if (it == vars.end())
return;
auto orderIt = std::find(varsOrdered.begin(), varsOrdered.end(), name);
if (orderIt != varsOrdered.end())
varsOrdered.erase(orderIt);
vars.erase(it);
}
template EGameSDK_API class VarMapBase<CVar>;
}

View File

@ -13,7 +13,6 @@
#endif
namespace EGSDK {
static constexpr uint32_t GAME_VER_COMPAT = 12001;
static constexpr std::array<uint32_t, 2> SUPPORTED_GAME_VERSIONS = { 11200, 12001 };
namespace Core {
@ -31,6 +30,8 @@ namespace EGSDK {
#endif
extern EGameSDK_API std::string GetSDKStoragePath();
extern EGameSDK_API std::string GetSupportedGameVersionsStr();
extern EGameSDK_API bool IsGameVerCompatible();
#ifdef EGameSDK_EXPORTS
extern void OnPostUpdate();

View File

@ -0,0 +1,54 @@
#pragma once
#include <EGSDK\ClassHelpers.h>
#include <EGSDK\Engine\VarBase.h>
#include <EGSDK\Engine\VarMapBase.h>
#include <EGSDK\Engine\VarManagerBase.h>
namespace EGSDK::Engine {
class EGameSDK_API CVar : public VarBase {
public:
union {
ClassHelpers::StaticBuffer<0x50, uint32_t> valueOffset;
};
explicit CVar(const std::string& name);
explicit CVar(const std::string& name, VarType type);
VarValueType& GetValue();
void SetValue(const VarValueType& value);
void AddValuePtr(uint64_t* ptr);
private:
struct VarValue {
VarValueType value;
std::vector<uint64_t*> valuePtrs;
};
static std::unordered_map<const CVar*, VarValue> varValues;
};
class EGameSDK_API FloatCVar : public CVar {
public:
explicit FloatCVar(const std::string& name);
};
class EGameSDK_API IntCVar : public CVar {
public:
explicit IntCVar(const std::string& name);
};
class EGameSDK_API CVarMap : public VarMapBase<CVar> {
public:
using VarMapBase<CVar>::Find;
using VarMapBase<CVar>::none_of;
bool none_of(uint32_t valueOffset);
CVar* Find(uint32_t valueOffset) const;
std::unique_ptr<CVar>& try_emplace(std::unique_ptr<CVar> var) override;
void Erase(const std::string& name) override;
private:
std::unordered_map<uint32_t, CVar*> varsByValueOffset;
};
class EGameSDK_API CVars : public VarManagerBase<CVarMap, CVar> {};
}

View File

@ -1,89 +0,0 @@
#pragma once
#include <any>
#include <unordered_map>
#include <vector>
#include <mutex>
#include <atomic>
#include <functional>
#include <EGSDK\ClassHelpers.h>
#include <EGSDK\Utils\Values.h>
namespace EGSDK::Engine {
enum EGameSDK_API RendererCVarType {
NONE = 0,
Float
};
class EGameSDK_API RendererCVar {
public:
RendererCVar(const std::string& name);
RendererCVar(const std::string& name, DWORD64 address);
const char* GetName();
void SetName(const std::string& name);
RendererCVarType GetType();
void SetType(RendererCVarType type);
DWORD64 GetAddress();
void SetAddress(DWORD64 address);
private:
std::string name{};
RendererCVarType type = RendererCVarType::NONE;
DWORD64 address = 0;
};
class EGameSDK_API FloatRendererCVar : public RendererCVar {
public:
explicit FloatRendererCVar(const std::string& name);
explicit FloatRendererCVar(const std::string& name, DWORD64 address);
float GetValue();
void SetValue(float value);
private:
float value = -404.0f;
};
class EGameSDK_API RendererCVarMap {
public:
RendererCVarMap() = default;
RendererCVarMap(const RendererCVarMap&) = delete;
RendererCVarMap& operator=(const RendererCVarMap&) = delete;
RendererCVarMap(RendererCVarMap&&) noexcept = default;
RendererCVarMap& operator=(RendererCVarMap&&) noexcept = default;
std::unique_ptr<RendererCVar>& try_emplace(std::unique_ptr<RendererCVar> rendererCVar);
bool empty();
bool none_of(const std::string& name);
bool none_of(DWORD64 address);
std::unique_ptr<RendererCVar>* FindPtr(const std::string& name);
RendererCVar* Find(const std::string& name);
RendererCVar* Find(DWORD64 address);
bool Erase(const std::string& name);
template <typename Callable, typename... Args>
void ForEach(Callable&& func, Args&&... args) {
std::lock_guard<std::mutex> lock(mutex);
for (const auto& name : _order)
func(_rendererCVars.at(name), std::forward<Args>(args)...);
}
private:
std::unordered_map<std::string, std::unique_ptr<RendererCVar>> _rendererCVars{};
std::unordered_map<DWORD64, RendererCVar*> _rendererCVarsByAddress{};
std::vector<std::string> _order{};
mutable std::mutex mutex{};
};
class EGameSDK_API RendererCVars {
public:
static RendererCVarMap rendererCVars;
static RendererCVarMap customRendererCVars;
static RendererCVarMap defaultRendererCVars;
static float GetRendererCVarValue(const std::string& name);
static void ChangeRendererCVar(const std::string& name, float value, RendererCVar* rendererCVar = nullptr);
static void ChangeRendererCVarFromList(const std::string& name, float value, RendererCVar* rendererCVar = nullptr);
};
}

View File

@ -0,0 +1,40 @@
#pragma once
#include <unordered_map>
#include <string>
#include <mutex>
#include <variant>
#include <EGSDK\Exports.h>
#include <EGSDK\Vec3.h>
#include <EGSDK\Vec4.h>
namespace EGSDK::Engine {
EGameSDK_API enum class VarType {
NONE = 0,
String,
Float,
Int,
Vec3,
Vec4,
Bool
};
using VarValueType = std::variant<std::string, float, int, Vec3, Vec4, bool>;
class EGameSDK_API VarBase {
public:
VarBase(const std::string& name);
VarBase(const std::string& name, VarType type);
~VarBase();
const char* GetName() const;
void SetName(const std::string& name);
VarType GetType() const;
void SetType(VarType type);
protected:
static std::recursive_mutex mutex;
private:
static std::unordered_map<const VarBase*, std::string> varNames;
static std::unordered_map<const VarBase*, VarType> varTypes;
};
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <string>
#include <EGSDK\Exports.h>
namespace EGSDK::Engine {
template <typename VarMapType, typename VarType>
class EGameSDK_API VarManagerBase {
public:
static VarMapType vars;
static VarMapType customVars;
static VarMapType defaultVars;
template <typename T>
static T* GetVarValue(const std::string& name);
template <typename T>
static T* GetVarValue(VarType* var);
template <typename T>
static T* GetVarValueFromMap(const std::string& name, const VarMapType& map);
template <typename T>
static void ChangeVar(const std::string& name, T value);
template <typename T>
static void ChangeVar(VarType* var, T value);
template <typename T>
static void ChangeVarFromList(const std::string& name, T value);
template <typename T>
static void ChangeVarFromList(VarType* var, T value);
};
}

View File

@ -0,0 +1,43 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <memory>
#include <mutex>
#include <functional>
#include <string>
#include <EGSDK\Exports.h>
namespace EGSDK::Engine {
template <typename VarType>
class EGameSDK_API VarMapBase {
public:
VarMapBase() = default;
VarMapBase(const VarMapBase&) = delete;
VarMapBase& operator=(const VarMapBase&) = delete;
VarMapBase(VarMapBase&&) noexcept = default;
VarMapBase& operator=(VarMapBase&&) noexcept = default;
virtual ~VarMapBase() = default;
virtual std::unique_ptr<VarType>& try_emplace(std::unique_ptr<VarType> var);
bool empty() const;
bool none_of(const std::string& name) const;
void reserve(size_t count);
size_t size();
VarType* Find(const std::string& name) const;
virtual void Erase(const std::string& name);
template <typename Callable, typename... Args>
void ForEach(Callable&& func, Args&&... args) {
std::lock_guard<decltype(mutex)> lock(mutex);
for (const auto& name : varsOrdered)
func(vars.at(name), std::forward<Args>(args)...);
}
protected:
std::unordered_map<std::string, std::unique_ptr<VarType>> vars{};
std::vector<std::string> varsOrdered{};
mutable std::recursive_mutex mutex{};
};
}

View File

@ -102,7 +102,11 @@ namespace EGSDK {
AddDynamicPattern(DisablePlayerRestrictionsSubFunc, "gamedll_ph_x64_rwdi.dll", void*)
AddDynamicPattern(HandlePlayerRestrictions, "gamedll_ph_x64_rwdi.dll", void*) // sub func of m_EnableRestrictions sub funcs and m_DisableRestrictions sub funcs
AddPattern(SetIsInCoSafeZone, "gamedll_ph_x64_rwdi.dll", "E8 [?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 74 ?? E8 ?? ?? ?? ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B 5C 24 ?? 48 83 C4", Utils::SigScan::PatternType::RelativePointer, void*)
AddPattern(UpdateCVarFloat, "engine_x64_rwdi.dll", "40 53 48 83 EC ?? 8B 51 ?? 49 8B D8 48 8B 4C 24 ?? 41 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 48 8D 0D ?? ?? ?? ?? 48 0F 45 C8 8B 01 89 03 48 83 C4 ?? 5B C3 CC CC CC CC CC CC CC CC CC CC CC CC 40 53 48 83 EC ?? 8B 51 ?? 49 8B D8 48 8B 4C 24 ?? 41 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 48 8D 0D ?? ?? ?? ?? 48 0F 45 C8 F2 0F 10 01", Utils::SigScan::PatternType::Address, void*)
AddPattern(LoadScriptedVarInt, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 55 57 41 54 41 56 41 57 48 83 EC ?? 45 0F B6 11 45 33 E4 4D 8B F1 4D 8B F8 48 8B FA 48 8B E9 49 8B D9 45 8B DC 45 84 D2 74 ?? 90 45 0F B6 C2 48 8D 5B ?? 41 80 EA ?? 41 80 FA ?? 44 0F B6 13 41 8D 40 ?? 0F B6 C8 41 0F 47 C8 45 6B DB ?? 0F BE C9 44 03 D9 45 84 D2 75 ?? 0F B6 47 ?? 41 8B D4 84 C0 75 ?? 44 8B 47 ?? EB ?? FE C8 44 0F B6 C0 41 83 E8 ?? 48 89 B4 24 ?? ?? ?? ?? 78 ?? 4C 8B 17 48 B8 ?? ?? ?? ?? ?? ?? ?? ?? 4C 23 D0 41 8D 0C 10 D1 F9 48 63 C1 49 8D 34 C2 49 8B 04 C2 44 39 58 ?? 74 ?? 8D 41 ?? 41 0F 42 C0 44 8B C0 8D 41 ?? 0F 42 D0 41 3B D0 7E ?? B9 ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 8B F8 48 85 C0 0F 84 ?? ?? ?? ?? 4C 89 60 ?? 4C 89 60 ?? 4C 89 60 ?? 66 44 89 60 ?? 44 88 60 ?? 48 8D 05 ?? ?? ?? ?? 48 89 07 48 8D 05 ?? ?? ?? ?? 48 89 47 ?? E9 ?? ?? ?? ?? 48 85 F6 74 ?? F6 40 ?? ?? 0F 85 ?? ?? ?? ?? B9 ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 8B F8 85 C0 0F 84 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 BE ?? ?? ?? ?? ?? ?? ?? ?? 48 8D 1D ?? ?? ?? ?? B9 ?? ?? ?? ?? 48 8B 10", Utils::SigScan::PatternType::Address, void*)
AddPattern(GetCVarT, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC ?? 44 0F B6 12 33 F6 41 8B E9", Utils::SigScan::PatternType::Address, void*)
AddPattern(GetCVarValue, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 8B D9 41 8B F0 8B FA", Utils::SigScan::PatternType::Address, void*)
AddPattern(UpdateFrameScript, "engine_x64_rwdi.dll", "48 81 C1 ?? ?? ?? ?? 4C 8D 05 ?? ?? ?? ?? E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC CC CC 48 81 C1 ?? ?? ?? ?? 4C 8D 05 ?? ?? ?? ?? E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC CC CC 48 81 C1", Utils::SigScan::PatternType::Address, void*)
AddPattern(GetListOfCVarValues, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 8B F9 48 8B 08 8B 49 ?? FF 15 ?? ?? ?? ?? 48 8B CF 48 8B F0 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 8B 09 48 8B 1A FF 15 ?? ?? ?? ?? FF C8 48 8B 54 C3 ?? 80 BA ?? ?? ?? ?? ?? 75 ?? 83 FE ?? 75 ?? 48 8D 47 ?? 48 8B 5C 24 ?? 48 8B 74 24 ?? 48 83 C4 ?? 5F C3 48 8B 5C 24 ?? 48 8D 4F ?? 85 F6 48 8D 47 ?? 48 8B 74 24 ?? 48 0F 44 C1 48 83 C4 ?? 5F C3 0F 57 C0", Utils::SigScan::PatternType::Address, void*)
AddPattern(HandleTimeWeatherInterpolationOnDemandTextureIsLoaded, "engine_x64_rwdi.dll", "40 84 ED 0F 84 ?? ?? ?? ?? 0F B6 4E", Utils::SigScan::PatternType::Address, void*)
private:
static void AddOffsets(DWORD gameVer, const std::unordered_map<std::string, DWORD>& offsets);

View File

@ -160,6 +160,9 @@ namespace EGSDK::Utils {
auto ExecuteOriginal(Args... args) {
return pOriginal(args...);
}
auto ExecuteDetour(Args... args) {
return pDetour(args...);
}
void RegisterCallback(CallbackType callback) {
callbacks.push_back(callback);
@ -225,6 +228,9 @@ namespace EGSDK::Utils {
auto ExecuteOriginal(Args... args) {
return pOriginal(args...);
}
auto ExecuteDetour(Args... args) {
return pDetour(args...);
}
void RegisterCallback(CallbackType callback) {
callbacks.push_back(callback);

View File

@ -10,6 +10,7 @@
#include <spdlog\sinks\rotating_file_sink.h>
#include <DbgHelp.h>
#include <thread>
#include <ranges>
namespace EGSDK::Core {
std::vector<spdlog::sink_ptr> spdlogSinks{};
@ -51,6 +52,19 @@ namespace EGSDK::Core {
}
return localAppDataDir += "\\EGameSDK";
}
std::string GetSupportedGameVersionsStr() {
std::ostringstream oss{};
for (const auto& version : SUPPORTED_GAME_VERSIONS) {
if (&version != &SUPPORTED_GAME_VERSIONS.front())
oss << ", ";
oss << "v" << EGSDK::GamePH::GameVerToStr(version);
}
return oss.str();
}
bool IsGameVerCompatible() {
return std::ranges::contains(SUPPORTED_GAME_VERSIONS, gameVer);
}
void OnPostUpdate() {
GamePH::PlayerVariables::GetPlayerVars();
@ -91,9 +105,9 @@ namespace EGSDK::Core {
#endif
static void GameVersionCheck() {
try {
SPDLOG_INFO("EGSDK supported game versions: {}", GetSupportedGameVersionsStr());
SPDLOG_DEBUG("Attempting to get current game version");
gameVer = GamePH::GetCurrentGameVersion();
SPDLOG_DEBUG("Got game version: {}", gameVer);
} catch (const std::exception& e) {
std::string errorMsg = "Failed to get game version, EXCEPTION: " + std::string(e.what()) + "\n\nThis shouldn't happen! Contact developer.";
SPDLOG_ERROR(errorMsg);
@ -103,11 +117,8 @@ namespace EGSDK::Core {
SPDLOG_INFO("Got game version: v{}", GamePH::GameVerToStr(gameVer));
SPDLOG_DEBUG("Comparing game version with compatible versions");
if (std::find(SUPPORTED_GAME_VERSIONS.begin(), SUPPORTED_GAME_VERSIONS.end(), Core::gameVer) == SUPPORTED_GAME_VERSIONS.end()) {
std::string warningMsg = "Unsupported game version v" + GamePH::GameVerToStr(gameVer) + ".\n\nPlease note that your game version has not been officially tested with this version of EGameSDK, therefore expect bugs, glitches or other mods to completely stop working.\n\nThe following game versions are officially supported: ";
for (const auto& version : SUPPORTED_GAME_VERSIONS)
warningMsg += "- v" + GamePH::GameVerToStr(version) + "\n";
if (!IsGameVerCompatible()) {
std::string warningMsg = "Unsupported game version v" + GamePH::GameVerToStr(gameVer) + ".\n\nPlease note that your game version has not been officially tested with this version of EGameSDK, therefore expect bugs, glitches or other mods to completely stop working.\n\nThe following game versions are officially supported: " + GetSupportedGameVersionsStr();
SPDLOG_WARN(warningMsg);
std::thread([warningMsg]() {
MessageBox(nullptr, warningMsg.c_str(), "EGameSDK unsupported game version", MB_ICONWARNING | MB_OK | MB_SETFOREGROUND);

View File

@ -0,0 +1,111 @@
#include <algorithm>
#include <EGSDK\Engine\CVars.h>
namespace EGSDK::Engine {
std::unordered_map<const CVar*, CVar::VarValue> CVar::varValues;
CVar::CVar(const std::string& name) : VarBase(name) {}
CVar::CVar(const std::string& name, VarType type) : VarBase(name, type) {}
VarValueType& CVar::GetValue() {
std::lock_guard<decltype(mutex)> lock(mutex);
auto it = varValues.find(this);
switch (GetType()) {
case VarType::Float:
if (it == varValues.end())
return varValues[this].value = 0.0f;
if (!it->second.valuePtrs.size())
return it->second.value;
if (!it->second.valuePtrs[0])
return it->second.value;
it->second.value = *reinterpret_cast<float*>(it->second.valuePtrs[0]);
return it->second.value;
case VarType::Int:
if (it == varValues.end())
return varValues[this].value = 0;
if (!it->second.valuePtrs.size())
return it->second.value;
if (!it->second.valuePtrs[0])
return it->second.value;
it->second.value = *reinterpret_cast<int*>(it->second.valuePtrs[0]);
return it->second.value;
default:
if (it == varValues.end())
return varValues[this].value = 0;
return it->second.value;
}
}
void CVar::SetValue(const VarValueType& value) {
std::lock_guard<decltype(mutex)> lock(mutex);
switch (GetType()) {
case VarType::Float:
{
if (auto floatVal = std::get_if<float>(&value)) {
for (const auto& ptr : varValues[this].valuePtrs) {
if (ptr)
*reinterpret_cast<float*>(ptr) = *floatVal;
}
varValues[this].value = *floatVal;
}
break;
}
case VarType::Int:
{
if (auto intVal = std::get_if<int>(&value)) {
for (const auto& ptr : varValues[this].valuePtrs) {
if (ptr)
*reinterpret_cast<int*>(ptr) = *intVal;
}
varValues[this].value = *intVal;
}
break;
}
}
}
void CVar::AddValuePtr(uint64_t* ptr) {
std::lock_guard<decltype(mutex)> lock(mutex);
varValues[this].valuePtrs.push_back(ptr);
}
FloatCVar::FloatCVar(const std::string& name) : CVar(name) {
SetType(VarType::Float);
}
IntCVar::IntCVar(const std::string& name) : CVar(name) {
SetType(VarType::Int);
}
std::unique_ptr<CVar>& CVarMap::try_emplace(std::unique_ptr<CVar> cVar) {
std::lock_guard<decltype(mutex)> lock(mutex);
const std::string& name = cVar->GetName();
auto [it, inserted] = vars.try_emplace(name, std::move(cVar));
if (inserted) {
varsOrdered.emplace_back(name);
if (uint32_t valueOffset = it->second->valueOffset.data; valueOffset || valueOffset != 0xCDCDCDCD)
varsByValueOffset[valueOffset] = it->second.get();
}
return it->second;
}
bool CVarMap::none_of(uint32_t valueOffset) {
std::lock_guard<decltype(mutex)> lock(mutex);
return varsByValueOffset.find(valueOffset) == varsByValueOffset.end();
}
CVar* CVarMap::Find(uint32_t valueOffset) const {
std::lock_guard<decltype(mutex)> lock(mutex);
auto it = varsByValueOffset.find(valueOffset);
return it == varsByValueOffset.end() ? nullptr : it->second;
}
void CVarMap::Erase(const std::string& name) {
std::lock_guard<decltype(mutex)> lock(mutex);
auto it = vars.find(name);
if (it == vars.end())
return;
auto orderIt = std::find(varsOrdered.begin(), varsOrdered.end(), name);
if (orderIt != varsOrdered.end())
varsOrdered.erase(orderIt);
varsByValueOffset.erase(it->second->valueOffset.data);
vars.erase(it);
}
}

View File

@ -1,147 +0,0 @@
#include <algorithm>
#include <spdlog\spdlog.h>
#include <EGSDK\Offsets.h>
#include <EGSDK\Utils\Time.h>
#include <EGSDK\Engine\RendererCVars.h>
namespace EGSDK::Engine {
RendererCVar::RendererCVar(const std::string& name) {
this->name = name;
this->type = RendererCVarType::NONE;
}
RendererCVar::RendererCVar(const std::string& name, DWORD64 address) {
this->name = name;
this->type = RendererCVarType::NONE;
this->address = address;
}
const char* RendererCVar::GetName() {
return name.c_str();
}
void RendererCVar::SetName(const std::string& name) {
this->name = name;
}
RendererCVarType RendererCVar::GetType() {
return type;
}
void RendererCVar::SetType(RendererCVarType type) {
this->type = type;
}
DWORD64 RendererCVar::GetAddress() {
return address;
}
void RendererCVar::SetAddress(DWORD64 address) {
this->address = address;
}
FloatRendererCVar::FloatRendererCVar(const std::string& name) : RendererCVar(name) {
SetType(RendererCVarType::Float);
}
FloatRendererCVar::FloatRendererCVar(const std::string& name, DWORD64 address) : RendererCVar(name, address) {
SetType(RendererCVarType::Float);
}
float FloatRendererCVar::GetValue() {
return value;
}
void FloatRendererCVar::SetValue(float value) {
this->value = value;
}
std::unique_ptr<RendererCVar>& RendererCVarMap::try_emplace(std::unique_ptr<RendererCVar> rendererCVar) {
std::lock_guard<std::mutex> lock(mutex);
const std::string& name = rendererCVar->GetName();
auto [it, inserted] = _rendererCVars.try_emplace(name, std::move(rendererCVar));
if (inserted) {
_order.emplace_back(name);
_rendererCVarsByAddress[it->second->GetAddress()] = it->second.get();
}
return it->second;
}
bool RendererCVarMap::empty() {
std::lock_guard<std::mutex> lock(mutex);
return _rendererCVars.empty();
}
bool RendererCVarMap::none_of(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex);
return _rendererCVars.find(name) == _rendererCVars.end();
}
bool RendererCVarMap::none_of(DWORD64 address) {
std::lock_guard<std::mutex> lock(mutex);
return _rendererCVarsByAddress.find(address) == _rendererCVarsByAddress.end();
}
std::unique_ptr<RendererCVar>* RendererCVarMap::FindPtr(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex);
auto it = _rendererCVars.find(name);
return it == _rendererCVars.end() ? nullptr : &it->second;
}
RendererCVar* RendererCVarMap::Find(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex);
auto it = _rendererCVars.find(name);
return it == _rendererCVars.end() ? nullptr : it->second.get();
}
RendererCVar* RendererCVarMap::Find(DWORD64 address) {
std::lock_guard<std::mutex> lock(mutex);
auto it = _rendererCVarsByAddress.find(address);
return it == _rendererCVarsByAddress.end() ? nullptr : it->second;
}
bool RendererCVarMap::Erase(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex);
auto it = _rendererCVars.find(name);
if (it != _rendererCVars.end())
return _rendererCVarsByAddress.erase(it->second->GetAddress()) > 0 && _rendererCVars.erase(name) > 0;
return false;
}
RendererCVarMap RendererCVars::rendererCVars{};
RendererCVarMap RendererCVars::customRendererCVars{};
RendererCVarMap RendererCVars::defaultRendererCVars{};
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;
}
float RendererCVars::GetRendererCVarValue(const std::string& name) {
auto rendererCVar = rendererCVars.Find(name);
if (!rendererCVar)
return getDefaultValue<float>();
return reinterpret_cast<FloatRendererCVar*>(rendererCVar)->GetValue();
}
void RendererCVars::ChangeRendererCVar(const std::string& name, float value, RendererCVar* rendererCVar) {
if (!rendererCVar)
rendererCVar = rendererCVars.Find(name);
if (!rendererCVar)
return;
if (rendererCVar->GetType() == RendererCVarType::Float)
reinterpret_cast<FloatRendererCVar*>(rendererCVar)->SetValue(value);
}
void RendererCVars::ChangeRendererCVarFromList(const std::string& name, float value, RendererCVar* rendererCVar) {
if (!rendererCVar)
rendererCVar = rendererCVars.Find(name);
if (!rendererCVar)
return;
auto customRendererCVar = customRendererCVars.Find(name);
auto defRendererCVar = defaultRendererCVars.Find(name);
if (rendererCVar->GetType() != RendererCVarType::Float)
return;
if (!customRendererCVar)
customRendererCVar = customRendererCVars.try_emplace(std::make_unique<FloatRendererCVar>(name, rendererCVar->GetAddress())).get();
if (!defRendererCVar) {
defRendererCVar = defaultRendererCVars.try_emplace(std::make_unique<FloatRendererCVar>(name)).get();
reinterpret_cast<FloatRendererCVar*>(defRendererCVar)->SetValue(reinterpret_cast<FloatRendererCVar*>(rendererCVar)->GetValue());
}
reinterpret_cast<FloatRendererCVar*>(rendererCVar)->SetValue(value);
reinterpret_cast<FloatRendererCVar*>(customRendererCVar)->SetValue(value);
}
}

View File

@ -0,0 +1,47 @@
#include <EGSDK\Engine\VarBase.h>
namespace EGSDK::Engine {
std::unordered_map<const VarBase*, std::string> VarBase::varNames{};
std::unordered_map<const VarBase*, VarType> VarBase::varTypes{};
std::recursive_mutex VarBase::mutex{};
VarBase::VarBase(const std::string& name) {
std::lock_guard<decltype(mutex)> lock(mutex);
varNames[this] = name;
varTypes[this] = VarType::NONE;
}
VarBase::VarBase(const std::string& name, VarType type) {
std::lock_guard<decltype(mutex)> lock(mutex);
varNames[this] = name;
varTypes[this] = type;
}
VarBase::~VarBase() {
std::lock_guard<decltype(mutex)> lock(mutex);
varNames.erase(this);
varTypes.erase(this);
}
const char* VarBase::GetName() const {
std::lock_guard<decltype(mutex)> lock(mutex);
auto it = varNames.find(this);
if (it != varNames.end())
return it->second.c_str();
return nullptr;
}
void VarBase::SetName(const std::string& newName) {
std::lock_guard<decltype(mutex)> lock(mutex);
varNames[this] = newName;
}
VarType VarBase::GetType() const {
std::lock_guard<decltype(mutex)> lock(mutex);
auto it = varTypes.find(this);
if (it != varTypes.end())
return it->second;
return VarType::NONE;
}
void VarBase::SetType(VarType newType) {
std::lock_guard<decltype(mutex)> lock(mutex);
varTypes[this] = newType;
}
}

View File

@ -0,0 +1 @@


View File

@ -0,0 +1 @@


View File

@ -108,6 +108,7 @@
<GenerateManifest>true</GenerateManifest>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetName>EGameTools</TargetName>
@ -147,7 +148,7 @@
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>DebugFastLink</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>DbgHelp.lib;Version.lib;EGameSDK.lib;libMinHook-x64-v141-mdd.lib;freetype-mdd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OptimizeReferences>
@ -187,7 +188,7 @@
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalLibraryDirectories>..\EGameSDK\deps\MinHook\lib;deps\freetype\lib;..\$(PlatformShortName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>DbgHelp.lib;Version.lib;EGameSDK.lib;libMinHook-x64-v141-mdd.lib;freetype-md.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>

View File

@ -4,6 +4,7 @@
#include <ImGui\imgui_internal.h>
#include <EGSDK\Utils\Time.h>
#include <EGSDK\Utils\Values.h>
#include <EGSDK\Core\Core.h>
namespace ImGui {
bool isAnyHotkeyBtnClicked = false;
@ -13,10 +14,10 @@ namespace ImGui {
VKey::VKey(std::string_view name, int code) : name(name), code(code) {}
#pragma region Option
Option::Option() {
Option::Option(bool value) : value(value), previousValue(value) {
GetInstances()->insert(this);
};
Option::Option(bool value) : value(value) {
Option::Option(bool value, std::initializer_list<uint32_t> unsupportedGameVers) : value(value), previousValue(value), unsupportedGameVers(unsupportedGameVers) {
GetInstances()->insert(this);
};
Option::~Option() {
@ -33,6 +34,7 @@ namespace ImGui {
bool Option::GetChangesAreDisabled() const {
return changesAreDisabled;
}
void Option::Toggle() {
previousValue = value;
value = !value;
@ -63,6 +65,11 @@ namespace ImGui {
bool Option::HasChangedTo(bool toValue) const {
return previousValue != value && value == toValue;
}
uint32_t Option::IsUnsupportedGameVer() const {
auto it = unsupportedGameVers.find(EGSDK::Core::gameVer);
return it != unsupportedGameVers.end() ? EGSDK::Core::gameVer : 0;
}
#pragma endregion
#pragma region KeyBindOption
@ -70,7 +77,7 @@ namespace ImGui {
bool KeyBindOption::scrolledMouseWheelUp = false;
bool KeyBindOption::scrolledMouseWheelDown = false;
KeyBindOption::KeyBindOption(int keyCode, bool isToggleableOption) : keyCode(keyCode), isToggleableOption(isToggleableOption) {
KeyBindOption::KeyBindOption(bool value, int keyCode, bool isToggleableOption, std::initializer_list<uint32_t> unsupportedGameVers) : keyCode(keyCode), isToggleableOption(isToggleableOption), Option(value, unsupportedGameVers) {
GetInstances()->insert(this);
};
KeyBindOption::~KeyBindOption() {
@ -452,29 +459,21 @@ namespace ImGui {
});
#pragma endregion
static void HotkeyDebugInfo(const std::string_view& label) {
ImGuiContext& g = *GImGui;
ImGui::Text("Hotkey Label: %s", label.data());
ImGui::Text("CurrentItemFlags: 0x%X", g.CurrentItemFlags);
ImGui::Text("DisabledStackSize: %d", g.DisabledStackSize);
ImGui::Text("ItemFlagsStack Size: %d", (int)g.ItemFlagsStack.size());
for (size_t i = 0; i < g.ItemFlagsStack.size(); ++i) {
ImGui::Text(" Stack[%d]: 0x%X", (int)i, g.ItemFlagsStack[i]);
}
}
void Hotkey(const std::string_view& label, KeyBindOption* key) {
if (key->IsUnsupportedGameVer())
ImGui::BeginDisabled(key->IsUnsupportedGameVer());
ImGuiContext& g = *GImGui;
bool wasDisabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
//HotkeyDebugInfo(label);
if (wasDisabled)
ImGui::EndDisabled();
ImGuiItemFlags backupFlags = g.CurrentItemFlags;
g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
float backupAlpha = g.Style.Alpha;
g.Style.Alpha = backupAlpha / g.Style.DisabledAlpha;
if (wasDisabled && !key->IsUnsupportedGameVer()) {
ImGui::EndDisabled();
g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
g.Style.Alpha = backupAlpha / g.Style.DisabledAlpha;
}
const ImGuiID id = GetID(label.data());
PushID(label.data());
@ -516,12 +515,13 @@ namespace ImGui {
PopID();
g.CurrentItemFlags = backupFlags;
g.Style.Alpha = backupAlpha;
if (wasDisabled)
if (wasDisabled && !key->IsUnsupportedGameVer()) {
g.CurrentItemFlags = backupFlags;
g.Style.Alpha = backupAlpha;
ImGui::BeginDisabled(true);
}
//HotkeyDebugInfo(label);
if (key->IsUnsupportedGameVer())
ImGui::EndDisabled();
}
}

View File

@ -30,15 +30,16 @@ namespace ImGui {
class Option {
public:
Option();
bool value = false;
Option(bool value);
Option(bool value, std::initializer_list<uint32_t> unsupportedGameVers);
~Option();
static std::set<Option*>* GetInstances();
bool value = false;
void SetChangesAreDisabled(bool newValue);
bool GetChangesAreDisabled() const;
void Toggle();
void Set(bool newValue);
void SetBothValues(bool newValue);
@ -48,9 +49,12 @@ namespace ImGui {
bool GetPrevValue() const;
bool HasChanged() const;
bool HasChangedTo(bool toValue) const;
uint32_t IsUnsupportedGameVer() const;
private:
bool changesAreDisabled = false;
bool previousValue = false;
std::set<uint32_t> unsupportedGameVers{};
};
class KeyBindOption : public Option {
public:
@ -58,7 +62,7 @@ namespace ImGui {
static bool scrolledMouseWheelUp;
static bool scrolledMouseWheelDown;
KeyBindOption(int keyCode, bool isToggleableOption = true);
KeyBindOption(bool value, int keyCode, bool isToggleableOption = true, std::initializer_list<uint32_t> unsupportedGameVers = {});
~KeyBindOption();
static std::set<KeyBindOption*>* GetInstances();

View File

@ -1,6 +1,6 @@
#include <ImGui\imgui_hotkey.h>
#include <ImGui\imgui_internal.h>
#include <EGSDK\GamePH\GamePH_Misc.h>
namespace ImGui {
static ImGuiStyle defImGuiStyle{};
static size_t tabIndex = 1;
@ -69,9 +69,13 @@ namespace ImGui {
return checkbox;
}
bool Checkbox(const char* label, Option* v) {
ImGui::BeginDisabled(v->IsUnsupportedGameVer());
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
if (window->SkipItems) {
ImGui::EndDisabled();
return false;
}
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
@ -84,6 +88,7 @@ namespace ImGui {
ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id)) {
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (v->GetValue() ? ImGuiItemStatusFlags_Checked : 0));
ImGui::EndDisabled();
return false;
}
@ -116,17 +121,20 @@ namespace ImGui {
RenderText(label_pos, label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (v->GetValue() ? ImGuiItemStatusFlags_Checked : 0));
ImGui::EndDisabled();
return pressed;
}
bool Checkbox(const char* label, Option* v, const char* tooltip) {
bool checkbox = Checkbox(label, v);
SetItemTooltip(tooltip);
std::string finalTooltip = v->IsUnsupportedGameVer() ? "Option is disabled because it does not support v" + EGSDK::GamePH::GameVerToStr(v->IsUnsupportedGameVer()) : tooltip ? tooltip : "";
if (!finalTooltip.empty())
SetItemTooltip(finalTooltip.c_str());
return checkbox;
}
bool CheckboxHotkey(const char* label, KeyBindOption* v, const char* tooltip) {
const bool checkbox = Checkbox(label, v);
if (tooltip)
SetItemTooltip(tooltip);
bool checkbox = Checkbox(label, v, tooltip);
Hotkey(std::string(label + std::string("##ToggleKey")), v);
return checkbox;
}

View File

@ -7,7 +7,6 @@
namespace EGT {
constexpr const char* MOD_VERSION_STR = "v1.3.0";
constexpr unsigned long MOD_VERSION = 10300;
constexpr unsigned long GAME_VER_COMPAT = 12001;
namespace Core {
extern void OpenIOBuffer();

View File

@ -275,15 +275,6 @@ namespace EGT::Core {
exit(0);
}
#endif
static void GameVersionCheck() {
SPDLOG_INFO("Game version: v{}", EGSDK::GamePH::GameVerToStr(EGSDK::Core::gameVer));
SPDLOG_DEBUG("Comparing game version with compatible version");
if (EGSDK::Core::gameVer != GAME_VER_COMPAT) {
SPDLOG_WARN("Game version is not compatible with mod");
SPDLOG_ERROR("Please note that your game version has not been officially tested with this mod, therefore expect bugs, glitches or the mod to completely stop working. If so, please {}", EGSDK::Core::gameVer > GAME_VER_COMPAT ? "wait for a new patch." : "upgrade your game version to one that the mod supports.");
} else
SPDLOG_DEBUG("Game version is compatible with mod");
}
DWORD64 WINAPI MainThread(HMODULE hModule) {
EGSDK::GamePH::Hooks::OnPostUpdateHook.RegisterCallback(OnPostUpdate);
@ -291,9 +282,6 @@ namespace EGT::Core {
SetUnhandledExceptionFilter(CrashHandler);
#endif
SPDLOG_INFO("Running game version checks");
GameVersionCheck();
SPDLOG_INFO("Initializing config");
Config::InitConfig();
threads.emplace_back(Config::ConfigLoop);

View File

@ -4,7 +4,7 @@
#include <EGSDK\Utils\Time.h>
#include <EGSDK\Utils\WinMemory.h>
#include <EGSDK\GamePH\LevelDI.h>
#include <EGSDK\Engine\RendererCVars.h>
#include <EGSDK\Engine\CVars.h>
#include <EGSDK\Engine\CBaseCamera.h>
#include <EGSDK\Engine\Engine_Misc.h>
#include <EGSDK\GamePH\FreeCamera.h>
@ -269,20 +269,71 @@ namespace EGT::Engine {
} };
#pragma endregion
#pragma region UpdateVarFloat
static EGSDK::Utils::Hook::MHook<void*, void(*)(uint64_t, uint64_t, float*, uint64_t, uint64_t), uint64_t, uint64_t, float*, uint64_t, uint64_t> UpdateCVarFloatHook{ "UpdateCVarFloat", &EGSDK::OffsetManager::Get_UpdateCVarFloat, [](uint64_t a1, uint64_t a2, float* varValue, uint64_t a4, uint64_t a5) -> void {
UpdateCVarFloatHook.ExecuteOriginal(a1, a2, varValue, a4, a5);
const char* name = reinterpret_cast<const char*>(a1 - 0x60);
#pragma region GetCVarT
EGSDK::Utils::Hook::MHook<void*, EGSDK::Engine::CVar*(*)(uint64_t, const char*, uint64_t, int), uint64_t, const char*, uint64_t, int> GetCVarTHook{ "GetCVarT", &EGSDK::OffsetManager::Get_GetCVarT, [](uint64_t pEvent, const char* name, uint64_t eventType, int someFlag) -> EGSDK::Engine::CVar* {
EGSDK::Engine::CVar* cVarPtr = GetCVarTHook.ExecuteOriginal(pEvent, name, eventType, someFlag);
if (!cVarPtr)
return cVarPtr;
if (EGSDK::Engine::CVars::vars.Find(name))
return cVarPtr;
auto floatRendererCVar = reinterpret_cast<EGSDK::Engine::FloatRendererCVar*>(EGSDK::Engine::RendererCVars::rendererCVars.Find(a1));
if (!floatRendererCVar)
floatRendererCVar = reinterpret_cast<EGSDK::Engine::FloatRendererCVar*>(EGSDK::Engine::RendererCVars::rendererCVars.try_emplace(std::make_unique<EGSDK::Engine::FloatRendererCVar>(name, a1)).get());
switch (eventType - pEvent) {
case 0x1A8:
{
cVarPtr->SetName(name);
cVarPtr->SetType(EGSDK::Engine::VarType::Float);
EGSDK::Engine::CVars::vars.try_emplace(std::unique_ptr<EGSDK::Engine::CVar>(cVarPtr));
break;
}
case 0x198:
{
cVarPtr->SetName(name);
cVarPtr->SetType(EGSDK::Engine::VarType::Int);
EGSDK::Engine::CVars::vars.try_emplace(std::unique_ptr<EGSDK::Engine::CVar>(cVarPtr));
break;
}
default:
break;
}
auto customFloatRendererCVar = reinterpret_cast<EGSDK::Engine::FloatRendererCVar*>(EGSDK::Engine::RendererCVars::customRendererCVars.Find(a1));
if (customFloatRendererCVar)
*varValue = customFloatRendererCVar->GetValue();
else if (floatRendererCVar)
floatRendererCVar->SetValue(*varValue);
return cVarPtr;
} };
#pragma endregion
#pragma region GetCVarValue
static std::unordered_map<uint32_t, uint64_t*> cVarValuePtrs;
static EGSDK::Utils::Hook::MHook<void*, uint64_t*(*)(uint64_t, uint32_t, int), uint64_t, uint32_t, int> GetCVarValueHook{ "GetCVarValue", &EGSDK::OffsetManager::Get_GetCVarValue, [](uint64_t a1, uint32_t valueOffset, int a3) -> uint64_t* {
uint64_t* varValuePtr = GetCVarValueHook.ExecuteOriginal(a1, valueOffset, a3);
if (!varValuePtr)
return varValuePtr;
EGSDK::Engine::CVar* cVar = EGSDK::Engine::CVars::vars.Find(valueOffset);
if (!cVar)
return varValuePtr;
cVar->AddValuePtr(varValuePtr);
EGSDK::Engine::CVar* customCVar = EGSDK::Engine::CVars::customVars.Find(cVar->GetName());
if (!customCVar)
return varValuePtr;
switch (cVar->GetType()) {
case EGSDK::Engine::VarType::Float:
{
auto value = EGSDK::Engine::CVars::GetVarValue<float>(customCVar);
if (value)
cVar->SetValue(*value);
break;
}
case EGSDK::Engine::VarType::Int:
{
auto value = EGSDK::Engine::CVars::GetVarValue<int>(customCVar);
if (value)
cVar->SetValue(*value);
break;
}
}
return varValuePtr;
} };
#pragma endregion

View File

@ -108,7 +108,7 @@ namespace EGT::GamePH {
#pragma endregion
#pragma region ShowTPPModelFunc3
ImGui::Option wannaUseTPPModel{};
ImGui::Option wannaUseTPPModel{ false };
static bool prevUseTPPModel;
static EGSDK::Utils::Hook::MHook<void*, void(*)(uint64_t, bool), uint64_t, bool> ShowTPPModelFunc3Hook{ "ShowTPPModelFunc3", &EGSDK::OffsetManager::Get_ShowTPPModelFunc3, [](uint64_t tppFunc2Addr, bool showTPPModel) -> void {

View File

@ -1,4 +1,5 @@
#include <Windows.h>
#define DIRECTINPUT_VERSION 0x0800
#include <Windows.h>
#include <dinput.h>
#include <spdlog\spdlog.h>
#include <ImGui\imgui_hotkey.h>

View File

@ -21,18 +21,18 @@ namespace EGT::Menu {
EGSDK::Vec3 cameraOffset{};
float firstPersonFOV = baseFOV;
float originalFirstPersonFOVAfterZoomIn = firstPersonFOV;
ImGui::KeyBindOption firstPersonZoomIn{ 'Q' , false };
ImGui::KeyBindOption firstPersonZoomIn{ false, 'Q', false };
static bool isZoomingIn = false;
ImGui::Option photoMode{ false };
ImGui::KeyBindOption freeCam{ VK_F3 };
ImGui::KeyBindOption freeCam{ false, VK_F3 };
float freeCamFOV = baseFOV;
float freeCamSpeed = 2.0f;
ImGui::KeyBindOption teleportPlayerToCamera{ VK_F4 };
ImGui::KeyBindOption teleportPlayerToCamera{ false, VK_F4 };
ImGui::KeyBindOption thirdPersonCamera{ VK_F1 };
ImGui::KeyBindOption tpUseTPPModel{ VK_F2 };
ImGui::KeyBindOption thirdPersonCamera{ false, VK_F1 };
ImGui::KeyBindOption tpUseTPPModel{ false, VK_F2 };
float thirdPersonFOV = baseFOV;
float thirdPersonDistanceBehindPlayer = 2.0f;
float thirdPersonHeightAbovePlayer = 1.3f;
@ -40,10 +40,10 @@ namespace EGT::Menu {
float lensDistortion = 20.0f;
static float altLensDistortion = lensDistortion;
ImGui::KeyBindOption goProMode{ VK_NONE };
ImGui::KeyBindOption disableSafezoneFOVReduction{ VK_NONE };
ImGui::KeyBindOption disablePhotoModeLimits{ VK_NONE };
ImGui::KeyBindOption disableHeadCorrection{ VK_NONE };
ImGui::KeyBindOption goProMode{ false, VK_NONE };
ImGui::KeyBindOption disableSafezoneFOVReduction{ false, VK_NONE };
ImGui::KeyBindOption disablePhotoModeLimits{ false, VK_NONE };
ImGui::KeyBindOption disableHeadCorrection{ false, VK_NONE };
static void CalculateBaseFOV() {
if (!EGSDK::Utils::Values::are_samef(baseFOV, 0.0f))

View File

@ -61,14 +61,12 @@ namespace EGT::Menu {
ImGui::TextCentered(thankYou.c_str());
ImGui::Spacing(ImVec2(0.0f, 5.0f));
const std::string gameCompat = "This version of the mod is compatible with game version v" + EGSDK::GamePH::GameVerToStr(GAME_VER_COMPAT) + ".";
const std::string gameCompat = "This version of the mod is compatible with game versions: " + EGSDK::Core::GetSupportedGameVersionsStr() + ".";
ImGui::TextCentered(gameCompat.c_str());
const std::string gameVer = "The game version you are currently running is v" + EGSDK::GamePH::GameVerToStr(EGSDK::Core::gameVer) + ".";
ImGui::TextCentered(gameVer.c_str());
if (EGSDK::Core::gameVer != GAME_VER_COMPAT) {
const std::string gameNotCompat = "Please note that your game version has not been officially tested with this mod, therefore expect bugs, glitches or the mod to completely stop working. If so, please " + std::string(EGSDK::Core::gameVer > GAME_VER_COMPAT ? "wait for a new patch." : "upgrade your game version to one that the mod supports.");
ImGui::TextCenteredColored(gameNotCompat.c_str(), IM_COL32(200, 0, 0, 255));
}
if (!EGSDK::Core::IsGameVerCompatible())
ImGui::TextCenteredColored("Please note that your game version has not been officially tested with this mod, therefore expect bugs, glitches or the mod to completely stop working. If so, please upgrade or downgrade your game version to one that the mod supports.", IM_COL32(200, 0, 0, 255));
ImGui::Spacing(ImVec2(0.0f, 5.0f));
ImGui::TextCentered("I will not bore you with what this mod is about, so let's get right to teaching you how to use it!");

View File

@ -19,7 +19,7 @@ namespace EGT::Menu {
static constexpr ImVec2 defMaxWndSize = ImVec2(900.0f, 725.0f);
static ImVec2 maxWndSize = defMaxWndSize;
ImGui::KeyBindOption menuToggle{ VK_F5 };
ImGui::KeyBindOption menuToggle{ false, VK_F5 };
float opacity = 99.0f;
float scale = 1.0f;
@ -41,7 +41,7 @@ namespace EGT::Menu {
ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.0f) - (EGTLogoSize.x / 2.0f));
ImGui::Image(EGTLogoTexture, EGTLogoSize);
const float footerHeight = ImGui::GetFrameHeightWithSpacing() * 3.0f + (EGSDK::Core::gameVer != GAME_VER_COMPAT ? (ImGui::CalcTextSize("").y * 2.0f) + GImGui->Style.FramePadding.y + GImGui->Style.ItemSpacing.y : 0.0f) + GImGui->Style.WindowPadding.y * 2.0f + GImGui->Style.FramePadding.y * 2.0f;
const float footerHeight = ImGui::GetFrameHeightWithSpacing() * 3.0f + (!EGSDK::Core::IsGameVerCompatible() ? (ImGui::CalcTextSize("").y * 2.0f) + GImGui->Style.FramePadding.y + GImGui->Style.ItemSpacing.y : 0.0f) + GImGui->Style.WindowPadding.y * 2.0f + GImGui->Style.FramePadding.y * 2.0f;
const float remainingHeight = ImGui::GetContentRegionAvail().y - footerHeight;
if (ImGui::BeginTabBar("##MainTabBar")) {
@ -51,7 +51,7 @@ namespace EGT::Menu {
ImGui::SpanNextTabAcrossWidth(childWidth, MenuTab::GetInstances()->size());
if (ImGui::BeginTabItem(tab.second->tabName.data())) {
ImGui::SetNextWindowBgAlpha(static_cast<float>(opacity) / 100.0f);
ImGui::SetNextWindowSizeConstraints(ImVec2(std::fmax(minWndSize.x - GImGui->Style.WindowPadding.x * 2.0f, ImGui::CalcTextSize(EGSDK::Core::gameVer > GAME_VER_COMPAT ? "Please wait for a new mod update." : "Upgrade your game version to one that the mod supports.").x), remainingHeight), ImVec2(maxWndSize.x - GImGui->Style.WindowPadding.x * 2.0f, remainingHeight));
ImGui::SetNextWindowSizeConstraints(ImVec2(EGSDK::Core::IsGameVerCompatible() ? minWndSize.x - GImGui->Style.WindowPadding.x * 2.0f : std::fmax(minWndSize.x - GImGui->Style.WindowPadding.x * 2.0f, ImGui::CalcTextSize(std::string("Compatible game versions: %s" + EGSDK::Core::GetSupportedGameVersionsStr()).c_str()).x), remainingHeight), ImVec2(maxWndSize.x - GImGui->Style.WindowPadding.x * 2.0f, remainingHeight));
ImGui::BeginDisabled(!EGSDK::GamePH::Hooks::didOnPostUpdateHookExecute);
if (ImGui::BeginChild("##TabChild", ImVec2(0.0f, 0.0f), ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_Border)) {
@ -70,9 +70,9 @@ namespace EGT::Menu {
ImGui::Hotkey("Menu Toggle Key", &menuToggle);
ImGui::SliderFloat("Menu Opacity", &opacity, 0.0f, 100.0f, "%.1f%%", ImGuiSliderFlags_AlwaysClamp);
ImGui::SliderFloat("Menu Scale", &scale, 1.0f, 2.5f, "%.1f%%", ImGuiSliderFlags_AlwaysClamp);
if (EGSDK::Core::gameVer != GAME_VER_COMPAT) {
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "Incompatible game version detected!");
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "Compatible game version: v%s", EGSDK::GamePH::GameVerToStr(GAME_VER_COMPAT).c_str());
if (!EGSDK::Core::IsGameVerCompatible()) {
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "Incompatible game version (v%s) detected!", EGSDK::GamePH::GameVerToStr(EGSDK::Core::gameVer).c_str());
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "Compatible game versions: %s", EGSDK::Core::GetSupportedGameVersionsStr().c_str());
}
ImGui::End();
}

View File

@ -1,7 +1,7 @@
#include <ImGui\imgui_hotkey.h>
#include <ImGui\imguiex.h>
#include <EGSDK\Utils\Hook.h>
#include <EGSDK\Engine\RendererCVars.h>
#include <EGSDK\Engine\CVars.h>
#include <EGSDK\GamePH\GameDI_PH.h>
#include <EGSDK\GamePH\LevelDI.h>
#include <EGT\ImGui_impl\DeferredActions.h>
@ -10,8 +10,8 @@
namespace EGT::Menu {
namespace Misc {
ImGui::KeyBindOption disableGamePauseWhileAFK{ VK_NONE };
ImGui::KeyBindOption disableHUD{ VK_F8 };
ImGui::KeyBindOption disableGamePauseWhileAFK{ false, VK_NONE };
ImGui::KeyBindOption disableHUD{ false, VK_F8 };
ImGui::Option disableSavegameCRCCheck{ false };
ImGui::Option disableDataPAKsCRCCheck{ false };
ImGui::Option increaseDataPAKsLimit{ false };
@ -23,57 +23,105 @@ namespace EGT::Menu {
disableHUD.SetChangesAreDisabled(!iLevel || !iLevel->IsLoaded());
}
static bool ShouldDisplayVariable(const std::unique_ptr<EGSDK::Engine::RendererCVar>& rendererCVarPtr, const std::string& searchFilter) {
if (rendererCVarPtr->GetType() == EGSDK::Engine::RendererCVarType::NONE)
return false;
if (EGSDK::Utils::Values::are_samef(reinterpret_cast<EGSDK::Engine::FloatRendererCVar*>(rendererCVarPtr.get())->GetValue(), -404.0f))
static bool ShouldDisplayVariable(const std::unique_ptr<EGSDK::Engine::CVar>& cVarPtr, const std::string& searchFilter) {
if (cVarPtr->GetType() == EGSDK::Engine::VarType::NONE)
return false;
if (searchFilter.empty())
return true;
// Convert searchFilter and variable name to lowercase
std::string lowerFilter = EGSDK::Utils::Values::to_lower(searchFilter);
std::string lowerKey = EGSDK::Utils::Values::to_lower(rendererCVarPtr->GetName());
std::string lowerKey = EGSDK::Utils::Values::to_lower(cVarPtr->GetName());
return lowerKey.find(lowerFilter) != std::string::npos;
}
static void RestoreVariableToDefault(const std::string& name) {
ImGui_impl::DeferredActions::Add([name]() {
auto defRendererCVar = EGSDK::Engine::RendererCVars::defaultRendererCVars.Find(name);
if (!defRendererCVar)
return;
static void RestoreVariableToDefault(const std::unique_ptr<EGSDK::Engine::CVar>& cVarPtr) {
auto cVar = cVarPtr.get();
EGSDK::Engine::RendererCVars::ChangeRendererCVar(name, reinterpret_cast<EGSDK::Engine::FloatRendererCVar*>(defRendererCVar)->GetValue());
ImGui_impl::DeferredActions::Add([cVar]() {
switch (cVar->GetType()) {
case EGSDK::Engine::VarType::Float:
{
auto defValue = EGSDK::Engine::CVars::GetVarValueFromMap<float>(cVar->GetName(), EGSDK::Engine::CVars::defaultVars);
if (!defValue)
return;
EGSDK::Engine::RendererCVars::defaultRendererCVars.Erase(name);
EGSDK::Engine::RendererCVars::customRendererCVars.Erase(name);
EGSDK::Engine::CVars::ChangeVar(cVar->GetName(), *defValue);
break;
}
case EGSDK::Engine::VarType::Int:
{
auto defValue = EGSDK::Engine::CVars::GetVarValueFromMap<int>(cVar->GetName(), EGSDK::Engine::CVars::defaultVars);
if (!defValue)
return;
EGSDK::Engine::CVars::ChangeVar(cVar->GetName(), *defValue);
break;
}
}
EGSDK::Engine::CVars::defaultVars.Erase(cVar->GetName());
EGSDK::Engine::CVars::customVars.Erase(cVar->GetName());
});
}
static void RenderRendererCVar(const std::unique_ptr<EGSDK::Engine::RendererCVar>& rendererCVarPtr) {
auto rendererCVar = rendererCVarPtr.get();
static void RestoreVariablesToDefault() {
EGSDK::Engine::CVars::customVars.ForEach([](const std::unique_ptr<EGSDK::Engine::CVar>& cVarPtr) {
RestoreVariableToDefault(cVarPtr);
});
}
static void RenderRendererCVar(const std::unique_ptr<EGSDK::Engine::CVar>& cVarPtr) {
auto cVar = cVarPtr.get();
float newValue = reinterpret_cast<EGSDK::Engine::FloatRendererCVar*>(rendererCVar)->GetValue();
if (ImGui::InputFloat(rendererCVar->GetName(), &newValue))
EGSDK::Engine::RendererCVars::ChangeRendererCVarFromList(rendererCVar->GetName(), newValue, rendererCVar);
switch (cVar->GetType()) {
case EGSDK::Engine::VarType::Float:
{
auto value = EGSDK::Engine::CVars::GetVarValue<float>(cVar);
if (!value)
return;
auto newValue = *value;
if (ImGui::InputFloat(cVar->GetName(), &newValue))
EGSDK::Engine::CVars::ChangeVarFromList(cVar, newValue);
break;
}
case EGSDK::Engine::VarType::Int:
{
auto value = EGSDK::Engine::CVars::GetVarValue<int>(cVar);
if (!value)
return;
auto newValue = *value;
if (ImGui::InputInt(cVar->GetName(), &newValue))
EGSDK::Engine::CVars::ChangeVarFromList(cVar, newValue);
break;
}
default:
break;
}
ImGui::SameLine();
std::string restoreBtnName = "Restore##" + std::string(rendererCVarPtr->GetName());
std::string restoreBtnName = "Restore##" + std::string(cVar->GetName());
ImGui::BeginDisabled(EGSDK::Engine::RendererCVars::customRendererCVars.none_of(rendererCVarPtr->GetName()));
ImGui::BeginDisabled(EGSDK::Engine::CVars::customVars.none_of(cVar->GetName()));
if (ImGui::Button(restoreBtnName.c_str(), "Restores renderer cvar to default"))
RestoreVariableToDefault(rendererCVarPtr->GetName());
RestoreVariableToDefault(cVarPtr);
ImGui::EndDisabled();
}
static void HandleRendererCVarsList() {
ImGui::BeginDisabled(EGSDK::Engine::RendererCVars::rendererCVars.empty());
ImGui::BeginDisabled(EGSDK::Engine::CVars::vars.empty());
if (ImGui::CollapsingHeader("Renderer CVars list", ImGuiTreeNodeFlags_None)) {
ImGui::Indent();
ImGui::BeginDisabled(EGSDK::Engine::CVars::customVars.empty());
if (ImGui::Button("Restore variables to default"))
RestoreVariablesToDefault();
ImGui::EndDisabled();
ImGui::Separator();
ImGui::InputTextWithHint("##RendererCVarsSearch", "Search variables", rendererCVarsSearchFilter, 64);
EGSDK::Engine::RendererCVars::rendererCVars.ForEach([](std::unique_ptr<EGSDK::Engine::RendererCVar>& rendererCVarPtr) {
if (ShouldDisplayVariable(rendererCVarPtr, rendererCVarsSearchFilter))
RenderRendererCVar(rendererCVarPtr);
EGSDK::Engine::CVars::vars.ForEach([](std::unique_ptr<EGSDK::Engine::CVar>& cVarPtr) {
if (ShouldDisplayVariable(cVarPtr, rendererCVarsSearchFilter))
RenderRendererCVar(cVarPtr);
});
ImGui::Unindent();

View File

@ -30,18 +30,18 @@ namespace EGT::Menu {
float playerImmunity = 80.0f;
float playerMaxImmunity = 80.0f;
int oldWorldMoney = 0;
ImGui::KeyBindOption godMode{ VK_F6 };
ImGui::KeyBindOption freezePlayer{ VK_NONE };
ImGui::KeyBindOption unlimitedImmunity{ VK_NONE };
ImGui::KeyBindOption unlimitedStamina{ VK_NONE };
ImGui::KeyBindOption unlimitedItems{ VK_NONE };
ImGui::KeyBindOption oneHitKill{ VK_NONE };
ImGui::KeyBindOption invisibleToEnemies{ VK_NONE };
ImGui::KeyBindOption disableOutOfBoundsTimer{ VK_NONE };
ImGui::KeyBindOption nightrunnerMode{ VK_F7 };
ImGui::KeyBindOption oneHandedMode{ VK_NONE };
ImGui::KeyBindOption disableSafezoneRestrictions{ VK_NONE };
ImGui::KeyBindOption disableAirControl{ VK_NONE };
ImGui::KeyBindOption godMode{ false, VK_F6 };
ImGui::KeyBindOption freezePlayer{ false, VK_NONE };
ImGui::KeyBindOption unlimitedImmunity{ false, VK_NONE };
ImGui::KeyBindOption unlimitedStamina{ false, VK_NONE };
ImGui::KeyBindOption unlimitedItems{ false, VK_NONE };
ImGui::KeyBindOption oneHitKill{ false, VK_NONE, true, { 11200 } };
ImGui::KeyBindOption invisibleToEnemies{ false, VK_NONE };
ImGui::KeyBindOption disableOutOfBoundsTimer{ false, VK_NONE };
ImGui::KeyBindOption nightrunnerMode{ false, VK_F7 };
ImGui::KeyBindOption oneHandedMode{ false, VK_NONE };
ImGui::KeyBindOption disableSafezoneRestrictions{ false, VK_NONE };
ImGui::KeyBindOption disableAirControl{ false, VK_NONE };
ImGui::Option playerVariables{ false };
std::string saveSCRPath{};
@ -559,7 +559,9 @@ namespace EGT::Menu {
ImGui::CheckboxHotkey("Unlimited Stamina", &unlimitedStamina, "Stops stamina from draining");
ImGui::CheckboxHotkey("Unlimited Items", &unlimitedItems, "Stops the game from lowering the amount of items such as consumables / throwables when using them, alongside other inventory items such as ammo, lockpicks and other items;\nWARNING: This will not stop the item from getting removed from your inventory if you drop the entire amount\nCurrently, if the amount of item is 1, it will still drop from your inventory unfortunately");
ImGui::SameLine();
ImGui::CheckboxHotkey("One-Hit Kill", &oneHitKill, "Makes the player one-hit kill EVERYTHING and EVERYONE RAWRRR");
ImGui::CheckboxHotkey("Invisible to Enemies", &invisibleToEnemies, "Makes the player invisible to the enemies");
ImGui::SameLine();
ImGui::CheckboxHotkey("Disable Out of Bounds Timer", &disableOutOfBoundsTimer, "Disables the timer that runs when out of map bounds or mission bounds");

View File

@ -24,9 +24,9 @@ namespace EGT::Menu {
bool justTeleportedToWaypoint = false;
static EGSDK::Vec3 teleportCoords{};
ImGui::KeyBindOption teleportToSelectedLocation{ VK_F9 };
ImGui::KeyBindOption teleportToCoords{ VK_NONE };
ImGui::KeyBindOption teleportToWaypoint{ VK_F10 };
ImGui::KeyBindOption teleportToSelectedLocation{ false, VK_F9 };
ImGui::KeyBindOption teleportToCoords{ false, VK_NONE };
ImGui::KeyBindOption teleportToWaypoint{ false, VK_F10 };
void UpdateTeleportLocationVisualNames() {
savedTeleportLocationNames.clear();

View File

@ -9,11 +9,11 @@
namespace EGT::Menu {
namespace Weapon {
float currentWeaponDurability = 0.0f;
ImGui::KeyBindOption unlimitedDurability{ VK_NONE };
ImGui::KeyBindOption unlimitedAmmo{ VK_NONE };
ImGui::KeyBindOption noSpread{ VK_NONE };
ImGui::KeyBindOption noRecoil{ VK_NONE };
ImGui::KeyBindOption instantReload{ VK_NONE };
ImGui::KeyBindOption unlimitedDurability{ false, VK_NONE };
ImGui::KeyBindOption unlimitedAmmo{ false, VK_NONE };
ImGui::KeyBindOption noSpread{ false, VK_NONE };
ImGui::KeyBindOption noRecoil{ false, VK_NONE };
ImGui::KeyBindOption instantReload{ false, VK_NONE };
static constexpr float baseWeaponDurabilityMul = 1.0f;
static constexpr float baseWeaponAccuracyMul = 1.0f;

View File

@ -18,8 +18,8 @@ namespace EGT::Menu {
static bool isModifyingGameSpeed = false;
static float actualGameSpeed = gameSpeed;
static float gameSpeedBeforeSlowMo = gameSpeed;
ImGui::KeyBindOption freezeTime{ VK_NONE };
ImGui::KeyBindOption slowMotion{ '4' };
ImGui::KeyBindOption freezeTime{ false, VK_NONE };
ImGui::KeyBindOption slowMotion{ false, '4' };
float slowMotionSpeed = 0.4f;
static float slowMotionSpeedLerp = gameSpeed;
float slowMotionTransitionTime = 1.0f;