diff --git a/Blueprint control.esp b/Blueprint control.esp new file mode 100644 index 00000000..a0863814 Binary files /dev/null and b/Blueprint control.esp differ diff --git a/scripts/_00E_BlueprintCollectionItem.pex b/scripts/_00E_BlueprintCollectionItem.pex new file mode 100644 index 00000000..2da75ca8 Binary files /dev/null and b/scripts/_00E_BlueprintCollectionItem.pex differ diff --git a/scripts/_00E_BlueprintControlAlias.pex b/scripts/_00E_BlueprintControlAlias.pex new file mode 100644 index 00000000..510a9c00 Binary files /dev/null and b/scripts/_00E_BlueprintControlAlias.pex differ diff --git a/scripts/_00e_nq24_leveledlistcheck.pex b/scripts/_00e_nq24_leveledlistcheck.pex index 62a90a70..fc2433b3 100644 Binary files a/scripts/_00e_nq24_leveledlistcheck.pex and b/scripts/_00e_nq24_leveledlistcheck.pex differ diff --git a/scripts/enderalfunctions.pex b/scripts/enderalfunctions.pex index 89990827..8c4ef08a 100644 Binary files a/scripts/enderalfunctions.pex and b/scripts/enderalfunctions.pex differ diff --git a/source/Enderal DLL/src/PapyrusFunctions.h b/source/Enderal DLL/src/PapyrusFunctions.h index e9cfa280..5213bd7a 100644 --- a/source/Enderal DLL/src/PapyrusFunctions.h +++ b/source/Enderal DLL/src/PapyrusFunctions.h @@ -128,6 +128,33 @@ namespace Papyrus::PapyrusFunctions return false; } + uint32_t MoveItemsToCountByKeyword(RE::StaticFunctionTag*, RE::TESObjectREFR* a_sourceRef, RE::TESObjectREFR* a_targetRef, RE::BGSKeyword* a_keyword, uint32_t a_count = 1) + { + const auto inv = a_sourceRef->GetInventory([&](RE::TESBoundObject& a_exform) { + auto miscItem = a_exform.As(); + return miscItem && miscItem->HasKeyword(a_keyword); + }); + + uint32_t iResult = 0; + for (const auto& item : inv) { + if (item.second.first > 0) { + int32_t iMoveCount = a_count - GetItemCount(a_targetRef, item.first); + if (iMoveCount > 0) { + a_sourceRef->RemoveItem(item.first, iMoveCount, RE::ITEM_REMOVE_REASON::kStoreInContainer, nullptr, a_targetRef); + iResult += iMoveCount; + } + } + } + + auto inventory_menu = RE::UI::GetSingleton()->GetMenu(); + + if (inventory_menu) { + inventory_menu->GetRuntimeData().itemList->Update(); + } + + return iResult; + } + inline void Bind(VM& a_vm) { BIND(CreatePotion); @@ -150,5 +177,7 @@ namespace Papyrus::PapyrusFunctions logger::info("{}", "Registered ComputeNeededExp"sv); BIND(IsInRegion); logger::info("{}", "Registered IsInRegion"sv); + BIND(MoveItemsToCountByKeyword); + logger::info("{}", "Registered MoveItemsToCountByKeyword"sv); } } diff --git a/source/Enderal DLL/src/Util.h b/source/Enderal DLL/src/Util.h index 8d526efd..353ccb19 100644 --- a/source/Enderal DLL/src/Util.h +++ b/source/Enderal DLL/src/Util.h @@ -192,4 +192,36 @@ inline float ComputeNeededExpPoints(std::uint32_t CurrentLevel, float Slope, flo result += (pow(40, Slope) - pow(30, Slope)) * Mult * fExpAcc_Level30; result += (pow(CurrentLevel, Slope) - pow(40, Slope)) * Mult * fExpAcc_Level40; return result; -} \ No newline at end of file +} + +inline std::uint32_t GetItemCount(RE::TESObjectREFR* a_container, RE::TESForm* a_form) +{ + std::int32_t iResult = 0; + + auto invChanges = a_container->GetInventoryChanges(); + if (invChanges && invChanges->entryList) { + for (auto& entry : *invChanges->entryList) { + if (entry && entry->object == a_form) { + if (entry->IsLeveled()) { + return entry->countDelta > 0 ? entry->countDelta : 0; + } else { + iResult = entry->countDelta; + break; + } + } + } + } + + auto container = a_container->GetContainer(); + if (container) { + container->ForEachContainerObject([&](RE::ContainerObject& a_entry) { + if (a_entry.obj == a_form) { + iResult += a_entry.count; + return RE::BSContainer::ForEachResult::kStop; + } + return RE::BSContainer::ForEachResult::kContinue; + }); + } + + return iResult > 0 ? iResult : 0; +} diff --git a/source/scripts/_00E_BlueprintCollectionItem.psc b/source/scripts/_00E_BlueprintCollectionItem.psc new file mode 100644 index 00000000..31d2a871 --- /dev/null +++ b/source/scripts/_00E_BlueprintCollectionItem.psc @@ -0,0 +1,85 @@ +Scriptname _00E_BlueprintCollectionItem extends ObjectReference Hidden + +Event OnEquipped(Actor akActor) + + If akActor != PlayerREF || ! (GetBaseObject() as MiscObject) + return + endif + + bInventoryMenu = SKSE.GetVersion() > 0 && UI.IsMenuOpen("InventoryMenu") + _00E_FS_BlueprintContainerActorREF.SetPlayerTeammate(True, True) + + Int iButton = _00E_FS_Blueprint_Message_SE.Show() + If iButton == 0 + AddBlueprints() + ElseIf iButton == 1 + StoreSingleCopy() + ElseIf iButton == 2 + TakeBlueprints() + EndIf + +EndEvent + +Function AddBlueprints() + if bInventoryMenu + ; The DisablePlayerControls method does not remember last inventory tab to return where we were + Input.TapKey(Input.GetMappedKey("Tween Menu")) + endif + Game.DisablePlayerControls(abMenu = true) + Game.EnablePlayerControls(abMenu = true) + Utility.Wait(0.05) + _00E_FS_BlueprintContainerActorREF.ShowGiftMenu(True, _00E_FS_BlueprintList, True, False) + if bInventoryMenu + Utility.wait(0.2) + Input.TapKey(Input.GetMappedKey("Quick Inventory")) + endif +EndFunction + +function StoreSingleCopy() +;/ Too slow + int iItemsToStore = PlayerREF.GetItemCount(Blueprint) - _00E_FS_BlueprintContainerActorREF.GetItemCount(Blueprint) + bool bStoreSilently = iItemsToStore > 3 + Int iFormIndex = PlayerREF.GetNumItems() + While iFormIndex > 0 + iFormIndex -= 1 + Form kForm = PlayerREF.GetNthForm(iFormIndex) + If kForm as MiscObject && kForm.HasKeyword(Blueprint) && _00E_FS_BlueprintContainerActorREF.GetItemCount(kForm) == 0 + PlayerREF.RemoveItem(kForm, 1, bStoreSilently, _00E_FS_BlueprintContainerActorREF) + EndIf + EndWhile + if bStoreSilently + _00E_FS_BlueprintItemsStored.Show(iItemsToStore) + endif +/; + ITMBookClose.Play(PlayerREF) + _00E_FS_BlueprintItemsStored.Show(EnderalFunctions.MoveItemsToCountByKeyword(PlayerREF, _00E_FS_BlueprintContainerActorREF, Blueprint, 1)) +endfunction + +Function TakeBlueprints() + if bInventoryMenu + ; The DisablePlayerControls method does not remember last inventory tab to return where we were + Input.TapKey(Input.GetMappedKey("Tween Menu")) + endif + Game.DisablePlayerControls(abMenu = true) + Game.EnablePlayerControls(abMenu = true) + Utility.Wait(0.05) + _00E_FS_BlueprintContainerActorREF.ShowGiftMenu(False, _00E_FS_BlueprintList, True, False) + if bInventoryMenu + Utility.wait(0.2) + Input.TapKey(Input.GetMappedKey("Quick Inventory")) + endif +EndFunction + +bool bInventoryMenu + +Actor Property PlayerRef Auto +Actor Property _00E_FS_BlueprintContainerActorREF Auto + +Message Property _00E_FS_Blueprint_Message_SE Auto +Message Property _00E_FS_BlueprintItemsStored Auto + +FormList Property _00E_FS_BlueprintList Auto + +Keyword Property Blueprint Auto + +Sound Property ITMBookClose Auto diff --git a/source/scripts/_00E_BlueprintControlAlias.psc b/source/scripts/_00E_BlueprintControlAlias.psc new file mode 100644 index 00000000..58881422 --- /dev/null +++ b/source/scripts/_00E_BlueprintControlAlias.psc @@ -0,0 +1,19 @@ +Scriptname _00E_BlueprintControlAlias extends ReferenceAlias Hidden + +auto state Waiting + Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) + if ! (akBaseItem as MiscObject) || ! akBaseItem.HasKeyword(Blueprint) + return + endif + GotoState("DoNothing") + _00E_BlueprintCollectionItemRef.Activate(GetReference()) + Clear() + EndEvent +endstate + +state DoNothing +endstate + +Keyword Property Blueprint Auto + +ObjectReference Property _00E_BlueprintCollectionItemRef Auto diff --git a/source/scripts/_00e_nq24_leveledlistcheck.psc b/source/scripts/_00e_nq24_leveledlistcheck.psc index dfd969d5..cc8de016 100644 --- a/source/scripts/_00e_nq24_leveledlistcheck.psc +++ b/source/scripts/_00e_nq24_leveledlistcheck.psc @@ -21,13 +21,14 @@ Event OnTriggerEnter (ObjectReference akActionRef) EndIf ;not NQ24 related but still needs to be handled the same way, did not want to create a new script - If _00E_FS_BlueprintContainerBookOwned.GetValueInt() == 0 - _00E_FS_LeveledListBlueprintContainer.AddForm(_00E_FS_BlueprintContainerBook, 1, 1) - VendorItemsBanker.AddForm(VendorItemFSBlueprintContainer) - ElseIf _00E_FS_BlueprintContainerBookOwned.GetValueInt() == 1 - _00E_FS_LeveledListBlueprintContainer.Revert() - VendorItemsBanker.RemoveAddedForm(VendorItemFSBlueprintContainer) - EndIf + ;2.1: Replaced with a misc item + ;If _00E_FS_BlueprintContainerBookOwned.GetValueInt() == 0 + ; _00E_FS_LeveledListBlueprintContainer.AddForm(_00E_FS_BlueprintContainerBook, 1, 1) + ; VendorItemsBanker.AddForm(VendorItemFSBlueprintContainer) + ;ElseIf _00E_FS_BlueprintContainerBookOwned.GetValueInt() == 1 + ; _00E_FS_LeveledListBlueprintContainer.Revert() + ; VendorItemsBanker.RemoveAddedForm(VendorItemFSBlueprintContainer) + ;EndIf ;just for FS_NQ07 If _00E_FS_NQ07_DoorOwned.GetValueInt() == 0 && FS_NQ07.GetCurrentStageID() >= 115 @@ -47,22 +48,22 @@ Quest Property FS_NQ07 Auto GlobalVariable Property _00E_NQ24_PlayerHouseMarketOwned Auto GlobalVariable Property _00E_NQ24_PlayerHouseNobleOwned Auto -GlobalVariable Property _00E_FS_BlueprintContainerBookOwned Auto +;GlobalVariable Property _00E_FS_BlueprintContainerBookOwned Auto GlobalVariable Property _00E_FS_NQ07_DoorOwned Auto FormList Property VendorItemsBanker Auto LeveledItem Property _00E_NQ24_LeveledListHouseMarket Auto LeveledItem Property _00E_NQ24_LeveledListHouseNoble Auto -LeveledItem Property _00E_FS_LeveledListBlueprintContainer Auto +;LeveledItem Property _00E_FS_LeveledListBlueprintContainer Auto LeveledItem Property _00E_FS_NQ07_LeveledListDoor Auto MiscObject Property _00E_Game_Playerhouse_ArkMarket_Document Auto MiscObject Property _00E_Game_Playerhouse_UpperCity_Document Auto -Book Property _00E_FS_BlueprintContainerBook Auto +;Book Property _00E_FS_BlueprintContainerBook Auto MiscObject Property _00E_FS_NQ07_MiscDoor Auto Keyword Property VendorItemPropertyArkMarket Auto Keyword Property VendorItemPropertyArkUpperCity Auto -Keyword Property VendorItemFSBlueprintContainer Auto +;Keyword Property VendorItemFSBlueprintContainer Auto Keyword Property _00E_FS_NQ07_VendorNoSale Auto \ No newline at end of file diff --git a/source/scripts/enderalfunctions.psc b/source/scripts/enderalfunctions.psc index f1ba4c5e..301a6863 100644 --- a/source/scripts/enderalfunctions.psc +++ b/source/scripts/enderalfunctions.psc @@ -27,6 +27,8 @@ Function EnableDialogueQuitting() native global bool function IsInRegion(Form region) native global +int function MoveItemsToCountByKeyword(ObjectReference sourceRef, ObjectReference targetRef, Keyword kword, int iCount = 1) native global + bool function IsDLLLoaded() global return SKSE.GetPluginVersion("EnderalSE") > 0 endfunction