Jump to content

How to use GetInveRefsForItem


Recommended Posts

Thanks! You confirmed that this is something broken in my game or maybe a corrupted save. I am really burned out on this right now.

 

A few days ago I tested what would happen if I put all gems in a container and then saved and restarted the game. It fixed the problem for a while.

 

The ONLY time I get the wrong soul size is for creatures that are PC Offset but have a set soul size, like the ogres in Pale Pass: level 24, soul size set to Common. I haven't figured out that one because of the bigger one.

Edited by GamerRick
Link to comment
Share on other sites

Ogres in Pale Pass comes from leveled list, but their base object doesn't use PCLevelOffset (so they have static level). And yes, they're all edited to have common souls and as I tested that the soul gem will be filled with common soul after they die.

Link to comment
Share on other sites

Ogres in Pale Pass comes from leveled list, but their base object doesn't use PCLevelOffset (so they have static level). And yes, they're all edited to have common souls and as I tested that the soul gem will be filled with common soul after they die.

Must be OOO that changes them. It does that to a lot of actors throughout the game.

 

I gave up on the GetInvRefs because it doesn't work better than foreach and it doesn't handle Azura's star.

 

I also have another related script that may or may not have anything to do with the count problem.

 

Here are my scripts:

scn RFFnOnSoulTrap
;= INPUTS
ref rTarget
long lEffect
;===
long lSTRP
ref rEffectCode
ref rItem
ref rItemBase
short iSoulSize
short iGemCount
;short iObjType
short iCurrSoulLevel
short iPetty
short iLesser
short iCommon
short iGreater
short iGrand
short iBlack
short bAzuraStar
begin Function { rTarget, lEffect }
if rTarget.IsActor
  PrintC"RFFnOnSoulTrap called on %n" rTarget
endif
let lSTRP := MagicEffectCodeFromChars "STRP"
if lSTRP != lEffect
  let rEffectCode := MagicEffectFromCode lEffect
  PrintC "RFFnOnSoulTrap called with spell %n (%.0f)", rEffectCode, lEffect
  return
endif

if rTarget.GetIsReference player
  return
endif
if rTarget.IsActor == 0
  Message "Target is not an Actor" 4
else
  ;set RFLightSpellQuest.rTarget to rTarget
  ;set RFLightSpellQuest.bShowSoulGemCount to 1
endif
;return ;==========================

if rTarget.IsActor
  if rTarget.IsCreature == 0
   set iSoulSize to 6
  elseif rTarget.GetLevel >= 18
   set iSoulSize to 5
  elseif rTarget.GetLevel >= 13
   set iSoulSize to 4
  elseif rTarget.GetLevel >= 7
   set iSoulSize to 3
  elseif rTarget.GetLevel >= 2
   set iSoulSize to 2
  else
   set iSoulSize to 1
  endif
  set iPetty to 0
  set iLesser to 0
  set iCommon to 0
  set iGreater to 0
  set iGrand to 0
  set iBlack to 0
  set bAzuraStar to 0
  set rItem to 0
  if RFGEMCOUNT == 1
   foreach rItem <- Player
    if rItem.IsSoulGem
     let iCurrSoulLevel := rItem.GetCurrentSoulLevel
     let iGemCount := rItem.GetRefCount
     let rItemBase := rItem.GetBaseObject
     ;PrintC "RFFnOnSoulTrap ------ Stack Count for %n is %g, Current Soul Level = %g", rItemBase, iGemCount, iCurrSoulLevel
     if iCurrSoulLevel == 0 && iGemCount > 0  ; Soulgem & empty
     
      if iSoulSize == 1
       if rItemBase == SoulGemEmpty1Petty  ; rItem.GetSoulGemCapacity == 1
        PrintC "RFFnOnSoulTrap ------ Stack Count for %n is %g, Current Soul Level = %g", rItemBase, iGemCount, iCurrSoulLevel
        set iPetty to iPetty + iGemCount
       endif
      elseif iSoulSize == 2
       if rItemBase == SoulGemEmpty2Lesser  ;rItem.GetSoulGemCapacity == 2
        PrintC "RFFnOnSoulTrap ------ Stack Count for %n is %g, Current Soul Level = %g", rItemBase, iGemCount, iCurrSoulLevel
        set iLesser to iLesser + iGemCount
       endif
      elseif iSoulSize == 3
       if rItemBase == SoulGemEmpty3Common  ;rItem.GetSoulGemCapacity == 3
        PrintC "RFFnOnSoulTrap ------ Stack Count for %n is %g, Current Soul Level = %g", rItemBase, iGemCount, iCurrSoulLevel
        set iCommon to iCommon + iGemCount
       endif
      elseif iSoulSize == 4
       if rItemBase == SoulGemEmpty4Greater  ;rItem.GetSoulGemCapacity == 4
        PrintC "RFFnOnSoulTrap ------ Stack Count for %n is %g, Current Soul Level = %g", rItemBase, iGemCount, iCurrSoulLevel
        set iGreater to iGreater + iGemCount
       endif
      elseif iSoulSize == 5
       if rItemBase == AzurasStar
        set bAzuraStar to 1    
       elseif rItemBase == SoulGemEmpty5Grand
        PrintC "RFFnOnSoulTrap ------ Stack Count for %n is %g, Current Soul Level = %g", rItemBase, iGemCount, iCurrSoulLevel
        set iGrand to iGrand + iGemCount
       endif
      elseif iSoulSize == 6
       if rItemBase == BlackSoulGem
        PrintC "RFFnOnSoulTrap ------ Stack Count for %n is %g, Current Soul Level = %g", rItemBase, iGemCount, iCurrSoulLevel
        set iBlack to iBlack + iGemCount
       endif
      endif
     endif
    endif
   loop ;
   set rItem to 0
  endif
  if iSoulSize == 1
   Message "Target soul level is PETTY (%.0f)" iPetty, 4
   ;Message "Target soul level is PETTY (%.0f)" iPetty, 4
   PrintC "Target soul level is PETTY. Player has %g empty Petty soulgems" iPetty  
  elseif iSoulSize == 2
   Message "Target soul level is LESSER (%.0f)" iLesser, 4
   ;Message "Target soul level is LESSER (%.0f)" iLesser, 4
   PrintC "Target soul level is Lesser. Player has %g empty Lesser soulgems" iLesser
  elseif iSoulSize == 3
   Message "Target soul level is COMMON (%.0f)" iCommon, 4
   ;Message "Target soul level is COMMON (%.0f)" iCommon, 4
   PrintC "Target soul level is Common. Player has %g empty Common soulgems" iCommon
  elseif iSoulSize == 4
   Message "Target soul level is GREATER (%.0f)" iGreater, 4
   ;Message "Target soul level is GREATER (%.0f)" iGreater, 4
   PrintC "Target soul level is Greater. Player has %g empty Greater soulgems" iGreater
  elseif iSoulSize == 5
   if player.GetItemCount AzurasStar > 0
    if bAzuraStar == 0
     Message "Target soul level is GRAND (%.0f) (Azura's Star is FULL)" iGrand, 4
     ;Message "Target soul level is GRAND (%.0f) (Azura's Star is FULL)" iGrand, 4
     PrintC "Target soul level is Grand. Player has %g empty Grand soulgems.  Azura's Star is FULL" iGrand
    else
     Message "Target soul level is GRAND (%.0f) (AzurasStar is EMPTY)" iGrand, 4
     ;Message "Target soul level is GRAND (%.0f) (AzurasStar is EMPTY)" iGrand, 4
     PrintC "Target soul level is Grand. Player has %g empty Grand soulgems.  Azura's Star is EMPTY" iGrand
    endif
   else
    Message "Target soul level is GRAND (%.0f)" iGrand, 4
    ;Message "Target soul level is GRAND (%.0f)" iGrand, 4
    PrintC "Target soul level is Grand. Player has %g empty Grand soulgems.  Player does not have Azura's Star." iGrand
   endif
  else
   Message "Target soul level is BLACK (%.0f)" iBlack, 4
   ;Message "Target soul level is BLACK (%.0f)" iBlack, 4
   PrintC "Target soul level is Black. Player has %g empty Black soulgems." iBlack
  endif
else
  ;Message "Target is not an Actor" 4 
  Message "Target is not an Actor" 4
endif
end

This one converts user filled soulgems to their filled versions. You can also see my first failed attempt to use pluggy to write stuff to file:

elseif iButton == 5      ; Soulgem Boogie
  
   set bShowMenu1 to 0
   ;RFSoulGemSwapContainerRef.MoveTo player 0,0,-20
   set iCount to 0
   ;set strFilename to CreateString -1, "Ricks\RicksSigilStoneBoogieout.txt",1,1
   ;StringToTxtFile strFilename, strFilename, 1
   ;PrintC "Created String: %z" strFilename
   set rItem to 0
   foreach rItem <- PlayerRef
    ;set rItem to rItemIter
    set rItemBase to rItem.GetBaseObject
   
    if rItem.IsSoulGem
     let iNumItems := rItem.GetRefCount
     let iSoulGemSoulSize := rItem.GetCurrentSoulLevel
     ; StringToTxtFile FilenameStringID StringID:long LineEnd:short
    
     ;let strHexID := GetFormIDString rItemBase
     ; FmtString strPluggyString, 0, "==== PROCESSING %g)  %n (%z) with soul level %g.", iNumItems, rItemBase, strHexID, iSoulGemSoulSize
     ;let strOutputText := sv_Construct "==== PROCESSING %g)  %n (%z) with soul level %g." iNumItems, rItemBase, strHexID, iSoulGemSoulSize
     ;set strPluggyString to -1, strOutputText, 1, 1
     ;PrintC "Created String: %z" strPluggyString
     ;StringToTxtFile strFilename, strPluggyString, 1
     ;DestroyString strPluggyString
     PrintC"==== PROCESSING %g)  %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
     ;sv_Destruct strHexID, strOutputText
    
     if iNumItems > 0 && iSoulGemSoulSize > 0
      PrintC"Exchanging %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
      ;let strOutputText := sv_Construct "Exchanging %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
      ;set strPluggyString to -1, strOutputText, 1, 1
      ;StringToTxtFile strFilename strPluggyString 1
      ;DestroyString strPluggyString
      ;sv_Destruct strOutputText
      if rItemBase == SoulGemEmpty1Petty
       RFSoulGemSwapContainerRef.AddItem SoulGem1Petty1PettySoul iNumItems
       rItem.RemoveMEIR
       PrintC"Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;let strOutputText := sv_Construct "Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;set strPluggyString to -1, strOutputText, 1, 1
       ;StringToTxtFile strFilename strPluggyString 1
       ;DestroyString strPluggyString
       ;sv_Destruct strOutputText
      elseif rItemBase == SoulGemEmpty2Lesser
       if iNumItems > PlayerRef.GetItemCount SoulGemEmpty2Lesser
        PrintC "RFHotkeys SoulGem Boogie - number of ref items for SoulGemEmpty2Lesser is greater than number of base items!"
       endif
       if iSoulGemSoulSize == 1
        RFSoulGemSwapContainerRef.AddItem SoulGem2Lesser1PettySoul iNumItems
       else
        RFSoulGemSwapContainerRef.AddItem SoulGem2Lesser2LesserSoul iNumItems
       endif
       rItem.RemoveMEIR
       PrintC"Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;let strOutputText := sv_Construct "Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;set strPluggyString to -1, strOutputText, 1, 1
       ;StringToTxtFile strFilename strPluggyString 1
       ;DestroyString strPluggyString
       ;sv_Destruct strOutputText
      elseif rItemBase == SoulGemEmpty3Common
       if iNumItems > PlayerRef.GetItemCount SoulGemEmpty3Common
        PrintC "RFHotkeys SoulGem Boogie - number of ref items for SoulGemEmpty3Common is greater than number of base items!"
       endif
       if iSoulGemSoulSize == 1
        RFSoulGemSwapContainerRef.AddItem SoulGem3Common1PettySoul iNumItems
       elseif iSoulGemSoulSize == 2
        RFSoulGemSwapContainerRef.AddItem SoulGem3Common2LesserSoul iNumItems
       else
        PrintC"   Adding common/commons to the temp swap container."
        RFSoulGemSwapContainerRef.AddItem SoulGem3Common3CommonSoul iNumItems
       endif
       rItem.RemoveMEIR
       PrintC"Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;let strOutputText := sv_Construct "Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;set strPluggyString to -1, strOutputText, 1, 1
       ;StringToTxtFile strFilename strPluggyString 1
       ;DestroyString strPluggyString
       ;sv_Destruct strOutputText
      elseif rItemBase == SoulGemEmpty4Greater
       if iNumItems > PlayerRef.GetItemCount SoulGemEmpty4Greater
        PrintC "RFHotkeys SoulGem Boogie - number of ref items for SoulGemEmpty4Greater is greater than number of base items!"
       endif
       if iSoulGemSoulSize == 1
        RFSoulGemSwapContainerRef.AddItem SoulGem4Greater1PettySoul iNumItems
       elseif iSoulGemSoulSize == 2
        RFSoulGemSwapContainerRef.AddItem SoulGem4Greater2LesserSoul iNumItems
       elseif iSoulGemSoulSize == 3
        RFSoulGemSwapContainerRef.AddItem SoulGem4Greater3CommonSoul iNumItems
       else
        RFSoulGemSwapContainerRef.AddItem SoulGem4Greater4GreaterSoul iNumItems
       endif
       rItem.RemoveMEIR
       PrintC"Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;let strOutputText := sv_Construct "Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;set strPluggyString to -1, strOutputText, 1, 1
       ;StringToTxtFile strFilename strPluggyString 1
       ;DestroyString strPluggyString
       ;sv_Destruct strOutputText
      elseif rItemBase == SoulGemEmpty5Grand
       if iNumItems > PlayerRef.GetItemCount SoulGemEmpty5Grand
        PrintC "RFHotkeys SoulGem Boogie - number of ref items for SoulGemEmpty5Grand is greater than number of base items!"
       endif
       if iSoulGemSoulSize == 1
        RFSoulGemSwapContainerRef.AddItem SoulGem5Grand1PettySoul iNumItems
       elseif iSoulGemSoulSize == 2
        RFSoulGemSwapContainerRef.AddItem SoulGem5Grand2LesserSoul iNumItems
       elseif iSoulGemSoulSize == 3
        RFSoulGemSwapContainerRef.AddItem SoulGem5Grand3CommonSoul iNumItems
       elseif iSoulGemSoulSize == 4
        RFSoulGemSwapContainerRef.AddItem SoulGem5Grand4GreaterSoul iNumItems
       else
        RFSoulGemSwapContainerRef.AddItem SoulGem5Grand5GrandSoul iNumItems
       endif
       rItem.RemoveMEIR
       PrintC"Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;let strOutputText := sv_Construct "Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       ;set strPluggyString to -1, strOutputText, 1, 1
       ;StringToTxtFile strFilename strPluggyString 1
       ;DestroyString strPluggyString
       ;sv_Destruct strOutputText
      elseif rItemBase == BlackSoulGem
       if iNumItems > PlayerRef.GetItemCount BlackSoulGem
        PrintC "RFHotkeys SoulGem Boogie - number of ref items for BlackSoulGem is greater than number of base items!"
       endif
       if iSoulGemSoulSize == 5
        RFSoulGemSwapContainerRef.AddItem BlackSoulGemFilled iNumItems
        rItem.RemoveMEIR
        PrintC"Exchanged %g) %n with soul level %g." iNumItems, rItemBase, iSoulGemSoulSize
       endif
      endif
     endif
    endif
   loop
   set rItem to 0
   ;set rItem to 0
   ;PrintC"=============   Dump temp swap container  =========="
   ;foreach rItem <- RFSoulGemSwapContainerRef
    ;set rItemBase to rItem.GetBaseObject
    ;set iNumItems to rItem.GetRefCount
    ;PrintC"RFSoulGemSwapContainerRef - Found %g) %n)" iNumItems, rItemBase
   ;loop
  
   RFSoulGemSwapContainerRef.RemoveAllItems player 0
   player.PlaySound3D SPLMysticismCast
   Message "Soulgem boogie complete."
   ;DestroyString strFilename
  elseif iButton == 6

Soulgem Boogie seems to be working lately. Though in the past it would sometimes convert one soulgem I filled to two full ones. LOL! Other times I would see my entire stack of empty ones disappear and a big stack of full ones appear. However, it happens so sporadically that I can't pinpoint the cause.

 

EDIT:

 

My suspicion is that one (or both) of my loops are somehow corrupting the inventory stacks of soulgems in my inventory. Or xOBSE has a bug that is doing this and my scripts just happen to hit that bug in its head. I updated xOBSE at some point to 22.7 and am now at 22.9. The problem may have started with 22.7. I tried going back to OBSE 22.1, but the problem continued. I am back to 22.9 now.

Edited by GamerRick
Link to comment
Share on other sites

The first seems OK, as it only checks something, it can't alter item stacks in any way. But in second one you're using AddItem command within ForEach loop, the docs explicitly say to not use such commands until it ends. Maybe you can use CreateTempRef, SetRefCount and CopyIR, but I'm not sure, as example is doing it after the end of loop too.

Edited by RomanR
Link to comment
Share on other sites

The correct way to determine the soul level for creatures. Refscope is where I found this.

  if rTarget.IsCreature == 0
     set iSoulSize to 6
  elseif rTarget.IsPCLevelOffset == 0
     let rTargetBase := rTarget.GetBaseObject
     Let iSoulSize := rTarget.GetCreatureSoulLevel
     PrintC"RFFnOnSoulTrap: Creature %n is NOT PCLO, Soulsize is %g", rTargetBase, iSoulSize
  elseif rTarget.GetLevel >= 18
     set iSoulSize to 5
  elseif rTarget.GetLevel >= 13
     set iSoulSize to 4
  elseif rTarget.GetLevel >= 7
     set iSoulSize to 3
  elseif rTarget.GetLevel >= 2
     set iSoulSize to 2
  else
     set iSoulSize to 1
  endif
Edited by GamerRick
Link to comment
Share on other sites

Yes, yours soul level part is now almost same as mine, just more tidy. Still .... this alone can't result in wrong stacks amounts. However as I saw your second script again , I have a theory about wrong timing using AddItem commands and then RemoveAllItems on a swap container. As such commands goes into queue, maybe it's better to execute RemoveAllItems next frame after AddItem command(s) fill a swap container with soul gem(s). But my experience is that only enchanted items needs such handling for equip and unequip when using OBSE, so I may be wrong.

Link to comment
Share on other sites

Actually, the script (SoulGemBoogie) that converts player filled empty gems with their filled counterparts works flawlessly. It's the one that counts the gems that are still empty that is failing. So, it would seem that the empty stack in the player's inventory is the one that is getting corrupted somehow.

 

Meanwhile I have done 2 things:

 

1) Change SoulGemBoogie to open the swap container, so that the player can put the non-empty empty gems into it. Upon exiting the container, the script's GameMode script will scan through the swap container, remove the stacks that can be converted, and do the AddItemNS command on the player to give them the converted ones. I did this so that there were no scripted RemoveMeIR commands being done on the player (that may or may not be cause the corruption).

 

2) Start a new game. It will be a while before I can cast a soultrap spell for the first time.

Edited by GamerRick
Link to comment
Share on other sites

  • 2 weeks later...
  • Recently Browsing   0 members

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