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;
@ -146,12 +273,12 @@ namespace Papyrus::ArtifactTracker
if (cellItems.contains(baseObj->formID)) { if (cellItems.contains(baseObj->formID)) {
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,105 +50,96 @@ 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")
return
endif
if bUpdateLists while bBusy
Debug.Notification("Found OnUpdate is busy")
Utility.wait(0.5)
endwhile
if Utility.IsInMenuMode() bBusy = true
RegisterForSingleUpdate(1.0)
iUpdateCount += 1
Debug.Notification("Running Found OnUpdate " + iUpdateCount)
if bRescanHome
if lastDestContainer && lastDestContainer as Actor && (lastDestContainer as Actor).IsPlayerTeammate()
lastDestContainer = None
return return
endif endif
bRescanHome = false
bUpdateLists = false ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
bUpdateFollowers = false ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
if ! bRescanPersistent
if bSyncStorage ETR_Functions.AddArtifactsToList(cellStorage, ETR_ItemsStored)
bSyncStorage = false
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeFromCellItems)
endif 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 endif
if bUpdateFollowers if bRescanPersistent
bUpdateFollowers = false bRescanPersistent = false
Form[] aContainers = ETR_PersistentStorageList.ToArray()
Debug.Notification("Team changed, updating lists") int n = aContainers.length
while n > 0
ETR_ItemsFound.Revert() n -= 1
ETR_Functions.AddItemsOfTypeAndKeywordToList(PlayerRef, ETR_ItemsFound, 26, None, ETR_ExcludeFromNew, false, false, false) ETR_Functions.AddArtifactsToList(aContainers[n], ETR_ItemsStored, ETR_ExcludeMisc, true)
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 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 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 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
if akDestContainer while bBusy
Debug.Notification("Stored OnUpdate is busy")
Utility.wait(0.5)
endwhile
if !(akDestContainer as Actor) bBusy = true
if ETR_PersistentStorageList.HasForm(akDestContainer)
return iUpdateCount += 1
endif Debug.Notification("Running Stored OnUpdate " + iUpdateCount)
elseif (akDestContainer as Actor).IsPlayerTeammate()
if bRescanHome
if lastSourceContainer && lastSourceContainer as Actor && (lastSourceContainer as Actor).IsPlayerTeammate()
lastSourceContainer = None
return return
endif 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) ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
endif
if cellStorage.GetItemCount(akBaseItem) == 0 if bRescanPersistent
cellStorage.AddItem(akBaseItem, 1, true)
endif 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 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) event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
if akSourceContainer && !(akSourceContainer as Actor) && ETR_PersistentStorageList.HasForm(akSourceContainer) if akSourceContainer
if ETR_Functions.GetItemCountInList(ETR_PersistentStorageList, akBaseItem) == 0 if lastSourceContainer != akSourceContainer
ETR_ItemsStored.RemoveAddedForm(akBaseItem) lastSourceContainer = akSourceContainer
ETR_ItemsFound.AddForm(akBaseItem) lastSourceIsPersistent = ETR_PersistentStorageList.HasForm(akSourceContainer)
endif
if bAtHome || lastSourceIsPersistent
bRescanHome = bAtHome
bRescanPersistent = true
RegisterForSingleUpdate(0.5)
endif endif
elseif bAtHome elseif bAtHome
ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer) ObjectReference cellStorage = ETR_Functions.GetCellStorage(PlayerRef, ETR_PersistentStorageList, ETR_CellStorageContainer)
int iCount = cellStorage.GetItemCount(akBaseItem) if cellStorage.GetItemCount(akBaseItem)
ETR_Functions.SyncCellStorage(cellStorage, ETR_ExcludeMisc)
if iCount > 0 && ! ETR_Functions.HasRefInCell(akBaseItem, None, true, ETR_PersistentStorageList)
cellStorage.RemoveItem(akBaseItem, iCount, true)
if ETR_Functions.GetItemCountInList(ETR_PersistentStorageList, akBaseItem) == 0 if ETR_Functions.GetItemCountInList(ETR_PersistentStorageList, akBaseItem) == 0
ETR_ItemsStored.RemoveAddedForm(akBaseItem) ETR_ItemsStored.RemoveAddedForm(akBaseItem)
ETR_ItemsFound.AddForm(akBaseItem) ETR_ItemsFound.AddForm(akBaseItem)
endif endif
endif endif
endif endif
endevent 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