From 76d611147a3b8b1a8f979984269c6146c793cade Mon Sep 17 00:00:00 2001 From: Eddoursul Date: Thu, 4 Jul 2024 17:09:06 +0200 Subject: [PATCH] Added INI settings --- src/EventListener.cpp | 30 ++++++++++---- src/IniLoader.h | 91 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 src/IniLoader.h diff --git a/src/EventListener.cpp b/src/EventListener.cpp index 75104e1..9c1184d 100644 --- a/src/EventListener.cpp +++ b/src/EventListener.cpp @@ -1,9 +1,21 @@ #include "EventListener.h" +#include "IniLoader.h" +#include "Util.h" RE::BGSKeyword* EventListener::keywordGem; RE::BGSKeyword* EventListener::keywordHide; RE::BGSKeyword* EventListener::keywordIngot; +inline std::map g_settings{ + { "fRadius", 350.0f }, + { "bPickupGold", true }, + { "bPickupLockpicks", true }, + { "bPickupMaterials", true }, + { "bPickupArrows", true }, + { "bPickupFlora", true }, + { "bPickupIngredients", true }, +}; + auto EventListener::GetSingleton() -> EventListener* { static EventListener singleton{}; @@ -12,6 +24,8 @@ auto EventListener::GetSingleton() -> EventListener* void EventListener::Install() { + LoadINI(&g_settings, std::format("Data/SKSE/Plugins/{}.ini", SKSE::PluginDeclaration::GetSingleton()->GetName()).c_str()); + RE::ScriptEventSourceHolder::GetSingleton()->GetEventSource()->AddEventSink(EventListener::GetSingleton()); } @@ -40,19 +54,19 @@ auto EventListener::ProcessEvent( RE::TESBoundObject* produceItem = nullptr; bool bIsCoinPouch = IsCoinPouch(baseObj); - bool bIsGold = bIsCoinPouch || baseObj->IsGold(); - bool bIsLockpick = baseObj->IsLockpick(); + bool bIsGold = std::any_cast(g_settings["bPickupGold"]) && (bIsCoinPouch || baseObj->IsGold()); + bool bIsLockpick = std::any_cast(g_settings["bPickupLockpicks"]) && baseObj->IsLockpick(); - RE::BGSKeywordForm* keywordForm = baseObj->Is(RE::FormType::Misc) ? baseObj->As() : nullptr; + RE::BGSKeywordForm* keywordForm = (baseObj->Is(RE::FormType::Misc) && std::any_cast(g_settings["bPickupMaterials"])) ? baseObj->As() : nullptr; bool bIsGem = keywordForm && keywordForm->HasKeyword(keywordGem); bool bIsHide = keywordForm && keywordForm->HasKeyword(keywordHide); bool bIsIngot = keywordForm && keywordForm->HasKeyword(keywordIngot); - bool bIsAmmo = (baseObj->IsAmmo() || baseObj->Is(RE::FormType::Projectile)) && baseObj->GetPlayable(); + bool bIsAmmo = std::any_cast(g_settings["bPickupArrows"]) && (baseObj->IsAmmo() || baseObj->Is(RE::FormType::Projectile)) && baseObj->GetPlayable(); - bool bIsFlora = !bIsCoinPouch && baseObj->Is(RE::FormType::Flora) && (produceItem = baseObj->As()->produceItem); - bool bIsTree = baseObj->Is(RE::FormType::Tree) && (produceItem = baseObj->As()->produceItem); - bool bIsIngredient = baseObj->Is(RE::FormType::Ingredient); + bool bIsFlora = std::any_cast(g_settings["bPickupFlora"]) && !bIsCoinPouch && baseObj->Is(RE::FormType::Flora) && (produceItem = baseObj->As()->produceItem); + bool bIsTree = std::any_cast(g_settings["bPickupFlora"]) && baseObj->Is(RE::FormType::Tree) && (produceItem = baseObj->As()->produceItem); + bool bIsIngredient = std::any_cast(g_settings["bPickupIngredients"]) && baseObj->Is(RE::FormType::Ingredient); if (!bIsGold && !bIsLockpick && !bIsGem && !bIsHide && !bIsIngot && !bIsAmmo && !bIsFlora && !bIsTree && !bIsIngredient) { return RE::BSEventNotifyControl::kContinue; @@ -70,7 +84,7 @@ auto EventListener::ProcessEvent( std::unordered_set refQueue; - TES->ForEachReferenceInRange(baseRef, 300.0f, [&](RE::TESObjectREFR* a_ref) { + TES->ForEachReferenceInRange(baseRef, std::any_cast(g_settings["fRadius"]), [&](RE::TESObjectREFR* a_ref) { if (!a_ref) { return RE::BSContainer::ForEachResult::kContinue; } diff --git a/src/IniLoader.h b/src/IniLoader.h new file mode 100644 index 0000000..3fecc2c --- /dev/null +++ b/src/IniLoader.h @@ -0,0 +1,91 @@ +#pragma once + +#include +#include + +inline void LoadINI(std::map* settings, const char* iniPath) +{ + for (auto it = settings->begin(); it != settings->end(); it++) { + if (it->first[0] == 'f') { + logger::info("[DEFAULT] {} = {}", it->first, std::any_cast(it->second)); + } else if (it->first[0] == 'i') { + logger::info("[DEFAULT] {} = {}", it->first, std::any_cast(it->second)); + } else if (it->first[0] == 's') { + logger::info("[DEFAULT] {} = {}", it->first, std::any_cast(it->second)); + } else { + logger::info("[DEFAULT] {} = {}", it->first, std::any_cast(it->second)); + } + } + + if (!std::filesystem::exists(iniPath)) { + logger::warn("{} does not exist, using default values.", iniPath); + return; + } + + try { + CSimpleIniA ini; + ini.SetUnicode(false); + ini.SetMultiKey(false); + SI_Error rc = ini.LoadFile(iniPath); + + if (rc < 0) { + logger::error("{}", rc); + return; + } + + std::list keysList; + ini.GetAllKeys("", keysList); + + bool bUpdateINI = false; + for (auto it = settings->begin(); it != settings->end(); it++) { + try { + bool bExists = false; + for (const auto& k : keysList) { + if (it->first == k.pItem) { + if (k.pItem[0] == 'f') { + float fValue = ini.GetDoubleValue("", k.pItem, std::any_cast(settings->at(k.pItem))); + settings->insert_or_assign(k.pItem, fValue); + logger::info("[INI] {} = {}", k.pItem, fValue); + } else if (k.pItem[0] == 'i') { + int iValue = ini.GetLongValue("", k.pItem, std::any_cast(settings->at(k.pItem))); + settings->insert_or_assign(k.pItem, iValue); + logger::info("[INI] {} = {}", k.pItem, iValue); + } else if (k.pItem[0] == 's') { + const char* sValue = ini.GetValue("", k.pItem, std::any_cast(settings->at(k.pItem))); + settings->insert_or_assign(k.pItem, sValue); + logger::info("[INI] {} = {}", k.pItem, sValue); + } else { + bool bValue = ini.GetBoolValue("", k.pItem, std::any_cast(settings->at(k.pItem))); + settings->insert_or_assign(k.pItem, bValue); + logger::info("[INI] {} = {}", k.pItem, bValue); + } + bExists = true; + break; + } + } + if (!bExists) { + if (it->first.c_str()[0] == 'f') { + ini.SetDoubleValue("", it->first.c_str(), std::any_cast(it->second)); + } else if (it->first.c_str()[0] == 'i') { + ini.SetLongValue("", it->first.c_str(), std::any_cast(it->second)); + } else if (it->first.c_str()[0] == 's') { + ini.SetValue("", it->first.c_str(), std::any_cast(it->second)); + } else { + ini.SetBoolValue("", it->first.c_str(), std::any_cast(it->second)); + } + bUpdateINI = true; + } + } catch (const std::exception& e) { + logger::error("[INI] {} = {}", it->first, e.what()); + } + } + + if (bUpdateINI) { + logger::info("New settings detected, adding to {}", iniPath); + ini.SaveFile(iniPath); + } + + } catch (const std::exception& e) { + logger::error("{}", e.what()); + } +}