davidlallen Posted February 23, 2011 Share Posted February 23, 2011 Parallel discussion on this thread:http://www.thenexusforums.com/index.php?/topic/305067-ammo-swapping-with-form-lists-and-nvse Link to comment Share on other sites More sharing options...
HerrBaron Posted February 23, 2011 Author Share Posted February 23, 2011 You only need one form list as storage; declare it in your mod. Put one blank item in it as a placeholder as suggested by rickerhk in the bethsoft thread. David, any idea if the TempCloneForm NVSE function has ever actually been there? GECK with GeckPU doesn't seem to know about it...? Thanks for the link; just checked it out. BTW, I'm gonna grab your quest mod as soon as I get back to playing instead of modding... :) Link to comment Share on other sites More sharing options...
davidlallen Posted February 24, 2011 Share Posted February 24, 2011 I have actively avoided learning about NVSE so far. Looking forward to feedback (and an endorsement, if you like it) for Decisions With Regrets. Link to comment Share on other sites More sharing options...
HerrBaron Posted February 24, 2011 Author Share Posted February 24, 2011 I have actively avoided learning about NVSE so far. Looking forward to feedback (and an endorsement, if you like it) for Decisions With Regrets. No doubt you've earned it; I suspect it's a very polished mod, and I respect the work that goes into those. Understand how you feel about NVSE, but there are some things you just can't accomplish without it. I resisted modding with it for a long time, myself, but as I got deeper into modding it, I found that there are a whole range of hoops you don't have to jump through with NVSE, and since most folks have it installed, I got over my qualms. My only issue with it, seriously, is that the form list support is so buggy; lists are essential in data processing; they're a natural data structure for a broad range of ComSci issues. They even invented a language once to work with them; it was called LISP. It didn't do much else well, but it did lists superbly...! :) Link to comment Share on other sites More sharing options...
davidlallen Posted February 24, 2011 Share Posted February 24, 2011 Ah, LISP, a quick flashback to the summer of 1985. Think of this as a programming challenge, how to do these effects without access to lists. Link to comment Share on other sites More sharing options...
rickerhk Posted February 26, 2011 Share Posted February 26, 2011 Here's some more info that might help in regards to clearing a list populated with Base forms. I've set up some test scripts and can manipulate base forms up until I try to remove a form - If I do the removal within a Label/Goto loop, one form will be removed, then the loop will abort. Any loop after that in the same script will also abort after one list function. I haven't checked if the list would be ok in subsequent frames for access, but a listcount is accurate. It does this in FOSE and NVSE. If I re-arrange the script, removing the Label/Goto loop so that one form is removed per frame, I can clear the list. This snippet aborts the loop after removing one Form: Label 300 if (iIndex) set iIndex to iIndex - 1 set rReadFormREF to ListGetNthForm RHKTestBaseFormList iIndex PrintToConsole "Item %n at Index %0.f", rReadFormREF, iIndex set iRemoveResult to ListRemoveNthForm RHKTestBaseFormList iIndex PrintToConsole "Remove Form Index %.0f Remove Result %.0f", iIndex, iRemoveResult Goto 300 endif Doing it this way clears the list: scn RHKTestBaseFormsQuestScript2 ref rBaseObjREF ref rReadFormREF short iIndex short iRemoveResult short iFormCount short iClearForm short iMenuInit ;Populate a list, read it back, then clear it ;Call with ResetQuest, then iMenuInit == 1, StartQuest ;Questdelay .033 BEGIN GameMode if (iMenuInit == 1) set rBaseObjREF to BehemothFireHydrant ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to CG02WeapBBGun ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to BMWeapNailBoard ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to LakelurkSonic2HL ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to MisterGutsyPlasma1HP ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to NellisArtillery ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to Weap10mmSubmachineGun ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to WeapFatman ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to WeapNVBallisticFist ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to WeapNVCaravanShotgun ListAddForm RHKTestBaseFormList rBaseObjREF set iFormCount to ListGetCount RHKTestBaseFormList set iIndex to iFormCount PrintToConsole "Form Count after Adds %.0f ", iFormCount Label 100 if (iIndex) set iIndex to iIndex - 1 set rReadFormREF to ListGetNthForm RHKTestBaseFormList iIndex PrintToConsole "Item %n at Index %0.f", rReadFormREF, iIndex Goto 100 endif set iMenuInit to 2 set iClearForm to 1 elseif (iMenuInit == 2) if (iClearForm) if (iFormCount) set iRemoveResult to ListRemoveNthForm RHKTestBaseFormList 0 ;Clear index zero, stuff moves up set iFormCount to iFormCount - 1 PrintToConsole "Removed form %.0f", iFormCount if (iFormCount == 0) set iClearForm to 0 endif endif else set iFormCount to ListGetCount RHKTestBaseFormList PrintToConsole "Form Count after del %.0f", iFormCount set iIndex to iFormCount Label 400 if (iIndex) set iIndex to iIndex - 1 set rReadFormREF to ListGetNthForm RHKTestBaseFormList iIndex PrintToConsole "Item %n at Index %0.f", rReadFormREF, iIndex Goto 400 endif StopQuest RHKFormTestMenu set iMenuInit to 0 endif endif END Link to comment Share on other sites More sharing options...
HerrBaron Posted February 26, 2011 Author Share Posted February 26, 2011 Here's some more info that might help in regards to clearing a list populated with Base forms. I've set up some test scripts and can manipulate base forms up until I try to remove a form - If I do the removal within a Label/Goto loop, one form will be removed, then the loop will abort. Any loop after that in the same script will also abort after one list function. I haven't checked if the list would be ok in subsequent frames for access, but a listcount is accurate. It does this in FOSE and NVSE. If I re-arrange the script, removing the Label/Goto loop so that one form is removed per frame, I can clear the list. This snippet aborts the loop after removing one Form: Label 300 if (iIndex) set iIndex to iIndex - 1 set rReadFormREF to ListGetNthForm RHKTestBaseFormList iIndex PrintToConsole "Item %n at Index %0.f", rReadFormREF, iIndex set iRemoveResult to ListRemoveNthForm RHKTestBaseFormList iIndex PrintToConsole "Remove Form Index %.0f Remove Result %.0f", iIndex, iRemoveResult Goto 300 endif Doing it this way clears the list: scn RHKTestBaseFormsQuestScript2 ref rBaseObjREF ref rReadFormREF short iIndex short iRemoveResult short iFormCount short iClearForm short iMenuInit ;Populate a list, read it back, then clear it ;Call with ResetQuest, then iMenuInit == 1, StartQuest ;Questdelay .033 BEGIN GameMode if (iMenuInit == 1) set rBaseObjREF to BehemothFireHydrant ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to CG02WeapBBGun ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to BMWeapNailBoard ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to LakelurkSonic2HL ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to MisterGutsyPlasma1HP ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to NellisArtillery ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to Weap10mmSubmachineGun ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to WeapFatman ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to WeapNVBallisticFist ListAddForm RHKTestBaseFormList rBaseObjREF set rBaseObjREF to WeapNVCaravanShotgun ListAddForm RHKTestBaseFormList rBaseObjREF set iFormCount to ListGetCount RHKTestBaseFormList set iIndex to iFormCount PrintToConsole "Form Count after Adds %.0f ", iFormCount Label 100 if (iIndex) set iIndex to iIndex - 1 set rReadFormREF to ListGetNthForm RHKTestBaseFormList iIndex PrintToConsole "Item %n at Index %0.f", rReadFormREF, iIndex Goto 100 endif set iMenuInit to 2 set iClearForm to 1 elseif (iMenuInit == 2) if (iClearForm) if (iFormCount) set iRemoveResult to ListRemoveNthForm RHKTestBaseFormList 0 ;Clear index zero, stuff moves up set iFormCount to iFormCount - 1 PrintToConsole "Removed form %.0f", iFormCount if (iFormCount == 0) set iClearForm to 0 endif endif else set iFormCount to ListGetCount RHKTestBaseFormList PrintToConsole "Form Count after del %.0f", iFormCount set iIndex to iFormCount Label 400 if (iIndex) set iIndex to iIndex - 1 set rReadFormREF to ListGetNthForm RHKTestBaseFormList iIndex PrintToConsole "Item %n at Index %0.f", rReadFormREF, iIndex Goto 400 endif StopQuest RHKFormTestMenu set iMenuInit to 0 endif endif END Hey Ricker! :) Thanks for going to the trouble on this. Very revealing, in that you're doing this in a quest rather than in a block handler that's responding to an event. I note that when my script crashes (it CTD's; it doesn't just abort processing), it's always at a particular place in NVSE_1_1.dll. We know that this game engine multithreads, and I'm wondering if maybe we're hitting a threading race condition or infinite loop or a combination of the two. In the next couple of days, I'm going to build a debug version of nvse_1_1.dll, and do some stepping through in the debugger with it. If I find anything, I'll post it here in this thread, and send what I find to the NVSE guys. Maybe it'll save them some time and effort. BTW, you write very nice, clean code! :) Link to comment Share on other sites More sharing options...
rickerhk Posted February 26, 2011 Share Posted February 26, 2011 Thanks for going to the trouble on this. Very revealing, in that you're doing this in a quest rather than in a block handler that's responding to an event. Hmm - I've never run a Label/Goto Loop inside an event handler block. I don't recall clearly but I may have read that that should not be done. I just use that type of block to set things up for a gamemode or menumode block to follow. I tried a similar test script on an armor token added to the player, with the same results. But generally, I use quest scripts sort of like subroutines, starting and stopping when needed. I like them because I can adjust the quest delay so they don't necessarily have to run every frame, depending on the application. I note that when my script crashes (it CTD's; it doesn't just abort processing), it's always at a particular place in NVSE_1_1.dll. We know that this game engine multithreads, and I'm wondering if maybe we're hitting a threading race condition or infinite loop or a combination of the two. My understanding is that all scripts are run in the same thread, sequentially. So you won't have a case where you have two scripts trying to change the same variable somewhere else at the same time, for example. In the next couple of days, I'm going to build a debug version of nvse_1_1.dll, and do some stepping through in the debugger with it. If I find anything, I'll post it here in this thread, and send what I find to the NVSE guys. Maybe it'll save them some time and effort. BTW, you write very nice, clean code! Thanks. I think the NVSE guys could use some help because from what i've gathered, they are really busy with real-life concerns. Like work ;) That would be really cool if you could do that and they were receptive to it. Link to comment Share on other sites More sharing options...
HerrBaron Posted February 26, 2011 Author Share Posted February 26, 2011 Thanks for going to the trouble on this. Very revealing, in that you're doing this in a quest rather than in a block handler that's responding to an event. Hmm - I've never run a Label/Goto Loop inside an event handler block. I don't recall clearly but I may have read that that should not be done. I just use that type of block to set things up for a gamemode or menumode block to follow. I tried a similar test script on an armor token added to the player, with the same results. But generally, I use quest scripts sort of like subroutines, starting and stopping when needed. I like them because I can adjust the quest delay so they don't necessarily have to run every frame, depending on the application. I note that when my script crashes (it CTD's; it doesn't just abort processing), it's always at a particular place in NVSE_1_1.dll. We know that this game engine multithreads, and I'm wondering if maybe we're hitting a threading race condition or infinite loop or a combination of the two. My understanding is that all scripts are run in the same thread, sequentially. So you won't have a case where you have two scripts trying to change the same variable somewhere else at the same time, for example. In the next couple of days, I'm going to build a debug version of nvse_1_1.dll, and do some stepping through in the debugger with it. If I find anything, I'll post it here in this thread, and send what I find to the NVSE guys. Maybe it'll save them some time and effort. BTW, you write very nice, clean code! Thanks. I think the NVSE guys could use some help because from what i've gathered, they are really busy with real-life concerns. Like work ;) That would be really cool if you could do that and they were receptive to it. Ah, guess I wasn't clear; the gamemode block is where I'm doing the clear loop, not in an OnActivate or whatever. That said, I've assumed that gamemode is an event handler of sorts, just called on the basis of being there for each frame. It's GREAT to know that scripts are run on the same thread sequentially; that eliminates a big worry and a great big can of worms debugging-wise... Very good points about quest scripts; I'll build a version of the script I'm having problems with to run as a quest script modelled on your example above; this may be all it takes. Roger on the receptive thing; real life must always trump pro bono stuff. That said, they do include the source code with each download. The NVSE guys are tops in my book; IMHO, they've contributed more to these games with their script extenders than anyone else, by enabling a whole class of high-quality mods that wouldn't have been possible without them. Thanks again, Ricker! Good to have you around! :) Link to comment Share on other sites More sharing options...
HerrBaron Posted February 26, 2011 Author Share Posted February 26, 2011 Ok, I'll bite: have a look; maybe you can see something I'm not. This still always crashes the second time it's run! I'd rip my hair out, if I had any...! (Boy, the code tag here really, really sucks!) ScriptName WSTNHKExceptionListMgrScript; -; state machine states; -short bInitList;short bMoveItems;short bClearList; short HotKeyIndex; int iListIndex; int HotKeyItemCount;int ItemType;int nItems; ref rHKBaseObject; Begin GameMode if ( bInitList ) ;-------- ; This part works every time... ;-------- ; Get a list of weapons assigned to hotkeys; these ; will not be removed. set HotKeyItemCount to 0; set HotKeyIndex to 0; label 100 set HotKeyIndex to HotKeyIndex + 1; if ( HotKeyIndex <= 8 ) set rHKBaseObject to Player.GetHotKeyItem HotKeyIndex; if ( rHKBaseObject ) set ItemType to GetObjectType rHKBaseObject; if ( ItemType == 40 ) printc "Adding %n", rHKBaseObject; AddFormToFormList WSTNHKItemList, rHKBaseObject; set rHKBaseObject to 0; set HotKeyItemCount to HotKeyItemCount + 1; endif endif goto 100; endif ; ( HotKeyIndex <= 8 ) set bInitList to 0; set bMoveItems to 1; elseif ( bMoveItems ) set nItems to Player.GetNumItems; if ( nItems ) ;----- ; I THINK this works every time, but can't be sure, since game CTD's. No way to check the console ;----- if ( HotKeyItemCount ) printc "HKItemCount = %x", HotKeyItemCount; Player.RemoveAllTypedItems StgWeaponsREF, 0, 1, 40, WSTNHKItemList; else ; No hotkeyed weapons, just take 'em. Player.RemoveAllTypedItems StgWeaponsREF, 0, 1, 40; endif ; ( HotKeyItemCount ) endif ;( nItems ) set bMoveItems to 0; set bClearList to 1; elseif ( bClearList ) set HotKeyItemCount to ListGetCount WSTNHKItemList; if ( HotKeyItemCount ) set rHKBaseObject to ListRemoveNthForm WSTNHKItemList, 0; printc "removed %0.f", rHKBaseObject; else StopQuest WSTNHKExceptionListMgrQuest endif ; ( HotKeyItemCount ) endif ; ( bClearList ) End Link to comment Share on other sites More sharing options...
Recommended Posts