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 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) inline bool is_artifact(RE::TESForm* a_form, RE::TESForm* a_excludeForm = NULL)
{ {
const auto formType = a_form->GetFormType(); const auto formType = a_form->GetFormType();
@ -10,13 +58,93 @@ namespace Papyrus::ArtifactTracker
return false; 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 false;
} }
return true; 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*, inline RE::TESObjectREFR* GetCellStorage(RE::StaticFunctionTag*,
RE::TESObjectREFR* a_ref, RE::TESObjectREFR* a_ref,
RE::BGSListForm* a_refList, RE::BGSListForm* a_refList,
@ -119,12 +247,11 @@ namespace Papyrus::ArtifactTracker
continue; 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) { for (const auto& [item, data] : contInv) {
if (cellItems.contains(item->formID)) {
continue;
}
const auto& [count, entry] = data; const auto& [count, entry] = data;
if (count > 0) { if (count > 0) {
cellItems[item->formID] = true; cellItems[item->formID] = true;
@ -147,12 +274,12 @@ namespace Papyrus::ArtifactTracker
continue; continue;
} }
cellItems[baseObj->formID] = true;
if (!is_artifact(baseObj, a_excludeForm)) { if (!is_artifact(baseObj, a_excludeForm)) {
continue; continue;
} }
cellItems[baseObj->formID] = true;
if (inv.find(baseObj) == inv.end()) { if (inv.find(baseObj) == inv.end()) {
a_cellStorage->AddObjectToContainer(baseObj, nullptr, 1, nullptr); a_cellStorage->AddObjectToContainer(baseObj, nullptr, 1, nullptr);
} }
@ -170,6 +297,10 @@ namespace Papyrus::ArtifactTracker
inline void Bind(VM& a_vm) inline void Bind(VM& a_vm)
{ {
BIND(AddAllFormsToList);
logger::info("Registered AddAllFormsToList"sv);
BIND(AddArtifactsToList);
logger::info("Registered AddArtifactsToList"sv);
BIND(GetCellStorage); BIND(GetCellStorage);
logger::info("Registered GetCellStorage"sv); logger::info("Registered GetCellStorage"sv);
BIND(HasRefInCell); BIND(HasRefInCell);

View File

@ -2,194 +2,6 @@
namespace Papyrus::ObjectReference 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*, inline std::uint32_t GetItemCountInList(RE::StaticFunctionTag*,
RE::BGSListForm* a_containerList, RE::BGSListForm* a_containerList,
RE::TESBoundObject* a_form) RE::TESBoundObject* a_form)
@ -256,10 +68,6 @@ namespace Papyrus::ObjectReference
inline void Bind(VM& a_vm) inline void Bind(VM& a_vm)
{ {
BIND(AddAllFormsToList);
logger::info("Registered AddAllFormsToList"sv);
BIND(AddItemsOfTypeAndKeywordToList);
logger::info("Registered AddItemsOfTypeAndKeywordToList"sv);
BIND(GetItemCountInList); BIND(GetItemCountInList);
logger::info("Registered GetItemCountInList"sv); logger::info("Registered GetItemCountInList"sv);
BIND(GetItemCountInActors); BIND(GetItemCountInActors);

View File

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

View File

@ -1,12 +1,8 @@
Scriptname ETR_Functions Hidden Scriptname ETR_Functions Hidden
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; int function AddAllFormsToList(FormList targetList, int formType, Form excludeForm = None) native global
; ObjectReference functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
int function AddAllFormsToList(FormList targetList, int formType, Form keywordOrList = None, Form excludeForm = None, bool onlyPlayable = true) native global int function AddArtifactsToList(Form refOrList, FormList targetList, Form excludeForm = None, bool excludeOnlyMisc = false) 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 GetItemCountInList(FormList refList, Form baseForm) 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 Actor[] function GetPlayerFollowers() native global
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Artifact Tracker
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ObjectReference function GetCellStorage(ObjectReference ref, FormList refList, Form refToCreate, bool autoCreate = true) native global 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 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_ItemsStored Auto
FormList Property ETR_PersistentStorageList Auto FormList Property ETR_PersistentStorageList Auto
FormList Property ETR_ExcludeFromNew Auto FormList Property ETR_ExcludeFromNew Auto
FormList Property ETR_ExcludeFromCellItems Auto FormList Property ETR_ExcludeMisc Auto
Container Property ETR_CellStorageContainer Auto Container Property ETR_CellStorageContainer Auto
Keyword Property LocTypePlayerHouse Auto Keyword Property LocTypePlayerHouse Auto
bool bAtHome = false bool bBusy = false
int iFollowerIndex = 0 int iFollowerIndex = 0
bool bUpdateFollowers = false bool bAtHome = false
bool bSyncStorage = false bool bRescanHome = false
bool bUpdateLists = false bool bRescanPersistent = false
ObjectReference lastDestContainer = None
bool lastDestIsPersistent = false
int iUpdateCount
event OnInit() event OnInit()
@ -27,12 +30,16 @@ endevent
Event OnPlayerLoadGame() Event OnPlayerLoadGame()
AddInventoryEventFilter(ETR_ItemsFound) AddInventoryEventFilter(ETR_ItemsFound)
Location currentLocation = PlayerRef.GetCurrentLocation()
bAtHome = currentLocation && currentLocation.HasKeyword(LocTypePlayerHouse)
lastDestContainer = None
EndEvent EndEvent
Event OnLocationChange(Location akOldLoc, Location akNewLoc) Event OnLocationChange(Location akOldLoc, Location akNewLoc)
bAtHome = akNewLoc && akNewLoc.HasKeyword(LocTypePlayerHouse) bAtHome = akNewLoc && akNewLoc.HasKeyword(LocTypePlayerHouse)
lastDestContainer = None
int iCurrentFollowers = 0; int iCurrentFollowers = 0;
Actor[] aFollowers = ETR_Functions.GetPlayerFollowers() Actor[] aFollowers = ETR_Functions.GetPlayerFollowers()
@ -43,95 +50,72 @@ Event OnLocationChange(Location akOldLoc, Location akNewLoc)
endwhile endwhile
if iCurrentFollowers != iFollowerIndex if iCurrentFollowers != iFollowerIndex
; If the list of followers has changed, rebuild ETR_ItemsFound and ETR_ItemsNew
iFollowerIndex = iCurrentFollowers iFollowerIndex = iCurrentFollowers
bUpdateFollowers = true bRescanHome = false
bRescanPersistent = false
RegisterForSingleUpdate(3.0) ; wait until followers load into the location RegisterForSingleUpdate(3.0) ; wait until followers load into the location
endif endif
endEvent endEvent
Event OnMenuClose(String MenuName)
UnregisterForUpdate()
OnUpdate()
EndEvent
Event OnUpdate() Event OnUpdate()
Actor[] aFollowers if UI.IsMenuOpen("ContainerMenu")
int i RegisterForMenu("ContainerMenu")
if bUpdateLists
if Utility.IsInMenuMode()
RegisterForSingleUpdate(1.0)
return return
endif endif
bUpdateLists = false while bBusy
bUpdateFollowers = false Debug.Notification("Found OnUpdate is busy")
Utility.wait(0.5)
endwhile
if bSyncStorage bBusy = true
bSyncStorage = false
iUpdateCount += 1
Debug.Notification("Running Found OnUpdate " + iUpdateCount)
if bRescanHome
if lastDestContainer && lastDestContainer as Actor && (lastDestContainer as Actor).IsPlayerTeammate()
lastDestContainer = None
return
endif
bRescanHome = false
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer) ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeFromCellItems) ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
if ! bRescanPersistent
ETR_Functions.AddArtifactsToList(cellStorage, ETR_ItemsStored)
endif
endif endif
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 26, None, ETR_ExcludeFromCellItems) if bRescanPersistent
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 41, None, ETR_ExcludeFromCellItems) bRescanPersistent = false
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 27, None, ETR_ExcludeFromCellItems) Form[] aContainers = ETR_PersistentStorageList.ToArray()
ETR_Functions.AddItemsOfTypeAndKeywordToList(ETR_PersistentStorageList, ETR_ItemsStored, 32, None, ETR_ExcludeFromCellItems) int n = aContainers.length
while n > 0
n -= 1
ETR_Functions.AddArtifactsToList(aContainers[n], ETR_ItemsStored, ETR_ExcludeMisc, true)
endwhile
endif
ETR_ItemsFound.Revert() ETR_ItemsFound.Revert()
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false) ETR_Functions.AddArtifactsToList(PlayerRef, ETR_ItemsFound, ETR_ExcludeFromNew)
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() Actor[] aFollowers = ETR_Functions.GetPlayerFollowers()
i = aFollowers.length int i = aFollowers.length
while i > 0 while i > 0
i -= 1 i -= 1
ETR_Functions.AddItemsOfTypeAndKeywordToList(aFollowers[i], ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false) ETR_Functions.AddArtifactsToList(aFollowers[i], ETR_ItemsFound, ETR_ExcludeFromNew)
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 endwhile
ETR_ItemsNew.Revert() bBusy = false
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)
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
EndEvent EndEvent
@ -139,9 +123,23 @@ EndEvent
event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
if akDestContainer if akDestContainer
bSyncStorage = bAtHome if lastDestContainer != akDestContainer
bUpdateLists = true lastDestContainer = akDestContainer
RegisterForSingleUpdate(1.0) 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 elseif bAtHome && akItemReference
ETR_ItemsFound.RemoveAddedForm(akBaseItem) ETR_ItemsFound.RemoveAddedForm(akBaseItem)
ETR_ItemsStored.AddForm(akBaseItem) ETR_ItemsStored.AddForm(akBaseItem)

View File

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

View File

@ -6,12 +6,22 @@ FormList Property ETR_ItemsNew Auto
FormList Property ETR_ItemsFound Auto FormList Property ETR_ItemsFound Auto
FormList Property ETR_ItemsStored Auto FormList Property ETR_ItemsStored Auto
FormList Property ETR_PersistentStorageList Auto FormList Property ETR_PersistentStorageList Auto
FormList Property ETR_ExcludeFromNew Auto
FormList Property ETR_ExcludeMisc Auto
Container Property ETR_CellStorageContainer Auto Container Property ETR_CellStorageContainer Auto
Keyword Property LocTypePlayerHouse Auto Keyword Property LocTypePlayerHouse Auto
bool bBusy = false
bool bAtHome = 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() event OnInit()
@ -21,69 +31,134 @@ endevent
Event OnPlayerLoadGame() Event OnPlayerLoadGame()
AddInventoryEventFilter(ETR_ItemsStored) AddInventoryEventFilter(ETR_ItemsStored)
Location currentLocation = PlayerRef.GetCurrentLocation()
bAtHome = currentLocation && currentLocation.HasKeyword(LocTypePlayerHouse)
if bAtHome
GotoState("AtHome")
else
GotoState("")
endif
EndEvent EndEvent
Event OnLocationChange(Location akOldLoc, Location akNewLoc) Event OnLocationChange(Location akOldLoc, Location akNewLoc)
bAtHome = akNewLoc && akNewLoc.HasKeyword(LocTypePlayerHouse) bAtHome = akNewLoc && akNewLoc.HasKeyword(LocTypePlayerHouse)
if bAtHome
GotoState("AtHome")
else
GotoState("")
endif
endEvent endEvent
; The item is already registered as stored, and we just stored more Event OnMenuClose(String MenuName)
event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) UnregisterForUpdate()
OnUpdate()
EndEvent
if ! bAtHome
Event OnUpdate()
if UI.IsMenuOpen("ContainerMenu")
RegisterForMenu("ContainerMenu")
return return
endif endif
while bBusy
Debug.Notification("Stored OnUpdate is busy")
Utility.wait(0.5)
endwhile
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
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
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
bBusy = false
EndEvent
; 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
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)
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 akDestContainer
if lastDestContainer != akDestContainer
if !(akDestContainer as Actor) lastDestContainer = akDestContainer
if ETR_PersistentStorageList.HasForm(akDestContainer) lastDestIsPersistent = ETR_PersistentStorageList.HasForm(akDestContainer)
return
endif endif
elseif (akDestContainer as Actor).IsPlayerTeammate() if ! lastDestIsPersistent
return bRescanHome = true
bRescanPersistent = false
RegisterForSingleUpdate(0.5)
endif endif
elseif akItemReference
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) ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
if cellStorage.GetItemCount(akBaseItem) == 0 if cellStorage.GetItemCount(akBaseItem) == 0
cellStorage.AddItem(akBaseItem, 1, true) cellStorage.AddItem(akBaseItem, 1, true)
endif endif
endif endif
endevent endevent
endstate
; We took a stored item, and we want to find out if it's 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)
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 ETR_Functions.GetItemCountInList(ETR_PersistentStorageList, akBaseItem) == 0
ETR_ItemsStored.RemoveAddedForm(akBaseItem)
ETR_ItemsFound.AddForm(akBaseItem)
endif
endif
endif
endevent