Jump to content

Scripting Noob in Need of Help from The Pros


Recommended Posts

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);MoveTo
RemoveItem(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 by Chris20201986
Link to comment
Share on other sites

  • Replies 44
  • Created
  • Last Reply

Top Posters In This Topic

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
EndEvent

Moves 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

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 by ReDragon2013
Link to comment
Share on other sites

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)
EndIf
EndEvent

 

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

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

Ok that seems easy enough. So:

 

ObjectReference Property JL_Ingredients_Wardrobe Auto

Event OnActivate(objectReference akActivator)
If akActivator == Game.GetPlayer()
JL_Ingredients_Wardrobe.RemoveAllItems(akActivator)
EndIf
EndEvent

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

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

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...