mirror of
https://github.com/EricPlayZ/EGameTools.git
synced 2025-07-18 17:37:53 +08:00
- Automatically calculate base FOV at start of the game (so we don't have to rely on setting it based on game version)
- Fixed some time/weather interpolation problems - Renamed Vector3 to Vec3 - Added Mtx34 struct
This commit is contained in:
@ -52,6 +52,7 @@
|
||||
<ClCompile Include="src\GamePH\SessionCooperativeDI.cpp" />
|
||||
<ClCompile Include="src\GamePH\TimeWeather\CSystem.cpp" />
|
||||
<ClCompile Include="src\GamePH\TPPCameraDI.cpp" />
|
||||
<ClCompile Include="src\Mtx34.cpp" />
|
||||
<ClCompile Include="src\Utils\Files.cpp" />
|
||||
<ClCompile Include="src\Utils\Hook.cpp" />
|
||||
<ClCompile Include="src\Utils\Memory.cpp" />
|
||||
@ -59,7 +60,7 @@
|
||||
<ClCompile Include="src\Utils\Sigscan.cpp" />
|
||||
<ClCompile Include="src\Utils\Time.cpp" />
|
||||
<ClCompile Include="src\Utils\Values.cpp" />
|
||||
<ClCompile Include="src\Vector3.cpp" />
|
||||
<ClCompile Include="src\Vec3.cpp" />
|
||||
<ClCompile Include="SteamAPI.cpp" />
|
||||
<ClCompile Include="WinMemory.cpp" />
|
||||
</ItemGroup>
|
||||
@ -109,6 +110,7 @@
|
||||
<ClInclude Include="include\EGSDK\GamePH\TimeWeather\EWeather.h" />
|
||||
<ClInclude Include="include\EGSDK\GamePH\TimeWeather\ISubsystem.h" />
|
||||
<ClInclude Include="include\EGSDK\GamePH\TPPCameraDI.h" />
|
||||
<ClInclude Include="include\EGSDK\Mtx34.h" />
|
||||
<ClInclude Include="include\EGSDK\Offsets.h" />
|
||||
<ClInclude Include="include\EGSDK\Utils\Files.h" />
|
||||
<ClInclude Include="include\EGSDK\Utils\Hook.h" />
|
||||
@ -118,7 +120,7 @@
|
||||
<ClInclude Include="include\EGSDK\Utils\Time.h" />
|
||||
<ClInclude Include="include\EGSDK\Utils\Values.h" />
|
||||
<ClInclude Include="include\EGSDK\Utils\WinMemory.h" />
|
||||
<ClInclude Include="include\EGSDK\Vector3.h" />
|
||||
<ClInclude Include="include\EGSDK\Vec3.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
|
@ -124,7 +124,7 @@
|
||||
<ClCompile Include="src\dllmain.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Vector3.cpp">
|
||||
<ClCompile Include="src\Vec3.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ClassHelpers.cpp">
|
||||
@ -154,6 +154,9 @@
|
||||
<ClCompile Include="src\Engine\IPhysicsCharacter.cpp">
|
||||
<Filter>src\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Mtx34.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="include">
|
||||
@ -212,7 +215,7 @@
|
||||
<ClInclude Include="include\EGSDK\Offsets.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\EGSDK\Vector3.h">
|
||||
<ClInclude Include="include\EGSDK\Vec3.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\EGSDK\Utils\Hook.h">
|
||||
@ -368,5 +371,8 @@
|
||||
<ClInclude Include="include\EGSDK\GamePH\TimeWeather\ISubsystem.h">
|
||||
<Filter>include\GamePH\TimeWeather</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\EGSDK\Mtx34.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <EGSDK\Vector3.h>
|
||||
#include <EGSDK\Vec3.h>
|
||||
#include <EGSDK\Engine\IPhysicsCharacter.h>
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
|
||||
@ -7,15 +7,15 @@ namespace EGSDK::Engine {
|
||||
class EGameSDK_API CBulletPhysicsCharacter : IPhysicsCharacter {
|
||||
public:
|
||||
union {
|
||||
DynamicField(CBulletPhysicsCharacter, Vector3, playerPos);
|
||||
DynamicField(CBulletPhysicsCharacter, Vector3, playerPos2);
|
||||
DynamicField(CBulletPhysicsCharacter, Vec3, playerPos);
|
||||
DynamicField(CBulletPhysicsCharacter, Vec3, playerPos2);
|
||||
DynamicField(CBulletPhysicsCharacter, float, playerDownwardVelocity);
|
||||
};
|
||||
|
||||
static Vector3 posBeforeFreeze;
|
||||
static Vec3 posBeforeFreeze;
|
||||
|
||||
void FreezeCharacter();
|
||||
void MoveCharacter(const Vector3& pos);
|
||||
void MoveCharacter(const Vec3& pos);
|
||||
|
||||
static CBulletPhysicsCharacter* Get();
|
||||
};
|
||||
|
@ -1,17 +1,25 @@
|
||||
#pragma once
|
||||
#include <EGSDK\Vector3.h>
|
||||
#include <stdint.h>
|
||||
#include <EGSDK\Mtx34.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
struct EGameSDK_API CameraMtx {
|
||||
Mtx34* mtx1{};
|
||||
Mtx34* mtx2{};
|
||||
};
|
||||
|
||||
class EGameSDK_API IBaseCamera {
|
||||
public:
|
||||
float GetFOV();
|
||||
Vector3* GetForwardVector(Vector3* outForwardVec);
|
||||
Vector3* GetUpVector(Vector3* outUpVec);
|
||||
Vector3* GetLeftVector(Vector3* outLeftVec);
|
||||
Vector3* GetPosition(Vector3* outPos);
|
||||
Vec3* GetForwardVector(Vec3* outForwardVec);
|
||||
Vec3* GetUpVector(Vec3* outUpVec);
|
||||
Vec3* GetLeftVector(Vec3* outLeftVec);
|
||||
Vec3* GetPosition(Vec3* outPos);
|
||||
CameraMtx* GetViewMatrix();
|
||||
|
||||
void SetFOV(float fov);
|
||||
void SetPosition(const Vector3* pos);
|
||||
void SetPosition(const Vec3* pos);
|
||||
void SetCameraMatrix(const CameraMtx* mtx);
|
||||
|
||||
static bool isSetFOVCalledByEGSDK;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <EGSDK\Vector3.h>
|
||||
#include <EGSDK\Vec3.h>
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
|
30
EGameSDK/include/EGSDK/Mtx34.h
Normal file
30
EGameSDK/include/EGSDK/Mtx34.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include <EGSDK\Vec3.h>
|
||||
#include <EGSDK\Exports.h>
|
||||
|
||||
namespace EGSDK {
|
||||
struct EGameSDK_API Mtx34 {
|
||||
Vec3 XAxis;
|
||||
Vec3 YAxis;
|
||||
Vec3 ZAxis;
|
||||
Vec3 Position;
|
||||
|
||||
Mtx34();
|
||||
Mtx34(const Vec3& xAxis, const Vec3& yAxis, const Vec3& zAxis, const Vec3& position);
|
||||
|
||||
bool operator==(const Mtx34& m) const;
|
||||
Mtx34& operator+=(const Mtx34& m);
|
||||
Mtx34& operator-=(const Mtx34& m);
|
||||
Mtx34 operator+(const Mtx34& m) const;
|
||||
Mtx34 operator-(const Mtx34& m) const;
|
||||
Mtx34 operator*(const Mtx34& scalar) const;
|
||||
Mtx34 operator/(const Mtx34& scalar) const;
|
||||
Mtx34 operator*(const Vec3& scalar) const;
|
||||
Mtx34 operator/(const Vec3& scalar) const;
|
||||
|
||||
Vec3 TransformPosition(const Vec3& v) const;
|
||||
void Normalize();
|
||||
|
||||
Mtx34 TransposeRotation() const;
|
||||
};
|
||||
}
|
30
EGameSDK/include/EGSDK/Vec3.h
Normal file
30
EGameSDK/include/EGSDK/Vec3.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include <EGSDK\Exports.h>
|
||||
|
||||
namespace EGSDK {
|
||||
struct EGameSDK_API Vec3 {
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
|
||||
Vec3();
|
||||
Vec3(float x, float y, float z);
|
||||
|
||||
bool operator==(const Vec3& v) const;
|
||||
Vec3& operator+=(const Vec3& v);
|
||||
Vec3& operator-=(const Vec3& v);
|
||||
Vec3 operator+(const Vec3& v) const;
|
||||
Vec3 operator-(const Vec3& v) const;
|
||||
Vec3 operator*(const Vec3& scalar) const;
|
||||
Vec3 operator/(const Vec3& scalar) const;
|
||||
Vec3 operator*(float scalar) const;
|
||||
Vec3 operator/(float scalar) const;
|
||||
|
||||
Vec3 normalize();
|
||||
Vec3 cross(const Vec3& v) const;
|
||||
Vec3 round();
|
||||
Vec3 round(int decimals);
|
||||
|
||||
bool isDefault() const;
|
||||
};
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#include <EGSDK\Exports.h>
|
||||
|
||||
namespace EGSDK {
|
||||
struct EGameSDK_API Vector3 {
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
|
||||
Vector3();
|
||||
Vector3(float x, float y, float z);
|
||||
|
||||
bool operator==(const Vector3& v) const;
|
||||
Vector3& operator+=(const Vector3& v);
|
||||
Vector3& operator-=(const Vector3& v);
|
||||
Vector3 operator+(const Vector3& v) const;
|
||||
Vector3 operator-(const Vector3& v) const;
|
||||
Vector3 operator*(float scalar) const;
|
||||
Vector3 operator/(float scalar) const;
|
||||
|
||||
Vector3 normalize();
|
||||
Vector3 cross(const Vector3& v) const;
|
||||
Vector3 round();
|
||||
Vector3 round(int decimals);
|
||||
|
||||
bool isDefault() const;
|
||||
};
|
||||
}
|
@ -4,12 +4,12 @@
|
||||
#include <EGSDK\ClassHelpers.h>
|
||||
|
||||
namespace EGSDK::Engine {
|
||||
Vector3 CBulletPhysicsCharacter::posBeforeFreeze{};
|
||||
Vec3 CBulletPhysicsCharacter::posBeforeFreeze{};
|
||||
|
||||
void CBulletPhysicsCharacter::FreezeCharacter() {
|
||||
MoveCharacter(posBeforeFreeze);
|
||||
}
|
||||
void CBulletPhysicsCharacter::MoveCharacter(const Vector3& pos) {
|
||||
void CBulletPhysicsCharacter::MoveCharacter(const Vec3& pos) {
|
||||
playerDownwardVelocity = 0.0f;
|
||||
playerPos = pos;
|
||||
playerPos2 = pos;
|
||||
|
@ -8,17 +8,20 @@ namespace EGSDK::Engine {
|
||||
float IBaseCamera::GetFOV() {
|
||||
return Utils::Memory::SafeCallFunction<float>("engine_x64_rwdi.dll", "?GetFOV@IBaseCamera@@QEBAMXZ", -1.0f, this);
|
||||
}
|
||||
Vector3* IBaseCamera::GetForwardVector(Vector3* outForwardVec) {
|
||||
return Utils::Memory::SafeCallFunction<Vector3*>("engine_x64_rwdi.dll", "?GetForwardVector@IBaseCamera@@QEBA?BVvec3@@XZ", nullptr, this, outForwardVec);
|
||||
Vec3* IBaseCamera::GetForwardVector(Vec3* outForwardVec) {
|
||||
return Utils::Memory::SafeCallFunction<Vec3*>("engine_x64_rwdi.dll", "?GetForwardVector@IBaseCamera@@QEBA?BVvec3@@XZ", nullptr, this, outForwardVec);
|
||||
}
|
||||
Vector3* IBaseCamera::GetUpVector(Vector3* outUpVec) {
|
||||
return Utils::Memory::SafeCallFunction<Vector3*>("engine_x64_rwdi.dll", "?GetUpVector@IBaseCamera@@QEBA?BVvec3@@XZ", nullptr, this, outUpVec);
|
||||
Vec3* IBaseCamera::GetUpVector(Vec3* outUpVec) {
|
||||
return Utils::Memory::SafeCallFunction<Vec3*>("engine_x64_rwdi.dll", "?GetUpVector@IBaseCamera@@QEBA?BVvec3@@XZ", nullptr, this, outUpVec);
|
||||
}
|
||||
Vector3* IBaseCamera::GetLeftVector(Vector3* outLeftVec) {
|
||||
return Utils::Memory::SafeCallFunction<Vector3*>("engine_x64_rwdi.dll", "?GetLeftVector@IBaseCamera@@QEBA?BVvec3@@XZ", nullptr, this, outLeftVec);
|
||||
Vec3* IBaseCamera::GetLeftVector(Vec3* outLeftVec) {
|
||||
return Utils::Memory::SafeCallFunction<Vec3*>("engine_x64_rwdi.dll", "?GetLeftVector@IBaseCamera@@QEBA?BVvec3@@XZ", nullptr, this, outLeftVec);
|
||||
}
|
||||
Vector3* IBaseCamera::GetPosition(Vector3* outPos) {
|
||||
return Utils::Memory::SafeCallFunction<Vector3*>("engine_x64_rwdi.dll", "?GetPosition@IBaseCamera@@UEBA?BVvec3@@XZ", nullptr, this, outPos);
|
||||
Vec3* IBaseCamera::GetPosition(Vec3* outPos) {
|
||||
return Utils::Memory::SafeCallFunction<Vec3*>("engine_x64_rwdi.dll", "?GetPosition@IBaseCamera@@UEBA?BVvec3@@XZ", nullptr, this, outPos);
|
||||
}
|
||||
CameraMtx* IBaseCamera::GetViewMatrix() {
|
||||
return Utils::Memory::SafeCallFunction<CameraMtx*>("engine_x64_rwdi.dll", "?GetViewMatrix@IBaseCamera@@QEAAAEBVmtx34@@XZ", nullptr, this);
|
||||
}
|
||||
|
||||
void IBaseCamera::SetFOV(float fov) {
|
||||
@ -26,7 +29,10 @@ namespace EGSDK::Engine {
|
||||
Utils::Memory::SafeCallFunctionVoid("engine_x64_rwdi.dll", "?SetFOV@IBaseCamera@@QEAAXM@Z", this, fov);
|
||||
isSetFOVCalledByEGSDK = false;
|
||||
}
|
||||
void IBaseCamera::SetPosition(const Vector3* pos) {
|
||||
void IBaseCamera::SetPosition(const Vec3* pos) {
|
||||
Utils::Memory::SafeCallFunctionVoid("engine_x64_rwdi.dll", "?SetPosition@IBaseCamera@@QEAAXAEBVvec3@@@Z", this, pos);
|
||||
}
|
||||
void IBaseCamera::SetCameraMatrix(const CameraMtx* mtx) {
|
||||
Utils::Memory::SafeCallFunctionVoid("engine_x64_rwdi.dll", "?SetCameraMatrix@IBaseCamera@@QEAAXAEBVmtx34@@@Z", this, mtx);
|
||||
}
|
||||
}
|
64
EGameSDK/src/Mtx34.cpp
Normal file
64
EGameSDK/src/Mtx34.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include <EGSDK\Mtx34.h>
|
||||
|
||||
namespace EGSDK {
|
||||
Mtx34::Mtx34() : XAxis(1.0f, 0.0f, 0.0f), YAxis(0.0f, 1.0f, 0.0f), ZAxis(0.0f, 0.0f, 1.0f), Position(0.0f, 0.0f, 0.0f) {}
|
||||
Mtx34::Mtx34(const Vec3& XAxis, const Vec3& YAxis, const Vec3& ZAxis, const Vec3& Pos) : XAxis(XAxis), YAxis(YAxis), ZAxis(ZAxis), Position(Pos) {}
|
||||
|
||||
bool Mtx34::operator==(const Mtx34& m) const {
|
||||
return XAxis == m.XAxis && YAxis == m.YAxis && ZAxis == m.ZAxis && Position == m.Position;
|
||||
}
|
||||
Mtx34& Mtx34::operator+=(const Mtx34& m) {
|
||||
XAxis += m.XAxis;
|
||||
YAxis += m.YAxis;
|
||||
ZAxis += m.ZAxis;
|
||||
Position += m.Position;
|
||||
return *this;
|
||||
}
|
||||
Mtx34& Mtx34::operator-=(const Mtx34& m) {
|
||||
XAxis -= m.XAxis;
|
||||
YAxis -= m.YAxis;
|
||||
ZAxis -= m.ZAxis;
|
||||
Position -= m.Position;
|
||||
return *this;
|
||||
}
|
||||
Mtx34 Mtx34::operator+(const Mtx34& m) const {
|
||||
return { XAxis + m.XAxis, YAxis + m.YAxis, ZAxis + m.ZAxis, Position + m.Position };
|
||||
}
|
||||
Mtx34 Mtx34::operator-(const Mtx34& m) const {
|
||||
return { XAxis - m.XAxis, YAxis - m.YAxis, ZAxis - m.ZAxis, Position - m.Position };
|
||||
}
|
||||
Mtx34 Mtx34::operator*(const Mtx34& scalar) const {
|
||||
return { XAxis * scalar.XAxis, YAxis * scalar.YAxis, ZAxis * scalar.ZAxis, Position * scalar.Position };
|
||||
}
|
||||
Mtx34 Mtx34::operator/(const Mtx34& scalar) const {
|
||||
return { XAxis / scalar.XAxis, YAxis / scalar.YAxis, ZAxis / scalar.ZAxis, Position / scalar.Position };
|
||||
}
|
||||
Mtx34 Mtx34::operator*(const Vec3& scalar) const {
|
||||
return { XAxis * scalar, YAxis * scalar, ZAxis * scalar, Position * scalar };
|
||||
}
|
||||
Mtx34 Mtx34::operator/(const Vec3& scalar) const {
|
||||
return { XAxis / scalar, YAxis / scalar, ZAxis / scalar, Position / scalar };
|
||||
}
|
||||
|
||||
Vec3 Mtx34::TransformPosition(const Vec3& v) const {
|
||||
return {
|
||||
XAxis.X * v.X + YAxis.X * v.Y + ZAxis.X * v.Z + Position.X,
|
||||
XAxis.Y * v.X + YAxis.Y * v.Y + ZAxis.Y * v.Z + Position.Y,
|
||||
XAxis.Z * v.X + YAxis.Z * v.Y + ZAxis.Z * v.Z + Position.Z
|
||||
};
|
||||
}
|
||||
void Mtx34::Normalize() {
|
||||
XAxis = XAxis.normalize();
|
||||
YAxis = YAxis.normalize();
|
||||
ZAxis = ZAxis.normalize();
|
||||
}
|
||||
|
||||
Mtx34 Mtx34::TransposeRotation() const {
|
||||
return Mtx34(
|
||||
Vec3(XAxis.X, YAxis.X, ZAxis.X),
|
||||
Vec3(XAxis.Y, YAxis.Y, ZAxis.Y),
|
||||
Vec3(XAxis.Z, YAxis.Z, ZAxis.Z),
|
||||
Position
|
||||
);
|
||||
}
|
||||
}
|
@ -1,60 +1,66 @@
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#include <EGSDK\Vector3.h>
|
||||
#include <EGSDK\Vec3.h>
|
||||
#include <EGSDK\Utils\Values.h>
|
||||
|
||||
namespace EGSDK {
|
||||
Vector3::Vector3() : X(0.0f), Y(0.0f), Z(0.0f) {}
|
||||
Vector3::Vector3(float x, float y, float z) : X(x), Y(y), Z(z) {}
|
||||
Vec3::Vec3() : X(0.0f), Y(0.0f), Z(0.0f) {}
|
||||
Vec3::Vec3(float x, float y, float z) : X(x), Y(y), Z(z) {}
|
||||
|
||||
bool Vector3::operator==(const Vector3& v) const {
|
||||
bool Vec3::operator==(const Vec3& v) const {
|
||||
return Utils::Values::are_samef(X, v.X) && Utils::Values::are_samef(Y, v.Y) && Utils::Values::are_samef(Z, v.Z);
|
||||
}
|
||||
Vector3& Vector3::operator+=(const Vector3& v) {
|
||||
Vec3& Vec3::operator+=(const Vec3& v) {
|
||||
X += v.X;
|
||||
Y += v.Y;
|
||||
Z += v.Z;
|
||||
return *this;
|
||||
}
|
||||
Vector3& Vector3::operator-=(const Vector3& v) {
|
||||
Vec3& Vec3::operator-=(const Vec3& v) {
|
||||
X -= v.X;
|
||||
Y -= v.Y;
|
||||
Z -= v.Z;
|
||||
return *this;
|
||||
}
|
||||
Vector3 Vector3::operator+(const Vector3& v) const {
|
||||
Vec3 Vec3::operator+(const Vec3& v) const {
|
||||
return { X + v.X, Y + v.Y, Z + v.Z };
|
||||
}
|
||||
Vector3 Vector3::operator-(const Vector3& v) const {
|
||||
Vec3 Vec3::operator-(const Vec3& v) const {
|
||||
return { X - v.X, Y - v.Y, Z - v.Z };
|
||||
}
|
||||
Vector3 Vector3::operator*(float scalar) const {
|
||||
Vec3 Vec3::operator*(const Vec3& scalar) const {
|
||||
return { X * scalar.X, Y * scalar.Y, Z * scalar.Z };
|
||||
}
|
||||
Vec3 Vec3::operator/(const Vec3& scalar) const {
|
||||
return { X / scalar.X, Y / scalar.Y, Z / scalar.Z };
|
||||
}
|
||||
Vec3 Vec3::operator*(float scalar) const {
|
||||
return { X * scalar, Y * scalar, Z * scalar };
|
||||
}
|
||||
Vector3 Vector3::operator/(float scalar) const {
|
||||
Vec3 Vec3::operator/(float scalar) const {
|
||||
return { X / scalar, Y / scalar, Z / scalar };
|
||||
}
|
||||
|
||||
Vector3 Vector3::normalize() {
|
||||
Vec3 Vec3::normalize() {
|
||||
float length = std::sqrt(X * X + Y * Y + Z * Z);
|
||||
return { X / length, Y / length, Z / length };
|
||||
}
|
||||
Vector3 Vector3::cross(const Vector3& v) const {
|
||||
Vec3 Vec3::cross(const Vec3& v) const {
|
||||
return {
|
||||
Y * v.Z - Z * v.Y,
|
||||
Z * v.X - X * v.Z,
|
||||
X * v.Y - Y * v.X
|
||||
};
|
||||
}
|
||||
Vector3 Vector3::round() {
|
||||
Vec3 Vec3::round() {
|
||||
return { std::roundf(X), std::roundf(Y), std::roundf(Z) };
|
||||
}
|
||||
Vector3 Vector3::round(int decimals) {
|
||||
Vec3 Vec3::round(int decimals) {
|
||||
float power = std::powf(10.0f, static_cast<float>(decimals));
|
||||
return { std::roundf(X * power) / power, std::roundf(Y * power) / power, std::roundf(Z * power) / power };
|
||||
}
|
||||
|
||||
bool Vector3::isDefault() const {
|
||||
bool Vec3::isDefault() const {
|
||||
return Utils::Values::are_samef(X, 0.0f) && Utils::Values::are_samef(Y, 0.0f) && Utils::Values::are_samef(Z, 0.0f);
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommand>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2 E3 Definitive\ph\work\bin\x64\DyingLightGame_x64_rwdi.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerWorkingDirectory>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2 E3 Definitive\ph\work\bin\x64</LocalDebuggerWorkingDirectory>
|
||||
<LocalDebuggerCommand>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2\ph\work\bin\x64\DyingLightGame_x64_rwdi.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerWorkingDirectory>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2\ph\work\bin\x64</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerAttach>false</LocalDebuggerAttach>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerCommand>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2 E3 Definitive\ph\work\bin\x64\DyingLightGame_x64_rwdi.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerWorkingDirectory>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2 E3 Definitive\ph\work\bin\x64</LocalDebuggerWorkingDirectory>
|
||||
<LocalDebuggerCommand>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2\ph\work\bin\x64\DyingLightGame_x64_rwdi.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerWorkingDirectory>D:\Program Files (x86)\Steam\steamapps\common\Dying Light 2\ph\work\bin\x64</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerAttach>false</LocalDebuggerAttach>
|
||||
</PropertyGroup>
|
||||
|
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <EGSDK\Vector3.h>
|
||||
#include <EGSDK\Vec3.h>
|
||||
#include <EGSDK\Utils\Hook.h>
|
||||
|
||||
namespace EGT::Engine {
|
||||
namespace Hooks {
|
||||
extern bool switchedFreeCamByGamePause;
|
||||
extern EGSDK::Vector3 freeCamPosBeforeGamePause;
|
||||
extern EGSDK::Vec3 freeCamPosBeforeGamePause;
|
||||
extern int mountDataPaksRanWith8Count;
|
||||
|
||||
extern EGSDK::Utils::Hook::MHook<void*, DWORD64(*)(DWORD64, DWORD, DWORD), DWORD64, DWORD, DWORD> FsOpenHook;
|
||||
|
@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
#include <EGSDK\Vector3.h>
|
||||
#include <EGSDK\Vec3.h>
|
||||
#include <EGT\Core\Core.h>
|
||||
#include <EGT\Menu\Menu.h>
|
||||
|
||||
namespace EGT::Menu {
|
||||
namespace Camera {
|
||||
extern EGSDK::Vector3 cameraOffset;
|
||||
extern EGSDK::Vec3 cameraOffset;
|
||||
extern float firstPersonFOV;
|
||||
extern float originalFirstPersonFOVAfterZoomIn;
|
||||
extern ImGui::KeyBindOption firstPersonZoomIn;
|
||||
|
@ -1,19 +1,19 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <EGT\Menu\Menu.h>
|
||||
#include <EGSDK\Vector3.h>
|
||||
#include <EGSDK\Vec3.h>
|
||||
|
||||
namespace EGT::Menu {
|
||||
namespace Teleport {
|
||||
struct TeleportLocation {
|
||||
std::string name{};
|
||||
EGSDK::Vector3 pos{};
|
||||
EGSDK::Vec3 pos{};
|
||||
};
|
||||
|
||||
extern std::string savedTeleportLocationsStr;
|
||||
extern std::vector<TeleportLocation> savedTeleportLocations;
|
||||
|
||||
extern EGSDK::Vector3 waypointCoords;
|
||||
extern EGSDK::Vec3 waypointCoords;
|
||||
extern bool* waypointIsSet;
|
||||
extern bool justTeleportedToWaypoint;
|
||||
|
||||
|
@ -14,9 +14,9 @@ namespace EGT::Engine {
|
||||
namespace Hooks {
|
||||
#pragma region MoveCameraFromForwardUpPos
|
||||
bool switchedFreeCamByGamePause = false;
|
||||
EGSDK::Vector3 freeCamPosBeforeGamePause{};
|
||||
EGSDK::Vec3 freeCamPosBeforeGamePause{};
|
||||
|
||||
static EGSDK::Utils::Hook::MHook<void*, void(*)(void*, float*, float*, EGSDK::Vector3*), void*, float*, float*, EGSDK::Vector3*> MoveCameraFromForwardUpPosHook{ "MoveCameraFromForwardUpPos", &EGSDK::OffsetManager::Get_MoveCameraFromForwardUpPos, [](void* pCBaseCamera, float* a3, float* a4, EGSDK::Vector3* pos) -> void {
|
||||
static EGSDK::Utils::Hook::MHook<void*, void(*)(void*, float*, float*, EGSDK::Vec3*), void*, float*, float*, EGSDK::Vec3*> MoveCameraFromForwardUpPosHook{ "MoveCameraFromForwardUpPos", &EGSDK::OffsetManager::Get_MoveCameraFromForwardUpPos, [](void* pCBaseCamera, float* a3, float* a4, EGSDK::Vec3* pos) -> void {
|
||||
auto iLevel = EGSDK::GamePH::LevelDI::Get();
|
||||
if (!iLevel || !iLevel->IsLoaded() || iLevel->IsTimerFrozen())
|
||||
return MoveCameraFromForwardUpPosHook.ExecuteCallbacksWithOriginal(pCBaseCamera, a3, a4, pos);
|
||||
@ -35,7 +35,7 @@ namespace EGT::Engine {
|
||||
if (!viewCam)
|
||||
return MoveCameraFromForwardUpPosHook.ExecuteCallbacksWithOriginal(pCBaseCamera, a3, a4, pos);
|
||||
|
||||
EGSDK::Vector3 forwardVec, upVec, leftVec = {};
|
||||
EGSDK::Vec3 forwardVec, upVec, leftVec = {};
|
||||
viewCam->GetForwardVector(&forwardVec);
|
||||
viewCam->GetUpVector(&upVec);
|
||||
viewCam->GetLeftVector(&leftVec);
|
||||
@ -44,7 +44,7 @@ namespace EGT::Engine {
|
||||
const auto normUpVec = upVec.normalize();
|
||||
const auto normLeftVec = leftVec.normalize();
|
||||
|
||||
EGSDK::Vector3 newCamPos = *pos;
|
||||
EGSDK::Vec3 newCamPos = *pos;
|
||||
|
||||
if (!Menu::Camera::cameraOffset.isDefault() && !Menu::Camera::thirdPersonCamera.GetValue()) {
|
||||
newCamPos -= normLeftVec * Menu::Camera::cameraOffset.X;
|
||||
|
@ -196,7 +196,7 @@ namespace EGT::GamePH {
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SetNewWaypointLocation
|
||||
static EGSDK::Utils::Hook::MHook<void*, uint64_t(*)(uint64_t, int, EGSDK::Vector3*), uint64_t, int, EGSDK::Vector3*> SetNewWaypointLocationHook{ "SetNewWaypointLocation", &EGSDK::OffsetManager::Get_SetNewWaypointLocation, [](uint64_t pLogicalPlayer, int a2, EGSDK::Vector3* newWaypointLoc) -> uint64_t {
|
||||
static EGSDK::Utils::Hook::MHook<void*, uint64_t(*)(uint64_t, int, EGSDK::Vec3*), uint64_t, int, EGSDK::Vec3*> SetNewWaypointLocationHook{ "SetNewWaypointLocation", &EGSDK::OffsetManager::Get_SetNewWaypointLocation, [](uint64_t pLogicalPlayer, int a2, EGSDK::Vec3* newWaypointLoc) -> uint64_t {
|
||||
uint64_t result = SetNewWaypointLocationHook.ExecuteCallbacksWithOriginal(pLogicalPlayer, a2, newWaypointLoc);
|
||||
Menu::Teleport::waypointCoords = *newWaypointLoc;
|
||||
if (EGSDK::OffsetManager::Get_SetNewWaypointLocationWaypointIsSetBoolInstr()) {
|
||||
|
@ -15,11 +15,11 @@
|
||||
|
||||
namespace EGT::Menu {
|
||||
namespace Camera {
|
||||
static float baseFOV = 57;
|
||||
static float baseFOV = 0.0f;
|
||||
static constexpr float baseSafezoneFOVReduction = -10.0f;
|
||||
static constexpr float baseSprintHeadCorrectionFactor = 0.55f;
|
||||
|
||||
EGSDK::Vector3 cameraOffset{};
|
||||
EGSDK::Vec3 cameraOffset{};
|
||||
float firstPersonFOV = baseFOV;
|
||||
float originalFirstPersonFOVAfterZoomIn = firstPersonFOV;
|
||||
ImGui::KeyBindOption firstPersonZoomIn{ 'Q' , false };
|
||||
@ -46,15 +46,38 @@ namespace EGT::Menu {
|
||||
ImGui::KeyBindOption disablePhotoModeLimits{ VK_NONE };
|
||||
ImGui::KeyBindOption disableHeadCorrection{ VK_NONE };
|
||||
|
||||
static void CalculateBaseFOV() {
|
||||
if (!EGSDK::Utils::Values::are_samef(baseFOV, 0.0f))
|
||||
return;
|
||||
|
||||
auto pCVideoSettings = EGSDK::Engine::CVideoSettings::Get();
|
||||
if (!pCVideoSettings)
|
||||
return;
|
||||
auto iLevel = EGSDK::GamePH::LevelDI::Get();
|
||||
if (!iLevel || !iLevel->IsLoaded())
|
||||
return;
|
||||
auto viewCam = reinterpret_cast<EGSDK::Engine::CBaseCamera*>(iLevel->GetViewCamera());
|
||||
if (!viewCam)
|
||||
return;
|
||||
|
||||
baseFOV = std::roundf(viewCam->GetFOV() - pCVideoSettings->extraFOV);
|
||||
firstPersonFOV = baseFOV;
|
||||
if (EGSDK::Utils::Values::are_samef(thirdPersonFOV, 0.0f))
|
||||
thirdPersonFOV = baseFOV;
|
||||
if (EGSDK::Utils::Values::are_samef(freeCamFOV, 0.0f))
|
||||
freeCamFOV = baseFOV;
|
||||
}
|
||||
static void UpdateFirstPersonFOV() {
|
||||
auto iLevel = EGSDK::GamePH::LevelDI::Get();
|
||||
auto viewCam = iLevel ? reinterpret_cast<EGSDK::Engine::CBaseCamera*>(iLevel->GetViewCamera()) : nullptr;
|
||||
auto viewCam = iLevel && iLevel->IsLoaded() ? reinterpret_cast<EGSDK::Engine::CBaseCamera*>(iLevel->GetViewCamera()) : nullptr;
|
||||
|
||||
static float previousFirstPersonFOV = firstPersonFOV;
|
||||
static bool hasChangedZoomLevel = false;
|
||||
static int zoomLevel = 0;
|
||||
|
||||
if (iLevel && viewCam) {
|
||||
if (iLevel && iLevel->IsLoaded() && viewCam) {
|
||||
auto shit = viewCam->GetViewMatrix();
|
||||
|
||||
if (goProMode.GetValue()) {
|
||||
if (goProMode.HasChangedTo(true)) {
|
||||
previousFirstPersonFOV = firstPersonFOV;
|
||||
@ -71,7 +94,7 @@ namespace EGT::Menu {
|
||||
}
|
||||
}
|
||||
|
||||
if (iLevel && viewCam && !thirdPersonCamera.GetValue() && !freeCam.GetValue()) {
|
||||
if (iLevel && iLevel->IsLoaded() && viewCam && !thirdPersonCamera.GetValue() && !freeCam.GetValue()) {
|
||||
if (firstPersonZoomIn.IsKeyDown()) {
|
||||
if (firstPersonZoomIn.IsKeyPressed()) {
|
||||
hasChangedZoomLevel = true;
|
||||
@ -128,8 +151,8 @@ namespace EGT::Menu {
|
||||
}
|
||||
|
||||
auto videoSettings = EGSDK::Engine::CVideoSettings::Get();
|
||||
if (videoSettings && !goProMode.GetValue() && !menuToggle.GetValue() && !isZoomingIn)
|
||||
firstPersonFOV = static_cast<int>(videoSettings->extraFOV) + baseFOV;
|
||||
if (videoSettings && !EGSDK::Utils::Values::are_samef(baseFOV, 0.0f) && !goProMode.GetValue() && !menuToggle.GetValue() && !isZoomingIn)
|
||||
firstPersonFOV = videoSettings->extraFOV + baseFOV;
|
||||
}
|
||||
static void FreeCamUpdate() {
|
||||
if (photoMode.GetValue())
|
||||
@ -166,7 +189,7 @@ namespace EGT::Menu {
|
||||
}
|
||||
|
||||
pFreeCam->speedMultiplier = freeCamSpeed;
|
||||
pFreeCam->SetFOV(static_cast<float>(freeCamFOV));
|
||||
pFreeCam->SetFOV(freeCamFOV);
|
||||
|
||||
if (ImGui::IsKeyDown(ImGuiKey_LeftShift))
|
||||
pFreeCam->speedMultiplier *= 2.0f;
|
||||
@ -258,15 +281,9 @@ namespace EGT::Menu {
|
||||
}
|
||||
|
||||
Tab Tab::instance{};
|
||||
void Tab::Init() {
|
||||
if (EGSDK::Core::gameVer == 11200) {
|
||||
baseFOV = 52;
|
||||
firstPersonFOV = baseFOV;
|
||||
thirdPersonFOV = baseFOV;
|
||||
freeCamFOV = baseFOV;
|
||||
}
|
||||
}
|
||||
void Tab::Init() {}
|
||||
void Tab::Update() {
|
||||
CalculateBaseFOV();
|
||||
UpdateFirstPersonFOV();
|
||||
FreeCamUpdate();
|
||||
UpdateTPPModel();
|
||||
@ -277,10 +294,10 @@ namespace EGT::Menu {
|
||||
void Tab::Render() {
|
||||
ImGui::SeparatorText("First Person Camera");
|
||||
auto pCVideoSettings = EGSDK::Engine::CVideoSettings::Get();
|
||||
ImGui::BeginDisabled(!pCVideoSettings || goProMode.GetValue() || isZoomingIn);
|
||||
ImGui::BeginDisabled(!pCVideoSettings || EGSDK::Utils::Values::are_samef(baseFOV, 0.0f) || goProMode.GetValue() || isZoomingIn);
|
||||
if (ImGui::SliderFloat("FOV##FirstPerson", "First person camera field of view", &firstPersonFOV, 20.0f, 160.0f, "%.0f") && pCVideoSettings)
|
||||
pCVideoSettings->extraFOV = firstPersonFOV - baseFOV;
|
||||
else if (pCVideoSettings && !goProMode.GetValue())
|
||||
else if (pCVideoSettings && !goProMode.GetValue() && !EGSDK::Utils::Values::are_samef(baseFOV, 0.0f))
|
||||
firstPersonFOV = pCVideoSettings->extraFOV + baseFOV;
|
||||
ImGui::EndDisabled();
|
||||
ImGui::BeginDisabled(freeCam.GetChangesAreDisabled());
|
||||
@ -300,7 +317,9 @@ namespace EGT::Menu {
|
||||
ImGui::CheckboxHotkey("Use Third Person Player (TPP) Model", &tpUseTPPModel, "Uses Aiden's TPP (Third Person Player) model while the third person camera is enabled");
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::BeginDisabled(EGSDK::Utils::Values::are_samef(baseFOV, 0.0f));
|
||||
ImGui::SliderFloat("FOV##ThirdPerson", "Third person camera field of view", &thirdPersonFOV, 20.0f, 160.0f, "%.0f");
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SliderFloat("Distance behind player", &thirdPersonDistanceBehindPlayer, 1.0f, 10.0f, "%.2fm");
|
||||
ImGui::SliderFloat("Height above player", &thirdPersonHeightAbovePlayer, 1.0f, 3.0f, "%.2fm");
|
||||
ImGui::SliderFloat("Horizontal distance from player", &thirdPersonHorizontalDistanceFromPlayer, -2.0f, 2.0f, "%.2fm");
|
||||
@ -316,7 +335,9 @@ namespace EGT::Menu {
|
||||
ImGui::CheckboxHotkey("Teleport Player to Camera", &teleportPlayerToCamera, "Teleports the player to the camera while Free Camera is activated");
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::BeginDisabled(EGSDK::Utils::Values::are_samef(baseFOV, 0.0f));
|
||||
ImGui::SliderFloat("FOV##FreeCam", "Free camera field of view", &freeCamFOV, 20.0f, 160.0f, "%.0f");
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SliderFloat("Speed##FreeCam", &freeCamSpeed, 0.1f, 200.0f, "%.2fx", ImGuiSliderFlags_AlwaysClamp);
|
||||
|
||||
ImGui::SeparatorText("Misc");
|
||||
|
@ -405,7 +405,7 @@ namespace EGT::Menu {
|
||||
if (!freeCam)
|
||||
return;
|
||||
|
||||
EGSDK::Vector3 camPos{};
|
||||
EGSDK::Vec3 camPos{};
|
||||
freeCam->GetPosition(&camPos);
|
||||
if (!camPos.isDefault())
|
||||
playerCharacter->MoveCharacter(camPos);
|
||||
|
@ -17,10 +17,10 @@ namespace EGT::Menu {
|
||||
static int selectedTPLocation = -1;
|
||||
static char newLocationName[125]{};
|
||||
|
||||
EGSDK::Vector3 waypointCoords{};
|
||||
EGSDK::Vec3 waypointCoords{};
|
||||
bool* waypointIsSet = nullptr;
|
||||
bool justTeleportedToWaypoint = false;
|
||||
static EGSDK::Vector3 teleportCoords{};
|
||||
static EGSDK::Vec3 teleportCoords{};
|
||||
|
||||
ImGui::KeyBindOption teleportToSelectedLocation{ VK_F9 };
|
||||
ImGui::KeyBindOption teleportToCoords{ VK_NONE };
|
||||
@ -91,7 +91,7 @@ namespace EGT::Menu {
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
static std::string GetFormattedPosition(const EGSDK::Vector3* position) {
|
||||
static std::string GetFormattedPosition(const EGSDK::Vec3* position) {
|
||||
if (!position || position->isDefault())
|
||||
return "X: 0.00, Y: 0.00, Z: 0.00";
|
||||
static std::string formattedStr{};
|
||||
@ -125,7 +125,7 @@ namespace EGT::Menu {
|
||||
teleportCoords = playerCharacter->playerPos;
|
||||
}
|
||||
}
|
||||
static bool TeleportPlayerTo(const EGSDK::Vector3& pos) {
|
||||
static bool TeleportPlayerTo(const EGSDK::Vec3& pos) {
|
||||
if (isTeleportationDisabled() || pos.isDefault())
|
||||
return false;
|
||||
|
||||
@ -202,7 +202,7 @@ namespace EGT::Menu {
|
||||
return false;
|
||||
}
|
||||
|
||||
EGSDK::Vector3 playerPos{};
|
||||
EGSDK::Vec3 playerPos{};
|
||||
|
||||
if (Camera::freeCam.GetValue()) {
|
||||
EGSDK::GamePH::FreeCamera* freeCam = EGSDK::GamePH::FreeCamera::Get();
|
||||
@ -213,7 +213,7 @@ namespace EGT::Menu {
|
||||
return false;
|
||||
}
|
||||
|
||||
EGSDK::Vector3 camPos{};
|
||||
EGSDK::Vec3 camPos{};
|
||||
freeCam->GetPosition(&camPos);
|
||||
if (camPos.isDefault()) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
@ -307,7 +307,7 @@ namespace EGT::Menu {
|
||||
auto playerCharacter = EGSDK::Engine::CBulletPhysicsCharacter::Get();
|
||||
auto freeCam = EGSDK::GamePH::FreeCamera::Get();
|
||||
|
||||
EGSDK::Vector3 camPos{};
|
||||
EGSDK::Vec3 camPos{};
|
||||
ImGui::Text("Player Position: %s", GetFormattedPosition(playerCharacter ? &*playerCharacter->playerPos.getPointer() : nullptr).data());
|
||||
ImGui::Text("Free Camera Position: %s", GetFormattedPosition(freeCam && Camera::freeCam.GetValue() ? freeCam->GetPosition(&camPos) : nullptr).data());
|
||||
ImGui::Text("Waypoint Position: %s", GetFormattedPosition(waypointIsSet && *waypointIsSet && !waypointCoords.isDefault() ? &waypointCoords : nullptr).data());
|
||||
|
@ -130,7 +130,8 @@ namespace EGT::Menu {
|
||||
timeWeather->blendTime2 = 1.0f;
|
||||
if (!EGSDK::Utils::Memory::IsBadReadPtr(timeWeather->nextSubSystem))
|
||||
timeWeather->nextSubSystem->blendTime = 1.0f;
|
||||
}
|
||||
} else if (!EGSDK::Utils::Memory::IsBadReadPtr(timeWeather->nextSubSystem) && !EGSDK::Utils::Values::are_samef(timeWeather->nextSubSystem->blendTime, 1.0f))
|
||||
timeWeather->nextSubSystem->blendTime = 1.0f;
|
||||
} else {
|
||||
timeWeather->blendTime = previousBlendTime;
|
||||
timeWeather->blendTime2 = previousBlendTime2;
|
||||
@ -162,7 +163,6 @@ namespace EGT::Menu {
|
||||
if (timeSlider) {
|
||||
requestedTimeWeatherInterpolation = true;
|
||||
timeBeforeFreeze = time;
|
||||
//UpdateWeatherInterpolation();
|
||||
dayNightCycle->SetDaytime(time);
|
||||
}
|
||||
|
||||
@ -186,7 +186,6 @@ namespace EGT::Menu {
|
||||
ImGui::BeginDisabled(weatherDisabledFlag);
|
||||
if (ImGui::Combo("Weather", reinterpret_cast<int*>(&weather), weatherItems, IM_ARRAYSIZE(weatherItems))) {
|
||||
requestedTimeWeatherInterpolation = true;
|
||||
//UpdateWeatherInterpolation();
|
||||
timeWeatherSystem->SetForcedWeather(static_cast<EGSDK::GamePH::TimeWeather::EWeather>(weather - 1));
|
||||
}
|
||||
ImGui::Text("Current weather: %s", !weatherDisabledFlag ? weatherItems[timeWeatherSystem->GetCurrentWeather() + 1] : "");
|
||||
|
Reference in New Issue
Block a user