diff --git a/src/DirectionalMovementHandler.cpp b/src/DirectionalMovementHandler.cpp index 6c2442e..7ef8126 100644 --- a/src/DirectionalMovementHandler.cpp +++ b/src/DirectionalMovementHandler.cpp @@ -39,35 +39,35 @@ DirectionalMovementHandler* DirectionalMovementHandler::GetSingleton() return std::addressof(singleton); } -void DirectionalMovementHandler::Register() +void DirectionalMovementHandler::RegisterAnimationEvents() { - auto playerCharacter = RE::PlayerCharacter::GetSingleton(); - bool bSuccess = playerCharacter->AddAnimationGraphEventSink(DirectionalMovementHandler::GetSingleton()); - if (bSuccess) { - logger::info("Registered {}"sv, typeid(RE::BSAnimationGraphEvent).name()); - } else { - RE::BSAnimationGraphManagerPtr graphManager; - playerCharacter->GetAnimationGraphManager(graphManager); - bool bSinked = false; - if (graphManager) { - for (auto& animationGraph : graphManager->graphs) { - if (bSinked) { - break; - } - auto eventSource = animationGraph->GetEventSource(); - for (auto& sink : eventSource->sinks) { - if (sink == DirectionalMovementHandler::GetSingleton()) { - bSinked = true; - break; - } - } - } + auto player = RE::PlayerCharacter::GetSingleton(); + if (!player) { + return; + } + + RE::BSAnimationGraphManagerPtr graphManager; + player->GetAnimationGraphManager(graphManager); + if (!graphManager || graphManager->graphs.empty()) { + return; + } + + RE::BShkbAnimationGraphPtr graph = graphManager->graphs[0]; + if (!graph) { + return; + } + + auto eventSource = graph->GetEventSource(); + if (!eventSource) { + return; + } + + for (const auto& sink : eventSource->sinks) { + if (sink == this) { + return; } - - if (!bSinked) { - logger::info("Failed to register {}"sv, typeid(RE::BSAnimationGraphEvent).name()); - } } + eventSource->AddEventSink(this); } constexpr uint32_t hash(const char* data, size_t const size) noexcept @@ -164,6 +164,8 @@ void DirectionalMovementHandler::Update() return; } + RegisterAnimationEvents(); + Settings::UpdateGlobals(); ProgressTimers(); @@ -1316,8 +1318,41 @@ bool DirectionalMovementHandler::IFPV_IsFirstPerson() const bool DirectionalMovementHandler::ImprovedCamera_IsFirstPerson() const { - if (_ImprovedCamera_IsFirstPerson) { - return *_ImprovedCamera_IsFirstPerson; + if (_bICInstalled) { + // Reddit version 1.0.0.4 + if (_ImprovedCamera_IsFirstPerson) { + return *_ImprovedCamera_IsFirstPerson; + } + + auto camera = RE::PlayerCamera::GetSingleton(); + if (!camera) { + return false; + } + + // Normal first person. + if (camera->IsInFirstPerson()) { + return true; + } + // TFC. + if (camera->IsInFreeCameraMode()) { + return false; + } + + auto currentState = camera ? camera->currentState.get() : nullptr; + if (!currentState) { + return false; + } + + // CameraID correction, not all camera states inherit from ThirdPersonState. + auto cameraID = currentState->id; + if (cameraID < RE::CameraState::kThirdPerson || cameraID > RE::CameraState::kDragon) { + cameraID = RE::CameraState::kThirdPerson; + } + // Fake first person. + auto thirdPersonState = static_cast(camera->cameraStates[cameraID].get()); + if (thirdPersonState && thirdPersonState->targetZoomOffset == -0.275f) { + return true; + } } return false; @@ -2931,7 +2966,7 @@ void DirectionalMovementHandler::InitCameraModsCompatibility() _bACCInstalled = true; } - if (GetModuleHandle("ImprovedCameraSE.dll")) { + if (GetModuleHandle("ImprovedCameraSE.dll") || GetModuleHandle("ImprovedCameraNG.dll")) { _bICInstalled = true; } @@ -2973,6 +3008,7 @@ void DirectionalMovementHandler::InitCameraModsCompatibility() if (v0 == ICSignatures::FileVersion[0] && v1 == ICSignatures::FileVersion[1] && v2 == ICSignatures::FileVersion[2] && v3 == ICSignatures::FileVersion[3]) { + _bICInstalled = true; _ImprovedCamera_IsFirstPerson = reinterpret_cast(reinterpret_cast(hMod) + 0x4d510); } } diff --git a/src/DirectionalMovementHandler.h b/src/DirectionalMovementHandler.h index a1c94b6..d80c3dc 100644 --- a/src/DirectionalMovementHandler.h +++ b/src/DirectionalMovementHandler.h @@ -42,7 +42,6 @@ class DirectionalMovementHandler : using EventResult = RE::BSEventNotifyControl; static DirectionalMovementHandler* GetSingleton(); - static void Register(); // override BSTEventSink virtual EventResult ProcessEvent(const RE::BSAnimationGraphEvent* a_event, RE::BSTEventSource* a_eventSource) override; @@ -58,6 +57,7 @@ class DirectionalMovementHandler : void UpdateSwimmingPitchOffset(); void UpdateMountedArchery(); void ProgressTimers(); + void RegisterAnimationEvents(); void OnDodge(); diff --git a/src/Hooks.h b/src/Hooks.h index f394ad0..b725215 100644 --- a/src/Hooks.h +++ b/src/Hooks.h @@ -460,7 +460,7 @@ namespace Hooks static inline REL::Relocation _SetInt; }; - class PlayerCameraHook // to fix Improved Camera breaking player pitch during target lock + class PlayerCameraHook // to fix freeRotation.y (pitch) breaking when freeRotationEnabled is active during target lock. { public: static void Hook() diff --git a/src/main.cpp b/src/main.cpp index 59279c3..47d14a1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,7 +32,6 @@ void MessageHandler(SKSE::MessagingInterface::Message* a_msg) case SKSE::MessagingInterface::kNewGame: APIs::RequestAPIs(); Settings::OnPostLoadGame(); - DirectionalMovementHandler::Register(); break; } }