AddForm(), Revert(), and compability between mods

Post » Sat Jul 16, 2016 7:15 am

I've noticed a big loophole in the functions to adjust http://www.creationkit.com/index.php?title=LeveledItem_Script lists.



1. Items added to Leveled Item lists will persist through game saves, meaning that if you ever add an item more than once, it will have multiple entries in the list.


2. The Revert() function will remove ALL script added forms to the Leveled Item list.



So what does this mean? It means that you should only ever add to this list once, for example the first time your mod is loaded.


However, it also means that if another mod ever uses the Revert() function, it will remove everything you added to the list.



This doesn't make sense at all, because if you add things to the lists multiple times, you will screw up the game's probability of selecting other items on it. And if you only add them once, theres a risk of another mod breaking your changes. It looks something like this:


  • Skyrim loads default lists, with previous saved changes applied.

  • Mod_01 reverts a list to remove changes, and adds new items to it.

  • Mod_02 reverts the same list, removing Mod_01's list items, then add it's own items.

  • Mod_03 resets the list, etc. etc.

  • Result: Only default items and Mod_03's items are on the specified list.


It would be a lot smarter if the game did not save changes made to these lists, then each mod would be responsible of adding their items to the lists after each game load, which would look something like this:


  • Skyrim loads default lists.

  • Mod_1 adds items to the vendor misc list

  • Mod_2 adds more items to the vendor misc list

  • Mod_3 adds even more items to the same list

  • Result: All mods have their items on the list


So.. Are there any ways to fight against the current system?


The only way I can think of right now would be if it was possible to return the index in the list where your item is added to, and save it in a global variable. Then on each load, you would check that index for the item you placed there, and if that index doesn't exist or another item is there, it's safe to assume someone has reverted the list.


However, for that to work, it would have to be possible to return an integer when using the AddForm() function, so you know where to check..



What are your thoughts about all this?

User avatar
Avril Louise
 
Posts: 3408
Joined: Thu Jun 15, 2006 10:37 pm

Post » Sat Jul 16, 2016 1:02 am

Scripting should always be the last way you try to solve a problem not the first.



That leveled list problem is why we avoided modifying them using scripts in Oblivion. You can get greater mod compatibility by altering the leveled lists directly in the ESP and then letting Wrye Bash merge them. And the importance of merging leveled lists is why that's one of the few things a Bashed Patch actually implements in Skyrim compared to Oblivion. It was viewed as absolutely critical for mod compatibility.



If you're manipulating your own leveled lists go ahead and use scripts if you like. But if you're trying to alter the game's original lists do it in the CK.

User avatar
Dan Scott
 
Posts: 3373
Joined: Sun Nov 11, 2007 3:45 am

Post » Sat Jul 16, 2016 3:34 am


Why? Maybe it's because I'm new to Skyrim modding, but for me the opposite of what you just said should be true. If it's my own custom list, I can modify it in the CK without screwing up another mod. But if I add things directly to the default vendor misc item list, I am overwriting the default file which would conflict with any other mod doing the same.. right?



However, I just wrote a code that's a viable solution to tackle this problem, which will only add items the first time, or if it detects the list having been reverted.




This script safely adds a book to the list (the process would be the same for different item types too)



LeveledItem Property LiVendorBooks Auto ;the list to add items to
Book Property helpBook Auto ;the item to add

int bookCheckIndex ;used to store the index where the item was placed in the list
Book bookCheckItem ;used to store info about which item was placed at the index

Function AddBookToList()
If (!bookCheckIndex || LiVendorBooks.GetNthForm(bookCheckIndex) != bookCheckItem )
bookCheckIndex = LiVendorBooks.GetNumForms()
bookCheckItem = helpBook ;The stored item on this line needs to be...
LiVendorBooks.AddForm(helpBook, 1, 1) ;...the same item as on this line
;ADD ANY ADDITIONAL ITEMS BELOW HERE:
Debug.Notification("Book added to list position " + bookCheckIndex)
EndIf
EndFunction


The script should be self-explanatory, but I'll give it a quick walk-through.



The if-statement basically checks if bookCheckIndex has been given a value earlier, OR if the item placed at a certain index in the list doesn't match what you previously placed there.


So the if-statement will always return true the first time, then add your items and store information about the first custom index and the item placed there. The next time the if-statement runs, it will take a look at that index position in the list to see if the previously placed item is still there.


If it's mysteriously gone, it is safe to assume that the list has been reverted and that we can re-add our items, because there's really no other reason why an earlier list index would change or not exist, since newly added items are appended at the end of the list.



And even if you add 50 different items to the list, it should be safe to just check the first item you placed in it.


But this needs to be done for every different list.



Edit: Oh, and I forgot to mention that this function should be executed after every game load. Preferably after a 5-10 second timer to let other mods have some time to potentially revert the list.



And the only real issue would be if another mod reverts the list in the middle of gameplay. But calling the function again would fix that, so it could theoretically be called just before opening the merchant's shop menu.

User avatar
Svenja Hedrich
 
Posts: 3496
Joined: Mon Apr 23, 2007 3:18 pm

Post » Sat Jul 16, 2016 12:58 am

You missed the part about the Bashed Patch ability to merge lists. Experience has shown us that scripted changes to the lists result in odd unexpected behaviors and incompatibilities when multiple mods are involved. And since the changes are scripted the source of the resulting problems are extremely hard to track down. If the edits are made directly to the list then it's a simple matter of loading up all the mods in a player's load order into TES5Edit and looking for conflicts. In this particular case the problem is so well-defined that Wrye Bash actually solves it automatically when you build the Patch.

User avatar
Bones47
 
Posts: 3399
Joined: Fri Nov 09, 2007 11:15 pm

Post » Sat Jul 16, 2016 4:22 am


Did not know what the Bashed Patch was, and to be honest, while it seems useful for some mods, I would rather try to make my mod work properly without relying on every single player to patch and fix my screwups before playing.


I can imagine though that people have been seeing odd behaviors with multiple mods using scripts to alter leveled lists -- which is exactly why I started this thread. The functions are potentially dangerous to use considering what they do, so people with less programming experience are prone to accidentally screwing things up for both themselves and other mods. It's very easy to accidentally add things multiple times to the list, which after a while may bloat the save file with tens of thousands of items on the lists. And imho the Revert() function should be avoided completely if possible.


But if these functions are used carefully, I don't see a reason why the list would behave strangely.



I'm pretty certain that the script I posted above is proof against these kind of screw-ups.


There is no function listed on the wiki to change the item located at a certain index -- which means that no other mod can move or change the type of item you added to the list without reverting the entire list.


So, by checking if your item is still where you put it in the list, it possible to make sure you don't add the same items multiple times, yet still being able to detect if the list was reverted so you can add them back when necessary.

User avatar
sally R
 
Posts: 3503
Joined: Mon Sep 25, 2006 10:34 pm


Return to V - Skyrim