Jump to content

[LE] How can I give the player a list of items with a random count every seven days


capngagi

Recommended Posts

Make a new formlist, put your stuff you want to give in it. Then make a new quest that's start game enabled, and put this script on it.

 

 

 

Scriptname MyMod_GivePlayerStuff extends Quest 

Formlist Property StuffToGive Auto
Actor Property PlayerRef Auto

Event OnInit() 
    GivePlayerItems()
    RegisterForSingleUpdateGameTime(168) ; updates in 168 hours, or 7 days.
EndEvent

Event OnUpdateGameTime()
    GivePlayerItems()
    RegisterForSingleUpdateGameTime(168)
EndEvent

Function GivePlayerItems()
    Int RandomAmount = Utility.RandomInt(0, 10) ; finds random number between 0 and 10
    PlayerRef.AddItem(StuffToGive, RandomAmount) 
EndFunction

The script will give the same amount of each item to the player. If you want different amounts for each item, change the function to this:

Function GivePlayerItems()
    Int M = StuffToGive.GetSize()
    While M > 0
        M -= 1
        PlayerRef.AddItem(StuffToGive.GetAt(M), Utility.RandomInt(0, 10))
    EndWhile
EndFunction

Change the script name to something more unique
Edited by dylbill
Link to comment
Share on other sites

Keep in mind that update events do not run when the game is paused and many menus pause the game including the sleep / wait menu. So it is possible that should the update have triggered while sleeping or waiting the event will run later than intended after the menu closes.

Link to comment
Share on other sites

Keep in mind that update events do not run when the game is paused and many menus pause the game including the sleep / wait menu. So it is possible that should the update have triggered while sleeping or waiting the event will run later than intended after the menu closes.

 

The way around this is to track the gametime and use that to adjust when the next event is registered for. So it fires for the first time, notes the current gametime, and registers for an update in seven days; when that update fires, it checks the current gametime, and then if there's been any delay, removes that much from the time period for the next registration.

 

I personally would avoid using a script randomization loop for amounts. There's a built in tool for this in Leveled Lists; use those instead. They offer significantly more control.

Link to comment
Share on other sites

You mean doing something like this?

 

 

 

Formlist Property TestStuffToGive Auto
Actor Property PlayerRef Auto
GlobalVariable Property GameDaysPassed Auto 

Float DaysPassed

Event OnInit() 
    GivePlayerItems()
    DaysPassed = GameDaysPassed.GetValue()
    RegisterForSingleUpdateGameTime(168) ; updates in 168 hours, or 7 days.
EndEvent

Event OnUpdateGameTime()
    GivePlayerItems()
    Float Extra = ((GameDaysPassed.GetValue() - DaysPassed - 7) * 24)
    Float NextUpdate = 168 - Extra ;subracts extra time from next update, if there is any. 
    DaysPassed = GameDaysPassed.GetValue() - Extra
    RegisterForSingleUpdateGameTime(NextUpdate)
EndEvent

Function GivePlayerItems()
    Int M = TestStuffToGive.GetSize()
    While M > 0
        M -= 1
        PlayerRef.AddItem(TestStuffToGive.GetAt(M), Utility.RandomInt(0, 10))
    EndWhile
EndFunction

I'm not really familiar with Leveled Lists as I haven't used them in my own mods.
Edited by dylbill
Link to comment
Share on other sites

 

Keep in mind that update events do not run when the game is paused and many menus pause the game including the sleep / wait menu. So it is possible that should the update have triggered while sleeping or waiting the event will run later than intended after the menu closes.

 

The way around this is to track the gametime and use that to adjust when the next event is registered for. So it fires for the first time, notes the current gametime, and registers for an update in seven days; when that update fires, it checks the current gametime, and then if there's been any delay, removes that much from the time period for the next registration.

 

I personally would avoid using a script randomization loop for amounts. There's a built in tool for this in Leveled Lists; use those instead. They offer significantly more control.

 

How do I randomize leveled lists?

Link to comment
Share on other sites

maybe somethings like this.. I use the code from dylbill as base. Like any other papyrus script, give it a unique name.

 

capnGivePlayerQuestScript

 

Scriptname capnGivePlayerQuestScript extends Quest
; https://forums.nexusmods.com/index.php?/topic/9189458-how-can-i-give-the-player-a-list-of-items-with-a-random-count-every-seven-days/

  Formlist PROPERTY myList auto        ; CK created formlist, filled with "stuff to give"
      ; you can put into this list other formlists, leveleditems or miscitems (whatever you want)
 
  Int dayspassed                    ; [default=0]


; -- EVENTs --
; https://www.creationkit.com/index.php?title=AddItem_-_ObjectReference

EVENT OnInit()
    RegisterForSingleUpdateGameTime(24.0)    ; init a check for every day
ENDEVENT


EVENT OnUpdateGameTime()
    Utility.Wait(1.0)

IF ( myList )                                ; make sure the mod is still active
    dayspassed = dayspassed + 1
    IF (dayspassed >= 7)
        dayspassed = 0                     ; ### edited, reset this counter
;;      Debug.Notification("You will get some items..")
        GivePlayerItems()
    ENDIF
    RegisterForSingleUpdateGameTime(24.0)    ; register again for next day
ENDIF
ENDEVENT


; -- FUNCTIONs -- 2

;-------------------------
FUNCTION GivePlayerItems()
;-------------------------
    actor player = Game.GetPlayer()            ; get it once here and store into function variable

    WHILE player.IsInCombat()
        Utility.Wait(2.5)                      ; do not add any item during combat
    ENDWHILE

int i = myList.GetSize()                       ; set maximum of entries
    WHILE (i)                ; (i > 0)
        i = i - 1
        form fm = myList.GetAt(i)
        IF (fm as FormList)
            myF_Give(fm, player, 1)            ; !!! to randomize the count of this formlist entries use 2 or more, instead of 1 !!!
        ELSEIF (fm as ObjectReference)
            player.AddItem(fm, 1, TRUE)        ; see comment in link from above
        ELSE
            player.AddItem(fm, Utility.RandomInt(1, 4), TRUE)    ; give amount of item(s) (from 1 up to 4)
        ENDIF
    ENDIF
ENDFUNCTION


;----------------------------------------------
FUNCTION myF_Give(Form fm, actor player, Int r)  ; helper (we assume only baseobjects inside like miscObject, Armor, Weapon, Ingredient, etc.)
;----------------------------------------------
IF (r <= 0)
    RETURN    ; - STOP -    nothings to give
ENDIF
;---------------------
IF (r == 1)
    player.AddItem(fm, 1, TRUE)                ; do not notify to screen
    RETURN    ; - STOP -    give one from every item in this formlist
ENDIF
;---------------------    
    formlist fml = fm as FormList
    int i = fml.GetSize()
    WHILE (i)
        i = i - 1
        player.AddItem(fml.GetAt(i), Utility.RandomInt(1, r), TRUE)
    ENDWHILE
ENDFUNCTION

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

 

 

Keep in mind that update events do not run when the game is paused and many menus pause the game including the sleep / wait menu. So it is possible that should the update have triggered while sleeping or waiting the event will run later than intended after the menu closes.

 

The way around this is to track the gametime and use that to adjust when the next event is registered for. So it fires for the first time, notes the current gametime, and registers for an update in seven days; when that update fires, it checks the current gametime, and then if there's been any delay, removes that much from the time period for the next registration.

 

I personally would avoid using a script randomization loop for amounts. There's a built in tool for this in Leveled Lists; use those instead. They offer significantly more control.

 

How do I randomize leveled lists?

 

 

Game does it for you if you have the leveled list set up for it (i.e you do not have Use All ticked). It will randomly select 1 thing amongst all the items in the list (all of which can have independently set quantities, and which can include duplicates) at or below the player's level (there are some corner cases where it uses a different actor's level instead but they don't apply here). You can nest leveled lists inside leveled lists, as well. Between these behaviours you can basically make a leveled list generate pretty much any kind of inventory generation behaviour you want. And giving someone a random selection of items is the entire reason they were made in the first place; it drives nearly every chest and NPC inventory in the game.

 

 

 

You mean doing something like this?

 

 

You can use a LeveledItem object in the AddItem command directly and it will do everything for you, so there's no need to walk through the list and independently randomize the quantities.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...