From 2b38e7710154c49cdb6a038ee15da06907c9d177 Mon Sep 17 00:00:00 2001 From: Eddoursul Date: Sun, 7 Jul 2024 17:43:00 +0200 Subject: [PATCH] Use a Load3D hook --- src/EventListener.cpp | 65 +++++++------------------------------------ src/EventListener.h | 12 -------- src/Hooks.h | 24 ++++++++++++++++ src/Util.h | 25 +++++++++-------- 4 files changed, 47 insertions(+), 79 deletions(-) create mode 100644 src/Hooks.h diff --git a/src/EventListener.cpp b/src/EventListener.cpp index 290140a..9d0cbef 100644 --- a/src/EventListener.cpp +++ b/src/EventListener.cpp @@ -1,13 +1,12 @@ #include "EventListener.h" #include "IniLoader.h" #include "Util.h" +#include "Hooks.h" RE::TESEffectShader* EventListener::regularBookShader; RE::TESEffectShader* EventListener::spellBookShader; RE::TESEffectShader* EventListener::skillBookShader; -inline bool bScanDroppedBooks = false; - auto EventListener::GetSingleton() -> EventListener* { static EventListener singleton{}; @@ -18,14 +17,15 @@ void EventListener::Install() { logger::info("{} is initializing...", SKSE::PluginDeclaration::GetSingleton()->GetName()); - RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource()->AddEventSink(EventListener::GetSingleton()); + SetBookShaderHook::Install(); + RE::PlayerCharacter::GetSingleton()->AsBGSActorCellEventSource()->AddEventSink(EventListener::GetSingleton()); RE::UI::GetSingleton()->AddEventSink(EventListener::GetSingleton()); std::map settings{ - { "sRegularBookShader", "Skyrim.esm@D2057" }, - { "sSpellBookShader", "Skyrim.esm@C5EF7" }, - { "sSkillBookShader", "Skyrim.esm@C34B1" }, + { "sRegularBookShader", "Skyrim.esm@C723A" }, + { "sSpellBookShader", "Skyrim.esm@B6BF9" }, + { "sSkillBookShader", "Skyrim.esm@B6BFA" }, }; LoadINI(&settings, std::format("Data/SKSE/Plugins/{}.ini", SKSE::PluginDeclaration::GetSingleton()->GetName()).c_str()); @@ -37,39 +37,13 @@ void EventListener::Install() EventListener::skillBookShader = retrieveFormByString(std::any_cast(settings["sSkillBookShader"]), defaultShader)->As(); } -auto EventListener::ProcessEvent( - const RE::TESContainerChangedEvent* a_event, - RE::BSTEventSource* a_eventSource) - -> RE::BSEventNotifyControl -{ - if (!a_event->newContainer && a_event->oldContainer == 0x14) { - if (const auto baseObj = RE::TESForm::LookupByID(a_event->baseObj); baseObj->Is(RE::FormType::Book)) { - bScanDroppedBooks = true; - } - } - - return RE::BSEventNotifyControl::kContinue; -} - auto EventListener::ProcessEvent( const RE::BGSActorCellEvent* a_event, RE::BSTEventSource* a_eventSource) -> RE::BSEventNotifyControl { if (a_event->flags == RE::BGSActorCellEvent::CellFlag::kEnter) { - SKSE::GetTaskInterface()->AddTask(ClearOldShaders); - } - - return RE::BSEventNotifyControl::kContinue; -} - -auto EventListener::ProcessEvent( - const RE::TESCellAttachDetachEvent* a_event, - RE::BSTEventSource* a_eventSource) - -> RE::BSEventNotifyControl -{ - if (a_event && a_event->attached && a_event->reference) { - TryAddBookRefShader(a_event->reference.get()); + ClearOldShaders(); } return RE::BSEventNotifyControl::kContinue; @@ -80,28 +54,9 @@ auto EventListener::ProcessEvent( RE::BSTEventSource* a_eventSource) -> RE::BSEventNotifyControl { - if (a_event) { - if (a_event->opening) { - if (a_event->menuName == RE::InventoryMenu::MENU_NAME) { - RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource()->AddEventSink(EventListener::GetSingleton()); - } - } else { - if (a_event->menuName == RE::InventoryMenu::MENU_NAME) { - RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource()->RemoveEventSink(EventListener::GetSingleton()); - - if (bScanDroppedBooks) { - bScanDroppedBooks = false; - if (const auto TES = RE::TES::GetSingleton()) { - TES->ForEachReferenceInRange(RE::PlayerCharacter::GetSingleton(), 300.0f, [](RE::TESObjectREFR* a_ref) { - TryAddBookRefShader(a_ref); - return RE::BSContainer::ForEachResult::kContinue; - }); - } - } - - } else if (a_event->menuName == RE::BookMenu::MENU_NAME) { - SKSE::GetTaskInterface()->AddTask(ClearOldShaders); - } + if (a_event && !a_event->opening) { + if (a_event->menuName == RE::BookMenu::MENU_NAME) { + ClearOldShaders(); } } diff --git a/src/EventListener.h b/src/EventListener.h index beaed34..58298bc 100644 --- a/src/EventListener.h +++ b/src/EventListener.h @@ -1,9 +1,7 @@ #pragma once class EventListener : - public RE::BSTEventSink, public RE::BSTEventSink, - public RE::BSTEventSink, public RE::BSTEventSink { public: @@ -16,21 +14,11 @@ public: static void Install(); - auto ProcessEvent( - const RE::TESContainerChangedEvent* a_event, - RE::BSTEventSource* a_eventSource) - -> RE::BSEventNotifyControl override; - auto ProcessEvent( const RE::BGSActorCellEvent* a_event, RE::BSTEventSource* a_eventSource) -> RE::BSEventNotifyControl override; - auto ProcessEvent( - const RE::TESCellAttachDetachEvent* a_event, - RE::BSTEventSource* a_eventSource) - -> RE::BSEventNotifyControl override; - auto ProcessEvent( const RE::MenuOpenCloseEvent* a_event, RE::BSTEventSource* a_eventSource) diff --git a/src/Hooks.h b/src/Hooks.h new file mode 100644 index 0000000..f0402a7 --- /dev/null +++ b/src/Hooks.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Util.h" + +struct SetBookShaderHook +{ + static RE::NiAVObject* thunk(RE::TESObjectREFR& a_this, bool a_loadInBackground) + { + const auto ret = func(a_this, a_loadInBackground); + + TryAddBookRefShader(&a_this); + + return ret; + } + + static inline REL::Relocation func; + + static void Install() + { + REL::Relocation vTable(RE::TESObjectREFR::VTABLE[0]); + func = vTable.write_vfunc(0x6A, thunk); // NiAVObject* Load3D(bool a_backgroundLoading) + logger::info("Added book shader hook"); + } +}; diff --git a/src/Util.h b/src/Util.h index 628ccbd..0c55974 100644 --- a/src/Util.h +++ b/src/Util.h @@ -31,21 +31,22 @@ inline void TryAddBookRefShader(RE::TESObjectREFR* a_ref) inline void ClearOldShaders() { - if (const auto processLists = RE::ProcessLists::GetSingleton()) { - processLists->ForEachShaderEffect([&](RE::ShaderReferenceEffect* a_shaderEffect) -> RE::BSContainer::ForEachResult { - if (a_shaderEffect && (a_shaderEffect->effectData == EventListener::regularBookShader || a_shaderEffect->effectData == EventListener::spellBookShader || a_shaderEffect->effectData == EventListener::skillBookShader) && a_shaderEffect->target) { - if (const auto targetRef = a_shaderEffect->target.get()) { - if (const auto baseObj = targetRef->GetBaseObject(); baseObj->IsBook()) { - if (baseObj->As()->IsRead()) { - a_shaderEffect->finished = true; + SKSE::GetTaskInterface()->AddTask([]() { + if (const auto processLists = RE::ProcessLists::GetSingleton()) { + processLists->ForEachShaderEffect([&](RE::ShaderReferenceEffect* a_shaderEffect) -> RE::BSContainer::ForEachResult { + if (a_shaderEffect && (a_shaderEffect->effectData == EventListener::regularBookShader || a_shaderEffect->effectData == EventListener::spellBookShader || a_shaderEffect->effectData == EventListener::skillBookShader) && a_shaderEffect->target) { + if (const auto targetRef = a_shaderEffect->target.get()) { + if (const auto baseObj = targetRef->GetBaseObject(); baseObj->IsBook()) { + if (baseObj->As()->IsRead()) { + a_shaderEffect->finished = true; + } } } } - } - - return RE::BSContainer::ForEachResult::kContinue; - }); - } + return RE::BSContainer::ForEachResult::kContinue; + }); + } + }); } inline RE::TESForm* retrieveFormByString(std::string a_str, RE::TESForm* a_defaultForm)