commit e331108089dbf3eb0f8821c9966c7e94180801a6 Author: Eddoursul Date: Sun Feb 13 03:15:13 2022 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f9dfed9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/meta.ini diff --git a/Pickup Helper.esp b/Pickup Helper.esp new file mode 100644 index 0000000..d1455c2 Binary files /dev/null and b/Pickup Helper.esp differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..def42bf --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +## Pickup Helper + +Picks up loose gold, arrows, ingredients, flora, leather, hides, and ingots of the same type. + +Inspired by dylbill's [Take All Loose Gold and Arrows](https://www.nexusmods.com/skyrimspecialedition/mods/22680), but approaches certain tasks differently. Made mainly for personal use, hence the lack of customization. + +- Pickup Helper is based on a perk with the Activate entrypoint instead of using [OnItemAdded](https://ck.uesp.net/wiki/OnItemAdded_-_ObjectReference). +- Picks up wider range of items, becoming a simple autoloot helper as well. +- Does not rely on pre-defined item lists and uses automatic detection more extensively. diff --git a/Scripts/ETAxPlayerAliasScript.pex b/Scripts/ETAxPlayerAliasScript.pex new file mode 100644 index 0000000..db1f1a0 Binary files /dev/null and b/Scripts/ETAxPlayerAliasScript.pex differ diff --git a/Scripts/PRKF_ETAxTakePerk_02000805.pex b/Scripts/PRKF_ETAxTakePerk_02000805.pex new file mode 100644 index 0000000..89ffa49 Binary files /dev/null and b/Scripts/PRKF_ETAxTakePerk_02000805.pex differ diff --git a/Source/Scripts/ETAxPlayerAliasScript.psc b/Source/Scripts/ETAxPlayerAliasScript.psc new file mode 100644 index 0000000..febde44 --- /dev/null +++ b/Source/Scripts/ETAxPlayerAliasScript.psc @@ -0,0 +1,194 @@ +Scriptname ETAxPlayerAliasScript extends ReferenceAlias + +int iFloraCount = 0 +int iArrowCount = 0 + +event OnInit() + PlayerRef.AddPerk(ETAxTakePerk) + RegisterForSingleUpdate(10.0) +endevent + +event OnPlayerLoadGame() + RegisterForSingleUpdate(10.0) +endevent + +event OnUpdate() + ScanPouches() + ScanArrows() +endevent + +function ScanArrows() + + Form[] aItems = PO3_SKSEfunctions.GetAllForms(42) ; ammo + int i = aItems.Length + + if iArrowCount == i + return + endif + + iArrowCount = i + + Projectile arrowProjectile + ETAxArrowList.Revert() + + while i > 0 + i -= 1 + if aItems[i].IsPlayable() + + ETAxArrowList.AddForm(aItems[i]) + + arrowProjectile = (aItems[i] as Ammo).GetProjectile() + + if arrowProjectile && ! ETAxArrowList.HasForm(arrowProjectile) + ETAxArrowList.AddForm(arrowProjectile) + endif + + endif + endwhile + +endfunction + +function ScanPouches() + + Form[] aItems = PO3_SKSEfunctions.GetAllForms(39) ; flora + int i = aItems.Length + + if iFloraCount == i + return + endif + + iFloraCount = i + + SoundDescriptor refSound + ETAxGoldList.Revert() + + While i > 0 + i -= 1 + refSound = (aItems[i] as Flora).GetHarvestSound() + if refSound && ETAxPouchSounds.Find(refSound) != -1 && ! ETAxGoldList.HasForm(aItems[i]) + ETAxGoldList.AddForm(aItems[i]) + endif + Endwhile + +endfunction + +function TakeByArray(ObjectReference[] aRefs, bool bCheckWeight = false) + + float fDelay = ETAxPickUpDelay.Value + int i = aRefs.Length + + While i > 0 + i -= 1 + if aRefs[i].IsEnabled() && aRefs[i].Is3DLoaded() + if fDelay > 0 + Utility.wait(fDelay) + endif + if ! bCheckWeight || aRefs[i].GetBaseObject().GetWeight() <= ETAxWeightLimit.Value + aRefs[i].Activate(PlayerRef) + endif + endif + Endwhile + +endfunction + +function PickFloraByType(Form rBase) + + int iType = rBase.GetType() + Form pickedIngredient + + if iType == 38 ; tree + pickedIngredient = (rBase as TreeObject).GetIngredient() + elseif iType == 39 ; flora + pickedIngredient = (rBase as Flora).GetIngredient() + else + return + endif + + ObjectReference[] aRefs = PO3_SKSEfunctions.FindAllReferencesOfFormType(PlayerRef, iType, ETAxPickUpRadius.Value * 1.5) + int i = aRefs.Length + float fDelay = ETAxPickUpDelay.Value + Form refIngredient + + while i > 0 + i -= 1 + + if aRefs[i].GetBaseObject() == rBase + + if ! aRefs[i].IsHarvested() && aRefs[i].IsEnabled() && aRefs[i].Is3DLoaded() + if fDelay > 0 + Utility.wait(fDelay) + endif + aRefs[i].Activate(PlayerRef) + endif + + else + + if iType == 38 ; tree + refIngredient = (aRefs[i].GetBaseObject() as TreeObject).GetIngredient() + else + refIngredient = (aRefs[i].GetBaseObject() as Flora).GetIngredient() + endif + + if refIngredient == pickedIngredient && ! aRefs[i].IsHarvested() && aRefs[i].IsEnabled() && aRefs[i].Is3DLoaded() + if fDelay > 0 + Utility.wait(fDelay) + endif + aRefs[i].Activate(PlayerRef) + endif + + endif + + endwhile + +endfunction + +function PickFloraByTypeIdAndIngredient(int iType, Form fIngredient) + + ObjectReference[] aRefs = PO3_SKSEfunctions.FindAllReferencesOfFormType(PlayerRef, iType, ETAxPickUpRadius.Value * 1.5) + int i = aRefs.Length + float fDelay = ETAxPickUpDelay.Value + Form refIngredient + + while i > 0 + i -= 1 + + if iType == 38 ; tree + refIngredient = (aRefs[i].GetBaseObject() as TreeObject).GetIngredient() + else + refIngredient = (aRefs[i].GetBaseObject() as Flora).GetIngredient() + endif + + if refIngredient == fIngredient && ! aRefs[i].IsHarvested() && aRefs[i].IsEnabled() && aRefs[i].Is3DLoaded() + if fDelay > 0 + Utility.wait(fDelay) + endif + aRefs[i].Activate(PlayerRef) + endif + + endwhile + +endfunction + +function TakeByFormOrList(Form formOrList) + TakeByArray(PO3_SKSEfunctions.FindAllReferencesOfType(PlayerRef, formOrList, ETAxPickUpRadius.Value)) +endfunction + +function TakeByKeyword(Form keywordOrList, bool bCheckWeight = false) + TakeByArray(PO3_SKSEfunctions.FindAllReferencesWithKeyword(PlayerRef, keywordOrList, ETAxPickUpRadius.Value, false), bCheckWeight) +endfunction + +function TakeByFormType(int iFormType) + TakeByArray(PO3_SKSEfunctions.FindAllReferencesOfFormType(PlayerRef, iFormType, ETAxPickUpRadius.Value)) +endfunction + +Actor Property PlayerRef Auto + +Perk Property ETAxTakePerk Auto + +GlobalVariable Property ETAxPickUpDelay Auto +GlobalVariable Property ETAxPickUpRadius Auto +GlobalVariable Property ETAxWeightLimit Auto + +FormList Property ETAxPouchSounds Auto +FormList Property ETAxGoldList Auto +FormList Property ETAxArrowList Auto diff --git a/Source/Scripts/PRKF_ETAxTakePerk_02000805.psc b/Source/Scripts/PRKF_ETAxTakePerk_02000805.psc new file mode 100644 index 0000000..2f2494c --- /dev/null +++ b/Source/Scripts/PRKF_ETAxTakePerk_02000805.psc @@ -0,0 +1,88 @@ +;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment +;NEXT FRAGMENT INDEX 36 +Scriptname PRKF_ETAxTakePerk_02000805 Extends Perk Hidden + +;BEGIN FRAGMENT Fragment_33 +Function Fragment_33(ObjectReference akTargetRef, Actor akActor) +;BEGIN CODE +PlayerScript.TakeByKeyword(VendorItemAnimalHide, true) +;END CODE +EndFunction +;END FRAGMENT + +;BEGIN FRAGMENT Fragment_15 +Function Fragment_15(ObjectReference akTargetRef, Actor akActor) +;BEGIN CODE +; Ingredients +; This fails on dropped items, looking for a proper way to detect them +Form rBase = akTargetRef.GetBaseObject() +if rBase + PlayerScript.TakeByFormOrList(rBase) + ;PlayerScript.PickFloraByTypeIdAndIngredient(38, rBase) ; tree + ;PlayerScript.PickFloraByTypeIdAndIngredient(39, rBase) ; flora +else + PlayerScript.TakeByFormType(30) +endif +;END CODE +EndFunction +;END FRAGMENT + +;BEGIN FRAGMENT Fragment_6 +Function Fragment_6(ObjectReference akTargetRef, Actor akActor) +;BEGIN CODE +; Arrows and projectiles +PlayerScript.TakeByFormOrList(ETAxArrowList) +;END CODE +EndFunction +;END FRAGMENT + +;BEGIN FRAGMENT Fragment_3 +Function Fragment_3(ObjectReference akTargetRef, Actor akActor) +;BEGIN CODE +PlayerScript.TakeByFormOrList(ETAxGoldList) +;END CODE +EndFunction +;END FRAGMENT + +;BEGIN FRAGMENT Fragment_12 +Function Fragment_12(ObjectReference akTargetRef, Actor akActor) +;BEGIN CODE +PlayerScript.TakeByKeyword(VendorItemOreIngot, true) +;END CODE +EndFunction +;END FRAGMENT + +;BEGIN FRAGMENT Fragment_18 +Function Fragment_18(ObjectReference akTargetRef, Actor akActor) +;BEGIN CODE +; Flora +if ! akTargetRef.IsActivationBlocked() + PlayerScript.PickFloraByType(akTargetRef.GetBaseObject()) +endif +;END CODE +EndFunction +;END FRAGMENT + +;BEGIN FRAGMENT Fragment_31 +Function Fragment_31(ObjectReference akTargetRef, Actor akActor) +;BEGIN CODE +PlayerScript.TakeByFormOrList(Lockpick) +;END CODE +EndFunction +;END FRAGMENT + +;END FRAGMENT CODE - Do not edit anything between this and the begin comment + +ETAxPlayerAliasScript Property PlayerScript Auto + +Actor Property PlayerRef Auto + +FormList Property ETAxGoldList Auto + +FormList Property ETAxArrowList Auto + +Keyword Property VendorItemOreIngot Auto + +MiscObject Property Lockpick Auto + +Keyword Property VendorItemAnimalHide Auto