diff --git a/SKSE/Plugins/ArtifactTracker.dll b/SKSE/Plugins/ArtifactTracker.dll index 52910a8..2b51718 100644 Binary files a/SKSE/Plugins/ArtifactTracker.dll and b/SKSE/Plugins/ArtifactTracker.dll differ diff --git a/Source/ArtifactTrackerDLL/src/ArtifactTracker.cpp b/Source/ArtifactTrackerDLL/src/ArtifactTracker.cpp index a002c46..a828875 100644 --- a/Source/ArtifactTrackerDLL/src/ArtifactTracker.cpp +++ b/Source/ArtifactTrackerDLL/src/ArtifactTracker.cpp @@ -332,7 +332,7 @@ namespace ArtifactTracker const auto& [count, entry] = data; if (count > 0 && !cellItems.contains(item->formID)) { g_cellStorage->RemoveItem(item, count, RE::ITEM_REMOVE_REASON::kRemove, nullptr, nullptr); - if (!RefHasItem(g_persistentStorage, item->formID)) { + if (!RefListHasItem(g_persistentStorage, item->formID)) { ListRemoveItem(g_listStored, item); g_listFound->AddForm(item); } @@ -351,7 +351,7 @@ namespace ArtifactTracker if (g_persistentMap.contains(a_event->oldContainer)) { // Items in persistent containers are marked as stored by definition, no need to check the list - if (!RefHasItem(g_persistentStorage, a_event->baseObj)) { + if (!RefListHasItem(g_persistentStorage, a_event->baseObj)) { ListRemoveItem(g_listStored, form); g_listFound->AddForm(form); } @@ -400,7 +400,7 @@ namespace ArtifactTracker if (!a_event->newContainer) { // no destination container if (g_cellStorage && a_event->reference) { // dropped or placed on rack at home - if (!RefHasItem(g_cellStorage, form->formID)) { + if (GetItemCount(g_cellStorage, form) <= 0) { #ifdef _DEBUG SKSE::log::info("Added dropped {} to cell storage", form->GetName()); RE::DebugNotification("Adding to cell storage"); @@ -418,7 +418,7 @@ namespace ArtifactTracker } // NB: During OnContainerChanged, InventoryChanges do not have the current change included yet - if ((GetItemCount(RE::PlayerCharacter::GetSingleton(), form->formID) - a_event->itemCount <= 0) && !FollowersHaveItem(form->formID)) { + if ((GetItemCount(RE::PlayerCharacter::GetSingleton(), form->formID) - a_event->itemCount <= 0) && !FollowersHaveItem(form)) { ListRemoveItem(g_listFound, form); ListRemoveItem(g_listNew, form); g_listNew->AddForm(form); @@ -446,7 +446,7 @@ namespace ArtifactTracker const auto targetContainer = RE::TESForm::LookupByID(a_event->newContainer); if (IsValidContainer(targetContainer)) { - if (!RefHasItem(g_cellStorage, form->formID)) { + if (GetItemCount(g_cellStorage, form) <= 0) { g_cellStorage->AddObjectToContainer(form->As(), nullptr, 1, nullptr); } @@ -457,7 +457,7 @@ namespace ArtifactTracker } // NB: During OnContainerChanged, InventoryChanges do not have the current change included yet - } else if (g_listFound->HasForm(form) && (GetItemCount(RE::PlayerCharacter::GetSingleton(), form->formID) - a_event->itemCount <= 0) && !FollowersHaveItem(form->formID)) { + } else if (g_listFound->HasForm(form) && (GetItemCount(RE::PlayerCharacter::GetSingleton(), form->formID) - a_event->itemCount <= 0) && !FollowersHaveItem(form)) { ListRemoveItem(g_listFound, form); g_listNew->AddForm(form); } diff --git a/Source/ArtifactTrackerDLL/src/Util.h b/Source/ArtifactTrackerDLL/src/Util.h index e0f79f6..7def5bb 100644 --- a/Source/ArtifactTrackerDLL/src/Util.h +++ b/Source/ArtifactTrackerDLL/src/Util.h @@ -14,6 +14,38 @@ inline void ListRevert(RE::BGSListForm* a_form) return func(a_form); } +inline std::int32_t GetItemCount(RE::TESObjectREFR* a_container, RE::TESForm* a_form) +{ + std::int32_t iResult = 0; + + auto invChanges = a_container->GetInventoryChanges(); + if (invChanges && invChanges->entryList) { + for (auto& entry : *invChanges->entryList) { + if (entry && entry->object == a_form) { + if (entry->IsLeveled()) { + return entry->countDelta > 0 ? entry->countDelta : 0; + } else { + iResult = entry->countDelta; + break; + } + } + } + } + + auto container = a_container->GetContainer(); + if (container) { + container->ForEachContainerObject([&](RE::ContainerObject& a_entry) { + if (a_entry.obj == a_form) { + iResult += a_entry.count; + return false; + } + return true; + }); + } + + return iResult > 0 ? iResult : 0; +} + inline std::int32_t GetItemCount(RE::TESObjectREFR* a_container, RE::FormID a_formID) { std::int32_t iResult = 0; @@ -35,7 +67,7 @@ inline std::int32_t GetItemCount(RE::TESObjectREFR* a_container, RE::FormID a_fo auto container = a_container->GetContainer(); if (container) { container->ForEachContainerObject([&](RE::ContainerObject& a_entry) { - if (a_entry.obj->formID == a_formID) { + if (a_entry.obj && a_entry.obj->formID == a_formID) { iResult += a_entry.count; return false; } @@ -46,7 +78,7 @@ inline std::int32_t GetItemCount(RE::TESObjectREFR* a_container, RE::FormID a_fo return iResult > 0 ? iResult : 0; } -inline bool RefHasItem(RE::TESForm* a_refOrList, RE::FormID a_formID) +inline bool RefListHasItem(RE::TESForm* a_refOrList, RE::FormID a_formID) { if (!a_refOrList || !a_formID) { SKSE::log::warn("Invalid arguments in RefHasItem"); @@ -64,7 +96,7 @@ inline bool RefHasItem(RE::TESForm* a_refOrList, RE::FormID a_formID) if (list) { bool bResult = false; list->ForEachForm([&](RE::TESForm& a_form) { - if (&a_form && RefHasItem(&a_form, a_formID)) { + if (&a_form && RefListHasItem(&a_form, a_formID)) { bResult = true; return false; } @@ -76,13 +108,13 @@ inline bool RefHasItem(RE::TESForm* a_refOrList, RE::FormID a_formID) return false; } -inline bool FollowersHaveItem(RE::FormID a_formID) +inline bool FollowersHaveItem(RE::TESForm* a_form) { if (const auto processLists = RE::ProcessLists::GetSingleton(); processLists) { for (auto& actorHandle : processLists->highActorHandles) { if (auto actor = actorHandle.get(); actor && actor->IsPlayerTeammate()) { - if (GetItemCount(actor->As(), a_formID) > 0) { + if (GetItemCount(actor->As(), a_form) > 0) { return true; }