MongoMonk wrote: Does anyone know how the performance compares from JsonUtil to StorageUtil? I want to save several FormIDs for each actor encountered ingame. StorageUtil seems to be the obvious choice but JsonUtil would be neat in order to possibly edit the saved forms externally.
exiledviper wrote: There isn't much of a speed difference, at least none worth worrying about. From some basic benchmarking I've done, over 2000 iterations of setting and getting an int and a form value: JsonUtil: 0.062598 seconds, StorageUtil: 0.100601 seconds. So JsonUtil came out fractions of a second faster, which isn't worth fussing over.
Insteads it's better to just look at what your needs are. With JsonUtil all data is shared between all saves and characters. With StorageUtil the data is specific to the save.
MongoMonk wrote: Thank you for telling me. How is the handling of the json files done? Is the whole file loaded to memory once I request one entry? I'm planning to save NPCs from different mods into different files if I use JsonUtil. Also are saved FormIDs tied to the current load order? Or will they persist if the mod they're from changed its load order?
One other advantage of JsonUtil would be to actually "see" what you're saving and make sure it's stored the way you intended to.
Is there any more documentation I can read?
By the way when using Mod Organizer you can still keep the settings save specific and copy them if you want.
exiledviper wrote: Forms saved aren't load order dependent, they get saved as a string such as "mymod.esp|3426" for example, which it uses to look up the current load order of the owning mod and adjust the form id (which is saved as decimal rather than hex, 3426 = 0xD62). If the forms mod isn't loaded, attempting to read it will return as none.
Files are parsed loaded into memory the first time you try to use them, then any changes you make exist only memory until saved via jsonutil.save("file") or saved automatically at the same time skyrim writes a save. It will create the file as well during save if the file doesn't exist yet and you've set values to it.
If you load a new save, all json files loaded are automatically unloaded, and any unsaved changes lost. If you want to discard any changes you've made to a file manually, you can call jsonutil.unload("file", saveChanges=false). jsonutil.unload will remove a file from memory, optionally writing your changes or ignoring them beforehand.
The JSON handling uses jsoncpp internally (https://github.com/open-source-parsers/jsoncpp)
MongoMonk wrote: That sounds all very good. Thank you again for helping me out.
Allow me one further question: What happens to dynamically created forms (like dynamic NPCs), e.g. 0xFF003426 ? What would the "mymod.esp" in mymod.esp|3426 say? And what happens when they are unloaded from the game? Will they just return none as well?
exiledviper wrote: Wasn't sure to be honest, didn't think to test that specifically with JsonUtil. So I just did now! Looks like temporary objects save as a string saying "0", resulting in a none form on return.
I'll fix this next release. Though I'm not so sure there is, nor should there be, much of a demand for this. Point of saving to an external json is to have shareable/editable save independent data storage; so there isn't much of a purpose in being able to save temporary forms with it. The return value would be too unreliable unless used for only short lived reasons, most of which would be better served by using StorageUtil instead.
As for StorageUtil and temporary forms; it does save and load temporary forms just fine, with a couple catches though. Temporary form values will save and load fine, assuming the form still exists, it only saves the formid however, so if the temporary form is ever deleted, and the formid re-used by the game engine for a new temporary form, you'll end up with the new/replaced form on that formid being returned instead.
Saving ON a temporary as the objKey argument in StorageUtil, should remain mostly consistent, as the objkey is stored along with the form's type so it can check if the form is still the same type of form it was before. So if the temporary formid is later reused for a temporary form of a different form type, it will start accessing different maps of data, and the previous now invalid type's data discarded on save/load.
I've come to the conclusion that StorageUtil is the best bet for me. I may add an export/import feature through JsonUtil later. Since I will store all values on forms (using them as the key argument) I will probably be safe from dynamic form weirdness. I might add some checks for dynamic forms specifically in any case.
Again, thank you for the elaborate answer. You're really helping me out here (although a more exhaustive documentation could also help ).
I've got some more questions, they come as I code the new Papyrus stuff and as I map it out.
What happens to values I saved when the mod is uninstalled? Does StorageUtil have a way to check for that & clear the corresponding values or do I have to include some sort of "uninstaller" to my mod?
Also I stumbled across this function in MiscUtil: function ScanCellActors. It could prove very useful to me. Is it based on Cell.GetNthRef from SKSE? Or your own implementation? Also, would it be possible to optionally include dead actors into the search?
MongoMonk wrote: Does anyone know how the performance compares from JsonUtil to StorageUtil? I want to save several FormIDs for each actor encountered ingame. StorageUtil seems to be the obvious choice but JsonUtil would be neat in order to possibly edit the saved forms externally.
exiledviper wrote: There isn't much of a speed difference, at least none worth worrying about. From some basic benchmarking I've done, over 2000 iterations of setting and getting an int and a form value: JsonUtil: 0.062598 seconds, StorageUtil: 0.100601 seconds. So JsonUtil came out fractions of a second faster, which isn't worth fussing over.
Insteads it's better to just look at what your needs are. With JsonUtil all data is shared between all saves and characters. With StorageUtil the data is specific to the save.
MongoMonk wrote: Thank you for telling me. How is the handling of the json files done? Is the whole file loaded to memory once I request one entry? I'm planning to save NPCs from different mods into different files if I use JsonUtil. Also are saved FormIDs tied to the current load order? Or will they persist if the mod they're from changed its load order?
One other advantage of JsonUtil would be to actually "see" what you're saving and make sure it's stored the way you intended to.
Is there any more documentation I can read?
By the way when using Mod Organizer you can still keep the settings save specific and copy them if you want.
exiledviper wrote: Forms saved aren't load order dependent, they get saved as a string such as "mymod.esp|3426" for example, which it uses to look up the current load order of the owning mod and adjust the form id (which is saved as decimal rather than hex, 3426 = 0xD62). If the forms mod isn't loaded, attempting to read it will return as none.
Files are parsed loaded into memory the first time you try to use them, then any changes you make exist only memory until saved via jsonutil.save("file") or saved automatically at the same time skyrim writes a save. It will create the file as well during save if the file doesn't exist yet and you've set values to it.
If you load a new save, all json files loaded are automatically unloaded, and any unsaved changes lost. If you want to discard any changes you've made to a file manually, you can call jsonutil.unload("file", saveChanges=false). jsonutil.unload will remove a file from memory, optionally writing your changes or ignoring them beforehand.
The JSON handling uses jsoncpp internally (https://github.com/open-source-parsers/jsoncpp)
MongoMonk wrote: That sounds all very good. Thank you again for helping me out.
Allow me one further question: What happens to dynamically created forms (like dynamic NPCs), e.g. 0xFF003426 ? What would the "mymod.esp" in mymod.esp|3426 say? And what happens when they are unloaded from the game? Will they just return none as well?
exiledviper wrote: Wasn't sure to be honest, didn't think to test that specifically with JsonUtil. So I just did now! Looks like temporary objects save as a string saying "0", resulting in a none form on return.
I'll fix this next release. Though I'm not so sure there is, nor should there be, much of a demand for this. Point of saving to an external json is to have shareable/editable save independent data storage; so there isn't much of a purpose in being able to save temporary forms with it. The return value would be too unreliable unless used for only short lived reasons, most of which would be better served by using StorageUtil instead.
As for StorageUtil and temporary forms; it does save and load temporary forms just fine, with a couple catches though. Temporary form values will save and load fine, assuming the form still exists, it only saves the formid however, so if the temporary form is ever deleted, and the formid re-used by the game engine for a new temporary form, you'll end up with the new/replaced form on that formid being returned instead.
Saving ON a temporary as the objKey argument in StorageUtil, should remain mostly consistent, as the objkey is stored along with the form's type so it can check if the form is still the same type of form it was before. So if the temporary formid is later reused for a temporary form of a different form type, it will start accessing different maps of data, and the previous now invalid type's data discarded on save/load.
MongoMonk wrote: I've come to the conclusion that StorageUtil is the best bet for me. I may add an export/import feature through JsonUtil later. Since I will store all values on forms (using them as the key argument) I will probably be safe from dynamic form weirdness. I might add some checks for dynamic forms specifically in any case.
Again, thank you for the elaborate answer. You're really helping me out here (although a more exhaustive documentation could also help ).
I've got some more questions, they come as I code the new Papyrus stuff and as I map it out.
What happens to values I saved when the mod is uninstalled? Does StorageUtil have a way to check for that & clear the corresponding values or do I have to include some sort of "uninstaller" to my mod?
Also I stumbled across this function in MiscUtil: function ScanCellActors. It could prove very useful to me. Is it based on Cell.GetNthRef from SKSE? Or your own implementation? Also, would it be possible to optionally include dead actors into the search?
If a mod is uninstalled, any forms from it become none in the value storage. If the form was being used as the objkey in storageutil, during load if it can't find the objkey's owning mod anymore, all of it's values are cleared.
If you're storing values on forms not owned by your mod, those values won't go away when you uninstall the mod obviously. So, I'd suggest keeping a basic "uninstall list" stored in the global space (using "none" as your objkey) via a stroageutil.formlistadd(none, "myModsList", form, false) which you would call anytime you add a value to a new form not owned by your mod. This way you can iterate over that list and clear any values set by your mod on other forms to ensure there is no lingering data.
ScanCellActors does use SKSE's GetNth functions internally. The main benefit is that it's significantly faster at filtering out specific results, since you're not doing it via papyrus. ScanCellActors specifically doesn't have anyway to disable the removal of dead actors from the results, you could simulate something like that though by using ScanCellObjects with form type 43 and keyword ActorTypeNPC.
MongoMonk wrote: Does anyone know how the performance compares from JsonUtil to StorageUtil? I want to save several FormIDs for each actor encountered ingame. StorageUtil seems to be the obvious choice but JsonUtil would be neat in order to possibly edit the saved forms externally.
exiledviper wrote: There isn't much of a speed difference, at least none worth worrying about. From some basic benchmarking I've done, over 2000 iterations of setting and getting an int and a form value: JsonUtil: 0.062598 seconds, StorageUtil: 0.100601 seconds. So JsonUtil came out fractions of a second faster, which isn't worth fussing over.
Insteads it's better to just look at what your needs are. With JsonUtil all data is shared between all saves and characters. With StorageUtil the data is specific to the save.
MongoMonk wrote: Thank you for telling me. How is the handling of the json files done? Is the whole file loaded to memory once I request one entry? I'm planning to save NPCs from different mods into different files if I use JsonUtil. Also are saved FormIDs tied to the current load order? Or will they persist if the mod they're from changed its load order?
One other advantage of JsonUtil would be to actually "see" what you're saving and make sure it's stored the way you intended to.
Is there any more documentation I can read?
By the way when using Mod Organizer you can still keep the settings save specific and copy them if you want.
exiledviper wrote: Forms saved aren't load order dependent, they get saved as a string such as "mymod.esp|3426" for example, which it uses to look up the current load order of the owning mod and adjust the form id (which is saved as decimal rather than hex, 3426 = 0xD62). If the forms mod isn't loaded, attempting to read it will return as none.
Files are parsed loaded into memory the first time you try to use them, then any changes you make exist only memory until saved via jsonutil.save("file") or saved automatically at the same time skyrim writes a save. It will create the file as well during save if the file doesn't exist yet and you've set values to it.
If you load a new save, all json files loaded are automatically unloaded, and any unsaved changes lost. If you want to discard any changes you've made to a file manually, you can call jsonutil.unload("file", saveChanges=false). jsonutil.unload will remove a file from memory, optionally writing your changes or ignoring them beforehand.
The JSON handling uses jsoncpp internally (https://github.com/open-source-parsers/jsoncpp)
MongoMonk wrote: That sounds all very good. Thank you again for helping me out.
Allow me one further question: What happens to dynamically created forms (like dynamic NPCs), e.g. 0xFF003426 ? What would the "mymod.esp" in mymod.esp|3426 say? And what happens when they are unloaded from the game? Will they just return none as well?
exiledviper wrote: Wasn't sure to be honest, didn't think to test that specifically with JsonUtil. So I just did now! Looks like temporary objects save as a string saying "0", resulting in a none form on return.
I'll fix this next release. Though I'm not so sure there is, nor should there be, much of a demand for this. Point of saving to an external json is to have shareable/editable save independent data storage; so there isn't much of a purpose in being able to save temporary forms with it. The return value would be too unreliable unless used for only short lived reasons, most of which would be better served by using StorageUtil instead.
As for StorageUtil and temporary forms; it does save and load temporary forms just fine, with a couple catches though. Temporary form values will save and load fine, assuming the form still exists, it only saves the formid however, so if the temporary form is ever deleted, and the formid re-used by the game engine for a new temporary form, you'll end up with the new/replaced form on that formid being returned instead.
Saving ON a temporary as the objKey argument in StorageUtil, should remain mostly consistent, as the objkey is stored along with the form's type so it can check if the form is still the same type of form it was before. So if the temporary formid is later reused for a temporary form of a different form type, it will start accessing different maps of data, and the previous now invalid type's data discarded on save/load.
MongoMonk wrote: I've come to the conclusion that StorageUtil is the best bet for me. I may add an export/import feature through JsonUtil later. Since I will store all values on forms (using them as the key argument) I will probably be safe from dynamic form weirdness. I might add some checks for dynamic forms specifically in any case.
Again, thank you for the elaborate answer. You're really helping me out here (although a more exhaustive documentation could also help ).
I've got some more questions, they come as I code the new Papyrus stuff and as I map it out.
What happens to values I saved when the mod is uninstalled? Does StorageUtil have a way to check for that & clear the corresponding values or do I have to include some sort of "uninstaller" to my mod?
Also I stumbled across this function in MiscUtil: function ScanCellActors. It could prove very useful to me. Is it based on Cell.GetNthRef from SKSE? Or your own implementation? Also, would it be possible to optionally include dead actors into the search?
exiledviper wrote: If a mod is uninstalled, any forms from it become none in the value storage. If the form was being used as the objkey in storageutil, during load if it can't find the objkey's owning mod anymore, all of it's values are cleared.
If you're storing values on forms not owned by your mod, those values won't go away when you uninstall the mod obviously. So, I'd suggest keeping a basic "uninstall list" stored in the global space (using "none" as your objkey) via a stroageutil.formlistadd(none, "myModsList", form, false) which you would call anytime you add a value to a new form not owned by your mod. This way you can iterate over that list and clear any values set by your mod on other forms to ensure there is no lingering data.
ScanCellActors does use SKSE's GetNth functions internally. The main benefit is that it's significantly faster at filtering out specific results, since you're not doing it via papyrus. ScanCellActors specifically doesn't have anyway to disable the removal of dead actors from the results, you could simulate something like that though by using ScanCellObjects with form type 43 and keyword ActorTypeNPC.
Okay, I'll have a look then at ScanCellObjects since I want to specifically get dead actors. As for the uninstaller I was thinking of using ClearIntValuePrefix etc. since all my saved values start with the same prefix (" EBD_" ) which I think is unique enough so I don't touch other mods.
However, am I right in the assumption that I would not need an uninstaller if I were to use JsonUtil? Since all value associations are only written to external jsons? Or are they kept as copies in the savegame (for error checking or something) as well?
EDIT: I know it's probably not feasible but I ask anyway: Would it be possible to provide some uninstallation framework?
I.E. I register my mod with something like RegisterModUninstall("myMod.esp", "prefix_to_clear" ). Then, when myMod.esp vanishes from the load order JsonUtil would remove all values with the "prefix_to_clear".
It's probably much more work than I think but it would really streamline removal of a mod.
EDIT 2: I had a look at the ScanCellObjects function. There seems to be an issue though with the keyword parameter.
This will return zero actors: ScanCellObjects(43, PlayerREF, 0.0, EBDScriptKeyWord)
This works fine: ScanCellObjects(43, PlayerREF, 0.0)
Checking akActor.hasKeyword(EBDScriptKeyWord) returns true for all the actors I want, so the keyword is definitely there.
First, thank you so much for PapyrusUtil. It has enabled features in Campfire and Simply Knock that wouldn't be possible otherwise.
I have a couple of questions:
* Is it best practice to require users to download PapyrusUtil separately, or is bundling certain components with the mod (personally, I use JsonUtil a lot) OK? The permissions section has no data so I wanted to be sure.
* If old PapyrusUtil components (say, 3.1) are bundled in a mod, and then a user loads PapyrusUtil as a separate mod and places it at the end of their load order, will the mod in question inherit the latest changes and bug fixes? Since the components in question will be overridden / replaced, I'm inclined to say "yes" (assuming the API doesn't change), but again, wanted to make sure.
Chesko wrote: First, thank you so much for PapyrusUtil. It has enabled features in Campfire and Simply Knock that wouldn't be possible otherwise.
I have a couple of questions:
* Is it best practice to require users to download PapyrusUtil separately, or is bundling certain components with the mod (personally, I use JsonUtil a lot) OK? The permissions section has no data so I wanted to be sure.
* If old PapyrusUtil components (say, 3.1) are bundled in a mod, and then a user loads PapyrusUtil as a separate mod and places it at the end of their load order, will the mod in question inherit the latest changes and bug fixes? Since the components in question will be overridden / replaced, I'm inclined to say "yes" (assuming the API doesn't change), but again, wanted to make sure.
Thanks!
* I'm not really picky about how it's packaged. Feel free to package it with your mod and just leave a credit or link users here listing it as a separate dependency. I understand the desire to keep the install process short for users by not requiring them to install to many other seperate mods as dependencies.
On the other hand though, I will say my biggest annoyance when dealing with support for my other mod (SL) is users complaining that it's telling them their PapyrusUtil install is outdated because they've recently installed another mod that has an older version bundled- this is apparently incredibly cryptic going by how often I see it. That's my problem though, not yours. Do whatever you think best for your users.
---
* Versions are rarely not backwards or forwards compatible. The syntax for any functions rarely, if ever, changes. If a new versions syntax for a function does have to change for some reason, it's done under a new function name so it doesn't break any compatibility with existing mods. You're fine to develop on 3.1 or older, then in the majority of cases throw in 3.2 later without having to recompile anything. Same applies vice versa, if you develop in and bundle 3.2, if a user overrides it with 3.1 there shouldn't be any problems (other than the possible obvious bug/performance regression) so long as you didn't use any functions that were added by 3.2+ specifically.
MongoMonk wrote: Does anyone know how the performance compares from JsonUtil to StorageUtil? I want to save several FormIDs for each actor encountered ingame. StorageUtil seems to be the obvious choice but JsonUtil would be neat in order to possibly edit the saved forms externally.
exiledviper wrote: There isn't much of a speed difference, at least none worth worrying about. From some basic benchmarking I've done, over 2000 iterations of setting and getting an int and a form value: JsonUtil: 0.062598 seconds, StorageUtil: 0.100601 seconds. So JsonUtil came out fractions of a second faster, which isn't worth fussing over.
Insteads it's better to just look at what your needs are. With JsonUtil all data is shared between all saves and characters. With StorageUtil the data is specific to the save.
MongoMonk wrote: Thank you for telling me. How is the handling of the json files done? Is the whole file loaded to memory once I request one entry? I'm planning to save NPCs from different mods into different files if I use JsonUtil. Also are saved FormIDs tied to the current load order? Or will they persist if the mod they're from changed its load order?
One other advantage of JsonUtil would be to actually "see" what you're saving and make sure it's stored the way you intended to.
Is there any more documentation I can read?
By the way when using Mod Organizer you can still keep the settings save specific and copy them if you want.
exiledviper wrote: Forms saved aren't load order dependent, they get saved as a string such as "mymod.esp|3426" for example, which it uses to look up the current load order of the owning mod and adjust the form id (which is saved as decimal rather than hex, 3426 = 0xD62). If the forms mod isn't loaded, attempting to read it will return as none.
Files are parsed loaded into memory the first time you try to use them, then any changes you make exist only memory until saved via jsonutil.save("file") or saved automatically at the same time skyrim writes a save. It will create the file as well during save if the file doesn't exist yet and you've set values to it.
If you load a new save, all json files loaded are automatically unloaded, and any unsaved changes lost. If you want to discard any changes you've made to a file manually, you can call jsonutil.unload("file", saveChanges=false). jsonutil.unload will remove a file from memory, optionally writing your changes or ignoring them beforehand.
The JSON handling uses jsoncpp internally (https://github.com/open-source-parsers/jsoncpp)
MongoMonk wrote: That sounds all very good. Thank you again for helping me out.
Allow me one further question: What happens to dynamically created forms (like dynamic NPCs), e.g. 0xFF003426 ? What would the "mymod.esp" in mymod.esp|3426 say? And what happens when they are unloaded from the game? Will they just return none as well?
exiledviper wrote: Wasn't sure to be honest, didn't think to test that specifically with JsonUtil. So I just did now! Looks like temporary objects save as a string saying "0", resulting in a none form on return.
I'll fix this next release. Though I'm not so sure there is, nor should there be, much of a demand for this. Point of saving to an external json is to have shareable/editable save independent data storage; so there isn't much of a purpose in being able to save temporary forms with it. The return value would be too unreliable unless used for only short lived reasons, most of which would be better served by using StorageUtil instead.
As for StorageUtil and temporary forms; it does save and load temporary forms just fine, with a couple catches though. Temporary form values will save and load fine, assuming the form still exists, it only saves the formid however, so if the temporary form is ever deleted, and the formid re-used by the game engine for a new temporary form, you'll end up with the new/replaced form on that formid being returned instead.
Saving ON a temporary as the objKey argument in StorageUtil, should remain mostly consistent, as the objkey is stored along with the form's type so it can check if the form is still the same type of form it was before. So if the temporary formid is later reused for a temporary form of a different form type, it will start accessing different maps of data, and the previous now invalid type's data discarded on save/load.
MongoMonk wrote: I've come to the conclusion that StorageUtil is the best bet for me. I may add an export/import feature through JsonUtil later. Since I will store all values on forms (using them as the key argument) I will probably be safe from dynamic form weirdness. I might add some checks for dynamic forms specifically in any case.
Again, thank you for the elaborate answer. You're really helping me out here (although a more exhaustive documentation could also help ).
I've got some more questions, they come as I code the new Papyrus stuff and as I map it out.
What happens to values I saved when the mod is uninstalled? Does StorageUtil have a way to check for that & clear the corresponding values or do I have to include some sort of "uninstaller" to my mod?
Also I stumbled across this function in MiscUtil: function ScanCellActors. It could prove very useful to me. Is it based on Cell.GetNthRef from SKSE? Or your own implementation? Also, would it be possible to optionally include dead actors into the search?
exiledviper wrote: If a mod is uninstalled, any forms from it become none in the value storage. If the form was being used as the objkey in storageutil, during load if it can't find the objkey's owning mod anymore, all of it's values are cleared.
If you're storing values on forms not owned by your mod, those values won't go away when you uninstall the mod obviously. So, I'd suggest keeping a basic "uninstall list" stored in the global space (using "none" as your objkey) via a stroageutil.formlistadd(none, "myModsList", form, false) which you would call anytime you add a value to a new form not owned by your mod. This way you can iterate over that list and clear any values set by your mod on other forms to ensure there is no lingering data.
ScanCellActors does use SKSE's GetNth functions internally. The main benefit is that it's significantly faster at filtering out specific results, since you're not doing it via papyrus. ScanCellActors specifically doesn't have anyway to disable the removal of dead actors from the results, you could simulate something like that though by using ScanCellObjects with form type 43 and keyword ActorTypeNPC.
MongoMonk wrote: Okay, I'll have a look then at ScanCellObjects since I want to specifically get dead actors. As for the uninstaller I was thinking of using ClearIntValuePrefix etc. since all my saved values start with the same prefix (" EBD_" ) which I think is unique enough so I don't touch other mods.
However, am I right in the assumption that I would not need an uninstaller if I were to use JsonUtil? Since all value associations are only written to external jsons? Or are they kept as copies in the savegame (for error checking or something) as well?
EDIT: I know it's probably not feasible but I ask anyway: Would it be possible to provide some uninstallation framework?
I.E. I register my mod with something like RegisterModUninstall("myMod.esp", "prefix_to_clear" ). Then, when myMod.esp vanishes from the load order JsonUtil would remove all values with the "prefix_to_clear".
It's probably much more work than I think but it would really streamline removal of a mod.
EDIT 2: I had a look at the ScanCellObjects function. There seems to be an issue though with the keyword parameter.
This will return zero actors: ScanCellObjects(43, PlayerREF, 0.0, EBDScriptKeyWord)
This works fine: ScanCellObjects(43, PlayerREF, 0.0)
Checking akActor.hasKeyword(EBDScriptKeyWord) returns true for all the actors I want, so the keyword is definitely there.
Will look into the keyword issue, and possibly just add an updated actor scan function that has a bool parameter for including/ignoring dead actors.
In response to post #34327505. #34367225 is also a reply to the same post.
Spoiler
Chesko wrote: First, thank you so much for PapyrusUtil. It has enabled features in Campfire and Simply Knock that wouldn't be possible otherwise.
I have a couple of questions:
* Is it best practice to require users to download PapyrusUtil separately, or is bundling certain components with the mod (personally, I use JsonUtil a lot) OK? The permissions section has no data so I wanted to be sure.
* If old PapyrusUtil components (say, 3.1) are bundled in a mod, and then a user loads PapyrusUtil as a separate mod and places it at the end of their load order, will the mod in question inherit the latest changes and bug fixes? Since the components in question will be overridden / replaced, I'm inclined to say "yes" (assuming the API doesn't change), but again, wanted to make sure.
Thanks!
exiledviper wrote: * I'm not really picky about how it's packaged. Feel free to package it with your mod and just leave a credit or link users here listing it as a separate dependency. I understand the desire to keep the install process short for users by not requiring them to install to many other seperate mods as dependencies.
On the other hand though, I will say my biggest annoyance when dealing with support for my other mod (SL) is users complaining that it's telling them their PapyrusUtil install is outdated because they've recently installed another mod that has an older version bundled- this is apparently incredibly cryptic going by how often I see it. That's my problem though, not yours. Do whatever you think best for your users.
---
* Versions are rarely not backwards or forwards compatible. The syntax for any functions rarely, if ever, changes. If a new versions syntax for a function does have to change for some reason, it's done under a new function name so it doesn't break any compatibility with existing mods. You're fine to develop on 3.1 or older, then in the majority of cases throw in 3.2 later without having to recompile anything. Same applies vice versa, if you develop in and bundle 3.2, if a user overrides it with 3.1 there shouldn't be any problems (other than the possible obvious bug/performance regression) so long as you didn't use any functions that were added by 3.2+ specifically.
This is such a fantastic collection of well-thought out utility functions. Thank you so much!
I do have a few questions relating to best practices around StorageUtil (with ObjKeys). I have a few spells that add values to actors and I want to make sure I clean up the values correctly. The spell unsets the values after a specified amount of time, but if it gets dispelled, the player leaves the area, or the actor dies, this doesn't happen. So, my questions are:
1. If an actor is killed, are the values that have them as their ObjKey automatically cleared? I did notice that the actor's body is removed correctly on cell reset, but I wanted to make sure the value itself was cleared as well.
2. If the cell containing the actor is reset, are the values associated with that actor cleared?
3. Is calling `StorageUtil.ClearAllPrefix(<my mod's prefix> ) ` a good way of clearing all stored values when my mod is uninstalled?
Any general recommendations for cleaning up safely?