1

Added INI support, excludes disenchantable items by default

This commit is contained in:
Eddoursul 2022-07-05 21:17:52 +02:00
parent 81b174e028
commit db410f6537
6 changed files with 92 additions and 10 deletions

Binary file not shown.

View File

@ -15,6 +15,8 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
include(GNUInstallDirs)
find_path(SIMPLEINI_INCLUDE_DIRS "ConvertUTF.c")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in
${CMAKE_CURRENT_BINARY_DIR}/version.rc
@ -47,7 +49,9 @@ target_include_directories(${PROJECT_NAME}
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/src>
$<INSTALL_INTERFACE:src>)
$<INSTALL_INTERFACE:src>
${SIMPLEINI_INCLUDE_DIRS}
)
target_include_directories(${PROJECT_NAME}
PUBLIC

View File

@ -24,6 +24,8 @@ namespace ArtifactTracker
return true;
}
SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton());
const auto dataHandler = RE::TESDataHandler::GetSingleton();
if (!dataHandler) {
@ -44,10 +46,13 @@ namespace ArtifactTracker
const auto recipeKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xF5CB0, "Skyrim.esm"); // VendorItemRecipe
const auto excludeKeywords = dataHandler->LookupForm<RE::BGSListForm>(0x801, "Artifact Tracker.esp"); // ETR_ExcludeMiscKeywords
const auto dummyKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xF3E6C, "Skyrim.esm"); // Dummy
const auto disallowEnchanting = dataHandler->LookupForm<RE::BGSKeyword>(0xC27BD, "Skyrim.esm"); // MagicDisallowEnchanting
const auto daedricArtifact = dataHandler->LookupForm<RE::BGSKeyword>(0xA8668, "Skyrim.esm"); // DaedricArtifact
const auto extraArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xDE3FD3, "Update.esm"); // ETR_ExtraArtifact
const auto notArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xDE3FD4, "Update.esm"); // ETR_NotArtifact
if (!g_cellContainer || !g_listNew || !g_listStored || !g_listFound || !g_persistentStorage || !g_homeKeyword || !recipeKeyword || !excludeKeywords || !dummyKeyword || !extraArtifactKeyword || !notArtifactKeyword) {
if (!g_cellContainer || !g_listNew || !g_listStored || !g_listFound || !g_persistentStorage || !g_homeKeyword || !recipeKeyword || !excludeKeywords || !dummyKeyword || !extraArtifactKeyword || !notArtifactKeyword || !disallowEnchanting || !daedricArtifact) {
SKSE::log::warn("Unable to load data from Artifact Tracker.esp");
RE::DebugMessageBox("Unable to load data from Artifact Tracker.esp, the mod is disabled.");
return false;
@ -55,18 +60,34 @@ namespace ArtifactTracker
// Preloading item lists
std::map<std::string, bool> settings{
{ "ExcludeDisenchantableItems", true },
{ "DumpItemNames", false },
};
LoadINI(&settings, "Data/SKSE/Plugins/ArtifactTracker.ini");
bool bExcludeDisenchantableItems = settings.at("ExcludeDisenchantableItems");
g_artifactFormTypes.insert(RE::FormType::Weapon);
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectWEAP>()) {
if (form->GetPlayable() && !form->IsBound() && !form->weaponData.flags.all(RE::TESObjectWEAP::Data::Flag::kCantDrop) && !form->IsDeleted() && !form->HasKeyword(dummyKeyword) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form;
if (form->GetPlayable() && !form->IsBound() && !form->weaponData.flags.all(RE::TESObjectWEAP::Data::Flag::kCantDrop) && !form->IsDeleted() && !form->HasKeyword(dummyKeyword)) {
if (!bExcludeDisenchantableItems || !form->As<RE::TESEnchantableForm>()->formEnchanting || form->HasKeyword(disallowEnchanting) || form->HasKeyword(daedricArtifact) || form->HasKeyword(extraArtifactKeyword)) {
if (!form->HasKeyword(notArtifactKeyword) && strlen(form->GetName()) > 0) {
g_artifactMap[form->formID] = form;
}
}
}
}
g_artifactMap.erase(0x1F4); // Unarmed
g_artifactFormTypes.insert(RE::FormType::Armor);
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectARMO>()) {
if (form->GetPlayable() && !form->IsDeleted() && !form->HasKeyword(dummyKeyword) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form;
if (form->GetPlayable() && !form->IsDeleted() && !form->HasKeyword(dummyKeyword)) {
if (!bExcludeDisenchantableItems || !form->As<RE::TESEnchantableForm>()->formEnchanting || form->HasKeyword(disallowEnchanting) || form->HasKeyword(daedricArtifact) || form->HasKeyword(extraArtifactKeyword)) {
if (!form->HasKeyword(notArtifactKeyword) && strlen(form->GetName()) > 0) {
g_artifactMap[form->formID] = form;
}
}
}
}
g_artifactMap.erase(0xD64); // SkinNaked
@ -82,7 +103,7 @@ namespace ArtifactTracker
g_artifactFormTypes.insert(RE::FormType::Misc);
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectMISC>()) {
if (form->GetPlayable() && !form->IsDeleted() && (form->HasKeyword(extraArtifactKeyword) || !form->HasKeywordInList(excludeKeywords, false)) && !form->HasKeyword(notArtifactKeyword)) {
if (form->GetPlayable() && !form->IsDeleted() && (form->HasKeyword(extraArtifactKeyword) || !form->HasKeywordInList(excludeKeywords, false)) && !form->HasKeyword(notArtifactKeyword) && strlen(form->GetName()) > 0) {
g_artifactMap[form->formID] = form;
}
}
@ -121,8 +142,16 @@ namespace ArtifactTracker
OnGameLoad();
EventListener::Install();
g_bLoaded = true;
SKSE::log::info("Total artifacts: {}", g_artifactMap.size());
if (settings.at("DumpItemNames")) {
for (const auto& item : g_artifactMap) {
SKSE::log::info("[{:08X}] {}", item.second->formID, item.second->GetName());
}
}
return true;
}

View File

@ -32,7 +32,6 @@ namespace {
if (message->type == MessagingInterface::kPostLoad) {
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton());
} else if (message->type == MessagingInterface::kNewGame || message->type == MessagingInterface::kPreLoadGame) {
SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton());
ArtifactTracker::Init(); // if KID is not installed
} else if (message->type == MessagingInterface::kPostLoadGame) {
ArtifactTracker::OnGameLoad(); // refresh g_persistentMap from savegame

View File

@ -1,5 +1,7 @@
#pragma once
#include <SimpleIni.h>
inline void ListRemoveItem(RE::BGSListForm* a_List, RE::TESForm* a_form)
{
using func_t = decltype(&ListRemoveItem);
@ -129,3 +131,50 @@ inline bool IsInSameCell(RE::TESObjectREFR* ref)
{
return ref && (ref->GetParentCell() == RE::PlayerCharacter::GetSingleton()->GetParentCell());
}
inline void LoadINI(std::map<std::string, bool>* settings, const char* iniPath)
{
for (auto it = settings->begin(); it != settings->end(); it++) {
SKSE::log::info("[DEFAULT] {} = {}", it->first, it->second);
}
if (!std::filesystem::exists(iniPath)) {
SKSE::log::warn("{} does not exists, using default values.", iniPath);
return;
}
try {
CSimpleIniA ini;
ini.SetUnicode(false);
ini.SetMultiKey(false);
ini.LoadFile(iniPath);
std::list<CSimpleIniA::Entry> keysList;
ini.GetAllKeys("", keysList);
bool bUpdateINI = false;
for (auto it = settings->begin(); it != settings->end(); it++) {
bool bExists = false;
for (const auto& k : keysList) {
if (it->first == k.pItem) {
settings->insert_or_assign(k.pItem, ini.GetBoolValue("", k.pItem, settings->at(k.pItem)));
SKSE::log::info("[INI] {} = {}", k.pItem, settings->at(k.pItem));
bExists = true;
break;
}
}
if (!bExists) {
ini.SetBoolValue("", it->first.c_str(), it->second);
bUpdateINI = true;
}
}
if (bUpdateINI) {
SKSE::log::info("New settings detected, adding to ArtifactTracker.ini");
ini.SaveFile(iniPath);
}
} catch (const std::exception& e) {
SKSE::log::error(e.what());
}
}

View File

@ -10,7 +10,8 @@
"plugin": {
"description": "Build the SKSE plugin.",
"dependencies": [
"commonlibsse-ng"
"commonlibsse-ng",
"simpleini"
]
}
},