|
|
@ -9,6 +9,7 @@ using namespace SKSE::log; |
|
|
|
namespace ArtifactTracker |
|
|
|
namespace ArtifactTracker |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool g_bLoaded = false; |
|
|
|
bool g_bLoaded = false; |
|
|
|
|
|
|
|
bool g_bSaveLoaded = true; |
|
|
|
bool g_bHomeContainer = false; |
|
|
|
bool g_bHomeContainer = false; |
|
|
|
bool g_bBookShelf = false; |
|
|
|
bool g_bBookShelf = false; |
|
|
|
bool g_bTakeAll = false; |
|
|
|
bool g_bTakeAll = false; |
|
|
@ -316,7 +317,7 @@ namespace ArtifactTracker |
|
|
|
|
|
|
|
|
|
|
|
bool IsValidContainer(RE::TESObjectREFR* a_ref) |
|
|
|
bool IsValidContainer(RE::TESObjectREFR* a_ref) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!a_ref) { |
|
|
|
if (!a_ref || a_ref->IsMarkedForDeletion()) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -327,6 +328,11 @@ namespace ArtifactTracker |
|
|
|
|
|
|
|
|
|
|
|
void OnCellEnter(const RE::FormID a_formID) |
|
|
|
void OnCellEnter(const RE::FormID a_formID) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
if (!g_bSaveLoaded) { |
|
|
|
|
|
|
|
// Cell load events fire before formlists are loaded from savegame
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
@ -339,40 +345,75 @@ namespace ArtifactTracker |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
RE::TESObjectREFR* cellStorage = nullptr; |
|
|
|
RE::TESObjectREFR* cellStorage = nullptr; |
|
|
|
|
|
|
|
bool bHasDupes = false; |
|
|
|
|
|
|
|
|
|
|
|
g_persistentStorage->ForEachForm([&](RE::TESForm& a_form) { |
|
|
|
g_persistentStorage->ForEachForm([&](RE::TESForm& a_form) { |
|
|
|
const auto refr = a_form.As<RE::TESObjectREFR>(); |
|
|
|
const auto refr = a_form.As<RE::TESObjectREFR>(); |
|
|
|
if (refr && refr->GetBaseObject() == g_cellContainer && refr->GetParentCell()->formID == a_formID) { |
|
|
|
if (refr && refr->GetParentCell()->formID == a_formID && refr->GetBaseObject() == g_cellContainer) { |
|
|
|
cellStorage = refr; |
|
|
|
if (cellStorage) { |
|
|
|
return false; |
|
|
|
log::warn("Multiple cell storages detected in {}", cell->GetName()); |
|
|
|
|
|
|
|
bHasDupes = true; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
cellStorage = refr; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG |
|
|
|
|
|
|
|
if (cellStorage) { |
|
|
|
|
|
|
|
log::info("Found cell storage in {} (first pass)", cell->GetName()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
ToggleHomeMode(cellStorage); |
|
|
|
ToggleHomeMode(cellStorage); |
|
|
|
|
|
|
|
|
|
|
|
if (!cellStorage) { |
|
|
|
if (!cellStorage || bHasDupes) { |
|
|
|
RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESCellFullyLoadedEvent>(EventListener::GetSingleton()); |
|
|
|
RE::ScriptEventSourceHolder::GetSingleton()->AddEventSink<RE::TESCellFullyLoadedEvent>(EventListener::GetSingleton()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void OnCellEnter(const RE::BGSLocation* location, const RE::TESObjectCELL* cell) |
|
|
|
void OnCellEnter(const RE::BGSLocation* location, const RE::TESObjectCELL* cell) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
RE::ScriptEventSourceHolder::GetSingleton()->RemoveEventSink<RE::TESCellFullyLoadedEvent>(EventListener::GetSingleton()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!g_bSaveLoaded) { |
|
|
|
|
|
|
|
// Cell load events fire before formlists are loaded from savegame, duh!
|
|
|
|
|
|
|
|
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)) { |
|
|
|
ToggleHomeMode(nullptr); |
|
|
|
ToggleHomeMode(nullptr); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
RE::TESObjectREFR* cellStorage = nullptr; |
|
|
|
RE::TESObjectREFR* cellStorage = nullptr; |
|
|
|
|
|
|
|
std::vector<RE::TESObjectREFR*> dupes; |
|
|
|
|
|
|
|
|
|
|
|
for (const auto& a_ref : cell->references) { |
|
|
|
cell->ForEachReference([&cellStorage, &dupes](RE::TESObjectREFR& a_ref) { |
|
|
|
if (a_ref.get()->GetBaseObject() == g_cellContainer) { |
|
|
|
if (a_ref.GetBaseObject() == g_cellContainer && !a_ref.IsMarkedForDeletion()) { |
|
|
|
cellStorage = a_ref.get(); |
|
|
|
if (cellStorage) { |
|
|
|
break; |
|
|
|
dupes.push_back(&a_ref); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
cellStorage = &a_ref; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dupes.size(); i++) { |
|
|
|
|
|
|
|
log::warn("Removing duplicate storage {:08X}", dupes[i]->formID); |
|
|
|
|
|
|
|
g_persistentMap.erase(dupes[i]->formID); |
|
|
|
|
|
|
|
ListRemoveItem(g_persistentStorage, dupes[i]); |
|
|
|
|
|
|
|
dupes[i]->Disable(); |
|
|
|
|
|
|
|
dupes[i]->SetDelete(true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
dupes.clear(); |
|
|
|
|
|
|
|
|
|
|
|
if (cellStorage) { |
|
|
|
if (cellStorage) { |
|
|
|
|
|
|
|
#ifdef _DEBUG |
|
|
|
|
|
|
|
log::info("Found cell storage in {} (second pass)", cell->GetName()); |
|
|
|
|
|
|
|
#endif |
|
|
|
if (!g_persistentMap.contains(cellStorage->formID)) { |
|
|
|
if (!g_persistentMap.contains(cellStorage->formID)) { |
|
|
|
g_persistentStorage->AddForm(cellStorage); |
|
|
|
g_persistentStorage->AddForm(cellStorage); |
|
|
|
g_persistentMap[cellStorage->formID] = cellStorage; |
|
|
|
g_persistentMap[cellStorage->formID] = cellStorage; |
|
|
@ -390,6 +431,9 @@ namespace ArtifactTracker |
|
|
|
const auto cellStorage = RE::PlayerCharacter::GetSingleton()->PlaceObjectAtMe(g_cellContainer, true).get(); |
|
|
|
const auto cellStorage = RE::PlayerCharacter::GetSingleton()->PlaceObjectAtMe(g_cellContainer, true).get(); |
|
|
|
|
|
|
|
|
|
|
|
if (cellStorage) { |
|
|
|
if (cellStorage) { |
|
|
|
|
|
|
|
#ifdef _DEBUG |
|
|
|
|
|
|
|
log::info("Created storage {:08X}", cellStorage->formID); |
|
|
|
|
|
|
|
#endif |
|
|
|
cellStorage->Disable(); |
|
|
|
cellStorage->Disable(); |
|
|
|
g_persistentStorage->AddForm(cellStorage); |
|
|
|
g_persistentStorage->AddForm(cellStorage); |
|
|
|
g_persistentMap[cellStorage->formID] = cellStorage; |
|
|
|
g_persistentMap[cellStorage->formID] = cellStorage; |
|
|
|