Highlight dropped books
This commit is contained in:
parent
a41283638b
commit
1c89562e2a
@ -6,6 +6,8 @@ RE::TESEffectShader* EventListener::regularBookShader;
|
||||
RE::TESEffectShader* EventListener::spellBookShader;
|
||||
RE::TESEffectShader* EventListener::skillBookShader;
|
||||
|
||||
inline bool bScanDroppedBooks = false;
|
||||
|
||||
auto EventListener::GetSingleton() -> EventListener*
|
||||
{
|
||||
static EventListener singleton{};
|
||||
@ -29,9 +31,24 @@ void EventListener::Install()
|
||||
LoadINI(&settings, std::format("Data/SKSE/Plugins/{}.ini", SKSE::PluginDeclaration::GetSingleton()->GetName()).c_str());
|
||||
|
||||
RE::TESEffectShader* defaultShader = RE::TESForm::LookupByID<RE::TESEffectShader>(0xC5EF7);
|
||||
EventListener::regularBookShader = retrieveFormByString(std::any_cast<const char*>(settings["sRegularBookShader"]), defaultShader)->As<RE::TESEffectShader>();
|
||||
EventListener::spellBookShader = retrieveFormByString(std::any_cast<const char*>(settings["sSpellBookShader"]), defaultShader)->As<RE::TESEffectShader>();
|
||||
EventListener::skillBookShader = retrieveFormByString(std::any_cast<const char*>(settings["sSkillBookShader"]), defaultShader)->As<RE::TESEffectShader>();
|
||||
|
||||
EventListener::regularBookShader = retrieveFormByString(std::any_cast<std::string>(settings["sRegularBookShader"]), defaultShader)->As<RE::TESEffectShader>();
|
||||
EventListener::spellBookShader = retrieveFormByString(std::any_cast<std::string>(settings["sSpellBookShader"]), defaultShader)->As<RE::TESEffectShader>();
|
||||
EventListener::skillBookShader = retrieveFormByString(std::any_cast<std::string>(settings["sSkillBookShader"]), defaultShader)->As<RE::TESEffectShader>();
|
||||
}
|
||||
|
||||
auto EventListener::ProcessEvent(
|
||||
const RE::TESContainerChangedEvent* a_event,
|
||||
RE::BSTEventSource<RE::TESContainerChangedEvent>* 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(
|
||||
@ -52,27 +69,7 @@ auto EventListener::ProcessEvent(
|
||||
-> RE::BSEventNotifyControl
|
||||
{
|
||||
if (a_event && a_event->attached && a_event->reference) {
|
||||
if (const auto baseObj = a_event->reference->GetBaseObject(); baseObj->IsBook()) {
|
||||
if (const auto bookObj = baseObj->As<RE::TESObjectBOOK>()) {
|
||||
if (!bookObj->IsRead()) {
|
||||
RE::TESObjectREFR* ref = a_event->reference.get();
|
||||
|
||||
auto shader = EventListener::regularBookShader;
|
||||
|
||||
if (bookObj->TeachesSpell()) {
|
||||
shader = EventListener::spellBookShader;
|
||||
} else if (bookObj->TeachesSkill()) {
|
||||
shader = EventListener::skillBookShader;
|
||||
}
|
||||
|
||||
SKSE::GetTaskInterface()->AddTask([ref, shader]() {
|
||||
if (ref) {
|
||||
ref->ApplyEffectShader(shader);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
TryAddBookRefShader(a_event->reference.get());
|
||||
}
|
||||
|
||||
return RE::BSEventNotifyControl::kContinue;
|
||||
@ -83,9 +80,30 @@ auto EventListener::ProcessEvent(
|
||||
RE::BSTEventSource<RE::MenuOpenCloseEvent>* a_eventSource)
|
||||
-> RE::BSEventNotifyControl
|
||||
{
|
||||
if (a_event && !a_event->opening && a_event->menuName == RE::BookMenu::MENU_NAME) {
|
||||
if (a_event) {
|
||||
if (a_event->opening) {
|
||||
if (a_event->menuName == RE::InventoryMenu::MENU_NAME) {
|
||||
RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource<RE::TESContainerChangedEvent>()->AddEventSink(EventListener::GetSingleton());
|
||||
}
|
||||
} else {
|
||||
if (a_event->menuName == RE::InventoryMenu::MENU_NAME) {
|
||||
RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource<RE::TESContainerChangedEvent>()->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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RE::BSEventNotifyControl::kContinue;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
class EventListener :
|
||||
public RE::BSTEventSink<RE::TESContainerChangedEvent>,
|
||||
public RE::BSTEventSink<RE::BGSActorCellEvent>,
|
||||
public RE::BSTEventSink<RE::TESCellAttachDetachEvent>,
|
||||
public RE::BSTEventSink<RE::MenuOpenCloseEvent>
|
||||
@ -15,6 +16,11 @@ public:
|
||||
|
||||
static void Install();
|
||||
|
||||
auto ProcessEvent(
|
||||
const RE::TESContainerChangedEvent* a_event,
|
||||
RE::BSTEventSource<RE::TESContainerChangedEvent>* a_eventSource)
|
||||
-> RE::BSEventNotifyControl override;
|
||||
|
||||
auto ProcessEvent(
|
||||
const RE::BGSActorCellEvent* a_event,
|
||||
RE::BSTEventSource<RE::BGSActorCellEvent>* a_eventSource)
|
||||
|
52
src/Util.h
52
src/Util.h
@ -2,6 +2,33 @@
|
||||
|
||||
#include "EventListener.h"
|
||||
|
||||
inline void TryAddBookRefShader(RE::TESObjectREFR* a_ref)
|
||||
{
|
||||
if (!a_ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto baseObj = a_ref->GetBaseObject(); baseObj->IsBook()) {
|
||||
if (const auto bookObj = baseObj->As<RE::TESObjectBOOK>()) {
|
||||
if (!bookObj->IsRead()) {
|
||||
auto shader = EventListener::regularBookShader;
|
||||
|
||||
if (bookObj->TeachesSpell()) {
|
||||
shader = EventListener::spellBookShader;
|
||||
} else if (bookObj->TeachesSkill()) {
|
||||
shader = EventListener::skillBookShader;
|
||||
}
|
||||
|
||||
SKSE::GetTaskInterface()->AddTask([a_ref, shader]() {
|
||||
if (a_ref) {
|
||||
a_ref->ApplyEffectShader(shader);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearOldShaders()
|
||||
{
|
||||
if (const auto processLists = RE::ProcessLists::GetSingleton()) {
|
||||
@ -21,31 +48,18 @@ inline void ClearOldShaders()
|
||||
}
|
||||
}
|
||||
|
||||
// std::string str = "adsf+qwer+poui+fdgh";
|
||||
// std::vector<std::string> v = split (str, '+');
|
||||
inline std::vector<std::string> split(const std::string& s, char delim)
|
||||
inline RE::TESForm* retrieveFormByString(std::string a_str, RE::TESForm* a_defaultForm)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
|
||||
while (getline(ss, item, delim)) {
|
||||
result.push_back(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline RE::TESForm* retrieveFormByString(const char* a_str, RE::TESForm* a_defaultForm)
|
||||
{
|
||||
std::vector<std::string> segments = split(a_str, '@');
|
||||
int pos = a_str.find_first_of('@');
|
||||
std::string sHex = a_str.substr(pos + 1),
|
||||
sFilename = a_str.substr(0, pos);
|
||||
|
||||
RE::FormID id;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << segments[1];
|
||||
ss << std::hex << sHex;
|
||||
ss >> id;
|
||||
|
||||
RE::TESForm* result = RE::TESDataHandler::GetSingleton()->LookupForm(id, segments[0]);
|
||||
RE::TESForm* result = RE::TESDataHandler::GetSingleton()->LookupForm(id, sFilename);
|
||||
|
||||
if (!result) {
|
||||
logger::error("Unable to retrieve {}, using default value", a_str);
|
||||
|
Loading…
Reference in New Issue
Block a user