Jump to content
  • 0
CptJesus

Python Scripts (Wrye Bash)

Question

Included in this post are some fun little python scripts that I've been using for the STEP install. All of the scripts deal with repacking archives to 7zip maximum compression with solid archives turned off. These are tuned towards Wrye Bash, because that's my tool of choice for this process. All of these require the 7zip binary in the same folder as the scripts, as well as Python installed. I've tested all of these with Python 3.x, but it's entirely possible they may work with 2.x. The scripts have a variable called FOLDERPATH, which should point to your Skyrim Mods folder. 

 

archivefixer.py

import sys
import subprocess
import os
import shutil
import re

FOLDERPATH = "X:\Steam\steamapps\common\Skyrim Mods\Bash Installers"

def main(argv):
   if (os.path.exists("temp")):
      shutil.rmtree("temp")
   infile = argv[1]
   outfile = os.path.splitext(infile)[0]
   startdir = os.getcwd() + "\\"
   zippath = os.path.abspath("7z.exe")
   outputpath = startdir + outfile+".7z"
   infile = startdir  +  infile
   origsize = os.stat(infile).st_size
   cmd = [zippath,'x','-otemp',infile]
   subprocess.call(cmd)
   os.remove(infile)
   traverse("temp",zippath,outputpath)
   os.chdir(startdir)
   shutil.rmtree("temp")
   finalsize = os.stat(outputpath).st_size
   shutil.move(outputpath,FOLDERPATH)
   saving = (origsize - finalsize) / 1024
   print("Total Bytes Saved: " + str(saving) + "kb")

def traverse(path,zippath,outputpath):
   os.chdir(path)
   filenames = os.listdir(os.getcwd())
   for filen in filenames:
      if re.match(".*esp",filen) or re.match(".*esm",filen):
         print("We've found the directory with the esp! Zip it all up")
         cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
         subprocess.call(cmd)
         return
      elif re.match("00.*",filen) or re.match("01.*",filen):
         print("Found a directory with Wrye Bash Stuff. Zip it all up!")
         cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
         subprocess.call(cmd)
         return

   filenames = [x.lower() for x in filenames]

   if ("meshes" in filenames or "textures" in filenames or "interface" in filenames or "video" in filenames or "strings" in filenames or "sound" in filenames or "scripts" in filenames):
      print("We've found the meshes/textures directory! Zip it all up")
      cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
      subprocess.call(cmd)
      return
   elif ("skse" in filenames or "SKSE" in filenames or "Skse" in filenames):
      print("SKSE Plugin. Zip it!")
      cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
      subprocess.call(cmd)
      return
   elif (len(filenames) > 0):
      for filen in filenames:
         if (os.path.isdir(filen)):
            traverse(filen,zippath,outputpath)
            os.chdir("..")
      return
   else:
      return

if __name__=="__main__":
   main(sys.argv)

 

 

 

 

This script will take any archive, unpack it and then recompress it. This is meant for simple archives that don't need repacking. It will find Wrye Bash folders, as well as simple archives with textures/meshes/sounds etc. Also ESP file. It takes a single archive and will repack it with the same name that it came in with. It'll move the final archive to FOLDERPATH. For example:

 

archivefixer.py "HQ Shields-225-1.7z"

 

magicpacker.py

import sys
import os
import shutil
import glob
import subprocess
import re

FOLDERPATH = "X:\Steam\steamapps\common\Skyrim Mods\Bash Installers"

DUALSHEATHLIST = {"Dual Sheath Redux-34155-1-6b.7z":"00 Core","Elemental Staffs Pack-34155-.7z":"01 Elemental Staffs Patch","Skyrim Weapon De-LARP-ification Project Pack On Back Update-34155-.7z":"02 Skyrim De-LARP Patch"}
NACMIM = {"NACMIM - Full-26822-1-6.zip":"00 Core","NACMIM SkyUI 3-4 Patch - Default-26822-1-34.zip":"01 SkyUI Patch"}
SKYHD = {"Skyrim HD v1_5 LITE - Dungeons-607.7z":"00 Dungeons","Skyrim HD v1_5 LITE - Towns-607.7z":"00 Towns","Skyrim HD v1_5 LITE - Landscape-607.7z":"00 Landscape","Skyrim HD v1_5 LITE - Misc-607.7z":"00 Misc"}
SERIOUSHD = {"Serious HD Retexture LANDSCAPE 1024px-2146-v2-0.rar":"00 Core","Serious HD Retexture RIFTEN 1024px-2146.rar":"01 Riften Patch"}
TOBE = {"Tobes Highres Textures 1_2 1024-1123-1-2.rar":"00 Core","Tobes Highres Textures 1_2b SMIM Patch-1123-1-2.rar":"01 SMIM Patch"}
FOOTPRINTS = {"Footprints v0_99-22745-0-99.7z":"00 Core","Footprints v0_99 - Ash Supplemental-22745-0-99.7z":"01 Ash Supplemental"}
LANTERNS = {"Lanterns Of Skyrim - All In One - MCM Special Edition-18916-2-3.rar":"00 Core","Lanterns Of Skyrim - All In One - Default preset-18916-.rar":"01 Preset"}
MUSHROOM = {"Mushroom retexture pack-29935-1-1.rar":"00 Core","mushroom stew-29935-1.rar":"01 Mushroom Stew"}
VILLAGEANIMALS = {"More Village Animals-8565-2-1.rar":"00 Core","More Village Animals Ivarstead Extended-8565-2-1.rar":"01 Ivarstead",
"More Village Animals Rorikstead Extended-8565-2-1.rar":"02 Rorikstead"}
BETTERMALEFEET = {"Better Male Feet-32378-.rar":"00 Core","Dawnguard Patch-32378-.rar":"01 Dawnguard"}
CROSSBOW = {"Explosive Bolts Visualized v1_0_2-21922-1-0-2.7z":"00 Core","Explosive Bolts Visualized HD Textures-21922-1.7z":"01 HD Patch"}
ELEMENTALSTAFF = {"Elemental Staffs 1K-15152-1-00.rar":"00 Core","Elemental Staffs Update-15152-1-10.rar":"01 1.10 Patch"}
DELARP = {"Skyrim Weapon DeLARPification Project v1_0_5-16072-1-0-5.7z":"00 Core",
"Skyrim Weapon DeLARPification Project Dawnguard v1_0-16072-DG1-0.7z":"01 Dawnguard","Skyrim Weapon DeLARPification Project Dawnguard v1_0_1-16072-1-0-1.7z":"02 Dragonborn"}
GREATSWORD = {"Greatswords SSwTB v2_3-27178-2-3.rar":"00 Core","Greatswords SSwTB - Dawnguard v2-27178-2.rar":"01 Dawnguard",
"Greatswords SSwTB - Dragonborn-27178-1.rar":"02 Dragonborn"}
CLOSEHELMET = {"Improved Closefaced Helmets --FULL SET-- V0_9-15927-0-9.zip":"00 Core",
"Improved Dawnguard helmets-15927-0-9b.zip":"01 Dawnguard","improved imperial full face helmet - no cloth around the neck--15927-0-9.zip":"02 No Cloth"}

def processarchive(archivename,outputdir):
   print("Extracting Archive " + archivename + " to " + outputdir)
   tempcwd = os.getcwd()
   os.makedirs(outputdir)
   cmd = ["7z.exe",'x','-otemp',archivename]
   with open(os.devnull, "w") as q:
      subprocess.call(cmd,stdout = q)
   os.remove(archivename)
   out = os.path.abspath(outputdir)
   traverse("temp",out)
   os.chdir(tempcwd)
   shutil.rmtree("temp")

def traverse(path,outputpath):
   os.chdir(path)
   filenameso = os.listdir(os.getcwd())
   founddir = False
   for filen in filenameso:
      if re.match(".*esp",filen) or re.match(".*esm",filen):
         founddir = True

   filenames = [x.lower() for x in filenameso]

   if (founddir or "meshes" in filenames or "textures" in filenames or "interface" in filenames
      or "video" in filenames or "strings" in filenames
      or "sound" in filenames or "scripts" in filenames):
      for filex in filenameso:
         shutil.move(filex,outputpath)
      return
   elif (len(filenames) > 0):
      for filen in filenames:
         if (os.path.isdir(filen)):
            traverse(filen,outputpath)
            os.chdir("..")
      return
   else:
      return

def testlist(filenames,test,listname):
   testset = set(test.keys())

   if (testset.issubset(filenames)):
      print("Found files for " + listname)
      templ = []
      for k in testset:
         processarchive(k,test[k])
         templ.append(test[k])
      print("Compressing archives to our new package: " + listname + ".7z")
      cmd = ["7z.exe",'a','-ms=off','-mx9',listname + ".7z"]
      cmd.extend(templ)
      with open(os.devnull, "w") as q:
         subprocess.call(cmd,stdout = q)
      for t in templ:
         shutil.rmtree(t)
      print("Moving our file to its new home!")
      shutil.move(listname + ".7z",FOLDERPATH)

def main():
   filenames = glob.glob('*.rar')
   filenames.extend(glob.glob('*.7z'))
   filenames.extend(glob.glob('*.zip'))

   converted = set(filenames)

   testlist(filenames,DUALSHEATHLIST,"Dual Sheath Redux")
   testlist(filenames,NACMIM,"Not Another Colored Map Icon Mod")
   testlist(filenames,SKYHD,"Skyrim HD")
   testlist(filenames,SERIOUSHD,"Serious HD")
   testlist(filenames,TOBE,"Tobe's Highres Textures")
   testlist(filenames,FOOTPRINTS,"Footprints")
   testlist(filenames,LANTERNS,"Lanterns of Skyrim")
   testlist(filenames,MUSHROOM,"Realistic Mushrooms")
   testlist(filenames,VILLAGEANIMALS,"More Village Animals")
   testlist(filenames,BETTERMALEFEET,"Better Male Feet")
   testlist(filenames,CROSSBOW,"Explosive Bolts Visualized")
   testlist(filenames,ELEMENTALSTAFF,"Elemental Staffs")
   testlist(filenames,DELARP,"Skyrim Weapon De-LARPification Project")
   testlist(filenames,GREATSWORD,"Greatswords Sheaths and Scabbards")
   testlist(filenames,CLOSEHELMET,"Improved Closefaced Helmets")

if __name__=="__main__":
   main()

 

 

 

This is designed to help re-compress archives that have patches with them. It's already preconfigured with a lot of the complex archives from STEP. Simply download the main archive and the patches, and then run magicpacker.py and it'll automagically make a nice Wrye Bash archive. I'm in the process of adding all the patched archives, but it's going to take some time to go through the whole thing.

 

wizardparser.py

import sys

def main(argv):
f = open(argv[1],"r")
o = open("wizard.txt","w")

for line in f:
   newline = line.replace("REQUIRE","RequireVersions \"\", \"\", \"\", \"296+\" ; Skyrim version, SKSE version, (no SKGE), Wrye Bash version")
   newline = newline.replace("SM","SelectMany")
   newline = newline.replace("SO","SelectOne")
   newline = newline.replace("SSP","SelectSubPackage")
   newline = newline.replace("DSA","DeSelectAll")
   newline = newline.replace("BRK","Break")
   newline = newline.replace("ES","EndSelect")
   newline = newline.replace("IMG","Wizard Images\\\\")
   newline = newline.replace("DEF","Default Texture")
   newline = newline.replace("CUST", "Custom Texture")
   newline = newline.replace("NOIN","Do not install a texture")
   newline = newline.replace("\"CTEX","\"Customized Texture from")

   o.write(newline)

if __name__=="__main__":
   main(sys.argv)

 

This script is designed to help simplify the process of making Wrye Bash Wizards by converting shorthand to a full Wizard. All it takes is an input file, and it will output wizard.txt. Here's an example of input:

 

REQUIRE

DSA

SO "Select Configuration for Book of Silence (Weapons)", \
   "|No Flesh (STEP Recommended)", "The recommended install for Step", "IMGOpt 4 - No Flesh.jpg", \
   "Option 0", "","IMGOpt 0.jpg", \
   "Option 1", "","IMGOpt 1.jpg", \
   "Option 2","","IMGOpt 2.jpg", \
   "Option 3","","IMGOpt 3.jpg"

   Case "No Flesh (STEP Recommended)"
      SSP "00 Option 4 - No Flesh"
   BRK

   Case "Option 0"
      SSP "00 Option 0"
   BRK

   Case "Option 1"
      SSP "00 Option 1"
   BRK

   Case "Option 2"
      SSP "00 Option 2"
   BRK

   Case "Option 3"
      SSP "00 Option 3"
   BRK
ES

This will convert to:

 

RequireVersions "", "", "", "296+" ; Skyrim version, SKSE version, (no SKGE), Wrye Bash version

DeSelectAll

SelectOne "Select Configuration for Book of Silence (Weapons)", \
   "|No Flesh (STEP Recommended)", "The recommended install for Step", "Wizard Images\\Opt 4 - No Flesh.jpg", \
   "Option 0", "","Wizard Images\\Opt 0.jpg", \
   "Option 1", "","Wizard Images\\Opt 1.jpg", \
   "Option 2","","Wizard Images\\Opt 2.jpg", \
   "Option 3","","Wizard Images\\Opt 3.jpg"

   Case "No Flesh (STEP Recommended)"
      SelectSubPackage "00 Option 4 - No Flesh"
   Break

   Case "Option 0"
      SelectSubPackage "00 Option 0"
   Break

   Case "Option 1"
      SelectSubPackage "00 Option 1"
   Break

   Case "Option 2"
      SelectSubPackage "00 Option 2"
   Break

   Case "Option 3"
      SelectSubPackage "00 Option 3"
   Break
EndSelect

 

Example usage is wizardparser.py test.txt

 

The following shorthand is used:

 

REQUIRE is the Require String

SM = SelectMany

SO = SelectOne

SSP = SelectSubPackage

DSA = DeSelectAll

BRK = Break

ES = EndSelect

IMG = Wizard Images\\

DEF = Default Texture

CUST = Custom Texture

NOIN = Do not install a texture

CTEX = Customized Texture from

 

 

Hope some of these scripts help out you STEPpers

Share this post


Link to post
Share on other sites

Recommended Posts

  • 0

Thanks CptJesus!

 

I'll give it a try over the next week. I have been learning Python in my spare time, so this will be a good working example for me to use and build upon if it makes sense for me (I am very specific about my repackaging too, and I prefer a minimal, non-solid compression format for speed of install/uninstall via WB).

Share this post


Link to post
Share on other sites
  • 0

I fixed some bugs, so heres an updated version!

 

import sys
import subprocess
import os
import shutil
import re

FOLDERPATH = "C:\Program Files (x86)\Steam\SteamApps\common\Skyrim Mods\Bash Installers"

def main(argv):
	if (os.path.exists("temp")):
		shutil.rmtree("temp")
	infile = argv[1]
	outfile = os.path.splitext(infile)[0]
	startdir = os.getcwd() + "\\"
	zippath = os.path.abspath("7z.exe")
	outputpath = startdir + outfile+".7z"
	infile = startdir  +  infile 
	origsize = os.stat(infile).st_size
	cmd = [zippath,'x','-otemp',infile]
	subprocess.call(cmd)
	os.remove(infile)
	traverse("temp",zippath,outputpath)
	os.chdir(startdir)
	shutil.rmtree("temp")
	finalsize = os.stat(outputpath).st_size
	shutil.move(outputpath,FOLDERPATH)
	saving = (origsize - finalsize) / 1024
	print("Total Bytes Saved: " + str(saving) + "kb")


def traverse(path,zippath,outputpath):
	os.chdir(path)
	filenames = os.listdir(os.getcwd())
	for filen in filenames:
		if re.match(".*esp",filen) or re.match(".*esm",filen):
			print("We've found the directory with the esp! Zip it all up")
			cmd = [zippath,'a','-mx9',outputpath,'*']
			subprocess.call(cmd)
			return
		elif re.match("00.*",filen) or re.match("01.*",filen):
			print("Found a directory with Wrye Bash Stuff. Zip it all up!")
			cmd = [zippath,'a','-mx9',outputpath,'*']
			subprocess.call(cmd)
			return

	filenames = [x.lower() for x in filenames]

	if ("meshes" in filenames or "textures" in filenames or "interface" in filenames or "video" in filenames or "strings" in filenames or "sound" in filenames or "scripts" in filenames):
		print("We've found the meshes/textures directory! Zip it all up")
		cmd = [zippath,'a','-mx9',outputpath,'*']
		subprocess.call(cmd)
		return
	elif ("skse" in filenames or "SKSE" in filenames or "Skse" in filenames):
		print("SKSE Plugin. Zip it!")
		cmd = [zippath,'a','-mx9',outputpath,'*']
		subprocess.call(cmd)
		return
	elif (len(filenames) > 0):
		for filen in filenames:
			if (os.path.isdir(filen)):
				traverse(filen,zippath,outputpath)
				os.chdir("..")
		return
	else:
		return

if __name__=="__main__":
	main(sys.argv)

Now it only needs one argument, which is the name of the archive. Additionally, the script will move the new archive to your Skyrim Mods/Bash Installers folder automatically (hardcoded into the script). If you have your Skyrim Mods folder somewhere else, change the variable called FOLDERPATH in the code.

Share this post


Link to post
Share on other sites
  • 0

Sad that this doesn't work for the complex archives, but I suppose it would be near impossible to make a script that could encompass all of those. As a small request, would it be possible to add doc/txt/html and add them to a Doc Folder in the archive? Makes keeping track of those files much easier.

 

That aside, this seems very useful, as I basically do this manually anyway.

Share this post


Link to post
Share on other sites
  • 0

I fixed some bugs, so heres an updated version!

 

 

 

Now it only needs one argument, which is the name of the archive. Additionally, the script will move the new archive to your Skyrim Mods/Bash Installers folder automatically (hardcoded into the script)

Thanks for creating this; I've never learned Python well enough to write tools like this. You might want to note that users who have the Steam folder in a directory other than "Program Files", as STEP recommends, should change the directory name in the script.

Share this post


Link to post
Share on other sites
  • 0

Sad that this doesn't work for the complex archives, but I suppose it would be near impossible to make a script that could encompass all of those. As a small request, would it be possible to add doc/txt/html and add them to a Doc Folder in the archive? Makes keeping track of those files much easier.

 

That aside, this seems very useful, as I basically do this manually anyway.

 

Yeah, complex archives are nearly impossible. On the flipside, I'm working on a tool that will help automate the process of creating BCFs, so that should speed things up considerably. If I ever get it working to my standards, I'll just go ahead and BCF most of the nastier archives that you find. I'm wondering if its worth it to compress archives as non-solid. Currently I'm using the default settings for that. It would increase file size, but probably make Wrye Bash a lot happier.

 

I fixed some bugs, so heres an updated version!

 

 

 

Now it only needs one argument, which is the name of the archive. Additionally, the script will move the new archive to your Skyrim Mods/Bash Installers folder automatically (hardcoded into the script)

Thanks for creating this; I've never learned Python well enough to write tools like this. You might want to note that users who have the Steam folder in a directory other than "Program Files", as STEP recommends, should change the directory name in the script.

 

Sorry, forgot to mention that. I'll edit my post above. Just for future reference, how do you link BCFs to mods? I went ahead and created one for Book of Silence (Unique Items) and uploaded it. Its located at

https://wiki.step-project.com/File:AMidianBorn_Book_of_Silence_(Unique_Items)-BCF.7z

Share this post


Link to post
Share on other sites
  • 0

I'm wondering if its worth it to compress archives as non-solid. Currently I'm using the default settings for that. It would increase file size, but probably make Wrye Bash a lot happier.

 

Non-solid is best format, especially for large archives. WB can unpack only what is needed rather than the entire contents, so it can be much faster to process.

Just for future reference, how do you link BCFs to mods?

Go to the mod page and click on "Add BCF"

Share this post


Link to post
Share on other sites
  • 0
I'm wondering if its worth it to compress archives as non-solid. Currently I'm using the default settings for that. It would increase file size' date=' but probably make Wrye Bash a lot happier.[/quote']

Non-solid is best format' date=' especially for large archives. WB can unpack only what is needed rather than the entire contents, so it can be much faster to process.

Just for future reference, how do you link BCFs to mods?

Go to the mod page and click on "Add BCF"

 

Added the BCF to the page, but I don't see it there. I'm going to alter my script to compress with non-solid

Share this post


Link to post
Share on other sites
  • 0

I noticed previously that it can take a while for the mod pages to refresh to show BCFs that were added.

Share this post


Link to post
Share on other sites
  • 0

Ok so I come with 2 gifts. The first is an updated compression script with solid off.

 

import sys
import subprocess
import os
import shutil
import re

FOLDERPATH = "C:\Program Files (x86)\Steam\SteamApps\common\Skyrim Mods\Bash Installers"

def main(argv):
	if (os.path.exists("temp")):
		shutil.rmtree("temp")
	infile = argv[1]
	outfile = os.path.splitext(infile)[0]
	startdir = os.getcwd() + "\\"
	zippath = os.path.abspath("7z.exe")
	outputpath = startdir + outfile+".7z"
	infile = startdir  +  infile 
	origsize = os.stat(infile).st_size
	cmd = [zippath,'x','-otemp',infile]
	subprocess.call(cmd)
	os.remove(infile)
	traverse("temp",zippath,outputpath)
	os.chdir(startdir)
	shutil.rmtree("temp")
	finalsize = os.stat(outputpath).st_size
	shutil.move(outputpath,FOLDERPATH)
	saving = (origsize - finalsize) / 1024
	print("Total Bytes Saved: " + str(saving) + "kb")


def traverse(path,zippath,outputpath):
	os.chdir(path)
	filenames = os.listdir(os.getcwd())
	for filen in filenames:
		if re.match(".*esp",filen) or re.match(".*esm",filen):
			print("We've found the directory with the esp! Zip it all up")
			cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
			subprocess.call(cmd)
			return
		elif re.match("00.*",filen) or re.match("01.*",filen):
			print("Found a directory with Wrye Bash Stuff. Zip it all up!")
			cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
			subprocess.call(cmd)
			return

	filenames = [x.lower() for x in filenames]

	if ("meshes" in filenames or "textures" in filenames or "interface" in filenames or "video" in filenames or "strings" in filenames or "sound" in filenames or "scripts" in filenames):
		print("We've found the meshes/textures directory! Zip it all up")
		cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
		subprocess.call(cmd)
		return
	elif ("skse" in filenames or "SKSE" in filenames or "Skse" in filenames):
		print("SKSE Plugin. Zip it!")
		cmd = [zippath,'a','-ms=off','-mx9',outputpath,'*']
		subprocess.call(cmd)
		return
	elif (len(filenames) > 0):
		for filen in filenames:
			if (os.path.isdir(filen)):
				traverse(filen,zippath,outputpath)
				os.chdir("..")
		return
	else:
		return

if __name__=="__main__":
	main(sys.argv)

The second thing I bring is what I'm calling wizardwizard. It automates the process of making Wrye Bash wizards to some extent. It's kind of hard to understand, but it'll allow you to make a wizard in almost any which way. It's very rough around the edges, but I'm putting it out there. If you can improve on it, feel free and let me know. I put it together in like a couple hours. It requires the EasyGUI package because I was way too lazy to code up any complicated GUI stuff.

 

import sys
import easygui as eg
import shutil
import os

depth = 0

f = None

#==== Utilites for Writing to the file
def dwrite(text):
	global f
	if (depth > 0):
		f.write("\t" * depth)

	f.write(text)

def twrite(text):
	global f
	if (depth > 0):
		f.write("\t" * depth + "SelectSubPackage \"")

	while text[-1:] == "\n":
		text = text[:-1]

	text = text.replace('\n','\n' + '\t' * depth + "SelectSubPackage \"")

	f.write(text + "\"")
	f.write('\n')

def awrite(text):
	global f
	f.write(text)

def main():
	if os.path.exists("wizard.txt"):
		os.remove("wizard.txt")

	global f
	f = open("wizard.txt","w")
	dwrite("RequireVersions \"\", \"\", \"\", \"296+\" ; Skyrim version, SKSE version, (no SKGE), Wrye Bash version\n\n")

	dwrite("DeSelectAll\n\n")

	msg = "Is there a core package?"
	title= "Core Package"

	directory = ""
	if (eg.ynbox(msg,title) == 1):
		directory = eg.enterbox("What is the name of the core directory")
		dwrite("SelectSubpackage " + directory + "\n\n")

	SelectOne()

def choice():
	choices = ["SelectOne","SelectMany","Text"]
	return eg.choicebox("Pick the next element","Next Element",choices)

def casepick(casename):
	choices = ["SelectOne","SelectMany","Text","Finish"]
	return eg.choicebox("Pick the next element for " + casename,"Next Element",choices)

def SelectMany():
	cases = []
	msg = "Create SelectMany"
	title = eg.enterbox("Title of SelectMany")
	dwrite("SelectOne \"" + title + "\", \\\n")

	global depth
	depth = depth + 1

	m = "Enter Case Details"
	fieldNames = ["Case Name","Case Description","Screenshot Path"]
	values = []
	values = eg.multenterbox(m,"Create Case",fieldNames)

	dwrite("\"|" + values[0] + "\", \"" + values[1] + "\", \"" + values[2] + "\"")

	cases.append(values[0])

	msg = "Add another case?"

	while (eg.ynbox(msg) == 1):
		awrite(", \\\n")

		m = "Enter Case Details"
		fieldNames = ["Case Name","Case Description","Screenshot Path"]
		values = []
		values = eg.multenterbox(m,"Create Case",fieldNames)

		cases.append(values[0])

		dwrite("\"" + values[0] + "\", \"" + values[1] + "\", \"" + values[2] + "\"")

	awrite("\n")

	processCases(cases)

	depth = depth - 1

	dwrite("EndSelect\n")

def SelectOne():
	cases = []
	msg = "Create SelectOne"
	title = eg.enterbox("Title of SelectOne")
	dwrite("SelectOne \"" + title + "\", \\\n")

	global depth
	depth = depth + 1

	m = "Enter Case Details"
	fieldNames = ["Case Name","Case Description","Screenshot Path"]
	values = []
	values = eg.multenterbox(m,"Create Case",fieldNames)

	dwrite("\"|" + values[0] + "\", \"" + values[1] + "\", \"" + values[2] + "\"")

	cases.append(values[0])

	msg = "Add another case?"

	while (eg.ynbox(msg) == 1):
		awrite(", \\\n")

		m = "Enter Case Details"
		fieldNames = ["Case Name","Case Description","Screenshot Path"]
		values = []
		values = eg.multenterbox(m,"Create Case",fieldNames)

		cases.append(values[0])

		dwrite("\"" + values[0] + "\", \"" + values[1] + "\", \"" + values[2] + "\"")

	awrite("\n")

	processCases(cases)

	depth = depth - 1

	dwrite("EndSelect\n")

def processCases(cases):
	global depth
	
	for case in cases:
		awrite("\n")
		dwrite("Case \"" + case + "\"\n")
		depth = depth + 1
		pick = ""
		while (pick != "Finish"):
			pick = casepick(case)
			if (pick == "Text"):
				text = eg.textbox("Enter subpackages for " + case)
				twrite(text)
			elif (pick == "SelectOne"):
				SelectOne()
			elif (pick == "SelectMany"):
				SelectMany()
			else:
				depth = depth - 1
				dwrite("Break\n")

if __name__=="__main__":
	main()

Just as a side note, I'm writing this in part to teach myself python, so sorry for the weird coding quirks =)

Share this post


Link to post
Share on other sites
  • 0

I noticed previously that it can take a while for the mod pages to refresh to show BCFs that were added.

Altered pages incorporating SMW functionality need to be refreshed, and that can only be done by sysops. I'll take care of it

Share this post


Link to post
Share on other sites
  • 0

Making a decent Wrye Bash Wizard Creator is a lot harder than I thought. I think I need to take a different approach to this. I might try a parser of some kind where you shorthand the wizard and it replaces everything with the proper syntax

Share this post


Link to post
Share on other sites
  • 0

So as an update, I decided to scrap my wizardwizard and just wrote a simple parser that takes a file and converts it to Wrye Bash format. You write the whole thing in shorthand and it'll give you a working Wrye Bash wizard in return.

 

import sys

def main(argv):
f = open(argv[1],"r")
o = open("wizard.txt","w")

for line in f:
  newline = line.replace("REQUIRE","RequireVersions \"\", \"\", \"\", \"296+\" ; Skyrim version, SKSE version, (no SKGE), Wrye Bash version")
  newline = newline.replace("SM","SelectMany")
  newline = newline.replace("SO","SelectOne")
  newline = newline.replace("SSP","SelectSubPackage")
  newline = newline.replace("DSA","DeSelectAll")
  newline = newline.replace("BRK","Break")
  newline = newline.replace("ES","EndSelect")
  newline = newline.replace("IMG","Wizard Images\\\\")
  newline = newline.replace("DEF","Default Texture")
  newline = newline.replace("CUST", "Custom Texture")
  newline = newline.replace("NOIN","Do not install a texture")
  newline = newline.replace("\"CTEX","\"Customized Texture from")

  o.write(newline)

if __name__=="__main__":
main(sys.argv)

 

 

The following shorthand is used:

 

REQUIRE is the Require String

SM = SelectMany

SO = SelectOne

SSP = SelectSubPackage

DSA = DeSelectAll

BRK = Break

ES = EndSelect

IMG = Wizard Images\\

DEF = Default Texture

CUST = Custom Texture

NOIN = Do not install a texture

CTEX = Customized Texture from

 

Im working on a better solution, but this is a decent stopgap.We'll create an awesome solution yet!

 

Example Usage: wizardparser text.txt

Outputs wizard.txt

 

Heres an example input:

REQUIRE

DSA

SO "Select Configuration for Book of Silence (Weapons)", \
"|STEP Default", "The recommended install for Step", "IMGdefault.jpg", \
"Customized Install", "Customize your installation", "IMGcustom.jpg"

Case "STEP Default"
  SSP "01 Iron"
  SSP "02 Steel"
  SSP "03 Skyforge"
  SSP "04 Silver"
  SSP "05 Orcish"
  SSP "06 Dwarven"
BRK

Case "Customized Install"
  SO "Iron Weapons", \
   "|CUST","CTEX Book of Silence","IMGiron.jpg",
   "DEF","NOIN",""

   Case "CUST"
    SSP "01 Iron"
   BRK

   Case "DEF"
   BRK
  ES

  SO "Steel Weapons", \
   "|CUST","CTEX Book of Silence","IMGsteel.jpg",
   "DEF","NOIN",""

   Case "CUST"
    SSP "02 Steel"
   BRK

   Case "DEF"
   BRK
  ES

  SO "Skyforge Weapons", \
   "|CUST","CTEX Book of Silence","IMGskyforge weapons.jpg",
   "DEF","NOIN",""

   Case "CUST"
    SSP "03 Skyforge"
   BRK

   Case "DEF"
   BRK
  ES

  SO "Silver Weapons", \
   "|CUST","CTEX Book of Silence","IMGsilver.jpg",
   "DEF","NOIN",""

   Case "CUST"
    SSP "04 Silver"
   BRK

   Case "DEF"
   BRK
  ES

  SO "Orcish Weapons", \
   "|CUST","CTEX Book of Silence","IMGorcish.jpg",
   "DEF","NOIN",""

   Case "CUST"
    SSP "05 Orcish"
   BRK

   Case "DEF"
   BRK
  ES

  SO "Dwarven Weapons", \
   "|CUST","CTEX Book of Silence","IMGdwarven.jpg",
   "DEF","NOIN",""

   Case "CUST"
    SSP "06 Dwarven"
   BRK

   Case "DEF"
   BRK
  ES
BRK
ES

 

And heres the output:

 

RequireVersions "", "", "", "296+" ; Skyrim version, SKSE version, (no SKGE), Wrye Bash version

DeSelectAll

SelectOne "Select Configuration for Book of Silence (Weapons)", \
"|STEP Default", "The recommended install for Step", "Wizard Images\\default.jpg", \
"Customized Install", "Customize your installation", "Wizard Images\\custom.jpg"

Case "STEP Default"
  SelectSubPackage "01 Iron"
  SelectSubPackage "02 Steel"
  SelectSubPackage "03 Skyforge"
  SelectSubPackage "04 Silver"
  SelectSubPackage "05 Orcish"
  SelectSubPackage "06 Dwarven"
Break

Case "Customized Install"
  SelectOne "Iron Weapons", \
   "|Custom Texture","Customized Texture from Book of Silence","Wizard Images\\iron.jpg",
   "Default Texture","Do not install a texture",""

   Case "Custom Texture"
    SelectSubPackage "01 Iron"
   Break

   Case "Default Texture"
   Break
  EndSelect

  SelectOne "Steel Weapons", \
   "|Custom Texture","Customized Texture from Book of Silence","Wizard Images\\steel.jpg",
   "Default Texture","Do not install a texture",""

   Case "Custom Texture"
    SelectSubPackage "02 Steel"
   Break

   Case "Default Texture"
   Break
  EndSelect

  SelectOne "Skyforge Weapons", \
   "|Custom Texture","Customized Texture from Book of Silence","Wizard Images\\skyforge weapons.jpg",
   "Default Texture","Do not install a texture",""

   Case "Custom Texture"
    SelectSubPackage "03 Skyforge"
   Break

   Case "Default Texture"
   Break
  EndSelect

  SelectOne "Silver Weapons", \
   "|Custom Texture","Customized Texture from Book of Silence","Wizard Images\\silver.jpg",
   "Default Texture","Do not install a texture",""

   Case "Custom Texture"
    SelectSubPackage "04 Silver"
   Break

   Case "Default Texture"
   Break
  EndSelect

  SelectOne "Orcish Weapons", \
   "|Custom Texture","Customized Texture from Book of Silence","Wizard Images\\orcish.jpg",
   "Default Texture","Do not install a texture",""

   Case "Custom Texture"
    SelectSubPackage "05 Orcish"
   Break

   Case "Default Texture"
   Break
  EndSelect

  SelectOne "Dwarven Weapons", \
   "|Custom Texture","Customized Texture from Book of Silence","Wizard Images\\dwarven.jpg",
   "Default Texture","Do not install a texture",""

   Case "Custom Texture"
    SelectSubPackage "06 Dwarven"
   Break

   Case "Default Texture"
   Break
  EndSelect
Break
EndSelect

Share this post


Link to post
Share on other sites
  • 0

Good friends, I bring you yet another script. This one will take multiple archives and allow you to repack them in a sane manner. For example, the Skyrim Weapon Delarpificatioon Project. If you pass the three archives to the script, it will allow you to pick new folder names for each one, and then unpack them. It will repackage the final folders into a single 7zip compressed to maximum and non-solid.

 

import sys
import subprocess
import shutil
import re
import os

FOLDERPATH = "C:\Program Files (x86)\Steam\SteamApps\common\Skyrim Mods\Bash Installers"

def main(argv):
filelist = argv[1:]
final = []
origsize = 0
startdir = os.getcwd() + "\\"
for f in filelist:
  origsize = origsize + os.stat(f).st_size
  foldername = input("Choose folder name for " + f + ": ")
  final.append(foldername)
  os.makedirs(foldername)
  zippath = os.path.abspath("7z.exe")
  cmd = ["7z.exe",'x','-otemp',f]
  subprocess.call(cmd)

  folderpath = os.path.abspath(foldername)
  traverse("temp",zippath,folderpath)
  os.chdir(startdir)
  shutil.rmtree("temp")


finalname = input("Enter the final filename: ")
finalname = finalname + ".7z"
cmd = ["7z.exe",'a','-ms=off','-mx9',finalname]
cmd.extend(final)

subprocess.call(cmd)

finalsize = os.stat(finalname).st_size
saving = (origsize - finalsize) / 1024
print("Size Difference: " + str(saving) + "kb")
for fn in final:
  shutil.rmtree(fn)

shutil.move(finalname,FOLDERPATH)

def traverse(path,zippath,outputpath):
os.chdir(path)
filenameso = os.listdir(os.getcwd())
founddir = False
for filen in filenameso:
  if re.match(".*esp",filen) or re.match(".*esm",filen):
   print("We've found the directory with the esp! Zip it all up")
   founddir = True

filenames = [x.lower() for x in filenameso]

if (founddir or "meshes" in filenames or "textures" in filenames or "interface" in filenames
  or "video" in filenames or "strings" in filenames
  or "sound" in filenames or "scripts" in filenames):
  print("We've found the meshes/textures directory! Zip it all up")
  for filex in filenameso:
   shutil.move(filex,outputpath)
  return
elif (len(filenames) > 0):
  for filen in filenames:
   if (os.path.isdir(filen)):
    traverse(filen,zippath,outputpath)
    os.chdir("..")
  return
else:
  return


if __name__=="__main__":
main(sys.argv)

 

 

 

 

For example:

repacker.py DeLARPCore DeLARPDawnguard DeLARPDragonborn

 

Choose folder names 00 Core, 01 Dawnguard, 02 Dragonborn

 

Voila, DeLARP with both patches in a nice Wrye Bash compatible format. Hope someone finds a use for this!

Share this post


Link to post
Share on other sites
  • 0

I noticed previously that it can take a while for the mod pages to refresh to show BCFs that were added.

Altered pages incorporating SMW functionality need to be refreshed, and that can only be done by sysops. I'll take care of it
FYI, the above statement is only true for pages that are protected, or for when you want to force an update of all wiki pages. Any user can request a "purge" of a single page that is not protected (i.e. Mod pages) by selecting the menu option "PAGE TOOLS->REFRESH". Purging a page forces the HTML cache to be rebuilt, which will re-evaluate any SMW properties/queries as well.

Share this post


Link to post
Share on other sites
  • 0

Cool I'll make sure to refresh my pages then

 

Sent from my SGH-T889 using Tapatalk 2

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.