1

Updated to CommonLibSSE-NG 3.6 (1.6.629+ support); formlist of cells with persistent containers

This commit is contained in:
Eddoursul 2022-12-01 01:39:28 +01:00
parent 654067f863
commit 4919e92157
9 changed files with 64 additions and 37 deletions

Binary file not shown.

Binary file not shown.

View File

@ -6,7 +6,7 @@ message("Using toolchain file ${CMAKE_TOOLCHAIN_FILE}.")
######################################################################################################################## ########################################################################################################################
project( project(
ArtifactTracker ArtifactTracker
VERSION 1.0.7 VERSION 1.0.8
DESCRIPTION "Artifact Tracker" DESCRIPTION "Artifact Tracker"
LANGUAGES CXX) LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)

View File

@ -22,6 +22,8 @@ namespace ArtifactTracker
RE::BGSListForm* g_listStored; RE::BGSListForm* g_listStored;
RE::BGSListForm* g_listFound; RE::BGSListForm* g_listFound;
RE::BGSListForm* g_persistentStorage; RE::BGSListForm* g_persistentStorage;
RE::BGSListForm* g_persistentCells;
RE::BGSListForm* g_persistentCellStorageList;
RE::BGSKeyword* g_homeKeyword; RE::BGSKeyword* g_homeKeyword;
std::unordered_map<RE::FormID, RE::TESForm*> g_artifactMap; std::unordered_map<RE::FormID, RE::TESForm*> g_artifactMap;
std::unordered_set<RE::FormType> g_artifactFormTypes; std::unordered_set<RE::FormType> g_artifactFormTypes;
@ -52,6 +54,8 @@ namespace ArtifactTracker
g_listStored = dataHandler->LookupForm<RE::BGSListForm>(0x801, "Artifact Tracker.esp"); // ETR_ItemsStored g_listStored = dataHandler->LookupForm<RE::BGSListForm>(0x801, "Artifact Tracker.esp"); // ETR_ItemsStored
g_listFound = dataHandler->LookupForm<RE::BGSListForm>(0x802, "Artifact Tracker.esp"); // ETR_ItemsFound g_listFound = dataHandler->LookupForm<RE::BGSListForm>(0x802, "Artifact Tracker.esp"); // ETR_ItemsFound
g_persistentStorage = dataHandler->LookupForm<RE::BGSListForm>(0x803, "Artifact Tracker.esp"); // ETR_PersistentStorageList g_persistentStorage = dataHandler->LookupForm<RE::BGSListForm>(0x803, "Artifact Tracker.esp"); // ETR_PersistentStorageList
g_persistentCells = dataHandler->LookupForm<RE::BGSListForm>(0x805, "Artifact Tracker.esp"); // ETR_PersistentCellList
g_persistentCellStorageList = dataHandler->LookupForm<RE::BGSListForm>(0x806, "Artifact Tracker.esp"); // ETR_PersistentCellStorageList
g_homeKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xFC1A3, "Skyrim.esm"); // LocTypePlayerHouse g_homeKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xFC1A3, "Skyrim.esm"); // LocTypePlayerHouse
@ -59,7 +63,7 @@ namespace ArtifactTracker
const auto notArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xAFC111, "Update.esm"); // ETR_NotArtifact const auto notArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xAFC111, "Update.esm"); // ETR_NotArtifact
const auto npcRaceKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0x13794, "Skyrim.esm"); // ActorTypeNPC const auto npcRaceKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0x13794, "Skyrim.esm"); // ActorTypeNPC
if (!g_cellContainer || !g_listNew || !g_listStored || !g_listFound || !g_persistentStorage || !g_homeKeyword || !extraArtifactKeyword || !notArtifactKeyword || !npcRaceKeyword) { if (!g_cellContainer || !g_listNew || !g_listStored || !g_listFound || !g_persistentStorage || !g_persistentCells || !g_persistentCellStorageList || !g_homeKeyword || !extraArtifactKeyword || !notArtifactKeyword || !npcRaceKeyword) {
log::warn("Unable to load data from Artifact Tracker.esp"); 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;
@ -147,6 +151,7 @@ namespace ArtifactTracker
EventListener::Install(); EventListener::Install();
OnGameLoad(); // covers new game and coc'ing from the main menu OnGameLoad(); // covers new game and coc'ing from the main menu
g_bLoaded = true; g_bLoaded = true;
if (bKID) { if (bKID) {
@ -202,7 +207,27 @@ namespace ArtifactTracker
if (&a_exform) { if (&a_exform) {
g_persistentMap[a_exform.formID] = a_exform.As<RE::TESObjectREFR>(); g_persistentMap[a_exform.formID] = a_exform.As<RE::TESObjectREFR>();
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
});
const auto parentCell = RE::PlayerCharacter::GetSingleton()->GetParentCell();
ListRevert(g_persistentCellStorageList);
g_persistentCells->ForEachForm([&](RE::TESForm& a_exform) {
if (&a_exform) {
const auto cell = a_exform.As<RE::TESObjectCELL>();
if (cell && cell != parentCell) {
cell->ForEachReference([&parentCell](RE::TESObjectREFR& a_ref) {
if (&a_ref && (a_ref.formFlags & RE::TESObjectREFR::RecordFlags::kPersistent) != 0 && a_ref.GetBaseObject()->Is(RE::FormType::Container)) {
//RE::DebugNotification(a_ref.GetBaseObject()->GetName());
g_persistentMap[a_ref.formID] = &a_ref;
g_persistentCellStorageList->AddForm(&a_ref);
}
return RE::BSContainer::ForEachResult::kContinue;
});
}
}
return RE::BSContainer::ForEachResult::kContinue;
}); });
std::uint32_t savedCount = g_listStored->forms.size() + g_listFound->forms.size() + g_listNew->forms.size(); std::uint32_t savedCount = g_listStored->forms.size() + g_listFound->forms.size() + g_listNew->forms.size();
@ -362,7 +387,7 @@ namespace ArtifactTracker
RE::TESObjectCELL* cell = RE::TESForm::LookupByID<RE::TESObjectCELL>(a_formID); RE::TESObjectCELL* cell = RE::TESForm::LookupByID<RE::TESObjectCELL>(a_formID);
RE::BGSLocation* location = cell ? cell->GetLocation() : nullptr; RE::BGSLocation* location = cell ? cell->GetLocation() : nullptr;
if (!cell || !location || !cell->IsInteriorCell() || !location->HasKeyword(g_homeKeyword)) { if (!cell || !location || !cell->IsInteriorCell() || !location->HasKeyword(g_homeKeyword) || g_persistentCells->HasForm(cell)) {
if (IsHome()) { if (IsHome()) {
RE::ScriptEventSourceHolder::GetSingleton()->RemoveEventSink<RE::TESCellFullyLoadedEvent>(EventListener::GetSingleton()); RE::ScriptEventSourceHolder::GetSingleton()->RemoveEventSink<RE::TESCellFullyLoadedEvent>(EventListener::GetSingleton());
ToggleHomeMode(nullptr); ToggleHomeMode(nullptr);
@ -383,7 +408,7 @@ namespace ArtifactTracker
cellStorage = refr; cellStorage = refr;
} }
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
}); });
#ifdef _DEBUG #ifdef _DEBUG
@ -408,7 +433,7 @@ namespace ArtifactTracker
return; return;
} }
if (!location || !cell->IsInteriorCell() || cell != RE::PlayerCharacter::GetSingleton()->GetParentCell() || !location->HasKeyword(g_homeKeyword)) { if (!location || !cell->IsInteriorCell() || cell != RE::PlayerCharacter::GetSingleton()->GetParentCell() || !location->HasKeyword(g_homeKeyword) || g_persistentCells->HasForm(cell)) {
ToggleHomeMode(nullptr); ToggleHomeMode(nullptr);
return; return;
} }
@ -424,7 +449,7 @@ namespace ArtifactTracker
cellStorage = &a_ref; cellStorage = &a_ref;
} }
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
}); });
for (int i = 0; i < dupes.size(); i++) { for (int i = 0; i < dupes.size(); i++) {
@ -495,14 +520,14 @@ namespace ArtifactTracker
cell->ForEachReference([&](RE::TESObjectREFR& a_ref) { cell->ForEachReference([&](RE::TESObjectREFR& a_ref) {
if (ignoreFormID && ignoreFormID == a_ref.formID) { if (ignoreFormID && ignoreFormID == a_ref.formID) {
return true; return RE::BSContainer::ForEachResult::kContinue;
} }
const auto baseObj = a_ref.GetBaseObject(); const auto baseObj = a_ref.GetBaseObject();
if (IsValidContainer(&a_ref)) { if (IsValidContainer(&a_ref)) {
if (g_cellContainer == baseObj || baseObj->formID == 0xDC9E7 || g_persistentMap.contains(a_ref.formID)) { // skip persistent and PlayerBookShelfContainer if (g_cellContainer == baseObj || baseObj->formID == 0xDC9E7 || g_persistentMap.contains(a_ref.formID)) { // skip persistent and PlayerBookShelfContainer
return true; return RE::BSContainer::ForEachResult::kContinue;
} }
const auto contInv = a_ref.GetInventory([&](RE::TESBoundObject& a_object) -> bool { const auto contInv = a_ref.GetInventory([&](RE::TESBoundObject& a_object) -> bool {
@ -523,11 +548,11 @@ namespace ArtifactTracker
} }
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
} }
if (!g_artifactAllFormTypes.contains(baseObj->GetFormType()) || a_ref.IsDisabled() || a_ref.IsMarkedForDeletion() || cellItems.contains(baseObj->formID)) { if (!g_artifactAllFormTypes.contains(baseObj->GetFormType()) || a_ref.IsDisabled() || a_ref.IsMarkedForDeletion() || cellItems.contains(baseObj->formID)) {
return true; return RE::BSContainer::ForEachResult::kContinue;
} }
cellItems.insert(baseObj->formID); cellItems.insert(baseObj->formID);
@ -542,7 +567,7 @@ namespace ArtifactTracker
g_listStored->AddForm(baseObj); g_listStored->AddForm(baseObj);
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
}); });
for (const auto& [item, data] : inv) { for (const auto& [item, data] : inv) {
@ -550,7 +575,7 @@ namespace ArtifactTracker
if (count > 0 && !cellItems.contains(item->formID)) { if (count > 0 && !cellItems.contains(item->formID)) {
g_cellStorage->RemoveItem(item, count, RE::ITEM_REMOVE_REASON::kRemove, nullptr, nullptr); g_cellStorage->RemoveItem(item, count, RE::ITEM_REMOVE_REASON::kRemove, nullptr, nullptr);
if (IsArtifact(item) && !RefListHasItem(g_persistentStorage, item->formID)) { if (IsArtifact(item) && !RefListHasItem(g_persistentStorage, item->formID) && !RefListHasItem(g_persistentCellStorageList, item->formID)) {
ListRemoveItem(g_listStored, item); ListRemoveItem(g_listStored, item);
if (GetItemCount(RE::PlayerCharacter::GetSingleton(), item) || FollowersHaveItem(item)) { if (GetItemCount(RE::PlayerCharacter::GetSingleton(), item) || FollowersHaveItem(item)) {
ListRemoveItem(g_listNew, item); ListRemoveItem(g_listNew, item);
@ -788,7 +813,7 @@ namespace ArtifactTracker
if (refrItem) { if (refrItem) {
AddRefArtifactsToList(refrItem, a_targetList, a_excludeList); AddRefArtifactsToList(refrItem, a_targetList, a_excludeList);
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
}); });
return; return;
} }
@ -826,6 +851,7 @@ namespace ArtifactTracker
{ {
ListRevert(g_listStored); ListRevert(g_listStored);
AddRefArtifactsToList(g_persistentStorage, g_listStored); AddRefArtifactsToList(g_persistentStorage, g_listStored);
AddRefArtifactsToList(g_persistentCellStorageList, g_listStored);
} }
void RescanNewArtifacts() void RescanNewArtifacts()

View File

@ -10,7 +10,7 @@ auto EventListener::GetSingleton() -> EventListener*
void EventListener::Install() void EventListener::Install()
{ {
RE::PlayerCharacter::GetSingleton()->AddEventSink<RE::BGSActorCellEvent>(EventListener::GetSingleton()); RE::PlayerCharacter::GetSingleton()->AsBGSActorCellEventSource()->AddEventSink<RE::BGSActorCellEvent>(EventListener::GetSingleton());
RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESContainerChangedEvent>(EventListener::GetSingleton()); RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESContainerChangedEvent>(EventListener::GetSingleton());
RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESActorLocationChangeEvent>(EventListener::GetSingleton()); RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESActorLocationChangeEvent>(EventListener::GetSingleton());
RE::UI::GetSingleton()->AddEventSink<RE::MenuOpenCloseEvent>(EventListener::GetSingleton()); RE::UI::GetSingleton()->AddEventSink<RE::MenuOpenCloseEvent>(EventListener::GetSingleton());

View File

@ -13,7 +13,8 @@ namespace {
stl::report_and_fail("Failed to find standard logging directory"sv); stl::report_and_fail("Failed to find standard logging directory"sv);
} }
*path /= "ArtifactTracker.log"sv; *path /= PluginDeclaration::GetSingleton()->GetName();
*path += ".log"sv;
auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(path->string(), true); auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(path->string(), true);
auto log = std::make_shared<spdlog::logger>("global log"s, std::move(sink)); auto log = std::make_shared<spdlog::logger>("global log"s, std::move(sink));
@ -28,9 +29,7 @@ namespace {
void InitializeMessaging() void InitializeMessaging()
{ {
GetMessagingInterface()->RegisterListener([](MessagingInterface::Message* message) { GetMessagingInterface()->RegisterListener([](MessagingInterface::Message* message) {
if (message->type == MessagingInterface::kPostLoad) { if (message->type == MessagingInterface::kDataLoaded) {
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton()); // runs, if KID is installed
} else if (message->type == MessagingInterface::kDataLoaded) {
const auto kidSE = ArtifactTracker::g_loadInterface->GetPluginInfo("po3_KeywordItemDistributor"); const auto kidSE = ArtifactTracker::g_loadInterface->GetPluginInfo("po3_KeywordItemDistributor");
const auto kidAE = ArtifactTracker::g_loadInterface->GetPluginInfo("Keyword Item Distributor"); // KID 2.0 for AE has a different internal name const auto kidAE = ArtifactTracker::g_loadInterface->GetPluginInfo("Keyword Item Distributor"); // KID 2.0 for AE has a different internal name
if (!kidSE && !kidAE) { if (!kidSE && !kidAE) {
@ -64,6 +63,8 @@ SKSEPluginLoad(const LoadInterface* skse) {
ArtifactTracker::g_loadInterface = skse; ArtifactTracker::g_loadInterface = skse;
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton()); // runs when KID is installed
log::info("{} has finished loading.", plugin->GetName()); log::info("{} has finished loading.", plugin->GetName());
return true; return true;
} }

View File

@ -42,9 +42,9 @@ inline std::uint32_t GetItemCount(RE::TESObjectREFR* a_container, RE::TESForm* a
container->ForEachContainerObject([&](RE::ContainerObject& a_entry) { container->ForEachContainerObject([&](RE::ContainerObject& a_entry) {
if (a_entry.obj == a_form) { if (a_entry.obj == a_form) {
iResult += a_entry.count; iResult += a_entry.count;
return false; return RE::BSContainer::ForEachResult::kStop;
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
}); });
} }
@ -74,9 +74,9 @@ inline std::int32_t GetItemCount(RE::TESObjectREFR* a_container, RE::FormID a_fo
container->ForEachContainerObject([&](RE::ContainerObject& a_entry) { container->ForEachContainerObject([&](RE::ContainerObject& a_entry) {
if (a_entry.obj && a_entry.obj->formID == a_formID) { if (a_entry.obj && a_entry.obj->formID == a_formID) {
iResult += a_entry.count; iResult += a_entry.count;
return false; return RE::BSContainer::ForEachResult::kStop;
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
}); });
} }
@ -103,9 +103,9 @@ inline bool RefListHasItem(RE::TESForm* a_refOrList, RE::FormID a_formID)
list->ForEachForm([&](RE::TESForm& a_form) { list->ForEachForm([&](RE::TESForm& a_form) {
if (&a_form && RefListHasItem(&a_form, a_formID)) { if (&a_form && RefListHasItem(&a_form, a_formID)) {
bResult = true; bResult = true;
return false; return RE::BSContainer::ForEachResult::kStop;
} }
return true; return RE::BSContainer::ForEachResult::kContinue;
}); });
return bResult; return bResult;
} }

View File

@ -3,7 +3,7 @@
{ {
"kind": "git", "kind": "git",
"repository": "https://gitlab.com/colorglass/vcpkg-colorglass", "repository": "https://gitlab.com/colorglass/vcpkg-colorglass",
"baseline": "5a11d06fd1b2d7cd6339d6aea48d450309e89cc1", "baseline": "6fb127f7d425ae3cf3fab0f79005d907c885c0d8",
"packages": [ "packages": [
"commonlibsse-ng", "commonlibsse-ng",
"gluino", "gluino",

View File

@ -1,7 +1,7 @@
{ {
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
"name": "artifact-tracker", "name": "artifact-tracker",
"version-string": "1.0.7", "version-string": "1.0.8",
"port-version": 0, "port-version": 0,
"description": "Artifact Tracker", "description": "Artifact Tracker",
"homepage": "https://eddoursul.win/mods/artifact-tracker/", "homepage": "https://eddoursul.win/mods/artifact-tracker/",