|
|
|
@ -22,6 +22,8 @@ namespace ArtifactTracker |
|
|
|
|
RE::BGSListForm* g_listStored; |
|
|
|
|
RE::BGSListForm* g_listFound; |
|
|
|
|
RE::BGSListForm* g_persistentStorage; |
|
|
|
|
RE::BGSListForm* g_persistentCells; |
|
|
|
|
RE::BGSListForm* g_persistentCellStorageList; |
|
|
|
|
RE::BGSKeyword* g_homeKeyword; |
|
|
|
|
std::unordered_map<RE::FormID, RE::TESForm*> g_artifactMap; |
|
|
|
|
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_listFound = dataHandler->LookupForm<RE::BGSListForm>(0x802, "Artifact Tracker.esp"); // ETR_ItemsFound
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
@ -59,7 +63,7 @@ namespace ArtifactTracker |
|
|
|
|
const auto notArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xAFC111, "Update.esm"); // ETR_NotArtifact
|
|
|
|
|
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"); |
|
|
|
|
RE::DebugMessageBox("Unable to load data from Artifact Tracker.esp, the mod is disabled."); |
|
|
|
|
return false; |
|
|
|
@ -147,6 +151,7 @@ namespace ArtifactTracker |
|
|
|
|
|
|
|
|
|
EventListener::Install(); |
|
|
|
|
OnGameLoad(); // covers new game and coc'ing from the main menu
|
|
|
|
|
|
|
|
|
|
g_bLoaded = true; |
|
|
|
|
|
|
|
|
|
if (bKID) { |
|
|
|
@ -202,7 +207,27 @@ namespace ArtifactTracker |
|
|
|
|
if (&a_exform) { |
|
|
|
|
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(); |
|
|
|
@ -362,7 +387,7 @@ namespace ArtifactTracker |
|
|
|
|
RE::TESObjectCELL* cell = RE::TESForm::LookupByID<RE::TESObjectCELL>(a_formID); |
|
|
|
|
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()) { |
|
|
|
|
RE::ScriptEventSourceHolder::GetSingleton()->RemoveEventSink<RE::TESCellFullyLoadedEvent>(EventListener::GetSingleton()); |
|
|
|
|
ToggleHomeMode(nullptr); |
|
|
|
@ -383,7 +408,7 @@ namespace ArtifactTracker |
|
|
|
|
cellStorage = refr; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
return RE::BSContainer::ForEachResult::kContinue; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG |
|
|
|
@ -408,7 +433,7 @@ namespace ArtifactTracker |
|
|
|
|
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); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -424,7 +449,7 @@ namespace ArtifactTracker |
|
|
|
|
cellStorage = &a_ref; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
return RE::BSContainer::ForEachResult::kContinue; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dupes.size(); i++) { |
|
|
|
@ -495,14 +520,14 @@ namespace ArtifactTracker |
|
|
|
|
|
|
|
|
|
cell->ForEachReference([&](RE::TESObjectREFR& a_ref) { |
|
|
|
|
if (ignoreFormID && ignoreFormID == a_ref.formID) { |
|
|
|
|
return true; |
|
|
|
|
return RE::BSContainer::ForEachResult::kContinue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const auto baseObj = a_ref.GetBaseObject(); |
|
|
|
|
|
|
|
|
|
if (IsValidContainer(&a_ref)) { |
|
|
|
|
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 { |
|
|
|
@ -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)) { |
|
|
|
|
return true; |
|
|
|
|
return RE::BSContainer::ForEachResult::kContinue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cellItems.insert(baseObj->formID); |
|
|
|
@ -542,7 +567,7 @@ namespace ArtifactTracker |
|
|
|
|
g_listStored->AddForm(baseObj); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
return RE::BSContainer::ForEachResult::kContinue; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
for (const auto& [item, data] : inv) { |
|
|
|
@ -550,7 +575,7 @@ namespace ArtifactTracker |
|
|
|
|
if (count > 0 && !cellItems.contains(item->formID)) { |
|
|
|
|
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); |
|
|
|
|
if (GetItemCount(RE::PlayerCharacter::GetSingleton(), item) || FollowersHaveItem(item)) { |
|
|
|
|
ListRemoveItem(g_listNew, item); |
|
|
|
@ -788,7 +813,7 @@ namespace ArtifactTracker |
|
|
|
|
if (refrItem) { |
|
|
|
|
AddRefArtifactsToList(refrItem, a_targetList, a_excludeList); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
return RE::BSContainer::ForEachResult::kContinue; |
|
|
|
|
}); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -826,6 +851,7 @@ namespace ArtifactTracker |
|
|
|
|
{ |
|
|
|
|
ListRevert(g_listStored); |
|
|
|
|
AddRefArtifactsToList(g_persistentStorage, g_listStored); |
|
|
|
|
AddRefArtifactsToList(g_persistentCellStorageList, g_listStored); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RescanNewArtifacts() |
|
|
|
|