Updated to CommonLibSSE-NG 3.6 (1.6.629+ support); formlist of cells with persistent containers
This commit is contained in:
parent
654067f863
commit
4919e92157
Binary file not shown.
Binary file not shown.
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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());
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"registries": [
|
"registries": [
|
||||||
{
|
{
|
||||||
"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",
|
||||||
"script-extender-common",
|
"script-extender-common",
|
||||||
"skse"
|
"skse"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -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/",
|
||||||
|
Loading…
Reference in New Issue
Block a user