1
Fork 0

Added the exclusion keyword ETR_NotArtifact, improved artifact filtering

ae-1.6.629
Eddoursul 2 years ago
parent 0c22f0b8bd
commit 81b174e028
  1. BIN
      Artifact Tracker.esp
  2. 3
      Artifact Tracker_KID.ini
  3. BIN
      SKSE/Plugins/ArtifactTracker.dll
  4. BIN
      Scripts/ArtifactTrackerPlayer.pex
  5. 2
      Source/ArtifactTrackerDLL/.clang-format
  6. 117
      Source/ArtifactTrackerDLL/src/ArtifactTracker.cpp
  7. 16
      Source/ArtifactTrackerDLL/src/ArtifactTracker.h
  8. 2
      Source/ArtifactTrackerDLL/src/EventListener.cpp
  9. 11
      Source/ArtifactTrackerDLL/src/Main.cpp
  10. 8
      Source/ArtifactTrackerDLL/src/PapyrusFunctions.h
  11. 4
      Source/Scripts/ArtifactTrackerPlayer.psc

Binary file not shown.

@ -3,3 +3,6 @@ Keyword = ETR_ExtraArtifact|Misc Item|0x1F6D4,0x200B6,0x200BA,0x20949,0x59654,0x
; Treasure Maps ; Treasure Maps
Keyword = ETR_ExtraArtifact|Book|0xEF07A,0xF33CD,0xF33CE,0xF33CF,0xF33D0,0xF33D1,0xF33D2,0xF33D3,0xF33D4,0xF33D5,0xF33E0 Keyword = ETR_ExtraArtifact|Book|0xEF07A,0xF33CD,0xF33CE,0xF33CF,0xF33D0,0xF33D1,0xF33D2,0xF33D3,0xF33D4,0xF33D5,0xF33E0
; Soul Gem Fragments
Keyword = ETR_NotArtifact|Misc Item|0x67181,0x67182,0x67183,0x67184,0x67185

Binary file not shown.

Binary file not shown.

@ -60,7 +60,7 @@ DisableFormat: 'false'
FixNamespaceComments: 'false' FixNamespaceComments: 'false'
IncludeBlocks: Preserve IncludeBlocks: Preserve
IndentCaseBlocks: 'true' IndentCaseBlocks: 'true'
IndentCaseLabels: 'false' IndentCaseLabels: 'true'
IndentExternBlock: Indent IndentExternBlock: Indent
IndentGotoLabels: 'false' IndentGotoLabels: 'false'
IndentPPDirectives: AfterHash IndentPPDirectives: AfterHash

@ -18,15 +18,18 @@ namespace ArtifactTracker
std::unordered_map<RE::FormID, RE::TESObjectREFR*> g_persistentMap; std::unordered_map<RE::FormID, RE::TESObjectREFR*> g_persistentMap;
RE::TESObjectREFR* g_cellStorage; RE::TESObjectREFR* g_cellStorage;
void Init() bool Init()
{ {
g_bLoaded = false; if (g_bLoaded) {
return true;
}
const auto dataHandler = RE::TESDataHandler::GetSingleton(); const auto dataHandler = RE::TESDataHandler::GetSingleton();
if (!dataHandler) { if (!dataHandler) {
SKSE::log::error("Failed to call RE::TESDataHandler::GetSingleton()"); SKSE::log::error("Unable to call RE::TESDataHandler::GetSingleton()");
return; RE::DebugMessageBox("Unable to initialize Artifact Tracker.");
return false;
} }
g_cellContainer = dataHandler->LookupForm(0x800, "Artifact Tracker.esp")->As<RE::TESBoundObject>(); // ETR_CellStorageContainer g_cellContainer = dataHandler->LookupForm(0x800, "Artifact Tracker.esp")->As<RE::TESBoundObject>(); // ETR_CellStorageContainer
@ -40,111 +43,95 @@ 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 extraArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xDE3FD3, "Update.esm"); // ETR_ExtraArtifact
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) { if (!g_cellContainer || !g_listNew || !g_listStored || !g_listFound || !g_persistentStorage || !g_homeKeyword || !recipeKeyword || !excludeKeywords || !dummyKeyword || !extraArtifactKeyword || !notArtifactKeyword) {
SKSE::log::warn("Failed to load data from Artifact Tracker.esp"); SKSE::log::warn("Unable to load data from Artifact Tracker.esp");
RE::DebugMessageBox("Failed 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; return false;
} }
// Preloading item lists // Preloading item lists
g_artifactFormTypes.insert(RE::FormType::Weapon); g_artifactFormTypes.insert(RE::FormType::Weapon);
for (const auto& form : dataHandler->GetFormArray(RE::FormType::Weapon)) { for (const auto& form : dataHandler->GetFormArray<RE::TESObjectWEAP>()) {
if (form->GetPlayable()) { if (form->GetPlayable() && !form->IsBound() && !form->weaponData.flags.all(RE::TESObjectWEAP::Data::Flag::kCantDrop) && !form->IsDeleted() && !form->HasKeyword(dummyKeyword) && !form->HasKeyword(notArtifactKeyword)) {
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::FormType::Armor)) { for (const auto& form : dataHandler->GetFormArray<RE::TESObjectARMO>()) {
if (form->GetPlayable()) { if (form->GetPlayable() && !form->IsDeleted() && !form->HasKeyword(dummyKeyword) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form; g_artifactMap[form->formID] = form;
} }
} }
g_artifactMap.erase(0xD64); // SkinNaked
g_artifactMap.erase(0x69CE3); // SkinNakedBeast
g_artifactMap.erase(0xCDD86); // SkinNakedWerewolfBeast
g_artifactFormTypes.insert(RE::FormType::Book); g_artifactFormTypes.insert(RE::FormType::Book);
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectBOOK>()) { for (const auto& form : dataHandler->GetFormArray<RE::TESObjectBOOK>()) {
if (form && !form->TeachesSpell() && (form->HasKeyword(recipeKeyword) || BookCheck::IsBook(form))) { if (!form->TeachesSpell() && !form->IsDeleted() && (form->HasKeyword(recipeKeyword) || form->HasKeyword(extraArtifactKeyword) || BookCheck::IsBook(form)) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form; g_artifactMap[form->formID] = form;
} }
} }
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->HasKeywordInList(excludeKeywords, false)) { if (form->GetPlayable() && !form->IsDeleted() && (form->HasKeyword(extraArtifactKeyword) || !form->HasKeywordInList(excludeKeywords, false)) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form; g_artifactMap[form->formID] = form;
} }
} }
g_artifactMap.erase(0xA); // Lockpick g_artifactMap.erase(0xA); // Lockpick
g_artifactMap.erase(0xF); // Gold g_artifactMap.erase(0xF); // Gold
// Fishing CC
const auto plaqueFish = dataHandler->LookupForm<RE::BGSListForm>(0xF4B, "ccBGSSSE001-Fish.esm"); // ccBGSSSE001_FishPlaqueGiftFilterList
if (plaqueFish) {
plaqueFish->ForEachForm([&](RE::TESForm& a_form) {
g_artifactMap[a_form.formID] = &a_form;
return true;
});
}
OnGameLoad();
EventListener::Install();
g_bLoaded = true;
}
void OnKeywordDistribution()
{
const auto dataHandler = RE::TESDataHandler::GetSingleton();
const auto extraArtifactKeyword = dataHandler->LookupForm<RE::BGSKeyword>(0xDE3FD3, "Update.esm"); // ETR_ExtraArtifact
if (!dataHandler || !extraArtifactKeyword) {
SKSE::log::error("Unable to load ETR_ExtraArtifact in OnKeywordDistribution");
return;
}
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectBOOK>()) {
if (form->HasKeyword(extraArtifactKeyword)) {
g_artifactMap[form->formID] = form;
}
}
for (const auto& form : dataHandler->GetFormArray<RE::TESObjectMISC>()) {
if (form->GetPlayable() && form->HasKeyword(extraArtifactKeyword)) {
g_artifactMap[form->formID] = form;
}
}
for (const auto& form : dataHandler->GetFormArray<RE::AlchemyItem>()) { for (const auto& form : dataHandler->GetFormArray<RE::AlchemyItem>()) {
if (form->HasKeyword(extraArtifactKeyword)) { if (!form->IsDeleted() && form->HasKeyword(extraArtifactKeyword) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form; g_artifactMap[form->formID] = form;
g_artifactFormTypes.insert(RE::FormType::AlchemyItem); g_artifactFormTypes.insert(RE::FormType::AlchemyItem);
} }
} }
for (const auto& form : dataHandler->GetFormArray<RE::IngredientItem>()) { for (const auto& form : dataHandler->GetFormArray<RE::IngredientItem>()) {
if (form->HasKeyword(extraArtifactKeyword)) { if (!form->IsDeleted() && form->HasKeyword(extraArtifactKeyword) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form; g_artifactMap[form->formID] = form;
g_artifactFormTypes.insert(RE::FormType::Ingredient); g_artifactFormTypes.insert(RE::FormType::Ingredient);
} }
} }
for (const auto& form : dataHandler->GetFormArray<RE::TESSoulGem>()) { for (const auto& form : dataHandler->GetFormArray<RE::TESSoulGem>()) {
if (form->HasKeyword(extraArtifactKeyword)) { if (!form->IsDeleted() && form->HasKeyword(extraArtifactKeyword) && !form->HasKeyword(notArtifactKeyword)) {
g_artifactMap[form->formID] = form; g_artifactMap[form->formID] = form;
g_artifactFormTypes.insert(RE::FormType::SoulGem); g_artifactFormTypes.insert(RE::FormType::SoulGem);
} }
} }
// Fishing CC (remove, when KID adds formlist support)
const auto plaqueFish = dataHandler->LookupForm<RE::BGSListForm>(0xF4B, "ccBGSSSE001-Fish.esm"); // ccBGSSSE001_FishPlaqueGiftFilterList
if (plaqueFish) {
plaqueFish->ForEachForm([&](RE::TESForm& a_form) {
g_artifactMap[a_form.formID] = &a_form;
return true;
});
}
OnGameLoad();
EventListener::Install();
g_bLoaded = true;
return true;
} }
bool IsArtifact(RE::TESForm* a_form) bool IsArtifact(const RE::TESForm* a_form)
{ {
return a_form && g_artifactFormTypes.contains(a_form->GetFormType()) && g_artifactMap.contains(a_form->formID); return a_form && g_artifactFormTypes.contains(a_form->GetFormType()) && g_artifactMap.contains(a_form->formID);
} }
RE::TESForm* GetArtifactByID(RE::FormID a_formID) RE::TESForm* GetArtifactByID(const RE::FormID a_formID)
{ {
if (!a_formID) { if (!a_formID) {
return nullptr; return nullptr;
@ -169,7 +156,7 @@ namespace ArtifactTracker
}); });
} }
void SetContainerMode(bool bOpening) void SetContainerMode(const bool bOpening)
{ {
if (bOpening) { if (bOpening) {
@ -229,7 +216,7 @@ namespace ArtifactTracker
return baseObj->formType == RE::FormType::Container || (baseObj->formType == RE::FormType::NPC && !a_ref->IsDisabled() && baseObj->As<RE::TESNPC>()->GetRace()->formID == 0x0010760A); return baseObj->formType == RE::FormType::Container || (baseObj->formType == RE::FormType::NPC && !a_ref->IsDisabled() && baseObj->As<RE::TESNPC>()->GetRace()->formID == 0x0010760A);
} }
void OnCellEnter(RE::FormID a_formID) void OnCellEnter(const RE::FormID a_formID)
{ {
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;
@ -260,7 +247,7 @@ namespace ArtifactTracker
} }
} }
void OnCellEnter(RE::BGSLocation* location, RE::TESObjectCELL* cell) void OnCellEnter(const RE::BGSLocation* location, const RE::TESObjectCELL* cell)
{ {
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);
@ -303,7 +290,7 @@ namespace ArtifactTracker
} }
} }
void SyncCellStorage(RE::FormID a_ignoreRef) void SyncCellStorage(const RE::TESObjectREFR* a_ignoreRef)
{ {
if (!IsHome()) { if (!IsHome()) {
#ifdef _DEBUG #ifdef _DEBUG
@ -322,7 +309,7 @@ namespace ArtifactTracker
const auto inv = g_cellStorage->GetInventory(); const auto inv = g_cellStorage->GetInventory();
for (const auto& a_ref : cell->references) { for (const auto& a_ref : cell->references) {
if (a_ignoreRef == a_ref->formID) { if (a_ignoreRef && a_ignoreRef->formID == a_ref->formID) {
continue; continue;
} }
@ -428,7 +415,7 @@ namespace ArtifactTracker
if (!g_bHomeContainer) { if (!g_bHomeContainer) {
const auto container = RE::TESForm::LookupByID<RE::TESObjectREFR>(a_event->oldContainer); const auto container = RE::TESForm::LookupByID<RE::TESObjectREFR>(a_event->oldContainer);
if (container && !GetItemCount(container, form)) { if (container && !GetItemCount(container, form)) {
SyncCellStorage(container->formID); SyncCellStorage(container);
} }
} }
@ -575,7 +562,7 @@ namespace ArtifactTracker
if (g_cellStorage && IsInSameCell(container)) { // deleted from container at home if (g_cellStorage && IsInSameCell(container)) { // deleted from container at home
if (!GetItemCount(container, form)) { if (!GetItemCount(container, form)) {
SyncCellStorage(container->formID); SyncCellStorage(container);
} }
} }

@ -15,25 +15,23 @@ namespace ArtifactTracker
extern std::unordered_map<RE::FormID, RE::TESObjectREFR*> g_persistentMap; extern std::unordered_map<RE::FormID, RE::TESObjectREFR*> g_persistentMap;
extern RE::TESObjectREFR* g_cellStorage; extern RE::TESObjectREFR* g_cellStorage;
void Init(); bool Init();
void OnKeywordDistribution(); bool IsArtifact(const RE::TESForm* a_item);
bool IsArtifact(RE::TESForm* a_item); RE::TESForm* GetArtifactByID(const RE::FormID a_formID);
RE::TESForm* GetArtifactByID(RE::FormID a_formID);
bool IsHome(); bool IsHome();
void OnGameLoad(); void OnGameLoad();
void SetContainerMode(bool bOpening); void SetContainerMode(const bool bOpening);
void OnCellEnter(RE::FormID a_formID); void OnCellEnter(const RE::FormID a_formID);
void OnCellEnter(RE::BGSLocation* location, RE::TESObjectCELL* cell); void OnCellEnter(const RE::BGSLocation* location, const RE::TESObjectCELL* cell);
void SyncCellStorage(RE::FormID a_ignoreRef = NULL); void SyncCellStorage(const RE::TESObjectREFR* a_ignoreRef = nullptr);
void OnContainerChanged(const RE::TESContainerChangedEvent* a_event, RE::TESForm* form); void OnContainerChanged(const RE::TESContainerChangedEvent* a_event, RE::TESForm* form);

@ -20,7 +20,7 @@ auto EventListener::ProcessEvent(
{ {
if (a_event->eventName == "KID_KeywordDistributionDone") { if (a_event->eventName == "KID_KeywordDistributionDone") {
SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton()); SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton());
ArtifactTracker::OnKeywordDistribution(); ArtifactTracker::Init();
} }
return RE::BSEventNotifyControl::kContinue; return RE::BSEventNotifyControl::kContinue;

@ -29,14 +29,13 @@ namespace {
void InitializeMessaging() void InitializeMessaging()
{ {
GetMessagingInterface()->RegisterListener([](MessagingInterface::Message* message) { GetMessagingInterface()->RegisterListener([](MessagingInterface::Message* message) {
if (message->type == MessagingInterface::kPostLoad) {
if (message->type == MessagingInterface::kPostPostLoad) {
SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton()); SKSE::GetModCallbackEventSource()->AddEventSink(EventListener::GetSingleton());
} else if (message->type == MessagingInterface::kDataLoaded) { } else if (message->type == MessagingInterface::kNewGame || message->type == MessagingInterface::kPreLoadGame) {
ArtifactTracker::Init();
} else if (message->type == MessagingInterface::kPostLoadGame) {
SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton()); SKSE::GetModCallbackEventSource()->RemoveEventSink(EventListener::GetSingleton());
ArtifactTracker::OnGameLoad(); ArtifactTracker::Init(); // if KID is not installed
} else if (message->type == MessagingInterface::kPostLoadGame) {
ArtifactTracker::OnGameLoad(); // refresh g_persistentMap from savegame
} }
}); });
} }

@ -5,9 +5,9 @@
namespace Papyrus::PapyrusFunctions namespace Papyrus::PapyrusFunctions
{ {
constexpr bool IsLoaded(RE::StaticFunctionTag*) inline bool Load(RE::StaticFunctionTag*)
{ {
return ArtifactTracker::g_bLoaded; return ArtifactTracker::Init();
} }
inline RE::TESObjectREFR* GetCellStorage(RE::StaticFunctionTag*) inline RE::TESObjectREFR* GetCellStorage(RE::StaticFunctionTag*)
@ -75,8 +75,8 @@ namespace Papyrus::PapyrusFunctions
inline void Bind(VM& a_vm) inline void Bind(VM& a_vm)
{ {
BIND(IsLoaded); BIND(Load);
logger::info("Registered IsLoaded"sv); logger::info("Registered Load"sv);
BIND(GetArtifactCount); BIND(GetArtifactCount);
logger::info("Registered GetArtifactCount"sv); logger::info("Registered GetArtifactCount"sv);
BIND(RescanStoredArtifacts); BIND(RescanStoredArtifacts);

@ -22,7 +22,7 @@ endevent
Event OnPlayerLoadGame() Event OnPlayerLoadGame()
if ! IsLoaded() if ! Load()
ETR_ItemsNew.Revert() ETR_ItemsNew.Revert()
ETR_ItemsFound.Revert() ETR_ItemsFound.Revert()
ETR_ItemsStored.Revert() ETR_ItemsStored.Revert()
@ -166,7 +166,7 @@ endstate
; NATIVE FUNCTIONS ; NATIVE FUNCTIONS
bool function IsLoaded() native global bool function Load() native global
int function GetArtifactCount() native global int function GetArtifactCount() native global

Loading…
Cancel
Save