Added INI support, excludes disenchantable items by default
This commit is contained in:
parent
81b174e028
commit
db410f6537
Binary file not shown.
@ -15,6 +15,8 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
|||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
find_path(SIMPLEINI_INCLUDE_DIRS "ConvertUTF.c")
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in
|
${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
||||||
@ -47,7 +49,9 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/src>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/src>
|
||||||
$<INSTALL_INTERFACE:src>)
|
$<INSTALL_INTERFACE:src>
|
||||||
|
${SIMPLEINI_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME}
|
target_include_directories(${PROJECT_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
@ -24,6 +24,8 @@ namespace ArtifactTracker
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton());
|
||||||
|
|
||||||
const auto dataHandler = RE::TESDataHandler::GetSingleton();
|
const auto dataHandler = RE::TESDataHandler::GetSingleton();
|
||||||
|
|
||||||
if (!dataHandler) {
|
if (!dataHandler) {
|
||||||
@ -44,10 +46,13 @@ namespace ArtifactTracker
|
|||||||
const auto recipeKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xF5CB0, "Skyrim.esm"); // VendorItemRecipe
|
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 excludeKeywords = dataHandler->LookupForm<RE::BGSListForm>(0x801, "Artifact Tracker.esp"); // ETR_ExcludeMiscKeywords
|
||||||
const auto dummyKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xF3E6C, "Skyrim.esm"); // Dummy
|
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 extraArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xDE3FD3, "Update.esm"); // ETR_ExtraArtifact
|
||||||
const auto notArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xDE3FD4, "Update.esm"); // ETR_NotArtifact
|
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");
|
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.");
|
RE::DebugMessageBox("Unable to load data from Artifact Tracker.esp, the mod is disabled.");
|
||||||
return false;
|
return false;
|
||||||
@ -55,20 +60,36 @@ namespace ArtifactTracker
|
|||||||
|
|
||||||
// Preloading item lists
|
// 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);
|
g_artifactFormTypes.insert(RE::FormType::Weapon);
|
||||||
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectWEAP>()) {
|
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)) {
|
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[form->formID] = form;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
g_artifactMap.erase(0x1F4); // Unarmed
|
g_artifactMap.erase(0x1F4); // Unarmed
|
||||||
|
|
||||||
g_artifactFormTypes.insert(RE::FormType::Armor);
|
g_artifactFormTypes.insert(RE::FormType::Armor);
|
||||||
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectARMO>()) {
|
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectARMO>()) {
|
||||||
if (form->GetPlayable() && !form->IsDeleted() && !form->HasKeyword(dummyKeyword) && !form->HasKeyword(notArtifactKeyword)) {
|
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[form->formID] = form;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
g_artifactMap.erase(0xD64); // SkinNaked
|
g_artifactMap.erase(0xD64); // SkinNaked
|
||||||
g_artifactMap.erase(0x69CE3); // SkinNakedBeast
|
g_artifactMap.erase(0x69CE3); // SkinNakedBeast
|
||||||
g_artifactMap.erase(0xCDD86); // SkinNakedWerewolfBeast
|
g_artifactMap.erase(0xCDD86); // SkinNakedWerewolfBeast
|
||||||
@ -82,7 +103,7 @@ namespace ArtifactTracker
|
|||||||
|
|
||||||
g_artifactFormTypes.insert(RE::FormType::Misc);
|
g_artifactFormTypes.insert(RE::FormType::Misc);
|
||||||
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectMISC>()) {
|
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;
|
g_artifactMap[form->formID] = form;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,8 +142,16 @@ namespace ArtifactTracker
|
|||||||
|
|
||||||
OnGameLoad();
|
OnGameLoad();
|
||||||
EventListener::Install();
|
EventListener::Install();
|
||||||
|
|
||||||
g_bLoaded = true;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ namespace {
|
|||||||
if (message->type == MessagingInterface::kPostLoad) {
|
if (message->type == MessagingInterface::kPostLoad) {
|
||||||
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton());
|
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton());
|
||||||
} else if (message->type == MessagingInterface::kNewGame || message->type == MessagingInterface::kPreLoadGame) {
|
} else if (message->type == MessagingInterface::kNewGame || message->type == MessagingInterface::kPreLoadGame) {
|
||||||
SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton());
|
|
||||||
ArtifactTracker::Init(); // if KID is not installed
|
ArtifactTracker::Init(); // if KID is not installed
|
||||||
} else if (message->type == MessagingInterface::kPostLoadGame) {
|
} else if (message->type == MessagingInterface::kPostLoadGame) {
|
||||||
ArtifactTracker::OnGameLoad(); // refresh g_persistentMap from savegame
|
ArtifactTracker::OnGameLoad(); // refresh g_persistentMap from savegame
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <SimpleIni.h>
|
||||||
|
|
||||||
inline void ListRemoveItem(RE::BGSListForm* a_List, RE::TESForm* a_form)
|
inline void ListRemoveItem(RE::BGSListForm* a_List, RE::TESForm* a_form)
|
||||||
{
|
{
|
||||||
using func_t = decltype(&ListRemoveItem);
|
using func_t = decltype(&ListRemoveItem);
|
||||||
@ -129,3 +131,50 @@ inline bool IsInSameCell(RE::TESObjectREFR* ref)
|
|||||||
{
|
{
|
||||||
return ref && (ref->GetParentCell() == RE::PlayerCharacter::GetSingleton()->GetParentCell());
|
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());
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,8 @@
|
|||||||
"plugin": {
|
"plugin": {
|
||||||
"description": "Build the SKSE plugin.",
|
"description": "Build the SKSE plugin.",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"commonlibsse-ng"
|
"commonlibsse-ng",
|
||||||
|
"simpleini"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user