ofiag Posted February 17, 2017 Posted February 17, 2017 This is rough guide to batch editing glossiness and specular strength settings in nif files using pyffi. It is specifically meant as a solution for the disappearing oily body problem encountered when using outfit replacers such as ChronoTrigger77's Remodeled Armor HDT. Keep in mind that this solution is mostly a giant hack, cobbled together from multiple other sources and glued with a bit of trial and error. As such, I am mostly ignorant of how and why this method works and will not be able to offer much help should you encounter any hiccups. In such cases, Google is your friend. Now, before we begin, everybody give a big round of applause to SiSaSyco, who in this post (http://niftools.sourceforge.net/forum/viewtopic.php?f=33&t=4381) provided the source code that is the core of my solution. Without that, I would probably still be stuck trying to wade through the esoteric quagmire that is the pyffi api documentation. Step 1)Install Pyffi according to the directions here: https://www.darkcreations.org/forums/topic/3646-using-niftoaster-for-bulk-retexturing/ Note that the command "python Scriptsniftoaster.py --help" may have a typo; you might need a slash between "Scripts" and "niftoaster.py" (so it should look like this: "python Scripts/niftoaster.py --help"). Follow the directions until you reach the point: "you should get the output:Usage: niftoaster.py [options] <spell1> <spell2> ... <file>|<folder>Apply the spells <spell1>, <spell2>, and so on, on <file>, or recursively on<folder>." Ensure that your output matches the one above; that's how you know if you've installed pyffi correctly. Step 2)Open windows explorer and navigate to your Python32 folder. From there, go to Lib>site-packages>pyffi>spells>nif. There should be python file called "modify" in there. Back up that file before you proceed; we will be mangling it slightly as part of our solution. Step 3)Right click "modify" and select edit with Notepad++ (or whatever your preferred text editor is). Use control+f to find the class "SpellDelBranches". Since I don't know how to create and register a whole new class, we will be editing this one instead. This is the "slight mangling" I mentioned earlier and the reason behind backing up the "modify" file. Theoretically, you could use any of the other classes that are listed instead of "SpellDelBranches"; I just happened to pick this one. Step 4)Highlight everything in the class and replace it with the code below: class SpellDelBranches(NifSpell): """change all at once.""" SPELLNAME = "modify_delbranches" READONLY = False def datainspect(self): return self.inspectblocktype(NifFormat.BSLightingShaderProperty) def dataentry(self): self.change_done = False return True def branchinspect(self, branch): if self.change_done: return False return isinstance(branch, (NifFormat.NiAVObject,NifFormat.BSLightingShaderProperty)) def branchentry(self, branch): if isinstance(branch, NifFormat.BSLightingShaderProperty): if branch.glossiness == 30.0: branch.glossiness = 500.0 self.changed = True if branch.specular_strength == 3.0: branch.specular_strength = 15.0 self.changed = True return False else: return True Where it says " branch.glossiness = 500.0" and " branch.specular_strength = 15.0", change the values to your preferred glossiness and specular strength settings. After you are done, save your settings. Now, a warning. This method is only tested (and not even conclusively at that) with the mod "Remodeled Armor for CBBE Bodyslide HDT" http://www.nexusmods.com/skyrim/mods/25259/? If you are using any other outfit replacer, even if they're other versions of remodeled armor, this method is not guaranteed to work. If you are using any other outfit replacer (and even if you're not), I highly recommend that you read through the EXPLANATIONS section down below. That will give you an understanding of how this method works and hopefully allow you to edit the code to fit other outfit replacers. Step 5) Open up command prompt. Change directories until you're in C:\Python32. Type: "python Scripts/niftoaster.py --help-spell modify_delbranches" without the quotations. It should output: "pyffi.toaster:INFO:change all at once." If it outputs: "IndentationError: unident does not match any outer indentation level", then you have spacebar spaces mixed in with tab spaces in your SpellDelBranches class. Go back and use the arrow keys to locate any spacebar spaces, delete them with backspace, and replace with tab. Remember that 4 spacebar spaces equals one tab. Tedious I know, but that's a consequence of copy-pasting; it tends to chew up formatting. If you get any other errors, google them and work it out. Once you get the correct output, you're ready to move on to the next step. Step 6) Create a new folder on your Desktop. Name it "Testing" without the quotations. Locate the nifs for your outfit replacer and copy-paste them into "Testing". Yes, you can copy-paste folders, pyffi will still parse through them. Step 7) Open command prompt. Ensure you are in the directory C:\Python32. Type:" python Scripts/niftoaster.py modify_delbranches C:\Users\YourName\Desktop\Testing" without the quotations (and with your actual name instead of YourName). You will get a warning asking for confirmation. Hit y, then enter. Pyffi will now start batch editing your nifs. For something as large as the remodeled armor mod, expect anywhere from 30 minutes to 1 hour for it to complete, depending on your specs. Step 8) Check through the nif files in your "Testing" folder to ensure that the specular strength and glossiness settings were edited correctly. If they are, great! If they're not, read through the EXPLANATIONS section below to see where you might have gone wrong. EXPLANATIONS FOR CODE class SpellDelBranches(NifSpell): """change all at once.""" SPELLNAME = "modify_delbranches" READONLY = False def datainspect(self): return self.inspectblocktype(NifFormat.BSLightingShaderProperty) def dataentry(self): self.change_done = False return True def branchinspect(self, branch): if self.change_done: return False return isinstance(branch, (NifFormat.NiAVObject,NifFormat.BSLightingShaderProperty)) The above segment was all straight copy-pasted from SiSaSyco's code (barring the first line). I have no idea what any of it means, nor is it particularly relevant to understanding my method; I'm just putting it here so people don't get confused about why I jumped straight to branchentry. def branchentry(self, branch): if isinstance(branch, NifFormat.BSLightingShaderProperty): if branch.glossiness == 30.0: branch.glossiness = 500.0 self.changed = True if branch.specular_strength == 3.0: branch.specular_strength = 15.0 self.changed = True return False else: return True Now, a bit of background. People who already know all this, bear with me for a moment. In outfit replacers like Remodeled Armor, the outfit nifs contain one NiTriShape named "BaseShape" (which is essentially a body nif) and other NiTriShapes that form the outfit and are named things like "Chestpiece" or "Legpiece". Every NiTriShape contains a BSLightingShaderProperty, which contains the settings for glossiness and specular strength. If branchentry looked like this: def branchentry(self, branch): if isinstance(branch, NifFormat.BSLightingShaderProperty): branch.glossiness = 500.0 branch.specular_strength = 15.0 self.changed = true else: return True then EVERY NiTriShape (BaseShape, Chestpiece, Legpiece, Whateverpiece) would become oily/glossy, not just the body. Some people may like this (in which case they should replace branchentry with the one directly above), but others may not. As such, we need some way to differentiate BaseShape NiTriShapes from Outfit NiTriShapes. Ideally, there would exist some function that can check a NiTriShape's name and only edit specular strength/glossiness settings if it matches "BaseShape" (or "body" or whatever the outfit replacer calls its body NiTriShapes). Unfortunately, I could not find such a function. Instead, I made a workaround. I noticed that all of the "BaseShapes" in Remodeled Armor had a default glossiness and specular strength setting of 30 and 3, respectively. I also noticed that all of the outfit NiTriShapes (at least in the nifs I checked) had default glossiness and specular strength settings that were NOT 30 and 3. So, I simply added two if statements that check if glossiness and specular strength settings are 30 or 3, then changes them to my preferred values if they are. This is, however roundabout, a working method for differentiating BaseShape NiTriShapes from Outfit NiTriShapes. Again, as far as I know, the default glossiness and specular strength settings of 30 and 3 only apply to Remodeled Armor. Other outfit replacers may have different default values. If you are using other outfit replacers, check through the nifs to find the default body values for glossiness and specular strength, then replace the values in the if statements with them. If your outfit replacer has default values that are the same between body NiTriShapes and outfit NiTriShapes, then I'm afraid this method won't work for you. Good luck, have fun!
MrKrupples Posted May 15, 2018 Posted May 15, 2018 You sir, have saved me so from so much pain and suffering. Bravo!
Recommended Posts
Archived
This topic is now archived and is closed to further replies.