Refactor MouseControlCheat
- Split ModMenuModule::MouseControlCheat into multiple smaller subclasses called workers
This commit is contained in:
parent
7d755b4314
commit
f054d9c5ae
@ -647,7 +647,13 @@ echo Created $(ProjectDir)src\git.h with commit %GIT_HASH% (dirty=%GIT_DIRTY%)
|
||||
<ClInclude Include="src\modules\modmenu\cheats\invulnerability.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\force-controls.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\last-car.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\left-right-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\mouse-control-worker-registry.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\mouse-control-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\mouse-control.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\point-at-mouse-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\locked-mouse-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\attack-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\native-cheats-keeper.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\player-appearance.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\player-pos.h" />
|
||||
@ -890,7 +896,12 @@ echo Created $(ProjectDir)src\git.h with commit %GIT_HASH% (dirty=%GIT_DIRTY%)
|
||||
<ClCompile Include="src\modules\modmenu\cheats\invulnerability.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\force-controls.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\last-car.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\attack-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\left-right-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\mouse-control-worker-registry.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\mouse-control.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\point-at-mouse-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\locked-mouse-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\native-cheats-keeper.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\player-appearance.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\player-pos.cpp" />
|
||||
|
||||
@ -172,6 +172,11 @@
|
||||
<ClCompile Include="src\modules\modmenu\quick-actions\toggle-steering-assist.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\camera\freecam.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\mouse-control.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\locked-mouse-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\point-at-mouse-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\attack-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\left-right-worker.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\cheats\mouse-control\mouse-control-worker-registry.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\converters\ammo.h" />
|
||||
@ -460,6 +465,12 @@
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\toggle-steering-assist.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\camera\freecam.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\mouse-control.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\mouse-control-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\locked-mouse-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\point-at-mouse-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\attack-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\left-right-worker.h" />
|
||||
<ClInclude Include="src\modules\modmenu\cheats\mouse-control\mouse-control-worker-registry.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="GTA2.props" />
|
||||
|
||||
81
src/modules/modmenu/cheats/mouse-control/attack-worker.cpp
Normal file
81
src/modules/modmenu/cheats/mouse-control/attack-worker.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "attack-worker.h"
|
||||
#include "mouse-control.h"
|
||||
#include "../../common.h"
|
||||
|
||||
static constexpr size_t ATTACK_CONTROL_INDEX = Game::Utils::GetControlIndex(Game::KEYBOARD_STATE_ATTACK);
|
||||
|
||||
void ModMenuModule::AttackWorker::Start()
|
||||
{
|
||||
spdlog::debug("AttackWorker: Starting");
|
||||
|
||||
if (!CreateControlHandle()) return;
|
||||
AddEventListener<MouseModule::MouseButtonDownEvent>(&AttackWorker::OnMouseButtonDown);
|
||||
AddEventListener<MouseModule::MouseButtonUpEvent>(&AttackWorker::OnMouseButtonUp);
|
||||
m_running = true;
|
||||
|
||||
ForceUpdate();
|
||||
}
|
||||
|
||||
void ModMenuModule::AttackWorker::Stop()
|
||||
{
|
||||
spdlog::debug("AttackWorker: Stopping");
|
||||
|
||||
RemoveEventListener<MouseModule::MouseButtonDownEvent>();
|
||||
RemoveEventListener<MouseModule::MouseButtonUpEvent>();
|
||||
FreeControlHandle();
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void ModMenuModule::AttackWorker::OnMouseButtonDown(MouseModule::MouseButtonDownEvent& event)
|
||||
{
|
||||
if (event.GetButton() != MouseModule::MouseButton::Left) return;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, ForceControlState::ForceDown);
|
||||
}
|
||||
|
||||
void ModMenuModule::AttackWorker::OnMouseButtonUp(MouseModule::MouseButtonUpEvent & event)
|
||||
{
|
||||
if (event.GetButton() != MouseModule::MouseButton::Left) return;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, ForceControlState::Unmodified);
|
||||
}
|
||||
|
||||
bool ModMenuModule::AttackWorker::CreateControlHandle()
|
||||
{
|
||||
if (ForceControlsCheat::CheckUsesGamepad(ATTACK_CONTROL_INDEX)) {
|
||||
spdlog::error("AttackWorker: cannot create control handle for attack control because it is used by gamepad controls");
|
||||
MouseControlCheat::GetInstance()->ShowGamepadControlsToast();
|
||||
return false;
|
||||
}
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
|
||||
m_attackControlHandle = forceControlsCheat->CreateControlHandle(ATTACK_CONTROL_INDEX);
|
||||
if (m_attackControlHandle == -1) {
|
||||
spdlog::error("AttackWorker: failed to create control handle for the control: attack");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModMenuModule::AttackWorker::FreeControlHandle()
|
||||
{
|
||||
if (m_attackControlHandle == -1) return;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, ForceControlState::Unmodified);
|
||||
forceControlsCheat->FreeControlHandle(m_attackControlHandle);
|
||||
m_attackControlHandle = -1;
|
||||
}
|
||||
|
||||
void ModMenuModule::AttackWorker::ForceUpdate() const
|
||||
{
|
||||
MouseModule::MouseState mouseState = MouseModule::MouseManager::FetchMouseState();
|
||||
bool shouldAttack = mouseState.leftButtonDown;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, shouldAttack ? ForceControlState::ForceDown : ForceControlState::Unmodified);
|
||||
}
|
||||
28
src/modules/modmenu/cheats/mouse-control/attack-worker.h
Normal file
28
src/modules/modmenu/cheats/mouse-control/attack-worker.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "mouse-control-worker.h"
|
||||
#include "../force-controls.h"
|
||||
|
||||
namespace ModMenuModule {
|
||||
class AttackWorker : public MouseControlWorker, public Core::EventListenerSupport {
|
||||
public:
|
||||
AttackWorker() = default;
|
||||
AttackWorker(const AttackWorker&) = delete;
|
||||
AttackWorker& operator=(const AttackWorker&) = delete;
|
||||
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
bool IsRunning() const override { return m_running; }
|
||||
|
||||
private:
|
||||
void OnMouseButtonDown(MouseModule::MouseButtonDownEvent& event);
|
||||
void OnMouseButtonUp(MouseModule::MouseButtonUpEvent& event);
|
||||
|
||||
bool CreateControlHandle();
|
||||
void FreeControlHandle();
|
||||
|
||||
void ForceUpdate() const;
|
||||
|
||||
bool m_running = false;
|
||||
ForceControlsCheat::ControlHandle m_attackControlHandle = -1;
|
||||
};
|
||||
}
|
||||
100
src/modules/modmenu/cheats/mouse-control/left-right-worker.cpp
Normal file
100
src/modules/modmenu/cheats/mouse-control/left-right-worker.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include "left-right-worker.h"
|
||||
#include "mouse-control.h"
|
||||
#include "../../common.h"
|
||||
|
||||
static constexpr float LEFT_RIGHT_INPUT_THRESHOLD = 0.15f;
|
||||
static constexpr float LEFT_RIGHT_DELTA_DECLINE = 0.20943928f;
|
||||
|
||||
static constexpr size_t LEFT_CONTROL_INDEX = Game::Utils::GetControlIndex(Game::KEYBOARD_STATE_LEFT);
|
||||
static constexpr size_t RIGHT_CONTROL_INDEX = Game::Utils::GetControlIndex(Game::KEYBOARD_STATE_RIGHT);
|
||||
|
||||
void ModMenuModule::LeftRightWorker::Start()
|
||||
{
|
||||
spdlog::debug("LeftRightWorker: Starting");
|
||||
|
||||
if (!CreateControlHandles()) return;
|
||||
|
||||
MouseControlCheat* mouseControlCheat = MouseControlCheat::GetInstance();
|
||||
mouseControlCheat->SetDeltaX(0.0f);
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
void ModMenuModule::LeftRightWorker::Stop()
|
||||
{
|
||||
spdlog::debug("LeftRightWorker: Stopping");
|
||||
|
||||
FreeControlHandles();
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void ModMenuModule::LeftRightWorker::Update()
|
||||
{
|
||||
MouseControlCheat* mouseControlCheat = MouseControlCheat::GetInstance();
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
|
||||
float deltaX = mouseControlCheat->GetDeltaX();
|
||||
char direction = GetDirection(deltaX);
|
||||
bool shouldPressLeft = direction < 0;
|
||||
bool shouldPressRight = direction > 0;
|
||||
|
||||
forceControlsCheat->SetControlState(m_leftControlHandle, shouldPressLeft ? ForceControlState::ForceDown : ForceControlState::ForceUp);
|
||||
forceControlsCheat->SetControlState(m_rightControlHandle, shouldPressRight ? ForceControlState::ForceDown : ForceControlState::ForceUp);
|
||||
|
||||
deltaX -= (direction * LEFT_RIGHT_DELTA_DECLINE);
|
||||
mouseControlCheat->SetDeltaX(deltaX);
|
||||
}
|
||||
|
||||
bool ModMenuModule::LeftRightWorker::CreateControlHandles()
|
||||
{
|
||||
bool anyUsesGamepad = ForceControlsCheat::CheckUsesGamepad(LEFT_CONTROL_INDEX)
|
||||
|| ForceControlsCheat::CheckUsesGamepad(RIGHT_CONTROL_INDEX);
|
||||
|
||||
if (anyUsesGamepad) {
|
||||
spdlog::error("LeftRightWorker: cannot create control handle for left/right controls because they are used by gamepad controls");
|
||||
MouseControlCheat::GetInstance()->ShowGamepadControlsToast();
|
||||
return false;
|
||||
}
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
|
||||
m_leftControlHandle = forceControlsCheat->CreateControlHandle(LEFT_CONTROL_INDEX);
|
||||
if (m_leftControlHandle == -1) {
|
||||
spdlog::error("LeftRightWorker: failed to create control handle for the control: left");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rightControlHandle = forceControlsCheat->CreateControlHandle(RIGHT_CONTROL_INDEX);
|
||||
if (m_rightControlHandle == -1) {
|
||||
spdlog::error("LeftRightWorker: failed to create control handle for the control: right");
|
||||
forceControlsCheat->FreeControlHandle(m_leftControlHandle);
|
||||
m_leftControlHandle = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModMenuModule::LeftRightWorker::FreeControlHandles()
|
||||
{
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
|
||||
if (m_leftControlHandle != -1) {
|
||||
forceControlsCheat->SetControlState(m_leftControlHandle, ForceControlState::Unmodified);
|
||||
forceControlsCheat->FreeControlHandle(m_leftControlHandle);
|
||||
m_leftControlHandle = -1;
|
||||
}
|
||||
|
||||
if (m_rightControlHandle != -1) {
|
||||
forceControlsCheat->SetControlState(m_rightControlHandle, ForceControlState::Unmodified);
|
||||
forceControlsCheat->FreeControlHandle(m_rightControlHandle);
|
||||
m_rightControlHandle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
char ModMenuModule::LeftRightWorker::GetDirection(float delta)
|
||||
{
|
||||
if (std::abs(delta) < LEFT_RIGHT_INPUT_THRESHOLD) {
|
||||
return 0;
|
||||
}
|
||||
return delta > 0 ? 1 : -1;
|
||||
}
|
||||
27
src/modules/modmenu/cheats/mouse-control/left-right-worker.h
Normal file
27
src/modules/modmenu/cheats/mouse-control/left-right-worker.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "mouse-control-worker.h"
|
||||
#include "../force-controls.h"
|
||||
|
||||
namespace ModMenuModule {
|
||||
class LeftRightWorker : public MouseControlWorker, public Core::EventListenerSupport {
|
||||
public:
|
||||
LeftRightWorker() = default;
|
||||
LeftRightWorker(const LeftRightWorker&) = delete;
|
||||
LeftRightWorker& operator=(const LeftRightWorker&) = delete;
|
||||
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
bool IsRunning() const override { return m_running; }
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
bool CreateControlHandles();
|
||||
void FreeControlHandles();
|
||||
|
||||
static char GetDirection(float deltaAngle);
|
||||
|
||||
bool m_running = false;
|
||||
ForceControlsCheat::ControlHandle m_leftControlHandle = -1;
|
||||
ForceControlsCheat::ControlHandle m_rightControlHandle = -1;
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
#include "locked-mouse-worker.h"
|
||||
#include "mouse-control.h"
|
||||
#include "../../common.h"
|
||||
|
||||
static constexpr float LOCKED_MOUSE_SMOOTING = 0.2f;
|
||||
|
||||
void ModMenuModule::LockedMouseWorker::Start()
|
||||
{
|
||||
spdlog::debug("LockedMouseWorker: Starting");
|
||||
|
||||
AddEventListener<MouseModule::MouseLockedMoveEvent>(&LockedMouseWorker::OnMouseLockedMove);
|
||||
|
||||
MouseModule::MouseManager* mouseManager = MouseModule::MouseManager::GetInstance();
|
||||
mouseManager->SetLocked(true);
|
||||
mouseManager->SetCursorVisibility(MouseModule::CursorVisibility::ForceInvisible);
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
void ModMenuModule::LockedMouseWorker::Stop()
|
||||
{
|
||||
spdlog::debug("LockedMouseWorker: Stopping");
|
||||
|
||||
RemoveEventListener<MouseModule::MouseLockedMoveEvent>();
|
||||
|
||||
MouseModule::MouseManager* mouseManager = MouseModule::MouseManager::GetInstance();
|
||||
mouseManager->SetLocked(false);
|
||||
mouseManager->SetCursorVisibility(MouseModule::CursorVisibility::Unmodified);
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void ModMenuModule::LockedMouseWorker::Update()
|
||||
{
|
||||
MouseControlCheat* mouseControlCheat = MouseControlCheat::GetInstance();
|
||||
float deltaX = mouseControlCheat->GetDeltaX();
|
||||
float deltaY = mouseControlCheat->GetDeltaY();
|
||||
|
||||
deltaX *= (1.0f - LOCKED_MOUSE_SMOOTING);
|
||||
deltaY *= (1.0f - LOCKED_MOUSE_SMOOTING);
|
||||
|
||||
mouseControlCheat->SetDeltaX(deltaX);
|
||||
mouseControlCheat->SetDeltaY(deltaY);
|
||||
}
|
||||
|
||||
void ModMenuModule::LockedMouseWorker::OnMouseLockedMove(MouseModule::MouseLockedMoveEvent& event)
|
||||
{
|
||||
MouseControlCheat* mouseControlCheat = MouseControlCheat::GetInstance();
|
||||
float sensitivity = mouseControlCheat->GetOptions().rotateModeSensitivity;
|
||||
|
||||
float deltaX = mouseControlCheat->GetDeltaX();
|
||||
float deltaY = mouseControlCheat->GetDeltaY();
|
||||
|
||||
deltaX += (event.GetDelta().x * sensitivity);
|
||||
deltaY += (event.GetDelta().y * sensitivity);
|
||||
|
||||
mouseControlCheat->SetDeltaX(deltaX);
|
||||
mouseControlCheat->SetDeltaY(deltaY);
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "mouse-control-worker.h"
|
||||
#include "../force-controls.h"
|
||||
|
||||
namespace ModMenuModule {
|
||||
class LockedMouseWorker : public MouseControlWorker, public Core::EventListenerSupport {
|
||||
public:
|
||||
LockedMouseWorker() = default;
|
||||
LockedMouseWorker(const LockedMouseWorker&) = delete;
|
||||
LockedMouseWorker& operator=(const LockedMouseWorker&) = delete;
|
||||
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
bool IsRunning() const override { return m_running; }
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
void OnMouseLockedMove(MouseModule::MouseLockedMoveEvent& event);
|
||||
|
||||
bool m_running = false;
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
#include "mouse-control-worker.h"
|
||||
#include "attack-worker.h"
|
||||
#include "locked-mouse-worker.h"
|
||||
#include "point-at-mouse-worker.h"
|
||||
#include "left-right-worker.h"
|
||||
#include "mouse-control-worker-registry.h"
|
||||
|
||||
namespace ModMenuModule::MouseControlWorkerRegistry {
|
||||
namespace {
|
||||
using WorkerFactory = std::unique_ptr<MouseControlWorker>(*)();
|
||||
|
||||
template<typename WorkerT>
|
||||
std::unique_ptr<MouseControlWorker> CreateWorkerInstance()
|
||||
{
|
||||
return std::make_unique<WorkerT>();
|
||||
}
|
||||
|
||||
const std::unordered_map<WorkerType, WorkerFactory>& GetWorkerFactories()
|
||||
{
|
||||
static const std::unordered_map<WorkerType, WorkerFactory> factories = {
|
||||
{ GetWorkerType<AttackWorker>(), &CreateWorkerInstance<AttackWorker> },
|
||||
{ GetWorkerType<LockedMouseWorker>(), &CreateWorkerInstance<LockedMouseWorker> },
|
||||
{ GetWorkerType<PointAtMouseWorker>(), &CreateWorkerInstance<PointAtMouseWorker> },
|
||||
{ GetWorkerType<LeftRightWorker>(), &CreateWorkerInstance<LeftRightWorker> },
|
||||
};
|
||||
|
||||
return factories;
|
||||
}
|
||||
|
||||
const std::unordered_map<WorkerSetType, MouseControlWorkerSetDef>& GetWorkerSetDefs()
|
||||
{
|
||||
static const std::unordered_map<WorkerSetType, MouseControlWorkerSetDef> workerSetDefs = {
|
||||
{ WorkerSetType::RotateMode, MouseControlWorkerSetDef::Create<AttackWorker, LockedMouseWorker, LeftRightWorker>() },
|
||||
{ WorkerSetType::RotateModeInCar, MouseControlWorkerSetDef::Create<AttackWorker, void, void>() },
|
||||
{ WorkerSetType::PointAtMode, MouseControlWorkerSetDef::Create<AttackWorker, PointAtMouseWorker, LeftRightWorker>() },
|
||||
{ WorkerSetType::PointAtModeInCar, MouseControlWorkerSetDef::Create<AttackWorker, void, void>() },
|
||||
};
|
||||
|
||||
return workerSetDefs;
|
||||
}
|
||||
}
|
||||
|
||||
const MouseControlWorkerSetDef& GetWorkerSetDef(WorkerSetType type)
|
||||
{
|
||||
return GetWorkerSetDefs().at(type);
|
||||
}
|
||||
|
||||
const std::unique_ptr<MouseControlWorker> CreateWorker(WorkerType type)
|
||||
{
|
||||
const auto& factories = GetWorkerFactories();
|
||||
const auto factoryIt = factories.find(type);
|
||||
return factoryIt != factories.end() ? factoryIt->second() : nullptr;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include "../../common.h"
|
||||
#include "mouse-control-worker.h"
|
||||
|
||||
namespace ModMenuModule::MouseControlWorkerRegistry {
|
||||
enum class WorkerSetType {
|
||||
None = 0,
|
||||
RotateMode,
|
||||
RotateModeInCar,
|
||||
PointAtMode,
|
||||
PointAtModeInCar,
|
||||
};
|
||||
|
||||
using WorkerType = std::type_index;
|
||||
|
||||
template<typename WorkerT>
|
||||
static inline WorkerType GetWorkerType()
|
||||
{
|
||||
return std::type_index(typeid(WorkerT));
|
||||
}
|
||||
|
||||
static inline WorkerType GetWorkerType(MouseControlWorker* worker)
|
||||
{
|
||||
return worker ? std::type_index(typeid(*worker)) : std::type_index(typeid(void));
|
||||
}
|
||||
|
||||
struct MouseControlWorkerSetDef {
|
||||
WorkerType attackWorkerType;
|
||||
WorkerType mouseWorkerType;
|
||||
WorkerType resultWorkerType;
|
||||
|
||||
template<typename AttackWorkerT, typename MouseWorkerT, typename ResultWorkerT>
|
||||
static constexpr MouseControlWorkerSetDef Create()
|
||||
{
|
||||
return {
|
||||
GetWorkerType<AttackWorkerT>(),
|
||||
GetWorkerType<MouseWorkerT>(),
|
||||
GetWorkerType<ResultWorkerT>()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const MouseControlWorkerSetDef& GetWorkerSetDef(WorkerSetType type);
|
||||
const std::unique_ptr<MouseControlWorker> CreateWorker(WorkerType type);
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
namespace ModMenuModule {
|
||||
class MouseControlCheat;
|
||||
|
||||
class MouseControlWorker {
|
||||
public:
|
||||
virtual ~MouseControlWorker() = default;
|
||||
|
||||
virtual void Start() = 0;
|
||||
virtual void Stop() = 0;
|
||||
virtual bool IsRunning() const = 0;
|
||||
virtual void Update() {}
|
||||
|
||||
protected:
|
||||
MouseControlWorker() = default;
|
||||
MouseControlWorker(const MouseControlWorker&) = delete;
|
||||
MouseControlWorker& operator=(const MouseControlWorker&) = delete;
|
||||
};
|
||||
}
|
||||
@ -1,16 +1,10 @@
|
||||
#include "mouse-control.h"
|
||||
#include "../../utils/angle-utils.h"
|
||||
#include "../camera/camera.h"
|
||||
#include "../../toast-manager.h"
|
||||
#include "../../events/cheat-options-update.h"
|
||||
#include "../../cheat-registry.h"
|
||||
|
||||
static constexpr float ROTATE_MODE_SMOOTING = 0.2f;
|
||||
static constexpr float ROTATION_INPUT_THRESHOLD = 0.15f;
|
||||
static constexpr float ROTATION_SPEED = 0.20943928f;
|
||||
|
||||
static constexpr size_t LEFT_CONTROL_INDEX = Game::Utils::GetControlIndex(Game::KEYBOARD_STATE_LEFT);
|
||||
static constexpr size_t RIGHT_CONTROL_INDEX = Game::Utils::GetControlIndex(Game::KEYBOARD_STATE_RIGHT);
|
||||
static constexpr size_t ATTACK_CONTROL_INDEX = Game::Utils::GetControlIndex(Game::KEYBOARD_STATE_ATTACK);
|
||||
static constexpr size_t PERSISTENCE_VERSION = 1;
|
||||
|
||||
ModMenuModule::MouseControlCheat* ModMenuModule::MouseControlCheat::m_instance = nullptr;
|
||||
|
||||
@ -47,9 +41,26 @@ void ModMenuModule::MouseControlCheat::SetOptions(const MouseControlCheatOptions
|
||||
return;
|
||||
}
|
||||
|
||||
SetOptionsInternal(options);
|
||||
MouseControlCheatOptions oldOptions = m_options;
|
||||
m_options = options;
|
||||
|
||||
Core::EventManager* eventManager = Core::EventManager::GetInstance();
|
||||
CheatOptionsUpdateEvent<MouseControlCheat> event(oldOptions, m_options);
|
||||
eventManager->Dispatch(event);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::ShowGamepadControlsToast()
|
||||
{
|
||||
if (m_gamepadControlsToastShown) return;
|
||||
m_gamepadControlsToastShown = true;
|
||||
|
||||
// the name "Controller" is purposely used instead of "Gamepad" or because that's how the preset is named in GTA2 Manager
|
||||
spdlog::warn("Mouse control won't work with Controller controls. Please update your controls in GTA2 Manager");
|
||||
ToastManager::GetInstance()->Show({ L"Mouse control won't work with Controller controls.", ToastType::Warning, 240 });
|
||||
ToastManager::GetInstance()->Show({ L"Please update your controls in GTA2 Manager", ToastType::Warning, 240 });
|
||||
}
|
||||
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnFirstEnable()
|
||||
{
|
||||
LoadFromPersistence();
|
||||
@ -57,182 +68,41 @@ void ModMenuModule::MouseControlCheat::OnFirstEnable()
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnEnable()
|
||||
{
|
||||
AddEventListener<GameStartEvent>(&MouseControlCheat::OnGameStart);
|
||||
AddEventListener<PreGameTickEvent>(&MouseControlCheat::OnPreGameTick);
|
||||
AddEventListener<GameEndEvent>(&MouseControlCheat::OnGameEnd);
|
||||
AddEventListener<GamePauseEvent>(&MouseControlCheat::OnGamePause);
|
||||
AddEventListener<GameUnpauseEvent>(&MouseControlCheat::OnGameUnpause);
|
||||
UpdateAutoModeListeners();
|
||||
UpdateAutoMode();
|
||||
CreateControlHandles();
|
||||
if (ForceControlsCheat::CheckGameReadyToForce()) Start();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnDisable()
|
||||
{
|
||||
RemoveEventListener<GameStartEvent>();
|
||||
RemoveEventListener<PreGameTickEvent>();
|
||||
RemoveEventListener<GameEndEvent>();
|
||||
RemoveEventListener<GamePauseEvent>();
|
||||
RemoveEventListener<GameUnpauseEvent>();
|
||||
RemoveAutoModeListeners();
|
||||
Stop();
|
||||
FreeControlHandles();
|
||||
|
||||
ClearWorkerSet();
|
||||
SaveToPersistence();
|
||||
|
||||
m_gamepadControlsToastShown = false;
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnPreGameTick(PreGameTickEvent& event)
|
||||
{
|
||||
if (CheckShouldUseRotation()) {
|
||||
StartRotation();
|
||||
UpdateTargetDeltaRotation();
|
||||
}
|
||||
else {
|
||||
StopRotation();
|
||||
return;
|
||||
}
|
||||
|
||||
char rotationDirection = GetRotationDirection(m_targetDeltaRotation);
|
||||
bool shouldRotateLeft = rotationDirection == -1;
|
||||
bool shouldRotateRight = rotationDirection == 1;
|
||||
|
||||
if (shouldRotateLeft) m_targetDeltaRotation -= ROTATION_SPEED;
|
||||
else if (shouldRotateRight) m_targetDeltaRotation += ROTATION_SPEED;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_leftControlHandle, shouldRotateLeft ? ForceControlState::ForceDown : ForceControlState::ForceUp);
|
||||
forceControlsCheat->SetControlState(m_rightControlHandle, shouldRotateRight ? ForceControlState::ForceDown : ForceControlState::ForceUp);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnMouseLockedMove(MouseModule::MouseLockedMoveEvent& event)
|
||||
{
|
||||
int deltaX = event.GetDelta().x;
|
||||
m_targetDeltaRotation -= deltaX * m_options.rotateModeSensitivity;
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnMouseMove(MouseModule::MouseMoveEvent& event)
|
||||
{
|
||||
MouseModule::MousePosition pos = event.GetPosition();
|
||||
m_lastNormalizedPos = MouseModule::MouseManager::ToNormalizedPosition(pos);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnMouseButtonDown(MouseModule::MouseButtonDownEvent& event)
|
||||
{
|
||||
if (event.GetButton() != MouseModule::MouseButton::Left) return;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, ForceControlState::ForceDown);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnMouseButtonUp(MouseModule::MouseButtonUpEvent& event)
|
||||
{
|
||||
if (event.GetButton() != MouseModule::MouseButton::Left) return;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, ForceControlState::Unmodified);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnGameStart(GameStartEvent& event)
|
||||
{
|
||||
if (ForceControlsCheat::CheckGameReadyToForce()) Start();
|
||||
ApplyAutoMode();
|
||||
UpdateWorkerSet();
|
||||
SendWorkersUpdate();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnGameEnd(GameEndEvent& event)
|
||||
{
|
||||
Stop();
|
||||
ClearWorkerSet();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnGamePause(GamePauseEvent& event)
|
||||
{
|
||||
Stop();
|
||||
ClearWorkerSet();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnGameUnpause(GameUnpauseEvent& event)
|
||||
{
|
||||
if (ForceControlsCheat::CheckGameReadyToForce(true)) Start();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnCheatStateChange(CheatStateEvent& event)
|
||||
{
|
||||
if (event.GetCheatType() != typeid(CameraCheat)) return;
|
||||
|
||||
UpdateAutoMode();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::OnCameraCheatOptionsUpdate(CheatOptionsUpdateEvent<CameraCheat>& event)
|
||||
{
|
||||
if (event.GetOldOptions().followPedRotation == event.GetNewOptions().followPedRotation) return;
|
||||
|
||||
UpdateAutoMode();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::SetOptionsInternal(const MouseControlCheatOptions& options)
|
||||
{
|
||||
MouseControlCheatOptions oldOptions = m_options;
|
||||
m_options = options;
|
||||
|
||||
bool autoModeChanged = (oldOptions.autoMode != m_options.autoMode);
|
||||
if (autoModeChanged) {
|
||||
if (m_options.autoMode) m_options.mode = GetAutoModeTargetMode();
|
||||
if (IsEnabled()) UpdateAutoModeListeners();
|
||||
}
|
||||
|
||||
bool modeChanged = (oldOptions.mode != m_options.mode);
|
||||
if (m_started && modeChanged) UpdateMode();
|
||||
|
||||
Core::EventManager* eventManager = Core::EventManager::GetInstance();
|
||||
CheatOptionsUpdateEvent<MouseControlCheat> event(oldOptions, m_options);
|
||||
eventManager->Dispatch(event);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateTargetDeltaRotation()
|
||||
{
|
||||
float currentRotation = GetPlayerPedRotation();
|
||||
bool isPointAtMode = m_options.mode == MouseControlCheatMode::PointAt;
|
||||
|
||||
if (isPointAtMode) {
|
||||
std::optional<float> targetRotationOpt = GetTargetRotation(m_lastNormalizedPos);
|
||||
if (!targetRotationOpt.has_value()) {
|
||||
m_targetDeltaRotation = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
m_targetDeltaRotation = Utils::Angle::GetShortestAngleDifference(currentRotation, targetRotationOpt.value());
|
||||
}
|
||||
else {
|
||||
m_targetDeltaRotation *= (1.0f - ROTATE_MODE_SMOOTING);
|
||||
}
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateMode()
|
||||
{
|
||||
bool isRotateMode = m_options.mode == MouseControlCheatMode::Rotate;
|
||||
bool isPointAtMode = m_options.mode == MouseControlCheatMode::PointAt;
|
||||
|
||||
SetEventListener<MouseModule::MouseLockedMoveEvent>(&MouseControlCheat::OnMouseLockedMove, isRotateMode);
|
||||
SetEventListener<MouseModule::MouseMoveEvent>(&MouseControlCheat::OnMouseMove, isPointAtMode);
|
||||
|
||||
MouseModule::MouseManager* mouseManager = MouseModule::MouseManager::GetInstance();
|
||||
mouseManager->SetLocked(isRotateMode);
|
||||
mouseManager->SetCursorVisibility(isRotateMode ? MouseModule::CursorVisibility::ForceInvisible : MouseModule::CursorVisibility::ForceVisible);
|
||||
|
||||
if (isPointAtMode) UpdateLastNormalizedPos();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateLastNormalizedPos()
|
||||
{
|
||||
MouseModule::MousePosition currentPos = MouseModule::MouseManager::FetchMouseState().position;
|
||||
m_lastNormalizedPos = MouseModule::MouseManager::ToNormalizedPosition(currentPos);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateAttack() const
|
||||
{
|
||||
MouseModule::MouseState mouseState = MouseModule::MouseManager::FetchMouseState();
|
||||
bool shouldAttack = mouseState.leftButtonDown;
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, shouldAttack ? ForceControlState::ForceDown : ForceControlState::Unmodified);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateAutoMode()
|
||||
void ModMenuModule::MouseControlCheat::ApplyAutoMode()
|
||||
{
|
||||
if (!m_options.autoMode) return;
|
||||
|
||||
@ -240,229 +110,11 @@ void ModMenuModule::MouseControlCheat::UpdateAutoMode()
|
||||
newOptions.mode = GetAutoModeTargetMode();
|
||||
|
||||
if (newOptions.mode != m_options.mode) {
|
||||
SetOptionsInternal(newOptions);
|
||||
SetOptions(newOptions);
|
||||
}
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateAutoModeListeners()
|
||||
{
|
||||
SetEventListener<CheatStateEvent>(&MouseControlCheat::OnCheatStateChange, m_options.autoMode);
|
||||
SetEventListener<CheatOptionsUpdateEvent<CameraCheat>>(&MouseControlCheat::OnCameraCheatOptionsUpdate, m_options.autoMode);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::RemoveAutoModeListeners()
|
||||
{
|
||||
RemoveEventListener<CheatStateEvent>(true);
|
||||
RemoveEventListener<CheatOptionsUpdateEvent<CameraCheat>>(true);
|
||||
}
|
||||
|
||||
bool ModMenuModule::MouseControlCheat::EnsureNotGamepadControls() const
|
||||
{
|
||||
bool allOk = !ForceControlsCheat::CheckUsesGamepad(LEFT_CONTROL_INDEX)
|
||||
&& !ForceControlsCheat::CheckUsesGamepad(RIGHT_CONTROL_INDEX)
|
||||
&& !ForceControlsCheat::CheckUsesGamepad(ATTACK_CONTROL_INDEX);
|
||||
|
||||
if (!allOk) {
|
||||
// the name "Controller" is purposely used instead of "Gamepad" or because that's how the preset is named in GTA2 Manager
|
||||
spdlog::warn("Mouse control won't work with Controller controls. Please update your controls in GTA2 Manager");
|
||||
ToastManager::GetInstance()->Show({ L"Mouse control won't work with Controller controls.", ToastType::Warning, 240 });
|
||||
ToastManager::GetInstance()->Show({ L"Please update your controls in GTA2 Manager", ToastType::Warning, 240 });
|
||||
}
|
||||
|
||||
return allOk;
|
||||
}
|
||||
|
||||
bool ModMenuModule::MouseControlCheat::EnsureControlHandlesOk() const
|
||||
{
|
||||
if (m_controlHandlesOk) return true;
|
||||
|
||||
spdlog::warn("Mouse control cheat cannot start because control handles are not ok");
|
||||
ToastManager::GetInstance()->Show({ L"Mouse control cheat has failed to start", ToastType::Error, 240 });
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::StartRotation()
|
||||
{
|
||||
if (m_usingRotation) return;
|
||||
spdlog::debug("MouseControlCheat: Starting rotation");
|
||||
m_usingRotation = true;
|
||||
m_targetDeltaRotation = 0.0f;
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::StopRotation()
|
||||
{
|
||||
if (!m_usingRotation) return;
|
||||
spdlog::debug("MouseControlCheat: Stopping rotation");
|
||||
m_usingRotation = false;
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_leftControlHandle, ForceControlState::Unmodified);
|
||||
forceControlsCheat->SetControlState(m_rightControlHandle, ForceControlState::Unmodified);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::Start()
|
||||
{
|
||||
if (m_started) return;
|
||||
if (!EnsureControlHandlesOk()) return;
|
||||
if (!EnsureNotGamepadControls()) return;
|
||||
spdlog::debug("MouseControlCheat: Starting");
|
||||
m_started = true;
|
||||
|
||||
AddEventListener<PreGameTickEvent>(&MouseControlCheat::OnPreGameTick);
|
||||
AddEventListener<MouseModule::MouseButtonDownEvent>(&MouseControlCheat::OnMouseButtonDown);
|
||||
AddEventListener<MouseModule::MouseButtonUpEvent>(&MouseControlCheat::OnMouseButtonUp);
|
||||
|
||||
UpdateMode();
|
||||
UpdateAttack();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::Stop()
|
||||
{
|
||||
if (!m_started) return;
|
||||
spdlog::debug("MouseControlCheat: Stopping");
|
||||
m_started = false;
|
||||
|
||||
RemoveEventListener<PreGameTickEvent>();
|
||||
RemoveEventListener<MouseModule::MouseButtonDownEvent>();
|
||||
RemoveEventListener<MouseModule::MouseButtonUpEvent>();
|
||||
RemoveEventListener<MouseModule::MouseLockedMoveEvent>(true);
|
||||
RemoveEventListener<MouseModule::MouseMoveEvent>(true);
|
||||
|
||||
MouseModule::MouseManager* mouseManager = MouseModule::MouseManager::GetInstance();
|
||||
mouseManager->SetLocked(false);
|
||||
mouseManager->SetCursorVisibility(MouseModule::CursorVisibility::Unmodified);
|
||||
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
forceControlsCheat->SetControlState(m_attackControlHandle, ForceControlState::Unmodified);
|
||||
StopRotation();
|
||||
}
|
||||
|
||||
bool ModMenuModule::MouseControlCheat::CreateControlHandles()
|
||||
{
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
|
||||
m_leftControlHandle = forceControlsCheat->CreateControlHandle(LEFT_CONTROL_INDEX);
|
||||
m_rightControlHandle = forceControlsCheat->CreateControlHandle(RIGHT_CONTROL_INDEX);
|
||||
m_attackControlHandle = forceControlsCheat->CreateControlHandle(ATTACK_CONTROL_INDEX);
|
||||
|
||||
m_controlHandlesOk = (m_leftControlHandle != -1) && (m_rightControlHandle != -1) && (m_attackControlHandle != -1);
|
||||
if(!m_controlHandlesOk) {
|
||||
spdlog::error("Mouse control cheat failed to create control handles");
|
||||
FreeControlHandles();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::FreeControlHandles()
|
||||
{
|
||||
ForceControlsCheat* forceControlsCheat = ForceControlsCheat::GetInstance();
|
||||
|
||||
if (m_leftControlHandle != -1) {
|
||||
forceControlsCheat->FreeControlHandle(m_leftControlHandle);
|
||||
m_leftControlHandle = -1;
|
||||
}
|
||||
|
||||
if (m_rightControlHandle != -1) {
|
||||
forceControlsCheat->FreeControlHandle(m_rightControlHandle);
|
||||
m_rightControlHandle = -1;
|
||||
}
|
||||
|
||||
if (m_attackControlHandle != -1) {
|
||||
forceControlsCheat->FreeControlHandle(m_attackControlHandle);
|
||||
m_attackControlHandle = -1;
|
||||
}
|
||||
|
||||
m_controlHandlesOk = false;
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::SaveToPersistence() const
|
||||
{
|
||||
PersistenceModule::PersistenceManager* persistence = PersistenceModule::PersistenceManager::GetInstance();
|
||||
size_t dataSize = 1 + sizeof(MouseControlCheatOptions);
|
||||
std::unique_ptr<uint8_t[]> dataPtr = std::make_unique<uint8_t[]>(dataSize);
|
||||
|
||||
dataPtr[0] = 1; // version
|
||||
memcpy(dataPtr.get() + 1, &m_options, sizeof(MouseControlCheatOptions));
|
||||
|
||||
persistence->SaveRaw("Cheat_MouseControl_State", dataPtr.get(), dataSize);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::LoadFromPersistence()
|
||||
{
|
||||
PersistenceModule::PersistenceManager* persistence = PersistenceModule::PersistenceManager::GetInstance();
|
||||
std::unique_ptr<uint8_t[]> dataPtr = nullptr;
|
||||
size_t dataSize = 0;
|
||||
if (!persistence->LoadRaw("Cheat_MouseControl_State", dataPtr, dataSize)) return;
|
||||
if (dataSize < 1) {
|
||||
spdlog::error("MouseControlCheat::LoadFromPersistence: invalid data size");
|
||||
return;
|
||||
}
|
||||
uint8_t version = dataPtr[0];
|
||||
if (version != 1) {
|
||||
spdlog::error("MouseControlCheat::LoadFromPersistence: unsupported version {}", version);
|
||||
return;
|
||||
}
|
||||
if (dataSize != 1 + sizeof(MouseControlCheatOptions)) {
|
||||
spdlog::error("MouseControlCheat::LoadFromPersistence: invalid data size for version {}", version);
|
||||
return;
|
||||
}
|
||||
memcpy(&m_options, dataPtr.get() + 1, sizeof(MouseControlCheatOptions));
|
||||
SetOptions(m_options);
|
||||
}
|
||||
|
||||
bool ModMenuModule::MouseControlCheat::CheckShouldUseRotation()
|
||||
{
|
||||
Game::Ped* playerPed = Game::Utils::GetPlayerCurrentPed();
|
||||
if (!playerPed || !playerPed->gameObject) return false;
|
||||
if (playerPed->targetCarForEnter) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char ModMenuModule::MouseControlCheat::GetRotationDirection(float deltaAngle)
|
||||
{
|
||||
if (std::abs(deltaAngle) < ROTATION_INPUT_THRESHOLD) {
|
||||
return 0;
|
||||
}
|
||||
return deltaAngle > 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
float ModMenuModule::MouseControlCheat::GetPlayerPedRotation()
|
||||
{
|
||||
Game::Ped* playerPed = Game::Utils::GetPlayerCurrentPed();
|
||||
if (!playerPed || !playerPed->gameObject) return 0; // prior verified by ShouldUseRotation to not let this happen
|
||||
|
||||
return Game::Utils::FromGTAAngleToRad(playerPed->gameObject->spriteRotation);
|
||||
}
|
||||
|
||||
std::optional<float> ModMenuModule::MouseControlCheat::GetTargetRotation(MouseModule::NormalizedMousePosition normalizedPos)
|
||||
{
|
||||
normalizedPos.x -= 0.5f;
|
||||
normalizedPos.y -= 0.5f;
|
||||
normalizedPos.x *= -1.0f;
|
||||
|
||||
normalizedPos.x *= MouseModule::MouseManager::GetClientAreaAspectRatio();
|
||||
float targetAngle;
|
||||
|
||||
CameraCheat* cameraCheat = CameraCheat::GetInstance();
|
||||
if (cameraCheat->IsEnabled()) {
|
||||
CameraCheatOptions cameraOptions = cameraCheat->GetOptions();
|
||||
normalizedPos.x *= std::cos(cameraOptions.cameraTransform.horizontalAngleRad);
|
||||
if (normalizedPos.x == 0.0f && normalizedPos.y == 0.0f) return std::nullopt;
|
||||
targetAngle = std::atan2(normalizedPos.y, normalizedPos.x) - static_cast<float>(M_PI / 2.0f);
|
||||
|
||||
float cameraRotation = cameraCheat->GetOptions().cameraTransform.verticalAngleRad;
|
||||
targetAngle += cameraRotation;
|
||||
}
|
||||
else {
|
||||
targetAngle = std::atan2(normalizedPos.y, normalizedPos.x) - static_cast<float>(M_PI / 2.0f);
|
||||
}
|
||||
|
||||
return Utils::Angle::NormalizeAngle(targetAngle);
|
||||
}
|
||||
|
||||
ModMenuModule::MouseControlCheatMode ModMenuModule::MouseControlCheat::GetAutoModeTargetMode()
|
||||
ModMenuModule::MouseControlCheatMode ModMenuModule::MouseControlCheat::GetAutoModeTargetMode() const
|
||||
{
|
||||
CameraCheat* cameraCheat = CameraCheat::GetInstance();
|
||||
if (!cameraCheat->IsEnabled()) {
|
||||
@ -477,4 +129,142 @@ ModMenuModule::MouseControlCheatMode ModMenuModule::MouseControlCheat::GetAutoMo
|
||||
return MouseControlCheatMode::Rotate;
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateWorkerSet()
|
||||
{
|
||||
using namespace MouseControlWorkerRegistry;
|
||||
|
||||
WorkerSetType appliableWorkerSetType = GetAppliableWorkerSetType();
|
||||
if (appliableWorkerSetType == m_workerSetType) return;
|
||||
|
||||
const MouseControlWorkerSetDef& workerSetDef = GetWorkerSetDef(appliableWorkerSetType);
|
||||
|
||||
UpdateWorker(m_attackWorker, workerSetDef.attackWorkerType);
|
||||
UpdateWorker(m_mouseWorker, workerSetDef.mouseWorkerType);
|
||||
UpdateWorker(m_resultWorker, workerSetDef.resultWorkerType);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::ClearWorkerSet()
|
||||
{
|
||||
m_workerSetType = MouseControlWorkerRegistry::WorkerSetType::None;
|
||||
RemoveWorker(m_attackWorker);
|
||||
RemoveWorker(m_mouseWorker);
|
||||
RemoveWorker(m_resultWorker);
|
||||
}
|
||||
|
||||
ModMenuModule::MouseControlWorkerRegistry::WorkerSetType ModMenuModule::MouseControlCheat::GetAppliableWorkerSetType() const
|
||||
{
|
||||
using namespace MouseControlWorkerRegistry;
|
||||
|
||||
Game::Game* game = Game::Memory::GetGame();
|
||||
if (!game || game->gameStatus != Game::GAME_RUN) {
|
||||
return WorkerSetType::None;
|
||||
}
|
||||
|
||||
Game::Ped* playerPed = Game::Utils::GetPlayerCurrentPed();
|
||||
bool isInCar = playerPed && (playerPed->currentCar != nullptr || playerPed->targetCarForEnter != nullptr);
|
||||
bool hasGameObject = playerPed && playerPed->gameObject != nullptr;
|
||||
|
||||
switch (m_options.mode) {
|
||||
case MouseControlCheatMode::Rotate:
|
||||
if (isInCar) return WorkerSetType::RotateModeInCar;
|
||||
else if (hasGameObject) return WorkerSetType::RotateMode;
|
||||
return WorkerSetType::None;
|
||||
case MouseControlCheatMode::PointAt:
|
||||
if (isInCar) return WorkerSetType::PointAtModeInCar;
|
||||
else if (hasGameObject) return WorkerSetType::PointAtMode;
|
||||
return WorkerSetType::None;
|
||||
default:
|
||||
spdlog::error("MouseControlCheat::GetAppliableWorkerSet: unknown mode {}", static_cast<int>(m_options.mode));
|
||||
return WorkerSetType::None;
|
||||
}
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::UpdateWorker(std::unique_ptr<MouseControlWorker>& worker, MouseControlWorkerRegistry::WorkerType targetType)
|
||||
{
|
||||
if (worker && MouseControlWorkerRegistry::GetWorkerType(worker.get()) == targetType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (worker) {
|
||||
RemoveWorker(worker);
|
||||
}
|
||||
|
||||
if (targetType != MouseControlWorkerRegistry::GetWorkerType<void>()) {
|
||||
CreateWorker(worker, targetType);
|
||||
}
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::CreateWorker(std::unique_ptr<MouseControlWorker>& worker, MouseControlWorkerRegistry::WorkerType type)
|
||||
{
|
||||
std::unique_ptr<MouseControlWorker> newWorker = MouseControlWorkerRegistry::CreateWorker(type);
|
||||
if (!newWorker) {
|
||||
spdlog::error("MouseControlCheat::CreateWorker: failed to create worker for type {}", type.name());
|
||||
return;
|
||||
}
|
||||
|
||||
newWorker->Start();
|
||||
if(!newWorker->IsRunning()) {
|
||||
spdlog::error("MouseControlCheat::CreateWorker: failed to start worker for type {}", type.name());
|
||||
return;
|
||||
}
|
||||
|
||||
worker = std::move(newWorker);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::RemoveWorker(std::unique_ptr<MouseControlWorker>& worker)
|
||||
{
|
||||
if (!worker) return;
|
||||
|
||||
worker->Stop();
|
||||
worker.reset();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::SendWorkersUpdate()
|
||||
{
|
||||
if (m_attackWorker) m_attackWorker->Update();
|
||||
if (m_mouseWorker) m_mouseWorker->Update();
|
||||
if (m_resultWorker) m_resultWorker->Update();
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::SaveToPersistence() const
|
||||
{
|
||||
PersistenceModule::PersistenceManager* persistence = PersistenceModule::PersistenceManager::GetInstance();
|
||||
size_t dataSize = 1 + sizeof(MouseControlCheatOptions);
|
||||
std::unique_ptr<uint8_t[]> dataPtr = std::make_unique<uint8_t[]>(dataSize);
|
||||
|
||||
dataPtr[0] = PERSISTENCE_VERSION; // version
|
||||
memcpy(dataPtr.get() + 1, &m_options, sizeof(MouseControlCheatOptions));
|
||||
|
||||
persistence->SaveRaw("Cheat_MouseControl_State", dataPtr.get(), dataSize);
|
||||
}
|
||||
|
||||
void ModMenuModule::MouseControlCheat::LoadFromPersistence()
|
||||
{
|
||||
PersistenceModule::PersistenceManager* persistence = PersistenceModule::PersistenceManager::GetInstance();
|
||||
std::unique_ptr<uint8_t[]> dataPtr = nullptr;
|
||||
size_t dataSize = 0;
|
||||
if (!persistence->LoadRaw("Cheat_MouseControl_State", dataPtr, dataSize)) return;
|
||||
|
||||
if (dataSize < 1) {
|
||||
spdlog::error("MouseControlCheat::LoadFromPersistence: invalid data size");
|
||||
return;
|
||||
}
|
||||
uint8_t version = dataPtr[0];
|
||||
if (version != PERSISTENCE_VERSION) {
|
||||
if (!ConvertPersistence(dataPtr, dataSize, version)) return;
|
||||
}
|
||||
if (dataSize != 1 + sizeof(MouseControlCheatOptions)) {
|
||||
spdlog::error("MouseControlCheat::LoadFromPersistence: invalid persistence data size");
|
||||
return;
|
||||
}
|
||||
memcpy(&m_options, dataPtr.get() + 1, sizeof(MouseControlCheatOptions));
|
||||
SetOptions(m_options);
|
||||
}
|
||||
|
||||
bool ModMenuModule::MouseControlCheat::ConvertPersistence(std::unique_ptr<uint8_t[]>& dataPtr, size_t& dataSize, uint8_t version)
|
||||
{
|
||||
spdlog::error("MouseControlCheat::ConvertPersistence: unsupported version {}", version);
|
||||
return false;
|
||||
}
|
||||
|
||||
REGISTER_CHEAT(MouseControlCheat)
|
||||
|
||||
@ -3,17 +3,12 @@
|
||||
#include "../../cheat-base.h"
|
||||
#include "../force-controls.h"
|
||||
#include "../../../../events/game-tick.h"
|
||||
#include "../../../../events/game-start.h"
|
||||
#include "../../../../events/game-end.h"
|
||||
#include "../../../../events/game-pause.h"
|
||||
#include "../../../../events/game-unpause.h"
|
||||
#include "../../events/cheat-state.h"
|
||||
#include "../../events/cheat-options-update.h"
|
||||
#include "../../../mouse/normalized-mouse-position.h"
|
||||
#include "mouse-control-worker.h"
|
||||
#include "mouse-control-worker-registry.h"
|
||||
|
||||
namespace ModMenuModule {
|
||||
class CameraCheat;
|
||||
|
||||
enum class MouseControlCheatMode {
|
||||
Rotate = 0,
|
||||
PointAt = 2,
|
||||
@ -41,58 +36,47 @@ namespace ModMenuModule {
|
||||
void SetOptions(const MouseControlCheatOptions& options);
|
||||
MouseControlCheatOptions GetOptions() const { return m_options; }
|
||||
|
||||
void ShowGamepadControlsToast();
|
||||
void SetDeltaX(float deltaX) { m_deltaX = deltaX; }
|
||||
float GetDeltaX() const { return m_deltaX; }
|
||||
void SetDeltaY(float deltaY) { m_deltaY = deltaY; }
|
||||
float GetDeltaY() const { return m_deltaY; }
|
||||
|
||||
private:
|
||||
virtual void OnFirstEnable() override;
|
||||
virtual void OnEnable() override;
|
||||
virtual void OnDisable() override;
|
||||
|
||||
void OnPreGameTick(PreGameTickEvent& event);
|
||||
void OnMouseLockedMove(MouseModule::MouseLockedMoveEvent& event);
|
||||
void OnMouseMove(MouseModule::MouseMoveEvent& event);
|
||||
void OnMouseButtonDown(MouseModule::MouseButtonDownEvent& event);
|
||||
void OnMouseButtonUp(MouseModule::MouseButtonUpEvent& event);
|
||||
void OnGameStart(GameStartEvent& event);
|
||||
void OnGameEnd(GameEndEvent& event);
|
||||
void OnGamePause(GamePauseEvent& event);
|
||||
void OnGameUnpause(GameUnpauseEvent& event);
|
||||
void OnCheatStateChange(CheatStateEvent& event);
|
||||
void OnCameraCheatOptionsUpdate(CheatOptionsUpdateEvent<CameraCheat>& event);
|
||||
|
||||
void SetOptionsInternal(const MouseControlCheatOptions& options);
|
||||
void UpdateTargetDeltaRotation();
|
||||
void UpdateMode();
|
||||
void UpdateLastNormalizedPos();
|
||||
void UpdateAttack() const;
|
||||
void UpdateAutoMode();
|
||||
void UpdateAutoModeListeners();
|
||||
void RemoveAutoModeListeners();
|
||||
bool EnsureNotGamepadControls() const;
|
||||
bool EnsureControlHandlesOk() const;
|
||||
void StartRotation();
|
||||
void StopRotation();
|
||||
void Start();
|
||||
void Stop();
|
||||
bool CreateControlHandles();
|
||||
void FreeControlHandles();
|
||||
void ApplyAutoMode();
|
||||
MouseControlCheatMode GetAutoModeTargetMode() const;
|
||||
|
||||
void UpdateWorkerSet();
|
||||
void ClearWorkerSet();
|
||||
MouseControlWorkerRegistry::WorkerSetType GetAppliableWorkerSetType() const;
|
||||
|
||||
void UpdateWorker(std::unique_ptr<MouseControlWorker>& worker, MouseControlWorkerRegistry::WorkerType targetType);
|
||||
void CreateWorker(std::unique_ptr<MouseControlWorker>& worker, MouseControlWorkerRegistry::WorkerType type);
|
||||
void RemoveWorker(std::unique_ptr<MouseControlWorker>& worker);
|
||||
|
||||
void SendWorkersUpdate();
|
||||
|
||||
void SaveToPersistence() const;
|
||||
void LoadFromPersistence();
|
||||
|
||||
static bool CheckShouldUseRotation();
|
||||
static char GetRotationDirection(float deltaAngle);
|
||||
static float GetPlayerPedRotation();
|
||||
static std::optional<float> GetTargetRotation(MouseModule::NormalizedMousePosition normalizedPos);
|
||||
static MouseControlCheatMode GetAutoModeTargetMode();
|
||||
static bool ConvertPersistence(std::unique_ptr<uint8_t[]>& dataPtr, size_t& dataSize, uint8_t version);
|
||||
|
||||
static MouseControlCheat* m_instance;
|
||||
MouseControlCheatOptions m_options;
|
||||
float m_targetDeltaRotation = 0.0f;
|
||||
MouseModule::NormalizedMousePosition m_lastNormalizedPos = {};
|
||||
bool m_started = false;
|
||||
ForceControlsCheat::ControlHandle m_leftControlHandle = -1;
|
||||
ForceControlsCheat::ControlHandle m_rightControlHandle = -1;
|
||||
ForceControlsCheat::ControlHandle m_attackControlHandle = -1;
|
||||
bool m_controlHandlesOk = false;
|
||||
bool m_usingRotation = false;
|
||||
MouseControlWorkerRegistry::WorkerSetType m_workerSetType = MouseControlWorkerRegistry::WorkerSetType::None;
|
||||
std::unique_ptr<MouseControlWorker> m_attackWorker;
|
||||
std::unique_ptr<MouseControlWorker> m_mouseWorker;
|
||||
std::unique_ptr<MouseControlWorker> m_resultWorker;
|
||||
bool m_gamepadControlsToastShown = false;
|
||||
|
||||
float m_deltaX = 0.0f;
|
||||
float m_deltaY = 0.0f;
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
#include "point-at-mouse-worker.h"
|
||||
#include "mouse-control.h"
|
||||
#include "../camera/camera.h"
|
||||
#include "../../common.h"
|
||||
#include "../../utils/angle-utils.h"
|
||||
|
||||
void ModMenuModule::PointAtMouseWorker::Start()
|
||||
{
|
||||
spdlog::debug("PointAtMouseWorker: Starting");
|
||||
|
||||
AddEventListener<MouseModule::MouseMoveEvent>(&PointAtMouseWorker::OnMouseMove);
|
||||
|
||||
MouseModule::MouseManager* mouseManager = MouseModule::MouseManager::GetInstance();
|
||||
mouseManager->SetLocked(false); // ensure
|
||||
mouseManager->SetCursorVisibility(MouseModule::CursorVisibility::ForceVisible);
|
||||
m_running = true;
|
||||
|
||||
UpdateLastMousePosition();
|
||||
}
|
||||
|
||||
void ModMenuModule::PointAtMouseWorker::Stop()
|
||||
{
|
||||
spdlog::debug("PointAtMouseWorker: Stopping");
|
||||
|
||||
RemoveEventListener<MouseModule::MouseMoveEvent>();
|
||||
|
||||
MouseModule::MouseManager* mouseManager = MouseModule::MouseManager::GetInstance();
|
||||
mouseManager->SetCursorVisibility(MouseModule::CursorVisibility::Unmodified);
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void ModMenuModule::PointAtMouseWorker::Update()
|
||||
{
|
||||
float deltaRotation = 0.0f;
|
||||
float currentRotation = GetPlayerPedRotation();
|
||||
|
||||
std::optional<float> targetRotationOpt = GetTargetRotation(m_lastMousePosition);
|
||||
if (targetRotationOpt.has_value()) {
|
||||
deltaRotation = Utils::Angle::GetShortestAngleDifference(currentRotation, targetRotationOpt.value());
|
||||
}
|
||||
|
||||
MouseControlCheat* mouseControlCheat = MouseControlCheat::GetInstance();
|
||||
mouseControlCheat->SetDeltaX(deltaRotation);
|
||||
}
|
||||
|
||||
void ModMenuModule::PointAtMouseWorker::OnMouseMove(MouseModule::MouseMoveEvent& event)
|
||||
{
|
||||
MouseModule::MousePosition pos = event.GetPosition();
|
||||
m_lastMousePosition = MouseModule::MouseManager::ToNormalizedPosition(pos);
|
||||
}
|
||||
|
||||
void ModMenuModule::PointAtMouseWorker::UpdateLastMousePosition()
|
||||
{
|
||||
MouseModule::MousePosition currentPos = MouseModule::MouseManager::FetchMouseState().position;
|
||||
m_lastMousePosition = MouseModule::MouseManager::ToNormalizedPosition(currentPos);
|
||||
}
|
||||
|
||||
std::optional<float> ModMenuModule::PointAtMouseWorker::GetTargetRotation(MouseModule::NormalizedMousePosition normalizedPos)
|
||||
{
|
||||
normalizedPos.x -= 0.5f;
|
||||
normalizedPos.y -= 0.5f;
|
||||
normalizedPos.x *= -1.0f;
|
||||
|
||||
normalizedPos.x *= MouseModule::MouseManager::GetClientAreaAspectRatio();
|
||||
float targetAngle;
|
||||
|
||||
CameraCheat* cameraCheat = CameraCheat::GetInstance();
|
||||
if (cameraCheat->IsEnabled()) {
|
||||
CameraCheatOptions cameraOptions = cameraCheat->GetOptions();
|
||||
normalizedPos.x *= std::cos(cameraOptions.cameraTransform.horizontalAngleRad);
|
||||
if (normalizedPos.x == 0.0f && normalizedPos.y == 0.0f) return std::nullopt;
|
||||
targetAngle = std::atan2(normalizedPos.x, normalizedPos.y);
|
||||
|
||||
float cameraRotation = cameraCheat->GetOptions().cameraTransform.verticalAngleRad;
|
||||
targetAngle -= cameraRotation;
|
||||
}
|
||||
else {
|
||||
targetAngle = std::atan2(normalizedPos.x, normalizedPos.y);
|
||||
}
|
||||
|
||||
return Utils::Angle::NormalizeAngle(targetAngle);
|
||||
}
|
||||
|
||||
float ModMenuModule::PointAtMouseWorker::GetPlayerPedRotation()
|
||||
{
|
||||
Game::Ped* playerPed = Game::Utils::GetPlayerCurrentPed();
|
||||
if (!playerPed || !playerPed->gameObject) return 0;
|
||||
|
||||
return -Game::Utils::FromGTAAngleToRad(playerPed->gameObject->spriteRotation);
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "mouse-control-worker.h"
|
||||
#include "../force-controls.h"
|
||||
|
||||
namespace ModMenuModule {
|
||||
class PointAtMouseWorker : public MouseControlWorker, public Core::EventListenerSupport {
|
||||
public:
|
||||
PointAtMouseWorker() = default;
|
||||
PointAtMouseWorker(const PointAtMouseWorker&) = delete;
|
||||
PointAtMouseWorker& operator=(const PointAtMouseWorker&) = delete;
|
||||
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
bool IsRunning() const override { return m_running; }
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
void OnMouseMove(MouseModule::MouseMoveEvent& event);
|
||||
|
||||
void UpdateLastMousePosition();
|
||||
|
||||
static std::optional<float> GetTargetRotation(MouseModule::NormalizedMousePosition normalizedPos);
|
||||
static float GetPlayerPedRotation();
|
||||
|
||||
bool m_running = false;
|
||||
MouseModule::NormalizedMousePosition m_lastMousePosition{ 0.0f, 0.0f };
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user