Refwalk on MISC Items Crashing Game?

Post » Thu May 03, 2012 4:33 am

In my mod, I refwalk through the MISC items in a cell and, if they're truly junk, transfer them to a box in the player's house. Occasionally, after a lot of play, when I enter an area filled with a lot of junk (so far, the Arlington(?) Library and Dukov's place), the game will crash about the time the script should start running. It's not necessarily reproducible (i.e., when I load up a save game from just before walking through the door, it doesn't crash). I can't figure out what's wrong. My current possibilities are that 1) there's so much junk in the cell that all the sudden processing after lots of previous play svcks the remaining memory or other resources out of the game and crashes it, 2) there's so much junk in the cell that my loop can't get through it all before the frame changes and a reference goes null in the middle of use, or 3) there's so much junk in the area that trying to process it all while the cell is loading (even with a 5 second delay) svcks all the memory/resources out of the game and it crashes. Are there other things I should do in this script to try to prevent crashing? Is there some way to figure out what's causing the crashes (since it's not reliably reproducible, and there are bajillions of pieces of junk out there, I can't just turn on my PrintToConsole statements (removed from the code, below) and dump everything to a text file with SCOF)?

ScriptName DALCOJunkOMaticScript;This script is attached to the DALCOJunkOMatic device in the player's inventory.  The only difference between this script and the one with the 2 is the box things go in.;It looks for all the MISC items in a cell, and checks for ownership and true junk status;It then activates it delete it from the cell and to transfer one piece to the player's inventory (a fault with activate - it should move the whole stack).;It then does an AddItem for that item directly to the Box in the player's house for all the items in the stack.  Then, it removes the 1 piece brought in by Activate.float fTimershort bRunItshort iSizeOfStackreference rBaseObjectreference rOwnerreference rPieceOfMiscBegin OnEquipif GetFOSEVersion ; checks to see if FOSE is present (required)  set bRunIt to 1  ;Failsafe Variable Initializations  set fTimer to 0  set iSizeOfStack to 1else ;If FOSE isn't running, display a warning and set things up to quit  set bRunIt to 0  ShowMessage DALCOJOMFoseWarningMessageendif ;done with FOSE existence checkEndBegin GameModeif bRunIt  if (fTimer < 5) ; Want the big stuff to run only periodically.  So, if less than five seconds have passed, just increment the timer   set fTimer to fTimer + GetSecondsPassed    else ; This is the main stuff that run every 5 seconds   set rPieceOfMisc to GetFirstRef 31 0 0 ; Finds the first reference in the current cell of MISC type ("31")   Label 10 ; this is the start of the loop to grab all MISC items in the cell   if (rPieceOfMisc) ; if it found something to process -- now see if it's not mine already  	set rOwner to rPieceOfMisc.GetOwner	if (rOwner != player) ; Only look at things that don't belong to me	 if (rPieceOfMisc.IsInList DALJunkItemsList) ; if it's in this list, it's junk	  set iSizeOfStack to rPieceOfMisc.GetRefCount ; find out how many items are being pointed to	  rPieceOfMisc.SetOwnership ; since it's junk (i.e., mostly worthless), set it to me so I can take it	  set rBaseObject to rPieceOfMisc.GetBaseObject ; for use after Activate on the ref	  rPieceOfMisc.Activate player ; removes the item from the cell and adds one piece to player's inventory	  DALCOMiscItemsBox.AddItem rBaseObject iSizeOfStack 1 ; add all of the item to a container in the player's home (without a message)	  player.RemoveItem rBaseObject 1 1 ; removes the one item from the Activate statement	 endif	endif  	set rPieceOfMisc to Apple ; Prevent "apple" bug	set rPieceOfMisc to GetNextRef ; get the next reference in the current cell of MISC type ("31") and repeat	Goto 10   endif   set fTimer to 0 ; we've done our processing for this clock cycle, so set the timer back to 0  endifendifEndBegin OnUnequipset bRunIt to 0End
User avatar
Ashley Campos
 
Posts: 3415
Joined: Fri Sep 22, 2006 9:03 pm

Post » Thu May 03, 2012 3:52 am

It looks like your script should be fine. The thing that comes to mind that may be a problem is the adding/removing bunches of items from the player in the same frame - scripted misc items could be the culprit. You can take the player out of the equation entirely by just disabling the item that you are 'picking up'.

ScriptName DALCOJunkOMaticScript;This script is attached to the DALCOJunkOMatic device in the player's inventory.  The only difference between this script and the one with the 2 is the box things go in.;It looks for all the MISC items in a cell, and checks for ownership and true junk status;It then activates it delete it from the cell and to transfer one piece to the player's inventory (a fault with activate - it should move the whole stack).;It then does an AddItem for that item directly to the Box in the player's house for all the items in the stack.  Then, it removes the 1 piece brought in by Activate.float fTimershort bRunItshort iSizeOfStackreference rBaseObjectreference rOwnerreference rPieceOfMiscBegin OnEquip    if GetFOSEVersion ; checks to see if FOSE is present (required)      set bRunIt to 1      ;Failsafe Variable Initializations      set fTimer to 0      set iSizeOfStack to 1    else ;If FOSE isn't running, display a warning and set things up to quit      set bRunIt to 0      ShowMessage DALCOJOMFoseWarningMessage    endif ;done with FOSE existence checkEndBegin GameMode    if bRunIt      if (fTimer < 5) ; Want the big stuff to run only periodically.  So, if less than five seconds have passed, just increment the timer       set fTimer to fTimer + GetSecondsPassed            else ; This is the main stuff that run every 5 seconds       set rPieceOfMisc to GetFirstRef 31 0 0 ; Finds the first reference in the current cell of MISC type ("31")       Label 10 ; this is the start of the loop to grab all MISC items in the cell       if (rPieceOfMisc) ; if it found something to process -- now see if it's not mine already                  set rOwner to rPieceOfMisc.GetOwner            if (rOwner != player) ; Only look at things that don't belong to me             if (rPieceOfMisc.IsInList DALJunkItemsList) ; if it's in this list, it's junk              set iSizeOfStack to rPieceOfMisc.GetRefCount ; find out how many items are being pointed to              set rBaseObject to rPieceOfMisc.GetBaseObject ; for use after Activate on the ref                            rPieceOfMisc.disable                            DALCOMiscItemsBox.AddItem rBaseObject iSizeOfStack 1 ; add all of the item to a container in the player's home (without a message)             endif            endif                  set rPieceOfMisc to Apple ; Prevent "apple" bug            set rPieceOfMisc to GetNextRef ; get the next reference in the current cell of MISC type ("31") and repeat            Goto 10       endif       set fTimer to 0 ; we've done our processing for this clock cycle, so set the timer back to 0      endif    endifEndBegin OnUnequipset bRunIt to 0End
User avatar
Jade Barnes-Mackey
 
Posts: 3418
Joined: Thu Jul 13, 2006 7:29 am

Post » Thu May 03, 2012 1:34 pm

I was a bit worried about the quick turnaround of the item between my Activate and Removeitem calls. But, I figured that if it was a problem, the script would fail for EVERY item. I had thought of using Disable. But, for some reason, I didn't use it. Anyway, your suggestion sounds good and I'll give it a shot.

Just to make sure -- along with the

rPieceOfMisc.Disable,

do I need an

rPieceOfMisc.MarkForDelete?

Oops: after writing the above, I realized that I had tried the Disable/MarkForDelete route once. But, the items didn't disappear from the ground until I left the cell and returned. And, since the point of the mod is to clear the junk out of the area so the player can see the important stuff, that sort of defeated the purpose.

I'll give it a try again, just to make sure I'm not mis-remembering. If it doesn't work, maybe I'll try adding a short timer type thing between the Activate and Remove. I think I remember a Cipscis post somewhere mentioning how much time it takes for something to show up in inventory. I'll try to find it. I hope it's not until after the frame refreshes, since I'm pretty sure that would break the refwalk, too.
User avatar
Soph
 
Posts: 3499
Joined: Fri Oct 13, 2006 8:24 am

Post » Thu May 03, 2012 3:53 pm

I wouldn't do a markfordelete. Sometimes scripted items will crash. But that's strange that disable would delay like that. I've never seen it happen.
User avatar
Bird
 
Posts: 3492
Joined: Fri Nov 30, 2007 12:45 am

Post » Thu May 03, 2012 2:56 pm

Well, this is odd. I definitely must have done something wrong in my earlier testing of Disable. I tried it again and the items promptly disappeared from the cell. I was dancing for joy. But, I went to double-check that the items were getting to the container where I was dumping them. They were there, so I took them. Five seconds later, there were more items in the box. I took them. Rinse and repeat. Even if I leave everything in the box, the set of items increases by one full set every five seconds (there are 18 items in that set -- 8 of them are stacks).

So, for some reason, if I Disable (and I even added a check for GetDisabled at the top of the loop and included MarkForDelete), it adds a list of items (the same list) into that box every time my script loops through. It takes nothing from my inventory or from the immediate vicinity (the container is in my Megaton House). It's an infinite junk generator. I put my Activate/RemoveItem script back and nothing like that happens. It makes a one-time grab of all the junk in the area (a different set than what appears with Disable) and then the container remains empty after I take everything from it (and doesn't increase if I leave it). It makes no sense.

If the lists of appearing items were the same with the two versions, I'd say the game just wasn't getting around to deleting the references before my script came around again (though, my check for GetDisabled should stop the script from grabbing them). If the stuff only appeared every 3 days or so (whatever the time period is for the game repleneshing things), I could understand that. But, it happens every 5 seconds.
User avatar
Danielle Brown
 
Posts: 3380
Joined: Wed Sep 27, 2006 6:03 am

Post » Thu May 03, 2012 12:11 pm

Oh, and here's the new script:

ScriptName DALCOJunkOMaticScript;This script is attached to the DALCOJunkOMatic device in the player's inventory.  The only difference between this script and the one with the 2 is the box things go in.;It looks for all the MISC items in a cell, and checks for ownership and true junk status;It then activates it delete it from the cell and to transfer one piece to the player's inventory (a fault with activate - it should move the whole stack).;It then does an AddItem for that item directly to the Box in the player's house for all the items in the stack.  Then, it removes the 1 piece brought in by Activate.float fTimershort bRunItshort iSizeOfStackreference rBaseObjectreference rOwnerreference rPieceOfMiscBegin OnEquipif GetFOSEVersion ; checks to see if FOSE is present (required)  set bRunIt to 1  ;Failsafe Variable Initializations  set fTimer to 0  set iSizeOfStack to 1else ;If FOSE isn't running, display a warning and set things up to quit  set bRunIt to 0  ShowMessage DALCOJOMFoseWarningMessageendif ;done with FOSE existence checkEndBegin GameModeif bRunIt  if (fTimer < 5) ; Want the big stuff to run only periodically.  So, if less than five seconds have passed, just increment the timer    set fTimer to fTimer + GetSecondsPassed    else ; This is the main stuff that run every 5 seconds   set rPieceOfMisc to GetFirstRef 31 0 0 ; Finds the first reference in the current cell of MISC type ("31")   Label 10 ; this is the start of the loop to grab all MISC items in the cell   if (rPieceOfMisc) ; if it found something to process -- now see if it's not mine already      if (rPieceOfMisc.GetDisabled == 0) ; make sure I haven't already disabled the item (the game hasn't deleted it yet)  	 set rOwner to rPieceOfMisc.GetOwner 	 if (rOwner != player) ; Only look at things that don't belong to me	  if (rPieceOfMisc.IsInList DALJunkItemsList) ; if it's in this list, it's junk	   set iSizeOfStack to rPieceOfMisc.GetRefCount ; find out how many items are being pointed to	   rPieceOfMisc.SetOwnership ; since it's junk (i.e., mostly worthless), set it to me so I can take it	   set rBaseObject to rPieceOfMisc.GetBaseObject ; for use after Activate on the ref	   rPieceOfMisc.Disable ; disables the item (makes it disappear from the game)	   rPieceOfMisc.MarkForDelete ; tells the game to actually delete the object (when it gets around to it)	   DALCOMiscItemsBox.AddItem rBaseObject iSizeOfStack 1 ; add all of the item to a container in the player's home (without a message)	  endif	 endif    endif       set rPieceOfMisc to Apple ; Prevent "apple" bug    set rPieceOfMisc to GetNextRef ; get the next reference in the current cell of MISC type ("31") and repeat    Goto 10   endif   set fTimer to 0 ; we've done our processing for this clock cycle, so set the timer back to 0  endifendifEndBegin OnUnequipset bRunIt to 0End
User avatar
Sabrina garzotto
 
Posts: 3384
Joined: Fri Dec 29, 2006 4:58 pm

Post » Thu May 03, 2012 9:23 am

OK. I'm pretty sure I found what's causing this (though not why). I checked the FO3 Wiki at:

http://fallout.wikia.com/wiki/My_Megaton_house

and looked at the themes and the items the player can add to the house. The list of items that are appearing in the container are the very same junk items (and number of items) that the theme and upgrades I bought add to the house. I can't imagine the game instantly restocking those items if someone disables them (as opposed to taking (activating) them). So, perhaps the game has somehow locked those items to prevent them from being disabled or altered. I'm going to have to dig around in the GECK and see if I can figure out how those themes/upgrades work.
User avatar
Sudah mati ini Keparat
 
Posts: 3605
Joined: Mon Jul 23, 2007 6:14 pm

Post » Thu May 03, 2012 4:07 pm

Oops.
I forgot that a ref-walk catches disabled items too. So skipping them is required in your script. I still wouldn't use markfordelete, though. Just disable. If a script comes along later and tries to enable a deleted reference, there will be a crash. disabling an item just makes it invisible. It's still there, running scripts and accessible through scripts.

Edit - The items in the house not disappearing may be due to them having an 'enable parent', which would be an invisible object in the cell that a script controls. These items will use the parent as the 'boss' as to whether they should be enabled or not.
User avatar
gemma king
 
Posts: 3523
Joined: Fri Feb 09, 2007 12:11 pm

Post » Thu May 03, 2012 9:59 am

Earlier, I had made the player's houses (where the box is located) owned by the player. So, I used IsInMyOwnedCell to not process in those houses. I did some testing and everything seems to work. Thanks again. If you're interested, the mod is at:

http://www.fallout3nexus.com/downloads/file.php?id=17176

EDIT: I'm torn on the MarkForDelete thing. I left it in this version. I understand that there could be problems with other scripts trying to do things with the deleted references. But, I'm under the impression they'd have to know the actual reference ID of the object. All the stuff I'm deleting (and there's a lot of it) is just junk. It's unused anywhere in the base game and DLCs except for selling it to a merchant. For a problem to happen, wouldn't someone have to target a specific piece of junk that's gone (i.e, this bent tin can in the corner under the desk in the library)? After being truly deleted, another script won't be able to refwalk on them since they're gone. I can't imagine anyone targeting a script at a specific piece of junk. Or, am I totally misinterpreting this?

EDIT 2: After thinking about it some more and considering other people's input, I've decided to err on the side of compatibility instead of save game file size: I've removed the MarkForDelete lines from my mod. Thanks again.
User avatar
Mariana
 
Posts: 3426
Joined: Mon Jun 12, 2006 9:39 pm


Return to Fallout 3