HELLJUMPERS21 Posted April 18, 2021 Share Posted April 18, 2021 (edited) Hi there! I know a lot of scripting and modding for Skyrim is kind of old but I love the game and still playing. Well, late in the game so to speak, i have decided to make myself a player home. So far so good! I've done alot and loving the way it looks and feels but the scripting.......I am having trouble. So as simple as my request is can you please help? I've done a lot of auto sorting scripts already which was a chore but it works! I have an activator in front of some static items. Currently it is linked to a chest with a linkeddummyscript. What I want to do is Event OnActivate, remove all items in chest and give to player. I know what I want to do but I don't understand yet how to speak the language. Another one: In my auto sorters I am using:If akBaseItem.HasKeyword(VendorItemIngredient);MoveToRemoveItem(akBaseItem, aiItemCount, True, JL_Alchemy_Wardrobe)debug.notification("Item Auto Sorted") Thats great but what if I wanted to just speak about one item? Say an ingot? it would be MiscObject Property? How would I modify the script above to understand it? How would I incorporate a Form List into that? Thanks so much! Edited April 18, 2021 by Chris20201986 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted April 18, 2021 Share Posted April 18, 2021 Moving all items from a container to the player. There are multiple ways to do this and some are better than others. Some are fast but can cause stack dumps with too many items. Some are slow and can tie up processing for a few minutes but won't cause stack dumps. Here are a few simple examples. There are probably additional possibilities not listed. Moves all items at once, can cause stack dumps with lots of items Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() Self.RemoveAllItems(akActivator) EndIf EndEventMoves a form list as a whole, can cause stack dumps if there are a lot entries FormList Property myStorageList Auto Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() Int num = Self.GetItemCount(myStorageList) Self.RemoveItem(myStorageList,num,true,akActivator) EndIf EndEvent Moves items individually from a form list, will not cause a stack dump but does take longer. The longer the list, the longer it will take FormList Property myStorageList Auto Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() Int index = myStorageList.GetSize() While index >= 0 index -= 1 Form Entry = myStorageList.GetAt(index) Int num = Self.GetItemCount(Entry) If num > 0 Self.RemoveItem(Entry,num,true,akActivator) EndIf EndWhile EndIf EndEvent Moves all items individually from a container, does not cause stack dumps, takes longer and requires SKSE Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() Int index = Self.GetNumItems() - 1 ;SKSE function While index >= 0 Form Entry = Self.GetNthForm(index) ;SKSE function Int num = Self.GetItemCount(Entry) If num > 0 Self.RemoveItem(Entry,num,true,akActivator) EndIf index -= 1 EndWhile EndIf EndEvent If you want to move one specific item, it may be best to have its own property. But if you have a formlist with that object already listed, you could use the index to get that item. But both require that you know ahead of time that you want to transfer that one specific item. Adapting the earlier examples to show how to move a single object from a container. MiscObject Property IronIngot Auto Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() Int num = Self.GetItemCount(IronIngot) If num > 0 Self.RemoveItem(IronIngot,num,true,akActivator) EndIf EndIf EndEvent FormList Property myStorageList Auto Int Property myIndex Auto Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() Form Entry = myStorageList.GetAt(myIndex) Int num = Self.GetItemCount(Entry) If num > 0 Self.RemoveItem(Entry,num,true,akActivator) EndIf EndIf EndEvent It should be mentioned that stack dumps are when papyrus gets overloaded and dumps what is pending in order to continue. Often times it will appear harmless in game. However, there are times when a script not even running the event that caused the overload gets included in the dump. This is a problem when the script is supposed to advance a quest or update data used elsewhere. Link to comment Share on other sites More sharing options...
HELLJUMPERS21 Posted April 18, 2021 Author Share Posted April 18, 2021 Thanks so much for the response! I stumbled on your auto sorting script mod today and was all up in it. Thank you it is all helpful! Link to comment Share on other sites More sharing options...
ReDragon2013 Posted April 19, 2021 Share Posted April 19, 2021 (edited) Nothing special here, I only want to show IsharaMeradins very nice code samples inside a script with different functions. xyzSample_GiveItemsToPlayerScript Scriptname xyzSample_GiveItemsToPlayerScript extends ObjectReference ; https://forums.nexusmods.com/index.php?/topic/9910898-scripting-noob-in-need-of-help-from-the-pros/ FormList PROPERTY myItemsList auto ; vanilla existing or mod created formlist MiscObject PROPERTY IronIngot auto ; use auto-fill here Int PROPERTY myIndex = 0 auto ; [default=0] ; Chris20201986 wrote: "What I want to do is .. remove all items in chest and give to player" ; -- EVENTs -- EVENT OnInit() Debug.Trace(" OnInit() - has been called.. " +self) ; for debugging only ENDEVENT EVENT OnActivate(ObjectReference akActionRef) IF (akActionRef == Game.GetPlayer() as ObjectReference) ELSE RETURN ; - STOP - not player activated ENDIF ;--------------------- gotoState("Busy") ; do not allow to trigger OnActivate() event for a while myF_Action(akActionRef) gotoState("") ; allow it again ENDEVENT ;=========================== state Busy ; empty event here to avoid multiple action in a row ;========= EVENT OnActivate(ObjectReference akActionRef) ENDEVENT ;======= endState ; -- FUNCTIONs -- ;----------------------------------------- FUNCTION myF_Action(ObjectReference akRef) ; main function ;----------------------------------------- ; select only this function that fit your purpose myF_All(akRef) ; move all to player ;; myF_SKSE(akRef) ; move all step by step to player ;; myF_REM(IronIngot, akRef) ; move a specific item depends on filled property ;; myF_REM(myItemsList.GetAt(myIndex), akRef) ; move a specific item from formlist depends on property preset ;; myF_MoveItem_HasForm(akRef, IronIngot) ; move a specific item, if item property was found in list ;; myF_MoveItem_InList(akRef, IronIngot) ; move a specific item, if item property was found in list ;; recursion = 0 ; to avoid left over from older function call ;; myF_MoveItem_IfNestedInLists(akRef, myItemsList, IronIngot) ; .. try to find a property inside any formlist of formlists ;; myF_FormList(akRef) ; move all items depends on formlist entries ;; myF_FormList_A(akRef) ;; myF_FormList_B(akRef) ENDFUNCTION ;-------------------------------------- FUNCTION myF_All(ObjectReference akRef) ; move every item (at once) "from chest/container to actors inventory" ;-------------------------------------- 1 ; can cause stack dumps with lots of items self.RemoveAllItems(akRef) ENDFUNCTION ;------------------------------------------------------------ FUNCTION myF_MoveItem_HasForm(ObjectReference akRef, Form fm) ;------------------------------------------------------------ 4a ; https://www.creationkit.com/index.php?title=HasForm_-_FormList IF myItemsList.HasForm(fm) myF_REM(fm, akRef) ENDIF ENDFUNCTION ;------------------------------------------------------------ FUNCTION myF_MoveItem_InList(ObjectReference akRef, Form fm) ;------------------------------------------------------------ 4b ; https://www.creationkit.com/index.php?title=Find_-_FormList ; Keep in mind: "A formlist inside a formlist will not be checked for items." int i = myItemsList.Find(fm) ; it will not release the lock on self IF (i > -1) myF_REM(myItemsList.GetAt(i), akRef) ENDIF ENDFUNCTION Int recursion ; [default=0] counter to handle recursive function calls in a loop ;------------------------------------------------------------------------------------- FUNCTION myF_MoveItem_IfNestedInLists(ObjectReference akRef, FormList akList, Form fm) ;------------------------------------------------------------------------------------- 4c IF akList.HasForm(fm) myF_REM(fm, akRef) recursion = 1 RETURN ; - STOP - item was moved in this recursion, nothing more to do ENDIF ;--------------------- int i = akList.GetSize() ; get size of valid list WHILE (i) i = i - 1 formlist T = akList.GetAt(i) as FormList IF ( T ) ; found formlist inside our current formlist go inside this list recursion -= 1 ; -1, decrease function calling counter myF_MoveItem_NestedInLists(akRef, T, fm) IF (recursion == 1) RETURN ; - STOP - break this loop immediately ENDIF ; ---------------------- recursion += 1 ; +1, increase function calling counter ENDIF ENDWHILE ENDFUNCTION ;------------------------------------------------- FUNCTION myF_REM(Form item, ObjectReference akRef) ; helper with outsourced common function code ;------------------------------------------------- int n = self.GetItemCount(item) IF ( n ) ; (n > 0) ; we assume "n" will be only positive! self.RemoveItem(item, n, TRUE, akRef) ENDIF ENDFUNCTION ;--------------------------------------- FUNCTION myF_SKSE(ObjectReference akRef) ; move all items individually "from.." ;--------------------------------------- 2 ; does not cause stack dumps, but does take more runtime depends items inside. ; SKSE required!! IF (SKSE.GetVersion() == 0) Debug.Trace(self+" *** SKSE not found! ***") RETURN ; - STOP - SKSE not found! ENDIF ;--------------------- ; https://www.creationkit.com/index.php?title=GetNumItems_-_ObjectReference ; "i" has number of item types in the container regardless of the amount of any particular item. int i = self.GetNumItems() ; SKSE WHILE (i > 0) i = i - 1 myF_REM(self.GetNthForm(i), akRef) ; SKSE ENDWHILE ENDFUNCTION ;------------------------------------------- FUNCTION myF_Formlist(ObjectReference akRef) ; move all items defined by formlist "from.." ;------------------------------------------- 3 ; can cause stack dumps, if there are a lot entries int n = self.GetItemCount(myItemsList) self.RemoveItem(myItemsList, n, TRUE, akRef) ENDFUNCTION ;--------------------------------------------- FUNCTION myF_Fromlist_A(ObjectReference akRef) ; top-down approach by moving formlist items individually "from.." ;--------------------------------------------- 3a ; will not cause a stack dump, but does take more runtime depends on formlist size. ; The longer the list, the longer it will take! int i = myItemsList.GetSize() WHILE (i) ; (i > 0), we are sure index counter cannot be negative here! i = i - 1 ; decrease by 1 myF_REM(myItemsList.GetAt(i), akRef) ; start with last formlist entry and end by "myItemsList.GetAt(0)" ENDWHILE ENDFUNCTION ;--------------------------------------------- FUNCTION myF_Fromlist_B(ObjectReference akRef) ; bottom-up approach by moving formlist items individually "from.." ;--------------------------------------------- 3b ; will not cause a stack dump, but does take more runtime depends on formlist size. ; The longer the list, the longer it will take! int iMax = myItemsList.GetSize() int i = 0 WHILE (i < iMax) myF_REM(myItemsList.GetAt(i), akRef) ; start with first formlist entry and end by "myItemsList.GetAt(iMax - 1)" i = i + 1 ; increase by 1 ENDWHILE ENDFUNCTION Edited April 19, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
HELLJUMPERS21 Posted April 19, 2021 Author Share Posted April 19, 2021 OK. I am about to give up on this lol. So I used a "button activator" on my static items. I have a wardrobe underneath the shelf of said static items. I put this script on the activator: Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() Self.RemoveAllItems(akActivator) EndIfEndEvent And then linked the activator through the linked reference tab to the wardrobe. It doesnt work. The idea is, when you look at the shelf with static items, you can take all ingredients, or you can look down and access the ingredients through the wardrobe to pick and choose what you want. Was I supposed to add something to the script? Thank you for putting up with my ignorance. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted April 19, 2021 Share Posted April 19, 2021 Always helps to know how a situation is setup so that code can be done appropriately. You have a button that when pressed you want it to move stuff from the player to a container. The script code will have to be modified slightly. Adapting what you last posted: ObjectReference Property myContainer Auto ;assign this the pre-placed container Event OnActivate(objectReference akActivator) If akActivator == Game.GetPlayer() myContainer.RemoveAllItems(akActivator) EndIf EndEvent Link to comment Share on other sites More sharing options...
HELLJUMPERS21 Posted April 20, 2021 Author Share Posted April 20, 2021 Ok that seems easy enough. So: ObjectReference Property JL_Ingredients_Wardrobe AutoEvent OnActivate(objectReference akActivator)If akActivator == Game.GetPlayer()JL_Ingredients_Wardrobe.RemoveAllItems(akActivator)EndIfEndEvent Or do you mean to assign it via the attached references tab? I am learning albeit slowly lol Link to comment Share on other sites More sharing options...
IsharaMeradin Posted April 20, 2021 Share Posted April 20, 2021 That would be the code for the script that will be assigned to the button activator. Link to comment Share on other sites More sharing options...
HELLJUMPERS21 Posted April 21, 2021 Author Share Posted April 21, 2021 Ok I just reread your reply and I cant believe I missed it: You have a button that when pressed you want it to move stuff from the player to a container. That isn't what I am going for and that's my fault! I have a noble chest of drawers, with a noble chest shelf on top of that. The shelf has static items (ingredients) in a collision box. The chest of drawers has ingredients that get auto sorted in(already wrote the scripts for that). When the player walks up to the shelf of static items, there will be an activator or trigger for them to click. Upon activating trigger, all the ingredients from the chest of drawers will be removed and deposited into the player container (players inventory). If the player would rather grab a specific ingredient, they can just access them through the chest of drawers below the "Take all trigger" I am trying to make. Link to comment Share on other sites More sharing options...
IsharaMeradin Posted April 21, 2021 Share Posted April 21, 2021 Okay, the script goes on the activator wrapping the static ingredients. There is no difference other than visuals between a button activator and a static wrapped by an activator. Link to comment Share on other sites More sharing options...
Recommended Posts