Jump to content
Heavy Traffic ×

[LE] Script Help - Fusing Soul Gem Pieces


Nyrolian

Recommended Posts

Hello,

 

Baby modder here. I've been working on a script to fuse soul gem pieces together and I can't get this thing to compile for the life of me.

 

Something that I really don't understand is that when I change the lines in the function TakeAway from (PiecesToRemove -=) to (PiecesToRemove = PiecesToRemove - 1), what used to be only six or so errors confined ONLY to that function suddenly become a bazillion errors spread throughout the whole script. Don't these mean the same thing? Is my syntax wrong? The compiler treats PiecesToRemove-= and PiecesToRemove -= as the same thing.

 

My apologies if the post is too long or I'm breaking some kind of forum rules or something. I'm very new here and just want to figure out what I'm doing wrong. Thank you.

 

 

 

Scriptname CustomSoulGemRefuser

{This script detects how many soul gem pieces a Player has, and allows them to fuse a certain amount together to make a whole empty one of a certain size.}
FormList Property SoulGemPieceList Auto
;List of all accepted pieces, used to determine what menu pops up and how many options it includes
SoulGem Property EmptyPetty Auto
SoulGem Property EmptyLesser Auto
SoulGem Property EmptyCommon Auto
;Base items of unfilled soul gems, given to Player
MiscItem Property SoulGemPiece001 Auto
MiscItem Property SoulGemPiece002 Auto
MiscItem Property SoulGemPiece003 Auto
MiscItem Property SoulGemPiece004 Auto
MiscItem Property SoulGemPiece005 Auto
;Soul gem pieces, needed for function TakeAway (i had them there but was getting errors???)
Message Property OnlyPetty Auto
Message Property PettyLesser Auto
Message Property PettyLesserCommon Auto
;The three menus based on how many soul gem pieces the Player has. Options are limited to only what they can make
;EG if they have four pieces, the menu will not include the option to craft a common soul gem
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Event OnActivate(ObjectReference akActionRef)
Menu()
EndEvent
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function Menu(Int aiButton = 0)
;This function determines what menu pops up based on how many soul gems the Player has and introduces the PiecesToRemove variable
Int PlayerPieceCount = Game.GetPlayer().GetItemCount(SoulGemPieceList)
Int PiecesToRemove = 0
If PlayerPieceCount == 3
PiecesToRemove = 3
aiButton = OnlyPetty.show()
If aiButton == 0 ;Cancel option
ElseIf aiButton == 1 ;Make petty soul gem option
TakeAway()
Game.GetPlayer().AddItem(EmptyPetty)
EndIf
;This is the menu option if the player has only 3 pieces. They will only be able to craft a petty soul gem or exit the menu
ElseIf PlayerPieceCount == 4
aiButton = PettyLesser.show()
If aiButton == 0
ElseIf aiButton == 1
PiecesToRemove = 4
TakeAway()
Game.GetPlayer().AddItem(EmptyPetty)
ElseIf aiButton == 2
PiecesToRemove = 3
TakeAway()
Game.GetPlayer().AddItem(EmptyLesser)
;The menu option for 4 pieces. Options are to cancel, make a petty gem, or make a lesser gem
ElseIf PlayerPieceCount > 4
aiButton = PettyLesserCommon.show()
If aiButton == 0
ElseIf aiButton == 1
PiecesToRemove == 3
TakeAway()
Game.GetPlayer().AddItem(EmptyPetty)
ElseIf aiButton == 2
PiecesToRemove == 4
TakeAway()
Game.GetPlayer().AddItem(EmptyLesser)
ElseIf aiButton == 3
PiecesToRemove == 5
TakeAway()
Game.GetPlayer().AddItem(EmptyCommon)
;The menu option if the player has more than 4 gems. All soul gem crafting options are offered to them
Else
Debug.Notification("You don't have enough soul gem pieces to make anything")
EndIf
;If the Player has 2 or fewer pieces, this notification will show
EndIf
Endif
EndFunction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function TakeAway(Int PiecesToRemove)
;These properties point to base items of all 5 soul gem pieces individually, used for Function TakeAway
Int Piece01 = Game.GetPlayer().GetItemCount(SoulGemPiece001)
Int Piece02 = Game.GetPlayer().GetItemCount(SoulGemPiece002)
Int Piece03 = Game.GetPlayer().GetItemCount(SoulGemPiece003)
Int Piece04 = Game.GetPlayer().GetItemCount(SoulGemPiece004)
Int Piece05 = Game.GetPlayer().GetItemCount(SoulGemPiece005)
While PiecesToRemove > 0
While Piece01 > 0
Game.GetPlayer().RemoveItem(SoulGemPiece001)
PiecesToRemove = PiecesToRemove - 1
EndWhile
While Piece02 > 0
Game.GetPlayer().RemoveItem(SoulGemPiece002)
PiecesToRemove = PiecesToRemove - 1
EndWhile
While Piece03 > 0
Game.GetPlayer().RemoveItem(SoulGemPiece003)
PiecesToRemove = PiecesToRemove - 1
EndWhile
While Piece04 > 0
Game.GetPlayer().RemoveItem(SoulGemPiece004)
PiecesToRemove = PiecesToRemove - 1
EndWhile
While Piece05 > 0
Game.GetPlayer().RemoveItem(SoulGemPiece005)
PiecesToRemove = PiecesToRemove - 1
EndWhile
EndWhile
EndFunction
Link to comment
Share on other sites

I believe it is confused by the multiple operators.

 

Do one of the following:

PiecesToRemove -= 1
PiecesToRemove = (PiecesToRemove - 1)

You can speed up your script execution by replacing all those Game.GetPlayer calls with a variable referencing the player. It does not need to be a property, a local variable or even an event parameter variable will do.

 

I would also utilize the formlist that you already have containing the soul gem pieces instead of listing them separately as properties. And because there are a lot of similar things going on, I would create a custom function to handle the work load.

 

The following compiles and demonstrates what I've mentioned, but whether it works for your needs or not... only you can determine that

 

 

Scriptname CustomSoulGemRefuser Extends ObjectReference
{This script detects how many soul gem pieces a Player has, and allows them to fuse a certain amount together to make a whole empty one of a certain size.}
 
FormList Property SoulGemPieceList Auto
;List of all accepted pieces, used to determine what menu pops up and how many options it includes
 
SoulGem Property EmptyPetty Auto
SoulGem Property EmptyLesser Auto
SoulGem Property EmptyCommon Auto
;Base items of unfilled soul gems, given to Player
 
Message Property OnlyPetty Auto
Message Property PettyLesser Auto
Message Property PettyLesserCommon Auto
;The three menus based on how many soul gem pieces the Player has. Options are limited to only what they can make
;EG if they have four pieces, the menu will not include the option to craft a common soul gem
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
Event OnActivate(ObjectReference akActionRef)
  If akActionRef == Game.GetPlayer()
    Menu(akActionRef)
  EndIf
EndEvent
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
Function Menu(ObjectReference myReader)
  Int PlayerPieceCount = myReader.GetItemCount(SoulGemPieceList)
 
  If PlayerPieceCount == 3
    Int aiButton = OnlyPetty.show()
    If aiButton == 0
    ElseIf aiButton == 1
      HandleMenuOption(myReader,3,EmptyPetty)
    EndIf
  ElseIf PlayerPieceCount == 4 
    Int aiButton = PettyLesser.show()
    If aiButton == 0
    ElseIf aiButton == 1
      HandleMenuOption(myReader,4,EmptyLesser)
    ElseIf aiButton == 2
      HandleMenuOption(myReader,3,EmptyPetty)
    EndIf
  ElseIf PlayerPieceCount > 4
    Int aiButton = PettyLesserCommon.show()
    If aiButton == 0
    ElseIf aiButton == 1
      HandleMenuOption(myReader,3,EmptyPetty)
    ElseIf aiButton == 2
      HandleMenuOption(myReader,4,EmptyLesser)
    ElseIf aiButton == 3
      HandleMenuOption(myReader,5,EmptyCommon)
    Else
      Debug.Notification("You don't have enough soul gem pieces to make anything")
    EndIf
  Endif
EndFunction
 
Function HandleMenuOption(ObjectReference mySelector, Int PTR, Form ObjectToGive)
  ;take away the pieces
  Int index = 0
  While (index < SoulGemPieceList.GetSize()) && (PTR > 0)
    Form Entry = SoulGemPieceList.GetAt(index)
    If mySelector.GetItemCount(Entry) > 0
      mySelector.RemoveItem(Entry,1,true)
      PTR -= 1
    EndIf
    index += 1
  EndWhile
 
  ;give the empty gem
  mySelector.AddItem(ObjectToGive)
EndFunction

 

 

 

Link to comment
Share on other sites

First of all, thank you very much for taking the time to look at my code and troubleshoot with me. I'm still teaching myself Papyrus, and while I still don't understand all of it, looking at the code you provided and dissecting it helped me understand what I was doing wrong. The main problem was that I didn't fully understand how parameters worked with new functions and what to put in the parentheses and how they related to each other in the different functions. Now I think I've finally got it! Also it didn't help that I wrote MiscItem property instead of the correct MiscObject property. No idea where I got the idea that it was called MiscItem.

 

Just for posterity, this is the code I ended up going with. I tested it in-game and it works perfectly. Your suggestion for using the formlist to take away the soul gem pieces was fantastic. I didn't even realize that was an option before.

 

Again, thank you! You really helped me get a better understanding of how this stuff works.

 

 

 

Scriptname CustomSoulGemPieceCounter extends ObjectReference  
{Script detects how many soul gem pieces a player has, offers up a menu, and takes away a certain number of pieces and replaces them with a corresponding empty soul gem}
 
FormList Property SoulGemPieces Auto
Message Property OnlyPettyOption Auto
Message Property PettyLesser Auto
Message Property PettyLesserCommon Auto
Soulgem Property EmptyPetty Auto
Soulgem Property EmptyLesser Auto
Soulgem Property EmptyCommon Auto
 
Event OnActivate(ObjectReference akActionRef)
Int PlayerPieces = Game.GetPlayer().GetItemCount(SoulGemPieces)
If PlayerPieces > 2
Menu(PlayerPieces, akActionRef)
Else
Debug.Messagebox("You don't have enough soul gem pieces to make anything")
EndIf
EndEvent
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
Function Menu(int PlayerPieces, ObjectReference Player)
int aiButton = 0
 
If PlayerPieces == 3
aiButton = OnlyPettyOption.show()
If aiButton == 0
ElseIf aiButton == 1
Int PiecesToRemove = 3
TakeAway(PiecesToRemove, Player, EmptyPetty)
EndIf
 
ElseIf PlayerPieces == 4
aiButton = PettyLesser.show()
If aiButton == 0
ElseIf aiButton == 1
Int PiecesToRemove = 3
TakeAway(PiecesToRemove, Player, EmptyPetty)
ElseIf aiButton == 2
Int PiecesToRemove = 4
TakeAway(PiecesToRemove, Player, EmptyLesser)
EndIf
 
Else
aiButton = PettyLesserCommon.show()
If aiButton == 0
ElseIf aiButton == 1
Int PiecesToRemove = 3
TakeAway (PiecesToRemove, Player, EmptyPetty)
ElseIf aiButton == 2
Int PiecesToRemove = 4
TakeAway(PiecesToRemove, Player, EmptyLesser)
ElseIf aiButton == 3
Int PiecesToRemove = 5
TakeAway(PiecesToRemove, Player, EmptyCommon)
EndIf
EndIf
 
EndFunction
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
Function TakeAway(int PiecesToRemove, ObjectReference Player, Form ObjectToGive)
 
  Int index = 0
 
  While (index < SoulGemPieces.GetSize()) && (PiecesToRemove > 0)
     Form Entry = SoulGemPieces.GetAt(index)
    If Player.GetItemCount(Entry) > 0
               Player.RemoveItem(Entry,1,true)
              PiecesToRemove -= 1
     EndIf
     index += 1
   EndWhile
 
Player.AddItem(ObjectToGive)
 
EndFunction


 

 

Edited by Nyrolian
Link to comment
Share on other sites

You can reduce that loop further for greater efficiency too. Your current loop is going in the opposite direction I think. Storing the form count as it's not expected to change, you can instead loop the other way and not have the compiler constantly query for the form count with GetSize().

 

 

; Store the number of forms contained in the list
Int index = SoulPieces.GetSize()

While index > 0 && PiecesToRemove > 0
    Form Entry = SoulGemPieces.GetAt(index)
   
    if player.GetItemCount(Entry) > 0
        player.RemoveItem(Entry, 1, true)
        PiecesToRemove -= 1
    endif
   
    index -= 1
EndWhile
Link to comment
Share on other sites

There is a logic error in your while loop. It doesn't matter to make it in "bottom-up" or "top-down" method. Let me explain: You have for example 3 soulgem fragments of type 3 (SoulGemPiece003).
The player got the empty petty soulgem after confirming the message selection, but only one fragment has been removed from inventory by the loop, not three.

Nyrolian loop:

 

    Int index = 0
    While (index < SoulGemPieces.GetSize()) && (PiecesToRemove > 0)
        Form Entry = SoulGemPieces.GetAt(index)
        If Player.GetItemCount(Entry) > 0
            Player.RemoveItem(Entry,1,true)
            PiecesToRemove -= 1
        EndIf
        index += 1
    EndWhile

 


AnishaDawn loop:

 

    ; Store the number of forms contained in the list
    Int index = SoulPieces.GetSize()
    While index > 0 && PiecesToRemove > 0
        Form Entry = SoulGemPieces.GetAt(index)
        if player.GetItemCount(Entry) > 0
            player.RemoveItem(Entry, 1, true)
            PiecesToRemove -= 1
        endif
        index -= 1
    EndWhile

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

first approach CustomSoulGemRefuser

 

Scriptname CustomSoulGemRefuser extends ObjectReference
{This script detects how many soul gem pieces a Player has, and allows them to fuse a certain amount together to make a whole empty one of a certain size.}
; https://forums.nexusmods.com/index.php?/topic/9876698-script-help-fusing-soul-gem-pieces/

;The three menus based on how many soulgem pieces the Player has. Options are limited to only what they can make
;EG if they have four pieces, the menu will not include the option to craft a common soul gem

  Message PROPERTY OnlyPetty         auto
  Message PROPERTY PettyLesser       auto
  Message PROPERTY PettyLesserCommon auto

;Base items of unfilled soul gems, will be given to Player
  SoulGem PROPERTY EmptyPetty  auto
  SoulGem PROPERTY EmptyLesser auto
  SoulGem PROPERTY EmptyCommon auto

;List of all accepted pieces (point to base items of all 5 soul gem pieces individually), used to determine,
; what menu pops up and how many options it includes
  FormList PROPERTY SoulGemPieceList auto
 

; -- EVENT --
 
EVENT OnActivate(ObjectReference akActionRef)
    IF (akActionRef == Game.GetPlayer() as ObjectReference)
        Menu(akActionRef)
    ENDIF
ENDEVENT


; -- FUNCTIONs -- 3

;-----------------------------------------
FUNCTION Menu(ObjectReference akActionRef)
;-----------------------------------------
;This function determines what menu pops up based on how many soulgems the Player has.

    int n = akActionRef.GetItemCount(SoulGemPieceList)            ; n = PlayerPieceCount
    int i                                                         ; i = aiButton    
    
IF     (n == 3)                            ; 0=cancel, 1=petty; only be able to craft a petty soulgem
    i = OnlyPetty.show()

ELSEIF (n == 4)                            ; 0=cancel, 1=petty, 2=lesser; make a petty or a lesser soulgem
    i = PettyLesser.show()

ELSEIF (n > 4)                             ; 0,1,2, 3=common; All soulgem crafting options are offered
    i = PettyLesserCommon.show()

ELSE
    Debug.Notification("You do not have enough soulgem pieces.")
    RETURN    ; - STOP -
ENDIF
;---------------------
    IF (i > 0)
        TakeAway(i+2)        ; i+2 = introduces the PiecesToRemove variable
    ENDIF
ENDFUNCTION


;-----------------------------------------------
Int FUNCTION myF_REM(Actor player, Int n, Int i)  ; helper
;-----------------------------------------------
    form fm = SoulGemPieceList.GetAt(n)            ; Form Entry = SoulGemPieceList.GetAt(index)

IF (i > 0)
    n = player.GetItemCount(fm)
    WHILE (n > 0) && (i > 0)
        player.RemoveItem(fm)                    ; mySelector.RemoveItem(Entry,1,true)
        i = i - 1
        n = n - 1
    ENDWHILE
ENDIF

    RETURN i    ; give back the "piecesToRemove" counter to caller function
ENDFUNCTION


;-----------------------
FUNCTION TakeAway(Int i)
;-----------------------
    actor player = Game.GetPlayer()
    soulGem SG

    IF     (i == 3)
                    SG = EmptyPetty
    ELSEIF (i == 4)
                    SG = EmptyLesser
    ELSEIF (i == 5)
                    SG = EmptyCommon
    ENDIF

;--------------------------------
    WHILE (i > 0)
        i = myF_REM(player, 0, i)    ; SoulGemPiece001
        i = myF_REM(player, 1, i)    ; SoulGemPiece002
        i = myF_REM(player, 2, i)    ; SoulGemPiece003
        i = myF_REM(player, 3, i)    ; SoulGemPiece004
        i = myF_REM(player, 4, i)    ; SoulGemPiece005
    ENDWHILE
;--------------------------------

    IF ( SG )
        player.AddItem(SG as Form)
    ENDIF
ENDFUNCTION

 

 

 

second approach CustomSoulGemRefuser

 

Scriptname CustomSoulGemRefuser extends ObjectReference
{This script detects how many soul gem pieces a Player has, and allows them to fuse a certain amount together to make a whole empty one of a certain size.}
; https://forums.nexusmods.com/index.php?/topic/9876698-script-help-fusing-soul-gem-pieces/

;The three menus based on how many soulgem pieces the Player has. Options are limited to only what they can make
;EG if they have four pieces, the menu will not include the option to craft a common empty soulgem

  Message PROPERTY OnlyPetty         auto
  Message PROPERTY PettyLesser       auto
  Message PROPERTY PettyLesserCommon auto

;Base items of unfilled soul gems, will be given to Player
  SoulGem PROPERTY EmptyPetty  auto
  SoulGem PROPERTY EmptyLesser auto
  SoulGem PROPERTY EmptyCommon auto

;List of all accepted pieces (point to base items of all 5 soul gem pieces individually), used to determine,
  FormList PROPERTY SoulGemPieceList auto
 

; -- EVENT --
 
EVENT OnActivate(ObjectReference akActionRef)
    IF (akActionRef == Game.GetPlayer() as ObjectReference)
        Menu(akActionRef)                      ; we are sure (at this point) akActionRef is the player, that means player has activated this object/activator
    ENDIF
ENDEVENT


; -- FUNCTIONs -- 2

;---------------------------------------
FUNCTION Menu(ObjectReference playerRef)
;---------------------------------------
;This function determines what menu pops up based on how many soulgems the Player has.

    int n = playerRef.GetItemCount(SoulGemPieceList)            ; n = PlayerPieceCount, PlayerPieces

IF (n < 3)
    Debug.Notification("You do not have enough soulgem pieces.")
    RETURN    ; - STOP -
ENDIF
;===================== n is the amount of all soulgem pieces the player has in his inventory
    int i                                                        ; i = aiButton    
    
    IF     (n == 3)                               ; 0=cancel, 1=petty; only be able to craft a petty soulgem
        i = OnlyPetty.show()            ; 3

    ELSEIF (n == 4)                               ; 0=cancel, 1=petty, 2=lesser; make a petty or a lesser soulgem
        i = PettyLesser.show()          ; 3,4

    ELSE ;IF (n > 4)                              ; 0,1,2, 3=common; All soulgem crafting options are offered
        i = PettyLesserCommon.show()    ; 3,4,5
    ENDIF

    IF (i > 0)                          ; i+2 = introduces the PiecesToRemove variable
        i = i + 2
        playerRef.AddItem( TransferItems(playerRef, i) )
    ENDIF
ENDFUNCTION


;------------------------------------------------------------
Form FUNCTION TransferItems(ObjectReference playerRef, Int i)  ; Bottom-up method
;------------------------------------------------------------
    soulGem SG

    IF     (i == 3)
                    SG = EmptyPetty
    ELSEIF (i == 4)
                    SG = EmptyLesser
    ELSEIF (i == 5)
                    SG = EmptyCommon
    ENDIF

;--------------------------------
    int iMaxToRemove = i                         ; iMaxToRemove = PiecesToRemove

    i = 0
    WHILE (iMaxToRemove > 0) && (i < SoulGemPieces.GetSize())
        form fm = SoulGemPieces.GetAt(i)
            ; GetAt(0) is SoulGemPiece001
            ; ..
            ; GetAt(4) is SoulGemPiece005
        
        int n = playerRef.GetItemCount(fm)       ; get players count of soulgem pieces
        IF (n > iMaxToRemove)
            n = iMaxToRemove                     ; reduce to max
        ENDIF

        IF (n > 0)
            playerRef.RemoveItem(fm, n, TRUE)
            iMaxToRemove = iMaxToRemove - n      ; adjust remove counter
        ENDIF

        i = i + 1                                ; increase formlist counter
    ENDWHILE
;--------------------------------

    RETURN (SG as Form)
ENDFUNCTION


;--------------------------------------------------------------
Form FUNCTION TransferItems_2(ObjectReference playerRef, Int i)  ; Top-down method, like AnishaDawn suggested
;--------------------------------------------------------------
    soulGem SG

    IF     (i == 3)
                    SG = EmptyPetty
    ELSEIF (i == 4)
                    SG = EmptyLesser
    ELSEIF (i == 5)
                    SG = EmptyCommon
    ENDIF

;--------------------------------
    int iMaxToRemove = i                         ; iMaxToRemove = PiecesToRemove

    i = SoulGemPieces.GetSize()                  ; get formlist size, once here
    WHILE (i > 0)
        i = i - 1                                ; decrease counter to run loop for valid formlist entry

        form fm = SoulGemPieces.GetAt(i)
            ; GetAt(4) is SoulGemPiece005
            ; ..
            ; GetAt(0) is SoulGemPiece001
        
        int n = playerRef.GetItemCount(fm)       ; get players count of soulgem pieces
        IF (n > iMaxToRemove)
            n = iMaxToRemove                     ; reduce pieces counter to max
        ENDIF

        IF (n > 0)
            playerRef.RemoveItem(fm, n, TRUE)
            iMaxToRemove = iMaxToRemove - n      ; adjust remove counter
        ENDIF

        IF (iMaxToRemove == 0)
            i = 0                                ; break loop
        ENDIF
    ENDWHILE
;--------------------------------

    RETURN (SG as Form)
ENDFUNCTION

 

 

 

third approach CustomSoulGemRefuser

 

Scriptname CustomSoulGemRefuser extends ObjectReference
{This script detects how many soul gem pieces a Player has, and allows them to fuse a certain amount together to make a whole empty one of a certain size.}
; https://forums.nexusmods.com/index.php?/topic/9876698-script-help-fusing-soul-gem-pieces/

;The three menus based on how many soulgem pieces the Player has. Options are limited to only what they can make
;EG if they have four pieces, the menu will not include the option to craft a common soul gem

  Message PROPERTY OnlyPetty         auto
  Message PROPERTY PettyLesser       auto
  Message PROPERTY PettyLesserCommon auto

;Base items of unfilled soul gems, will be given to Player
  SoulGem PROPERTY EmptyPetty  auto
  SoulGem PROPERTY EmptyLesser auto
  SoulGem PROPERTY EmptyCommon auto

;List of all accepted pieces (point to base items of all 5 soul gem pieces individually), used to determine,
; what menu pops up and how many options it includes
  FormList PROPERTY SoulGemPieceList auto
 

; -- EVENT --
 
EVENT OnActivate(ObjectReference akActionRef)
    IF (akActionRef == Game.GetPlayer() as ObjectReference)
        Menu(akActionRef)
    ENDIF
ENDEVENT


; -- FUNCTIONs -- 2

;---------------------------------------
FUNCTION Menu(ObjectReference playerRef)
;---------------------------------------
;This function determines what menu pops up based on how many soulgems the Player has.

    int n = playerRef.GetItemCount(SoulGemPieceList)            ; n = PlayerPieceCount

IF (n < 3)
     Debug.Notification("You do not have enough soulgem pieces.")
    RETURN    ; - STOP -
ENDIF
;---------------------
    int i                                                        ; i = aiButton    
    
    IF     (n == 3)                     ; 0=cancel, 1=petty; only be able to craft a petty soulgem
        i = OnlyPetty.show()

    ELSEIF (n == 4)                     ; 0=cancel, 1=petty, 2=lesser; make a petty or a lesser soulgem
        i = PettyLesser.show()

    ELSE ;IF (n > 4)                    ; 0,1,2, 3=common; All soulgem crafting options are offered
        i = PettyLesserCommon.show()
    ENDIF

    IF (i > 0)
        TakeAway(playerRef, i+2)        ; i+2 = introduces the PiecesToRemove variable
    ENDIF
ENDFUNCTION


;--------------------------------------------------
FUNCTION TakeAway(ObjectReference playerRef, Int i)  ; random list entry at the begin (with a single loop counter and condition)
;--------------------------------------------------
    soulGem SG

    IF     (i == 3)
                    SG = EmptyPetty
    ELSEIF (i == 4)
                    SG = EmptyLesser
    ELSEIF (i == 5)
                    SG = EmptyCommon
    ENDIF

;--------------------------------
    int iMaxToRemove = i
    
    i = Utility.RandomInt(1, SoulGemPieceList.GetSize())    ; random number here
    WHILE (iMaxToRemove > 0)
        IF (i == 0)
            i = SoulGemPieceList.GetSize()
        ENDIF
        i = i - 1                                    ; update our formlist counter by -1, top-down cycle
    
        form fm = SoulGemPieceList.GetAt(i)          ; valid soulgem fragment from list (i = 0..4)

        IF (playerRef.GetItemCount(fm) > 0)          ; get amount of current soulgem fragment in players inventory
            playerRef.RemoveItem(fm, 1, TRUE)        ; reduce players inventory for this fragment by 1
            iMaxToRemove = iMaxToRemove - 1          ; decrease the item remove counter by 1
        ENDIF
    ENDWHILE
;--------------------------------

    IF ( SG )
        playerRef.AddItem(SG as Form)
    ENDIF
ENDFUNCTION

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

I had also noticed that error but didn't know how to approach it(I thought maybe RemoveItem(Entry, PiecesToRemove, true) would be it but..).

It also doesn't make much logical sense to keep calling a native function when it's not necessary to do so but if it works, it works I guess.

Edited by AnishaDawn
Link to comment
Share on other sites

Here's my take on it. Just modify the Takeaway function a bit.

Function TakeAway(int PiecesToRemove, ObjectReference Player, Form ObjectToGive)

    Int index = 0
    Int M = SoulGemPieces.GetSize()
    
    While (index < M) && (PiecesToRemove > 0)
        Form Entry = SoulGemPieces.GetAt(index)
        Int Count = Player.GetItemCount(Entry)
        If  Count > 0
            If Count > PiecesToRemove
                Count = PiecesToRemove
            Endif
            Player.RemoveItem(Entry,Count,true)
            PiecesToRemove -= Count
        EndIf
        index += 1
    EndWhile

    Player.AddItem(ObjectToGive)

EndFunction
Link to comment
Share on other sites

One more thing. If you're going to cycle top to bottom, you should subtract from the index first. This is because if let's say the list has 5 forms, getsize() will return 5, but the available entries are from 0 to 4. So the first time through the loop, Form Entry = SoulGemPieces.GetAt(index) (index = 5) would return none.

 

Function TakeAway(int PiecesToRemove, ObjectReference Player, Form ObjectToGive)

    Int index = SoulGemPieces.GetSize()
    
    While (index > 0) && (PiecesToRemove > 0)
        index -= 1
        Form Entry = SoulGemPieces.GetAt(index)
        Int Count = Player.GetItemCount(Entry)
        If  Count > 0
            If Count > PiecesToRemove
                Count = PiecesToRemove
            Endif
            Player.RemoveItem(Entry,Count,true)
            PiecesToRemove -= Count
        EndIf
       
    EndWhile

    Player.AddItem(ObjectToGive)

EndFunction
Link to comment
Share on other sites

My thought when I suggested the while loop was that it would take one of each until the amount was reached rather than taking all of one type. And it would if the player had each, but apparently it would fail if the player had enough of one of the types but none of the others. Sorry for any confusion.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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