1

Delayed processing of items moved to a container

This commit is contained in:
Eddoursul 2022-06-21 22:10:12 +02:00
parent 90d5e69df4
commit d22ec901b5
13 changed files with 339 additions and 338 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,6 +2,54 @@
namespace Papyrus::ArtifactTracker
{
inline bool is_excluded(RE::TESForm* a_form, RE::TESForm* a_excludeForm = NULL)
{
if (!a_excludeForm) {
return false;
}
const RE::BGSListForm* list = a_excludeForm->As<RE::BGSListForm>();
if (list) {
if (list->HasForm(a_form)) {
return true;
} else {
bool isExcluded = false;
list->ForEachForm([&](RE::TESForm& a_exform) {
const auto exlist = a_exform.As<RE::BGSListForm>();
if (exlist) {
if (exlist->forms.size() > 0) {
if (exlist->forms[0]->Is(RE::FormType::Keyword) ? a_form->HasKeywordInList(exlist, false) : exlist->HasForm(a_form)) {
isExcluded = true;
return false;
}
}
} else {
const auto exkeyword = a_exform.As<RE::BGSKeyword>();
if (exkeyword && a_form->As<RE::BGSKeywordForm>()->HasKeyword(exkeyword)) {
isExcluded = true;
return false;
}
}
return true;
});
return isExcluded;
}
}
const RE::BGSKeyword* keyword = a_excludeForm->As<RE::BGSKeyword>();
if (keyword) {
if (a_form->As<RE::BGSKeywordForm>()->HasKeyword(keyword)) {
return true;
}
}
return false;
}
inline bool is_artifact(RE::TESForm* a_form, RE::TESForm* a_excludeForm = NULL)
{
const auto formType = a_form->GetFormType();
@ -10,13 +58,93 @@ namespace Papyrus::ArtifactTracker
return false;
}
if (Papyrus::ObjectReference::inv_util::is_excluded(a_form, a_excludeForm)) {
if (!a_form->GetPlayable() || is_excluded(a_form, a_excludeForm)) {
return false;
}
return true;
}
inline std::int32_t AddAllFormsToList(RE::StaticFunctionTag*,
RE::BGSListForm* a_targetList,
short a_formType,
RE::TESForm* a_excludeForm = NULL)
{
const auto dataHandler = RE::TESDataHandler::GetSingleton();
if (!dataHandler) {
return a_targetList->forms.size();
}
const auto formType = static_cast<RE::FormType>(a_formType);
for (const auto& form : dataHandler->GetFormArray(formType)) {
if (!form || !form->GetPlayable()) {
continue;
}
if (a_excludeForm && is_excluded(form, a_excludeForm)) {
continue;
}
a_targetList->AddForm(form);
}
return a_targetList->forms.size();
}
inline std::int32_t AddArtifactsToList(VM* a_vm, StackID a_stackID, RE::StaticFunctionTag*,
RE::TESForm* a_refOrList,
RE::BGSListForm* a_targetList,
RE::TESForm* a_excludeForm = NULL,
bool excludeOnlyMisc = false)
{
if (!a_refOrList) {
a_vm->TraceStack("a_refOrList in AddItemsOfTypeAndKeywordToList is None", a_stackID);
return 0;
}
if (!a_targetList) {
a_vm->TraceStack("a_targetList in AddItemsOfTypeAndKeywordToList is None", a_stackID);
return 0;
}
if (a_refOrList->Is(RE::FormType::FormList)) {
a_refOrList->As<RE::BGSListForm>()->ForEachForm([&](RE::TESForm& a_exform) {
const auto refrItem = a_exform.As<RE::TESObjectREFR>();
if (refrItem) {
AddArtifactsToList(a_vm, a_stackID, {}, refrItem, a_targetList, a_excludeForm, excludeOnlyMisc);
}
return true;
});
return a_targetList->forms.size();
}
const auto containerRef = a_refOrList->As<RE::TESObjectREFR>();
if (!containerRef) {
a_vm->TraceStack("containerRef in AddItemsOfTypeAndKeywordToList is not a reference", a_stackID);
return 0;
}
auto inv = containerRef->GetInventory([&](RE::TESBoundObject& a_exform) {
return a_exform.GetPlayable()
&& (
a_exform.formType == RE::FormType::Armor
|| (a_exform.formType == RE::FormType::Weapon && a_exform.formID != 0x000001F4)
|| a_exform.formType == RE::FormType::Misc
|| a_exform.formType == RE::FormType::Book
)
&& (excludeOnlyMisc ? (a_exform.formType != RE::FormType::Misc || !is_excluded(&a_exform, a_excludeForm)) : !is_excluded(&a_exform, a_excludeForm));
});
for (const auto& [item, data] : inv) {
const auto& [count, entry] = data;
if (count > 0) {
a_targetList->AddForm(item);
}
}
return a_targetList->forms.size();
}
inline RE::TESObjectREFR* GetCellStorage(RE::StaticFunctionTag*,
RE::TESObjectREFR* a_ref,
RE::BGSListForm* a_refList,
@ -119,12 +247,11 @@ namespace Papyrus::ArtifactTracker
continue;
}
const auto contInv = a_ref->GetInventory();
const auto contInv = a_ref->GetInventory([&](RE::TESBoundObject& a_object) -> bool {
return !cellItems.contains(a_object.formID);
});
for (const auto& [item, data] : contInv) {
if (cellItems.contains(item->formID)) {
continue;
}
const auto& [count, entry] = data;
if (count > 0) {
cellItems[item->formID] = true;
@ -146,12 +273,12 @@ namespace Papyrus::ArtifactTracker
if (cellItems.contains(baseObj->formID)) {
continue;
}
cellItems[baseObj->formID] = true;
if (!is_artifact(baseObj, a_excludeForm)) {
continue;
}
cellItems[baseObj->formID] = true;
if (inv.find(baseObj) == inv.end()) {
a_cellStorage->AddObjectToContainer(baseObj, nullptr, 1, nullptr);
@ -170,6 +297,10 @@ namespace Papyrus::ArtifactTracker
inline void Bind(VM& a_vm)
{
BIND(AddAllFormsToList);
logger::info("Registered AddAllFormsToList"sv);
BIND(AddArtifactsToList);
logger::info("Registered AddArtifactsToList"sv);
BIND(GetCellStorage);
logger::info("Registered GetCellStorage"sv);
BIND(HasRefInCell);

View File

@ -2,194 +2,6 @@
namespace Papyrus::ObjectReference
{
namespace inv_util
{
inline bool can_be_taken(const std::unique_ptr<RE::InventoryEntryData>& a_entry, bool a_noEquipped, bool a_noFavourited, bool a_noQuestItem)
{
if (a_noEquipped && a_entry->IsWorn()) {
return false;
}
if (a_noFavourited && a_entry->IsFavorited()) {
return false;
}
if (a_noQuestItem && a_entry->IsQuestObject()) {
return false;
}
if (a_entry->object->formID == 0x000001F4) { // Unarmed
return false;
}
return true;
}
inline bool is_excluded(RE::TESForm* a_form, RE::TESForm* a_excludeForm = NULL)
{
if (!a_excludeForm) {
return false;
}
const RE::BGSListForm* list = a_excludeForm->As<RE::BGSListForm>();
if (list) {
if (list->HasForm(a_form)) {
return true;
} else {
bool isExcluded = false;
list->ForEachForm([&](RE::TESForm& a_exform) {
const auto exlist = a_exform.As<RE::BGSListForm>();
if (exlist) {
if (exlist->forms.size() > 0) {
if (exlist->forms[0]->Is(RE::FormType::Keyword) ? a_form->HasKeywordInList(exlist, false) : exlist->HasForm(a_form)) {
isExcluded = true;
return false;
}
}
} else {
const auto exkeyword = a_exform.As<RE::BGSKeyword>();
if (exkeyword && a_form->As<RE::BGSKeywordForm>()->HasKeyword(exkeyword)) {
isExcluded = true;
return false;
}
}
return true;
});
return isExcluded;
}
}
const RE::BGSKeyword* keyword = a_excludeForm->As<RE::BGSKeyword>();
if (keyword) {
if (a_form->As<RE::BGSKeywordForm>()->HasKeyword(keyword)) {
return true;
}
}
return false;
}
inline RE::ITEM_REMOVE_REASON get_remove_reason(RE::TESObjectREFR* atargetRef)
{
RE::ITEM_REMOVE_REASON iReason = RE::ITEM_REMOVE_REASON::kStoreInContainer;
if (atargetRef->As<RE::Actor>() && atargetRef->As<RE::Actor>()->IsPlayerTeammate()) {
iReason = RE::ITEM_REMOVE_REASON::kStoreInTeammate;
}
return iReason;
}
}
inline std::int32_t AddAllFormsToList(RE::StaticFunctionTag*,
RE::BGSListForm* a_targetList,
std::int32_t a_formType,
RE::TESForm* a_keywordOrList = NULL,
RE::TESForm* a_excludeForm = NULL,
bool a_onlyPlayable = true)
{
const auto formType = static_cast<RE::FormType>(a_formType);
const auto keyword = a_keywordOrList ? a_keywordOrList->As<RE::BGSKeyword>() : nullptr;
const auto keywordList = a_keywordOrList ? a_keywordOrList->As<RE::BGSListForm>() : nullptr;
const auto dataHandler = RE::TESDataHandler::GetSingleton();
if (!dataHandler) {
return a_targetList->forms.size();
}
for (const auto& form : dataHandler->GetFormArray(formType)) {
if (!form) {
continue;
}
if (a_onlyPlayable && !form->GetPlayable()) {
continue;
}
if ((keyword && !form->As<RE::BGSKeywordForm>()->HasKeyword(keyword)) || (keywordList && !form->HasKeywordInList(keywordList, false))) {
continue;
}
if (a_excludeForm && inv_util::is_excluded(form, a_excludeForm)) {
continue;
}
a_targetList->AddForm(form);
}
return a_targetList->forms.size();
}
inline std::int32_t AddItemsOfTypeAndKeywordToList(VM* a_vm, StackID a_stackID, RE::StaticFunctionTag*,
RE::TESForm* a_refOrList,
RE::BGSListForm* a_targetList,
std::uint32_t a_formType = 0,
RE::TESForm* a_keywordOrList = NULL,
RE::TESForm* a_excludeForm = NULL,
bool a_noEquipped = TRUE,
bool a_noFavourited = TRUE,
bool a_noQuestItem = TRUE)
{
if (!a_refOrList) {
a_vm->TraceStack("a_refOrList in AddItemsOfTypeAndKeywordToList is None", a_stackID);
return 0;
}
if (!a_targetList) {
a_vm->TraceStack("a_targetList in AddItemsOfTypeAndKeywordToList is None", a_stackID);
return 0;
}
if (a_refOrList->Is(RE::FormType::FormList)) {
a_refOrList->As<RE::BGSListForm>()->ForEachForm([&](RE::TESForm& a_exform) {
const auto refrItem = a_exform.As<RE::TESObjectREFR>();
if (refrItem) {
AddItemsOfTypeAndKeywordToList(a_vm, a_stackID, {}, refrItem, a_targetList, a_formType, a_keywordOrList, a_excludeForm, a_noEquipped, a_noFavourited, a_noQuestItem);
}
return true;
});
return a_targetList->forms.size();
}
const auto containerRef = a_refOrList->As<RE::TESObjectREFR>();
if (!containerRef) {
a_vm->TraceStack("containerRef in AddItemsOfTypeAndKeywordToList is not a reference", a_stackID);
return 0;
}
const auto formType = static_cast<RE::FormType>(a_formType);
const bool bNoType = formType == RE::FormType::None;
const auto keyword = a_keywordOrList ? a_keywordOrList->As<RE::BGSKeyword>() : nullptr;
const auto keywordList = a_keywordOrList ? a_keywordOrList->As<RE::BGSListForm>() : nullptr;
auto inv = containerRef->GetInventory([&](RE::TESBoundObject& a_exform) {
return (bNoType || a_exform.formType == formType)
&& (
(!keyword && !keywordList)
|| (keyword && a_exform.As<RE::BGSKeywordForm>()->HasKeyword(keyword))
|| (keywordList && a_exform.HasKeywordInList(keywordList, false)))
&& (!a_excludeForm || !inv_util::is_excluded(&a_exform, a_excludeForm))
&& a_exform.GetPlayable() && a_exform.formID != 0x000001F4;
});
if (containerRef->IsPlayerRef()) {
for (const auto& [item, data] : inv) {
const auto& [count, entry] = data;
if (count > 0 && inv_util::can_be_taken(entry, a_noEquipped, a_noFavourited, a_noQuestItem)) {
a_targetList->AddForm(item);
}
}
} else {
for (const auto& [item, data] : inv) {
const auto& [count, entry] = data;
if (count > 0) {
a_targetList->AddForm(item);
}
}
}
return a_targetList->forms.size();
}
inline std::uint32_t GetItemCountInList(RE::StaticFunctionTag*,
RE::BGSListForm* a_containerList,
RE::TESBoundObject* a_form)
@ -256,10 +68,6 @@ namespace Papyrus::ObjectReference
inline void Bind(VM& a_vm)
{
BIND(AddAllFormsToList);
logger::info("Registered AddAllFormsToList"sv);
BIND(AddItemsOfTypeAndKeywordToList);
logger::info("Registered AddItemsOfTypeAndKeywordToList"sv);
BIND(GetItemCountInList);
logger::info("Registered GetItemCountInList"sv);
BIND(GetItemCountInActors);

View File

@ -9,7 +9,7 @@ namespace Papyrus {
using StackID = RE::VMStackID;
using Severity = RE::BSScript::ErrorLogger::Severity;
inline constexpr auto script = "EddsArtifactTracker"sv;
inline constexpr auto script = "ETR_Functions"sv;
bool Bind(VM* a_vm);
}

View File

@ -1,12 +1,8 @@
Scriptname ETR_Functions Hidden
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ObjectReference functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
int function AddAllFormsToList(FormList targetList, int formType, Form excludeForm = None) native global
int function AddAllFormsToList(FormList targetList, int formType, Form keywordOrList = None, Form excludeForm = None, bool onlyPlayable = true) native global
int function AddItemsOfTypeAndKeywordToList(Form refOrList, FormList targetList, int formType = 0, Form keywordOrList = None, Form excludeForm = None, bool noEquipped = true, bool noFavourited = true, bool noQuestItem = true) native global
int function AddArtifactsToList(Form refOrList, FormList targetList, Form excludeForm = None, bool excludeOnlyMisc = false) native global
int function GetItemCountInList(FormList refList, Form baseForm) native global
@ -14,10 +10,6 @@ int function GetItemCountInActors(Actor[] refArray, Form baseForm) native global
Actor[] function GetPlayerFollowers() native global
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Artifact Tracker
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ObjectReference function GetCellStorage(ObjectReference ref, FormList refList, Form refToCreate, bool autoCreate = true) native global
bool function HasRefInCell(Form item, Cell currentCell = None, bool checkContainers = true, FormList excludeList = None) native global

View File

@ -7,17 +7,20 @@ FormList Property ETR_ItemsFound Auto
FormList Property ETR_ItemsStored Auto
FormList Property ETR_PersistentStorageList Auto
FormList Property ETR_ExcludeFromNew Auto
FormList Property ETR_ExcludeFromCellItems Auto
FormList Property ETR_ExcludeMisc Auto
Container Property ETR_CellStorageContainer Auto
Keyword Property LocTypePlayerHouse Auto
bool bAtHome = false
bool bBusy = false
int iFollowerIndex = 0
bool bUpdateFollowers = false
bool bSyncStorage = false
bool bUpdateLists = false
bool bAtHome = false
bool bRescanHome = false
bool bRescanPersistent = false
ObjectReference lastDestContainer = None
bool lastDestIsPersistent = false
int iUpdateCount
event OnInit()
@ -27,12 +30,16 @@ endevent
Event OnPlayerLoadGame()
AddInventoryEventFilter(ETR_ItemsFound)
Location currentLocation = PlayerRef.GetCurrentLocation()
bAtHome = currentLocation && currentLocation.HasKeyword(LocTypePlayerHouse)
lastDestContainer = None
EndEvent
Event OnLocationChange(Location akOldLoc, Location akNewLoc)
bAtHome = akNewLoc && akNewLoc.HasKeyword(LocTypePlayerHouse)
lastDestContainer = None
int iCurrentFollowers = 0;
Actor[] aFollowers = ETR_Functions.GetPlayerFollowers()
@ -43,105 +50,96 @@ Event OnLocationChange(Location akOldLoc, Location akNewLoc)
endwhile
if iCurrentFollowers != iFollowerIndex
; If the list of followers has changed, rebuild ETR_ItemsFound and ETR_ItemsNew
iFollowerIndex = iCurrentFollowers
bUpdateFollowers = true
bRescanHome = false
bRescanPersistent = false
RegisterForSingleUpdate(3.0) ; wait until followers load into the location
endif
endEvent
Event OnMenuClose(String MenuName)
UnregisterForUpdate()
OnUpdate()
EndEvent
Event OnUpdate()
Actor[] aFollowers
int i
if UI.IsMenuOpen("ContainerMenu")
RegisterForMenu("ContainerMenu")
return
endif
if bUpdateLists
while bBusy
Debug.Notification("Found OnUpdate is busy")
Utility.wait(0.5)
endwhile
if Utility.IsInMenuMode()
RegisterForSingleUpdate(1.0)
bBusy = true
iUpdateCount += 1
Debug.Notification("Running Found OnUpdate " + iUpdateCount)
if bRescanHome
if lastDestContainer && lastDestContainer as Actor && (lastDestContainer as Actor).IsPlayerTeammate()
lastDestContainer = None
return
endif
bUpdateLists = false
bUpdateFollowers = false
if bSyncStorage
bSyncStorage = false
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeFromCellItems)
bRescanHome = false
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
if ! bRescanPersistent
ETR_Functions.AddArtifactsToList(cellStorage, ETR_ItemsStored)
endif
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 26, None, ETR_ExcludeFromCellItems)
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 41, None, ETR_ExcludeFromCellItems)
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 27, None, ETR_ExcludeFromCellItems)
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 32, None, ETR_ExcludeFromCellItems)
ETR_ItemsFound.Revert()
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 41, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 27, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 32, None, ETR_ExcludeFromNew, false, false, false)
aFollowers = ETR_Functions.GetPlayerFollowers()
i = aFollowers.length
while i > 0
i -= 1
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 41, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 27, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 32, None, ETR_ExcludeFromNew, false, false, false)
endwhile
ETR_ItemsNew.Revert()
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 26, None, ETR_ExcludeFromNew) ; armor
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 41, None, ETR_ExcludeFromNew) ; weapons
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 27, None, ETR_ExcludeFromNew) ; books
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 32, None, ETR_ExcludeFromNew) ; misc items
return
endif
if bUpdateFollowers
bUpdateFollowers = false
Debug.Notification("Team changed, updating lists")
ETR_ItemsFound.Revert()
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 41, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 27, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 32, None, ETR_ExcludeFromNew, false, false, false)
aFollowers = ETR_Functions.GetPlayerFollowers()
i = aFollowers.length
while i > 0
i -= 1
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 41, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 27, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 32, None, ETR_ExcludeFromNew, false, false, false)
if bRescanPersistent
bRescanPersistent = false
Form[] aContainers = ETR_PersistentStorageList.ToArray()
int n = aContainers.length
while n > 0
n -= 1
ETR_Functions.AddArtifactsToList(aContainers[n], ETR_ItemsStored, ETR_ExcludeMisc, true)
endwhile
ETR_ItemsNew.Revert()
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 26, None, ETR_ExcludeFromNew) ; armor
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 41, None, ETR_ExcludeFromNew) ; weapons
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 27, None, ETR_ExcludeFromNew) ; books
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 32, None, ETR_ExcludeFromNew) ; misc items
endif
ETR_ItemsFound.Revert()
ETR_Functions.AddArtifactsToList(PlayerRef, ETR_ItemsFound, ETR_ExcludeFromNew)
Actor[] aFollowers = ETR_Functions.GetPlayerFollowers()
int i = aFollowers.length
while i > 0
i -= 1
ETR_Functions.AddArtifactsToList(aFollowers[i], ETR_ItemsFound, ETR_ExcludeFromNew)
endwhile
bBusy = false
EndEvent
event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
if akDestContainer
bSyncStorage = bAtHome
bUpdateLists = true
RegisterForSingleUpdate(1.0)
if lastDestContainer != akDestContainer
lastDestContainer = akDestContainer
lastDestIsPersistent = ETR_PersistentStorageList.HasForm(akDestContainer)
endif
; Moving items without latent functions should help with avoiding stack dumps
if lastDestIsPersistent
bRescanHome = false
bRescanPersistent = true
RegisterForSingleUpdate(0.5)
elseif bAtHome
bRescanHome = true
bRescanPersistent = false
RegisterForSingleUpdate(0.5)
elseif PlayerRef.GetItemCount(akBaseItem) == 0 && ETR_Functions.GetItemCountInActors(ETR_Functions.GetPlayerFollowers(), akBaseItem) == 0
ETR_ItemsFound.RemoveAddedForm(akBaseItem)
ETR_ItemsNew.AddForm(akBaseItem)
endif
elseif bAtHome && akItemReference
ETR_ItemsFound.RemoveAddedForm(akBaseItem)
ETR_ItemsStored.AddForm(akBaseItem)

View File

@ -7,6 +7,8 @@ FormList Property ETR_ItemsFound Auto
FormList Property ETR_ItemsStored Auto
FormList Property ETR_ExcludeFromNew Auto
FormList Property ETR_PersistentStorageList Auto
FormList Property ETR_ExcludeMisc Auto
FormList Property ETR_FoundAndStored Auto
event OnInit()
@ -36,37 +38,32 @@ event OnPlayerLoadGame()
ahzmorehudie.RegisterIconFormList("dbmDisp", ETR_ItemsStored)
endif
If SKSE.GetPluginVersion("QuickLootRE") >= 292
QuickLootRE.RegisterNewItemsList(ETR_ItemsNew)
QuickLootRE.RegisterDisplayedItemsList(ETR_ItemsStored)
QuickLootRE.RegisterFoundItemsList(ETR_ItemsFound)
endif
; Rebuild all lists to avoid discrepancies, stale data, and broken records
ETR_ItemsStored.Revert()
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 26, None, ETR_ExcludeFromNew)
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 41, None, ETR_ExcludeFromNew)
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 27, None, ETR_ExcludeFromNew)
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 32, None, ETR_ExcludeFromNew)
ETR_Functions.AddArtifactsToList(ETR_PersistentStorageList, ETR_ItemsStored, ETR_ExcludeMisc, true)
ETR_ItemsFound.Revert()
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 41, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 27, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 32, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddArtifactsToList(PlayerRef, ETR_ItemsFound, ETR_ExcludeFromNew)
Actor[] aFollowers = ETR_Functions.GetPlayerFollowers()
int i = aFollowers.length
while i > 0
i -= 1
if ! aFollowers[i].IsDead() && ! aFollowers[i].IsDisabled()
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 41, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 27, None, ETR_ExcludeFromNew, false, false, false)
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 32, None, ETR_ExcludeFromNew, false, false, false)
endif
ETR_Functions.AddArtifactsToList(aFollowers[i], ETR_ItemsFound, ETR_ExcludeFromNew)
endwhile
ETR_ItemsNew.Revert()
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 26, None, ETR_ExcludeFromNew) ; armor
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 41, None, ETR_ExcludeFromNew) ; weapons
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 27, None, ETR_ExcludeFromNew) ; books
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 32, None, ETR_ExcludeFromNew) ; misc items
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 26, ETR_FoundAndStored)
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 27, ETR_FoundAndStored)
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 32, ETR_ExcludeFromNew)
ETR_Functions.AddAllFormsToList(ETR_ItemsNew, 41, ETR_FoundAndStored)
endevent

View File

@ -6,12 +6,22 @@ FormList Property ETR_ItemsNew Auto
FormList Property ETR_ItemsFound Auto
FormList Property ETR_ItemsStored Auto
FormList Property ETR_PersistentStorageList Auto
FormList Property ETR_ExcludeFromNew Auto
FormList Property ETR_ExcludeMisc Auto
Container Property ETR_CellStorageContainer Auto
Keyword Property LocTypePlayerHouse Auto
bool bBusy = false
bool bAtHome = false
bool bRescanHome = false
bool bRescanPersistent = false
ObjectReference lastDestContainer = None
bool lastDestIsPersistent = false
ObjectReference lastSourceContainer = None
bool lastSourceIsPersistent = false
int iUpdateCount
event OnInit()
@ -21,69 +31,134 @@ endevent
Event OnPlayerLoadGame()
AddInventoryEventFilter(ETR_ItemsStored)
Location currentLocation = PlayerRef.GetCurrentLocation()
bAtHome = currentLocation && currentLocation.HasKeyword(LocTypePlayerHouse)
if bAtHome
GotoState("AtHome")
else
GotoState("")
endif
EndEvent
Event OnLocationChange(Location akOldLoc, Location akNewLoc)
bAtHome = akNewLoc && akNewLoc.HasKeyword(LocTypePlayerHouse)
if bAtHome
GotoState("AtHome")
else
GotoState("")
endif
endEvent
; The item is already registered as stored, and we just stored more
event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
Event OnMenuClose(String MenuName)
UnregisterForUpdate()
OnUpdate()
EndEvent
if ! bAtHome
Event OnUpdate()
if UI.IsMenuOpen("ContainerMenu")
RegisterForMenu("ContainerMenu")
return
endif
if akDestContainer
while bBusy
Debug.Notification("Stored OnUpdate is busy")
Utility.wait(0.5)
endwhile
if !(akDestContainer as Actor)
if ETR_PersistentStorageList.HasForm(akDestContainer)
return
endif
elseif (akDestContainer as Actor).IsPlayerTeammate()
bBusy = true
iUpdateCount += 1
Debug.Notification("Running Stored OnUpdate " + iUpdateCount)
if bRescanHome
if lastSourceContainer && lastSourceContainer as Actor && (lastSourceContainer as Actor).IsPlayerTeammate()
lastSourceContainer = None
return
endif
endif
if ((akDestContainer && akDestContainer.GetParentCell() == PlayerRef.GetParentCell()) || (! akDestContainer && ETR_Functions.HasRefInCell(akBaseItem, None, true, ETR_PersistentStorageList)))
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
endif
if cellStorage.GetItemCount(akBaseItem) == 0
cellStorage.AddItem(akBaseItem, 1, true)
endif
if bRescanPersistent
ETR_ItemsStored.Revert()
Form[] aContainers = ETR_PersistentStorageList.ToArray()
int n = aContainers.length
while n > 0
n -= 1
ETR_Functions.AddArtifactsToList(aContainers[n], ETR_ItemsStored, ETR_ExcludeMisc, true)
endwhile
ETR_ItemsFound.Revert()
ETR_Functions.AddArtifactsToList(PlayerRef, ETR_ItemsFound, ETR_ExcludeFromNew)
Actor[] aFollowers = ETR_Functions.GetPlayerFollowers()
int i = aFollowers.length
while i > 0
i -= 1
ETR_Functions.AddArtifactsToList(aFollowers[i], ETR_ItemsFound, ETR_ExcludeFromNew)
endwhile
endif
endevent
bBusy = false
EndEvent
; We took a stored item, and we want to find out if it's the last stored item of its kind
; We acquired a stored item, and we want to find out if we just have taken the last stored item of its kind
event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
if akSourceContainer && !(akSourceContainer as Actor) && ETR_PersistentStorageList.HasForm(akSourceContainer)
if ETR_Functions.GetItemCountInList(ETR_PersistentStorageList, akBaseItem) == 0
ETR_ItemsStored.RemoveAddedForm(akBaseItem)
ETR_ItemsFound.AddForm(akBaseItem)
if akSourceContainer
if lastSourceContainer != akSourceContainer
lastSourceContainer = akSourceContainer
lastSourceIsPersistent = ETR_PersistentStorageList.HasForm(akSourceContainer)
endif
if bAtHome || lastSourceIsPersistent
bRescanHome = bAtHome
bRescanPersistent = true
RegisterForSingleUpdate(0.5)
endif
elseif bAtHome
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
int iCount = cellStorage.GetItemCount(akBaseItem)
if iCount > 0 && ! ETR_Functions.HasRefInCell(akBaseItem, None, true, ETR_PersistentStorageList)
cellStorage.RemoveItem(akBaseItem, iCount, true)
if cellStorage.GetItemCount(akBaseItem)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
if ETR_Functions.GetItemCountInList(ETR_PersistentStorageList, akBaseItem) == 0
ETR_ItemsStored.RemoveAddedForm(akBaseItem)
ETR_ItemsFound.AddForm(akBaseItem)
endif
endif
endif
endevent
state AtHome
; The item is already registered as stored, and we just stored more
event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
if akDestContainer
if lastDestContainer != akDestContainer
lastDestContainer = akDestContainer
lastDestIsPersistent = ETR_PersistentStorageList.HasForm(akDestContainer)
endif
if ! lastDestIsPersistent
bRescanHome = true
bRescanPersistent = false
RegisterForSingleUpdate(0.5)
endif
elseif akItemReference
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
if cellStorage.GetItemCount(akBaseItem) == 0
cellStorage.AddItem(akBaseItem, 1, true)
endif
endif
endevent
endstate