Skip to content

Commit

Permalink
Aiming: Filter out other player controllers (MP support)
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Dec 18, 2023
1 parent 9d980ac commit 3cb9b25
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 14 deletions.
21 changes: 21 additions & 0 deletions shared/sdk/APlayerCameraManager.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
#include <sdk/UObjectArray.hpp>
#include <sdk/UClass.hpp>

#include "APlayerCameraManager.hpp"

namespace sdk {
sdk::UClass* APlayerCameraManager::static_class() {
return (UClass*)sdk::find_uobject(L"Class /Script/Engine.PlayerCameraManager");
}

sdk::APlayerController* APlayerCameraManager::get_owning_player_controller() {
static const auto sc = static_class();
if (sc == nullptr) {
return nullptr;
}

static const auto func = sc->find_function(L"GetOwningPlayerController");

if (func == nullptr) {
return nullptr;
}

struct {
APlayerController* result{};
} params;

this->process_event(func, &params);
return params.result;
}
}
4 changes: 3 additions & 1 deletion shared/sdk/APlayerCameraManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

namespace sdk {
class UClass;
class APlayerController;

class APlayerCameraManager : public UObject {
public:
static UClass* static_class();
// TODO

APlayerController* get_owning_player_controller();
};
}
22 changes: 22 additions & 0 deletions shared/sdk/APlayerController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,28 @@ glm::vec3 AController::get_control_rotation() {
return *(glm::vec<3, double>*)params.data();
}

bool AController::is_local_player_controller() {
static const auto sc = static_class();

if (sc == nullptr) {
return true; // whatever
}

static const auto func = sc->find_function(L"IsLocalPlayerController");

if (func == nullptr) {
return true; // whatever
}

struct {
bool result{};
} params;

this->process_event(func, &params);

return params.result;
}

UClass* APlayerController::static_class() {
return sdk::find_uobject<UClass>(L"Class /Script/Engine.PlayerController");
}
Expand Down
2 changes: 2 additions & 0 deletions shared/sdk/APlayerController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class AController : public UObject {
void set_control_rotation(const glm::vec3& newrotation);
glm::vec3 get_control_rotation();

bool is_local_player_controller();

protected:
};

Expand Down
1 change: 1 addition & 0 deletions src/mods/VR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2104,6 +2104,7 @@ void VR::on_draw_sidebar_entry(std::string_view name) {
m_previous_aim_method = (AimMethod)m_aim_method->value();
}

m_aim_multiplayer_support->draw("Multiplayer Support");
m_aim_interp->draw("Smoothing");
m_aim_speed->draw("Speed");

Expand Down
6 changes: 6 additions & 0 deletions src/mods/VR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ class VR : public Mod {
float get_aim_speed() const {
return m_aim_speed->value();
}

bool is_aim_multiplayer_support_enabled() const {
return m_aim_multiplayer_support->value();
}

bool is_aim_interpolation_enabled() const {
return m_aim_interp->value();
Expand Down Expand Up @@ -757,6 +761,7 @@ class VR : public Mod {
const ModCombo::Ptr m_aim_method{ ModCombo::create(generate_name("AimMethod"), s_aim_method_names, AimMethod::GAME) };
const ModCombo::Ptr m_movement_orientation{ ModCombo::create(generate_name("MovementOrientation"), s_aim_method_names, AimMethod::GAME) };
AimMethod m_previous_aim_method{ AimMethod::GAME };
const ModToggle::Ptr m_aim_multiplayer_support{ ModToggle::create(generate_name("AimMPSupport"), true) };
const ModToggle::Ptr m_aim_interp{ ModToggle::create(generate_name("AimInterp"), true, true) };
const ModSlider::Ptr m_aim_speed{ ModSlider::create(generate_name("AimSpeed"), 0.01f, 25.0f, 15.0f) };
const ModToggle::Ptr m_dpad_shifting{ ModToggle::create(generate_name("DPadShifting"), true) };
Expand Down Expand Up @@ -830,6 +835,7 @@ class VR : public Mod {
*m_snapturn_angle,
*m_aim_method,
*m_movement_orientation,
*m_aim_multiplayer_support,
*m_aim_speed,
*m_aim_interp,
*m_dpad_shifting,
Expand Down
49 changes: 40 additions & 9 deletions src/mods/vr/IXRTrackingSystemHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#include <sdk/UClass.hpp>
#include <sdk/FProperty.hpp>
#include <sdk/ScriptVector.hpp>
#include <sdk/UGameplayStatics.hpp>
#include <sdk/APlayerController.hpp>
#include <sdk/APlayerCameraManager.hpp>

#include "../VR.hpp"

Expand Down Expand Up @@ -1266,7 +1269,7 @@ IXRTrackingSystemHook::SharedPtr* IXRTrackingSystemHook::get_view_extension(sdk:
return out;
}

void IXRTrackingSystemHook::apply_hmd_rotation(sdk::IXRCamera*, void* player_controller, Rotator<float>* rot) {
void IXRTrackingSystemHook::apply_hmd_rotation(sdk::IXRCamera*, sdk::APlayerController* player_controller, Rotator<float>* rot) {
SPDLOG_INFO_ONCE("apply_hmd_rotation {:x}", (uintptr_t)_ReturnAddress());

if (VR::get()->is_hmd_active() && !g_hook->m_process_view_rotation_hook && !g_hook->m_attempted_hook_view_rotation) {
Expand Down Expand Up @@ -1294,7 +1297,7 @@ void IXRTrackingSystemHook::apply_hmd_rotation(sdk::IXRCamera*, void* player_con
func.calls_apply_hmd_rotation = true;
}

g_hook->update_view_rotation(rot);
g_hook->update_view_rotation(player_controller, rot);
}

/*if (g_hook->m_stereo_hook == nullptr) {
Expand Down Expand Up @@ -1429,11 +1432,11 @@ void* IXRTrackingSystemHook::process_view_rotation_analyzer(void* a1, size_t a2,
}

void IXRTrackingSystemHook::process_view_rotation(
void* player_controller, float delta_time, Rotator<float>* rot, Rotator<float>* delta_rot) {
sdk::APlayerCameraManager* pcm, float delta_time, Rotator<float>* rot, Rotator<float>* delta_rot) {
SPDLOG_INFO_ONCE("process_view_rotation {:x}", (uintptr_t)_ReturnAddress());

auto call_orig = [&]() {
g_hook->m_process_view_rotation_hook.call<void>(player_controller, delta_time, rot, delta_rot);
g_hook->m_process_view_rotation_hook.call<void>(pcm, delta_time, rot, delta_rot);
};

auto& vr = VR::get();
Expand All @@ -1447,10 +1450,10 @@ void IXRTrackingSystemHook::process_view_rotation(

call_orig();

g_hook->update_view_rotation(rot);
g_hook->update_view_rotation(pcm, rot);
}

void IXRTrackingSystemHook::pre_update_view_rotation(Rotator<float>* rot) {
void IXRTrackingSystemHook::pre_update_view_rotation(sdk::UObject* reference_obj, Rotator<float>* rot) {
auto& vr = VR::get();

if (m_stereo_hook->has_double_precision()) {
Expand All @@ -1462,15 +1465,43 @@ void IXRTrackingSystemHook::pre_update_view_rotation(Rotator<float>* rot) {
}
}

void IXRTrackingSystemHook::update_view_rotation(Rotator<float>* rot) {
void IXRTrackingSystemHook::update_view_rotation(sdk::UObject* reference_obj, Rotator<float>* rot) {
auto& vr = VR::get();

// Double check that the player controller passed through here is the local player controller
static bool had_detection_error = false;
if (!had_detection_error && vr->is_aim_multiplayer_support_enabled()) try {
const auto engine = sdk::UEngine::get();
if (engine != nullptr && reference_obj != nullptr && sdk::FUObjectArray::get() != nullptr) {
const auto reference_obj_c = reference_obj->get_class();

static const auto player_controller_class = sdk::APlayerController::static_class();
static const auto player_camera_manager_class = sdk::APlayerCameraManager::static_class();

sdk::APlayerController* pc = nullptr;

if (player_controller_class != nullptr && reference_obj_c != nullptr && reference_obj_c->is_a(player_controller_class)) {
pc = (sdk::APlayerController*)reference_obj;
} else if (player_camera_manager_class != nullptr && reference_obj_c != nullptr && reference_obj_c->is_a(player_camera_manager_class)) {
const auto pcm = (sdk::APlayerCameraManager*)reference_obj;
pc = pcm->get_owning_player_controller();
}

if (pc != nullptr && !pc->is_local_player_controller()) {
return;
}
}
} catch(...) {
had_detection_error = true;
SPDLOG_ERROR("[IXRTrackingSystemHook] Error detecting reference object, cannot support multiplayer");
}

const auto now = std::chrono::high_resolution_clock::now();
const auto delta_time = now - m_process_view_rotation_data.last_update;
const auto delta_float = glm::min(std::chrono::duration_cast<std::chrono::duration<float>>(delta_time).count(), 0.1f);
m_process_view_rotation_data.last_update = now;
m_process_view_rotation_data.was_called = true;

auto& vr = VR::get();

if (!vr->is_hmd_active() || !vr->is_any_aim_method_active()) {
return;
}
Expand Down
10 changes: 6 additions & 4 deletions src/mods/vr/IXRTrackingSystemHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class UEngine;
class IXRTrackingSystem;
class IXRCamera;
class IHeadMountedDisplay;
class APlayerController;
class APlayerCameraManager;
}

class FFakeStereoRenderingHook;
Expand Down Expand Up @@ -71,17 +73,17 @@ class IXRTrackingSystemHook : public ModComponent {
static SharedPtr* get_view_extension(sdk::IHeadMountedDisplay*, SharedPtr* out);

// IXRCamera
static void apply_hmd_rotation(sdk::IXRCamera*, void* player_controller, Rotator<float>* rot);
static void apply_hmd_rotation(sdk::IXRCamera*, sdk::APlayerController* player_controller, Rotator<float>* rot);
static bool update_player_camera(sdk::IXRCamera*, Quat<float>* rel_rot, glm::vec3* rel_pos);
// This function is the precursor to actually hooking ProcessViewRotation
// Because there's a very real possibility that we can accidentally hook the wrong function
// We need to verify that arg 2 and 3 are on the stack
// And the function that calls it is also a virtual function (APlayerController::UpdateRotation)
static void* process_view_rotation_analyzer(void*, size_t, size_t, size_t, size_t, size_t);
static void process_view_rotation(void* player_controller, float delta_time, Rotator<float>* rot, Rotator<float>* delta_rot);
static void process_view_rotation(sdk::APlayerCameraManager* pcm, float delta_time, Rotator<float>* rot, Rotator<float>* delta_rot);

void pre_update_view_rotation(Rotator<float>* rot);
void update_view_rotation(Rotator<float>* rot);
void pre_update_view_rotation(sdk::UObject* reference_obj, Rotator<float>* rot);
void update_view_rotation(sdk::UObject* reference_obj, Rotator<float>* rot);

FFakeStereoRenderingHook* m_stereo_hook{nullptr};

Expand Down

0 comments on commit 3cb9b25

Please sign in to comment.